Merge pull request #28 from zcash-hackworks/orchard-commitments
Add Orchard commitments
This commit is contained in:
commit
12a07b4f61
2
ff1.py
2
ff1.py
|
@ -7,7 +7,7 @@ from binascii import unhexlify, hexlify
|
||||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
from sapling_utils import bebs2ip, i2bebsp, beos2ip, bebs2osp, cldiv
|
from utils import bebs2ip, i2bebsp, beos2ip, bebs2osp, cldiv
|
||||||
|
|
||||||
# Morris Dworkin
|
# Morris Dworkin
|
||||||
# NIST Special Publication 800-38G
|
# NIST Special Publication 800-38G
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
#!/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 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(rand):
|
||||||
|
return Scalar.random(rand)
|
||||||
|
|
||||||
|
# https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit
|
||||||
|
def sinsemilla_commit(r: Scalar, D, M):
|
||||||
|
assert isinstance(r, Scalar)
|
||||||
|
return sinsemilla_hash_to_point(D + b"-M", M).checked_incomplete_add(
|
||||||
|
group_hash(D + b"-r", 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,
|
||||||
|
b"z.cash:Orchard-NoteCommit",
|
||||||
|
g_d + pk_d + i2lebsp(64, v) + i2lebsp(L_ORCHARD_BASE, rho.s) + i2lebsp(L_ORCHARD_BASE, psi.s)
|
||||||
|
)
|
||||||
|
|
||||||
|
def rcm_trapdoor(rand):
|
||||||
|
return Scalar.random(rand)
|
||||||
|
|
||||||
|
# https://zips.z.cash/protocol/nu5.pdf#concreteorchardnotecommit
|
||||||
|
def commit_ivk(rivk: Scalar, ak: Fp, nk: Fp):
|
||||||
|
return sinsemilla_short_commit(
|
||||||
|
rivk,
|
||||||
|
b"z.cash:Orchard-CommitIvk",
|
||||||
|
i2lebsp(L_ORCHARD_BASE, ak.s) + i2lebsp(L_ORCHARD_BASE, nk.s)
|
||||||
|
)
|
||||||
|
|
||||||
|
def rivk_trapdoor(rand):
|
||||||
|
return Scalar.random(rand)
|
||||||
|
|
||||||
|
# Test consistency of ValueCommit^{Orchard} with precomputed generators
|
||||||
|
def test_value_commit():
|
||||||
|
from random import Random
|
||||||
|
from tv_rand import Rand
|
||||||
|
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)
|
||||||
|
rand = Rand(randbytes)
|
||||||
|
|
||||||
|
rcv = rcv_trapdoor(rand)
|
||||||
|
v = Scalar(100000000)
|
||||||
|
|
||||||
|
assert value_commit(rcv, v) == VALUE_COMMITMENT_RANDOMNESS_BASE * rcv + VALUE_COMMITMENT_VALUE_BASE * v
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_value_commit()
|
|
@ -0,0 +1,61 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
||||||
|
|
||||||
|
from pyblake2 import blake2s
|
||||||
|
|
||||||
|
from tv_output import render_args, render_tv
|
||||||
|
from orchard_group_hash import group_hash
|
||||||
|
from orchard_sinsemilla import sinsemilla_hash_to_point
|
||||||
|
|
||||||
|
# https://zips.z.cash/protocol/nu5.pdf#concretespendauthsig
|
||||||
|
SPENDING_KEY_BASE = group_hash(b'z.cash:Orchard', b'G')
|
||||||
|
|
||||||
|
# https://zips.z.cash/protocol/nu5.pdf#commitmentsandnullifiers
|
||||||
|
NULLIFIER_K_BASE = group_hash(b'z.cash:Orchard', b'K')
|
||||||
|
|
||||||
|
# https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit
|
||||||
|
VALUE_COMMITMENT_VALUE_BASE = group_hash(b'z.cash:Orchard-cv', b'v')
|
||||||
|
VALUE_COMMITMENT_RANDOMNESS_BASE = group_hash(b'z.cash:Orchard-cv', b'r')
|
||||||
|
|
||||||
|
# Used in SinsemillaCommit (https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit)
|
||||||
|
NOTE_COMMITMENT_BASE = group_hash(b'z.cash:Orchard-NoteCommit-r', b'')
|
||||||
|
NOTE_COMMITMENT_Q = group_hash(b'z.cash:SinsemillaQ', b'z.cash:Orchard-NoteCommit-M')
|
||||||
|
|
||||||
|
# Used in SinsemillaShortCommit (https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit)
|
||||||
|
IVK_COMMITMENT_BASE = group_hash(b'z.cash:Orchard-CommitIvk-r', b'')
|
||||||
|
IVK_COMMITMENT_Q = group_hash(b'z.cash:SinsemillaQ', b'z.cash:Orchard-CommitIvk-M')
|
||||||
|
|
||||||
|
# Used in SinsemillaHash (https://zips.z.cash/protocol/nu5.pdf#orchardmerklecrh)
|
||||||
|
MERKLE_CRH_Q = group_hash(b'z.cash:SinsemillaQ', b'z.cash:Orchard-MerkleCRH')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
render_tv(
|
||||||
|
render_args(),
|
||||||
|
'orchard_generators',
|
||||||
|
(
|
||||||
|
('skb', '[u8; 32]'),
|
||||||
|
('nkb', '[u8; 32]'),
|
||||||
|
('vcvb', '[u8; 32]'),
|
||||||
|
('vcrb', '[u8; 32]'),
|
||||||
|
('cmb', '[u8; 32]'),
|
||||||
|
('cmq', '[u8; 32]'),
|
||||||
|
('ivkb', '[u8; 32]'),
|
||||||
|
('ivkq', '[u8; 32]'),
|
||||||
|
('mcq', '[u8; 32]'),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
'skb': bytes(SPENDING_KEY_BASE),
|
||||||
|
'nkb': bytes(NULLIFIER_K_BASE),
|
||||||
|
'vcvb': bytes(VALUE_COMMITMENT_VALUE_BASE),
|
||||||
|
'vcrb': bytes(VALUE_COMMITMENT_RANDOMNESS_BASE),
|
||||||
|
'cmb': bytes(NOTE_COMMITMENT_BASE),
|
||||||
|
'cmq': bytes(NOTE_COMMITMENT_Q),
|
||||||
|
'ivkb': bytes(IVK_COMMITMENT_BASE),
|
||||||
|
'ivkq': bytes(IVK_COMMITMENT_Q),
|
||||||
|
'mcq': bytes(MERKLE_CRH_Q),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -8,7 +8,7 @@ import orchard_iso_pallas
|
||||||
from pyblake2 import blake2b
|
from pyblake2 import blake2b
|
||||||
from orchard_pallas import Fp, p, q, PALLAS_B, Point
|
from orchard_pallas import Fp, p, q, PALLAS_B, Point
|
||||||
from orchard_iso_pallas import PALLAS_ISO_B, PALLAS_ISO_A
|
from orchard_iso_pallas import PALLAS_ISO_B, PALLAS_ISO_A
|
||||||
from sapling_utils import i2beosp, cldiv, beos2ip, i2leosp, lebs2ip
|
from utils import i2beosp, cldiv, beos2ip, i2leosp, lebs2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
from tv_rand import Rand
|
from tv_rand import Rand
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ from tv_rand import Rand
|
||||||
def sxor(s1,s2):
|
def sxor(s1,s2):
|
||||||
return bytes([a ^ b for a,b in zip(s1,s2)])
|
return bytes([a ^ b for a,b in zip(s1,s2)])
|
||||||
|
|
||||||
def expand_message_xmd(msg, dst, len_in_bytes):
|
def expand_message_xmd(msg: bytes, dst: bytes, len_in_bytes: int):
|
||||||
|
assert isinstance(msg, bytes)
|
||||||
|
assert isinstance(dst, bytes)
|
||||||
assert len(dst) <= 255
|
assert len(dst) <= 255
|
||||||
|
|
||||||
b_in_bytes = 64 # hash function output size
|
b_in_bytes = 64 # hash function output size
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
from orchard_group_hash import map_to_curve_simple_swu
|
from orchard_group_hash import map_to_curve_simple_swu
|
||||||
from orchard_iso_pallas import Point as IsoPoint
|
from orchard_iso_pallas import Point as IsoPoint
|
||||||
from orchard_pallas import Fp
|
from orchard_pallas import Fp
|
||||||
from sapling_utils import leos2ip
|
from utils import leos2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
from tv_rand import Rand
|
from tv_rand import Rand
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from binascii import unhexlify
|
||||||
from orchard_pallas import Fp
|
from orchard_pallas import Fp
|
||||||
from orchard_sinsemilla import sinsemilla_hash
|
from orchard_sinsemilla import sinsemilla_hash
|
||||||
|
|
||||||
from sapling_utils import i2lebsp, leos2bsp
|
from utils import i2lebsp, leos2bsp
|
||||||
|
|
||||||
# https://zips.z.cash/protocol/nu5.pdf#constants
|
# https://zips.z.cash/protocol/nu5.pdf#constants
|
||||||
MERKLE_DEPTH = 32
|
MERKLE_DEPTH = 32
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
||||||
|
|
||||||
from sapling_jubjub import FieldElement
|
from sapling_jubjub import FieldElement
|
||||||
from sapling_utils import leos2ip
|
from utils import leos2ip
|
||||||
|
|
||||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||||
|
@ -31,6 +31,13 @@ class Fp(FieldElement):
|
||||||
def from_bytes(buf):
|
def from_bytes(buf):
|
||||||
return Fp(leos2ip(buf), strict=True)
|
return Fp(leos2ip(buf), strict=True)
|
||||||
|
|
||||||
|
def random(rand):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
return Fp(leos2ip(rand.b(32)), strict=True)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
def __init__(self, s, strict=False):
|
def __init__(self, s, strict=False):
|
||||||
FieldElement.__init__(self, Fp, s, p, strict=strict)
|
FieldElement.__init__(self, Fp, s, p, strict=strict)
|
||||||
|
|
||||||
|
@ -90,16 +97,29 @@ class Scalar(FieldElement):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'Scalar(%s)' % self.s
|
return 'Scalar(%s)' % self.s
|
||||||
|
|
||||||
Fp.ZERO = Fp(0)
|
@staticmethod
|
||||||
Fp.ONE = Fp(1)
|
def from_bytes(buf):
|
||||||
Fp.MINUS_ONE = Fp(-1)
|
return Scalar(leos2ip(buf), strict=True)
|
||||||
|
|
||||||
assert Fp.ZERO + Fp.ZERO == Fp.ZERO
|
def random(rand):
|
||||||
assert Fp.ZERO + Fp.ONE == Fp.ONE
|
while True:
|
||||||
assert Fp.ONE + Fp.ZERO == Fp.ONE
|
try:
|
||||||
assert Fp.ZERO - Fp.ONE == Fp.MINUS_ONE
|
return Scalar(leos2ip(rand.b(32)), strict=True)
|
||||||
assert Fp.ZERO * Fp.ONE == Fp.ZERO
|
except ValueError:
|
||||||
assert Fp.ONE * Fp.ZERO == Fp.ZERO
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
for F in (Fp, Scalar):
|
||||||
|
F.ZERO = F(0)
|
||||||
|
F.ONE = F(1)
|
||||||
|
F.MINUS_ONE = F(-1)
|
||||||
|
|
||||||
|
assert F.ZERO + F.ZERO == F.ZERO
|
||||||
|
assert F.ZERO + F.ONE == F.ONE
|
||||||
|
assert F.ONE + F.ZERO == F.ONE
|
||||||
|
assert F.ZERO - F.ONE == F.MINUS_ONE
|
||||||
|
assert F.ZERO * F.ONE == F.ZERO
|
||||||
|
assert F.ONE * F.ZERO == F.ZERO
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -209,6 +229,7 @@ class Point(object):
|
||||||
return self.x
|
return self.x
|
||||||
|
|
||||||
def __mul__(self, s):
|
def __mul__(self, s):
|
||||||
|
assert isinstance(s, Scalar)
|
||||||
s = format(s.s, '0256b')
|
s = format(s.s, '0256b')
|
||||||
ret = self.ZERO
|
ret = self.ZERO
|
||||||
for c in s:
|
for c in s:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from orchard_pallas import Fp
|
from orchard_pallas import Fp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from sapling_utils import leos2ip
|
from utils import leos2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
from tv_rand import Rand
|
from tv_rand import Rand
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from orchard_pallas import Fp
|
from orchard_pallas import Fp
|
||||||
from orchard_poseidon import perm
|
from orchard_poseidon import perm
|
||||||
from sapling_utils import leos2ip
|
from utils import leos2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
from tv_rand import Rand
|
from tv_rand import Rand
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import math
|
||||||
import orchard_iso_pallas
|
import orchard_iso_pallas
|
||||||
|
|
||||||
from orchard_pallas import Fp, Point
|
from orchard_pallas import Fp, Point
|
||||||
from sapling_utils import cldiv, lebs2ip, i2leosp
|
from utils import cldiv, lebs2ip, i2leosp
|
||||||
from orchard_group_hash import group_hash
|
from orchard_group_hash import group_hash
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
from tv_rand import Rand
|
from tv_rand import Rand
|
||||||
|
|
|
@ -5,7 +5,7 @@ from pyblake2 import blake2s
|
||||||
|
|
||||||
from sapling_jubjub import Point, JUBJUB_COFACTOR
|
from sapling_jubjub import Point, JUBJUB_COFACTOR
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
from sapling_utils import i2leosp
|
from utils import i2leosp
|
||||||
|
|
||||||
# First 64 bytes of the BLAKE2s input during group hash.
|
# First 64 bytes of the BLAKE2s input during group hash.
|
||||||
# This is chosen to be some random string that we couldn't have
|
# This is chosen to be some random string that we couldn't have
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
||||||
|
|
||||||
from sapling_utils import i2lebsp, leos2ip, i2leosp
|
from utils import i2lebsp, leos2ip, i2leosp
|
||||||
|
|
||||||
q_j = 52435875175126190479447740508185965837690552500527637822603658699938581184513
|
q_j = 52435875175126190479447740508185965837690552500527637822603658699938581184513
|
||||||
r_j = 6554484396890773809930967563523245729705921265872317281365359162392183254199
|
r_j = 6554484396890773809930967563523245729705921265872317281365359162392183254199
|
||||||
|
|
|
@ -7,7 +7,7 @@ from sapling_generators import PROVING_KEY_BASE, SPENDING_KEY_BASE, group_hash
|
||||||
from sapling_jubjub import Fr
|
from sapling_jubjub import Fr
|
||||||
from sapling_merkle_tree import MERKLE_DEPTH
|
from sapling_merkle_tree import MERKLE_DEPTH
|
||||||
from sapling_notes import note_commit, note_nullifier
|
from sapling_notes import note_commit, note_nullifier
|
||||||
from sapling_utils import leos2bsp, leos2ip
|
from utils import leos2bsp, leos2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -4,7 +4,7 @@ import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
|
|
||||||
from sapling_pedersen import pedersen_hash
|
from sapling_pedersen import pedersen_hash
|
||||||
from sapling_utils import i2lebsp, leos2bsp
|
from utils import i2lebsp, leos2bsp
|
||||||
|
|
||||||
MERKLE_DEPTH = 32
|
MERKLE_DEPTH = 32
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ from sapling_generators import VALUE_COMMITMENT_VALUE_BASE, VALUE_COMMITMENT_RAN
|
||||||
from sapling_jubjub import Fr, JUBJUB_COFACTOR
|
from sapling_jubjub import Fr, JUBJUB_COFACTOR
|
||||||
from sapling_key_components import SpendingKey, diversify_hash
|
from sapling_key_components import SpendingKey, diversify_hash
|
||||||
from sapling_notes import note_commit
|
from sapling_notes import note_commit
|
||||||
from sapling_utils import leos2bsp, leos2ip
|
from utils import leos2bsp, leos2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from sapling_pedersen import (
|
||||||
mixing_pedersen_hash,
|
mixing_pedersen_hash,
|
||||||
windowed_pedersen_commitment,
|
windowed_pedersen_commitment,
|
||||||
)
|
)
|
||||||
from sapling_utils import i2lebsp
|
from utils import i2lebsp
|
||||||
|
|
||||||
def note_commit(rcm, g_d, pk_d, v):
|
def note_commit(rcm, g_d, pk_d, v):
|
||||||
return windowed_pedersen_commitment(rcm, [1] * 6 + i2lebsp(64, v) + g_d + pk_d)
|
return windowed_pedersen_commitment(rcm, [1] * 6 + i2lebsp(64, v) + g_d + pk_d)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from sapling_generators import (
|
||||||
WINDOWED_PEDERSEN_RANDOMNESS_BASE,
|
WINDOWED_PEDERSEN_RANDOMNESS_BASE,
|
||||||
)
|
)
|
||||||
from sapling_jubjub import Fr, Point
|
from sapling_jubjub import Fr, Point
|
||||||
from sapling_utils import cldiv, i2leosp
|
from utils import cldiv, i2leosp
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -7,7 +7,7 @@ from pyblake2 import blake2b
|
||||||
from sapling_generators import SPENDING_KEY_BASE
|
from sapling_generators import SPENDING_KEY_BASE
|
||||||
from sapling_jubjub import Fr, Point, r_j
|
from sapling_jubjub import Fr, Point, r_j
|
||||||
from sapling_key_components import to_scalar
|
from sapling_key_components import to_scalar
|
||||||
from sapling_utils import cldiv, leos2ip
|
from utils import cldiv, leos2ip
|
||||||
from tv_output import render_args, render_tv
|
from tv_output import render_args, render_tv
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from pyblake2 import blake2b
|
||||||
|
|
||||||
from sapling_key_components import to_scalar, prf_expand, diversify_hash, DerivedAkNk, DerivedIvk
|
from sapling_key_components import to_scalar, prf_expand, diversify_hash, DerivedAkNk, DerivedIvk
|
||||||
from sapling_generators import SPENDING_KEY_BASE, PROVING_KEY_BASE
|
from sapling_generators import SPENDING_KEY_BASE, PROVING_KEY_BASE
|
||||||
from sapling_utils import i2leosp, i2lebsp, lebs2osp
|
from utils import i2leosp, i2lebsp, lebs2osp
|
||||||
from ff1 import ff1_aes256_encrypt
|
from ff1 import ff1_aes256_encrypt
|
||||||
from tv_output import render_args, render_tv, option, Some
|
from tv_output import render_args, render_tv, option, Some
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import struct
|
||||||
|
|
||||||
from sapling_generators import find_group_hash, SPENDING_KEY_BASE
|
from sapling_generators import find_group_hash, SPENDING_KEY_BASE
|
||||||
from sapling_jubjub import Fq, Point
|
from sapling_jubjub import Fq, Point
|
||||||
from sapling_utils import leos2ip
|
from utils import leos2ip
|
||||||
from zc_utils import write_compact_size
|
from zc_utils import write_compact_size
|
||||||
|
|
||||||
MAX_MONEY = 21000000 * 100000000
|
MAX_MONEY = 21000000 * 100000000
|
||||||
|
|
Loading…
Reference in New Issue