zcash-test-vectors/orchard_commitments.py

74 lines
2.4 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
from orchard_group_hash import group_hash
from orchard_pallas import Fp, Scalar
from orchard_sinsemilla import sinsemilla_hash_to_point
from sapling_utils import i2lebsp
# Commitment schemes used in Orchard https://zips.z.cash/protocol/nu5.pdf#concretecommit
# https://zips.z.cash/protocol/nu5.pdf#constants
L_ORCHARD_BASE = 255
# https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit
def homomorphic_pedersen_commitment(rcv: Scalar, D, v: Scalar):
return group_hash(D, b"v") * v + group_hash(D, b"r") * rcv
def value_commit(rcv: Scalar, v: Scalar):
return homomorphic_pedersen_commitment(rcv, b"z.cash:Orchard-cv", v)
def rcv_trapdoor(randbytes):
return Scalar.random(randbytes)
# https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit
def sinsemilla_commit(r: Scalar, D, M):
return sinsemilla_hash_to_point(D + b"-M", M).checked_incomplete_add(
r * group_hash(D + b"-r", "")
)
def sinsemilla_short_commit(r: Scalar, D, M):
return sinsemilla_commit(r, D, M).extract()
# https://zips.z.cash/protocol/nu5.pdf#concreteorchardnotecommit
def note_commit(rcm, g_d, pk_d, v, rho, psi):
return sinsemilla_commit(
rcm,
"z.cash: Orchard-NoteCommit",
g_d + pk_d + i2lebsp(64, v) + i2lebsp(L_ORCHARD_BASE, rho) + i2lebsp(L_ORCHARD_BASE, psi)
)
def rcm_trapdoor(randbytes):
return Scalar.random(randbytes)
# https://zips.z.cash/protocol/nu5.pdf#concreteorchardnotecommit
def commit_ivk(rivk, ak, nk):
return sinsemilla_short_commit(
rivk,
"z.cash: Orchard-CommitIvk",
i2lebsp(L_ORCHARD_BASE, ak) + i2lebsp(L_ORCHARD_BASE, nk)
)
def rivk_trapdoor(randbytes):
return Scalar.random(randbytes)
# Test consistency of ValueCommit^{Orchard} with precomputed generators
def test_value_commit():
from random import Random
from orchard_generators import VALUE_COMMITMENT_RANDOMNESS_BASE, VALUE_COMMITMENT_VALUE_BASE
rng = Random(0xabad533d)
def randbytes(l):
ret = []
while len(ret) < l:
ret.append(rng.randrange(0, 256))
return bytes(ret)
rcv = rcv_trapdoor(randbytes)
v = Scalar(100000000)
assert value_commit(rcv, v) == VALUE_COMMITMENT_RANDOMNESS_BASE * rcv + VALUE_COMMITMENT_VALUE_BASE * v
if __name__ == '__main__':
test_value_commit()