Merge pull request #102 from zcash/orchard-zip32

Add Orchard ZIP 32 test vectors
This commit is contained in:
Kris Nuttycombe 2024-10-24 13:14:43 -06:00 committed by GitHub
commit 5b76d4bba0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 260 additions and 35 deletions

View File

@ -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)"

View File

@ -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"

View File

@ -1,36 +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
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

View File

@ -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"]
]

View File

@ -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
],
},
];

View File

@ -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"]
]

View File

@ -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()