2018-05-17 16:57:11 -07:00
|
|
|
#!/usr/bin/env python3
|
2018-05-17 23:28:00 -07:00
|
|
|
from binascii import hexlify
|
2018-05-17 16:57:11 -07:00
|
|
|
from pyblake2 import blake2s
|
|
|
|
|
|
|
|
from sapling_jubjub import Point, JUBJUB_COFACTOR
|
2018-06-04 21:10:43 -07:00
|
|
|
from tv_output import chunk
|
2018-05-17 16:57:11 -07:00
|
|
|
|
|
|
|
# First 64 bytes of the BLAKE2s input during group hash.
|
|
|
|
# This is chosen to be some random string that we couldn't have
|
|
|
|
# anticipated when we designed the algorithm, for rigidity purposes.
|
|
|
|
# We deliberately use an ASCII hex string of 32 bytes here.
|
|
|
|
CRS = b'096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0'
|
|
|
|
|
2018-05-17 17:45:19 -07:00
|
|
|
|
|
|
|
#
|
|
|
|
# Group hash
|
|
|
|
#
|
|
|
|
|
|
|
|
def group_hash(D, M):
|
|
|
|
digest = blake2s(person=D)
|
2018-05-17 16:57:11 -07:00
|
|
|
digest.update(CRS)
|
2018-05-17 17:45:19 -07:00
|
|
|
digest.update(M)
|
2018-05-17 16:57:11 -07:00
|
|
|
p = Point.from_bytes(digest.digest())
|
|
|
|
if not p:
|
|
|
|
return None
|
|
|
|
q = p * JUBJUB_COFACTOR
|
|
|
|
if q == Point.ZERO:
|
|
|
|
return None
|
|
|
|
return q
|
|
|
|
|
2018-05-17 17:45:19 -07:00
|
|
|
def find_group_hash(D, M):
|
2018-05-17 16:57:11 -07:00
|
|
|
i = 0
|
|
|
|
while True:
|
2018-05-17 17:45:19 -07:00
|
|
|
p = group_hash(D, M + bytes([i]))
|
2018-05-17 16:57:11 -07:00
|
|
|
if p:
|
|
|
|
return p
|
|
|
|
i += 1
|
2018-05-17 23:00:45 -07:00
|
|
|
assert i < 256
|
2018-05-17 16:57:11 -07:00
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Sapling generators
|
|
|
|
#
|
|
|
|
|
|
|
|
SPENDING_KEY_BASE = find_group_hash(b'Zcash_G_', b'')
|
|
|
|
PROVING_KEY_BASE = find_group_hash(b'Zcash_H_', b'')
|
2018-05-17 17:47:05 -07:00
|
|
|
NOTE_POSITION_BASE = find_group_hash(b'Zcash_J_', b'')
|
|
|
|
WINDOWED_PEDERSEN_RANDOMNESS_BASE = find_group_hash(b'Zcash_PH', b'r')
|
|
|
|
VALUE_COMMITMENT_VALUE_BASE = find_group_hash(b'Zcash_cv', b'v')
|
|
|
|
VALUE_COMMITMENT_RANDOMNESS_BASE = find_group_hash(b'Zcash_cv', b'r')
|
2018-05-17 23:28:00 -07:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
print('''
|
|
|
|
struct SaplingGenerators {
|
|
|
|
skb: [u8; 32],
|
|
|
|
pkb: [u8; 32],
|
|
|
|
npb: [u8; 32],
|
|
|
|
wprb: [u8; 32],
|
|
|
|
vcvb: [u8; 32],
|
|
|
|
vcrb: [u8; 32],
|
|
|
|
};
|
|
|
|
|
2018-05-18 12:48:49 -07:00
|
|
|
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_generators.py
|
2018-05-17 23:28:00 -07:00
|
|
|
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))),
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|