package bip85 import ( "bytes" "encoding/hex" "fmt" "strings" "testing" "github.com/tyler-smith/go-bip39" ) const ( // Test master BIP32 root key from the BIP85 specification testMasterKey = "xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb" ) // logTestVector logs test information to make it clear what's being tested func logTestVector(t *testing.T, title, description string) { t.Logf("TEST VECTOR: %s", title) t.Logf("FROM BIP85 SPECIFICATION: %s", description) } // TestDerivedKey is a helper function to test the derived key directly func TestDerivedKey(t *testing.T) { logTestVector(t, "Derived Child Keys", "Testing direct key derivation for BIP85 paths") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Test case 1 path := "m/83696968'/0'/0'" t.Logf("Deriving key for path: %s", path) derivedKeyBytes, err := DeriveChildKey(masterKey, path) if err != nil { t.Fatalf("Failed to derive child key: %v", err) } derivedKeyHex := hex.EncodeToString(derivedKeyBytes) expectedKeyHex := "cca20ccb0e9a90feb0912870c3323b24874b0ca3d8018c4b96d0b97c0e82ded0" t.Logf("EXPECTED: %s", expectedKeyHex) t.Logf("ACTUAL: %s", derivedKeyHex) if derivedKeyHex != expectedKeyHex { t.Errorf("Expected derived key bytes %s, got %s", expectedKeyHex, derivedKeyHex) } else { t.Logf("RESULT: PASS ✓") } // Test case 2 path = "m/83696968'/0'/1'" t.Logf("Deriving key for path: %s", path) derivedKeyBytes, err = DeriveChildKey(masterKey, path) if err != nil { t.Fatalf("Failed to derive child key: %v", err) } derivedKeyHex = hex.EncodeToString(derivedKeyBytes) expectedKeyHex = "503776919131758bb7de7beb6c0ae24894f4ec042c26032890c29359216e21ba" t.Logf("EXPECTED: %s", expectedKeyHex) t.Logf("ACTUAL: %s", derivedKeyHex) if derivedKeyHex != expectedKeyHex { t.Errorf("Expected derived key bytes %s, got %s", expectedKeyHex, derivedKeyHex) } else { t.Logf("RESULT: PASS ✓") } } // TestCase1 tests the first test vector from the BIP85 specification func TestCase1(t *testing.T) { logTestVector(t, "Test Case 1", "Basic entropy derivation with path m/83696968'/0'/0'") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } path := "m/83696968'/0'/0'" t.Logf("Test path: %s", path) entropy, err := DeriveBIP85Entropy(masterKey, path) if err != nil { t.Fatalf("Failed to derive entropy: %v", err) } derivedEntropyHex := hex.EncodeToString(entropy) expectedDerivedEntropy := "efecfbccffea313214232d29e71563d941229afb4338c21f9517c41aaa0d16f00b83d2a09ef747e7a64e8e2bd5a14869e693da66ce94ac2da570ab7ee48618f7" t.Logf("EXPECTED: %s", expectedDerivedEntropy) t.Logf("ACTUAL: %s", derivedEntropyHex) if derivedEntropyHex != expectedDerivedEntropy { t.Errorf("Expected derived entropy %s, got %s", expectedDerivedEntropy, derivedEntropyHex) } else { t.Logf("RESULT: PASS ✓") } } // TestCase2 tests the second test vector from the BIP85 specification func TestCase2(t *testing.T) { logTestVector(t, "Test Case 2", "Basic entropy derivation with path m/83696968'/0'/1'") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } path := "m/83696968'/0'/1'" t.Logf("Test path: %s", path) entropy, err := DeriveBIP85Entropy(masterKey, path) if err != nil { t.Fatalf("Failed to derive entropy: %v", err) } derivedEntropyHex := hex.EncodeToString(entropy) expectedDerivedEntropy := "70c6e3e8ebee8dc4c0dbba66076819bb8c09672527c4277ca8729532ad711872218f826919f6b67218adde99018a6df9095ab2b58d803b5b93ec9802085a690e" t.Logf("EXPECTED: %s", expectedDerivedEntropy) t.Logf("ACTUAL: %s", derivedEntropyHex) if derivedEntropyHex != expectedDerivedEntropy { t.Errorf("Expected derived entropy %s, got %s", expectedDerivedEntropy, derivedEntropyHex) } else { t.Logf("RESULT: PASS ✓") } } // TestBIP39_12EnglishWords tests the BIP39 12 English words test vector func TestBIP39_12EnglishWords(t *testing.T) { logTestVector(t, "BIP39 12 English Words", "Deriving a 12-word English BIP39 mnemonic") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } t.Logf("Path: m/83696968'/39'/0'/12'/0'") t.Logf("Parameters: Language=English(0), Words=12, Index=0") // BIP39 English 12 word mnemonic entropy, err := DeriveBIP39Entropy(masterKey, 0, 12, 0) if err != nil { t.Fatalf("Failed to derive BIP39 entropy: %v", err) } derivedEntropyHex := hex.EncodeToString(entropy) expectedDerivedEntropy := "6250b68daf746d12a24d58b4787a714b" t.Logf("EXPECTED ENTROPY: %s", expectedDerivedEntropy) t.Logf("ACTUAL ENTROPY: %s", derivedEntropyHex) if derivedEntropyHex != expectedDerivedEntropy { t.Errorf("Expected derived entropy %s, got %s", expectedDerivedEntropy, derivedEntropyHex) } else { t.Logf("ENTROPY MATCH: PASS ✓") } // Convert entropy to mnemonic mnemonic, err := bip39.NewMnemonic(entropy) if err != nil { t.Fatalf("Failed to create mnemonic: %v", err) } expectedMnemonic := "girl mad pet galaxy egg matter matrix prison refuse sense ordinary nose" t.Logf("EXPECTED MNEMONIC: %s", expectedMnemonic) t.Logf("ACTUAL MNEMONIC: %s", mnemonic) if mnemonic != expectedMnemonic { t.Errorf("Expected mnemonic '%s', got '%s'", expectedMnemonic, mnemonic) } else { t.Logf("MNEMONIC MATCH: PASS ✓") } } // TestBIP39_18EnglishWords tests the BIP39 18 English words test vector func TestBIP39_18EnglishWords(t *testing.T) { logTestVector(t, "BIP39 18 English Words", "Deriving an 18-word English BIP39 mnemonic") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } t.Logf("Path: m/83696968'/39'/0'/18'/0'") t.Logf("Parameters: Language=English(0), Words=18, Index=0") // BIP39 English 18 word mnemonic entropy, err := DeriveBIP39Entropy(masterKey, 0, 18, 0) if err != nil { t.Fatalf("Failed to derive BIP39 entropy: %v", err) } derivedEntropyHex := hex.EncodeToString(entropy) expectedDerivedEntropy := "938033ed8b12698449d4bbca3c853c66b293ea1b1ce9d9dc" t.Logf("EXPECTED ENTROPY: %s", expectedDerivedEntropy) t.Logf("ACTUAL ENTROPY: %s", derivedEntropyHex) if derivedEntropyHex != expectedDerivedEntropy { t.Errorf("Expected derived entropy %s, got %s", expectedDerivedEntropy, derivedEntropyHex) } else { t.Logf("ENTROPY MATCH: PASS ✓") } // Convert entropy to mnemonic mnemonic, err := bip39.NewMnemonic(entropy) if err != nil { t.Fatalf("Failed to create mnemonic: %v", err) } expectedMnemonic := "near account window bike charge season chef number sketch tomorrow excuse sniff circle vital hockey outdoor supply token" t.Logf("EXPECTED MNEMONIC: %s", expectedMnemonic) t.Logf("ACTUAL MNEMONIC: %s", mnemonic) if mnemonic != expectedMnemonic { t.Errorf("Expected mnemonic '%s', got '%s'", expectedMnemonic, mnemonic) } else { t.Logf("MNEMONIC MATCH: PASS ✓") } } // TestBIP39_24EnglishWords tests the BIP39 24 English words test vector func TestBIP39_24EnglishWords(t *testing.T) { logTestVector(t, "BIP39 24 English Words", "Deriving a 24-word English BIP39 mnemonic") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } t.Logf("Path: m/83696968'/39'/0'/24'/0'") t.Logf("Parameters: Language=English(0), Words=24, Index=0") // BIP39 English 24 word mnemonic entropy, err := DeriveBIP39Entropy(masterKey, 0, 24, 0) if err != nil { t.Fatalf("Failed to derive BIP39 entropy: %v", err) } derivedEntropyHex := hex.EncodeToString(entropy) expectedDerivedEntropy := "ae131e2312cdc61331542efe0d1077bac5ea803adf24b313a4f0e48e9c51f37f" t.Logf("EXPECTED ENTROPY: %s", expectedDerivedEntropy) t.Logf("ACTUAL ENTROPY: %s", derivedEntropyHex) if derivedEntropyHex != expectedDerivedEntropy { t.Errorf("Expected derived entropy %s, got %s", expectedDerivedEntropy, derivedEntropyHex) } else { t.Logf("ENTROPY MATCH: PASS ✓") } // Convert entropy to mnemonic mnemonic, err := bip39.NewMnemonic(entropy) if err != nil { t.Fatalf("Failed to create mnemonic: %v", err) } expectedMnemonic := "puppy ocean match cereal symbol another shed magic wrap hammer bulb intact gadget divorce twin tonight reason outdoor destroy simple truth cigar social volcano" t.Logf("EXPECTED MNEMONIC: %s", expectedMnemonic) t.Logf("ACTUAL MNEMONIC: %s", mnemonic) if mnemonic != expectedMnemonic { t.Errorf("Expected mnemonic '%s', got '%s'", expectedMnemonic, mnemonic) } else { t.Logf("MNEMONIC MATCH: PASS ✓") } } // TestHD_WIF tests the WIF test vector func TestHD_WIF(t *testing.T) { logTestVector(t, "HD-Seed WIF", "Deriving a WIF-encoded private key for Bitcoin Core hdseed") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } t.Logf("Path: m/83696968'/2'/0'") wif, err := DeriveWIFKey(masterKey, 0) if err != nil { t.Fatalf("Failed to derive WIF key: %v", err) } expectedWIF := "Kzyv4uF39d4Jrw2W7UryTHwZr1zQVNk4dAFyqE6BuMrMh1Za7uhp" t.Logf("EXPECTED WIF: %s", expectedWIF) t.Logf("ACTUAL WIF: %s", wif) if wif != expectedWIF { t.Errorf("Expected WIF %s, got %s", expectedWIF, wif) } else { t.Logf("RESULT: PASS ✓") } } // TestXPRV tests the XPRV test vector func TestXPRV(t *testing.T) { logTestVector(t, "XPRV", "Deriving an extended private key (XPRV)") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } t.Logf("Path: m/83696968'/32'/0'") derivedKey, err := DeriveXPRV(masterKey, 0) if err != nil { t.Fatalf("Failed to derive XPRV: %v", err) } expectedXPRV := "xprv9s21ZrQH143K2srSbCSg4m4kLvPMzcWydgmKEnMmoZUurYuBuYG46c6P71UGXMzmriLzCCBvKQWBUv3vPB3m1SATMhp3uEjXHJ42jFg7myX" derivedXPRV := derivedKey.String() t.Logf("EXPECTED XPRV: %s", expectedXPRV) t.Logf("ACTUAL XPRV: %s", derivedXPRV) if derivedXPRV != expectedXPRV { t.Errorf("Expected XPRV %s, got %s", expectedXPRV, derivedXPRV) } else { t.Logf("RESULT: PASS ✓") } } // TestDRNG_SHAKE256 tests the BIP85-DRNG-SHAKE256 test vector func TestDRNG_SHAKE256(t *testing.T) { logTestVector(t, "DRNG-SHAKE256", "Testing the deterministic random number generator with SHAKE256") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Derive entropy for the DRNG path := "m/83696968'/0'/0'" t.Logf("Deriving entropy from path: %s", path) entropy, err := DeriveBIP85Entropy(masterKey, path) if err != nil { t.Fatalf("Failed to derive entropy: %v", err) } // Create DRNG drng := NewBIP85DRNG(entropy) // Read 80 bytes t.Logf("Reading 80 bytes from DRNG") buffer := make([]byte, 80) n, err := drng.Read(buffer) if err != nil { t.Fatalf("Failed to read from DRNG: %v", err) } if n != 80 { t.Errorf("Expected to read 80 bytes, got %d", n) } hexOutput := hex.EncodeToString(buffer) expectedOutput := "b78b1ee6b345eae6836c2d53d33c64cdaf9a696487be81b03e822dc84b3f1cd883d7559e53d175f243e4c349e822a957bbff9224bc5dde9492ef54e8a439f6bc8c7355b87a925a37ee405a7502991111" t.Logf("EXPECTED: %s", expectedOutput) t.Logf("ACTUAL: %s", hexOutput) if !strings.EqualFold(hexOutput, expectedOutput) { t.Errorf("Expected DRNG output %s, got %s", expectedOutput, hexOutput) } else { t.Logf("RESULT: PASS ✓") } } // TestDiceRolls tests the dice rolls application func TestDiceRolls(t *testing.T) { logTestVector(t, "Dice Rolls", "Generating deterministic dice rolls") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Derive 10 rolls of a 6-sided die t.Logf("Path: m/83696968'/89101'/6'/10'/0'") t.Logf("Parameters: Sides=6, Rolls=10, Index=0") rolls, err := DeriveDiceRolls(masterKey, 6, 10, 0) if err != nil { t.Fatalf("Failed to derive dice rolls: %v", err) } // Expected rolls from the specification expectedRolls := []uint32{1, 0, 0, 2, 0, 1, 5, 5, 2, 4} t.Logf("EXPECTED ROLLS: %v", expectedRolls) t.Logf("ACTUAL ROLLS: %v", rolls) if len(rolls) != len(expectedRolls) { t.Errorf("Expected %d rolls, got %d", len(expectedRolls), len(rolls)) } else { match := true for i, expected := range expectedRolls { if rolls[i] != expected { t.Errorf("Roll %d: expected %d, got %d", i, expected, rolls[i]) match = false } } if match { t.Logf("RESULT: PASS ✓") } } // Show rolls in a more readable format rollStr := "" for _, roll := range rolls { rollStr += fmt.Sprintf("%d,", roll) } rollStr = strings.TrimSuffix(rollStr, ",") t.Logf("Roll sequence: %s", rollStr) } // TestPWDBase64 tests the Base64 password test vector func TestPWDBase64(t *testing.T) { logTestVector(t, "PWD Base64", "Deriving a Base64-encoded password") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Testing with the example from the BIP85 spec - 21 characters t.Logf("Path: m/83696968'/707764'/21'/0'") t.Logf("Parameters: Length=21, Index=0") pwd, err := DeriveBase64Password(masterKey, 21, 0) if err != nil { t.Fatalf("Failed to derive Base64 password: %v", err) } // The test vector from the BIP85 specification expectedPwd := "dKLoepugzdVJvdL56ogNV" t.Logf("EXPECTED PASSWORD: %s", expectedPwd) t.Logf("ACTUAL PASSWORD: %s", pwd) if pwd != expectedPwd { t.Errorf("Expected password '%s', got '%s'", expectedPwd, pwd) } else { t.Logf("RESULT: PASS ✓") } t.Logf("Password length: %d characters", len(pwd)) } // TestPWDBase85 tests the Base85 password test vector func TestPWDBase85(t *testing.T) { logTestVector(t, "PWD Base85", "Deriving a Base85-encoded password") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Testing with the example from the BIP85 spec - 12 characters t.Logf("Path: m/83696968'/707785'/12'/0'") t.Logf("Parameters: Length=12, Index=0") pwd, err := DeriveBase85Password(masterKey, 12, 0) if err != nil { t.Fatalf("Failed to derive Base85 password: %v", err) } // The test vector from the BIP85 specification expectedPwd := "_s`{TW89)i4`" t.Logf("EXPECTED PASSWORD: %s", expectedPwd) t.Logf("ACTUAL PASSWORD: %s", pwd) if pwd != expectedPwd { t.Errorf("Expected password '%s', got '%s'", expectedPwd, pwd) } else { t.Logf("RESULT: PASS ✓") } t.Logf("Password length: %d characters", len(pwd)) } // TestInvalidParameters tests error conditions for parameter validation func TestInvalidParameters(t *testing.T) { logTestVector(t, "Invalid Parameters", "Testing error handling for invalid inputs") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Test cases for parameter validation testCases := []struct { name string testFunc func() error }{ { name: "BIP39 invalid word count", testFunc: func() error { _, err := DeriveBIP39Entropy(masterKey, 0, 13, 0) // 13 is not valid (must be 12, 15, 18, 21, 24) return err }, }, { name: "Base64 password too short", testFunc: func() error { _, err := DeriveBase64Password(masterKey, 19, 0) // Min is 20 return err }, }, { name: "Base64 password too long", testFunc: func() error { _, err := DeriveBase64Password(masterKey, 87, 0) // Max is 86 return err }, }, { name: "Base85 password too short", testFunc: func() error { _, err := DeriveBase85Password(masterKey, 9, 0) // Min is 10 return err }, }, { name: "Base85 password too long", testFunc: func() error { _, err := DeriveBase85Password(masterKey, 81, 0) // Max is 80 return err }, }, { name: "Hex data too small", testFunc: func() error { _, err := DeriveHex(masterKey, 15, 0) // Min is 16 return err }, }, { name: "Hex data too large", testFunc: func() error { _, err := DeriveHex(masterKey, 65, 0) // Max is 64 return err }, }, { name: "Dice roll invalid sides", testFunc: func() error { _, err := DeriveDiceRolls(masterKey, 1, 10, 0) // Min sides is 2 return err }, }, { name: "Dice roll zero rolls", testFunc: func() error { _, err := DeriveDiceRolls(masterKey, 6, 0, 0) // Min rolls is 1 return err }, }, } // Run all validation test cases for _, tc := range testCases { t.Logf("Testing: %s", tc.name) err := tc.testFunc() if err == nil { t.Errorf("Expected error for %s, but got nil", tc.name) } else { t.Logf("Got expected error: %v", err) t.Logf("RESULT: PASS ✓") } } } // TestAdditionalDeriveHex tests additional hex derivation scenarios func TestAdditionalDeriveHex(t *testing.T) { logTestVector(t, "Additional Hex Derivation", "Testing hex data derivation with various lengths") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Test min size (16 bytes) hexMinBytes, err := DeriveHex(masterKey, 16, 0) if err != nil { t.Fatalf("Failed to derive 16-byte hex: %v", err) } t.Logf("16-byte hex: %s", hexMinBytes) if len(hexMinBytes) != 32 { // 16 bytes = 32 hex chars t.Errorf("Expected 32 hex chars (16 bytes), got %d chars", len(hexMinBytes)) } else { t.Logf("RESULT: PASS ✓") } // Test max size (64 bytes) hexMaxBytes, err := DeriveHex(masterKey, 64, 0) if err != nil { t.Fatalf("Failed to derive 64-byte hex: %v", err) } t.Logf("64-byte hex: %s", hexMaxBytes) if len(hexMaxBytes) != 128 { // 64 bytes = 128 hex chars t.Errorf("Expected 128 hex chars (64 bytes), got %d chars", len(hexMaxBytes)) } else { t.Logf("RESULT: PASS ✓") } // Test different index values hex1, err := DeriveHex(masterKey, 32, 0) if err != nil { t.Fatalf("Failed to derive hex with index 0: %v", err) } hex2, err := DeriveHex(masterKey, 32, 1) if err != nil { t.Fatalf("Failed to derive hex with index 1: %v", err) } t.Logf("Hex index 0: %s", hex1) t.Logf("Hex index 1: %s", hex2) if hex1 == hex2 { t.Errorf("Expected different hex values for different indexes") } else { t.Logf("Different indexes produced different outputs: PASS ✓") } } // TestDRNGDifferentSizes tests the DRNG with different buffer sizes func TestDRNGDifferentSizes(t *testing.T) { logTestVector(t, "DRNG Different Sizes", "Testing the DRNG with different buffer sizes") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } path := "m/83696968'/0'/0'" entropy, err := DeriveBIP85Entropy(masterKey, path) if err != nil { t.Fatalf("Failed to derive entropy: %v", err) } // Create DRNG drng := NewBIP85DRNG(entropy) // Test reading different sizes for _, size := range []int{32, 64, 128, 256} { t.Logf("Reading %d bytes from DRNG", size) buffer := make([]byte, size) n, err := drng.Read(buffer) if err != nil { t.Fatalf("Failed to read %d bytes from DRNG: %v", size, err) } if n != size { t.Errorf("Expected to read %d bytes, got %d", size, n) } else { t.Logf("Successfully read %d bytes: PASS ✓", size) } } // Test deterministic behavior - two DRNGs with the same seed should produce the same output drng1 := NewBIP85DRNG(entropy) drng2 := NewBIP85DRNG(entropy) buffer1 := make([]byte, 32) buffer2 := make([]byte, 32) _, err = drng1.Read(buffer1) if err != nil { t.Fatalf("Failed to read from first DRNG: %v", err) } _, err = drng2.Read(buffer2) if err != nil { t.Fatalf("Failed to read from second DRNG: %v", err) } if !bytes.Equal(buffer1, buffer2) { t.Errorf("Expected identical outputs from DRNGs with same seed") } else { t.Logf("DRNGs with same seed produced identical outputs: PASS ✓") } // Reading another 32 bytes should produce different output from the first read buffer3 := make([]byte, 32) _, err = drng1.Read(buffer3) if err != nil { t.Fatalf("Failed to read second buffer from DRNG: %v", err) } if bytes.Equal(buffer1, buffer3) { t.Errorf("Expected different outputs from sequential reads") } else { t.Logf("Sequential reads produced different outputs: PASS ✓") } } // TestMasterKeyParsing tests parsing of different master key formats func TestMasterKeyParsing(t *testing.T) { logTestVector(t, "Master Key Parsing", "Testing parsing of master keys in different formats") // Test valid master key t.Logf("Testing valid master key") _, err := ParseMasterKey(testMasterKey) if err != nil { t.Errorf("Failed to parse valid master key: %v", err) } else { t.Logf("Valid master key parsed successfully: PASS ✓") } // Test invalid master key (wrong checksum) t.Logf("Testing invalid master key (corrupted)") invalidKey := "xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbXX" _, err = ParseMasterKey(invalidKey) if err == nil { t.Errorf("Expected error for invalid master key, but got nil") } else { t.Logf("Got expected error for invalid master key: %v", err) t.Logf("RESULT: PASS ✓") } // Test testnet master key (tprv) t.Logf("Testing testnet master key format") testnetKey := "tprv8ZgxMBicQKsPeWHBt7a68nPnvgTnuDhUgDWC8wZCgA8GahrQ3f3uWpq7wE7Uc1dLBnCe1hhCZ886K6ND37memRDWqsA9HgSKDXtwh2Qxo6J" testnetMasterKey, err := ParseMasterKey(testnetKey) if err != nil { t.Errorf("Failed to parse testnet master key: %v", err) } else { t.Logf("Testnet master key parsed successfully: PASS ✓") // Test that XPRV derivation using a testnet master key produces a testnet XPRV derivedKey, err := DeriveXPRV(testnetMasterKey, 0) if err != nil { t.Fatalf("Failed to derive XPRV from testnet key: %v", err) } derivedKeyStr := derivedKey.String() if !strings.HasPrefix(derivedKeyStr, "tprv") { t.Errorf("Expected derived key to be testnet (tprv prefix), got: %s", derivedKeyStr) } else { t.Logf("Testnet XPRV derived successfully: %s", derivedKeyStr) t.Logf("RESULT: PASS ✓") } } } // TestDifferentPathFormats tests different path format expressions func TestDifferentPathFormats(t *testing.T) { logTestVector(t, "Path Formats", "Testing different path format expressions") masterKey, err := ParseMasterKey(testMasterKey) if err != nil { t.Fatalf("Failed to parse master key: %v", err) } // Define equivalent paths in different formats paths := []string{ "m/83696968'/0'/0'", "m/83696968h/0h/0h", "/83696968'/0'/0'", "83696968'/0'/0'", } var results [][]byte // Derive entropy using each path for i, path := range paths { t.Logf("Testing path format %d: %s", i+1, path) entropy, err := DeriveBIP85Entropy(masterKey, path) if err != nil { t.Errorf("Failed to derive entropy with path %s: %v", path, err) continue } results = append(results, entropy) t.Logf("Derivation succeeded: PASS ✓") } // Verify all results are the same for i := 1; i < len(results); i++ { if !bytes.Equal(results[0], results[i]) { t.Errorf("Path %s produced different entropy than path %s", paths[0], paths[i]) } } if len(results) > 1 { t.Logf("All equivalent path formats produced the same entropy: PASS ✓") } }