Ensure that successive diversified UAs have the same structure.
In 23321662d1
, the unified address
test vectors were modified to include multiple addresses for each
account at successive diversifier indices. However, the generation
process resulted in such diversified addresses having varying sets
of typecodes within a single account; in particular, p2sh and p2pkh
addresses were interleaved in a manner that made testing transparent
functionality using the resulting test vectors more difficult.
In the process of this fix, it was also noted that the handling of
unknown typecodes was inconsistent, with the unknown typecode always
being included in the resulting test vector even if no data
corresponding to that typecode was present. This has also been
modified such that if an unknown typecode is present, data is present,
and vice versa.
This commit is contained in:
parent
ac92513d4e
commit
fb5f931e5f
|
@ -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<u32>'),
|
||||
('unknown_bytes', {'rust_type': 'Option<Vec<u8>>', 'bitcoin_flavoured': False}),
|
||||
('unified_addr', {'rust_type': '&\'static str'}),
|
||||
('root_seed', {'rust_type': 'Vec<u8>', 'bitcoin_flavoured': False}),
|
||||
|
|
Loading…
Reference in New Issue