mirror of
https://github.com/muun/recovery.git
synced 2025-11-12 06:50:18 -05:00
Update project structure and build process
This commit is contained in:
62
libwallet/addresses/addresses.go
Normal file
62
libwallet/addresses/addresses.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
const (
|
||||
V1 = 1
|
||||
V2 = 2
|
||||
V3 = 3
|
||||
V4 = 4
|
||||
V5 = 5
|
||||
SubmarineSwapV1 = 101
|
||||
SubmarineSwapV2 = 102
|
||||
IncomingSwap = 201
|
||||
)
|
||||
|
||||
type WalletAddress struct {
|
||||
version int
|
||||
derivationPath string
|
||||
address string
|
||||
}
|
||||
|
||||
func New(version int, derivationPath string, address string) *WalletAddress {
|
||||
return &WalletAddress{
|
||||
version: version,
|
||||
derivationPath: derivationPath,
|
||||
address: address,
|
||||
}
|
||||
}
|
||||
|
||||
func Create(version int, userKey, muunKey *hdkeychain.ExtendedKey, path string, network *chaincfg.Params) (*WalletAddress, error) {
|
||||
switch version {
|
||||
case V1:
|
||||
return CreateAddressV1(userKey, path, network)
|
||||
case V2:
|
||||
return CreateAddressV2(userKey, muunKey, path, network)
|
||||
case V3:
|
||||
return CreateAddressV3(userKey, muunKey, path, network)
|
||||
case V4:
|
||||
return CreateAddressV4(userKey, muunKey, path, network)
|
||||
case V5:
|
||||
return CreateAddressV5(userKey, muunKey, path, network)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown or unsupported version %v", version)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *WalletAddress) Version() int {
|
||||
return a.version
|
||||
}
|
||||
|
||||
func (a *WalletAddress) DerivationPath() string {
|
||||
return a.derivationPath
|
||||
}
|
||||
|
||||
func (a *WalletAddress) Address() string {
|
||||
return a.address
|
||||
}
|
||||
30
libwallet/addresses/addresses_test.go
Normal file
30
libwallet/addresses/addresses_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
"github.com/muun/libwallet/hdpath"
|
||||
)
|
||||
|
||||
func parseKey(s string) *hdkeychain.ExtendedKey {
|
||||
key, err := hdkeychain.NewKeyFromString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func derive(key *hdkeychain.ExtendedKey, fromPath, toPath string) *hdkeychain.ExtendedKey {
|
||||
indexes := hdpath.MustParse(toPath).IndexesFrom(hdpath.MustParse(fromPath))
|
||||
for _, index := range indexes {
|
||||
var err error
|
||||
var modifier uint32
|
||||
if index.Hardened {
|
||||
modifier = hdkeychain.HardenedKeyStart
|
||||
}
|
||||
key, err = key.Child(index.Index | modifier)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return key
|
||||
}
|
||||
24
libwallet/addresses/v1.go
Normal file
24
libwallet/addresses/v1.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
// CreateAddressV1 returns a P2PKH WalletAddress from a publicKey for use in TransactionSchemeV1
|
||||
func CreateAddressV1(userKey *hdkeychain.ExtendedKey, path string, network *chaincfg.Params) (*WalletAddress, error) {
|
||||
pubKey, err := userKey.ECPubKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
address, err := btcutil.NewAddressPubKey(pubKey.SerializeCompressed(), network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &WalletAddress{
|
||||
address: address.EncodeAddress(),
|
||||
version: V1,
|
||||
derivationPath: path,
|
||||
}, nil
|
||||
}
|
||||
59
libwallet/addresses/v2.go
Normal file
59
libwallet/addresses/v2.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func CreateAddressV2(userKey, muunKey *hdkeychain.ExtendedKey, path string, network *chaincfg.Params) (*WalletAddress, error) {
|
||||
|
||||
script, err := CreateRedeemScriptV2(userKey, muunKey, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate redeem script v2: %w", err)
|
||||
}
|
||||
|
||||
address, err := btcutil.NewAddressScriptHash(script, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate multisig address: %w", err)
|
||||
}
|
||||
|
||||
return &WalletAddress{
|
||||
address: address.EncodeAddress(),
|
||||
version: V2,
|
||||
derivationPath: path,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CreateRedeemScriptV2(userKey, muunKey *hdkeychain.ExtendedKey, network *chaincfg.Params) ([]byte, error) {
|
||||
return createMultisigRedeemScript(userKey, muunKey, network)
|
||||
}
|
||||
|
||||
func createMultisigRedeemScript(userKey, muunKey *hdkeychain.ExtendedKey, network *chaincfg.Params) ([]byte, error) {
|
||||
userPublicKey, err := userKey.ECPubKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userAddress, err := btcutil.NewAddressPubKey(userPublicKey.SerializeCompressed(), network)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to generate address for user")
|
||||
}
|
||||
|
||||
muunPublicKey, err := muunKey.ECPubKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
WalletAddress, err := btcutil.NewAddressPubKey(muunPublicKey.SerializeCompressed(), network)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to generate address for muun")
|
||||
}
|
||||
|
||||
return txscript.MultiSigScript([]*btcutil.AddressPubKey{
|
||||
userAddress,
|
||||
WalletAddress,
|
||||
}, 2)
|
||||
}
|
||||
57
libwallet/addresses/v2_test.go
Executable file
57
libwallet/addresses/v2_test.go
Executable file
@@ -0,0 +1,57 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
var network = &chaincfg.RegressionNetParams
|
||||
|
||||
func TestCreateAddressV2(t *testing.T) {
|
||||
|
||||
const (
|
||||
addressPath = "m/schema:1'/recovery:1'/external:1/0"
|
||||
originAddress = "2NDeWrsJEwvxwVnvtWzPjhDC5B2LYkFuX2s"
|
||||
|
||||
encodedMuunKey = "tpubDBYMnFoxYLdMBZThTk4uARTe4kGPeEYWdKcaEzaUxt1cesetnxtTqmAxVkzDRou51emWytommyLWcF91SdF5KecA6Ja8oHK1FF7d5U2hMxX"
|
||||
encodedUserKey = "tprv8dfM4H5fYJirMai5Er3LguicgUAyxmcSQbFub5ens16amX1e1HAFiW4SXnFVw9nu9FedFQqTPGTTjPEmgfvvXMKww3UcRpFbbC4DFjbCcTb"
|
||||
basePath = "m/schema:1'/recovery:1'"
|
||||
v2EncodedScript = "5221029fa5af7a34c142c1ce348b360abeb7de01df25b1d50129e58a67a6b846c9303b21025714f6b3670d4a38f5e2d6e8f239c9fc072543ce33dca54fcb4f4886a5cb87a652ae"
|
||||
)
|
||||
|
||||
baseMuunKey := parseKey(encodedMuunKey)
|
||||
muunKey := derive(baseMuunKey, basePath, addressPath)
|
||||
|
||||
baseUserKey := parseKey(encodedUserKey)
|
||||
userKey := derive(baseUserKey, basePath, addressPath)
|
||||
|
||||
type args struct {
|
||||
userKey *hdkeychain.ExtendedKey
|
||||
muunKey *hdkeychain.ExtendedKey
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *WalletAddress
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "gen address",
|
||||
args: args{userKey: userKey, muunKey: muunKey},
|
||||
want: &WalletAddress{address: originAddress, derivationPath: addressPath, version: V2}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := CreateAddressV2(tt.args.userKey, tt.args.muunKey, addressPath, network)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreateAddressV2() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("CreateAddressV2() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
55
libwallet/addresses/v3.go
Normal file
55
libwallet/addresses/v3.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
func CreateAddressV3(userKey, muunKey *hdkeychain.ExtendedKey, path string, network *chaincfg.Params) (*WalletAddress, error) {
|
||||
|
||||
redeemScript, err := CreateRedeemScriptV3(userKey, muunKey, network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
address, err := btcutil.NewAddressScriptHash(redeemScript, network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WalletAddress{
|
||||
address: address.EncodeAddress(),
|
||||
version: V3,
|
||||
derivationPath: path,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CreateRedeemScriptV3(userKey, muunKey *hdkeychain.ExtendedKey, network *chaincfg.Params) ([]byte, error) {
|
||||
witnessScript, err := CreateWitnessScriptV3(userKey, muunKey, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate redeem script v3: %w", err)
|
||||
}
|
||||
|
||||
return createNonNativeSegwitRedeemScript(witnessScript)
|
||||
}
|
||||
|
||||
func CreateWitnessScriptV3(userKey, muunKey *hdkeychain.ExtendedKey, network *chaincfg.Params) ([]byte, error) {
|
||||
// createMultisigRedeemScript creates a valid script for both V2 and V3 schemes
|
||||
return createMultisigRedeemScript(userKey, muunKey, network)
|
||||
}
|
||||
|
||||
func createNonNativeSegwitRedeemScript(witnessScript []byte) ([]byte, error) {
|
||||
witnessScriptHash := sha256.Sum256(witnessScript)
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
builder.AddInt64(0)
|
||||
builder.AddData(witnessScriptHash[:])
|
||||
|
||||
return builder.Script()
|
||||
}
|
||||
54
libwallet/addresses/v3_test.go
Executable file
54
libwallet/addresses/v3_test.go
Executable file
@@ -0,0 +1,54 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
func TestCreateAddressV3(t *testing.T) {
|
||||
|
||||
const (
|
||||
addressPath = "m/schema:1'/recovery:1'/external:1/0"
|
||||
|
||||
v3Address = "2MswEXmCLaHQq6pUTtnUVF8wVArfYSqUec5"
|
||||
basePK = "tpubDAN21T1DFREQQS4FvpUktKRBzXXsj5ddenAa5u198hLXvErFFR4Lj8bt8xMG3xnZr6u8mx1vrFW9RwCDXQwQuYRCLq1j9Nr2VJUrENzteQH"
|
||||
baseCosigningPK = "tpubDAsVhzq6otpasovieofhiaY38bSFGyJaBGvrJjBv9whhSnftUXfMTMVrq4BbTXT5A9b78CqqbPuM2j1ZGWdiggd7JHUTZAHh8GXDTt4Pkj9"
|
||||
basePath = "m/schema:1'/recovery:1'"
|
||||
v3EncodedScript = "0020e1fbfbd395aff8b4087fee3e4488815ef659b559b3cd0d6800b5a591efd99f38"
|
||||
)
|
||||
|
||||
baseMuunKey := parseKey(baseCosigningPK)
|
||||
muunKey := derive(baseMuunKey, basePath, addressPath)
|
||||
|
||||
baseUserKey := parseKey(basePK)
|
||||
userKey := derive(baseUserKey, basePath, addressPath)
|
||||
|
||||
type args struct {
|
||||
userKey *hdkeychain.ExtendedKey
|
||||
muunKey *hdkeychain.ExtendedKey
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *WalletAddress
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "gen address",
|
||||
args: args{userKey: userKey, muunKey: muunKey},
|
||||
want: &WalletAddress{address: v3Address, derivationPath: addressPath, version: V3}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := CreateAddressV3(tt.args.userKey, tt.args.muunKey, addressPath, network)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreateAddressV3() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("CreateAddressV3() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
36
libwallet/addresses/v4.go
Normal file
36
libwallet/addresses/v4.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
// CreateAddressV4 returns a P2WSH WalletAddress from a user HD-pubkey and a Muun co-signing HD-pubkey.
|
||||
func CreateAddressV4(userKey, muunKey *hdkeychain.ExtendedKey, path string, network *chaincfg.Params) (*WalletAddress, error) {
|
||||
|
||||
witnessScript, err := CreateWitnessScriptV4(userKey, muunKey, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate witness script v4: %w", err)
|
||||
}
|
||||
witnessScript256 := sha256.Sum256(witnessScript)
|
||||
|
||||
address, err := btcutil.NewAddressWitnessScriptHash(witnessScript256[:], network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WalletAddress{
|
||||
address: address.EncodeAddress(),
|
||||
version: V4,
|
||||
derivationPath: path,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CreateWitnessScriptV4(userKey, muunKey *hdkeychain.ExtendedKey, network *chaincfg.Params) ([]byte, error) {
|
||||
// createMultisigRedeemScript creates a valid script for V2, V3 and V4 schemes
|
||||
return createMultisigRedeemScript(userKey, muunKey, network)
|
||||
}
|
||||
52
libwallet/addresses/v4_test.go
Executable file
52
libwallet/addresses/v4_test.go
Executable file
@@ -0,0 +1,52 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
func TestCreateAddressV4(t *testing.T) {
|
||||
const (
|
||||
addressPath = "m/schema:1'/recovery:1'/external:1/2"
|
||||
|
||||
v4Address = "bcrt1qrs3vk4dzv70syck2qdz3g06tgckq4pftenuk5p77st9glnskpvtqe2tvvk"
|
||||
basePK = "tpubDBf5wCeqg3KrLJiXaveDzD5JtFJ1ss9NVvFMx4RYS73SjwPEEawcAQ7V1B5DGM4gunWDeYNrnkc49sUaf7mS1wUKiJJQD6WEctExUQoLvrg"
|
||||
baseCosigningPK = "tpubDB22PFkUaHoB7sgxh7exCivV5rAevVSzbB8WkFCCdbHq39r8xnYexiot4NGbi8PM6E1ySVeaHsoDeMYb6EMndpFrzVmuX8iQNExzwNpU61B"
|
||||
basePath = "m/schema:1'/recovery:1'"
|
||||
)
|
||||
|
||||
baseMuunKey := parseKey(baseCosigningPK)
|
||||
muunKey := derive(baseMuunKey, basePath, addressPath)
|
||||
|
||||
baseUserKey := parseKey(basePK)
|
||||
userKey := derive(baseUserKey, basePath, addressPath)
|
||||
|
||||
type args struct {
|
||||
userKey *hdkeychain.ExtendedKey
|
||||
muunKey *hdkeychain.ExtendedKey
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *WalletAddress
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "gen bech32 address",
|
||||
args: args{userKey: userKey, muunKey: muunKey},
|
||||
want: &WalletAddress{address: v4Address, derivationPath: addressPath, version: V4}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := CreateAddressV4(tt.args.userKey, tt.args.muunKey, addressPath, network)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CreateAddressV4() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("CreateAddressV4() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
50
libwallet/addresses/v5.go
Normal file
50
libwallet/addresses/v5.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
"github.com/muun/libwallet/btcsuitew/btcutilw"
|
||||
"github.com/muun/libwallet/musig"
|
||||
)
|
||||
|
||||
// CreateAddressV5 returns a P2TR WalletAddress using Musig with the signing and cosigning keys.
|
||||
func CreateAddressV5(userKey, muunKey *hdkeychain.ExtendedKey, path string, network *chaincfg.Params) (*WalletAddress, error) {
|
||||
witnessProgram, err := CreateWitnessScriptV5(userKey, muunKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate witness script v5: %w", err)
|
||||
}
|
||||
|
||||
address, err := btcutilw.NewAddressTaprootKey(witnessProgram, network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WalletAddress{
|
||||
address: address.EncodeAddress(),
|
||||
version: V5,
|
||||
derivationPath: path,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CreateWitnessScriptV5(userKey, muunKey *hdkeychain.ExtendedKey) ([]byte, error) {
|
||||
userPublicKey, err := userKey.ECPubKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
muunPublicKey, err := muunKey.ECPubKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
combined, err := musig.CombinePubKeysWithTweak(userPublicKey, muunPublicKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
xOnlyCombined := combined.SerializeCompressed()[1:]
|
||||
|
||||
return xOnlyCombined, nil
|
||||
}
|
||||
34
libwallet/addresses/v5_test.go
Normal file
34
libwallet/addresses/v5_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package addresses
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateAddressV5(t *testing.T) {
|
||||
const (
|
||||
addressPath = "m/schema:1'/recovery:1'/external:1/17"
|
||||
|
||||
v5Address = "bcrt1pvqngr85tm8hmsv2hjyrejlpsy7u65f7vke8mmrxnyuj3aj3xsapqvh8yrf"
|
||||
basePK = "tpubDBf5wCeqg3KrLJiXaveDzD5JtFJ1ss9NVvFMx4RYS73SjwPEEawcAQ7V1B5DGM4gunWDeYNrnkc49sUaf7mS1wUKiJJQD6WEctExUQoLvrg"
|
||||
baseCosigningPK = "tpubDB22PFkUaHoB7sgxh7exCivV5rAevVSzbB8WkFCCdbHq39r8xnYexiot4NGbi8PM6E1ySVeaHsoDeMYb6EMndpFrzVmuX8iQNExzwNpU61B"
|
||||
basePath = "m/schema:1'/recovery:1'"
|
||||
)
|
||||
|
||||
baseMuunKey := parseKey(baseCosigningPK)
|
||||
muunKey := derive(baseMuunKey, basePath, addressPath)
|
||||
|
||||
baseUserKey := parseKey(basePK)
|
||||
userKey := derive(baseUserKey, basePath, addressPath)
|
||||
|
||||
expectedAddr := &WalletAddress{address: v5Address, derivationPath: addressPath, version: V5}
|
||||
|
||||
actualAddr, err := CreateAddressV5(userKey, muunKey, addressPath, network)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actualAddr, expectedAddr) {
|
||||
t.Errorf("Created v5 address %v, expected %v", actualAddr, expectedAddr)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user