muun-recovery/address_generator.go

130 lines
3.6 KiB
Go
Raw Permalink Normal View History

2019-10-01 11:22:30 -04:00
package main
import (
"fmt"
"log"
"github.com/muun/libwallet"
2022-10-04 13:55:21 -04:00
"github.com/muun/recovery/utils"
2019-10-01 11:22:30 -04:00
)
type AddressGenerator struct {
2022-10-04 13:55:21 -04:00
addressCount int
userKey *libwallet.HDPrivateKey
muunKey *libwallet.HDPrivateKey
generateContacts bool
2019-10-01 11:22:30 -04:00
}
2022-10-04 13:55:21 -04:00
func NewAddressGenerator(userKey, muunKey *libwallet.HDPrivateKey, generateContacts bool) *AddressGenerator {
2019-10-01 11:22:30 -04:00
return &AddressGenerator{
2022-10-04 13:55:21 -04:00
addressCount: 0,
userKey: userKey,
muunKey: muunKey,
generateContacts: generateContacts,
2019-10-01 11:22:30 -04:00
}
}
2021-03-17 14:28:04 -04:00
// Stream returns a channel that emits all addresses generated.
func (g *AddressGenerator) Stream() chan libwallet.MuunAddress {
ch := make(chan libwallet.MuunAddress)
go func() {
2022-10-04 13:55:21 -04:00
g.generate(ch)
utils.NewLogger("ADDR").Printf("Addresses %v\n", g.addressCount)
2021-03-17 14:28:04 -04:00
close(ch)
}()
return ch
}
2022-10-04 13:55:21 -04:00
func (g *AddressGenerator) generate(consumer chan libwallet.MuunAddress) {
g.generateChangeAddrs(consumer)
g.generateExternalAddrs(consumer)
if g.generateContacts {
g.generateContactAddrs(consumer, 100)
}
2019-10-01 11:22:30 -04:00
}
2022-10-04 13:55:21 -04:00
func (g *AddressGenerator) generateChangeAddrs(consumer chan libwallet.MuunAddress) {
2019-10-01 11:22:30 -04:00
const changePath = "m/1'/1'/0"
changeUserKey, _ := g.userKey.DeriveTo(changePath)
changeMuunKey, _ := g.muunKey.DeriveTo(changePath)
2022-10-04 13:55:21 -04:00
g.deriveTree(consumer, changeUserKey, changeMuunKey, 2500, "change")
2019-10-01 11:22:30 -04:00
}
2022-10-04 13:55:21 -04:00
func (g *AddressGenerator) generateExternalAddrs(consumer chan libwallet.MuunAddress) {
2019-10-01 11:22:30 -04:00
const externalPath = "m/1'/1'/1"
externalUserKey, _ := g.userKey.DeriveTo(externalPath)
externalMuunKey, _ := g.muunKey.DeriveTo(externalPath)
2022-10-04 13:55:21 -04:00
g.deriveTree(consumer, externalUserKey, externalMuunKey, 2500, "external")
2019-10-01 11:22:30 -04:00
}
2022-10-04 13:55:21 -04:00
func (g *AddressGenerator) generateContactAddrs(consumer chan libwallet.MuunAddress, numContacts int64) {
2019-10-01 11:22:30 -04:00
const addressPath = "m/1'/1'/2"
contactUserKey, _ := g.userKey.DeriveTo(addressPath)
contactMuunKey, _ := g.muunKey.DeriveTo(addressPath)
for i := int64(0); i <= numContacts; i++ {
partialContactUserKey, _ := contactUserKey.DerivedAt(i, false)
partialMuunUserKey, _ := contactMuunKey.DerivedAt(i, false)
branch := fmt.Sprintf("contacts-%v", i)
2022-10-04 13:55:21 -04:00
g.deriveTree(consumer, partialContactUserKey, partialMuunUserKey, 200, branch)
2019-10-01 11:22:30 -04:00
}
}
2022-10-04 13:55:21 -04:00
func (g *AddressGenerator) deriveTree(
consumer chan libwallet.MuunAddress,
rootUserKey, rootMuunKey *libwallet.HDPrivateKey,
count int64,
name string,
) {
2019-10-01 11:22:30 -04:00
for i := int64(0); i <= count; i++ {
userKey, err := rootUserKey.DerivedAt(i, false)
if err != nil {
log.Printf("skipping child %v for %v due to %v", i, name, err)
continue
}
muunKey, err := rootMuunKey.DerivedAt(i, false)
if err != nil {
log.Printf("skipping child %v for %v due to %v", i, name, err)
continue
}
addrV2, err := libwallet.CreateAddressV2(userKey.PublicKey(), muunKey.PublicKey())
if err == nil {
2022-10-04 13:55:21 -04:00
consumer <- addrV2
g.addressCount++
2019-11-28 18:13:09 -05:00
} else {
2019-10-01 11:22:30 -04:00
log.Printf("failed to generate %v v2 for %v due to %v", name, i, err)
}
addrV3, err := libwallet.CreateAddressV3(userKey.PublicKey(), muunKey.PublicKey())
if err == nil {
2022-10-04 13:55:21 -04:00
consumer <- addrV3
g.addressCount++
2019-11-28 18:13:09 -05:00
} else {
2019-10-01 11:22:30 -04:00
log.Printf("failed to generate %v v3 for %v due to %v", name, i, err)
}
2019-11-28 18:13:09 -05:00
addrV4, err := libwallet.CreateAddressV4(userKey.PublicKey(), muunKey.PublicKey())
if err == nil {
2022-10-04 13:55:21 -04:00
consumer <- addrV4
g.addressCount++
2019-11-28 18:13:09 -05:00
} else {
log.Printf("failed to generate %v v4 for %v due to %v", name, i, err)
}
2021-11-12 17:06:13 -05:00
addrV5, err := libwallet.CreateAddressV5(userKey.PublicKey(), muunKey.PublicKey())
if err == nil {
2022-10-04 13:55:21 -04:00
consumer <- addrV5
g.addressCount++
2021-11-12 17:06:13 -05:00
} else {
log.Printf("failed to generate %v v5 for %v due to %v", name, i, err)
}
2019-10-01 11:22:30 -04:00
}
2019-11-28 18:13:09 -05:00
}