From 4052b6404b3104bf37303d1068a6bbbb411a260c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 27 Apr 2021 15:41:19 +1200 Subject: [PATCH] Add rendering logic to Orchard GroupHash and Sinsemilla --- orchard_group_hash.py | 35 ++++++++++++++++++++++++++++++++++- orchard_sinsemilla.py | 41 ++++++++++++++++++++++++++++++++++------- tv_output.py | 13 +++++++++++++ 3 files changed, 81 insertions(+), 8 deletions(-) diff --git a/orchard_group_hash.py b/orchard_group_hash.py index a569bd3..0fda02a 100755 --- a/orchard_group_hash.py +++ b/orchard_group_hash.py @@ -9,6 +9,7 @@ from pyblake2 import blake2b from orchard_pallas import Fp, p, q, PALLAS_B, Point from orchard_iso_pallas import PALLAS_ISO_B, PALLAS_ISO_A from sapling_utils import i2beosp, cldiv, beos2ip, i2leosp, lebs2ip +from tv_output import render_args, render_tv # https://stackoverflow.com/questions/2612720/how-to-do-bitwise-exclusive-or-of-two-strings-in-python def sxor(s1,s2): @@ -131,4 +132,36 @@ def group_hash(d, m): q = [map_to_curve_simple_swu(elems[0]), map_to_curve_simple_swu(elems[1])] - return q[0] + q[1] \ No newline at end of file + return q[0] + q[1] + + +def main(): + test_vectors = [ + (b"z.cash:test", b"Trans rights now!"), + ] + + # This is the Pallas test vector from the Sage and Rust code (in affine coordinates). + gh = group_hash(test_vectors[0][0], test_vectors[0][1]) + assert gh == Point(Fp(10899331951394555178876036573383466686793225972744812919361819919497009261523), + Fp(851679174277466283220362715537906858808436854303373129825287392516025427980)) + + test_vectors = [{ + 'domain': domain, + 'msg': msg, + 'point': bytes(group_hash(domain, msg)), + } for (domain, msg) in test_vectors] + + render_tv( + render_args(), + 'orchard_group_hash', + ( + ('domain', 'Vec'), + ('msg', 'Vec'), + ('point', '[u8; 32]'), + ), + test_vectors, + ) + + +if __name__ == "__main__": + main() diff --git a/orchard_sinsemilla.py b/orchard_sinsemilla.py index fe611a1..ca2304c 100755 --- a/orchard_sinsemilla.py +++ b/orchard_sinsemilla.py @@ -8,6 +8,7 @@ import orchard_iso_pallas from orchard_pallas import Fp, Point from sapling_utils import cldiv, lebs2ip, i2leosp from orchard_group_hash import group_hash +from tv_output import render_args, render_tv SINSEMILLA_K = 10 @@ -40,13 +41,39 @@ def sinsemilla_hash_to_point(d, m): def sinsemilla_hash(d, m): return sinsemilla_hash_to_point(d, m).extract() -if __name__ == "__main__": - # This is the Pallas test vector from the Sage and Rust code (in affine coordinates). - gh = group_hash(b"z.cash:test", b"Trans rights now!") - assert gh == Point(Fp(10899331951394555178876036573383466686793225972744812919361819919497009261523), - Fp(851679174277466283220362715537906858808436854303373129825287392516025427980)) - # 40 bits, so no padding - sh = sinsemilla_hash_to_point(b"z.cash:test-Sinsemilla", '0001011010100110001101100011011011110110') +def main(): + test_vectors = [ + # 40 bits, so no padding + (b"z.cash:test-Sinsemilla", [0,0,0,1,0,1,1,0,1,0,1,0,0,1,1,0,0,0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,1,1,1,1,0,1,1,0]), + ] + + sh = sinsemilla_hash_to_point(test_vectors[0][0], test_vectors[0][1]) assert sh == Point(Fp(19681977528872088480295086998934490146368213853811658798708435106473481753752), Fp(14670850419772526047574141291705097968771694788047376346841674072293161339903)) + + test_vectors = [{ + 'domain': domain, + 'msg': msg, + 'point': bytes(sinsemilla_hash_to_point(domain, msg)), + 'hash': bytes(sinsemilla_hash(domain, msg)), + } for (domain, msg) in test_vectors] + + render_tv( + render_args(), + 'orchard_sinsemilla', + ( + ('domain', 'Vec'), + ('msg', { + 'rust_type': 'Vec', + 'rust_fmt': lambda x: str_to_bits(x), + }), + ('point', '[u8; 32]'), + ('hash', '[u8; 32]'), + ), + test_vectors, + ) + + +if __name__ == "__main__": + main() diff --git a/tv_output.py b/tv_output.py index fcb225d..90180a2 100644 --- a/tv_output.py +++ b/tv_output.py @@ -75,6 +75,17 @@ def tv_vec_bytes_rust(name, value, pad): pad, )) +def tv_vec_bool_rust(name, value, pad): + print('''%s%s: vec![ + %s%s +%s],''' % ( + pad, + name, + pad, + ', '.join(['true' if x else 'false' for x in value]), + pad, + )) + def tv_option_bytes_rust(name, value, pad): if value: print('''%s%s: Some([ @@ -121,6 +132,8 @@ def tv_part_rust(name, value, config, indent=3): tv_option_vec_bytes_rust(name, value, pad) elif config['rust_type'] == 'Vec': tv_vec_bytes_rust(name, value, pad) + elif config['rust_type'] == 'Vec': + tv_vec_bool_rust(name, value, pad) elif config['rust_type'].startswith('Option<['): tv_option_bytes_rust(name, value, pad) elif type(value) == bytes: