diff --git a/pyproject.toml b/pyproject.toml index 290a759..d3722f2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ zip_0244 = "zcash_test_vectors.zip_0244:main" # Transparent test vectors bip_0032 = "zcash_test_vectors.transparent.bip_0032:main" zip_0316 = "zcash_test_vectors.transparent.zip_0316:main" +zip_0320 = "zcash_test_vectors.transparent.zip_0320:main" # Sapling test vectors sapling_generators = "zcash_test_vectors.sapling.generators:main" diff --git a/regenerate.sh b/regenerate.sh index 880e326..d42fd88 100755 --- a/regenerate.sh +++ b/regenerate.sh @@ -25,7 +25,8 @@ tv_scripts=( zip_0143 zip_0243 zip_0244 - zip_0316) + zip_0316 + zip_0320) for generator in "${tv_scripts[@]}" do diff --git a/test-vectors/json/zip_0320.json b/test-vectors/json/zip_0320.json new file mode 100644 index 0000000..8335328 --- /dev/null +++ b/test-vectors/json/zip_0320.json @@ -0,0 +1,19 @@ +[ + ["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/transparent/zip_0320.py"], + ["t_addr, p2pkh_bytes, tex_addr, account, child_index"], + ["t1V9mnyk5Z5cTNMCkLbaDwSskgJZucTLdgW", "7bb83570b8fae146e03c5331a020b1e0892f631d", "tex10wur2u9clts5dcpu2vc6qg93uzyj7cca2xm732", 0, 0], + ["t1LZdE42PAt1wREUv1YMYRFwJDPHPW8toLL", "1d81e86791c72d292f906e7c039a729e4b1ff7fc", "tex1rkq7seu3cukjjtusde7q8xnjne93laluyvdxu7", 0, 1], + ["t1M5AgJw56FNFRBNGtzAGX4AHfQh7ZCxd4w", "231839e305c0a02ed681406faf222585f6623904", "tex1yvvrncc9czsza45pgph67g39shmxywgyvsypwn", 0, 2], + ["t1bh6KjXccz6Ed45vFc3GeqoxWbwPxe8w2n", "c3755398b8b77f633fca7ccbda900831478979c9", "tex1cd648x9ckalkx0720n9a4yqgx9rcj7wfvjcq63", 1, 0], + ["t1WvCtHojWHSHBdDtCFgorUN1TzUFV8sCth", "8f17950e22b08886ac4832e22e24f2e8f3cb6b21", "tex13ute2r3zkzygdtzgxt3zuf8jareuk6ep7qd8ty", 1, 1], + ["t1U2MF7f81qrXkWouT3Xt4hLDAMjC9LniTK", "6f58adaf02bb48e6b398a442a2b294589e041620", "tex1dav2mtczhdywdvuc53p29v55tz0qg93qvfjp46", 1, 2], + ["t1awMYfhispKsnJPHn7jgUxNnVW1DTpTJx9", "bb2fbb540f0f7e434636680eaea2eefe375a7591", "tex1hvhmk4q0palyx33kdq82aghwlcm45av3ezlrzn", 2, 0], + ["t1Kgn7v5a2rKkxC24LoXNyHRn4q4Gs3KEEF", "13e41e47448122cad13c5c7f5bd31c77639a9f99", "tex1z0jpu36ysy3v45fut3l4h5cuwa3e48uea95pc6", 2, 1], + ["t1c1ixUTuStCzo19qPg89U9XFYmWDLru9mt", "c6fb64d8757e5c85b230a3358711697ae6540b44", "tex1cmakfkr40ewgtv3s5v6cwytf0tn9gz6y9j5z8e", 2, 2], + ["t1WBxR5jNWgg4Cqeot3FvNkBb9ztYyjVELp", "871a089d446268aa7ac03d2a6f60ae70808f3974", "tex1sudq382yvf5257kq854x7c9wwzqg7wt5h2c24u", 3, 0], + ["t1VEuDXP1QocoNaxrq4gZArTqqKCZdrwjG7", "7cb07c31b58040ac7cc12bfaaa138cfbefb38457", "tex10jc8cvd4spq2clxp90a25yuvl0hm8pzheuufxw", 3, 1], + ["t1PXVM8oR6qVrVjtcnU1iNmH2CfvZyBai8u", "3e02e08b5965fce9c20ce6de6f9407674d01ba02", "tex18cpwpz6evh7wnssvum0xl9q8vaxsrwsz83vght", 3, 2], + ["t1M3p1MgJCgjq4FMogS84kVvuszJbxPnpSM", "22d68debb3928da4046370d25ed2bbe8d5e985d0", "tex1yttgm6anj2x6gprrwrf9a54mar27npws73jwdy", 4, 0], + ["t1aqnebXhA45WpgQHLiXTPU1Kk6rp8vVDDr", "ba2230b41fdc81714328231f40ab73feb52645a4", "tex1hg3rpdqlmjqhzsegyv05p2mnl66jv3dykth955", 4, 1], + ["t1UG6FVxexmJRFXG4gvEmSF9HSTwHMFaSDT", "71f1fc6fd69370f23611536b3b64e7df1cebef69", "tex1w8clcm7kjdc0yds32d4nke88muwwhmmfunhkhd", 4, 2] +] diff --git a/test-vectors/rust/zip_0320.rs b/test-vectors/rust/zip_0320.rs new file mode 100644 index 0000000..5279365 --- /dev/null +++ b/test-vectors/rust/zip_0320.rs @@ -0,0 +1,146 @@ + struct TestVector { + t_addr: &'static str, + p2pkh_bytes: [u8; 20], + tex_addr: &'static str, + account: u32, + child_index: u32, + }; + + // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/transparent/zip_0320.py + let test_vectors = vec![ + TestVector { + t_addr: "t1V9mnyk5Z5cTNMCkLbaDwSskgJZucTLdgW", + p2pkh_bytes: [ + 0x7b, 0xb8, 0x35, 0x70, 0xb8, 0xfa, 0xe1, 0x46, 0xe0, 0x3c, 0x53, 0x31, 0xa0, 0x20, 0xb1, 0xe0, 0x89, 0x2f, 0x63, 0x1d + ], + tex_addr: "tex10wur2u9clts5dcpu2vc6qg93uzyj7cca2xm732", + account: 0, + child_index: 0, + }, + TestVector { + t_addr: "t1LZdE42PAt1wREUv1YMYRFwJDPHPW8toLL", + p2pkh_bytes: [ + 0x1d, 0x81, 0xe8, 0x67, 0x91, 0xc7, 0x2d, 0x29, 0x2f, 0x90, 0x6e, 0x7c, 0x03, 0x9a, 0x72, 0x9e, 0x4b, 0x1f, 0xf7, 0xfc + ], + tex_addr: "tex1rkq7seu3cukjjtusde7q8xnjne93laluyvdxu7", + account: 0, + child_index: 1, + }, + TestVector { + t_addr: "t1M5AgJw56FNFRBNGtzAGX4AHfQh7ZCxd4w", + p2pkh_bytes: [ + 0x23, 0x18, 0x39, 0xe3, 0x05, 0xc0, 0xa0, 0x2e, 0xd6, 0x81, 0x40, 0x6f, 0xaf, 0x22, 0x25, 0x85, 0xf6, 0x62, 0x39, 0x04 + ], + tex_addr: "tex1yvvrncc9czsza45pgph67g39shmxywgyvsypwn", + account: 0, + child_index: 2, + }, + TestVector { + t_addr: "t1bh6KjXccz6Ed45vFc3GeqoxWbwPxe8w2n", + p2pkh_bytes: [ + 0xc3, 0x75, 0x53, 0x98, 0xb8, 0xb7, 0x7f, 0x63, 0x3f, 0xca, 0x7c, 0xcb, 0xda, 0x90, 0x08, 0x31, 0x47, 0x89, 0x79, 0xc9 + ], + tex_addr: "tex1cd648x9ckalkx0720n9a4yqgx9rcj7wfvjcq63", + account: 1, + child_index: 0, + }, + TestVector { + t_addr: "t1WvCtHojWHSHBdDtCFgorUN1TzUFV8sCth", + p2pkh_bytes: [ + 0x8f, 0x17, 0x95, 0x0e, 0x22, 0xb0, 0x88, 0x86, 0xac, 0x48, 0x32, 0xe2, 0x2e, 0x24, 0xf2, 0xe8, 0xf3, 0xcb, 0x6b, 0x21 + ], + tex_addr: "tex13ute2r3zkzygdtzgxt3zuf8jareuk6ep7qd8ty", + account: 1, + child_index: 1, + }, + TestVector { + t_addr: "t1U2MF7f81qrXkWouT3Xt4hLDAMjC9LniTK", + p2pkh_bytes: [ + 0x6f, 0x58, 0xad, 0xaf, 0x02, 0xbb, 0x48, 0xe6, 0xb3, 0x98, 0xa4, 0x42, 0xa2, 0xb2, 0x94, 0x58, 0x9e, 0x04, 0x16, 0x20 + ], + tex_addr: "tex1dav2mtczhdywdvuc53p29v55tz0qg93qvfjp46", + account: 1, + child_index: 2, + }, + TestVector { + t_addr: "t1awMYfhispKsnJPHn7jgUxNnVW1DTpTJx9", + p2pkh_bytes: [ + 0xbb, 0x2f, 0xbb, 0x54, 0x0f, 0x0f, 0x7e, 0x43, 0x46, 0x36, 0x68, 0x0e, 0xae, 0xa2, 0xee, 0xfe, 0x37, 0x5a, 0x75, 0x91 + ], + tex_addr: "tex1hvhmk4q0palyx33kdq82aghwlcm45av3ezlrzn", + account: 2, + child_index: 0, + }, + TestVector { + t_addr: "t1Kgn7v5a2rKkxC24LoXNyHRn4q4Gs3KEEF", + p2pkh_bytes: [ + 0x13, 0xe4, 0x1e, 0x47, 0x44, 0x81, 0x22, 0xca, 0xd1, 0x3c, 0x5c, 0x7f, 0x5b, 0xd3, 0x1c, 0x77, 0x63, 0x9a, 0x9f, 0x99 + ], + tex_addr: "tex1z0jpu36ysy3v45fut3l4h5cuwa3e48uea95pc6", + account: 2, + child_index: 1, + }, + TestVector { + t_addr: "t1c1ixUTuStCzo19qPg89U9XFYmWDLru9mt", + p2pkh_bytes: [ + 0xc6, 0xfb, 0x64, 0xd8, 0x75, 0x7e, 0x5c, 0x85, 0xb2, 0x30, 0xa3, 0x35, 0x87, 0x11, 0x69, 0x7a, 0xe6, 0x54, 0x0b, 0x44 + ], + tex_addr: "tex1cmakfkr40ewgtv3s5v6cwytf0tn9gz6y9j5z8e", + account: 2, + child_index: 2, + }, + TestVector { + t_addr: "t1WBxR5jNWgg4Cqeot3FvNkBb9ztYyjVELp", + p2pkh_bytes: [ + 0x87, 0x1a, 0x08, 0x9d, 0x44, 0x62, 0x68, 0xaa, 0x7a, 0xc0, 0x3d, 0x2a, 0x6f, 0x60, 0xae, 0x70, 0x80, 0x8f, 0x39, 0x74 + ], + tex_addr: "tex1sudq382yvf5257kq854x7c9wwzqg7wt5h2c24u", + account: 3, + child_index: 0, + }, + TestVector { + t_addr: "t1VEuDXP1QocoNaxrq4gZArTqqKCZdrwjG7", + p2pkh_bytes: [ + 0x7c, 0xb0, 0x7c, 0x31, 0xb5, 0x80, 0x40, 0xac, 0x7c, 0xc1, 0x2b, 0xfa, 0xaa, 0x13, 0x8c, 0xfb, 0xef, 0xb3, 0x84, 0x57 + ], + tex_addr: "tex10jc8cvd4spq2clxp90a25yuvl0hm8pzheuufxw", + account: 3, + child_index: 1, + }, + TestVector { + t_addr: "t1PXVM8oR6qVrVjtcnU1iNmH2CfvZyBai8u", + p2pkh_bytes: [ + 0x3e, 0x02, 0xe0, 0x8b, 0x59, 0x65, 0xfc, 0xe9, 0xc2, 0x0c, 0xe6, 0xde, 0x6f, 0x94, 0x07, 0x67, 0x4d, 0x01, 0xba, 0x02 + ], + tex_addr: "tex18cpwpz6evh7wnssvum0xl9q8vaxsrwsz83vght", + account: 3, + child_index: 2, + }, + TestVector { + t_addr: "t1M3p1MgJCgjq4FMogS84kVvuszJbxPnpSM", + p2pkh_bytes: [ + 0x22, 0xd6, 0x8d, 0xeb, 0xb3, 0x92, 0x8d, 0xa4, 0x04, 0x63, 0x70, 0xd2, 0x5e, 0xd2, 0xbb, 0xe8, 0xd5, 0xe9, 0x85, 0xd0 + ], + tex_addr: "tex1yttgm6anj2x6gprrwrf9a54mar27npws73jwdy", + account: 4, + child_index: 0, + }, + TestVector { + t_addr: "t1aqnebXhA45WpgQHLiXTPU1Kk6rp8vVDDr", + p2pkh_bytes: [ + 0xba, 0x22, 0x30, 0xb4, 0x1f, 0xdc, 0x81, 0x71, 0x43, 0x28, 0x23, 0x1f, 0x40, 0xab, 0x73, 0xfe, 0xb5, 0x26, 0x45, 0xa4 + ], + tex_addr: "tex1hg3rpdqlmjqhzsegyv05p2mnl66jv3dykth955", + account: 4, + child_index: 1, + }, + TestVector { + t_addr: "t1UG6FVxexmJRFXG4gvEmSF9HSTwHMFaSDT", + p2pkh_bytes: [ + 0x71, 0xf1, 0xfc, 0x6f, 0xd6, 0x93, 0x70, 0xf2, 0x36, 0x11, 0x53, 0x6b, 0x3b, 0x64, 0xe7, 0xdf, 0x1c, 0xeb, 0xef, 0x69 + ], + tex_addr: "tex1w8clcm7kjdc0yds32d4nke88muwwhmmfunhkhd", + account: 4, + child_index: 2, + }, + ]; diff --git a/test-vectors/zcash/zip_0320.json b/test-vectors/zcash/zip_0320.json new file mode 100644 index 0000000..8335328 --- /dev/null +++ b/test-vectors/zcash/zip_0320.json @@ -0,0 +1,19 @@ +[ + ["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/transparent/zip_0320.py"], + ["t_addr, p2pkh_bytes, tex_addr, account, child_index"], + ["t1V9mnyk5Z5cTNMCkLbaDwSskgJZucTLdgW", "7bb83570b8fae146e03c5331a020b1e0892f631d", "tex10wur2u9clts5dcpu2vc6qg93uzyj7cca2xm732", 0, 0], + ["t1LZdE42PAt1wREUv1YMYRFwJDPHPW8toLL", "1d81e86791c72d292f906e7c039a729e4b1ff7fc", "tex1rkq7seu3cukjjtusde7q8xnjne93laluyvdxu7", 0, 1], + ["t1M5AgJw56FNFRBNGtzAGX4AHfQh7ZCxd4w", "231839e305c0a02ed681406faf222585f6623904", "tex1yvvrncc9czsza45pgph67g39shmxywgyvsypwn", 0, 2], + ["t1bh6KjXccz6Ed45vFc3GeqoxWbwPxe8w2n", "c3755398b8b77f633fca7ccbda900831478979c9", "tex1cd648x9ckalkx0720n9a4yqgx9rcj7wfvjcq63", 1, 0], + ["t1WvCtHojWHSHBdDtCFgorUN1TzUFV8sCth", "8f17950e22b08886ac4832e22e24f2e8f3cb6b21", "tex13ute2r3zkzygdtzgxt3zuf8jareuk6ep7qd8ty", 1, 1], + ["t1U2MF7f81qrXkWouT3Xt4hLDAMjC9LniTK", "6f58adaf02bb48e6b398a442a2b294589e041620", "tex1dav2mtczhdywdvuc53p29v55tz0qg93qvfjp46", 1, 2], + ["t1awMYfhispKsnJPHn7jgUxNnVW1DTpTJx9", "bb2fbb540f0f7e434636680eaea2eefe375a7591", "tex1hvhmk4q0palyx33kdq82aghwlcm45av3ezlrzn", 2, 0], + ["t1Kgn7v5a2rKkxC24LoXNyHRn4q4Gs3KEEF", "13e41e47448122cad13c5c7f5bd31c77639a9f99", "tex1z0jpu36ysy3v45fut3l4h5cuwa3e48uea95pc6", 2, 1], + ["t1c1ixUTuStCzo19qPg89U9XFYmWDLru9mt", "c6fb64d8757e5c85b230a3358711697ae6540b44", "tex1cmakfkr40ewgtv3s5v6cwytf0tn9gz6y9j5z8e", 2, 2], + ["t1WBxR5jNWgg4Cqeot3FvNkBb9ztYyjVELp", "871a089d446268aa7ac03d2a6f60ae70808f3974", "tex1sudq382yvf5257kq854x7c9wwzqg7wt5h2c24u", 3, 0], + ["t1VEuDXP1QocoNaxrq4gZArTqqKCZdrwjG7", "7cb07c31b58040ac7cc12bfaaa138cfbefb38457", "tex10jc8cvd4spq2clxp90a25yuvl0hm8pzheuufxw", 3, 1], + ["t1PXVM8oR6qVrVjtcnU1iNmH2CfvZyBai8u", "3e02e08b5965fce9c20ce6de6f9407674d01ba02", "tex18cpwpz6evh7wnssvum0xl9q8vaxsrwsz83vght", 3, 2], + ["t1M3p1MgJCgjq4FMogS84kVvuszJbxPnpSM", "22d68debb3928da4046370d25ed2bbe8d5e985d0", "tex1yttgm6anj2x6gprrwrf9a54mar27npws73jwdy", 4, 0], + ["t1aqnebXhA45WpgQHLiXTPU1Kk6rp8vVDDr", "ba2230b41fdc81714328231f40ab73feb52645a4", "tex1hg3rpdqlmjqhzsegyv05p2mnl66jv3dykth955", 4, 1], + ["t1UG6FVxexmJRFXG4gvEmSF9HSTwHMFaSDT", "71f1fc6fd69370f23611536b3b64e7df1cebef69", "tex1w8clcm7kjdc0yds32d4nke88muwwhmmfunhkhd", 4, 2] +] diff --git a/zcash_test_vectors/transparent/zip_0320.py b/zcash_test_vectors/transparent/zip_0320.py new file mode 100644 index 0000000..69462da --- /dev/null +++ b/zcash_test_vectors/transparent/zip_0320.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +import sys; assert sys.version_info[0] >= 3, "Python 3 required." + +import math +from random import Random +import struct +import base58 + +from ..bech32m import bech32_encode, bech32_decode, convertbits, Encoding +from ..output import render_args, render_tv, Some +from ..rand import Rand, randbytes +from ..hd_common import ZCASH_MAIN_COINTYPE, hardened +from .bip_0032 import ExtendedSecretKey + +class HrpMismatch(Exception): + pass + +class InvalidEncoding(Exception): + pass + +def encode(hrp, p2pkh_bytes): + converted = convertbits(p2pkh_bytes, 8, 5) + return bech32_encode("tex", converted, Encoding.BECH32M) + +def decode(hrp_expected, tex_addr): + (hrp, data, encoding) = bech32_decode(tex_addr) + if data is None or encoding != Encoding.BECH32M: + raise InvalidEncoding("ZIP 320 addresses must be encoded using Bech32m") + if hrp != hrp_expected: + raise HrpMismatch("Expected: " + hrp_expected + "; got " + hrp) + return bytes(convertbits(data, 5, 8, False)) + +def main(): + args = render_args() + + rng = Random(0xabad533d) + rand = Rand(randbytes(rng)) + seed = bytes(range(32)) + + t_root_key = ExtendedSecretKey.master(seed) + t_purpose_key = t_root_key.child(hardened(44)) + t_coin_key = t_purpose_key.child(hardened(ZCASH_MAIN_COINTYPE)) + + test_vectors = [] + for account in range(0, 5): + for j in range(0, 3): + t_account_key = t_coin_key.child(hardened(account)) + t_external_key = t_account_key.child(0) + t_index_key = t_external_key.child(j) + t_index_pubkey = t_index_key.public_key() + p2pkh_bytes = t_index_pubkey.address() + t_addr = base58.b58encode_check(bytes([0x1c, 0xb8]) + p2pkh_bytes).decode('utf-8') + + tex_addr = encode("tex", p2pkh_bytes) + + p2pkh_bytes_decoded = decode("tex", tex_addr) + assert p2pkh_bytes_decoded == p2pkh_bytes + + test_vectors.append({ + 't_addr': t_addr, + 'p2pkh_bytes': p2pkh_bytes, + 'tex_addr': tex_addr, + 'account': account, + 'child_index': j, + }) + + render_tv( + args, + 'transparent/zip_0320', + ( + ('t_addr', {'rust_type': '&\'static str'}), + ('p2pkh_bytes', '[u8; 20]'), + ('tex_addr', {'rust_type': '&\'static str'}), + ('account', 'u32'), + ('child_index', 'u32'), + ), + test_vectors, + ) + + +if __name__ == "__main__": + main()