Merge pull request #4 from str4d/json-output

Implement Zcash test vector output format
This commit is contained in:
str4d 2018-06-13 23:09:49 +12:00 committed by GitHub
commit 0e854b1ddd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 196 additions and 173 deletions

View File

@ -1,9 +1,8 @@
#!/usr/bin/env python3
from binascii import hexlify
from pyblake2 import blake2s
from sapling_jubjub import Point, JUBJUB_COFACTOR
from sapling_utils import chunk
from tv_output import render_args, render_tv
# First 64 bytes of the BLAKE2s input during group hash.
# This is chosen to be some random string that we couldn't have
@ -51,44 +50,26 @@ VALUE_COMMITMENT_RANDOMNESS_BASE = find_group_hash(b'Zcash_cv', b'r')
def main():
print('''
struct SaplingGenerators {
skb: [u8; 32],
pkb: [u8; 32],
npb: [u8; 32],
wprb: [u8; 32],
vcvb: [u8; 32],
vcrb: [u8; 32],
};
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_generators.py
let sapling_generators = SaplingGenerators {
skb: [
%s
],
pkb: [
%s
],
npb: [
%s
],
wprb: [
%s
],
vcvb: [
%s
],
vcrb: [
%s
],
};''' % (
chunk(hexlify(bytes(SPENDING_KEY_BASE))),
chunk(hexlify(bytes(PROVING_KEY_BASE))),
chunk(hexlify(bytes(NOTE_POSITION_BASE))),
chunk(hexlify(bytes(WINDOWED_PEDERSEN_RANDOMNESS_BASE))),
chunk(hexlify(bytes(VALUE_COMMITMENT_VALUE_BASE))),
chunk(hexlify(bytes(VALUE_COMMITMENT_RANDOMNESS_BASE))),
))
render_tv(
render_args(),
'sapling_generators',
(
('skb', '[u8; 32]'),
('pkb', '[u8; 32]'),
('npb', '[u8; 32]'),
('wprb', '[u8; 32]'),
('vcvb', '[u8; 32]'),
('vcrb', '[u8; 32]'),
),
{
'skb': bytes(SPENDING_KEY_BASE),
'pkb': bytes(PROVING_KEY_BASE),
'npb': bytes(NOTE_POSITION_BASE),
'wprb': bytes(WINDOWED_PEDERSEN_RANDOMNESS_BASE),
'vcvb': bytes(VALUE_COMMITMENT_VALUE_BASE),
'vcrb': bytes(VALUE_COMMITMENT_RANDOMNESS_BASE),
},
)
if __name__ == '__main__':

View File

@ -1,12 +1,12 @@
#!/usr/bin/env python3
from binascii import hexlify
from pyblake2 import blake2b, blake2s
from sapling_generators import PROVING_KEY_BASE, SPENDING_KEY_BASE, group_hash
from sapling_jubjub import Fr
from sapling_merkle_tree import MERKLE_DEPTH
from sapling_notes import note_commit, note_nullifier
from sapling_utils import chunk, leos2bsp, leos2ip
from sapling_utils import leos2bsp, leos2ip
from tv_output import render_args, render_tv
#
# Utilities
@ -91,26 +91,9 @@ class SpendingKey(object):
def main():
print('''
struct TestVector {
sk: [u8; 32],
ask: [u8; 32],
nsk: [u8; 32],
ovk: [u8; 32],
ak: [u8; 32],
nk: [u8; 32],
ivk: [u8; 32],
default_d: [u8; 11],
default_pk_d: [u8; 32],
note_v: u64,
note_r: [u8; 32],
note_cm: [u8; 32],
note_pos: u64,
note_nf: [u8; 32],
};
args = render_args()
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_key_components.py
let test_vectors = vec![''')
test_vectors = []
for i in range(0, 10):
sk = SpendingKey(bytes([i] * 32))
note_v = (2548793025584392057432895043257984320*i) % 2**64
@ -122,62 +105,44 @@ def main():
note_v)
note_pos = (980705743285409327583205473820957432*i) % 2**MERKLE_DEPTH
note_nf = note_nullifier(sk.nk(), note_cm, Fr(note_pos))
print(''' TestVector {
sk: [
%s
],
ask: [
%s
],
nsk: [
%s
],
ovk: [
%s
],
ak: [
%s
],
nk: [
%s
],
ivk: [
%s
],
default_d: [
%s
],
default_pk_d: [
%s
],
note_v: %s,
note_r: [
%s
],
note_cm: [
%s
],
note_pos: %s,
note_nf: [
%s
],
},''' % (
chunk(hexlify(sk.data)),
chunk(hexlify(bytes(sk.ask()))),
chunk(hexlify(bytes(sk.nsk()))),
chunk(hexlify(sk.ovk())),
chunk(hexlify(bytes(sk.ak()))),
chunk(hexlify(bytes(sk.nk()))),
chunk(hexlify(bytes(sk.ivk()))),
chunk(hexlify(sk.default_d())),
chunk(hexlify(bytes(sk.default_pkd()))),
note_v,
chunk(hexlify(bytes(note_r))),
chunk(hexlify(bytes(note_cm.u))),
note_pos,
chunk(hexlify(note_nf)),
))
print(' ];')
test_vectors.append({
'sk': sk.data,
'ask': bytes(sk.ask()),
'nsk': bytes(sk.nsk()),
'ovk': sk.ovk(),
'ak': bytes(sk.ak()),
'nk': bytes(sk.nk()),
'ivk': bytes(sk.ivk()),
'default_d': sk.default_d(),
'default_pk_d': bytes(sk.default_pkd()),
'note_v': note_v,
'note_r': bytes(note_r),
'note_cm': bytes(note_cm.u),
'note_pos': note_pos,
'note_nf': note_nf,
})
render_tv(
args,
'sapling_key_components',
(
('sk', '[u8; 32]'),
('ask', '[u8; 32]'),
('nsk', '[u8; 32]'),
('ovk', '[u8; 32]'),
('ak', '[u8; 32]'),
('nk', '[u8; 32]'),
('ivk', '[u8; 32]'),
('default_d', '[u8; 11]'),
('default_pk_d', '[u8; 32]'),
('note_v', 'u64'),
('note_r', '[u8; 32]'),
('note_cm', '[u8; 32]'),
('note_pos', 'u64'),
('note_nf', '[u8; 32]'),
),
test_vectors,
)
if __name__ == '__main__':

View File

@ -1,12 +1,12 @@
#!/usr/bin/env python3
from binascii import hexlify
import os
from pyblake2 import blake2b
from sapling_generators import SPENDING_KEY_BASE
from sapling_jubjub import Fr, Point, r_j
from sapling_key_components import to_scalar
from sapling_utils import cldiv, chunk, leos2ip
from sapling_utils import cldiv, leos2ip
from tv_output import render_args, render_tv
def H(x):
@ -65,6 +65,8 @@ class RedJubjub(object):
def main():
args = render_args()
from random import Random
rng = Random(0xabad533d)
def randbytes(l):
@ -74,20 +76,7 @@ def main():
return bytes(ret)
rj = RedJubjub(SPENDING_KEY_BASE, randbytes)
print('''
struct TestVector {
sk: [u8; 32],
vk: [u8; 32],
alpha: [u8; 32],
rsk: [u8; 32],
rvk: [u8; 32],
m: [u8; 32],
sig: [u8; 64],
rsig: [u8; 64],
};
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_signatures.py
let test_vectors = vec![''')
test_vectors = []
for i in range(0, 10):
sk = rj.gen_private()
vk = rj.derive_public(sk)
@ -103,42 +92,32 @@ def main():
assert not rj.verify(vk, M, rsig)
assert not rj.verify(rvk, M, sig)
print(''' TestVector {
sk: [
%s
],
vk: [
%s
],
alpha: [
%s
],
rsk: [
%s
],
rvk: [
%s
],
m: [
%s
],
sig: [
%s
],
rsig: [
%s
],
},''' % (
chunk(hexlify(bytes(sk))),
chunk(hexlify(bytes(vk))),
chunk(hexlify(bytes(alpha))),
chunk(hexlify(bytes(rsk))),
chunk(hexlify(bytes(rvk))),
chunk(hexlify(M)),
chunk(hexlify(sig)),
chunk(hexlify(rsig)),
))
print(' ];')
test_vectors.append({
'sk': bytes(sk),
'vk': bytes(vk),
'alpha': bytes(alpha),
'rsk': bytes(rsk),
'rvk': bytes(rvk),
'm': M,
'sig': sig,
'rsig': rsig,
})
render_tv(
args,
'sapling_signatures',
(
('sk', '[u8; 32]'),
('vk', '[u8; 32]'),
('alpha', '[u8; 32]'),
('rsk', '[u8; 32]'),
('rvk', '[u8; 32]'),
('m', '[u8; 32]'),
('sig', '[u8; 64]'),
('rsig', '[u8; 64]'),
),
test_vectors,
)
if __name__ == '__main__':

View File

@ -3,10 +3,6 @@
def cldiv(n, divisor):
return (n + (divisor - 1)) // divisor
def chunk(h):
h = str(h, 'utf-8')
return '0x' + ', 0x'.join([h[i:i+2] for i in range(0, len(h), 2)])
def i2lebsp(l, x):
return [int(c) for c in format(x, '0%sb' % l)[::-1]]

102
tv_output.py Normal file
View File

@ -0,0 +1,102 @@
import argparse
from binascii import hexlify
import json
def chunk(h):
h = str(h, 'utf-8')
return '0x' + ', 0x'.join([h[i:i+2] for i in range(0, len(h), 2)])
#
# JSON (with string comments)
# If bitcoin_flavoured == True, 32-byte values are reversed
#
def tv_value_json(value, bitcoin_flavoured):
if type(value) == bytes:
if bitcoin_flavoured and len(value) == 32:
value = value[::-1]
value = hexlify(value).decode()
return value
def tv_json(filename, parts, vectors, bitcoin_flavoured):
if type(vectors) == type({}):
vectors = [vectors]
print('''[
["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/%s.py"],
["%s"],''' % (
filename,
', '.join([p[0] for p in parts])
))
print(' ' + ',\n '.join([
json.dumps([tv_value_json(v[p[0]], bitcoin_flavoured) for p in parts]) for v in vectors
]))
print(']')
#
# Rust
#
def tv_bytes_rust(name, value, pad):
print('''%s%s: [
%s%s
%s],''' % (
pad,
name,
pad,
chunk(hexlify(value)),
pad,
))
def tv_int_rust(name, value, pad):
print('%s%s: %d,' % (pad, name, value))
def tv_part_rust(name, value, indent=3):
pad = ' ' * indent
if type(value) == bytes:
tv_bytes_rust(name, value, pad)
elif type(value) == int:
tv_int_rust(name, value, pad)
else:
raise ValueError('Invalid type(%s): %s' % (name, type(value)))
def tv_rust(filename, parts, vectors):
print(' struct TestVector {')
[print(' %s: %s,' % p) for p in parts]
print(''' };
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/%s.py''' % (
filename,
))
if type(vectors) == type({}):
print(' let test_vector = TestVector {')
[tv_part_rust(p[0], vectors[p[0]]) for p in parts]
print(' };')
elif type(vectors) == type([]):
print(' let test_vectors = vec![')
for vector in vectors:
print(' TestVector {')
[tv_part_rust(p[0], vector[p[0]], 4) for p in parts]
print(' },')
print(' ];')
else:
raise ValueError('Invalid type(vectors)')
#
# Rendering functions
#
def render_args():
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', choices=['zcash', 'rust'], default='rust')
return parser.parse_args()
def render_tv(args, filename, parts, vectors):
if args.target == 'rust':
tv_rust(filename, parts, vectors)
elif args.target == 'zcash':
tv_json(filename, parts, vectors, True)