def test_root_address_derivation_scheme(self): mnemonic = "all all all all all all all all all all all all" passphrase = "" node = bip32.from_mnemonic_cardano(mnemonic, passphrase) # 44'/1815' address, _ = derive_address_and_node( node, [0x80000000 | 44, 0x80000000 | 1815]) self.assertEqual( address, "Ae2tdPwUPEZ2FGHX3yCKPSbSgyuuTYgMxNq652zKopxT4TuWvEd8Utd92w3") priv, ext, pub, chain = ( b"204ec79cbb6502a141de60d274962010c7f1c94a2987b26506433184d228ed51", b"975cdd1c8610b44701567f05934c45c8716064263ccfe72ed2167ccb705c09b6", b"8c47ebce34234d04fd3dfbac33feaba6133e4e3d77c4b5ab18120ec6878ad4ce", b"02ac67c59a8b0264724a635774ca2c242afa10d7ab70e2bf0a8f7d4bb10f1f7a" ) _, n = derive_address_and_node(node, [0x80000000 | 44, 0x80000000 | 1815]) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) self.assertEqual(hexlify(n.chain_code()), chain)
def test_hardened_address_derivation_scheme(self): mnemonic = "all all all all all all all all all all all all" passphrase = "" node = bip32.from_mnemonic_cardano(mnemonic, passphrase) node.derive_cardano(0x80000000 | 44) node.derive_cardano(0x80000000 | 1815) keychain = Keychain(node) addresses = [ "Ae2tdPwUPEZ98eHFwxSsPBDz73amioKpr58Vw85mP1tMkzq8siaftiejJ3j", "Ae2tdPwUPEZKA971NCHuHqaEnxZDFWPzH3fEsLpDnbEpG6UeMRHnRzCzEwK", "Ae2tdPwUPEZL9Ag1ouS4b1zjuPxKpvEUgjpVpG1KQFs5pNewQb65F1WXVQ2", ] for i, expected in enumerate(addresses): # 44'/1815'/0'/0/i' address, _ = derive_address_and_node(keychain, [ 0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i ]) self.assertEqual(expected, address) nodes = [ (b"3881a8de77d069001010d7f7d5211552e7d539b0e253add710367f95e528ed51", b"9b77608b38e0a0c7861aa234557c81482f42aae2d17993a8ddaec1868fb04d60", b"a938c8554ae04616cfaae7cd0eb557475082c4e910242ce774967e0bd7492408", b"cbf6ab47c8eb1a0477fc40b25dbb6c4a99454edb97d6fe5acedd3e238ef46fe0" ), (b"3003aca659846540b9ed04f2b844f2d8ea964856ca38a7dffedef4f6e528ed51", b"8844ccc81d633e1c7126f30c2524c1652617cf58da755014070215bf5070ba38", b"be28c00ed6cb9b70310f78028f8e3a2db935baf482d84afa590b0b5b864571cc", b"584b4631d752023a249e980779517280e6c0b3ac7a7f27c6e9456bfd228ca60b" ), (b"68e4482add0a741e14c8f2306bf83206a623e3729dd24175915eedece428ed51", b"3165a80c5efe846224d46a0427cdb2be4f31ea3585c51f4131faefc4328ad95a", b"9a32499976ffb582daa9988dfc42a303de5ed00c320c929f496be3c6eb1cf405", b"da07ca30a3d1c5fe3c34ce5fa197722446a646624a10bdf8889a4b9c347b2ef2" ), ] for i, (priv, ext, pub, chain) in enumerate(nodes): _, n = derive_address_and_node(keychain, [ 0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i ]) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual( hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) self.assertEqual(hexlify(n.chain_code()), chain)
def test_non_hardened_address_derivation_scheme(self): mnemonic = "all all all all all all all all all all all all" passphrase = "" node = bip32.from_mnemonic_cardano(mnemonic, passphrase) node.derive_cardano(0x80000000 | 44) node.derive_cardano(0x80000000 | 1815) keychain = Keychain(node) addresses = [ "Ae2tdPwUPEZ5YUb8sM3eS8JqKgrRLzhiu71crfuH2MFtqaYr5ACNRdsswsZ", "Ae2tdPwUPEZJb8r1VZxweSwHDTYtqeYqF39rZmVbrNK62JHd4Wd7Ytsc8eG", "Ae2tdPwUPEZFm6Y7aPZGKMyMAK16yA5pWWKU9g73ncUQNZsAjzjhszenCsq", ] for i, expected in enumerate(addresses): # 44'/1815'/0'/0/i address, _ = derive_address_and_node( keychain, [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(address, expected) nodes = [ (b"d03ba81163fd55af97bd132bf651a0da5b5e6201b15b1caca60b0be8e028ed51", b"493f44aa8d25fe0d3fe2935c76ea6b3e9e41c79e9dbcbe7131357c5aa1b6cac5", b"b90fb812a2268e9569ff1172e8daed1da3dc7e72c7bded7c5bcb7282039f90d5", b"fd8e71c1543de2cdc7f7623130c5f2cceb53549055fa1f5bc88199989e08cce7" ), (b"08b6438c8dd49d34b71c8e914d6ac3184e5ab3dcc8af023d08503a7edf28ed51", b"3fee605fdfaddc1ee2ea0b246b02c9abc54ad741054bc83943e8b21487b5a053", b"89053545a6c254b0d9b1464e48d2b5fcf91d4e25c128afb1fcfc61d0843338ea", b"26308151516f3b0e02bb1638142747863c520273ce9bd3e5cd91e1d46fe2a635" ), (b"088f0275bf4a1bd18f08d7ef06c6ddb6ce7e3dc415fb4e89fe21bf39e628ed51", b"4c44563c7df519ea9b4d1801c1ab98b449db28b87f1c3837759c20f68c4c1e65", b"52548cb98e6f46a592bdf7f3598a9abc0126c78dfa3f46d1894ee52a5213e833", b"91af0668ee449e613e61bbb2482e5ddee1d9b15785727ec3e362c36861bff923" ), ] for i, (priv, ext, pub, chain) in enumerate(nodes): _, n = derive_address_and_node( keychain, [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual( hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) self.assertEqual(hexlify(n.chain_code()), chain)
def _process_outputs(self): change_addresses = [] change_derivation_paths = [] output_addresses = [] outgoing_coins = [] change_coins = [] for output in self.outputs: if output.address_n: address, _ = derive_address_and_node(self.keychain, output.address_n) change_addresses.append(address) change_derivation_paths.append(output.address_n) change_coins.append(output.amount) else: if output.address is None: raise wire.ProcessError( "Each output must have address or address_n field!" ) if not is_safe_output_address(output.address): raise wire.ProcessError("Invalid output address!") outgoing_coins.append(output.amount) output_addresses.append(output.address) self.change_addresses = change_addresses self.output_addresses = output_addresses self.outgoing_coins = outgoing_coins self.change_coins = change_coins self.change_derivation_paths = change_derivation_paths
def test_hardened_address_derivation(self): mnemonic = "plastic that delay conduct police ticket swim gospel intact harsh obtain entire" node = bip32.from_mnemonic_cardano(mnemonic) addresses = [ "DdzFFzCqrhtDB6YEgPQqFiVnhKsfyEMe9MLQabhayVUL2WRN1dbLLFS7VfKYBy8n3uemZRcDyqMnv7STCU9vj2eAR8CgFgKMDG2mkQN7", "DdzFFzCqrhtCGRQ2UYpcouvRgDnPsAYpmzWVtd5YLvaRrMAMoDmYsKhNMAWePbK7a1XbZ8ghTeyaSLZ2488extnB5F9SwHus4UFaFwkS", "DdzFFzCqrhsqHyZLVLeFrgcxUrPA5YMJJRJCxkESHcPkV1EuuDKhKkJNPkEyrWXhPbuMHxSnz1cNYUCN8tJsLwaFiSxMz3ab19GEvaNP", ] for i, expected in enumerate(addresses): # 44'/1815'/0'/0/i' address, _ = derive_address_and_node(node, [ 0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i ]) self.assertEqual(expected, address) nodes = [ ("d4dd69a2f2a6374f3733f53e03f610d73dd4f1d5131169bc144e6d34c9bcbe04", "21d97a697583630e2cef01e5fc1555ea4fd9625ff8fcde1fc72e67aa42f975ec", "2df46e04ebf0816e242bfaa1c73e5ebe8863d05d7a96c8aac16f059975e63f30", "057658de1308930ad4a5663e4f77477014b04954a9d488e62d73b04fc659a35c" ), ("3476630290051477e4cc206fd5f6587065d3c9558c9891cc1c0ed5a408d5b60c", "3f1d4beaefd2ffff59a45cb75519960d02f4de62c076a165bc39a7d7b1fec168", "35b0cc0b770e04d86a9cddb0e2068b3a242f6b6e93c9a9d3c4f0899bd62b4266", "35bb811c631b3db3b10559bc15821a39969654ebcad80cedf544ac8bf2a73ce7" ), ("06a6f53baf84ac6713cd1c441081dff00d1c4abee33091dc5c5ebdec2044270c", "4978871e479a3a58adabb030565162832c63a2909442d306c96eaf03823ff5c9", "9f26aad725aef1bb0609085f2c961b4d2579bceccfb1b01f3c7d1dbdd02b50b1", "70f72ce51d0c984c4bbddd0297f4ffe0b4710c2c3f9a7e17f7d7e3e1810b5c33" ), ] for i, (priv, ext, pub, chain) in enumerate(nodes): _, n = derive_address_and_node(node, [ 0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i ]) self.assertEqual(unhexlify(priv), n.private_key()) self.assertEqual(unhexlify(ext), n.private_key_ext()) self.assertEqual(unhexlify(pub), seed.remove_ed25519_prefix(n.public_key())) self.assertEqual(unhexlify(chain), n.chain_code())
def test_non_hardened_address_derivation(self): mnemonic = "plastic that delay conduct police ticket swim gospel intact harsh obtain entire" node = bip32.from_mnemonic_cardano(mnemonic) addresses = [ "2w1sdSJu3GVezU6nw8LodErz7kSrEQ9hKQhsGLWk4JxTCxg7tkJvSowGKLFE7PMxknbkuYjtaWbpnJLhJgwmwNA98GPX2SGSN1t", "2w1sdSJu3GVg7mRbtq2aGUFKxXnpFoP9hesA1n7KJrnQ9QEgyy7DGbLU52L2cytPqCoNNhkvRCF9ZsBLwMv1E35CVh6XBiWj2GE", "2w1sdSJu3GVg193D2yhiiH947J9UwrbPAmNao6ciAZi3GeU7sG1D3fTAnQakzHSe1FVyuRdUjcx52Q7575LxBBNE8aCunKFA4kA", ] for i, expected in enumerate(addresses): # 44'/1815'/0'/0/i address, _ = derive_address_and_node( node, [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(expected, address) nodes = [ ("a75a851505db79ee8557a8cb3ef561ab7d6bd24d7cc0e97b8496654431fc2e0c", "21fa8154e009a46a1c44709fe23b75735c8abc6256c44cc3c208c1c914f037ce", "723fdc0eb1300fe7f2b9b6989216a831835a88695ba2c2d5c50c8470b7d1b239", "ae09010e921de259b02f34ce7fd76f9c09ad224d436fe8fa38aa212177937ffe" ), ("48ded246510a563f759fde920016ad1356238ab5936869e45ccec5b4d8fcce0c", "0216c5c777bfe196576b776bd9faf2ac1318966c820edb203754166d5a0f4d92", "6dc82a0d40257cfc1ea5d728c6ccfa52ad5673c2dc4cfed239dff642d29fbc46", "cd490ae08bd2ff18e8b61c39173f6bf0db85709130baa103b9f00e4160ec150f" ), ("8e651d540f55a4670bb5ec8cd0812731ce734a1e745059c4f445fd8cd8fcb604", "ab7f8d9e7927a1a71b7b08eb3b871246dc4717d9e309b7682df0eee202a5a97a", "e55323d6881ca92a0816695def558145ef22f0d0c4f6133aab7a8a3f2f98ef78", "6c9313fcf93b55a977184514aefa1c778c1abadb2ba9f2c1351b587b7c1e1572" ), ] for i, (priv, ext, pub, chain) in enumerate(nodes): _, n = derive_address_and_node( node, [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(unhexlify(priv), n.private_key()) self.assertEqual(unhexlify(ext), n.private_key_ext()) self.assertEqual(unhexlify(pub), seed.remove_ed25519_prefix(n.public_key())) self.assertEqual(unhexlify(chain), n.chain_code())
def test_root_address_derivation(self): mnemonic = "plastic that delay conduct police ticket swim gospel intact harsh obtain entire" node = bip32.from_mnemonic_cardano(mnemonic) # 44'/1815' address, _ = derive_address_and_node( node, [0x80000000 | 44, 0x80000000 | 1815]) self.assertEqual( "Ae2tdPwUPEYygPo2ZNZ7Ve6ZExaFZvkGcQFZ5oSyqVNoJn5J65Foyz2XiSU", address) priv, ext, pub, chain = ( "90bc16ad766aebce31b407f111db3ba95de2780c5bb760f3333dac1b3823ee53", "10f20917dcfa2b3c295386413ae3564365e4a51f063da644d0945f4d3da57699", "7d1de3f22f53904d007ff833fadd7cd6482ea1e83918b985b4ea33e63c16d183", "7a04a6aab0ed12af562a26db4d10344454274d0bfa6e3581df1dc02f13c5fbe5") _, n = derive_address_and_node(node, [0x80000000 | 44, 0x80000000 | 1815]) self.assertEqual(unhexlify(priv), n.private_key()) self.assertEqual(unhexlify(ext), n.private_key_ext()) self.assertEqual(unhexlify(pub), seed.remove_ed25519_prefix(n.public_key())) self.assertEqual(unhexlify(chain), n.chain_code())
def _get_public_key(keychain, derivation_path: list): _, node = derive_address_and_node(keychain, derivation_path) public_key = hexlify(remove_ed25519_prefix(node.public_key())).decode() chain_code = hexlify(node.chain_code()).decode() xpub_key = public_key + chain_code node_type = HDNodeType( depth=node.depth(), child_num=node.child_num(), fingerprint=node.fingerprint(), chain_code=node.chain_code(), public_key=remove_ed25519_prefix(node.public_key()), ) return CardanoPublicKey(node=node_type, xpub=xpub_key)
def _build_witnesses(self, tx_aux_hash: str): witnesses = [] for input in self.inputs: _, node = derive_address_and_node(self.keychain, input.address_n) message = (b"\x01" + cbor.encode(self.protocol_magic) + b"\x58\x20" + tx_aux_hash) signature = ed25519.sign_ext(node.private_key(), node.private_key_ext(), message) extended_public_key = (remove_ed25519_prefix(node.public_key()) + node.chain_code()) witnesses.append([ (input.type or 0), cbor.Tagged(24, cbor.encode([extended_public_key, signature])), ]) return witnesses
async def get_address(ctx, msg, keychain: seed.Keychain): await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE) try: address, _ = derive_address_and_node(keychain, msg.address_n) except ValueError as e: if __debug__: log.exception(__name__, e) raise wire.ProcessError("Deriving address failed") if msg.show_display: desc = address_n_to_str(msg.address_n) while True: if await show_address(ctx, address, desc=desc): break if await show_qr(ctx, address, desc=desc): break return CardanoAddress(address=address)
async def get_address(ctx, msg): keychain = await seed.get_keychain(ctx) await paths.validate_path(ctx, validate_full_path, path=msg.address_n) try: address, _ = derive_address_and_node(keychain, msg.address_n) except ValueError as e: if __debug__: log.exception(__name__, e) raise wire.ProcessError("Deriving address failed") if msg.show_display: if not await confirm_with_pagination(ctx, address, "Export address", icon=ui.ICON_SEND, icon_color=ui.GREEN): raise wire.ActionCancelled("Exporting cancelled") return CardanoAddress(address=address)
def _process_inputs(self): input_coins = [] input_hashes = [] output_indexes = [] types = [] tx_data = {} for raw_transaction in self.transactions: tx_hash = hashlib.blake2b(data=bytes(raw_transaction), outlen=32).digest() tx_data[tx_hash] = cbor.decode(raw_transaction) for input in self.inputs: input_hashes.append(input.prev_hash) output_indexes.append(input.prev_index) types.append(input.type or 0) nodes = [] for input in self.inputs: _, node = derive_address_and_node(self.keychain, input.address_n) nodes.append(node) for index, output_index in enumerate(output_indexes): tx_hash = bytes(input_hashes[index]) if tx_hash in tx_data: tx = tx_data[tx_hash] outputs = tx[1] amount = outputs[output_index][1] input_coins.append(amount) else: raise wire.ProcessError("No tx data sent for input " + str(index)) self.input_coins = input_coins self.nodes = nodes self.types = types self.input_hashes = input_hashes self.output_indexes = output_indexes
def test_slip39_256(self): mnemonics = [ "hobo romp academic axis august founder knife legal recover alien expect " "emphasis loan kitchen involve teacher capture rebuild trial numb spider forward " "ladle lying voter typical security quantity hawk legs idle leaves gasoline", "hobo romp academic agency ancestor industry argue sister scene midst graduate " "profile numb paid headset airport daisy flame express scene usual welcome " "quick silent downtown oral critical step remove says rhythm venture aunt" ] passphrase = b"TREZOR" identifier, exponent, ems = slip39.recover_ems(mnemonics) master_secret = slip39.decrypt(ems, passphrase, exponent, identifier) node = bip32.from_seed(master_secret, "ed25519 cardano seed") # Check root node. root_priv = b"90633724b5daf770a8b420b8658e7d8bc21e066b60ec8cd4d5730681cc294e4f" root_ext = b"f9d99bf3cd9c7e12663e8646afa40cb3aecf15d91f2abc15d21056c6bccb3414" root_pub = b"eea170f0ef97b59d22907cb429888029721ed67d3e7a1b56b81731086ab7db64" root_chain = b"04f1de750b62725fcc1ae1b93ca4063acb53c486b959cadaa100ebd7828e5460" self.assertEqual(hexlify(node.private_key()), root_priv) self.assertEqual(hexlify(node.private_key_ext()), root_ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(node.public_key())), root_pub) self.assertEqual(hexlify(node.chain_code()), root_chain) # Check derived nodes and addresses. node.derive_cardano(0x80000000 | 44) node.derive_cardano(0x80000000 | 1815) keychain = Keychain([0x80000000 | 44, 0x80000000 | 1815], node) nodes = [ ( "Ae2tdPwUPEYyDD1C2FbVJFAE3FuAxLspfMYt29TJ1urnSKr57cVhEcioSCC", b"38e8a4b17ca07b6a309f1cee83f87593e34a1fc3a289785ea451ef65df294e4f", b"405d10ef71c2b0019250d11837de8db825d8556bf1e57f8866920af6d8c90002", b"967a9a041ad1379e31c2c7f2aa4bc2b3f7769341c0ea89ccfb12a904f2e10877", b"7b15d8d9006afe3cd7e04f375a1126a8c7c7c07c59a6f0c5b0310f4245f4edbb", ), ( "Ae2tdPwUPEZHJGtyz47F6wD7qAegt1JNRJWuiE36QLvFzeqJPBZ2EBvhr8M", b"a09f90e3f76a7bdb7f8721cc0c142dbd6398fd704b83455e123fa886dc294e4f", b"917e4166bb404def9f12634e84ecbcb98afdea051ba7c38745e208178a9e9baf", b"6f3805bbc1b7a75afa95dffec331671f3c4662800615e80d2ec1202a9d874c86", b"44baf30fd549e6a1e05f99c2a2c8971aea8894ee8d9c5fc2c5ae6ee839a56b2d", ), ( "Ae2tdPwUPEYxD9xNPBJTzYmtFVVWEPB6KW4TCDijQ4pDwU11wt5621PyCi4", b"78dd824aea33bed5c1502d1a17f11a4adbe923aac1cd1f7ae98c9506db294e4f", b"ddfe7f27e2894b983df773d8ac2a07973fc37ff36e93a2f2d71fb7327d4e18f4", b"7f145b50ef07fb9accc40ee07a01fe93ceb6fa07d5a9f20fc3c8a48246dd4d02", b"e67d2864614ada5eec8fb8ee1225a94a6fb0a1b3c347c854ec3037351c6a0fc7", ) ] for i, (address, priv, ext, pub, chain) in enumerate(nodes): # 44'/1815'/0'/0/i a, n = derive_address_and_node(keychain, [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(a, address) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) self.assertEqual(hexlify(n.chain_code()), chain)
def test_slip39_128(self): mnemonics = [ "extra extend academic bishop cricket bundle tofu goat apart victim " "enlarge program behavior permit course armed jerky faint language modern", "extra extend academic acne away best indicate impact square oasis " "prospect painting voting guest either argue username racism enemy eclipse", "extra extend academic arcade born dive legal hush gross briefing " "talent drug much home firefly toxic analysis idea umbrella slice" ] passphrase = b"TREZOR" identifier, exponent, ems = slip39.recover_ems(mnemonics) master_secret = slip39.decrypt(ems, passphrase, exponent, identifier) node = bip32.from_seed(master_secret, "ed25519 cardano seed") # Check root node. root_priv = b"c0fe4a6973df4de06262693fc9186f71faf292960350882d49456bf108d13954" root_ext = b"4064253ffefc4127489bce1b825a47329010c5afb4d21154ef949ef786204405" root_pub = b"83e3ecaf57f90f022c45e10d1b8cb78499c30819515ad9a81ad82139fdb12a90" root_chain = b"22c12755afdd192742613b3062069390743ea232bc1b366c8f41e37292af9305" self.assertEqual(hexlify(node.private_key()), root_priv) self.assertEqual(hexlify(node.private_key_ext()), root_ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(node.public_key())), root_pub) self.assertEqual(hexlify(node.chain_code()), root_chain) # Check derived nodes and addresses. node.derive_cardano(0x80000000 | 44) node.derive_cardano(0x80000000 | 1815) keychain = Keychain([0x80000000 | 44, 0x80000000 | 1815], node) nodes = [ ( "Ae2tdPwUPEYxF9NAMNdd3v2LZoMeWp7gCZiDb6bZzFQeeVASzoP7HC4V9s6", b"e0acfe234aa6e1219ce7d3d8d91853e0808bab92ecb8a0ff0f345ff31ad13954", b"ff89dc71365c4b67bb7bb75d566e65b8a95f16e4d70cce51c25937db15614530", b"bc043d84b8b891d49890edb6aced6f2d78395f255c5b6aea8878b913f83e8579", b"dc3f0d2b5cccb822335ef6213fd133f4ca934151ec44a6000aee43b8a101078c", ), ( "Ae2tdPwUPEZ1TjYcvfkWAbiHtGVxv4byEHHZoSyQXjPJ362DifCe1ykgqgy", b"d0ce3e7a6445bc91801319b9bbaf47fdfca9364257295fb13bc5046a20d13954", b"c800359abdc875944754ae7368bab7ef75184d48816c368f5a28af4bcf1d1ee8", b"24c4fe188a39103db88818bc191fd8571eae7b284ebcbdf2462bde97b058a95c", b"6f7a744035f4b3ddb8f861c18446169643cc3ae85e271b4b4f0eda05cf84c65b", ), ( "Ae2tdPwUPEZGXmSbda1kBNfyhRQGRcQxJFdk7mhWZXAGnapyejv2b2U3aRb", b"e8320644cce22a6e9fc33865fc5a598b1cda061c47a548aead3af4ed1cd13954", b"9e2ece5d7fe8119cb76090009be926a84fc5d3b95855b5962ffe2f880836cf09", b"831a63d381a8dab1e6e1ee991a4300fc70687aae5f97f4fcf92ed1b6c2bd99de", b"672d6af4707aba201b7940231e83dd357f92f8851b3dfdc224ef311e1b64cdeb" ) ] for i, (address, priv, ext, pub, chain) in enumerate(nodes): # 44'/1815'/0'/0/i a, n = derive_address_and_node(keychain, [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(a, address) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) self.assertEqual(hexlify(n.chain_code()), chain)