diff --git a/zcash_test_vectors/unified_address.py b/zcash_test_vectors/unified_address.py index d271c19..996cfce 100755 --- a/zcash_test_vectors/unified_address.py +++ b/zcash_test_vectors/unified_address.py @@ -39,7 +39,11 @@ def main(): test_vectors = [] for account in range(0, 20): + # Each set of sequential diversified addresses should have the same set + # of typecodes, to simplify use in tests. has_t_addr = rand.bool() + # use p2pkh 3/4 of the time + is_p2pkh = rand.bool() or rand.bool() if has_t_addr: # This randomness is only used if this UA will have a P2SH key. # If it will have a P2PKH key, it gets overwritten below (after @@ -48,53 +52,58 @@ def main(): else: t_addr = None + has_s_addr = rand.bool() + has_o_addr = (not has_s_addr) or rand.bool() + # include an unknown item 1/4 of the time + has_unknown_item = rand.bool() and rand.bool() + # use the range reserved for experimental typecodes for unknowns + unknown_tc = rng.randrange(0xFFFA, 0xFFFF+1) + unknown_len = rng.randrange(32, 256) + + # we will increment the diversifier index after generating each sample + # within the current account j = 0 for _ in range(0, 3): - has_s_addr = rand.bool() + receivers = [] if has_s_addr: s_account_key = s_coin_key.child(hardened(account)) j = s_account_key.find_j(j) sapling_d = s_account_key.diversifier(j) sapling_pk_d = s_account_key.pk_d(j) sapling_raw_addr = sapling_d + bytes(sapling_pk_d) + receivers.append((SAPLING_ITEM, sapling_raw_addr)) else: sapling_raw_addr = None - has_o_addr = (not has_s_addr) or rand.bool() if has_o_addr: o_account_key = o_coin_key.child(hardened(account)) orchard_fvk = orchard_key_components.FullViewingKey.from_spending_key(o_account_key) orchard_d = orchard_fvk.diversifier(j) orchard_pk_d = orchard_fvk.pk_d(j) orchard_raw_addr = orchard_d + bytes(orchard_pk_d) + receivers.append((ORCHARD_ITEM, orchard_raw_addr)) else: orchard_raw_addr = None - is_p2pkh = rand.bool() - if has_t_addr and is_p2pkh: - 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() - t_addr = t_index_pubkey.address() + if has_t_addr: + if is_p2pkh: + 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() + t_addr = t_index_pubkey.address() + receivers.append((P2PKH_ITEM, t_addr)) + else: + receivers.append((P2SH_ITEM, t_addr)) + else: + t_addr = None - # include an unknown item 1/4 of the time - has_unknown_item = rand.bool() and rand.bool() - # use the range reserved for experimental typecodes for unknowns - unknown_tc = rng.randrange(0xFFFA, 0xFFFF+1) - unknown_len = rng.randrange(32, 256) if has_unknown_item: unknown_bytes = b"".join([rand.b(unknown_len)]) + receivers.append((unknown_tc, unknown_bytes)) else: unknown_bytes = None - receivers = [ - (ORCHARD_ITEM, orchard_raw_addr), - (SAPLING_ITEM, sapling_raw_addr), - (P2PKH_ITEM, t_addr if is_p2pkh else None), - (P2SH_ITEM, None if is_p2pkh else t_addr), - (unknown_tc, unknown_bytes), - ] ua = encode_unified(rng, receivers, "u") expected_lengths = { @@ -108,15 +117,17 @@ def main(): assert decoded.get('orchard') == orchard_raw_addr assert decoded.get('sapling') == sapling_raw_addr assert decoded.get('transparent') == t_addr - assert decoded.get('unknown') == ((unknown_tc, unknown_bytes) if unknown_bytes else None) - assert decoded.get('transparent') == t_addr + if has_unknown_item: + assert decoded.get('unknown') == ((unknown_tc, unknown_bytes)) + else: + assert decoded.get('unknown') == None test_vectors.append({ 'p2pkh_bytes': t_addr if is_p2pkh else None, 'p2sh_bytes': None if is_p2pkh else t_addr, 'sapling_raw_addr': sapling_raw_addr, 'orchard_raw_addr': orchard_raw_addr, - 'unknown_typecode': unknown_tc, + 'unknown_typecode': unknown_tc if has_unknown_item else None, 'unknown_bytes': unknown_bytes, 'unified_addr': ua, 'root_seed': seed, @@ -134,7 +145,7 @@ def main(): ('p2sh_bytes', 'Option<[u8; 20]>'), ('sapling_raw_addr', 'Option<[u8; 43]>'), ('orchard_raw_addr', 'Option<[u8; 43]>'), - ('unknown_typecode', 'u32'), + ('unknown_typecode', 'Option'), ('unknown_bytes', {'rust_type': 'Option>', 'bitcoin_flavoured': False}), ('unified_addr', {'rust_type': '&\'static str'}), ('root_seed', {'rust_type': 'Vec', 'bitcoin_flavoured': False}),