123 lines
3.3 KiB
Go
123 lines
3.3 KiB
Go
package bitcoin
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
|
"github.com/btcsuite/btcd/chaincfg"
|
|
"github.com/tyler-smith/go-bip39"
|
|
)
|
|
|
|
const (
|
|
testMnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
|
)
|
|
|
|
func TestDeriveAddresses(t *testing.T) {
|
|
seed := bip39.NewSeed(testMnemonic, "")
|
|
|
|
addresses, err := DeriveAddresses(seed, 5)
|
|
if err != nil {
|
|
t.Fatalf("DeriveAddresses failed: %v", err)
|
|
}
|
|
|
|
// We expect 5 addresses per path * 3 paths = 15 addresses
|
|
expectedCount := 5 * len(StandardPaths)
|
|
if len(addresses) != expectedCount {
|
|
t.Errorf("Expected %d addresses, got %d", expectedCount, len(addresses))
|
|
}
|
|
|
|
// Test known addresses for the test mnemonic
|
|
expectedAddresses := map[string]string{
|
|
"m/44'/0'/0'/0/0": "1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA",
|
|
"m/84'/0'/0'/0/0": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
|
|
}
|
|
|
|
addressMap := make(map[string]string)
|
|
for _, addr := range addresses {
|
|
addressMap[addr.Path] = addr.Address
|
|
}
|
|
|
|
for path, expectedAddr := range expectedAddresses {
|
|
if actualAddr, exists := addressMap[path]; !exists {
|
|
t.Errorf("Address for path %s not found", path)
|
|
} else if actualAddr != expectedAddr {
|
|
t.Errorf("Address mismatch for path %s: expected %s, got %s", path, expectedAddr, actualAddr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDerivePathAddresses(t *testing.T) {
|
|
seed := bip39.NewSeed(testMnemonic, "")
|
|
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create master key: %v", err)
|
|
}
|
|
|
|
tests := []struct {
|
|
path DerivationPath
|
|
addressIndex int
|
|
expectedAddress string
|
|
}{
|
|
{
|
|
path: StandardPaths[0], // BIP44
|
|
addressIndex: 0,
|
|
expectedAddress: "1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA",
|
|
},
|
|
{
|
|
path: StandardPaths[1], // BIP49
|
|
addressIndex: 0,
|
|
expectedAddress: "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
|
|
},
|
|
{
|
|
path: StandardPaths[2], // BIP84
|
|
addressIndex: 0,
|
|
expectedAddress: "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.path.Name, func(t *testing.T) {
|
|
addresses, err := derivePathAddresses(masterKey, tt.path, 5)
|
|
if err != nil {
|
|
t.Fatalf("derivePathAddresses failed: %v", err)
|
|
}
|
|
|
|
if len(addresses) != 5 {
|
|
t.Errorf("Expected 5 addresses, got %d", len(addresses))
|
|
}
|
|
|
|
if addresses[tt.addressIndex].Address != tt.expectedAddress {
|
|
t.Errorf("Address mismatch: expected %s, got %s",
|
|
tt.expectedAddress, addresses[tt.addressIndex].Address)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeriveAddressesWithPassphrase(t *testing.T) {
|
|
seed := bip39.NewSeed(testMnemonic, "TREZOR")
|
|
|
|
addresses, err := DeriveAddresses(seed, 1)
|
|
if err != nil {
|
|
t.Fatalf("DeriveAddresses failed: %v", err)
|
|
}
|
|
|
|
// With passphrase, addresses should be different
|
|
if len(addresses) == 0 {
|
|
t.Error("Expected addresses to be generated")
|
|
}
|
|
|
|
// The first BIP44 address with "TREZOR" passphrase should be different
|
|
addressMap := make(map[string]string)
|
|
for _, addr := range addresses {
|
|
addressMap[addr.Path] = addr.Address
|
|
}
|
|
|
|
// Should NOT match the address without passphrase
|
|
if addr, exists := addressMap["m/44'/0'/0'/0/0"]; exists {
|
|
if addr == "1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA" {
|
|
t.Error("Address should be different with passphrase")
|
|
}
|
|
}
|
|
}
|