From 580dc95437ba1b544b4285fb6143912571f9466e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 1 Oct 2024 18:13:08 +0100 Subject: [PATCH 1/3] Add Orchard ZIP 32 test vectors --- pyproject.toml | 1 + regenerate.sh | 1 + zcash_test_vectors/orchard/zip32.py | 101 ++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100755 zcash_test_vectors/orchard/zip32.py diff --git a/pyproject.toml b/pyproject.toml index a0f9359..bc787b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,3 +69,4 @@ orchard_note_encryption = "zcash_test_vectors.orchard.note_encryption:main" orchard_poseidon = "zcash_test_vectors.orchard.poseidon:main" orchard_poseidon_hash = "zcash_test_vectors.orchard.poseidon:hash_test_vectors" orchard_sinsemilla = "zcash_test_vectors.orchard.sinsemilla:main" +orchard_zip32 = "zcash_test_vectors.orchard.zip32:main" diff --git a/regenerate.sh b/regenerate.sh index 2f6f923..bcf8c91 100755 --- a/regenerate.sh +++ b/regenerate.sh @@ -14,6 +14,7 @@ tv_scripts=( orchard_poseidon orchard_poseidon_hash orchard_sinsemilla + orchard_zip32 sapling_generators sapling_key_components sapling_note_encryption diff --git a/zcash_test_vectors/orchard/zip32.py b/zcash_test_vectors/orchard/zip32.py new file mode 100755 index 0000000..f9c6a60 --- /dev/null +++ b/zcash_test_vectors/orchard/zip32.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +import sys; assert sys.version_info[0] >= 3, "Python 3 required." + +from hashlib import blake2b + +from .key_components import FullViewingKey, ExtendedSpendingKey + +from ..hd_common import hardened +from ..utils import i2leosp +from ..output import render_args, render_tv + + +class DerivedSpendingKey(object): + def __init__(self, extsk, depth=0, parent_tag=i2leosp(32, 0), i=0): + self._extsk = extsk + self._depth = depth + self._parent_tag = parent_tag + self._i = i + + def __eq__(self, other): + return (self._extsk == other._extsk and + self._depth == other._depth and + self._parent_tag == other._parent_tag and + self._i == other._i) + + @classmethod + def master(cls, S): + return cls(ExtendedSpendingKey.master(S)) + + def sk(self): + return self._extsk.data + + def c(self): + return self._extsk.chaincode + + def depth(self): + return self._depth + + def parent_tag(self): + return self._parent_tag + + def i(self): + return self._i + + def fingerprint(self): + fvk = FullViewingKey.from_spending_key(self._extsk) + digest = blake2b(person=b'ZcashOrchardFVFP', digest_size=32) + digest.update(bytes(fvk.ak) + bytes(fvk.nk) + bytes(fvk.rivk)) + return digest.digest() + + def tag(self): + return self.fingerprint()[:4] + + def __bytes__(self): + return (i2leosp(8, self.depth()) + + self.parent_tag() + + i2leosp(32, self.i()) + + self.c() + + self.sk()) + + def child(self, i): + return self.__class__(self._extsk.child(i), self.depth()+1, self.tag(), i) + + +def main(): + args = render_args() + + seed = bytes(range(32)) + m = DerivedSpendingKey.master(seed) + m_1h = m.child(hardened(1)) + m_1h_2h = m_1h.child(hardened(2)) + m_1h_2h_3h = m_1h_2h.child(hardened(3)) + + keys = [m, m_1h, m_1h_2h, m_1h_2h_3h] + + render_tvs(args, keys) + +def render_tvs(args, keys): + test_vectors = [ + {'sk' : k.sk(), + 'c' : k.c(), + 'xsk' : bytes(k), + 'fp' : k.fingerprint(), + } + for k in keys + ] + + render_tv( + args, + 'orchard_zip32', + ( + ('sk', '[u8; 32]'), + ('c', '[u8; 32]'), + ('xsk', '[u8; 73]'), + ('fp', '[u8; 32]'), + ), + test_vectors, + ) + +if __name__ == '__main__': + main() From 346740a68035d1c2784d669e9667b337c2b26087 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 1 Oct 2024 14:31:32 -0600 Subject: [PATCH 2/3] Modify the `regenerate` script to be more user-friendly. This now takes the generation type or 'all' as the first argument, and then the generator or 'all' as the second argument. File extensions are detemined automatically from the generation type. --- .github/workflows/test_vectors.yml | 5 +- regenerate.sh | 107 ++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 36 deletions(-) diff --git a/.github/workflows/test_vectors.yml b/.github/workflows/test_vectors.yml index 9352782..b1c93c1 100644 --- a/.github/workflows/test_vectors.yml +++ b/.github/workflows/test_vectors.yml @@ -11,13 +11,10 @@ jobs: kind: ['rust', 'json', 'zcash'] include: - kind: 'rust' - extension: 'rs' name: 'Rust' - kind: 'json' - extension: 'json' name: 'JSON' - kind: 'zcash' - extension: 'json' name: 'Bitcoin-flavoured JSON' fail-fast: false @@ -34,7 +31,7 @@ jobs: run: poetry install --no-root - name: Regenerate test vectors - run: ./regenerate.sh ${{ matrix.kind }} ${{ matrix.extension }} + run: ./regenerate.sh ${{ matrix.kind }} all - name: Verify there are no changes run: git diff; git ls-files --others --exclude-standard; test -z "$(git status --porcelain)" diff --git a/regenerate.sh b/regenerate.sh index bcf8c91..0695b70 100755 --- a/regenerate.sh +++ b/regenerate.sh @@ -1,37 +1,80 @@ #!/usr/bin/env bash -tv_scripts=( - bip_0032 - f4jumble - f4jumble_long - orchard_empty_roots - orchard_generators - orchard_group_hash - orchard_key_components - orchard_map_to_curve - orchard_merkle_tree - orchard_note_encryption - orchard_poseidon - orchard_poseidon_hash - orchard_sinsemilla - orchard_zip32 - sapling_generators - sapling_key_components - sapling_note_encryption - sapling_signatures - sapling_zip32 - sapling_zip32_hard - unified_address - unified_full_viewing_keys - unified_incoming_viewing_keys - zip_0143 - zip_0243 - zip_0244 - zip_0316 - zip_0320) +case "$1" in + "rust" ) + gen_types=(rust) + ;; + "zcash" ) + gen_types=(zcash) + ;; + "json") + gen_types=(json) + ;; + "all") + gen_types=(rust zcash json) + ;; + *) + echo "Unexpected generation type: $1" + exit 1 + ;; +esac -for generator in "${tv_scripts[@]}" +case "$2" in + "all" ) + tv_scripts=( + bip_0032 + f4jumble + f4jumble_long + orchard_empty_roots + orchard_generators + orchard_group_hash + orchard_key_components + orchard_map_to_curve + orchard_merkle_tree + orchard_note_encryption + orchard_poseidon + orchard_poseidon_hash + orchard_sinsemilla + orchard_zip32 + sapling_generators + sapling_key_components + sapling_note_encryption + sapling_signatures + sapling_zip32 + sapling_zip32_hard + unified_address + unified_full_viewing_keys + unified_incoming_viewing_keys + zip_0143 + zip_0243 + zip_0244 + zip_0316 + zip_0320) + ;; + *) + tv_scripts=($2) + ;; +esac + +for gen_type in "${gen_types[@]}" do - echo "# $generator" - poetry run $generator -t $1 >test-vectors/$1/$generator.$2 + echo "Generating $gen_type test vectors..." + case "$gen_type" in + "rust" ) + extension="rs" + ;; + "zcash" ) + extension="json" + ;; + "json") + extension="json" + ;; + esac + + for generator in "${tv_scripts[@]}" + do + echo "# $generator" + poetry run $generator -t $gen_type >test-vectors/$gen_type/$generator.$extension + done + echo "Finished $gen_type." done From bff71ae1a81adc127af3819305593c5c40673939 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 1 Oct 2024 14:32:31 -0600 Subject: [PATCH 3/3] Generate test vectors for orchard_zip32 --- test-vectors/json/orchard_zip32.json | 8 ++++ test-vectors/rust/orchard_zip32.rs | 66 +++++++++++++++++++++++++++ test-vectors/zcash/orchard_zip32.json | 8 ++++ 3 files changed, 82 insertions(+) create mode 100644 test-vectors/json/orchard_zip32.json create mode 100644 test-vectors/rust/orchard_zip32.rs create mode 100644 test-vectors/zcash/orchard_zip32.json diff --git a/test-vectors/json/orchard_zip32.json b/test-vectors/json/orchard_zip32.json new file mode 100644 index 0000000..4f19f29 --- /dev/null +++ b/test-vectors/json/orchard_zip32.json @@ -0,0 +1,8 @@ +[ + ["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_zip32.py"], + ["sk, c, xsk, fp"], + ["7eee3c1017870990a3dd6891b82f80be8976c1e7dc20d60817a5e88e8b2cd4b8", "ab8b7a00509ef20e469b5292b61d474b7cffcb1657924cda720250ae40526677", "000000000000000000ab8b7a00509ef20e469b5292b61d474b7cffcb1657924cda720250ae405266777eee3c1017870990a3dd6891b82f80be8976c1e7dc20d60817a5e88e8b2cd4b8", "ff4cda5002c8d182058807b84e616b6d339e1bbeecea01650568d891a438e706"], + ["98d703fcb40504c95b3b6ed10ecd50082cff97dfd1dd9aa0913c78f977c962af", "6a041dfb9cfebee97cb1854fdc481cc04f02c9577aa6f13b2c445b80a9669a22", "01ff4cda50010000806a041dfb9cfebee97cb1854fdc481cc04f02c9577aa6f13b2c445b80a9669a2298d703fcb40504c95b3b6ed10ecd50082cff97dfd1dd9aa0913c78f977c962af", "32bbdc921d066f235dc93e913b8fe1fd5b9f7f6a13d56f18ec0d3620d1f7b9a6"], + ["99afd8894baad58784d0ec08f5148ee2c2a17b2b294b08ef9e0a0cf14bcc0920", "6da8b57a36c77ad6412a9dc0115f12aced0ee01c402a0cf0a507cb17fc7bbd1d", "0232bbdc92020000806da8b57a36c77ad6412a9dc0115f12aced0ee01c402a0cf0a507cb17fc7bbd1d99afd8894baad58784d0ec08f5148ee2c2a17b2b294b08ef9e0a0cf14bcc0920", "36a57c4fc5b8b4a3d62f22a5500878f393856b7ecce771ad597ca964b98637d9"], + ["96439ea348a4b2ce4ec7beb4543c70274c8f76495d60c5fa5f018b68f3c32367", "b196e9b5809d76577a8944c3f8c8a83f93f0c8f5ace6e7bc9ce4396c034d93fe", "0336a57c4f03000080b196e9b5809d76577a8944c3f8c8a83f93f0c8f5ace6e7bc9ce4396c034d93fe96439ea348a4b2ce4ec7beb4543c70274c8f76495d60c5fa5f018b68f3c32367", "be1a1b661d2ca319822a32550d6dc488b6571e0cd781d5078b8f7ba366ddd368"] +] diff --git a/test-vectors/rust/orchard_zip32.rs b/test-vectors/rust/orchard_zip32.rs new file mode 100644 index 0000000..381c07f --- /dev/null +++ b/test-vectors/rust/orchard_zip32.rs @@ -0,0 +1,66 @@ + struct TestVector { + sk: [u8; 32], + c: [u8; 32], + xsk: [u8; 73], + fp: [u8; 32], + }; + + // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_zip32.py + let test_vectors = vec![ + TestVector { + sk: [ + 0x7e, 0xee, 0x3c, 0x10, 0x17, 0x87, 0x09, 0x90, 0xa3, 0xdd, 0x68, 0x91, 0xb8, 0x2f, 0x80, 0xbe, 0x89, 0x76, 0xc1, 0xe7, 0xdc, 0x20, 0xd6, 0x08, 0x17, 0xa5, 0xe8, 0x8e, 0x8b, 0x2c, 0xd4, 0xb8 + ], + c: [ + 0xab, 0x8b, 0x7a, 0x00, 0x50, 0x9e, 0xf2, 0x0e, 0x46, 0x9b, 0x52, 0x92, 0xb6, 0x1d, 0x47, 0x4b, 0x7c, 0xff, 0xcb, 0x16, 0x57, 0x92, 0x4c, 0xda, 0x72, 0x02, 0x50, 0xae, 0x40, 0x52, 0x66, 0x77 + ], + xsk: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x8b, 0x7a, 0x00, 0x50, 0x9e, 0xf2, 0x0e, 0x46, 0x9b, 0x52, 0x92, 0xb6, 0x1d, 0x47, 0x4b, 0x7c, 0xff, 0xcb, 0x16, 0x57, 0x92, 0x4c, 0xda, 0x72, 0x02, 0x50, 0xae, 0x40, 0x52, 0x66, 0x77, 0x7e, 0xee, 0x3c, 0x10, 0x17, 0x87, 0x09, 0x90, 0xa3, 0xdd, 0x68, 0x91, 0xb8, 0x2f, 0x80, 0xbe, 0x89, 0x76, 0xc1, 0xe7, 0xdc, 0x20, 0xd6, 0x08, 0x17, 0xa5, 0xe8, 0x8e, 0x8b, 0x2c, 0xd4, 0xb8 + ], + fp: [ + 0xff, 0x4c, 0xda, 0x50, 0x02, 0xc8, 0xd1, 0x82, 0x05, 0x88, 0x07, 0xb8, 0x4e, 0x61, 0x6b, 0x6d, 0x33, 0x9e, 0x1b, 0xbe, 0xec, 0xea, 0x01, 0x65, 0x05, 0x68, 0xd8, 0x91, 0xa4, 0x38, 0xe7, 0x06 + ], + }, + TestVector { + sk: [ + 0x98, 0xd7, 0x03, 0xfc, 0xb4, 0x05, 0x04, 0xc9, 0x5b, 0x3b, 0x6e, 0xd1, 0x0e, 0xcd, 0x50, 0x08, 0x2c, 0xff, 0x97, 0xdf, 0xd1, 0xdd, 0x9a, 0xa0, 0x91, 0x3c, 0x78, 0xf9, 0x77, 0xc9, 0x62, 0xaf + ], + c: [ + 0x6a, 0x04, 0x1d, 0xfb, 0x9c, 0xfe, 0xbe, 0xe9, 0x7c, 0xb1, 0x85, 0x4f, 0xdc, 0x48, 0x1c, 0xc0, 0x4f, 0x02, 0xc9, 0x57, 0x7a, 0xa6, 0xf1, 0x3b, 0x2c, 0x44, 0x5b, 0x80, 0xa9, 0x66, 0x9a, 0x22 + ], + xsk: [ + 0x01, 0xff, 0x4c, 0xda, 0x50, 0x01, 0x00, 0x00, 0x80, 0x6a, 0x04, 0x1d, 0xfb, 0x9c, 0xfe, 0xbe, 0xe9, 0x7c, 0xb1, 0x85, 0x4f, 0xdc, 0x48, 0x1c, 0xc0, 0x4f, 0x02, 0xc9, 0x57, 0x7a, 0xa6, 0xf1, 0x3b, 0x2c, 0x44, 0x5b, 0x80, 0xa9, 0x66, 0x9a, 0x22, 0x98, 0xd7, 0x03, 0xfc, 0xb4, 0x05, 0x04, 0xc9, 0x5b, 0x3b, 0x6e, 0xd1, 0x0e, 0xcd, 0x50, 0x08, 0x2c, 0xff, 0x97, 0xdf, 0xd1, 0xdd, 0x9a, 0xa0, 0x91, 0x3c, 0x78, 0xf9, 0x77, 0xc9, 0x62, 0xaf + ], + fp: [ + 0x32, 0xbb, 0xdc, 0x92, 0x1d, 0x06, 0x6f, 0x23, 0x5d, 0xc9, 0x3e, 0x91, 0x3b, 0x8f, 0xe1, 0xfd, 0x5b, 0x9f, 0x7f, 0x6a, 0x13, 0xd5, 0x6f, 0x18, 0xec, 0x0d, 0x36, 0x20, 0xd1, 0xf7, 0xb9, 0xa6 + ], + }, + TestVector { + sk: [ + 0x99, 0xaf, 0xd8, 0x89, 0x4b, 0xaa, 0xd5, 0x87, 0x84, 0xd0, 0xec, 0x08, 0xf5, 0x14, 0x8e, 0xe2, 0xc2, 0xa1, 0x7b, 0x2b, 0x29, 0x4b, 0x08, 0xef, 0x9e, 0x0a, 0x0c, 0xf1, 0x4b, 0xcc, 0x09, 0x20 + ], + c: [ + 0x6d, 0xa8, 0xb5, 0x7a, 0x36, 0xc7, 0x7a, 0xd6, 0x41, 0x2a, 0x9d, 0xc0, 0x11, 0x5f, 0x12, 0xac, 0xed, 0x0e, 0xe0, 0x1c, 0x40, 0x2a, 0x0c, 0xf0, 0xa5, 0x07, 0xcb, 0x17, 0xfc, 0x7b, 0xbd, 0x1d + ], + xsk: [ + 0x02, 0x32, 0xbb, 0xdc, 0x92, 0x02, 0x00, 0x00, 0x80, 0x6d, 0xa8, 0xb5, 0x7a, 0x36, 0xc7, 0x7a, 0xd6, 0x41, 0x2a, 0x9d, 0xc0, 0x11, 0x5f, 0x12, 0xac, 0xed, 0x0e, 0xe0, 0x1c, 0x40, 0x2a, 0x0c, 0xf0, 0xa5, 0x07, 0xcb, 0x17, 0xfc, 0x7b, 0xbd, 0x1d, 0x99, 0xaf, 0xd8, 0x89, 0x4b, 0xaa, 0xd5, 0x87, 0x84, 0xd0, 0xec, 0x08, 0xf5, 0x14, 0x8e, 0xe2, 0xc2, 0xa1, 0x7b, 0x2b, 0x29, 0x4b, 0x08, 0xef, 0x9e, 0x0a, 0x0c, 0xf1, 0x4b, 0xcc, 0x09, 0x20 + ], + fp: [ + 0x36, 0xa5, 0x7c, 0x4f, 0xc5, 0xb8, 0xb4, 0xa3, 0xd6, 0x2f, 0x22, 0xa5, 0x50, 0x08, 0x78, 0xf3, 0x93, 0x85, 0x6b, 0x7e, 0xcc, 0xe7, 0x71, 0xad, 0x59, 0x7c, 0xa9, 0x64, 0xb9, 0x86, 0x37, 0xd9 + ], + }, + TestVector { + sk: [ + 0x96, 0x43, 0x9e, 0xa3, 0x48, 0xa4, 0xb2, 0xce, 0x4e, 0xc7, 0xbe, 0xb4, 0x54, 0x3c, 0x70, 0x27, 0x4c, 0x8f, 0x76, 0x49, 0x5d, 0x60, 0xc5, 0xfa, 0x5f, 0x01, 0x8b, 0x68, 0xf3, 0xc3, 0x23, 0x67 + ], + c: [ + 0xb1, 0x96, 0xe9, 0xb5, 0x80, 0x9d, 0x76, 0x57, 0x7a, 0x89, 0x44, 0xc3, 0xf8, 0xc8, 0xa8, 0x3f, 0x93, 0xf0, 0xc8, 0xf5, 0xac, 0xe6, 0xe7, 0xbc, 0x9c, 0xe4, 0x39, 0x6c, 0x03, 0x4d, 0x93, 0xfe + ], + xsk: [ + 0x03, 0x36, 0xa5, 0x7c, 0x4f, 0x03, 0x00, 0x00, 0x80, 0xb1, 0x96, 0xe9, 0xb5, 0x80, 0x9d, 0x76, 0x57, 0x7a, 0x89, 0x44, 0xc3, 0xf8, 0xc8, 0xa8, 0x3f, 0x93, 0xf0, 0xc8, 0xf5, 0xac, 0xe6, 0xe7, 0xbc, 0x9c, 0xe4, 0x39, 0x6c, 0x03, 0x4d, 0x93, 0xfe, 0x96, 0x43, 0x9e, 0xa3, 0x48, 0xa4, 0xb2, 0xce, 0x4e, 0xc7, 0xbe, 0xb4, 0x54, 0x3c, 0x70, 0x27, 0x4c, 0x8f, 0x76, 0x49, 0x5d, 0x60, 0xc5, 0xfa, 0x5f, 0x01, 0x8b, 0x68, 0xf3, 0xc3, 0x23, 0x67 + ], + fp: [ + 0xbe, 0x1a, 0x1b, 0x66, 0x1d, 0x2c, 0xa3, 0x19, 0x82, 0x2a, 0x32, 0x55, 0x0d, 0x6d, 0xc4, 0x88, 0xb6, 0x57, 0x1e, 0x0c, 0xd7, 0x81, 0xd5, 0x07, 0x8b, 0x8f, 0x7b, 0xa3, 0x66, 0xdd, 0xd3, 0x68 + ], + }, + ]; diff --git a/test-vectors/zcash/orchard_zip32.json b/test-vectors/zcash/orchard_zip32.json new file mode 100644 index 0000000..1d8cfd9 --- /dev/null +++ b/test-vectors/zcash/orchard_zip32.json @@ -0,0 +1,8 @@ +[ + ["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_zip32.py"], + ["sk, c, xsk, fp"], + ["b8d42c8b8ee8a51708d620dce7c17689be802fb89168dda390098717103cee7e", "77665240ae500272da4c925716cbff7c4b471db692529b460ef29e50007a8bab", "000000000000000000ab8b7a00509ef20e469b5292b61d474b7cffcb1657924cda720250ae405266777eee3c1017870990a3dd6891b82f80be8976c1e7dc20d60817a5e88e8b2cd4b8", "06e738a491d868056501eaecbe1b9e336d6b614eb807880582d1c80250da4cff"], + ["af62c977f9783c91a09addd1df97ff2c0850cd0ed16e3b5bc90405b4fc03d798", "229a66a9805b442c3bf1a67a57c9024fc01c48dc4f85b17ce9befe9cfb1d046a", "01ff4cda50010000806a041dfb9cfebee97cb1854fdc481cc04f02c9577aa6f13b2c445b80a9669a2298d703fcb40504c95b3b6ed10ecd50082cff97dfd1dd9aa0913c78f977c962af", "a6b9f7d120360dec186fd5136a7f9f5bfde18f3b913ec95d236f061d92dcbb32"], + ["2009cc4bf10c0a9eef084b292b7ba1c2e28e14f508ecd08487d5aa4b89d8af99", "1dbd7bfc17cb07a5f00c2a401ce00eedac125f11c09d2a41d67ac7367ab5a86d", "0232bbdc92020000806da8b57a36c77ad6412a9dc0115f12aced0ee01c402a0cf0a507cb17fc7bbd1d99afd8894baad58784d0ec08f5148ee2c2a17b2b294b08ef9e0a0cf14bcc0920", "d93786b964a97c59ad71e7cc7e6b8593f3780850a5222fd6a3b4b8c54f7ca536"], + ["6723c3f3688b015ffac5605d49768f4c27703c54b4bec74eceb2a448a39e4396", "fe934d036c39e49cbce7e6acf5c8f0933fa8c8f8c344897a57769d80b5e996b1", "0336a57c4f03000080b196e9b5809d76577a8944c3f8c8a83f93f0c8f5ace6e7bc9ce4396c034d93fe96439ea348a4b2ce4ec7beb4543c70274c8f76495d60c5fa5f018b68f3c32367", "68d3dd66a37b8f8b07d581d70c1e57b688c46d0d55322a8219a32c1d661b1abe"] +]