Add Orchard commitments

HomomorphicPedersenCommit -> ValueCommit
SinsemillaCommit -> NoteCommit
SinsemillaShortCommit -> CommitIvk
This commit is contained in:
therealyingtong 2021-05-03 14:26:44 +08:00
parent bd7c367590
commit 72cae20b61
2 changed files with 83 additions and 0 deletions

73
orchard_commitments.py Normal file
View File

@ -0,0 +1,73 @@
#!/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()

View File

@ -31,6 +31,9 @@ class Fp(FieldElement):
def from_bytes(buf):
return Fp(leos2ip(buf), strict=True)
def random(randbytes):
return Fp(leos2ip(randbytes(32)), strict=False)
def __init__(self, s, strict=False):
FieldElement.__init__(self, Fp, s, p, strict=strict)
@ -90,6 +93,13 @@ class Scalar(FieldElement):
def __str__(self):
return 'Scalar(%s)' % self.s
@staticmethod
def from_bytes(buf):
return Scalar(leos2ip(buf), strict=True)
def random(randbytes):
return Scalar(leos2ip(randbytes(32)), strict=False)
Fp.ZERO = Fp(0)
Fp.ONE = Fp(1)
Fp.MINUS_ONE = Fp(-1)