mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
crypto: WIP pasta port.
This commit is contained in:
3608
Cargo.lock
generated
3608
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
110
Cargo.toml
110
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "darkfi"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
homepage = "https://dark.fi"
|
||||
description = "Anonymous. Uncensored. Sovereign."
|
||||
authors = ["darkfi <dev@dark.fi>"]
|
||||
@@ -11,76 +11,52 @@ edition = "2021"
|
||||
[lib]
|
||||
name = "drk"
|
||||
|
||||
[dependencies]
|
||||
ff = "0.8"
|
||||
group = "0.8"
|
||||
bellman = { version = "0.8", default-features = false, features = ["groth16"] }
|
||||
bls12_381 = "0.3.1"
|
||||
jubjub = "0.5.1"
|
||||
zcash_primitives = "0.5.0"
|
||||
zcash_proofs = "0.5.0"
|
||||
rand = "0.7.3"
|
||||
rand_core = "0.5.1"
|
||||
sha2 = "0.9.8"
|
||||
ripemd160 = "0.9.1"
|
||||
blake2s_simd = "0.5"
|
||||
blake2b_simd = "0.5.11"
|
||||
crypto_api_chachapoly = "0.4"
|
||||
bitvec = "0.18"
|
||||
bimap = "0.5.2"
|
||||
hex = "0.4.2"
|
||||
bs58 = "0.4.0"
|
||||
prettytable-rs = "0.8"
|
||||
num_cpus = "1.13.0"
|
||||
num-bigint = {version = "0.3.2", features = ["rand", "serde"]}
|
||||
[dependencies.halo2]
|
||||
version = "=0.1.0-beta.1"
|
||||
features = ["dev-graph", "gadget-traces", "sanity-checks"]
|
||||
|
||||
[dependencies.halo2_gadgets]
|
||||
git = "https://github.com/parazyd/halo2_gadgets.git"
|
||||
rev = "8238cb3471b798c76dd53b278524fc80685c7d4f"
|
||||
features = ["dev-graph", "test-dependencies"]
|
||||
|
||||
[dependencies.rocksdb]
|
||||
git = "https://github.com/parazyd/rust-rocksdb"
|
||||
rev = "bd966750ec861d687913d59a9939a1408ac53131"
|
||||
default-features = false
|
||||
features = ["lz4"]
|
||||
|
||||
[dependencies]
|
||||
pasta_curves = "0.2.1"
|
||||
rand = "0.8.4"
|
||||
num-bigint = "0.4.2"
|
||||
blake2b_simd = "0.5.11"
|
||||
blake2s_simd = "0.5.11"
|
||||
group = "0.11.0"
|
||||
crypto_api_chachapoly = "0.5.0"
|
||||
|
||||
hex = "0.4.3"
|
||||
bs58 = "0.4.0"
|
||||
toml = "0.5.8"
|
||||
url = "2.2.2"
|
||||
serde_json = "1.0.68"
|
||||
serde = {version = "1.0.130", features = ["derive"]}
|
||||
|
||||
smol = "1.2.5"
|
||||
futures = "0.3.17"
|
||||
async-channel = "1.6.1"
|
||||
async-trait = "0.1.51"
|
||||
async-executor = "1.4.1"
|
||||
async-std = "1.10.0"
|
||||
async-native-tls = "0.3.3"
|
||||
async-trait = "0.1.51"
|
||||
async-channel = "1.6.1"
|
||||
native-tls = "0.2.8"
|
||||
easy-parallel = "3.1.0"
|
||||
async-native-tls = "0.3.3"
|
||||
async-executor = "1.4.1"
|
||||
futures = "0.3.17"
|
||||
smol = "1.2.5"
|
||||
|
||||
log = "0.4.14"
|
||||
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
tungstenite = "0.15.0"
|
||||
async-tungstenite = "0.15.0"
|
||||
|
||||
simple_logger = "1.13.0"
|
||||
log = "0.4.14"
|
||||
clap = "2.33.3"
|
||||
toml = "0.5.8"
|
||||
dirs = "4.0.0"
|
||||
url = "2.2.2"
|
||||
serde = {version = "1.0.130", features = ["derive"]}
|
||||
serde_json = "1.0.68"
|
||||
bytes = "1.0.1"
|
||||
signal-hook = "0.3.10"
|
||||
signal-hook-async-std = "0.2.1"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
rocksdb = {version = "0.16.0", default-features = false, features = ["lz4"]}
|
||||
zeromq = {version = "0.2.2", default-features = false, features = ["async-std-runtime", "all-transport"]}
|
||||
rusqlite = {version = "0.26.0", features = ["bundled-sqlcipher"]}
|
||||
|
||||
## Cashier Solana Dependencies
|
||||
solana-sdk = {version = "1.8.1", optional = true}
|
||||
solana-client = {version = "1.8.1", optional = true}
|
||||
spl-token = {version = "3.2.0", features = ["no-entrypoint"], optional = true}
|
||||
spl-associated-token-account = {version = "1.0.3", features = ["no-entrypoint"], optional = true}
|
||||
|
||||
## Cashier Bitcoin Dependencies
|
||||
anyhow = "1.0.44"
|
||||
bdk = {version = "0.12.0", optional = true}
|
||||
bitcoin = {version = "0.27.0", optional = true }
|
||||
secp256k1 = {version = "0.20.3", default-features = false, features = ["rand-std"], optional = true}
|
||||
|
||||
## Cashier Ethereum Dependencies
|
||||
hash-db = {version = "0.15.2", optional = true}
|
||||
keccak-hasher = {version = "0.15.3", optional = true}
|
||||
|
||||
[features]
|
||||
btc = ["bdk", "bitcoin", "secp256k1"]
|
||||
sol = ["solana-sdk", "solana-client", "spl-token", "spl-associated-token-account"]
|
||||
eth = ["keccak-hasher", "hash-db"]
|
||||
rusqlite = {version = "0.26.1", features = ["bundled-sqlcipher"]}
|
||||
zeromq = {version = "0.3.0", default-features = false, features = ["async-std-runtime", "all-transport"]}
|
||||
|
||||
4
Makefile
4
Makefile
@@ -16,7 +16,9 @@ BINDEPS = \
|
||||
$(shell find token -type f) \
|
||||
$(shell find sql -type f)
|
||||
|
||||
all: $(BINS)
|
||||
#all: $(BINS)
|
||||
all:
|
||||
cargo build --release --all-features --lib
|
||||
|
||||
$(BINS): $(BINDEPS)
|
||||
$(CARGO) build --release --all-features --bin $@
|
||||
|
||||
@@ -1,181 +1,425 @@
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_mut)]
|
||||
use crate::crypto::merkle_node::SAPLING_COMMITMENT_TREE_DEPTH;
|
||||
use bellman::{
|
||||
gadgets::{
|
||||
blake2s, boolean,
|
||||
boolean::{AllocatedBit, Boolean},
|
||||
multipack, num, Assignment,
|
||||
},
|
||||
groth16, Circuit, ConstraintSystem, SynthesisError,
|
||||
};
|
||||
use bls12_381::Bls12;
|
||||
use ff::{Field, PrimeField};
|
||||
use group::Curve;
|
||||
use zcash_proofs::circuit::{ecc, pedersen_hash};
|
||||
use pasta_curves as pasta;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MintContract {
|
||||
pub value: Option<u64>,
|
||||
pub token_id: Option<jubjub::Fr>,
|
||||
pub randomness_value: Option<jubjub::Fr>,
|
||||
pub randomness_token: Option<jubjub::Fr>,
|
||||
pub serial: Option<jubjub::Fr>,
|
||||
pub randomness_coin: Option<jubjub::Fr>,
|
||||
pub public: Option<jubjub::SubgroupPoint>,
|
||||
use halo2::{
|
||||
circuit::{Layouter, SimpleFloorPlanner},
|
||||
plonk,
|
||||
plonk::{Advice, Circuit, Column, ConstraintSystem, Instance as InstanceColumn, Selector},
|
||||
poly::Rotation,
|
||||
};
|
||||
use halo2_gadgets::{
|
||||
ecc::{
|
||||
chip::{EccChip, EccConfig},
|
||||
FixedPoint,
|
||||
},
|
||||
poseidon::{
|
||||
Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
|
||||
StateWord, Word,
|
||||
},
|
||||
primitives::poseidon::{ConstantLength, P128Pow5T3},
|
||||
sinsemilla::{
|
||||
chip::{SinsemillaChip, SinsemillaConfig},
|
||||
merkle::chip::{MerkleChip, MerkleConfig},
|
||||
},
|
||||
utilities::{
|
||||
copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::crypto::constants::{
|
||||
sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
|
||||
OrchardFixedBases,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MintConfig {
|
||||
primary: Column<InstanceColumn>,
|
||||
q_add: Selector,
|
||||
advices: [Column<Advice>; 10],
|
||||
ecc_config: EccConfig,
|
||||
merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
merkle_config_2: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
sinsemilla_config_1:
|
||||
SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
sinsemilla_config_2:
|
||||
SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
poseidon_config: PoseidonConfig<pasta::Fp>,
|
||||
}
|
||||
|
||||
impl Circuit<bls12_381::Scalar> for MintContract {
|
||||
fn synthesize<CS: ConstraintSystem<bls12_381::Scalar>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<(), SynthesisError> {
|
||||
// Line 20: u64_as_binary_le value param:value
|
||||
let value = boolean::u64_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 20: u64_as_binary_le value param:value"),
|
||||
impl MintConfig {
|
||||
fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
|
||||
EccChip::construct(self.ecc_config.clone())
|
||||
}
|
||||
|
||||
fn poseidon_chip(&self) -> PoseidonChip<pasta::Fp> {
|
||||
PoseidonChip::construct(self.poseidon_config.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// The public input array offsets
|
||||
const MINT_COIN_OFFSET: usize = 0;
|
||||
const MINT_VALCOMX_OFFSET: usize = 1;
|
||||
const MINT_VALCOMY_OFFSET: usize = 2;
|
||||
const MINT_ASSCOMX_OFFSET: usize = 3;
|
||||
const MINT_ASSCOMY_OFFSET: usize = 4;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct MintContract {
|
||||
pub pub_x: Option<pasta::Fp>, // x coordinate for pubkey
|
||||
pub pub_y: Option<pasta::Fp>, // y coordinate for pubkey
|
||||
pub value: Option<pasta::Fp>, // The value of this coin
|
||||
pub asset: Option<pasta::Fp>, // The asset ID
|
||||
pub serial: Option<pasta::Fp>, // Unique serial number corresponding to this coin
|
||||
pub coin_blind: Option<pasta::Fp>, // Random blinding factor for coin
|
||||
pub value_blind: Option<pasta::Fq>, // Random blinding factor for value commitment
|
||||
pub asset_blind: Option<pasta::Fq>, // Random blinding factor for the asset ID
|
||||
}
|
||||
|
||||
impl UtilitiesInstructions<pasta::Fp> for MintContract {
|
||||
type Var = CellValue<pasta::Fp>;
|
||||
}
|
||||
|
||||
impl Circuit<pasta::Fp> for MintContract {
|
||||
type Config = MintConfig;
|
||||
type FloorPlanner = SimpleFloorPlanner;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<pasta::Fp>) -> Self::Config {
|
||||
// Advice columns used in the circuit
|
||||
let advices = [
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
];
|
||||
|
||||
// Addition of two field elements
|
||||
/*
|
||||
let q_add = meta.selector();
|
||||
meta.create_gate("poseidon_hash(a, b) + c", |meta| {
|
||||
let q_add = meta.query_selector(q_add);
|
||||
let sum = meta.query_advice(advices[6], Rotation::cur());
|
||||
let hash = meta.query_advice(advices[7], Rotation::cur());
|
||||
let c = meta.query_advice(advices[8], Rotation::cur());
|
||||
|
||||
vec![q_add * (hash + c - sum)]
|
||||
});
|
||||
*/
|
||||
let q_add = meta.selector();
|
||||
meta.create_gate("a+b+c", |meta| {
|
||||
let q_add = meta.query_selector(q_add);
|
||||
let sum = meta.query_advice(advices[5], Rotation::cur());
|
||||
let a = meta.query_advice(advices[6], Rotation::cur());
|
||||
let b = meta.query_advice(advices[7], Rotation::cur());
|
||||
let c = meta.query_advice(advices[8], Rotation::cur());
|
||||
|
||||
vec![q_add * (a + b + c - sum)]
|
||||
});
|
||||
|
||||
// Fixed columns for the Sinsemilla generator lookup table
|
||||
let table_idx = meta.lookup_table_column();
|
||||
let lookup = (
|
||||
table_idx,
|
||||
meta.lookup_table_column(),
|
||||
meta.lookup_table_column(),
|
||||
);
|
||||
|
||||
// Instance column used for public inputs
|
||||
let primary = meta.instance_column();
|
||||
meta.enable_equality(primary.into());
|
||||
|
||||
// Permutation over all advice columns
|
||||
for advice in advices.iter() {
|
||||
meta.enable_equality((*advice).into());
|
||||
}
|
||||
|
||||
// Poseidon requires four advice columns, while ECC incomplete addition
|
||||
// requires six. We can reduce the proof size by sharing fixed columns
|
||||
// between the ECC and Poseidon chips.
|
||||
// TODO: For multiple invocations they could/should be configured in
|
||||
// parallel rather than sharing perhaps?
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
|
||||
let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
|
||||
|
||||
// Also use the first Lagrange coefficient column for loading global constants.
|
||||
meta.enable_constant(lagrange_coeffs[0]);
|
||||
|
||||
// Use one of the right-most advice columns for all of our range checks.
|
||||
let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
|
||||
|
||||
// Configuration for curve point operations.
|
||||
// This uses 10 advice columns and spans the whole circuit.
|
||||
let ecc_config = EccChip::<OrchardFixedBases>::configure(
|
||||
meta,
|
||||
advices,
|
||||
lagrange_coeffs,
|
||||
range_check.clone(),
|
||||
);
|
||||
|
||||
// Configuration for the Poseidon hash
|
||||
let poseidon_config = PoseidonChip::configure(
|
||||
meta,
|
||||
P128Pow5T3,
|
||||
advices[6..9].try_into().unwrap(),
|
||||
advices[5],
|
||||
rc_a,
|
||||
rc_b,
|
||||
);
|
||||
|
||||
// Configuration for a Sinsemilla hash instantiation and a
|
||||
// Merkle hash instantiation using this Sinsemilla instance.
|
||||
// Since the Sinsemilla config uses only 5 advice columns,
|
||||
// we can fit two instances side-by-side.
|
||||
let (sinsemilla_config_1, merkle_config_1) = {
|
||||
let sinsemilla_config_1 = SinsemillaChip::configure(
|
||||
meta,
|
||||
advices[..5].try_into().unwrap(),
|
||||
advices[6],
|
||||
lagrange_coeffs[0],
|
||||
lookup,
|
||||
range_check.clone(),
|
||||
);
|
||||
let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
|
||||
(sinsemilla_config_1, merkle_config_1)
|
||||
};
|
||||
|
||||
// Configuration for a Sinsemilla hash instantiation and a
|
||||
// Merkle hash instantiation using this Sinsemilla instance.
|
||||
// Since the Sinsemilla config uses only 5 advice columns,
|
||||
// we can fit two instances side-by-side.
|
||||
let (sinsemilla_config_2, merkle_config_2) = {
|
||||
let sinsemilla_config_2 = SinsemillaChip::configure(
|
||||
meta,
|
||||
advices[5..].try_into().unwrap(),
|
||||
advices[7],
|
||||
lagrange_coeffs[1],
|
||||
lookup,
|
||||
range_check,
|
||||
);
|
||||
let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
|
||||
|
||||
(sinsemilla_config_2, merkle_config_2)
|
||||
};
|
||||
|
||||
MintConfig {
|
||||
primary,
|
||||
q_add,
|
||||
advices,
|
||||
ecc_config,
|
||||
merkle_config_1,
|
||||
merkle_config_2,
|
||||
sinsemilla_config_1,
|
||||
sinsemilla_config_2,
|
||||
poseidon_config,
|
||||
}
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<pasta::Fp>,
|
||||
) -> Result<(), plonk::Error> {
|
||||
let ecc_chip = config.ecc_chip();
|
||||
|
||||
let pub_x = self.load_private(
|
||||
layouter.namespace(|| "load pubkey x"),
|
||||
config.advices[0],
|
||||
self.pub_x,
|
||||
)?;
|
||||
|
||||
let pub_y = self.load_private(
|
||||
layouter.namespace(|| "load pubkey y"),
|
||||
config.advices[0],
|
||||
self.pub_y,
|
||||
)?;
|
||||
|
||||
let value = self.load_private(
|
||||
layouter.namespace(|| "load value"),
|
||||
config.advices[0],
|
||||
self.value,
|
||||
)?;
|
||||
|
||||
// Line 21: fr_as_binary_le token_id param:token_id
|
||||
let token_id = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 21: fr_as_binary_le token_id param:token_id"),
|
||||
self.token_id,
|
||||
let asset = self.load_private(
|
||||
layouter.namespace(|| "load asset"),
|
||||
config.advices[0],
|
||||
self.asset,
|
||||
)?;
|
||||
|
||||
// Line 22: fr_as_binary_le randomness_value param:randomness_value
|
||||
let randomness_value = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 22: fr_as_binary_le randomness_value param:randomness_value"),
|
||||
self.randomness_value,
|
||||
)?;
|
||||
|
||||
// Line 23: fr_as_binary_le randomness_token param:randomness_token
|
||||
let randomness_token = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 23: fr_as_binary_le randomness_token param:randomness_token"),
|
||||
self.randomness_token,
|
||||
)?;
|
||||
|
||||
// Line 24: fr_as_binary_le serial param:serial
|
||||
let serial = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 24: fr_as_binary_le serial param:serial"),
|
||||
let serial = self.load_private(
|
||||
layouter.namespace(|| "load serial"),
|
||||
config.advices[0],
|
||||
self.serial,
|
||||
)?;
|
||||
|
||||
// Line 25: fr_as_binary_le randomness_coin param:randomness_coin
|
||||
let randomness_coin = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 25: fr_as_binary_le randomness_coin param:randomness_coin"),
|
||||
self.randomness_coin,
|
||||
let coin_blind = self.load_private(
|
||||
layouter.namespace(|| "load coin_blind"),
|
||||
config.advices[0],
|
||||
self.coin_blind,
|
||||
)?;
|
||||
|
||||
// Line 27: witness public param:public
|
||||
let public = ecc::EdwardsPoint::witness(
|
||||
cs.namespace(|| "Line 27: witness public param:public"),
|
||||
self.public.map(jubjub::ExtendedPoint::from),
|
||||
)?;
|
||||
// =========
|
||||
// Coin hash
|
||||
// =========
|
||||
let messages = [[pub_x, pub_y], [value, asset], [serial, coin_blind]];
|
||||
let mut hashes = vec![];
|
||||
|
||||
// Line 28: assert_not_small_order public
|
||||
public.assert_not_small_order(cs.namespace(|| "Line 28: assert_not_small_order public"))?;
|
||||
for message in messages.iter() {
|
||||
let hash = {
|
||||
let poseidon_message = layouter.assign_region(
|
||||
|| "load message",
|
||||
|mut region| {
|
||||
let mut message_word = |i: usize| {
|
||||
let value = message[i].value();
|
||||
let var = region.assign_advice(
|
||||
|| format!("load message_{}", i),
|
||||
config.poseidon_config.state()[i],
|
||||
0,
|
||||
|| value.ok_or(plonk::Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(var, message[i].cell())?;
|
||||
Ok(Word::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
|
||||
var, value,
|
||||
)))
|
||||
};
|
||||
Ok([message_word(0)?, message_word(1)?])
|
||||
},
|
||||
)?;
|
||||
|
||||
// Line 33: ec_mul_const vcv value G_VCV
|
||||
let vcv = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 33: ec_mul_const vcv value G_VCV"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR,
|
||||
&value,
|
||||
)?;
|
||||
let poseidon_hasher = PoseidonHash::init(
|
||||
config.poseidon_chip(),
|
||||
layouter.namespace(|| "Poseidon init"),
|
||||
ConstantLength::<2>,
|
||||
)?;
|
||||
|
||||
// Line 34: ec_mul_const rcv randomness_value G_VCR
|
||||
let rcv = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 34: ec_mul_const rcv randomness_value G_VCR"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
|
||||
&randomness_value,
|
||||
)?;
|
||||
let poseidon_output = poseidon_hasher.hash(
|
||||
layouter.namespace(|| "Poseidon hash (a, b)"),
|
||||
poseidon_message,
|
||||
)?;
|
||||
|
||||
// Line 35: ec_add cv vcv rcv
|
||||
let cv = vcv.add(cs.namespace(|| "Line 35: ec_add cv vcv rcv"), &rcv)?;
|
||||
let poseidon_output: CellValue<pasta::Fp> = poseidon_output.inner().into();
|
||||
poseidon_output
|
||||
};
|
||||
|
||||
// Line 37: emit_ec cv
|
||||
cv.inputize(cs.namespace(|| "Line 37: emit_ec cv"))?;
|
||||
|
||||
// Line 42: ec_mul_const vca token_id G_VCV
|
||||
let vca = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 42: ec_mul_const vca token_id G_VCV"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR,
|
||||
&token_id,
|
||||
)?;
|
||||
|
||||
// Line 43: ec_mul_const rca randomness_token G_VCR
|
||||
let rca = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 43: ec_mul_const rca randomness_token G_VCR"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
|
||||
&randomness_token,
|
||||
)?;
|
||||
|
||||
// Line 44: ec_add ca vca rca
|
||||
let ca = vca.add(cs.namespace(|| "Line 44: ec_add ca vca rca"), &rca)?;
|
||||
|
||||
// Line 46: emit_ec ca
|
||||
ca.inputize(cs.namespace(|| "Line 46: emit_ec ca"))?;
|
||||
|
||||
// Line 53: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 56: ec_repr repr_public public
|
||||
let repr_public = public.repr(cs.namespace(|| "Line 56: ec_repr repr_public public"))?;
|
||||
|
||||
// Line 57: binary_extend preimage repr_public
|
||||
preimage.extend(repr_public);
|
||||
|
||||
// Line 60: binary_extend preimage value
|
||||
preimage.extend(value);
|
||||
|
||||
// Line 99: binary_extend preimage token_id
|
||||
preimage.extend(token_id);
|
||||
|
||||
// add 4 zero bits
|
||||
for _ in 0..4 {
|
||||
// Line 71: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 72: binary_push preimage zero_bit
|
||||
preimage.push(zero_bit);
|
||||
hashes.push(hash);
|
||||
}
|
||||
|
||||
// Line 67: binary_extend preimage serial
|
||||
preimage.extend(serial);
|
||||
let coin = layouter.assign_region(
|
||||
|| " `coin` = hash(a,b) + hash(c, d) + hash(e, f)",
|
||||
|mut region| {
|
||||
config.q_add.enable(&mut region, 0)?;
|
||||
|
||||
// add 4 zero bits
|
||||
for _ in 0..4 {
|
||||
// Line 71: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
copy(&mut region, || "copy ab", config.advices[6], 0, &hashes[0])?;
|
||||
copy(&mut region, || "copy cd", config.advices[7], 0, &hashes[1])?;
|
||||
copy(&mut region, || "copy ef", config.advices[8], 0, &hashes[2])?;
|
||||
|
||||
// Line 72: binary_push preimage zero_bit
|
||||
preimage.push(zero_bit);
|
||||
}
|
||||
let scalar_val = hashes[0]
|
||||
.value()
|
||||
.zip(hashes[1].value())
|
||||
.zip(hashes[2].value())
|
||||
.map(|(abcd, ef)| abcd.0 + abcd.1 + ef);
|
||||
|
||||
// Line 83: binary_extend preimage randomness_coin
|
||||
preimage.extend(randomness_coin);
|
||||
|
||||
// add 4 zero bits
|
||||
for _ in 0..4 {
|
||||
// Line 71: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 72: binary_push preimage zero_bit
|
||||
preimage.push(zero_bit);
|
||||
}
|
||||
|
||||
// Line 120: static_assert_binary_size preimage 1088
|
||||
assert_eq!(preimage.len(), 1088);
|
||||
|
||||
// Line 121: blake2s coin preimage CRH_IVK
|
||||
let mut coin = blake2s::blake2s(
|
||||
cs.namespace(|| "Line 121: blake2s coin preimage CRH_IVK"),
|
||||
&preimage,
|
||||
zcash_primitives::constants::CRH_IVK_PERSONALIZATION,
|
||||
let cell = region.assign_advice(
|
||||
|| "hash(a,b)+hash(c,d)+hash(e,f)",
|
||||
config.advices[5],
|
||||
0,
|
||||
|| scalar_val.ok_or(plonk::Error::SynthesisError),
|
||||
)?;
|
||||
Ok(CellValue::new(cell, scalar_val))
|
||||
},
|
||||
)?;
|
||||
|
||||
// Line 122: emit_binary coin
|
||||
multipack::pack_into_inputs(cs.namespace(|| "Line 122: emit_binary coin"), &coin)?;
|
||||
// Constrain the coin C
|
||||
layouter.constrain_instance(coin.cell(), config.primary, MINT_COIN_OFFSET)?;
|
||||
|
||||
// ================
|
||||
// Value commitment
|
||||
// ================
|
||||
|
||||
// This constant one is used for short multiplication
|
||||
let one = self.load_private(
|
||||
layouter.namespace(|| "load constant one"),
|
||||
config.advices[0],
|
||||
Some(pasta::Fp::one()),
|
||||
)?;
|
||||
|
||||
// v * G_1
|
||||
let (commitment, _) = {
|
||||
let value_commit_v = OrchardFixedBases::ValueCommitV;
|
||||
let value_commit_v = FixedPoint::from_inner(ecc_chip.clone(), value_commit_v);
|
||||
value_commit_v.mul_short(layouter.namespace(|| "[value] ValueCommitV"), (value, one))?
|
||||
};
|
||||
|
||||
// r_V * G_2
|
||||
let (blind, _rcv) = {
|
||||
let rcv = self.value_blind;
|
||||
let value_commit_r = OrchardFixedBases::ValueCommitR;
|
||||
let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), value_commit_r);
|
||||
value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
|
||||
};
|
||||
|
||||
// Constrain the value commitment coordinates
|
||||
let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
|
||||
layouter.constrain_instance(
|
||||
value_commit.inner().x().cell(),
|
||||
config.primary,
|
||||
MINT_VALCOMX_OFFSET,
|
||||
)?;
|
||||
layouter.constrain_instance(
|
||||
value_commit.inner().y().cell(),
|
||||
config.primary,
|
||||
MINT_VALCOMY_OFFSET,
|
||||
)?;
|
||||
|
||||
// ================
|
||||
// Asset commitment
|
||||
// ================
|
||||
// a * G_1
|
||||
let (commitment, _) = {
|
||||
let asset_commit_v = OrchardFixedBases::ValueCommitV;
|
||||
let asset_commit_v = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_v);
|
||||
asset_commit_v.mul_short(layouter.namespace(|| "[asset] ValueCommitV"), (asset, one))?
|
||||
};
|
||||
|
||||
// r_A * G_2
|
||||
let (blind, _rca) = {
|
||||
let rca = self.asset_blind;
|
||||
let asset_commit_r = OrchardFixedBases::ValueCommitR;
|
||||
let asset_commit_r = FixedPoint::from_inner(ecc_chip, asset_commit_r);
|
||||
asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
|
||||
};
|
||||
|
||||
// Constrain the asset commitment coordinates
|
||||
let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
|
||||
layouter.constrain_instance(
|
||||
asset_commit.inner().x().cell(),
|
||||
config.primary,
|
||||
MINT_ASSCOMX_OFFSET,
|
||||
)?;
|
||||
layouter.constrain_instance(
|
||||
asset_commit.inner().y().cell(),
|
||||
config.primary,
|
||||
MINT_ASSCOMY_OFFSET,
|
||||
)?;
|
||||
|
||||
// At this point we've enforced all of our public inputs.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,517 +1,460 @@
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_mut)]
|
||||
use bellman::{
|
||||
gadgets::{
|
||||
blake2s, boolean,
|
||||
boolean::{AllocatedBit, Boolean},
|
||||
multipack, num, Assignment,
|
||||
use pasta_curves as pasta;
|
||||
|
||||
use halo2::{
|
||||
circuit::{Layouter, SimpleFloorPlanner},
|
||||
plonk::{
|
||||
Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
|
||||
},
|
||||
poly::Rotation,
|
||||
};
|
||||
use halo2_gadgets::{
|
||||
ecc::{
|
||||
chip::{EccChip, EccConfig},
|
||||
FixedPoint,
|
||||
},
|
||||
poseidon::{
|
||||
Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
|
||||
StateWord, Word,
|
||||
},
|
||||
primitives::poseidon::{ConstantLength, P128Pow5T3},
|
||||
sinsemilla::{
|
||||
chip::{SinsemillaChip, SinsemillaConfig},
|
||||
merkle::chip::{MerkleChip, MerkleConfig},
|
||||
merkle::MerklePath,
|
||||
},
|
||||
utilities::{
|
||||
lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
|
||||
},
|
||||
groth16, Circuit, ConstraintSystem, SynthesisError,
|
||||
};
|
||||
use bls12_381::Bls12;
|
||||
use ff::{Field, PrimeField};
|
||||
use group::Curve;
|
||||
use zcash_proofs::circuit::{ecc, pedersen_hash};
|
||||
|
||||
use crate::crypto::merkle_node::SAPLING_COMMITMENT_TREE_DEPTH;
|
||||
use crate::crypto::constants::{
|
||||
sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
|
||||
OrchardFixedBases,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SpendContract {
|
||||
pub value: Option<u64>,
|
||||
pub token_id: Option<jubjub::Fr>,
|
||||
pub randomness_value: Option<jubjub::Fr>,
|
||||
pub randomness_token: Option<jubjub::Fr>,
|
||||
pub serial: Option<jubjub::Fr>,
|
||||
pub randomness_coin: Option<jubjub::Fr>,
|
||||
pub secret: Option<jubjub::Fr>,
|
||||
pub branch: [Option<bls12_381::Scalar>; SAPLING_COMMITMENT_TREE_DEPTH],
|
||||
pub is_right: [Option<bool>; SAPLING_COMMITMENT_TREE_DEPTH],
|
||||
pub signature_secret: Option<jubjub::Fr>,
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BurnConfig {
|
||||
primary: Column<InstanceColumn>,
|
||||
q_add: Selector,
|
||||
advices: [Column<Advice>; 10],
|
||||
ecc_config: EccConfig,
|
||||
merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
merkle_config_2: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
sinsemilla_config_1:
|
||||
SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
sinsemilla_config_2:
|
||||
SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
poseidon_config: PoseidonConfig<pasta::Fp>,
|
||||
}
|
||||
impl Circuit<bls12_381::Scalar> for SpendContract {
|
||||
fn synthesize<CS: ConstraintSystem<bls12_381::Scalar>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<(), SynthesisError> {
|
||||
// Line 40: u64_as_binary_le value param:value
|
||||
let value = boolean::u64_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 40: u64_as_binary_le value param:value"),
|
||||
self.value,
|
||||
|
||||
impl BurnConfig {
|
||||
fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
|
||||
EccChip::construct(self.ecc_config.clone())
|
||||
}
|
||||
|
||||
/*
|
||||
fn sinsemilla_chip_1(
|
||||
&self,
|
||||
) -> SinsemillaChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
|
||||
SinsemillaChip::construct(self.sinsemilla_config_1.clone())
|
||||
}
|
||||
|
||||
fn sinsemilla_chip_2(
|
||||
&self,
|
||||
) -> SinsemillaChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
|
||||
SinsemillaChip::construct(self.sinsemilla_config_2.clone())
|
||||
}
|
||||
*/
|
||||
|
||||
fn merkle_chip_1(
|
||||
&self,
|
||||
) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
|
||||
MerkleChip::construct(self.merkle_config_1.clone())
|
||||
}
|
||||
|
||||
fn merkle_chip_2(
|
||||
&self,
|
||||
) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
|
||||
MerkleChip::construct(self.merkle_config_2.clone())
|
||||
}
|
||||
|
||||
fn poseidon_chip(&self) -> PoseidonChip<pasta::Fp> {
|
||||
PoseidonChip::construct(self.poseidon_config.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// The public input array offsets
|
||||
const BURN_NULLIFIER_OFFSET: usize = 0;
|
||||
const BURN_VALCOMX_OFFSET: usize = 1;
|
||||
const BURN_VALCOMY_OFFSET: usize = 2;
|
||||
const BURN_ASSCOMX_OFFSET: usize = 3;
|
||||
const BURN_ASSCOMY_OFFSET: usize = 4;
|
||||
const BURN_MERKLEROOT_OFFSET: usize = 5;
|
||||
const BURN_SIGKEYX_OFFSET: usize = 6;
|
||||
const BURN_SIGKEYY_OFFSET: usize = 7;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct BurnContract {
|
||||
secret_key: Option<pasta::Fp>,
|
||||
serial: Option<pasta::Fp>,
|
||||
value: Option<pasta::Fp>,
|
||||
asset: Option<pasta::Fp>,
|
||||
coin_blind: Option<pasta::Fp>,
|
||||
value_blind: Option<pasta::Fq>,
|
||||
asset_blind: Option<pasta::Fq>,
|
||||
leaf: Option<pasta::Fp>,
|
||||
leaf_pos: Option<u32>,
|
||||
merkle_path: Option<[pasta::Fp; 32]>,
|
||||
sig_secret: Option<pasta::Fq>,
|
||||
}
|
||||
|
||||
impl UtilitiesInstructions<pasta::Fp> for BurnContract {
|
||||
type Var = CellValue<pasta::Fp>;
|
||||
}
|
||||
|
||||
impl Circuit<pasta::Fp> for BurnContract {
|
||||
type Config = BurnConfig;
|
||||
type FloorPlanner = SimpleFloorPlanner;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<pasta::Fp>) -> Self::Config {
|
||||
// Advice columns used in the circuit
|
||||
let advices = [
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
];
|
||||
|
||||
// Addition of three field elements
|
||||
let q_add = meta.selector();
|
||||
meta.create_gate("a+b+c", |meta| {
|
||||
let q_add = meta.query_selector(q_add);
|
||||
let sum = meta.query_advice(advices[5], Rotation::cur());
|
||||
let a = meta.query_advice(advices[6], Rotation::cur());
|
||||
let b = meta.query_advice(advices[7], Rotation::cur());
|
||||
let c = meta.query_advice(advices[8], Rotation::cur());
|
||||
|
||||
vec![q_add * (a + b + c - sum)]
|
||||
});
|
||||
|
||||
// Fixed columns for the Sinsemilla generator lookup table
|
||||
let table_idx = meta.lookup_table_column();
|
||||
let lookup = (
|
||||
table_idx,
|
||||
meta.lookup_table_column(),
|
||||
meta.lookup_table_column(),
|
||||
);
|
||||
|
||||
// Instance column used for public inputs
|
||||
let primary = meta.instance_column();
|
||||
meta.enable_equality(primary.into());
|
||||
|
||||
// Permutation over all advice columns
|
||||
for advice in advices.iter() {
|
||||
meta.enable_equality((*advice).into());
|
||||
}
|
||||
|
||||
// Poseidon requires four advice columns, while ECC incomplete addition
|
||||
// requires six. We can reduce the proof size by sharing fixed columns
|
||||
// between the ECC and Poseidon chips.
|
||||
// TODO: For multiple invocations they could/should be configured in
|
||||
// parallel rather than sharing perhaps?
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
|
||||
let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
|
||||
|
||||
// Also use the first Lagrange coefficient column for loading global constants.
|
||||
meta.enable_constant(lagrange_coeffs[0]);
|
||||
|
||||
// Use one of the right-most advice columns for all of our range checks.
|
||||
let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
|
||||
|
||||
// Configuration for curve point operations.
|
||||
// This uses 10 advice columns and spans the whole circuit.
|
||||
let ecc_config = EccChip::<OrchardFixedBases>::configure(
|
||||
meta,
|
||||
advices,
|
||||
lagrange_coeffs,
|
||||
range_check.clone(),
|
||||
);
|
||||
|
||||
// Configuration for the Poseidon hash
|
||||
let poseidon_config = PoseidonChip::configure(
|
||||
meta,
|
||||
P128Pow5T3,
|
||||
advices[6..9].try_into().unwrap(),
|
||||
advices[5],
|
||||
rc_a,
|
||||
rc_b,
|
||||
);
|
||||
|
||||
// Configuration for a Sinsemilla hash instantiation and a
|
||||
// Merkle hash instantiation using this Sinsemilla instance.
|
||||
// Since the Sinsemilla config uses only 5 advice columns,
|
||||
// we can fit two instances side-by-side.
|
||||
let (sinsemilla_config_1, merkle_config_1) = {
|
||||
let sinsemilla_config_1 = SinsemillaChip::configure(
|
||||
meta,
|
||||
advices[..5].try_into().unwrap(),
|
||||
advices[6],
|
||||
lagrange_coeffs[0],
|
||||
lookup,
|
||||
range_check.clone(),
|
||||
);
|
||||
let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
|
||||
(sinsemilla_config_1, merkle_config_1)
|
||||
};
|
||||
|
||||
// Configuration for a Sinsemilla hash instantiation and a
|
||||
// Merkle hash instantiation using this Sinsemilla instance.
|
||||
// Since the Sinsemilla config uses only 5 advice columns,
|
||||
// we can fit two instances side-by-side.
|
||||
let (sinsemilla_config_2, merkle_config_2) = {
|
||||
let sinsemilla_config_2 = SinsemillaChip::configure(
|
||||
meta,
|
||||
advices[5..].try_into().unwrap(),
|
||||
advices[7],
|
||||
lagrange_coeffs[1],
|
||||
lookup,
|
||||
range_check,
|
||||
);
|
||||
let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
|
||||
|
||||
(sinsemilla_config_2, merkle_config_2)
|
||||
};
|
||||
|
||||
BurnConfig {
|
||||
primary,
|
||||
q_add,
|
||||
advices,
|
||||
ecc_config,
|
||||
merkle_config_1,
|
||||
merkle_config_2,
|
||||
sinsemilla_config_1,
|
||||
sinsemilla_config_2,
|
||||
poseidon_config,
|
||||
}
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<pasta::Fp>,
|
||||
) -> Result<(), Error> {
|
||||
// Load the Sinsemilla generator lookup table used by the whole circuit.
|
||||
SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
|
||||
|
||||
// Construct the ECC chip.
|
||||
let ecc_chip = config.ecc_chip();
|
||||
|
||||
// Construct the merkle chips
|
||||
let merkle_chip_1 = config.merkle_chip_1();
|
||||
let merkle_chip_2 = config.merkle_chip_2();
|
||||
|
||||
// =========
|
||||
// Nullifier
|
||||
// =========
|
||||
let hashed_secret_key = self.load_private(
|
||||
layouter.namespace(|| "load sinsemilla(secret key)"),
|
||||
config.advices[0],
|
||||
self.secret_key,
|
||||
)?;
|
||||
|
||||
// Line 41: u64_as_binary_le token_id param:token_id
|
||||
let token_id = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 41: u64_as_binary_le value param:value"),
|
||||
self.token_id,
|
||||
)?;
|
||||
|
||||
// Line 41: fr_as_binary_le randomness_value param:randomness_value
|
||||
let randomness_value = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 41: fr_as_binary_le randomness_value param:randomness_value"),
|
||||
self.randomness_value,
|
||||
)?;
|
||||
|
||||
// Line 41: fr_as_binary_le randomness_token param:randomness_token
|
||||
let randomness_token = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 41: fr_as_binary_le randomness_token param:randomness_token"),
|
||||
self.randomness_token,
|
||||
)?;
|
||||
|
||||
// Line 46: ec_mul_const vcv value G_VCV
|
||||
let vcv = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 46: ec_mul_const vcv value G_VCV"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR,
|
||||
&value,
|
||||
)?;
|
||||
|
||||
// Line 47: ec_mul_const rcv randomness_value G_VCR
|
||||
let rcv = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 47: ec_mul_const rcv randomness_value G_VCR"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
|
||||
&randomness_value,
|
||||
)?;
|
||||
|
||||
// Line 48: ec_add cv vcv rcv
|
||||
let cv = vcv.add(cs.namespace(|| "Line 48: ec_add cv vcv rcv"), &rcv)?;
|
||||
|
||||
// Line 50: emit_ec cv
|
||||
cv.inputize(cs.namespace(|| "Line 50: emit_ec cv"))?;
|
||||
|
||||
// Line 46: ec_mul_const vca token_id G_VCV
|
||||
let vca = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 46: ec_mul_const vca token_id G_VCV"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR,
|
||||
&token_id,
|
||||
)?;
|
||||
|
||||
// Line 47: ec_mul_const rca randomness_token G_VCR
|
||||
let rca = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 47: ec_mul_const rca randomness_token G_VCR"),
|
||||
&zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
|
||||
&randomness_token,
|
||||
)?;
|
||||
|
||||
// Line 48: ec_add ca vca rca
|
||||
let ca = vca.add(cs.namespace(|| "Line 48: ec_add ca vca rca"), &rca)?;
|
||||
|
||||
// Line 50: emit_ec ca
|
||||
ca.inputize(cs.namespace(|| "Line 50: emit_ec ca"))?;
|
||||
|
||||
// Line 54: fr_as_binary_le serial param:serial
|
||||
let serial = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 54: fr_as_binary_le serial param:serial"),
|
||||
let serial = self.load_private(
|
||||
layouter.namespace(|| "load serial"),
|
||||
config.advices[0],
|
||||
self.serial,
|
||||
)?;
|
||||
|
||||
// Line 55: fr_as_binary_le secret param:secret
|
||||
let secret = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 55: fr_as_binary_le secret param:secret"),
|
||||
self.secret,
|
||||
)?;
|
||||
|
||||
// Line 57: alloc_binary nf_preimage
|
||||
let mut nf_preimage = vec![];
|
||||
|
||||
// Line 64: binary_clone secret2 secret
|
||||
let mut secret2: Vec<_> = secret.to_vec();
|
||||
|
||||
// Line 65: binary_extend nf_preimage secret2
|
||||
nf_preimage.extend(secret2);
|
||||
|
||||
// Line 67: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 68: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 70: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 71: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 73: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 74: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 76: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 77: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 81: binary_clone serial2 serial
|
||||
let mut serial2: Vec<_> = serial.to_vec();
|
||||
|
||||
// Line 82: binary_extend nf_preimage serial2
|
||||
nf_preimage.extend(serial2);
|
||||
|
||||
// Line 84: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 85: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 87: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 88: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 90: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 91: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 93: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 94: binary_push nf_preimage zero_bit
|
||||
nf_preimage.push(zero_bit);
|
||||
|
||||
// Line 100: static_assert_binary_size nf_preimage 512
|
||||
assert_eq!(nf_preimage.len(), 512);
|
||||
|
||||
// Line 101: blake2s nf nf_preimage PRF_NF
|
||||
let mut nf = blake2s::blake2s(
|
||||
cs.namespace(|| "Line 101: blake2s nf nf_preimage PRF_NF"),
|
||||
&nf_preimage,
|
||||
zcash_primitives::constants::PRF_NF_PERSONALIZATION,
|
||||
)?;
|
||||
|
||||
// Line 102: emit_binary nf
|
||||
multipack::pack_into_inputs(cs.namespace(|| "Line 102: emit_binary nf"), &nf)?;
|
||||
|
||||
// Line 106: ec_mul_const public secret G_SPEND
|
||||
let public = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Line 106: ec_mul_const public secret G_SPEND"),
|
||||
&zcash_proofs::constants::SPENDING_KEY_GENERATOR,
|
||||
&secret,
|
||||
)?;
|
||||
|
||||
// Line 110: fr_as_binary_le randomness_coin param:randomness_coin
|
||||
let randomness_coin = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Line 110: fr_as_binary_le randomness_coin param:randomness_coin"),
|
||||
self.randomness_coin,
|
||||
)?;
|
||||
|
||||
// Line 113: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 116: ec_repr repr_public public
|
||||
let repr_public = public.repr(cs.namespace(|| "Line 116: ec_repr repr_public public"))?;
|
||||
|
||||
// Line 117: binary_extend preimage repr_public
|
||||
preimage.extend(repr_public);
|
||||
|
||||
// Line 120: binary_extend preimage value
|
||||
preimage.extend(value);
|
||||
|
||||
// Line 109: binary_extend preimage token_id
|
||||
preimage.extend(token_id);
|
||||
|
||||
// add 4 zero bits
|
||||
for _ in 0..4 {
|
||||
// Line 71: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 72: binary_push preimage zero_bit
|
||||
preimage.push(zero_bit);
|
||||
}
|
||||
|
||||
// Line 123: binary_extend preimage serial
|
||||
preimage.extend(serial);
|
||||
|
||||
// add 4 zero bits
|
||||
for _ in 0..4 {
|
||||
// Line 71: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 72: binary_push preimage zero_bit
|
||||
preimage.push(zero_bit);
|
||||
}
|
||||
|
||||
// Line 139: binary_extend preimage randomness_coin
|
||||
preimage.extend(randomness_coin);
|
||||
|
||||
// add 4 zero bits
|
||||
for _ in 0..4 {
|
||||
// Line 71: alloc_const_bit zero_bit false
|
||||
let zero_bit = Boolean::constant(false);
|
||||
|
||||
// Line 72: binary_push preimage zero_bit
|
||||
preimage.push(zero_bit);
|
||||
}
|
||||
|
||||
// Line 159: static_assert_binary_size preimage 1088
|
||||
assert_eq!(preimage.len(), 1088);
|
||||
|
||||
// Line 160: blake2s coin preimage CRH_IVK
|
||||
let mut coin = blake2s::blake2s(
|
||||
cs.namespace(|| "Line 160: blake2s coin preimage CRH_IVK"),
|
||||
&preimage,
|
||||
zcash_primitives::constants::CRH_IVK_PERSONALIZATION,
|
||||
)?;
|
||||
|
||||
// Line 166: pedersen_hash cm coin NOTE_COMMIT
|
||||
let mut cm = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "Line 166: pedersen_hash cm coin NOTE_COMMIT"),
|
||||
pedersen_hash::Personalization::NoteCommitment,
|
||||
&coin,
|
||||
)?;
|
||||
|
||||
// Line 168: ec_get_u current cm
|
||||
let mut current = cm.get_u().clone();
|
||||
|
||||
for i in 0..SAPLING_COMMITMENT_TREE_DEPTH {
|
||||
// Line 174: alloc_scalar branch param:branch_0
|
||||
let branch = num::AllocatedNum::alloc(
|
||||
cs.namespace(|| "Line 174: alloc_scalar branch param:branch_0"),
|
||||
|| Ok(*self.branch[i].get()?),
|
||||
let message = [hashed_secret_key, serial];
|
||||
let hash = {
|
||||
let poseidon_message = layouter.assign_region(
|
||||
|| "load message",
|
||||
|mut region| {
|
||||
let mut message_word = |i: usize| {
|
||||
let value = message[i].value();
|
||||
let var = region.assign_advice(
|
||||
|| format!("load message_{}", i),
|
||||
config.poseidon_config.state()[i],
|
||||
0,
|
||||
|| value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(var, message[i].cell())?;
|
||||
Ok(Word::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
|
||||
var, value,
|
||||
)))
|
||||
};
|
||||
Ok([message_word(0)?, message_word(1)?])
|
||||
},
|
||||
)?;
|
||||
|
||||
// Line 177: alloc_bit is_right param:is_right_0
|
||||
let is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc(
|
||||
cs.namespace(|| "Line 177: alloc_bit is_right param:is_right_0"),
|
||||
self.is_right[i],
|
||||
)?);
|
||||
|
||||
// Line 180: conditionally_reverse left right current branch is_right
|
||||
let (left, right) = num::AllocatedNum::conditionally_reverse(
|
||||
cs.namespace(|| {
|
||||
"Line 180: conditionally_reverse left right current branch is_right"
|
||||
}),
|
||||
¤t,
|
||||
&branch,
|
||||
&is_right,
|
||||
let poseidon_hasher = PoseidonHash::init(
|
||||
config.poseidon_chip(),
|
||||
layouter.namespace(|| "Poseidon init"),
|
||||
ConstantLength::<2>,
|
||||
)?;
|
||||
|
||||
// Line 183: scalar_as_binary left left
|
||||
let left = left.to_bits_le(cs.namespace(|| "Line 183: scalar_as_binary left left"))?;
|
||||
|
||||
// Line 184: scalar_as_binary right right
|
||||
let right =
|
||||
right.to_bits_le(cs.namespace(|| "Line 184: scalar_as_binary right right"))?;
|
||||
|
||||
// Line 185: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 186: binary_extend preimage left
|
||||
preimage.extend(left);
|
||||
|
||||
// Line 187: binary_extend preimage right
|
||||
preimage.extend(right);
|
||||
|
||||
// Line 188: pedersen_hash cm preimage MERKLE_0
|
||||
let mut cm = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "Line 188: pedersen_hash cm preimage MERKLE_0"),
|
||||
pedersen_hash::Personalization::MerkleTree(i),
|
||||
&preimage,
|
||||
let poseidon_output = poseidon_hasher.hash(
|
||||
layouter.namespace(|| "Poseidon hash (secretkey, serial)"),
|
||||
poseidon_message,
|
||||
)?;
|
||||
|
||||
// Line 190: ec_get_u current cm
|
||||
current = cm.get_u().clone();
|
||||
}
|
||||
let poseidon_output: CellValue<pasta::Fp> = poseidon_output.inner().into();
|
||||
poseidon_output
|
||||
};
|
||||
|
||||
/*
|
||||
// Line 174: alloc_scalar branch param:branch_0
|
||||
let branch = num::AllocatedNum::alloc(
|
||||
cs.namespace(|| "Line 174: alloc_scalar branch param:branch_0"),
|
||||
|| Ok(*self.branch_0.get()?),
|
||||
layouter.constrain_instance(hash.cell(), config.primary, BURN_NULLIFIER_OFFSET)?;
|
||||
|
||||
// ===========
|
||||
// Merkle root
|
||||
// ===========
|
||||
let leaf = self.load_private(
|
||||
layouter.namespace(|| "load leaf"),
|
||||
config.advices[0],
|
||||
self.leaf,
|
||||
)?;
|
||||
|
||||
// Line 177: alloc_bit is_right param:is_right_0
|
||||
let is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc(
|
||||
cs.namespace(|| "Line 177: alloc_bit is_right param:is_right_0"),
|
||||
self.is_right_0,
|
||||
)?);
|
||||
let path = MerklePath {
|
||||
chip_1: merkle_chip_1,
|
||||
chip_2: merkle_chip_2,
|
||||
domain: OrchardHashDomains::MerkleCrh,
|
||||
leaf_pos: self.leaf_pos,
|
||||
path: self.merkle_path,
|
||||
};
|
||||
|
||||
// Line 180: conditionally_reverse left right current branch is_right
|
||||
let (left, right) = num::AllocatedNum::conditionally_reverse(
|
||||
cs.namespace(|| "Line 180: conditionally_reverse left right current branch is_right"),
|
||||
¤t,
|
||||
&branch,
|
||||
&is_right,
|
||||
let computed_final_root =
|
||||
path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?;
|
||||
|
||||
layouter.constrain_instance(
|
||||
computed_final_root.cell(),
|
||||
config.primary,
|
||||
BURN_MERKLEROOT_OFFSET,
|
||||
)?;
|
||||
|
||||
// Line 183: scalar_as_binary left left
|
||||
let left = left.to_bits_le(cs.namespace(|| "Line 183: scalar_as_binary left left"))?;
|
||||
// ================
|
||||
// Value commitment
|
||||
// ================
|
||||
|
||||
// Line 184: scalar_as_binary right right
|
||||
let right = right.to_bits_le(cs.namespace(|| "Line 184: scalar_as_binary right right"))?;
|
||||
|
||||
// Line 185: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 186: binary_extend preimage left
|
||||
preimage.extend(left);
|
||||
|
||||
// Line 187: binary_extend preimage right
|
||||
preimage.extend(right);
|
||||
|
||||
// Line 188: pedersen_hash cm preimage MERKLE_0
|
||||
let mut cm = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "Line 188: pedersen_hash cm preimage MERKLE_0"),
|
||||
pedersen_hash::Personalization::MerkleTree(0),
|
||||
&preimage,
|
||||
// This constant one is used for multiplication
|
||||
let one = self.load_private(
|
||||
layouter.namespace(|| "load constant one"),
|
||||
config.advices[0],
|
||||
Some(pasta::Fp::one()),
|
||||
)?;
|
||||
|
||||
// Line 190: ec_get_u current cm
|
||||
let mut current = cm.get_u().clone();
|
||||
|
||||
// Line 194: alloc_scalar branch param:branch_1
|
||||
let branch = num::AllocatedNum::alloc(
|
||||
cs.namespace(|| "Line 194: alloc_scalar branch param:branch_1"),
|
||||
|| Ok(*self.branch_1.get()?),
|
||||
let value = self.load_private(
|
||||
layouter.namespace(|| "load value"),
|
||||
config.advices[0],
|
||||
self.value,
|
||||
)?;
|
||||
|
||||
// Line 197: alloc_bit is_right param:is_right_1
|
||||
let is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc(
|
||||
cs.namespace(|| "Line 197: alloc_bit is_right param:is_right_1"),
|
||||
self.is_right_1,
|
||||
)?);
|
||||
// v * G_1
|
||||
let (commitment, _) = {
|
||||
let value_commit_v = OrchardFixedBases::ValueCommitV;
|
||||
let value_commit_v = FixedPoint::from_inner(ecc_chip.clone(), value_commit_v);
|
||||
value_commit_v.mul_short(layouter.namespace(|| "[value] ValueCommitV"), (value, one))?
|
||||
};
|
||||
|
||||
// Line 200: conditionally_reverse left right current branch is_right
|
||||
let (left, right) = num::AllocatedNum::conditionally_reverse(
|
||||
cs.namespace(|| "Line 200: conditionally_reverse left right current branch is_right"),
|
||||
¤t,
|
||||
&branch,
|
||||
&is_right,
|
||||
// r_V * G_2
|
||||
let (blind, _rcv) = {
|
||||
let rcv = self.value_blind;
|
||||
let value_commit_r = OrchardFixedBases::ValueCommitR;
|
||||
let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), value_commit_r);
|
||||
value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
|
||||
};
|
||||
|
||||
// Constrain the value commitment coordinates
|
||||
let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
|
||||
layouter.constrain_instance(
|
||||
value_commit.inner().x().cell(),
|
||||
config.primary,
|
||||
BURN_VALCOMX_OFFSET,
|
||||
)?;
|
||||
layouter.constrain_instance(
|
||||
value_commit.inner().y().cell(),
|
||||
config.primary,
|
||||
BURN_VALCOMY_OFFSET,
|
||||
)?;
|
||||
|
||||
// Line 203: scalar_as_binary left left
|
||||
let left = left.to_bits_le(cs.namespace(|| "Line 203: scalar_as_binary left left"))?;
|
||||
// ================
|
||||
// Asset commitment
|
||||
// ================
|
||||
|
||||
// Line 204: scalar_as_binary right right
|
||||
let right = right.to_bits_le(cs.namespace(|| "Line 204: scalar_as_binary right right"))?;
|
||||
|
||||
// Line 205: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 206: binary_extend preimage left
|
||||
preimage.extend(left);
|
||||
|
||||
// Line 207: binary_extend preimage right
|
||||
preimage.extend(right);
|
||||
|
||||
// Line 208: pedersen_hash cm preimage MERKLE_1
|
||||
let mut cm = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "Line 208: pedersen_hash cm preimage MERKLE_1"),
|
||||
pedersen_hash::Personalization::MerkleTree(1),
|
||||
&preimage,
|
||||
let asset = self.load_private(
|
||||
layouter.namespace(|| "load asset"),
|
||||
config.advices[0],
|
||||
self.asset,
|
||||
)?;
|
||||
|
||||
// Line 210: ec_get_u current cm
|
||||
let mut current = cm.get_u().clone();
|
||||
// a * G_1
|
||||
let (commitment, _) = {
|
||||
let asset_commit_v = OrchardFixedBases::ValueCommitV;
|
||||
let asset_commit_v = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_v);
|
||||
asset_commit_v.mul_short(layouter.namespace(|| "[asset] ValueCommitV"), (asset, one))?
|
||||
};
|
||||
|
||||
// Line 214: alloc_scalar branch param:branch_2
|
||||
let branch = num::AllocatedNum::alloc(
|
||||
cs.namespace(|| "Line 214: alloc_scalar branch param:branch_2"),
|
||||
|| Ok(*self.branch_2.get()?),
|
||||
// r_A * G_2
|
||||
let (blind, _rca) = {
|
||||
let rca = self.asset_blind;
|
||||
let asset_commit_r = OrchardFixedBases::ValueCommitR;
|
||||
let asset_commit_r = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_r);
|
||||
asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
|
||||
};
|
||||
|
||||
// Constrain the asset commitment coordinates
|
||||
let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
|
||||
layouter.constrain_instance(
|
||||
asset_commit.inner().x().cell(),
|
||||
config.primary,
|
||||
BURN_ASSCOMX_OFFSET,
|
||||
)?;
|
||||
layouter.constrain_instance(
|
||||
asset_commit.inner().y().cell(),
|
||||
config.primary,
|
||||
BURN_ASSCOMY_OFFSET,
|
||||
)?;
|
||||
|
||||
// Line 217: alloc_bit is_right param:is_right_2
|
||||
let is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc(
|
||||
cs.namespace(|| "Line 217: alloc_bit is_right param:is_right_2"),
|
||||
self.is_right_2,
|
||||
)?);
|
||||
// ========================
|
||||
// Signature key derivation
|
||||
// ========================
|
||||
let (sig_pub, _) = {
|
||||
let spend_auth_g = OrchardFixedBases::SpendAuthG;
|
||||
let spend_auth_g = FixedPoint::from_inner(ecc_chip, spend_auth_g);
|
||||
// TODO: Do we need to load sig_secret somewhere first?
|
||||
spend_auth_g.mul(layouter.namespace(|| "[x_s] SpendAuthG"), self.sig_secret)?
|
||||
};
|
||||
|
||||
// Line 220: conditionally_reverse left right current branch is_right
|
||||
let (left, right) = num::AllocatedNum::conditionally_reverse(
|
||||
cs.namespace(|| "Line 220: conditionally_reverse left right current branch is_right"),
|
||||
¤t,
|
||||
&branch,
|
||||
&is_right,
|
||||
layouter.constrain_instance(
|
||||
sig_pub.inner().x().cell(),
|
||||
config.primary,
|
||||
BURN_SIGKEYX_OFFSET,
|
||||
)?;
|
||||
layouter.constrain_instance(
|
||||
sig_pub.inner().y().cell(),
|
||||
config.primary,
|
||||
BURN_SIGKEYY_OFFSET,
|
||||
)?;
|
||||
|
||||
// Line 223: scalar_as_binary left left
|
||||
let left = left.to_bits_le(cs.namespace(|| "Line 223: scalar_as_binary left left"))?;
|
||||
|
||||
// Line 224: scalar_as_binary right right
|
||||
let right = right.to_bits_le(cs.namespace(|| "Line 224: scalar_as_binary right right"))?;
|
||||
|
||||
// Line 225: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 226: binary_extend preimage left
|
||||
preimage.extend(left);
|
||||
|
||||
// Line 227: binary_extend preimage right
|
||||
preimage.extend(right);
|
||||
|
||||
// Line 228: pedersen_hash cm preimage MERKLE_2
|
||||
let mut cm = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "Line 228: pedersen_hash cm preimage MERKLE_2"),
|
||||
pedersen_hash::Personalization::MerkleTree(2),
|
||||
&preimage,
|
||||
)?;
|
||||
|
||||
// Line 230: ec_get_u current cm
|
||||
let mut current = cm.get_u().clone();
|
||||
|
||||
// Line 234: alloc_scalar branch param:branch_3
|
||||
let branch = num::AllocatedNum::alloc(
|
||||
cs.namespace(|| "Line 234: alloc_scalar branch param:branch_3"),
|
||||
|| Ok(*self.branch_3.get()?),
|
||||
)?;
|
||||
|
||||
// Line 237: alloc_bit is_right param:is_right_3
|
||||
let is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc(
|
||||
cs.namespace(|| "Line 237: alloc_bit is_right param:is_right_3"),
|
||||
self.is_right_3,
|
||||
)?);
|
||||
|
||||
// Line 240: conditionally_reverse left right current branch is_right
|
||||
let (left, right) = num::AllocatedNum::conditionally_reverse(
|
||||
cs.namespace(|| "Line 240: conditionally_reverse left right current branch is_right"),
|
||||
¤t,
|
||||
&branch,
|
||||
&is_right,
|
||||
)?;
|
||||
|
||||
// Line 243: scalar_as_binary left left
|
||||
let left = left.to_bits_le(cs.namespace(|| "Line 243: scalar_as_binary left left"))?;
|
||||
|
||||
// Line 244: scalar_as_binary right right
|
||||
let right = right.to_bits_le(cs.namespace(|| "Line 244: scalar_as_binary right right"))?;
|
||||
|
||||
// Line 245: alloc_binary preimage
|
||||
let mut preimage = vec![];
|
||||
|
||||
// Line 246: binary_extend preimage left
|
||||
preimage.extend(left);
|
||||
|
||||
// Line 247: binary_extend preimage right
|
||||
preimage.extend(right);
|
||||
|
||||
// Line 248: pedersen_hash cm preimage MERKLE_3
|
||||
let mut cm = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "Line 248: pedersen_hash cm preimage MERKLE_3"),
|
||||
pedersen_hash::Personalization::MerkleTree(3),
|
||||
&preimage,
|
||||
)?;
|
||||
|
||||
// Line 250: ec_get_u current cm
|
||||
let mut current = cm.get_u().clone();
|
||||
*/
|
||||
|
||||
// Line 253: emit_scalar current
|
||||
current.inputize(cs.namespace(|| "Line 253: emit_scalar current"))?;
|
||||
|
||||
let signature_secret = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "Signature secret"),
|
||||
self.signature_secret,
|
||||
)?;
|
||||
let signature_public = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "Signature public"),
|
||||
&zcash_proofs::constants::SPENDING_KEY_GENERATOR,
|
||||
&signature_secret,
|
||||
)?;
|
||||
signature_public.inputize(cs.namespace(|| "Signature public inputize"))?;
|
||||
|
||||
// At this point we've enforced all of our public inputs.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::io;
|
||||
|
||||
use crate::{
|
||||
error::Result,
|
||||
serial::{Decodable, Encodable},
|
||||
Result,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -29,4 +29,3 @@ impl Decodable for Coin {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
src/crypto/constants.rs
Normal file
7
src/crypto/constants.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
pub mod fixed_bases;
|
||||
pub mod sinsemilla;
|
||||
pub mod util;
|
||||
|
||||
pub use fixed_bases::OrchardFixedBases;
|
||||
|
||||
pub const DRK_SCHNORR_DOMAIN: &[u8] = b"DarkFi_Schnorr";
|
||||
74
src/crypto/constants/fixed_bases.rs
Normal file
74
src/crypto/constants/fixed_bases.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use halo2_gadgets::ecc::{
|
||||
chip::{compute_lagrange_coeffs, NUM_WINDOWS, NUM_WINDOWS_SHORT},
|
||||
FixedPoints, H,
|
||||
};
|
||||
use pasta_curves::pallas;
|
||||
|
||||
pub mod commit_ivk_r;
|
||||
pub mod note_commit_r;
|
||||
pub mod nullifier_k;
|
||||
pub mod spend_auth_g;
|
||||
pub mod value_commit_r;
|
||||
pub mod value_commit_v;
|
||||
|
||||
/// SWU hash-to-curve personalization for the value commitment generator
|
||||
pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv";
|
||||
|
||||
/// SWU hash-to-curve value for the value commitment generator
|
||||
pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r";
|
||||
|
||||
/// SWU hash-to-curve value for the value commitment generator
|
||||
pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v";
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum OrchardFixedBases {
|
||||
CommitIvkR,
|
||||
NoteCommitR,
|
||||
ValueCommitR,
|
||||
SpendAuthG,
|
||||
NullifierK,
|
||||
ValueCommitV,
|
||||
}
|
||||
|
||||
impl FixedPoints<pallas::Affine> for OrchardFixedBases {
|
||||
fn generator(&self) -> pallas::Affine {
|
||||
match self {
|
||||
OrchardFixedBases::CommitIvkR => commit_ivk_r::generator(),
|
||||
OrchardFixedBases::NoteCommitR => note_commit_r::generator(),
|
||||
OrchardFixedBases::ValueCommitR => value_commit_r::generator(),
|
||||
OrchardFixedBases::SpendAuthG => spend_auth_g::generator(),
|
||||
OrchardFixedBases::NullifierK => nullifier_k::generator(),
|
||||
OrchardFixedBases::ValueCommitV => value_commit_v::generator(),
|
||||
}
|
||||
}
|
||||
fn u(&self) -> Vec<[[u8; 32]; H]> {
|
||||
match self {
|
||||
OrchardFixedBases::CommitIvkR => commit_ivk_r::U.to_vec(),
|
||||
OrchardFixedBases::NoteCommitR => note_commit_r::U.to_vec(),
|
||||
OrchardFixedBases::ValueCommitR => value_commit_r::U.to_vec(),
|
||||
OrchardFixedBases::SpendAuthG => spend_auth_g::U.to_vec(),
|
||||
OrchardFixedBases::NullifierK => nullifier_k::U.to_vec(),
|
||||
OrchardFixedBases::ValueCommitV => value_commit_v::U_SHORT.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn z(&self) -> Vec<u64> {
|
||||
match self {
|
||||
OrchardFixedBases::CommitIvkR => commit_ivk_r::Z.to_vec(),
|
||||
OrchardFixedBases::NoteCommitR => note_commit_r::Z.to_vec(),
|
||||
OrchardFixedBases::ValueCommitR => value_commit_r::Z.to_vec(),
|
||||
OrchardFixedBases::SpendAuthG => spend_auth_g::Z.to_vec(),
|
||||
OrchardFixedBases::NullifierK => nullifier_k::Z.to_vec(),
|
||||
OrchardFixedBases::ValueCommitV => value_commit_v::Z_SHORT.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn lagrange_coeffs(&self) -> Vec<[pallas::Base; H]> {
|
||||
match self {
|
||||
OrchardFixedBases::ValueCommitV => {
|
||||
compute_lagrange_coeffs(self.generator(), NUM_WINDOWS_SHORT)
|
||||
}
|
||||
_ => compute_lagrange_coeffs(self.generator(), NUM_WINDOWS),
|
||||
}
|
||||
}
|
||||
}
|
||||
2965
src/crypto/constants/fixed_bases/commit_ivk_r.rs
Normal file
2965
src/crypto/constants/fixed_bases/commit_ivk_r.rs
Normal file
File diff suppressed because it is too large
Load Diff
2965
src/crypto/constants/fixed_bases/note_commit_r.rs
Normal file
2965
src/crypto/constants/fixed_bases/note_commit_r.rs
Normal file
File diff suppressed because it is too large
Load Diff
2963
src/crypto/constants/fixed_bases/nullifier_k.rs
Normal file
2963
src/crypto/constants/fixed_bases/nullifier_k.rs
Normal file
File diff suppressed because it is too large
Load Diff
2965
src/crypto/constants/fixed_bases/spend_auth_g.rs
Normal file
2965
src/crypto/constants/fixed_bases/spend_auth_g.rs
Normal file
File diff suppressed because it is too large
Load Diff
2965
src/crypto/constants/fixed_bases/value_commit_r.rs
Normal file
2965
src/crypto/constants/fixed_bases/value_commit_r.rs
Normal file
File diff suppressed because it is too large
Load Diff
818
src/crypto/constants/fixed_bases/value_commit_v.rs
Normal file
818
src/crypto/constants/fixed_bases/value_commit_v.rs
Normal file
@@ -0,0 +1,818 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
/// The value commitment is used to check balance between inputs and outputs. The value is
|
||||
/// placed over this generator.
|
||||
pub const GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
[
|
||||
103, 67, 249, 58, 110, 189, 167, 42, 140, 124, 90, 43, 127, 163, 4, 254, 50, 178, 155, 79,
|
||||
112, 106, 168, 247, 66, 15, 61, 142, 122, 89, 112, 47,
|
||||
],
|
||||
[
|
||||
142, 242, 90, 175, 126, 196, 19, 164, 219, 227, 255, 167, 102, 167, 158, 29, 66, 108, 109,
|
||||
19, 99, 127, 145, 30, 175, 25, 25, 49, 105, 81, 14, 45,
|
||||
],
|
||||
);
|
||||
|
||||
/// Short signed z-values for GENERATOR
|
||||
pub const Z_SHORT: [u64; super::NUM_WINDOWS_SHORT] = [
|
||||
163547, 76040, 88852, 128479, 54088, 89871, 39598, 144309, 43471, 102492, 741, 55288, 33756,
|
||||
77312, 12095, 48253, 45718, 202901, 33132, 71081, 152108, 169712,
|
||||
];
|
||||
|
||||
/// Short signed u-values for GENERATOR
|
||||
pub const U_SHORT: [[[u8; 32]; super::H]; super::NUM_WINDOWS_SHORT] = [
|
||||
[
|
||||
[
|
||||
16, 88, 158, 52, 92, 165, 59, 177, 224, 70, 108, 93, 144, 51, 8, 133, 114, 192, 151,
|
||||
40, 85, 33, 52, 118, 147, 163, 220, 193, 171, 43, 73, 27,
|
||||
],
|
||||
[
|
||||
201, 84, 190, 165, 219, 228, 63, 155, 182, 74, 179, 74, 230, 96, 89, 168, 110, 162, 83,
|
||||
218, 185, 137, 194, 92, 244, 85, 1, 60, 59, 16, 119, 14,
|
||||
],
|
||||
[
|
||||
113, 146, 25, 32, 206, 37, 173, 225, 58, 41, 184, 214, 177, 123, 211, 55, 42, 208, 214,
|
||||
45, 149, 99, 31, 171, 172, 226, 219, 171, 246, 85, 116, 59,
|
||||
],
|
||||
[
|
||||
10, 79, 89, 241, 37, 161, 115, 213, 183, 43, 68, 233, 219, 249, 131, 137, 41, 119, 153,
|
||||
24, 92, 87, 138, 167, 93, 46, 32, 97, 102, 164, 164, 53,
|
||||
],
|
||||
[
|
||||
50, 252, 2, 254, 234, 133, 190, 34, 244, 192, 31, 96, 156, 152, 150, 88, 154, 224, 223,
|
||||
144, 223, 113, 203, 226, 214, 44, 69, 198, 171, 60, 26, 45,
|
||||
],
|
||||
[
|
||||
151, 65, 173, 0, 249, 13, 78, 201, 84, 58, 255, 120, 124, 169, 98, 242, 239, 132, 149,
|
||||
204, 146, 244, 55, 176, 56, 26, 19, 148, 125, 42, 26, 32,
|
||||
],
|
||||
[
|
||||
6, 29, 196, 176, 135, 157, 248, 239, 196, 9, 100, 82, 220, 41, 203, 49, 35, 108, 76,
|
||||
59, 222, 47, 82, 39, 35, 23, 88, 136, 61, 90, 23, 57,
|
||||
],
|
||||
[
|
||||
169, 203, 101, 116, 220, 68, 34, 248, 199, 107, 202, 59, 111, 171, 90, 121, 119, 80,
|
||||
146, 214, 191, 197, 220, 212, 125, 139, 12, 140, 198, 191, 110, 31,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
16, 171, 139, 236, 248, 28, 27, 145, 109, 161, 63, 121, 19, 190, 106, 193, 13, 122,
|
||||
108, 54, 95, 202, 195, 184, 118, 60, 72, 213, 154, 240, 52, 34,
|
||||
],
|
||||
[
|
||||
131, 218, 16, 142, 97, 153, 190, 249, 118, 171, 187, 254, 21, 17, 202, 48, 107, 23,
|
||||
103, 72, 159, 238, 228, 38, 183, 166, 74, 136, 77, 51, 85, 18,
|
||||
],
|
||||
[
|
||||
137, 78, 204, 243, 154, 87, 148, 200, 11, 98, 58, 33, 89, 170, 198, 87, 29, 187, 167,
|
||||
122, 157, 151, 5, 148, 254, 216, 113, 12, 158, 243, 102, 63,
|
||||
],
|
||||
[
|
||||
16, 187, 216, 98, 244, 19, 70, 209, 217, 133, 240, 226, 111, 219, 247, 74, 4, 231, 183,
|
||||
216, 35, 174, 192, 96, 129, 159, 39, 96, 200, 174, 126, 1,
|
||||
],
|
||||
[
|
||||
185, 2, 174, 129, 110, 163, 212, 152, 214, 139, 105, 150, 23, 209, 185, 245, 71, 8,
|
||||
171, 142, 43, 57, 167, 172, 233, 77, 194, 166, 118, 232, 127, 35,
|
||||
],
|
||||
[
|
||||
57, 28, 236, 33, 234, 0, 214, 131, 161, 209, 42, 25, 194, 150, 82, 126, 216, 23, 81,
|
||||
85, 90, 47, 95, 46, 119, 108, 253, 12, 92, 29, 13, 25,
|
||||
],
|
||||
[
|
||||
100, 162, 156, 175, 254, 203, 69, 171, 182, 190, 85, 161, 94, 117, 225, 0, 95, 121,
|
||||
190, 235, 79, 7, 147, 134, 48, 156, 113, 55, 114, 229, 174, 25,
|
||||
],
|
||||
[
|
||||
243, 93, 223, 98, 132, 0, 171, 125, 135, 53, 111, 49, 49, 173, 69, 211, 62, 106, 168,
|
||||
221, 115, 208, 2, 20, 14, 150, 124, 130, 189, 48, 16, 15,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
43, 238, 4, 240, 186, 135, 47, 128, 185, 51, 70, 196, 3, 137, 22, 254, 29, 247, 161,
|
||||
233, 187, 255, 239, 183, 150, 179, 8, 64, 90, 33, 17, 54,
|
||||
],
|
||||
[
|
||||
20, 226, 19, 60, 92, 195, 1, 255, 100, 188, 89, 54, 98, 225, 138, 133, 26, 140, 202,
|
||||
76, 107, 199, 46, 54, 167, 23, 119, 80, 19, 25, 34, 5,
|
||||
],
|
||||
[
|
||||
145, 109, 10, 159, 200, 145, 32, 253, 32, 93, 187, 12, 66, 161, 44, 217, 16, 100, 225,
|
||||
37, 139, 125, 169, 119, 83, 34, 96, 130, 234, 255, 138, 38,
|
||||
],
|
||||
[
|
||||
148, 127, 71, 227, 195, 244, 12, 49, 83, 78, 218, 9, 176, 158, 12, 5, 194, 54, 44, 157,
|
||||
252, 228, 175, 170, 54, 91, 49, 254, 83, 228, 180, 61,
|
||||
],
|
||||
[
|
||||
36, 96, 238, 61, 227, 144, 153, 81, 121, 197, 74, 190, 35, 216, 255, 92, 70, 7, 168,
|
||||
219, 130, 255, 172, 71, 200, 31, 142, 232, 255, 117, 96, 15,
|
||||
],
|
||||
[
|
||||
50, 152, 255, 238, 188, 127, 140, 240, 203, 33, 246, 193, 228, 179, 25, 1, 227, 194,
|
||||
79, 70, 41, 160, 83, 243, 148, 1, 95, 86, 63, 22, 55, 40,
|
||||
],
|
||||
[
|
||||
99, 228, 147, 46, 232, 157, 225, 210, 45, 159, 169, 42, 184, 90, 3, 165, 62, 4, 93,
|
||||
181, 74, 187, 112, 156, 26, 103, 199, 84, 132, 148, 14, 24,
|
||||
],
|
||||
[
|
||||
120, 163, 182, 125, 197, 141, 122, 21, 166, 103, 203, 57, 160, 228, 242, 192, 203, 40,
|
||||
233, 179, 8, 173, 199, 21, 213, 215, 222, 129, 23, 153, 25, 29,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
189, 6, 27, 46, 68, 6, 124, 69, 159, 212, 18, 104, 218, 16, 66, 183, 250, 92, 69, 5,
|
||||
218, 234, 31, 198, 123, 100, 216, 103, 106, 113, 192, 43,
|
||||
],
|
||||
[
|
||||
226, 152, 83, 159, 143, 155, 164, 90, 171, 100, 22, 240, 187, 26, 55, 172, 170, 133,
|
||||
128, 192, 29, 33, 35, 8, 59, 142, 20, 204, 151, 172, 29, 28,
|
||||
],
|
||||
[
|
||||
196, 57, 232, 112, 46, 200, 26, 93, 224, 191, 117, 154, 9, 47, 228, 145, 122, 137, 238,
|
||||
236, 70, 14, 112, 163, 96, 140, 239, 122, 75, 200, 206, 12,
|
||||
],
|
||||
[
|
||||
91, 66, 65, 159, 86, 50, 113, 39, 30, 12, 213, 235, 15, 70, 163, 119, 112, 27, 22, 170,
|
||||
151, 20, 71, 172, 65, 251, 224, 76, 26, 189, 118, 42,
|
||||
],
|
||||
[
|
||||
195, 200, 87, 207, 125, 122, 254, 50, 24, 40, 189, 169, 237, 228, 134, 66, 37, 220, 23,
|
||||
98, 202, 193, 152, 184, 171, 63, 105, 11, 70, 94, 154, 58,
|
||||
],
|
||||
[
|
||||
4, 0, 82, 125, 41, 130, 11, 238, 112, 201, 95, 30, 144, 31, 31, 233, 86, 121, 145, 200,
|
||||
204, 89, 182, 51, 151, 169, 58, 206, 184, 219, 181, 46,
|
||||
],
|
||||
[
|
||||
36, 240, 60, 205, 120, 239, 9, 98, 61, 228, 247, 9, 145, 71, 67, 10, 164, 160, 186,
|
||||
104, 25, 225, 210, 37, 31, 42, 58, 208, 44, 19, 30, 29,
|
||||
],
|
||||
[
|
||||
163, 214, 140, 64, 48, 239, 54, 175, 108, 32, 187, 248, 142, 77, 244, 117, 10, 236, 39,
|
||||
80, 158, 44, 98, 44, 248, 24, 208, 60, 173, 247, 115, 28,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
230, 166, 7, 118, 178, 55, 26, 250, 91, 159, 230, 158, 34, 135, 91, 49, 166, 244, 124,
|
||||
175, 86, 228, 159, 119, 231, 15, 19, 199, 219, 85, 233, 19,
|
||||
],
|
||||
[
|
||||
65, 240, 77, 9, 197, 255, 96, 35, 239, 161, 177, 115, 83, 114, 180, 179, 118, 158, 220,
|
||||
61, 177, 3, 175, 70, 132, 51, 87, 79, 36, 104, 129, 15,
|
||||
],
|
||||
[
|
||||
245, 9, 141, 218, 228, 57, 204, 250, 83, 156, 160, 158, 146, 157, 206, 198, 16, 94, 80,
|
||||
59, 31, 242, 163, 30, 80, 99, 32, 142, 193, 101, 172, 22,
|
||||
],
|
||||
[
|
||||
22, 68, 73, 27, 236, 149, 225, 78, 69, 83, 174, 202, 98, 113, 148, 167, 43, 132, 118,
|
||||
49, 153, 96, 186, 134, 20, 103, 123, 48, 75, 104, 207, 6,
|
||||
],
|
||||
[
|
||||
186, 5, 66, 183, 166, 255, 222, 14, 34, 0, 105, 167, 36, 11, 210, 228, 91, 103, 65,
|
||||
248, 3, 48, 117, 240, 180, 214, 201, 222, 5, 202, 103, 42,
|
||||
],
|
||||
[
|
||||
231, 31, 19, 122, 240, 72, 34, 93, 204, 125, 90, 215, 124, 174, 124, 28, 145, 103, 126,
|
||||
178, 1, 9, 152, 240, 251, 118, 14, 195, 197, 167, 136, 22,
|
||||
],
|
||||
[
|
||||
121, 57, 39, 104, 26, 135, 98, 221, 85, 199, 94, 230, 223, 129, 28, 191, 185, 0, 46,
|
||||
200, 72, 116, 202, 255, 80, 180, 13, 98, 229, 217, 238, 17,
|
||||
],
|
||||
[
|
||||
228, 158, 59, 241, 50, 224, 177, 78, 8, 121, 211, 157, 95, 196, 88, 59, 85, 141, 134,
|
||||
50, 123, 168, 175, 115, 240, 153, 223, 61, 71, 229, 77, 10,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
196, 151, 212, 168, 230, 19, 214, 179, 118, 17, 196, 50, 76, 231, 114, 80, 178, 137,
|
||||
232, 241, 60, 2, 0, 124, 25, 239, 98, 131, 220, 159, 221, 51,
|
||||
],
|
||||
[
|
||||
207, 216, 50, 53, 106, 200, 85, 166, 137, 33, 29, 239, 97, 46, 104, 218, 177, 150, 178,
|
||||
64, 232, 238, 208, 98, 103, 58, 233, 97, 1, 243, 73, 5,
|
||||
],
|
||||
[
|
||||
174, 215, 22, 124, 193, 136, 79, 91, 111, 146, 51, 128, 249, 129, 203, 168, 157, 164,
|
||||
252, 144, 206, 10, 63, 253, 250, 113, 251, 65, 218, 23, 12, 25,
|
||||
],
|
||||
[
|
||||
186, 92, 109, 134, 176, 198, 214, 156, 148, 7, 106, 121, 226, 70, 250, 192, 180, 164,
|
||||
16, 29, 245, 196, 155, 183, 214, 26, 3, 26, 249, 134, 153, 38,
|
||||
],
|
||||
[
|
||||
244, 56, 170, 227, 236, 145, 153, 150, 166, 77, 201, 48, 100, 130, 204, 194, 108, 207,
|
||||
3, 243, 227, 41, 45, 8, 136, 106, 58, 70, 126, 3, 132, 59,
|
||||
],
|
||||
[
|
||||
215, 169, 24, 118, 5, 192, 171, 217, 47, 86, 212, 249, 228, 92, 248, 103, 242, 222, 17,
|
||||
206, 36, 157, 126, 224, 105, 113, 239, 102, 54, 25, 151, 14,
|
||||
],
|
||||
[
|
||||
129, 213, 202, 163, 74, 201, 249, 43, 200, 62, 4, 232, 68, 211, 44, 153, 25, 71, 155,
|
||||
5, 93, 19, 117, 195, 201, 179, 158, 207, 252, 213, 166, 62,
|
||||
],
|
||||
[
|
||||
86, 75, 236, 222, 217, 118, 49, 0, 141, 130, 201, 248, 34, 225, 69, 91, 186, 90, 246,
|
||||
36, 141, 152, 166, 216, 118, 7, 38, 133, 147, 190, 79, 3,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
226, 55, 121, 73, 104, 77, 129, 202, 168, 123, 192, 163, 28, 9, 195, 37, 116, 207, 125,
|
||||
198, 203, 244, 121, 236, 232, 91, 168, 14, 142, 241, 250, 60,
|
||||
],
|
||||
[
|
||||
222, 86, 183, 37, 132, 107, 210, 125, 127, 46, 94, 81, 18, 91, 72, 160, 16, 193, 239,
|
||||
114, 238, 186, 186, 203, 96, 169, 87, 155, 108, 36, 97, 6,
|
||||
],
|
||||
[
|
||||
110, 110, 99, 98, 167, 78, 75, 128, 33, 138, 18, 19, 194, 192, 219, 184, 74, 196, 82,
|
||||
115, 241, 102, 30, 197, 199, 194, 154, 120, 49, 10, 95, 37,
|
||||
],
|
||||
[
|
||||
212, 206, 154, 98, 20, 33, 185, 182, 138, 207, 65, 197, 246, 19, 132, 52, 173, 186, 42,
|
||||
243, 88, 20, 51, 11, 206, 25, 216, 48, 162, 138, 124, 13,
|
||||
],
|
||||
[
|
||||
32, 161, 64, 72, 1, 32, 243, 175, 251, 37, 86, 248, 136, 187, 181, 55, 39, 255, 98,
|
||||
228, 189, 235, 194, 2, 228, 39, 92, 104, 245, 17, 117, 7,
|
||||
],
|
||||
[
|
||||
207, 205, 116, 251, 54, 21, 8, 82, 173, 45, 205, 38, 245, 155, 16, 56, 198, 232, 173,
|
||||
88, 97, 22, 234, 26, 139, 206, 108, 254, 123, 87, 181, 26,
|
||||
],
|
||||
[
|
||||
38, 147, 223, 169, 68, 76, 49, 169, 137, 141, 72, 63, 166, 88, 34, 220, 163, 91, 167,
|
||||
251, 29, 160, 254, 199, 205, 74, 158, 105, 252, 182, 158, 21,
|
||||
],
|
||||
[
|
||||
221, 44, 183, 72, 226, 191, 226, 165, 162, 153, 186, 190, 97, 53, 19, 115, 215, 71,
|
||||
155, 33, 79, 120, 197, 228, 216, 212, 249, 15, 179, 11, 216, 32,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
248, 136, 25, 30, 234, 18, 242, 209, 97, 211, 74, 228, 236, 199, 101, 200, 206, 52,
|
||||
146, 207, 72, 125, 28, 3, 60, 86, 34, 195, 250, 251, 204, 0,
|
||||
],
|
||||
[
|
||||
204, 182, 197, 171, 247, 159, 161, 27, 18, 146, 249, 99, 198, 138, 25, 61, 119, 232,
|
||||
160, 152, 18, 149, 7, 67, 125, 231, 237, 3, 68, 190, 137, 0,
|
||||
],
|
||||
[
|
||||
141, 245, 108, 181, 49, 171, 106, 247, 202, 169, 106, 39, 93, 40, 122, 2, 236, 255,
|
||||
198, 215, 122, 254, 242, 192, 49, 250, 243, 35, 7, 219, 21, 22,
|
||||
],
|
||||
[
|
||||
239, 85, 174, 15, 207, 84, 128, 92, 87, 80, 129, 20, 21, 225, 233, 158, 193, 136, 141,
|
||||
114, 66, 146, 29, 193, 223, 250, 27, 56, 195, 15, 135, 17,
|
||||
],
|
||||
[
|
||||
231, 242, 76, 43, 57, 10, 41, 166, 32, 254, 129, 47, 147, 118, 189, 200, 44, 102, 204,
|
||||
116, 96, 82, 186, 150, 106, 27, 30, 73, 237, 94, 36, 44,
|
||||
],
|
||||
[
|
||||
240, 139, 69, 197, 199, 228, 206, 96, 255, 229, 189, 207, 65, 97, 93, 211, 161, 190,
|
||||
228, 249, 50, 82, 223, 251, 13, 173, 241, 221, 78, 243, 105, 19,
|
||||
],
|
||||
[
|
||||
44, 224, 170, 161, 50, 93, 212, 80, 100, 243, 51, 74, 51, 165, 60, 208, 244, 18, 158,
|
||||
30, 158, 81, 111, 213, 136, 95, 125, 173, 143, 108, 106, 4,
|
||||
],
|
||||
[
|
||||
134, 244, 131, 92, 152, 118, 30, 139, 153, 128, 62, 115, 88, 25, 58, 29, 205, 101, 47,
|
||||
208, 93, 89, 222, 17, 122, 112, 71, 56, 147, 68, 92, 22,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
59, 157, 112, 130, 217, 2, 102, 228, 79, 211, 152, 82, 183, 186, 47, 151, 125, 13, 97,
|
||||
121, 115, 253, 17, 121, 227, 250, 99, 14, 84, 249, 18, 30,
|
||||
],
|
||||
[
|
||||
80, 180, 155, 59, 6, 182, 136, 39, 134, 168, 238, 138, 129, 174, 195, 206, 210, 167,
|
||||
214, 167, 35, 139, 130, 27, 21, 59, 7, 200, 165, 37, 91, 29,
|
||||
],
|
||||
[
|
||||
220, 228, 189, 172, 68, 102, 135, 236, 7, 70, 152, 244, 120, 217, 67, 44, 43, 74, 155,
|
||||
179, 2, 148, 106, 238, 232, 186, 181, 130, 141, 114, 60, 1,
|
||||
],
|
||||
[
|
||||
68, 132, 80, 55, 28, 52, 222, 165, 156, 6, 214, 236, 207, 37, 223, 118, 42, 55, 40,
|
||||
123, 208, 181, 240, 56, 14, 142, 58, 72, 193, 71, 120, 58,
|
||||
],
|
||||
[
|
||||
93, 114, 68, 232, 179, 37, 202, 74, 41, 64, 245, 112, 233, 162, 231, 19, 223, 207, 232,
|
||||
213, 178, 60, 106, 26, 35, 191, 108, 19, 243, 220, 40, 41,
|
||||
],
|
||||
[
|
||||
166, 223, 96, 196, 120, 210, 67, 47, 249, 123, 164, 213, 148, 138, 7, 155, 96, 222,
|
||||
176, 166, 88, 85, 95, 71, 221, 237, 138, 181, 198, 165, 163, 0,
|
||||
],
|
||||
[
|
||||
241, 254, 24, 83, 47, 65, 146, 151, 5, 182, 233, 205, 182, 13, 75, 173, 10, 14, 48,
|
||||
223, 227, 201, 141, 212, 114, 205, 196, 92, 137, 253, 127, 60,
|
||||
],
|
||||
[
|
||||
20, 41, 204, 77, 168, 230, 68, 202, 73, 251, 254, 88, 95, 80, 130, 216, 122, 75, 173,
|
||||
105, 236, 192, 177, 209, 26, 66, 205, 127, 154, 188, 245, 17,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
239, 194, 214, 218, 225, 244, 0, 110, 12, 75, 130, 236, 76, 102, 205, 64, 104, 144,
|
||||
198, 188, 183, 46, 119, 96, 230, 68, 210, 161, 253, 91, 8, 20,
|
||||
],
|
||||
[
|
||||
84, 32, 226, 77, 213, 16, 207, 156, 234, 224, 147, 173, 186, 249, 186, 155, 90, 255,
|
||||
34, 55, 48, 108, 76, 214, 254, 66, 95, 200, 174, 191, 52, 43,
|
||||
],
|
||||
[
|
||||
37, 103, 206, 174, 250, 172, 136, 87, 30, 68, 89, 230, 110, 190, 148, 71, 5, 249, 217,
|
||||
112, 54, 182, 127, 54, 173, 89, 6, 63, 230, 69, 32, 35,
|
||||
],
|
||||
[
|
||||
160, 186, 242, 212, 179, 197, 16, 239, 56, 24, 91, 241, 68, 7, 138, 200, 93, 194, 45,
|
||||
155, 210, 60, 30, 4, 167, 246, 82, 244, 71, 217, 31, 20,
|
||||
],
|
||||
[
|
||||
182, 132, 62, 134, 4, 186, 95, 160, 230, 255, 125, 156, 5, 134, 66, 99, 83, 182, 156,
|
||||
207, 98, 84, 197, 48, 160, 47, 126, 2, 253, 64, 69, 25,
|
||||
],
|
||||
[
|
||||
135, 241, 60, 121, 32, 218, 195, 61, 68, 66, 190, 195, 208, 2, 201, 111, 158, 101, 108,
|
||||
228, 145, 141, 82, 80, 36, 16, 157, 212, 65, 213, 188, 61,
|
||||
],
|
||||
[
|
||||
190, 186, 202, 30, 121, 177, 200, 82, 245, 162, 14, 253, 114, 50, 43, 134, 246, 12,
|
||||
100, 222, 149, 242, 117, 174, 136, 192, 117, 132, 228, 144, 238, 39,
|
||||
],
|
||||
[
|
||||
160, 120, 19, 13, 34, 38, 71, 236, 116, 162, 150, 254, 247, 252, 222, 198, 196, 59, 98,
|
||||
165, 54, 33, 22, 120, 58, 73, 225, 42, 37, 211, 88, 21,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
252, 1, 229, 131, 50, 189, 111, 31, 191, 210, 177, 219, 234, 21, 100, 182, 115, 212,
|
||||
154, 111, 130, 59, 237, 32, 142, 202, 110, 96, 166, 120, 188, 1,
|
||||
],
|
||||
[
|
||||
247, 244, 137, 120, 38, 62, 94, 38, 17, 38, 102, 240, 225, 129, 15, 214, 213, 142, 79,
|
||||
176, 156, 118, 85, 80, 167, 47, 122, 152, 206, 19, 67, 40,
|
||||
],
|
||||
[
|
||||
27, 159, 102, 201, 17, 4, 75, 28, 159, 5, 194, 6, 63, 104, 157, 219, 53, 38, 84, 216,
|
||||
73, 181, 11, 118, 29, 177, 147, 135, 150, 5, 58, 10,
|
||||
],
|
||||
[
|
||||
97, 168, 102, 245, 40, 187, 155, 99, 147, 65, 114, 119, 191, 225, 196, 34, 117, 134,
|
||||
116, 162, 73, 69, 158, 103, 144, 16, 22, 216, 146, 38, 10, 41,
|
||||
],
|
||||
[
|
||||
149, 231, 10, 10, 17, 16, 88, 231, 24, 215, 115, 237, 123, 68, 9, 209, 24, 141, 150,
|
||||
207, 109, 56, 107, 192, 252, 112, 156, 0, 65, 234, 86, 10,
|
||||
],
|
||||
[
|
||||
201, 24, 6, 113, 122, 123, 58, 3, 233, 141, 78, 228, 137, 112, 71, 121, 200, 171, 158,
|
||||
233, 87, 171, 121, 118, 205, 98, 38, 24, 176, 153, 170, 25,
|
||||
],
|
||||
[
|
||||
6, 114, 137, 241, 204, 203, 173, 160, 14, 124, 220, 164, 166, 224, 0, 253, 255, 68, 40,
|
||||
182, 248, 135, 226, 25, 213, 247, 45, 116, 94, 147, 107, 3,
|
||||
],
|
||||
[
|
||||
73, 103, 138, 222, 168, 203, 85, 216, 242, 63, 127, 158, 153, 60, 168, 180, 234, 71,
|
||||
27, 10, 38, 161, 207, 26, 81, 150, 195, 37, 91, 228, 57, 46,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
188, 220, 107, 162, 250, 116, 137, 134, 75, 73, 102, 28, 11, 158, 166, 162, 77, 99,
|
||||
159, 21, 166, 195, 208, 99, 28, 0, 51, 64, 126, 222, 203, 28,
|
||||
],
|
||||
[
|
||||
115, 93, 10, 209, 3, 81, 82, 191, 158, 74, 26, 242, 145, 24, 85, 106, 28, 36, 54, 17,
|
||||
216, 109, 58, 102, 221, 11, 10, 157, 226, 90, 53, 3,
|
||||
],
|
||||
[
|
||||
197, 172, 174, 245, 150, 142, 92, 221, 45, 118, 174, 8, 83, 195, 45, 83, 221, 212, 122,
|
||||
239, 218, 103, 89, 56, 184, 102, 73, 70, 1, 40, 246, 54,
|
||||
],
|
||||
[
|
||||
131, 77, 239, 236, 59, 58, 35, 163, 25, 57, 251, 93, 224, 202, 225, 84, 189, 195, 1,
|
||||
234, 156, 138, 3, 2, 102, 170, 173, 235, 97, 41, 224, 0,
|
||||
],
|
||||
[
|
||||
251, 165, 141, 221, 2, 154, 174, 224, 120, 187, 163, 188, 37, 146, 49, 193, 150, 241,
|
||||
183, 33, 12, 228, 96, 92, 105, 198, 238, 59, 247, 172, 247, 54,
|
||||
],
|
||||
[
|
||||
31, 84, 10, 130, 68, 107, 203, 153, 201, 34, 69, 151, 1, 180, 37, 198, 113, 64, 82,
|
||||
116, 116, 142, 251, 62, 22, 122, 138, 130, 200, 159, 145, 2,
|
||||
],
|
||||
[
|
||||
229, 126, 102, 192, 242, 5, 109, 247, 248, 70, 34, 78, 35, 23, 81, 67, 34, 226, 133,
|
||||
119, 200, 242, 142, 111, 223, 102, 159, 61, 162, 226, 222, 11,
|
||||
],
|
||||
[
|
||||
171, 0, 253, 102, 188, 223, 208, 250, 186, 183, 127, 172, 10, 41, 201, 173, 242, 156,
|
||||
106, 219, 236, 139, 76, 115, 200, 123, 176, 228, 181, 248, 121, 38,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
187, 71, 125, 130, 250, 45, 125, 44, 56, 31, 103, 55, 71, 87, 166, 228, 184, 12, 252,
|
||||
79, 26, 221, 65, 188, 62, 254, 222, 87, 189, 71, 43, 0,
|
||||
],
|
||||
[
|
||||
248, 127, 55, 175, 11, 237, 134, 201, 211, 212, 93, 115, 63, 118, 15, 121, 71, 55, 176,
|
||||
74, 3, 75, 20, 100, 177, 194, 39, 92, 67, 109, 243, 38,
|
||||
],
|
||||
[
|
||||
147, 188, 248, 11, 127, 3, 176, 153, 109, 5, 65, 101, 2, 46, 70, 203, 246, 245, 254,
|
||||
67, 193, 214, 156, 21, 116, 165, 60, 79, 219, 45, 180, 47,
|
||||
],
|
||||
[
|
||||
78, 126, 47, 15, 17, 83, 240, 144, 40, 174, 95, 250, 144, 43, 132, 67, 241, 189, 140,
|
||||
244, 41, 221, 164, 186, 104, 156, 223, 233, 160, 99, 190, 39,
|
||||
],
|
||||
[
|
||||
29, 119, 16, 42, 190, 69, 200, 191, 3, 160, 164, 28, 189, 135, 85, 63, 59, 121, 213,
|
||||
143, 9, 96, 150, 14, 21, 93, 132, 57, 4, 165, 174, 12,
|
||||
],
|
||||
[
|
||||
54, 200, 34, 46, 89, 210, 152, 121, 245, 147, 150, 48, 193, 246, 108, 154, 243, 12, 10,
|
||||
10, 97, 83, 225, 116, 187, 177, 176, 80, 248, 185, 5, 38,
|
||||
],
|
||||
[
|
||||
245, 84, 103, 49, 77, 27, 84, 143, 30, 40, 54, 249, 178, 71, 191, 135, 199, 72, 204,
|
||||
162, 75, 110, 203, 246, 193, 61, 70, 158, 74, 154, 13, 45,
|
||||
],
|
||||
[
|
||||
123, 98, 28, 217, 129, 160, 71, 205, 19, 41, 168, 124, 76, 145, 108, 71, 57, 60, 26,
|
||||
154, 163, 64, 250, 13, 52, 179, 197, 193, 54, 184, 29, 32,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
103, 140, 102, 88, 162, 193, 224, 59, 243, 31, 145, 100, 116, 71, 36, 129, 94, 248, 33,
|
||||
0, 102, 46, 146, 206, 22, 255, 216, 58, 61, 118, 226, 47,
|
||||
],
|
||||
[
|
||||
21, 127, 228, 231, 155, 190, 28, 145, 48, 160, 35, 104, 47, 120, 243, 107, 145, 118,
|
||||
199, 126, 138, 164, 246, 143, 153, 59, 153, 209, 81, 118, 167, 9,
|
||||
],
|
||||
[
|
||||
4, 84, 44, 30, 90, 253, 226, 166, 218, 12, 39, 214, 231, 241, 223, 87, 87, 82, 93, 220,
|
||||
65, 132, 166, 75, 221, 33, 236, 113, 198, 43, 210, 39,
|
||||
],
|
||||
[
|
||||
243, 54, 41, 143, 244, 171, 75, 158, 218, 230, 55, 35, 236, 18, 40, 55, 157, 139, 180,
|
||||
29, 58, 159, 88, 208, 214, 87, 168, 227, 93, 211, 194, 17,
|
||||
],
|
||||
[
|
||||
97, 131, 219, 190, 19, 178, 244, 173, 141, 143, 113, 3, 27, 63, 35, 185, 170, 43, 75,
|
||||
64, 75, 38, 5, 13, 123, 39, 147, 243, 141, 122, 217, 39,
|
||||
],
|
||||
[
|
||||
3, 24, 126, 200, 122, 92, 125, 221, 95, 205, 139, 145, 231, 77, 223, 96, 84, 39, 33,
|
||||
66, 139, 41, 82, 182, 22, 102, 95, 173, 66, 125, 77, 21,
|
||||
],
|
||||
[
|
||||
27, 50, 52, 183, 190, 198, 236, 248, 71, 251, 120, 132, 192, 227, 113, 36, 155, 81,
|
||||
225, 48, 72, 17, 246, 99, 208, 242, 236, 93, 2, 19, 53, 31,
|
||||
],
|
||||
[
|
||||
99, 18, 31, 165, 229, 52, 216, 52, 162, 62, 66, 1, 190, 22, 69, 133, 11, 126, 106, 165,
|
||||
131, 180, 218, 253, 238, 124, 3, 16, 42, 196, 148, 57,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
0, 209, 105, 72, 69, 130, 81, 154, 136, 174, 169, 182, 42, 150, 112, 115, 234, 136, 47,
|
||||
170, 158, 213, 211, 65, 178, 62, 18, 172, 135, 59, 253, 19,
|
||||
],
|
||||
[
|
||||
145, 192, 219, 168, 214, 190, 54, 248, 68, 248, 196, 148, 4, 254, 61, 193, 67, 218,
|
||||
131, 110, 235, 60, 159, 101, 200, 218, 208, 195, 30, 249, 163, 32,
|
||||
],
|
||||
[
|
||||
21, 246, 3, 74, 137, 246, 202, 207, 71, 59, 198, 73, 117, 224, 124, 57, 2, 82, 110, 6,
|
||||
190, 80, 143, 143, 113, 62, 127, 122, 164, 202, 6, 54,
|
||||
],
|
||||
[
|
||||
252, 245, 11, 63, 63, 70, 60, 82, 15, 154, 188, 35, 211, 222, 252, 180, 109, 109, 98,
|
||||
69, 197, 240, 137, 46, 189, 8, 167, 87, 15, 179, 18, 12,
|
||||
],
|
||||
[
|
||||
125, 206, 204, 128, 43, 62, 39, 36, 246, 164, 44, 6, 250, 83, 14, 207, 53, 201, 166,
|
||||
231, 175, 110, 140, 200, 48, 239, 20, 171, 46, 80, 115, 54,
|
||||
],
|
||||
[
|
||||
167, 7, 74, 225, 61, 229, 21, 154, 196, 11, 247, 27, 158, 112, 217, 238, 57, 53, 63,
|
||||
251, 162, 91, 168, 86, 37, 203, 207, 119, 68, 135, 205, 9,
|
||||
],
|
||||
[
|
||||
84, 187, 71, 200, 46, 254, 136, 13, 25, 137, 121, 128, 232, 221, 40, 0, 175, 232, 153,
|
||||
227, 181, 162, 29, 67, 225, 234, 249, 102, 82, 171, 226, 1,
|
||||
],
|
||||
[
|
||||
24, 185, 170, 6, 35, 57, 108, 85, 245, 134, 216, 239, 33, 12, 223, 38, 227, 73, 145,
|
||||
100, 25, 14, 244, 177, 84, 38, 101, 67, 21, 96, 249, 61,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
57, 9, 82, 174, 160, 195, 27, 106, 241, 225, 207, 16, 11, 131, 29, 63, 187, 187, 5, 76,
|
||||
34, 39, 136, 124, 56, 25, 58, 99, 70, 116, 170, 19,
|
||||
],
|
||||
[
|
||||
143, 6, 32, 114, 74, 44, 29, 53, 226, 34, 62, 232, 111, 63, 201, 203, 46, 115, 209,
|
||||
118, 31, 27, 1, 120, 254, 70, 252, 80, 5, 111, 123, 55,
|
||||
],
|
||||
[
|
||||
62, 18, 214, 41, 0, 12, 4, 12, 145, 201, 12, 6, 179, 4, 20, 84, 36, 155, 8, 99, 181,
|
||||
18, 150, 144, 203, 228, 172, 135, 166, 152, 214, 8,
|
||||
],
|
||||
[
|
||||
49, 93, 249, 139, 121, 113, 205, 158, 145, 118, 40, 96, 206, 154, 71, 190, 146, 65,
|
||||
233, 104, 83, 91, 25, 118, 176, 14, 149, 115, 137, 27, 223, 41,
|
||||
],
|
||||
[
|
||||
116, 160, 29, 244, 254, 193, 228, 122, 194, 168, 126, 1, 222, 247, 90, 191, 253, 101,
|
||||
123, 197, 178, 127, 30, 113, 38, 73, 48, 240, 82, 52, 161, 12,
|
||||
],
|
||||
[
|
||||
156, 145, 203, 40, 113, 83, 199, 161, 230, 196, 203, 227, 217, 212, 254, 139, 37, 215,
|
||||
39, 230, 190, 141, 119, 120, 87, 23, 61, 21, 3, 209, 179, 47,
|
||||
],
|
||||
[
|
||||
179, 114, 238, 159, 43, 22, 64, 61, 207, 56, 101, 90, 62, 245, 27, 21, 165, 0, 205, 34,
|
||||
104, 32, 170, 75, 215, 255, 83, 74, 123, 73, 159, 19,
|
||||
],
|
||||
[
|
||||
14, 208, 162, 223, 209, 5, 175, 15, 1, 78, 222, 82, 21, 113, 25, 129, 103, 64, 139, 21,
|
||||
226, 245, 199, 114, 252, 69, 133, 254, 128, 63, 61, 13,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
255, 187, 20, 3, 51, 61, 230, 80, 83, 233, 71, 190, 94, 131, 225, 143, 139, 246, 196,
|
||||
161, 165, 85, 92, 167, 71, 198, 83, 10, 164, 120, 89, 26,
|
||||
],
|
||||
[
|
||||
250, 108, 167, 151, 249, 92, 38, 36, 21, 96, 210, 31, 41, 91, 113, 183, 104, 192, 3,
|
||||
45, 165, 253, 37, 75, 239, 245, 28, 148, 5, 255, 134, 60,
|
||||
],
|
||||
[
|
||||
59, 154, 220, 255, 37, 98, 169, 60, 50, 196, 202, 240, 225, 57, 165, 129, 255, 66, 169,
|
||||
162, 7, 30, 198, 27, 160, 208, 193, 106, 29, 119, 104, 48,
|
||||
],
|
||||
[
|
||||
137, 180, 21, 151, 27, 173, 213, 11, 238, 163, 104, 192, 171, 59, 79, 249, 123, 55,
|
||||
183, 8, 94, 117, 32, 48, 41, 141, 231, 207, 61, 135, 104, 2,
|
||||
],
|
||||
[
|
||||
242, 254, 15, 0, 58, 49, 204, 28, 27, 56, 2, 67, 248, 104, 160, 32, 214, 242, 10, 206,
|
||||
233, 61, 23, 103, 180, 53, 179, 198, 56, 254, 65, 6,
|
||||
],
|
||||
[
|
||||
136, 214, 253, 248, 156, 140, 42, 172, 221, 187, 160, 233, 86, 213, 239, 5, 110, 252,
|
||||
70, 18, 193, 29, 156, 156, 136, 70, 167, 59, 98, 223, 7, 30,
|
||||
],
|
||||
[
|
||||
84, 25, 227, 152, 61, 51, 53, 59, 135, 229, 159, 248, 6, 39, 151, 139, 121, 149, 226,
|
||||
142, 126, 136, 248, 196, 93, 176, 131, 254, 221, 204, 179, 36,
|
||||
],
|
||||
[
|
||||
198, 74, 99, 58, 59, 34, 82, 94, 95, 64, 17, 241, 173, 114, 211, 57, 124, 181, 140,
|
||||
102, 105, 79, 13, 1, 60, 121, 143, 88, 192, 253, 159, 47,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
90, 115, 165, 218, 163, 197, 210, 143, 213, 125, 1, 77, 74, 165, 200, 244, 80, 39, 20,
|
||||
247, 86, 120, 109, 109, 93, 7, 209, 199, 109, 12, 144, 46,
|
||||
],
|
||||
[
|
||||
231, 44, 48, 128, 109, 202, 114, 192, 218, 67, 233, 141, 64, 251, 104, 41, 58, 212, 60,
|
||||
65, 93, 58, 34, 149, 128, 90, 30, 197, 191, 244, 8, 37,
|
||||
],
|
||||
[
|
||||
56, 47, 18, 80, 195, 143, 175, 35, 183, 225, 201, 236, 138, 29, 26, 229, 194, 202, 13,
|
||||
43, 71, 188, 3, 204, 12, 15, 218, 207, 15, 83, 219, 39,
|
||||
],
|
||||
[
|
||||
50, 71, 182, 171, 33, 129, 211, 168, 40, 85, 193, 218, 165, 54, 220, 203, 164, 124, 8,
|
||||
37, 19, 210, 8, 253, 120, 158, 239, 239, 28, 195, 253, 37,
|
||||
],
|
||||
[
|
||||
245, 191, 155, 103, 118, 221, 209, 204, 89, 48, 249, 160, 180, 1, 114, 3, 254, 220, 94,
|
||||
244, 221, 122, 224, 55, 184, 106, 99, 11, 236, 89, 211, 38,
|
||||
],
|
||||
[
|
||||
182, 208, 168, 152, 15, 192, 45, 31, 93, 181, 13, 203, 128, 82, 126, 145, 129, 220, 19,
|
||||
252, 188, 247, 49, 216, 218, 198, 178, 70, 180, 209, 175, 22,
|
||||
],
|
||||
[
|
||||
72, 71, 200, 22, 21, 120, 50, 111, 112, 195, 141, 79, 49, 52, 98, 8, 37, 130, 142, 13,
|
||||
78, 197, 15, 92, 203, 50, 108, 82, 109, 254, 158, 12,
|
||||
],
|
||||
[
|
||||
71, 44, 114, 76, 152, 26, 79, 25, 44, 244, 191, 178, 150, 102, 34, 230, 54, 251, 209,
|
||||
155, 90, 28, 81, 49, 127, 246, 116, 238, 106, 105, 196, 29,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
208, 87, 78, 186, 184, 128, 38, 190, 131, 156, 221, 119, 87, 12, 144, 4, 240, 77, 118,
|
||||
209, 74, 131, 37, 155, 247, 155, 206, 167, 80, 71, 127, 18,
|
||||
],
|
||||
[
|
||||
190, 54, 229, 228, 15, 167, 185, 240, 161, 238, 216, 88, 210, 31, 242, 20, 81, 147, 48,
|
||||
54, 38, 226, 251, 64, 69, 196, 67, 166, 242, 34, 118, 39,
|
||||
],
|
||||
[
|
||||
58, 171, 187, 174, 13, 247, 253, 15, 102, 171, 48, 63, 136, 157, 55, 28, 117, 130, 104,
|
||||
23, 145, 203, 155, 105, 121, 249, 115, 106, 88, 114, 86, 11,
|
||||
],
|
||||
[
|
||||
105, 30, 100, 75, 20, 206, 29, 147, 150, 37, 48, 216, 33, 147, 61, 193, 82, 230, 205,
|
||||
122, 142, 65, 148, 102, 47, 185, 182, 147, 185, 31, 29, 54,
|
||||
],
|
||||
[
|
||||
158, 245, 169, 236, 26, 185, 17, 174, 156, 69, 81, 196, 60, 109, 99, 91, 19, 208, 93,
|
||||
58, 9, 109, 228, 186, 109, 127, 171, 156, 229, 215, 195, 59,
|
||||
],
|
||||
[
|
||||
23, 42, 4, 183, 91, 177, 2, 172, 168, 182, 158, 185, 157, 118, 199, 184, 237, 203, 60,
|
||||
170, 35, 121, 162, 7, 130, 171, 121, 207, 32, 2, 227, 62,
|
||||
],
|
||||
[
|
||||
0, 139, 174, 217, 13, 116, 28, 230, 238, 117, 190, 91, 86, 105, 38, 231, 147, 100, 233,
|
||||
187, 70, 128, 111, 82, 184, 113, 154, 136, 59, 27, 21, 10,
|
||||
],
|
||||
[
|
||||
4, 208, 53, 136, 59, 196, 102, 52, 69, 1, 231, 8, 254, 19, 67, 134, 251, 73, 157, 156,
|
||||
30, 94, 170, 147, 185, 72, 11, 143, 226, 255, 0, 60,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
214, 131, 68, 196, 131, 169, 22, 250, 29, 101, 142, 26, 106, 96, 18, 190, 18, 15, 19,
|
||||
59, 203, 203, 119, 251, 61, 221, 198, 116, 24, 178, 61, 42,
|
||||
],
|
||||
[
|
||||
101, 161, 133, 103, 0, 112, 204, 255, 98, 240, 20, 161, 242, 253, 216, 204, 83, 96, 93,
|
||||
228, 77, 76, 63, 70, 116, 156, 69, 253, 121, 189, 2, 36,
|
||||
],
|
||||
[
|
||||
156, 83, 226, 206, 4, 35, 12, 137, 209, 181, 109, 81, 194, 119, 188, 216, 30, 233, 135,
|
||||
220, 213, 40, 74, 152, 49, 14, 0, 3, 223, 41, 238, 54,
|
||||
],
|
||||
[
|
||||
47, 25, 110, 4, 111, 57, 200, 91, 168, 73, 47, 175, 189, 60, 49, 243, 128, 11, 63, 17,
|
||||
151, 123, 80, 140, 139, 202, 93, 104, 190, 32, 67, 54,
|
||||
],
|
||||
[
|
||||
90, 100, 132, 107, 167, 162, 164, 62, 239, 68, 20, 223, 157, 1, 90, 95, 248, 82, 65,
|
||||
61, 241, 63, 238, 10, 2, 160, 230, 104, 101, 197, 60, 52,
|
||||
],
|
||||
[
|
||||
41, 144, 80, 156, 134, 224, 6, 48, 188, 57, 30, 205, 84, 135, 190, 75, 213, 94, 16, 72,
|
||||
11, 96, 41, 117, 75, 60, 62, 133, 29, 133, 105, 15,
|
||||
],
|
||||
[
|
||||
219, 66, 247, 117, 3, 137, 38, 43, 131, 177, 137, 150, 9, 65, 160, 206, 235, 121, 121,
|
||||
245, 205, 233, 229, 78, 72, 200, 171, 149, 240, 64, 184, 5,
|
||||
],
|
||||
[
|
||||
22, 179, 118, 116, 100, 222, 159, 96, 236, 247, 38, 23, 224, 103, 6, 5, 42, 95, 161, 4,
|
||||
128, 2, 240, 122, 117, 247, 127, 207, 76, 205, 137, 31,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
255, 68, 73, 184, 204, 219, 231, 9, 237, 101, 142, 55, 146, 252, 138, 14, 186, 62, 32,
|
||||
108, 79, 130, 251, 188, 101, 134, 179, 162, 172, 160, 149, 22,
|
||||
],
|
||||
[
|
||||
93, 226, 69, 177, 229, 17, 78, 185, 6, 206, 195, 246, 145, 189, 141, 7, 197, 148, 166,
|
||||
43, 203, 235, 170, 119, 102, 76, 108, 98, 216, 237, 121, 34,
|
||||
],
|
||||
[
|
||||
211, 167, 46, 90, 228, 111, 217, 129, 255, 3, 113, 207, 200, 221, 28, 48, 33, 62, 31,
|
||||
245, 116, 175, 130, 128, 180, 252, 132, 178, 56, 58, 16, 2,
|
||||
],
|
||||
[
|
||||
159, 176, 149, 39, 220, 58, 146, 80, 175, 91, 125, 15, 166, 114, 133, 117, 52, 243,
|
||||
219, 221, 223, 114, 140, 236, 106, 39, 65, 168, 43, 244, 140, 57,
|
||||
],
|
||||
[
|
||||
144, 68, 49, 189, 208, 94, 145, 108, 143, 62, 16, 188, 15, 110, 23, 239, 71, 48, 32,
|
||||
238, 96, 19, 43, 91, 231, 90, 77, 162, 159, 162, 71, 15,
|
||||
],
|
||||
[
|
||||
103, 8, 114, 153, 156, 97, 188, 167, 128, 217, 58, 42, 208, 82, 234, 142, 53, 71, 10,
|
||||
38, 177, 2, 13, 35, 8, 49, 196, 134, 215, 255, 42, 54,
|
||||
],
|
||||
[
|
||||
229, 29, 149, 199, 252, 232, 6, 148, 31, 243, 79, 192, 221, 191, 136, 186, 249, 198,
|
||||
35, 155, 198, 198, 19, 183, 159, 123, 65, 127, 169, 3, 156, 59,
|
||||
],
|
||||
[
|
||||
2, 244, 213, 144, 80, 83, 125, 211, 252, 98, 209, 105, 104, 213, 143, 183, 164, 199,
|
||||
103, 53, 110, 48, 230, 35, 34, 129, 221, 255, 225, 224, 42, 42,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
145, 41, 77, 21, 230, 237, 146, 98, 160, 218, 242, 227, 198, 83, 11, 39, 148, 69, 31,
|
||||
185, 143, 52, 71, 75, 157, 26, 157, 188, 179, 27, 114, 24,
|
||||
],
|
||||
[
|
||||
160, 247, 33, 120, 242, 78, 125, 237, 149, 68, 194, 190, 248, 145, 93, 23, 171, 167,
|
||||
181, 242, 226, 41, 104, 67, 0, 116, 81, 246, 87, 82, 103, 51,
|
||||
],
|
||||
[
|
||||
84, 35, 131, 165, 134, 206, 147, 191, 7, 3, 253, 142, 49, 128, 111, 47, 53, 169, 88,
|
||||
17, 31, 193, 20, 98, 19, 173, 111, 175, 134, 186, 166, 27,
|
||||
],
|
||||
[
|
||||
49, 150, 139, 110, 180, 138, 202, 107, 41, 238, 123, 185, 17, 161, 67, 30, 2, 2, 39,
|
||||
91, 7, 35, 69, 121, 34, 12, 247, 78, 138, 39, 59, 8,
|
||||
],
|
||||
[
|
||||
64, 14, 249, 58, 50, 65, 122, 135, 174, 11, 102, 220, 221, 64, 29, 66, 24, 169, 57,
|
||||
114, 140, 176, 7, 149, 78, 15, 211, 255, 101, 244, 151, 46,
|
||||
],
|
||||
[
|
||||
127, 185, 215, 42, 158, 164, 234, 37, 140, 239, 228, 75, 189, 8, 197, 4, 206, 24, 136,
|
||||
191, 73, 206, 141, 195, 85, 123, 141, 189, 82, 250, 65, 21,
|
||||
],
|
||||
[
|
||||
49, 239, 163, 97, 219, 143, 242, 84, 53, 166, 149, 155, 243, 11, 207, 69, 250, 25, 159,
|
||||
142, 240, 8, 72, 229, 91, 179, 218, 39, 128, 133, 201, 6,
|
||||
],
|
||||
[
|
||||
96, 144, 236, 91, 71, 246, 217, 36, 27, 102, 209, 14, 75, 249, 185, 211, 2, 97, 216,
|
||||
204, 141, 6, 234, 251, 183, 215, 152, 151, 125, 210, 121, 14,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{
|
||||
test_lagrange_coeffs, test_zs_and_us, NUM_WINDOWS_SHORT, VALUE_COMMITMENT_PERSONALIZATION,
|
||||
};
|
||||
use super::*;
|
||||
use group::Curve;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, CurveExt, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn generator() {
|
||||
let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
|
||||
let point = hasher(b"v");
|
||||
let coords = point.to_affine().coordinates().unwrap();
|
||||
|
||||
assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lagrange_coeffs_short() {
|
||||
let base = super::generator();
|
||||
test_lagrange_coeffs(base, NUM_WINDOWS_SHORT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn z_short() {
|
||||
let base = super::generator();
|
||||
test_zs_and_us(base, &Z_SHORT, &U_SHORT, NUM_WINDOWS_SHORT);
|
||||
}
|
||||
}
|
||||
261
src/crypto/constants/sinsemilla.rs
Normal file
261
src/crypto/constants/sinsemilla.rs
Normal file
@@ -0,0 +1,261 @@
|
||||
//! Sinsemilla generators
|
||||
use super::OrchardFixedBases;
|
||||
//use crate::spec::i2lebsp;
|
||||
|
||||
use halo2_gadgets::sinsemilla::{CommitDomains, HashDomains};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
/// Number of bits of each message piece in $\mathsf{SinsemillaHashToPoint}$
|
||||
pub const K: usize = 10;
|
||||
|
||||
/// $\frac{1}{2^K}$
|
||||
pub const INV_TWO_POW_K: [u8; 32] = [
|
||||
1, 0, 192, 196, 160, 229, 70, 82, 221, 165, 74, 202, 85, 7, 62, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 240, 63,
|
||||
];
|
||||
|
||||
/// The largest integer such that $2^c \leq (r_P - 1) / 2$, where $r_P$ is the order
|
||||
/// of Pallas.
|
||||
pub const C: usize = 253;
|
||||
|
||||
/// $\ell^\mathsf{Orchard}_\mathsf{Merkle}$
|
||||
//pub(crate) const L_ORCHARD_MERKLE: usize = 255;
|
||||
|
||||
/// SWU hash-to-curve personalization for the Merkle CRH generator
|
||||
pub const MERKLE_CRH_PERSONALIZATION: &str = "z.cash:Orchard-MerkleCRH";
|
||||
|
||||
// Sinsemilla Q generators
|
||||
|
||||
/// SWU hash-to-curve personalization for Sinsemilla $Q$ generators.
|
||||
pub const Q_PERSONALIZATION: &str = "z.cash:SinsemillaQ";
|
||||
|
||||
// Sinsemilla S generators
|
||||
|
||||
/// SWU hash-to-curve personalization for Sinsemilla $S$ generators.
|
||||
pub const S_PERSONALIZATION: &str = "z.cash:SinsemillaS";
|
||||
|
||||
/// Generator used in SinsemillaHashToPoint for note commitment
|
||||
pub const Q_NOTE_COMMITMENT_M_GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
[
|
||||
93, 116, 168, 64, 9, 186, 14, 50, 42, 221, 70, 253, 90, 15, 150, 197, 93, 237, 176, 121,
|
||||
180, 242, 159, 247, 13, 205, 251, 86, 160, 7, 128, 23,
|
||||
],
|
||||
[
|
||||
99, 172, 73, 115, 90, 10, 39, 135, 158, 94, 219, 129, 136, 18, 34, 136, 44, 201, 244, 110,
|
||||
217, 194, 190, 78, 131, 112, 198, 138, 147, 88, 160, 50,
|
||||
],
|
||||
);
|
||||
|
||||
/// Generator used in SinsemillaHashToPoint for IVK commitment
|
||||
pub const Q_COMMIT_IVK_M_GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
[
|
||||
242, 130, 15, 121, 146, 47, 203, 107, 50, 162, 40, 81, 36, 204, 27, 66, 250, 65, 162, 90,
|
||||
184, 129, 204, 125, 17, 200, 169, 74, 241, 12, 188, 5,
|
||||
],
|
||||
[
|
||||
190, 222, 173, 207, 206, 229, 90, 190, 241, 165, 109, 201, 29, 53, 196, 70, 75, 5, 222, 32,
|
||||
70, 7, 89, 239, 230, 190, 26, 212, 246, 76, 1, 27,
|
||||
],
|
||||
);
|
||||
|
||||
/// Generator used in SinsemillaHashToPoint for Merkle collision-resistant hash
|
||||
pub const Q_MERKLE_CRH: ([u8; 32], [u8; 32]) = (
|
||||
[
|
||||
160, 198, 41, 127, 249, 199, 185, 248, 112, 16, 141, 192, 85, 185, 190, 201, 153, 14, 137,
|
||||
239, 90, 54, 15, 160, 185, 24, 168, 99, 150, 210, 22, 22,
|
||||
],
|
||||
[
|
||||
98, 234, 242, 37, 206, 174, 233, 134, 150, 21, 116, 5, 234, 150, 28, 226, 121, 89, 163, 79,
|
||||
62, 242, 196, 45, 153, 32, 175, 227, 163, 66, 134, 53,
|
||||
],
|
||||
);
|
||||
|
||||
/*
|
||||
pub(crate) fn lebs2ip_k(bits: &[bool]) -> u32 {
|
||||
assert!(bits.len() == K);
|
||||
bits.iter()
|
||||
.enumerate()
|
||||
.fold(0u32, |acc, (i, b)| acc + if *b { 1 << i } else { 0 })
|
||||
}
|
||||
|
||||
/// The sequence of K bits in little-endian order representing an integer
|
||||
/// up to `2^K` - 1.
|
||||
pub(crate) fn i2lebsp_k(int: usize) -> [bool; K] {
|
||||
assert!(int < (1 << K));
|
||||
i2lebsp(int as u64)
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum OrchardHashDomains {
|
||||
NoteCommit,
|
||||
CommitIvk,
|
||||
MerkleCrh,
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl HashDomains<pallas::Affine> for OrchardHashDomains {
|
||||
fn Q(&self) -> pallas::Affine {
|
||||
match self {
|
||||
OrchardHashDomains::CommitIvk => pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
OrchardHashDomains::NoteCommit => pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
OrchardHashDomains::MerkleCrh => pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap(),
|
||||
pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum OrchardCommitDomains {
|
||||
NoteCommit,
|
||||
CommitIvk,
|
||||
}
|
||||
|
||||
impl CommitDomains<pallas::Affine, OrchardFixedBases, OrchardHashDomains> for OrchardCommitDomains {
|
||||
fn r(&self) -> OrchardFixedBases {
|
||||
match self {
|
||||
Self::NoteCommit => OrchardFixedBases::NoteCommitR,
|
||||
Self::CommitIvk => OrchardFixedBases::CommitIvkR,
|
||||
}
|
||||
}
|
||||
|
||||
fn hash_domain(&self) -> OrchardHashDomains {
|
||||
match self {
|
||||
Self::NoteCommit => OrchardHashDomains::NoteCommit,
|
||||
Self::CommitIvk => OrchardHashDomains::CommitIvk,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::constants::{
|
||||
fixed_bases::{COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION},
|
||||
sinsemilla::MERKLE_CRH_PERSONALIZATION,
|
||||
};
|
||||
use halo2_gadgets::primitives::sinsemilla::{CommitDomain, HashDomain};
|
||||
|
||||
use ff::PrimeField;
|
||||
use group::Curve;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use rand::{self, rngs::OsRng, Rng};
|
||||
|
||||
#[test]
|
||||
// Nodes in the Merkle tree are Pallas base field elements.
|
||||
fn l_orchard_merkle() {
|
||||
assert_eq!(super::L_ORCHARD_MERKLE, pallas::Base::NUM_BITS as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lebs2ip_k_round_trip() {
|
||||
let mut rng = OsRng;
|
||||
{
|
||||
let int = rng.gen_range(0..(1 << K));
|
||||
assert_eq!(lebs2ip_k(&i2lebsp_k(int)) as usize, int);
|
||||
}
|
||||
|
||||
assert_eq!(lebs2ip_k(&i2lebsp_k(0)) as usize, 0);
|
||||
assert_eq!(lebs2ip_k(&i2lebsp_k((1 << K) - 1)) as usize, (1 << K) - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i2lebsp_k_round_trip() {
|
||||
{
|
||||
let bitstring = (0..K).map(|_| rand::random()).collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(),
|
||||
bitstring
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
let bitstring = [false; K];
|
||||
assert_eq!(
|
||||
i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(),
|
||||
bitstring
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
let bitstring = [true; K];
|
||||
assert_eq!(
|
||||
i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(),
|
||||
bitstring
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn q_note_commitment_m() {
|
||||
let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
|
||||
let point = domain.Q();
|
||||
let coords = point.to_affine().coordinates().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*coords.x(),
|
||||
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
*coords.y(),
|
||||
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn q_commit_ivk_m() {
|
||||
let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION);
|
||||
let point = domain.Q();
|
||||
let coords = point.to_affine().coordinates().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*coords.x(),
|
||||
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
*coords.y(),
|
||||
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn q_merkle_crh() {
|
||||
let domain = HashDomain::new(MERKLE_CRH_PERSONALIZATION);
|
||||
let point = domain.Q();
|
||||
let coords = point.to_affine().coordinates().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*coords.x(),
|
||||
pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
*coords.y(),
|
||||
pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inv_two_pow_k() {
|
||||
let two_pow_k = pallas::Base::from_u64(1u64 << K);
|
||||
let inv_two_pow_k = pallas::Base::from_bytes(&INV_TWO_POW_K).unwrap();
|
||||
|
||||
assert_eq!(two_pow_k * inv_two_pow_k, pallas::Base::one());
|
||||
}
|
||||
}
|
||||
31
src/crypto/constants/util.rs
Normal file
31
src/crypto/constants/util.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use pasta_curves::arithmetic::{CurveAffine, Field, FieldExt};
|
||||
|
||||
/// Evaluate y = f(x) given the coefficients of f(x)
|
||||
pub fn evaluate<C: CurveAffine>(x: u8, coeffs: &[C::Base]) -> C::Base {
|
||||
let x = C::Base::from_u64(x as u64);
|
||||
coeffs
|
||||
.iter()
|
||||
.rev()
|
||||
.cloned()
|
||||
.reduce(|acc, coeff| acc * x + coeff)
|
||||
.unwrap_or_else(C::Base::zero)
|
||||
}
|
||||
|
||||
/// Takes in an FnMut closure and returns a constant-length array with elements of
|
||||
/// type `Output`.
|
||||
pub fn gen_const_array<Output: Copy + Default, const LEN: usize>(
|
||||
closure: impl FnMut(usize) -> Output,
|
||||
) -> [Output; LEN] {
|
||||
gen_const_array_with_default(Default::default(), closure)
|
||||
}
|
||||
|
||||
pub(crate) fn gen_const_array_with_default<Output: Copy, const LEN: usize>(
|
||||
default_value: Output,
|
||||
mut closure: impl FnMut(usize) -> Output,
|
||||
) -> [Output; LEN] {
|
||||
let mut ret: [Output; LEN] = [default_value; LEN];
|
||||
for (bit, val) in ret.iter_mut().zip((0..LEN).map(|idx| closure(idx))) {
|
||||
*bit = val;
|
||||
}
|
||||
ret
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use group::{cofactor::CofactorGroup, GroupEncoding};
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::group::{cofactor::CofactorGroup, GroupEncoding};
|
||||
|
||||
pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
|
||||
|
||||
@@ -8,7 +9,7 @@ pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
|
||||
/// Sapling key agreement for note encryption.
|
||||
///
|
||||
/// Implements section 5.4.4.3 of the Zcash Protocol Specification.
|
||||
pub fn sapling_ka_agree(esk: &jubjub::Fr, pk_d: &jubjub::ExtendedPoint) -> jubjub::SubgroupPoint {
|
||||
pub fn sapling_ka_agree(esk: &pasta::Fq, pk_d: &pasta::Ep) -> pasta::Ep {
|
||||
// [8 esk] pk_d
|
||||
// <ExtendedPoint as CofactorGroup>::clear_cofactor is implemented using
|
||||
// ExtendedPoint::mul_by_cofactor in the jubjub crate.
|
||||
@@ -25,7 +26,7 @@ pub fn sapling_ka_agree(esk: &jubjub::Fr, pk_d: &jubjub::ExtendedPoint) -> jubju
|
||||
/// Sapling KDF for note encryption.
|
||||
///
|
||||
/// Implements section 5.4.4.4 of the Zcash Protocol Specification.
|
||||
pub fn kdf_sapling(dhsecret: jubjub::SubgroupPoint, epk: &jubjub::ExtendedPoint) -> Blake2bHash {
|
||||
pub fn kdf_sapling(dhsecret: pasta::Ep, epk: &pasta::Ep) -> Blake2bHash {
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(KDF_SAPLING_PERSONALIZATION)
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
use bellman::gadgets::multipack;
|
||||
use bellman::groth16;
|
||||
use blake2s_simd::Params as Blake2sParams;
|
||||
use bls12_381::Bls12;
|
||||
use group::{Curve, GroupEncoding};
|
||||
use rand::rngs::OsRng;
|
||||
use std::io;
|
||||
use std::time::Instant;
|
||||
|
||||
use halo2_gadgets::primitives;
|
||||
use halo2_gadgets::primitives::poseidon::{ConstantLength, P128Pow5T3};
|
||||
use log::debug;
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
group::Curve,
|
||||
};
|
||||
|
||||
use super::{
|
||||
proof::{Proof, ProvingKey, VerifyingKey},
|
||||
types::*,
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
};
|
||||
use crate::circuit::mint_contract::MintContract;
|
||||
use crate::error::Result;
|
||||
use crate::serial::{Decodable, Encodable};
|
||||
|
||||
pub struct MintRevealedValues {
|
||||
pub value_commit: jubjub::SubgroupPoint,
|
||||
pub token_commit: jubjub::SubgroupPoint,
|
||||
pub value_commit: DrkValueCommit,
|
||||
pub token_commit: DrkValueCommit,
|
||||
pub coin: [u8; 32],
|
||||
}
|
||||
|
||||
impl MintRevealedValues {
|
||||
fn compute(
|
||||
value: u64,
|
||||
token_id: jubjub::Fr,
|
||||
randomness_value: &jubjub::Fr,
|
||||
randomness_token: &jubjub::Fr,
|
||||
serial: &jubjub::Fr,
|
||||
randomness_coin: &jubjub::Fr,
|
||||
public: &jubjub::SubgroupPoint,
|
||||
token_id: DrkTokenId,
|
||||
value_blind: DrkValueBlind,
|
||||
token_blind: DrkValueBlind,
|
||||
serial: DrkSerial,
|
||||
coin_blind: DrkCoinBlind,
|
||||
public_key: DrkPublicKey,
|
||||
) -> Self {
|
||||
let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
|
||||
* jubjub::Fr::from(value))
|
||||
+ (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
|
||||
* randomness_value);
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
|
||||
let token_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
|
||||
* token_id)
|
||||
+ (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
|
||||
* randomness_token);
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
let messages = [
|
||||
[*coords.x(), *coords.y()],
|
||||
[pasta::Fp::from_u64(value), token_id],
|
||||
[serial, coin_blind],
|
||||
];
|
||||
|
||||
let mut coin = [0; 32];
|
||||
coin.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&public.to_bytes())
|
||||
.update(&value.to_le_bytes())
|
||||
.update(&token_id.to_bytes())
|
||||
.update(&serial.to_bytes())
|
||||
.update(&randomness_coin.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
);
|
||||
let mut hash = pasta::Fp::zero();
|
||||
for msg in messages.iter() {
|
||||
hash += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
|
||||
}
|
||||
|
||||
let coin = hash.to_bytes();
|
||||
|
||||
MintRevealedValues {
|
||||
value_commit,
|
||||
@@ -59,41 +59,19 @@ impl MintRevealedValues {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_outputs(&self) -> [bls12_381::Scalar; 6] {
|
||||
let mut public_input = [bls12_381::Scalar::zero(); 6];
|
||||
fn make_outputs(&self) -> [pasta::Fp; 5] {
|
||||
let value_coords = self.value_commit.to_affine().coordinates().unwrap();
|
||||
let token_coords = self.value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
{
|
||||
let result = jubjub::ExtendedPoint::from(self.value_commit);
|
||||
let affine = result.to_affine();
|
||||
//let (u, v) = (affine.get_u(), affine.get_v());
|
||||
let u = affine.get_u();
|
||||
let v = affine.get_v();
|
||||
public_input[0] = u;
|
||||
public_input[1] = v;
|
||||
}
|
||||
|
||||
{
|
||||
let result = jubjub::ExtendedPoint::from(self.token_commit);
|
||||
let affine = result.to_affine();
|
||||
let u = affine.get_u();
|
||||
let v = affine.get_v();
|
||||
public_input[2] = u;
|
||||
public_input[3] = v;
|
||||
}
|
||||
|
||||
{
|
||||
// Pack the hash as inputs for proof verification.
|
||||
let hash = multipack::bytes_to_bits_le(&self.coin);
|
||||
let hash = multipack::compute_multipacking(&hash);
|
||||
|
||||
// There are 2 chunks for a blake hash
|
||||
assert_eq!(hash.len(), 2);
|
||||
|
||||
public_input[4] = hash[0];
|
||||
public_input[5] = hash[1];
|
||||
}
|
||||
|
||||
public_input
|
||||
vec![
|
||||
pasta::Fp::from_bytes(&self.coin).unwrap(),
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
*token_coords.y(),
|
||||
]
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,72 +95,54 @@ impl Decodable for MintRevealedValues {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_mint_prover() -> groth16::Parameters<Bls12> {
|
||||
println!("Mint: Making random params...");
|
||||
let start = Instant::now();
|
||||
let params = {
|
||||
let c = MintContract {
|
||||
value: None,
|
||||
token_id: None,
|
||||
randomness_value: None,
|
||||
randomness_token: None,
|
||||
serial: None,
|
||||
randomness_coin: None,
|
||||
public: None,
|
||||
};
|
||||
groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
|
||||
};
|
||||
println!("Setup: [{:?}]", start.elapsed());
|
||||
params
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn create_mint_proof(
|
||||
params: &groth16::Parameters<Bls12>,
|
||||
value: u64,
|
||||
token_id: jubjub::Fr,
|
||||
randomness_value: jubjub::Fr,
|
||||
randomness_token: jubjub::Fr,
|
||||
serial: jubjub::Fr,
|
||||
randomness_coin: jubjub::Fr,
|
||||
public: jubjub::SubgroupPoint,
|
||||
) -> (groth16::Proof<Bls12>, MintRevealedValues) {
|
||||
token_id: pasta::Fp,
|
||||
value_blind: pasta::Fq,
|
||||
token_blind: pasta::Fq,
|
||||
serial: pasta::Fp,
|
||||
coin_blind: pasta::Fp,
|
||||
public_key: pasta::Ep,
|
||||
) -> Result<(Proof, MintRevealedValues)> {
|
||||
let revealed = MintRevealedValues::compute(
|
||||
value,
|
||||
token_id,
|
||||
&randomness_value,
|
||||
&randomness_token,
|
||||
&serial,
|
||||
&randomness_coin,
|
||||
&public,
|
||||
value_blind,
|
||||
token_blind,
|
||||
serial,
|
||||
coin_blind,
|
||||
public_key,
|
||||
);
|
||||
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
|
||||
let c = MintContract {
|
||||
value: Some(value),
|
||||
token_id: Some(token_id),
|
||||
randomness_value: Some(randomness_value),
|
||||
randomness_token: Some(randomness_token),
|
||||
pub_x: Some(*coords.x()),
|
||||
pub_y: Some(*coords.y()),
|
||||
value: Some(pasta::Fp::from_u64(value)),
|
||||
asset: Some(token_id),
|
||||
serial: Some(serial),
|
||||
randomness_coin: Some(randomness_coin),
|
||||
public: Some(public),
|
||||
coin_blind: Some(coin_blind),
|
||||
value_blind: Some(value_blind),
|
||||
asset_blind: Some(token_blind),
|
||||
};
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = groth16::create_random_proof(c, params, &mut OsRng).unwrap();
|
||||
println!("Prove: [{:?}]", start.elapsed());
|
||||
|
||||
(proof, revealed)
|
||||
}
|
||||
|
||||
pub fn verify_mint_proof(
|
||||
pvk: &groth16::PreparedVerifyingKey<Bls12>,
|
||||
proof: &groth16::Proof<Bls12>,
|
||||
revealed: &MintRevealedValues,
|
||||
) -> bool {
|
||||
let public_input = revealed.make_outputs();
|
||||
let pk = ProvingKey::build(11, MintContract::default());
|
||||
debug!("Setup: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let result = groth16::verify_proof(pvk, proof, &public_input).is_ok();
|
||||
println!("Verify: [{:?}]", start.elapsed());
|
||||
result
|
||||
let public_inputs = revealed.make_outputs();
|
||||
let proof = Proof::create(&pk, &[c], &public_inputs)?;
|
||||
debug!("Prove: [{:?}]", start.elapsed());
|
||||
|
||||
Ok((proof, revealed))
|
||||
}
|
||||
|
||||
pub fn verify_mint_proof(proof: Proof, revealed: &MintRevealedValues) -> Result<()> {
|
||||
let public_inputs = revealed.make_outputs();
|
||||
|
||||
let vk = VerifyingKey::build(11, MintContract::default());
|
||||
Ok(proof.verify(&vk, &public_inputs)?)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
pub mod coin;
|
||||
pub mod constants;
|
||||
pub mod diffie_hellman;
|
||||
pub mod fr_serial;
|
||||
pub mod merkle;
|
||||
pub mod merkle_node;
|
||||
//pub mod merkle;
|
||||
//pub mod merkle_node;
|
||||
pub mod mint_proof;
|
||||
pub mod note;
|
||||
pub mod nullifier;
|
||||
pub mod pasta_serial;
|
||||
pub mod proof;
|
||||
pub mod schnorr;
|
||||
pub mod spend_proof;
|
||||
pub mod types;
|
||||
//pub mod spend_proof;
|
||||
pub mod util;
|
||||
|
||||
/*
|
||||
use bellman::groth16;
|
||||
use bls12_381::Bls12;
|
||||
|
||||
@@ -48,3 +51,4 @@ pub fn load_params(
|
||||
let pvk = groth16::prepare_verifying_key(¶ms.vk);
|
||||
Ok((params, pvk))
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
use crypto_api_chachapoly::ChachaPolyIetf;
|
||||
use ff::Field;
|
||||
use rand::rngs::OsRng;
|
||||
use std::io;
|
||||
|
||||
use super::diffie_hellman::{kdf_sapling, sapling_ka_agree};
|
||||
use crypto_api_chachapoly::ChachaPolyIetf;
|
||||
use halo2_gadgets::ecc::FixedPoints;
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::arithmetic::Field;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use super::{
|
||||
constants::OrchardFixedBases,
|
||||
diffie_hellman::{kdf_sapling, sapling_ka_agree},
|
||||
};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::serial::{Decodable, Encodable, ReadExt, WriteExt};
|
||||
|
||||
@@ -17,11 +23,11 @@ pub const ENC_CIPHERTEXT_SIZE: usize = NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Note {
|
||||
pub serial: jubjub::Fr,
|
||||
pub serial: pasta::Fp,
|
||||
pub value: u64,
|
||||
pub token_id: jubjub::Fr,
|
||||
pub coin_blind: jubjub::Fr,
|
||||
pub valcom_blind: jubjub::Fr,
|
||||
pub token_id: pasta::Fp,
|
||||
pub coin_blind: pasta::Fp,
|
||||
pub valcom_blind: pasta::Fq,
|
||||
}
|
||||
|
||||
impl Encodable for Note {
|
||||
@@ -49,9 +55,9 @@ impl Decodable for Note {
|
||||
}
|
||||
|
||||
impl Note {
|
||||
pub fn encrypt(&self, public: &jubjub::SubgroupPoint) -> Result<EncryptedNote> {
|
||||
let ephem_secret = jubjub::Fr::random(&mut OsRng);
|
||||
let ephem_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * ephem_secret;
|
||||
pub fn encrypt(&self, public: &pasta::Ep) -> Result<EncryptedNote> {
|
||||
let ephem_secret = pasta::Fq::random(&mut OsRng);
|
||||
let ephem_public = OrchardFixedBases::SpendAuthG.generator() * ephem_secret;
|
||||
let shared_secret = sapling_ka_agree(&ephem_secret, public.into());
|
||||
let key = kdf_sapling(shared_secret, &ephem_public.into());
|
||||
|
||||
@@ -75,7 +81,7 @@ impl Note {
|
||||
|
||||
pub struct EncryptedNote {
|
||||
ciphertext: [u8; ENC_CIPHERTEXT_SIZE],
|
||||
ephem_public: jubjub::SubgroupPoint,
|
||||
ephem_public: pasta::Ep,
|
||||
}
|
||||
|
||||
impl Encodable for EncryptedNote {
|
||||
@@ -100,7 +106,7 @@ impl Decodable for EncryptedNote {
|
||||
}
|
||||
|
||||
impl EncryptedNote {
|
||||
pub fn decrypt(&self, secret: &jubjub::Fr) -> Result<Note> {
|
||||
pub fn decrypt(&self, secret: &pasta::Fq) -> Result<Note> {
|
||||
let shared_secret = sapling_ka_agree(secret, &self.ephem_public.into());
|
||||
let key = kdf_sapling(shared_secret, &self.ephem_public.into());
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use std::io;
|
||||
|
||||
use crate::{
|
||||
error::Result,
|
||||
serial::{Decodable, Encodable},
|
||||
Result,
|
||||
};
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Nullifier {
|
||||
pub repr: [u8; 32],
|
||||
@@ -30,4 +29,3 @@ impl Decodable for Nullifier {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
use group::GroupEncoding;
|
||||
use std::io;
|
||||
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::{arithmetic::FieldExt, group::GroupEncoding};
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::serial::{Decodable, Encodable, ReadExt, WriteExt};
|
||||
|
||||
impl Encodable for jubjub::Fr {
|
||||
impl Encodable for pasta::Fp {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for jubjub::Fr {
|
||||
impl Decodable for pasta::Fp {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
@@ -24,14 +26,34 @@ impl Decodable for jubjub::Fr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for jubjub::SubgroupPoint {
|
||||
impl Encodable for pasta::Fq {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for jubjub::SubgroupPoint {
|
||||
impl Decodable for pasta::Fq {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = Self::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for pasta::Ep {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pasta::Ep {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
84
src/crypto/proof.rs
Normal file
84
src/crypto/proof.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::vesta;
|
||||
|
||||
use halo2::{
|
||||
plonk,
|
||||
plonk::Circuit,
|
||||
poly::commitment,
|
||||
transcript::{Blake2bRead, Blake2bWrite},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VerifyingKey {
|
||||
pub params: commitment::Params<vesta::Affine>,
|
||||
pub vk: plonk::VerifyingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl VerifyingKey {
|
||||
pub fn build(k: u32, c: impl Circuit<pasta::Fp>) -> Self {
|
||||
let params = commitment::Params::new(k);
|
||||
let vk = plonk::keygen_vk(¶ms, &c).unwrap();
|
||||
VerifyingKey { params, vk }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProvingKey {
|
||||
pub params: commitment::Params<vesta::Affine>,
|
||||
pub pk: plonk::ProvingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl ProvingKey {
|
||||
pub fn build(k: u32, c: impl Circuit<pasta::Fp>) -> Self {
|
||||
let params = commitment::Params::new(k);
|
||||
let vk = plonk::keygen_vk(¶ms, &c).unwrap();
|
||||
let pk = plonk::keygen_pk(¶ms, vk, &c).unwrap();
|
||||
ProvingKey { params, pk }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Proof(Vec<u8>);
|
||||
|
||||
impl AsRef<[u8]> for Proof {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Proof {
|
||||
pub fn create(
|
||||
pk: &ProvingKey,
|
||||
circuits: &[impl Circuit<pasta::Fp>],
|
||||
pubinputs: &[pasta::Fp],
|
||||
) -> Result<Self, plonk::Error> {
|
||||
let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
|
||||
|
||||
plonk::create_proof(
|
||||
&pk.params,
|
||||
&pk.pk,
|
||||
circuits,
|
||||
&[&[pubinputs]],
|
||||
&mut transcript,
|
||||
)?;
|
||||
|
||||
Ok(Proof(transcript.finalize()))
|
||||
}
|
||||
|
||||
pub fn verify(&self, vk: &VerifyingKey, pubinputs: &[pasta::Fp]) -> Result<(), plonk::Error> {
|
||||
let msm = vk.params.empty_msm();
|
||||
let mut transcript = Blake2bRead::init(&self.0[..]);
|
||||
let guard = plonk::verify_proof(&vk.params, &vk.vk, msm, &[&[pubinputs]], &mut transcript)?;
|
||||
let msm = guard.clone().use_challenges();
|
||||
|
||||
if msm.eval() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(plonk::Error::ConstraintSystemFailure)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(bytes: Vec<u8>) -> Self {
|
||||
Proof(bytes)
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,45 @@
|
||||
use ff::Field;
|
||||
use group::GroupEncoding;
|
||||
use rand::rngs::OsRng;
|
||||
use std::io;
|
||||
|
||||
use super::util::hash_to_scalar;
|
||||
use halo2_gadgets::ecc::FixedPoints;
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::{arithmetic::Field, group::GroupEncoding};
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use super::{
|
||||
constants::{OrchardFixedBases, DRK_SCHNORR_DOMAIN},
|
||||
util::hash_to_scalar,
|
||||
};
|
||||
use crate::error::Result;
|
||||
use crate::serial::{Decodable, Encodable};
|
||||
|
||||
pub struct SecretKey(pub jubjub::Fr);
|
||||
pub struct SecretKey(pub pasta::Fq);
|
||||
|
||||
impl SecretKey {
|
||||
pub fn random() -> Self {
|
||||
Self(jubjub::Fr::random(&mut OsRng))
|
||||
Self(pasta::Fq::random(&mut OsRng))
|
||||
}
|
||||
|
||||
pub fn sign(&self, message: &[u8]) -> Signature {
|
||||
let mask = jubjub::Fr::random(&mut OsRng);
|
||||
let commit = zcash_primitives::constants::SPENDING_KEY_GENERATOR * mask;
|
||||
|
||||
let challenge = hash_to_scalar(b"DarkFi_Schnorr", &commit.to_bytes(), message);
|
||||
let mask = pasta::Fq::random(&mut OsRng);
|
||||
let commit = OrchardFixedBases::SpendAuthG.generator() * mask;
|
||||
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
|
||||
let response = mask + challenge * self.0;
|
||||
|
||||
Signature { commit, response }
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> PublicKey {
|
||||
let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * self.0;
|
||||
let public = OrchardFixedBases::SpendAuthG.generator() * self.0;
|
||||
PublicKey(public)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PublicKey(pub jubjub::SubgroupPoint);
|
||||
pub struct PublicKey(pub pasta::Ep);
|
||||
|
||||
pub struct Signature {
|
||||
commit: jubjub::SubgroupPoint,
|
||||
response: jubjub::Fr,
|
||||
commit: pasta::Ep,
|
||||
response: pasta::Fq,
|
||||
}
|
||||
|
||||
impl Encodable for Signature {
|
||||
@@ -58,9 +62,8 @@ impl Decodable for Signature {
|
||||
|
||||
impl PublicKey {
|
||||
pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
|
||||
let challenge = hash_to_scalar(b"DarkFi_Schnorr", &signature.commit.to_bytes(), message);
|
||||
zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature.response
|
||||
- self.0 * challenge
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
|
||||
OrchardFixedBases::SpendAuthG.generator() * signature.response - self.0 * challenge
|
||||
== signature.commit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
//! Type aliases used in the codebase.
|
||||
// Helpful for changing the curve and crypto we're using.
|
||||
use halo2_gadgets::ecc::FixedPoints;
|
||||
use pasta_curves as pasta;
|
||||
|
||||
pub type PublicKey = jubjub::SubgroupPoint;
|
||||
use super::{constants::OrchardFixedBases, util::mod_r_p};
|
||||
|
||||
pub type SecretKey = jubjub::Fr;
|
||||
pub type DrkTokenId = pasta::Fp;
|
||||
pub type DrkSerial = pasta::Fp;
|
||||
pub type DrkCoinBlind = pasta::Fp;
|
||||
|
||||
pub fn derive_publickey(secret: SecretKey) -> PublicKey {
|
||||
zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret
|
||||
pub type DrkValueBlind = pasta::Fq;
|
||||
pub type DrkValueCommit = pasta::Ep;
|
||||
|
||||
pub type DrkPublicKey = pasta::Ep;
|
||||
pub type DrkSecretKey = pasta::Fp;
|
||||
|
||||
pub fn derive_publickey(s: DrkSecretKey) -> DrkPublicKey {
|
||||
let skrt = mod_r_p(s);
|
||||
OrchardFixedBases::SpendAuthG.generator() * skrt
|
||||
}
|
||||
|
||||
pub type TokenId = jubjub::Fr;
|
||||
|
||||
pub type NullifierSerial = jubjub::Fr;
|
||||
|
||||
pub type CoinBlind = jubjub::Fr;
|
||||
|
||||
pub type ValueCommitBlind = jubjub::Fr;
|
||||
|
||||
pub type TokenCommitBlind = jubjub::Fr;
|
||||
|
||||
@@ -1,9 +1,35 @@
|
||||
use blake2b_simd::Params;
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveExt, FieldExt},
|
||||
group::ff::PrimeField,
|
||||
};
|
||||
|
||||
pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> jubjub::Fr {
|
||||
use super::constants::fixed_bases::{
|
||||
VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES,
|
||||
};
|
||||
|
||||
pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> pasta::Fq {
|
||||
let mut hasher = Params::new().hash_length(64).personal(persona).to_state();
|
||||
hasher.update(a);
|
||||
hasher.update(b);
|
||||
let ret = hasher.finalize();
|
||||
jubjub::Fr::from_bytes_wide(ret.as_array())
|
||||
pasta::Fq::from_bytes_wide(ret.as_array())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn pedersen_commitment_scalar(value: pasta::Fq, blind: pasta::Fq) -> pasta::Ep {
|
||||
let hasher = pasta::Ep::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
|
||||
let V = hasher(&VALUE_COMMITMENT_V_BYTES);
|
||||
let R = hasher(&VALUE_COMMITMENT_R_BYTES);
|
||||
|
||||
V * value + R * blind
|
||||
}
|
||||
|
||||
pub fn pedersen_commitment_u64(value: u64, blind: pasta::Fq) -> pasta::Ep {
|
||||
pedersen_commitment_scalar(pasta::Fq::from_u64(value), blind)
|
||||
}
|
||||
|
||||
pub fn mod_r_p(x: pasta::Fp) -> pasta::Fq {
|
||||
pasta::Fq::from_repr(x.to_repr()).unwrap()
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod proof;
|
||||
pub mod types;
|
||||
pub mod util;
|
||||
@@ -1,252 +0,0 @@
|
||||
use std::time::Instant;
|
||||
|
||||
use bellman::{gadgets::multipack, groth16, Circuit};
|
||||
use blake2s_simd::Params as Blake2sParams;
|
||||
use bls12_381::Bls12;
|
||||
use ff::PrimeField;
|
||||
use group::{Curve, GroupEncoding};
|
||||
use log::debug;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use crate::circuit::{mint_contract::MintContract, spend_contract::SpendContract};
|
||||
use crate::crypto::merkle_node::{merkle_hash, MerkleNode, SAPLING_COMMITMENT_TREE_DEPTH};
|
||||
use crate::crypto::nullifier::Nullifier;
|
||||
use crate::crypto_new::{
|
||||
types::*,
|
||||
util::{pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
};
|
||||
use crate::{Error, Result};
|
||||
|
||||
pub struct Proof(groth16::Proof<Bls12>);
|
||||
|
||||
impl Proof {
|
||||
pub fn create(
|
||||
pk: &groth16::Parameters<Bls12>,
|
||||
circuits: impl Circuit<bls12_381::Scalar>,
|
||||
_pubinputs: &[bls12_381::Scalar],
|
||||
) -> Result<Self> {
|
||||
let start = Instant::now();
|
||||
let proof = groth16::create_random_proof(circuits, pk, &mut OsRng).unwrap();
|
||||
debug!("Prove: [{:?}]", start.elapsed());
|
||||
Ok(Proof(proof))
|
||||
}
|
||||
|
||||
pub fn verify(
|
||||
&self,
|
||||
vk: &groth16::PreparedVerifyingKey<Bls12>,
|
||||
pubinputs: &[bls12_381::Scalar],
|
||||
) -> Result<()> {
|
||||
let start = Instant::now();
|
||||
let result = groth16::verify_proof(vk, &self.0, pubinputs);
|
||||
debug!("Verify: [{:?}]", start);
|
||||
if result.is_ok() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::VerifyFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const MINT_COIN0_OFFSET: usize = 0;
|
||||
pub const MINT_COIN1_OFFSET: usize = 1;
|
||||
pub const MINT_VALCOMX_OFFSET: usize = 2;
|
||||
pub const MINT_VALCOMY_OFFSET: usize = 3;
|
||||
pub const MINT_TOKCOMX_OFFSET: usize = 4;
|
||||
pub const MINT_TOKCOMY_OFFSET: usize = 5;
|
||||
pub const MINT_PUBINPUTS_LEN: usize = 6;
|
||||
|
||||
pub fn setup_mint_prover() -> groth16::Parameters<Bls12> {
|
||||
debug!("Mint: Making random params...");
|
||||
let start = Instant::now();
|
||||
let params = {
|
||||
let c = MintContract::default();
|
||||
groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
|
||||
};
|
||||
debug!("Setup: [{:?}]", start.elapsed());
|
||||
params
|
||||
}
|
||||
|
||||
pub fn create_mint_proof(
|
||||
params: &groth16::Parameters<Bls12>,
|
||||
value: u64,
|
||||
token_id: DrkTokenId,
|
||||
randomness_value: DrkValueBlind,
|
||||
randomness_token: DrkTokenBlind,
|
||||
serial: DrkSerial,
|
||||
randomness_coin: DrkCoinBlind,
|
||||
public: DrkPublicKey,
|
||||
) -> Result<(Proof, Vec<DrkPublicInput>)> {
|
||||
let mut public_inputs = vec![DrkPublicInput::zero(); MINT_PUBINPUTS_LEN];
|
||||
|
||||
let mut coin = [0; 32];
|
||||
coin.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&public.to_bytes())
|
||||
.update(&value.to_le_bytes())
|
||||
.update(&token_id.to_bytes())
|
||||
.update(&serial.to_bytes())
|
||||
.update(&randomness_coin.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
);
|
||||
|
||||
let hash = multipack::bytes_to_bits_le(&coin);
|
||||
let hash = multipack::compute_multipacking(&hash);
|
||||
assert_eq!(hash.len(), 2);
|
||||
public_inputs[MINT_COIN0_OFFSET] = hash[0];
|
||||
public_inputs[MINT_COIN1_OFFSET] = hash[1];
|
||||
|
||||
let value_commit = pedersen_commitment_u64(value, randomness_value);
|
||||
let affine = jubjub::ExtendedPoint::from(value_commit).to_affine();
|
||||
public_inputs[MINT_VALCOMX_OFFSET] = affine.get_u();
|
||||
public_inputs[MINT_VALCOMY_OFFSET] = affine.get_v();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(token_id, randomness_token);
|
||||
let affine = jubjub::ExtendedPoint::from(token_commit).to_affine();
|
||||
public_inputs[MINT_TOKCOMX_OFFSET] = affine.get_u();
|
||||
public_inputs[MINT_TOKCOMY_OFFSET] = affine.get_v();
|
||||
|
||||
let c = MintContract {
|
||||
value: Some(value),
|
||||
token_id: Some(token_id),
|
||||
randomness_value: Some(randomness_value),
|
||||
randomness_token: Some(randomness_token),
|
||||
serial: Some(serial),
|
||||
randomness_coin: Some(randomness_coin),
|
||||
public: Some(public),
|
||||
};
|
||||
|
||||
let proof = Proof::create(params, c, &public_inputs)?;
|
||||
Ok((proof, public_inputs))
|
||||
}
|
||||
|
||||
pub const SPEND_VALCOMX_OFFSET: usize = 0;
|
||||
pub const SPEND_VALCOMY_OFFSET: usize = 1;
|
||||
pub const SPEND_TOKCOMX_OFFSET: usize = 2;
|
||||
pub const SPEND_TOKCOMY_OFFSET: usize = 3;
|
||||
pub const SPEND_NULLIFIER0_OFFSET: usize = 4;
|
||||
pub const SPEND_NULLIFIER1_OFFSET: usize = 5;
|
||||
pub const SPEND_MERKLEROOT_OFFSET: usize = 6;
|
||||
pub const SPEND_SIGPUBX_OFFSET: usize = 7;
|
||||
pub const SPEND_SIGPUBY_OFFSET: usize = 8;
|
||||
pub const SPEND_PUBINPUTS_LEN: usize = 9;
|
||||
|
||||
pub fn setup_spend_prover() -> groth16::Parameters<Bls12> {
|
||||
debug!("Spend: Making random params...");
|
||||
let start = Instant::now();
|
||||
let params = {
|
||||
let c = SpendContract::default();
|
||||
groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
|
||||
};
|
||||
debug!("Setup: [{:?}]", start.elapsed());
|
||||
params
|
||||
}
|
||||
|
||||
pub fn create_spend_proof(
|
||||
params: &groth16::Parameters<Bls12>,
|
||||
value: u64,
|
||||
token_id: DrkTokenId,
|
||||
randomness_value: DrkValueBlind,
|
||||
randomness_token: DrkTokenBlind,
|
||||
serial: DrkSerial,
|
||||
randomness_coin: DrkCoinBlind,
|
||||
secret: DrkSecretKey,
|
||||
merkle_path: [(bls12_381::Scalar, bool); SAPLING_COMMITMENT_TREE_DEPTH],
|
||||
signature_secret: DrkSecretKey,
|
||||
) -> Result<(Proof, Vec<DrkPublicInput>)> {
|
||||
let mut public_inputs = vec![DrkPublicInput::zero(); SPEND_PUBINPUTS_LEN];
|
||||
|
||||
let value_commit = pedersen_commitment_u64(value, randomness_value);
|
||||
let affine = jubjub::ExtendedPoint::from(value_commit).to_affine();
|
||||
public_inputs[SPEND_VALCOMX_OFFSET] = affine.get_u();
|
||||
public_inputs[SPEND_VALCOMY_OFFSET] = affine.get_v();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(token_id, randomness_token);
|
||||
let affine = jubjub::ExtendedPoint::from(token_commit).to_affine();
|
||||
public_inputs[SPEND_TOKCOMX_OFFSET] = affine.get_u();
|
||||
public_inputs[SPEND_TOKCOMY_OFFSET] = affine.get_v();
|
||||
|
||||
let mut nullifier = [0; 32];
|
||||
nullifier.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(zcash_primitives::constants::PRF_NF_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&secret.to_bytes())
|
||||
.update(&serial.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
);
|
||||
let nullifier = Nullifier::new(nullifier);
|
||||
let hash = multipack::bytes_to_bits_le(&nullifier.repr);
|
||||
let hash = multipack::compute_multipacking(&hash);
|
||||
assert_eq!(hash.len(), 2);
|
||||
public_inputs[SPEND_NULLIFIER0_OFFSET] = hash[0];
|
||||
public_inputs[SPEND_NULLIFIER1_OFFSET] = hash[1];
|
||||
|
||||
let sig_pub = zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret;
|
||||
let affine = jubjub::ExtendedPoint::from(sig_pub).to_affine();
|
||||
public_inputs[SPEND_SIGPUBX_OFFSET] = affine.get_u();
|
||||
public_inputs[SPEND_TOKCOMY_OFFSET] = affine.get_v();
|
||||
|
||||
let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
|
||||
|
||||
let mut coin = [0; 32];
|
||||
coin.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&public.to_bytes())
|
||||
.update(&value.to_le_bytes())
|
||||
.update(&token_id.to_bytes())
|
||||
.update(&serial.to_bytes())
|
||||
.update(&randomness_coin.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
);
|
||||
|
||||
use zcash_primitives::pedersen_hash::pedersen_hash;
|
||||
use zcash_primitives::pedersen_hash::Personalization::NoteCommitment;
|
||||
let merkle_root = jubjub::ExtendedPoint::from(pedersen_hash(
|
||||
NoteCommitment,
|
||||
multipack::bytes_to_bits_le(&coin),
|
||||
));
|
||||
let affine = merkle_root.to_affine();
|
||||
let mut merkle_root = affine.get_u();
|
||||
|
||||
let mut branch: [_; SAPLING_COMMITMENT_TREE_DEPTH] = Default::default();
|
||||
let mut is_right: [_; SAPLING_COMMITMENT_TREE_DEPTH] = Default::default();
|
||||
|
||||
for (i, (branch_i, is_right_i)) in merkle_path.iter().enumerate() {
|
||||
branch[i] = Some(*branch_i);
|
||||
is_right[i] = Some(*is_right_i);
|
||||
if *is_right_i {
|
||||
merkle_root = merkle_hash(i, &branch_i.to_repr(), &merkle_root.to_repr());
|
||||
} else {
|
||||
merkle_root = merkle_hash(i, &merkle_root.to_repr(), &branch_i.to_repr());
|
||||
}
|
||||
}
|
||||
|
||||
let merkle_root = MerkleNode::new(merkle_root.to_repr());
|
||||
public_inputs[SPEND_MERKLEROOT_OFFSET] = merkle_root.into();
|
||||
|
||||
let c = SpendContract {
|
||||
value: Some(value),
|
||||
token_id: Some(token_id),
|
||||
randomness_value: Some(randomness_value),
|
||||
randomness_token: Some(randomness_token),
|
||||
serial: Some(serial),
|
||||
randomness_coin: Some(randomness_coin),
|
||||
secret: Some(secret),
|
||||
branch,
|
||||
is_right,
|
||||
signature_secret: Some(signature_secret),
|
||||
};
|
||||
|
||||
let proof = Proof::create(params, c, &public_inputs)?;
|
||||
Ok((proof, public_inputs))
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
pub type DrkValue = jubjub::Fr;
|
||||
pub type DrkTokenId = jubjub::Fr;
|
||||
pub type DrkValueBlind = jubjub::Fr;
|
||||
pub type DrkTokenBlind = jubjub::Fr;
|
||||
|
||||
pub type DrkValueCommit = jubjub::SubgroupPoint;
|
||||
|
||||
pub type DrkSerial = jubjub::Fr;
|
||||
pub type DrkCoinBlind = jubjub::Fr;
|
||||
pub type DrkPublicKey = jubjub::SubgroupPoint;
|
||||
pub type DrkSecretKey = jubjub::Fr;
|
||||
|
||||
pub type DrkPublicInput = jubjub::Fq;
|
||||
@@ -1,13 +0,0 @@
|
||||
use crate::crypto_new::types::*;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn pedersen_commitment_scalar(value: DrkValue, blind: DrkValueBlind) -> DrkValueCommit {
|
||||
let V = zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR;
|
||||
let R = zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR;
|
||||
|
||||
V * value + R * blind
|
||||
}
|
||||
|
||||
pub fn pedersen_commitment_u64(value: u64, blind: DrkValueBlind) -> DrkValueCommit {
|
||||
pedersen_commitment_scalar(DrkValue::from(value), blind)
|
||||
}
|
||||
27
src/error.rs
27
src/error.rs
@@ -1,8 +1,7 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::client;
|
||||
use crate::state;
|
||||
use crate::vm::ZkVmError;
|
||||
//use crate::client;
|
||||
//use crate::state;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
@@ -43,6 +42,7 @@ pub enum Error {
|
||||
VmError,
|
||||
BadContract,
|
||||
Groth16Error,
|
||||
PlonkError,
|
||||
OperationFailed,
|
||||
NoteDecryptionFailed,
|
||||
VerifyFailed,
|
||||
@@ -117,6 +117,7 @@ impl fmt::Display for Error {
|
||||
Error::VmError => f.write_str("VM error"),
|
||||
Error::BadContract => f.write_str("Contract is poorly defined"),
|
||||
Error::Groth16Error => f.write_str("Groth16 error"),
|
||||
Error::PlonkError => f.write_str("Plonk error"),
|
||||
Error::RusqliteError(ref err) => write!(f, "Rusqlite error {}", err),
|
||||
Error::OperationFailed => f.write_str("Operation failed"),
|
||||
Error::ConnectFailed => f.write_str("Connection failed"),
|
||||
@@ -193,18 +194,6 @@ impl From<rusqlite::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ZkVmError> for Error {
|
||||
fn from(_err: ZkVmError) -> Error {
|
||||
Error::VmError
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bellman::SynthesisError> for Error {
|
||||
fn from(_err: bellman::SynthesisError) -> Error {
|
||||
Error::Groth16Error
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<async_channel::SendError<T>> for Error {
|
||||
fn from(_err: async_channel::SendError<T>) -> Error {
|
||||
Error::AsyncChannelSenderError
|
||||
@@ -277,6 +266,7 @@ impl From<std::str::Utf8Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl From<state::VerifyFailed> for Error {
|
||||
fn from(_err: state::VerifyFailed) -> Error {
|
||||
Error::VerifyFailed
|
||||
@@ -288,6 +278,7 @@ impl From<client::ClientFailed> for Error {
|
||||
Error::ClientFailed(err.to_string())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[cfg(feature = "btc")]
|
||||
impl From<crate::service::BtcFailed> for Error {
|
||||
@@ -345,3 +336,9 @@ impl From<tungstenite::Error> for Error {
|
||||
Error::TungsteniteError
|
||||
}
|
||||
}
|
||||
|
||||
impl From<halo2::plonk::Error> for Error {
|
||||
fn from(_err: halo2::plonk::Error) -> Error {
|
||||
Error::PlonkError
|
||||
}
|
||||
}
|
||||
|
||||
28
src/lib.rs
28
src/lib.rs
@@ -1,32 +1,27 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use bellman::groth16;
|
||||
use bls12_381::{Bls12, Scalar};
|
||||
|
||||
pub mod async_serial;
|
||||
pub mod blockchain;
|
||||
pub mod bls_extensions;
|
||||
// pub mod bls_extensions;
|
||||
pub mod circuit;
|
||||
pub mod cli;
|
||||
pub mod client;
|
||||
// pub mod client;
|
||||
pub mod crypto;
|
||||
pub mod crypto_new;
|
||||
pub mod endian;
|
||||
pub mod error;
|
||||
pub mod net;
|
||||
pub mod rpc;
|
||||
pub mod serial;
|
||||
pub mod service;
|
||||
pub mod state;
|
||||
// pub mod service;
|
||||
// pub mod state;
|
||||
pub mod system;
|
||||
pub mod tx;
|
||||
pub mod util;
|
||||
pub mod vm;
|
||||
pub mod vm_serial;
|
||||
pub mod wallet;
|
||||
// pub mod tx;
|
||||
// pub mod util;
|
||||
// pub mod vm;
|
||||
// pub mod vm_serial;
|
||||
// pub mod wallet;
|
||||
|
||||
pub use crate::bls_extensions::BlsStringConversion;
|
||||
pub use crate::error::{Error, Result};
|
||||
/*
|
||||
pub use crate::bls_extensions::BlsStringConversion;
|
||||
pub use crate::net::p2p::P2p;
|
||||
pub use crate::serial::{Decodable, Encodable};
|
||||
pub use crate::vm::{
|
||||
@@ -128,3 +123,4 @@ impl ZkContract {
|
||||
self.vm.verify(&proof.proof, &public)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -3,8 +3,6 @@ use std::io::{Cursor, Read, Write};
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::{io, mem};
|
||||
|
||||
use bls12_381 as bls;
|
||||
|
||||
use crate::endian;
|
||||
use crate::error::{Error, Result};
|
||||
|
||||
@@ -461,7 +459,7 @@ macro_rules! impl_vec {
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_vec!(bls::Scalar);
|
||||
|
||||
impl_vec!(SocketAddr);
|
||||
impl_vec!([u8; 32]);
|
||||
|
||||
@@ -557,29 +555,26 @@ impl Decodable for Box<[u8]> {
|
||||
|
||||
// Tuples
|
||||
macro_rules! tuple_encode {
|
||||
($($x:ident),*) => (
|
||||
impl <$($x: Encodable),*> Encodable for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize> {
|
||||
let &($(ref $x),*) = self;
|
||||
let mut len = 0;
|
||||
$(len += $x.encode(&mut s)?;)*
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
($($x:ident),*) => (
|
||||
impl <$($x: Encodable),*> Encodable for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
let &($(ref $x),*) = self;
|
||||
let mut len = 0;
|
||||
$(len += $x.encode(&mut s)?;)*
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($x: Decodable),*> Decodable for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
Ok(($({let $x = Decodable::decode(&mut d)?; $x }),*))
|
||||
}
|
||||
}
|
||||
);
|
||||
impl<$($x: Decodable),*> Decodable for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
Ok(($({let $x = Decodable::decode(&mut d)?; $x }),*))
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
tuple_encode!(T0, T1);
|
||||
|
||||
@@ -1,37 +1,33 @@
|
||||
use async_std::sync::Arc;
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use ff::Field;
|
||||
use log::*;
|
||||
use async_std::sync::Arc;
|
||||
use log::debug;
|
||||
use pasta_curves::arithmetic::Field;
|
||||
use rand::rngs::OsRng;
|
||||
use rusqlite::{named_params, params, Connection};
|
||||
|
||||
use super::WalletApi;
|
||||
use crate::client::ClientFailed;
|
||||
use crate::crypto::{
|
||||
coin::Coin,
|
||||
merkle::IncrementalWitness,
|
||||
merkle_node::MerkleNode,
|
||||
note::Note,
|
||||
nullifier::Nullifier,
|
||||
types::{PublicKey, SecretKey, TokenId},
|
||||
OwnCoin, OwnCoins,
|
||||
use crate::{
|
||||
client::ClientFailed,
|
||||
crypto::{
|
||||
coin::Coin, merkle::IncrementalWitness, merkle_node::MerkleNode, note::Note,
|
||||
nullifier::Nullifier, types::*, OwnCoin, OwnCoins,
|
||||
},
|
||||
serial, Error, Result,
|
||||
};
|
||||
use crate::serial;
|
||||
use crate::{Error, Result};
|
||||
|
||||
pub type WalletPtr = Arc<WalletDb>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Keypair {
|
||||
pub public: PublicKey,
|
||||
pub private: SecretKey,
|
||||
pub public: DrkPublicKey,
|
||||
pub private: DrkSecretKey,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Balance {
|
||||
pub token_id: TokenId,
|
||||
pub token_id: DrkTokenId,
|
||||
pub value: u64,
|
||||
pub nullifier: Nullifier,
|
||||
}
|
||||
@@ -103,8 +99,8 @@ impl WalletDb {
|
||||
let mut stmt = conn.prepare("SELECT * FROM keys WHERE key_id > ?")?;
|
||||
let key_check = stmt.exists(params!["0"])?;
|
||||
if !key_check {
|
||||
let secret: SecretKey = SecretKey::random(&mut OsRng);
|
||||
let public: PublicKey = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
|
||||
let secret = DrkSecretKey::random(&mut OsRng);
|
||||
let public = derive_publickey(secret);
|
||||
self.put_keypair(&public, &secret)?;
|
||||
} else {
|
||||
debug!(target: "WALLETDB", "Keys already exist.");
|
||||
@@ -113,7 +109,7 @@ impl WalletDb {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn put_keypair(&self, key_public: &PublicKey, key_private: &SecretKey) -> Result<()> {
|
||||
pub fn put_keypair(&self, key_public: &DrkPublicKey, key_private: &DrkSecretKey) -> Result<()> {
|
||||
let conn = Connection::open(&self.path)?;
|
||||
|
||||
conn.pragma_update(None, "key", &self.password)?;
|
||||
@@ -141,8 +137,8 @@ impl WalletDb {
|
||||
let key = key?;
|
||||
let public = key.0;
|
||||
let private = key.1;
|
||||
let public: PublicKey = self.get_value_deserialized(public)?;
|
||||
let private: SecretKey = self.get_value_deserialized(private)?;
|
||||
let public: DrkPublicKey = self.get_value_deserialized(public)?;
|
||||
let private: DrkSecretKey = self.get_value_deserialized(private)?;
|
||||
keypairs.push(Keypair { public, private });
|
||||
}
|
||||
|
||||
@@ -195,7 +191,7 @@ impl WalletDb {
|
||||
};
|
||||
|
||||
let witness = self.get_value_deserialized(row.6)?;
|
||||
let secret: SecretKey = self.get_value_deserialized(row.7)?;
|
||||
let secret: DrkSecretKey = self.get_value_deserialized(row.7)?;
|
||||
let nullifier: Nullifier = self.get_value_deserialized(row.8)?;
|
||||
|
||||
let oc = OwnCoin {
|
||||
@@ -354,7 +350,7 @@ impl WalletDb {
|
||||
for row in rows {
|
||||
let row = row?;
|
||||
let value: u64 = row.0;
|
||||
let token_id: TokenId = self.get_value_deserialized(row.1)?;
|
||||
let token_id: DrkTokenId = self.get_value_deserialized(row.1)?;
|
||||
let nullifier: Nullifier = self.get_value_deserialized(row.2)?;
|
||||
balances.add(&Balance {
|
||||
token_id,
|
||||
@@ -366,7 +362,7 @@ impl WalletDb {
|
||||
Ok(balances)
|
||||
}
|
||||
|
||||
pub fn get_token_id(&self) -> Result<Vec<TokenId>> {
|
||||
pub fn get_token_id(&self) -> Result<Vec<DrkTokenId>> {
|
||||
debug!(target: "WALLETDB", "Get token ID...");
|
||||
let conn = Connection::open(&self.path)?;
|
||||
conn.pragma_update(None, "key", &self.password)?;
|
||||
@@ -387,7 +383,7 @@ impl WalletDb {
|
||||
Ok(token_ids)
|
||||
}
|
||||
|
||||
pub fn token_id_exists(&self, token_id: &TokenId) -> Result<bool> {
|
||||
pub fn token_id_exists(&self, token_id: &DrkTokenId) -> Result<bool> {
|
||||
debug!(target: "WALLETDB", "Check tokenID exists");
|
||||
let conn = Connection::open(&self.path)?;
|
||||
conn.pragma_update(None, "key", &self.password)?;
|
||||
@@ -444,12 +440,12 @@ mod tests {
|
||||
let wallet = WalletDb::new(&walletdb_path, password.clone())?;
|
||||
init_db(&walletdb_path, password)?;
|
||||
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let public = derive_publickey(secret);
|
||||
let secret = DrkSecretKey::random(&mut OsRng);
|
||||
let public = secret.derive_publickey();
|
||||
|
||||
wallet.put_keypair(&public, &secret)?;
|
||||
|
||||
let token_id = TokenId::random(&mut OsRng);
|
||||
let token_id = DrkTokenId::random(&mut OsRng);
|
||||
|
||||
let note = Note {
|
||||
serial: NullifierSerial::random(&mut OsRng),
|
||||
@@ -502,12 +498,12 @@ mod tests {
|
||||
let wallet = WalletDb::new(&walletdb_path, password.clone())?;
|
||||
init_db(&walletdb_path, password)?;
|
||||
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let public = derive_publickey(secret);
|
||||
let secret = DrkSecretKey::random(&mut OsRng);
|
||||
let public = secret.derive_publickey();
|
||||
|
||||
wallet.put_keypair(&public, &secret)?;
|
||||
|
||||
let token_id = TokenId::random(&mut OsRng);
|
||||
let token_id = DrkTokenId::random(&mut OsRng);
|
||||
|
||||
let note = Note {
|
||||
serial: NullifierSerial::random(&mut OsRng),
|
||||
@@ -557,8 +553,8 @@ mod tests {
|
||||
let wallet = WalletDb::new(&walletdb_path, password.clone())?;
|
||||
init_db(&walletdb_path, password)?;
|
||||
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let public = derive_publickey(secret);
|
||||
let secret = DrkSecretKey::random(&mut OsRng);
|
||||
let public = secret.derive_publickey();
|
||||
|
||||
wallet.put_keypair(&public, &secret)?;
|
||||
|
||||
@@ -579,15 +575,15 @@ mod tests {
|
||||
let wallet = WalletDb::new(&walletdb_path, password.clone())?;
|
||||
init_db(&walletdb_path, password)?;
|
||||
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let public = derive_publickey(secret);
|
||||
let secret = DrkSecretKey::random(&mut OsRng);
|
||||
let public = secret.derive_publickey();
|
||||
|
||||
wallet.put_keypair(&public, &secret)?;
|
||||
|
||||
let note = Note {
|
||||
serial: NullifierSerial::random(&mut OsRng),
|
||||
value: 110,
|
||||
token_id: TokenId::random(&mut OsRng),
|
||||
token_id: DrkTokenId::random(&mut OsRng),
|
||||
coin_blind: CoinBlind::random(&mut OsRng),
|
||||
valcom_blind: ValueCommitBlind::random(&mut OsRng),
|
||||
};
|
||||
@@ -650,8 +646,8 @@ mod tests {
|
||||
let wallet = WalletDb::new(&walletdb_path, password.clone())?;
|
||||
init_db(&walletdb_path, password)?;
|
||||
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let public = derive_publickey(secret);
|
||||
let secret = DrkSecretKey::random(&mut OsRng);
|
||||
let public = secret.derive_publickey();
|
||||
|
||||
wallet.put_keypair(&public, &secret)?;
|
||||
|
||||
@@ -660,7 +656,7 @@ mod tests {
|
||||
let note = Note {
|
||||
serial: NullifierSerial::random(&mut OsRng),
|
||||
value: 110,
|
||||
token_id: TokenId::random(&mut OsRng),
|
||||
token_id: DrkTokenId::random(&mut OsRng),
|
||||
coin_blind: CoinBlind::random(&mut OsRng),
|
||||
valcom_blind: ValueCommitBlind::random(&mut OsRng),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user