From d5b6b9aa1ea247201c555a7d2da1d241fe7b57fc Mon Sep 17 00:00:00 2001 From: str4d Date: Sat, 19 May 2018 07:46:38 +1200 Subject: [PATCH 001/105] Test note nullifier in key component test vectors --- librustzcash/src/tests/key_components.rs | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/librustzcash/src/tests/key_components.rs b/librustzcash/src/tests/key_components.rs index d63c4d4..a31a9a0 100644 --- a/librustzcash/src/tests/key_components.rs +++ b/librustzcash/src/tests/key_components.rs @@ -27,6 +27,8 @@ fn key_components() { note_v: u64, note_r: [u8; 32], note_cm: [u8; 32], + note_pos: u64, + note_nf: [u8; 32], }; // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_key_components.py @@ -86,6 +88,12 @@ fn key_components() { 0x18, 0x50, 0xc9, 0xfe, 0xd4, 0x4f, 0xce, 0x08, 0x06, 0x27, 0x8f, 0x08, 0x3e, 0xf2, 0xdd, 0x07, 0x64, 0x39, ], + note_pos: 0, + note_nf: [ + 0x44, 0xfa, 0xd6, 0x56, 0x4f, 0xfd, 0xec, 0x9f, 0xa1, 0x9c, 0x43, 0xa2, 0x8f, 0x86, + 0x1d, 0x5e, 0xbf, 0x60, 0x23, 0x46, 0x00, 0x7d, 0xe7, 0x62, 0x67, 0xd9, 0x75, 0x27, + 0x47, 0xab, 0x40, 0x63, + ], }, TestVector { sk: [ @@ -142,6 +150,12 @@ fn key_components() { 0x89, 0xe1, 0x0e, 0x26, 0x6b, 0xcf, 0xa3, 0x1c, 0x31, 0xb2, 0x9a, 0x53, 0xae, 0x72, 0xca, 0xd4, 0x69, 0x50, ], + note_pos: 763714296, + note_nf: [ + 0x67, 0x9e, 0xb0, 0xc3, 0xa7, 0x57, 0xe2, 0xae, 0x83, 0xcd, 0xb4, 0x2a, 0x1a, 0xb2, + 0x59, 0xd7, 0x83, 0x88, 0x31, 0x54, 0x19, 0xad, 0xc7, 0x1d, 0x2e, 0x37, 0x63, 0x17, + 0x4c, 0x2e, 0x9d, 0x93, + ], }, TestVector { sk: [ @@ -198,6 +212,12 @@ fn key_components() { 0xb7, 0x40, 0x82, 0x96, 0x66, 0x17, 0x70, 0xb1, 0x01, 0xb0, 0xaa, 0x87, 0x83, 0x9f, 0x4e, 0x55, 0xf1, 0x51, ], + note_pos: 1527428592, + note_nf: [ + 0xe9, 0x8f, 0x6a, 0x8f, 0x34, 0xff, 0x49, 0x80, 0x59, 0xb3, 0xc7, 0x31, 0xb9, 0x1f, + 0x45, 0x11, 0x08, 0xc4, 0x95, 0x4d, 0x91, 0x94, 0x84, 0x36, 0x1c, 0xf9, 0xb4, 0x8f, + 0x59, 0xae, 0x1d, 0x14, + ], }, TestVector { sk: [ @@ -254,6 +274,12 @@ fn key_components() { 0xbd, 0x10, 0x5d, 0x88, 0x39, 0x21, 0x2e, 0x0d, 0x16, 0x44, 0xb9, 0xd5, 0x5c, 0xaa, 0x60, 0xd1, 0x9b, 0x6c, ], + note_pos: 2291142888, + note_nf: [ + 0x55, 0x47, 0xaa, 0x12, 0xff, 0x80, 0xa6, 0xb3, 0x30, 0x4e, 0x3b, 0x05, 0x86, 0x56, + 0x47, 0x2a, 0xbd, 0x2c, 0x81, 0x83, 0xb5, 0x9d, 0x07, 0x37, 0xb9, 0x3c, 0xee, 0x75, + 0x8b, 0xec, 0x47, 0xa1, + ], }, TestVector { sk: [ @@ -310,6 +336,12 @@ fn key_components() { 0xcf, 0x1e, 0x67, 0x15, 0xbf, 0xe7, 0x0b, 0x63, 0x2d, 0x04, 0x4b, 0x26, 0xfb, 0x2b, 0xc7, 0x1b, 0x7f, 0x36, ], + note_pos: 3054857184, + note_nf: [ + 0x8a, 0x9a, 0xbd, 0xa3, 0xd4, 0xef, 0x85, 0xca, 0xf2, 0x2b, 0xfa, 0xf2, 0xc4, 0x8f, + 0x62, 0x38, 0x2a, 0x73, 0xa1, 0x62, 0x4e, 0xb8, 0xeb, 0x2b, 0xd0, 0x0d, 0x27, 0x03, + 0x01, 0xbf, 0x3d, 0x13, + ], }, TestVector { sk: [ @@ -366,6 +398,12 @@ fn key_components() { 0x1d, 0x74, 0xc5, 0xbc, 0xf2, 0xe1, 0xef, 0x95, 0x66, 0x90, 0x44, 0x73, 0x01, 0x69, 0xde, 0x1a, 0x5b, 0x4c, ], + note_pos: 3818571480, + note_nf: [ + 0x33, 0x2a, 0xd9, 0x9e, 0xb9, 0xe9, 0x77, 0xeb, 0x62, 0x7a, 0x12, 0x2d, 0xbf, 0xb2, + 0xf2, 0x5f, 0xe5, 0x88, 0xe5, 0x97, 0x75, 0x3e, 0xc5, 0x58, 0x0f, 0xf2, 0xbe, 0x20, + 0xb6, 0xc9, 0xa7, 0xe1, + ], }, TestVector { sk: [ @@ -422,6 +460,12 @@ fn key_components() { 0x90, 0xb6, 0xe0, 0xf2, 0xf4, 0xbf, 0x4e, 0xc4, 0xa0, 0xdb, 0x5b, 0xbc, 0xcb, 0x5b, 0x78, 0x3a, 0x1e, 0x55, ], + note_pos: 287318480, + note_nf: [ + 0xfc, 0x74, 0xcd, 0x0e, 0x4b, 0xe0, 0x49, 0x57, 0xb1, 0x96, 0xcf, 0x87, 0x34, 0xae, + 0x99, 0x23, 0x96, 0xaf, 0x4c, 0xfa, 0x8f, 0xec, 0xbb, 0x86, 0xf9, 0x61, 0xe6, 0xb4, + 0x07, 0xd5, 0x1e, 0x11, + ], }, TestVector { sk: [ @@ -478,6 +522,12 @@ fn key_components() { 0x60, 0xa0, 0x06, 0xf8, 0x2b, 0xb7, 0xad, 0xcd, 0x75, 0x22, 0x3f, 0xa8, 0x59, 0x36, 0xf7, 0x8c, 0x2b, 0x23, ], + note_pos: 1051032776, + note_nf: [ + 0xd2, 0xe8, 0x87, 0xbd, 0x85, 0x4a, 0x80, 0x2b, 0xce, 0x85, 0x70, 0x53, 0x02, 0x0f, + 0x5d, 0x3e, 0x7c, 0x8a, 0xe5, 0x26, 0x7c, 0x5b, 0x65, 0x83, 0xb3, 0xd2, 0x12, 0xcc, + 0x8b, 0xb6, 0x98, 0x90, + ], }, TestVector { sk: [ @@ -534,6 +584,12 @@ fn key_components() { 0x23, 0x36, 0xc2, 0xa0, 0x5a, 0x08, 0x03, 0x23, 0x9b, 0x5b, 0x88, 0xfd, 0x92, 0x07, 0x8f, 0xea, 0x4d, 0x04, ], + note_pos: 1814747072, + note_nf: [ + 0xa8, 0x2f, 0x17, 0x50, 0xcc, 0x5b, 0x2b, 0xee, 0x64, 0x9a, 0x36, 0x5c, 0x04, 0x20, + 0xed, 0x87, 0x07, 0x5b, 0x88, 0x71, 0xfd, 0xa4, 0xa7, 0xf5, 0x84, 0x0d, 0x6b, 0xbe, + 0xb1, 0x7c, 0xd6, 0x20, + ], }, TestVector { sk: [ @@ -590,6 +646,12 @@ fn key_components() { 0x64, 0x41, 0x9b, 0x0e, 0x55, 0x0a, 0xbb, 0xcb, 0x8e, 0x2b, 0xcb, 0xda, 0x8b, 0x63, 0xe4, 0x1d, 0xeb, 0x37, ], + note_pos: 2578461368, + note_nf: [ + 0x65, 0x36, 0x74, 0x87, 0x3b, 0x3c, 0x67, 0x0c, 0x58, 0x85, 0x84, 0x73, 0xe7, 0xfe, + 0x72, 0x19, 0x72, 0xfb, 0x96, 0xe2, 0x15, 0xb8, 0x73, 0x77, 0xa1, 0x7c, 0xa3, 0x71, + 0x0d, 0x93, 0xc9, 0xe9, + ], }, ]; @@ -662,5 +724,7 @@ fn key_components() { note.cm(&JUBJUB).into_repr().write_le(&mut vec).unwrap(); assert_eq!(&vec, &tv.note_cm); } + + assert_eq!(note.nf(&fvk, tv.note_pos, &JUBJUB), tv.note_nf); } } From 999dcbfcab0171678824f775bdfad87d7592cea0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 4 Jun 2019 13:15:12 +0100 Subject: [PATCH 002/105] Migrate to blake2b_simd and blake2s_simd crates The primary reason for migrating is that these crates provide APIs for setting the personalisation string. This enables us to depend solely on published crates, and thus publish our own crates. The SIMD implementations are ported from libsodium. Closes #67. --- Cargo.lock | 43 ++++++--- librustzcash/Cargo.toml | 6 +- librustzcash/src/equihash.rs | 15 +-- librustzcash/src/rustzcash.rs | 10 +- sapling-crypto/Cargo.toml | 6 +- sapling-crypto/src/circuit/blake2s.rs | 4 +- sapling-crypto/src/circuit/test/mod.rs | 6 +- sapling-crypto/src/group_hash.rs | 16 ++-- sapling-crypto/src/lib.rs | 3 +- sapling-crypto/src/primitives/mod.rs | 21 ++-- sapling-crypto/src/util.rs | 4 +- zcash_primitives/Cargo.toml | 5 +- zcash_primitives/src/keys.rs | 13 ++- zcash_primitives/src/lib.rs | 2 +- zcash_primitives/src/note_encryption.rs | 20 ++-- zcash_primitives/src/transaction/sighash.rs | 100 +++++++++++--------- zcash_primitives/src/zip32.rs | 14 ++- zcash_proofs/Cargo.toml | 5 +- zcash_proofs/src/hashreader.rs | 6 +- zcash_proofs/src/lib.rs | 2 +- 20 files changed, 172 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34b20d2..ab8b628 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,14 @@ dependencies = [ "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" -version = "0.4.7" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -70,12 +75,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9#7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" +name = "blake2b_simd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "blake2s_simd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -292,7 +307,8 @@ name = "librustzcash" version = "0.1.0" dependencies = [ "bellman 0.1.0", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -435,7 +451,8 @@ name = "sapling-crypto" version = "0.0.1" dependencies = [ "bellman 0.1.0", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", @@ -529,7 +546,7 @@ name = "zcash_primitives" version = "0.0.0" dependencies = [ "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", @@ -547,7 +564,7 @@ name = "zcash_proofs" version = "0.0.0" dependencies = [ "bellman 0.1.0", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", @@ -559,11 +576,13 @@ dependencies = [ "checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873" "checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" "checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" -"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" -"checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "" +"checksum blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d909f9ef55928e57e7de9638828bc9407233b5cb0904066a7edebbaa9946db2f" +"checksum blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa20660ff9f1e6d0a05444b5ebbbae13e4c018d4c66cc78c7e421e3396358a52" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" "checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index 3edc928..e75a71c 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -15,6 +15,8 @@ crate-type = ["staticlib"] [dependencies] bellman = { path = "../bellman" } +blake2b_simd = "0.5" +blake2s_simd = "0.5" ff = { path = "../ff" } libc = "0.2" pairing = { path = "../pairing" } @@ -24,7 +26,3 @@ rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } zcash_proofs = { path = "../zcash_proofs" } - -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" diff --git a/librustzcash/src/equihash.rs b/librustzcash/src/equihash.rs index da2693b..d251bc1 100644 --- a/librustzcash/src/equihash.rs +++ b/librustzcash/src/equihash.rs @@ -1,4 +1,4 @@ -use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams, State as Blake2bState}; use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; use std::io::Cursor; use std::mem::size_of; @@ -33,7 +33,7 @@ impl Params { } impl Node { - fn new(p: &Params, state: &Blake2b, i: u32) -> Self { + fn new(p: &Params, state: &Blake2bState, i: u32) -> Self { let hash = generate_hash(state, i / p.indices_per_hash_output()); let start = ((i % p.indices_per_hash_output()) * p.n / 8) as usize; let end = start + (p.n as usize) / 8; @@ -99,15 +99,18 @@ impl Node { } } -fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2b { +fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2bState { let mut personalization: Vec = Vec::from("ZcashPoW"); personalization.write_u32::(n).unwrap(); personalization.write_u32::(k).unwrap(); - Blake2b::with_params(digest_len as usize, &[], &[], &personalization) + Blake2bParams::new() + .hash_length(digest_len as usize) + .personal(&personalization) + .to_state() } -fn generate_hash(base_state: &Blake2b, i: u32) -> Blake2bResult { +fn generate_hash(base_state: &Blake2bState, i: u32) -> Blake2bHash { let mut lei = [0u8; 4]; (&mut lei[..]).write_u32::(i).unwrap(); @@ -249,7 +252,7 @@ pub fn is_valid_solution_iterative( return rows[0].is_zero(hash_len); } -fn tree_validator(p: &Params, state: &Blake2b, indices: &[u32]) -> Option { +fn tree_validator(p: &Params, state: &Blake2bState, indices: &[u32]) -> Option { if indices.len() > 1 { let end = indices.len(); let mid = end / 2; diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index fb72827..51a980e 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -1,5 +1,6 @@ extern crate bellman; -extern crate blake2_rfc; +extern crate blake2b_simd; +extern crate blake2s_simd; extern crate byteorder; extern crate ff; extern crate libc; @@ -33,7 +34,7 @@ use bellman::groth16::{ create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, }; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::Params as Blake2sParams; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -336,7 +337,10 @@ pub extern "system" fn librustzcash_crh_ivk( let ak = unsafe { &*ak }; let nk = unsafe { &*nk }; - let mut h = Blake2s::with_params(32, &[], &[], CRH_IVK_PERSONALIZATION); + let mut h = Blake2sParams::new() + .hash_length(32) + .personal(CRH_IVK_PERSONALIZATION) + .to_state(); h.update(ak); h.update(nk); let mut h = h.finalize().as_ref().to_vec(); diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index d985219..7d43774 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -14,15 +14,13 @@ features = ["expose-arith"] [dependencies] bellman = { path = "../bellman" } +blake2b_simd = "0.5" +blake2s_simd = "0.5" ff = { path = "../ff" } rand = "0.4" digest = "0.7" byteorder = "1" -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" - [dev-dependencies] hex-literal = "0.1" rust-crypto = "0.2" diff --git a/sapling-crypto/src/circuit/blake2s.rs b/sapling-crypto/src/circuit/blake2s.rs index 93af806..46bbe67 100644 --- a/sapling-crypto/src/circuit/blake2s.rs +++ b/sapling-crypto/src/circuit/blake2s.rs @@ -320,13 +320,13 @@ pub fn blake2s>( #[cfg(test)] mod test { + use blake2s_simd::Params as Blake2sParams; use rand::{XorShiftRng, SeedableRng, Rng}; use pairing::bls12_381::{Bls12}; use ::circuit::boolean::{Boolean, AllocatedBit}; use ::circuit::test::TestConstraintSystem; use super::blake2s; use bellman::{ConstraintSystem}; - use blake2_rfc::blake2s::Blake2s; #[test] fn test_blank_hash() { @@ -392,7 +392,7 @@ mod test { for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { - let mut h = Blake2s::with_params(32, &[], &[], b"12345678"); + let mut h = Blake2sParams::new().hash_length(32).personal(b"12345678").to_state(); let data: Vec = (0..input_len).map(|_| rng.gen()).collect(); diff --git a/sapling-crypto/src/circuit/test/mod.rs b/sapling-crypto/src/circuit/test/mod.rs index 18a77ba..79d128a 100644 --- a/sapling-crypto/src/circuit/test/mod.rs +++ b/sapling-crypto/src/circuit/test/mod.rs @@ -16,7 +16,7 @@ use byteorder::{BigEndian, ByteOrder}; use std::cmp::Ordering; use std::collections::BTreeMap; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::{Params as Blake2sParams, State as Blake2sState}; #[derive(Debug)] enum NamedObject { @@ -96,7 +96,7 @@ fn proc_lc( fn hash_lc( terms: &[(Variable, E::Fr)], - h: &mut Blake2s + h: &mut Blake2sState ) { let map = proc_lc::(terms); @@ -226,7 +226,7 @@ impl TestConstraintSystem { } pub fn hash(&self) -> String { - let mut h = Blake2s::new(32); + let mut h = Blake2sParams::new().hash_length(32).to_state(); { let mut buf = [0u8; 24]; diff --git a/sapling-crypto/src/group_hash.rs b/sapling-crypto/src/group_hash.rs index 43e87e8..7369e04 100644 --- a/sapling-crypto/src/group_hash.rs +++ b/sapling-crypto/src/group_hash.rs @@ -8,7 +8,7 @@ use ff::{ PrimeField }; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::Params; use constants; /// Produces a random point in the Jubjub curve. @@ -25,13 +25,15 @@ pub fn group_hash( // Check to see that scalar field is 255 bits assert!(E::Fr::NUM_BITS == 255); - let mut h = Blake2s::with_params(32, &[], &[], personalization); - h.update(constants::GH_FIRST_BLOCK); - h.update(tag); - let h = h.finalize().as_ref().to_vec(); - assert!(h.len() == 32); + let h = Params::new() + .hash_length(32) + .personal(personalization) + .to_state() + .update(constants::GH_FIRST_BLOCK) + .update(tag) + .finalize(); - match edwards::Point::::read(&h[..], params) { + match edwards::Point::::read(h.as_ref(), params) { Ok(p) => { let p = p.mul_by_cofactor(params); diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index ae37573..0535d9a 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -1,6 +1,7 @@ extern crate pairing; extern crate bellman; -extern crate blake2_rfc; +extern crate blake2b_simd; +extern crate blake2s_simd; extern crate digest; extern crate ff; extern crate rand; diff --git a/sapling-crypto/src/primitives/mod.rs b/sapling-crypto/src/primitives/mod.rs index fea332c..4026392 100644 --- a/sapling-crypto/src/primitives/mod.rs +++ b/sapling-crypto/src/primitives/mod.rs @@ -22,7 +22,7 @@ use jubjub::{ FixedGenerators }; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::Params as Blake2sParams; #[derive(Clone)] pub struct ValueCommitment { @@ -87,9 +87,12 @@ impl ViewingKey { self.ak.write(&mut preimage[0..32]).unwrap(); self.nk.write(&mut preimage[32..64]).unwrap(); - let mut h = Blake2s::with_params(32, &[], &[], constants::CRH_IVK_PERSONALIZATION); - h.update(&preimage); - let mut h = h.finalize().as_ref().to_vec(); + let mut h = [0; 32]; + h.copy_from_slice(Blake2sParams::new() + .hash_length(32) + .personal(constants::CRH_IVK_PERSONALIZATION) + .hash(&preimage) + .as_bytes()); // Drop the most significant five bits, so it can be interpreted as a scalar. h[31] &= 0b0000_0111; @@ -255,10 +258,12 @@ impl Note { let mut nf_preimage = [0u8; 64]; viewing_key.nk.write(&mut nf_preimage[0..32]).unwrap(); rho.write(&mut nf_preimage[32..64]).unwrap(); - let mut h = Blake2s::with_params(32, &[], &[], constants::PRF_NF_PERSONALIZATION); - h.update(&nf_preimage); - - h.finalize().as_ref().to_vec() + Blake2sParams::new() + .hash_length(32) + .personal(constants::PRF_NF_PERSONALIZATION) + .hash(&nf_preimage) + .as_bytes() + .to_vec() } /// Computes the note commitment diff --git a/sapling-crypto/src/util.rs b/sapling-crypto/src/util.rs index e67e660..1e759ba 100644 --- a/sapling-crypto/src/util.rs +++ b/sapling-crypto/src/util.rs @@ -1,9 +1,9 @@ -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::Params; use jubjub::{JubjubEngine, ToUniform}; pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> E::Fs { - let mut hasher = Blake2b::with_params(64, &[], &[], persona); + let mut hasher = Params::new().hash_length(64).personal(persona).to_state(); hasher.update(a); hasher.update(b); let ret = hasher.finalize(); diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 06a117b..771f351 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -7,6 +7,7 @@ authors = [ [dependencies] aes = "0.2" +blake2b_simd = "0.5" byteorder = "1" crypto_api_chachapoly = "0.1" ff = { path = "../ff" } @@ -17,7 +18,3 @@ pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" - -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" diff --git a/zcash_primitives/src/keys.rs b/zcash_primitives/src/keys.rs index e6066e3..fca31ed 100644 --- a/zcash_primitives/src/keys.rs +++ b/zcash_primitives/src/keys.rs @@ -2,7 +2,7 @@ //! //! Implements section 4.2.2 of the Zcash Protocol Specification. -use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use ff::{PrimeField, PrimeFieldRepr}; use sapling_crypto::{ jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, ToUniform, Unknown}, @@ -13,12 +13,15 @@ use std::io::{self, Read, Write}; pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed"; /// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t) -pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bResult { - prf_expand_vec(sk, &[t]) +pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bHash { + prf_expand_vec(sk, &vec![t]) } -pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bResult { - let mut h = Blake2b::with_params(64, &[], &[], PRF_EXPAND_PERSONALIZATION); +pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bHash { + let mut h = Blake2bParams::new() + .hash_length(64) + .personal(PRF_EXPAND_PERSONALIZATION) + .to_state(); h.update(sk); for t in ts { h.update(t); diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 962811e..eb33461 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -2,7 +2,7 @@ extern crate lazy_static; extern crate aes; -extern crate blake2_rfc; +extern crate blake2b_simd; extern crate byteorder; extern crate crypto_api_chachapoly; extern crate ff; diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index 3d1c55b..610b746 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -1,6 +1,6 @@ //! Implementation of in-band secret distribution for Zcash transactions. -use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use ff::{PrimeField, PrimeFieldRepr}; @@ -168,14 +168,15 @@ where fn kdf_sapling( dhsecret: edwards::Point, epk: &edwards::Point, -) -> Blake2bResult { +) -> Blake2bHash { let mut input = [0u8; 64]; dhsecret.write(&mut input[0..32]).unwrap(); epk.write(&mut input[32..64]).unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], KDF_SAPLING_PERSONALIZATION); - h.update(&input); - h.finalize() + Blake2bParams::new() + .hash_length(32) + .personal(KDF_SAPLING_PERSONALIZATION) + .hash(&input) } /// Sapling PRF^ock. @@ -186,16 +187,17 @@ fn prf_ock( cv: &edwards::Point, cmu: &Fr, epk: &edwards::Point, -) -> Blake2bResult { +) -> Blake2bHash { let mut ock_input = [0u8; 128]; ock_input[0..32].copy_from_slice(&ovk.0); cv.write(&mut ock_input[32..64]).unwrap(); cmu.into_repr().write_le(&mut ock_input[64..96]).unwrap(); epk.write(&mut ock_input[96..128]).unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], PRF_OCK_PERSONALIZATION); - h.update(&ock_input); - h.finalize() + Blake2bParams::new() + .hash_length(32) + .personal(PRF_OCK_PERSONALIZATION) + .hash(&ock_input) } /// An API for encrypting Sapling notes. diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index 85302ee..774e7b4 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -1,4 +1,4 @@ -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use byteorder::{LittleEndian, WriteBytesExt}; use ff::{PrimeField, PrimeFieldRepr}; @@ -39,7 +39,7 @@ macro_rules! update_i64 { macro_rules! update_hash { ($h:expr, $cond:expr, $value:expr) => { if $cond { - $h.update(&$value); + $h.update(&$value.as_ref()); } else { $h.update(&[0; 32]); } @@ -67,47 +67,51 @@ impl SigHashVersion { } } -fn prevout_hash(tx: &TransactionData) -> Vec { +fn prevout_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.vin.len() * 36); for t_in in &tx.vin { t_in.prevout.write(&mut data).unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_PREVOUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_PREVOUTS_HASH_PERSONALIZATION) + .hash(&data) } -fn sequence_hash(tx: &TransactionData) -> Vec { +fn sequence_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.vin.len() * 4); for t_in in &tx.vin { (&mut data) .write_u32::(t_in.sequence) .unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SEQUENCE_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_SEQUENCE_HASH_PERSONALIZATION) + .hash(&data) } -fn outputs_hash(tx: &TransactionData) -> Vec { +fn outputs_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.vout.len() * (4 + 1)); for t_out in &tx.vout { t_out.write(&mut data).unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION) + .hash(&data) } -fn single_output_hash(tx_out: &TxOut) -> Vec { +fn single_output_hash(tx_out: &TxOut) -> Blake2bHash { let mut data = vec![]; tx_out.write(&mut data).unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION) + .hash(&data) } -fn joinsplits_hash(tx: &TransactionData) -> Vec { +fn joinsplits_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity( tx.joinsplits.len() * if tx.version < SAPLING_TX_VERSION { @@ -120,12 +124,13 @@ fn joinsplits_hash(tx: &TransactionData) -> Vec { js.write(&mut data).unwrap(); } data.extend_from_slice(&tx.joinsplit_pubkey.unwrap()); - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_JOINSPLITS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_JOINSPLITS_HASH_PERSONALIZATION) + .hash(&data) } -fn shielded_spends_hash(tx: &TransactionData) -> Vec { +fn shielded_spends_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.shielded_spends.len() * 384); for s_spend in &tx.shielded_spends { s_spend.cv.write(&mut data).unwrap(); @@ -134,19 +139,21 @@ fn shielded_spends_hash(tx: &TransactionData) -> Vec { s_spend.rk.write(&mut data).unwrap(); data.extend_from_slice(&s_spend.zkproof); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION) + .hash(&data) } -fn shielded_outputs_hash(tx: &TransactionData) -> Vec { +fn shielded_outputs_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.shielded_outputs.len() * 948); for s_out in &tx.shielded_outputs { s_out.write(&mut data).unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION) + .hash(&data) } pub fn signature_hash_data( @@ -158,26 +165,16 @@ pub fn signature_hash_data( let sigversion = SigHashVersion::from_tx(tx); match sigversion { SigHashVersion::Overwinter | SigHashVersion::Sapling => { - let hash_outputs = if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE - && (hash_type & SIGHASH_MASK) != SIGHASH_NONE - { - outputs_hash(tx) - } else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE - && transparent_input.is_some() - && transparent_input.as_ref().unwrap().0 < tx.vout.len() - { - single_output_hash(&tx.vout[transparent_input.as_ref().unwrap().0]) - } else { - vec![0; 32] - }; - let mut personal = [0; 16]; (&mut personal[..12]).copy_from_slice(ZCASH_SIGHASH_PERSONALIZATION_PREFIX); (&mut personal[12..]) .write_u32::(consensus_branch_id) .unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], &personal); + let mut h = Blake2bParams::new() + .hash_length(32) + .personal(&personal) + .to_state(); let mut tmp = [0; 8]; update_u32!(h, tx.header(), tmp); @@ -190,7 +187,20 @@ pub fn signature_hash_data( && (hash_type & SIGHASH_MASK) != SIGHASH_NONE, sequence_hash(tx) ); - h.update(&hash_outputs); + if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE + && (hash_type & SIGHASH_MASK) != SIGHASH_NONE + { + h.update(outputs_hash(tx).as_ref()); + } else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE + && transparent_input.is_some() + && transparent_input.as_ref().unwrap().0 < tx.vout.len() + { + h.update( + single_output_hash(&tx.vout[transparent_input.as_ref().unwrap().0]).as_ref(), + ); + } else { + h.update(&[0; 32]); + }; update_hash!(h, !tx.joinsplits.is_empty(), joinsplits_hash(tx)); if sigversion == SigHashVersion::Sapling { update_hash!(h, !tx.shielded_spends.is_empty(), shielded_spends_hash(tx)); diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index db5adcd..a34ae18 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -1,5 +1,5 @@ use aes::Aes256; -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::Params as Blake2bParams; use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; use ff::Field; use fpe::ff1::{BinaryNumeralString, FF1}; @@ -33,7 +33,10 @@ struct FVKFingerprint([u8; 32]); impl From<&FullViewingKey> for FVKFingerprint { fn from(fvk: &FullViewingKey) -> Self { - let mut h = Blake2b::with_params(32, &[], &[], ZIP32_SAPLING_FVFP_PERSONALIZATION); + let mut h = Blake2bParams::new() + .hash_length(32) + .personal(ZIP32_SAPLING_FVFP_PERSONALIZATION) + .to_state(); h.update(&fvk.to_bytes()); let mut fvfp = [0u8; 32]; fvfp.copy_from_slice(h.finalize().as_bytes()); @@ -225,9 +228,10 @@ impl std::fmt::Debug for ExtendedFullViewingKey { impl ExtendedSpendingKey { pub fn master(seed: &[u8]) -> Self { - let mut h = Blake2b::with_params(64, &[], &[], ZIP32_SAPLING_MASTER_PERSONALIZATION); - h.update(seed); - let i = h.finalize(); + let i = Blake2bParams::new() + .hash_length(64) + .personal(ZIP32_SAPLING_MASTER_PERSONALIZATION) + .hash(seed); let sk_m = &i.as_bytes()[..32]; let mut c_m = [0u8; 32]; diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 5bcdb26..2139749 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -7,12 +7,9 @@ authors = [ [dependencies] bellman = { path = "../bellman" } +blake2b_simd = "0.5" byteorder = "1" ff = { path = "../ff" } pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } - -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" diff --git a/zcash_proofs/src/hashreader.rs b/zcash_proofs/src/hashreader.rs index a422d52..dbe686f 100644 --- a/zcash_proofs/src/hashreader.rs +++ b/zcash_proofs/src/hashreader.rs @@ -1,10 +1,10 @@ -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::State; use std::io::{self, Read}; /// Abstraction over a reader which hashes the data being read. pub struct HashReader { reader: R, - hasher: Blake2b, + hasher: State, } impl HashReader { @@ -12,7 +12,7 @@ impl HashReader { pub fn new(reader: R) -> Self { HashReader { reader: reader, - hasher: Blake2b::new(64), + hasher: State::new(), } } diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index ca17a8b..d061818 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -1,5 +1,5 @@ extern crate bellman; -extern crate blake2_rfc; +extern crate blake2b_simd; extern crate byteorder; extern crate ff; extern crate pairing; From d1ce6749fe4147b60e6c14e509925933d773f010 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 10 Jul 2019 13:12:26 -0400 Subject: [PATCH 003/105] Bump minimum Rust version to 1.36 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a773623..9ddae8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: rust rust: - - 1.32.0 + - 1.36.0 cache: cargo From 785f22ca5a49f595d4f82416899fe957ae002ffb Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Oct 2018 13:18:39 +0100 Subject: [PATCH 004/105] Move Sapling commitment tree hash into zcash_primitives --- librustzcash/src/rustzcash.rs | 32 +++++++--------------------- zcash_primitives/src/sapling.rs | 37 ++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index fb72827..20af7ed 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -11,7 +11,7 @@ extern crate zcash_proofs; extern crate lazy_static; -use ff::{BitIterator, PrimeField, PrimeFieldRepr}; +use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::{ @@ -22,7 +22,6 @@ use sapling_crypto::{ fs::{Fs, FsRepr}, FixedGenerators, JubjubEngine, JubjubParams, PrimeOrder, ToUniform, Unknown, }, - pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{self, Signature}, }; @@ -57,7 +56,11 @@ use std::ffi::OsString; use std::os::windows::ffi::OsStringExt; use sapling_crypto::primitives::{ProofGenerationKey, ViewingKey}; -use zcash_primitives::{note_encryption::sapling_ka_agree, sapling::spend_sig, zip32, JUBJUB}; +use zcash_primitives::{ + note_encryption::sapling_ka_agree, + sapling::{merkle_hash, spend_sig}, + zip32, JUBJUB, +}; use zcash_proofs::{ load_parameters, sapling::{CommitmentTreeWitness, SaplingProvingContext, SaplingVerificationContext}, @@ -254,28 +257,7 @@ pub extern "system" fn librustzcash_merkle_hash( // size of the representation let b_repr = read_le(unsafe { &(&*b)[..] }); - let mut lhs = [false; 256]; - let mut rhs = [false; 256]; - - for (a, b) in lhs.iter_mut().rev().zip(BitIterator::new(a_repr)) { - *a = b; - } - - for (a, b) in rhs.iter_mut().rev().zip(BitIterator::new(b_repr)) { - *a = b; - } - - let tmp = pedersen_hash::( - Personalization::MerkleTree(depth), - lhs.iter() - .map(|&x| x) - .take(Fr::NUM_BITS as usize) - .chain(rhs.iter().map(|&x| x).take(Fr::NUM_BITS as usize)), - &JUBJUB, - ) - .into_xy() - .0 - .into_repr(); + let tmp = merkle_hash(depth, &a_repr, &b_repr); // Should be okay, caller is responsible for ensuring the pointer // is a valid pointer to 32 bytes that can be mutated. diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index b59dc2b..62f5118 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -1,10 +1,45 @@ -use pairing::bls12_381::Bls12; +use ff::{BitIterator, PrimeField}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; use rand::OsRng; use sapling_crypto::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, + pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{PrivateKey, PublicKey, Signature}, }; +use JUBJUB; + +/// Compute a parent node in the Sapling commitment tree given its two children. +pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr { + let lhs = { + let mut tmp = [false; 256]; + for (a, b) in tmp.iter_mut().rev().zip(BitIterator::new(lhs)) { + *a = b; + } + tmp + }; + + let rhs = { + let mut tmp = [false; 256]; + for (a, b) in tmp.iter_mut().rev().zip(BitIterator::new(rhs)) { + *a = b; + } + tmp + }; + + pedersen_hash::( + Personalization::MerkleTree(depth), + lhs.iter() + .map(|&x| x) + .take(Fr::NUM_BITS as usize) + .chain(rhs.iter().map(|&x| x).take(Fr::NUM_BITS as usize)), + &JUBJUB, + ) + .into_xy() + .0 + .into_repr() +} + /// Create the spendAuthSig for a Sapling SpendDescription. pub fn spend_sig( ask: PrivateKey, From 8f3f95ee0830a2d17d20106ae6ee2e89eb3bb4d8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Oct 2018 20:09:17 +0100 Subject: [PATCH 005/105] Sapling commitment tree empty roots --- zcash_primitives/src/lib.rs | 1 + zcash_primitives/src/merkle_tree.rs | 113 ++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 zcash_primitives/src/merkle_tree.rs diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 962811e..07d2385 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -17,6 +17,7 @@ use sapling_crypto::jubjub::JubjubBls12; pub mod block; pub mod keys; +pub mod merkle_tree; pub mod note_encryption; pub mod sapling; mod serialize; diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs new file mode 100644 index 0000000..cb74ea1 --- /dev/null +++ b/zcash_primitives/src/merkle_tree.rs @@ -0,0 +1,113 @@ +use ff::PrimeField; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use sapling_crypto::primitives::Note; + +use sapling::merkle_hash; + +const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32; + +trait Hashable: Clone + Copy { + /// Returns the parent node within the tree of the two given nodes. + fn combine(usize, &Self, &Self) -> Self; + + /// Returns a blank leaf node. + fn blank() -> Self; +} + +#[derive(Clone, Copy)] +pub struct Node { + repr: FrRepr, +} + +impl Node { + pub fn new(repr: FrRepr) -> Self { + Node { repr } + } +} + +impl Hashable for Node { + fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self { + Node { + repr: merkle_hash(depth, &lhs.repr, &rhs.repr), + } + } + + fn blank() -> Self { + Node { + repr: Note::::uncommitted().into_repr(), + } + } +} + +impl From for Fr { + fn from(node: Node) -> Self { + Fr::from_repr(node.repr).expect("Tree nodes should be in the prime field") + } +} + +lazy_static! { + static ref EMPTY_ROOTS: Vec = { + let mut v = vec![Node::blank()]; + for d in 0..SAPLING_COMMITMENT_TREE_DEPTH { + let next = Node::combine(d, &v[d], &v[d]); + v.push(next); + } + v + }; +} + +#[cfg(test)] +mod tests { + use super::EMPTY_ROOTS; + + use ff::PrimeFieldRepr; + use hex; + + const HEX_EMPTY_ROOTS: [&str; 33] = [ + "0100000000000000000000000000000000000000000000000000000000000000", + "817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155", + "ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34", + "d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c", + "e110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49", + "912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a", + "8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613", + "d6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813", + "7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444", + "43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b", + "ba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72", + "4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c", + "ec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048", + "1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651", + "bd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c", + "d6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f", + "1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451", + "6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c", + "cd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00", + "6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216", + "8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673", + "08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023", + "0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49", + "4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850", + "fee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712", + "16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a", + "d2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58", + "a5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a", + "28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a", + "e1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72", + "12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d", + "b2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814", + "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + ]; + + #[test] + fn empty_root_test_vectors() { + let mut tmp = [0u8; 32]; + for i in 0..HEX_EMPTY_ROOTS.len() { + EMPTY_ROOTS[i] + .repr + .write_le(&mut tmp[..]) + .expect("length is 32 bytes"); + assert_eq!(hex::encode(tmp), HEX_EMPTY_ROOTS[i]); + } + } +} From f4059a5faa1ccb5d3c86f4ecc4e17d13cf1eca33 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 8 Oct 2018 14:52:27 +0100 Subject: [PATCH 006/105] Sapling commitment tree --- zcash_primitives/src/merkle_tree.rs | 263 +++++++++++++++++++++++++++- 1 file changed, 262 insertions(+), 1 deletion(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index cb74ea1..6e458e4 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1,6 +1,7 @@ use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::primitives::Note; +use std::collections::VecDeque; use sapling::merkle_hash; @@ -56,12 +57,147 @@ lazy_static! { }; } +struct PathFiller { + queue: VecDeque, +} + +impl PathFiller { + fn empty() -> Self { + PathFiller { + queue: VecDeque::new(), + } + } + + fn next(&mut self, depth: usize) -> Node { + self.queue.pop_front().unwrap_or_else(|| EMPTY_ROOTS[depth]) + } +} + +/// A Merkle tree of Sapling note commitments. +pub struct CommitmentTree { + left: Option, + right: Option, + parents: Vec>, +} + +impl CommitmentTree { + /// Creates an empty tree. + pub fn new() -> Self { + CommitmentTree { + left: None, + right: None, + parents: vec![], + } + } + + /// Returns the number of notes in the tree. + pub fn size(&self) -> usize { + self.parents.iter().enumerate().fold( + match (self.left.is_some(), self.right.is_some()) { + (false, false) => 0, + (true, false) | (false, true) => 1, + (true, true) => 2, + }, + |acc, (i, p)| { + // Treat occupation of parents array as a binary number + // (right-shifted by 1) + acc + if p.is_some() { 1 << (i + 1) } else { 0 } + }, + ) + } + + fn is_complete(&self, depth: usize) -> bool { + self.left.is_some() + && self.right.is_some() + && self.parents.len() == depth - 1 + && self.parents.iter().fold(true, |acc, p| acc && p.is_some()) + } + + /// Adds a note to the tree. Returns an error if the tree is full. + pub fn append(&mut self, node: Node) -> Result<(), ()> { + self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH) + } + + fn append_inner(&mut self, node: Node, depth: usize) -> Result<(), ()> { + if self.is_complete(depth) { + // Tree is full + return Err(()); + } + + match (self.left, self.right) { + (None, _) => self.left = Some(node), + (_, None) => self.right = Some(node), + (Some(l), Some(r)) => { + let mut combined = Node::combine(0, &l, &r); + self.left = Some(node); + self.right = None; + + for i in 0..depth { + if i < self.parents.len() { + if let Some(p) = self.parents[i] { + combined = Node::combine(i + 1, &p, &combined); + self.parents[i] = None; + } else { + self.parents[i] = Some(combined); + break; + } + } else { + self.parents.push(Some(combined)); + break; + } + } + } + } + + Ok(()) + } + + /// Returns the current root of the tree. + pub fn root(&self) -> Node { + self.root_inner(SAPLING_COMMITMENT_TREE_DEPTH, PathFiller::empty()) + } + + fn root_inner(&self, depth: usize, mut filler: PathFiller) -> Node { + assert!(depth > 0); + + // 1) Hash left and right leaves together. + // - Empty leaves are used as needed. + let leaf_root = Node::combine( + 0, + &match self.left { + Some(node) => node, + None => filler.next(0), + }, + &match self.right { + Some(node) => node, + None => filler.next(0), + }, + ); + + // 2) Hash in parents up to the currently-filled depth. + // - Roots of the empty subtrees are used as needed. + let mid_root = self + .parents + .iter() + .enumerate() + .fold(leaf_root, |root, (i, p)| match p { + Some(node) => Node::combine(i + 1, node, &root), + None => Node::combine(i + 1, &root, &filler.next(i + 1)), + }); + + // 3) Hash in roots of the empty subtrees up to the final depth. + ((self.parents.len() + 1)..depth) + .fold(mid_root, |root, d| Node::combine(d, &root, &filler.next(d))) + } +} + #[cfg(test)] mod tests { - use super::EMPTY_ROOTS; + use super::{CommitmentTree, Hashable, Node, PathFiller, EMPTY_ROOTS}; use ff::PrimeFieldRepr; use hex; + use pairing::bls12_381::FrRepr; const HEX_EMPTY_ROOTS: [&str; 33] = [ "0100000000000000000000000000000000000000000000000000000000000000", @@ -99,6 +235,28 @@ mod tests { "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", ]; + const TESTING_DEPTH: usize = 4; + + struct TestCommitmentTree(CommitmentTree); + + impl TestCommitmentTree { + fn new() -> Self { + TestCommitmentTree(CommitmentTree::new()) + } + + fn size(&self) -> usize { + self.0.size() + } + + fn append(&mut self, node: Node) -> Result<(), ()> { + self.0.append_inner(node, TESTING_DEPTH) + } + + fn root(&self) -> Node { + self.0.root_inner(TESTING_DEPTH, PathFiller::empty()) + } + } + #[test] fn empty_root_test_vectors() { let mut tmp = [0u8; 32]; @@ -110,4 +268,107 @@ mod tests { assert_eq!(hex::encode(tmp), HEX_EMPTY_ROOTS[i]); } } + + #[test] + fn sapling_empty_root() { + let mut tmp = [0u8; 32]; + CommitmentTree::new() + .root() + .repr + .write_le(&mut tmp[..]) + .expect("length is 32 bytes"); + assert_eq!( + hex::encode(tmp), + "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e" + ); + } + + #[test] + fn empty_commitment_tree_roots() { + let tree = CommitmentTree::new(); + let mut tmp = [0u8; 32]; + for i in 1..HEX_EMPTY_ROOTS.len() { + tree.root_inner(i, PathFiller::empty()) + .repr + .write_le(&mut tmp[..]) + .expect("length is 32 bytes"); + assert_eq!(hex::encode(tmp), HEX_EMPTY_ROOTS[i]); + } + } + + #[test] + fn test_sapling_tree() { + // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_commitments_sapling.json + // Byte-reversed because the original test vectors are loaded using uint256S() + let commitments = [ + "b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55", + "225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458", + "7c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c", + "50421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030", + "aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12", + "f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02", + "bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e", + "da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a511", + "3a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f77446", + "c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008", + "f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702", + "e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c608", + "8cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e826", + "22fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03", + "f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c", + "3a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac15", + ]; + + // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_roots_sapling.json + let roots = [ + "8c3daa300c9710bf24d2595536e7c80ff8d147faca726636d28e8683a0c27703", + "8611f17378eb55e8c3c3f0a5f002e2b0a7ca39442fc928322b8072d1079c213d", + "3db73b998d536be0e1c2ec124df8e0f383ae7b602968ff6a5276ca0695023c46", + "7ac2e6442fec5970e116dfa4f2ee606f395366cafb1fa7dfd6c3de3ce18c4363", + "6a8f11ab2a11c262e39ed4ea3825ae6c94739ccf94479cb69402c5722b034532", + "149595eed0b54a7e694cc8a68372525b9ae2c7b102514f527460db91eb690565", + "8c0432f1994a2381a7a4b5fda770336011f9e0b30784f9a5597901619c797045", + "e780c48d70420601f3313ff8488d7766b70c059c53aa3cda2ff1ef57ff62383c", + "f919f03caaed8a2c60f58c0d43838f83e670dc7e8ccd25daa04a13f3e8f45541", + "74f32b36629724038e71cbd6823b5a666440205a7d1a9242e95870b53d81f34a", + "a4af205a4e1ee02102866b23a68930ac33efda9235832f49b17fcc4939be4525", + "a946a42f1636045a16e65b2308e036d9da70089686c87c692e45912bd1cab772", + "a1db2dbac055364c1cb43cbeb49c7e2815bff855122602a2ad0fb981a91e0e39", + "16329b3ba4f0640f4d306532d9ea6ba0fbf0e70e44ed57d27b4277ed9cda6849", + "7b6523b2d9b23f72fec6234aa6a1f8fae3dba1c6a266023ea8b1826feba7a25c", + "5c0bea7e17bde5bee4eb795c2eec3d389a68da587b36dd687b134826ecc09308", + ]; + + fn assert_root_eq(root: Node, expected: &str) { + let mut tmp = [0u8; 32]; + root.repr + .write_le(&mut tmp[..]) + .expect("length is 32 bytes"); + assert_eq!(hex::encode(tmp), expected); + } + + let mut tree = TestCommitmentTree::new(); + assert_eq!(tree.size(), 0); + + for i in 0..16 { + let mut cm = FrRepr::default(); + cm.read_le(&hex::decode(commitments[i]).unwrap()[..]) + .expect("length is 32 bytes"); + + let cm = Node::new(cm); + + // Append a commitment to the tree + assert!(tree.append(cm).is_ok()); + + // Size incremented by one. + assert_eq!(tree.size(), i + 1); + + // Check tree root consistency + assert_root_eq(tree.root(), roots[i]); + } + + // Tree should be full now + let node = Node::blank(); + assert!(tree.append(node).is_err()); + } } From bf74915053d490fa4af507c32d9c4e55ca6ef7f2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 9 Nov 2018 00:07:25 +1300 Subject: [PATCH 007/105] Move CommitmentTreeWitness into zcash_primitives --- Cargo.lock | 1 + librustzcash/src/rustzcash.rs | 3 +- zcash_primitives/src/merkle_tree.rs | 75 ++++++++++++++++++++++++++- zcash_proofs/Cargo.toml | 1 + zcash_proofs/src/lib.rs | 1 + zcash_proofs/src/sapling/mod.rs | 2 +- zcash_proofs/src/sapling/prover.rs | 78 ++--------------------------- 7 files changed, 83 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34b20d2..26def55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -553,6 +553,7 @@ dependencies = [ "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", + "zcash_primitives 0.0.0", ] [metadata] diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 20af7ed..96bb718 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -57,13 +57,14 @@ use std::os::windows::ffi::OsStringExt; use sapling_crypto::primitives::{ProofGenerationKey, ViewingKey}; use zcash_primitives::{ + merkle_tree::CommitmentTreeWitness, note_encryption::sapling_ka_agree, sapling::{merkle_hash, spend_sig}, zip32, JUBJUB, }; use zcash_proofs::{ load_parameters, - sapling::{CommitmentTreeWitness, SaplingProvingContext, SaplingVerificationContext}, + sapling::{SaplingProvingContext, SaplingVerificationContext}, }; pub mod equihash; diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 6e458e4..a715215 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1,6 +1,7 @@ -use ff::PrimeField; +use byteorder::{LittleEndian, ReadBytesExt}; +use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use sapling_crypto::primitives::Note; +use sapling_crypto::{circuit::sapling::TREE_DEPTH, primitives::Note}; use std::collections::VecDeque; use sapling::merkle_hash; @@ -191,6 +192,76 @@ impl CommitmentTree { } } +/// A witness to a path from a position in a particular Sapling commitment tree +/// to the root of that tree. +pub struct CommitmentTreeWitness { + pub auth_path: Vec>, + pub position: u64, +} + +impl CommitmentTreeWitness { + pub fn from_slice(mut witness: &[u8]) -> Result { + // Skip the first byte, which should be "32" to signify the length of + // the following vector of Pedersen hashes. + assert_eq!(witness[0], TREE_DEPTH as u8); + witness = &witness[1..]; + + // Begin to construct the authentication path + let mut auth_path = vec![None; TREE_DEPTH]; + + // The vector works in reverse + for i in (0..TREE_DEPTH).rev() { + // skip length of inner vector + assert_eq!(witness[0], 32); // the length of a pedersen hash + witness = &witness[1..]; + + // Grab the sibling node at this depth in the tree + let mut sibling = [0u8; 32]; + sibling.copy_from_slice(&witness[0..32]); + witness = &witness[32..]; + + // Sibling node should be an element of Fr + let sibling = match { + let mut repr = FrRepr::default(); + repr.read_le(&sibling[..]).expect("length is 32 bytes"); + Fr::from_repr(repr) + } { + Ok(p) => p, + Err(_) => return Err(()), + }; + + // Set the value in the auth path; we put false here + // for now (signifying the position bit) which we'll + // fill in later. + auth_path[i] = Some((sibling, false)); + } + + // Read the position from the witness + let position = witness + .read_u64::() + .expect("should have had index at the end"); + + // Given the position, let's finish constructing the authentication + // path + let mut tmp = position; + for i in 0..TREE_DEPTH { + auth_path[i].as_mut().map(|p| p.1 = (tmp & 1) == 1); + + tmp >>= 1; + } + + // The witness should be empty now; if it wasn't, the caller would + // have provided more information than they should have, indicating + // a bug downstream + assert_eq!(witness.len(), 0); + + Ok(CommitmentTreeWitness { + auth_path, + position, + }) + } +} + #[cfg(test)] mod tests { use super::{CommitmentTree, Hashable, Node, PathFiller, EMPTY_ROOTS}; diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 5bcdb26..85a7210 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -12,6 +12,7 @@ ff = { path = "../ff" } pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } +zcash_primitives = { path = "../zcash_primitives" } [dependencies.blake2-rfc] git = "https://github.com/gtank/blake2-rfc" diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index ca17a8b..97dd501 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -5,6 +5,7 @@ extern crate ff; extern crate pairing; extern crate rand; extern crate sapling_crypto; +extern crate zcash_primitives; use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey, VerifyingKey}; use pairing::bls12_381::Bls12; diff --git a/zcash_proofs/src/sapling/mod.rs b/zcash_proofs/src/sapling/mod.rs index 2cfb2e9..4c37306 100644 --- a/zcash_proofs/src/sapling/mod.rs +++ b/zcash_proofs/src/sapling/mod.rs @@ -6,7 +6,7 @@ use sapling_crypto::jubjub::{ mod prover; mod verifier; -pub use self::prover::{CommitmentTreeWitness, SaplingProvingContext}; +pub use self::prover::SaplingProvingContext; pub use self::verifier::SaplingVerificationContext; // This function computes `value` in the exponent of the value commitment base diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 3a3511c..feb1d2c 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -1,92 +1,22 @@ use bellman::groth16::{ create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, }; -use byteorder::{LittleEndian, ReadBytesExt}; -use ff::{Field, PrimeField, PrimeFieldRepr}; -use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use ff::Field; +use pairing::bls12_381::{Bls12, Fr}; use rand::{OsRng, Rand}; use sapling_crypto::{ circuit::{ multipack, - sapling::{Output, Spend, TREE_DEPTH}, + sapling::{Output, Spend}, }, jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, redjubjub::{PrivateKey, PublicKey, Signature}, }; +use zcash_primitives::merkle_tree::CommitmentTreeWitness; use super::compute_value_balance; -/// A witness to a path from a postion in a particular Sapling commitment tree -/// to the root of that tree. -pub struct CommitmentTreeWitness { - auth_path: Vec>, - position: u64, -} - -impl CommitmentTreeWitness { - pub fn from_slice(mut witness: &[u8]) -> Result { - // Skip the first byte, which should be "32" to signify the length of - // the following vector of Pedersen hashes. - assert_eq!(witness[0], TREE_DEPTH as u8); - witness = &witness[1..]; - - // Begin to construct the authentication path - let mut auth_path = vec![None; TREE_DEPTH]; - - // The vector works in reverse - for i in (0..TREE_DEPTH).rev() { - // skip length of inner vector - assert_eq!(witness[0], 32); // the length of a pedersen hash - witness = &witness[1..]; - - // Grab the sibling node at this depth in the tree - let mut sibling = [0u8; 32]; - sibling.copy_from_slice(&witness[0..32]); - witness = &witness[32..]; - - // Sibling node should be an element of Fr - let sibling = match { - let mut repr = FrRepr::default(); - repr.read_le(&sibling[..]).expect("length is 32 bytes"); - Fr::from_repr(repr) - } { - Ok(p) => p, - Err(_) => return Err(()), - }; - - // Set the value in the auth path; we put false here - // for now (signifying the position bit) which we'll - // fill in later. - auth_path[i] = Some((sibling, false)); - } - - // Read the position from the witness - let position = witness - .read_u64::() - .expect("should have had index at the end"); - - // Given the position, let's finish constructing the authentication - // path - let mut tmp = position; - for i in 0..TREE_DEPTH { - auth_path[i].as_mut().map(|p| p.1 = (tmp & 1) == 1); - - tmp >>= 1; - } - - // The witness should be empty now; if it wasn't, the caller would - // have provided more information than they should have, indicating - // a bug downstream - assert_eq!(witness.len(), 0); - - Ok(CommitmentTreeWitness { - auth_path, - position, - }) - } -} - /// A context object for creating the Sapling components of a Zcash transaction. pub struct SaplingProvingContext { bsk: Fs, From 667d6101c9dc3916559d74fb9b4ccbd093f54e47 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 10 Oct 2018 17:43:02 +0100 Subject: [PATCH 008/105] Sapling incremental witnesses --- zcash_primitives/src/merkle_tree.rs | 374 +++++++++++++++++++++++++++- 1 file changed, 366 insertions(+), 8 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index a715215..2a6eaf2 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -3,6 +3,7 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::{circuit::sapling::TREE_DEPTH, primitives::Note}; use std::collections::VecDeque; +use std::iter; use sapling::merkle_hash; @@ -16,7 +17,7 @@ trait Hashable: Clone + Copy { fn blank() -> Self; } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct Node { repr: FrRepr, } @@ -75,6 +76,7 @@ impl PathFiller { } /// A Merkle tree of Sapling note commitments. +#[derive(Clone)] pub struct CommitmentTree { left: Option, right: Option, @@ -192,25 +194,203 @@ impl CommitmentTree { } } +#[derive(Clone)] +pub struct IncrementalWitness { + tree: CommitmentTree, + filled: Vec, + cursor_depth: usize, + cursor: Option, +} + +impl IncrementalWitness { + pub fn from_tree(tree: &CommitmentTree) -> IncrementalWitness { + IncrementalWitness { + tree: tree.clone(), + filled: vec![], + cursor_depth: 0, + cursor: None, + } + } + + /// Returns the position of the witnessed note in the commitment tree. + pub fn position(&self) -> usize { + self.tree.size() - 1 + } + + fn filler(&self) -> PathFiller { + let cursor_root = self + .cursor + .as_ref() + .map(|c| c.root_inner(self.cursor_depth, PathFiller::empty())); + + let queue = if let Some(node) = cursor_root { + self.filled + .iter() + .cloned() + .chain(iter::once(node)) + .collect() + } else { + self.filled.iter().cloned().collect() + }; + + PathFiller { queue } + } + + /// Finds the next "depth" of an unfilled subtree. + fn next_depth(&self) -> usize { + let mut skip = self.filled.len(); + + if self.tree.left.is_none() { + if skip > 0 { + skip -= 1; + } else { + return 0; + } + } + + if self.tree.right.is_none() { + if skip > 0 { + skip -= 1; + } else { + return 0; + } + } + + let mut d = 1; + for p in &self.tree.parents { + if p.is_none() { + if skip > 0 { + skip -= 1; + } else { + return d; + } + } + d += 1; + } + + d + skip + } + + /// Tracks a note that has been added to the underlying tree. Returns an + /// error if the tree is full. + pub fn append(&mut self, node: Node) -> Result<(), ()> { + self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH) + } + + fn append_inner(&mut self, node: Node, depth: usize) -> Result<(), ()> { + if let Some(mut cursor) = self.cursor.take() { + cursor + .append_inner(node, depth) + .expect("cursor should not be full"); + if cursor.is_complete(self.cursor_depth) { + self.filled + .push(cursor.root_inner(self.cursor_depth, PathFiller::empty())); + } else { + self.cursor = Some(cursor); + } + } else { + self.cursor_depth = self.next_depth(); + if self.cursor_depth >= depth { + // Tree is full + return Err(()); + } + + if self.cursor_depth == 0 { + self.filled.push(node); + } else { + let mut cursor = CommitmentTree::new(); + cursor + .append_inner(node, depth) + .expect("cursor should not be full"); + self.cursor = Some(cursor); + } + } + + Ok(()) + } + + /// Returns the current root of the tree corresponding to the witness. + pub fn root(&self) -> Node { + self.root_inner(SAPLING_COMMITMENT_TREE_DEPTH) + } + + fn root_inner(&self, depth: usize) -> Node { + self.tree.root_inner(depth, self.filler()) + } + + /// Returns the current witness, or None if the tree is empty. + pub fn path(&self) -> Option { + self.path_inner(SAPLING_COMMITMENT_TREE_DEPTH) + } + + fn path_inner(&self, depth: usize) -> Option { + let mut filler = self.filler(); + let mut auth_path = Vec::new(); + + if let Some(node) = self.tree.left { + if self.tree.right.is_some() { + auth_path.push(Some((node, true))); + } else { + auth_path.push(Some((filler.next(0), false))); + } + } else { + // Can't create an authentication path for the beginning of the tree + return None; + } + + for (i, p) in self.tree.parents.iter().enumerate() { + auth_path.push(match p { + Some(node) => Some((*node, true)), + None => Some((filler.next(i + 1), false)), + }); + } + + for i in self.tree.parents.len()..(depth - 1) { + auth_path.push(Some((filler.next(i + 1), false))); + } + assert_eq!(auth_path.len(), depth); + + Some(CommitmentTreeWitness::from_path( + auth_path + .iter() + .map(|n| n.map(|(node, b)| (node.into(), b))) + .collect(), + self.position() as u64, + )) + } +} + /// A witness to a path from a position in a particular Sapling commitment tree /// to the root of that tree. +#[derive(Debug, PartialEq)] pub struct CommitmentTreeWitness { pub auth_path: Vec>, pub position: u64, } impl CommitmentTreeWitness { - pub fn from_slice(mut witness: &[u8]) -> Result { + pub fn from_path(auth_path: Vec>, position: u64) -> Self { + CommitmentTreeWitness { + auth_path, + position, + } + } + + pub fn from_slice(witness: &[u8]) -> Result { + Self::from_slice_with_depth(witness, TREE_DEPTH) + } + + pub fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result { // Skip the first byte, which should be "32" to signify the length of // the following vector of Pedersen hashes. - assert_eq!(witness[0], TREE_DEPTH as u8); + assert_eq!(witness[0], depth as u8); witness = &witness[1..]; // Begin to construct the authentication path - let mut auth_path = vec![None; TREE_DEPTH]; + let mut auth_path = vec![None; depth]; // The vector works in reverse - for i in (0..TREE_DEPTH).rev() { + for i in (0..depth).rev() { // skip length of inner vector assert_eq!(witness[0], 32); // the length of a pedersen hash witness = &witness[1..]; @@ -244,7 +424,7 @@ impl CommitmentTreeWitness { // Given the position, let's finish constructing the authentication // path let mut tmp = position; - for i in 0..TREE_DEPTH { + for i in 0..depth { auth_path[i].as_mut().map(|p| p.1 = (tmp & 1) == 1); tmp >>= 1; @@ -264,7 +444,10 @@ impl CommitmentTreeWitness { #[cfg(test)] mod tests { - use super::{CommitmentTree, Hashable, Node, PathFiller, EMPTY_ROOTS}; + use super::{ + CommitmentTree, CommitmentTreeWitness, Hashable, IncrementalWitness, Node, PathFiller, + EMPTY_ROOTS, + }; use ff::PrimeFieldRepr; use hex; @@ -328,6 +511,26 @@ mod tests { } } + struct TestIncrementalWitness(IncrementalWitness); + + impl TestIncrementalWitness { + fn from_tree(tree: &TestCommitmentTree) -> Self { + TestIncrementalWitness(IncrementalWitness::from_tree(&tree.0)) + } + + fn append(&mut self, node: Node) -> Result<(), ()> { + self.0.append_inner(node, TESTING_DEPTH) + } + + fn root(&self) -> Node { + self.0.root_inner(TESTING_DEPTH) + } + + fn path(&self) -> Option { + self.0.path_inner(TESTING_DEPTH) + } + } + #[test] fn empty_root_test_vectors() { let mut tmp = [0u8; 32]; @@ -410,6 +613,130 @@ mod tests { "5c0bea7e17bde5bee4eb795c2eec3d389a68da587b36dd687b134826ecc09308", ]; + // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_path_sapling.json + let paths = [ + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342037b3a0921a4047e617bde62b8958f86c010e6af6cc650959b9f50af8c7e8392620225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342037b3a0921a4047e617bde62b8958f86c010e6af6cc650959b9f50af8c7e8392620b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f1740220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f1740220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f174022062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f174022062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c157320f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c157320f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c15732062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c15732062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d32220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d32220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d3222062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d3222062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564206ab2e08286c36f6fe4374baebdc28b97e2f1f4ea3544fafd8a6489f42824bf0e20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564206ab2e08286c36f6fe4374baebdc28b97e2f1f4ea3544fafd8a6489f42824bf0e20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342076bd791f7708c0b6f5a348d574032e07ce3b1929daae19530346f5de955d543c20c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342076bd791f7708c0b6f5a348d574032e07ce3b1929daae19530346f5de955d543c203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c20817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca1552022fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030c00000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c2045d573e80606a552974215e13b5d3e7b4dd8675c77b8d612d293475ee139b9472022fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030c00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c2045d573e80606a552974215e13b5d3e7b4dd8675c77b8d612d293475ee139b947208cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260d00000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000", + "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c20afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a5322022fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030c00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c20afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a532208cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260d00000000000000", + "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c205991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349203a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac150e00000000000000", + ]; + fn assert_root_eq(root: Node, expected: &str) { let mut tmp = [0u8; 32]; root.repr @@ -421,6 +748,8 @@ mod tests { let mut tree = TestCommitmentTree::new(); assert_eq!(tree.size(), 0); + let mut witnesses = vec![]; + let mut paths_i = 0; for i in 0..16 { let mut cm = FrRepr::default(); cm.read_le(&hex::decode(commitments[i]).unwrap()[..]) @@ -428,7 +757,10 @@ mod tests { let cm = Node::new(cm); - // Append a commitment to the tree + // Witness here + witnesses.push(TestIncrementalWitness::from_tree(&tree)); + + // Now append a commitment to the tree assert!(tree.append(cm).is_ok()); // Size incremented by one. @@ -436,10 +768,36 @@ mod tests { // Check tree root consistency assert_root_eq(tree.root(), roots[i]); + + let mut first = true; // The first witness can never form a path + for witness in witnesses.as_mut_slice() { + // Append the same commitment to all the witnesses + assert!(witness.append(cm).is_ok()); + + if first { + assert!(witness.path().is_none()); + } else { + let path = witness.path().expect("should be able to create a path"); + let expected = CommitmentTreeWitness::from_slice_with_depth( + &mut hex::decode(paths[paths_i]).unwrap(), + TESTING_DEPTH, + ) + .unwrap(); + assert_eq!(path, expected); + paths_i += 1; + } + + assert_eq!(witness.root(), tree.root()); + + first = false; + } } // Tree should be full now let node = Node::blank(); assert!(tree.append(node).is_err()); + for witness in witnesses.as_mut_slice() { + assert!(witness.append(node).is_err()); + } } } From 70a70690586138fa4e2bb7c97c65b96d8e492c93 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 1 Dec 2018 17:16:32 +0000 Subject: [PATCH 009/105] Helper for serializing Option --- zcash_primitives/src/serialize.rs | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/zcash_primitives/src/serialize.rs b/zcash_primitives/src/serialize.rs index f142943..8312312 100644 --- a/zcash_primitives/src/serialize.rs +++ b/zcash_primitives/src/serialize.rs @@ -82,6 +82,37 @@ impl Vector { } } +pub struct Optional; + +impl Optional { + pub fn read(mut reader: R, func: F) -> io::Result> + where + F: Fn(&mut R) -> io::Result, + { + match reader.read_u8()? { + 0 => Ok(None), + 1 => Ok(Some(func(&mut reader)?)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "non-canonical Option", + )), + } + } + + pub fn write(mut writer: W, val: &Option, func: F) -> io::Result<()> + where + F: Fn(&mut W, &T) -> io::Result<()>, + { + match val { + None => writer.write_u8(0), + Some(e) => { + writer.write_u8(1)?; + func(&mut writer, e) + } + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -153,4 +184,46 @@ mod tests { eval!(vec![7; 260], expected); } } + + #[test] + fn optional() { + macro_rules! eval { + ($value:expr, $expected:expr, $write:expr, $read:expr) => { + let mut data = vec![]; + Optional::write(&mut data, &$value, $write).unwrap(); + assert_eq!(&data[..], &$expected[..]); + match Optional::read(&data[..], $read) { + Ok(v) => assert_eq!(v, $value), + Err(e) => panic!("Unexpected error: {:?}", e), + } + }; + } + + macro_rules! eval_u8 { + ($value:expr, $expected:expr) => { + eval!($value, $expected, |w, e| w.write_u8(*e), |r| r.read_u8()) + }; + } + + macro_rules! eval_vec { + ($value:expr, $expected:expr) => { + eval!( + $value, + $expected, + |w, v| Vector::write(w, v, |w, e| w.write_u8(*e)), + |r| Vector::read(r, |r| r.read_u8()) + ) + }; + } + + eval_u8!(None, [0]); + eval_u8!(Some(0), [1, 0]); + eval_u8!(Some(1), [1, 1]); + eval_u8!(Some(5), [1, 5]); + + eval_vec!(Some(vec![]), [1, 0]); + eval_vec!(Some(vec![0]), [1, 1, 0]); + eval_vec!(Some(vec![1]), [1, 1, 1]); + eval_vec!(Some(vec![5; 8]), [1, 8, 5, 5, 5, 5, 5, 5, 5, 5]); + } } From 9b4186705af5aa63ff871984028322aa5a511e6e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 1 Dec 2018 17:17:16 +0000 Subject: [PATCH 010/105] Add serialization APIs to CommitmentTree and IncrementalWitness --- zcash_primitives/src/merkle_tree.rs | 269 ++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 2a6eaf2..8fbc2a3 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -3,9 +3,11 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::{circuit::sapling::TREE_DEPTH, primitives::Note}; use std::collections::VecDeque; +use std::io::{self, Read, Write}; use std::iter; use sapling::merkle_hash; +use serialize::{Optional, Vector}; const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32; @@ -26,6 +28,16 @@ impl Node { pub fn new(repr: FrRepr) -> Self { Node { repr } } + + pub fn read(mut reader: R) -> io::Result { + let mut repr = FrRepr::default(); + repr.read_le(&mut reader)?; + Ok(Node::new(repr)) + } + + pub fn write(&self, mut writer: W) -> io::Result<()> { + self.repr.write_le(&mut writer) + } } impl Hashable for Node { @@ -93,6 +105,26 @@ impl CommitmentTree { } } + pub fn read(mut reader: R) -> io::Result { + let left = Optional::read(&mut reader, |r| Node::read(r))?; + let right = Optional::read(&mut reader, |r| Node::read(r))?; + let parents = Vector::read(&mut reader, |r| Optional::read(r, |r| Node::read(r)))?; + + Ok(CommitmentTree { + left, + right, + parents, + }) + } + + pub fn write(&self, mut writer: W) -> io::Result<()> { + Optional::write(&mut writer, &self.left, |w, n| n.write(w))?; + Optional::write(&mut writer, &self.right, |w, n| n.write(w))?; + Vector::write(&mut writer, &self.parents, |w, e| { + Optional::write(w, e, |w, n| n.write(w)) + }) + } + /// Returns the number of notes in the tree. pub fn size(&self) -> usize { self.parents.iter().enumerate().fold( @@ -212,6 +244,29 @@ impl IncrementalWitness { } } + pub fn read(mut reader: R) -> io::Result { + let tree = CommitmentTree::read(&mut reader)?; + let filled = Vector::read(&mut reader, |r| Node::read(r))?; + let cursor = Optional::read(&mut reader, |r| CommitmentTree::read(r))?; + + let mut witness = IncrementalWitness { + tree, + filled, + cursor_depth: 0, + cursor, + }; + + witness.cursor_depth = witness.next_depth(); + + Ok(witness) + } + + pub fn write(&self, mut writer: W) -> io::Result<()> { + self.tree.write(&mut writer)?; + Vector::write(&mut writer, &self.filled, |w, n| n.write(w))?; + Optional::write(&mut writer, &self.cursor, |w, t| t.write(w)) + } + /// Returns the position of the witnessed note in the commitment tree. pub fn position(&self) -> usize { self.tree.size() - 1 @@ -452,6 +507,7 @@ mod tests { use ff::PrimeFieldRepr; use hex; use pairing::bls12_381::FrRepr; + use std::io::{self, Read, Write}; const HEX_EMPTY_ROOTS: [&str; 33] = [ "0100000000000000000000000000000000000000000000000000000000000000", @@ -498,6 +554,15 @@ mod tests { TestCommitmentTree(CommitmentTree::new()) } + pub fn read(reader: R) -> io::Result { + let tree = CommitmentTree::read(reader)?; + Ok(TestCommitmentTree(tree)) + } + + pub fn write(&self, writer: W) -> io::Result<()> { + self.0.write(writer) + } + fn size(&self) -> usize { self.0.size() } @@ -518,6 +583,15 @@ mod tests { TestIncrementalWitness(IncrementalWitness::from_tree(&tree.0)) } + pub fn read(reader: R) -> io::Result { + let witness = IncrementalWitness::read(reader)?; + Ok(TestIncrementalWitness(witness)) + } + + pub fn write(&self, writer: W) -> io::Result<()> { + self.0.write(writer) + } + fn append(&mut self, node: Node) -> Result<(), ()> { self.0.append_inner(node, TESTING_DEPTH) } @@ -613,6 +687,26 @@ mod tests { "5c0bea7e17bde5bee4eb795c2eec3d389a68da587b36dd687b134826ecc09308", ]; + // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_serialization_sapling.json + let tree_ser = [ + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145800", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "01f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0003015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + "01f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c013a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac1503015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d", + ]; + // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_path_sapling.json let paths = [ "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000", @@ -737,6 +831,146 @@ mod tests { "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c205991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349203a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac150e00000000000000", ]; + // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_witness_serialization_sapling.json + let witness_ser = [ + "00000001b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5500", + "00000002b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145800", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000001225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145800", + "00000002b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145801017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000001225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145801017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458000001017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0000", + "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826400", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826400", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826400", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a03000", + "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666000101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000", + "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666000101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200", + "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666000101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0000", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0000", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c00", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c00", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51100", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020000", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d000101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020000", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614400", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614400", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c60800", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c60801018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c60801018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300", + "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b61440101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b61440101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d000101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0000", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d000101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0000", + "00000005b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000004225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580003f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660350421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66602130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656403f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c1d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c1d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5111d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564011d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d03c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000", + "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c608076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000", + "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0222fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a53200", + "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a53200", + "01f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0003015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d013a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac1500", + ]; + fn assert_root_eq(root: Node, expected: &str) { let mut tmp = [0u8; 32]; root.repr @@ -745,11 +979,39 @@ mod tests { assert_eq!(hex::encode(tmp), expected); } + fn assert_tree_ser_eq(tree: &TestCommitmentTree, expected: &str) { + // Check that the tree matches its encoding + let mut tmp = Vec::new(); + tree.write(&mut tmp).unwrap(); + assert_eq!(hex::encode(&tmp[..]), expected); + + // Check round-trip encoding + let decoded = TestCommitmentTree::read(&hex::decode(expected).unwrap()[..]).unwrap(); + tmp.clear(); + decoded.write(&mut tmp).unwrap(); + assert_eq!(hex::encode(tmp), expected); + } + + fn assert_witness_ser_eq(witness: &TestIncrementalWitness, expected: &str) { + // Check that the witness matches its encoding + let mut tmp = Vec::new(); + witness.write(&mut tmp).unwrap(); + assert_eq!(hex::encode(&tmp[..]), expected); + + // Check round-trip encoding + let decoded = + TestIncrementalWitness::read(&hex::decode(expected).unwrap()[..]).unwrap(); + tmp.clear(); + decoded.write(&mut tmp).unwrap(); + assert_eq!(hex::encode(tmp), expected); + } + let mut tree = TestCommitmentTree::new(); assert_eq!(tree.size(), 0); let mut witnesses = vec![]; let mut paths_i = 0; + let mut witness_ser_i = 0; for i in 0..16 { let mut cm = FrRepr::default(); cm.read_le(&hex::decode(commitments[i]).unwrap()[..]) @@ -769,6 +1031,9 @@ mod tests { // Check tree root consistency assert_root_eq(tree.root(), roots[i]); + // Check serialization of tree + assert_tree_ser_eq(&tree, tree_ser[i]); + let mut first = true; // The first witness can never form a path for witness in witnesses.as_mut_slice() { // Append the same commitment to all the witnesses @@ -787,6 +1052,10 @@ mod tests { paths_i += 1; } + // Check witness serialization + assert_witness_ser_eq(witness, witness_ser[witness_ser_i]); + witness_ser_i += 1; + assert_eq!(witness.root(), tree.root()); first = false; From 98d7621135b8abcd68a04ab56c20a418edbac047 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 19 Mar 2019 22:10:34 +1300 Subject: [PATCH 011/105] Don't assert when parsing a CommitmentTreeWitness --- zcash_primitives/src/merkle_tree.rs | 31 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 8fbc2a3..3608335 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -436,9 +436,11 @@ impl CommitmentTreeWitness { } pub fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result { - // Skip the first byte, which should be "32" to signify the length of + // Skip the first byte, which should be "depth" to signify the length of // the following vector of Pedersen hashes. - assert_eq!(witness[0], depth as u8); + if witness[0] != depth as u8 { + return Err(()); + } witness = &witness[1..]; // Begin to construct the authentication path @@ -447,7 +449,9 @@ impl CommitmentTreeWitness { // The vector works in reverse for i in (0..depth).rev() { // skip length of inner vector - assert_eq!(witness[0], 32); // the length of a pedersen hash + if witness[0] != 32 { // the length of a pedersen hash + return Err(()); + } witness = &witness[1..]; // Grab the sibling node at this depth in the tree @@ -472,9 +476,10 @@ impl CommitmentTreeWitness { } // Read the position from the witness - let position = witness - .read_u64::() - .expect("should have had index at the end"); + let position = match witness.read_u64::() { + Ok(pos) => pos, + Err(_) => return Err(()), + }; // Given the position, let's finish constructing the authentication // path @@ -488,12 +493,14 @@ impl CommitmentTreeWitness { // The witness should be empty now; if it wasn't, the caller would // have provided more information than they should have, indicating // a bug downstream - assert_eq!(witness.len(), 0); - - Ok(CommitmentTreeWitness { - auth_path, - position, - }) + if witness.is_empty() { + Ok(CommitmentTreeWitness { + auth_path, + position, + }) + } else { + Err(()) + } } } From 263bbe1207b1c3c9e9014f9f74648e110bc35eae Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 19 Mar 2019 22:11:29 +1300 Subject: [PATCH 012/105] Use Iterator::all() in place of Iterator::fold() --- zcash_primitives/src/merkle_tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 3608335..0a830ba 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -145,7 +145,7 @@ impl CommitmentTree { self.left.is_some() && self.right.is_some() && self.parents.len() == depth - 1 - && self.parents.iter().fold(true, |acc, p| acc && p.is_some()) + && self.parents.iter().all(|p| p.is_some()) } /// Adds a note to the tree. Returns an error if the tree is full. From b9cea33804fa5fb8390162ba2e8a54744b55485e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 16 Apr 2019 00:27:44 +0100 Subject: [PATCH 013/105] Move merkle_tree::Node into sapling module This makes the merkle_tree module properly generic over the tree hash. It still hard-codes a depth 32 tree, because Rust doesn't yet support generic sizes, and we are unlikely to need to alter the tree depth in future circuit changes. --- zcash_primitives/src/merkle_tree.rs | 153 +++++++++------------------- zcash_primitives/src/sapling.rs | 64 +++++++++++- zcash_proofs/src/sapling/prover.rs | 10 +- 3 files changed, 118 insertions(+), 109 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 0a830ba..08bf992 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1,81 +1,35 @@ use byteorder::{LittleEndian, ReadBytesExt}; -use ff::{PrimeField, PrimeFieldRepr}; -use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use sapling_crypto::{circuit::sapling::TREE_DEPTH, primitives::Note}; +use sapling_crypto::circuit::sapling::TREE_DEPTH; use std::collections::VecDeque; use std::io::{self, Read, Write}; use std::iter; -use sapling::merkle_hash; +use sapling::SAPLING_COMMITMENT_TREE_DEPTH; use serialize::{Optional, Vector}; -const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32; +/// A hashable node within a Merkle tree. +pub trait Hashable: Clone + Copy { + /// Parses a node from the given byte source. + fn read(reader: R) -> io::Result; + + /// Serializes this node. + fn write(&self, writer: W) -> io::Result<()>; -trait Hashable: Clone + Copy { /// Returns the parent node within the tree of the two given nodes. fn combine(usize, &Self, &Self) -> Self; /// Returns a blank leaf node. fn blank() -> Self; + + /// Returns the empty root for the given depth. + fn empty_root(usize) -> Self; } -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Node { - repr: FrRepr, -} - -impl Node { - pub fn new(repr: FrRepr) -> Self { - Node { repr } - } - - pub fn read(mut reader: R) -> io::Result { - let mut repr = FrRepr::default(); - repr.read_le(&mut reader)?; - Ok(Node::new(repr)) - } - - pub fn write(&self, mut writer: W) -> io::Result<()> { - self.repr.write_le(&mut writer) - } -} - -impl Hashable for Node { - fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self { - Node { - repr: merkle_hash(depth, &lhs.repr, &rhs.repr), - } - } - - fn blank() -> Self { - Node { - repr: Note::::uncommitted().into_repr(), - } - } -} - -impl From for Fr { - fn from(node: Node) -> Self { - Fr::from_repr(node.repr).expect("Tree nodes should be in the prime field") - } -} - -lazy_static! { - static ref EMPTY_ROOTS: Vec = { - let mut v = vec![Node::blank()]; - for d in 0..SAPLING_COMMITMENT_TREE_DEPTH { - let next = Node::combine(d, &v[d], &v[d]); - v.push(next); - } - v - }; -} - -struct PathFiller { +struct PathFiller { queue: VecDeque, } -impl PathFiller { +impl PathFiller { fn empty() -> Self { PathFiller { queue: VecDeque::new(), @@ -83,19 +37,21 @@ impl PathFiller { } fn next(&mut self, depth: usize) -> Node { - self.queue.pop_front().unwrap_or_else(|| EMPTY_ROOTS[depth]) + self.queue + .pop_front() + .unwrap_or_else(|| Node::empty_root(depth)) } } /// A Merkle tree of Sapling note commitments. #[derive(Clone)] -pub struct CommitmentTree { +pub struct CommitmentTree { left: Option, right: Option, parents: Vec>, } -impl CommitmentTree { +impl CommitmentTree { /// Creates an empty tree. pub fn new() -> Self { CommitmentTree { @@ -192,7 +148,7 @@ impl CommitmentTree { self.root_inner(SAPLING_COMMITMENT_TREE_DEPTH, PathFiller::empty()) } - fn root_inner(&self, depth: usize, mut filler: PathFiller) -> Node { + fn root_inner(&self, depth: usize, mut filler: PathFiller) -> Node { assert!(depth > 0); // 1) Hash left and right leaves together. @@ -227,15 +183,15 @@ impl CommitmentTree { } #[derive(Clone)] -pub struct IncrementalWitness { - tree: CommitmentTree, +pub struct IncrementalWitness { + tree: CommitmentTree, filled: Vec, cursor_depth: usize, - cursor: Option, + cursor: Option>, } -impl IncrementalWitness { - pub fn from_tree(tree: &CommitmentTree) -> IncrementalWitness { +impl IncrementalWitness { + pub fn from_tree(tree: &CommitmentTree) -> IncrementalWitness { IncrementalWitness { tree: tree.clone(), filled: vec![], @@ -272,7 +228,7 @@ impl IncrementalWitness { self.tree.size() - 1 } - fn filler(&self) -> PathFiller { + fn filler(&self) -> PathFiller { let cursor_root = self .cursor .as_ref() @@ -374,11 +330,11 @@ impl IncrementalWitness { } /// Returns the current witness, or None if the tree is empty. - pub fn path(&self) -> Option { + pub fn path(&self) -> Option> { self.path_inner(SAPLING_COMMITMENT_TREE_DEPTH) } - fn path_inner(&self, depth: usize) -> Option { + fn path_inner(&self, depth: usize) -> Option> { let mut filler = self.filler(); let mut auth_path = Vec::new(); @@ -406,10 +362,7 @@ impl IncrementalWitness { assert_eq!(auth_path.len(), depth); Some(CommitmentTreeWitness::from_path( - auth_path - .iter() - .map(|n| n.map(|(node, b)| (node.into(), b))) - .collect(), + auth_path, self.position() as u64, )) } @@ -418,13 +371,13 @@ impl IncrementalWitness { /// A witness to a path from a position in a particular Sapling commitment tree /// to the root of that tree. #[derive(Debug, PartialEq)] -pub struct CommitmentTreeWitness { - pub auth_path: Vec>, +pub struct CommitmentTreeWitness { + pub auth_path: Vec>, pub position: u64, } -impl CommitmentTreeWitness { - pub fn from_path(auth_path: Vec>, position: u64) -> Self { +impl CommitmentTreeWitness { + pub fn from_path(auth_path: Vec>, position: u64) -> Self { CommitmentTreeWitness { auth_path, position, @@ -449,7 +402,8 @@ impl CommitmentTreeWitness { // The vector works in reverse for i in (0..depth).rev() { // skip length of inner vector - if witness[0] != 32 { // the length of a pedersen hash + if witness[0] != 32 { + // the length of a pedersen hash return Err(()); } witness = &witness[1..]; @@ -460,11 +414,7 @@ impl CommitmentTreeWitness { witness = &witness[32..]; // Sibling node should be an element of Fr - let sibling = match { - let mut repr = FrRepr::default(); - repr.read_le(&sibling[..]).expect("length is 32 bytes"); - Fr::from_repr(repr) - } { + let sibling = match Node::read(&sibling[..]) { Ok(p) => p, Err(_) => return Err(()), }; @@ -506,10 +456,8 @@ impl CommitmentTreeWitness { #[cfg(test)] mod tests { - use super::{ - CommitmentTree, CommitmentTreeWitness, Hashable, IncrementalWitness, Node, PathFiller, - EMPTY_ROOTS, - }; + use super::{CommitmentTree, CommitmentTreeWitness, Hashable, IncrementalWitness, PathFiller}; + use sapling::Node; use ff::PrimeFieldRepr; use hex; @@ -554,7 +502,7 @@ mod tests { const TESTING_DEPTH: usize = 4; - struct TestCommitmentTree(CommitmentTree); + struct TestCommitmentTree(CommitmentTree); impl TestCommitmentTree { fn new() -> Self { @@ -583,7 +531,7 @@ mod tests { } } - struct TestIncrementalWitness(IncrementalWitness); + struct TestIncrementalWitness(IncrementalWitness); impl TestIncrementalWitness { fn from_tree(tree: &TestCommitmentTree) -> Self { @@ -607,7 +555,7 @@ mod tests { self.0.root_inner(TESTING_DEPTH) } - fn path(&self) -> Option { + fn path(&self) -> Option> { self.0.path_inner(TESTING_DEPTH) } } @@ -616,9 +564,8 @@ mod tests { fn empty_root_test_vectors() { let mut tmp = [0u8; 32]; for i in 0..HEX_EMPTY_ROOTS.len() { - EMPTY_ROOTS[i] - .repr - .write_le(&mut tmp[..]) + Node::empty_root(i) + .write(&mut tmp[..]) .expect("length is 32 bytes"); assert_eq!(hex::encode(tmp), HEX_EMPTY_ROOTS[i]); } @@ -627,10 +574,9 @@ mod tests { #[test] fn sapling_empty_root() { let mut tmp = [0u8; 32]; - CommitmentTree::new() + CommitmentTree::::new() .root() - .repr - .write_le(&mut tmp[..]) + .write(&mut tmp[..]) .expect("length is 32 bytes"); assert_eq!( hex::encode(tmp), @@ -640,12 +586,11 @@ mod tests { #[test] fn empty_commitment_tree_roots() { - let tree = CommitmentTree::new(); + let tree = CommitmentTree::::new(); let mut tmp = [0u8; 32]; for i in 1..HEX_EMPTY_ROOTS.len() { tree.root_inner(i, PathFiller::empty()) - .repr - .write_le(&mut tmp[..]) + .write(&mut tmp[..]) .expect("length is 32 bytes"); assert_eq!(hex::encode(tmp), HEX_EMPTY_ROOTS[i]); } @@ -980,9 +925,7 @@ mod tests { fn assert_root_eq(root: Node, expected: &str) { let mut tmp = [0u8; 32]; - root.repr - .write_le(&mut tmp[..]) - .expect("length is 32 bytes"); + root.write(&mut tmp[..]).expect("length is 32 bytes"); assert_eq!(hex::encode(tmp), expected); } diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 62f5118..356f072 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -1,14 +1,19 @@ -use ff::{BitIterator, PrimeField}; +use ff::{BitIterator, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use rand::OsRng; use sapling_crypto::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, pedersen_hash::{pedersen_hash, Personalization}, + primitives::Note, redjubjub::{PrivateKey, PublicKey, Signature}, }; +use std::io::{self, Read, Write}; +use crate::merkle_tree::Hashable; use JUBJUB; +pub(crate) const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32; + /// Compute a parent node in the Sapling commitment tree given its two children. pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr { let lhs = { @@ -40,6 +45,63 @@ pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr { .into_repr() } +/// A node within a Merkle tree. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Node { + repr: FrRepr, +} + +impl Node { + pub fn new(repr: FrRepr) -> Self { + Node { repr } + } +} + +impl Hashable for Node { + fn read(mut reader: R) -> io::Result { + let mut repr = FrRepr::default(); + repr.read_le(&mut reader)?; + Ok(Node::new(repr)) + } + + fn write(&self, mut writer: W) -> io::Result<()> { + self.repr.write_le(&mut writer) + } + + fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self { + Node { + repr: merkle_hash(depth, &lhs.repr, &rhs.repr), + } + } + + fn blank() -> Self { + Node { + repr: Note::::uncommitted().into_repr(), + } + } + + fn empty_root(depth: usize) -> Self { + EMPTY_ROOTS[depth] + } +} + +impl From for Fr { + fn from(node: Node) -> Self { + Fr::from_repr(node.repr).expect("Tree nodes should be in the prime field") + } +} + +lazy_static! { + static ref EMPTY_ROOTS: Vec = { + let mut v = vec![Node::blank()]; + for d in 0..SAPLING_COMMITMENT_TREE_DEPTH { + let next = Node::combine(d, &v[d], &v[d]); + v.push(next); + } + v + }; +} + /// Create the spendAuthSig for a Sapling SpendDescription. pub fn spend_sig( ask: PrivateKey, diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index feb1d2c..4d63033 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -13,7 +13,7 @@ use sapling_crypto::{ primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, redjubjub::{PrivateKey, PublicKey, Signature}, }; -use zcash_primitives::merkle_tree::CommitmentTreeWitness; +use zcash_primitives::{merkle_tree::CommitmentTreeWitness, sapling::Node}; use super::compute_value_balance; @@ -43,7 +43,7 @@ impl SaplingProvingContext { ar: Fs, value: u64, anchor: Fr, - witness: CommitmentTreeWitness, + witness: CommitmentTreeWitness, proving_key: &Parameters, verifying_key: &PreparedVerifyingKey, params: &JubjubBls12, @@ -112,7 +112,11 @@ impl SaplingProvingContext { payment_address: Some(payment_address), commitment_randomness: Some(rcm), ar: Some(ar), - auth_path: witness.auth_path, + auth_path: witness + .auth_path + .iter() + .map(|n| n.map(|(node, b)| (node.into(), b))) + .collect(), anchor: Some(anchor), }; From e67560b154a203601a45faef346c3bf5be99a7f7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 16 Apr 2019 08:29:09 +0100 Subject: [PATCH 014/105] Document merkle_tree module --- zcash_primitives/src/merkle_tree.rs | 62 ++++++++++++++++++++++++++--- zcash_primitives/src/sapling.rs | 4 +- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 08bf992..3b4af3a 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1,3 +1,5 @@ +//! Implementation of a Merkle tree of commitments used to prove the existence of notes. + use byteorder::{LittleEndian, ReadBytesExt}; use sapling_crypto::circuit::sapling::TREE_DEPTH; use std::collections::VecDeque; @@ -43,7 +45,10 @@ impl PathFiller { } } -/// A Merkle tree of Sapling note commitments. +/// A Merkle tree of note commitments. +/// +/// The depth of the Merkle tree is fixed at 32, equal to the depth of the Sapling +/// commitment tree. #[derive(Clone)] pub struct CommitmentTree { left: Option, @@ -61,6 +66,7 @@ impl CommitmentTree { } } + /// Reads a `CommitmentTree` from its serialized form. pub fn read(mut reader: R) -> io::Result { let left = Optional::read(&mut reader, |r| Node::read(r))?; let right = Optional::read(&mut reader, |r| Node::read(r))?; @@ -73,6 +79,7 @@ impl CommitmentTree { }) } + /// Serializes this tree as an array of bytes. pub fn write(&self, mut writer: W) -> io::Result<()> { Optional::write(&mut writer, &self.left, |w, n| n.write(w))?; Optional::write(&mut writer, &self.right, |w, n| n.write(w))?; @@ -104,7 +111,9 @@ impl CommitmentTree { && self.parents.iter().all(|p| p.is_some()) } - /// Adds a note to the tree. Returns an error if the tree is full. + /// Adds a note to the tree. + /// + /// Returns an error if the tree is full. pub fn append(&mut self, node: Node) -> Result<(), ()> { self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH) } @@ -182,6 +191,40 @@ impl CommitmentTree { } } +/// An updatable witness to a path from a position in a particular [`CommitmentTree`]. +/// +/// Appending the same commitments in the same order to both the original +/// [`CommitmentTree`] and this `IncrementalWitness` will result in a witness to the path +/// from the target position to the root of the updated tree. +/// +/// # Examples +/// +/// ``` +/// extern crate pairing; +/// extern crate rand; +/// extern crate zcash_primitives; +/// +/// use pairing::bls12_381::FrRepr; +/// use rand::{OsRng, Rand}; +/// use zcash_primitives::{ +/// merkle_tree::{CommitmentTree, IncrementalWitness}, +/// sapling::Node, +/// }; +/// +/// let mut rng = OsRng::new().unwrap(); +/// let mut tree = CommitmentTree::::new(); +/// +/// tree.append(Node::new(FrRepr::rand(&mut rng))); +/// tree.append(Node::new(FrRepr::rand(&mut rng))); +/// let mut witness = IncrementalWitness::from_tree(&tree); +/// assert_eq!(witness.position(), 1); +/// assert_eq!(tree.root(), witness.root()); +/// +/// let cmu = Node::new(FrRepr::rand(&mut rng)); +/// tree.append(cmu); +/// witness.append(cmu); +/// assert_eq!(tree.root(), witness.root()); +/// ``` #[derive(Clone)] pub struct IncrementalWitness { tree: CommitmentTree, @@ -191,6 +234,8 @@ pub struct IncrementalWitness { } impl IncrementalWitness { + /// Creates an `IncrementalWitness` for the most recent commitment added to the given + /// [`CommitmentTree`]. pub fn from_tree(tree: &CommitmentTree) -> IncrementalWitness { IncrementalWitness { tree: tree.clone(), @@ -200,6 +245,7 @@ impl IncrementalWitness { } } + /// Reads an `IncrementalWitness` from its serialized form. pub fn read(mut reader: R) -> io::Result { let tree = CommitmentTree::read(&mut reader)?; let filled = Vector::read(&mut reader, |r| Node::read(r))?; @@ -217,6 +263,7 @@ impl IncrementalWitness { Ok(witness) } + /// Serializes this `IncrementalWitness` as an array of bytes. pub fn write(&self, mut writer: W) -> io::Result<()> { self.tree.write(&mut writer)?; Vector::write(&mut writer, &self.filled, |w, n| n.write(w))?; @@ -282,8 +329,9 @@ impl IncrementalWitness { d + skip } - /// Tracks a note that has been added to the underlying tree. Returns an - /// error if the tree is full. + /// Tracks a note that has been added to the underlying tree. + /// + /// Returns an error if the tree is full. pub fn append(&mut self, node: Node) -> Result<(), ()> { self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH) } @@ -368,8 +416,8 @@ impl IncrementalWitness { } } -/// A witness to a path from a position in a particular Sapling commitment tree -/// to the root of that tree. +/// A witness to a path from a position in a particular commitment tree to the root of +/// that tree. #[derive(Debug, PartialEq)] pub struct CommitmentTreeWitness { pub auth_path: Vec>, @@ -377,6 +425,7 @@ pub struct CommitmentTreeWitness { } impl CommitmentTreeWitness { + /// Constructs a witness directly from its path and position. pub fn from_path(auth_path: Vec>, position: u64) -> Self { CommitmentTreeWitness { auth_path, @@ -384,6 +433,7 @@ impl CommitmentTreeWitness { } } + /// Reads a witness from its serialized form. pub fn from_slice(witness: &[u8]) -> Result { Self::from_slice_with_depth(witness, TREE_DEPTH) } diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 356f072..517d9fd 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -1,3 +1,5 @@ +//! Structs and constants specific to the Sapling shielded pool. + use ff::{BitIterator, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use rand::OsRng; @@ -45,7 +47,7 @@ pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr { .into_repr() } -/// A node within a Merkle tree. +/// A node within the Sapling commitment tree. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Node { repr: FrRepr, From 79006ecbdff7a216b78025252fd13c4709f197f2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 16 Apr 2019 08:40:38 +0100 Subject: [PATCH 015/105] Unify Sapling tree depth constants When sapling-crypto is refactored, the zcash_primitives::sapling constant would become the canonical one. --- zcash_primitives/src/merkle_tree.rs | 5 ++--- zcash_primitives/src/sapling.rs | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 3b4af3a..2dcc5cc 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1,7 +1,6 @@ //! Implementation of a Merkle tree of commitments used to prove the existence of notes. use byteorder::{LittleEndian, ReadBytesExt}; -use sapling_crypto::circuit::sapling::TREE_DEPTH; use std::collections::VecDeque; use std::io::{self, Read, Write}; use std::iter; @@ -435,10 +434,10 @@ impl CommitmentTreeWitness { /// Reads a witness from its serialized form. pub fn from_slice(witness: &[u8]) -> Result { - Self::from_slice_with_depth(witness, TREE_DEPTH) + Self::from_slice_with_depth(witness, SAPLING_COMMITMENT_TREE_DEPTH) } - pub fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result { + fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result { // Skip the first byte, which should be "depth" to signify the length of // the following vector of Pedersen hashes. if witness[0] != depth as u8 { diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 517d9fd..0ee808c 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -14,7 +14,8 @@ use std::io::{self, Read, Write}; use crate::merkle_tree::Hashable; use JUBJUB; -pub(crate) const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32; +pub(crate) const SAPLING_COMMITMENT_TREE_DEPTH: usize = + sapling_crypto::circuit::sapling::TREE_DEPTH; /// Compute a parent node in the Sapling commitment tree given its two children. pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr { From 07dbfbef591d39029afef1ae84b52dab116fd0c3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 3 Jun 2019 11:14:01 +0100 Subject: [PATCH 016/105] Address Eirik's review comments --- zcash_primitives/src/merkle_tree.rs | 8 ++++---- zcash_primitives/src/serialize.rs | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 2dcc5cc..e48f8ee 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -90,10 +90,10 @@ impl CommitmentTree { /// Returns the number of notes in the tree. pub fn size(&self) -> usize { self.parents.iter().enumerate().fold( - match (self.left.is_some(), self.right.is_some()) { - (false, false) => 0, - (true, false) | (false, true) => 1, - (true, true) => 2, + match (self.left, self.right) { + (None, None) => 0, + (Some(_), None) | (None, Some(_)) => 1, + (Some(_), Some(_)) => 2, }, |acc, (i, p)| { // Treat occupation of parents array as a binary number diff --git a/zcash_primitives/src/serialize.rs b/zcash_primitives/src/serialize.rs index 8312312..41778dc 100644 --- a/zcash_primitives/src/serialize.rs +++ b/zcash_primitives/src/serialize.rs @@ -221,6 +221,7 @@ mod tests { eval_u8!(Some(1), [1, 1]); eval_u8!(Some(5), [1, 5]); + eval_vec!(None as Option>, [0]); eval_vec!(Some(vec![]), [1, 0]); eval_vec!(Some(vec![0]), [1, 1, 0]); eval_vec!(Some(vec![1]), [1, 1, 1]); From 504c3eaeae9685bf2fe48a21aa0bc150d135409c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 15 Jul 2019 16:33:43 +0200 Subject: [PATCH 017/105] Address Daira's review comments --- zcash_primitives/src/merkle_tree.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index e48f8ee..118d7db 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -87,13 +87,14 @@ impl CommitmentTree { }) } - /// Returns the number of notes in the tree. + /// Returns the number of leaf nodes in the tree. pub fn size(&self) -> usize { self.parents.iter().enumerate().fold( match (self.left, self.right) { (None, None) => 0, - (Some(_), None) | (None, Some(_)) => 1, + (Some(_), None) => 1, (Some(_), Some(_)) => 2, + (None, Some(_)) => unreachable!(), }, |acc, (i, p)| { // Treat occupation of parents array as a binary number @@ -110,7 +111,7 @@ impl CommitmentTree { && self.parents.iter().all(|p| p.is_some()) } - /// Adds a note to the tree. + /// Adds a leaf node to the tree. /// /// Returns an error if the tree is full. pub fn append(&mut self, node: Node) -> Result<(), ()> { @@ -269,7 +270,7 @@ impl IncrementalWitness { Optional::write(&mut writer, &self.cursor, |w, t| t.write(w)) } - /// Returns the position of the witnessed note in the commitment tree. + /// Returns the position of the witnessed leaf node in the commitment tree. pub fn position(&self) -> usize { self.tree.size() - 1 } @@ -328,7 +329,7 @@ impl IncrementalWitness { d + skip } - /// Tracks a note that has been added to the underlying tree. + /// Tracks a leaf node that has been added to the underlying tree. /// /// Returns an error if the tree is full. pub fn append(&mut self, node: Node) -> Result<(), ()> { From 7a6642b221b3936aff93b9eeb35d8d112e128de4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 10 Jul 2019 18:35:05 -0400 Subject: [PATCH 018/105] Migrate ff to rand_core 0.3 (used by rand 0.5) --- Cargo.lock | 17 +++++++++++++++- ff/Cargo.toml | 2 +- ff/ff_derive/src/lib.rs | 43 +++++++++++++++++++---------------------- ff/src/lib.rs | 9 ++++++--- 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03b2a4d..b41ccd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,7 +186,7 @@ version = "0.4.0" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff_derive 0.3.0", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -424,6 +424,19 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "redox_syscall" version = "0.1.40" @@ -623,6 +636,8 @@ dependencies = [ "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" diff --git a/ff/Cargo.toml b/ff/Cargo.toml index 22db67a..f428ccd 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/ebfull/ff" [dependencies] byteorder = "1" -rand = "0.4" +rand_core = "0.3" ff_derive = { version = "0.3.0", path = "ff_derive", optional = true } [features] diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index 45d3445..aea7a50 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -136,13 +136,6 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } - impl ::rand::Rand for #repr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - #repr(rng.gen()) - } - } - impl ::std::fmt::Display for #repr { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { try!(write!(f, "0x")); @@ -839,22 +832,6 @@ fn prime_field_impl( } } - impl ::rand::Rand for #name { - /// Computes a uniformly random element using rejection sampling. - fn rand(rng: &mut R) -> Self { - loop { - let mut tmp = #name(#repr::rand(rng)); - - // Mask away the unused bits at the beginning. - tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; - - if tmp.is_valid() { - return tmp - } - } - } - } - impl From<#name> for #repr { fn from(e: #name) -> #repr { e.into_repr() @@ -904,6 +881,26 @@ fn prime_field_impl( } impl ::ff::Field for #name { + /// Computes a uniformly random element using rejection sampling. + fn random(rng: &mut R) -> Self { + loop { + let mut tmp = { + let mut repr = [0u64; #limbs]; + for i in 0..#limbs { + repr[i] = rng.next_u64(); + } + #name(#repr(repr)) + }; + + // Mask away the unused bits at the beginning. + tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; + + if tmp.is_valid() { + return tmp + } + } + } + #[inline] fn zero() -> Self { #name(#repr::from(0)) diff --git a/ff/src/lib.rs b/ff/src/lib.rs index a9d117f..482dc46 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -1,7 +1,7 @@ #![allow(unused_imports)] extern crate byteorder; -extern crate rand; +extern crate rand_core; #[cfg(feature = "derive")] #[macro_use] @@ -10,14 +10,18 @@ extern crate ff_derive; #[cfg(feature = "derive")] pub use ff_derive::*; +use rand_core::RngCore; use std::error::Error; use std::fmt; use std::io::{self, Read, Write}; /// This trait represents an element of a field. pub trait Field: - Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand + Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static { + /// Returns an element chosen uniformly at random using a user-provided RNG. + fn random(rng: &mut R) -> Self; + /// Returns the zero element of the field, the additive identity. fn zero() -> Self; @@ -100,7 +104,6 @@ pub trait PrimeFieldRepr: + fmt::Debug + fmt::Display + 'static - + rand::Rand + AsRef<[u64]> + AsMut<[u64]> + From From ce6e2a5825a816c5b3bd29b54d76896518a5b1a0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 10 Jul 2019 18:35:57 -0400 Subject: [PATCH 019/105] Migrate group to rand 0.5 --- Cargo.lock | 30 ++++++++++- group/Cargo.toml | 2 +- group/src/lib.rs | 16 ++---- group/src/tests/mod.rs | 111 +++++++++++++++++++++++++---------------- 4 files changed, 104 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b41ccd8..159946b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,6 +136,14 @@ name = "byteorder" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "constant_time_eq" version = "0.1.3" @@ -213,6 +221,11 @@ dependencies = [ "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -267,7 +280,7 @@ name = "group" version = "0.1.0" dependencies = [ "ff 0.4.0", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -424,6 +437,18 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -603,6 +628,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" @@ -611,6 +637,7 @@ dependencies = [ "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" @@ -636,6 +663,7 @@ dependencies = [ "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" diff --git a/group/Cargo.toml b/group/Cargo.toml index ad3f84d..020a5bd 100644 --- a/group/Cargo.toml +++ b/group/Cargo.toml @@ -14,4 +14,4 @@ repository = "https://github.com/ebfull/group" [dependencies] ff = { path = "../ff" } -rand = "0.4" +rand = "0.5" diff --git a/group/src/lib.rs b/group/src/lib.rs index fc924c3..a97a72c 100644 --- a/group/src/lib.rs +++ b/group/src/lib.rs @@ -2,6 +2,7 @@ extern crate ff; extern crate rand; use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField}; +use rand::RngCore; use std::error::Error; use std::fmt; @@ -13,23 +14,16 @@ pub use self::wnaf::Wnaf; /// Projective representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. pub trait CurveProjective: - PartialEq - + Eq - + Sized - + Copy - + Clone - + Send - + Sync - + fmt::Debug - + fmt::Display - + rand::Rand - + 'static + PartialEq + Eq + Sized + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static { type Engine: ScalarEngine; type Scalar: PrimeField + SqrtField; type Base: SqrtField; type Affine: CurveAffine; + /// Returns an element chosen uniformly at random using a user-provided RNG. + fn random(rng: &mut R) -> Self; + /// Returns the additive identity. fn zero() -> Self; diff --git a/group/src/tests/mod.rs b/group/src/tests/mod.rs index b4c47db..5d7e546 100644 --- a/group/src/tests/mod.rs +++ b/group/src/tests/mod.rs @@ -1,9 +1,13 @@ -use rand::{Rand, Rng, SeedableRng, XorShiftRng}; +use ff::{Field, PrimeField}; +use rand::{SeedableRng, XorShiftRng}; use {CurveAffine, CurveProjective, EncodedPoint}; pub fn curve_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); // Negation edge case with zero. { @@ -21,7 +25,7 @@ pub fn curve_tests() { // Addition edge cases with zero { - let mut r = G::rand(&mut rng); + let mut r = G::random(&mut rng); let rcopy = r; r.add_assign(&G::zero()); assert_eq!(r, rcopy); @@ -45,9 +49,10 @@ pub fn curve_tests() { // Transformations { - let a = G::rand(&mut rng); + let a = G::random(&mut rng); let b = a.into_affine().into_projective(); - let c = a.into_affine() + let c = a + .into_affine() .into_projective() .into_affine() .into_projective(); @@ -65,11 +70,12 @@ pub fn curve_tests() { } fn random_wnaf_tests() { - use ff::PrimeField; - use wnaf::*; - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); { let mut table = vec![]; @@ -77,8 +83,8 @@ fn random_wnaf_tests() { for w in 2..14 { for _ in 0..100 { - let g = G::rand(&mut rng); - let s = G::Scalar::rand(&mut rng).into_repr(); + let g = G::random(&mut rng); + let s = G::Scalar::random(&mut rng).into_repr(); let mut g1 = g; g1.mul_assign(s); @@ -95,8 +101,8 @@ fn random_wnaf_tests() { fn only_compiles_if_send(_: &S) {} for _ in 0..100 { - let g = G::rand(&mut rng); - let s = G::Scalar::rand(&mut rng).into_repr(); + let g = G::random(&mut rng); + let s = G::Scalar::random(&mut rng).into_repr(); let mut g1 = g; g1.mul_assign(s); @@ -129,7 +135,8 @@ fn random_wnaf_tests() { let mut wnaf = Wnaf::new(); { // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); + wnaf.base(G::random(&mut rng), 1) + .scalar(G::Scalar::random(&mut rng).into_repr()); } wnaf.base(g, 1).scalar(s) }; @@ -137,7 +144,8 @@ fn random_wnaf_tests() { let mut wnaf = Wnaf::new(); { // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); + wnaf.base(G::random(&mut rng), 1) + .scalar(G::Scalar::random(&mut rng).into_repr()); } wnaf.scalar(s).base(g) }; @@ -145,7 +153,8 @@ fn random_wnaf_tests() { let mut wnaf = Wnaf::new(); { // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); + wnaf.base(G::random(&mut rng), 1) + .scalar(G::Scalar::random(&mut rng).into_repr()); } let mut shared = wnaf.base(g, 1).shared(); @@ -157,7 +166,8 @@ fn random_wnaf_tests() { let mut wnaf = Wnaf::new(); { // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); + wnaf.base(G::random(&mut rng), 1) + .scalar(G::Scalar::random(&mut rng).into_repr()); } let mut shared = wnaf.scalar(s).shared(); @@ -179,14 +189,15 @@ fn random_wnaf_tests() { } fn random_negation_tests() { - use ff::Field; - - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let r = G::rand(&mut rng); + let r = G::random(&mut rng); - let s = G::Scalar::rand(&mut rng); + let s = G::Scalar::random(&mut rng); let mut sneg = s; sneg.negate(); @@ -210,11 +221,14 @@ fn random_negation_tests() { } fn random_doubling_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let mut a = G::rand(&mut rng); - let mut b = G::rand(&mut rng); + let mut a = G::random(&mut rng); + let mut b = G::random(&mut rng); // 2(a + b) let mut tmp1 = a; @@ -237,15 +251,18 @@ fn random_doubling_tests() { } fn random_multiplication_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let mut a = G::rand(&mut rng); - let mut b = G::rand(&mut rng); + let mut a = G::random(&mut rng); + let mut b = G::random(&mut rng); let a_affine = a.into_affine(); let b_affine = b.into_affine(); - let s = G::Scalar::rand(&mut rng); + let s = G::Scalar::random(&mut rng); // s ( a + b ) let mut tmp1 = a; @@ -269,12 +286,15 @@ fn random_multiplication_tests() { } fn random_addition_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let a = G::rand(&mut rng); - let b = G::rand(&mut rng); - let c = G::rand(&mut rng); + let a = G::random(&mut rng); + let b = G::random(&mut rng); + let c = G::random(&mut rng); let a_affine = a.into_affine(); let b_affine = b.into_affine(); let c_affine = c.into_affine(); @@ -347,10 +367,13 @@ fn random_addition_tests() { } fn random_transformation_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let g = G::rand(&mut rng); + let g = G::random(&mut rng); let g_affine = g.into_affine(); let g_projective = g_affine.into_projective(); assert_eq!(g, g_projective); @@ -358,24 +381,25 @@ fn random_transformation_tests() { // Batch normalization for _ in 0..10 { - let mut v = (0..1000).map(|_| G::rand(&mut rng)).collect::>(); + let mut v = (0..1000).map(|_| G::random(&mut rng)).collect::>(); for i in &v { assert!(!i.is_normalized()); } - use rand::distributions::{IndependentSample, Range}; - let between = Range::new(0, 1000); + use rand::distributions::{Distribution, Uniform}; + let between = Uniform::new(0, 1000); // Sprinkle in some normalized points for _ in 0..5 { - v[between.ind_sample(&mut rng)] = G::zero(); + v[between.sample(&mut rng)] = G::zero(); } for _ in 0..5 { - let s = between.ind_sample(&mut rng); + let s = between.sample(&mut rng); v[s] = v[s].into_affine().into_projective(); } - let expected_v = v.iter() + let expected_v = v + .iter() .map(|v| v.into_affine().into_projective()) .collect::>(); G::batch_normalization(&mut v); @@ -389,7 +413,10 @@ fn random_transformation_tests() { } fn random_encoding_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); assert_eq!( G::zero().into_uncompressed().into_affine().unwrap(), @@ -402,7 +429,7 @@ fn random_encoding_tests() { ); for _ in 0..1000 { - let mut r = G::Projective::rand(&mut rng).into_affine(); + let mut r = G::Projective::random(&mut rng).into_affine(); let uncompressed = r.into_uncompressed(); let de_uncompressed = uncompressed.into_affine().unwrap(); From a7e22b3550d1b129d564af12d86a9e634b10ff2e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 10 Jul 2019 18:36:40 -0400 Subject: [PATCH 020/105] Migrate pairing to rand 0.5 --- Cargo.lock | 3 +- pairing/Cargo.toml | 5 +- pairing/src/bls12_381/ec.rs | 24 ++++--- pairing/src/bls12_381/fq.rs | 121 ++++++++++++++++++++++------------ pairing/src/bls12_381/fq12.rs | 31 ++++----- pairing/src/bls12_381/fq2.rs | 19 +++--- pairing/src/bls12_381/fq6.rs | 46 +++++++------ pairing/src/bls12_381/fr.rs | 121 ++++++++++++++++++++++------------ pairing/src/lib.rs | 3 + pairing/src/tests/engine.rs | 49 ++++++++------ pairing/src/tests/field.rs | 60 ++++++++++------- pairing/src/tests/repr.rs | 45 ++++++++----- 12 files changed, 325 insertions(+), 202 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 159946b..7764696 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,7 +385,8 @@ dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "group 0.1.0", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml index 3446f46..b6ba134 100644 --- a/pairing/Cargo.toml +++ b/pairing/Cargo.toml @@ -15,11 +15,14 @@ homepage = "https://github.com/ebfull/pairing" repository = "https://github.com/ebfull/pairing" [dependencies] -rand = "0.4" +rand_core = "0.3" byteorder = "1" ff = { path = "../ff", features = ["derive"] } group = { path = "../group" } +[dev-dependencies] +rand = "0.5" + [features] unstable-features = ["expose-arith"] expose-arith = [] diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index f5a6d8f..b20dea8 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -200,11 +200,16 @@ macro_rules! curve_impl { } - impl Rand for $projective { - fn rand(rng: &mut R) -> Self { + impl CurveProjective for $projective { + type Engine = Bls12; + type Scalar = $scalarfield; + type Base = $basefield; + type Affine = $affine; + + fn random(rng: &mut R) -> Self { loop { - let x = rng.gen(); - let greatest = rng.gen(); + let x = $basefield::random(rng); + let greatest = rng.next_u32() % 2 != 0; if let Some(p) = $affine::get_point_from_x(x, greatest) { let p = p.scale_by_cofactor(); @@ -215,13 +220,6 @@ macro_rules! curve_impl { } } } - } - - impl CurveProjective for $projective { - type Engine = Bls12; - type Scalar = $scalarfield; - type Base = $basefield; - type Affine = $affine; // The point at infinity is always represented by // Z = 0. @@ -629,7 +627,7 @@ pub mod g1 { use super::g2::G2Affine; use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; - use rand::{Rand, Rng}; + use rand_core::RngCore; use std::fmt; use {Engine, PairingCurveAffine}; @@ -1276,7 +1274,7 @@ pub mod g2 { use super::g1::G1Affine; use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; - use rand::{Rand, Rng}; + use rand_core::RngCore; use std::fmt; use {Engine, PairingCurveAffine}; diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index fd0d416..b006812 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -1173,7 +1173,7 @@ fn test_neg_one() { } #[cfg(test)] -use rand::{Rand, SeedableRng, XorShiftRng}; +use rand::{SeedableRng, XorShiftRng}; #[test] fn test_fq_repr_ordering() { @@ -1396,7 +1396,10 @@ fn test_fq_repr_num_bits() { #[test] fn test_fq_repr_sub_noborrow() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut t = FqRepr([ 0x827a4a08041ebd9, @@ -1426,7 +1429,7 @@ fn test_fq_repr_sub_noborrow() { ); for _ in 0..1000 { - let mut a = FqRepr::rand(&mut rng); + let mut a = Fq::random(&mut rng).into_repr(); a.0[5] >>= 30; let mut b = a; for _ in 0..10 { @@ -1483,7 +1486,10 @@ fn test_fq_repr_sub_noborrow() { #[test] fn test_fq_repr_add_nocarry() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut t = FqRepr([ 0x827a4a08041ebd9, @@ -1514,9 +1520,9 @@ fn test_fq_repr_add_nocarry() { // Test for the associativity of addition. for _ in 0..1000 { - let mut a = FqRepr::rand(&mut rng); - let mut b = FqRepr::rand(&mut rng); - let mut c = FqRepr::rand(&mut rng); + let mut a = Fq::random(&mut rng).into_repr(); + let mut b = Fq::random(&mut rng).into_repr(); + let mut c = Fq::random(&mut rng).into_repr(); // Unset the first few bits, so that overflow won't occur. a.0[5] >>= 3; @@ -1595,10 +1601,13 @@ fn test_fq_is_valid() { ])).is_valid() ); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); assert!(a.is_valid()); } } @@ -1708,13 +1717,16 @@ fn test_fq_add_assign() { // Test associativity - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Generate a, b, c and ensure (a + b) + c == a + (b + c). - let a = Fq::rand(&mut rng); - let b = Fq::rand(&mut rng); - let c = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); + let b = Fq::random(&mut rng); + let c = Fq::random(&mut rng); let mut tmp1 = a; tmp1.add_assign(&b); @@ -1818,12 +1830,15 @@ fn test_fq_sub_assign() { ); } - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure that (a - b) + (b - a) = 0. - let a = Fq::rand(&mut rng); - let b = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); + let b = Fq::random(&mut rng); let mut tmp1 = a; tmp1.sub_assign(&b); @@ -1865,13 +1880,16 @@ fn test_fq_mul_assign() { ])) ); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000000 { // Ensure that (a * b) * c = a * (b * c) - let a = Fq::rand(&mut rng); - let b = Fq::rand(&mut rng); - let c = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); + let b = Fq::random(&mut rng); + let c = Fq::random(&mut rng); let mut tmp1 = a; tmp1.mul_assign(&b); @@ -1887,10 +1905,10 @@ fn test_fq_mul_assign() { for _ in 0..1000000 { // Ensure that r * (a + b + c) = r*a + r*b + r*c - let r = Fq::rand(&mut rng); - let mut a = Fq::rand(&mut rng); - let mut b = Fq::rand(&mut rng); - let mut c = Fq::rand(&mut rng); + let r = Fq::random(&mut rng); + let mut a = Fq::random(&mut rng); + let mut b = Fq::random(&mut rng); + let mut c = Fq::random(&mut rng); let mut tmp1 = a; tmp1.add_assign(&b); @@ -1932,11 +1950,14 @@ fn test_fq_squaring() { ])).unwrap() ); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000000 { // Ensure that (a * a) = a^2 - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); let mut tmp = a; tmp.square(); @@ -1952,13 +1973,16 @@ fn test_fq_squaring() { fn test_fq_inverse() { assert!(Fq::zero().inverse().is_none()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let one = Fq::one(); for _ in 0..1000 { // Ensure that a * a^-1 = 1 - let mut a = Fq::rand(&mut rng); + let mut a = Fq::random(&mut rng); let ainv = a.inverse().unwrap(); a.mul_assign(&ainv); assert_eq!(a, one); @@ -1967,11 +1991,14 @@ fn test_fq_inverse() { #[test] fn test_fq_double() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure doubling a is equivalent to adding a to itself. - let mut a = Fq::rand(&mut rng); + let mut a = Fq::random(&mut rng); let mut b = a; b.add_assign(&a); a.double(); @@ -1988,11 +2015,14 @@ fn test_fq_negate() { assert!(a.is_zero()); } - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure (a - (-a)) = 0. - let mut a = Fq::rand(&mut rng); + let mut a = Fq::random(&mut rng); let mut b = a; b.negate(); a.add_assign(&b); @@ -2003,12 +2033,15 @@ fn test_fq_negate() { #[test] fn test_fq_pow() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for i in 0..1000 { // Exponentiate by various small numbers and ensure it consists with repeated // multiplication. - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); let target = a.pow(&[i]); let mut c = Fq::one(); for _ in 0..i { @@ -2019,7 +2052,7 @@ fn test_fq_pow() { for _ in 0..1000 { // Exponentiating by the modulus should have no effect in a prime field. - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); assert_eq!(a, a.pow(Fq::char())); } @@ -2029,13 +2062,16 @@ fn test_fq_pow() { fn test_fq_sqrt() { use ff::SqrtField; - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero()); for _ in 0..1000 { // Ensure sqrt(a^2) = a or -a - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); let mut nega = a; nega.negate(); let mut b = a; @@ -2048,7 +2084,7 @@ fn test_fq_sqrt() { for _ in 0..1000 { // Ensure sqrt(a)^2 = a for random a - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); if let Some(mut tmp) = a.sqrt() { tmp.square(); @@ -2108,11 +2144,14 @@ fn test_fq_from_into_repr() { // Zero should be in the field. assert!(Fq::from_repr(FqRepr::from(0)).unwrap().is_zero()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Try to turn Fq elements into representations and back again, and compare. - let a = Fq::rand(&mut rng); + let a = Fq::random(&mut rng); let a_repr = a.into_repr(); let b_repr = FqRepr::from(a); assert_eq!(a_repr, b_repr); @@ -2205,7 +2244,7 @@ fn test_fq_ordering() { #[test] fn fq_repr_tests() { - ::tests::repr::random_repr_tests::(); + ::tests::repr::random_repr_tests::(); } #[test] diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index b24fcaa..4f675cf 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -2,7 +2,7 @@ use super::fq::FROBENIUS_COEFF_FQ12_C1; use super::fq2::Fq2; use super::fq6::Fq6; use ff::Field; -use rand::{Rand, Rng}; +use rand_core::{RngCore}; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -17,15 +17,6 @@ impl ::std::fmt::Display for Fq12 { } } -impl Rand for Fq12 { - fn rand(rng: &mut R) -> Self { - Fq12 { - c0: rng.gen(), - c1: rng.gen(), - } - } -} - impl Fq12 { pub fn conjugate(&mut self) { self.c1.negate(); @@ -49,6 +40,13 @@ impl Fq12 { } impl Field for Fq12 { + fn random(rng: &mut R) -> Self { + Fq12 { + c0: Fq6::random(rng), + c1: Fq6::random(rng), + } + } + fn zero() -> Self { Fq12 { c0: Fq6::zero(), @@ -153,13 +151,16 @@ use rand::{SeedableRng, XorShiftRng}; #[test] fn test_fq12_mul_by_014() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let c0 = Fq2::rand(&mut rng); - let c1 = Fq2::rand(&mut rng); - let c5 = Fq2::rand(&mut rng); - let mut a = Fq12::rand(&mut rng); + let c0 = Fq2::random(&mut rng); + let c1 = Fq2::random(&mut rng); + let c5 = Fq2::random(&mut rng); + let mut a = Fq12::random(&mut rng); let mut b = a; a.mul_by_014(&c0, &c1, &c5); diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index 363439a..c69f13c 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -1,6 +1,6 @@ use super::fq::{FROBENIUS_COEFF_FQ2_C1, Fq, NEGATIVE_ONE}; use ff::{Field, SqrtField}; -use rand::{Rand, Rng}; +use rand_core::RngCore; use std::cmp::Ordering; @@ -56,16 +56,14 @@ impl Fq2 { } } -impl Rand for Fq2 { - fn rand(rng: &mut R) -> Self { +impl Field for Fq2 { + fn random(rng: &mut R) -> Self { Fq2 { - c0: rng.gen(), - c1: rng.gen(), + c0: Fq::random(rng), + c1: Fq::random(rng), } } -} -impl Field for Fq2 { fn zero() -> Self { Fq2 { c0: Fq::zero(), @@ -883,7 +881,10 @@ use rand::{SeedableRng, XorShiftRng}; #[test] fn test_fq2_mul_nonresidue() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let nqr = Fq2 { c0: Fq::one(), @@ -891,7 +892,7 @@ fn test_fq2_mul_nonresidue() { }; for _ in 0..1000 { - let mut a = Fq2::rand(&mut rng); + let mut a = Fq2::random(&mut rng); let mut b = a; a.mul_by_nonresidue(); b.mul_assign(&nqr); diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index 36c6e28..21c8310 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -1,7 +1,7 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2}; use super::fq2::Fq2; use ff::Field; -use rand::{Rand, Rng}; +use rand_core::RngCore; /// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2). #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -17,15 +17,6 @@ impl ::std::fmt::Display for Fq6 { } } -impl Rand for Fq6 { - fn rand(rng: &mut R) -> Self { - Fq6 { - c0: rng.gen(), - c1: rng.gen(), - c2: rng.gen(), - } - } -} impl Fq6 { /// Multiply by quadratic nonresidue v. @@ -110,6 +101,14 @@ impl Fq6 { } impl Field for Fq6 { + fn random(rng: &mut R) -> Self { + Fq6 { + c0: Fq2::random(rng), + c1: Fq2::random(rng), + c2: Fq2::random(rng), + } + } + fn zero() -> Self { Fq6 { c0: Fq2::zero(), @@ -306,7 +305,10 @@ use rand::{SeedableRng, XorShiftRng}; #[test] fn test_fq6_mul_nonresidue() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let nqr = Fq6 { c0: Fq2::zero(), @@ -315,7 +317,7 @@ fn test_fq6_mul_nonresidue() { }; for _ in 0..1000 { - let mut a = Fq6::rand(&mut rng); + let mut a = Fq6::random(&mut rng); let mut b = a; a.mul_by_nonresidue(); b.mul_assign(&nqr); @@ -326,11 +328,14 @@ fn test_fq6_mul_nonresidue() { #[test] fn test_fq6_mul_by_1() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let c1 = Fq2::rand(&mut rng); - let mut a = Fq6::rand(&mut rng); + let c1 = Fq2::random(&mut rng); + let mut a = Fq6::random(&mut rng); let mut b = a; a.mul_by_1(&c1); @@ -346,12 +351,15 @@ fn test_fq6_mul_by_1() { #[test] fn test_fq6_mul_by_01() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let c0 = Fq2::rand(&mut rng); - let c1 = Fq2::rand(&mut rng); - let mut a = Fq6::rand(&mut rng); + let c0 = Fq2::random(&mut rng); + let c1 = Fq2::random(&mut rng); + let mut a = Fq6::random(&mut rng); let mut b = a; a.mul_by_01(&c0, &c1); diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index 5e57631..20811cd 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -6,7 +6,7 @@ use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; pub struct Fr(FrRepr); #[cfg(test)] -use rand::{Rand, SeedableRng, XorShiftRng}; +use rand::{SeedableRng, XorShiftRng}; #[test] fn test_fr_repr_ordering() { @@ -197,7 +197,10 @@ fn test_fr_repr_num_bits() { #[test] fn test_fr_repr_sub_noborrow() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut t = FrRepr([ 0x8e62a7e85264e2c3, @@ -221,7 +224,7 @@ fn test_fr_repr_sub_noborrow() { ); for _ in 0..1000 { - let mut a = FrRepr::rand(&mut rng); + let mut a = Fr::random(&mut rng).into_repr(); a.0[3] >>= 30; let mut b = a; for _ in 0..10 { @@ -296,7 +299,10 @@ fn test_fr_legendre() { #[test] fn test_fr_repr_add_nocarry() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut t = FrRepr([ 0xd64f669809cbc6a4, @@ -322,9 +328,9 @@ fn test_fr_repr_add_nocarry() { // Test for the associativity of addition. for _ in 0..1000 { - let mut a = FrRepr::rand(&mut rng); - let mut b = FrRepr::rand(&mut rng); - let mut c = FrRepr::rand(&mut rng); + let mut a = Fr::random(&mut rng).into_repr(); + let mut b = Fr::random(&mut rng).into_repr(); + let mut c = Fr::random(&mut rng).into_repr(); // Unset the first few bits, so that overflow won't occur. a.0[3] >>= 3; @@ -397,10 +403,13 @@ fn test_fr_is_valid() { ])).is_valid() ); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); assert!(a.is_valid()); } } @@ -492,13 +501,16 @@ fn test_fr_add_assign() { // Test associativity - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Generate a, b, c and ensure (a + b) + c == a + (b + c). - let a = Fr::rand(&mut rng); - let b = Fr::rand(&mut rng); - let c = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); + let b = Fr::random(&mut rng); + let c = Fr::random(&mut rng); let mut tmp1 = a; tmp1.add_assign(&b); @@ -586,12 +598,15 @@ fn test_fr_sub_assign() { ); } - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure that (a - b) + (b - a) = 0. - let a = Fr::rand(&mut rng); - let b = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); + let b = Fr::random(&mut rng); let mut tmp1 = a; tmp1.sub_assign(&b); @@ -627,13 +642,16 @@ fn test_fr_mul_assign() { ])) ); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000000 { // Ensure that (a * b) * c = a * (b * c) - let a = Fr::rand(&mut rng); - let b = Fr::rand(&mut rng); - let c = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); + let b = Fr::random(&mut rng); + let c = Fr::random(&mut rng); let mut tmp1 = a; tmp1.mul_assign(&b); @@ -649,10 +667,10 @@ fn test_fr_mul_assign() { for _ in 0..1000000 { // Ensure that r * (a + b + c) = r*a + r*b + r*c - let r = Fr::rand(&mut rng); - let mut a = Fr::rand(&mut rng); - let mut b = Fr::rand(&mut rng); - let mut c = Fr::rand(&mut rng); + let r = Fr::random(&mut rng); + let mut a = Fr::random(&mut rng); + let mut b = Fr::random(&mut rng); + let mut c = Fr::random(&mut rng); let mut tmp1 = a; tmp1.add_assign(&b); @@ -690,11 +708,14 @@ fn test_fr_squaring() { ])).unwrap() ); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000000 { // Ensure that (a * a) = a^2 - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); let mut tmp = a; tmp.square(); @@ -710,13 +731,16 @@ fn test_fr_squaring() { fn test_fr_inverse() { assert!(Fr::zero().inverse().is_none()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let one = Fr::one(); for _ in 0..1000 { // Ensure that a * a^-1 = 1 - let mut a = Fr::rand(&mut rng); + let mut a = Fr::random(&mut rng); let ainv = a.inverse().unwrap(); a.mul_assign(&ainv); assert_eq!(a, one); @@ -725,11 +749,14 @@ fn test_fr_inverse() { #[test] fn test_fr_double() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure doubling a is equivalent to adding a to itself. - let mut a = Fr::rand(&mut rng); + let mut a = Fr::random(&mut rng); let mut b = a; b.add_assign(&a); a.double(); @@ -746,11 +773,14 @@ fn test_fr_negate() { assert!(a.is_zero()); } - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure (a - (-a)) = 0. - let mut a = Fr::rand(&mut rng); + let mut a = Fr::random(&mut rng); let mut b = a; b.negate(); a.add_assign(&b); @@ -761,12 +791,15 @@ fn test_fr_negate() { #[test] fn test_fr_pow() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for i in 0..1000 { // Exponentiate by various small numbers and ensure it consists with repeated // multiplication. - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); let target = a.pow(&[i]); let mut c = Fr::one(); for _ in 0..i { @@ -777,7 +810,7 @@ fn test_fr_pow() { for _ in 0..1000 { // Exponentiating by the modulus should have no effect in a prime field. - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); assert_eq!(a, a.pow(Fr::char())); } @@ -787,13 +820,16 @@ fn test_fr_pow() { fn test_fr_sqrt() { use ff::SqrtField; - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); assert_eq!(Fr::zero().sqrt().unwrap(), Fr::zero()); for _ in 0..1000 { // Ensure sqrt(a^2) = a or -a - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); let mut nega = a; nega.negate(); let mut b = a; @@ -806,7 +842,7 @@ fn test_fr_sqrt() { for _ in 0..1000 { // Ensure sqrt(a)^2 = a for random a - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); if let Some(mut tmp) = a.sqrt() { tmp.square(); @@ -858,11 +894,14 @@ fn test_fr_from_into_repr() { // Zero should be in the field. assert!(Fr::from_repr(FrRepr::from(0)).unwrap().is_zero()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Try to turn Fr elements into representations and back again, and compare. - let a = Fr::rand(&mut rng); + let a = Fr::random(&mut rng); let a_repr = a.into_repr(); let b_repr = FrRepr::from(a); assert_eq!(a_repr, b_repr); @@ -982,5 +1021,5 @@ fn fr_field_tests() { #[test] fn fr_repr_tests() { - ::tests::repr::random_repr_tests::(); + ::tests::repr::random_repr_tests::(); } diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index 686938f..d498c35 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -14,6 +14,9 @@ extern crate byteorder; extern crate ff; extern crate group; +extern crate rand_core; + +#[cfg(test)] extern crate rand; #[cfg(test)] diff --git a/pairing/src/tests/engine.rs b/pairing/src/tests/engine.rs index 7b1944d..8616129 100644 --- a/pairing/src/tests/engine.rs +++ b/pairing/src/tests/engine.rs @@ -1,14 +1,17 @@ use group::{CurveAffine, CurveProjective}; -use rand::{Rand, SeedableRng, XorShiftRng}; +use rand::{SeedableRng, XorShiftRng}; use {Engine, Field, PairingCurveAffine, PrimeField}; pub fn engine_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..10 { - let a = E::G1::rand(&mut rng).into_affine(); - let b = E::G2::rand(&mut rng).into_affine(); + let a = E::G1::random(&mut rng).into_affine(); + let b = E::G2::random(&mut rng).into_affine(); assert!(a.pairing_with(&b) == b.pairing_with(&a)); assert!(a.pairing_with(&b) == E::pairing(a, b)); @@ -18,10 +21,10 @@ pub fn engine_tests() { let z1 = E::G1Affine::zero().prepare(); let z2 = E::G2Affine::zero().prepare(); - let a = E::G1::rand(&mut rng).into_affine().prepare(); - let b = E::G2::rand(&mut rng).into_affine().prepare(); - let c = E::G1::rand(&mut rng).into_affine().prepare(); - let d = E::G2::rand(&mut rng).into_affine().prepare(); + let a = E::G1::random(&mut rng).into_affine().prepare(); + let b = E::G2::random(&mut rng).into_affine().prepare(); + let c = E::G1::random(&mut rng).into_affine().prepare(); + let d = E::G2::random(&mut rng).into_affine().prepare(); assert_eq!( E::Fqk::one(), @@ -49,12 +52,15 @@ pub fn engine_tests() { } fn random_miller_loop_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); // Exercise the miller loop for a reduced pairing for _ in 0..1000 { - let a = E::G1::rand(&mut rng); - let b = E::G2::rand(&mut rng); + let a = E::G1::random(&mut rng); + let b = E::G2::random(&mut rng); let p2 = E::pairing(a, b); @@ -68,10 +74,10 @@ fn random_miller_loop_tests() { // Exercise a double miller loop for _ in 0..1000 { - let a = E::G1::rand(&mut rng); - let b = E::G2::rand(&mut rng); - let c = E::G1::rand(&mut rng); - let d = E::G2::rand(&mut rng); + let a = E::G1::random(&mut rng); + let b = E::G2::random(&mut rng); + let c = E::G1::random(&mut rng); + let d = E::G2::random(&mut rng); let ab = E::pairing(a, b); let cd = E::pairing(c, d); @@ -92,14 +98,17 @@ fn random_miller_loop_tests() { } fn random_bilinearity_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let a = E::G1::rand(&mut rng); - let b = E::G2::rand(&mut rng); + let a = E::G1::random(&mut rng); + let b = E::G2::random(&mut rng); - let c = E::Fr::rand(&mut rng); - let d = E::Fr::rand(&mut rng); + let c = E::Fr::random(&mut rng); + let d = E::Fr::random(&mut rng); let mut ac = a; ac.mul_assign(c); diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 55396a7..0f2f1b2 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -2,11 +2,14 @@ use ff::{Field, LegendreSymbol, PrimeField, SqrtField}; use rand::{Rng, SeedableRng, XorShiftRng}; pub fn random_frobenius_tests>(characteristic: C, maxpower: usize) { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { for i in 0..(maxpower + 1) { - let mut a = F::rand(&mut rng); + let mut a = F::random(&mut rng); let mut b = a; for _ in 0..i { @@ -20,10 +23,13 @@ pub fn random_frobenius_tests>(characteristic: C, maxp } pub fn random_sqrt_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..10000 { - let a = F::rand(&mut rng); + let a = F::random(&mut rng); let mut b = a; b.square(); assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); @@ -54,7 +60,10 @@ pub fn random_sqrt_tests() { } pub fn random_field_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); random_multiplication_tests::(&mut rng); random_addition_tests::(&mut rng); @@ -76,14 +85,14 @@ pub fn random_field_tests() { // Multiplication by zero { - let mut a = F::rand(&mut rng); + let mut a = F::random(&mut rng); a.mul_assign(&F::zero()); assert!(a.is_zero()); } // Addition by zero { - let mut a = F::rand(&mut rng); + let mut a = F::random(&mut rng); let copy = a; a.add_assign(&F::zero()); assert_eq!(a, copy); @@ -106,7 +115,10 @@ pub fn from_str_tests() { } { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let n: u64 = rng.gen(); @@ -126,9 +138,9 @@ pub fn from_str_tests() { fn random_multiplication_tests(rng: &mut R) { for _ in 0..10000 { - let a = F::rand(rng); - let b = F::rand(rng); - let c = F::rand(rng); + let a = F::random(rng); + let b = F::random(rng); + let c = F::random(rng); let mut t0 = a; // (a * b) * c t0.mul_assign(&b); @@ -149,9 +161,9 @@ fn random_multiplication_tests(rng: &mut R) { fn random_addition_tests(rng: &mut R) { for _ in 0..10000 { - let a = F::rand(rng); - let b = F::rand(rng); - let c = F::rand(rng); + let a = F::random(rng); + let b = F::random(rng); + let c = F::random(rng); let mut t0 = a; // (a + b) + c t0.add_assign(&b); @@ -172,8 +184,8 @@ fn random_addition_tests(rng: &mut R) { fn random_subtraction_tests(rng: &mut R) { for _ in 0..10000 { - let a = F::rand(rng); - let b = F::rand(rng); + let b = F::random(rng); + let a = F::random(rng); let mut t0 = a; // (a - b) t0.sub_assign(&b); @@ -190,7 +202,7 @@ fn random_subtraction_tests(rng: &mut R) { fn random_negation_tests(rng: &mut R) { for _ in 0..10000 { - let a = F::rand(rng); + let a = F::random(rng); let mut b = a; b.negate(); b.add_assign(&a); @@ -201,7 +213,7 @@ fn random_negation_tests(rng: &mut R) { fn random_doubling_tests(rng: &mut R) { for _ in 0..10000 { - let mut a = F::rand(rng); + let mut a = F::random(rng); let mut b = a; a.add_assign(&b); b.double(); @@ -212,7 +224,7 @@ fn random_doubling_tests(rng: &mut R) { fn random_squaring_tests(rng: &mut R) { for _ in 0..10000 { - let mut a = F::rand(rng); + let mut a = F::random(rng); let mut b = a; a.mul_assign(&b); b.square(); @@ -225,7 +237,7 @@ fn random_inversion_tests(rng: &mut R) { assert!(F::zero().inverse().is_none()); for _ in 0..10000 { - let mut a = F::rand(rng); + let mut a = F::random(rng); let b = a.inverse().unwrap(); // probablistically nonzero a.mul_assign(&b); @@ -237,10 +249,10 @@ fn random_expansion_tests(rng: &mut R) { for _ in 0..10000 { // Compare (a + b)(c + d) and (a*c + b*c + a*d + b*d) - let a = F::rand(rng); - let b = F::rand(rng); - let c = F::rand(rng); - let d = F::rand(rng); + let a = F::random(rng); + let b = F::random(rng); + let c = F::random(rng); + let d = F::random(rng); let mut t0 = a; t0.add_assign(&b); diff --git a/pairing/src/tests/repr.rs b/pairing/src/tests/repr.rs index 09dd441..692c4d3 100644 --- a/pairing/src/tests/repr.rs +++ b/pairing/src/tests/repr.rs @@ -1,21 +1,24 @@ -use ff::PrimeFieldRepr; +use ff::{PrimeField, PrimeFieldRepr}; use rand::{SeedableRng, XorShiftRng}; -pub fn random_repr_tests() { - random_encoding_tests::(); - random_shl_tests::(); - random_shr_tests::(); +pub fn random_repr_tests() { + random_encoding_tests::

(); + random_shl_tests::

(); + random_shr_tests::

(); } -fn random_encoding_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); +fn random_encoding_tests() { + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let r = R::rand(&mut rng); + let r = P::random(&mut rng).into_repr(); // Big endian { - let mut rdecoded = R::default(); + let mut rdecoded =

::Repr::default(); let mut v: Vec = vec![]; r.write_be(&mut v).unwrap(); @@ -26,7 +29,7 @@ fn random_encoding_tests() { // Little endian { - let mut rdecoded = R::default(); + let mut rdecoded =

::Repr::default(); let mut v: Vec = vec![]; r.write_le(&mut v).unwrap(); @@ -36,8 +39,8 @@ fn random_encoding_tests() { } { - let mut rdecoded_le = R::default(); - let mut rdecoded_be_flip = R::default(); + let mut rdecoded_le =

::Repr::default(); + let mut rdecoded_be_flip =

::Repr::default(); let mut v: Vec = vec![]; r.write_le(&mut v).unwrap(); @@ -55,11 +58,14 @@ fn random_encoding_tests() { } } -fn random_shl_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); +fn random_shl_tests() { + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { - let r = R::rand(&mut rng); + let r = P::random(&mut rng).into_repr(); for shift in 0..(r.num_bits() + 1) { let mut r1 = r; @@ -76,11 +82,14 @@ fn random_shl_tests() { } } -fn random_shr_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); +fn random_shr_tests() { + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { - let r = R::rand(&mut rng); + let r = P::random(&mut rng).into_repr(); for shift in 0..(r.num_bits() + 1) { let mut r1 = r; From 4606a0cefb4b557f3fdbf0e38fa481d0aa3b7463 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 10 Jul 2019 19:40:20 -0400 Subject: [PATCH 021/105] Migrate bellman to rand 0.5 --- Cargo.lock | 3 ++- bellman/Cargo.toml | 5 ++++- bellman/src/domain.rs | 20 ++++++++++---------- bellman/src/groth16/generator.rs | 18 +++++++++--------- bellman/src/groth16/mod.rs | 6 +++--- bellman/src/groth16/prover.rs | 8 ++++---- bellman/src/groth16/tests/dummy_engine.rs | 22 +++++++++------------- bellman/src/lib.rs | 5 ++++- bellman/src/multiexp.rs | 6 +++--- bellman/tests/mimc.rs | 10 +++++----- 10 files changed, 53 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7764696..9eb4dc4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,7 +61,8 @@ dependencies = [ "group 0.1.0", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index 20602c2..72a8034 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/ebfull/bellman" version = "0.1.0" [dependencies] -rand = "0.4" +rand_core = "0.3" bit-vec = "0.4.4" ff = { path = "../ff" } futures = "0.1" @@ -20,6 +20,9 @@ crossbeam = { version = "0.3", optional = true } pairing = { path = "../pairing", optional = true } byteorder = "1" +[dev-dependencies] +rand = "0.5" + [features] groth16 = ["pairing"] multicore = ["futures-cpupool", "crossbeam", "num_cpus"] diff --git a/bellman/src/domain.rs b/bellman/src/domain.rs index 4606ce5..5d7d500 100644 --- a/bellman/src/domain.rs +++ b/bellman/src/domain.rs @@ -375,16 +375,16 @@ fn parallel_fft>( #[test] fn polynomial_arith() { use pairing::bls12_381::Bls12; - use rand::{self, Rand}; + use rand_core::RngCore; - fn test_mul(rng: &mut R) + fn test_mul(rng: &mut R) { let worker = Worker::new(); for coeffs_a in 0..70 { for coeffs_b in 0..70 { - let mut a: Vec<_> = (0..coeffs_a).map(|_| Scalar::(E::Fr::rand(rng))).collect(); - let mut b: Vec<_> = (0..coeffs_b).map(|_| Scalar::(E::Fr::rand(rng))).collect(); + let mut a: Vec<_> = (0..coeffs_a).map(|_| Scalar::(E::Fr::random(rng))).collect(); + let mut b: Vec<_> = (0..coeffs_b).map(|_| Scalar::(E::Fr::random(rng))).collect(); // naive evaluation let mut naive = vec![Scalar(E::Fr::zero()); coeffs_a + coeffs_b]; @@ -423,9 +423,9 @@ fn polynomial_arith() { #[test] fn fft_composition() { use pairing::bls12_381::Bls12; - use rand; + use rand_core::RngCore; - fn test_comp(rng: &mut R) + fn test_comp(rng: &mut R) { let worker = Worker::new(); @@ -434,7 +434,7 @@ fn fft_composition() { let mut v = vec![]; for _ in 0..coeffs { - v.push(Scalar::(rng.gen())); + v.push(Scalar::(E::Fr::random(rng))); } let mut domain = EvaluationDomain::from_coeffs(v.clone()).unwrap(); @@ -462,10 +462,10 @@ fn fft_composition() { #[test] fn parallel_fft_consistency() { use pairing::bls12_381::Bls12; - use rand::{self, Rand}; + use rand_core::RngCore; use std::cmp::min; - fn test_consistency(rng: &mut R) + fn test_consistency(rng: &mut R) { let worker = Worker::new(); @@ -473,7 +473,7 @@ fn parallel_fft_consistency() { for log_d in 0..10 { let d = 1 << log_d; - let v1 = (0..d).map(|_| Scalar::(E::Fr::rand(rng))).collect::>(); + let v1 = (0..d).map(|_| Scalar::(E::Fr::random(rng))).collect::>(); let mut v1 = EvaluationDomain::from_coeffs(v1).unwrap(); let mut v2 = EvaluationDomain::from_coeffs(v1.coeffs.clone()).unwrap(); diff --git a/bellman/src/groth16/generator.rs b/bellman/src/groth16/generator.rs index 50d5bd7..3e15b2b 100644 --- a/bellman/src/groth16/generator.rs +++ b/bellman/src/groth16/generator.rs @@ -1,4 +1,4 @@ -use rand::Rng; +use rand_core::RngCore; use std::sync::Arc; @@ -35,15 +35,15 @@ pub fn generate_random_parameters( circuit: C, rng: &mut R ) -> Result, SynthesisError> - where E: Engine, C: Circuit, R: Rng + where E: Engine, C: Circuit, R: RngCore { - let g1 = rng.gen(); - let g2 = rng.gen(); - let alpha = rng.gen(); - let beta = rng.gen(); - let gamma = rng.gen(); - let delta = rng.gen(); - let tau = rng.gen(); + let g1 = E::G1::random(rng); + let g2 = E::G2::random(rng); + let alpha = E::Fr::random(rng); + let beta = E::Fr::random(rng); + let gamma = E::Fr::random(rng); + let delta = E::Fr::random(rng); + let tau = E::Fr::random(rng); generate_parameters::( circuit, diff --git a/bellman/src/groth16/mod.rs b/bellman/src/groth16/mod.rs index e613d66..767150c 100644 --- a/bellman/src/groth16/mod.rs +++ b/bellman/src/groth16/mod.rs @@ -487,7 +487,7 @@ mod test_with_bls12_381 { use {Circuit, SynthesisError, ConstraintSystem}; use ff::Field; - use rand::{Rand, thread_rng}; + use rand::{thread_rng}; use pairing::bls12_381::{Bls12, Fr}; #[test] @@ -547,8 +547,8 @@ mod test_with_bls12_381 { let pvk = prepare_verifying_key::(¶ms.vk); for _ in 0..100 { - let a = Fr::rand(rng); - let b = Fr::rand(rng); + let a = Fr::random(rng); + let b = Fr::random(rng); let mut c = a; c.mul_assign(&b); diff --git a/bellman/src/groth16/prover.rs b/bellman/src/groth16/prover.rs index c674622..ceb3dce 100644 --- a/bellman/src/groth16/prover.rs +++ b/bellman/src/groth16/prover.rs @@ -1,4 +1,4 @@ -use rand::Rng; +use rand_core::RngCore; use std::sync::Arc; @@ -189,10 +189,10 @@ pub fn create_random_proof>( params: P, rng: &mut R ) -> Result, SynthesisError> - where E: Engine, C: Circuit, R: Rng + where E: Engine, C: Circuit, R: RngCore { - let r = rng.gen(); - let s = rng.gen(); + let r = E::Fr::random(rng); + let s = E::Fr::random(rng); create_proof::(circuit, params, r, s) } diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index d5f37a9..654b814 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -6,7 +6,7 @@ use pairing::{Engine, PairingCurveAffine}; use std::cmp::Ordering; use std::fmt; -use rand::{Rand, Rng}; +use rand_core::RngCore; use std::num::Wrapping; const MODULUS_R: Wrapping = Wrapping(64513); @@ -20,13 +20,11 @@ impl fmt::Display for Fr { } } -impl Rand for Fr { - fn rand(rng: &mut R) -> Self { - Fr(Wrapping(rng.gen()) % MODULUS_R) - } -} - impl Field for Fr { + fn random(rng: &mut R) -> Self { + Fr(Wrapping(rng.next_u32()) % MODULUS_R) + } + fn zero() -> Self { Fr(Wrapping(0)) } @@ -145,12 +143,6 @@ impl PartialOrd for FrRepr { } } -impl Rand for FrRepr { - fn rand(rng: &mut R) -> Self { - FrRepr([rng.gen()]) - } -} - impl fmt::Display for FrRepr { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "{}", (self.0)[0]) @@ -300,6 +292,10 @@ impl CurveProjective for Fr { type Scalar = Fr; type Engine = DummyEngine; + fn random(rng: &mut R) -> Self { + ::random(rng) + } + fn zero() -> Self { ::zero() } diff --git a/bellman/src/lib.rs b/bellman/src/lib.rs index d22d90f..bf9a4e1 100644 --- a/bellman/src/lib.rs +++ b/bellman/src/lib.rs @@ -2,7 +2,7 @@ extern crate ff; extern crate group; #[cfg(feature = "pairing")] extern crate pairing; -extern crate rand; +extern crate rand_core; extern crate futures; extern crate bit_vec; @@ -15,6 +15,9 @@ extern crate futures_cpupool; #[cfg(feature = "multicore")] extern crate num_cpus; +#[cfg(test)] +extern crate rand; + pub mod multicore; mod multiexp; pub mod domain; diff --git a/bellman/src/multiexp.rs b/bellman/src/multiexp.rs index d24572b..c655397 100644 --- a/bellman/src/multiexp.rs +++ b/bellman/src/multiexp.rs @@ -274,14 +274,14 @@ fn test_with_bls12() { acc } - use rand::{self, Rand}; + use rand; use pairing::{bls12_381::Bls12, Engine}; const SAMPLES: usize = 1 << 14; let rng = &mut rand::thread_rng(); - let v = Arc::new((0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>()); - let g = Arc::new((0..SAMPLES).map(|_| ::G1::rand(rng).into_affine()).collect::>()); + let v = Arc::new((0..SAMPLES).map(|_| ::Fr::random(rng).into_repr()).collect::>()); + let g = Arc::new((0..SAMPLES).map(|_| ::G1::random(rng).into_affine()).collect::>()); let naive = naive_multiexp(g.clone(), v.clone()); diff --git a/bellman/tests/mimc.rs b/bellman/tests/mimc.rs index 1d554a5..d08940f 100644 --- a/bellman/tests/mimc.rs +++ b/bellman/tests/mimc.rs @@ -4,13 +4,13 @@ extern crate pairing; extern crate rand; // For randomness (during paramgen and proof generation) -use rand::{thread_rng, Rng}; +use rand::thread_rng; // For benchmarking use std::time::{Duration, Instant}; // Bring in some tools for using pairing-friendly curves -use ff::Field; +use ff::{Field, ScalarEngine}; use pairing::Engine; // We're going to use the BLS12-381 pairing-friendly elliptic curve. @@ -172,7 +172,7 @@ fn test_mimc() { let rng = &mut thread_rng(); // Generate the MiMC round constants - let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); + let constants = (0..MIMC_ROUNDS).map(|_| ::Fr::random(rng)).collect::>(); println!("Creating parameters..."); @@ -203,8 +203,8 @@ fn test_mimc() { for _ in 0..SAMPLES { // Generate a random preimage and compute the image - let xl = rng.gen(); - let xr = rng.gen(); + let xl = ::Fr::random(rng); + let xr = ::Fr::random(rng); let image = mimc::(xl, xr, &constants); proof_vec.truncate(0); From adfc88926bbf3cfc0984fcce9b0b7702b1cb356a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 11 Jul 2019 08:46:47 -0400 Subject: [PATCH 022/105] Migrate sapling-crypto to rand 0.5 --- Cargo.lock | 2 +- sapling-crypto/Cargo.toml | 2 +- sapling-crypto/examples/bench.rs | 27 ++-- sapling-crypto/src/circuit/blake2s.rs | 15 +- sapling-crypto/src/circuit/ecc.rs | 70 ++++++--- sapling-crypto/src/circuit/lookup.rs | 23 ++- sapling-crypto/src/circuit/multipack.rs | 5 +- sapling-crypto/src/circuit/num.rs | 24 +-- sapling-crypto/src/circuit/pedersen_hash.rs | 10 +- sapling-crypto/src/circuit/sapling/mod.rs | 44 ++++-- sapling-crypto/src/circuit/sha256.rs | 10 +- sapling-crypto/src/circuit/uint32.rs | 45 ++++-- sapling-crypto/src/jubjub/edwards.rs | 2 +- sapling-crypto/src/jubjub/fs.rs | 161 ++++++++++++-------- sapling-crypto/src/jubjub/montgomery.rs | 2 +- sapling-crypto/src/jubjub/tests.rs | 59 +++++-- sapling-crypto/src/redjubjub.rs | 16 +- 17 files changed, 347 insertions(+), 170 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9eb4dc4..a823c3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,7 +498,7 @@ dependencies = [ "ff 0.4.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 7d43774..3d895db 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -17,7 +17,7 @@ bellman = { path = "../bellman" } blake2b_simd = "0.5" blake2s_simd = "0.5" ff = { path = "../ff" } -rand = "0.4" +rand = "0.5" digest = "0.7" byteorder = "1" diff --git a/sapling-crypto/examples/bench.rs b/sapling-crypto/examples/bench.rs index 4b7a707..9b4c0ae 100644 --- a/sapling-crypto/examples/bench.rs +++ b/sapling-crypto/examples/bench.rs @@ -1,8 +1,10 @@ +extern crate ff; extern crate sapling_crypto; extern crate bellman; extern crate rand; extern crate pairing; +use ff::Field; use std::time::{Duration, Instant}; use sapling_crypto::jubjub::{ JubjubBls12, @@ -18,14 +20,17 @@ use sapling_crypto::primitives::{ ValueCommitment }; use bellman::groth16::*; -use rand::{XorShiftRng, SeedableRng, Rng}; +use rand::{XorShiftRng, SeedableRng, Rng, RngCore}; use pairing::bls12_381::{Bls12, Fr}; const TREE_DEPTH: usize = 32; fn main() { let jubjub_params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); println!("Creating sample parameters..."); let groth_params = generate_random_parameters::( @@ -48,10 +53,10 @@ fn main() { for _ in 0..SAMPLES { let value_commitment = ValueCommitment { value: 1, - randomness: rng.gen() + randomness: fs::Fs::random(rng) }; - let nsk: fs::Fs = rng.gen(); + let nsk = fs::Fs::random(rng); let ak = edwards::Point::rand(rng, jubjub_params).mul_by_cofactor(jubjub_params); let proof_generation_key = ProofGenerationKey { @@ -64,7 +69,11 @@ fn main() { let payment_address; loop { - let diversifier = Diversifier(rng.gen()); + let diversifier = { + let mut d = [0; 11]; + rng.fill_bytes(&mut d); + Diversifier(d) + }; if let Some(p) = viewing_key.into_payment_address( diversifier, @@ -76,10 +85,10 @@ fn main() { } } - let commitment_randomness: fs::Fs = rng.gen(); - let auth_path = vec![Some((rng.gen(), rng.gen())); TREE_DEPTH]; - let ar: fs::Fs = rng.gen(); - let anchor: Fr = rng.gen(); + let commitment_randomness = fs::Fs::random(rng); + let auth_path = vec![Some((Fr::random(rng), rng.gen())); TREE_DEPTH]; + let ar = fs::Fs::random(rng); + let anchor = Fr::random(rng); let start = Instant::now(); let _ = create_random_proof(Spend { diff --git a/sapling-crypto/src/circuit/blake2s.rs b/sapling-crypto/src/circuit/blake2s.rs index 46bbe67..e6748ba 100644 --- a/sapling-crypto/src/circuit/blake2s.rs +++ b/sapling-crypto/src/circuit/blake2s.rs @@ -366,7 +366,10 @@ mod test { // doesn't result in more constraints. let mut cs = TestConstraintSystem::::new(); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let input_bits: Vec<_> = (0..512) .map(|_| Boolean::constant(rng.gen())) .chain((0..512) @@ -380,7 +383,10 @@ mod test { #[test] fn test_blake2s_constant_constraints() { let mut cs = TestConstraintSystem::::new(); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let input_bits: Vec<_> = (0..512).map(|_| Boolean::constant(rng.gen())).collect(); blake2s(&mut cs, &input_bits, b"12345678").unwrap(); assert_eq!(cs.num_constraints(), 0); @@ -388,7 +394,10 @@ mod test { #[test] fn test_blake2s() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { diff --git a/sapling-crypto/src/circuit/ecc.rs b/sapling-crypto/src/circuit/ecc.rs index 1071649..3fc9713 100644 --- a/sapling-crypto/src/circuit/ecc.rs +++ b/sapling-crypto/src/circuit/ecc.rs @@ -748,7 +748,7 @@ impl MontgomeryPoint { #[cfg(test)] mod test { use bellman::{ConstraintSystem}; - use rand::{XorShiftRng, SeedableRng, Rand, Rng}; + use rand::{XorShiftRng, SeedableRng, Rng}; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; use ::circuit::test::*; @@ -774,7 +774,10 @@ mod test { #[test] fn test_into_edwards() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); @@ -798,12 +801,12 @@ mod test { assert!(q.x.get_value().unwrap() == u); assert!(q.y.get_value().unwrap() == v); - cs.set("u/num", rng.gen()); + cs.set("u/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied().unwrap(), "u computation"); cs.set("u/num", u); assert!(cs.is_satisfied()); - cs.set("v/num", rng.gen()); + cs.set("v/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied().unwrap(), "v computation"); cs.set("v/num", v); assert!(cs.is_satisfied()); @@ -813,7 +816,10 @@ mod test { #[test] fn test_interpret() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let p = edwards::Point::::rand(rng, ¶ms); @@ -853,8 +859,8 @@ mod test { // Random (x, y) are unlikely to be on the curve. for _ in 0..100 { - let x = rng.gen(); - let y = rng.gen(); + let x = Fr::random(rng); + let y = Fr::random(rng); let mut cs = TestConstraintSystem::::new(); let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || { @@ -873,13 +879,16 @@ mod test { #[test] fn test_edwards_fixed_base_multiplication() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); let p = params.generator(FixedGenerators::NoteCommitmentRandomness); - let s = Fs::rand(rng); + let s = Fs::random(rng); let q = p.mul(s, params); let (x1, y1) = q.into_xy(); @@ -908,13 +917,16 @@ mod test { #[test] fn test_edwards_multiplication() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); let p = edwards::Point::::rand(rng, params); - let s = Fs::rand(rng); + let s = Fs::random(rng); let q = p.mul(s, params); let (x0, y0) = p.into_xy(); @@ -965,7 +977,10 @@ mod test { #[test] fn test_conditionally_select() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); @@ -1031,7 +1046,10 @@ mod test { #[test] fn test_edwards_addition() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let p1 = edwards::Point::::rand(rng, params); @@ -1077,19 +1095,19 @@ mod test { assert!(p3.y.get_value().unwrap() == y2); let u = cs.get("addition/U/num"); - cs.set("addition/U/num", rng.gen()); + cs.set("addition/U/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied(), Some("addition/U computation")); cs.set("addition/U/num", u); assert!(cs.is_satisfied()); let x3 = cs.get("addition/x3/num"); - cs.set("addition/x3/num", rng.gen()); + cs.set("addition/x3/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied(), Some("addition/x3 computation")); cs.set("addition/x3/num", x3); assert!(cs.is_satisfied()); let y3 = cs.get("addition/y3/num"); - cs.set("addition/y3/num", rng.gen()); + cs.set("addition/y3/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied(), Some("addition/y3 computation")); cs.set("addition/y3/num", y3); assert!(cs.is_satisfied()); @@ -1099,7 +1117,10 @@ mod test { #[test] fn test_edwards_doubling() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let p1 = edwards::Point::::rand(rng, params); @@ -1134,11 +1155,14 @@ mod test { #[test] fn test_montgomery_addition() { let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let p1 = loop { - let x: Fr = rng.gen(); + let x = Fr::random(rng); let s: bool = rng.gen(); if let Some(p) = montgomery::Point::::get_for_x(x, s, params) { @@ -1147,7 +1171,7 @@ mod test { }; let p2 = loop { - let x: Fr = rng.gen(); + let x = Fr::random(rng); let s: bool = rng.gen(); if let Some(p) = montgomery::Point::::get_for_x(x, s, params) { @@ -1194,17 +1218,17 @@ mod test { assert!(p3.x.get_value().unwrap() == x2); assert!(p3.y.get_value().unwrap() == y2); - cs.set("addition/yprime/num", rng.gen()); + cs.set("addition/yprime/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied(), Some("addition/evaluate yprime")); cs.set("addition/yprime/num", y2); assert!(cs.is_satisfied()); - cs.set("addition/xprime/num", rng.gen()); + cs.set("addition/xprime/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied(), Some("addition/evaluate xprime")); cs.set("addition/xprime/num", x2); assert!(cs.is_satisfied()); - cs.set("addition/lambda/num", rng.gen()); + cs.set("addition/lambda/num", Fr::random(rng)); assert_eq!(cs.which_is_unsatisfied(), Some("addition/evaluate lambda")); } } diff --git a/sapling-crypto/src/circuit/lookup.rs b/sapling-crypto/src/circuit/lookup.rs index 272f5f6..4b6e13b 100644 --- a/sapling-crypto/src/circuit/lookup.rs +++ b/sapling-crypto/src/circuit/lookup.rs @@ -196,7 +196,7 @@ pub fn lookup3_xy_with_conditional_negation( #[cfg(test)] mod test { - use rand::{SeedableRng, Rand, Rng, XorShiftRng}; + use rand::{SeedableRng, Rng, XorShiftRng}; use super::*; use ::circuit::test::*; use ::circuit::boolean::{Boolean, AllocatedBit}; @@ -204,7 +204,10 @@ mod test { #[test] fn test_lookup3_xy() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0656]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); @@ -226,7 +229,7 @@ mod test { let bits = vec![a, b, c]; - let points: Vec<(Fr, Fr)> = (0..8).map(|_| (rng.gen(), rng.gen())).collect(); + let points: Vec<(Fr, Fr)> = (0..8).map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))).collect(); let res = lookup3_xy(&mut cs, &bits, &points).unwrap(); @@ -244,7 +247,10 @@ mod test { #[test] fn test_lookup3_xy_with_conditional_negation() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); @@ -266,7 +272,7 @@ mod test { let bits = vec![a, b, c]; - let points: Vec<(Fr, Fr)> = (0..4).map(|_| (rng.gen(), rng.gen())).collect(); + let points: Vec<(Fr, Fr)> = (0..4).map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))).collect(); let res = lookup3_xy_with_conditional_negation(&mut cs, &bits, &points).unwrap(); @@ -285,12 +291,15 @@ mod test { #[test] fn test_synth() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let window_size = 4; let mut assignment = vec![Fr::zero(); 1 << window_size]; - let constants: Vec<_> = (0..(1 << window_size)).map(|_| Fr::rand(&mut rng)).collect(); + let constants: Vec<_> = (0..(1 << window_size)).map(|_| Fr::random(&mut rng)).collect(); synth::(window_size, &constants, &mut assignment); diff --git a/sapling-crypto/src/circuit/multipack.rs b/sapling-crypto/src/circuit/multipack.rs index bf1b046..fd7cbfb 100644 --- a/sapling-crypto/src/circuit/multipack.rs +++ b/sapling-crypto/src/circuit/multipack.rs @@ -86,7 +86,10 @@ fn test_multipacking() { use ::circuit::test::*; use super::boolean::{AllocatedBit, Boolean}; - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for num_bits in 0..1500 { let mut cs = TestConstraintSystem::::new(); diff --git a/sapling-crypto/src/circuit/num.rs b/sapling-crypto/src/circuit/num.rs index 919d921..7201356 100644 --- a/sapling-crypto/src/circuit/num.rs +++ b/sapling-crypto/src/circuit/num.rs @@ -455,7 +455,7 @@ impl Num { #[cfg(test)] mod test { - use rand::{SeedableRng, Rand, Rng, XorShiftRng}; + use rand::{SeedableRng, XorShiftRng}; use bellman::{ConstraintSystem}; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; @@ -502,12 +502,15 @@ mod test { #[test] fn test_num_conditional_reversal() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); { let mut cs = TestConstraintSystem::::new(); - let a = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(rng.gen())).unwrap(); - let b = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(rng.gen())).unwrap(); + let a = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::random(&mut rng))).unwrap(); + let b = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::random(&mut rng))).unwrap(); let condition = Boolean::constant(false); let (c, d) = AllocatedNum::conditionally_reverse(&mut cs, &a, &b, &condition).unwrap(); @@ -520,8 +523,8 @@ mod test { { let mut cs = TestConstraintSystem::::new(); - let a = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(rng.gen())).unwrap(); - let b = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(rng.gen())).unwrap(); + let a = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::random(&mut rng))).unwrap(); + let b = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::random(&mut rng))).unwrap(); let condition = Boolean::constant(true); let (c, d) = AllocatedNum::conditionally_reverse(&mut cs, &a, &b, &condition).unwrap(); @@ -573,10 +576,13 @@ mod test { #[test] fn test_into_bits() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for i in 0..200 { - let r = Fr::rand(&mut rng); + let r = Fr::random(&mut rng); let mut cs = TestConstraintSystem::::new(); let n = AllocatedNum::alloc(&mut cs, || Ok(r)).unwrap(); @@ -597,7 +603,7 @@ mod test { } } - cs.set("num", Fr::rand(&mut rng)); + cs.set("num", Fr::random(&mut rng)); assert!(!cs.is_satisfied()); cs.set("num", r); assert!(cs.is_satisfied()); diff --git a/sapling-crypto/src/circuit/pedersen_hash.rs b/sapling-crypto/src/circuit/pedersen_hash.rs index 297a0e0..f26b98e 100644 --- a/sapling-crypto/src/circuit/pedersen_hash.rs +++ b/sapling-crypto/src/circuit/pedersen_hash.rs @@ -121,7 +121,10 @@ mod test { #[test] fn test_pedersen_hash_constraints() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let params = &JubjubBls12::new(); let mut cs = TestConstraintSystem::::new(); @@ -146,7 +149,10 @@ mod test { #[test] fn test_pedersen_hash() { - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let params = &JubjubBls12::new(); for length in 0..751 { diff --git a/sapling-crypto/src/circuit/sapling/mod.rs b/sapling-crypto/src/circuit/sapling/mod.rs index e84b94a..2c4d566 100644 --- a/sapling-crypto/src/circuit/sapling/mod.rs +++ b/sapling-crypto/src/circuit/sapling/mod.rs @@ -600,22 +600,25 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { fn test_input_circuit_with_bls12_381() { use ff::{BitIterator, Field}; use pairing::bls12_381::*; - use rand::{SeedableRng, Rng, XorShiftRng}; + use rand::{SeedableRng, Rng, RngCore, XorShiftRng}; use ::circuit::test::*; use jubjub::{JubjubBls12, fs, edwards}; let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x58, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let tree_depth = 32; for _ in 0..10 { let value_commitment = ValueCommitment { value: rng.gen(), - randomness: rng.gen() + randomness: fs::Fs::random(rng), }; - let nsk: fs::Fs = rng.gen(); + let nsk = fs::Fs::random(rng); let ak = edwards::Point::rand(rng, params).mul_by_cofactor(params); let proof_generation_key = ::primitives::ProofGenerationKey { @@ -628,7 +631,11 @@ fn test_input_circuit_with_bls12_381() { let payment_address; loop { - let diversifier = ::primitives::Diversifier(rng.gen()); + let diversifier = { + let mut d = [0; 11]; + rng.fill_bytes(&mut d); + ::primitives::Diversifier(d) + }; if let Some(p) = viewing_key.into_payment_address( diversifier, @@ -641,9 +648,9 @@ fn test_input_circuit_with_bls12_381() { } let g_d = payment_address.diversifier.g_d(params).unwrap(); - let commitment_randomness: fs::Fs = rng.gen(); - let auth_path = vec![Some((rng.gen(), rng.gen())); tree_depth]; - let ar: fs::Fs = rng.gen(); + let commitment_randomness = fs::Fs::random(rng); + let auth_path = vec![Some((Fr::random(rng), rng.gen())); tree_depth]; + let ar = fs::Fs::random(rng); { let rk = viewing_key.rk(ar, params).into_xy(); @@ -732,20 +739,23 @@ fn test_input_circuit_with_bls12_381() { fn test_output_circuit_with_bls12_381() { use ff::Field; use pairing::bls12_381::*; - use rand::{SeedableRng, Rng, XorShiftRng}; + use rand::{SeedableRng, Rng, RngCore, XorShiftRng}; use ::circuit::test::*; use jubjub::{JubjubBls12, fs, edwards}; let params = &JubjubBls12::new(); - let rng = &mut XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x58, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { let value_commitment = ValueCommitment { value: rng.gen(), - randomness: rng.gen() + randomness: fs::Fs::random(rng), }; - let nsk: fs::Fs = rng.gen(); + let nsk = fs::Fs::random(rng); let ak = edwards::Point::rand(rng, params).mul_by_cofactor(params); let proof_generation_key = ::primitives::ProofGenerationKey { @@ -758,7 +768,11 @@ fn test_output_circuit_with_bls12_381() { let payment_address; loop { - let diversifier = ::primitives::Diversifier(rng.gen()); + let diversifier = { + let mut d = [0; 11]; + rng.fill_bytes(&mut d); + ::primitives::Diversifier(d) + }; if let Some(p) = viewing_key.into_payment_address( diversifier, @@ -770,8 +784,8 @@ fn test_output_circuit_with_bls12_381() { } } - let commitment_randomness: fs::Fs = rng.gen(); - let esk: fs::Fs = rng.gen(); + let commitment_randomness = fs::Fs::random(rng); + let esk = fs::Fs::random(rng); { let mut cs = TestConstraintSystem::::new(); diff --git a/sapling-crypto/src/circuit/sha256.rs b/sapling-crypto/src/circuit/sha256.rs index 7b55fc8..4837640 100644 --- a/sapling-crypto/src/circuit/sha256.rs +++ b/sapling-crypto/src/circuit/sha256.rs @@ -341,7 +341,10 @@ mod test { #[test] fn test_full_block() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let iv = get_sha256_iv(); @@ -370,7 +373,10 @@ mod test { use crypto::sha2::Sha256; use crypto::digest::Digest; - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { diff --git a/sapling-crypto/src/circuit/uint32.rs b/sapling-crypto/src/circuit/uint32.rs index 6dd4535..daca627 100644 --- a/sapling-crypto/src/circuit/uint32.rs +++ b/sapling-crypto/src/circuit/uint32.rs @@ -420,7 +420,10 @@ mod test { #[test] fn test_uint32_from_bits_be() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0653]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut v = (0..32).map(|_| Boolean::constant(rng.gen())).collect::>(); @@ -451,7 +454,10 @@ mod test { #[test] fn test_uint32_from_bits() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0653]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut v = (0..32).map(|_| Boolean::constant(rng.gen())).collect::>(); @@ -482,7 +488,10 @@ mod test { #[test] fn test_uint32_xor() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0653]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); @@ -524,7 +533,10 @@ mod test { #[test] fn test_uint32_addmany_constants() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); @@ -563,7 +575,10 @@ mod test { #[test] fn test_uint32_addmany() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); @@ -620,7 +635,10 @@ mod test { #[test] fn test_uint32_rotr() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut num = rng.gen(); @@ -650,7 +668,10 @@ mod test { #[test] fn test_uint32_shr() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..50 { for i in 0..60 { @@ -670,7 +691,10 @@ mod test { #[test] fn test_uint32_sha256_maj() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0653]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); @@ -711,7 +735,10 @@ mod test { #[test] fn test_uint32_sha256_ch() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0653]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); diff --git a/sapling-crypto/src/jubjub/edwards.rs b/sapling-crypto/src/jubjub/edwards.rs index 16d21e7..95b6120 100644 --- a/sapling-crypto/src/jubjub/edwards.rs +++ b/sapling-crypto/src/jubjub/edwards.rs @@ -188,7 +188,7 @@ impl Point { pub fn rand(rng: &mut R, params: &E::Params) -> Self { loop { - let y: E::Fr = rng.gen(); + let y = E::Fr::random(rng); if let Some(p) = Self::get_for_y(y, rng.gen(), params) { return p; diff --git a/sapling-crypto/src/jubjub/fs.rs b/sapling-crypto/src/jubjub/fs.rs index 6a51573..55df2cb 100644 --- a/sapling-crypto/src/jubjub/fs.rs +++ b/sapling-crypto/src/jubjub/fs.rs @@ -4,6 +4,7 @@ use ff::{ LegendreSymbol::{self, *}, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField, }; +use rand::RngCore; use super::ToUniform; @@ -42,13 +43,6 @@ const NEGATIVE_ONE: Fs = Fs(FsRepr([0xaa9f02ab1d6124de, 0xb3524a6466112932, 0x73 #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] pub struct FsRepr(pub [u64; 4]); -impl ::rand::Rand for FsRepr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - FsRepr(rng.gen()) - } -} - impl ::std::fmt::Display for FsRepr { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -240,21 +234,6 @@ impl ::std::fmt::Display for Fs } } -impl ::rand::Rand for Fs { - fn rand(rng: &mut R) -> Self { - loop { - let mut tmp = Fs(FsRepr::rand(rng)); - - // Mask away the unused bits at the beginning. - tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; - - if tmp.is_valid() { - return tmp - } - } - } -} - impl From for FsRepr { fn from(e: Fs) -> FsRepr { e.into_repr() @@ -303,6 +282,25 @@ impl PrimeField for Fs { } impl Field for Fs { + fn random(rng: &mut R) -> Self { + loop { + let mut tmp = { + let mut repr = [0u64; 4]; + for i in 0..4 { + repr[i] = rng.next_u64(); + } + Fs(FsRepr(repr)) + }; + + // Mask away the unused bits at the beginning. + tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; + + if tmp.is_valid() { + return tmp + } + } + } + #[inline] fn zero() -> Self { Fs(FsRepr::from(0)) @@ -622,7 +620,7 @@ fn test_neg_one() { } #[cfg(test)] -use rand::{SeedableRng, XorShiftRng, Rand}; +use rand::{SeedableRng, XorShiftRng}; #[test] fn test_fs_repr_ordering() { @@ -760,14 +758,17 @@ fn test_fs_repr_num_bits() { #[test] fn test_fs_repr_sub_noborrow() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut t = FsRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495]); t.sub_noborrow(&FsRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf])); assert!(t == FsRepr([0xb813415048991c1f, 0x10ad07ae88725d92, 0x5a7b851271759961, 0x36850eedd30c39c5])); for _ in 0..1000 { - let mut a = FsRepr::rand(&mut rng); + let mut a = Fs::random(&mut rng).into_repr(); a.0[3] >>= 30; let mut b = a; for _ in 0..10 { @@ -806,7 +807,10 @@ fn test_fs_legendre() { #[test] fn test_fr_repr_add_nocarry() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let mut t = FsRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf]); t.add_nocarry(&FsRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495])); @@ -814,9 +818,9 @@ fn test_fr_repr_add_nocarry() { // Test for the associativity of addition. for _ in 0..1000 { - let mut a = FsRepr::rand(&mut rng); - let mut b = FsRepr::rand(&mut rng); - let mut c = FsRepr::rand(&mut rng); + let mut a = Fs::random(&mut rng).into_repr(); + let mut b = Fs::random(&mut rng).into_repr(); + let mut c = Fs::random(&mut rng).into_repr(); // Unset the first few bits, so that overflow won't occur. a.0[3] >>= 3; @@ -865,10 +869,13 @@ fn test_fs_is_valid() { assert!(Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])).is_valid()); assert!(!Fs(FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])).is_valid()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); assert!(a.is_valid()); } } @@ -903,13 +910,16 @@ fn test_fs_add_assign() { // Test associativity - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Generate a, b, c and ensure (a + b) + c == a + (b + c). - let a = Fs::rand(&mut rng); - let b = Fs::rand(&mut rng); - let c = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); + let b = Fs::random(&mut rng); + let c = Fs::random(&mut rng); let mut tmp1 = a; tmp1.add_assign(&b); @@ -948,12 +958,15 @@ fn test_fs_sub_assign() { assert_eq!(tmp, Fs(FsRepr([0x361e16aef5cce835, 0x55bbde2536e274c1, 0x4dc77a63fd15ee75, 0x1e14bb37c14f230]))); } - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure that (a - b) + (b - a) = 0. - let a = Fs::rand(&mut rng); - let b = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); + let b = Fs::random(&mut rng); let mut tmp1 = a; tmp1.sub_assign(&b); @@ -972,13 +985,16 @@ fn test_fs_mul_assign() { tmp.mul_assign(&Fs(FsRepr([0xdae00fc63c9fa90f, 0x5a5ed89b96ce21ce, 0x913cd26101bd6f58, 0x3f0822831697fe9]))); assert!(tmp == Fs(FsRepr([0xb68ecb61d54d2992, 0x5ff95874defce6a6, 0x3590eb053894657d, 0x53823a118515933]))); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000000 { // Ensure that (a * b) * c = a * (b * c) - let a = Fs::rand(&mut rng); - let b = Fs::rand(&mut rng); - let c = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); + let b = Fs::random(&mut rng); + let c = Fs::random(&mut rng); let mut tmp1 = a; tmp1.mul_assign(&b); @@ -994,10 +1010,10 @@ fn test_fs_mul_assign() { for _ in 0..1000000 { // Ensure that r * (a + b + c) = r*a + r*b + r*c - let r = Fs::rand(&mut rng); - let mut a = Fs::rand(&mut rng); - let mut b = Fs::rand(&mut rng); - let mut c = Fs::rand(&mut rng); + let r = Fs::random(&mut rng); + let mut a = Fs::random(&mut rng); + let mut b = Fs::random(&mut rng); + let mut c = Fs::random(&mut rng); let mut tmp1 = a; tmp1.add_assign(&b); @@ -1022,11 +1038,14 @@ fn test_fr_squaring() { a.square(); assert_eq!(a, Fs::from_repr(FsRepr([0x12c7f55cbc52fbaa, 0xdedc98a0b5e6ce9e, 0xad2892726a5396a, 0x9fe82af8fee77b3])).unwrap()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000000 { // Ensure that (a * a) = a^2 - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); let mut tmp = a; tmp.square(); @@ -1042,13 +1061,16 @@ fn test_fr_squaring() { fn test_fs_inverse() { assert!(Fs::zero().inverse().is_none()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let one = Fs::one(); for _ in 0..1000 { // Ensure that a * a^-1 = 1 - let mut a = Fs::rand(&mut rng); + let mut a = Fs::random(&mut rng); let ainv = a.inverse().unwrap(); a.mul_assign(&ainv); assert_eq!(a, one); @@ -1057,11 +1079,14 @@ fn test_fs_inverse() { #[test] fn test_fs_double() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure doubling a is equivalent to adding a to itself. - let mut a = Fs::rand(&mut rng); + let mut a = Fs::random(&mut rng); let mut b = a; b.add_assign(&a); a.double(); @@ -1078,11 +1103,14 @@ fn test_fs_negate() { assert!(a.is_zero()); } - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Ensure (a - (-a)) = 0. - let mut a = Fs::rand(&mut rng); + let mut a = Fs::random(&mut rng); let mut b = a; b.negate(); a.add_assign(&b); @@ -1093,12 +1121,15 @@ fn test_fs_negate() { #[test] fn test_fs_pow() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for i in 0..1000 { // Exponentiate by various small numbers and ensure it consists with repeated // multiplication. - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); let target = a.pow(&[i]); let mut c = Fs::one(); for _ in 0..i { @@ -1109,7 +1140,7 @@ fn test_fs_pow() { for _ in 0..1000 { // Exponentiating by the modulus should have no effect in a prime field. - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); assert_eq!(a, a.pow(Fs::char())); } @@ -1117,13 +1148,16 @@ fn test_fs_pow() { #[test] fn test_fs_sqrt() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); assert_eq!(Fs::zero().sqrt().unwrap(), Fs::zero()); for _ in 0..1000 { // Ensure sqrt(a^2) = a or -a - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); let mut nega = a; nega.negate(); let mut b = a; @@ -1136,7 +1170,7 @@ fn test_fs_sqrt() { for _ in 0..1000 { // Ensure sqrt(a)^2 = a for random a - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); if let Some(mut tmp) = a.sqrt() { tmp.square(); @@ -1166,11 +1200,14 @@ fn test_fs_from_into_repr() { // Zero should be in the field. assert!(Fs::from_repr(FsRepr::from(0)).unwrap().is_zero()); - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { // Try to turn Fs elements into representations and back again, and compare. - let a = Fs::rand(&mut rng); + let a = Fs::random(&mut rng); let a_repr = a.into_repr(); let b_repr = FsRepr::from(a); assert_eq!(a_repr, b_repr); diff --git a/sapling-crypto/src/jubjub/montgomery.rs b/sapling-crypto/src/jubjub/montgomery.rs index 76203eb..28dce8e 100644 --- a/sapling-crypto/src/jubjub/montgomery.rs +++ b/sapling-crypto/src/jubjub/montgomery.rs @@ -104,7 +104,7 @@ impl Point { pub fn rand(rng: &mut R, params: &E::Params) -> Self { loop { - let x: E::Fr = rng.gen(); + let x = E::Fr::random(rng); match Self::get_for_x(x, rng.gen(), params) { Some(p) => { diff --git a/sapling-crypto/src/jubjub/tests.rs b/sapling-crypto/src/jubjub/tests.rs index eb7e36b..19aae80 100644 --- a/sapling-crypto/src/jubjub/tests.rs +++ b/sapling-crypto/src/jubjub/tests.rs @@ -14,7 +14,7 @@ use ff::{ LegendreSymbol }; -use rand::{XorShiftRng, SeedableRng, Rand}; +use rand::{RngCore, XorShiftRng, SeedableRng}; pub fn test_suite(params: &E::Params) { test_back_and_forth::(params); @@ -78,7 +78,10 @@ fn is_on_twisted_edwards_curve>( } fn test_loworder(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let inf = montgomery::Point::zero(); // try to find a point of order 8 @@ -109,15 +112,18 @@ fn test_loworder(params: &E::Params) { fn test_mul_associativity(params: &E::Params) { use self::edwards::Point; - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..100 { // Pick a random point and multiply it by the cofactor let base = Point::::rand(rng, params).mul_by_cofactor(params); - let mut a = E::Fs::rand(rng); - let b = E::Fs::rand(rng); - let c = E::Fs::rand(rng); + let mut a = E::Fs::random(rng); + let b = E::Fs::random(rng); + let c = E::Fs::random(rng); let res1 = base.mul(a, params).mul(b, params).mul(c, params); let res2 = base.mul(b, params).mul(c, params).mul(a, params); @@ -143,7 +149,10 @@ fn test_mul_associativity(params: &E::Params) { fn test_order(params: &E::Params) { use self::edwards::Point; - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); // The neutral element is in the prime order subgroup. assert!(Point::::zero().as_prime_order(params).is_some()); @@ -170,7 +179,10 @@ fn test_order(params: &E::Params) { } fn test_addition_associativity(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { use self::montgomery::Point; @@ -194,7 +206,10 @@ fn test_addition_associativity(params: &E::Params) { } fn test_identities(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); { use self::edwards::Point; @@ -228,11 +243,14 @@ fn test_identities(params: &E::Params) { } fn test_get_for(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let y = E::Fr::rand(rng); - let sign = bool::rand(rng); + let y = E::Fr::random(rng); + let sign = rng.next_u32() % 2 == 1; if let Some(mut p) = edwards::Point::::get_for_y(y, sign, params) { assert!(p.into_xy().0.into_repr().is_odd() == sign); @@ -247,7 +265,10 @@ fn test_get_for(params: &E::Params) { } fn test_read_write(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let e = edwards::Point::::rand(rng, params); @@ -262,7 +283,10 @@ fn test_read_write(params: &E::Params) { } fn test_rand(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { let p = montgomery::Point::::rand(rng, params); @@ -281,10 +305,13 @@ fn test_rand(params: &E::Params) { } fn test_back_and_forth(params: &E::Params) { - let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x5d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); for _ in 0..1000 { - let s = E::Fs::rand(rng); + let s = E::Fs::random(rng); let edwards_p1 = edwards::Point::::rand(rng, params); let mont_p1 = montgomery::Point::from_edwards(&edwards_p1, params); let mont_p2 = montgomery::Point::::rand(rng, params); diff --git a/sapling-crypto/src/redjubjub.rs b/sapling-crypto/src/redjubjub.rs index 00e2f8f..2b34654 100644 --- a/sapling-crypto/src/redjubjub.rs +++ b/sapling-crypto/src/redjubjub.rs @@ -2,7 +2,7 @@ //! See section 5.4.6 of the Sapling protocol specification. use ff::{Field, PrimeField, PrimeFieldRepr}; -use rand::{Rng, Rand}; +use rand::{Rng}; use std::io::{self, Read, Write}; use jubjub::{FixedGenerators, JubjubEngine, JubjubParams, Unknown, edwards::Point}; @@ -184,7 +184,7 @@ pub fn batch_verify<'a, E: JubjubEngine, R: Rng>( let mut c = h_star::(&entry.sig.rbar[..], entry.msg); - let z = E::Fs::rand(rng); + let z = E::Fs::random(rng); s.mul_assign(&z); s.negate(); @@ -218,13 +218,13 @@ mod tests { let params = &JubjubBls12::new(); let p_g = FixedGenerators::SpendingKeyGenerator; - let sk1 = PrivateKey::(rng.gen()); + let sk1 = PrivateKey::(Fs::random(rng)); let vk1 = PublicKey::from_private(&sk1, p_g, params); let msg1 = b"Foo bar"; let sig1 = sk1.sign(msg1, rng, p_g, params); assert!(vk1.verify(msg1, &sig1, p_g, params)); - let sk2 = PrivateKey::(rng.gen()); + let sk2 = PrivateKey::(Fs::random(rng)); let vk2 = PublicKey::from_private(&sk2, p_g, params); let msg2 = b"Foo bar"; let sig2 = sk2.sign(msg2, rng, p_g, params); @@ -262,7 +262,7 @@ mod tests { } }; - let sk = PrivateKey::(rng.gen()); + let sk = PrivateKey::(Fs::random(rng)); let vk = PublicKey::from_private(&sk, p_g, params); // TODO: This test will need to change when #77 is fixed @@ -281,7 +281,7 @@ mod tests { let params = &JubjubBls12::new(); for _ in 0..1000 { - let sk = PrivateKey::(rng.gen()); + let sk = PrivateKey::(Fs::random(rng)); let vk = PublicKey::from_private(&sk, p_g, params); let msg = b"Foo bar"; let sig = sk.sign(msg, rng, p_g, params); @@ -314,7 +314,7 @@ mod tests { let params = &JubjubBls12::new(); for _ in 0..1000 { - let sk = PrivateKey::(rng.gen()); + let sk = PrivateKey::(Fs::random(rng)); let vk = PublicKey::from_private(&sk, p_g, params); let msg1 = b"Foo bar"; @@ -328,7 +328,7 @@ mod tests { assert!(!vk.verify(msg1, &sig2, p_g, params)); assert!(!vk.verify(msg2, &sig1, p_g, params)); - let alpha = rng.gen(); + let alpha = Fs::random(rng); let rsk = sk.randomize(alpha); let rvk = vk.randomize(alpha, p_g, params); From 6149166ccb41d500eef227a9e6ec492086f9be9b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 11 Jul 2019 09:00:24 -0400 Subject: [PATCH 023/105] Migrate zcash_primitives to rand 0.5 --- Cargo.lock | 2 +- zcash_primitives/Cargo.toml | 2 +- zcash_primitives/src/merkle_tree.rs | 12 +++++---- zcash_primitives/src/note_encryption.rs | 32 +++++++++++++---------- zcash_primitives/src/transaction/tests.rs | 10 ++++--- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a823c3e..d846871 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -594,7 +594,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 771f351..d82b3bc 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -15,6 +15,6 @@ fpe = "0.1" hex = "0.3" lazy_static = "1" pairing = { path = "../pairing" } -rand = "0.4" +rand = "0.5" sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 118d7db..3b94bd9 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -200,12 +200,14 @@ impl CommitmentTree { /// # Examples /// /// ``` +/// extern crate ff; /// extern crate pairing; /// extern crate rand; /// extern crate zcash_primitives; /// -/// use pairing::bls12_381::FrRepr; -/// use rand::{OsRng, Rand}; +/// use ff::{Field, PrimeField}; +/// use pairing::bls12_381::Fr; +/// use rand::OsRng; /// use zcash_primitives::{ /// merkle_tree::{CommitmentTree, IncrementalWitness}, /// sapling::Node, @@ -214,13 +216,13 @@ impl CommitmentTree { /// let mut rng = OsRng::new().unwrap(); /// let mut tree = CommitmentTree::::new(); /// -/// tree.append(Node::new(FrRepr::rand(&mut rng))); -/// tree.append(Node::new(FrRepr::rand(&mut rng))); +/// tree.append(Node::new(Fr::random(&mut rng).into_repr())); +/// tree.append(Node::new(Fr::random(&mut rng).into_repr())); /// let mut witness = IncrementalWitness::from_tree(&tree); /// assert_eq!(witness.position(), 1); /// assert_eq!(tree.root(), witness.root()); /// -/// let cmu = Node::new(FrRepr::rand(&mut rng)); +/// let cmu = Node::new(Fr::random(&mut rng).into_repr()); /// tree.append(cmu); /// witness.append(cmu); /// assert_eq!(tree.root(), witness.root()); diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index 610b746..b1b483f 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -211,12 +211,14 @@ fn prf_ock( /// # Examples /// /// ``` +/// extern crate ff; /// extern crate pairing; /// extern crate rand; /// extern crate sapling_crypto; /// +/// use ff::Field; /// use pairing::bls12_381::Bls12; -/// use rand::{OsRng, Rand}; +/// use rand::OsRng; /// use sapling_crypto::{ /// jubjub::fs::Fs, /// primitives::{Diversifier, PaymentAddress, ValueCommitment}, @@ -238,7 +240,7 @@ fn prf_ock( /// let ovk = OutgoingViewingKey([0; 32]); /// /// let value = 1000; -/// let rcv = Fs::rand(&mut rng); +/// let rcv = Fs::random(&mut rng); /// let cv = ValueCommitment:: { /// value, /// randomness: rcv.clone(), @@ -558,9 +560,9 @@ pub fn try_sapling_output_recovery( #[cfg(test)] mod tests { use crypto_api_chachapoly::ChachaPolyIetf; - use ff::{PrimeField, PrimeFieldRepr}; + use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; - use rand::{thread_rng, Rand, Rng}; + use rand::{thread_rng, RngCore}; use sapling_crypto::{ jubjub::{ edwards, @@ -692,8 +694,8 @@ mod tests { assert_eq!(Memo::default().to_utf8(), None); } - fn random_enc_ciphertext( - mut rng: &mut Rng, + fn random_enc_ciphertext( + mut rng: &mut R, ) -> ( OutgoingViewingKey, Fs, @@ -704,7 +706,7 @@ mod tests { [u8; OUT_CIPHERTEXT_SIZE], ) { let diversifier = Diversifier([0; 11]); - let ivk = Fs::rand(&mut rng); + let ivk = Fs::random(&mut rng); let pk_d = diversifier.g_d::(&JUBJUB).unwrap().mul(ivk, &JUBJUB); let pa = PaymentAddress { diversifier, pk_d }; @@ -712,11 +714,13 @@ mod tests { let value = 100; let value_commitment = ValueCommitment:: { value, - randomness: Fs::rand(&mut rng), + randomness: Fs::random(&mut rng), }; let cv = value_commitment.cm(&JUBJUB).into(); - let note = pa.create_note(value, Fs::rand(&mut rng), &JUBJUB).unwrap(); + let note = pa + .create_note(value, Fs::random(&mut rng), &JUBJUB) + .unwrap(); let cmu = note.cm(&JUBJUB); let ovk = OutgoingViewingKey([0; 32]); @@ -849,7 +853,7 @@ mod tests { let (_, _, _, cmu, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); assert_eq!( - try_sapling_note_decryption(&Fs::rand(&mut rng), &epk, &cmu, &enc_ciphertext), + try_sapling_note_decryption(&Fs::random(&mut rng), &epk, &cmu, &enc_ciphertext), None ); } @@ -878,7 +882,7 @@ mod tests { let (_, ivk, _, _, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); assert_eq!( - try_sapling_note_decryption(&ivk, &epk, &Fr::rand(&mut rng), &enc_ciphertext), + try_sapling_note_decryption(&ivk, &epk, &Fr::random(&mut rng), &enc_ciphertext), None ); } @@ -970,7 +974,7 @@ mod tests { assert_eq!( try_sapling_compact_note_decryption( - &Fs::rand(&mut rng), + &Fs::random(&mut rng), &epk, &cmu, &enc_ciphertext[..COMPACT_NOTE_SIZE] @@ -1006,7 +1010,7 @@ mod tests { try_sapling_compact_note_decryption( &ivk, &epk, - &Fr::rand(&mut rng), + &Fr::random(&mut rng), &enc_ciphertext[..COMPACT_NOTE_SIZE] ), None @@ -1137,7 +1141,7 @@ mod tests { try_sapling_output_recovery( &ovk, &cv, - &Fr::rand(&mut rng), + &Fr::random(&mut rng), &epk, &enc_ciphertext, &out_ciphertext diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 1275bba..7ef691f 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1,6 +1,10 @@ +use ff::Field; use pairing::bls12_381::Bls12; -use rand::{thread_rng, Rng}; -use sapling_crypto::{jubjub::FixedGenerators, redjubjub::PrivateKey}; +use rand::thread_rng; +use sapling_crypto::{ + jubjub::{fs::Fs, FixedGenerators}, + redjubjub::PrivateKey, +}; use super::{ components::{Amount, Script}, @@ -194,7 +198,7 @@ fn tx_write_rejects_unexpected_binding_sig() { // Fails with an unexpected binding signature { let rng = &mut thread_rng(); - let sk = PrivateKey::(rng.gen()); + let sk = PrivateKey::(Fs::random(rng)); let sig = sk.sign( b"Foo bar", rng, From ccf75c39c125a806cb811ff32f780f21fba70c9f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 11 Jul 2019 09:03:04 -0400 Subject: [PATCH 024/105] Migrate remaining crates to rand 0.5 --- Cargo.lock | 6 +++--- librustzcash/Cargo.toml | 2 +- zcash_client_backend/Cargo.toml | 2 +- zcash_client_backend/src/encoding.rs | 28 ++++++++++++++++++++-------- zcash_proofs/Cargo.toml | 2 +- zcash_proofs/src/sapling/prover.rs | 6 +++--- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d846871..0efc26d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -328,7 +328,7 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", "zcash_proofs 0.0.0", @@ -576,7 +576,7 @@ version = "0.0.0" dependencies = [ "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -608,7 +608,7 @@ dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index e75a71c..f37b899 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -22,7 +22,7 @@ libc = "0.2" pairing = { path = "../pairing" } lazy_static = "1" byteorder = "1" -rand = "0.4" +rand = "0.5" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } zcash_proofs = { path = "../zcash_proofs" } diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index bc57fdb..38c9988 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -13,4 +13,4 @@ sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] -rand = "0.4" +rand = "0.5" diff --git a/zcash_client_backend/src/encoding.rs b/zcash_client_backend/src/encoding.rs index 17ef335..3d70b41 100644 --- a/zcash_client_backend/src/encoding.rs +++ b/zcash_client_backend/src/encoding.rs @@ -112,7 +112,10 @@ pub fn decode_extended_full_viewing_key( /// }; /// use zcash_primitives::JUBJUB; /// -/// let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); +/// let rng = &mut XorShiftRng::from_seed([ +/// 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, +/// 0xbc, 0xe5, +/// ]); /// /// let pa = PaymentAddress { /// diversifier: Diversifier([0u8; 11]), @@ -121,7 +124,7 @@ pub fn decode_extended_full_viewing_key( /// /// assert_eq!( /// encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &pa), -/// "ztestsapling1qqqqqqqqqqqqqqqqqqxrrfaccydp867g6zg7ne5ht37z38jtfyw0ygmp0ja6hhf07twjq6awtaj", +/// "ztestsapling1qqqqqqqqqqqqqqqqqrjq05nyfku05msvu49mawhg6kr0wwljahypwyk2h88z6975u563j0ym7pe", /// ); /// ``` pub fn encode_payment_address(hrp: &str, addr: &PaymentAddress) -> String { @@ -148,7 +151,10 @@ pub fn encode_payment_address(hrp: &str, addr: &PaymentAddress) -> String /// }; /// use zcash_primitives::JUBJUB; /// -/// let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); +/// let rng = &mut XorShiftRng::from_seed([ +/// 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, +/// 0xbc, 0xe5, +/// ]); /// /// let pa = PaymentAddress { /// diversifier: Diversifier([0u8; 11]), @@ -158,7 +164,7 @@ pub fn encode_payment_address(hrp: &str, addr: &PaymentAddress) -> String /// assert_eq!( /// decode_payment_address( /// HRP_SAPLING_PAYMENT_ADDRESS, -/// "ztestsapling1qqqqqqqqqqqqqqqqqqxrrfaccydp867g6zg7ne5ht37z38jtfyw0ygmp0ja6hhf07twjq6awtaj", +/// "ztestsapling1qqqqqqqqqqqqqqqqqrjq05nyfku05msvu49mawhg6kr0wwljahypwyk2h88z6975u563j0ym7pe", /// ), /// Ok(Some(pa)), /// ); @@ -194,7 +200,10 @@ mod tests { #[test] fn payment_address() { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, + ]); let addr = PaymentAddress { diversifier: Diversifier([0u8; 11]), @@ -202,9 +211,9 @@ mod tests { }; let encoded_main = - "zs1qqqqqqqqqqqqqqqqqqxrrfaccydp867g6zg7ne5ht37z38jtfyw0ygmp0ja6hhf07twjqj2ug6x"; + "zs1qqqqqqqqqqqqqqqqqrjq05nyfku05msvu49mawhg6kr0wwljahypwyk2h88z6975u563j8nfaxd"; let encoded_test = - "ztestsapling1qqqqqqqqqqqqqqqqqqxrrfaccydp867g6zg7ne5ht37z38jtfyw0ygmp0ja6hhf07twjq6awtaj"; + "ztestsapling1qqqqqqqqqqqqqqqqqrjq05nyfku05msvu49mawhg6kr0wwljahypwyk2h88z6975u563j0ym7pe"; assert_eq!( encode_payment_address(constants::mainnet::HRP_SAPLING_PAYMENT_ADDRESS, &addr), @@ -235,7 +244,10 @@ mod tests { #[test] fn invalid_diversifier() { - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, + ]); let addr = PaymentAddress { diversifier: Diversifier([1u8; 11]), diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 34bd520..7072fb2 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -11,6 +11,6 @@ blake2b_simd = "0.5" byteorder = "1" ff = { path = "../ff" } pairing = { path = "../pairing" } -rand = "0.4" +rand = "0.5" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 4d63033..5600cdb 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -3,7 +3,7 @@ use bellman::groth16::{ }; use ff::Field; use pairing::bls12_381::{Bls12, Fr}; -use rand::{OsRng, Rand}; +use rand::OsRng; use sapling_crypto::{ circuit::{ multipack, @@ -59,7 +59,7 @@ impl SaplingProvingContext { let mut rng = OsRng::new().expect("should be able to construct RNG"); // We create the randomness of the value commitment - let rcv = Fs::rand(&mut rng); + let rcv = Fs::random(&mut rng); // Accumulate the value commitment randomness in the context { @@ -194,7 +194,7 @@ impl SaplingProvingContext { // We construct ephemeral randomness for the value commitment. This // randomness is not given back to the caller, but the synthetic // blinding factor `bsk` is accumulated in the context. - let rcv = Fs::rand(&mut rng); + let rcv = Fs::random(&mut rng); // Accumulate the value commitment randomness in the context { From 5728bda2c1a91dd0a5942153652510cb496a1400 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 11 Jul 2019 10:27:05 -0400 Subject: [PATCH 025/105] Replace rust-crypto with sha2 in sapling-crypto dev-dependencies This removes rand < 0.5 from our Cargo.lock. --- Cargo.lock | 82 +--------------------------- sapling-crypto/Cargo.toml | 2 +- sapling-crypto/src/circuit/sha256.rs | 6 +- sapling-crypto/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0efc26d..034f7ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,20 +227,6 @@ name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "futures" version = "0.1.21" @@ -255,11 +241,6 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gcc" -version = "0.3.54" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "generic-array" version = "0.9.0" @@ -419,26 +400,6 @@ dependencies = [ "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.5.6" @@ -464,28 +425,6 @@ name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "redox_syscall" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "sapling-crypto" version = "0.0.1" @@ -499,7 +438,7 @@ dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -531,16 +470,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "time" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "typenum" version = "1.10.0" @@ -640,11 +569,8 @@ dependencies = [ "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" @@ -663,18 +589,12 @@ dependencies = [ "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" -"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 3d895db..34e91eb 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -23,4 +23,4 @@ byteorder = "1" [dev-dependencies] hex-literal = "0.1" -rust-crypto = "0.2" +sha2 = "0.8" diff --git a/sapling-crypto/src/circuit/sha256.rs b/sapling-crypto/src/circuit/sha256.rs index 4837640..86147f8 100644 --- a/sapling-crypto/src/circuit/sha256.rs +++ b/sapling-crypto/src/circuit/sha256.rs @@ -370,8 +370,7 @@ mod test { #[test] fn test_against_vectors() { - use crypto::sha2::Sha256; - use crypto::digest::Digest; + use sha2::{Digest, Sha256}; let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -383,8 +382,7 @@ mod test { let mut h = Sha256::new(); let data: Vec = (0..input_len).map(|_| rng.gen()).collect(); h.input(&data); - let mut hash_result = [0u8; 32]; - h.result(&mut hash_result[..]); + let hash_result = h.result(); let mut cs = TestConstraintSystem::::new(); let mut input_bits = vec![]; diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index 0535d9a..da3bbc4 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -12,7 +12,7 @@ extern crate byteorder; extern crate hex_literal; #[cfg(test)] -extern crate crypto; +extern crate sha2; pub mod jubjub; pub mod group_hash; From 83e1af104e9371aeea85db9c60f07b52857e053f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 12 Jul 2019 23:51:35 -0400 Subject: [PATCH 026/105] Migrate ff, group, pairing, and bellman to rand 0.6 --- Cargo.lock | 119 ++++++++++++++++++++++++++++++++-- bellman/Cargo.toml | 4 +- ff/Cargo.toml | 2 +- group/Cargo.toml | 3 +- group/src/lib.rs | 1 + group/src/tests/mod.rs | 3 +- pairing/Cargo.toml | 4 +- pairing/src/bls12_381/fq.rs | 4 +- pairing/src/bls12_381/fq12.rs | 4 +- pairing/src/bls12_381/fq2.rs | 4 +- pairing/src/bls12_381/fq6.rs | 4 +- pairing/src/bls12_381/fr.rs | 4 +- pairing/src/lib.rs | 2 +- pairing/src/tests/engine.rs | 3 +- pairing/src/tests/field.rs | 21 +++--- pairing/src/tests/repr.rs | 3 +- 16 files changed, 154 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 034f7ee..d4aee36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,6 +43,11 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bech32" version = "0.6.0" @@ -61,8 +66,8 @@ dependencies = [ "group 0.1.0", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -195,7 +200,7 @@ version = "0.4.0" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff_derive 0.3.0", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -262,7 +267,8 @@ name = "group" version = "0.1.0" dependencies = [ "ff 0.4.0", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -367,8 +373,8 @@ dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "group 0.1.0", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -412,6 +418,33 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -425,6 +458,70 @@ name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sapling-crypto" version = "0.0.1" @@ -548,6 +645,7 @@ dependencies = [ "checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" "checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" @@ -590,8 +688,17 @@ dependencies = [ "checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index 72a8034..a56b1ed 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/ebfull/bellman" version = "0.1.0" [dependencies] -rand_core = "0.3" +rand_core = "0.4" bit-vec = "0.4.4" ff = { path = "../ff" } futures = "0.1" @@ -21,7 +21,7 @@ pairing = { path = "../pairing", optional = true } byteorder = "1" [dev-dependencies] -rand = "0.5" +rand = "0.6" [features] groth16 = ["pairing"] diff --git a/ff/Cargo.toml b/ff/Cargo.toml index f428ccd..853f19d 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/ebfull/ff" [dependencies] byteorder = "1" -rand_core = "0.3" +rand_core = "0.4" ff_derive = { version = "0.3.0", path = "ff_derive", optional = true } [features] diff --git a/group/Cargo.toml b/group/Cargo.toml index 020a5bd..f278b4e 100644 --- a/group/Cargo.toml +++ b/group/Cargo.toml @@ -14,4 +14,5 @@ repository = "https://github.com/ebfull/group" [dependencies] ff = { path = "../ff" } -rand = "0.5" +rand = "0.6" +rand_xorshift = "0.1" diff --git a/group/src/lib.rs b/group/src/lib.rs index a97a72c..448c5a3 100644 --- a/group/src/lib.rs +++ b/group/src/lib.rs @@ -1,5 +1,6 @@ extern crate ff; extern crate rand; +extern crate rand_xorshift; use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField}; use rand::RngCore; diff --git a/group/src/tests/mod.rs b/group/src/tests/mod.rs index 5d7e546..2b58b6c 100644 --- a/group/src/tests/mod.rs +++ b/group/src/tests/mod.rs @@ -1,5 +1,6 @@ use ff::{Field, PrimeField}; -use rand::{SeedableRng, XorShiftRng}; +use rand::SeedableRng; +use rand_xorshift::XorShiftRng; use {CurveAffine, CurveProjective, EncodedPoint}; diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml index b6ba134..5a065e2 100644 --- a/pairing/Cargo.toml +++ b/pairing/Cargo.toml @@ -15,13 +15,13 @@ homepage = "https://github.com/ebfull/pairing" repository = "https://github.com/ebfull/pairing" [dependencies] -rand_core = "0.3" +rand_core = "0.4" byteorder = "1" ff = { path = "../ff", features = ["derive"] } group = { path = "../group" } [dev-dependencies] -rand = "0.5" +rand_xorshift = "0.1" [features] unstable-features = ["expose-arith"] diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index b006812..0f54196 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -1173,7 +1173,9 @@ fn test_neg_one() { } #[cfg(test)] -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +#[cfg(test)] +use rand_xorshift::XorShiftRng; #[test] fn test_fq_repr_ordering() { diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 4f675cf..f07a337 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -147,7 +147,9 @@ impl Field for Fq12 { } #[cfg(test)] -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +#[cfg(test)] +use rand_xorshift::XorShiftRng; #[test] fn test_fq12_mul_by_014() { diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index c69f13c..994a28a 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -877,7 +877,9 @@ fn test_fq2_legendre() { } #[cfg(test)] -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +#[cfg(test)] +use rand_xorshift::XorShiftRng; #[test] fn test_fq2_mul_nonresidue() { diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index 21c8310..87e64cb 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -301,7 +301,9 @@ impl Field for Fq6 { } #[cfg(test)] -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +#[cfg(test)] +use rand_xorshift::XorShiftRng; #[test] fn test_fq6_mul_nonresidue() { diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index 20811cd..cb378f4 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -6,7 +6,9 @@ use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; pub struct Fr(FrRepr); #[cfg(test)] -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +#[cfg(test)] +use rand_xorshift::XorShiftRng; #[test] fn test_fr_repr_ordering() { diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index d498c35..1c8d90c 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -17,7 +17,7 @@ extern crate group; extern crate rand_core; #[cfg(test)] -extern crate rand; +extern crate rand_xorshift; #[cfg(test)] pub mod tests; diff --git a/pairing/src/tests/engine.rs b/pairing/src/tests/engine.rs index 8616129..fc74f1b 100644 --- a/pairing/src/tests/engine.rs +++ b/pairing/src/tests/engine.rs @@ -1,5 +1,6 @@ use group::{CurveAffine, CurveProjective}; -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +use rand_xorshift::XorShiftRng; use {Engine, Field, PairingCurveAffine, PrimeField}; diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 0f2f1b2..0a33a73 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -1,5 +1,6 @@ use ff::{Field, LegendreSymbol, PrimeField, SqrtField}; -use rand::{Rng, SeedableRng, XorShiftRng}; +use rand_core::{RngCore, SeedableRng}; +use rand_xorshift::XorShiftRng; pub fn random_frobenius_tests>(characteristic: C, maxpower: usize) { let mut rng = XorShiftRng::from_seed([ @@ -121,7 +122,7 @@ pub fn from_str_tests() { ]); for _ in 0..1000 { - let n: u64 = rng.gen(); + let n = rng.next_u64(); let a = F::from_str(&format!("{}", n)).unwrap(); let b = F::from_repr(n.into()).unwrap(); @@ -136,7 +137,7 @@ pub fn from_str_tests() { assert!(F::from_str("00000000000").is_none()); } -fn random_multiplication_tests(rng: &mut R) { +fn random_multiplication_tests(rng: &mut R) { for _ in 0..10000 { let a = F::random(rng); let b = F::random(rng); @@ -159,7 +160,7 @@ fn random_multiplication_tests(rng: &mut R) { } } -fn random_addition_tests(rng: &mut R) { +fn random_addition_tests(rng: &mut R) { for _ in 0..10000 { let a = F::random(rng); let b = F::random(rng); @@ -182,7 +183,7 @@ fn random_addition_tests(rng: &mut R) { } } -fn random_subtraction_tests(rng: &mut R) { +fn random_subtraction_tests(rng: &mut R) { for _ in 0..10000 { let b = F::random(rng); let a = F::random(rng); @@ -200,7 +201,7 @@ fn random_subtraction_tests(rng: &mut R) { } } -fn random_negation_tests(rng: &mut R) { +fn random_negation_tests(rng: &mut R) { for _ in 0..10000 { let a = F::random(rng); let mut b = a; @@ -211,7 +212,7 @@ fn random_negation_tests(rng: &mut R) { } } -fn random_doubling_tests(rng: &mut R) { +fn random_doubling_tests(rng: &mut R) { for _ in 0..10000 { let mut a = F::random(rng); let mut b = a; @@ -222,7 +223,7 @@ fn random_doubling_tests(rng: &mut R) { } } -fn random_squaring_tests(rng: &mut R) { +fn random_squaring_tests(rng: &mut R) { for _ in 0..10000 { let mut a = F::random(rng); let mut b = a; @@ -233,7 +234,7 @@ fn random_squaring_tests(rng: &mut R) { } } -fn random_inversion_tests(rng: &mut R) { +fn random_inversion_tests(rng: &mut R) { assert!(F::zero().inverse().is_none()); for _ in 0..10000 { @@ -245,7 +246,7 @@ fn random_inversion_tests(rng: &mut R) { } } -fn random_expansion_tests(rng: &mut R) { +fn random_expansion_tests(rng: &mut R) { for _ in 0..10000 { // Compare (a + b)(c + d) and (a*c + b*c + a*d + b*d) diff --git a/pairing/src/tests/repr.rs b/pairing/src/tests/repr.rs index 692c4d3..67badd8 100644 --- a/pairing/src/tests/repr.rs +++ b/pairing/src/tests/repr.rs @@ -1,5 +1,6 @@ use ff::{PrimeField, PrimeFieldRepr}; -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +use rand_xorshift::XorShiftRng; pub fn random_repr_tests() { random_encoding_tests::

(); From 60d344a0a7d60b047a6c6c2d1fbc2adbc0b18265 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 12 Jul 2019 23:54:59 -0400 Subject: [PATCH 027/105] Migrate sapling-crypto to rand_core 0.4 --- Cargo.lock | 3 +- sapling-crypto/Cargo.toml | 3 +- sapling-crypto/examples/bench.rs | 8 ++-- sapling-crypto/src/circuit/blake2s.rs | 10 +++-- sapling-crypto/src/circuit/ecc.rs | 14 ++++--- sapling-crypto/src/circuit/lookup.rs | 15 +++---- sapling-crypto/src/circuit/multipack.rs | 6 ++- sapling-crypto/src/circuit/num.rs | 4 +- sapling-crypto/src/circuit/pedersen_hash.rs | 7 ++-- sapling-crypto/src/circuit/sapling/mod.rs | 13 ++++--- sapling-crypto/src/circuit/sha256.rs | 7 ++-- sapling-crypto/src/circuit/uint32.rs | 43 +++++++++++---------- sapling-crypto/src/jubjub/edwards.rs | 9 ++--- sapling-crypto/src/jubjub/fs.rs | 6 ++- sapling-crypto/src/jubjub/montgomery.rs | 9 ++--- sapling-crypto/src/jubjub/tests.rs | 3 +- sapling-crypto/src/lib.rs | 5 ++- sapling-crypto/src/redjubjub.rs | 29 ++++++++++---- 18 files changed, 115 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4aee36..4c36e99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -534,7 +534,8 @@ dependencies = [ "ff 0.4.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 34e91eb..da28615 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -17,10 +17,11 @@ bellman = { path = "../bellman" } blake2b_simd = "0.5" blake2s_simd = "0.5" ff = { path = "../ff" } -rand = "0.5" +rand_core = "0.4" digest = "0.7" byteorder = "1" [dev-dependencies] hex-literal = "0.1" +rand_xorshift = "0.1" sha2 = "0.8" diff --git a/sapling-crypto/examples/bench.rs b/sapling-crypto/examples/bench.rs index 9b4c0ae..e9ffc13 100644 --- a/sapling-crypto/examples/bench.rs +++ b/sapling-crypto/examples/bench.rs @@ -1,8 +1,9 @@ extern crate ff; extern crate sapling_crypto; extern crate bellman; -extern crate rand; extern crate pairing; +extern crate rand_core; +extern crate rand_xorshift; use ff::Field; use std::time::{Duration, Instant}; @@ -20,7 +21,8 @@ use sapling_crypto::primitives::{ ValueCommitment }; use bellman::groth16::*; -use rand::{XorShiftRng, SeedableRng, Rng, RngCore}; +use rand_core::{RngCore, SeedableRng}; +use rand_xorshift::XorShiftRng; use pairing::bls12_381::{Bls12, Fr}; const TREE_DEPTH: usize = 32; @@ -86,7 +88,7 @@ fn main() { } let commitment_randomness = fs::Fs::random(rng); - let auth_path = vec![Some((Fr::random(rng), rng.gen())); TREE_DEPTH]; + let auth_path = vec![Some((Fr::random(rng), rng.next_u32() % 2 != 0)); TREE_DEPTH]; let ar = fs::Fs::random(rng); let anchor = Fr::random(rng); diff --git a/sapling-crypto/src/circuit/blake2s.rs b/sapling-crypto/src/circuit/blake2s.rs index e6748ba..8627dc0 100644 --- a/sapling-crypto/src/circuit/blake2s.rs +++ b/sapling-crypto/src/circuit/blake2s.rs @@ -321,8 +321,10 @@ pub fn blake2s>( #[cfg(test)] mod test { use blake2s_simd::Params as Blake2sParams; - use rand::{XorShiftRng, SeedableRng, Rng}; use pairing::bls12_381::{Bls12}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; + use ::circuit::boolean::{Boolean, AllocatedBit}; use ::circuit::test::TestConstraintSystem; use super::blake2s; @@ -371,7 +373,7 @@ mod test { 0xe5, ]); let input_bits: Vec<_> = (0..512) - .map(|_| Boolean::constant(rng.gen())) + .map(|_| Boolean::constant(rng.next_u32() % 2 != 0)) .chain((0..512) .map(|i| AllocatedBit::alloc(cs.namespace(|| format!("input bit {}", i)), Some(true)).unwrap().into())) .collect(); @@ -387,7 +389,7 @@ mod test { 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5, ]); - let input_bits: Vec<_> = (0..512).map(|_| Boolean::constant(rng.gen())).collect(); + let input_bits: Vec<_> = (0..512).map(|_| Boolean::constant(rng.next_u32() % 2 != 0)).collect(); blake2s(&mut cs, &input_bits, b"12345678").unwrap(); assert_eq!(cs.num_constraints(), 0); } @@ -403,7 +405,7 @@ mod test { { let mut h = Blake2sParams::new().hash_length(32).personal(b"12345678").to_state(); - let data: Vec = (0..input_len).map(|_| rng.gen()).collect(); + let data: Vec = (0..input_len).map(|_| rng.next_u32() as u8).collect(); h.update(&data); diff --git a/sapling-crypto/src/circuit/ecc.rs b/sapling-crypto/src/circuit/ecc.rs index 3fc9713..9b4dbbc 100644 --- a/sapling-crypto/src/circuit/ecc.rs +++ b/sapling-crypto/src/circuit/ecc.rs @@ -748,9 +748,11 @@ impl MontgomeryPoint { #[cfg(test)] mod test { use bellman::{ConstraintSystem}; - use rand::{XorShiftRng, SeedableRng, Rng}; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; + use ::circuit::test::*; use ::jubjub::{ montgomery, @@ -1001,10 +1003,10 @@ mod test { y: num_y0 }; - let mut should_we_select = rng.gen(); + let mut should_we_select = rng.next_u32() % 2 != 0; // Conditionally allocate - let mut b = if rng.gen() { + let mut b = if rng.next_u32() % 2 != 0 { Boolean::from(AllocatedBit::alloc( cs.namespace(|| "condition"), Some(should_we_select) @@ -1014,7 +1016,7 @@ mod test { }; // Conditionally negate - if rng.gen() { + if rng.next_u32() % 2 != 0 { b = b.not(); should_we_select = !should_we_select; } @@ -1163,7 +1165,7 @@ mod test { for _ in 0..100 { let p1 = loop { let x = Fr::random(rng); - let s: bool = rng.gen(); + let s: bool = rng.next_u32() % 2 != 0; if let Some(p) = montgomery::Point::::get_for_x(x, s, params) { break p; @@ -1172,7 +1174,7 @@ mod test { let p2 = loop { let x = Fr::random(rng); - let s: bool = rng.gen(); + let s: bool = rng.next_u32() % 2 != 0; if let Some(p) = montgomery::Point::::get_for_x(x, s, params) { break p; diff --git a/sapling-crypto/src/circuit/lookup.rs b/sapling-crypto/src/circuit/lookup.rs index 4b6e13b..d57f17c 100644 --- a/sapling-crypto/src/circuit/lookup.rs +++ b/sapling-crypto/src/circuit/lookup.rs @@ -196,11 +196,12 @@ pub fn lookup3_xy_with_conditional_negation( #[cfg(test)] mod test { - use rand::{SeedableRng, Rng, XorShiftRng}; use super::*; use ::circuit::test::*; use ::circuit::boolean::{Boolean, AllocatedBit}; use pairing::bls12_381::{Bls12, Fr}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; #[test] fn test_lookup3_xy() { @@ -212,17 +213,17 @@ mod test { for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); - let a_val = rng.gen(); + let a_val = rng.next_u32() % 2 != 0; let a = Boolean::from( AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap() ); - let b_val = rng.gen(); + let b_val = rng.next_u32() % 2 != 0; let b = Boolean::from( AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap() ); - let c_val = rng.gen(); + let c_val = rng.next_u32() % 2 != 0; let c = Boolean::from( AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap() ); @@ -255,17 +256,17 @@ mod test { for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); - let a_val = rng.gen(); + let a_val = rng.next_u32() % 2 != 0; let a = Boolean::from( AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap() ); - let b_val = rng.gen(); + let b_val = rng.next_u32() % 2 != 0; let b = Boolean::from( AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap() ); - let c_val = rng.gen(); + let c_val = rng.next_u32() % 2 != 0; let c = Boolean::from( AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap() ); diff --git a/sapling-crypto/src/circuit/multipack.rs b/sapling-crypto/src/circuit/multipack.rs index fd7cbfb..fdecd34 100644 --- a/sapling-crypto/src/circuit/multipack.rs +++ b/sapling-crypto/src/circuit/multipack.rs @@ -80,9 +80,11 @@ pub fn compute_multipacking( #[test] fn test_multipacking() { - use rand::{SeedableRng, Rng, XorShiftRng}; use bellman::{ConstraintSystem}; use pairing::bls12_381::{Bls12}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; + use ::circuit::test::*; use super::boolean::{AllocatedBit, Boolean}; @@ -94,7 +96,7 @@ fn test_multipacking() { for num_bits in 0..1500 { let mut cs = TestConstraintSystem::::new(); - let bits: Vec = (0..num_bits).map(|_| rng.gen()).collect(); + let bits: Vec = (0..num_bits).map(|_| rng.next_u32() % 2 != 0).collect(); let circuit_bits = bits.iter().enumerate() .map(|(i, &b)| { diff --git a/sapling-crypto/src/circuit/num.rs b/sapling-crypto/src/circuit/num.rs index 7201356..1cdfe22 100644 --- a/sapling-crypto/src/circuit/num.rs +++ b/sapling-crypto/src/circuit/num.rs @@ -455,10 +455,12 @@ impl Num { #[cfg(test)] mod test { - use rand::{SeedableRng, XorShiftRng}; use bellman::{ConstraintSystem}; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; + use rand_core::SeedableRng; + use rand_xorshift::XorShiftRng; + use ::circuit::test::*; use super::{AllocatedNum, Boolean}; diff --git a/sapling-crypto/src/circuit/pedersen_hash.rs b/sapling-crypto/src/circuit/pedersen_hash.rs index f26b98e..dd000d3 100644 --- a/sapling-crypto/src/circuit/pedersen_hash.rs +++ b/sapling-crypto/src/circuit/pedersen_hash.rs @@ -112,12 +112,13 @@ pub fn pedersen_hash( #[cfg(test)] mod test { - use rand::{SeedableRng, Rng, XorShiftRng}; use super::*; use ::circuit::test::*; use ::circuit::boolean::{Boolean, AllocatedBit}; use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; #[test] fn test_pedersen_hash_constraints() { @@ -128,7 +129,7 @@ mod test { let params = &JubjubBls12::new(); let mut cs = TestConstraintSystem::::new(); - let input: Vec = (0..(Fr::NUM_BITS * 2)).map(|_| rng.gen()).collect(); + let input: Vec = (0..(Fr::NUM_BITS * 2)).map(|_| rng.next_u32() % 2 != 0).collect(); let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { Boolean::from( @@ -157,7 +158,7 @@ mod test { for length in 0..751 { for _ in 0..5 { - let mut input: Vec = (0..length).map(|_| rng.gen()).collect(); + let mut input: Vec = (0..length).map(|_| rng.next_u32() % 2 != 0).collect(); let mut cs = TestConstraintSystem::::new(); diff --git a/sapling-crypto/src/circuit/sapling/mod.rs b/sapling-crypto/src/circuit/sapling/mod.rs index 2c4d566..469ab2e 100644 --- a/sapling-crypto/src/circuit/sapling/mod.rs +++ b/sapling-crypto/src/circuit/sapling/mod.rs @@ -600,7 +600,9 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { fn test_input_circuit_with_bls12_381() { use ff::{BitIterator, Field}; use pairing::bls12_381::*; - use rand::{SeedableRng, Rng, RngCore, XorShiftRng}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; + use ::circuit::test::*; use jubjub::{JubjubBls12, fs, edwards}; @@ -614,7 +616,7 @@ fn test_input_circuit_with_bls12_381() { for _ in 0..10 { let value_commitment = ValueCommitment { - value: rng.gen(), + value: rng.next_u64(), randomness: fs::Fs::random(rng), }; @@ -649,7 +651,7 @@ fn test_input_circuit_with_bls12_381() { let g_d = payment_address.diversifier.g_d(params).unwrap(); let commitment_randomness = fs::Fs::random(rng); - let auth_path = vec![Some((Fr::random(rng), rng.gen())); tree_depth]; + let auth_path = vec![Some((Fr::random(rng), rng.next_u32() % 2 != 0)); tree_depth]; let ar = fs::Fs::random(rng); { @@ -739,7 +741,8 @@ fn test_input_circuit_with_bls12_381() { fn test_output_circuit_with_bls12_381() { use ff::Field; use pairing::bls12_381::*; - use rand::{SeedableRng, Rng, RngCore, XorShiftRng}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; use ::circuit::test::*; use jubjub::{JubjubBls12, fs, edwards}; @@ -751,7 +754,7 @@ fn test_output_circuit_with_bls12_381() { for _ in 0..100 { let value_commitment = ValueCommitment { - value: rng.gen(), + value: rng.next_u64(), randomness: fs::Fs::random(rng), }; diff --git a/sapling-crypto/src/circuit/sha256.rs b/sapling-crypto/src/circuit/sha256.rs index 86147f8..3b32282 100644 --- a/sapling-crypto/src/circuit/sha256.rs +++ b/sapling-crypto/src/circuit/sha256.rs @@ -308,7 +308,8 @@ mod test { use circuit::boolean::AllocatedBit; use pairing::bls12_381::Bls12; use circuit::test::TestConstraintSystem; - use rand::{XorShiftRng, SeedableRng, Rng}; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; #[test] fn test_blank_hash() { @@ -353,7 +354,7 @@ mod test { Boolean::from( AllocatedBit::alloc( cs.namespace(|| format!("input bit {}", i)), - Some(rng.gen()) + Some(rng.next_u32() % 2 != 0) ).unwrap() ) }).collect(); @@ -380,7 +381,7 @@ mod test { for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { let mut h = Sha256::new(); - let data: Vec = (0..input_len).map(|_| rng.gen()).collect(); + let data: Vec = (0..input_len).map(|_| rng.next_u32() as u8).collect(); h.input(&data); let hash_result = h.result(); diff --git a/sapling-crypto/src/circuit/uint32.rs b/sapling-crypto/src/circuit/uint32.rs index daca627..939b544 100644 --- a/sapling-crypto/src/circuit/uint32.rs +++ b/sapling-crypto/src/circuit/uint32.rs @@ -409,7 +409,6 @@ impl UInt32 { #[cfg(test)] mod test { - use rand::{XorShiftRng, SeedableRng, Rng}; use ::circuit::boolean::{Boolean}; use super::{UInt32}; use ff::Field; @@ -417,6 +416,8 @@ mod test { use ::circuit::test::*; use bellman::{ConstraintSystem}; use circuit::multieq::MultiEq; + use rand_core::{RngCore, SeedableRng}; + use rand_xorshift::XorShiftRng; #[test] fn test_uint32_from_bits_be() { @@ -426,7 +427,7 @@ mod test { ]); for _ in 0..1000 { - let mut v = (0..32).map(|_| Boolean::constant(rng.gen())).collect::>(); + let mut v = (0..32).map(|_| Boolean::constant(rng.next_u32() % 2 != 0)).collect::>(); let b = UInt32::from_bits_be(&v); @@ -460,7 +461,7 @@ mod test { ]); for _ in 0..1000 { - let mut v = (0..32).map(|_| Boolean::constant(rng.gen())).collect::>(); + let mut v = (0..32).map(|_| Boolean::constant(rng.next_u32() % 2 != 0)).collect::>(); let b = UInt32::from_bits(&v); @@ -496,9 +497,9 @@ mod test { for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); - let a: u32 = rng.gen(); - let b: u32 = rng.gen(); - let c: u32 = rng.gen(); + let a = rng.next_u32(); + let b = rng.next_u32(); + let c = rng.next_u32(); let mut expected = a ^ b ^ c; @@ -541,9 +542,9 @@ mod test { for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); - let a: u32 = rng.gen(); - let b: u32 = rng.gen(); - let c: u32 = rng.gen(); + let a = rng.next_u32(); + let b = rng.next_u32(); + let c = rng.next_u32(); let a_bit = UInt32::constant(a); let b_bit = UInt32::constant(b); @@ -583,10 +584,10 @@ mod test { for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); - let a: u32 = rng.gen(); - let b: u32 = rng.gen(); - let c: u32 = rng.gen(); - let d: u32 = rng.gen(); + let a = rng.next_u32(); + let b = rng.next_u32(); + let c = rng.next_u32(); + let d = rng.next_u32(); let mut expected = (a ^ b).wrapping_add(c).wrapping_add(d); @@ -640,7 +641,7 @@ mod test { 0xe5, ]); - let mut num = rng.gen(); + let mut num = rng.next_u32(); let a = UInt32::constant(num); @@ -675,7 +676,7 @@ mod test { for _ in 0..50 { for i in 0..60 { - let num = rng.gen(); + let num = rng.next_u32(); let a = UInt32::constant(num).shr(i); let b = UInt32::constant(num.wrapping_shr(i as u32)); @@ -699,9 +700,9 @@ mod test { for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); - let a: u32 = rng.gen(); - let b: u32 = rng.gen(); - let c: u32 = rng.gen(); + let a = rng.next_u32(); + let b = rng.next_u32(); + let c = rng.next_u32(); let mut expected = (a & b) ^ (a & c) ^ (b & c); @@ -743,9 +744,9 @@ mod test { for _ in 0..1000 { let mut cs = TestConstraintSystem::::new(); - let a: u32 = rng.gen(); - let b: u32 = rng.gen(); - let c: u32 = rng.gen(); + let a = rng.next_u32(); + let b = rng.next_u32(); + let c = rng.next_u32(); let mut expected = (a & b) ^ ((!a) & c); diff --git a/sapling-crypto/src/jubjub/edwards.rs b/sapling-crypto/src/jubjub/edwards.rs index 95b6120..e912aca 100644 --- a/sapling-crypto/src/jubjub/edwards.rs +++ b/sapling-crypto/src/jubjub/edwards.rs @@ -8,9 +8,7 @@ use super::{ montgomery }; -use rand::{ - Rng -}; +use rand_core::RngCore; use std::marker::PhantomData; @@ -185,12 +183,13 @@ impl Point { convert_subgroup(&tmp) } - pub fn rand(rng: &mut R, params: &E::Params) -> Self + pub fn rand(rng: &mut R, params: &E::Params) -> Self { loop { let y = E::Fr::random(rng); + let sign = rng.next_u32() % 2 != 0; - if let Some(p) = Self::get_for_y(y, rng.gen(), params) { + if let Some(p) = Self::get_for_y(y, sign, params) { return p; } } diff --git a/sapling-crypto/src/jubjub/fs.rs b/sapling-crypto/src/jubjub/fs.rs index 55df2cb..017292b 100644 --- a/sapling-crypto/src/jubjub/fs.rs +++ b/sapling-crypto/src/jubjub/fs.rs @@ -4,7 +4,7 @@ use ff::{ LegendreSymbol::{self, *}, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField, }; -use rand::RngCore; +use rand_core::RngCore; use super::ToUniform; @@ -620,7 +620,9 @@ fn test_neg_one() { } #[cfg(test)] -use rand::{SeedableRng, XorShiftRng}; +use rand_core::SeedableRng; +#[cfg(test)] +use rand_xorshift::XorShiftRng; #[test] fn test_fs_repr_ordering() { diff --git a/sapling-crypto/src/jubjub/montgomery.rs b/sapling-crypto/src/jubjub/montgomery.rs index 28dce8e..9bd6023 100644 --- a/sapling-crypto/src/jubjub/montgomery.rs +++ b/sapling-crypto/src/jubjub/montgomery.rs @@ -8,9 +8,7 @@ use super::{ edwards }; -use rand::{ - Rng -}; +use rand_core::RngCore; use std::marker::PhantomData; @@ -101,12 +99,13 @@ impl Point { convert_subgroup(&tmp) } - pub fn rand(rng: &mut R, params: &E::Params) -> Self + pub fn rand(rng: &mut R, params: &E::Params) -> Self { loop { let x = E::Fr::random(rng); + let sign = rng.next_u32() % 2 != 0; - match Self::get_for_x(x, rng.gen(), params) { + match Self::get_for_x(x, sign, params) { Some(p) => { return p }, diff --git a/sapling-crypto/src/jubjub/tests.rs b/sapling-crypto/src/jubjub/tests.rs index 19aae80..e15b81e 100644 --- a/sapling-crypto/src/jubjub/tests.rs +++ b/sapling-crypto/src/jubjub/tests.rs @@ -14,7 +14,8 @@ use ff::{ LegendreSymbol }; -use rand::{RngCore, XorShiftRng, SeedableRng}; +use rand_core::{RngCore, SeedableRng}; +use rand_xorshift::XorShiftRng; pub fn test_suite(params: &E::Params) { test_back_and_forth::(params); diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index da3bbc4..14e713d 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -4,13 +4,16 @@ extern crate blake2b_simd; extern crate blake2s_simd; extern crate digest; extern crate ff; -extern crate rand; +extern crate rand_core; extern crate byteorder; #[cfg(test)] #[macro_use] extern crate hex_literal; +#[cfg(test)] +extern crate rand_xorshift; + #[cfg(test)] extern crate sha2; diff --git a/sapling-crypto/src/redjubjub.rs b/sapling-crypto/src/redjubjub.rs index 2b34654..cd02347 100644 --- a/sapling-crypto/src/redjubjub.rs +++ b/sapling-crypto/src/redjubjub.rs @@ -2,7 +2,7 @@ //! See section 5.4.6 of the Sapling protocol specification. use ff::{Field, PrimeField, PrimeFieldRepr}; -use rand::{Rng}; +use rand_core::RngCore; use std::io::{self, Read, Write}; use jubjub::{FixedGenerators, JubjubEngine, JubjubParams, Unknown, edwards::Point}; @@ -71,7 +71,7 @@ impl PrivateKey { write_scalar::(&self.0, writer) } - pub fn sign( + pub fn sign( &self, msg: &[u8], rng: &mut R, @@ -163,7 +163,7 @@ pub struct BatchEntry<'a, E: JubjubEngine> { // TODO: #82: This is a naive implementation currently, // and doesn't use multiexp. -pub fn batch_verify<'a, E: JubjubEngine, R: Rng>( +pub fn batch_verify<'a, E: JubjubEngine, R: RngCore>( rng: &mut R, batch: &[BatchEntry<'a, E>], p_g: FixedGenerators, @@ -206,7 +206,8 @@ pub fn batch_verify<'a, E: JubjubEngine, R: Rng>( #[cfg(test)] mod tests { use pairing::bls12_381::Bls12; - use rand::thread_rng; + use rand_core::SeedableRng; + use rand_xorshift::XorShiftRng; use jubjub::{JubjubBls12, fs::Fs, edwards}; @@ -214,7 +215,10 @@ mod tests { #[test] fn test_batch_verify() { - let rng = &mut thread_rng(); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let params = &JubjubBls12::new(); let p_g = FixedGenerators::SpendingKeyGenerator; @@ -244,7 +248,10 @@ mod tests { #[test] fn cofactor_check() { - let rng = &mut thread_rng(); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let params = &JubjubBls12::new(); let zero = edwards::Point::zero(); let p_g = FixedGenerators::SpendingKeyGenerator; @@ -276,7 +283,10 @@ mod tests { #[test] fn round_trip_serialization() { - let rng = &mut thread_rng(); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let p_g = FixedGenerators::SpendingKeyGenerator; let params = &JubjubBls12::new(); @@ -309,7 +319,10 @@ mod tests { #[test] fn random_signatures() { - let rng = &mut thread_rng(); + let rng = &mut XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); let p_g = FixedGenerators::SpendingKeyGenerator; let params = &JubjubBls12::new(); From 8f7adec0d940e6e260d4abb14d2c09e3b6662ce6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 13 Jul 2019 00:16:54 -0400 Subject: [PATCH 028/105] Migrate zcash_primitives to rand_core 0.4 --- Cargo.lock | 3 +- zcash_primitives/Cargo.toml | 3 +- zcash_primitives/src/lib.rs | 3 +- zcash_primitives/src/merkle_tree.rs | 4 +- zcash_primitives/src/note_encryption.rs | 58 +++++++++++------------ zcash_primitives/src/sapling.rs | 2 +- zcash_primitives/src/transaction/tests.rs | 4 +- 7 files changed, 40 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c36e99..e435c6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -621,7 +621,8 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index d82b3bc..10c6d00 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -15,6 +15,7 @@ fpe = "0.1" hex = "0.3" lazy_static = "1" pairing = { path = "../pairing" } -rand = "0.5" +rand_core = "0.4" +rand_os = "0.1" sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 70bd8fa..90d69e6 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -9,7 +9,8 @@ extern crate ff; extern crate fpe; extern crate hex; extern crate pairing; -extern crate rand; +extern crate rand_core; +extern crate rand_os; extern crate sapling_crypto; extern crate sha2; diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 3b94bd9..a692073 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -202,12 +202,12 @@ impl CommitmentTree { /// ``` /// extern crate ff; /// extern crate pairing; -/// extern crate rand; +/// extern crate rand_os; /// extern crate zcash_primitives; /// /// use ff::{Field, PrimeField}; /// use pairing::bls12_381::Fr; -/// use rand::OsRng; +/// use rand_os::OsRng; /// use zcash_primitives::{ /// merkle_tree::{CommitmentTree, IncrementalWitness}, /// sapling::Node, diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index b1b483f..728818f 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -5,7 +5,8 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr}; -use rand::{OsRng, Rng}; +use rand_core::RngCore; +use rand_os::OsRng; use sapling_crypto::{ jubjub::{ edwards, @@ -138,9 +139,7 @@ fn generate_esk() -> Fs { // create random 64 byte buffer let mut rng = OsRng::new().expect("should be able to construct RNG"); let mut buffer = [0u8; 64]; - for i in 0..buffer.len() { - buffer[i] = rng.gen(); - } + rng.fill_bytes(&mut buffer); // reduce to uniform value Fs::to_uniform(&buffer[..]) @@ -213,12 +212,12 @@ fn prf_ock( /// ``` /// extern crate ff; /// extern crate pairing; -/// extern crate rand; +/// extern crate rand_os; /// extern crate sapling_crypto; /// /// use ff::Field; /// use pairing::bls12_381::Bls12; -/// use rand::OsRng; +/// use rand_os::OsRng; /// use sapling_crypto::{ /// jubjub::fs::Fs, /// primitives::{Diversifier, PaymentAddress, ValueCommitment}, @@ -562,7 +561,8 @@ mod tests { use crypto_api_chachapoly::ChachaPolyIetf; use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; - use rand::{thread_rng, RngCore}; + use rand_core::RngCore; + use rand_os::OsRng; use sapling_crypto::{ jubjub::{ edwards, @@ -848,7 +848,7 @@ mod tests { #[test] fn decryption_with_invalid_ivk() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, _, _, cmu, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -860,7 +860,7 @@ mod tests { #[test] fn decryption_with_invalid_epk() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, ivk, _, cmu, _, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -877,7 +877,7 @@ mod tests { #[test] fn decryption_with_invalid_cmu() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, ivk, _, _, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -889,7 +889,7 @@ mod tests { #[test] fn decryption_with_invalid_tag() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, ivk, _, cmu, epk, mut enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -902,7 +902,7 @@ mod tests { #[test] fn decryption_with_invalid_version_byte() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -924,7 +924,7 @@ mod tests { #[test] fn decryption_with_invalid_diversifier() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -946,7 +946,7 @@ mod tests { #[test] fn decryption_with_incorrect_diversifier() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -968,7 +968,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_ivk() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, _, _, cmu, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -985,7 +985,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_epk() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, ivk, _, cmu, _, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -1002,7 +1002,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_cmu() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (_, ivk, _, _, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -1019,7 +1019,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_version_byte() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1046,7 +1046,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_diversifier() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1073,7 +1073,7 @@ mod tests { #[test] fn compact_decryption_with_incorrect_diversifier() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1100,7 +1100,7 @@ mod tests { #[test] fn recovery_with_invalid_ovk() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (mut ovk, _, cv, cmu, epk, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1114,7 +1114,7 @@ mod tests { #[test] fn recovery_with_invalid_cv() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, _, cmu, epk, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1133,7 +1133,7 @@ mod tests { #[test] fn recovery_with_invalid_cmu() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, _, epk, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1152,7 +1152,7 @@ mod tests { #[test] fn recovery_with_invalid_epk() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, cmu, _, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1171,7 +1171,7 @@ mod tests { #[test] fn recovery_with_invalid_enc_tag() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1185,7 +1185,7 @@ mod tests { #[test] fn recovery_with_invalid_out_tag() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, cmu, epk, enc_ciphertext, mut out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1199,7 +1199,7 @@ mod tests { #[test] fn recovery_with_invalid_version_byte() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1221,7 +1221,7 @@ mod tests { #[test] fn recovery_with_invalid_diversifier() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1243,7 +1243,7 @@ mod tests { #[test] fn recovery_with_incorrect_diversifier() { - let mut rng = thread_rng(); + let mut rng = OsRng::new().expect("should be able to construct RNG"); let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 0ee808c..7f2b6f2 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -2,7 +2,7 @@ use ff::{BitIterator, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use rand::OsRng; +use rand_os::OsRng; use sapling_crypto::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, pedersen_hash::{pedersen_hash, Personalization}, diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 7ef691f..81f8e21 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1,6 +1,6 @@ use ff::Field; use pairing::bls12_381::Bls12; -use rand::thread_rng; +use rand_os::OsRng; use sapling_crypto::{ jubjub::{fs::Fs, FixedGenerators}, redjubjub::PrivateKey, @@ -197,7 +197,7 @@ fn tx_write_rejects_unexpected_binding_sig() { // Fails with an unexpected binding signature { - let rng = &mut thread_rng(); + let rng = &mut OsRng::new().expect("should be able to construct RNG"); let sk = PrivateKey::(Fs::random(rng)); let sig = sk.sign( b"Foo bar", From b0913afdd7f179466bb13dd4ad2a78d90a9a9d60 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 13 Jul 2019 01:54:47 -0400 Subject: [PATCH 029/105] Migrate remaining crates to rand_core 0.4 --- Cargo.lock | 21 +++++---------------- librustzcash/Cargo.toml | 3 ++- librustzcash/src/rustzcash.rs | 10 +++++----- librustzcash/src/tests/key_agreement.rs | 7 +++++-- zcash_client_backend/Cargo.toml | 3 ++- zcash_client_backend/src/encoding.rs | 9 ++++++--- zcash_proofs/Cargo.toml | 2 +- zcash_proofs/src/lib.rs | 2 +- zcash_proofs/src/sapling/prover.rs | 2 +- 9 files changed, 28 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e435c6d..d1cb83f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -315,7 +315,8 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", "zcash_proofs 0.0.0", @@ -406,18 +407,6 @@ dependencies = [ "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.6.5" @@ -603,7 +592,8 @@ version = "0.0.0" dependencies = [ "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -636,7 +626,7 @@ dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -689,7 +679,6 @@ dependencies = [ "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index f37b899..d67d4ee 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -22,7 +22,8 @@ libc = "0.2" pairing = { path = "../pairing" } lazy_static = "1" byteorder = "1" -rand = "0.5" +rand_core = "0.4" +rand_os = "0.1" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } zcash_proofs = { path = "../zcash_proofs" } diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index cfb26e1..7f10d1c 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -5,7 +5,8 @@ extern crate byteorder; extern crate ff; extern crate libc; extern crate pairing; -extern crate rand; +extern crate rand_core; +extern crate rand_os; extern crate sapling_crypto; extern crate zcash_primitives; extern crate zcash_proofs; @@ -37,7 +38,8 @@ use blake2s_simd::Params as Blake2sParams; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use rand::{OsRng, Rng}; +use rand_core::RngCore; +use rand_os::OsRng; use std::io::BufReader; use libc::{c_char, c_uchar, int64_t, size_t, uint32_t, uint64_t}; @@ -388,9 +390,7 @@ pub extern "system" fn librustzcash_sapling_generate_r(result: *mut [c_uchar; 32 // create random 64 byte buffer let mut rng = OsRng::new().expect("should be able to construct RNG"); let mut buffer = [0u8; 64]; - for i in 0..buffer.len() { - buffer[i] = rng.gen(); - } + rng.fill_bytes(&mut buffer); // reduce to uniform value let r = ::Fs::to_uniform(&buffer[..]); diff --git a/librustzcash/src/tests/key_agreement.rs b/librustzcash/src/tests/key_agreement.rs index a72abf0..9d22561 100644 --- a/librustzcash/src/tests/key_agreement.rs +++ b/librustzcash/src/tests/key_agreement.rs @@ -1,6 +1,7 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; -use rand::{OsRng, Rng}; +use rand_core::RngCore; +use rand_os::OsRng; use sapling_crypto::jubjub::{edwards, JubjubBls12}; use sapling_crypto::primitives::{Diversifier, ViewingKey}; @@ -22,7 +23,9 @@ fn test_key_agreement() { // Create a random address with the viewing key let addr = loop { - match vk.into_payment_address(Diversifier(rng.gen()), ¶ms) { + let mut d = [0; 11]; + rng.fill_bytes(&mut d); + match vk.into_payment_address(Diversifier(d), ¶ms) { Some(a) => break a, None => {} } diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 38c9988..8e7e055 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -13,4 +13,5 @@ sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] -rand = "0.5" +rand_core = "0.4" +rand_xorshift = "0.1" diff --git a/zcash_client_backend/src/encoding.rs b/zcash_client_backend/src/encoding.rs index 3d70b41..d816201 100644 --- a/zcash_client_backend/src/encoding.rs +++ b/zcash_client_backend/src/encoding.rs @@ -101,7 +101,8 @@ pub fn decode_extended_full_viewing_key( /// /// ``` /// use pairing::bls12_381::Bls12; -/// use rand::{SeedableRng, XorShiftRng}; +/// use rand_core::SeedableRng; +/// use rand_xorshift::XorShiftRng; /// use sapling_crypto::{ /// jubjub::edwards, /// primitives::{Diversifier, PaymentAddress}, @@ -140,7 +141,8 @@ pub fn encode_payment_address(hrp: &str, addr: &PaymentAddress) -> String /// /// ``` /// use pairing::bls12_381::Bls12; -/// use rand::{SeedableRng, XorShiftRng}; +/// use rand_core::SeedableRng; +/// use rand_xorshift::XorShiftRng; /// use sapling_crypto::{ /// jubjub::edwards, /// primitives::{Diversifier, PaymentAddress}, @@ -188,7 +190,8 @@ pub fn decode_payment_address(hrp: &str, s: &str) -> Result Date: Sun, 14 Jul 2019 12:19:01 +0100 Subject: [PATCH 030/105] Migrate to rand 0.7 --- Cargo.lock | 218 ++++++++-------------- bellman/Cargo.toml | 4 +- ff/Cargo.toml | 2 +- group/Cargo.toml | 4 +- librustzcash/Cargo.toml | 4 +- librustzcash/src/rustzcash.rs | 4 +- librustzcash/src/tests/key_agreement.rs | 2 +- pairing/Cargo.toml | 4 +- sapling-crypto/Cargo.toml | 4 +- zcash_client_backend/Cargo.toml | 4 +- zcash_primitives/Cargo.toml | 4 +- zcash_primitives/src/note_encryption.rs | 48 ++--- zcash_primitives/src/sapling.rs | 2 +- zcash_primitives/src/transaction/tests.rs | 2 +- zcash_proofs/Cargo.toml | 2 +- zcash_proofs/src/sapling/prover.rs | 6 +- 16 files changed, 126 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1cb83f..fac19e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,8 +66,8 @@ dependencies = [ "group 0.1.0", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -75,11 +75,6 @@ name = "bit-vec" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitflags" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "blake2b_simd" version = "0.5.1" @@ -143,11 +138,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "c2-chacha" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -200,7 +196,7 @@ version = "0.4.0" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff_derive 0.3.0", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -227,11 +223,6 @@ dependencies = [ "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "futures" version = "0.1.21" @@ -262,13 +253,22 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "getrandom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "group" version = "0.1.0" dependencies = [ "ff 0.4.0", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -295,12 +295,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.0.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "libc" -version = "0.2.40" +version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -312,11 +315,11 @@ dependencies = [ "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", "zcash_proofs 0.0.0", @@ -354,7 +357,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -374,10 +377,15 @@ dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "group 0.1.0", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ppv-lite86" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro-hack" version = "0.4.0" @@ -409,106 +417,57 @@ dependencies = [ [[package]] name = "rand" -version = "0.6.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rand_hc" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xorshift" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -523,8 +482,8 @@ dependencies = [ "ff 0.4.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -539,6 +498,11 @@ dependencies = [ "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stream-cipher" version = "0.1.1" @@ -567,33 +531,14 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "winapi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "zcash_client_backend" version = "0.0.0" dependencies = [ "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -609,10 +554,10 @@ dependencies = [ "ff 0.4.0", "fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -626,7 +571,7 @@ dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -640,7 +585,6 @@ dependencies = [ "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" "checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" -"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d909f9ef55928e57e7de9638828bc9407233b5cb0904066a7edebbaa9946db2f" "checksum blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa20660ff9f1e6d0a05444b5ebbbae13e4c018d4c66cc78c7e421e3396358a52" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" @@ -649,7 +593,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" @@ -658,16 +602,16 @@ dependencies = [ "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" +"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eceac7784c5dc97c2d6edf30259b4e153e6e2b42b3c85e9a6e9f45d06caef6e" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" @@ -675,26 +619,20 @@ dependencies = [ "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" +"checksum rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e193067942ef6f485a349a113329140d0ab9e2168ce92274499bb0e9a4190d9d" +"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8c83d0434e67e7a92be561af33f3ca17ff9899a4acf28030fabb8c5c323a1a" +"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index a56b1ed..b15671e 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -9,7 +9,6 @@ repository = "https://github.com/ebfull/bellman" version = "0.1.0" [dependencies] -rand_core = "0.4" bit-vec = "0.4.4" ff = { path = "../ff" } futures = "0.1" @@ -18,10 +17,11 @@ group = { path = "../group" } num_cpus = { version = "1", optional = true } crossbeam = { version = "0.3", optional = true } pairing = { path = "../pairing", optional = true } +rand_core = "0.5" byteorder = "1" [dev-dependencies] -rand = "0.6" +rand = "0.7" [features] groth16 = ["pairing"] diff --git a/ff/Cargo.toml b/ff/Cargo.toml index 853f19d..212f6c4 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -10,8 +10,8 @@ repository = "https://github.com/ebfull/ff" [dependencies] byteorder = "1" -rand_core = "0.4" ff_derive = { version = "0.3.0", path = "ff_derive", optional = true } +rand_core = "0.5" [features] default = [] diff --git a/group/Cargo.toml b/group/Cargo.toml index f278b4e..7d2d531 100644 --- a/group/Cargo.toml +++ b/group/Cargo.toml @@ -14,5 +14,5 @@ repository = "https://github.com/ebfull/group" [dependencies] ff = { path = "../ff" } -rand = "0.6" -rand_xorshift = "0.1" +rand = "0.7" +rand_xorshift = "0.2" diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index d67d4ee..ffc38fa 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -22,8 +22,8 @@ libc = "0.2" pairing = { path = "../pairing" } lazy_static = "1" byteorder = "1" -rand_core = "0.4" -rand_os = "0.1" +rand_core = "0.5" +rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } zcash_proofs = { path = "../zcash_proofs" } diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 7f10d1c..eabbc1b 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -388,7 +388,7 @@ fn test_gen_r() { #[no_mangle] pub extern "system" fn librustzcash_sapling_generate_r(result: *mut [c_uchar; 32]) { // create random 64 byte buffer - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let mut buffer = [0u8; 64]; rng.fill_bytes(&mut buffer); @@ -858,7 +858,7 @@ pub extern "system" fn librustzcash_sprout_prove( drop(sprout_fs); // Initialize secure RNG - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let proof = create_random_proof(js, ¶ms, &mut rng).expect("proving should not fail"); diff --git a/librustzcash/src/tests/key_agreement.rs b/librustzcash/src/tests/key_agreement.rs index 9d22561..412ecc3 100644 --- a/librustzcash/src/tests/key_agreement.rs +++ b/librustzcash/src/tests/key_agreement.rs @@ -13,7 +13,7 @@ use { #[test] fn test_key_agreement() { let params = JubjubBls12::new(); - let mut rng = OsRng::new().unwrap(); + let mut rng = OsRng; // Create random viewing key let vk = ViewingKey:: { diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml index 5a065e2..759fd3d 100644 --- a/pairing/Cargo.toml +++ b/pairing/Cargo.toml @@ -15,13 +15,13 @@ homepage = "https://github.com/ebfull/pairing" repository = "https://github.com/ebfull/pairing" [dependencies] -rand_core = "0.4" byteorder = "1" ff = { path = "../ff", features = ["derive"] } group = { path = "../group" } +rand_core = "0.5" [dev-dependencies] -rand_xorshift = "0.1" +rand_xorshift = "0.2" [features] unstable-features = ["expose-arith"] diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index da28615..0026f6c 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -17,11 +17,11 @@ bellman = { path = "../bellman" } blake2b_simd = "0.5" blake2s_simd = "0.5" ff = { path = "../ff" } -rand_core = "0.4" +rand_core = "0.5" digest = "0.7" byteorder = "1" [dev-dependencies] hex-literal = "0.1" -rand_xorshift = "0.1" +rand_xorshift = "0.2" sha2 = "0.8" diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 8e7e055..1d7848e 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -13,5 +13,5 @@ sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] -rand_core = "0.4" -rand_xorshift = "0.1" +rand_core = "0.5" +rand_xorshift = "0.2" diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 10c6d00..56070e4 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -15,7 +15,7 @@ fpe = "0.1" hex = "0.3" lazy_static = "1" pairing = { path = "../pairing" } -rand_core = "0.4" -rand_os = "0.1" +rand_core = "0.5" +rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index 728818f..1964361 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -137,7 +137,7 @@ impl Memo { fn generate_esk() -> Fs { // create random 64 byte buffer - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let mut buffer = [0u8; 64]; rng.fill_bytes(&mut buffer); @@ -228,7 +228,7 @@ fn prf_ock( /// JUBJUB, /// }; /// -/// let mut rng = OsRng::new().unwrap(); +/// let mut rng = OsRng; /// /// let diversifier = Diversifier([0; 11]); /// let pk_d = diversifier.g_d::(&JUBJUB).unwrap(); @@ -848,7 +848,7 @@ mod tests { #[test] fn decryption_with_invalid_ivk() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, _, _, cmu, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -860,7 +860,7 @@ mod tests { #[test] fn decryption_with_invalid_epk() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, ivk, _, cmu, _, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -877,7 +877,7 @@ mod tests { #[test] fn decryption_with_invalid_cmu() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, ivk, _, _, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -889,7 +889,7 @@ mod tests { #[test] fn decryption_with_invalid_tag() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, ivk, _, cmu, epk, mut enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -902,7 +902,7 @@ mod tests { #[test] fn decryption_with_invalid_version_byte() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -924,7 +924,7 @@ mod tests { #[test] fn decryption_with_invalid_diversifier() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -946,7 +946,7 @@ mod tests { #[test] fn decryption_with_incorrect_diversifier() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -968,7 +968,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_ivk() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, _, _, cmu, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -985,7 +985,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_epk() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, ivk, _, cmu, _, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -1002,7 +1002,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_cmu() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (_, ivk, _, _, epk, enc_ciphertext, _) = random_enc_ciphertext(&mut rng); @@ -1019,7 +1019,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_version_byte() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1046,7 +1046,7 @@ mod tests { #[test] fn compact_decryption_with_invalid_diversifier() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1073,7 +1073,7 @@ mod tests { #[test] fn compact_decryption_with_incorrect_diversifier() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, ivk, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1100,7 +1100,7 @@ mod tests { #[test] fn recovery_with_invalid_ovk() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (mut ovk, _, cv, cmu, epk, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1114,7 +1114,7 @@ mod tests { #[test] fn recovery_with_invalid_cv() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, _, cmu, epk, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1133,7 +1133,7 @@ mod tests { #[test] fn recovery_with_invalid_cmu() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, _, epk, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1152,7 +1152,7 @@ mod tests { #[test] fn recovery_with_invalid_epk() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, cmu, _, enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1171,7 +1171,7 @@ mod tests { #[test] fn recovery_with_invalid_enc_tag() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1185,7 +1185,7 @@ mod tests { #[test] fn recovery_with_invalid_out_tag() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, cmu, epk, enc_ciphertext, mut out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1199,7 +1199,7 @@ mod tests { #[test] fn recovery_with_invalid_version_byte() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1221,7 +1221,7 @@ mod tests { #[test] fn recovery_with_invalid_diversifier() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); @@ -1243,7 +1243,7 @@ mod tests { #[test] fn recovery_with_incorrect_diversifier() { - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; let (ovk, _, cv, cmu, epk, mut enc_ciphertext, out_ciphertext) = random_enc_ciphertext(&mut rng); diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 7f2b6f2..ad7e309 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -113,7 +113,7 @@ pub fn spend_sig( params: &JubjubBls12, ) -> Signature { // Initialize secure RNG - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; // We compute `rsk`... let rsk = ask.randomize(ar); diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 81f8e21..d9788ff 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -197,7 +197,7 @@ fn tx_write_rejects_unexpected_binding_sig() { // Fails with an unexpected binding signature { - let rng = &mut OsRng::new().expect("should be able to construct RNG"); + let rng = &mut OsRng; let sk = PrivateKey::(Fs::random(rng)); let sig = sk.sign( b"Foo bar", diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index e6bfd17..1eca6fd 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -11,6 +11,6 @@ blake2b_simd = "0.5" byteorder = "1" ff = { path = "../ff" } pairing = { path = "../pairing" } -rand_os = "0.1" +rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index df0b19d..fce4d8e 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -56,7 +56,7 @@ impl SaplingProvingContext { (), > { // Initialize secure RNG - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; // We create the randomness of the value commitment let rcv = Fs::random(&mut rng); @@ -189,7 +189,7 @@ impl SaplingProvingContext { params: &JubjubBls12, ) -> (Proof, edwards::Point) { // Initialize secure RNG - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; // We construct ephemeral randomness for the value commitment. This // randomness is not given back to the caller, but the synthetic @@ -250,7 +250,7 @@ impl SaplingProvingContext { params: &JubjubBls12, ) -> Result { // Initialize secure RNG - let mut rng = OsRng::new().expect("should be able to construct RNG"); + let mut rng = OsRng; // Grab the current `bsk` from the context let bsk = PrivateKey::(self.bsk); From c4e14ad0b1617bc693bc6ec28162be3a41d8e8be Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 14 Jul 2019 12:25:24 +0100 Subject: [PATCH 031/105] Address libc deprecations --- librustzcash/src/rustzcash.rs | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index eabbc1b..1db70ac 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -42,7 +42,7 @@ use rand_core::RngCore; use rand_os::OsRng; use std::io::BufReader; -use libc::{c_char, c_uchar, int64_t, size_t, uint32_t, uint64_t}; +use libc::{c_char, c_uchar, size_t}; use std::ffi::CStr; use std::fs::File; use std::path::{Path, PathBuf}; @@ -404,7 +404,7 @@ pub extern "system" fn librustzcash_sapling_generate_r(result: *mut [c_uchar; 32 fn priv_get_note( diversifier: *const [c_uchar; 11], pk_d: *const [c_uchar; 32], - value: uint64_t, + value: u64, r: *const [c_uchar; 32], ) -> Result, ()> { let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); @@ -444,11 +444,11 @@ fn priv_get_note( pub extern "system" fn librustzcash_sapling_compute_nf( diversifier: *const [c_uchar; 11], pk_d: *const [c_uchar; 32], - value: uint64_t, + value: u64, r: *const [c_uchar; 32], ak: *const [c_uchar; 32], nk: *const [c_uchar; 32], - position: uint64_t, + position: u64, result: *mut [c_uchar; 32], ) -> bool { let note = match priv_get_note(diversifier, pk_d, value, r) { @@ -489,7 +489,7 @@ pub extern "system" fn librustzcash_sapling_compute_nf( pub extern "system" fn librustzcash_sapling_compute_cm( diversifier: *const [c_uchar; 11], pk_d: *const [c_uchar; 32], - value: uint64_t, + value: u64, r: *const [c_uchar; 32], result: *mut [c_uchar; 32], ) -> bool { @@ -562,8 +562,8 @@ pub extern "system" fn librustzcash_sapling_ka_derivepublic( #[no_mangle] pub extern "system" fn librustzcash_eh_isvalid( - n: uint32_t, - k: uint32_t, + n: u32, + k: u32, input: *const c_uchar, input_len: size_t, nonce: *const c_uchar, @@ -700,7 +700,7 @@ pub extern "system" fn librustzcash_sapling_check_output( #[no_mangle] pub extern "system" fn librustzcash_sapling_final_check( ctx: *mut SaplingVerificationContext, - value_balance: int64_t, + value_balance: i64, binding_sig: *const [c_uchar; 64], sighash_value: *const [c_uchar; 32], ) -> bool { @@ -728,31 +728,31 @@ pub extern "system" fn librustzcash_sprout_prove( // First input in_sk1: *const [c_uchar; 32], - in_value1: uint64_t, + in_value1: u64, in_rho1: *const [c_uchar; 32], in_r1: *const [c_uchar; 32], in_auth1: *const [c_uchar; 1 + 33 * SPROUT_TREE_DEPTH + 8], // Second input in_sk2: *const [c_uchar; 32], - in_value2: uint64_t, + in_value2: u64, in_rho2: *const [c_uchar; 32], in_r2: *const [c_uchar; 32], in_auth2: *const [c_uchar; 1 + 33 * SPROUT_TREE_DEPTH + 8], // First output out_pk1: *const [c_uchar; 32], - out_value1: uint64_t, + out_value1: u64, out_r1: *const [c_uchar; 32], // Second output out_pk2: *const [c_uchar; 32], - out_value2: uint64_t, + out_value2: u64, out_r2: *const [c_uchar; 32], // Public value - vpub_old: uint64_t, - vpub_new: uint64_t, + vpub_old: u64, + vpub_new: u64, ) { let phi = unsafe { *phi }; let rt = unsafe { *rt }; @@ -878,8 +878,8 @@ pub extern "system" fn librustzcash_sprout_verify( nf2: *const [c_uchar; 32], cm1: *const [c_uchar; 32], cm2: *const [c_uchar; 32], - vpub_old: uint64_t, - vpub_new: uint64_t, + vpub_old: u64, + vpub_new: u64, ) -> bool { // Prepare the public input for the verifier let mut public_input = Vec::with_capacity((32 * 8) + (8 * 2)); @@ -923,7 +923,7 @@ pub extern "system" fn librustzcash_sapling_output_proof( diversifier: *const [c_uchar; 11], pk_d: *const [c_uchar; 32], rcm: *const [c_uchar; 32], - value: uint64_t, + value: u64, cv: *mut [c_uchar; 32], zkproof: *mut [c_uchar; GROTH_PROOF_SIZE], ) -> bool { @@ -1015,7 +1015,7 @@ pub extern "system" fn librustzcash_sapling_spend_sig( #[no_mangle] pub extern "system" fn librustzcash_sapling_binding_sig( ctx: *const SaplingProvingContext, - value_balance: int64_t, + value_balance: i64, sighash: *const [c_uchar; 32], result: *mut [c_uchar; 64], ) -> bool { @@ -1040,7 +1040,7 @@ pub extern "system" fn librustzcash_sapling_spend_proof( diversifier: *const [c_uchar; 11], rcm: *const [c_uchar; 32], ar: *const [c_uchar; 32], - value: uint64_t, + value: u64, anchor: *const [c_uchar; 32], witness: *const [c_uchar; 1 + 33 * SAPLING_TREE_DEPTH + 8], cv: *mut [c_uchar; 32], @@ -1161,7 +1161,7 @@ pub extern "system" fn librustzcash_zip32_xsk_master( #[no_mangle] pub extern "system" fn librustzcash_zip32_xsk_derive( xsk_parent: *const [c_uchar; 169], - i: uint32_t, + i: u32, xsk_i: *mut [c_uchar; 169], ) { let xsk_parent = zip32::ExtendedSpendingKey::read(&unsafe { *xsk_parent }[..]) @@ -1177,7 +1177,7 @@ pub extern "system" fn librustzcash_zip32_xsk_derive( #[no_mangle] pub extern "system" fn librustzcash_zip32_xfvk_derive( xfvk_parent: *const [c_uchar; 169], - i: uint32_t, + i: u32, xfvk_i: *mut [c_uchar; 169], ) -> bool { let xfvk_parent = zip32::ExtendedFullViewingKey::read(&unsafe { *xfvk_parent }[..]) From 7f60f0f881e6f24e6dade62a5534f7acc3112888 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 10 Jul 2019 11:07:22 -0700 Subject: [PATCH 032/105] Make some methods in DiversifierKey, DiversiferIndex pub --- zcash_primitives/src/zip32.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index db5adcd..54f386d 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -94,7 +94,7 @@ struct ChainCode([u8; 32]); pub struct DiversifierIndex(pub [u8; 11]); impl DiversifierIndex { - fn new() -> Self { + pub fn new() -> Self { DiversifierIndex([0; 11]) } @@ -113,10 +113,10 @@ impl DiversifierIndex { /// A key used to derive diversifiers for a particular child key #[derive(Clone, Copy, Debug, PartialEq)] -struct DiversifierKey([u8; 32]); +pub struct DiversifierKey(pub [u8; 32]); impl DiversifierKey { - fn master(sk_m: &[u8]) -> Self { + pub fn master(sk_m: &[u8]) -> Self { let mut dk_m = [0u8; 32]; dk_m.copy_from_slice(&prf_expand(sk_m, &[0x10]).as_bytes()[..32]); DiversifierKey(dk_m) @@ -131,7 +131,7 @@ impl DiversifierKey { /// Returns the first index starting from j that generates a valid /// diversifier, along with the corresponding diversifier. Returns /// an error if the diversifier space is exhausted. - fn diversifier(&self, mut j: DiversifierIndex) -> Result<(DiversifierIndex, Diversifier), ()> { + pub fn diversifier(&self, mut j: DiversifierIndex) -> Result<(DiversifierIndex, Diversifier), ()> { let ff = FF1::::new(&self.0, 2).unwrap(); loop { // Generate d_j From 0255dca16e5f699770c8d99537cbc783623e9267 Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 26 Jul 2019 19:43:42 +0100 Subject: [PATCH 033/105] Clarify masking of bits in Field::random impls Co-Authored-By: Daira Hopwood --- ff/ff_derive/src/lib.rs | 2 +- sapling-crypto/src/jubjub/fs.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index aea7a50..df2625b 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -892,7 +892,7 @@ fn prime_field_impl( #name(#repr(repr)) }; - // Mask away the unused bits at the beginning. + // Mask away the unused most-significant bits. tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; if tmp.is_valid() { diff --git a/sapling-crypto/src/jubjub/fs.rs b/sapling-crypto/src/jubjub/fs.rs index 017292b..baa16ef 100644 --- a/sapling-crypto/src/jubjub/fs.rs +++ b/sapling-crypto/src/jubjub/fs.rs @@ -292,7 +292,7 @@ impl Field for Fs { Fs(FsRepr(repr)) }; - // Mask away the unused bits at the beginning. + // Mask away the unused most-significant bits. tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; if tmp.is_valid() { From 01618038bfa274094d1c3a6dd20b61b6b7891371 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 18 Nov 2018 11:20:59 +0000 Subject: [PATCH 034/105] TxProver trait to abstract over the circuit parameters An implementation using local parameters is provided in the zcash_proofs crate. --- Cargo.lock | 33 +++ zcash_primitives/src/lib.rs | 1 + zcash_primitives/src/prover.rs | 162 +++++++++++++++ .../src/transaction/components.rs | 2 +- zcash_proofs/Cargo.toml | 1 + zcash_proofs/src/lib.rs | 2 + zcash_proofs/src/prover.rs | 190 ++++++++++++++++++ 7 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 zcash_primitives/src/prover.rs create mode 100644 zcash_proofs/src/prover.rs diff --git a/Cargo.lock b/Cargo.lock index fac19e3..a9a4f97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,6 +185,15 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "directories" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -531,6 +540,25 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "zcash_client_backend" version = "0.0.0" @@ -569,6 +597,7 @@ dependencies = [ "bellman 0.1.0", "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -600,6 +629,7 @@ dependencies = [ "checksum crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9ee35dbace0831b5fe7cb9b43eb029aa14a10f594a115025d4628a2baa63ab" "checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" @@ -636,3 +666,6 @@ dependencies = [ "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 90d69e6..797b9b6 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -20,6 +20,7 @@ pub mod block; pub mod keys; pub mod merkle_tree; pub mod note_encryption; +pub mod prover; pub mod sapling; mod serialize; pub mod transaction; diff --git a/zcash_primitives/src/prover.rs b/zcash_primitives/src/prover.rs new file mode 100644 index 0000000..87a76c7 --- /dev/null +++ b/zcash_primitives/src/prover.rs @@ -0,0 +1,162 @@ +//! Abstractions over the proving system and parameters. + +use pairing::bls12_381::{Bls12, Fr}; +use sapling_crypto::{ + jubjub::{edwards, fs::Fs, Unknown}, + primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, + redjubjub::{PublicKey, Signature}, +}; + +use crate::{ + merkle_tree::CommitmentTreeWitness, sapling::Node, transaction::components::GROTH_PROOF_SIZE, +}; + +/// Interface for creating zero-knowledge proofs for shielded transactions. +pub trait TxProver { + /// Type for persisting any necessary context across multiple Sapling proofs. + type SaplingProvingContext; + + /// Instantiate a new Sapling proving context. + fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext; + + /// Create the value commitment, re-randomized key, and proof for a Sapling + /// [`SpendDescription`], while accumulating its value commitment randomness inside + /// the context for later use. + /// + /// [`SpendDescription`]: crate::transaction::components::SpendDescription + fn spend_proof( + &self, + ctx: &mut Self::SaplingProvingContext, + proof_generation_key: ProofGenerationKey, + diversifier: Diversifier, + rcm: Fs, + ar: Fs, + value: u64, + anchor: Fr, + witness: CommitmentTreeWitness, + ) -> Result< + ( + [u8; GROTH_PROOF_SIZE], + edwards::Point, + PublicKey, + ), + (), + >; + + /// Create the value commitment and proof for a Sapling [`OutputDescription`], + /// while accumulating its value commitment randomness inside the context for later + /// use. + /// + /// [`OutputDescription`]: crate::transaction::components::OutputDescription + fn output_proof( + &self, + ctx: &mut Self::SaplingProvingContext, + esk: Fs, + payment_address: PaymentAddress, + rcm: Fs, + value: u64, + ) -> ([u8; GROTH_PROOF_SIZE], edwards::Point); + + /// Create the `bindingSig` for a Sapling transaction. All calls to + /// [`TxProver::spend_proof`] and [`TxProver::output_proof`] must be completed before + /// calling this function. + fn binding_sig( + &self, + ctx: &mut Self::SaplingProvingContext, + value_balance: i64, + sighash: &[u8; 32], + ) -> Result; +} + +#[cfg(test)] +pub(crate) mod mock { + use ff::Field; + use pairing::bls12_381::{Bls12, Fr}; + use rand_os::OsRng; + use sapling_crypto::{ + jubjub::{edwards, fs::Fs, FixedGenerators, Unknown}, + primitives::{Diversifier, PaymentAddress, ProofGenerationKey, ValueCommitment}, + redjubjub::{PublicKey, Signature}, + }; + + use crate::{ + merkle_tree::CommitmentTreeWitness, sapling::Node, + transaction::components::GROTH_PROOF_SIZE, JUBJUB, + }; + + use super::TxProver; + + pub(crate) struct MockTxProver; + + #[cfg(test)] + impl TxProver for MockTxProver { + type SaplingProvingContext = (); + + fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext {} + + fn spend_proof( + &self, + _ctx: &mut Self::SaplingProvingContext, + proof_generation_key: ProofGenerationKey, + _diversifier: Diversifier, + _rcm: Fs, + ar: Fs, + value: u64, + _anchor: Fr, + _witness: CommitmentTreeWitness, + ) -> Result< + ( + [u8; GROTH_PROOF_SIZE], + edwards::Point, + PublicKey, + ), + (), + > { + let mut rng = OsRng; + + let cv = ValueCommitment:: { + value, + randomness: Fs::random(&mut rng), + } + .cm(&JUBJUB) + .into(); + + let rk = PublicKey::(proof_generation_key.ak.clone().into()).randomize( + ar, + FixedGenerators::SpendingKeyGenerator, + &JUBJUB, + ); + + Ok(([0u8; GROTH_PROOF_SIZE], cv, rk)) + } + + fn output_proof( + &self, + _ctx: &mut Self::SaplingProvingContext, + _esk: Fs, + _payment_address: PaymentAddress, + _rcm: Fs, + value: u64, + ) -> ([u8; GROTH_PROOF_SIZE], edwards::Point) { + let mut rng = OsRng; + + let cv = ValueCommitment:: { + value, + randomness: Fs::random(&mut rng), + } + .cm(&JUBJUB) + .into(); + + ([0u8; GROTH_PROOF_SIZE], cv) + } + + fn binding_sig( + &self, + _ctx: &mut Self::SaplingProvingContext, + _value_balance: i64, + _sighash: &[u8; 32], + ) -> Result { + Err(()) + } + } +} diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index b8153f3..141d0ff 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -11,7 +11,7 @@ use serialize::Vector; use JUBJUB; // π_A + π_B + π_C -const GROTH_PROOF_SIZE: usize = (48 + 96 + 48); +pub const GROTH_PROOF_SIZE: usize = (48 + 96 + 48); // π_A + π_A' + π_B + π_B' + π_C + π_C' + π_K + π_H const PHGR_PROOF_SIZE: usize = (33 + 33 + 65 + 33 + 33 + 33 + 33 + 33); diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 1eca6fd..9e989fa 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -9,6 +9,7 @@ authors = [ bellman = { path = "../bellman" } blake2b_simd = "0.5" byteorder = "1" +directories = "1" ff = { path = "../ff" } pairing = { path = "../pairing" } rand_os = "0.2" diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index dd6975c..26aa2f1 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -1,6 +1,7 @@ extern crate bellman; extern crate blake2b_simd; extern crate byteorder; +extern crate directories; extern crate ff; extern crate pairing; extern crate rand_os; @@ -14,6 +15,7 @@ use std::io::{self, BufReader}; use std::path::Path; mod hashreader; +pub mod prover; pub mod sapling; pub fn load_parameters( diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs new file mode 100644 index 0000000..005d7eb --- /dev/null +++ b/zcash_proofs/src/prover.rs @@ -0,0 +1,190 @@ +//! Abstractions over the proving system and parameters for ease of use. + +use bellman::groth16::{Parameters, PreparedVerifyingKey}; +use directories::BaseDirs; +use pairing::bls12_381::{Bls12, Fr}; +use sapling_crypto::{ + jubjub::{edwards, fs::Fs, Unknown}, + primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, + redjubjub::{PublicKey, Signature}, +}; +use std::path::Path; +use zcash_primitives::{ + merkle_tree::CommitmentTreeWitness, prover::TxProver, sapling::Node, + transaction::components::GROTH_PROOF_SIZE, JUBJUB, +}; + +use crate::{load_parameters, sapling::SaplingProvingContext}; + +const SAPLING_SPEND_HASH: &str = "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c"; +const SAPLING_OUTPUT_HASH: &str = "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028"; + +/// An implementation of [`TxProver`] using Sapling Spend and Output parameters from +/// locally-accessible paths. +pub struct LocalTxProver { + spend_params: Parameters, + spend_vk: PreparedVerifyingKey, + output_params: Parameters, +} + +impl LocalTxProver { + /// Creates a `LocalTxProver` using parameters from the given local paths. + /// + /// # Examples + /// + /// ```should_panic + /// use std::path::Path; + /// use zcash_proofs::prover::LocalTxProver; + /// + /// let tx_prover = LocalTxProver::new( + /// Path::new("/path/to/sapling-spend.params"), + /// Path::new("/path/to/sapling-output.params"), + /// ); + /// ``` + /// + /// # Panics + /// + /// This function will panic if the paths do not point to valid parameter files with + /// the expected hashes. + pub fn new(spend_path: &Path, output_path: &Path) -> Self { + let (spend_params, spend_vk, output_params, _, _) = load_parameters( + spend_path, + SAPLING_SPEND_HASH, + output_path, + SAPLING_OUTPUT_HASH, + None, + None, + ); + LocalTxProver { + spend_params, + spend_vk, + output_params, + } + } + + /// Attempts to create a `LocalTxProver` using parameters from the default local + /// location. + /// + /// Returns `None` if any of the parameters cannot be found in the default local + /// location. + /// + /// # Examples + /// + /// ``` + /// use zcash_proofs::prover::LocalTxProver; + /// + /// match LocalTxProver::with_default_location() { + /// Some(tx_prover) => (), + /// None => println!("Please run zcash-fetch-params or fetch-params.sh to download the parameters."), + /// } + /// ``` + /// + /// # Panics + /// + /// This function will panic if the parameters in the default local location do not + /// have the expected hashes. + pub fn with_default_location() -> Option { + let base_dirs = BaseDirs::new()?; + let unix_params_dir = base_dirs.home_dir().join(".zcash-params"); + let win_osx_params_dir = base_dirs.data_dir().join("ZcashParams"); + let (spend_path, output_path) = if unix_params_dir.exists() { + ( + unix_params_dir.join("sapling-spend.params"), + unix_params_dir.join("sapling-output.params"), + ) + } else if win_osx_params_dir.exists() { + ( + win_osx_params_dir.join("sapling-spend.params"), + win_osx_params_dir.join("sapling-output.params"), + ) + } else { + return None; + }; + if !(spend_path.exists() && output_path.exists()) { + return None; + } + + Some(LocalTxProver::new(&spend_path, &output_path)) + } +} + +impl TxProver for LocalTxProver { + type SaplingProvingContext = SaplingProvingContext; + + fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext { + SaplingProvingContext::new() + } + + fn spend_proof( + &self, + ctx: &mut Self::SaplingProvingContext, + proof_generation_key: ProofGenerationKey, + diversifier: Diversifier, + rcm: Fs, + ar: Fs, + value: u64, + anchor: Fr, + witness: CommitmentTreeWitness, + ) -> Result< + ( + [u8; GROTH_PROOF_SIZE], + edwards::Point, + PublicKey, + ), + (), + > { + let (proof, cv, rk) = ctx.spend_proof( + proof_generation_key, + diversifier, + rcm, + ar, + value, + anchor, + witness, + &self.spend_params, + &self.spend_vk, + &JUBJUB, + )?; + + let mut zkproof = [0u8; GROTH_PROOF_SIZE]; + proof + .write(&mut zkproof[..]) + .expect("should be able to serialize a proof"); + + Ok((zkproof, cv, rk)) + } + + fn output_proof( + &self, + ctx: &mut Self::SaplingProvingContext, + esk: Fs, + payment_address: PaymentAddress, + rcm: Fs, + value: u64, + ) -> ([u8; GROTH_PROOF_SIZE], edwards::Point) { + let (proof, cv) = ctx.output_proof( + esk, + payment_address, + rcm, + value, + &self.output_params, + &JUBJUB, + ); + + let mut zkproof = [0u8; GROTH_PROOF_SIZE]; + proof + .write(&mut zkproof[..]) + .expect("should be able to serialize a proof"); + + (zkproof, cv) + } + + fn binding_sig( + &self, + ctx: &mut Self::SaplingProvingContext, + value_balance: i64, + sighash: &[u8; 32], + ) -> Result { + ctx.binding_sig(value_balance, sighash, &JUBJUB) + } +} From 1862354ea6d43ed5619b2dd2dbe29eb8442a25bc Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 20 Nov 2018 13:37:21 +0000 Subject: [PATCH 035/105] Sapling transaction builder --- Cargo.lock | 1 + zcash_primitives/Cargo.toml | 1 + zcash_primitives/src/lib.rs | 1 + zcash_primitives/src/merkle_tree.rs | 2 +- zcash_primitives/src/note_encryption.rs | 2 +- zcash_primitives/src/transaction/builder.rs | 615 ++++++++++++++++++++ zcash_primitives/src/transaction/mod.rs | 1 + 7 files changed, 621 insertions(+), 2 deletions(-) create mode 100644 zcash_primitives/src/transaction/builder.rs diff --git a/Cargo.lock b/Cargo.lock index a9a4f97..fc8644f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -584,6 +584,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 56070e4..804f8c6 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -15,6 +15,7 @@ fpe = "0.1" hex = "0.3" lazy_static = "1" pairing = { path = "../pairing" } +rand = "0.7" rand_core = "0.5" rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 797b9b6..d6ddcc9 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -9,6 +9,7 @@ extern crate ff; extern crate fpe; extern crate hex; extern crate pairing; +extern crate rand; extern crate rand_core; extern crate rand_os; extern crate sapling_crypto; diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index a692073..aa1596d 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -420,7 +420,7 @@ impl IncrementalWitness { /// A witness to a path from a position in a particular commitment tree to the root of /// that tree. -#[derive(Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct CommitmentTreeWitness { pub auth_path: Vec>, pub position: u64, diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index 1964361..d0a7250 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -135,7 +135,7 @@ impl Memo { } } -fn generate_esk() -> Fs { +pub fn generate_esk() -> Fs { // create random 64 byte buffer let mut rng = OsRng; let mut buffer = [0u8; 64]; diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs new file mode 100644 index 0000000..9f6cccd --- /dev/null +++ b/zcash_primitives/src/transaction/builder.rs @@ -0,0 +1,615 @@ +//! Structs for building transactions. + +use ff::Field; +use pairing::bls12_381::{Bls12, Fr}; +use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore}; +use sapling_crypto::{ + jubjub::fs::Fs, + primitives::{Diversifier, Note, PaymentAddress}, + redjubjub::PrivateKey, +}; +use zip32::ExtendedSpendingKey; + +use crate::{ + keys::OutgoingViewingKey, + merkle_tree::{CommitmentTreeWitness, IncrementalWitness}, + note_encryption::{generate_esk, Memo, SaplingNoteEncryption}, + prover::TxProver, + sapling::{spend_sig, Node}, + transaction::{ + components::{Amount, OutputDescription, SpendDescription}, + signature_hash_data, Transaction, TransactionData, SIGHASH_ALL, + }, + JUBJUB, +}; + +const DEFAULT_FEE: Amount = Amount(10000); +const DEFAULT_TX_EXPIRY_DELTA: u32 = 20; + +/// If there are any shielded inputs, always have at least two shielded outputs, padding +/// with dummy outputs if necessary. See https://github.com/zcash/zcash/issues/3615 +const MIN_SHIELDED_OUTPUTS: usize = 2; + +#[derive(Debug)] +pub struct Error(ErrorKind); + +impl Error { + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} + +#[derive(Debug, PartialEq)] +pub enum ErrorKind { + AnchorMismatch, + BindingSig, + ChangeIsNegative(i64), + InvalidAddress, + InvalidAmount, + InvalidWitness, + NoChangeAddress, + SpendProof, +} + +struct SpendDescriptionInfo { + extsk: ExtendedSpendingKey, + diversifier: Diversifier, + note: Note, + alpha: Fs, + witness: CommitmentTreeWitness, +} + +pub struct SaplingOutput { + ovk: OutgoingViewingKey, + to: PaymentAddress, + note: Note, + memo: Memo, +} + +impl SaplingOutput { + pub fn new( + rng: &mut R, + ovk: OutgoingViewingKey, + to: PaymentAddress, + value: Amount, + memo: Option, + ) -> Result { + let g_d = match to.g_d(&JUBJUB) { + Some(g_d) => g_d, + None => return Err(Error(ErrorKind::InvalidAddress)), + }; + if value.0 < 0 { + return Err(Error(ErrorKind::InvalidAmount)); + } + + let rcm = Fs::random(rng); + + let note = Note { + g_d, + pk_d: to.pk_d.clone(), + value: value.0 as u64, + r: rcm, + }; + + Ok(SaplingOutput { + ovk, + to, + note, + memo: memo.unwrap_or_default(), + }) + } + + pub fn build( + self, + prover: &P, + ctx: &mut P::SaplingProvingContext, + ) -> OutputDescription { + let encryptor = + SaplingNoteEncryption::new(self.ovk, self.note.clone(), self.to.clone(), self.memo); + + let (zkproof, cv) = prover.output_proof( + ctx, + encryptor.esk().clone(), + self.to, + self.note.r, + self.note.value, + ); + + let cmu = self.note.cm(&JUBJUB); + + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + let out_ciphertext = encryptor.encrypt_outgoing_plaintext(&cv, &cmu); + + let ephemeral_key = encryptor.epk().clone().into(); + + OutputDescription { + cv, + cmu, + ephemeral_key, + enc_ciphertext, + out_ciphertext, + zkproof, + } + } +} + +/// Metadata about a transaction created by a [`Builder`]. +pub struct TransactionMetadata { + spend_indices: Vec, + output_indices: Vec, +} + +impl TransactionMetadata { + fn new() -> Self { + TransactionMetadata { + spend_indices: vec![], + output_indices: vec![], + } + } + + /// Returns the index within the transaction of the [`SpendDescription`] corresponding + /// to the `n`-th call to [`Builder::add_sapling_spend`]. + /// + /// Note positions are randomized when building transactions for indistinguishability. + /// This means that the transaction consumer cannot assume that e.g. the first spend + /// they added (via the first call to [`Builder::add_sapling_spend`]) is the first + /// [`SpendDescription`] in the transaction. + pub fn spend_index(&self, n: usize) -> Option { + self.spend_indices.get(n).map(|i| *i) + } + + /// Returns the index within the transaction of the [`OutputDescription`] corresponding + /// to the `n`-th call to [`Builder::add_sapling_output`]. + /// + /// Note positions are randomized when building transactions for indistinguishability. + /// This means that the transaction consumer cannot assume that e.g. the first output + /// they added (via the first call to [`Builder::add_sapling_output`]) is the first + /// [`OutputDescription`] in the transaction. + pub fn output_index(&self, n: usize) -> Option { + self.output_indices.get(n).map(|i| *i) + } +} + +/// Generates a [`Transaction`] from its inputs and outputs. +pub struct Builder { + rng: OsRng, + mtx: TransactionData, + fee: Amount, + anchor: Option, + spends: Vec, + outputs: Vec, + change_address: Option<(OutgoingViewingKey, PaymentAddress)>, +} + +impl Builder { + /// Creates a new `Builder` targeted for inclusion in the block with the given height, + /// using default values for general transaction fields. + /// + /// # Default values + /// + /// The expiry height will be set to the given height plus the default transaction + /// expiry delta (20 blocks). + /// + /// The fee will be set to the default fee (0.0001 ZEC). + pub fn new(height: u32) -> Builder { + let mut mtx = TransactionData::new(); + mtx.expiry_height = height + DEFAULT_TX_EXPIRY_DELTA; + + Builder { + rng: OsRng, + mtx, + fee: DEFAULT_FEE, + anchor: None, + spends: vec![], + outputs: vec![], + change_address: None, + } + } + + /// Adds a Sapling note to be spent in this transaction. + /// + /// Returns an error if the given witness does not have the same anchor as previous + /// witnesses, or has no path. + pub fn add_sapling_spend( + &mut self, + extsk: ExtendedSpendingKey, + diversifier: Diversifier, + note: Note, + witness: IncrementalWitness, + ) -> Result<(), Error> { + // Consistency check: all anchors must equal the first one + if let Some(anchor) = self.anchor { + let witness_root: Fr = witness.root().into(); + if witness_root != anchor { + return Err(Error(ErrorKind::AnchorMismatch)); + } + } else { + self.anchor = Some(witness.root().into()) + } + let witness = witness.path().ok_or(Error(ErrorKind::InvalidWitness))?; + + let alpha = Fs::random(&mut self.rng); + + self.mtx.value_balance.0 += note.value as i64; + + self.spends.push(SpendDescriptionInfo { + extsk, + diversifier, + note, + alpha, + witness, + }); + + Ok(()) + } + + /// Adds a Sapling address to send funds to. + pub fn add_sapling_output( + &mut self, + ovk: OutgoingViewingKey, + to: PaymentAddress, + value: Amount, + memo: Option, + ) -> Result<(), Error> { + let output = SaplingOutput::new(&mut self.rng, ovk, to, value, memo)?; + + self.mtx.value_balance.0 -= value.0; + + self.outputs.push(output); + + Ok(()) + } + + /// Sets the Sapling address to which any change will be sent. + /// + /// By default, change is sent to the Sapling address corresponding to the first note + /// being spent (i.e. the first call to [`Builder::add_sapling_spend`]). + pub fn send_change_to(&mut self, ovk: OutgoingViewingKey, to: PaymentAddress) { + self.change_address = Some((ovk, to)); + } + + /// Builds a transaction from the configured spends and outputs. + /// + /// Upon success, returns a tuple containing the final transaction, and the + /// [`TransactionMetadata`] generated during the build process. + /// + /// `consensus_branch_id` must be valid for the block height that this transaction is + /// targeting. An invalid `consensus_branch_id` will *not* result in an error from + /// this function, and instead will generate a transaction that will be rejected by + /// the network. + pub fn build( + mut self, + consensus_branch_id: u32, + prover: impl TxProver, + ) -> Result<(Transaction, TransactionMetadata), Error> { + let mut tx_metadata = TransactionMetadata::new(); + + // + // Consistency checks + // + + // Valid change + let change = self.mtx.value_balance.0 - self.fee.0; + if change.is_negative() { + return Err(Error(ErrorKind::ChangeIsNegative(change))); + } + + // + // Change output + // + + if change.is_positive() { + // Send change to the specified change address. If no change address + // was set, send change to the first Sapling address given as input. + let change_address = if let Some(change_address) = self.change_address.take() { + change_address + } else if !self.spends.is_empty() { + ( + self.spends[0].extsk.expsk.ovk, + PaymentAddress { + diversifier: self.spends[0].diversifier, + pk_d: self.spends[0].note.pk_d.clone(), + }, + ) + } else { + return Err(Error(ErrorKind::NoChangeAddress)); + }; + + self.add_sapling_output(change_address.0, change_address.1, Amount(change), None)?; + } + + // + // Record initial positions of spends and outputs + // + let mut spends: Vec<_> = self.spends.into_iter().enumerate().collect(); + let mut outputs: Vec<_> = self + .outputs + .into_iter() + .enumerate() + .map(|(i, o)| Some((i, o))) + .collect(); + + // + // Sapling spends and outputs + // + + let mut ctx = prover.new_sapling_proving_context(); + let anchor = self.anchor.expect("anchor was set if spends were added"); + + // Pad Sapling outputs + let orig_outputs_len = outputs.len(); + if !spends.is_empty() { + while outputs.len() < MIN_SHIELDED_OUTPUTS { + outputs.push(None); + } + } + + // Randomize order of inputs and outputs + spends.shuffle(&mut self.rng); + outputs.shuffle(&mut self.rng); + tx_metadata.spend_indices.resize(spends.len(), 0); + tx_metadata.output_indices.resize(orig_outputs_len, 0); + + // Create Sapling SpendDescriptions + for (i, (pos, spend)) in spends.iter().enumerate() { + let proof_generation_key = spend.extsk.expsk.proof_generation_key(&JUBJUB); + + let mut nullifier = [0u8; 32]; + nullifier.copy_from_slice(&spend.note.nf( + &proof_generation_key.into_viewing_key(&JUBJUB), + spend.witness.position, + &JUBJUB, + )); + + let (zkproof, cv, rk) = prover + .spend_proof( + &mut ctx, + proof_generation_key, + spend.diversifier, + spend.note.r, + spend.alpha, + spend.note.value, + anchor, + spend.witness.clone(), + ) + .map_err(|()| Error(ErrorKind::SpendProof))?; + + self.mtx.shielded_spends.push(SpendDescription { + cv, + anchor: anchor, + nullifier, + rk, + zkproof, + spend_auth_sig: None, + }); + + // Record the post-randomized spend location + tx_metadata.spend_indices[*pos] = i; + } + + // Create Sapling OutputDescriptions + for (i, output) in outputs.into_iter().enumerate() { + let output_desc = if let Some((pos, output)) = output { + // Record the post-randomized output location + tx_metadata.output_indices[pos] = i; + + output.build(&prover, &mut ctx) + } else { + // This is a dummy output + let (dummy_to, dummy_note) = { + let (diversifier, g_d) = { + let mut diversifier; + let g_d; + loop { + let mut d = [0; 11]; + self.rng.fill_bytes(&mut d); + diversifier = Diversifier(d); + if let Some(val) = diversifier.g_d::(&JUBJUB) { + g_d = val; + break; + } + } + (diversifier, g_d) + }; + + let pk_d = { + let dummy_ivk = Fs::random(&mut self.rng); + g_d.mul(dummy_ivk, &JUBJUB) + }; + + ( + PaymentAddress { + diversifier, + pk_d: pk_d.clone(), + }, + Note { + g_d, + pk_d, + r: Fs::random(&mut self.rng), + value: 0, + }, + ) + }; + + let esk = generate_esk(); + let epk = dummy_note.g_d.mul(esk, &JUBJUB); + + let (zkproof, cv) = + prover.output_proof(&mut ctx, esk, dummy_to, dummy_note.r, dummy_note.value); + + let cmu = dummy_note.cm(&JUBJUB); + + let mut enc_ciphertext = [0u8; 580]; + let mut out_ciphertext = [0u8; 80]; + self.rng.fill_bytes(&mut enc_ciphertext[..]); + self.rng.fill_bytes(&mut out_ciphertext[..]); + + OutputDescription { + cv, + cmu, + ephemeral_key: epk.into(), + enc_ciphertext, + out_ciphertext, + zkproof, + } + }; + + self.mtx.shielded_outputs.push(output_desc); + } + + // + // Signatures + // + + let mut sighash = [0u8; 32]; + sighash.copy_from_slice(&signature_hash_data( + &self.mtx, + consensus_branch_id, + SIGHASH_ALL, + None, + )); + + // Create Sapling spendAuth and binding signatures + for (i, (_, spend)) in spends.into_iter().enumerate() { + self.mtx.shielded_spends[i].spend_auth_sig = Some(spend_sig( + PrivateKey(spend.extsk.expsk.ask), + spend.alpha, + &sighash, + &JUBJUB, + )); + } + self.mtx.binding_sig = Some( + prover + .binding_sig(&mut ctx, self.mtx.value_balance.0, &sighash) + .map_err(|()| Error(ErrorKind::BindingSig))?, + ); + + Ok(( + self.mtx.freeze().expect("Transaction should be complete"), + tx_metadata, + )) + } +} + +#[cfg(test)] +mod tests { + use ff::{Field, PrimeField}; + use rand::rngs::OsRng; + use sapling_crypto::jubjub::fs::Fs; + + use super::{Builder, ErrorKind}; + use crate::{ + merkle_tree::{CommitmentTree, IncrementalWitness}, + prover::mock::MockTxProver, + sapling::Node, + transaction::components::Amount, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + JUBJUB, + }; + + #[test] + fn fails_on_negative_output() { + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + let ovk = extfvk.fvk.ovk; + let to = extfvk.default_address().unwrap().1; + + let mut builder = Builder::new(0); + match builder.add_sapling_output(ovk, to, Amount(-1), None) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), + Ok(_) => panic!("Should have failed"), + } + } + + #[test] + fn fails_on_negative_change() { + let mut rng = OsRng; + + // Just use the master key as the ExtendedSpendingKey for this test + let extsk = ExtendedSpendingKey::master(&[]); + + // Fails with no inputs or outputs + // 0.0001 t-ZEC fee + { + let builder = Builder::new(0); + match builder.build(1, MockTxProver) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-10000)), + Ok(_) => panic!("Should have failed"), + } + } + + let extfvk = ExtendedFullViewingKey::from(&extsk); + let ovk = extfvk.fvk.ovk; + let to = extfvk.default_address().unwrap().1; + + // Fail if there is only a Sapling output + // 0.0005 z-ZEC out, 0.0001 t-ZEC fee + { + let mut builder = Builder::new(0); + builder + .add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None) + .unwrap(); + match builder.build(1, MockTxProver) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-60000)), + Ok(_) => panic!("Should have failed"), + } + } + + let note1 = to + .create_note(59999, Fs::random(&mut rng), &JUBJUB) + .unwrap(); + let cm1 = Node::new(note1.cm(&JUBJUB).into_repr()); + let mut tree = CommitmentTree::new(); + tree.append(cm1).unwrap(); + let mut witness1 = IncrementalWitness::from_tree(&tree); + + // Fail if there is only a Sapling output + // 0.0005 z-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in + { + let mut builder = Builder::new(0); + builder + .add_sapling_spend( + extsk.clone(), + to.diversifier, + note1.clone(), + witness1.clone(), + ) + .unwrap(); + builder + .add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None) + .unwrap(); + match builder.build(1, MockTxProver) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-1)), + Ok(_) => panic!("Should have failed"), + } + } + + let note2 = to.create_note(1, Fs::random(&mut rng), &JUBJUB).unwrap(); + let cm2 = Node::new(note2.cm(&JUBJUB).into_repr()); + tree.append(cm2).unwrap(); + witness1.append(cm2).unwrap(); + let witness2 = IncrementalWitness::from_tree(&tree); + + // Succeeds if there is sufficient input + // 0.0005 z-ZEC out, 0.0001 t-ZEC fee, 0.0006 z-ZEC in + // + // (Still fails because we are using a MockTxProver which doesn't correctly + // compute bindingSig.) + { + let mut builder = Builder::new(0); + builder + .add_sapling_spend(extsk.clone(), to.diversifier, note1, witness1) + .unwrap(); + builder + .add_sapling_spend(extsk, to.diversifier, note2, witness2) + .unwrap(); + builder + .add_sapling_output(ovk, to, Amount(50000), None) + .unwrap(); + match builder.build(1, MockTxProver) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::BindingSig), + Ok(_) => panic!("Should have failed"), + } + } + } +} diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 35e042a..19f4396 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -8,6 +8,7 @@ use std::ops::Deref; use serialize::Vector; +pub mod builder; pub mod components; mod sighash; From dab3c002b765807c2c5c89063cf880e189705e29 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 24 May 2019 12:30:14 +0100 Subject: [PATCH 036/105] Script opcode and data support Overrides the shift-left operator for pushing opcodes onto the Script, matching the notation used in zcashd. --- zcash_primitives/src/legacy.rs | 105 ++++++++++++++++++ zcash_primitives/src/lib.rs | 1 + .../src/transaction/components.rs | 16 +-- zcash_primitives/src/transaction/sighash.rs | 3 +- zcash_primitives/src/transaction/tests.rs | 7 +- 5 files changed, 111 insertions(+), 21 deletions(-) create mode 100644 zcash_primitives/src/legacy.rs diff --git a/zcash_primitives/src/legacy.rs b/zcash_primitives/src/legacy.rs new file mode 100644 index 0000000..ac22c6b --- /dev/null +++ b/zcash_primitives/src/legacy.rs @@ -0,0 +1,105 @@ +//! Support for legacy transparent addresses and scripts. + +use byteorder::{ReadBytesExt, WriteBytesExt}; +use std::io::{self, Read, Write}; +use std::ops::Shl; + +use crate::serialize::Vector; + +/// Script opcodes. +enum OpCode { + // push value + PushData1 = 0x4c, + PushData2 = 0x4d, + PushData4 = 0x4e, +} + +/// A serialized script, used inside transparent inputs and outputs of a transaction. +#[derive(Debug, Default)] +pub struct Script(pub Vec); + +impl Script { + pub fn read(mut reader: R) -> io::Result { + let script = Vector::read(&mut reader, |r| r.read_u8())?; + Ok(Script(script)) + } + + pub fn write(&self, mut writer: W) -> io::Result<()> { + Vector::write(&mut writer, &self.0, |w, e| w.write_u8(*e)) + } +} + +impl Shl for Script { + type Output = Self; + + fn shl(mut self, rhs: OpCode) -> Self { + self.0.push(rhs as u8); + self + } +} + +impl Shl<&[u8]> for Script { + type Output = Self; + + fn shl(mut self, data: &[u8]) -> Self { + if data.len() < OpCode::PushData1 as usize { + self.0.push(data.len() as u8); + } else if data.len() <= 0xff { + self.0.push(OpCode::PushData1 as u8); + self.0.push(data.len() as u8); + } else if data.len() <= 0xffff { + self.0.push(OpCode::PushData2 as u8); + self.0.extend(&(data.len() as u16).to_le_bytes()); + } else { + self.0.push(OpCode::PushData4 as u8); + self.0.extend(&(data.len() as u32).to_le_bytes()); + } + self.0.extend(data); + self + } +} + +#[cfg(test)] +mod tests { + use super::{OpCode, Script}; + + #[test] + fn script_opcode() { + { + let script = Script::default() << OpCode::PushData1; + assert_eq!(&script.0, &[OpCode::PushData1 as u8]); + } + } + + #[test] + fn script_pushdata() { + { + let script = Script::default() << &[1, 2, 3, 4][..]; + assert_eq!(&script.0, &[4, 1, 2, 3, 4]); + } + + { + let short_data = vec![2; 100]; + let script = Script::default() << &short_data[..]; + assert_eq!(script.0[0], OpCode::PushData1 as u8); + assert_eq!(script.0[1] as usize, 100); + assert_eq!(&script.0[2..], &short_data[..]); + } + + { + let medium_data = vec![7; 1024]; + let script = Script::default() << &medium_data[..]; + assert_eq!(script.0[0], OpCode::PushData2 as u8); + assert_eq!(&script.0[1..3], &[0x00, 0x04][..]); + assert_eq!(&script.0[3..], &medium_data[..]); + } + + { + let long_data = vec![42; 1_000_000]; + let script = Script::default() << &long_data[..]; + assert_eq!(script.0[0], OpCode::PushData4 as u8); + assert_eq!(&script.0[1..5], &[0x40, 0x42, 0x0f, 0x00][..]); + assert_eq!(&script.0[5..], &long_data[..]); + } + } +} diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index d6ddcc9..a95d000 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -19,6 +19,7 @@ use sapling_crypto::jubjub::JubjubBls12; pub mod block; pub mod keys; +pub mod legacy; pub mod merkle_tree; pub mod note_encryption; pub mod prover; diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index 141d0ff..d4479b5 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -7,7 +7,7 @@ use sapling_crypto::{ }; use std::io::{self, Read, Write}; -use serialize::Vector; +use legacy::Script; use JUBJUB; // π_A + π_B + π_C @@ -58,20 +58,6 @@ impl Amount { } } -#[derive(Debug)] -pub struct Script(pub Vec); - -impl Script { - pub fn read(mut reader: R) -> io::Result { - let script = Vector::read(&mut reader, |r| r.read_u8())?; - Ok(Script(script)) - } - - pub fn write(&self, mut writer: W) -> io::Result<()> { - Vector::write(&mut writer, &self.0, |w, e| w.write_u8(*e)) - } -} - #[derive(Debug)] pub struct OutPoint { hash: [u8; 32], diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index 774e7b4..bcc971a 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -3,10 +3,11 @@ use byteorder::{LittleEndian, WriteBytesExt}; use ff::{PrimeField, PrimeFieldRepr}; use super::{ - components::{Amount, Script, TxOut}, + components::{Amount, TxOut}, Transaction, TransactionData, OVERWINTER_VERSION_GROUP_ID, SAPLING_TX_VERSION, SAPLING_VERSION_GROUP_ID, }; +use legacy::Script; const ZCASH_SIGHASH_PERSONALIZATION_PREFIX: &'static [u8; 12] = b"ZcashSigHash"; const ZCASH_PREVOUTS_HASH_PERSONALIZATION: &'static [u8; 16] = b"ZcashPrevoutHash"; diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index d9788ff..1ebac3a 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -6,11 +6,8 @@ use sapling_crypto::{ redjubjub::PrivateKey, }; -use super::{ - components::{Amount, Script}, - sighash::signature_hash, - Transaction, TransactionData, -}; +use super::{components::Amount, sighash::signature_hash, Transaction, TransactionData}; +use legacy::Script; use JUBJUB; #[test] From c26188a0bb5dc6bd850aefa1b350bf0c38cf2d17 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 24 May 2019 13:23:27 +0100 Subject: [PATCH 037/105] TransparentAddress struct for P2PKH and P2SH --- zcash_primitives/src/legacy.rs | 65 +++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/zcash_primitives/src/legacy.rs b/zcash_primitives/src/legacy.rs index ac22c6b..02977ab 100644 --- a/zcash_primitives/src/legacy.rs +++ b/zcash_primitives/src/legacy.rs @@ -12,6 +12,17 @@ enum OpCode { PushData1 = 0x4c, PushData2 = 0x4d, PushData4 = 0x4e, + + // stack ops + Dup = 0x76, + + // bit logic + Equal = 0x87, + EqualVerify = 0x88, + + // crypto + Hash160 = 0xa9, + CheckSig = 0xac, } /// A serialized script, used inside transparent inputs and outputs of a transaction. @@ -59,9 +70,37 @@ impl Shl<&[u8]> for Script { } } +/// A transparent address corresponding to either a public key or a `Script`. +#[derive(Debug, PartialEq)] +pub enum TransparentAddress { + PublicKey([u8; 20]), + Script([u8; 20]), +} + +impl TransparentAddress { + /// Generate the `scriptPubKey` corresponding to this address. + pub fn script(&self) -> Script { + match self { + TransparentAddress::PublicKey(key_id) => { + // P2PKH script + Script::default() + << OpCode::Dup + << OpCode::Hash160 + << &key_id[..] + << OpCode::EqualVerify + << OpCode::CheckSig + } + TransparentAddress::Script(script_id) => { + // P2SH script + Script::default() << OpCode::Hash160 << &script_id[..] << OpCode::Equal + } + } + } +} + #[cfg(test)] mod tests { - use super::{OpCode, Script}; + use super::{OpCode, Script, TransparentAddress}; #[test] fn script_opcode() { @@ -102,4 +141,28 @@ mod tests { assert_eq!(&script.0[5..], &long_data[..]); } } + + #[test] + fn p2pkh() { + let addr = TransparentAddress::PublicKey([4; 20]); + assert_eq!( + &addr.script().0, + &[ + 0x76, 0xa9, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x88, 0xac, + ] + ) + } + + #[test] + fn p2sh() { + let addr = TransparentAddress::Script([7; 20]); + assert_eq!( + &addr.script().0, + &[ + 0xa9, 0x14, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x87, + ] + ) + } } From a1cd9dfbac68f7ec2f3760a2c27c58afc6fcfad7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 24 May 2019 13:32:55 +0100 Subject: [PATCH 038/105] transaction::Builder::add_transparent_output() --- zcash_primitives/src/transaction/builder.rs | 69 +++++++++++++++++-- .../src/transaction/components.rs | 4 +- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 9f6cccd..2def3a8 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -12,12 +12,13 @@ use zip32::ExtendedSpendingKey; use crate::{ keys::OutgoingViewingKey, + legacy::TransparentAddress, merkle_tree::{CommitmentTreeWitness, IncrementalWitness}, note_encryption::{generate_esk, Memo, SaplingNoteEncryption}, prover::TxProver, sapling::{spend_sig, Node}, transaction::{ - components::{Amount, OutputDescription, SpendDescription}, + components::{Amount, OutputDescription, SpendDescription, TxOut}, signature_hash_data, Transaction, TransactionData, SIGHASH_ALL, }, JUBJUB, @@ -260,6 +261,24 @@ impl Builder { Ok(()) } + /// Adds a transparent address to send funds to. + pub fn add_transparent_output( + &mut self, + to: &TransparentAddress, + value: Amount, + ) -> Result<(), Error> { + if value.0 < 0 { + return Err(Error(ErrorKind::InvalidAmount)); + } + + self.mtx.vout.push(TxOut { + value, + script_pubkey: to.script(), + }); + + Ok(()) + } + /// Sets the Sapling address to which any change will be sent. /// /// By default, change is sent to the Sapling address corresponding to the first note @@ -289,7 +308,14 @@ impl Builder { // // Valid change - let change = self.mtx.value_balance.0 - self.fee.0; + let change = self.mtx.value_balance.0 + - self.fee.0 + - self + .mtx + .vout + .iter() + .map(|output| output.value.0) + .sum::(); if change.is_negative() { return Err(Error(ErrorKind::ChangeIsNegative(change))); } @@ -499,6 +525,7 @@ mod tests { use super::{Builder, ErrorKind}; use crate::{ + legacy::TransparentAddress, merkle_tree::{CommitmentTree, IncrementalWitness}, prover::mock::MockTxProver, sapling::Node, @@ -521,6 +548,15 @@ mod tests { } } + #[test] + fn fails_on_negative_transparent_output() { + let mut builder = Builder::new(0); + match builder.add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(-1)) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), + Ok(_) => panic!("Should have failed"), + } + } + #[test] fn fails_on_negative_change() { let mut rng = OsRng; @@ -555,6 +591,19 @@ mod tests { } } + // Fail if there is only a transparent output + // 0.0005 t-ZEC out, 0.0001 t-ZEC fee + { + let mut builder = Builder::new(0); + builder + .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(50000)) + .unwrap(); + match builder.build(1, MockTxProver) { + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-60000)), + Ok(_) => panic!("Should have failed"), + } + } + let note1 = to .create_note(59999, Fs::random(&mut rng), &JUBJUB) .unwrap(); @@ -563,8 +612,8 @@ mod tests { tree.append(cm1).unwrap(); let mut witness1 = IncrementalWitness::from_tree(&tree); - // Fail if there is only a Sapling output - // 0.0005 z-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in + // Fail if there is insufficient input + // 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in { let mut builder = Builder::new(0); builder @@ -576,7 +625,10 @@ mod tests { ) .unwrap(); builder - .add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None) + .add_sapling_output(ovk.clone(), to.clone(), Amount(30000), None) + .unwrap(); + builder + .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000)) .unwrap(); match builder.build(1, MockTxProver) { Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-1)), @@ -591,7 +643,7 @@ mod tests { let witness2 = IncrementalWitness::from_tree(&tree); // Succeeds if there is sufficient input - // 0.0005 z-ZEC out, 0.0001 t-ZEC fee, 0.0006 z-ZEC in + // 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.0001 t-ZEC fee, 0.0006 z-ZEC in // // (Still fails because we are using a MockTxProver which doesn't correctly // compute bindingSig.) @@ -604,7 +656,10 @@ mod tests { .add_sapling_spend(extsk, to.diversifier, note2, witness2) .unwrap(); builder - .add_sapling_output(ovk, to, Amount(50000), None) + .add_sapling_output(ovk, to, Amount(30000), None) + .unwrap(); + builder + .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000)) .unwrap(); match builder.build(1, MockTxProver) { Err(e) => assert_eq!(e.kind(), &ErrorKind::BindingSig), diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index d4479b5..f04c5aa 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -107,8 +107,8 @@ impl TxIn { #[derive(Debug)] pub struct TxOut { - value: Amount, - script_pubkey: Script, + pub value: Amount, + pub script_pubkey: Script, } impl TxOut { From 54ef63baced8160ac3396966b60941ceab1dbb3f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 12 Jun 2019 17:36:09 +0100 Subject: [PATCH 039/105] Place zcash_proofs::prover::LocalTxProver behind a feature flag This enables zcash_proofs to be compiled to WASM, which the directories crate doesn't support. --- zcash_proofs/Cargo.toml | 6 +++++- zcash_proofs/src/lib.rs | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 9e989fa..598e013 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -9,9 +9,13 @@ authors = [ bellman = { path = "../bellman" } blake2b_simd = "0.5" byteorder = "1" -directories = "1" +directories = { version = "1", optional = true } ff = { path = "../ff" } pairing = { path = "../pairing" } rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } + +[features] +default = ["local-prover"] +local-prover = ["directories"] diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index 26aa2f1..d2dc877 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -1,13 +1,15 @@ extern crate bellman; extern crate blake2b_simd; extern crate byteorder; -extern crate directories; extern crate ff; extern crate pairing; extern crate rand_os; extern crate sapling_crypto; extern crate zcash_primitives; +#[cfg(feature = "local-prover")] +extern crate directories; + use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey, VerifyingKey}; use pairing::bls12_381::Bls12; use std::fs::File; @@ -15,9 +17,11 @@ use std::io::{self, BufReader}; use std::path::Path; mod hashreader; -pub mod prover; pub mod sapling; +#[cfg(feature = "local-prover")] +pub mod prover; + pub fn load_parameters( spend_path: &Path, spend_hash: &str, From 4b61120cd0658938ac3cb537c9538c098f1ac4b7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 12 Jun 2019 23:11:06 +0100 Subject: [PATCH 040/105] Pass tx builder RNG to SaplingNoteEncryption --- zcash_primitives/src/note_encryption.rs | 21 ++++++++++----------- zcash_primitives/src/transaction/builder.rs | 16 +++++++++++----- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index d0a7250..42e1398 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -5,8 +5,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr}; -use rand_core::RngCore; -use rand_os::OsRng; +use rand_core::{CryptoRng, RngCore}; use sapling_crypto::{ jubjub::{ edwards, @@ -135,9 +134,8 @@ impl Memo { } } -pub fn generate_esk() -> Fs { +pub fn generate_esk(rng: &mut R) -> Fs { // create random 64 byte buffer - let mut rng = OsRng; let mut buffer = [0u8; 64]; rng.fill_bytes(&mut buffer); @@ -247,7 +245,7 @@ fn prf_ock( /// let note = to.create_note(value, rcv, &JUBJUB).unwrap(); /// let cmu = note.cm(&JUBJUB); /// -/// let enc = SaplingNoteEncryption::new(ovk, note, to, Memo::default()); +/// let enc = SaplingNoteEncryption::new(ovk, note, to, Memo::default(), &mut rng); /// let encCiphertext = enc.encrypt_note_plaintext(); /// let outCiphertext = enc.encrypt_outgoing_plaintext(&cv.cm(&JUBJUB).into(), &cmu); /// ``` @@ -262,13 +260,14 @@ pub struct SaplingNoteEncryption { impl SaplingNoteEncryption { /// Creates a new encryption context for the given note. - pub fn new( + pub fn new( ovk: OutgoingViewingKey, note: Note, to: PaymentAddress, memo: Memo, + rng: &mut R, ) -> SaplingNoteEncryption { - let esk = generate_esk(); + let esk = generate_esk(rng); let epk = note.g_d.mul(esk, &JUBJUB); SaplingNoteEncryption { @@ -561,7 +560,7 @@ mod tests { use crypto_api_chachapoly::ChachaPolyIetf; use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; - use rand_core::RngCore; + use rand_core::{CryptoRng, RngCore}; use rand_os::OsRng; use sapling_crypto::{ jubjub::{ @@ -694,7 +693,7 @@ mod tests { assert_eq!(Memo::default().to_utf8(), None); } - fn random_enc_ciphertext( + fn random_enc_ciphertext( mut rng: &mut R, ) -> ( OutgoingViewingKey, @@ -724,7 +723,7 @@ mod tests { let cmu = note.cm(&JUBJUB); let ovk = OutgoingViewingKey([0; 32]); - let ne = SaplingNoteEncryption::new(ovk, note, pa, Memo([0; 512])); + let ne = SaplingNoteEncryption::new(ovk, note, pa, Memo([0; 512]), rng); let epk = ne.epk(); let enc_ciphertext = ne.encrypt_note_plaintext(); let out_ciphertext = ne.encrypt_outgoing_plaintext(&cv, &cmu); @@ -1371,7 +1370,7 @@ mod tests { // Test encryption // - let mut ne = SaplingNoteEncryption::new(ovk, note, to, Memo(tv.memo)); + let mut ne = SaplingNoteEncryption::new(ovk, note, to, Memo(tv.memo), &mut OsRng); // Swap in the ephemeral keypair from the test vectors ne.esk = esk; ne.epk = epk; diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 2def3a8..2ea4d0d 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -100,13 +100,19 @@ impl SaplingOutput { }) } - pub fn build( + pub fn build( self, prover: &P, ctx: &mut P::SaplingProvingContext, + rng: &mut R, ) -> OutputDescription { - let encryptor = - SaplingNoteEncryption::new(self.ovk, self.note.clone(), self.to.clone(), self.memo); + let encryptor = SaplingNoteEncryption::new( + self.ovk, + self.note.clone(), + self.to.clone(), + self.memo, + rng, + ); let (zkproof, cv) = prover.output_proof( ctx, @@ -419,7 +425,7 @@ impl Builder { // Record the post-randomized output location tx_metadata.output_indices[pos] = i; - output.build(&prover, &mut ctx) + output.build(&prover, &mut ctx, &mut self.rng) } else { // This is a dummy output let (dummy_to, dummy_note) = { @@ -457,7 +463,7 @@ impl Builder { ) }; - let esk = generate_esk(); + let esk = generate_esk(&mut self.rng); let epk = dummy_note.g_d.mul(esk, &JUBJUB); let (zkproof, cv) = From 532299d46eaa2802356049b209a40e6289ad2621 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 12 Jun 2019 23:11:51 +0100 Subject: [PATCH 041/105] Allow transaction::Builder RNG to be configured --- zcash_primitives/src/transaction/builder.rs | 27 ++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 2ea4d0d..4edcd20 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -178,8 +178,8 @@ impl TransactionMetadata { } /// Generates a [`Transaction`] from its inputs and outputs. -pub struct Builder { - rng: OsRng, +pub struct Builder { + rng: R, mtx: TransactionData, fee: Amount, anchor: Option, @@ -188,9 +188,9 @@ pub struct Builder { change_address: Option<(OutgoingViewingKey, PaymentAddress)>, } -impl Builder { +impl Builder { /// Creates a new `Builder` targeted for inclusion in the block with the given height, - /// using default values for general transaction fields. + /// using default values for general transaction fields and the default OS random. /// /// # Default values /// @@ -198,12 +198,27 @@ impl Builder { /// expiry delta (20 blocks). /// /// The fee will be set to the default fee (0.0001 ZEC). - pub fn new(height: u32) -> Builder { + pub fn new(height: u32) -> Self { + Builder::new_with_rng(height, OsRng) + } +} + +impl Builder { + /// Creates a new `Builder` targeted for inclusion in the block with the given height + /// and randomness source, using default values for general transaction fields. + /// + /// # Default values + /// + /// The expiry height will be set to the given height plus the default transaction + /// expiry delta (20 blocks). + /// + /// The fee will be set to the default fee (0.0001 ZEC). + pub fn new_with_rng(height: u32, rng: R) -> Builder { let mut mtx = TransactionData::new(); mtx.expiry_height = height + DEFAULT_TX_EXPIRY_DELTA; Builder { - rng: OsRng, + rng, mtx, fee: DEFAULT_FEE, anchor: None, From 17f6bbcc67d6d82704d14fc58069b71db77ff0ad Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 12 Jun 2019 23:12:55 +0100 Subject: [PATCH 042/105] Pass tx builder RNG to spend_sig() --- librustzcash/src/rustzcash.rs | 5 ++++- zcash_primitives/src/sapling.rs | 10 ++++------ zcash_primitives/src/transaction/builder.rs | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 1db70ac..4f27fa1 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -1002,8 +1002,11 @@ pub extern "system" fn librustzcash_sapling_spend_sig( Err(_) => return false, }; + // Initialize secure RNG + let mut rng = OsRng; + // Do the signing - let sig = spend_sig(ask, ar, unsafe { &*sighash }, &JUBJUB); + let sig = spend_sig(ask, ar, unsafe { &*sighash }, &mut rng, &JUBJUB); // Write out the signature sig.write(&mut (unsafe { &mut *result })[..]) diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index ad7e309..bd981e6 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -2,7 +2,7 @@ use ff::{BitIterator, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use rand_os::OsRng; +use rand_core::{CryptoRng, RngCore}; use sapling_crypto::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, pedersen_hash::{pedersen_hash, Personalization}, @@ -106,15 +106,13 @@ lazy_static! { } /// Create the spendAuthSig for a Sapling SpendDescription. -pub fn spend_sig( +pub fn spend_sig( ask: PrivateKey, ar: Fs, sighash: &[u8; 32], + rng: &mut R, params: &JubjubBls12, ) -> Signature { - // Initialize secure RNG - let mut rng = OsRng; - // We compute `rsk`... let rsk = ask.randomize(ar); @@ -130,7 +128,7 @@ pub fn spend_sig( // Do the signing rsk.sign( &data_to_be_signed, - &mut rng, + rng, FixedGenerators::SpendingKeyGenerator, params, ) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 4edcd20..5c0e643 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -522,6 +522,7 @@ impl Builder { PrivateKey(spend.extsk.expsk.ask), spend.alpha, &sighash, + &mut self.rng, &JUBJUB, )); } From fa50d551c8c7d969157d4b3d42e9cbda85548051 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 25 Jul 2019 18:30:56 +0100 Subject: [PATCH 043/105] Move Amount impl into a submodule --- .../src/transaction/components.rs | 90 +------------------ .../src/transaction/components/amount.rs | 89 ++++++++++++++++++ 2 files changed, 92 insertions(+), 87 deletions(-) create mode 100644 zcash_primitives/src/transaction/components/amount.rs diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index f04c5aa..f72dfc5 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -10,6 +10,9 @@ use std::io::{self, Read, Write}; use legacy::Script; use JUBJUB; +mod amount; +pub use self::amount::Amount; + // π_A + π_B + π_C pub const GROTH_PROOF_SIZE: usize = (48 + 96 + 48); // π_A + π_A' + π_B + π_B' + π_C + π_C' + π_K + π_H @@ -18,46 +21,6 @@ const PHGR_PROOF_SIZE: usize = (33 + 33 + 65 + 33 + 33 + 33 + 33 + 33); const ZC_NUM_JS_INPUTS: usize = 2; const ZC_NUM_JS_OUTPUTS: usize = 2; -const COIN: i64 = 1_0000_0000; -const MAX_MONEY: i64 = 21_000_000 * COIN; - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Amount(pub i64); - -impl Amount { - // Read an Amount from a signed 64-bit little-endian integer. - pub fn read_i64(mut reader: R, allow_negative: bool) -> io::Result { - let amount = reader.read_i64::()?; - if 0 <= amount && amount <= MAX_MONEY { - Ok(Amount(amount)) - } else if allow_negative && -MAX_MONEY <= amount && amount < 0 { - Ok(Amount(amount)) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - if allow_negative { - "Amount not in {-MAX_MONEY..MAX_MONEY}" - } else { - "Amount not in {0..MAX_MONEY}" - }, - )) - } - } - - // Read an Amount from an unsigned 64-bit little-endian integer. - pub fn read_u64(mut reader: R) -> io::Result { - let amount = reader.read_u64::()?; - if amount <= MAX_MONEY as u64 { - Ok(Amount(amount as i64)) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - "Amount not in {0..MAX_MONEY}", - )) - } - } -} - #[derive(Debug)] pub struct OutPoint { hash: [u8; 32], @@ -432,50 +395,3 @@ impl JSDescription { writer.write_all(&self.ciphertexts[1]) } } - -#[cfg(test)] -mod tests { - use super::{Amount, MAX_MONEY}; - - #[test] - fn amount_in_range() { - let zero = b"\x00\x00\x00\x00\x00\x00\x00\x00"; - assert_eq!(Amount::read_u64(&zero[..]).unwrap(), Amount(0)); - assert_eq!(Amount::read_i64(&zero[..], false).unwrap(), Amount(0)); - assert_eq!(Amount::read_i64(&zero[..], true).unwrap(), Amount(0)); - - let neg_one = b"\xff\xff\xff\xff\xff\xff\xff\xff"; - assert!(Amount::read_u64(&neg_one[..]).is_err()); - assert!(Amount::read_i64(&neg_one[..], false).is_err()); - assert_eq!(Amount::read_i64(&neg_one[..], true).unwrap(), Amount(-1)); - - let max_money = b"\x00\x40\x07\x5a\xf0\x75\x07\x00"; - assert_eq!(Amount::read_u64(&max_money[..]).unwrap(), Amount(MAX_MONEY)); - assert_eq!( - Amount::read_i64(&max_money[..], false).unwrap(), - Amount(MAX_MONEY) - ); - assert_eq!( - Amount::read_i64(&max_money[..], true).unwrap(), - Amount(MAX_MONEY) - ); - - let max_money_p1 = b"\x01\x40\x07\x5a\xf0\x75\x07\x00"; - assert!(Amount::read_u64(&max_money_p1[..]).is_err()); - assert!(Amount::read_i64(&max_money_p1[..], false).is_err()); - assert!(Amount::read_i64(&max_money_p1[..], true).is_err()); - - let neg_max_money = b"\x00\xc0\xf8\xa5\x0f\x8a\xf8\xff"; - assert!(Amount::read_u64(&neg_max_money[..]).is_err()); - assert!(Amount::read_i64(&neg_max_money[..], false).is_err()); - assert_eq!( - Amount::read_i64(&neg_max_money[..], true).unwrap(), - Amount(-MAX_MONEY) - ); - - let neg_max_money_m1 = b"\xff\xbf\xf8\xa5\x0f\x8a\xf8\xff"; - assert!(Amount::read_u64(&neg_max_money_m1[..]).is_err()); - assert!(Amount::read_i64(&neg_max_money_m1[..], false).is_err()); - assert!(Amount::read_i64(&neg_max_money_m1[..], true).is_err()); - } -} diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs new file mode 100644 index 0000000..593e98c --- /dev/null +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -0,0 +1,89 @@ +use byteorder::{LittleEndian, ReadBytesExt}; +use std::io::{self, Read}; + +const COIN: i64 = 1_0000_0000; +const MAX_MONEY: i64 = 21_000_000 * COIN; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Amount(pub i64); + +impl Amount { + // Read an Amount from a signed 64-bit little-endian integer. + pub fn read_i64(mut reader: R, allow_negative: bool) -> io::Result { + let amount = reader.read_i64::()?; + if 0 <= amount && amount <= MAX_MONEY { + Ok(Amount(amount)) + } else if allow_negative && -MAX_MONEY <= amount && amount < 0 { + Ok(Amount(amount)) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidData, + if allow_negative { + "Amount not in {-MAX_MONEY..MAX_MONEY}" + } else { + "Amount not in {0..MAX_MONEY}" + }, + )) + } + } + + // Read an Amount from an unsigned 64-bit little-endian integer. + pub fn read_u64(mut reader: R) -> io::Result { + let amount = reader.read_u64::()?; + if amount <= MAX_MONEY as u64 { + Ok(Amount(amount as i64)) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "Amount not in {0..MAX_MONEY}", + )) + } + } +} + +#[cfg(test)] +mod tests { + use super::{Amount, MAX_MONEY}; + + #[test] + fn amount_in_range() { + let zero = b"\x00\x00\x00\x00\x00\x00\x00\x00"; + assert_eq!(Amount::read_u64(&zero[..]).unwrap(), Amount(0)); + assert_eq!(Amount::read_i64(&zero[..], false).unwrap(), Amount(0)); + assert_eq!(Amount::read_i64(&zero[..], true).unwrap(), Amount(0)); + + let neg_one = b"\xff\xff\xff\xff\xff\xff\xff\xff"; + assert!(Amount::read_u64(&neg_one[..]).is_err()); + assert!(Amount::read_i64(&neg_one[..], false).is_err()); + assert_eq!(Amount::read_i64(&neg_one[..], true).unwrap(), Amount(-1)); + + let max_money = b"\x00\x40\x07\x5a\xf0\x75\x07\x00"; + assert_eq!(Amount::read_u64(&max_money[..]).unwrap(), Amount(MAX_MONEY)); + assert_eq!( + Amount::read_i64(&max_money[..], false).unwrap(), + Amount(MAX_MONEY) + ); + assert_eq!( + Amount::read_i64(&max_money[..], true).unwrap(), + Amount(MAX_MONEY) + ); + + let max_money_p1 = b"\x01\x40\x07\x5a\xf0\x75\x07\x00"; + assert!(Amount::read_u64(&max_money_p1[..]).is_err()); + assert!(Amount::read_i64(&max_money_p1[..], false).is_err()); + assert!(Amount::read_i64(&max_money_p1[..], true).is_err()); + + let neg_max_money = b"\x00\xc0\xf8\xa5\x0f\x8a\xf8\xff"; + assert!(Amount::read_u64(&neg_max_money[..]).is_err()); + assert!(Amount::read_i64(&neg_max_money[..], false).is_err()); + assert_eq!( + Amount::read_i64(&neg_max_money[..], true).unwrap(), + Amount(-MAX_MONEY) + ); + + let neg_max_money_m1 = b"\xff\xbf\xf8\xa5\x0f\x8a\xf8\xff"; + assert!(Amount::read_u64(&neg_max_money_m1[..]).is_err()); + assert!(Amount::read_i64(&neg_max_money_m1[..], false).is_err()); + assert!(Amount::read_i64(&neg_max_money_m1[..], true).is_err()); + } +} From 0ea4408d46e7e54c7d42854e87a0595b1a338c27 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 25 Jul 2019 20:50:17 +0100 Subject: [PATCH 044/105] Amount::{zero, is_positive, is_negative} --- zcash_primitives/src/transaction/builder.rs | 4 ++-- .../src/transaction/components/amount.rs | 17 +++++++++++++++++ zcash_primitives/src/transaction/mod.rs | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 5c0e643..a2ea4af 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -79,7 +79,7 @@ impl SaplingOutput { Some(g_d) => g_d, None => return Err(Error(ErrorKind::InvalidAddress)), }; - if value.0 < 0 { + if value.is_negative() { return Err(Error(ErrorKind::InvalidAmount)); } @@ -288,7 +288,7 @@ impl Builder { to: &TransparentAddress, value: Amount, ) -> Result<(), Error> { - if value.0 < 0 { + if value.is_negative() { return Err(Error(ErrorKind::InvalidAmount)); } diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index 593e98c..eedfe2a 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -8,6 +8,11 @@ const MAX_MONEY: i64 = 21_000_000 * COIN; pub struct Amount(pub i64); impl Amount { + /// Returns a zero-valued Amount. + pub const fn zero() -> Self { + Amount(0) + } + // Read an Amount from a signed 64-bit little-endian integer. pub fn read_i64(mut reader: R, allow_negative: bool) -> io::Result { let amount = reader.read_i64::()?; @@ -39,6 +44,18 @@ impl Amount { )) } } + + /// Returns `true` if `self` is positive and `false` if the number is zero or + /// negative. + pub const fn is_positive(self) -> bool { + self.0.is_positive() + } + + /// Returns `true` if `self` is negative and `false` if the number is zero or + /// positive. + pub const fn is_negative(self) -> bool { + self.0.is_negative() + } } #[cfg(test)] diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 19f4396..d8024eb 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -112,7 +112,7 @@ impl TransactionData { vout: vec![], lock_time: 0, expiry_height: 0, - value_balance: Amount(0), + value_balance: Amount::zero(), shielded_spends: vec![], shielded_outputs: vec![], joinsplits: vec![], @@ -190,7 +190,7 @@ impl Transaction { let so = Vector::read(&mut reader, OutputDescription::read)?; (vb, ss, so) } else { - (Amount(0), vec![], vec![]) + (Amount::zero(), vec![], vec![]) }; let (joinsplits, joinsplit_pubkey, joinsplit_sig) = if version >= 2 { From ab60b8804ae9d6900e51c61a93ce45309b19d822 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 25 Jul 2019 20:53:42 +0100 Subject: [PATCH 045/105] impl operators for Amount --- zcash_primitives/src/transaction/builder.rs | 24 ++++++------- .../src/transaction/components/amount.rs | 36 +++++++++++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index a2ea4af..b7bcb62 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -44,7 +44,7 @@ impl Error { pub enum ErrorKind { AnchorMismatch, BindingSig, - ChangeIsNegative(i64), + ChangeIsNegative(Amount), InvalidAddress, InvalidAmount, InvalidWitness, @@ -252,7 +252,7 @@ impl Builder { let alpha = Fs::random(&mut self.rng); - self.mtx.value_balance.0 += note.value as i64; + self.mtx.value_balance += Amount(note.value as i64); self.spends.push(SpendDescriptionInfo { extsk, @@ -275,7 +275,7 @@ impl Builder { ) -> Result<(), Error> { let output = SaplingOutput::new(&mut self.rng, ovk, to, value, memo)?; - self.mtx.value_balance.0 -= value.0; + self.mtx.value_balance -= value; self.outputs.push(output); @@ -329,14 +329,14 @@ impl Builder { // // Valid change - let change = self.mtx.value_balance.0 - - self.fee.0 + let change = self.mtx.value_balance + - self.fee - self .mtx .vout .iter() - .map(|output| output.value.0) - .sum::(); + .map(|output| output.value) + .sum::(); if change.is_negative() { return Err(Error(ErrorKind::ChangeIsNegative(change))); } @@ -362,7 +362,7 @@ impl Builder { return Err(Error(ErrorKind::NoChangeAddress)); }; - self.add_sapling_output(change_address.0, change_address.1, Amount(change), None)?; + self.add_sapling_output(change_address.0, change_address.1, change, None)?; } // @@ -591,7 +591,7 @@ mod tests { { let builder = Builder::new(0); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-10000)), + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-10000))), Ok(_) => panic!("Should have failed"), } } @@ -608,7 +608,7 @@ mod tests { .add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-60000)), + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-60000))), Ok(_) => panic!("Should have failed"), } } @@ -621,7 +621,7 @@ mod tests { .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(50000)) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-60000)), + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-60000))), Ok(_) => panic!("Should have failed"), } } @@ -653,7 +653,7 @@ mod tests { .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000)) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-1)), + Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-1))), Ok(_) => panic!("Should have failed"), } } diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index eedfe2a..fa9ee06 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -1,5 +1,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use std::io::{self, Read}; +use std::iter::Sum; +use std::ops::{Add, AddAssign, Sub, SubAssign}; const COIN: i64 = 1_0000_0000; const MAX_MONEY: i64 = 21_000_000 * COIN; @@ -58,6 +60,40 @@ impl Amount { } } +impl Add for Amount { + type Output = Amount; + + fn add(self, rhs: Amount) -> Amount { + Amount(self.0 + rhs.0) + } +} + +impl AddAssign for Amount { + fn add_assign(&mut self, rhs: Amount) { + *self = *self + rhs + } +} + +impl Sub for Amount { + type Output = Amount; + + fn sub(self, rhs: Amount) -> Amount { + Amount(self.0 - rhs.0) + } +} + +impl SubAssign for Amount { + fn sub_assign(&mut self, rhs: Amount) { + *self = *self - rhs + } +} + +impl Sum for Amount { + fn sum>(iter: I) -> Amount { + iter.fold(Amount::zero(), Add::add) + } +} + #[cfg(test)] mod tests { use super::{Amount, MAX_MONEY}; From 59ed258c7f673031cb22524004d72d54991cb38e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 25 Jul 2019 22:37:16 +0100 Subject: [PATCH 046/105] Make Amount opaque, and use it more This helps to ensure type-safety of values that are required to satisfy zatoshi range bounds. --- librustzcash/src/rustzcash.rs | 11 ++ zcash_primitives/src/prover.rs | 14 ++- zcash_primitives/src/transaction/builder.rs | 68 ++++++++--- .../src/transaction/components.rs | 29 +++-- .../src/transaction/components/amount.rs | 115 ++++++++++++------ zcash_primitives/src/transaction/mod.rs | 9 +- zcash_primitives/src/transaction/sighash.rs | 11 +- zcash_primitives/src/transaction/tests.rs | 12 +- zcash_proofs/src/prover.rs | 9 +- zcash_proofs/src/sapling/mod.rs | 5 +- zcash_proofs/src/sapling/prover.rs | 6 +- zcash_proofs/src/sapling/verifier.rs | 3 +- 12 files changed, 203 insertions(+), 89 deletions(-) diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 4f27fa1..0fad706 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -63,6 +63,7 @@ use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, note_encryption::sapling_ka_agree, sapling::{merkle_hash, spend_sig}, + transaction::components::Amount, zip32, JUBJUB, }; use zcash_proofs::{ @@ -704,6 +705,11 @@ pub extern "system" fn librustzcash_sapling_final_check( binding_sig: *const [c_uchar; 64], sighash_value: *const [c_uchar; 32], ) -> bool { + let value_balance = match Amount::from_i64(value_balance, true) { + Ok(vb) => vb, + Err(()) => return false, + }; + // Deserialize the signature let binding_sig = match Signature::read(&(unsafe { &*binding_sig })[..]) { Ok(sig) => sig, @@ -1022,6 +1028,11 @@ pub extern "system" fn librustzcash_sapling_binding_sig( sighash: *const [c_uchar; 32], result: *mut [c_uchar; 64], ) -> bool { + let value_balance = match Amount::from_i64(value_balance, true) { + Ok(vb) => vb, + Err(()) => return false, + }; + // Sign let sig = match unsafe { &*ctx }.binding_sig(value_balance, unsafe { &*sighash }, &JUBJUB) { Ok(s) => s, diff --git a/zcash_primitives/src/prover.rs b/zcash_primitives/src/prover.rs index 87a76c7..1d40965 100644 --- a/zcash_primitives/src/prover.rs +++ b/zcash_primitives/src/prover.rs @@ -8,7 +8,9 @@ use sapling_crypto::{ }; use crate::{ - merkle_tree::CommitmentTreeWitness, sapling::Node, transaction::components::GROTH_PROOF_SIZE, + merkle_tree::CommitmentTreeWitness, + sapling::Node, + transaction::components::{Amount, GROTH_PROOF_SIZE}, }; /// Interface for creating zero-knowledge proofs for shielded transactions. @@ -63,7 +65,7 @@ pub trait TxProver { fn binding_sig( &self, ctx: &mut Self::SaplingProvingContext, - value_balance: i64, + value_balance: Amount, sighash: &[u8; 32], ) -> Result; } @@ -80,8 +82,10 @@ pub(crate) mod mock { }; use crate::{ - merkle_tree::CommitmentTreeWitness, sapling::Node, - transaction::components::GROTH_PROOF_SIZE, JUBJUB, + merkle_tree::CommitmentTreeWitness, + sapling::Node, + transaction::components::{Amount, GROTH_PROOF_SIZE}, + JUBJUB, }; use super::TxProver; @@ -153,7 +157,7 @@ pub(crate) mod mock { fn binding_sig( &self, _ctx: &mut Self::SaplingProvingContext, - _value_balance: i64, + _value_balance: Amount, _sighash: &[u8; 32], ) -> Result { Err(()) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index b7bcb62..36490e4 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -18,13 +18,12 @@ use crate::{ prover::TxProver, sapling::{spend_sig, Node}, transaction::{ - components::{Amount, OutputDescription, SpendDescription, TxOut}, + components::{amount::DEFAULT_FEE, Amount, OutputDescription, SpendDescription, TxOut}, signature_hash_data, Transaction, TransactionData, SIGHASH_ALL, }, JUBJUB, }; -const DEFAULT_FEE: Amount = Amount(10000); const DEFAULT_TX_EXPIRY_DELTA: u32 = 20; /// If there are any shielded inputs, always have at least two shielded outputs, padding @@ -88,7 +87,7 @@ impl SaplingOutput { let note = Note { g_d, pk_d: to.pk_d.clone(), - value: value.0 as u64, + value: value.into(), r: rcm, }; @@ -252,7 +251,8 @@ impl Builder { let alpha = Fs::random(&mut self.rng); - self.mtx.value_balance += Amount(note.value as i64); + self.mtx.value_balance += + Amount::from_u64(note.value).map_err(|_| Error(ErrorKind::InvalidAmount))?; self.spends.push(SpendDescriptionInfo { extsk, @@ -528,7 +528,7 @@ impl Builder { } self.mtx.binding_sig = Some( prover - .binding_sig(&mut ctx, self.mtx.value_balance.0, &sighash) + .binding_sig(&mut ctx, self.mtx.value_balance, &sighash) .map_err(|()| Error(ErrorKind::BindingSig))?, ); @@ -564,7 +564,7 @@ mod tests { let to = extfvk.default_address().unwrap().1; let mut builder = Builder::new(0); - match builder.add_sapling_output(ovk, to, Amount(-1), None) { + match builder.add_sapling_output(ovk, to, Amount::from_i64(-1, true).unwrap(), None) { Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), Ok(_) => panic!("Should have failed"), } @@ -573,7 +573,10 @@ mod tests { #[test] fn fails_on_negative_transparent_output() { let mut builder = Builder::new(0); - match builder.add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(-1)) { + match builder.add_transparent_output( + &TransparentAddress::PublicKey([0; 20]), + Amount::from_i64(-1, true).unwrap(), + ) { Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), Ok(_) => panic!("Should have failed"), } @@ -591,7 +594,10 @@ mod tests { { let builder = Builder::new(0); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-10000))), + Err(e) => assert_eq!( + e.kind(), + &ErrorKind::ChangeIsNegative(Amount::from_i64(-10000, true).unwrap()) + ), Ok(_) => panic!("Should have failed"), } } @@ -605,10 +611,18 @@ mod tests { { let mut builder = Builder::new(0); builder - .add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None) + .add_sapling_output( + ovk.clone(), + to.clone(), + Amount::from_u64(50000).unwrap(), + None, + ) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-60000))), + Err(e) => assert_eq!( + e.kind(), + &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000, true).unwrap()) + ), Ok(_) => panic!("Should have failed"), } } @@ -618,10 +632,16 @@ mod tests { { let mut builder = Builder::new(0); builder - .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(50000)) + .add_transparent_output( + &TransparentAddress::PublicKey([0; 20]), + Amount::from_u64(50000).unwrap(), + ) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-60000))), + Err(e) => assert_eq!( + e.kind(), + &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000, true).unwrap()) + ), Ok(_) => panic!("Should have failed"), } } @@ -647,13 +667,24 @@ mod tests { ) .unwrap(); builder - .add_sapling_output(ovk.clone(), to.clone(), Amount(30000), None) + .add_sapling_output( + ovk.clone(), + to.clone(), + Amount::from_u64(30000).unwrap(), + None, + ) .unwrap(); builder - .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000)) + .add_transparent_output( + &TransparentAddress::PublicKey([0; 20]), + Amount::from_u64(20000).unwrap(), + ) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-1))), + Err(e) => assert_eq!( + e.kind(), + &ErrorKind::ChangeIsNegative(Amount::from_i64(-1, true).unwrap()) + ), Ok(_) => panic!("Should have failed"), } } @@ -678,10 +709,13 @@ mod tests { .add_sapling_spend(extsk, to.diversifier, note2, witness2) .unwrap(); builder - .add_sapling_output(ovk, to, Amount(30000), None) + .add_sapling_output(ovk, to, Amount::from_u64(30000).unwrap(), None) .unwrap(); builder - .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000)) + .add_transparent_output( + &TransparentAddress::PublicKey([0; 20]), + Amount::from_u64(20000).unwrap(), + ) .unwrap(); match builder.build(1, MockTxProver) { Err(e) => assert_eq!(e.kind(), &ErrorKind::BindingSig), diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index f72dfc5..c7dcebd 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -10,7 +10,7 @@ use std::io::{self, Read, Write}; use legacy::Script; use JUBJUB; -mod amount; +pub mod amount; pub use self::amount::Amount; // π_A + π_B + π_C @@ -76,7 +76,12 @@ pub struct TxOut { impl TxOut { pub fn read(mut reader: &mut R) -> io::Result { - let value = Amount::read_i64(&mut reader, false)?; + let value = { + let mut tmp = [0; 8]; + reader.read_exact(&mut tmp)?; + Amount::from_i64_le_bytes(tmp, false) + } + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "value out of range"))?; let script_pubkey = Script::read(&mut reader)?; Ok(TxOut { @@ -86,7 +91,7 @@ impl TxOut { } pub fn write(&self, mut writer: W) -> io::Result<()> { - writer.write_i64::(self.value.0)?; + writer.write_all(&self.value.to_i64_le_bytes())?; self.script_pubkey.write(&mut writer) } } @@ -298,10 +303,20 @@ impl std::fmt::Debug for JSDescription { impl JSDescription { pub fn read(mut reader: R, use_groth: bool) -> io::Result { // Consensus rule (§4.3): Canonical encoding is enforced here - let vpub_old = Amount::read_u64(&mut reader)?; + let vpub_old = { + let mut tmp = [0; 8]; + reader.read_exact(&mut tmp)?; + Amount::from_u64_le_bytes(tmp) + } + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "vpub_old out of range"))?; // Consensus rule (§4.3): Canonical encoding is enforced here - let vpub_new = Amount::read_u64(&mut reader)?; + let vpub_new = { + let mut tmp = [0; 8]; + reader.read_exact(&mut tmp)?; + Amount::from_u64_le_bytes(tmp) + } + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "vpub_new out of range"))?; // Consensus rule (§4.3): One of vpub_old and vpub_new being zero is // enforced by CheckTransactionWithoutProofVerification() in zcashd. @@ -374,8 +389,8 @@ impl JSDescription { } pub fn write(&self, mut writer: W) -> io::Result<()> { - writer.write_i64::(self.vpub_old.0)?; - writer.write_i64::(self.vpub_new.0)?; + writer.write_all(&self.vpub_old.to_i64_le_bytes())?; + writer.write_all(&self.vpub_new.to_i64_le_bytes())?; writer.write_all(&self.anchor)?; writer.write_all(&self.nullifiers[0])?; writer.write_all(&self.nullifiers[1])?; diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index fa9ee06..dca7056 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -1,13 +1,13 @@ -use byteorder::{LittleEndian, ReadBytesExt}; -use std::io::{self, Read}; use std::iter::Sum; use std::ops::{Add, AddAssign, Sub, SubAssign}; const COIN: i64 = 1_0000_0000; const MAX_MONEY: i64 = 21_000_000 * COIN; +pub const DEFAULT_FEE: Amount = Amount(10000); + #[derive(Clone, Copy, Debug, PartialEq)] -pub struct Amount(pub i64); +pub struct Amount(i64); impl Amount { /// Returns a zero-valued Amount. @@ -15,38 +15,51 @@ impl Amount { Amount(0) } - // Read an Amount from a signed 64-bit little-endian integer. - pub fn read_i64(mut reader: R, allow_negative: bool) -> io::Result { - let amount = reader.read_i64::()?; + /// Creates an Amount from an i64. + /// + /// Returns an error if the amount is out of range. + pub fn from_i64(amount: i64, allow_negative: bool) -> Result { if 0 <= amount && amount <= MAX_MONEY { Ok(Amount(amount)) } else if allow_negative && -MAX_MONEY <= amount && amount < 0 { Ok(Amount(amount)) } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - if allow_negative { - "Amount not in {-MAX_MONEY..MAX_MONEY}" - } else { - "Amount not in {0..MAX_MONEY}" - }, - )) + Err(()) } } - // Read an Amount from an unsigned 64-bit little-endian integer. - pub fn read_u64(mut reader: R) -> io::Result { - let amount = reader.read_u64::()?; + /// Creates an Amount from a u64. + /// + /// Returns an error if the amount is out of range. + pub fn from_u64(amount: u64) -> Result { if amount <= MAX_MONEY as u64 { Ok(Amount(amount as i64)) } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - "Amount not in {0..MAX_MONEY}", - )) + Err(()) } } + /// Reads an Amount from a signed 64-bit little-endian integer. + /// + /// Returns an error if the amount is out of range. + pub fn from_i64_le_bytes(bytes: [u8; 8], allow_negative: bool) -> Result { + let amount = i64::from_le_bytes(bytes); + Amount::from_i64(amount, allow_negative) + } + + /// Reads an Amount from an unsigned 64-bit little-endian integer. + /// + /// Returns an error if the amount is out of range. + pub fn from_u64_le_bytes(bytes: [u8; 8]) -> Result { + let amount = u64::from_le_bytes(bytes); + Amount::from_u64(amount) + } + + /// Returns the Amount encoded as a signed 64-bit little-endian integer. + pub fn to_i64_le_bytes(self) -> [u8; 8] { + self.0.to_le_bytes() + } + /// Returns `true` if `self` is positive and `false` if the number is zero or /// negative. pub const fn is_positive(self) -> bool { @@ -60,6 +73,18 @@ impl Amount { } } +impl From for i64 { + fn from(amount: Amount) -> i64 { + amount.0 + } +} + +impl From for u64 { + fn from(amount: Amount) -> u64 { + amount.0 as u64 + } +} + impl Add for Amount { type Output = Amount; @@ -101,42 +126,54 @@ mod tests { #[test] fn amount_in_range() { let zero = b"\x00\x00\x00\x00\x00\x00\x00\x00"; - assert_eq!(Amount::read_u64(&zero[..]).unwrap(), Amount(0)); - assert_eq!(Amount::read_i64(&zero[..], false).unwrap(), Amount(0)); - assert_eq!(Amount::read_i64(&zero[..], true).unwrap(), Amount(0)); + assert_eq!(Amount::from_u64_le_bytes(zero.clone()).unwrap(), Amount(0)); + assert_eq!( + Amount::from_i64_le_bytes(zero.clone(), false).unwrap(), + Amount(0) + ); + assert_eq!( + Amount::from_i64_le_bytes(zero.clone(), true).unwrap(), + Amount(0) + ); let neg_one = b"\xff\xff\xff\xff\xff\xff\xff\xff"; - assert!(Amount::read_u64(&neg_one[..]).is_err()); - assert!(Amount::read_i64(&neg_one[..], false).is_err()); - assert_eq!(Amount::read_i64(&neg_one[..], true).unwrap(), Amount(-1)); + assert!(Amount::from_u64_le_bytes(neg_one.clone()).is_err()); + assert!(Amount::from_i64_le_bytes(neg_one.clone(), false).is_err()); + assert_eq!( + Amount::from_i64_le_bytes(neg_one.clone(), true).unwrap(), + Amount(-1) + ); let max_money = b"\x00\x40\x07\x5a\xf0\x75\x07\x00"; - assert_eq!(Amount::read_u64(&max_money[..]).unwrap(), Amount(MAX_MONEY)); assert_eq!( - Amount::read_i64(&max_money[..], false).unwrap(), + Amount::from_u64_le_bytes(max_money.clone()).unwrap(), Amount(MAX_MONEY) ); assert_eq!( - Amount::read_i64(&max_money[..], true).unwrap(), + Amount::from_i64_le_bytes(max_money.clone(), false).unwrap(), + Amount(MAX_MONEY) + ); + assert_eq!( + Amount::from_i64_le_bytes(max_money.clone(), true).unwrap(), Amount(MAX_MONEY) ); let max_money_p1 = b"\x01\x40\x07\x5a\xf0\x75\x07\x00"; - assert!(Amount::read_u64(&max_money_p1[..]).is_err()); - assert!(Amount::read_i64(&max_money_p1[..], false).is_err()); - assert!(Amount::read_i64(&max_money_p1[..], true).is_err()); + assert!(Amount::from_u64_le_bytes(max_money_p1.clone()).is_err()); + assert!(Amount::from_i64_le_bytes(max_money_p1.clone(), false).is_err()); + assert!(Amount::from_i64_le_bytes(max_money_p1.clone(), true).is_err()); let neg_max_money = b"\x00\xc0\xf8\xa5\x0f\x8a\xf8\xff"; - assert!(Amount::read_u64(&neg_max_money[..]).is_err()); - assert!(Amount::read_i64(&neg_max_money[..], false).is_err()); + assert!(Amount::from_u64_le_bytes(neg_max_money.clone()).is_err()); + assert!(Amount::from_i64_le_bytes(neg_max_money.clone(), false).is_err()); assert_eq!( - Amount::read_i64(&neg_max_money[..], true).unwrap(), + Amount::from_i64_le_bytes(neg_max_money.clone(), true).unwrap(), Amount(-MAX_MONEY) ); let neg_max_money_m1 = b"\xff\xbf\xf8\xa5\x0f\x8a\xf8\xff"; - assert!(Amount::read_u64(&neg_max_money_m1[..]).is_err()); - assert!(Amount::read_i64(&neg_max_money_m1[..], false).is_err()); - assert!(Amount::read_i64(&neg_max_money_m1[..], true).is_err()); + assert!(Amount::from_u64_le_bytes(neg_max_money_m1.clone()).is_err()); + assert!(Amount::from_i64_le_bytes(neg_max_money_m1.clone(), false).is_err()); + assert!(Amount::from_i64_le_bytes(neg_max_money_m1.clone(), true).is_err()); } } diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index d8024eb..e5b83e5 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -185,7 +185,12 @@ impl Transaction { }; let (value_balance, shielded_spends, shielded_outputs) = if is_sapling_v4 { - let vb = Amount::read_i64(&mut reader, true)?; + let vb = { + let mut tmp = [0; 8]; + reader.read_exact(&mut tmp)?; + Amount::from_i64_le_bytes(tmp, true) + } + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "valueBalance out of range"))?; let ss = Vector::read(&mut reader, SpendDescription::read)?; let so = Vector::read(&mut reader, OutputDescription::read)?; (vb, ss, so) @@ -262,7 +267,7 @@ impl Transaction { } if is_sapling_v4 { - writer.write_i64::(self.value_balance.0)?; + writer.write_all(&self.value_balance.to_i64_le_bytes())?; Vector::write(&mut writer, &self.shielded_spends, |w, e| e.write(w))?; Vector::write(&mut writer, &self.shielded_outputs, |w, e| e.write(w))?; } diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index bcc971a..b4e9a69 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -30,13 +30,6 @@ macro_rules! update_u32 { }; } -macro_rules! update_i64 { - ($h:expr, $value:expr, $tmp:expr) => { - (&mut $tmp[..8]).write_i64::($value).unwrap(); - $h.update(&$tmp[..8]); - }; -} - macro_rules! update_hash { ($h:expr, $cond:expr, $value:expr) => { if $cond { @@ -214,7 +207,7 @@ pub fn signature_hash_data( update_u32!(h, tx.lock_time, tmp); update_u32!(h, tx.expiry_height, tmp); if sigversion == SigHashVersion::Sapling { - update_i64!(h, tx.value_balance.0, tmp); + h.update(&tx.value_balance.to_i64_le_bytes()); } update_u32!(h, hash_type, tmp); @@ -222,7 +215,7 @@ pub fn signature_hash_data( let mut data = vec![]; tx.vin[n].prevout.write(&mut data).unwrap(); script_code.write(&mut data).unwrap(); - (&mut data).write_i64::(amount.0).unwrap(); + data.extend_from_slice(&amount.to_i64_le_bytes()); (&mut data) .write_u32::(tx.vin[n].sequence) .unwrap(); diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 1ebac3a..7d84100 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1902,7 +1902,11 @@ fn zip_0143() { for tv in test_vectors { let tx = Transaction::read(&tv.tx[..]).unwrap(); let transparent_input = if let Some(n) = tv.transparent_input { - Some((n as usize, Script(tv.script_code), Amount(tv.amount))) + Some(( + n as usize, + Script(tv.script_code), + Amount::from_i64(tv.amount, false).unwrap(), + )) } else { None }; @@ -5393,7 +5397,11 @@ fn zip_0243() { for tv in test_vectors { let tx = Transaction::read(&tv.tx[..]).unwrap(); let transparent_input = if let Some(n) = tv.transparent_input { - Some((n as usize, Script(tv.script_code), Amount(tv.amount))) + Some(( + n as usize, + Script(tv.script_code), + Amount::from_i64(tv.amount, false).unwrap(), + )) } else { None }; diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 005d7eb..4b5b0f4 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -10,8 +10,11 @@ use sapling_crypto::{ }; use std::path::Path; use zcash_primitives::{ - merkle_tree::CommitmentTreeWitness, prover::TxProver, sapling::Node, - transaction::components::GROTH_PROOF_SIZE, JUBJUB, + merkle_tree::CommitmentTreeWitness, + prover::TxProver, + sapling::Node, + transaction::components::{Amount, GROTH_PROOF_SIZE}, + JUBJUB, }; use crate::{load_parameters, sapling::SaplingProvingContext}; @@ -182,7 +185,7 @@ impl TxProver for LocalTxProver { fn binding_sig( &self, ctx: &mut Self::SaplingProvingContext, - value_balance: i64, + value_balance: Amount, sighash: &[u8; 32], ) -> Result { ctx.binding_sig(value_balance, sighash, &JUBJUB) diff --git a/zcash_proofs/src/sapling/mod.rs b/zcash_proofs/src/sapling/mod.rs index 4c37306..98c4ba3 100644 --- a/zcash_proofs/src/sapling/mod.rs +++ b/zcash_proofs/src/sapling/mod.rs @@ -2,6 +2,7 @@ use pairing::bls12_381::Bls12; use sapling_crypto::jubjub::{ edwards, fs::FsRepr, FixedGenerators, JubjubBls12, JubjubParams, Unknown, }; +use zcash_primitives::transaction::components::Amount; mod prover; mod verifier; @@ -11,12 +12,12 @@ pub use self::verifier::SaplingVerificationContext; // This function computes `value` in the exponent of the value commitment base fn compute_value_balance( - value: i64, + value: Amount, params: &JubjubBls12, ) -> Option> { // Compute the absolute value (failing if -i64::MAX is // the value) - let abs = match value.checked_abs() { + let abs = match i64::from(value).checked_abs() { Some(a) => a as u64, None => return None, }; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index fce4d8e..4b5a5f4 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -13,7 +13,9 @@ use sapling_crypto::{ primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, redjubjub::{PrivateKey, PublicKey, Signature}, }; -use zcash_primitives::{merkle_tree::CommitmentTreeWitness, sapling::Node}; +use zcash_primitives::{ + merkle_tree::CommitmentTreeWitness, sapling::Node, transaction::components::Amount, +}; use super::compute_value_balance; @@ -245,7 +247,7 @@ impl SaplingProvingContext { /// and output_proof() must be completed before calling this function. pub fn binding_sig( &self, - value_balance: i64, + value_balance: Amount, sighash: &[u8; 32], params: &JubjubBls12, ) -> Result { diff --git a/zcash_proofs/src/sapling/verifier.rs b/zcash_proofs/src/sapling/verifier.rs index e83c426..47fc9fe 100644 --- a/zcash_proofs/src/sapling/verifier.rs +++ b/zcash_proofs/src/sapling/verifier.rs @@ -6,6 +6,7 @@ use sapling_crypto::{ jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}, redjubjub::{PublicKey, Signature}, }; +use zcash_primitives::transaction::components::Amount; use super::compute_value_balance; @@ -169,7 +170,7 @@ impl SaplingVerificationContext { /// have been checked before calling this function. pub fn final_check( &self, - value_balance: i64, + value_balance: Amount, sighash_value: &[u8; 32], binding_sig: Signature, params: &JubjubBls12, From 7c07914bfdd9e896602b4582ccbd715743a23d5c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 8 Aug 2019 00:55:23 +0100 Subject: [PATCH 047/105] Separate Amount::{from_i64, from_nonnegative_i64} APIs This is more intuitive than a boolean flag for handling non-negative Amounts stored in i64 values. --- librustzcash/src/rustzcash.rs | 4 +- zcash_primitives/src/transaction/builder.rs | 12 ++--- .../src/transaction/components.rs | 2 +- .../src/transaction/components/amount.rs | 54 ++++++++++++------- zcash_primitives/src/transaction/mod.rs | 2 +- zcash_primitives/src/transaction/tests.rs | 4 +- 6 files changed, 46 insertions(+), 32 deletions(-) diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 0fad706..99c3187 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -705,7 +705,7 @@ pub extern "system" fn librustzcash_sapling_final_check( binding_sig: *const [c_uchar; 64], sighash_value: *const [c_uchar; 32], ) -> bool { - let value_balance = match Amount::from_i64(value_balance, true) { + let value_balance = match Amount::from_i64(value_balance) { Ok(vb) => vb, Err(()) => return false, }; @@ -1028,7 +1028,7 @@ pub extern "system" fn librustzcash_sapling_binding_sig( sighash: *const [c_uchar; 32], result: *mut [c_uchar; 64], ) -> bool { - let value_balance = match Amount::from_i64(value_balance, true) { + let value_balance = match Amount::from_i64(value_balance) { Ok(vb) => vb, Err(()) => return false, }; diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 36490e4..ba07f34 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -564,7 +564,7 @@ mod tests { let to = extfvk.default_address().unwrap().1; let mut builder = Builder::new(0); - match builder.add_sapling_output(ovk, to, Amount::from_i64(-1, true).unwrap(), None) { + match builder.add_sapling_output(ovk, to, Amount::from_i64(-1).unwrap(), None) { Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), Ok(_) => panic!("Should have failed"), } @@ -575,7 +575,7 @@ mod tests { let mut builder = Builder::new(0); match builder.add_transparent_output( &TransparentAddress::PublicKey([0; 20]), - Amount::from_i64(-1, true).unwrap(), + Amount::from_i64(-1).unwrap(), ) { Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), Ok(_) => panic!("Should have failed"), @@ -596,7 +596,7 @@ mod tests { match builder.build(1, MockTxProver) { Err(e) => assert_eq!( e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-10000, true).unwrap()) + &ErrorKind::ChangeIsNegative(Amount::from_i64(-10000).unwrap()) ), Ok(_) => panic!("Should have failed"), } @@ -621,7 +621,7 @@ mod tests { match builder.build(1, MockTxProver) { Err(e) => assert_eq!( e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000, true).unwrap()) + &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) ), Ok(_) => panic!("Should have failed"), } @@ -640,7 +640,7 @@ mod tests { match builder.build(1, MockTxProver) { Err(e) => assert_eq!( e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000, true).unwrap()) + &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) ), Ok(_) => panic!("Should have failed"), } @@ -683,7 +683,7 @@ mod tests { match builder.build(1, MockTxProver) { Err(e) => assert_eq!( e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-1, true).unwrap()) + &ErrorKind::ChangeIsNegative(Amount::from_i64(-1).unwrap()) ), Ok(_) => panic!("Should have failed"), } diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index c7dcebd..d50b4fb 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -79,7 +79,7 @@ impl TxOut { let value = { let mut tmp = [0; 8]; reader.read_exact(&mut tmp)?; - Amount::from_i64_le_bytes(tmp, false) + Amount::from_nonnegative_i64_le_bytes(tmp) } .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "value out of range"))?; let script_pubkey = Script::read(&mut reader)?; diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index dca7056..d244876 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -18,10 +18,19 @@ impl Amount { /// Creates an Amount from an i64. /// /// Returns an error if the amount is out of range. - pub fn from_i64(amount: i64, allow_negative: bool) -> Result { - if 0 <= amount && amount <= MAX_MONEY { + pub fn from_i64(amount: i64) -> Result { + if -MAX_MONEY <= amount && amount <= MAX_MONEY { Ok(Amount(amount)) - } else if allow_negative && -MAX_MONEY <= amount && amount < 0 { + } else { + Err(()) + } + } + + /// Creates a non-negative Amount from an i64. + /// + /// Returns an error if the amount is out of range. + pub fn from_nonnegative_i64(amount: i64) -> Result { + if 0 <= amount && amount <= MAX_MONEY { Ok(Amount(amount)) } else { Err(()) @@ -42,9 +51,17 @@ impl Amount { /// Reads an Amount from a signed 64-bit little-endian integer. /// /// Returns an error if the amount is out of range. - pub fn from_i64_le_bytes(bytes: [u8; 8], allow_negative: bool) -> Result { + pub fn from_i64_le_bytes(bytes: [u8; 8]) -> Result { let amount = i64::from_le_bytes(bytes); - Amount::from_i64(amount, allow_negative) + Amount::from_i64(amount) + } + + /// Reads a non-negative Amount from a signed 64-bit little-endian integer. + /// + /// Returns an error if the amount is out of range. + pub fn from_nonnegative_i64_le_bytes(bytes: [u8; 8]) -> Result { + let amount = i64::from_le_bytes(bytes); + Amount::from_nonnegative_i64(amount) } /// Reads an Amount from an unsigned 64-bit little-endian integer. @@ -128,19 +145,16 @@ mod tests { let zero = b"\x00\x00\x00\x00\x00\x00\x00\x00"; assert_eq!(Amount::from_u64_le_bytes(zero.clone()).unwrap(), Amount(0)); assert_eq!( - Amount::from_i64_le_bytes(zero.clone(), false).unwrap(), - Amount(0) - ); - assert_eq!( - Amount::from_i64_le_bytes(zero.clone(), true).unwrap(), + Amount::from_nonnegative_i64_le_bytes(zero.clone()).unwrap(), Amount(0) ); + assert_eq!(Amount::from_i64_le_bytes(zero.clone()).unwrap(), Amount(0)); let neg_one = b"\xff\xff\xff\xff\xff\xff\xff\xff"; assert!(Amount::from_u64_le_bytes(neg_one.clone()).is_err()); - assert!(Amount::from_i64_le_bytes(neg_one.clone(), false).is_err()); + assert!(Amount::from_nonnegative_i64_le_bytes(neg_one.clone()).is_err()); assert_eq!( - Amount::from_i64_le_bytes(neg_one.clone(), true).unwrap(), + Amount::from_i64_le_bytes(neg_one.clone()).unwrap(), Amount(-1) ); @@ -150,30 +164,30 @@ mod tests { Amount(MAX_MONEY) ); assert_eq!( - Amount::from_i64_le_bytes(max_money.clone(), false).unwrap(), + Amount::from_nonnegative_i64_le_bytes(max_money.clone()).unwrap(), Amount(MAX_MONEY) ); assert_eq!( - Amount::from_i64_le_bytes(max_money.clone(), true).unwrap(), + Amount::from_i64_le_bytes(max_money.clone()).unwrap(), Amount(MAX_MONEY) ); let max_money_p1 = b"\x01\x40\x07\x5a\xf0\x75\x07\x00"; assert!(Amount::from_u64_le_bytes(max_money_p1.clone()).is_err()); - assert!(Amount::from_i64_le_bytes(max_money_p1.clone(), false).is_err()); - assert!(Amount::from_i64_le_bytes(max_money_p1.clone(), true).is_err()); + assert!(Amount::from_nonnegative_i64_le_bytes(max_money_p1.clone()).is_err()); + assert!(Amount::from_i64_le_bytes(max_money_p1.clone()).is_err()); let neg_max_money = b"\x00\xc0\xf8\xa5\x0f\x8a\xf8\xff"; assert!(Amount::from_u64_le_bytes(neg_max_money.clone()).is_err()); - assert!(Amount::from_i64_le_bytes(neg_max_money.clone(), false).is_err()); + assert!(Amount::from_nonnegative_i64_le_bytes(neg_max_money.clone()).is_err()); assert_eq!( - Amount::from_i64_le_bytes(neg_max_money.clone(), true).unwrap(), + Amount::from_i64_le_bytes(neg_max_money.clone()).unwrap(), Amount(-MAX_MONEY) ); let neg_max_money_m1 = b"\xff\xbf\xf8\xa5\x0f\x8a\xf8\xff"; assert!(Amount::from_u64_le_bytes(neg_max_money_m1.clone()).is_err()); - assert!(Amount::from_i64_le_bytes(neg_max_money_m1.clone(), false).is_err()); - assert!(Amount::from_i64_le_bytes(neg_max_money_m1.clone(), true).is_err()); + assert!(Amount::from_nonnegative_i64_le_bytes(neg_max_money_m1.clone()).is_err()); + assert!(Amount::from_i64_le_bytes(neg_max_money_m1.clone()).is_err()); } } diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index e5b83e5..aac0d35 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -188,7 +188,7 @@ impl Transaction { let vb = { let mut tmp = [0; 8]; reader.read_exact(&mut tmp)?; - Amount::from_i64_le_bytes(tmp, true) + Amount::from_i64_le_bytes(tmp) } .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "valueBalance out of range"))?; let ss = Vector::read(&mut reader, SpendDescription::read)?; diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 7d84100..4cd5d72 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1905,7 +1905,7 @@ fn zip_0143() { Some(( n as usize, Script(tv.script_code), - Amount::from_i64(tv.amount, false).unwrap(), + Amount::from_nonnegative_i64(tv.amount).unwrap(), )) } else { None @@ -5400,7 +5400,7 @@ fn zip_0243() { Some(( n as usize, Script(tv.script_code), - Amount::from_i64(tv.amount, false).unwrap(), + Amount::from_nonnegative_i64(tv.amount).unwrap(), )) } else { None From e6663212fff323d2750fdc6cf754da860cad1533 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 8 Aug 2019 09:21:09 +0100 Subject: [PATCH 048/105] Improve documentation for Amount --- .../src/transaction/components/amount.rs | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index d244876..f2d9d0f 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -6,6 +6,17 @@ const MAX_MONEY: i64 = 21_000_000 * COIN; pub const DEFAULT_FEE: Amount = Amount(10000); +/// A type-safe representation of some quantity of Zcash. +/// +/// An Amount can only be constructed from an integer that is within the valid monetary +/// range of `{-MAX_MONEY..MAX_MONEY}` (where `MAX_MONEY` = 21,000,000 × 10⁸ zatoshis). +/// However, this range is not preserved as an invariant internally; it is possible to +/// add two valid Amounts together to obtain an invalid Amount. It is the user's +/// responsibility to handle the result of serializing potentially-invalid Amounts. In +/// particular, a [`Transaction`] containing serialized invalid Amounts will be rejected +/// by the network consensus rules. +/// +/// [`Transaction`]: crate::transaction::Transaction #[derive(Clone, Copy, Debug, PartialEq)] pub struct Amount(i64); @@ -17,7 +28,7 @@ impl Amount { /// Creates an Amount from an i64. /// - /// Returns an error if the amount is out of range. + /// Returns an error if the amount is outside the range `{-MAX_MONEY..MAX_MONEY}`. pub fn from_i64(amount: i64) -> Result { if -MAX_MONEY <= amount && amount <= MAX_MONEY { Ok(Amount(amount)) @@ -28,7 +39,7 @@ impl Amount { /// Creates a non-negative Amount from an i64. /// - /// Returns an error if the amount is out of range. + /// Returns an error if the amount is outside the range `{0..MAX_MONEY}`. pub fn from_nonnegative_i64(amount: i64) -> Result { if 0 <= amount && amount <= MAX_MONEY { Ok(Amount(amount)) @@ -39,7 +50,7 @@ impl Amount { /// Creates an Amount from a u64. /// - /// Returns an error if the amount is out of range. + /// Returns an error if the amount is outside the range `{0..MAX_MONEY}`. pub fn from_u64(amount: u64) -> Result { if amount <= MAX_MONEY as u64 { Ok(Amount(amount as i64)) @@ -50,7 +61,7 @@ impl Amount { /// Reads an Amount from a signed 64-bit little-endian integer. /// - /// Returns an error if the amount is out of range. + /// Returns an error if the amount is outside the range `{-MAX_MONEY..MAX_MONEY}`. pub fn from_i64_le_bytes(bytes: [u8; 8]) -> Result { let amount = i64::from_le_bytes(bytes); Amount::from_i64(amount) @@ -58,7 +69,7 @@ impl Amount { /// Reads a non-negative Amount from a signed 64-bit little-endian integer. /// - /// Returns an error if the amount is out of range. + /// Returns an error if the amount is outside the range `{0..MAX_MONEY}`. pub fn from_nonnegative_i64_le_bytes(bytes: [u8; 8]) -> Result { let amount = i64::from_le_bytes(bytes); Amount::from_nonnegative_i64(amount) @@ -66,7 +77,7 @@ impl Amount { /// Reads an Amount from an unsigned 64-bit little-endian integer. /// - /// Returns an error if the amount is out of range. + /// Returns an error if the amount is outside the range `{0..MAX_MONEY}`. pub fn from_u64_le_bytes(bytes: [u8; 8]) -> Result { let amount = u64::from_le_bytes(bytes); Amount::from_u64(amount) @@ -77,13 +88,13 @@ impl Amount { self.0.to_le_bytes() } - /// Returns `true` if `self` is positive and `false` if the number is zero or + /// Returns `true` if `self` is positive and `false` if the Amount is zero or /// negative. pub const fn is_positive(self) -> bool { self.0.is_positive() } - /// Returns `true` if `self` is negative and `false` if the number is zero or + /// Returns `true` if `self` is negative and `false` if the Amount is zero or /// positive. pub const fn is_negative(self) -> bool { self.0.is_negative() From 3a73f946c58ba914f5c3f1d468f194e67b23a01d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 13 Aug 2019 15:10:57 +0100 Subject: [PATCH 049/105] Simplify structure of transaction builder errors --- zcash_primitives/src/transaction/builder.rs | 57 ++++++++------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index ba07f34..ff9c35f 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -30,17 +30,8 @@ const DEFAULT_TX_EXPIRY_DELTA: u32 = 20; /// with dummy outputs if necessary. See https://github.com/zcash/zcash/issues/3615 const MIN_SHIELDED_OUTPUTS: usize = 2; -#[derive(Debug)] -pub struct Error(ErrorKind); - -impl Error { - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} - #[derive(Debug, PartialEq)] -pub enum ErrorKind { +pub enum Error { AnchorMismatch, BindingSig, ChangeIsNegative(Amount), @@ -76,10 +67,10 @@ impl SaplingOutput { ) -> Result { let g_d = match to.g_d(&JUBJUB) { Some(g_d) => g_d, - None => return Err(Error(ErrorKind::InvalidAddress)), + None => return Err(Error::InvalidAddress), }; if value.is_negative() { - return Err(Error(ErrorKind::InvalidAmount)); + return Err(Error::InvalidAmount); } let rcm = Fs::random(rng); @@ -242,17 +233,16 @@ impl Builder { if let Some(anchor) = self.anchor { let witness_root: Fr = witness.root().into(); if witness_root != anchor { - return Err(Error(ErrorKind::AnchorMismatch)); + return Err(Error::AnchorMismatch); } } else { self.anchor = Some(witness.root().into()) } - let witness = witness.path().ok_or(Error(ErrorKind::InvalidWitness))?; + let witness = witness.path().ok_or(Error::InvalidWitness)?; let alpha = Fs::random(&mut self.rng); - self.mtx.value_balance += - Amount::from_u64(note.value).map_err(|_| Error(ErrorKind::InvalidAmount))?; + self.mtx.value_balance += Amount::from_u64(note.value).map_err(|_| Error::InvalidAmount)?; self.spends.push(SpendDescriptionInfo { extsk, @@ -289,7 +279,7 @@ impl Builder { value: Amount, ) -> Result<(), Error> { if value.is_negative() { - return Err(Error(ErrorKind::InvalidAmount)); + return Err(Error::InvalidAmount); } self.mtx.vout.push(TxOut { @@ -338,7 +328,7 @@ impl Builder { .map(|output| output.value) .sum::(); if change.is_negative() { - return Err(Error(ErrorKind::ChangeIsNegative(change))); + return Err(Error::ChangeIsNegative(change)); } // @@ -359,7 +349,7 @@ impl Builder { }, ) } else { - return Err(Error(ErrorKind::NoChangeAddress)); + return Err(Error::NoChangeAddress); }; self.add_sapling_output(change_address.0, change_address.1, change, None)?; @@ -419,7 +409,7 @@ impl Builder { anchor, spend.witness.clone(), ) - .map_err(|()| Error(ErrorKind::SpendProof))?; + .map_err(|()| Error::SpendProof)?; self.mtx.shielded_spends.push(SpendDescription { cv, @@ -529,7 +519,7 @@ impl Builder { self.mtx.binding_sig = Some( prover .binding_sig(&mut ctx, self.mtx.value_balance, &sighash) - .map_err(|()| Error(ErrorKind::BindingSig))?, + .map_err(|()| Error::BindingSig)?, ); Ok(( @@ -545,7 +535,7 @@ mod tests { use rand::rngs::OsRng; use sapling_crypto::jubjub::fs::Fs; - use super::{Builder, ErrorKind}; + use super::{Builder, Error}; use crate::{ legacy::TransparentAddress, merkle_tree::{CommitmentTree, IncrementalWitness}, @@ -565,7 +555,7 @@ mod tests { let mut builder = Builder::new(0); match builder.add_sapling_output(ovk, to, Amount::from_i64(-1).unwrap(), None) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), + Err(e) => assert_eq!(e, Error::InvalidAmount), Ok(_) => panic!("Should have failed"), } } @@ -577,7 +567,7 @@ mod tests { &TransparentAddress::PublicKey([0; 20]), Amount::from_i64(-1).unwrap(), ) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::InvalidAmount), + Err(e) => assert_eq!(e, Error::InvalidAmount), Ok(_) => panic!("Should have failed"), } } @@ -595,8 +585,8 @@ mod tests { let builder = Builder::new(0); match builder.build(1, MockTxProver) { Err(e) => assert_eq!( - e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-10000).unwrap()) + e, + Error::ChangeIsNegative(Amount::from_i64(-10000).unwrap()) ), Ok(_) => panic!("Should have failed"), } @@ -620,8 +610,8 @@ mod tests { .unwrap(); match builder.build(1, MockTxProver) { Err(e) => assert_eq!( - e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) + e, + Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) ), Ok(_) => panic!("Should have failed"), } @@ -639,8 +629,8 @@ mod tests { .unwrap(); match builder.build(1, MockTxProver) { Err(e) => assert_eq!( - e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) + e, + Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) ), Ok(_) => panic!("Should have failed"), } @@ -681,10 +671,7 @@ mod tests { ) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!( - e.kind(), - &ErrorKind::ChangeIsNegative(Amount::from_i64(-1).unwrap()) - ), + Err(e) => assert_eq!(e, Error::ChangeIsNegative(Amount::from_i64(-1).unwrap())), Ok(_) => panic!("Should have failed"), } } @@ -718,7 +705,7 @@ mod tests { ) .unwrap(); match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e.kind(), &ErrorKind::BindingSig), + Err(e) => assert_eq!(e, Error::BindingSig), Ok(_) => panic!("Should have failed"), } } From 1760b275a7388bbe1e12e126640c2f520b422e92 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 13 Aug 2019 15:24:08 +0100 Subject: [PATCH 050/105] Simplify transaction builder tests Requires impl PartialEq for Transaction, which is implemented as a TxId comparison (relying on the invariant that Transaction is immutable). --- zcash_primitives/src/transaction/builder.rs | 69 +++++++++------------ zcash_primitives/src/transaction/mod.rs | 6 ++ 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index ff9c35f..a3134c3 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -131,6 +131,7 @@ impl SaplingOutput { } /// Metadata about a transaction created by a [`Builder`]. +#[derive(Debug, PartialEq)] pub struct TransactionMetadata { spend_indices: Vec, output_indices: Vec, @@ -554,22 +555,22 @@ mod tests { let to = extfvk.default_address().unwrap().1; let mut builder = Builder::new(0); - match builder.add_sapling_output(ovk, to, Amount::from_i64(-1).unwrap(), None) { - Err(e) => assert_eq!(e, Error::InvalidAmount), - Ok(_) => panic!("Should have failed"), - } + assert_eq!( + builder.add_sapling_output(ovk, to, Amount::from_i64(-1).unwrap(), None), + Err(Error::InvalidAmount) + ); } #[test] fn fails_on_negative_transparent_output() { let mut builder = Builder::new(0); - match builder.add_transparent_output( - &TransparentAddress::PublicKey([0; 20]), - Amount::from_i64(-1).unwrap(), - ) { - Err(e) => assert_eq!(e, Error::InvalidAmount), - Ok(_) => panic!("Should have failed"), - } + assert_eq!( + builder.add_transparent_output( + &TransparentAddress::PublicKey([0; 20]), + Amount::from_i64(-1).unwrap(), + ), + Err(Error::InvalidAmount) + ); } #[test] @@ -583,13 +584,10 @@ mod tests { // 0.0001 t-ZEC fee { let builder = Builder::new(0); - match builder.build(1, MockTxProver) { - Err(e) => assert_eq!( - e, - Error::ChangeIsNegative(Amount::from_i64(-10000).unwrap()) - ), - Ok(_) => panic!("Should have failed"), - } + assert_eq!( + builder.build(1, MockTxProver), + Err(Error::ChangeIsNegative(Amount::from_i64(-10000).unwrap())) + ); } let extfvk = ExtendedFullViewingKey::from(&extsk); @@ -608,13 +606,10 @@ mod tests { None, ) .unwrap(); - match builder.build(1, MockTxProver) { - Err(e) => assert_eq!( - e, - Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) - ), - Ok(_) => panic!("Should have failed"), - } + assert_eq!( + builder.build(1, MockTxProver), + Err(Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap())) + ); } // Fail if there is only a transparent output @@ -627,13 +622,10 @@ mod tests { Amount::from_u64(50000).unwrap(), ) .unwrap(); - match builder.build(1, MockTxProver) { - Err(e) => assert_eq!( - e, - Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap()) - ), - Ok(_) => panic!("Should have failed"), - } + assert_eq!( + builder.build(1, MockTxProver), + Err(Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap())) + ); } let note1 = to @@ -670,10 +662,10 @@ mod tests { Amount::from_u64(20000).unwrap(), ) .unwrap(); - match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e, Error::ChangeIsNegative(Amount::from_i64(-1).unwrap())), - Ok(_) => panic!("Should have failed"), - } + assert_eq!( + builder.build(1, MockTxProver), + Err(Error::ChangeIsNegative(Amount::from_i64(-1).unwrap())) + ); } let note2 = to.create_note(1, Fs::random(&mut rng), &JUBJUB).unwrap(); @@ -704,10 +696,7 @@ mod tests { Amount::from_u64(20000).unwrap(), ) .unwrap(); - match builder.build(1, MockTxProver) { - Err(e) => assert_eq!(e, Error::BindingSig), - Ok(_) => panic!("Should have failed"), - } + assert_eq!(builder.build(1, MockTxProver), Err(Error::BindingSig)) } } } diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index aac0d35..a8ecb17 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -50,6 +50,12 @@ impl Deref for Transaction { } } +impl PartialEq for Transaction { + fn eq(&self, other: &Transaction) -> bool { + self.txid == other.txid + } +} + pub struct TransactionData { pub overwintered: bool, pub version: u32, From a28d94ff2e30897aca6806ff66d0d059f50f706e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 14 Aug 2019 00:16:09 +0100 Subject: [PATCH 051/105] Panic if Amount addition or subtraction overflows --- .../src/transaction/components/amount.rs | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index f2d9d0f..8d358fb 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -117,7 +117,7 @@ impl Add for Amount { type Output = Amount; fn add(self, rhs: Amount) -> Amount { - Amount(self.0 + rhs.0) + Amount::from_i64(self.0 + rhs.0).expect("addition should remain in range") } } @@ -131,7 +131,7 @@ impl Sub for Amount { type Output = Amount; fn sub(self, rhs: Amount) -> Amount { - Amount(self.0 - rhs.0) + Amount::from_i64(self.0 - rhs.0).expect("subtraction should remain in range") } } @@ -201,4 +201,32 @@ mod tests { assert!(Amount::from_nonnegative_i64_le_bytes(neg_max_money_m1.clone()).is_err()); assert!(Amount::from_i64_le_bytes(neg_max_money_m1.clone()).is_err()); } + + #[test] + #[should_panic] + fn add_panics_on_overflow() { + let v = Amount(MAX_MONEY); + let sum = v + Amount(1); + } + + #[test] + #[should_panic] + fn add_assign_panics_on_overflow() { + let mut a = Amount(MAX_MONEY); + a += Amount(1); + } + + #[test] + #[should_panic] + fn sub_panics_on_underflow() { + let v = Amount(-MAX_MONEY); + let diff = v - Amount(1); + } + + #[test] + #[should_panic] + fn sub_assign_panics_on_underflow() { + let mut a = Amount(-MAX_MONEY); + a -= Amount(1); + } } From 4a6c9ec4259931d14bd6be87d53c12850991ebaf Mon Sep 17 00:00:00 2001 From: str4d Date: Wed, 14 Aug 2019 00:30:18 +0100 Subject: [PATCH 052/105] Comment that we support a minimal set of script opcodes Co-Authored-By: Daira Hopwood --- zcash_primitives/src/legacy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_primitives/src/legacy.rs b/zcash_primitives/src/legacy.rs index 02977ab..d1d7c1a 100644 --- a/zcash_primitives/src/legacy.rs +++ b/zcash_primitives/src/legacy.rs @@ -6,7 +6,7 @@ use std::ops::Shl; use crate::serialize::Vector; -/// Script opcodes. +/// Minimal subset of script opcodes. enum OpCode { // push value PushData1 = 0x4c, From 2f1cae62b11e2c1d49e584ffaab99fbf47759734 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 22 Jul 2019 23:51:32 +0100 Subject: [PATCH 053/105] Upgrade to fpe 0.2 --- Cargo.lock | 66 +++++++++++++------------------------ zcash_primitives/Cargo.toml | 4 +-- 2 files changed, 24 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc8644f..ae3cbd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,32 +2,31 @@ # It is not intended for manual editing. [[package]] name = "aes" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aes-soft" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aesni" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -108,10 +107,10 @@ dependencies = [ [[package]] name = "block-cipher-trait" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -122,11 +121,6 @@ dependencies = [ "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "byte-tools" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byte-tools" version = "0.3.0" @@ -222,10 +216,10 @@ dependencies = [ [[package]] name = "fpe" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -369,11 +363,6 @@ dependencies = [ "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "opaque-debug" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "opaque-debug" version = "0.2.2" @@ -512,14 +501,6 @@ name = "spin" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "stream-cipher" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syn" version = "0.14.9" @@ -575,12 +556,12 @@ dependencies = [ name = "zcash_primitives" version = "0.0.0" dependencies = [ - "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", - "fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", @@ -607,9 +588,9 @@ dependencies = [ ] [metadata] -"checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873" -"checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" -"checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" +"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" @@ -618,9 +599,8 @@ dependencies = [ "checksum blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d909f9ef55928e57e7de9638828bc9407233b5cb0904066a7edebbaa9946db2f" "checksum blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa20660ff9f1e6d0a05444b5ebbbae13e4c018d4c66cc78c7e421e3396358a52" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" -"checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" -"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" @@ -632,7 +612,7 @@ dependencies = [ "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" +"checksum fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21988a326139165b75e3196bc6962ca638e5fb0c95102fbf152a3743174b01e4" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" @@ -648,7 +628,6 @@ dependencies = [ "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" @@ -663,7 +642,6 @@ dependencies = [ "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" -"checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 804f8c6..5327905 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -6,12 +6,12 @@ authors = [ ] [dependencies] -aes = "0.2" +aes = "0.3" blake2b_simd = "0.5" byteorder = "1" crypto_api_chachapoly = "0.1" ff = { path = "../ff" } -fpe = "0.1" +fpe = "0.2" hex = "0.3" lazy_static = "1" pairing = { path = "../pairing" } From a12b8053b0f1f97ed537f9b7787cbafd162683ca Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 22 Jul 2019 23:57:24 +0100 Subject: [PATCH 054/105] Upgrade to digest 0.8 --- Cargo.lock | 20 +------------------- sapling-crypto/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae3cbd8..2fb2992 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,14 +163,6 @@ dependencies = [ "crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "digest" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "digest" version = "0.8.0" @@ -240,14 +232,6 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "generic-array" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "generic-array" version = "0.12.0" @@ -476,7 +460,7 @@ dependencies = [ "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", @@ -608,7 +592,6 @@ dependencies = [ "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" "checksum crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9ee35dbace0831b5fe7cb9b43eb029aa14a10f594a115025d4628a2baa63ab" -"checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" @@ -616,7 +599,6 @@ dependencies = [ "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" -"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 0026f6c..c3aedd3 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -18,7 +18,7 @@ blake2b_simd = "0.5" blake2s_simd = "0.5" ff = { path = "../ff" } rand_core = "0.5" -digest = "0.7" +digest = "0.8" byteorder = "1" [dev-dependencies] From ec321382e11b9715344306ab5a3c377279a97fee Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 23 Jul 2019 00:18:53 +0100 Subject: [PATCH 055/105] Upgrade to bech32 0.7 --- Cargo.lock | 6 +++--- zcash_client_backend/Cargo.toml | 2 +- zcash_client_backend/src/encoding.rs | 15 +++++---------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fb2992..60bcbad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,7 +49,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bech32" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -528,7 +528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "zcash_client_backend" version = "0.0.0" dependencies = [ - "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -578,7 +578,7 @@ dependencies = [ "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" +"checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d909f9ef55928e57e7de9638828bc9407233b5cb0904066a7edebbaa9946db2f" "checksum blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa20660ff9f1e6d0a05444b5ebbbae13e4c018d4c66cc78c7e421e3396358a52" diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 1d7848e..31fba49 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -7,7 +7,7 @@ authors = [ edition = "2018" [dependencies] -bech32 = "0.6" +bech32 = "0.7" pairing = { path = "../pairing" } sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } diff --git a/zcash_client_backend/src/encoding.rs b/zcash_client_backend/src/encoding.rs index d816201..0c0a50b 100644 --- a/zcash_client_backend/src/encoding.rs +++ b/zcash_client_backend/src/encoding.rs @@ -3,7 +3,7 @@ //! Human-Readable Prefixes (HRPs) for Bech32 encodings are located in the [`constants`] //! module. -use bech32::{convert_bits, Bech32, Error}; +use bech32::{self, Error, FromBase32, ToBase32}; use pairing::bls12_381::Bls12; use sapling_crypto::{ jubjub::edwards, @@ -21,21 +21,16 @@ where { let mut data: Vec = vec![]; write(&mut data).expect("Should be able to write to a Vec"); - - let converted = - convert_bits(&data, 8, 5, true).expect("Should be able to convert Vec to Vec"); - let encoded = Bech32::new_check_data(hrp.into(), converted).expect("hrp is not empty"); - - encoded.to_string() + bech32::encode(hrp, data.to_base32()).expect("hrp is invalid") } fn bech32_decode(hrp: &str, s: &str, read: F) -> Result, Error> where F: Fn(Vec) -> Option, { - let decoded = s.parse::()?; - if decoded.hrp() == hrp { - convert_bits(decoded.data(), 5, 8, false).map(|data| read(data)) + let (decoded_hrp, data) = bech32::decode(s)?; + if decoded_hrp == hrp { + Vec::::from_base32(&data).map(|data| read(data)) } else { Ok(None) } From 32115363240a97c3d63f29baf6f49112ec48b609 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 23 Jul 2019 00:30:18 +0100 Subject: [PATCH 056/105] Upgrade to crypto_api_chachapoly >= 0.2.1 --- Cargo.lock | 6 +++--- zcash_primitives/Cargo.toml | 2 +- zcash_primitives/src/note_encryption.rs | 21 +++++---------------- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60bcbad..a733501 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,7 +157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crypto_api_chachapoly" -version = "0.1.8" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -543,7 +543,7 @@ dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -591,7 +591,7 @@ dependencies = [ "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" -"checksum crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9ee35dbace0831b5fe7cb9b43eb029aa14a10f594a115025d4628a2baa63ab" +"checksum crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "95b2ad7cab08fd71addba81df5077c49df208effdfb3118a1519f9cdeac5aaf2" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 5327905..ba724be 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -9,7 +9,7 @@ authors = [ aes = "0.3" blake2b_simd = "0.5" byteorder = "1" -crypto_api_chachapoly = "0.1" +crypto_api_chachapoly = "0.2.1" ff = { path = "../ff" } fpe = "0.2" hex = "0.3" diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index 42e1398..d6b66ce 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -444,23 +444,12 @@ pub fn try_sapling_compact_note_decryption( let shared_secret = sapling_ka_agree(ivk, epk); let key = kdf_sapling(shared_secret, &epk); - // Prefix plaintext with 64 zero-bytes to skip over Poly1305 keying output - const CHACHA20_BLOCK_SIZE: usize = 64; - let mut plaintext = [0; CHACHA20_BLOCK_SIZE + COMPACT_NOTE_SIZE]; - plaintext[CHACHA20_BLOCK_SIZE..].copy_from_slice(&enc_ciphertext[0..COMPACT_NOTE_SIZE]); - assert_eq!( - ChaCha20Ietf::cipher() - .decrypt( - &mut plaintext, - CHACHA20_BLOCK_SIZE + COMPACT_NOTE_SIZE, - key.as_bytes(), - &[0u8; 12], - ) - .ok()?, - CHACHA20_BLOCK_SIZE + COMPACT_NOTE_SIZE - ); + // Start from block 1 to skip over Poly1305 keying output + let mut plaintext = [0; COMPACT_NOTE_SIZE]; + plaintext.copy_from_slice(&enc_ciphertext); + ChaCha20Ietf::xor(key.as_bytes(), &[0u8; 12], 1, &mut plaintext); - parse_note_plaintext_without_memo(ivk, cmu, &plaintext[CHACHA20_BLOCK_SIZE..]) + parse_note_plaintext_without_memo(ivk, cmu, &plaintext) } /// Recovery of the full note plaintext by the sender. From 3e35dd215c0c03eed5b0e22f26da2f5ab8a06cde Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 30 Jul 2019 21:04:33 +0100 Subject: [PATCH 057/105] cargo update --- Cargo.lock | 262 ++++++++++++++++++++++++++--------------------------- 1 file changed, 131 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a733501..3ca7b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,8 +16,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -26,7 +26,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -36,15 +36,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -57,13 +57,13 @@ name = "bellman" version = "0.1.0" dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "group 0.1.0", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -76,33 +76,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2b_simd" -version = "0.5.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "blake2s_simd" -version = "0.5.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-buffer" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -110,25 +110,25 @@ name = "block-cipher-trait" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-padding" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "byte-tools" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.2" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -140,6 +140,11 @@ dependencies = [ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cfg-if" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "constant_time_eq" version = "0.1.3" @@ -165,10 +170,10 @@ dependencies = [ [[package]] name = "digest" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -176,7 +181,7 @@ name = "directories" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -189,7 +194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "ff" version = "0.4.0" dependencies = [ - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff_derive 0.3.0", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -198,11 +203,11 @@ dependencies = [ name = "ff_derive" version = "0.3.0" dependencies = [ - "num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -212,15 +217,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures" -version = "0.1.21" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -228,13 +233,13 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "generic-array" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -242,11 +247,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -265,32 +270,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hex-literal-impl" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" -version = "0.2.59" +version = "0.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -298,15 +300,15 @@ name = "librustzcash" version = "0.1.0" dependencies = [ "bellman 0.1.0", - "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", "zcash_proofs 0.0.0", @@ -314,49 +316,53 @@ dependencies = [ [[package]] name = "nodrop" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num-bigint" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "opaque-debug" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pairing" version = "0.14.2" dependencies = [ - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "group 0.1.0", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -370,20 +376,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro-hack" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack-impl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-hack-impl" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.14" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -391,10 +397,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.8" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -402,19 +408,18 @@ name = "rand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -424,7 +429,7 @@ name = "rand_core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -437,10 +442,10 @@ dependencies = [ [[package]] name = "rand_os" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -457,12 +462,12 @@ name = "sapling-crypto" version = "0.0.1" dependencies = [ "bellman 0.1.0", - "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -474,24 +479,19 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "spin" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "syn" version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,8 +541,8 @@ name = "zcash_primitives" version = "0.0.0" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -551,7 +551,7 @@ dependencies = [ "pairing 0.14.2", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -561,12 +561,12 @@ name = "zcash_proofs" version = "0.0.0" dependencies = [ "bellman 0.1.0", - "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", - "rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -576,54 +576,54 @@ dependencies = [ "checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" "checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" "checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" -"checksum blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d909f9ef55928e57e7de9638828bc9407233b5cb0904066a7edebbaa9946db2f" -"checksum blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa20660ff9f1e6d0a05444b5ebbbae13e4c018d4c66cc78c7e421e3396358a52" -"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2" +"checksum blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3a84d2614b18a5367d357331a90fd533d5ceb1e86abc319320df2104ab744c2a" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" -"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" -"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" -"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" "checksum crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "95b2ad7cab08fd71addba81df5077c49df208effdfb3118a1519f9cdeac5aaf2" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21988a326139165b75e3196bc6962ca638e5fb0c95102fbf152a3743174b01e4" -"checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" +"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" -"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" -"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" +"checksum hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc2928beef125e519d69ae1baa8c37ea2e0d3848545217f6db0179c5eb1d639" +"checksum hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "520870c3213943eb8d7803e80180d12a6c7ceb4ae74602544529d1643dc4ddda" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff" -"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eceac7784c5dc97c2d6edf30259b4e153e6e2b42b3c85e9a6e9f45d06caef6e" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)" = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" -"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" -"checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0" -"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" +"checksum proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "463bf29e7f11344e58c9e01f171470ab15c925c6822ad75028cc1c0e1d1eb63b" +"checksum proc-macro-hack-impl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38c47dcb1594802de8c02f3b899e2018c78291168a22c281be21ea0fb4796842" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" -"checksum rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e193067942ef6f485a349a113329140d0ab9e2168ce92274499bb0e9a4190d9d" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_os 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8c83d0434e67e7a92be561af33f3ca17ff9899a4acf28030fabb8c5c323a1a" +"checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967" "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" From 13933d8c51bb1d681c7b471f9be91477e42f5363 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 30 Jul 2019 21:28:27 +0100 Subject: [PATCH 058/105] Use modern clippy linter syntax --- pairing/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index 1c8d90c..7edb180 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -2,12 +2,12 @@ // common mistakes or strange code patterns. If the `cargo-clippy` feature // is provided, all compiler warnings are prohibited. #![cfg_attr(feature = "cargo-clippy", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(inline_always))] -#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] -#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] -#![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))] -#![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))] -#![cfg_attr(feature = "cargo-clippy", allow(write_literal))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::inline_always))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::unreadable_literal))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::many_single_char_names))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::write_literal))] // Force public structures to implement Debug #![deny(missing_debug_implementations)] From 81786c24c05be529fd5890f99c53b56739b95270 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 30 Jul 2019 21:30:59 +0100 Subject: [PATCH 059/105] Fix clippy linter errors in pairing crate --- pairing/src/bls12_381/ec.rs | 4 ++-- pairing/src/bls12_381/fq12.rs | 4 ++-- pairing/src/bls12_381/fq6.rs | 6 +++--- pairing/src/lib.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index b20dea8..fa659bd 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -955,7 +955,7 @@ pub mod g1 { let negyrepr = negy.into_repr(); let p = G1Affine { - x: x, + x, y: if yrepr < negyrepr { y } else { negy }, infinity: false, }; @@ -1637,7 +1637,7 @@ pub mod g2 { negy.negate(); let p = G2Affine { - x: x, + x, y: if y < negy { y } else { negy }, infinity: false, }; diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index f07a337..3c726d2 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -168,8 +168,8 @@ fn test_fq12_mul_by_014() { a.mul_by_014(&c0, &c1, &c5); b.mul_assign(&Fq12 { c0: Fq6 { - c0: c0, - c1: c1, + c0, + c1, c2: Fq2::zero(), }, c1: Fq6 { diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index 87e64cb..dbe58f7 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -343,7 +343,7 @@ fn test_fq6_mul_by_1() { a.mul_by_1(&c1); b.mul_assign(&Fq6 { c0: Fq2::zero(), - c1: c1, + c1, c2: Fq2::zero(), }); @@ -366,8 +366,8 @@ fn test_fq6_mul_by_01() { a.mul_by_01(&c0, &c1); b.mul_assign(&Fq6 { - c0: c0, - c1: c1, + c0, + c1, c2: Fq2::zero(), }); diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index 7edb180..a81d1a1 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -100,7 +100,7 @@ pub trait Engine: ScalarEngine { G2: Into, { Self::final_exponentiation(&Self::miller_loop( - [(&(p.into().prepare()), &(q.into().prepare()))].into_iter(), + [(&(p.into().prepare()), &(q.into().prepare()))].iter(), )).unwrap() } } From 7ea6d10480795f60ade4041963b3f51f1ebc9472 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 4 May 2019 17:47:18 +0100 Subject: [PATCH 060/105] Move redjubjub into zcash_primitives --- Cargo.lock | 1 + librustzcash/src/rustzcash.rs | 2 +- librustzcash/src/tests/signatures.rs | 6 ++---- sapling-crypto/src/lib.rs | 2 -- zcash_primitives/Cargo.toml | 3 +++ zcash_primitives/src/lib.rs | 5 +++++ zcash_primitives/src/prover.rs | 4 ++-- {sapling-crypto => zcash_primitives}/src/redjubjub.rs | 9 +++++---- zcash_primitives/src/sapling.rs | 2 +- zcash_primitives/src/transaction/builder.rs | 2 +- zcash_primitives/src/transaction/components.rs | 6 ++---- zcash_primitives/src/transaction/mod.rs | 2 +- zcash_primitives/src/transaction/tests.rs | 6 ++---- {sapling-crypto => zcash_primitives}/src/util.rs | 3 +-- zcash_proofs/src/prover.rs | 2 +- zcash_proofs/src/sapling/prover.rs | 6 ++++-- zcash_proofs/src/sapling/verifier.rs | 6 ++++-- 17 files changed, 36 insertions(+), 31 deletions(-) rename {sapling-crypto => zcash_primitives}/src/redjubjub.rs (98%) rename {sapling-crypto => zcash_primitives}/src/util.rs (84%) diff --git a/Cargo.lock b/Cargo.lock index 3ca7b39..53bc275 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -552,6 +552,7 @@ dependencies = [ "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 99c3187..bff8093 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -24,7 +24,6 @@ use sapling_crypto::{ fs::{Fs, FsRepr}, FixedGenerators, JubjubEngine, JubjubParams, PrimeOrder, ToUniform, Unknown, }, - redjubjub::{self, Signature}, }; use sapling_crypto::circuit::sapling::TREE_DEPTH as SAPLING_TREE_DEPTH; @@ -62,6 +61,7 @@ use sapling_crypto::primitives::{ProofGenerationKey, ViewingKey}; use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, note_encryption::sapling_ka_agree, + redjubjub::{self, Signature}, sapling::{merkle_hash, spend_sig}, transaction::components::Amount, zip32, JUBJUB, diff --git a/librustzcash/src/tests/signatures.rs b/librustzcash/src/tests/signatures.rs index 2b28437..034b05a 100644 --- a/librustzcash/src/tests/signatures.rs +++ b/librustzcash/src/tests/signatures.rs @@ -1,9 +1,7 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; -use sapling_crypto::{ - jubjub::{FixedGenerators, JubjubEngine}, - redjubjub::{PrivateKey, PublicKey, Signature}, -}; +use sapling_crypto::jubjub::{FixedGenerators, JubjubEngine}; +use zcash_primitives::redjubjub::{PrivateKey, PublicKey, Signature}; use super::JUBJUB; diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index 14e713d..3662629 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -23,5 +23,3 @@ pub mod circuit; pub mod pedersen_hash; pub mod primitives; pub mod constants; -pub mod redjubjub; -pub mod util; diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index ba724be..49b1b7d 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -20,3 +20,6 @@ rand_core = "0.5" rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" + +[dev-dependencies] +rand_xorshift = "0.2" diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index a95d000..771f13d 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -15,6 +15,9 @@ extern crate rand_os; extern crate sapling_crypto; extern crate sha2; +#[cfg(test)] +extern crate rand_xorshift; + use sapling_crypto::jubjub::JubjubBls12; pub mod block; @@ -23,9 +26,11 @@ pub mod legacy; pub mod merkle_tree; pub mod note_encryption; pub mod prover; +pub mod redjubjub; pub mod sapling; mod serialize; pub mod transaction; +mod util; pub mod zip32; #[cfg(test)] diff --git a/zcash_primitives/src/prover.rs b/zcash_primitives/src/prover.rs index 1d40965..a4af8d4 100644 --- a/zcash_primitives/src/prover.rs +++ b/zcash_primitives/src/prover.rs @@ -4,11 +4,11 @@ use pairing::bls12_381::{Bls12, Fr}; use sapling_crypto::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, - redjubjub::{PublicKey, Signature}, }; use crate::{ merkle_tree::CommitmentTreeWitness, + redjubjub::{PublicKey, Signature}, sapling::Node, transaction::components::{Amount, GROTH_PROOF_SIZE}, }; @@ -78,11 +78,11 @@ pub(crate) mod mock { use sapling_crypto::{ jubjub::{edwards, fs::Fs, FixedGenerators, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey, ValueCommitment}, - redjubjub::{PublicKey, Signature}, }; use crate::{ merkle_tree::CommitmentTreeWitness, + redjubjub::{PublicKey, Signature}, sapling::Node, transaction::components::{Amount, GROTH_PROOF_SIZE}, JUBJUB, diff --git a/sapling-crypto/src/redjubjub.rs b/zcash_primitives/src/redjubjub.rs similarity index 98% rename from sapling-crypto/src/redjubjub.rs rename to zcash_primitives/src/redjubjub.rs index cd02347..955c7e3 100644 --- a/sapling-crypto/src/redjubjub.rs +++ b/zcash_primitives/src/redjubjub.rs @@ -3,10 +3,12 @@ use ff::{Field, PrimeField, PrimeFieldRepr}; use rand_core::RngCore; +use sapling_crypto::jubjub::{ + edwards::Point, FixedGenerators, JubjubEngine, JubjubParams, Unknown, +}; use std::io::{self, Read, Write}; -use jubjub::{FixedGenerators, JubjubEngine, JubjubParams, Unknown, edwards::Point}; -use util::{hash_to_scalar}; +use util::hash_to_scalar; fn read_scalar(reader: R) -> io::Result { let mut s_repr = ::Repr::default(); @@ -208,8 +210,7 @@ mod tests { use pairing::bls12_381::Bls12; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; - - use jubjub::{JubjubBls12, fs::Fs, edwards}; + use sapling_crypto::jubjub::{edwards, fs::Fs, JubjubBls12}; use super::*; diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index bd981e6..002cc1a 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -7,11 +7,11 @@ use sapling_crypto::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, pedersen_hash::{pedersen_hash, Personalization}, primitives::Note, - redjubjub::{PrivateKey, PublicKey, Signature}, }; use std::io::{self, Read, Write}; use crate::merkle_tree::Hashable; +use crate::redjubjub::{PrivateKey, PublicKey, Signature}; use JUBJUB; pub(crate) const SAPLING_COMMITMENT_TREE_DEPTH: usize = diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index a3134c3..792582d 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -6,7 +6,6 @@ use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore}; use sapling_crypto::{ jubjub::fs::Fs, primitives::{Diversifier, Note, PaymentAddress}, - redjubjub::PrivateKey, }; use zip32::ExtendedSpendingKey; @@ -16,6 +15,7 @@ use crate::{ merkle_tree::{CommitmentTreeWitness, IncrementalWitness}, note_encryption::{generate_esk, Memo, SaplingNoteEncryption}, prover::TxProver, + redjubjub::PrivateKey, sapling::{spend_sig, Node}, transaction::{ components::{amount::DEFAULT_FEE, Amount, OutputDescription, SpendDescription, TxOut}, diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index d50b4fb..1785344 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -1,13 +1,11 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use sapling_crypto::{ - jubjub::{edwards, Unknown}, - redjubjub::{PublicKey, Signature}, -}; +use sapling_crypto::jubjub::{edwards, Unknown}; use std::io::{self, Read, Write}; use legacy::Script; +use redjubjub::{PublicKey, Signature}; use JUBJUB; pub mod amount; diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index a8ecb17..6e2d15f 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -1,11 +1,11 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use hex; -use sapling_crypto::redjubjub::Signature; use sha2::{Digest, Sha256}; use std::fmt; use std::io::{self, Read, Write}; use std::ops::Deref; +use redjubjub::Signature; use serialize::Vector; pub mod builder; diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 4cd5d72..041ac21 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1,13 +1,11 @@ use ff::Field; use pairing::bls12_381::Bls12; use rand_os::OsRng; -use sapling_crypto::{ - jubjub::{fs::Fs, FixedGenerators}, - redjubjub::PrivateKey, -}; +use sapling_crypto::jubjub::{fs::Fs, FixedGenerators}; use super::{components::Amount, sighash::signature_hash, Transaction, TransactionData}; use legacy::Script; +use redjubjub::PrivateKey; use JUBJUB; #[test] diff --git a/sapling-crypto/src/util.rs b/zcash_primitives/src/util.rs similarity index 84% rename from sapling-crypto/src/util.rs rename to zcash_primitives/src/util.rs index 1e759ba..f46e0a2 100644 --- a/sapling-crypto/src/util.rs +++ b/zcash_primitives/src/util.rs @@ -1,6 +1,5 @@ use blake2b_simd::Params; - -use jubjub::{JubjubEngine, ToUniform}; +use sapling_crypto::jubjub::{JubjubEngine, ToUniform}; pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> E::Fs { let mut hasher = Params::new().hash_length(64).personal(persona).to_state(); diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 4b5b0f4..c59ba62 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -6,12 +6,12 @@ use pairing::bls12_381::{Bls12, Fr}; use sapling_crypto::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, - redjubjub::{PublicKey, Signature}, }; use std::path::Path; use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, prover::TxProver, + redjubjub::{PublicKey, Signature}, sapling::Node, transaction::components::{Amount, GROTH_PROOF_SIZE}, JUBJUB, diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 4b5a5f4..3d30524 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -11,10 +11,12 @@ use sapling_crypto::{ }, jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, - redjubjub::{PrivateKey, PublicKey, Signature}, }; use zcash_primitives::{ - merkle_tree::CommitmentTreeWitness, sapling::Node, transaction::components::Amount, + merkle_tree::CommitmentTreeWitness, + redjubjub::{PrivateKey, PublicKey, Signature}, + sapling::Node, + transaction::components::Amount, }; use super::compute_value_balance; diff --git a/zcash_proofs/src/sapling/verifier.rs b/zcash_proofs/src/sapling/verifier.rs index 47fc9fe..ac4f3f7 100644 --- a/zcash_proofs/src/sapling/verifier.rs +++ b/zcash_proofs/src/sapling/verifier.rs @@ -4,9 +4,11 @@ use pairing::bls12_381::{Bls12, Fr}; use sapling_crypto::{ circuit::multipack, jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}, - redjubjub::{PublicKey, Signature}, }; -use zcash_primitives::transaction::components::Amount; +use zcash_primitives::{ + redjubjub::{PublicKey, Signature}, + transaction::components::Amount, +}; use super::compute_value_balance; From 2ae5804a679aea51128050ab3f5aa94e770fbd98 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 5 Aug 2019 22:45:12 +0100 Subject: [PATCH 061/105] Move Sprout and Sapling circuits into zcash_proofs --- Cargo.lock | 2 + librustzcash/src/rustzcash.rs | 4 +- sapling-crypto/src/circuit/mod.rs | 6 +- zcash_primitives/src/sapling.rs | 3 +- zcash_proofs/Cargo.toml | 4 ++ .../examples/bench.rs | 3 +- zcash_proofs/src/circuit.rs | 2 + .../src/circuit/sapling.rs | 52 ++++++++++-------- .../src/circuit/sprout/commitment.rs | 4 +- .../src/circuit/sprout/input.rs | 4 +- .../src/circuit/sprout/mod.rs | 8 +-- .../src/circuit/sprout/output.rs | 2 +- .../src/circuit/sprout/prfs.rs | 4 +- .../src/circuit/sprout/test_vectors.dat | Bin zcash_proofs/src/lib.rs | 7 +++ zcash_proofs/src/sapling/prover.rs | 6 +- 16 files changed, 63 insertions(+), 48 deletions(-) rename {sapling-crypto => zcash_proofs}/examples/bench.rs (97%) create mode 100644 zcash_proofs/src/circuit.rs rename sapling-crypto/src/circuit/sapling/mod.rs => zcash_proofs/src/circuit/sapling.rs (95%) rename {sapling-crypto => zcash_proofs}/src/circuit/sprout/commitment.rs (92%) rename {sapling-crypto => zcash_proofs}/src/circuit/sprout/input.rs (98%) rename {sapling-crypto => zcash_proofs}/src/circuit/sprout/mod.rs (98%) rename {sapling-crypto => zcash_proofs}/src/circuit/sprout/output.rs (95%) rename {sapling-crypto => zcash_proofs}/src/circuit/sprout/prfs.rs (95%) rename {sapling-crypto => zcash_proofs}/src/circuit/sprout/test_vectors.dat (100%) diff --git a/Cargo.lock b/Cargo.lock index 53bc275..3bc3137 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,7 +567,9 @@ dependencies = [ "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index bff8093..92f8d04 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -26,8 +26,8 @@ use sapling_crypto::{ }, }; -use sapling_crypto::circuit::sapling::TREE_DEPTH as SAPLING_TREE_DEPTH; -use sapling_crypto::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH}; +use zcash_proofs::circuit::sapling::TREE_DEPTH as SAPLING_TREE_DEPTH; +use zcash_proofs::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH}; use bellman::groth16::{ create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, diff --git a/sapling-crypto/src/circuit/mod.rs b/sapling-crypto/src/circuit/mod.rs index fe0fe50..4902f67 100644 --- a/sapling-crypto/src/circuit/mod.rs +++ b/sapling-crypto/src/circuit/mod.rs @@ -1,4 +1,3 @@ -#[cfg(test)] pub mod test; pub mod boolean; @@ -12,9 +11,6 @@ pub mod pedersen_hash; pub mod multipack; pub mod sha256; -pub mod sapling; -pub mod sprout; - use bellman::{ SynthesisError }; @@ -25,7 +21,7 @@ use bellman::{ /// This basically is just an extension to `Option` /// which allows for a convenient mapping to an /// error on `None`. -trait Assignment { +pub trait Assignment { fn get(&self) -> Result<&T, SynthesisError>; } diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 002cc1a..0b94e4e 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -14,8 +14,7 @@ use crate::merkle_tree::Hashable; use crate::redjubjub::{PrivateKey, PublicKey, Signature}; use JUBJUB; -pub(crate) const SAPLING_COMMITMENT_TREE_DEPTH: usize = - sapling_crypto::circuit::sapling::TREE_DEPTH; +pub const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32; /// Compute a parent node in the Sapling commitment tree given its two children. pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr { diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 598e013..fdb0bf8 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -16,6 +16,10 @@ rand_os = "0.2" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } +[dev-dependencies] +rand_core = "0.5" +rand_xorshift = "0.2" + [features] default = ["local-prover"] local-prover = ["directories"] diff --git a/sapling-crypto/examples/bench.rs b/zcash_proofs/examples/bench.rs similarity index 97% rename from sapling-crypto/examples/bench.rs rename to zcash_proofs/examples/bench.rs index e9ffc13..9adf028 100644 --- a/sapling-crypto/examples/bench.rs +++ b/zcash_proofs/examples/bench.rs @@ -4,6 +4,7 @@ extern crate bellman; extern crate pairing; extern crate rand_core; extern crate rand_xorshift; +extern crate zcash_proofs; use ff::Field; use std::time::{Duration, Instant}; @@ -12,7 +13,7 @@ use sapling_crypto::jubjub::{ edwards, fs, }; -use sapling_crypto::circuit::sapling::{ +use zcash_proofs::circuit::sapling::{ Spend }; use sapling_crypto::primitives::{ diff --git a/zcash_proofs/src/circuit.rs b/zcash_proofs/src/circuit.rs new file mode 100644 index 0000000..85fa1cf --- /dev/null +++ b/zcash_proofs/src/circuit.rs @@ -0,0 +1,2 @@ +pub mod sapling; +pub mod sprout; diff --git a/sapling-crypto/src/circuit/sapling/mod.rs b/zcash_proofs/src/circuit/sapling.rs similarity index 95% rename from sapling-crypto/src/circuit/sapling/mod.rs rename to zcash_proofs/src/circuit/sapling.rs index 469ab2e..64bf163 100644 --- a/sapling-crypto/src/circuit/sapling/mod.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -6,28 +6,28 @@ use bellman::{ Circuit }; -use jubjub::{ +use sapling_crypto::jubjub::{ JubjubEngine, FixedGenerators }; -use constants; +use sapling_crypto::constants; -use primitives::{ +use sapling_crypto::primitives::{ ValueCommitment, ProofGenerationKey, PaymentAddress }; -use super::Assignment; -use super::boolean; -use super::ecc; -use super::pedersen_hash; -use super::blake2s; -use super::num; -use super::multipack; +use sapling_crypto::circuit::Assignment; +use sapling_crypto::circuit::boolean; +use sapling_crypto::circuit::ecc; +use sapling_crypto::circuit::pedersen_hash; +use sapling_crypto::circuit::blake2s; +use sapling_crypto::circuit::num; +use sapling_crypto::circuit::multipack; -pub const TREE_DEPTH: usize = 32; +pub const TREE_DEPTH: usize = zcash_primitives::sapling::SAPLING_COMMITMENT_TREE_DEPTH; /// This is an instance of the `Spend` circuit. pub struct Spend<'a, E: JubjubEngine> { @@ -602,9 +602,12 @@ fn test_input_circuit_with_bls12_381() { use pairing::bls12_381::*; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - - use ::circuit::test::*; - use jubjub::{JubjubBls12, fs, edwards}; + use sapling_crypto::{ + circuit::test::*, + jubjub::{JubjubBls12, fs, edwards}, + pedersen_hash, + primitives::{Diversifier, Note, ProofGenerationKey}, + }; let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ @@ -623,7 +626,7 @@ fn test_input_circuit_with_bls12_381() { let nsk = fs::Fs::random(rng); let ak = edwards::Point::rand(rng, params).mul_by_cofactor(params); - let proof_generation_key = ::primitives::ProofGenerationKey { + let proof_generation_key = ProofGenerationKey { ak: ak.clone(), nsk: nsk.clone() }; @@ -636,7 +639,7 @@ fn test_input_circuit_with_bls12_381() { let diversifier = { let mut d = [0; 11]; rng.fill_bytes(&mut d); - ::primitives::Diversifier(d) + Diversifier(d) }; if let Some(p) = viewing_key.into_payment_address( @@ -657,7 +660,7 @@ fn test_input_circuit_with_bls12_381() { { let rk = viewing_key.rk(ar, params).into_xy(); let expected_value_cm = value_commitment.cm(params).into_xy(); - let note = ::primitives::Note { + let note = Note { value: value_commitment.value, g_d: g_d.clone(), pk_d: payment_address.pk_d.clone(), @@ -685,8 +688,8 @@ fn test_input_circuit_with_bls12_381() { lhs.reverse(); rhs.reverse(); - cur = ::pedersen_hash::pedersen_hash::( - ::pedersen_hash::Personalization::MerkleTree(i), + cur = pedersen_hash::pedersen_hash::( + pedersen_hash::Personalization::MerkleTree(i), lhs.into_iter() .take(Fr::NUM_BITS as usize) .chain(rhs.into_iter().take(Fr::NUM_BITS as usize)), @@ -743,8 +746,11 @@ fn test_output_circuit_with_bls12_381() { use pairing::bls12_381::*; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use ::circuit::test::*; - use jubjub::{JubjubBls12, fs, edwards}; + use sapling_crypto::{ + circuit::test::*, + jubjub::{JubjubBls12, fs, edwards}, + primitives::{Diversifier, ProofGenerationKey}, + }; let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ @@ -761,7 +767,7 @@ fn test_output_circuit_with_bls12_381() { let nsk = fs::Fs::random(rng); let ak = edwards::Point::rand(rng, params).mul_by_cofactor(params); - let proof_generation_key = ::primitives::ProofGenerationKey { + let proof_generation_key = ProofGenerationKey { ak: ak.clone(), nsk: nsk.clone() }; @@ -774,7 +780,7 @@ fn test_output_circuit_with_bls12_381() { let diversifier = { let mut d = [0; 11]; rng.fill_bytes(&mut d); - ::primitives::Diversifier(d) + Diversifier(d) }; if let Some(p) = viewing_key.into_payment_address( diff --git a/sapling-crypto/src/circuit/sprout/commitment.rs b/zcash_proofs/src/circuit/sprout/commitment.rs similarity index 92% rename from sapling-crypto/src/circuit/sprout/commitment.rs rename to zcash_proofs/src/circuit/sprout/commitment.rs index a32f05c..4d9f00b 100644 --- a/sapling-crypto/src/circuit/sprout/commitment.rs +++ b/zcash_proofs/src/circuit/sprout/commitment.rs @@ -1,9 +1,9 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use circuit::sha256::{ +use sapling_crypto::circuit::sha256::{ sha256 }; -use circuit::boolean::{ +use sapling_crypto::circuit::boolean::{ Boolean }; diff --git a/sapling-crypto/src/circuit/sprout/input.rs b/zcash_proofs/src/circuit/sprout/input.rs similarity index 98% rename from sapling-crypto/src/circuit/sprout/input.rs rename to zcash_proofs/src/circuit/sprout/input.rs index ce69bc0..e12723a 100644 --- a/sapling-crypto/src/circuit/sprout/input.rs +++ b/zcash_proofs/src/circuit/sprout/input.rs @@ -1,9 +1,9 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use circuit::sha256::{ +use sapling_crypto::circuit::sha256::{ sha256_block_no_padding }; -use circuit::boolean::{ +use sapling_crypto::circuit::boolean::{ AllocatedBit, Boolean }; diff --git a/sapling-crypto/src/circuit/sprout/mod.rs b/zcash_proofs/src/circuit/sprout/mod.rs similarity index 98% rename from sapling-crypto/src/circuit/sprout/mod.rs rename to zcash_proofs/src/circuit/sprout/mod.rs index 7027b4a..db2ea0d 100644 --- a/sapling-crypto/src/circuit/sprout/mod.rs +++ b/zcash_proofs/src/circuit/sprout/mod.rs @@ -1,11 +1,11 @@ use ff::Field; use pairing::Engine; use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination}; -use circuit::boolean::{ +use sapling_crypto::circuit::boolean::{ AllocatedBit, Boolean }; -use circuit::multipack::pack_into_inputs; +use sapling_crypto::circuit::multipack::pack_into_inputs; mod prfs; mod commitment; @@ -355,7 +355,7 @@ fn witness_u252( #[test] fn test_sprout_constraints() { use pairing::bls12_381::{Bls12}; - use ::circuit::test::*; + use sapling_crypto::circuit::test::*; use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; @@ -479,7 +479,7 @@ fn test_sprout_constraints() { expected_inputs.write_u64::(vpub_old.unwrap()).unwrap(); expected_inputs.write_u64::(vpub_new.unwrap()).unwrap(); - use circuit::multipack; + use sapling_crypto::circuit::multipack; let expected_inputs = multipack::bytes_to_bits(&expected_inputs); let expected_inputs = multipack::compute_multipacking::(&expected_inputs); diff --git a/sapling-crypto/src/circuit/sprout/output.rs b/zcash_proofs/src/circuit/sprout/output.rs similarity index 95% rename from sapling-crypto/src/circuit/sprout/output.rs rename to zcash_proofs/src/circuit/sprout/output.rs index 9cdbf52..65bcd49 100644 --- a/sapling-crypto/src/circuit/sprout/output.rs +++ b/zcash_proofs/src/circuit/sprout/output.rs @@ -1,6 +1,6 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use circuit::boolean::{Boolean}; +use sapling_crypto::circuit::boolean::{Boolean}; use super::*; use super::prfs::*; diff --git a/sapling-crypto/src/circuit/sprout/prfs.rs b/zcash_proofs/src/circuit/sprout/prfs.rs similarity index 95% rename from sapling-crypto/src/circuit/sprout/prfs.rs rename to zcash_proofs/src/circuit/sprout/prfs.rs index fff8648..53f65a0 100644 --- a/sapling-crypto/src/circuit/sprout/prfs.rs +++ b/zcash_proofs/src/circuit/sprout/prfs.rs @@ -1,9 +1,9 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use circuit::sha256::{ +use sapling_crypto::circuit::sha256::{ sha256_block_no_padding }; -use circuit::boolean::{ +use sapling_crypto::circuit::boolean::{ Boolean }; diff --git a/sapling-crypto/src/circuit/sprout/test_vectors.dat b/zcash_proofs/src/circuit/sprout/test_vectors.dat similarity index 100% rename from sapling-crypto/src/circuit/sprout/test_vectors.dat rename to zcash_proofs/src/circuit/sprout/test_vectors.dat diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index d2dc877..2a3c8f2 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -10,12 +10,19 @@ extern crate zcash_primitives; #[cfg(feature = "local-prover")] extern crate directories; +#[cfg(test)] +extern crate rand_core; + +#[cfg(test)] +extern crate rand_xorshift; + use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey, VerifyingKey}; use pairing::bls12_381::Bls12; use std::fs::File; use std::io::{self, BufReader}; use std::path::Path; +pub mod circuit; mod hashreader; pub mod sapling; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 3d30524..78958ad 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -5,10 +5,7 @@ use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand_os::OsRng; use sapling_crypto::{ - circuit::{ - multipack, - sapling::{Output, Spend}, - }, + circuit::multipack, jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, }; @@ -20,6 +17,7 @@ use zcash_primitives::{ }; use super::compute_value_balance; +use crate::circuit::sapling::{Output, Spend}; /// A context object for creating the Sapling components of a Zcash transaction. pub struct SaplingProvingContext { From 61c633db1e3098071d4b9167874686a711501649 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 6 Aug 2019 00:48:36 +0100 Subject: [PATCH 062/105] Move Jubjub and Pedersen hash gadgets into zcash_proofs These are currently too Zcash-specific to be generalized, and need some targeted refactoring. --- sapling-crypto/src/circuit/mod.rs | 2 -- zcash_proofs/src/circuit.rs | 3 ++ .../src/circuit/ecc.rs | 19 +++++++------ .../src/circuit/pedersen_hash.rs | 28 +++++++++---------- zcash_proofs/src/circuit/sapling.rs | 4 +-- 5 files changed, 28 insertions(+), 28 deletions(-) rename {sapling-crypto => zcash_proofs}/src/circuit/ecc.rs (99%) rename {sapling-crypto => zcash_proofs}/src/circuit/pedersen_hash.rs (90%) diff --git a/sapling-crypto/src/circuit/mod.rs b/sapling-crypto/src/circuit/mod.rs index 4902f67..016f33e 100644 --- a/sapling-crypto/src/circuit/mod.rs +++ b/sapling-crypto/src/circuit/mod.rs @@ -6,8 +6,6 @@ pub mod uint32; pub mod blake2s; pub mod num; pub mod lookup; -pub mod ecc; -pub mod pedersen_hash; pub mod multipack; pub mod sha256; diff --git a/zcash_proofs/src/circuit.rs b/zcash_proofs/src/circuit.rs index 85fa1cf..ac7e74c 100644 --- a/zcash_proofs/src/circuit.rs +++ b/zcash_proofs/src/circuit.rs @@ -1,2 +1,5 @@ +pub mod ecc; +pub mod pedersen_hash; + pub mod sapling; pub mod sprout; diff --git a/sapling-crypto/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs similarity index 99% rename from sapling-crypto/src/circuit/ecc.rs rename to zcash_proofs/src/circuit/ecc.rs index 9b4dbbc..e6cba96 100644 --- a/sapling-crypto/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -6,27 +6,27 @@ use bellman::{ ConstraintSystem }; -use super::{ +use sapling_crypto::circuit::{ Assignment }; -use super::num::{ +use sapling_crypto::circuit::num::{ AllocatedNum, Num }; -use ::jubjub::{ +use sapling_crypto::jubjub::{ edwards, JubjubEngine, JubjubParams, FixedGenerators }; -use super::lookup::{ +use sapling_crypto::circuit::lookup::{ lookup3_xy }; -use super::boolean::Boolean; +use sapling_crypto::circuit::boolean::Boolean; #[derive(Clone)] pub struct EdwardsPoint { @@ -753,22 +753,23 @@ mod test { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use ::circuit::test::*; - use ::jubjub::{ + use sapling_crypto::circuit::test::*; + use sapling_crypto::jubjub::{ montgomery, edwards, JubjubBls12, JubjubParams, FixedGenerators }; - use ::jubjub::fs::Fs; + use sapling_crypto::jubjub::fs::Fs; + use super::{ MontgomeryPoint, EdwardsPoint, AllocatedNum, fixed_base_multiplication }; - use super::super::boolean::{ + use sapling_crypto::circuit::boolean::{ Boolean, AllocatedBit }; diff --git a/sapling-crypto/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs similarity index 90% rename from sapling-crypto/src/circuit/pedersen_hash.rs rename to zcash_proofs/src/circuit/pedersen_hash.rs index dd000d3..bbaf999 100644 --- a/sapling-crypto/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -1,23 +1,20 @@ -use super::*; use super::ecc::{ MontgomeryPoint, EdwardsPoint }; -use super::boolean::Boolean; -use ::jubjub::*; +use sapling_crypto::circuit::boolean::Boolean; +use sapling_crypto::jubjub::*; use bellman::{ - ConstraintSystem + ConstraintSystem, SynthesisError }; -use super::lookup::*; -pub use pedersen_hash::Personalization; +use sapling_crypto::circuit::lookup::*; +pub use sapling_crypto::pedersen_hash::Personalization; -impl Personalization { - fn get_constant_bools(&self) -> Vec { - self.get_bits() +fn get_constant_bools(person: &Personalization) -> Vec { + person.get_bits() .into_iter() .map(|e| Boolean::constant(e)) .collect() - } } pub fn pedersen_hash( @@ -28,7 +25,7 @@ pub fn pedersen_hash( ) -> Result, SynthesisError> where CS: ConstraintSystem { - let personalization = personalization.get_constant_bools(); + let personalization = get_constant_bools(&personalization); assert_eq!(personalization.len(), 6); let mut edwards_result = None; @@ -113,8 +110,9 @@ pub fn pedersen_hash( #[cfg(test)] mod test { use super::*; - use ::circuit::test::*; - use ::circuit::boolean::{Boolean, AllocatedBit}; + use sapling_crypto::circuit::test::*; + use sapling_crypto::circuit::boolean::{Boolean, AllocatedBit}; + use sapling_crypto::pedersen_hash; use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; @@ -177,7 +175,7 @@ mod test { assert!(cs.is_satisfied()); - let expected = ::pedersen_hash::pedersen_hash::( + let expected = pedersen_hash::pedersen_hash::( Personalization::MerkleTree(1), input.clone().into_iter(), params @@ -187,7 +185,7 @@ mod test { assert_eq!(res.get_y().get_value().unwrap(), expected.1); // Test against the output of a different personalization - let unexpected = ::pedersen_hash::pedersen_hash::( + let unexpected = pedersen_hash::pedersen_hash::( Personalization::MerkleTree(0), input.into_iter(), params diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index 64bf163..1fc6e6c 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -21,8 +21,8 @@ use sapling_crypto::primitives::{ use sapling_crypto::circuit::Assignment; use sapling_crypto::circuit::boolean; -use sapling_crypto::circuit::ecc; -use sapling_crypto::circuit::pedersen_hash; +use super::ecc; +use super::pedersen_hash; use sapling_crypto::circuit::blake2s; use sapling_crypto::circuit::num; use sapling_crypto::circuit::multipack; From b8af749b4019da2cb1b85d797f9b7b10f5f13e4b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 6 Aug 2019 01:13:35 +0100 Subject: [PATCH 063/105] Move generic circuit gadgets into bellman --- Cargo.lock | 4 ++++ bellman/Cargo.toml | 4 ++++ .../src/circuit/mod.rs => bellman/src/gadgets.rs | 2 +- .../src/circuit => bellman/src/gadgets}/blake2s.rs | 8 ++++---- .../src/circuit => bellman/src/gadgets}/boolean.rs | 6 +++--- .../src/circuit => bellman/src/gadgets}/lookup.rs | 6 +++--- .../src/circuit => bellman/src/gadgets}/multieq.rs | 2 +- .../circuit => bellman/src/gadgets}/multipack.rs | 6 +++--- .../src/circuit => bellman/src/gadgets}/num.rs | 6 +++--- .../src/circuit => bellman/src/gadgets}/sha256.rs | 6 +++--- .../circuit => bellman/src/gadgets}/test/mod.rs | 2 +- .../src/circuit => bellman/src/gadgets}/uint32.rs | 10 +++++----- bellman/src/lib.rs | 12 ++++++++++++ librustzcash/src/rustzcash.rs | 2 +- sapling-crypto/src/lib.rs | 1 - zcash_proofs/src/circuit/ecc.rs | 12 ++++++------ zcash_proofs/src/circuit/pedersen_hash.rs | 8 ++++---- zcash_proofs/src/circuit/sapling.rs | 14 +++++++------- zcash_proofs/src/circuit/sprout/commitment.rs | 4 ++-- zcash_proofs/src/circuit/sprout/input.rs | 4 ++-- zcash_proofs/src/circuit/sprout/mod.rs | 8 ++++---- zcash_proofs/src/circuit/sprout/output.rs | 2 +- zcash_proofs/src/circuit/sprout/prfs.rs | 4 ++-- zcash_proofs/src/sapling/prover.rs | 8 +++++--- zcash_proofs/src/sapling/verifier.rs | 10 +++++----- 25 files changed, 86 insertions(+), 65 deletions(-) rename sapling-crypto/src/circuit/mod.rs => bellman/src/gadgets.rs (97%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/blake2s.rs (99%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/boolean.rs (99%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/lookup.rs (98%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/multieq.rs (99%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/multipack.rs (96%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/num.rs (99%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/sha256.rs (98%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/test/mod.rs (99%) rename {sapling-crypto/src/circuit => bellman/src/gadgets}/uint32.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index 3bc3137..670966e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,16 +57,20 @@ name = "bellman" version = "0.1.0" dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "group 0.1.0", + "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index b15671e..70521e7 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -10,6 +10,7 @@ version = "0.1.0" [dependencies] bit-vec = "0.4.4" +blake2s_simd = "0.5" ff = { path = "../ff" } futures = "0.1" futures-cpupool = { version = "0.1", optional = true } @@ -21,7 +22,10 @@ rand_core = "0.5" byteorder = "1" [dev-dependencies] +hex-literal = "0.1" rand = "0.7" +rand_xorshift = "0.2" +sha2 = "0.8" [features] groth16 = ["pairing"] diff --git a/sapling-crypto/src/circuit/mod.rs b/bellman/src/gadgets.rs similarity index 97% rename from sapling-crypto/src/circuit/mod.rs rename to bellman/src/gadgets.rs index 016f33e..6c4b09c 100644 --- a/sapling-crypto/src/circuit/mod.rs +++ b/bellman/src/gadgets.rs @@ -9,7 +9,7 @@ pub mod lookup; pub mod multipack; pub mod sha256; -use bellman::{ +use crate::{ SynthesisError }; diff --git a/sapling-crypto/src/circuit/blake2s.rs b/bellman/src/gadgets/blake2s.rs similarity index 99% rename from sapling-crypto/src/circuit/blake2s.rs rename to bellman/src/gadgets/blake2s.rs index 8627dc0..cef50eb 100644 --- a/sapling-crypto/src/circuit/blake2s.rs +++ b/bellman/src/gadgets/blake2s.rs @@ -2,7 +2,7 @@ use pairing::{ Engine, }; -use bellman::{ +use crate::{ SynthesisError, ConstraintSystem }; @@ -325,10 +325,10 @@ mod test { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use ::circuit::boolean::{Boolean, AllocatedBit}; - use ::circuit::test::TestConstraintSystem; + use crate::gadgets::boolean::{Boolean, AllocatedBit}; + use crate::gadgets::test::TestConstraintSystem; use super::blake2s; - use bellman::{ConstraintSystem}; + use crate::{ConstraintSystem}; #[test] fn test_blank_hash() { diff --git a/sapling-crypto/src/circuit/boolean.rs b/bellman/src/gadgets/boolean.rs similarity index 99% rename from sapling-crypto/src/circuit/boolean.rs rename to bellman/src/gadgets/boolean.rs index 2fe6ef1..f6c11b6 100644 --- a/sapling-crypto/src/circuit/boolean.rs +++ b/bellman/src/gadgets/boolean.rs @@ -1,7 +1,7 @@ use ff::{BitIterator, Field, PrimeField}; use pairing::Engine; -use bellman::{ +use crate::{ ConstraintSystem, SynthesisError, LinearCombination, @@ -801,10 +801,10 @@ impl From for Boolean { #[cfg(test)] mod test { - use bellman::{ConstraintSystem}; + use crate::{ConstraintSystem}; use ff::{Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; - use ::circuit::test::*; + use crate::gadgets::test::*; use super::{ AllocatedBit, Boolean, diff --git a/sapling-crypto/src/circuit/lookup.rs b/bellman/src/gadgets/lookup.rs similarity index 98% rename from sapling-crypto/src/circuit/lookup.rs rename to bellman/src/gadgets/lookup.rs index d57f17c..86ab10f 100644 --- a/sapling-crypto/src/circuit/lookup.rs +++ b/bellman/src/gadgets/lookup.rs @@ -7,7 +7,7 @@ use super::num::{ Num }; use super::boolean::Boolean; -use bellman::{ +use crate::{ ConstraintSystem }; @@ -197,8 +197,8 @@ pub fn lookup3_xy_with_conditional_negation( #[cfg(test)] mod test { use super::*; - use ::circuit::test::*; - use ::circuit::boolean::{Boolean, AllocatedBit}; + use crate::gadgets::test::*; + use crate::gadgets::boolean::{Boolean, AllocatedBit}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; diff --git a/sapling-crypto/src/circuit/multieq.rs b/bellman/src/gadgets/multieq.rs similarity index 99% rename from sapling-crypto/src/circuit/multieq.rs rename to bellman/src/gadgets/multieq.rs index 4cfc3b8..b1dfd7c 100644 --- a/sapling-crypto/src/circuit/multieq.rs +++ b/bellman/src/gadgets/multieq.rs @@ -1,7 +1,7 @@ use ff::{Field, PrimeField}; use pairing::Engine; -use bellman::{ +use crate::{ SynthesisError, ConstraintSystem, LinearCombination, diff --git a/sapling-crypto/src/circuit/multipack.rs b/bellman/src/gadgets/multipack.rs similarity index 96% rename from sapling-crypto/src/circuit/multipack.rs rename to bellman/src/gadgets/multipack.rs index fdecd34..b9b5877 100644 --- a/sapling-crypto/src/circuit/multipack.rs +++ b/bellman/src/gadgets/multipack.rs @@ -1,6 +1,6 @@ use ff::{Field, PrimeField}; use pairing::Engine; -use bellman::{ConstraintSystem, SynthesisError}; +use crate::{ConstraintSystem, SynthesisError}; use super::boolean::{Boolean}; use super::num::Num; use super::Assignment; @@ -80,12 +80,12 @@ pub fn compute_multipacking( #[test] fn test_multipacking() { - use bellman::{ConstraintSystem}; + use crate::{ConstraintSystem}; use pairing::bls12_381::{Bls12}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use ::circuit::test::*; + use crate::gadgets::test::*; use super::boolean::{AllocatedBit, Boolean}; let mut rng = XorShiftRng::from_seed([ diff --git a/sapling-crypto/src/circuit/num.rs b/bellman/src/gadgets/num.rs similarity index 99% rename from sapling-crypto/src/circuit/num.rs rename to bellman/src/gadgets/num.rs index 1cdfe22..077301f 100644 --- a/sapling-crypto/src/circuit/num.rs +++ b/bellman/src/gadgets/num.rs @@ -1,7 +1,7 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr}; use pairing::Engine; -use bellman::{ +use crate::{ SynthesisError, ConstraintSystem, LinearCombination, @@ -455,13 +455,13 @@ impl Num { #[cfg(test)] mod test { - use bellman::{ConstraintSystem}; + use crate::{ConstraintSystem}; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; - use ::circuit::test::*; + use crate::gadgets::test::*; use super::{AllocatedNum, Boolean}; #[test] diff --git a/sapling-crypto/src/circuit/sha256.rs b/bellman/src/gadgets/sha256.rs similarity index 98% rename from sapling-crypto/src/circuit/sha256.rs rename to bellman/src/gadgets/sha256.rs index 3b32282..2e4669e 100644 --- a/sapling-crypto/src/circuit/sha256.rs +++ b/bellman/src/gadgets/sha256.rs @@ -1,7 +1,7 @@ use super::uint32::UInt32; use super::multieq::MultiEq; use super::boolean::Boolean; -use bellman::{ConstraintSystem, SynthesisError}; +use crate::{ConstraintSystem, SynthesisError}; use pairing::Engine; const ROUND_CONSTANTS: [u32; 64] = [ @@ -305,9 +305,9 @@ fn sha256_compression_function( #[cfg(test)] mod test { use super::*; - use circuit::boolean::AllocatedBit; + use crate::gadgets::boolean::AllocatedBit; use pairing::bls12_381::Bls12; - use circuit::test::TestConstraintSystem; + use crate::gadgets::test::TestConstraintSystem; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; diff --git a/sapling-crypto/src/circuit/test/mod.rs b/bellman/src/gadgets/test/mod.rs similarity index 99% rename from sapling-crypto/src/circuit/test/mod.rs rename to bellman/src/gadgets/test/mod.rs index 79d128a..dc6adbf 100644 --- a/sapling-crypto/src/circuit/test/mod.rs +++ b/bellman/src/gadgets/test/mod.rs @@ -1,7 +1,7 @@ use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::Engine; -use bellman::{ +use crate::{ LinearCombination, SynthesisError, ConstraintSystem, diff --git a/sapling-crypto/src/circuit/uint32.rs b/bellman/src/gadgets/uint32.rs similarity index 99% rename from sapling-crypto/src/circuit/uint32.rs rename to bellman/src/gadgets/uint32.rs index 939b544..90f8d7e 100644 --- a/sapling-crypto/src/circuit/uint32.rs +++ b/bellman/src/gadgets/uint32.rs @@ -1,7 +1,7 @@ use ff::{Field, PrimeField}; use pairing::Engine; -use bellman::{ +use crate::{ SynthesisError, ConstraintSystem, LinearCombination @@ -409,13 +409,13 @@ impl UInt32 { #[cfg(test)] mod test { - use ::circuit::boolean::{Boolean}; + use crate::gadgets::boolean::{Boolean}; use super::{UInt32}; use ff::Field; use pairing::bls12_381::{Bls12}; - use ::circuit::test::*; - use bellman::{ConstraintSystem}; - use circuit::multieq::MultiEq; + use crate::gadgets::test::*; + use crate::{ConstraintSystem}; + use crate::gadgets::multieq::MultiEq; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; diff --git a/bellman/src/lib.rs b/bellman/src/lib.rs index bf9a4e1..ee6bb88 100644 --- a/bellman/src/lib.rs +++ b/bellman/src/lib.rs @@ -6,6 +6,7 @@ extern crate rand_core; extern crate futures; extern crate bit_vec; +extern crate blake2s_simd; extern crate byteorder; #[cfg(feature = "multicore")] @@ -15,9 +16,20 @@ extern crate futures_cpupool; #[cfg(feature = "multicore")] extern crate num_cpus; +#[cfg(test)] +#[macro_use] +extern crate hex_literal; + #[cfg(test)] extern crate rand; +#[cfg(test)] +extern crate rand_xorshift; + +#[cfg(test)] +extern crate sha2; + +pub mod gadgets; pub mod multicore; mod multiexp; pub mod domain; diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 92f8d04..a05d8ef 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -17,7 +17,6 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::{ - circuit::multipack, constants::CRH_IVK_PERSONALIZATION, jubjub::{ edwards, @@ -29,6 +28,7 @@ use sapling_crypto::{ use zcash_proofs::circuit::sapling::TREE_DEPTH as SAPLING_TREE_DEPTH; use zcash_proofs::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH}; +use bellman::gadgets::multipack; use bellman::groth16::{ create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, }; diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index 3662629..4e944e0 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -19,7 +19,6 @@ extern crate sha2; pub mod jubjub; pub mod group_hash; -pub mod circuit; pub mod pedersen_hash; pub mod primitives; pub mod constants; diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index e6cba96..cb11eb6 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -6,11 +6,11 @@ use bellman::{ ConstraintSystem }; -use sapling_crypto::circuit::{ +use bellman::gadgets::{ Assignment }; -use sapling_crypto::circuit::num::{ +use bellman::gadgets::num::{ AllocatedNum, Num }; @@ -22,11 +22,11 @@ use sapling_crypto::jubjub::{ FixedGenerators }; -use sapling_crypto::circuit::lookup::{ +use bellman::gadgets::lookup::{ lookup3_xy }; -use sapling_crypto::circuit::boolean::Boolean; +use bellman::gadgets::boolean::Boolean; #[derive(Clone)] pub struct EdwardsPoint { @@ -753,7 +753,7 @@ mod test { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use sapling_crypto::circuit::test::*; + use bellman::gadgets::test::*; use sapling_crypto::jubjub::{ montgomery, edwards, @@ -769,7 +769,7 @@ mod test { AllocatedNum, fixed_base_multiplication }; - use sapling_crypto::circuit::boolean::{ + use bellman::gadgets::boolean::{ Boolean, AllocatedBit }; diff --git a/zcash_proofs/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs index bbaf999..30a948f 100644 --- a/zcash_proofs/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -2,12 +2,12 @@ use super::ecc::{ MontgomeryPoint, EdwardsPoint }; -use sapling_crypto::circuit::boolean::Boolean; +use bellman::gadgets::boolean::Boolean; use sapling_crypto::jubjub::*; use bellman::{ ConstraintSystem, SynthesisError }; -use sapling_crypto::circuit::lookup::*; +use bellman::gadgets::lookup::*; pub use sapling_crypto::pedersen_hash::Personalization; fn get_constant_bools(person: &Personalization) -> Vec { @@ -110,8 +110,8 @@ pub fn pedersen_hash( #[cfg(test)] mod test { use super::*; - use sapling_crypto::circuit::test::*; - use sapling_crypto::circuit::boolean::{Boolean, AllocatedBit}; + use bellman::gadgets::test::*; + use bellman::gadgets::boolean::{Boolean, AllocatedBit}; use sapling_crypto::pedersen_hash; use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index 1fc6e6c..e381240 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -19,13 +19,13 @@ use sapling_crypto::primitives::{ PaymentAddress }; -use sapling_crypto::circuit::Assignment; -use sapling_crypto::circuit::boolean; +use bellman::gadgets::Assignment; +use bellman::gadgets::boolean; use super::ecc; use super::pedersen_hash; -use sapling_crypto::circuit::blake2s; -use sapling_crypto::circuit::num; -use sapling_crypto::circuit::multipack; +use bellman::gadgets::blake2s; +use bellman::gadgets::num; +use bellman::gadgets::multipack; pub const TREE_DEPTH: usize = zcash_primitives::sapling::SAPLING_COMMITMENT_TREE_DEPTH; @@ -598,12 +598,12 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { #[test] fn test_input_circuit_with_bls12_381() { + use bellman::gadgets::test::*; use ff::{BitIterator, Field}; use pairing::bls12_381::*; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use sapling_crypto::{ - circuit::test::*, jubjub::{JubjubBls12, fs, edwards}, pedersen_hash, primitives::{Diversifier, Note, ProofGenerationKey}, @@ -742,12 +742,12 @@ fn test_input_circuit_with_bls12_381() { #[test] fn test_output_circuit_with_bls12_381() { + use bellman::gadgets::test::*; use ff::Field; use pairing::bls12_381::*; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use sapling_crypto::{ - circuit::test::*, jubjub::{JubjubBls12, fs, edwards}, primitives::{Diversifier, ProofGenerationKey}, }; diff --git a/zcash_proofs/src/circuit/sprout/commitment.rs b/zcash_proofs/src/circuit/sprout/commitment.rs index 4d9f00b..ba889a3 100644 --- a/zcash_proofs/src/circuit/sprout/commitment.rs +++ b/zcash_proofs/src/circuit/sprout/commitment.rs @@ -1,9 +1,9 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use sapling_crypto::circuit::sha256::{ +use bellman::gadgets::sha256::{ sha256 }; -use sapling_crypto::circuit::boolean::{ +use bellman::gadgets::boolean::{ Boolean }; diff --git a/zcash_proofs/src/circuit/sprout/input.rs b/zcash_proofs/src/circuit/sprout/input.rs index e12723a..a84e3a6 100644 --- a/zcash_proofs/src/circuit/sprout/input.rs +++ b/zcash_proofs/src/circuit/sprout/input.rs @@ -1,9 +1,9 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use sapling_crypto::circuit::sha256::{ +use bellman::gadgets::sha256::{ sha256_block_no_padding }; -use sapling_crypto::circuit::boolean::{ +use bellman::gadgets::boolean::{ AllocatedBit, Boolean }; diff --git a/zcash_proofs/src/circuit/sprout/mod.rs b/zcash_proofs/src/circuit/sprout/mod.rs index db2ea0d..c28b8d7 100644 --- a/zcash_proofs/src/circuit/sprout/mod.rs +++ b/zcash_proofs/src/circuit/sprout/mod.rs @@ -1,11 +1,11 @@ use ff::Field; use pairing::Engine; use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination}; -use sapling_crypto::circuit::boolean::{ +use bellman::gadgets::boolean::{ AllocatedBit, Boolean }; -use sapling_crypto::circuit::multipack::pack_into_inputs; +use bellman::gadgets::multipack::pack_into_inputs; mod prfs; mod commitment; @@ -355,7 +355,7 @@ fn witness_u252( #[test] fn test_sprout_constraints() { use pairing::bls12_381::{Bls12}; - use sapling_crypto::circuit::test::*; + use bellman::gadgets::test::*; use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; @@ -479,7 +479,7 @@ fn test_sprout_constraints() { expected_inputs.write_u64::(vpub_old.unwrap()).unwrap(); expected_inputs.write_u64::(vpub_new.unwrap()).unwrap(); - use sapling_crypto::circuit::multipack; + use bellman::gadgets::multipack; let expected_inputs = multipack::bytes_to_bits(&expected_inputs); let expected_inputs = multipack::compute_multipacking::(&expected_inputs); diff --git a/zcash_proofs/src/circuit/sprout/output.rs b/zcash_proofs/src/circuit/sprout/output.rs index 65bcd49..f2e504a 100644 --- a/zcash_proofs/src/circuit/sprout/output.rs +++ b/zcash_proofs/src/circuit/sprout/output.rs @@ -1,6 +1,6 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use sapling_crypto::circuit::boolean::{Boolean}; +use bellman::gadgets::boolean::{Boolean}; use super::*; use super::prfs::*; diff --git a/zcash_proofs/src/circuit/sprout/prfs.rs b/zcash_proofs/src/circuit/sprout/prfs.rs index 53f65a0..0b3e42c 100644 --- a/zcash_proofs/src/circuit/sprout/prfs.rs +++ b/zcash_proofs/src/circuit/sprout/prfs.rs @@ -1,9 +1,9 @@ use pairing::{Engine}; use bellman::{ConstraintSystem, SynthesisError}; -use sapling_crypto::circuit::sha256::{ +use bellman::gadgets::sha256::{ sha256_block_no_padding }; -use sapling_crypto::circuit::boolean::{ +use bellman::gadgets::boolean::{ Boolean }; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 78958ad..7ca8bce 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -1,11 +1,13 @@ -use bellman::groth16::{ - create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, +use bellman::{ + gadgets::multipack, + groth16::{ + create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, + }, }; use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand_os::OsRng; use sapling_crypto::{ - circuit::multipack, jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, }; diff --git a/zcash_proofs/src/sapling/verifier.rs b/zcash_proofs/src/sapling/verifier.rs index ac4f3f7..01cba0c 100644 --- a/zcash_proofs/src/sapling/verifier.rs +++ b/zcash_proofs/src/sapling/verifier.rs @@ -1,10 +1,10 @@ -use bellman::groth16::{verify_proof, PreparedVerifyingKey, Proof}; +use bellman::{ + gadgets::multipack, + groth16::{verify_proof, PreparedVerifyingKey, Proof}, +}; use ff::Field; use pairing::bls12_381::{Bls12, Fr}; -use sapling_crypto::{ - circuit::multipack, - jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}, -}; +use sapling_crypto::jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}; use zcash_primitives::{ redjubjub::{PublicKey, Signature}, transaction::components::Amount, From 5fb9b86ba01df08179ee1c297e158ddfdcb28557 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 6 Aug 2019 10:46:40 +0100 Subject: [PATCH 064/105] Move Jubjub, Pedersen hash and primitives into zcash_primitives --- Cargo.lock | 8 +++--- librustzcash/Cargo.toml | 1 - librustzcash/src/rustzcash.rs | 27 ++++++++++--------- librustzcash/src/tests/key_agreement.rs | 4 +-- librustzcash/src/tests/key_components.rs | 2 +- librustzcash/src/tests/mod.rs | 2 +- librustzcash/src/tests/signatures.rs | 2 +- sapling-crypto/src/lib.rs | 6 ----- zcash_client_backend/Cargo.toml | 1 - zcash_client_backend/src/encoding.rs | 24 ++++++++--------- zcash_primitives/Cargo.toml | 3 ++- .../benches/pedersen_hash.rs | 16 ++++++----- .../src/constants.rs | 0 .../src/group_hash.rs | 0 .../src/jubjub/edwards.rs | 0 .../src/jubjub/fs.rs | 0 .../src/jubjub/mod.rs | 0 .../src/jubjub/montgomery.rs | 0 .../src/jubjub/tests.rs | 0 zcash_primitives/src/keys.rs | 4 +-- zcash_primitives/src/lib.rs | 15 ++++++++--- zcash_primitives/src/note_encryption.rs | 12 ++++----- .../src/pedersen_hash.rs | 0 .../src/primitives.rs | 0 zcash_primitives/src/prover.rs | 5 ++-- zcash_primitives/src/redjubjub.rs | 5 ++-- zcash_primitives/src/sapling.rs | 2 +- zcash_primitives/src/transaction/builder.rs | 5 ++-- .../src/transaction/components.rs | 2 +- zcash_primitives/src/transaction/tests.rs | 3 ++- zcash_primitives/src/util.rs | 3 ++- zcash_primitives/src/zip32.rs | 3 ++- zcash_proofs/Cargo.toml | 1 - zcash_proofs/examples/bench.rs | 6 ++--- zcash_proofs/src/circuit/ecc.rs | 6 ++--- zcash_proofs/src/circuit/pedersen_hash.rs | 6 ++--- zcash_proofs/src/circuit/sapling.rs | 10 +++---- zcash_proofs/src/lib.rs | 1 - zcash_proofs/src/prover.rs | 2 +- zcash_proofs/src/sapling/mod.rs | 2 +- zcash_proofs/src/sapling/prover.rs | 2 +- zcash_proofs/src/sapling/verifier.rs | 2 +- 42 files changed, 99 insertions(+), 94 deletions(-) rename {sapling-crypto => zcash_primitives}/benches/pedersen_hash.rs (50%) rename {sapling-crypto => zcash_primitives}/src/constants.rs (100%) rename {sapling-crypto => zcash_primitives}/src/group_hash.rs (100%) rename {sapling-crypto => zcash_primitives}/src/jubjub/edwards.rs (100%) rename {sapling-crypto => zcash_primitives}/src/jubjub/fs.rs (100%) rename {sapling-crypto => zcash_primitives}/src/jubjub/mod.rs (100%) rename {sapling-crypto => zcash_primitives}/src/jubjub/montgomery.rs (100%) rename {sapling-crypto => zcash_primitives}/src/jubjub/tests.rs (100%) rename {sapling-crypto => zcash_primitives}/src/pedersen_hash.rs (100%) rename sapling-crypto/src/primitives/mod.rs => zcash_primitives/src/primitives.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 670966e..ef4f552 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,7 +57,7 @@ name = "bellman" version = "0.1.0" dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", @@ -313,7 +313,6 @@ dependencies = [ "pairing 0.14.2", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", "zcash_proofs 0.0.0", ] @@ -536,7 +535,6 @@ dependencies = [ "pairing 0.14.2", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] @@ -546,18 +544,19 @@ version = "0.0.0" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sapling-crypto 0.0.1", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -574,7 +573,6 @@ dependencies = [ "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sapling-crypto 0.0.1", "zcash_primitives 0.0.0", ] diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index ffc38fa..3256d14 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -24,6 +24,5 @@ lazy_static = "1" byteorder = "1" rand_core = "0.5" rand_os = "0.2" -sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } zcash_proofs = { path = "../zcash_proofs" } diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index a05d8ef..b1e0a30 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -7,7 +7,6 @@ extern crate libc; extern crate pairing; extern crate rand_core; extern crate rand_os; -extern crate sapling_crypto; extern crate zcash_primitives; extern crate zcash_proofs; @@ -16,7 +15,7 @@ extern crate lazy_static; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use sapling_crypto::{ +use zcash_primitives::{ constants::CRH_IVK_PERSONALIZATION, jubjub::{ edwards, @@ -57,10 +56,12 @@ use std::ffi::OsString; #[cfg(target_os = "windows")] use std::os::windows::ffi::OsStringExt; -use sapling_crypto::primitives::{ProofGenerationKey, ViewingKey}; use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, note_encryption::sapling_ka_agree, + primitives::{ + Diversifier, Note, PaymentAddress, ProofGenerationKey, ViewingKey, + }, redjubjub::{self, Signature}, sapling::{merkle_hash, spend_sig}, transaction::components::Amount, @@ -236,7 +237,7 @@ fn init_zksnark_params( #[no_mangle] pub extern "system" fn librustzcash_tree_uncommitted(result: *mut [c_uchar; 32]) { - let tmp = sapling_crypto::primitives::Note::::uncommitted().into_repr(); + let tmp = Note::::uncommitted().into_repr(); // Should be okay, caller is responsible for ensuring the pointer // is a valid pointer to 32 bytes that can be mutated. @@ -341,7 +342,7 @@ pub extern "system" fn librustzcash_crh_ivk( #[no_mangle] pub extern "system" fn librustzcash_check_diversifier(diversifier: *const [c_uchar; 11]) -> bool { - let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); + let diversifier = Diversifier(unsafe { *diversifier }); diversifier.g_d::(&JUBJUB).is_some() } @@ -352,7 +353,7 @@ pub extern "system" fn librustzcash_ivk_to_pkd( result: *mut [c_uchar; 32], ) -> bool { let ivk = read_fs(unsafe { &*ivk }); - let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); + let diversifier = Diversifier(unsafe { *diversifier }); if let Some(g_d) = diversifier.g_d::(&JUBJUB) { let pk_d = g_d.mul(ivk, &JUBJUB); @@ -407,8 +408,8 @@ fn priv_get_note( pk_d: *const [c_uchar; 32], value: u64, r: *const [c_uchar; 32], -) -> Result, ()> { - let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); +) -> Result, ()> { + let diversifier = Diversifier(unsafe { *diversifier }); let g_d = match diversifier.g_d::(&JUBJUB) { Some(g_d) => g_d, None => return Err(()), @@ -430,7 +431,7 @@ fn priv_get_note( Err(_) => return Err(()), }; - let note = sapling_crypto::primitives::Note { + let note = Note { value, g_d, pk_d, @@ -539,7 +540,7 @@ pub extern "system" fn librustzcash_sapling_ka_derivepublic( esk: *const [c_uchar; 32], result: *mut [c_uchar; 32], ) -> bool { - let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); + let diversifier = Diversifier(unsafe { *diversifier }); // Compute g_d from the diversifier let g_d = match diversifier.g_d::(&JUBJUB) { @@ -940,7 +941,7 @@ pub extern "system" fn librustzcash_sapling_output_proof( }; // Grab the diversifier from the caller. - let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); + let diversifier = Diversifier(unsafe { *diversifier }); // Grab pk_d from the caller. let pk_d = match edwards::Point::::read(&(unsafe { &*pk_d })[..], &JUBJUB) { @@ -955,7 +956,7 @@ pub extern "system" fn librustzcash_sapling_output_proof( }; // Construct a payment address - let payment_address = sapling_crypto::primitives::PaymentAddress { + let payment_address = PaymentAddress { pk_d: pk_d, diversifier: diversifier, }; @@ -1086,7 +1087,7 @@ pub extern "system" fn librustzcash_sapling_spend_proof( }; // Grab the diversifier from the caller - let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); + let diversifier = Diversifier(unsafe { *diversifier }); // The caller chooses the note randomness let rcm = match Fs::from_repr(read_fs(&(unsafe { &*rcm })[..])) { diff --git a/librustzcash/src/tests/key_agreement.rs b/librustzcash/src/tests/key_agreement.rs index 412ecc3..ab1cc84 100644 --- a/librustzcash/src/tests/key_agreement.rs +++ b/librustzcash/src/tests/key_agreement.rs @@ -2,8 +2,8 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; use rand_core::RngCore; use rand_os::OsRng; -use sapling_crypto::jubjub::{edwards, JubjubBls12}; -use sapling_crypto::primitives::{Diversifier, ViewingKey}; +use zcash_primitives::jubjub::{edwards, JubjubBls12}; +use zcash_primitives::primitives::{Diversifier, ViewingKey}; use { librustzcash_sapling_generate_r, librustzcash_sapling_ka_agree, diff --git a/librustzcash/src/tests/key_components.rs b/librustzcash/src/tests/key_components.rs index 5f332e9..99d3f52 100644 --- a/librustzcash/src/tests/key_components.rs +++ b/librustzcash/src/tests/key_components.rs @@ -1,6 +1,6 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; -use sapling_crypto::{ +use zcash_primitives::{ jubjub::{fs::FsRepr, FixedGenerators, JubjubEngine, JubjubParams}, primitives::{Diversifier, ProofGenerationKey}, }; diff --git a/librustzcash/src/tests/mod.rs b/librustzcash/src/tests/mod.rs index a8cdcb7..dba7387 100644 --- a/librustzcash/src/tests/mod.rs +++ b/librustzcash/src/tests/mod.rs @@ -1,4 +1,4 @@ -use sapling_crypto::jubjub::{FixedGenerators, JubjubParams}; +use zcash_primitives::jubjub::{FixedGenerators, JubjubParams}; use super::JUBJUB; diff --git a/librustzcash/src/tests/signatures.rs b/librustzcash/src/tests/signatures.rs index 034b05a..68ac799 100644 --- a/librustzcash/src/tests/signatures.rs +++ b/librustzcash/src/tests/signatures.rs @@ -1,6 +1,6 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; -use sapling_crypto::jubjub::{FixedGenerators, JubjubEngine}; +use zcash_primitives::jubjub::{FixedGenerators, JubjubEngine}; use zcash_primitives::redjubjub::{PrivateKey, PublicKey, Signature}; use super::JUBJUB; diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index 4e944e0..af5dbb1 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -16,9 +16,3 @@ extern crate rand_xorshift; #[cfg(test)] extern crate sha2; - -pub mod jubjub; -pub mod group_hash; -pub mod pedersen_hash; -pub mod primitives; -pub mod constants; diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 31fba49..9996a47 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -9,7 +9,6 @@ edition = "2018" [dependencies] bech32 = "0.7" pairing = { path = "../pairing" } -sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] diff --git a/zcash_client_backend/src/encoding.rs b/zcash_client_backend/src/encoding.rs index 0c0a50b..e84defa 100644 --- a/zcash_client_backend/src/encoding.rs +++ b/zcash_client_backend/src/encoding.rs @@ -5,7 +5,7 @@ use bech32::{self, Error, FromBase32, ToBase32}; use pairing::bls12_381::Bls12; -use sapling_crypto::{ +use zcash_primitives::{ jubjub::edwards, primitives::{Diversifier, PaymentAddress}, }; @@ -98,15 +98,15 @@ pub fn decode_extended_full_viewing_key( /// use pairing::bls12_381::Bls12; /// use rand_core::SeedableRng; /// use rand_xorshift::XorShiftRng; -/// use sapling_crypto::{ -/// jubjub::edwards, -/// primitives::{Diversifier, PaymentAddress}, -/// }; /// use zcash_client_backend::{ /// constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, /// encoding::encode_payment_address, /// }; -/// use zcash_primitives::JUBJUB; +/// use zcash_primitives::{ +/// jubjub::edwards, +/// primitives::{Diversifier, PaymentAddress}, +/// JUBJUB, +/// }; /// /// let rng = &mut XorShiftRng::from_seed([ /// 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, @@ -138,15 +138,15 @@ pub fn encode_payment_address(hrp: &str, addr: &PaymentAddress) -> String /// use pairing::bls12_381::Bls12; /// use rand_core::SeedableRng; /// use rand_xorshift::XorShiftRng; -/// use sapling_crypto::{ -/// jubjub::edwards, -/// primitives::{Diversifier, PaymentAddress}, -/// }; /// use zcash_client_backend::{ /// constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, /// encoding::decode_payment_address, /// }; -/// use zcash_primitives::JUBJUB; +/// use zcash_primitives::{ +/// jubjub::edwards, +/// primitives::{Diversifier, PaymentAddress}, +/// JUBJUB, +/// }; /// /// let rng = &mut XorShiftRng::from_seed([ /// 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, @@ -187,7 +187,7 @@ mod tests { use pairing::bls12_381::Bls12; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; - use sapling_crypto::{ + use zcash_primitives::{ jubjub::edwards, primitives::{Diversifier, PaymentAddress}, }; diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 49b1b7d..b3173b7 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -8,6 +8,7 @@ authors = [ [dependencies] aes = "0.3" blake2b_simd = "0.5" +blake2s_simd = "0.5" byteorder = "1" crypto_api_chachapoly = "0.2.1" ff = { path = "../ff" } @@ -18,8 +19,8 @@ pairing = { path = "../pairing" } rand = "0.7" rand_core = "0.5" rand_os = "0.2" -sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" [dev-dependencies] +hex-literal = "0.1" rand_xorshift = "0.2" diff --git a/sapling-crypto/benches/pedersen_hash.rs b/zcash_primitives/benches/pedersen_hash.rs similarity index 50% rename from sapling-crypto/benches/pedersen_hash.rs rename to zcash_primitives/benches/pedersen_hash.rs index c5968de..a8f944e 100644 --- a/sapling-crypto/benches/pedersen_hash.rs +++ b/zcash_primitives/benches/pedersen_hash.rs @@ -1,20 +1,22 @@ #![feature(test)] -extern crate rand; +extern crate rand_core; +extern crate rand_os; extern crate test; extern crate pairing; -extern crate sapling_crypto; +extern crate zcash_primitives; -use rand::{Rand, thread_rng}; +use rand_core::RngCore; +use rand_os::OsRng; use pairing::bls12_381::Bls12; -use sapling_crypto::jubjub::JubjubBls12; -use sapling_crypto::pedersen_hash::{pedersen_hash, Personalization}; +use zcash_primitives::jubjub::JubjubBls12; +use zcash_primitives::pedersen_hash::{pedersen_hash, Personalization}; #[bench] fn bench_pedersen_hash(b: &mut test::Bencher) { let params = JubjubBls12::new(); - let rng = &mut thread_rng(); - let bits = (0..510).map(|_| bool::rand(rng)).collect::>(); + let rng = &mut OsRng; + let bits = (0..510).map(|_| (rng.next_u32() % 2) != 0).collect::>(); let personalization = Personalization::MerkleTree(31); b.iter(|| { diff --git a/sapling-crypto/src/constants.rs b/zcash_primitives/src/constants.rs similarity index 100% rename from sapling-crypto/src/constants.rs rename to zcash_primitives/src/constants.rs diff --git a/sapling-crypto/src/group_hash.rs b/zcash_primitives/src/group_hash.rs similarity index 100% rename from sapling-crypto/src/group_hash.rs rename to zcash_primitives/src/group_hash.rs diff --git a/sapling-crypto/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs similarity index 100% rename from sapling-crypto/src/jubjub/edwards.rs rename to zcash_primitives/src/jubjub/edwards.rs diff --git a/sapling-crypto/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs similarity index 100% rename from sapling-crypto/src/jubjub/fs.rs rename to zcash_primitives/src/jubjub/fs.rs diff --git a/sapling-crypto/src/jubjub/mod.rs b/zcash_primitives/src/jubjub/mod.rs similarity index 100% rename from sapling-crypto/src/jubjub/mod.rs rename to zcash_primitives/src/jubjub/mod.rs diff --git a/sapling-crypto/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs similarity index 100% rename from sapling-crypto/src/jubjub/montgomery.rs rename to zcash_primitives/src/jubjub/montgomery.rs diff --git a/sapling-crypto/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs similarity index 100% rename from sapling-crypto/src/jubjub/tests.rs rename to zcash_primitives/src/jubjub/tests.rs diff --git a/zcash_primitives/src/keys.rs b/zcash_primitives/src/keys.rs index fca31ed..ae2c77a 100644 --- a/zcash_primitives/src/keys.rs +++ b/zcash_primitives/src/keys.rs @@ -4,7 +4,7 @@ use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use ff::{PrimeField, PrimeFieldRepr}; -use sapling_crypto::{ +use crate::{ jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, ToUniform, Unknown}, primitives::{ProofGenerationKey, ViewingKey}, }; @@ -188,7 +188,7 @@ impl FullViewingKey { #[cfg(test)] mod tests { use pairing::bls12_381::Bls12; - use sapling_crypto::jubjub::{edwards, FixedGenerators, JubjubParams, PrimeOrder}; + use crate::jubjub::{edwards, FixedGenerators, JubjubParams, PrimeOrder}; use std::error::Error; use super::FullViewingKey; diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 771f13d..1d4806e 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -3,6 +3,7 @@ extern crate lazy_static; extern crate aes; extern crate blake2b_simd; +extern crate blake2s_simd; extern crate byteorder; extern crate crypto_api_chachapoly; extern crate ff; @@ -12,19 +13,25 @@ extern crate pairing; extern crate rand; extern crate rand_core; extern crate rand_os; -extern crate sapling_crypto; extern crate sha2; +#[cfg(test)] +#[macro_use] +extern crate hex_literal; + #[cfg(test)] extern crate rand_xorshift; -use sapling_crypto::jubjub::JubjubBls12; - pub mod block; +pub mod constants; +pub mod group_hash; +pub mod jubjub; pub mod keys; pub mod legacy; pub mod merkle_tree; pub mod note_encryption; +pub mod pedersen_hash; +pub mod primitives; pub mod prover; pub mod redjubjub; pub mod sapling; @@ -36,6 +43,8 @@ pub mod zip32; #[cfg(test)] mod test_vectors; +use jubjub::JubjubBls12; + lazy_static! { pub static ref JUBJUB: JubjubBls12 = { JubjubBls12::new() }; } diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index d6b66ce..e6804cf 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -6,7 +6,7 @@ use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{CryptoRng, RngCore}; -use sapling_crypto::{ +use crate::{ jubjub::{ edwards, fs::{Fs, FsRepr}, @@ -211,18 +211,16 @@ fn prf_ock( /// extern crate ff; /// extern crate pairing; /// extern crate rand_os; -/// extern crate sapling_crypto; +/// extern crate zcash_primitives; /// /// use ff::Field; /// use pairing::bls12_381::Bls12; /// use rand_os::OsRng; -/// use sapling_crypto::{ -/// jubjub::fs::Fs, -/// primitives::{Diversifier, PaymentAddress, ValueCommitment}, -/// }; /// use zcash_primitives::{ +/// jubjub::fs::Fs, /// keys::OutgoingViewingKey, /// note_encryption::{Memo, SaplingNoteEncryption}, +/// primitives::{Diversifier, PaymentAddress, ValueCommitment}, /// JUBJUB, /// }; /// @@ -551,7 +549,7 @@ mod tests { use pairing::bls12_381::{Bls12, Fr, FrRepr}; use rand_core::{CryptoRng, RngCore}; use rand_os::OsRng; - use sapling_crypto::{ + use crate::{ jubjub::{ edwards, fs::{Fs, FsRepr}, diff --git a/sapling-crypto/src/pedersen_hash.rs b/zcash_primitives/src/pedersen_hash.rs similarity index 100% rename from sapling-crypto/src/pedersen_hash.rs rename to zcash_primitives/src/pedersen_hash.rs diff --git a/sapling-crypto/src/primitives/mod.rs b/zcash_primitives/src/primitives.rs similarity index 100% rename from sapling-crypto/src/primitives/mod.rs rename to zcash_primitives/src/primitives.rs diff --git a/zcash_primitives/src/prover.rs b/zcash_primitives/src/prover.rs index a4af8d4..a434b4e 100644 --- a/zcash_primitives/src/prover.rs +++ b/zcash_primitives/src/prover.rs @@ -1,7 +1,7 @@ //! Abstractions over the proving system and parameters. use pairing::bls12_381::{Bls12, Fr}; -use sapling_crypto::{ +use crate::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, }; @@ -75,7 +75,8 @@ pub(crate) mod mock { use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand_os::OsRng; - use sapling_crypto::{ + + use crate::{ jubjub::{edwards, fs::Fs, FixedGenerators, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey, ValueCommitment}, }; diff --git a/zcash_primitives/src/redjubjub.rs b/zcash_primitives/src/redjubjub.rs index 955c7e3..b709419 100644 --- a/zcash_primitives/src/redjubjub.rs +++ b/zcash_primitives/src/redjubjub.rs @@ -3,7 +3,7 @@ use ff::{Field, PrimeField, PrimeFieldRepr}; use rand_core::RngCore; -use sapling_crypto::jubjub::{ +use crate::jubjub::{ edwards::Point, FixedGenerators, JubjubEngine, JubjubParams, Unknown, }; use std::io::{self, Read, Write}; @@ -210,7 +210,8 @@ mod tests { use pairing::bls12_381::Bls12; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; - use sapling_crypto::jubjub::{edwards, fs::Fs, JubjubBls12}; + + use crate::jubjub::{edwards, fs::Fs, JubjubBls12}; use super::*; diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 0b94e4e..4590c79 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -3,7 +3,7 @@ use ff::{BitIterator, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use rand_core::{CryptoRng, RngCore}; -use sapling_crypto::{ +use crate::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, pedersen_hash::{pedersen_hash, Personalization}, primitives::Note, diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 792582d..f32af7a 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -3,7 +3,7 @@ use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore}; -use sapling_crypto::{ +use crate::{ jubjub::fs::Fs, primitives::{Diversifier, Note, PaymentAddress}, }; @@ -534,7 +534,8 @@ impl Builder { mod tests { use ff::{Field, PrimeField}; use rand::rngs::OsRng; - use sapling_crypto::jubjub::fs::Fs; + + use crate::jubjub::fs::Fs; use super::{Builder, Error}; use crate::{ diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index 1785344..c8cfadc 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -1,7 +1,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use sapling_crypto::jubjub::{edwards, Unknown}; +use crate::jubjub::{edwards, Unknown}; use std::io::{self, Read, Write}; use legacy::Script; diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 041ac21..7c770c5 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1,7 +1,8 @@ use ff::Field; use pairing::bls12_381::Bls12; use rand_os::OsRng; -use sapling_crypto::jubjub::{fs::Fs, FixedGenerators}; + +use crate::jubjub::{fs::Fs, FixedGenerators}; use super::{components::Amount, sighash::signature_hash, Transaction, TransactionData}; use legacy::Script; diff --git a/zcash_primitives/src/util.rs b/zcash_primitives/src/util.rs index f46e0a2..1fdcde7 100644 --- a/zcash_primitives/src/util.rs +++ b/zcash_primitives/src/util.rs @@ -1,5 +1,6 @@ use blake2b_simd::Params; -use sapling_crypto::jubjub::{JubjubEngine, ToUniform}; + +use crate::jubjub::{JubjubEngine, ToUniform}; pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> E::Fs { let mut hasher = Params::new().hash_length(64).personal(persona).to_state(); diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index 0c60cf2..44b55f5 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -4,7 +4,8 @@ use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; use ff::Field; use fpe::ff1::{BinaryNumeralString, FF1}; use pairing::bls12_381::Bls12; -use sapling_crypto::{ + +use crate::{ jubjub::{fs::Fs, FixedGenerators, JubjubEngine, JubjubParams, ToUniform}, primitives::{Diversifier, PaymentAddress, ViewingKey}, }; diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index fdb0bf8..b7fa659 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -13,7 +13,6 @@ directories = { version = "1", optional = true } ff = { path = "../ff" } pairing = { path = "../pairing" } rand_os = "0.2" -sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] diff --git a/zcash_proofs/examples/bench.rs b/zcash_proofs/examples/bench.rs index 9adf028..a187ec6 100644 --- a/zcash_proofs/examples/bench.rs +++ b/zcash_proofs/examples/bench.rs @@ -1,14 +1,14 @@ extern crate ff; -extern crate sapling_crypto; extern crate bellman; extern crate pairing; extern crate rand_core; extern crate rand_xorshift; +extern crate zcash_primitives; extern crate zcash_proofs; use ff::Field; use std::time::{Duration, Instant}; -use sapling_crypto::jubjub::{ +use zcash_primitives::jubjub::{ JubjubBls12, edwards, fs, @@ -16,7 +16,7 @@ use sapling_crypto::jubjub::{ use zcash_proofs::circuit::sapling::{ Spend }; -use sapling_crypto::primitives::{ +use zcash_primitives::primitives::{ Diversifier, ProofGenerationKey, ValueCommitment diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index cb11eb6..593c57d 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -15,7 +15,7 @@ use bellman::gadgets::num::{ Num }; -use sapling_crypto::jubjub::{ +use zcash_primitives::jubjub::{ edwards, JubjubEngine, JubjubParams, @@ -754,14 +754,14 @@ mod test { use rand_xorshift::XorShiftRng; use bellman::gadgets::test::*; - use sapling_crypto::jubjub::{ + use zcash_primitives::jubjub::{ montgomery, edwards, JubjubBls12, JubjubParams, FixedGenerators }; - use sapling_crypto::jubjub::fs::Fs; + use zcash_primitives::jubjub::fs::Fs; use super::{ MontgomeryPoint, diff --git a/zcash_proofs/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs index 30a948f..0b67597 100644 --- a/zcash_proofs/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -3,12 +3,12 @@ use super::ecc::{ EdwardsPoint }; use bellman::gadgets::boolean::Boolean; -use sapling_crypto::jubjub::*; +use zcash_primitives::jubjub::*; use bellman::{ ConstraintSystem, SynthesisError }; use bellman::gadgets::lookup::*; -pub use sapling_crypto::pedersen_hash::Personalization; +pub use zcash_primitives::pedersen_hash::Personalization; fn get_constant_bools(person: &Personalization) -> Vec { person.get_bits() @@ -112,7 +112,7 @@ mod test { use super::*; use bellman::gadgets::test::*; use bellman::gadgets::boolean::{Boolean, AllocatedBit}; - use sapling_crypto::pedersen_hash; + use zcash_primitives::pedersen_hash; use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index e381240..1349c8c 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -6,14 +6,14 @@ use bellman::{ Circuit }; -use sapling_crypto::jubjub::{ +use zcash_primitives::jubjub::{ JubjubEngine, FixedGenerators }; -use sapling_crypto::constants; +use zcash_primitives::constants; -use sapling_crypto::primitives::{ +use zcash_primitives::primitives::{ ValueCommitment, ProofGenerationKey, PaymentAddress @@ -603,7 +603,7 @@ fn test_input_circuit_with_bls12_381() { use pairing::bls12_381::*; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use sapling_crypto::{ + use zcash_primitives::{ jubjub::{JubjubBls12, fs, edwards}, pedersen_hash, primitives::{Diversifier, Note, ProofGenerationKey}, @@ -747,7 +747,7 @@ fn test_output_circuit_with_bls12_381() { use pairing::bls12_381::*; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use sapling_crypto::{ + use zcash_primitives::{ jubjub::{JubjubBls12, fs, edwards}, primitives::{Diversifier, ProofGenerationKey}, }; diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index 2a3c8f2..3851481 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -4,7 +4,6 @@ extern crate byteorder; extern crate ff; extern crate pairing; extern crate rand_os; -extern crate sapling_crypto; extern crate zcash_primitives; #[cfg(feature = "local-prover")] diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index c59ba62..1c1a972 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -3,7 +3,7 @@ use bellman::groth16::{Parameters, PreparedVerifyingKey}; use directories::BaseDirs; use pairing::bls12_381::{Bls12, Fr}; -use sapling_crypto::{ +use zcash_primitives::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, }; diff --git a/zcash_proofs/src/sapling/mod.rs b/zcash_proofs/src/sapling/mod.rs index 98c4ba3..9aa62f1 100644 --- a/zcash_proofs/src/sapling/mod.rs +++ b/zcash_proofs/src/sapling/mod.rs @@ -1,5 +1,5 @@ use pairing::bls12_381::Bls12; -use sapling_crypto::jubjub::{ +use zcash_primitives::jubjub::{ edwards, fs::FsRepr, FixedGenerators, JubjubBls12, JubjubParams, Unknown, }; use zcash_primitives::transaction::components::Amount; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 7ca8bce..e914171 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -7,7 +7,7 @@ use bellman::{ use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand_os::OsRng; -use sapling_crypto::{ +use zcash_primitives::{ jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, }; diff --git a/zcash_proofs/src/sapling/verifier.rs b/zcash_proofs/src/sapling/verifier.rs index 01cba0c..0801023 100644 --- a/zcash_proofs/src/sapling/verifier.rs +++ b/zcash_proofs/src/sapling/verifier.rs @@ -4,7 +4,7 @@ use bellman::{ }; use ff::Field; use pairing::bls12_381::{Bls12, Fr}; -use sapling_crypto::jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}; +use zcash_primitives::jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}; use zcash_primitives::{ redjubjub::{PublicKey, Signature}, transaction::components::Amount, From 1b865ecfdf3d6743fa2e044b77f273db0e28cb9d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 6 Aug 2019 10:52:04 +0100 Subject: [PATCH 065/105] Remove sapling-crypto --- Cargo.lock | 17 --- Cargo.toml | 1 - sapling-crypto/.gitignore | 3 - sapling-crypto/COPYRIGHT | 14 --- sapling-crypto/Cargo.toml | 27 ----- sapling-crypto/LICENSE-APACHE | 201 ---------------------------------- sapling-crypto/LICENSE-MIT | 23 ---- sapling-crypto/README.md | 23 ---- sapling-crypto/src/lib.rs | 18 --- 9 files changed, 327 deletions(-) delete mode 100644 sapling-crypto/.gitignore delete mode 100644 sapling-crypto/COPYRIGHT delete mode 100644 sapling-crypto/Cargo.toml delete mode 100644 sapling-crypto/LICENSE-APACHE delete mode 100644 sapling-crypto/LICENSE-MIT delete mode 100644 sapling-crypto/README.md delete mode 100644 sapling-crypto/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ef4f552..d6f658a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -460,23 +460,6 @@ dependencies = [ "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sapling-crypto" -version = "0.0.1" -dependencies = [ - "bellman 0.1.0", - "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0", - "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "pairing 0.14.2", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sha2" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index c5e2257..69639cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "group", "librustzcash", "pairing", - "sapling-crypto", "zcash_client_backend", "zcash_primitives", "zcash_proofs", diff --git a/sapling-crypto/.gitignore b/sapling-crypto/.gitignore deleted file mode 100644 index 6aa1064..0000000 --- a/sapling-crypto/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target/ -**/*.rs.bk -Cargo.lock diff --git a/sapling-crypto/COPYRIGHT b/sapling-crypto/COPYRIGHT deleted file mode 100644 index f2c6a3b..0000000 --- a/sapling-crypto/COPYRIGHT +++ /dev/null @@ -1,14 +0,0 @@ -Copyrights in the "sapling-crypto" library are retained by their contributors. No -copyright assignment is required to contribute to the "sapling-crypto" library. - -The "sapling-crypto" library is licensed under either of - - * Apache License, Version 2.0, (see ./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license (see ./LICENSE-MIT or http://opensource.org/licenses/MIT) - -at your option. - -Unless you explicitly state otherwise, any contribution intentionally -submitted for inclusion in the work by you, as defined in the Apache-2.0 -license, shall be dual licensed as above, without any additional terms or -conditions. diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml deleted file mode 100644 index c3aedd3..0000000 --- a/sapling-crypto/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -authors = ["Sean Bowe "] -description = "Cryptographic library for Zcash Sapling" -documentation = "https://github.com/zcash-hackworks/sapling" -homepage = "https://github.com/zcash-hackworks/sapling" -license = "MIT/Apache-2.0" -name = "sapling-crypto" -repository = "https://github.com/zcash-hackworks/sapling" -version = "0.0.1" - -[dependencies.pairing] -path = "../pairing" -features = ["expose-arith"] - -[dependencies] -bellman = { path = "../bellman" } -blake2b_simd = "0.5" -blake2s_simd = "0.5" -ff = { path = "../ff" } -rand_core = "0.5" -digest = "0.8" -byteorder = "1" - -[dev-dependencies] -hex-literal = "0.1" -rand_xorshift = "0.2" -sha2 = "0.8" diff --git a/sapling-crypto/LICENSE-APACHE b/sapling-crypto/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/sapling-crypto/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/sapling-crypto/LICENSE-MIT b/sapling-crypto/LICENSE-MIT deleted file mode 100644 index 31aa793..0000000 --- a/sapling-crypto/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/sapling-crypto/README.md b/sapling-crypto/README.md deleted file mode 100644 index f5d3bce..0000000 --- a/sapling-crypto/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# sapling-crypto - -This repository contains a (work-in-progress) implementation of Zcash's "Sapling" cryptography. - -## Security Warnings - -This library is currently under development and has not been reviewed. - -## License - -Licensed under either of - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally -submitted for inclusion in the work by you, as defined in the Apache-2.0 -license, shall be dual licensed as above, without any additional terms or -conditions. diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs deleted file mode 100644 index af5dbb1..0000000 --- a/sapling-crypto/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -extern crate pairing; -extern crate bellman; -extern crate blake2b_simd; -extern crate blake2s_simd; -extern crate digest; -extern crate ff; -extern crate rand_core; -extern crate byteorder; - -#[cfg(test)] -#[macro_use] -extern crate hex_literal; - -#[cfg(test)] -extern crate rand_xorshift; - -#[cfg(test)] -extern crate sha2; From bc7ea564d32291a6723d57573119f2869f2ab265 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 15 Aug 2019 10:38:40 -0600 Subject: [PATCH 066/105] cargo fmt pairing --- pairing/src/bls12_381/ec.rs | 239 +++++++++++++++++++++------------- pairing/src/bls12_381/fq.rs | 60 +++++---- pairing/src/bls12_381/fq12.rs | 2 +- pairing/src/bls12_381/fq2.rs | 171 +++++++++++++++--------- pairing/src/bls12_381/fq6.rs | 1 - pairing/src/bls12_381/fr.rs | 54 ++++---- pairing/src/bls12_381/mod.rs | 4 +- pairing/src/lib.rs | 15 +-- pairing/src/tests/field.rs | 4 +- 9 files changed, 323 insertions(+), 227 deletions(-) diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index fa659bd..9a78e37 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -14,11 +14,10 @@ macro_rules! curve_impl { pub struct $affine { pub(crate) x: $basefield, pub(crate) y: $basefield, - pub(crate) infinity: bool + pub(crate) infinity: bool, } - impl ::std::fmt::Display for $affine - { + impl ::std::fmt::Display for $affine { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { if self.infinity { write!(f, "{}(Infinity)", $name) @@ -30,13 +29,12 @@ macro_rules! curve_impl { #[derive(Copy, Clone, Debug, Eq)] pub struct $projective { - pub(crate) x: $basefield, - pub(crate) y: $basefield, - pub(crate) z: $basefield + pub(crate) x: $basefield, + pub(crate) y: $basefield, + pub(crate) z: $basefield, } - impl ::std::fmt::Display for $projective - { + impl ::std::fmt::Display for $projective { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, "{}", self.into_affine()) } @@ -89,7 +87,9 @@ macro_rules! curve_impl { let mut res = $projective::zero(); for i in bits { res.double(); - if i { res.add_assign_mixed(self) } + if i { + res.add_assign_mixed(self) + } } res } @@ -112,12 +112,8 @@ macro_rules! curve_impl { $affine { x: x, - y: if (y < negy) ^ greatest { - y - } else { - negy - }, - infinity: false + y: if (y < negy) ^ greatest { y } else { negy }, + infinity: false, } }) } @@ -156,7 +152,7 @@ macro_rules! curve_impl { $affine { x: $basefield::zero(), y: $basefield::one(), - infinity: true + infinity: true, } } @@ -182,7 +178,6 @@ macro_rules! curve_impl { fn into_projective(&self) -> $projective { (*self).into() } - } impl PairingCurveAffine for $affine { @@ -197,7 +192,6 @@ macro_rules! curve_impl { fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult { self.perform_pairing(other) } - } impl CurveProjective for $projective { @@ -227,7 +221,7 @@ macro_rules! curve_impl { $projective { x: $basefield::zero(), y: $basefield::one(), - z: $basefield::zero() + z: $basefield::zero(), } } @@ -245,8 +239,7 @@ macro_rules! curve_impl { self.is_zero() || self.z == $basefield::one() } - fn batch_normalization(v: &mut [Self]) - { + fn batch_normalization(v: &mut [Self]) { // Montgomery’s Trick and Fast Implementation of Masked AES // Genelle, Prouff and Quisquater // Section 3.2 @@ -254,9 +247,10 @@ macro_rules! curve_impl { // First pass: compute [a, ab, abc, ...] let mut prod = Vec::with_capacity(v.len()); let mut tmp = $basefield::one(); - for g in v.iter_mut() - // Ignore normalized elements - .filter(|g| !g.is_normalized()) + for g in v + .iter_mut() + // Ignore normalized elements + .filter(|g| !g.is_normalized()) { tmp.mul_assign(&g.z); prod.push(tmp); @@ -266,13 +260,19 @@ macro_rules! curve_impl { tmp = tmp.inverse().unwrap(); // Guaranteed to be nonzero. // Second pass: iterate backwards to compute inverses - for (g, s) in v.iter_mut() - // Backwards - .rev() - // Ignore normalized elements - .filter(|g| !g.is_normalized()) - // Backwards, skip last element, fill in one for last term. - .zip(prod.into_iter().rev().skip(1).chain(Some($basefield::one()))) + for (g, s) in v + .iter_mut() + // Backwards + .rev() + // Ignore normalized elements + .filter(|g| !g.is_normalized()) + // Backwards, skip last element, fill in one for last term. + .zip( + prod.into_iter() + .rev() + .skip(1) + .chain(Some($basefield::one())), + ) { // tmp := tmp * g.z; g.z := tmp * s = 1/z let mut newtmp = tmp; @@ -283,9 +283,7 @@ macro_rules! curve_impl { } // Perform affine transformations - for g in v.iter_mut() - .filter(|g| !g.is_normalized()) - { + for g in v.iter_mut().filter(|g| !g.is_normalized()) { let mut z = g.z; // 1/z z.square(); // 1/z^2 g.x.mul_assign(&z); // x/z^2 @@ -538,8 +536,7 @@ macro_rules! curve_impl { let mut found_one = false; - for i in BitIterator::new(other.into()) - { + for i in BitIterator::new(other.into()) { if found_one { res.double(); } else { @@ -577,7 +574,7 @@ macro_rules! curve_impl { $projective { x: p.x, y: p.y, - z: $basefield::one() + z: $basefield::one(), } } } @@ -594,7 +591,7 @@ macro_rules! curve_impl { $affine { x: p.x, y: p.y, - infinity: false + infinity: false, } } else { // Z is nonzero, so it must have an inverse in a field. @@ -614,12 +611,12 @@ macro_rules! curve_impl { $affine { x: x, y: y, - infinity: false + infinity: false, } } } } - } + }; } pub mod g1 { @@ -990,7 +987,8 @@ pub mod g1 { 0x9fe83b1b4a5d648d, 0xf583cc5a508f6a40, 0xc3ad2aefde0bb13, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0x60aa6f9552f03aae, 0xecd01d5181300d35, @@ -998,7 +996,8 @@ pub mod g1 { 0xe760f57922998c9d, 0x953703f5795a39e5, 0xfe3ae0922df702c, - ])).unwrap(), + ])) + .unwrap(), infinity: false, }; assert!(!p.is_on_curve()); @@ -1015,7 +1014,8 @@ pub mod g1 { 0xea034ee2928b30a8, 0xbd8833dc7c79a7f7, 0xe45c9f0c0438675, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0x3b450eb1ab7b5dad, 0xa65cb81e975e8675, @@ -1023,7 +1023,8 @@ pub mod g1 { 0x753ddf21a2601d20, 0x532d0b640bd3ff8b, 0x118d2c543f031102, - ])).unwrap(), + ])) + .unwrap(), infinity: false, }; assert!(!p.is_on_curve()); @@ -1041,7 +1042,8 @@ pub mod g1 { 0xf35de9ce0d6b4e84, 0x265bddd23d1dec54, 0x12a8778088458308, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0x8a22defa0d526256, 0xc57ca55456fcb9ae, @@ -1049,7 +1051,8 @@ pub mod g1 { 0x921beef89d4f29df, 0x5b6fda44ad85fa78, 0xed74ab9f302cbe0, - ])).unwrap(), + ])) + .unwrap(), infinity: false, }; assert!(p.is_on_curve()); @@ -1067,7 +1070,8 @@ pub mod g1 { 0x485e77d50a5df10d, 0x4c6fcac4b55fd479, 0x86ed4d9906fb064, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0xd25ee6461538c65, 0x9f3bbb2ecd3719b9, @@ -1075,7 +1079,8 @@ pub mod g1 { 0xcefca68333c35288, 0x570c8005f8573fa6, 0x152ca696fe034442, - ])).unwrap(), + ])) + .unwrap(), z: Fq::one(), }; @@ -1087,7 +1092,8 @@ pub mod g1 { 0x5f44314ec5e3fb03, 0x24e8538737c6e675, 0x8abd623a594fba8, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0x6b0528f088bb7044, 0x2fdeb5c82917ff9e, @@ -1095,7 +1101,8 @@ pub mod g1 { 0xd65104c6f95a872a, 0x1f2998a5a9c61253, 0xe74846154a9e44, - ])).unwrap(), + ])) + .unwrap(), z: Fq::one(), }); @@ -1111,7 +1118,8 @@ pub mod g1 { 0xc4f9a52a428e23bb, 0xd178b28dd4f407ef, 0x17fb8905e9183c69 - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0xd0de9d65292b7710, 0xf6a05f2bcf1d9ca7, @@ -1119,7 +1127,8 @@ pub mod g1 { 0xeec8d1a5b7466c58, 0x4bc362649dce6376, 0x430cbdc5455b00a - ])).unwrap(), + ])) + .unwrap(), infinity: false, } ); @@ -1135,7 +1144,8 @@ pub mod g1 { 0x485e77d50a5df10d, 0x4c6fcac4b55fd479, 0x86ed4d9906fb064, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0xd25ee6461538c65, 0x9f3bbb2ecd3719b9, @@ -1143,7 +1153,8 @@ pub mod g1 { 0xcefca68333c35288, 0x570c8005f8573fa6, 0x152ca696fe034442, - ])).unwrap(), + ])) + .unwrap(), z: Fq::one(), }; @@ -1161,7 +1172,8 @@ pub mod g1 { 0x4b914c16687dcde0, 0x66c8baf177d20533, 0xaf960cff3d83833 - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0x3f0675695f5177a8, 0x2b6d82ae178a1ba0, @@ -1169,7 +1181,8 @@ pub mod g1 { 0x1771a65b60572f4e, 0x8b547c1313b27555, 0x135075589a687b1e - ])).unwrap(), + ])) + .unwrap(), infinity: false, } ); @@ -1192,7 +1205,8 @@ pub mod g1 { 0x71ffa8021531705, 0x7418d484386d267, 0xd5108d8ff1fbd6, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0xa776ccbfe9981766, 0x255632964ff40f4a, @@ -1200,7 +1214,8 @@ pub mod g1 { 0x520f74773e74c8c3, 0x484c8fc982008f0, 0xee2c3d922008cc6, - ])).unwrap(), + ])) + .unwrap(), infinity: false, }; @@ -1212,7 +1227,8 @@ pub mod g1 { 0xc6e05201e5f83991, 0xf7c75910816f207c, 0x18d4043e78103106, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0xa776ccbfe9981766, 0x255632964ff40f4a, @@ -1220,7 +1236,8 @@ pub mod g1 { 0x520f74773e74c8c3, 0x484c8fc982008f0, 0xee2c3d922008cc6, - ])).unwrap(), + ])) + .unwrap(), infinity: false, }; @@ -1235,7 +1252,8 @@ pub mod g1 { 0x9676ff02ec39c227, 0x4c12c15d7e55b9f3, 0x57fd1e317db9bd, - ])).unwrap(), + ])) + .unwrap(), y: Fq::from_repr(FqRepr([ 0x1288334016679345, 0xf955cd68615ff0b5, @@ -1243,7 +1261,8 @@ pub mod g1 { 0x1267d70db51049fb, 0x4696deb9ab2ba3e7, 0xb1e4e11177f59d4, - ])).unwrap(), + ])) + .unwrap(), infinity: false, }; @@ -1673,7 +1692,8 @@ pub mod g2 { 0x7a17a004747e3dbe, 0xcc65406a7c2e5a73, 0x10b8c03d64db4d0c, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xd30e70fe2f029778, 0xda30772df0f5212e, @@ -1681,7 +1701,8 @@ pub mod g2 { 0xfb777e5b9b568608, 0x789bac1fec71a2b9, 0x1342f02e2da54405, - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1691,7 +1712,8 @@ pub mod g2 { 0x663015d9410eb608, 0x78e82a79d829a544, 0x40a00545bb3c1e, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x4709802348e79377, 0xb5ac4dc9204bcfbd, @@ -1699,7 +1721,8 @@ pub mod g2 { 0x15008b1dc399e8df, 0x68128fd0548a3829, 0x16a613db5c873aaa, - ])).unwrap(), + ])) + .unwrap(), }, infinity: false, }; @@ -1718,7 +1741,8 @@ pub mod g2 { 0x41abba710d6c692c, 0xffcc4b2b62ce8484, 0x6993ec01b8934ed, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xb94e92d5f874e26, 0x44516408bc115d95, @@ -1726,7 +1750,8 @@ pub mod g2 { 0xa5a0c2b7131f3555, 0x83800965822367e7, 0x10cf1d3ad8d90bfa, - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1736,7 +1761,8 @@ pub mod g2 { 0x5a9171720e73eb51, 0x38eb4fd8d658adb7, 0xb649051bbc1164d, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x9225814253d7df75, 0xc196c2513477f887, @@ -1744,7 +1770,8 @@ pub mod g2 { 0x55f2b8efad953e04, 0x7379345eda55265e, 0x377f2e6208fd4cb, - ])).unwrap(), + ])) + .unwrap(), }, infinity: false, }; @@ -1764,7 +1791,8 @@ pub mod g2 { 0x2199bc19c48c393d, 0x4a151b732a6075bf, 0x17762a3b9108c4a7, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x26f461e944bbd3d1, 0x298f3189a9cf6ed6, @@ -1772,7 +1800,8 @@ pub mod g2 { 0x7e147f3f9e6e241, 0x72a9b63583963fff, 0x158b0083c000462, - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1782,7 +1811,8 @@ pub mod g2 { 0x68cad19430706b4d, 0x3ccfb97b924dcea8, 0x1660f93434588f8d, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xaaed3985b6dcb9c7, 0xc1e985d6d898d9f4, @@ -1790,7 +1820,8 @@ pub mod g2 { 0x3940a2dbb914b529, 0xbeb88137cf34f3e7, 0x1699ee577c61b694, - ])).unwrap(), + ])) + .unwrap(), }, infinity: false, }; @@ -1810,7 +1841,8 @@ pub mod g2 { 0x72556c999f3707ac, 0x4617f2e6774e9711, 0x100b2fe5bffe030b, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x7a33555977ec608, 0xe23039d1fe9c0881, @@ -1818,7 +1850,8 @@ pub mod g2 { 0x4637c4f417667e2e, 0x93ebe7c3e41f6acc, 0xde884f89a9a371b, - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1828,7 +1861,8 @@ pub mod g2 { 0x25fd427b4122f231, 0xd83112aace35cae, 0x191b2432407cbb7f, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xf68ae82fe97662f5, 0xe986057068b50b7d, @@ -1836,7 +1870,8 @@ pub mod g2 { 0x9eaa6d19de569196, 0xf6a03d31e2ec2183, 0x3bdafaf7ca9b39b, - ])).unwrap(), + ])) + .unwrap(), }, z: Fq2::one(), }; @@ -1850,7 +1885,8 @@ pub mod g2 { 0x8e73a96b329ad190, 0x27c546f75ee1f3ab, 0xa33d27add5e7e82, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x93b1ebcd54870dfe, 0xf1578300e1342e11, @@ -1858,7 +1894,8 @@ pub mod g2 { 0x2089faf462438296, 0x828e5848cd48ea66, 0x141ecbac1deb038b, - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1868,7 +1905,8 @@ pub mod g2 { 0x2767032fc37cc31d, 0xd5ee2aba84fd10fe, 0x16576ccd3dd0a4e8, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x4da9b6f6a96d1dd2, 0x9657f7da77f1650e, @@ -1876,7 +1914,8 @@ pub mod g2 { 0x31898db63f87363a, 0xabab040ddbd097cc, 0x11ad236b9ba02990, - ])).unwrap(), + ])) + .unwrap(), }, z: Fq2::one(), }); @@ -1894,7 +1933,8 @@ pub mod g2 { 0xf1273e6406eef9cc, 0xababd760ff05cb92, 0xd7c20456617e89 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xd1a50b8572cbd2b8, 0x238f0ac6119d07df, @@ -1902,7 +1942,8 @@ pub mod g2 { 0x8b203284c51edf6b, 0xc8a0b730bbb21f5e, 0x1a3b59d29a31274 - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1912,7 +1953,8 @@ pub mod g2 { 0x64528ab3863633dc, 0x159384333d7cba97, 0x4cb84741f3cafe8 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x242af0dc3640e1a4, 0xe90a73ad65c66919, @@ -1920,7 +1962,8 @@ pub mod g2 { 0x38528f92b689644d, 0xb6884deec59fb21f, 0x3c075d3ec52ba90 - ])).unwrap(), + ])) + .unwrap(), }, infinity: false, } @@ -1938,7 +1981,8 @@ pub mod g2 { 0x72556c999f3707ac, 0x4617f2e6774e9711, 0x100b2fe5bffe030b, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x7a33555977ec608, 0xe23039d1fe9c0881, @@ -1946,7 +1990,8 @@ pub mod g2 { 0x4637c4f417667e2e, 0x93ebe7c3e41f6acc, 0xde884f89a9a371b, - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -1956,7 +2001,8 @@ pub mod g2 { 0x25fd427b4122f231, 0xd83112aace35cae, 0x191b2432407cbb7f, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xf68ae82fe97662f5, 0xe986057068b50b7d, @@ -1964,7 +2010,8 @@ pub mod g2 { 0x9eaa6d19de569196, 0xf6a03d31e2ec2183, 0x3bdafaf7ca9b39b, - ])).unwrap(), + ])) + .unwrap(), }, z: Fq2::one(), }; @@ -1984,7 +2031,8 @@ pub mod g2 { 0xbcedcfce1e52d986, 0x9755d4a3926e9862, 0x18bab73760fd8024 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x4e7c5e0a2ae5b99e, 0x96e582a27f028961, @@ -1992,7 +2040,8 @@ pub mod g2 { 0xeb0cf5e610ef4fe7, 0x7b4c2bae8db6e70b, 0xf136e43909fca0 - ])).unwrap(), + ])) + .unwrap(), }, y: Fq2 { c0: Fq::from_repr(FqRepr([ @@ -2002,7 +2051,8 @@ pub mod g2 { 0xa5a2a51f7fde787b, 0x8b92866bc6384188, 0x81a53fe531d64ef - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x4c5d607666239b34, 0xeddb5f48304d14b3, @@ -2010,7 +2060,8 @@ pub mod g2 { 0xb271f52f12ead742, 0x244e6c2015c83348, 0x19e2deae6eb9b441 - ])).unwrap(), + ])) + .unwrap(), }, infinity: false, } diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index 0f54196..d272545 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -1582,26 +1582,24 @@ fn test_fq_is_valid() { a.0.sub_noborrow(&FqRepr::from(1)); assert!(a.is_valid()); assert!(Fq(FqRepr::from(0)).is_valid()); - assert!( - Fq(FqRepr([ - 0xdf4671abd14dab3e, - 0xe2dc0c9f534fbd33, - 0x31ca6c880cc444a6, - 0x257a67e70ef33359, - 0xf9b29e493f899b36, - 0x17c8be1800b9f059 - ])).is_valid() - ); - assert!( - !Fq(FqRepr([ - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff - ])).is_valid() - ); + assert!(Fq(FqRepr([ + 0xdf4671abd14dab3e, + 0xe2dc0c9f534fbd33, + 0x31ca6c880cc444a6, + 0x257a67e70ef33359, + 0xf9b29e493f899b36, + 0x17c8be1800b9f059 + ])) + .is_valid()); + assert!(!Fq(FqRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])) + .is_valid()); let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -1949,7 +1947,8 @@ fn test_fq_squaring() { 0xdc05c659b4e15b27, 0x79361e5a802c6a23, 0x24bcbe5d51b9a6f - ])).unwrap() + ])) + .unwrap() ); let mut rng = XorShiftRng::from_seed([ @@ -2099,16 +2098,15 @@ fn test_fq_sqrt() { #[test] fn test_fq_from_into_repr() { // q + 1 should not be in the field - assert!( - Fq::from_repr(FqRepr([ - 0xb9feffffffffaaac, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a - ])).is_err() - ); + assert!(Fq::from_repr(FqRepr([ + 0xb9feffffffffaaac, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a + ])) + .is_err()); // q should not be in the field assert!(Fq::from_repr(Fq::char()).is_err()); diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 3c726d2..dcfdef1 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -2,7 +2,7 @@ use super::fq::FROBENIUS_COEFF_FQ12_C1; use super::fq2::Fq2; use super::fq6::Fq6; use ff::Field; -use rand_core::{RngCore}; +use rand_core::RngCore; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index 994a28a..7818280 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -1,4 +1,4 @@ -use super::fq::{FROBENIUS_COEFF_FQ2_C1, Fq, NEGATIVE_ONE}; +use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE}; use ff::{Field, SqrtField}; use rand_core::RngCore; @@ -261,12 +261,11 @@ fn test_fq2_basics() { ); assert!(Fq2::zero().is_zero()); assert!(!Fq2::one().is_zero()); - assert!( - !Fq2 { - c0: Fq::zero(), - c1: Fq::one(), - }.is_zero() - ); + assert!(!Fq2 { + c0: Fq::zero(), + c1: Fq::one(), + } + .is_zero()); } #[test] @@ -309,7 +308,8 @@ fn test_fq2_squaring() { 0xf7f295a94e58ae7c, 0x41b76dcc1c3fbe5e, 0x7080c5fa1d8e042, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x38f473b3c870a4ab, 0x6ad3291177c8c7e5, @@ -317,7 +317,8 @@ fn test_fq2_squaring() { 0xbfb99020604137a0, 0xfc58a7b7be815407, 0x10d1615e75250a21, - ])).unwrap(), + ])) + .unwrap(), }; a.square(); assert_eq!( @@ -330,7 +331,8 @@ fn test_fq2_squaring() { 0xcb674157618da176, 0x4cf17b5893c3d327, 0x7eac81369c43361 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xc1579cf58e980cf8, 0xa23eb7e12dd54d98, @@ -338,7 +340,8 @@ fn test_fq2_squaring() { 0x38d0d7275a9689e1, 0x739c983042779a65, 0x1542a61c8a8db994 - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -356,7 +359,8 @@ fn test_fq2_mul() { 0x9ee53e7e84d7532e, 0x1c202d8ed97afb45, 0x51d3f9253e2516f, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xa7348a8b511aedcf, 0x143c215d8176b319, @@ -364,7 +368,8 @@ fn test_fq2_mul() { 0x9533e4a9a5158be, 0x7a5e1ecb676d65f9, 0x180c3ee46656b008, - ])).unwrap(), + ])) + .unwrap(), }; a.mul_assign(&Fq2 { c0: Fq::from_repr(FqRepr([ @@ -374,7 +379,8 @@ fn test_fq2_mul() { 0xcd460f9f0c23e430, 0x6c9110292bfa409, 0x2c93a72eb8af83e, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x4b1c3f936d8992d4, 0x1d2a72916dba4c8a, @@ -382,7 +388,8 @@ fn test_fq2_mul() { 0x57a06d3135a752ae, 0x634cd3c6c565096d, 0x19e17334d4e93558, - ])).unwrap(), + ])) + .unwrap(), }); assert_eq!( a, @@ -394,7 +401,8 @@ fn test_fq2_mul() { 0x5511fe4d84ee5f78, 0x5310a202d92f9963, 0x1751afbe166e5399 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x84af0e1bd630117a, 0x6c63cd4da2c2aa7, @@ -402,7 +410,8 @@ fn test_fq2_mul() { 0xc975106579c275ee, 0x33a9ac82ce4c5083, 0x1ef1a36c201589d - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -422,7 +431,8 @@ fn test_fq2_inverse() { 0x9ee53e7e84d7532e, 0x1c202d8ed97afb45, 0x51d3f9253e2516f, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xa7348a8b511aedcf, 0x143c215d8176b319, @@ -430,7 +440,8 @@ fn test_fq2_inverse() { 0x9533e4a9a5158be, 0x7a5e1ecb676d65f9, 0x180c3ee46656b008, - ])).unwrap(), + ])) + .unwrap(), }; let a = a.inverse().unwrap(); assert_eq!( @@ -443,7 +454,8 @@ fn test_fq2_inverse() { 0xdfba703293941c30, 0xa6c3d8f9586f2636, 0x1351ef01941b70c4 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x8c39fd76a8312cb4, 0x15d7b6b95defbff0, @@ -451,7 +463,8 @@ fn test_fq2_inverse() { 0xcbf651a0f367afb2, 0xdf4e54f0d3ef15a6, 0x103bdf241afb0019 - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -469,7 +482,8 @@ fn test_fq2_addition() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -477,7 +491,8 @@ fn test_fq2_addition() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837, - ])).unwrap(), + ])) + .unwrap(), }; a.add_assign(&Fq2 { c0: Fq::from_repr(FqRepr([ @@ -487,7 +502,8 @@ fn test_fq2_addition() { 0x3b88899a42a6318f, 0x986a4a62fa82a49d, 0x13ce433fa26027f5, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x66323bf80b58b9b9, 0xa1379b6facf6e596, @@ -495,7 +511,8 @@ fn test_fq2_addition() { 0x2236f55246d0d44d, 0x4c8c1800eb104566, 0x11d6e20e986c2085, - ])).unwrap(), + ])) + .unwrap(), }); assert_eq!( a, @@ -507,7 +524,8 @@ fn test_fq2_addition() { 0xf4ef57d604b6bca2, 0x65309427b3d5d090, 0x14c715d5553f01d2 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xfdb032e7d9079a94, 0x35a2809d15468d83, @@ -515,7 +533,8 @@ fn test_fq2_addition() { 0xd62fa51334f560fa, 0x9ad265eb46e01984, 0x1303f3465112c8bc - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -533,7 +552,8 @@ fn test_fq2_subtraction() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -541,7 +561,8 @@ fn test_fq2_subtraction() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837, - ])).unwrap(), + ])) + .unwrap(), }; a.sub_assign(&Fq2 { c0: Fq::from_repr(FqRepr([ @@ -551,7 +572,8 @@ fn test_fq2_subtraction() { 0x3b88899a42a6318f, 0x986a4a62fa82a49d, 0x13ce433fa26027f5, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x66323bf80b58b9b9, 0xa1379b6facf6e596, @@ -559,7 +581,8 @@ fn test_fq2_subtraction() { 0x2236f55246d0d44d, 0x4c8c1800eb104566, 0x11d6e20e986c2085, - ])).unwrap(), + ])) + .unwrap(), }); assert_eq!( a, @@ -571,7 +594,8 @@ fn test_fq2_subtraction() { 0xe255902672ef6c43, 0x7f77a718021c342d, 0x72ba14049fe9881 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xeb4abaf7c255d1cd, 0x11df49bc6cacc256, @@ -579,7 +603,8 @@ fn test_fq2_subtraction() { 0xf63905f39ad8cb1f, 0x4cd5dd9fb40b3b8f, 0x957411359ba6e4c - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -597,7 +622,8 @@ fn test_fq2_negation() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -605,7 +631,8 @@ fn test_fq2_negation() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837, - ])).unwrap(), + ])) + .unwrap(), }; a.negate(); assert_eq!( @@ -618,7 +645,8 @@ fn test_fq2_negation() { 0xab107d49317487ab, 0x7e555df189f880e3, 0x19083f5486a10cbd - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x228109103250c9d0, 0x8a411ad149045812, @@ -626,7 +654,8 @@ fn test_fq2_negation() { 0xb07e9bc405608611, 0xfcd559cbe77bd8b8, 0x18d400b280d93e62 - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -644,7 +673,8 @@ fn test_fq2_doubling() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -652,7 +682,8 @@ fn test_fq2_doubling() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837, - ])).unwrap(), + ])) + .unwrap(), }; a.double(); assert_eq!( @@ -665,7 +696,8 @@ fn test_fq2_doubling() { 0x72cd9c7784211627, 0x998c938972a657e7, 0x1f1a52b65bdb3b9 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x2efbeddf9b5dc1b6, 0x28d5ca5ad09f4fdb, @@ -673,7 +705,8 @@ fn test_fq2_doubling() { 0x67f15f81dc49195b, 0x9c8c9bd4b79fa83d, 0x25a226f714d506e - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -691,7 +724,8 @@ fn test_fq2_frobenius_map() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc, - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -699,7 +733,8 @@ fn test_fq2_frobenius_map() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837, - ])).unwrap(), + ])) + .unwrap(), }; a.frobenius_map(0); assert_eq!( @@ -712,7 +747,8 @@ fn test_fq2_frobenius_map() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -720,7 +756,8 @@ fn test_fq2_frobenius_map() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837 - ])).unwrap(), + ])) + .unwrap(), } ); a.frobenius_map(1); @@ -734,7 +771,8 @@ fn test_fq2_frobenius_map() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x228109103250c9d0, 0x8a411ad149045812, @@ -742,7 +780,8 @@ fn test_fq2_frobenius_map() { 0xb07e9bc405608611, 0xfcd559cbe77bd8b8, 0x18d400b280d93e62 - ])).unwrap(), + ])) + .unwrap(), } ); a.frobenius_map(1); @@ -756,7 +795,8 @@ fn test_fq2_frobenius_map() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -764,7 +804,8 @@ fn test_fq2_frobenius_map() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837 - ])).unwrap(), + ])) + .unwrap(), } ); a.frobenius_map(2); @@ -778,7 +819,8 @@ fn test_fq2_frobenius_map() { 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0x977df6efcdaee0db, 0x946ae52d684fa7ed, @@ -786,7 +828,8 @@ fn test_fq2_frobenius_map() { 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837 - ])).unwrap(), + ])) + .unwrap(), } ); } @@ -805,7 +848,8 @@ fn test_fq2_sqrt() { 0xdb4a116b5bf74aa1, 0x1e58b2159dfe10e2, 0x7ca7da1f13606ac - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xfa8de88b7516d2c3, 0x371a75ed14f41629, @@ -813,9 +857,11 @@ fn test_fq2_sqrt() { 0x212611bca4e99121, 0x8ee5394d77afb3d, 0xec92336650e49d5 - ])).unwrap(), - }.sqrt() + ])) .unwrap(), + } + .sqrt() + .unwrap(), Fq2 { c0: Fq::from_repr(FqRepr([ 0x40b299b2704258c5, @@ -824,7 +870,8 @@ fn test_fq2_sqrt() { 0x8d7f1f723d02c1d3, 0x881b3e01b611c070, 0x10f6963bbad2ebc5 - ])).unwrap(), + ])) + .unwrap(), c1: Fq::from_repr(FqRepr([ 0xc099534fc209e752, 0x7670594665676447, @@ -832,7 +879,8 @@ fn test_fq2_sqrt() { 0x6b852aeaf2afcb1b, 0xa4c93b08105d71a9, 0x8d7cfff94216330 - ])).unwrap(), + ])) + .unwrap(), } ); @@ -845,10 +893,12 @@ fn test_fq2_sqrt() { 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a - ])).unwrap(), - c1: Fq::zero(), - }.sqrt() + ])) .unwrap(), + c1: Fq::zero(), + } + .sqrt() + .unwrap(), Fq2 { c0: Fq::zero(), c1: Fq::from_repr(FqRepr([ @@ -858,7 +908,8 @@ fn test_fq2_sqrt() { 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a - ])).unwrap(), + ])) + .unwrap(), } ); } diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index dbe58f7..b85c95d 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -17,7 +17,6 @@ impl ::std::fmt::Display for Fq6 { } } - impl Fq6 { /// Multiply by quadratic nonresidue v. pub fn mul_by_nonresidue(&mut self) { diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index cb378f4..018e67a 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -388,22 +388,20 @@ fn test_fr_is_valid() { a.0.sub_noborrow(&FrRepr::from(1)); assert!(a.is_valid()); assert!(Fr(FrRepr::from(0)).is_valid()); - assert!( - Fr(FrRepr([ - 0xffffffff00000000, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48 - ])).is_valid() - ); - assert!( - !Fr(FrRepr([ - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff - ])).is_valid() - ); + assert!(Fr(FrRepr([ + 0xffffffff00000000, + 0x53bda402fffe5bfe, + 0x3339d80809a1d805, + 0x73eda753299d7d48 + ])) + .is_valid()); + assert!(!Fr(FrRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])) + .is_valid()); let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -707,7 +705,8 @@ fn test_fr_squaring() { 0xb79a310579e76ec2, 0xac1da8d0a9af4e5f, 0x13f629c49bf23e97 - ])).unwrap() + ])) + .unwrap() ); let mut rng = XorShiftRng::from_seed([ @@ -857,14 +856,13 @@ fn test_fr_sqrt() { #[test] fn test_fr_from_into_repr() { // r + 1 should not be in the field - assert!( - Fr::from_repr(FrRepr([ - 0xffffffff00000002, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48 - ])).is_err() - ); + assert!(Fr::from_repr(FrRepr([ + 0xffffffff00000002, + 0x53bda402fffe5bfe, + 0x3339d80809a1d805, + 0x73eda753299d7d48 + ])) + .is_err()); // r should not be in the field assert!(Fr::from_repr(Fr::char()).is_err()); @@ -967,7 +965,8 @@ fn test_fr_display() { 0x185ec8eb3f5b5aee, 0x684499ffe4b9dd99, 0x7c9bba7afb68faa - ])).unwrap() + ])) + .unwrap() ), "Fr(0x07c9bba7afb68faa684499ffe4b9dd99185ec8eb3f5b5aeec3cae746a3b5ecc7)".to_string() ); @@ -979,7 +978,8 @@ fn test_fr_display() { 0xb0ad10817df79b6a, 0xd034a80a2b74132b, 0x41cf9a1336f50719 - ])).unwrap() + ])) + .unwrap() ), "Fr(0x41cf9a1336f50719d034a80a2b74132bb0ad10817df79b6a44c71298ff198106)".to_string() ); diff --git a/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index 7bc03c6..deb6ffc 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -9,8 +9,8 @@ mod fr; mod tests; pub use self::ec::{ - G1, G1Affine, G1Compressed, G1Prepared, G1Uncompressed, G2, G2Affine, G2Compressed, G2Prepared, - G2Uncompressed, + G1Affine, G1Compressed, G1Prepared, G1Uncompressed, G2Affine, G2Compressed, G2Prepared, + G2Uncompressed, G1, G2, }; pub use self::fq::{Fq, FqRepr}; pub use self::fq12::Fq12; diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index a81d1a1..952185c 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -37,8 +37,7 @@ pub trait Engine: ScalarEngine { Base = Self::Fq, Scalar = Self::Fr, Affine = Self::G1Affine, - > - + From; + > + From; /// The affine representation of an element in G1. type G1Affine: PairingCurveAffine< @@ -48,8 +47,7 @@ pub trait Engine: ScalarEngine { Projective = Self::G1, Pair = Self::G2Affine, PairingResult = Self::Fqk, - > - + From; + > + From; /// The projective representation of an element in G2. type G2: CurveProjective< @@ -57,8 +55,7 @@ pub trait Engine: ScalarEngine { Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine, - > - + From; + > + From; /// The affine representation of an element in G2. type G2Affine: PairingCurveAffine< @@ -68,8 +65,7 @@ pub trait Engine: ScalarEngine { Projective = Self::G2, Pair = Self::G1Affine, PairingResult = Self::Fqk, - > - + From; + > + From; /// The base field that hosts G1. type Fq: PrimeField + SqrtField; @@ -101,7 +97,8 @@ pub trait Engine: ScalarEngine { { Self::final_exponentiation(&Self::miller_loop( [(&(p.into().prepare()), &(q.into().prepare()))].iter(), - )).unwrap() + )) + .unwrap() } } diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 0a33a73..8f3d8d9 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -117,8 +117,8 @@ pub fn from_str_tests() { { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { From 9a4f6812f1476f465bcff7b7528706f0054f144a Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 15 Aug 2019 10:38:41 -0600 Subject: [PATCH 067/105] cargo fmt bellman --- bellman/src/domain.rs | 101 +- bellman/src/gadgets.rs | 14 +- bellman/src/gadgets/blake2s.rs | 238 ++-- bellman/src/gadgets/boolean.rs | 1203 ++++++++++++--------- bellman/src/gadgets/lookup.rs | 193 ++-- bellman/src/gadgets/multieq.rs | 76 +- bellman/src/gadgets/multipack.rs | 79 +- bellman/src/gadgets/num.rs | 289 +++-- bellman/src/gadgets/sha256.rs | 231 ++-- bellman/src/gadgets/test/mod.rs | 199 ++-- bellman/src/gadgets/uint32.rs | 383 +++---- bellman/src/groth16/generator.rs | 211 ++-- bellman/src/groth16/mod.rs | 322 +++--- bellman/src/groth16/prover.rs | 189 ++-- bellman/src/groth16/tests/dummy_engine.rs | 45 +- bellman/src/groth16/tests/mod.rs | 166 ++- bellman/src/groth16/verifier.rs | 35 +- bellman/src/lib.rs | 180 ++- bellman/src/multicore.rs | 47 +- bellman/src/multiexp.rs | 120 +- bellman/tests/mimc.rs | 96 +- 21 files changed, 2252 insertions(+), 2165 deletions(-) diff --git a/bellman/src/domain.rs b/bellman/src/domain.rs index 5d7d500..808d2af 100644 --- a/bellman/src/domain.rs +++ b/bellman/src/domain.rs @@ -13,9 +13,7 @@ use ff::{Field, PrimeField, ScalarEngine}; use group::CurveProjective; -use super::{ - SynthesisError -}; +use super::SynthesisError; use super::multicore::Worker; @@ -25,7 +23,7 @@ pub struct EvaluationDomain> { omega: E::Fr, omegainv: E::Fr, geninv: E::Fr, - minv: E::Fr + minv: E::Fr, } impl> EvaluationDomain { @@ -41,8 +39,7 @@ impl> EvaluationDomain { self.coeffs } - pub fn from_coeffs(mut coeffs: Vec) -> Result, SynthesisError> - { + pub fn from_coeffs(mut coeffs: Vec) -> Result, SynthesisError> { // Compute the size of our evaluation domain let mut m = 1; let mut exp = 0; @@ -53,7 +50,7 @@ impl> EvaluationDomain { // The pairing-friendly curve may not be able to support // large enough (radix2) evaluation domains. if exp >= E::Fr::S { - return Err(SynthesisError::PolynomialDegreeTooLarge) + return Err(SynthesisError::PolynomialDegreeTooLarge); } } @@ -72,17 +69,18 @@ impl> EvaluationDomain { omega: omega, omegainv: omega.inverse().unwrap(), geninv: E::Fr::multiplicative_generator().inverse().unwrap(), - minv: E::Fr::from_str(&format!("{}", m)).unwrap().inverse().unwrap() + minv: E::Fr::from_str(&format!("{}", m)) + .unwrap() + .inverse() + .unwrap(), }) } - pub fn fft(&mut self, worker: &Worker) - { + pub fn fft(&mut self, worker: &Worker) { best_fft(&mut self.coeffs, worker, &self.omega, self.exp); } - pub fn ifft(&mut self, worker: &Worker) - { + pub fn ifft(&mut self, worker: &Worker) { best_fft(&mut self.coeffs, worker, &self.omegainv, self.exp); worker.scope(self.coeffs.len(), |scope, chunk| { @@ -98,8 +96,7 @@ impl> EvaluationDomain { }); } - pub fn distribute_powers(&mut self, worker: &Worker, g: E::Fr) - { + pub fn distribute_powers(&mut self, worker: &Worker, g: E::Fr) { worker.scope(self.coeffs.len(), |scope, chunk| { for (i, v) in self.coeffs.chunks_mut(chunk).enumerate() { scope.spawn(move || { @@ -113,14 +110,12 @@ impl> EvaluationDomain { }); } - pub fn coset_fft(&mut self, worker: &Worker) - { + pub fn coset_fft(&mut self, worker: &Worker) { self.distribute_powers(worker, E::Fr::multiplicative_generator()); self.fft(worker); } - pub fn icoset_fft(&mut self, worker: &Worker) - { + pub fn icoset_fft(&mut self, worker: &Worker) { let geninv = self.geninv; self.ifft(worker); @@ -139,9 +134,11 @@ impl> EvaluationDomain { /// The target polynomial is the zero polynomial in our /// evaluation domain, so we must perform division over /// a coset. - pub fn divide_by_z_on_coset(&mut self, worker: &Worker) - { - let i = self.z(&E::Fr::multiplicative_generator()).inverse().unwrap(); + pub fn divide_by_z_on_coset(&mut self, worker: &Worker) { + let i = self + .z(&E::Fr::multiplicative_generator()) + .inverse() + .unwrap(); worker.scope(self.coeffs.len(), |scope, chunk| { for v in self.coeffs.chunks_mut(chunk) { @@ -159,7 +156,11 @@ impl> EvaluationDomain { assert_eq!(self.coeffs.len(), other.coeffs.len()); worker.scope(self.coeffs.len(), |scope, chunk| { - for (a, b) in self.coeffs.chunks_mut(chunk).zip(other.coeffs.chunks(chunk)) { + for (a, b) in self + .coeffs + .chunks_mut(chunk) + .zip(other.coeffs.chunks(chunk)) + { scope.spawn(move || { for (a, b) in a.iter_mut().zip(b.iter()) { a.group_mul_assign(&b.0); @@ -174,7 +175,11 @@ impl> EvaluationDomain { assert_eq!(self.coeffs.len(), other.coeffs.len()); worker.scope(self.coeffs.len(), |scope, chunk| { - for (a, b) in self.coeffs.chunks_mut(chunk).zip(other.coeffs.chunks(chunk)) { + for (a, b) in self + .coeffs + .chunks_mut(chunk) + .zip(other.coeffs.chunks(chunk)) + { scope.spawn(move || { for (a, b) in a.iter_mut().zip(b.iter()) { a.group_sub_assign(&b); @@ -200,7 +205,7 @@ impl PartialEq for Point { } } -impl Copy for Point { } +impl Copy for Point {} impl Clone for Point { fn clone(&self) -> Point { @@ -231,7 +236,7 @@ impl PartialEq for Scalar { } } -impl Copy for Scalar { } +impl Copy for Scalar {} impl Clone for Scalar { fn clone(&self) -> Scalar { @@ -254,8 +259,7 @@ impl Group for Scalar { } } -fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32) -{ +fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32) { let log_cpus = worker.log_num_cpus(); if log_n <= log_cpus { @@ -265,8 +269,7 @@ fn best_fft>(a: &mut [T], worker: &Worker, omega: & } } -fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) -{ +fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) { fn bitreverse(mut n: u32, l: u32) -> u32 { let mut r = 0; for _ in 0..l { @@ -288,22 +291,22 @@ fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u let mut m = 1; for _ in 0..log_n { - let w_m = omega.pow(&[(n / (2*m)) as u64]); + let w_m = omega.pow(&[(n / (2 * m)) as u64]); let mut k = 0; while k < n { let mut w = E::Fr::one(); for j in 0..m { - let mut t = a[(k+j+m) as usize]; + let mut t = a[(k + j + m) as usize]; t.group_mul_assign(&w); - let mut tmp = a[(k+j) as usize]; + let mut tmp = a[(k + j) as usize]; tmp.group_sub_assign(&t); - a[(k+j+m) as usize] = tmp; - a[(k+j) as usize].group_add_assign(&t); + a[(k + j + m) as usize] = tmp; + a[(k + j) as usize].group_add_assign(&t); w.mul_assign(&w_m); } - k += 2*m; + k += 2 * m; } m *= 2; @@ -315,9 +318,8 @@ fn parallel_fft>( worker: &Worker, omega: &E::Fr, log_n: u32, - log_cpus: u32 -) -{ + log_cpus: u32, +) { assert!(log_n >= log_cpus); let num_cpus = 1 << log_cpus; @@ -377,14 +379,17 @@ fn polynomial_arith() { use pairing::bls12_381::Bls12; use rand_core::RngCore; - fn test_mul(rng: &mut R) - { + fn test_mul(rng: &mut R) { let worker = Worker::new(); for coeffs_a in 0..70 { for coeffs_b in 0..70 { - let mut a: Vec<_> = (0..coeffs_a).map(|_| Scalar::(E::Fr::random(rng))).collect(); - let mut b: Vec<_> = (0..coeffs_b).map(|_| Scalar::(E::Fr::random(rng))).collect(); + let mut a: Vec<_> = (0..coeffs_a) + .map(|_| Scalar::(E::Fr::random(rng))) + .collect(); + let mut b: Vec<_> = (0..coeffs_b) + .map(|_| Scalar::(E::Fr::random(rng))) + .collect(); // naive evaluation let mut naive = vec![Scalar(E::Fr::zero()); coeffs_a + coeffs_b]; @@ -425,8 +430,7 @@ fn fft_composition() { use pairing::bls12_381::Bls12; use rand_core::RngCore; - fn test_comp(rng: &mut R) - { + fn test_comp(rng: &mut R) { let worker = Worker::new(); for coeffs in 0..10 { @@ -465,19 +469,20 @@ fn parallel_fft_consistency() { use rand_core::RngCore; use std::cmp::min; - fn test_consistency(rng: &mut R) - { + fn test_consistency(rng: &mut R) { let worker = Worker::new(); for _ in 0..5 { for log_d in 0..10 { let d = 1 << log_d; - let v1 = (0..d).map(|_| Scalar::(E::Fr::random(rng))).collect::>(); + let v1 = (0..d) + .map(|_| Scalar::(E::Fr::random(rng))) + .collect::>(); let mut v1 = EvaluationDomain::from_coeffs(v1).unwrap(); let mut v2 = EvaluationDomain::from_coeffs(v1.coeffs.clone()).unwrap(); - for log_cpus in log_d..min(log_d+1, 3) { + for log_cpus in log_d..min(log_d + 1, 3) { parallel_fft(&mut v1.coeffs, &worker, &v1.omega, log_d, log_cpus); serial_fft(&mut v2.coeffs, &v2.omega, log_d); diff --git a/bellman/src/gadgets.rs b/bellman/src/gadgets.rs index 6c4b09c..cf366df 100644 --- a/bellman/src/gadgets.rs +++ b/bellman/src/gadgets.rs @@ -1,17 +1,15 @@ pub mod test; -pub mod boolean; -pub mod multieq; -pub mod uint32; pub mod blake2s; -pub mod num; +pub mod boolean; pub mod lookup; +pub mod multieq; pub mod multipack; +pub mod num; pub mod sha256; +pub mod uint32; -use crate::{ - SynthesisError -}; +use crate::SynthesisError; // TODO: This should probably be removed and we // should use existing helper methods on `Option` @@ -27,7 +25,7 @@ impl Assignment for Option { fn get(&self) -> Result<&T, SynthesisError> { match *self { Some(ref v) => Ok(v), - None => Err(SynthesisError::AssignmentMissing) + None => Err(SynthesisError::AssignmentMissing), } } } diff --git a/bellman/src/gadgets/blake2s.rs b/bellman/src/gadgets/blake2s.rs index cef50eb..c5cee23 100644 --- a/bellman/src/gadgets/blake2s.rs +++ b/bellman/src/gadgets/blake2s.rs @@ -1,19 +1,10 @@ -use pairing::{ - Engine, -}; +use pairing::Engine; -use crate::{ - SynthesisError, - ConstraintSystem -}; +use crate::{ConstraintSystem, SynthesisError}; -use super::boolean::{ - Boolean -}; +use super::boolean::Boolean; -use super::uint32::{ - UInt32 -}; +use super::uint32::UInt32; use super::multieq::MultiEq; @@ -65,7 +56,7 @@ const SIGMA: [[usize; 16]; 10] = [ [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0] + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], ]; /* @@ -98,17 +89,30 @@ fn mixing_g, M>( c: usize, d: usize, x: &UInt32, - y: &UInt32 + y: &UInt32, ) -> Result<(), SynthesisError> - where M: ConstraintSystem> +where + M: ConstraintSystem>, { - v[a] = UInt32::addmany(cs.namespace(|| "mixing step 1"), &[v[a].clone(), v[b].clone(), x.clone()])?; + v[a] = UInt32::addmany( + cs.namespace(|| "mixing step 1"), + &[v[a].clone(), v[b].clone(), x.clone()], + )?; v[d] = v[d].xor(cs.namespace(|| "mixing step 2"), &v[a])?.rotr(R1); - v[c] = UInt32::addmany(cs.namespace(|| "mixing step 3"), &[v[c].clone(), v[d].clone()])?; + v[c] = UInt32::addmany( + cs.namespace(|| "mixing step 3"), + &[v[c].clone(), v[d].clone()], + )?; v[b] = v[b].xor(cs.namespace(|| "mixing step 4"), &v[c])?.rotr(R2); - v[a] = UInt32::addmany(cs.namespace(|| "mixing step 5"), &[v[a].clone(), v[b].clone(), y.clone()])?; + v[a] = UInt32::addmany( + cs.namespace(|| "mixing step 5"), + &[v[a].clone(), v[b].clone(), y.clone()], + )?; v[d] = v[d].xor(cs.namespace(|| "mixing step 6"), &v[a])?.rotr(R3); - v[c] = UInt32::addmany(cs.namespace(|| "mixing step 7"), &[v[c].clone(), v[d].clone()])?; + v[c] = UInt32::addmany( + cs.namespace(|| "mixing step 7"), + &[v[c].clone(), v[d].clone()], + )?; v[b] = v[b].xor(cs.namespace(|| "mixing step 8"), &v[c])?.rotr(R4); Ok(()) @@ -162,15 +166,13 @@ fn mixing_g, M>( END FUNCTION. */ - fn blake2s_compression>( mut cs: CS, h: &mut [UInt32], m: &[UInt32], t: u64, - f: bool -) -> Result<(), SynthesisError> -{ + f: bool, +) -> Result<(), SynthesisError> { assert_eq!(h.len(), 8); assert_eq!(m.len(), 16); @@ -196,10 +198,16 @@ fn blake2s_compression>( assert_eq!(v.len(), 16); v[12] = v[12].xor(cs.namespace(|| "first xor"), &UInt32::constant(t as u32))?; - v[13] = v[13].xor(cs.namespace(|| "second xor"), &UInt32::constant((t >> 32) as u32))?; + v[13] = v[13].xor( + cs.namespace(|| "second xor"), + &UInt32::constant((t >> 32) as u32), + )?; if f { - v[14] = v[14].xor(cs.namespace(|| "third xor"), &UInt32::constant(u32::max_value()))?; + v[14] = v[14].xor( + cs.namespace(|| "third xor"), + &UInt32::constant(u32::max_value()), + )?; } { @@ -210,20 +218,92 @@ fn blake2s_compression>( let s = SIGMA[i % 10]; - mixing_g(cs.namespace(|| "mixing invocation 1"), &mut v, 0, 4, 8, 12, &m[s[ 0]], &m[s[ 1]])?; - mixing_g(cs.namespace(|| "mixing invocation 2"), &mut v, 1, 5, 9, 13, &m[s[ 2]], &m[s[ 3]])?; - mixing_g(cs.namespace(|| "mixing invocation 3"), &mut v, 2, 6, 10, 14, &m[s[ 4]], &m[s[ 5]])?; - mixing_g(cs.namespace(|| "mixing invocation 4"), &mut v, 3, 7, 11, 15, &m[s[ 6]], &m[s[ 7]])?; + mixing_g( + cs.namespace(|| "mixing invocation 1"), + &mut v, + 0, + 4, + 8, + 12, + &m[s[0]], + &m[s[1]], + )?; + mixing_g( + cs.namespace(|| "mixing invocation 2"), + &mut v, + 1, + 5, + 9, + 13, + &m[s[2]], + &m[s[3]], + )?; + mixing_g( + cs.namespace(|| "mixing invocation 3"), + &mut v, + 2, + 6, + 10, + 14, + &m[s[4]], + &m[s[5]], + )?; + mixing_g( + cs.namespace(|| "mixing invocation 4"), + &mut v, + 3, + 7, + 11, + 15, + &m[s[6]], + &m[s[7]], + )?; - mixing_g(cs.namespace(|| "mixing invocation 5"), &mut v, 0, 5, 10, 15, &m[s[ 8]], &m[s[ 9]])?; - mixing_g(cs.namespace(|| "mixing invocation 6"), &mut v, 1, 6, 11, 12, &m[s[10]], &m[s[11]])?; - mixing_g(cs.namespace(|| "mixing invocation 7"), &mut v, 2, 7, 8, 13, &m[s[12]], &m[s[13]])?; - mixing_g(cs.namespace(|| "mixing invocation 8"), &mut v, 3, 4, 9, 14, &m[s[14]], &m[s[15]])?; + mixing_g( + cs.namespace(|| "mixing invocation 5"), + &mut v, + 0, + 5, + 10, + 15, + &m[s[8]], + &m[s[9]], + )?; + mixing_g( + cs.namespace(|| "mixing invocation 6"), + &mut v, + 1, + 6, + 11, + 12, + &m[s[10]], + &m[s[11]], + )?; + mixing_g( + cs.namespace(|| "mixing invocation 7"), + &mut v, + 2, + 7, + 8, + 13, + &m[s[12]], + &m[s[13]], + )?; + mixing_g( + cs.namespace(|| "mixing invocation 8"), + &mut v, + 3, + 4, + 9, + 14, + &m[s[14]], + &m[s[15]], + )?; } } for i in 0..8 { - let mut cs = cs.namespace(|| format!("h[{i}] ^ v[{i}] ^ v[{i} + 8]", i=i)); + let mut cs = cs.namespace(|| format!("h[{i}] ^ v[{i}] ^ v[{i} + 8]", i = i)); h[i] = h[i].xor(cs.namespace(|| "first xor"), &v[i])?; h[i] = h[i].xor(cs.namespace(|| "second xor"), &v[i + 8])?; @@ -262,9 +342,8 @@ fn blake2s_compression>( pub fn blake2s>( mut cs: CS, input: &[Boolean], - personalization: &[u8] -) -> Result, SynthesisError> -{ + personalization: &[u8], +) -> Result, SynthesisError> { use byteorder::{ByteOrder, LittleEndian}; assert_eq!(personalization.len(), 8); @@ -279,8 +358,12 @@ pub fn blake2s>( h.push(UInt32::constant(0x9B05688C)); // Personalization is stored here - h.push(UInt32::constant(0x1F83D9AB ^ LittleEndian::read_u32(&personalization[0..4]))); - h.push(UInt32::constant(0x5BE0CD19 ^ LittleEndian::read_u32(&personalization[4..8]))); + h.push(UInt32::constant( + 0x1F83D9AB ^ LittleEndian::read_u32(&personalization[0..4]), + )); + h.push(UInt32::constant( + 0x5BE0CD19 ^ LittleEndian::read_u32(&personalization[4..8]), + )); let mut blocks: Vec> = vec![]; @@ -312,7 +395,13 @@ pub fn blake2s>( { let cs = cs.namespace(|| "final block"); - blake2s_compression(cs, &mut h, &blocks[blocks.len() - 1], (input.len() / 8) as u64, true)?; + blake2s_compression( + cs, + &mut h, + &blocks[blocks.len() - 1], + (input.len() / 8) as u64, + true, + )?; } Ok(h.iter().flat_map(|b| b.into_bits()).collect()) @@ -321,14 +410,14 @@ pub fn blake2s>( #[cfg(test)] mod test { use blake2s_simd::Params as Blake2sParams; - use pairing::bls12_381::{Bls12}; + use pairing::bls12_381::Bls12; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use crate::gadgets::boolean::{Boolean, AllocatedBit}; - use crate::gadgets::test::TestConstraintSystem; use super::blake2s; - use crate::{ConstraintSystem}; + use crate::gadgets::boolean::{AllocatedBit, Boolean}; + use crate::gadgets::test::TestConstraintSystem; + use crate::ConstraintSystem; #[test] fn test_blank_hash() { @@ -356,7 +445,13 @@ mod test { #[test] fn test_blake2s_constraints() { let mut cs = TestConstraintSystem::::new(); - let input_bits: Vec<_> = (0..512).map(|i| AllocatedBit::alloc(cs.namespace(|| format!("input bit {}", i)), Some(true)).unwrap().into()).collect(); + let input_bits: Vec<_> = (0..512) + .map(|i| { + AllocatedBit::alloc(cs.namespace(|| format!("input bit {}", i)), Some(true)) + .unwrap() + .into() + }) + .collect(); blake2s(&mut cs, &input_bits, b"12345678").unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 21518); @@ -369,14 +464,17 @@ mod test { let mut cs = TestConstraintSystem::::new(); let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let input_bits: Vec<_> = (0..512) - .map(|_| Boolean::constant(rng.next_u32() % 2 != 0)) - .chain((0..512) - .map(|i| AllocatedBit::alloc(cs.namespace(|| format!("input bit {}", i)), Some(true)).unwrap().into())) - .collect(); + .map(|_| Boolean::constant(rng.next_u32() % 2 != 0)) + .chain((0..512).map(|i| { + AllocatedBit::alloc(cs.namespace(|| format!("input bit {}", i)), Some(true)) + .unwrap() + .into() + })) + .collect(); blake2s(&mut cs, &input_bits, b"12345678").unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 21518); @@ -386,10 +484,12 @@ mod test { fn test_blake2s_constant_constraints() { let mut cs = TestConstraintSystem::::new(); let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); - let input_bits: Vec<_> = (0..512).map(|_| Boolean::constant(rng.next_u32() % 2 != 0)).collect(); + let input_bits: Vec<_> = (0..512) + .map(|_| Boolean::constant(rng.next_u32() % 2 != 0)) + .collect(); blake2s(&mut cs, &input_bits, b"12345678").unwrap(); assert_eq!(cs.num_constraints(), 0); } @@ -397,13 +497,15 @@ mod test { #[test] fn test_blake2s() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); - for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) - { - let mut h = Blake2sParams::new().hash_length(32).personal(b"12345678").to_state(); + for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { + let mut h = Blake2sParams::new() + .hash_length(32) + .personal(b"12345678") + .to_state(); let data: Vec = (0..input_len).map(|_| rng.next_u32() as u8).collect(); @@ -419,7 +521,11 @@ mod test { for bit_i in 0..8 { let cs = cs.namespace(|| format!("input bit {} {}", byte_i, bit_i)); - input_bits.push(AllocatedBit::alloc(cs, Some((input_byte >> bit_i) & 1u8 == 1u8)).unwrap().into()); + input_bits.push( + AllocatedBit::alloc(cs, Some((input_byte >> bit_i) & 1u8 == 1u8)) + .unwrap() + .into(), + ); } } @@ -427,17 +533,19 @@ mod test { assert!(cs.is_satisfied()); - let mut s = hash_result.as_ref().iter() - .flat_map(|&byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8)); + let mut s = hash_result + .as_ref() + .iter() + .flat_map(|&byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8)); for b in r { match b { Boolean::Is(b) => { assert!(s.next().unwrap() == b.get_value().unwrap()); - }, + } Boolean::Not(b) => { assert!(s.next().unwrap() != b.get_value().unwrap()); - }, + } Boolean::Constant(b) => { assert!(input_len == 0); assert!(s.next().unwrap() == b); diff --git a/bellman/src/gadgets/boolean.rs b/bellman/src/gadgets/boolean.rs index f6c11b6..414b290 100644 --- a/bellman/src/gadgets/boolean.rs +++ b/bellman/src/gadgets/boolean.rs @@ -1,23 +1,16 @@ use ff::{BitIterator, Field, PrimeField}; use pairing::Engine; -use crate::{ - ConstraintSystem, - SynthesisError, - LinearCombination, - Variable -}; +use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable}; -use super::{ - Assignment -}; +use super::Assignment; /// Represents a variable in the constraint system which is guaranteed /// to be either zero or one. #[derive(Clone)] pub struct AllocatedBit { variable: Variable, - value: Option + value: Option, } impl AllocatedBit { @@ -35,18 +28,22 @@ impl AllocatedBit { pub fn alloc_conditionally( mut cs: CS, value: Option, - must_be_false: &AllocatedBit + must_be_false: &AllocatedBit, ) -> Result - where E: Engine, - CS: ConstraintSystem + where + E: Engine, + CS: ConstraintSystem, { - let var = cs.alloc(|| "boolean", || { - if *value.get()? { - Ok(E::Fr::one()) - } else { - Ok(E::Fr::zero()) - } - })?; + let var = cs.alloc( + || "boolean", + || { + if *value.get()? { + Ok(E::Fr::one()) + } else { + Ok(E::Fr::zero()) + } + }, + )?; // Constrain: (1 - must_be_false - a) * a = 0 // if must_be_false is true, the equation @@ -58,31 +55,32 @@ impl AllocatedBit { || "boolean constraint", |lc| lc + CS::one() - must_be_false.variable - var, |lc| lc + var, - |lc| lc + |lc| lc, ); Ok(AllocatedBit { variable: var, - value: value + value: value, }) } /// Allocate a variable in the constraint system which can only be a /// boolean value. - pub fn alloc( - mut cs: CS, - value: Option, - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn alloc(mut cs: CS, value: Option) -> Result + where + E: Engine, + CS: ConstraintSystem, { - let var = cs.alloc(|| "boolean", || { - if *value.get()? { - Ok(E::Fr::one()) - } else { - Ok(E::Fr::zero()) - } - })?; + let var = cs.alloc( + || "boolean", + || { + if *value.get()? { + Ok(E::Fr::one()) + } else { + Ok(E::Fr::zero()) + } + }, + )?; // Constrain: (1 - a) * a = 0 // This constrains a to be either 0 or 1. @@ -90,38 +88,38 @@ impl AllocatedBit { || "boolean constraint", |lc| lc + CS::one() - var, |lc| lc + var, - |lc| lc + |lc| lc, ); Ok(AllocatedBit { variable: var, - value: value + value: value, }) } /// Performs an XOR operation over the two operands, returning /// an `AllocatedBit`. - pub fn xor( - mut cs: CS, - a: &Self, - b: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn xor(mut cs: CS, a: &Self, b: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { let mut result_value = None; - let result_var = cs.alloc(|| "xor result", || { - if *a.value.get()? ^ *b.value.get()? { - result_value = Some(true); + let result_var = cs.alloc( + || "xor result", + || { + if *a.value.get()? ^ *b.value.get()? { + result_value = Some(true); - Ok(E::Fr::one()) - } else { - result_value = Some(false); + Ok(E::Fr::one()) + } else { + result_value = Some(false); - Ok(E::Fr::zero()) - } - })?; + Ok(E::Fr::zero()) + } + }, + )?; // Constrain (a + a) * (b) = (a + b - c) // Given that a and b are boolean constrained, if they @@ -142,38 +140,38 @@ impl AllocatedBit { || "xor constraint", |lc| lc + a.variable + a.variable, |lc| lc + b.variable, - |lc| lc + a.variable + b.variable - result_var + |lc| lc + a.variable + b.variable - result_var, ); Ok(AllocatedBit { variable: result_var, - value: result_value + value: result_value, }) } /// Performs an AND operation over the two operands, returning /// an `AllocatedBit`. - pub fn and( - mut cs: CS, - a: &Self, - b: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn and(mut cs: CS, a: &Self, b: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { let mut result_value = None; - let result_var = cs.alloc(|| "and result", || { - if *a.value.get()? & *b.value.get()? { - result_value = Some(true); + let result_var = cs.alloc( + || "and result", + || { + if *a.value.get()? & *b.value.get()? { + result_value = Some(true); - Ok(E::Fr::one()) - } else { - result_value = Some(false); + Ok(E::Fr::one()) + } else { + result_value = Some(false); - Ok(E::Fr::zero()) - } - })?; + Ok(E::Fr::zero()) + } + }, + )?; // Constrain (a) * (b) = (c), ensuring c is 1 iff // a AND b are both 1. @@ -181,37 +179,37 @@ impl AllocatedBit { || "and constraint", |lc| lc + a.variable, |lc| lc + b.variable, - |lc| lc + result_var + |lc| lc + result_var, ); Ok(AllocatedBit { variable: result_var, - value: result_value + value: result_value, }) } /// Calculates `a AND (NOT b)`. - pub fn and_not( - mut cs: CS, - a: &Self, - b: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn and_not(mut cs: CS, a: &Self, b: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { let mut result_value = None; - let result_var = cs.alloc(|| "and not result", || { - if *a.value.get()? & !*b.value.get()? { - result_value = Some(true); + let result_var = cs.alloc( + || "and not result", + || { + if *a.value.get()? & !*b.value.get()? { + result_value = Some(true); - Ok(E::Fr::one()) - } else { - result_value = Some(false); + Ok(E::Fr::one()) + } else { + result_value = Some(false); - Ok(E::Fr::zero()) - } - })?; + Ok(E::Fr::zero()) + } + }, + )?; // Constrain (a) * (1 - b) = (c), ensuring c is 1 iff // a is true and b is false, and otherwise c is 0. @@ -219,37 +217,37 @@ impl AllocatedBit { || "and not constraint", |lc| lc + a.variable, |lc| lc + CS::one() - b.variable, - |lc| lc + result_var + |lc| lc + result_var, ); Ok(AllocatedBit { variable: result_var, - value: result_value + value: result_value, }) } /// Calculates `(NOT a) AND (NOT b)`. - pub fn nor( - mut cs: CS, - a: &Self, - b: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn nor(mut cs: CS, a: &Self, b: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { let mut result_value = None; - let result_var = cs.alloc(|| "nor result", || { - if !*a.value.get()? & !*b.value.get()? { - result_value = Some(true); + let result_var = cs.alloc( + || "nor result", + || { + if !*a.value.get()? & !*b.value.get()? { + result_value = Some(true); - Ok(E::Fr::one()) - } else { - result_value = Some(false); + Ok(E::Fr::one()) + } else { + result_value = Some(false); - Ok(E::Fr::zero()) - } - })?; + Ok(E::Fr::zero()) + } + }, + )?; // Constrain (1 - a) * (1 - b) = (c), ensuring c is 1 iff // a and b are both false, and otherwise c is 0. @@ -257,21 +255,20 @@ impl AllocatedBit { || "nor constraint", |lc| lc + CS::one() - a.variable, |lc| lc + CS::one() - b.variable, - |lc| lc + result_var + |lc| lc + result_var, ); Ok(AllocatedBit { variable: result_var, - value: result_value + value: result_value, }) } } pub fn u64_into_boolean_vec_le>( mut cs: CS, - value: Option -) -> Result, SynthesisError> -{ + value: Option, +) -> Result, SynthesisError> { let values = match value { Some(ref value) => { let mut tmp = Vec::with_capacity(64); @@ -281,27 +278,28 @@ pub fn u64_into_boolean_vec_le>( } tmp - }, - None => { - vec![None; 64] } + None => vec![None; 64], }; - let bits = values.into_iter().enumerate().map(|(i, b)| { - Ok(Boolean::from(AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - b - )?)) - }).collect::, SynthesisError>>()?; + let bits = values + .into_iter() + .enumerate() + .map(|(i, b)| { + Ok(Boolean::from(AllocatedBit::alloc( + cs.namespace(|| format!("bit {}", i)), + b, + )?)) + }) + .collect::, SynthesisError>>()?; Ok(bits) } pub fn field_into_boolean_vec_le, F: PrimeField>( cs: CS, - value: Option -) -> Result, SynthesisError> -{ + value: Option, +) -> Result, SynthesisError> { let v = field_into_allocated_bits_le::(cs, value)?; Ok(v.into_iter().map(|e| Boolean::from(e)).collect()) @@ -309,9 +307,8 @@ pub fn field_into_boolean_vec_le, F: PrimeFie pub fn field_into_allocated_bits_le, F: PrimeField>( mut cs: CS, - value: Option -) -> Result, SynthesisError> -{ + value: Option, +) -> Result, SynthesisError> { // Deconstruct in big-endian bit order let values = match value { Some(ref value) => { @@ -333,19 +330,17 @@ pub fn field_into_allocated_bits_le, F: Prime assert_eq!(tmp.len(), F::NUM_BITS as usize); tmp - }, - None => { - vec![None; F::NUM_BITS as usize] } + None => vec![None; F::NUM_BITS as usize], }; // Allocate in little-endian order - let bits = values.into_iter().rev().enumerate().map(|(i, b)| { - AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - b - ) - }).collect::, SynthesisError>>()?; + let bits = values + .into_iter() + .rev() + .enumerate() + .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("bit {}", i)), b)) + .collect::, SynthesisError>>()?; Ok(bits) } @@ -359,24 +354,21 @@ pub enum Boolean { /// Negated view of the boolean variable Not(AllocatedBit), /// Constant (not an allocated variable) - Constant(bool) + Constant(bool), } impl Boolean { pub fn is_constant(&self) -> bool { match *self { Boolean::Constant(_) => true, - _ => false + _ => false, } } - pub fn enforce_equal( - mut cs: CS, - a: &Self, - b: &Self - ) -> Result<(), SynthesisError> - where E: Engine, - CS: ConstraintSystem + pub fn enforce_equal(mut cs: CS, a: &Self, b: &Self) -> Result<(), SynthesisError> + where + E: Engine, + CS: ConstraintSystem, { match (a, b) { (&Boolean::Constant(a), &Boolean::Constant(b)) => { @@ -385,33 +377,33 @@ impl Boolean { } else { Err(SynthesisError::Unsatisfiable) } - }, + } (&Boolean::Constant(true), a) | (a, &Boolean::Constant(true)) => { cs.enforce( || "enforce equal to one", |lc| lc, |lc| lc, - |lc| lc + CS::one() - &a.lc(CS::one(), E::Fr::one()) + |lc| lc + CS::one() - &a.lc(CS::one(), E::Fr::one()), ); Ok(()) - }, + } (&Boolean::Constant(false), a) | (a, &Boolean::Constant(false)) => { cs.enforce( || "enforce equal to zero", |lc| lc, |lc| lc, - |_| a.lc(CS::one(), E::Fr::one()) + |_| a.lc(CS::one(), E::Fr::one()), ); Ok(()) - }, + } (a, b) => { cs.enforce( || "enforce equal", |lc| lc, |lc| lc, - |_| a.lc(CS::one(), E::Fr::one()) - &b.lc(CS::one(), E::Fr::one()) + |_| a.lc(CS::one(), E::Fr::one()) - &b.lc(CS::one(), E::Fr::one()), ); Ok(()) @@ -423,16 +415,11 @@ impl Boolean { match self { &Boolean::Constant(c) => Some(c), &Boolean::Is(ref v) => v.get_value(), - &Boolean::Not(ref v) => v.get_value().map(|b| !b) + &Boolean::Not(ref v) => v.get_value().map(|b| !b), } } - pub fn lc( - &self, - one: Variable, - coeff: E::Fr - ) -> LinearCombination - { + pub fn lc(&self, one: Variable, coeff: E::Fr) -> LinearCombination { match self { &Boolean::Constant(c) => { if c { @@ -440,10 +427,8 @@ impl Boolean { } else { LinearCombination::::zero() } - }, - &Boolean::Is(ref v) => { - LinearCombination::::zero() + (coeff, v.get_variable()) - }, + } + &Boolean::Is(ref v) => LinearCombination::::zero() + (coeff, v.get_variable()), &Boolean::Not(ref v) => { LinearCombination::::zero() + (coeff, one) - (coeff, v.get_variable()) } @@ -460,59 +445,54 @@ impl Boolean { match self { &Boolean::Constant(c) => Boolean::Constant(!c), &Boolean::Is(ref v) => Boolean::Not(v.clone()), - &Boolean::Not(ref v) => Boolean::Is(v.clone()) + &Boolean::Not(ref v) => Boolean::Is(v.clone()), } } /// Perform XOR over two boolean operands - pub fn xor<'a, E, CS>( - cs: CS, - a: &'a Self, - b: &'a Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn xor<'a, E, CS>(cs: CS, a: &'a Self, b: &'a Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { match (a, b) { (&Boolean::Constant(false), x) | (x, &Boolean::Constant(false)) => Ok(x.clone()), (&Boolean::Constant(true), x) | (x, &Boolean::Constant(true)) => Ok(x.not()), // a XOR (NOT b) = NOT(a XOR b) - (is @ &Boolean::Is(_), not @ &Boolean::Not(_)) | (not @ &Boolean::Not(_), is @ &Boolean::Is(_)) => { - Ok(Boolean::xor( - cs, - is, - ¬.not() - )?.not()) - }, + (is @ &Boolean::Is(_), not @ &Boolean::Not(_)) + | (not @ &Boolean::Not(_), is @ &Boolean::Is(_)) => { + Ok(Boolean::xor(cs, is, ¬.not())?.not()) + } // a XOR b = (NOT a) XOR (NOT b) - (&Boolean::Is(ref a), &Boolean::Is(ref b)) | (&Boolean::Not(ref a), &Boolean::Not(ref b)) => { + (&Boolean::Is(ref a), &Boolean::Is(ref b)) + | (&Boolean::Not(ref a), &Boolean::Not(ref b)) => { Ok(Boolean::Is(AllocatedBit::xor(cs, a, b)?)) } } } /// Perform AND over two boolean operands - pub fn and<'a, E, CS>( - cs: CS, - a: &'a Self, - b: &'a Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn and<'a, E, CS>(cs: CS, a: &'a Self, b: &'a Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { match (a, b) { // false AND x is always false - (&Boolean::Constant(false), _) | (_, &Boolean::Constant(false)) => Ok(Boolean::Constant(false)), + (&Boolean::Constant(false), _) | (_, &Boolean::Constant(false)) => { + Ok(Boolean::Constant(false)) + } // true AND x is always x (&Boolean::Constant(true), x) | (x, &Boolean::Constant(true)) => Ok(x.clone()), // a AND (NOT b) - (&Boolean::Is(ref is), &Boolean::Not(ref not)) | (&Boolean::Not(ref not), &Boolean::Is(ref is)) => { + (&Boolean::Is(ref is), &Boolean::Not(ref not)) + | (&Boolean::Not(ref not), &Boolean::Is(ref is)) => { Ok(Boolean::Is(AllocatedBit::and_not(cs, is, not)?)) - }, + } // (NOT a) AND (NOT b) = a NOR b (&Boolean::Not(ref a), &Boolean::Not(ref b)) => { Ok(Boolean::Is(AllocatedBit::nor(cs, a, b)?)) - }, + } // a AND b (&Boolean::Is(ref a), &Boolean::Is(ref b)) => { Ok(Boolean::Is(AllocatedBit::and(cs, a, b)?)) @@ -525,27 +505,26 @@ impl Boolean { mut cs: CS, a: &'a Self, b: &'a Self, - c: &'a Self + c: &'a Self, ) -> Result - where E: Engine, - CS: ConstraintSystem + where + E: Engine, + CS: ConstraintSystem, { let ch_value = match (a.get_value(), b.get_value(), c.get_value()) { (Some(a), Some(b), Some(c)) => { // (a and b) xor ((not a) and c) Some((a & b) ^ ((!a) & c)) - }, - _ => None + } + _ => None, }; match (a, b, c) { - (&Boolean::Constant(_), - &Boolean::Constant(_), - &Boolean::Constant(_)) => { + (&Boolean::Constant(_), &Boolean::Constant(_), &Boolean::Constant(_)) => { // They're all constants, so we can just compute the value. return Ok(Boolean::Constant(ch_value.expect("they're all constants"))); - }, + } (&Boolean::Constant(false), _, c) => { // If a is false // (a and b) xor ((not a) and c) @@ -554,29 +533,21 @@ impl Boolean { // equals // c return Ok(c.clone()); - }, + } (a, &Boolean::Constant(false), c) => { // If b is false // (a and b) xor ((not a) and c) // equals // ((not a) and c) - return Boolean::and( - cs, - &a.not(), - &c - ); - }, + return Boolean::and(cs, &a.not(), &c); + } (a, b, &Boolean::Constant(false)) => { // If c is false // (a and b) xor ((not a) and c) // equals // (a and b) - return Boolean::and( - cs, - &a, - &b - ); - }, + return Boolean::and(cs, &a, &b); + } (a, b, &Boolean::Constant(true)) => { // If c is true // (a and b) xor ((not a) and c) @@ -584,12 +555,8 @@ impl Boolean { // (a and b) xor (not a) // equals // not (a and (not b)) - return Ok(Boolean::and( - cs, - &a, - &b.not() - )?.not()); - }, + return Ok(Boolean::and(cs, &a, &b.not())?.not()); + } (a, &Boolean::Constant(true), c) => { // If b is true // (a and b) xor ((not a) and c) @@ -597,53 +564,47 @@ impl Boolean { // a xor ((not a) and c) // equals // not ((not a) and (not c)) - return Ok(Boolean::and( - cs, - &a.not(), - &c.not() - )?.not()); - }, + return Ok(Boolean::and(cs, &a.not(), &c.not())?.not()); + } (&Boolean::Constant(true), _, _) => { // If a is true // (a and b) xor ((not a) and c) // equals // b xor ((not a) and c) // So we just continue! - }, - (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Is(_)) | - (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Not(_)) | - (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Is(_)) | - (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Not(_)) | - (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Is(_)) | - (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Not(_)) | - (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Is(_)) | - (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Not(_)) - => {} + } + (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Is(_)) + | (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Not(_)) + | (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Is(_)) + | (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Not(_)) + | (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Is(_)) + | (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Not(_)) + | (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Is(_)) + | (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Not(_)) => {} } - let ch = cs.alloc(|| "ch", || { - ch_value.get().map(|v| { - if *v { - E::Fr::one() - } else { - E::Fr::zero() - } - }) - })?; + let ch = cs.alloc( + || "ch", + || { + ch_value + .get() + .map(|v| if *v { E::Fr::one() } else { E::Fr::zero() }) + }, + )?; // a(b - c) = ch - c cs.enforce( || "ch computation", - |_| b.lc(CS::one(), E::Fr::one()) - - &c.lc(CS::one(), E::Fr::one()), + |_| b.lc(CS::one(), E::Fr::one()) - &c.lc(CS::one(), E::Fr::one()), |_| a.lc(CS::one(), E::Fr::one()), - |lc| lc + ch - &c.lc(CS::one(), E::Fr::one()) + |lc| lc + ch - &c.lc(CS::one(), E::Fr::one()), ); Ok(AllocatedBit { value: ch_value, - variable: ch - }.into()) + variable: ch, + } + .into()) } /// Computes (a and b) xor (a and c) xor (b and c) @@ -653,58 +614,45 @@ impl Boolean { b: &'a Self, c: &'a Self, ) -> Result - where E: Engine, - CS: ConstraintSystem + where + E: Engine, + CS: ConstraintSystem, { let maj_value = match (a.get_value(), b.get_value(), c.get_value()) { (Some(a), Some(b), Some(c)) => { // (a and b) xor (a and c) xor (b and c) Some((a & b) ^ (a & c) ^ (b & c)) - }, - _ => None + } + _ => None, }; match (a, b, c) { - (&Boolean::Constant(_), - &Boolean::Constant(_), - &Boolean::Constant(_)) => { + (&Boolean::Constant(_), &Boolean::Constant(_), &Boolean::Constant(_)) => { // They're all constants, so we can just compute the value. return Ok(Boolean::Constant(maj_value.expect("they're all constants"))); - }, + } (&Boolean::Constant(false), b, c) => { // If a is false, // (a and b) xor (a and c) xor (b and c) // equals // (b and c) - return Boolean::and( - cs, - b, - c - ); - }, + return Boolean::and(cs, b, c); + } (a, &Boolean::Constant(false), c) => { // If b is false, // (a and b) xor (a and c) xor (b and c) // equals // (a and c) - return Boolean::and( - cs, - a, - c - ); - }, + return Boolean::and(cs, a, c); + } (a, b, &Boolean::Constant(false)) => { // If c is false, // (a and b) xor (a and c) xor (b and c) // equals // (a and b) - return Boolean::and( - cs, - a, - b - ); - }, + return Boolean::and(cs, a, b); + } (a, b, &Boolean::Constant(true)) => { // If c is true, // (a and b) xor (a and c) xor (b and c) @@ -712,54 +660,40 @@ impl Boolean { // (a and b) xor (a) xor (b) // equals // not ((not a) and (not b)) - return Ok(Boolean::and( - cs, - &a.not(), - &b.not() - )?.not()); - }, + return Ok(Boolean::and(cs, &a.not(), &b.not())?.not()); + } (a, &Boolean::Constant(true), c) => { // If b is true, // (a and b) xor (a and c) xor (b and c) // equals // (a) xor (a and c) xor (c) - return Ok(Boolean::and( - cs, - &a.not(), - &c.not() - )?.not()); - }, + return Ok(Boolean::and(cs, &a.not(), &c.not())?.not()); + } (&Boolean::Constant(true), b, c) => { // If a is true, // (a and b) xor (a and c) xor (b and c) // equals // (b) xor (c) xor (b and c) - return Ok(Boolean::and( - cs, - &b.not(), - &c.not() - )?.not()); - }, - (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Is(_)) | - (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Not(_)) | - (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Is(_)) | - (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Not(_)) | - (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Is(_)) | - (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Not(_)) | - (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Is(_)) | - (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Not(_)) - => {} + return Ok(Boolean::and(cs, &b.not(), &c.not())?.not()); + } + (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Is(_)) + | (&Boolean::Is(_), &Boolean::Is(_), &Boolean::Not(_)) + | (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Is(_)) + | (&Boolean::Is(_), &Boolean::Not(_), &Boolean::Not(_)) + | (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Is(_)) + | (&Boolean::Not(_), &Boolean::Is(_), &Boolean::Not(_)) + | (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Is(_)) + | (&Boolean::Not(_), &Boolean::Not(_), &Boolean::Not(_)) => {} } - let maj = cs.alloc(|| "maj", || { - maj_value.get().map(|v| { - if *v { - E::Fr::one() - } else { - E::Fr::zero() - } - }) - })?; + let maj = cs.alloc( + || "maj", + || { + maj_value + .get() + .map(|v| if *v { E::Fr::one() } else { E::Fr::zero() }) + }, + )?; // ¬(¬a ∧ ¬b) ∧ ¬(¬a ∧ ¬c) ∧ ¬(¬b ∧ ¬c) // (1 - ((1 - a) * (1 - b))) * (1 - ((1 - a) * (1 - c))) * (1 - ((1 - b) * (1 - c))) @@ -770,26 +704,24 @@ impl Boolean { // (b) * (c) = (bc) // (2bc - b - c) * (a) = bc - maj - let bc = Self::and( - cs.namespace(|| "b and c"), - b, - c - )?; + let bc = Self::and(cs.namespace(|| "b and c"), b, c)?; cs.enforce( || "maj computation", - |_| bc.lc(CS::one(), E::Fr::one()) - + &bc.lc(CS::one(), E::Fr::one()) - - &b.lc(CS::one(), E::Fr::one()) - - &c.lc(CS::one(), E::Fr::one()), + |_| { + bc.lc(CS::one(), E::Fr::one()) + &bc.lc(CS::one(), E::Fr::one()) + - &b.lc(CS::one(), E::Fr::one()) + - &c.lc(CS::one(), E::Fr::one()) + }, |_| a.lc(CS::one(), E::Fr::one()), - |_| bc.lc(CS::one(), E::Fr::one()) - maj + |_| bc.lc(CS::one(), E::Fr::one()) - maj, ); Ok(AllocatedBit { value: maj_value, - variable: maj - }.into()) + variable: maj, + } + .into()) } } @@ -801,16 +733,11 @@ impl From for Boolean { #[cfg(test)] mod test { - use crate::{ConstraintSystem}; + use super::{field_into_allocated_bits_le, u64_into_boolean_vec_le, AllocatedBit, Boolean}; + use crate::gadgets::test::*; + use crate::ConstraintSystem; use ff::{Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; - use crate::gadgets::test::*; - use super::{ - AllocatedBit, - Boolean, - field_into_allocated_bits_le, - u64_into_boolean_vec_le - }; #[test] fn test_allocated_bit() { @@ -839,10 +766,24 @@ mod test { assert!(cs.is_satisfied()); assert!(cs.get("a/boolean") == if *a_val { Field::one() } else { Field::zero() }); assert!(cs.get("b/boolean") == if *b_val { Field::one() } else { Field::zero() }); - assert!(cs.get("xor result") == if *a_val ^ *b_val { Field::one() } else { Field::zero() }); + assert!( + cs.get("xor result") + == if *a_val ^ *b_val { + Field::one() + } else { + Field::zero() + } + ); // Invert the result and check if the constraint system is still satisfied - cs.set("xor result", if *a_val ^ *b_val { Field::zero() } else { Field::one() }); + cs.set( + "xor result", + if *a_val ^ *b_val { + Field::zero() + } else { + Field::one() + }, + ); assert!(!cs.is_satisfied()); } } @@ -861,10 +802,24 @@ mod test { assert!(cs.is_satisfied()); assert!(cs.get("a/boolean") == if *a_val { Field::one() } else { Field::zero() }); assert!(cs.get("b/boolean") == if *b_val { Field::one() } else { Field::zero() }); - assert!(cs.get("and result") == if *a_val & *b_val { Field::one() } else { Field::zero() }); + assert!( + cs.get("and result") + == if *a_val & *b_val { + Field::one() + } else { + Field::zero() + } + ); // Invert the result and check if the constraint system is still satisfied - cs.set("and result", if *a_val & *b_val { Field::zero() } else { Field::one() }); + cs.set( + "and result", + if *a_val & *b_val { + Field::zero() + } else { + Field::one() + }, + ); assert!(!cs.is_satisfied()); } } @@ -883,10 +838,24 @@ mod test { assert!(cs.is_satisfied()); assert!(cs.get("a/boolean") == if *a_val { Field::one() } else { Field::zero() }); assert!(cs.get("b/boolean") == if *b_val { Field::one() } else { Field::zero() }); - assert!(cs.get("and not result") == if *a_val & !*b_val { Field::one() } else { Field::zero() }); + assert!( + cs.get("and not result") + == if *a_val & !*b_val { + Field::one() + } else { + Field::zero() + } + ); // Invert the result and check if the constraint system is still satisfied - cs.set("and not result", if *a_val & !*b_val { Field::zero() } else { Field::one() }); + cs.set( + "and not result", + if *a_val & !*b_val { + Field::zero() + } else { + Field::one() + }, + ); assert!(!cs.is_satisfied()); } } @@ -905,10 +874,24 @@ mod test { assert!(cs.is_satisfied()); assert!(cs.get("a/boolean") == if *a_val { Field::one() } else { Field::zero() }); assert!(cs.get("b/boolean") == if *b_val { Field::one() } else { Field::zero() }); - assert!(cs.get("nor result") == if !*a_val & !*b_val { Field::one() } else { Field::zero() }); + assert!( + cs.get("nor result") + == if !*a_val & !*b_val { + Field::one() + } else { + Field::zero() + } + ); // Invert the result and check if the constraint system is still satisfied - cs.set("nor result", if !*a_val & !*b_val { Field::zero() } else { Field::one() }); + cs.set( + "nor result", + if !*a_val & !*b_val { + Field::zero() + } else { + Field::one() + }, + ); assert!(!cs.is_satisfied()); } } @@ -923,8 +906,12 @@ mod test { { let mut cs = TestConstraintSystem::::new(); - let mut a = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_bool)).unwrap()); - let mut b = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_bool)).unwrap()); + let mut a = Boolean::from( + AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_bool)).unwrap(), + ); + let mut b = Boolean::from( + AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_bool)).unwrap(), + ); if a_neg { a = a.not(); @@ -935,16 +922,15 @@ mod test { Boolean::enforce_equal(&mut cs, &a, &b).unwrap(); - assert_eq!( - cs.is_satisfied(), - (a_bool ^ a_neg) == (b_bool ^ b_neg) - ); + assert_eq!(cs.is_satisfied(), (a_bool ^ a_neg) == (b_bool ^ b_neg)); } { let mut cs = TestConstraintSystem::::new(); let mut a = Boolean::Constant(a_bool); - let mut b = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_bool)).unwrap()); + let mut b = Boolean::from( + AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_bool)).unwrap(), + ); if a_neg { a = a.not(); @@ -955,15 +941,14 @@ mod test { Boolean::enforce_equal(&mut cs, &a, &b).unwrap(); - assert_eq!( - cs.is_satisfied(), - (a_bool ^ a_neg) == (b_bool ^ b_neg) - ); + assert_eq!(cs.is_satisfied(), (a_bool ^ a_neg) == (b_bool ^ b_neg)); } { let mut cs = TestConstraintSystem::::new(); - let mut a = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_bool)).unwrap()); + let mut a = Boolean::from( + AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_bool)).unwrap(), + ); let mut b = Boolean::Constant(b_bool); if a_neg { @@ -975,10 +960,7 @@ mod test { Boolean::enforce_equal(&mut cs, &a, &b).unwrap(); - assert_eq!( - cs.is_satisfied(), - (a_bool ^ a_neg) == (b_bool ^ b_neg) - ); + assert_eq!(cs.is_satisfied(), (a_bool ^ a_neg) == (b_bool ^ b_neg)); } { let mut cs = TestConstraintSystem::::new(); @@ -1015,43 +997,43 @@ mod test { let mut b = Boolean::from(AllocatedBit::alloc(&mut cs, Some(true)).unwrap()); match b { - Boolean::Is(_) => {}, - _ => panic!("unexpected value") + Boolean::Is(_) => {} + _ => panic!("unexpected value"), } b = b.not(); match b { - Boolean::Not(_) => {}, - _ => panic!("unexpected value") + Boolean::Not(_) => {} + _ => panic!("unexpected value"), } b = b.not(); match b { - Boolean::Is(_) => {}, - _ => panic!("unexpected value") + Boolean::Is(_) => {} + _ => panic!("unexpected value"), } b = Boolean::constant(true); match b { - Boolean::Constant(true) => {}, - _ => panic!("unexpected value") + Boolean::Constant(true) => {} + _ => panic!("unexpected value"), } b = b.not(); match b { - Boolean::Constant(false) => {}, - _ => panic!("unexpected value") + Boolean::Constant(false) => {} + _ => panic!("unexpected value"), } b = b.not(); match b { - Boolean::Constant(true) => {}, - _ => panic!("unexpected value") + Boolean::Constant(true) => {} + _ => panic!("unexpected value"), } } @@ -1062,7 +1044,7 @@ mod test { AllocatedTrue, AllocatedFalse, NegatedAllocatedTrue, - NegatedAllocatedFalse + NegatedAllocatedFalse, } impl OperandType { @@ -1073,7 +1055,7 @@ mod test { OperandType::AllocatedTrue => false, OperandType::AllocatedFalse => false, OperandType::NegatedAllocatedTrue => false, - OperandType::NegatedAllocatedFalse => false + OperandType::NegatedAllocatedFalse => false, } } @@ -1084,12 +1066,11 @@ mod test { OperandType::AllocatedTrue => true, OperandType::AllocatedFalse => false, OperandType::NegatedAllocatedTrue => false, - OperandType::NegatedAllocatedFalse => true + OperandType::NegatedAllocatedFalse => true, } } } - #[test] fn test_boolean_xor() { let variants = [ @@ -1098,7 +1079,7 @@ mod test { OperandType::AllocatedTrue, OperandType::AllocatedFalse, OperandType::NegatedAllocatedTrue, - OperandType::NegatedAllocatedFalse + OperandType::NegatedAllocatedFalse, ]; for first_operand in variants.iter().cloned() { @@ -1115,10 +1096,18 @@ mod test { match operand { OperandType::True => Boolean::constant(true), OperandType::False => Boolean::constant(false), - OperandType::AllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()), - OperandType::AllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()), - OperandType::NegatedAllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()).not(), - OperandType::NegatedAllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()).not(), + OperandType::AllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()) + } + OperandType::AllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()) + } + OperandType::NegatedAllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()).not() + } + OperandType::NegatedAllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()).not() + } } }; @@ -1131,97 +1120,161 @@ mod test { assert!(cs.is_satisfied()); match (first_operand, second_operand, c) { - (OperandType::True, OperandType::True, Boolean::Constant(false)) => {}, - (OperandType::True, OperandType::False, Boolean::Constant(true)) => {}, - (OperandType::True, OperandType::AllocatedTrue, Boolean::Not(_)) => {}, - (OperandType::True, OperandType::AllocatedFalse, Boolean::Not(_)) => {}, - (OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Is(_)) => {}, - (OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Is(_)) => {}, + (OperandType::True, OperandType::True, Boolean::Constant(false)) => {} + (OperandType::True, OperandType::False, Boolean::Constant(true)) => {} + (OperandType::True, OperandType::AllocatedTrue, Boolean::Not(_)) => {} + (OperandType::True, OperandType::AllocatedFalse, Boolean::Not(_)) => {} + (OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Is(_)) => {} + (OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Is(_)) => {} - (OperandType::False, OperandType::True, Boolean::Constant(true)) => {}, - (OperandType::False, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::False, OperandType::AllocatedTrue, Boolean::Is(_)) => {}, - (OperandType::False, OperandType::AllocatedFalse, Boolean::Is(_)) => {}, - (OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}, - (OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}, + (OperandType::False, OperandType::True, Boolean::Constant(true)) => {} + (OperandType::False, OperandType::False, Boolean::Constant(false)) => {} + (OperandType::False, OperandType::AllocatedTrue, Boolean::Is(_)) => {} + (OperandType::False, OperandType::AllocatedFalse, Boolean::Is(_)) => {} + (OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {} + (OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {} - (OperandType::AllocatedTrue, OperandType::True, Boolean::Not(_)) => {}, - (OperandType::AllocatedTrue, OperandType::False, Boolean::Is(_)) => {}, - (OperandType::AllocatedTrue, OperandType::AllocatedTrue, Boolean::Is(ref v)) => { + (OperandType::AllocatedTrue, OperandType::True, Boolean::Not(_)) => {} + (OperandType::AllocatedTrue, OperandType::False, Boolean::Is(_)) => {} + ( + OperandType::AllocatedTrue, + OperandType::AllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedTrue, OperandType::AllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedTrue, + OperandType::AllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::AllocatedTrue, OperandType::NegatedAllocatedTrue, Boolean::Not(ref v)) => { + } + ( + OperandType::AllocatedTrue, + OperandType::NegatedAllocatedTrue, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedTrue, OperandType::NegatedAllocatedFalse, Boolean::Not(ref v)) => { + } + ( + OperandType::AllocatedTrue, + OperandType::NegatedAllocatedFalse, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, + } - (OperandType::AllocatedFalse, OperandType::True, Boolean::Not(_)) => {}, - (OperandType::AllocatedFalse, OperandType::False, Boolean::Is(_)) => {}, - (OperandType::AllocatedFalse, OperandType::AllocatedTrue, Boolean::Is(ref v)) => { + (OperandType::AllocatedFalse, OperandType::True, Boolean::Not(_)) => {} + (OperandType::AllocatedFalse, OperandType::False, Boolean::Is(_)) => {} + ( + OperandType::AllocatedFalse, + OperandType::AllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::AllocatedFalse, OperandType::AllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::AllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedFalse, OperandType::NegatedAllocatedTrue, Boolean::Not(ref v)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::NegatedAllocatedTrue, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::AllocatedFalse, OperandType::NegatedAllocatedFalse, Boolean::Not(ref v)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::NegatedAllocatedFalse, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, + } - (OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Is(_)) => {}, - (OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Not(_)) => {}, - (OperandType::NegatedAllocatedTrue, OperandType::AllocatedTrue, Boolean::Not(ref v)) => { + (OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Is(_)) => {} + (OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Not(_)) => {} + ( + OperandType::NegatedAllocatedTrue, + OperandType::AllocatedTrue, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedTrue, OperandType::AllocatedFalse, Boolean::Not(ref v)) => { + } + ( + OperandType::NegatedAllocatedTrue, + OperandType::AllocatedFalse, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedTrue, + OperandType::NegatedAllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedTrue, + OperandType::NegatedAllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, + } - (OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Is(_)) => {}, - (OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Not(_)) => {}, - (OperandType::NegatedAllocatedFalse, OperandType::AllocatedTrue, Boolean::Not(ref v)) => { + (OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Is(_)) => {} + (OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Not(_)) => {} + ( + OperandType::NegatedAllocatedFalse, + OperandType::AllocatedTrue, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::NegatedAllocatedFalse, OperandType::AllocatedFalse, Boolean::Not(ref v)) => { + } + ( + OperandType::NegatedAllocatedFalse, + OperandType::AllocatedFalse, + Boolean::Not(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedTrue, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedFalse, + OperandType::NegatedAllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedFalse, + OperandType::NegatedAllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("xor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, + } - _ => panic!("this should never be encountered") + _ => panic!("this should never be encountered"), } } } @@ -1235,7 +1288,7 @@ mod test { OperandType::AllocatedTrue, OperandType::AllocatedFalse, OperandType::NegatedAllocatedTrue, - OperandType::NegatedAllocatedFalse + OperandType::NegatedAllocatedFalse, ]; for first_operand in variants.iter().cloned() { @@ -1252,10 +1305,18 @@ mod test { match operand { OperandType::True => Boolean::constant(true), OperandType::False => Boolean::constant(false), - OperandType::AllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()), - OperandType::AllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()), - OperandType::NegatedAllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()).not(), - OperandType::NegatedAllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()).not(), + OperandType::AllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()) + } + OperandType::AllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()) + } + OperandType::NegatedAllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()).not() + } + OperandType::NegatedAllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()).not() + } } }; @@ -1268,98 +1329,183 @@ mod test { assert!(cs.is_satisfied()); match (first_operand, second_operand, c) { - (OperandType::True, OperandType::True, Boolean::Constant(true)) => {}, - (OperandType::True, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::True, OperandType::AllocatedTrue, Boolean::Is(_)) => {}, - (OperandType::True, OperandType::AllocatedFalse, Boolean::Is(_)) => {}, - (OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}, - (OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}, + (OperandType::True, OperandType::True, Boolean::Constant(true)) => {} + (OperandType::True, OperandType::False, Boolean::Constant(false)) => {} + (OperandType::True, OperandType::AllocatedTrue, Boolean::Is(_)) => {} + (OperandType::True, OperandType::AllocatedFalse, Boolean::Is(_)) => {} + (OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {} + (OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {} - (OperandType::False, OperandType::True, Boolean::Constant(false)) => {}, - (OperandType::False, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::False, OperandType::AllocatedTrue, Boolean::Constant(false)) => {}, - (OperandType::False, OperandType::AllocatedFalse, Boolean::Constant(false)) => {}, - (OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Constant(false)) => {}, - (OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Constant(false)) => {}, + (OperandType::False, OperandType::True, Boolean::Constant(false)) => {} + (OperandType::False, OperandType::False, Boolean::Constant(false)) => {} + (OperandType::False, OperandType::AllocatedTrue, Boolean::Constant(false)) => {} + (OperandType::False, OperandType::AllocatedFalse, Boolean::Constant(false)) => { + } + ( + OperandType::False, + OperandType::NegatedAllocatedTrue, + Boolean::Constant(false), + ) => {} + ( + OperandType::False, + OperandType::NegatedAllocatedFalse, + Boolean::Constant(false), + ) => {} - (OperandType::AllocatedTrue, OperandType::True, Boolean::Is(_)) => {}, - (OperandType::AllocatedTrue, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::AllocatedTrue, OperandType::AllocatedTrue, Boolean::Is(ref v)) => { + (OperandType::AllocatedTrue, OperandType::True, Boolean::Is(_)) => {} + (OperandType::AllocatedTrue, OperandType::False, Boolean::Constant(false)) => {} + ( + OperandType::AllocatedTrue, + OperandType::AllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("and result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::AllocatedTrue, OperandType::AllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedTrue, + OperandType::AllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("and result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedTrue, OperandType::NegatedAllocatedTrue, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedTrue, + OperandType::NegatedAllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedTrue, OperandType::NegatedAllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedTrue, + OperandType::NegatedAllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::one()); assert_eq!(v.value, Some(true)); - }, + } - (OperandType::AllocatedFalse, OperandType::True, Boolean::Is(_)) => {}, - (OperandType::AllocatedFalse, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::AllocatedFalse, OperandType::AllocatedTrue, Boolean::Is(ref v)) => { + (OperandType::AllocatedFalse, OperandType::True, Boolean::Is(_)) => {} + (OperandType::AllocatedFalse, OperandType::False, Boolean::Constant(false)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::AllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("and result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedFalse, OperandType::AllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::AllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("and result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedFalse, OperandType::NegatedAllocatedTrue, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::NegatedAllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::AllocatedFalse, OperandType::NegatedAllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::AllocatedFalse, + OperandType::NegatedAllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, + } - (OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Not(_)) => {}, - (OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::NegatedAllocatedTrue, OperandType::AllocatedTrue, Boolean::Is(ref v)) => { + (OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Not(_)) => {} + ( + OperandType::NegatedAllocatedTrue, + OperandType::False, + Boolean::Constant(false), + ) => {} + ( + OperandType::NegatedAllocatedTrue, + OperandType::AllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedTrue, OperandType::AllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedTrue, + OperandType::AllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedTrue, + OperandType::NegatedAllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("nor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedTrue, + OperandType::NegatedAllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("nor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, + } - (OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Not(_)) => {}, - (OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Constant(false)) => {}, - (OperandType::NegatedAllocatedFalse, OperandType::AllocatedTrue, Boolean::Is(ref v)) => { + (OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Not(_)) => {} + ( + OperandType::NegatedAllocatedFalse, + OperandType::False, + Boolean::Constant(false), + ) => {} + ( + OperandType::NegatedAllocatedFalse, + OperandType::AllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::one()); assert_eq!(v.value, Some(true)); - }, - (OperandType::NegatedAllocatedFalse, OperandType::AllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedFalse, + OperandType::AllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("and not result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedTrue, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedFalse, + OperandType::NegatedAllocatedTrue, + Boolean::Is(ref v), + ) => { assert!(cs.get("nor result") == Field::zero()); assert_eq!(v.value, Some(false)); - }, - (OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse, Boolean::Is(ref v)) => { + } + ( + OperandType::NegatedAllocatedFalse, + OperandType::NegatedAllocatedFalse, + Boolean::Is(ref v), + ) => { assert!(cs.get("nor result") == Field::one()); assert_eq!(v.value, Some(true)); - }, + } _ => { - panic!("unexpected behavior at {:?} AND {:?}", first_operand, second_operand); + panic!( + "unexpected behavior at {:?} AND {:?}", + first_operand, second_operand + ); } } } @@ -1391,7 +1537,10 @@ mod test { fn test_field_into_allocated_bits_le() { let mut cs = TestConstraintSystem::::new(); - let r = Fr::from_str("9147677615426976802526883532204139322118074541891858454835346926874644257775").unwrap(); + let r = Fr::from_str( + "9147677615426976802526883532204139322118074541891858454835346926874644257775", + ) + .unwrap(); let bits = field_into_allocated_bits_le(&mut cs, Some(r)).unwrap(); @@ -1417,7 +1566,7 @@ mod test { OperandType::AllocatedTrue, OperandType::AllocatedFalse, OperandType::NegatedAllocatedTrue, - OperandType::NegatedAllocatedFalse + OperandType::NegatedAllocatedFalse, ]; for first_operand in variants.iter().cloned() { @@ -1430,8 +1579,8 @@ mod test { let c; // ch = (a and b) xor ((not a) and c) - let expected = (first_operand.val() & second_operand.val()) ^ - ((!first_operand.val()) & third_operand.val()); + let expected = (first_operand.val() & second_operand.val()) + ^ ((!first_operand.val()) & third_operand.val()); { let mut dyn_construct = |operand, name| { @@ -1440,10 +1589,20 @@ mod test { match operand { OperandType::True => Boolean::constant(true), OperandType::False => Boolean::constant(false), - OperandType::AllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()), - OperandType::AllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()), - OperandType::NegatedAllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()).not(), - OperandType::NegatedAllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()).not(), + OperandType::AllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()) + } + OperandType::AllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()) + } + OperandType::NegatedAllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()) + .not() + } + OperandType::NegatedAllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()) + .not() + } } }; @@ -1458,19 +1617,17 @@ mod test { assert_eq!(maj.get_value().unwrap(), expected); - if first_operand.is_constant() || - second_operand.is_constant() || - third_operand.is_constant() + if first_operand.is_constant() + || second_operand.is_constant() + || third_operand.is_constant() { - if first_operand.is_constant() && - second_operand.is_constant() && - third_operand.is_constant() + if first_operand.is_constant() + && second_operand.is_constant() + && third_operand.is_constant() { assert_eq!(cs.num_constraints(), 0); } - } - else - { + } else { assert_eq!(cs.get("ch"), { if expected { Fr::one() @@ -1500,7 +1657,7 @@ mod test { OperandType::AllocatedTrue, OperandType::AllocatedFalse, OperandType::NegatedAllocatedTrue, - OperandType::NegatedAllocatedFalse + OperandType::NegatedAllocatedFalse, ]; for first_operand in variants.iter().cloned() { @@ -1513,9 +1670,9 @@ mod test { let c; // maj = (a and b) xor (a and c) xor (b and c) - let expected = (first_operand.val() & second_operand.val()) ^ - (first_operand.val() & third_operand.val()) ^ - (second_operand.val() & third_operand.val()); + let expected = (first_operand.val() & second_operand.val()) + ^ (first_operand.val() & third_operand.val()) + ^ (second_operand.val() & third_operand.val()); { let mut dyn_construct = |operand, name| { @@ -1524,10 +1681,20 @@ mod test { match operand { OperandType::True => Boolean::constant(true), OperandType::False => Boolean::constant(false), - OperandType::AllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()), - OperandType::AllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()), - OperandType::NegatedAllocatedTrue => Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()).not(), - OperandType::NegatedAllocatedFalse => Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()).not(), + OperandType::AllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()) + } + OperandType::AllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()) + } + OperandType::NegatedAllocatedTrue => { + Boolean::from(AllocatedBit::alloc(cs, Some(true)).unwrap()) + .not() + } + OperandType::NegatedAllocatedFalse => { + Boolean::from(AllocatedBit::alloc(cs, Some(false)).unwrap()) + .not() + } } }; @@ -1542,19 +1709,17 @@ mod test { assert_eq!(maj.get_value().unwrap(), expected); - if first_operand.is_constant() || - second_operand.is_constant() || - third_operand.is_constant() + if first_operand.is_constant() + || second_operand.is_constant() + || third_operand.is_constant() { - if first_operand.is_constant() && - second_operand.is_constant() && - third_operand.is_constant() + if first_operand.is_constant() + && second_operand.is_constant() + && third_operand.is_constant() { assert_eq!(cs.num_constraints(), 0); } - } - else - { + } else { assert_eq!(cs.get("maj"), { if expected { Fr::one() diff --git a/bellman/src/gadgets/lookup.rs b/bellman/src/gadgets/lookup.rs index 86ab10f..bbb1da6 100644 --- a/bellman/src/gadgets/lookup.rs +++ b/bellman/src/gadgets/lookup.rs @@ -1,23 +1,15 @@ use ff::Field; use pairing::Engine; -use super::*; -use super::num::{ - AllocatedNum, - Num -}; use super::boolean::Boolean; -use crate::{ - ConstraintSystem -}; +use super::num::{AllocatedNum, Num}; +use super::*; +use crate::ConstraintSystem; // Synthesize the constants for each base pattern. -fn synth<'a, E: Engine, I>( - window_size: usize, - constants: I, - assignment: &mut [E::Fr] -) - where I: IntoIterator +fn synth<'a, E: Engine, I>(window_size: usize, constants: I, assignment: &mut [E::Fr]) +where + I: IntoIterator, { assert_eq!(assignment.len(), 1 << window_size); @@ -39,16 +31,20 @@ fn synth<'a, E: Engine, I>( pub fn lookup3_xy( mut cs: CS, bits: &[Boolean], - coords: &[(E::Fr, E::Fr)] + coords: &[(E::Fr, E::Fr)], ) -> Result<(AllocatedNum, AllocatedNum), SynthesisError> - where CS: ConstraintSystem +where + CS: ConstraintSystem, { assert_eq!(bits.len(), 3); assert_eq!(coords.len(), 8); // Calculate the index into `coords` - let i = - match (bits[0].get_value(), bits[1].get_value(), bits[2].get_value()) { + let i = match ( + bits[0].get_value(), + bits[1].get_value(), + bits[2].get_value(), + ) { (Some(a_value), Some(b_value), Some(c_value)) => { let mut tmp = 0; if a_value { @@ -61,25 +57,15 @@ pub fn lookup3_xy( tmp += 4; } Some(tmp) - }, - _ => None + } + _ => None, }; // Allocate the x-coordinate resulting from the lookup - let res_x = AllocatedNum::alloc( - cs.namespace(|| "x"), - || { - Ok(coords[*i.get()?].0) - } - )?; + let res_x = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(coords[*i.get()?].0))?; // Allocate the y-coordinate resulting from the lookup - let res_y = AllocatedNum::alloc( - cs.namespace(|| "y"), - || { - Ok(coords[*i.get()?].1) - } - )?; + let res_y = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(coords[*i.get()?].1))?; // Compute the coefficients for the lookup constraints let mut x_coeffs = [E::Fr::zero(); 8]; @@ -93,30 +79,38 @@ pub fn lookup3_xy( cs.enforce( || "x-coordinate lookup", - |lc| lc + (x_coeffs[0b001], one) + |lc| { + lc + (x_coeffs[0b001], one) + &bits[1].lc::(one, x_coeffs[0b011]) + &bits[2].lc::(one, x_coeffs[0b101]) - + &precomp.lc::(one, x_coeffs[0b111]), + + &precomp.lc::(one, x_coeffs[0b111]) + }, |lc| lc + &bits[0].lc::(one, E::Fr::one()), - |lc| lc + res_x.get_variable() + |lc| { + lc + res_x.get_variable() - (x_coeffs[0b000], one) - &bits[1].lc::(one, x_coeffs[0b010]) - &bits[2].lc::(one, x_coeffs[0b100]) - - &precomp.lc::(one, x_coeffs[0b110]), + - &precomp.lc::(one, x_coeffs[0b110]) + }, ); cs.enforce( || "y-coordinate lookup", - |lc| lc + (y_coeffs[0b001], one) + |lc| { + lc + (y_coeffs[0b001], one) + &bits[1].lc::(one, y_coeffs[0b011]) + &bits[2].lc::(one, y_coeffs[0b101]) - + &precomp.lc::(one, y_coeffs[0b111]), + + &precomp.lc::(one, y_coeffs[0b111]) + }, |lc| lc + &bits[0].lc::(one, E::Fr::one()), - |lc| lc + res_y.get_variable() + |lc| { + lc + res_y.get_variable() - (y_coeffs[0b000], one) - &bits[1].lc::(one, y_coeffs[0b010]) - &bits[2].lc::(one, y_coeffs[0b100]) - - &precomp.lc::(one, y_coeffs[0b110]), + - &precomp.lc::(one, y_coeffs[0b110]) + }, ); Ok((res_x, res_y)) @@ -127,16 +121,16 @@ pub fn lookup3_xy( pub fn lookup3_xy_with_conditional_negation( mut cs: CS, bits: &[Boolean], - coords: &[(E::Fr, E::Fr)] + coords: &[(E::Fr, E::Fr)], ) -> Result<(Num, Num), SynthesisError> - where CS: ConstraintSystem +where + CS: ConstraintSystem, { assert_eq!(bits.len(), 3); assert_eq!(coords.len(), 4); // Calculate the index into `coords` - let i = - match (bits[0].get_value(), bits[1].get_value()) { + let i = match (bits[0].get_value(), bits[1].get_value()) { (Some(a_value), Some(b_value)) => { let mut tmp = 0; if a_value { @@ -146,22 +140,19 @@ pub fn lookup3_xy_with_conditional_negation( tmp += 2; } Some(tmp) - }, - _ => None + } + _ => None, }; // Allocate the y-coordinate resulting from the lookup // and conditional negation - let y = AllocatedNum::alloc( - cs.namespace(|| "y"), - || { - let mut tmp = coords[*i.get()?].1; - if *bits[2].get_value().get()? { - tmp.negate(); - } - Ok(tmp) + let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let mut tmp = coords[*i.get()?].1; + if *bits[2].get_value().get()? { + tmp.negate(); } - )?; + Ok(tmp) + })?; let one = CS::one(); @@ -174,21 +165,21 @@ pub fn lookup3_xy_with_conditional_negation( let precomp = Boolean::and(cs.namespace(|| "precomp"), &bits[0], &bits[1])?; let x = Num::zero() - .add_bool_with_coeff(one, &Boolean::constant(true), x_coeffs[0b00]) - .add_bool_with_coeff(one, &bits[0], x_coeffs[0b01]) - .add_bool_with_coeff(one, &bits[1], x_coeffs[0b10]) - .add_bool_with_coeff(one, &precomp, x_coeffs[0b11]); + .add_bool_with_coeff(one, &Boolean::constant(true), x_coeffs[0b00]) + .add_bool_with_coeff(one, &bits[0], x_coeffs[0b01]) + .add_bool_with_coeff(one, &bits[1], x_coeffs[0b10]) + .add_bool_with_coeff(one, &precomp, x_coeffs[0b11]); - let y_lc = precomp.lc::(one, y_coeffs[0b11]) + - &bits[1].lc::(one, y_coeffs[0b10]) + - &bits[0].lc::(one, y_coeffs[0b01]) + - (y_coeffs[0b00], one); + let y_lc = precomp.lc::(one, y_coeffs[0b11]) + + &bits[1].lc::(one, y_coeffs[0b10]) + + &bits[0].lc::(one, y_coeffs[0b01]) + + (y_coeffs[0b00], one); cs.enforce( || "y-coordinate lookup", |lc| lc + &y_lc + &y_lc, |lc| lc + &bits[2].lc::(one, E::Fr::one()), - |lc| lc + &y_lc - y.get_variable() + |lc| lc + &y_lc - y.get_variable(), ); Ok((x, y.into())) @@ -197,8 +188,8 @@ pub fn lookup3_xy_with_conditional_negation( #[cfg(test)] mod test { use super::*; + use crate::gadgets::boolean::{AllocatedBit, Boolean}; use crate::gadgets::test::*; - use crate::gadgets::boolean::{Boolean, AllocatedBit}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -206,40 +197,42 @@ mod test { #[test] fn test_lookup3_xy() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); let a_val = rng.next_u32() % 2 != 0; - let a = Boolean::from( - AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap() - ); + let a = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap()); let b_val = rng.next_u32() % 2 != 0; - let b = Boolean::from( - AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap() - ); + let b = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap()); let c_val = rng.next_u32() % 2 != 0; - let c = Boolean::from( - AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap() - ); + let c = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap()); let bits = vec![a, b, c]; - let points: Vec<(Fr, Fr)> = (0..8).map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))).collect(); + let points: Vec<(Fr, Fr)> = (0..8) + .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) + .collect(); let res = lookup3_xy(&mut cs, &bits, &points).unwrap(); assert!(cs.is_satisfied()); let mut index = 0; - if a_val { index += 1 } - if b_val { index += 2 } - if c_val { index += 4 } + if a_val { + index += 1 + } + if b_val { + index += 2 + } + if c_val { + index += 4 + } assert_eq!(res.0.get_value().unwrap(), points[index].0); assert_eq!(res.1.get_value().unwrap(), points[index].1); @@ -249,43 +242,45 @@ mod test { #[test] fn test_lookup3_xy_with_conditional_negation() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { let mut cs = TestConstraintSystem::::new(); let a_val = rng.next_u32() % 2 != 0; - let a = Boolean::from( - AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap() - ); + let a = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap()); let b_val = rng.next_u32() % 2 != 0; - let b = Boolean::from( - AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap() - ); + let b = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap()); let c_val = rng.next_u32() % 2 != 0; - let c = Boolean::from( - AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap() - ); + let c = Boolean::from(AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap()); let bits = vec![a, b, c]; - let points: Vec<(Fr, Fr)> = (0..4).map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))).collect(); + let points: Vec<(Fr, Fr)> = (0..4) + .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) + .collect(); let res = lookup3_xy_with_conditional_negation(&mut cs, &bits, &points).unwrap(); assert!(cs.is_satisfied()); let mut index = 0; - if a_val { index += 1 } - if b_val { index += 2 } + if a_val { + index += 1 + } + if b_val { + index += 2 + } assert_eq!(res.0.get_value().unwrap(), points[index].0); let mut tmp = points[index].1; - if c_val { tmp.negate() } + if c_val { + tmp.negate() + } assert_eq!(res.1.get_value().unwrap(), tmp); } } @@ -293,14 +288,16 @@ mod test { #[test] fn test_synth() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let window_size = 4; let mut assignment = vec![Fr::zero(); 1 << window_size]; - let constants: Vec<_> = (0..(1 << window_size)).map(|_| Fr::random(&mut rng)).collect(); + let constants: Vec<_> = (0..(1 << window_size)) + .map(|_| Fr::random(&mut rng)) + .collect(); synth::(window_size, &constants, &mut assignment); diff --git a/bellman/src/gadgets/multieq.rs b/bellman/src/gadgets/multieq.rs index b1dfd7c..510802d 100644 --- a/bellman/src/gadgets/multieq.rs +++ b/bellman/src/gadgets/multieq.rs @@ -1,14 +1,9 @@ use ff::{Field, PrimeField}; use pairing::Engine; -use crate::{ - SynthesisError, - ConstraintSystem, - LinearCombination, - Variable -}; +use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable}; -pub struct MultiEq>{ +pub struct MultiEq> { cs: CS, ops: usize, bits_used: usize, @@ -23,12 +18,11 @@ impl> MultiEq { ops: 0, bits_used: 0, lhs: LinearCombination::zero(), - rhs: LinearCombination::zero() + rhs: LinearCombination::zero(), } } - fn accumulate(&mut self) - { + fn accumulate(&mut self) { let ops = self.ops; let lhs = self.lhs.clone(); let rhs = self.rhs.clone(); @@ -36,7 +30,7 @@ impl> MultiEq { || format!("multieq {}", ops), |_| lhs, |lc| lc + CS::one(), - |_| rhs + |_| rhs, ); self.lhs = LinearCombination::zero(); self.rhs = LinearCombination::zero(); @@ -48,9 +42,8 @@ impl> MultiEq { &mut self, num_bits: usize, lhs: &LinearCombination, - rhs: &LinearCombination - ) - { + rhs: &LinearCombination, + ) { // Check if we will exceed the capacity if (E::Fr::CAPACITY as usize) <= (self.bits_used + num_bits) { self.accumulate(); @@ -68,67 +61,60 @@ impl> MultiEq { impl> Drop for MultiEq { fn drop(&mut self) { if self.bits_used > 0 { - self.accumulate(); + self.accumulate(); } } } -impl> ConstraintSystem for MultiEq -{ +impl> ConstraintSystem for MultiEq { type Root = Self; fn one() -> Variable { CS::one() } - fn alloc( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { self.cs.alloc(annotation, f) } - fn alloc_input( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc_input(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { self.cs.alloc_input(annotation, f) } - fn enforce( - &mut self, - annotation: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, { self.cs.enforce(annotation, a, b, c) } fn push_namespace(&mut self, name_fn: N) - where NR: Into, N: FnOnce() -> NR + where + NR: Into, + N: FnOnce() -> NR, { self.cs.get_root().push_namespace(name_fn) } - fn pop_namespace(&mut self) - { + fn pop_namespace(&mut self) { self.cs.get_root().pop_namespace() } - fn get_root(&mut self) -> &mut Self::Root - { + fn get_root(&mut self) -> &mut Self::Root { self } } diff --git a/bellman/src/gadgets/multipack.rs b/bellman/src/gadgets/multipack.rs index b9b5877..34df7cd 100644 --- a/bellman/src/gadgets/multipack.rs +++ b/bellman/src/gadgets/multipack.rs @@ -1,20 +1,18 @@ -use ff::{Field, PrimeField}; -use pairing::Engine; -use crate::{ConstraintSystem, SynthesisError}; -use super::boolean::{Boolean}; +use super::boolean::Boolean; use super::num::Num; use super::Assignment; +use crate::{ConstraintSystem, SynthesisError}; +use ff::{Field, PrimeField}; +use pairing::Engine; /// Takes a sequence of booleans and exposes them as compact /// public inputs -pub fn pack_into_inputs( - mut cs: CS, - bits: &[Boolean] -) -> Result<(), SynthesisError> - where E: Engine, CS: ConstraintSystem +pub fn pack_into_inputs(mut cs: CS, bits: &[Boolean]) -> Result<(), SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { - for (i, bits) in bits.chunks(E::Fr::CAPACITY as usize).enumerate() - { + for (i, bits) in bits.chunks(E::Fr::CAPACITY as usize).enumerate() { let mut num = Num::::zero(); let mut coeff = E::Fr::one(); for bit in bits { @@ -23,44 +21,38 @@ pub fn pack_into_inputs( coeff.double(); } - let input = cs.alloc_input(|| format!("input {}", i), || { - Ok(*num.get_value().get()?) - })?; + let input = cs.alloc_input(|| format!("input {}", i), || Ok(*num.get_value().get()?))?; // num * 1 = input cs.enforce( || format!("packing constraint {}", i), |_| num.lc(E::Fr::one()), |lc| lc + CS::one(), - |lc| lc + input + |lc| lc + input, ); } Ok(()) } -pub fn bytes_to_bits(bytes: &[u8]) -> Vec -{ - bytes.iter() - .flat_map(|&v| (0..8).rev().map(move |i| (v >> i) & 1 == 1)) - .collect() +pub fn bytes_to_bits(bytes: &[u8]) -> Vec { + bytes + .iter() + .flat_map(|&v| (0..8).rev().map(move |i| (v >> i) & 1 == 1)) + .collect() } -pub fn bytes_to_bits_le(bytes: &[u8]) -> Vec -{ - bytes.iter() - .flat_map(|&v| (0..8).map(move |i| (v >> i) & 1 == 1)) - .collect() +pub fn bytes_to_bits_le(bytes: &[u8]) -> Vec { + bytes + .iter() + .flat_map(|&v| (0..8).map(move |i| (v >> i) & 1 == 1)) + .collect() } -pub fn compute_multipacking( - bits: &[bool] -) -> Vec -{ +pub fn compute_multipacking(bits: &[bool]) -> Vec { let mut result = vec![]; - for bits in bits.chunks(E::Fr::CAPACITY as usize) - { + for bits in bits.chunks(E::Fr::CAPACITY as usize) { let mut cur = E::Fr::zero(); let mut coeff = E::Fr::one(); @@ -80,13 +72,13 @@ pub fn compute_multipacking( #[test] fn test_multipacking() { - use crate::{ConstraintSystem}; - use pairing::bls12_381::{Bls12}; + use crate::ConstraintSystem; + use pairing::bls12_381::Bls12; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; - use crate::gadgets::test::*; use super::boolean::{AllocatedBit, Boolean}; + use crate::gadgets::test::*; let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -98,16 +90,15 @@ fn test_multipacking() { let bits: Vec = (0..num_bits).map(|_| rng.next_u32() % 2 != 0).collect(); - let circuit_bits = bits.iter().enumerate() - .map(|(i, &b)| { - Boolean::from( - AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - Some(b) - ).unwrap() - ) - }) - .collect::>(); + let circuit_bits = bits + .iter() + .enumerate() + .map(|(i, &b)| { + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| format!("bit {}", i)), Some(b)).unwrap(), + ) + }) + .collect::>(); let expected_inputs = compute_multipacking::(&bits); diff --git a/bellman/src/gadgets/num.rs b/bellman/src/gadgets/num.rs index 077301f..84843c1 100644 --- a/bellman/src/gadgets/num.rs +++ b/bellman/src/gadgets/num.rs @@ -1,78 +1,61 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr}; use pairing::Engine; -use crate::{ - SynthesisError, - ConstraintSystem, - LinearCombination, - Variable -}; +use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable}; -use super::{ - Assignment -}; +use super::Assignment; -use super::boolean::{ - self, - Boolean, - AllocatedBit -}; +use super::boolean::{self, AllocatedBit, Boolean}; pub struct AllocatedNum { value: Option, - variable: Variable + variable: Variable, } impl Clone for AllocatedNum { fn clone(&self) -> Self { AllocatedNum { value: self.value, - variable: self.variable + variable: self.variable, } } } impl AllocatedNum { - pub fn alloc( - mut cs: CS, - value: F, - ) -> Result - where CS: ConstraintSystem, - F: FnOnce() -> Result + pub fn alloc(mut cs: CS, value: F) -> Result + where + CS: ConstraintSystem, + F: FnOnce() -> Result, { let mut new_value = None; - let var = cs.alloc(|| "num", || { - let tmp = value()?; + let var = cs.alloc( + || "num", + || { + let tmp = value()?; - new_value = Some(tmp); + new_value = Some(tmp); - Ok(tmp) - })?; + Ok(tmp) + }, + )?; Ok(AllocatedNum { value: new_value, - variable: var + variable: var, }) } - pub fn inputize( - &self, - mut cs: CS - ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + pub fn inputize(&self, mut cs: CS) -> Result<(), SynthesisError> + where + CS: ConstraintSystem, { - let input = cs.alloc_input( - || "input variable", - || { - Ok(*self.value.get()?) - } - )?; + let input = cs.alloc_input(|| "input variable", || Ok(*self.value.get()?))?; cs.enforce( || "enforce input is correct", |lc| lc + input, |lc| lc + CS::one(), - |lc| lc + self.variable + |lc| lc + self.variable, ); Ok(()) @@ -83,18 +66,17 @@ impl AllocatedNum { /// order, requiring that the representation /// strictly exists "in the field" (i.e., a /// congruency is not allowed.) - pub fn into_bits_le_strict( - &self, - mut cs: CS - ) -> Result, SynthesisError> - where CS: ConstraintSystem + pub fn into_bits_le_strict(&self, mut cs: CS) -> Result, SynthesisError> + where + CS: ConstraintSystem, { pub fn kary_and( mut cs: CS, - v: &[AllocatedBit] + v: &[AllocatedBit], ) -> Result - where E: Engine, - CS: ConstraintSystem + where + E: Engine, + CS: ConstraintSystem, { assert!(v.len() > 0); @@ -109,7 +91,7 @@ impl AllocatedNum { cur = Some(AllocatedBit::and( cs.namespace(|| format!("and {}", i)), cur.as_ref().unwrap(), - v + v, )?); } } @@ -145,10 +127,7 @@ impl AllocatedNum { if b { // This is part of a run of ones. Let's just // allocate the boolean with the expected value. - let a_bit = AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - a_bit - )?; + let a_bit = AllocatedBit::alloc(cs.namespace(|| format!("bit {}", i)), a_bit)?; // ... and add it to the current run of ones. current_run.push(a_bit.clone()); result.push(a_bit); @@ -162,7 +141,7 @@ impl AllocatedNum { } last_run = Some(kary_and( cs.namespace(|| format!("run ending at {}", i)), - ¤t_run + ¤t_run, )?); current_run.truncate(0); } @@ -175,7 +154,7 @@ impl AllocatedNum { let a_bit = AllocatedBit::alloc_conditionally( cs.namespace(|| format!("bit {}", i)), a_bit, - &last_run.as_ref().expect("char always starts with a one") + &last_run.as_ref().expect("char always starts with a one"), )?; result.push(a_bit); } @@ -201,12 +180,7 @@ impl AllocatedNum { lc = lc - self.variable; - cs.enforce( - || "unpacking constraint", - |lc| lc, - |lc| lc, - |_| lc - ); + cs.enforce(|| "unpacking constraint", |lc| lc, |lc| lc, |_| lc); // Convert into booleans, and reverse for little-endian bit order Ok(result.into_iter().map(|b| Boolean::from(b)).rev().collect()) @@ -215,16 +189,11 @@ impl AllocatedNum { /// Convert the allocated number into its little-endian representation. /// Note that this does not strongly enforce that the commitment is /// "in the field." - pub fn into_bits_le( - &self, - mut cs: CS - ) -> Result, SynthesisError> - where CS: ConstraintSystem + pub fn into_bits_le(&self, mut cs: CS) -> Result, SynthesisError> + where + CS: ConstraintSystem, { - let bits = boolean::field_into_allocated_bits_le( - &mut cs, - self.value - )?; + let bits = boolean::field_into_allocated_bits_le(&mut cs, self.value)?; let mut lc = LinearCombination::zero(); let mut coeff = E::Fr::one(); @@ -237,94 +206,91 @@ impl AllocatedNum { lc = lc - self.variable; - cs.enforce( - || "unpacking constraint", - |lc| lc, - |lc| lc, - |_| lc - ); + cs.enforce(|| "unpacking constraint", |lc| lc, |lc| lc, |_| lc); Ok(bits.into_iter().map(|b| Boolean::from(b)).collect()) } - pub fn mul( - &self, - mut cs: CS, - other: &Self - ) -> Result - where CS: ConstraintSystem + pub fn mul(&self, mut cs: CS, other: &Self) -> Result + where + CS: ConstraintSystem, { let mut value = None; - let var = cs.alloc(|| "product num", || { - let mut tmp = *self.value.get()?; - tmp.mul_assign(other.value.get()?); + let var = cs.alloc( + || "product num", + || { + let mut tmp = *self.value.get()?; + tmp.mul_assign(other.value.get()?); - value = Some(tmp); + value = Some(tmp); - Ok(tmp) - })?; + Ok(tmp) + }, + )?; // Constrain: a * b = ab cs.enforce( || "multiplication constraint", |lc| lc + self.variable, |lc| lc + other.variable, - |lc| lc + var + |lc| lc + var, ); Ok(AllocatedNum { value: value, - variable: var + variable: var, }) } - pub fn square( - &self, - mut cs: CS - ) -> Result - where CS: ConstraintSystem + pub fn square(&self, mut cs: CS) -> Result + where + CS: ConstraintSystem, { let mut value = None; - let var = cs.alloc(|| "squared num", || { - let mut tmp = *self.value.get()?; - tmp.square(); + let var = cs.alloc( + || "squared num", + || { + let mut tmp = *self.value.get()?; + tmp.square(); - value = Some(tmp); + value = Some(tmp); - Ok(tmp) - })?; + Ok(tmp) + }, + )?; // Constrain: a * a = aa cs.enforce( || "squaring constraint", |lc| lc + self.variable, |lc| lc + self.variable, - |lc| lc + var + |lc| lc + var, ); Ok(AllocatedNum { value: value, - variable: var + variable: var, }) } - pub fn assert_nonzero( - &self, - mut cs: CS - ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + pub fn assert_nonzero(&self, mut cs: CS) -> Result<(), SynthesisError> + where + CS: ConstraintSystem, { - let inv = cs.alloc(|| "ephemeral inverse", || { - let tmp = *self.value.get()?; - - if tmp.is_zero() { - Err(SynthesisError::DivisionByZero) - } else { - Ok(tmp.inverse().unwrap()) - } - })?; + let inv = cs.alloc( + || "ephemeral inverse", + || { + let tmp = *self.value.get()?; + + if tmp.is_zero() { + Err(SynthesisError::DivisionByZero) + } else { + Ok(tmp.inverse().unwrap()) + } + }, + )?; // Constrain a * inv = 1, which is only valid // iff a has a multiplicative inverse, untrue @@ -333,7 +299,7 @@ impl AllocatedNum { || "nonzero assertion constraint", |lc| lc + self.variable, |lc| lc + inv, - |lc| lc + CS::one() + |lc| lc + CS::one(), ); Ok(()) @@ -346,44 +312,39 @@ impl AllocatedNum { mut cs: CS, a: &Self, b: &Self, - condition: &Boolean + condition: &Boolean, ) -> Result<(Self, Self), SynthesisError> - where CS: ConstraintSystem + where + CS: ConstraintSystem, { - let c = Self::alloc( - cs.namespace(|| "conditional reversal result 1"), - || { - if *condition.get_value().get()? { - Ok(*b.value.get()?) - } else { - Ok(*a.value.get()?) - } + let c = Self::alloc(cs.namespace(|| "conditional reversal result 1"), || { + if *condition.get_value().get()? { + Ok(*b.value.get()?) + } else { + Ok(*a.value.get()?) } - )?; + })?; cs.enforce( || "first conditional reversal", |lc| lc + a.variable - b.variable, |_| condition.lc(CS::one(), E::Fr::one()), - |lc| lc + a.variable - c.variable + |lc| lc + a.variable - c.variable, ); - let d = Self::alloc( - cs.namespace(|| "conditional reversal result 2"), - || { - if *condition.get_value().get()? { - Ok(*a.value.get()?) - } else { - Ok(*b.value.get()?) - } + let d = Self::alloc(cs.namespace(|| "conditional reversal result 2"), || { + if *condition.get_value().get()? { + Ok(*a.value.get()?) + } else { + Ok(*b.value.get()?) } - )?; + })?; cs.enforce( || "second conditional reversal", |lc| lc + b.variable - a.variable, |_| condition.lc(CS::one(), E::Fr::one()), - |lc| lc + b.variable - d.variable + |lc| lc + b.variable - d.variable, ); Ok((c, d)) @@ -400,14 +361,14 @@ impl AllocatedNum { pub struct Num { value: Option, - lc: LinearCombination + lc: LinearCombination, } impl From> for Num { fn from(num: AllocatedNum) -> Num { Num { value: num.value, - lc: LinearCombination::::zero() + num.variable + lc: LinearCombination::::zero() + num.variable, } } } @@ -416,7 +377,7 @@ impl Num { pub fn zero() -> Self { Num { value: Some(E::Fr::zero()), - lc: LinearCombination::zero() + lc: LinearCombination::zero(), } } @@ -428,13 +389,7 @@ impl Num { LinearCombination::zero() + (coeff, &self.lc) } - pub fn add_bool_with_coeff( - self, - one: Variable, - bit: &Boolean, - coeff: E::Fr - ) -> Self - { + pub fn add_bool_with_coeff(self, one: Variable, bit: &Boolean, coeff: E::Fr) -> Self { let newval = match (self.value, bit.get_value()) { (Some(mut curval), Some(bval)) => { if bval { @@ -442,27 +397,27 @@ impl Num { } Some(curval) - }, - _ => None + } + _ => None, }; Num { value: newval, - lc: self.lc + &bit.lc(one, coeff) + lc: self.lc + &bit.lc(one, coeff), } } } #[cfg(test)] mod test { - use crate::{ConstraintSystem}; + use crate::ConstraintSystem; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; - use crate::gadgets::test::*; use super::{AllocatedNum, Boolean}; + use crate::gadgets::test::*; #[test] fn test_allocated_num() { @@ -491,8 +446,10 @@ mod test { fn test_num_multiplication() { let mut cs = TestConstraintSystem::::new(); - let n = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::from_str("12").unwrap())).unwrap(); - let n2 = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::from_str("10").unwrap())).unwrap(); + let n = + AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::from_str("12").unwrap())).unwrap(); + let n2 = + AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::from_str("10").unwrap())).unwrap(); let n3 = n.mul(&mut cs, &n2).unwrap(); assert!(cs.is_satisfied()); @@ -505,8 +462,8 @@ mod test { #[test] fn test_num_conditional_reversal() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); { let mut cs = TestConstraintSystem::::new(); @@ -573,14 +530,17 @@ mod test { cs.set("bit 254/boolean", Fr::one()); // this makes the conditional boolean constraint fail - assert_eq!(cs.which_is_unsatisfied().unwrap(), "bit 254/boolean constraint"); + assert_eq!( + cs.which_is_unsatisfied().unwrap(), + "bit 254/boolean constraint" + ); } #[test] fn test_into_bits() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for i in 0..200 { @@ -597,7 +557,10 @@ mod test { assert!(cs.is_satisfied()); - for (b, a) in BitIterator::new(r.into_repr()).skip(1).zip(bits.iter().rev()) { + for (b, a) in BitIterator::new(r.into_repr()) + .skip(1) + .zip(bits.iter().rev()) + { if let &Boolean::Is(ref a) = a { assert_eq!(b, a.get_value().unwrap()); } else { diff --git a/bellman/src/gadgets/sha256.rs b/bellman/src/gadgets/sha256.rs index 2e4669e..cb057f8 100644 --- a/bellman/src/gadgets/sha256.rs +++ b/bellman/src/gadgets/sha256.rs @@ -1,6 +1,6 @@ -use super::uint32::UInt32; -use super::multieq::MultiEq; use super::boolean::Boolean; +use super::multieq::MultiEq; +use super::uint32::UInt32; use crate::{ConstraintSystem, SynthesisError}; use pairing::Engine; @@ -12,37 +12,35 @@ const ROUND_CONSTANTS: [u32; 64] = [ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, ]; const IV: [u32; 8] = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, ]; pub fn sha256_block_no_padding( mut cs: CS, - input: &[Boolean] + input: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(input.len(), 512); - Ok(sha256_compression_function( - &mut cs, - &input, - &get_sha256_iv() - )? - .into_iter() - .flat_map(|e| e.into_bits_be()) - .collect()) + Ok( + sha256_compression_function(&mut cs, &input, &get_sha256_iv())? + .into_iter() + .flat_map(|e| e.into_bits_be()) + .collect(), + ) } -pub fn sha256( - mut cs: CS, - input: &[Boolean] -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +pub fn sha256(mut cs: CS, input: &[Boolean]) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { assert!(input.len() % 8 == 0); @@ -62,16 +60,10 @@ pub fn sha256( let mut cur = get_sha256_iv(); for (i, block) in padded.chunks(512).enumerate() { - cur = sha256_compression_function( - cs.namespace(|| format!("block {}", i)), - block, - &cur - )?; + cur = sha256_compression_function(cs.namespace(|| format!("block {}", i)), block, &cur)?; } - Ok(cur.into_iter() - .flat_map(|e| e.into_bits_be()) - .collect()) + Ok(cur.into_iter().flat_map(|e| e.into_bits_be()).collect()) } fn get_sha256_iv() -> Vec { @@ -81,16 +73,19 @@ fn get_sha256_iv() -> Vec { fn sha256_compression_function( cs: CS, input: &[Boolean], - current_hash_value: &[UInt32] + current_hash_value: &[UInt32], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(input.len(), 512); assert_eq!(current_hash_value.len(), 8); - let mut w = input.chunks(32) - .map(|e| UInt32::from_bits_be(e)) - .collect::>(); + let mut w = input + .chunks(32) + .map(|e| UInt32::from_bits_be(e)) + .collect::>(); // We can save some constraints by combining some of // the constraints in different u32 additions @@ -100,30 +95,18 @@ fn sha256_compression_function( let cs = &mut cs.namespace(|| format!("w extension {}", i)); // s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3) - let mut s0 = w[i-15].rotr(7); - s0 = s0.xor( - cs.namespace(|| "first xor for s0"), - &w[i-15].rotr(18) - )?; - s0 = s0.xor( - cs.namespace(|| "second xor for s0"), - &w[i-15].shr(3) - )?; + let mut s0 = w[i - 15].rotr(7); + s0 = s0.xor(cs.namespace(|| "first xor for s0"), &w[i - 15].rotr(18))?; + s0 = s0.xor(cs.namespace(|| "second xor for s0"), &w[i - 15].shr(3))?; // s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10) - let mut s1 = w[i-2].rotr(17); - s1 = s1.xor( - cs.namespace(|| "first xor for s1"), - &w[i-2].rotr(19) - )?; - s1 = s1.xor( - cs.namespace(|| "second xor for s1"), - &w[i-2].shr(10) - )?; + let mut s1 = w[i - 2].rotr(17); + s1 = s1.xor(cs.namespace(|| "first xor for s1"), &w[i - 2].rotr(19))?; + s1 = s1.xor(cs.namespace(|| "second xor for s1"), &w[i - 2].shr(10))?; let tmp = UInt32::addmany( cs.namespace(|| "computation of w[i]"), - &[w[i-16].clone(), s0, w[i-7].clone(), s1] + &[w[i - 16].clone(), s0, w[i - 7].clone(), s1], )?; // w[i] := w[i-16] + s0 + w[i-7] + s1 @@ -134,29 +117,21 @@ fn sha256_compression_function( enum Maybe { Deferred(Vec), - Concrete(UInt32) + Concrete(UInt32), } impl Maybe { - fn compute( - self, - cs: M, - others: &[UInt32] - ) -> Result - where E: Engine, - CS: ConstraintSystem, - M: ConstraintSystem> + fn compute(self, cs: M, others: &[UInt32]) -> Result + where + E: Engine, + CS: ConstraintSystem, + M: ConstraintSystem>, { Ok(match self { - Maybe::Concrete(ref v) => { - return Ok(v.clone()) - }, + Maybe::Concrete(ref v) => return Ok(v.clone()), Maybe::Deferred(mut v) => { v.extend(others.into_iter().cloned()); - UInt32::addmany( - cs, - &v - )? + UInt32::addmany(cs, &v)? } }) } @@ -177,22 +152,11 @@ fn sha256_compression_function( // S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25) let new_e = e.compute(cs.namespace(|| "deferred e computation"), &[])?; let mut s1 = new_e.rotr(6); - s1 = s1.xor( - cs.namespace(|| "first xor for s1"), - &new_e.rotr(11) - )?; - s1 = s1.xor( - cs.namespace(|| "second xor for s1"), - &new_e.rotr(25) - )?; + s1 = s1.xor(cs.namespace(|| "first xor for s1"), &new_e.rotr(11))?; + s1 = s1.xor(cs.namespace(|| "second xor for s1"), &new_e.rotr(25))?; // ch := (e and f) xor ((not e) and g) - let ch = UInt32::sha256_ch( - cs.namespace(|| "ch"), - &new_e, - &f, - &g - )?; + let ch = UInt32::sha256_ch(cs.namespace(|| "ch"), &new_e, &f, &g)?; // temp1 := h + S1 + ch + k[i] + w[i] let temp1 = vec![ @@ -200,28 +164,17 @@ fn sha256_compression_function( s1, ch, UInt32::constant(ROUND_CONSTANTS[i]), - w[i].clone() + w[i].clone(), ]; // S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22) let new_a = a.compute(cs.namespace(|| "deferred a computation"), &[])?; let mut s0 = new_a.rotr(2); - s0 = s0.xor( - cs.namespace(|| "first xor for s0"), - &new_a.rotr(13) - )?; - s0 = s0.xor( - cs.namespace(|| "second xor for s0"), - &new_a.rotr(22) - )?; + s0 = s0.xor(cs.namespace(|| "first xor for s0"), &new_a.rotr(13))?; + s0 = s0.xor(cs.namespace(|| "second xor for s0"), &new_a.rotr(22))?; // maj := (a and b) xor (a and c) xor (b and c) - let maj = UInt32::sha256_maj( - cs.namespace(|| "maj"), - &new_a, - &b, - &c - )?; + let maj = UInt32::sha256_maj(cs.namespace(|| "maj"), &new_a, &b, &c)?; // temp2 := S0 + maj let temp2 = vec![s0, maj]; @@ -244,7 +197,13 @@ fn sha256_compression_function( d = c; c = b; b = new_a; - a = Maybe::Deferred(temp1.iter().cloned().chain(temp2.iter().cloned()).collect::>()); + a = Maybe::Deferred( + temp1 + .iter() + .cloned() + .chain(temp2.iter().cloned()) + .collect::>(), + ); } /* @@ -261,42 +220,42 @@ fn sha256_compression_function( let h0 = a.compute( cs.namespace(|| "deferred h0 computation"), - &[current_hash_value[0].clone()] + &[current_hash_value[0].clone()], )?; let h1 = UInt32::addmany( cs.namespace(|| "new h1"), - &[current_hash_value[1].clone(), b] + &[current_hash_value[1].clone(), b], )?; let h2 = UInt32::addmany( cs.namespace(|| "new h2"), - &[current_hash_value[2].clone(), c] + &[current_hash_value[2].clone(), c], )?; let h3 = UInt32::addmany( cs.namespace(|| "new h3"), - &[current_hash_value[3].clone(), d] + &[current_hash_value[3].clone(), d], )?; let h4 = e.compute( cs.namespace(|| "deferred h4 computation"), - &[current_hash_value[4].clone()] + &[current_hash_value[4].clone()], )?; let h5 = UInt32::addmany( cs.namespace(|| "new h5"), - &[current_hash_value[5].clone(), f] + &[current_hash_value[5].clone(), f], )?; let h6 = UInt32::addmany( cs.namespace(|| "new h6"), - &[current_hash_value[6].clone(), g] + &[current_hash_value[6].clone(), g], )?; let h7 = UInt32::addmany( cs.namespace(|| "new h7"), - &[current_hash_value[7].clone(), h] + &[current_hash_value[7].clone(), h], )?; Ok(vec![h0, h1, h2, h3, h4, h5, h6, h7]) @@ -306,8 +265,8 @@ fn sha256_compression_function( mod test { use super::*; use crate::gadgets::boolean::AllocatedBit; - use pairing::bls12_381::Bls12; use crate::gadgets::test::TestConstraintSystem; + use pairing::bls12_381::Bls12; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -318,11 +277,7 @@ mod test { let mut cs = TestConstraintSystem::::new(); let mut input_bits: Vec<_> = (0..512).map(|_| Boolean::Constant(false)).collect(); input_bits[0] = Boolean::Constant(true); - let out = sha256_compression_function( - &mut cs, - &input_bits, - &iv - ).unwrap(); + let out = sha256_compression_function(&mut cs, &input_bits, &iv).unwrap(); let out_bits: Vec<_> = out.into_iter().flat_map(|e| e.into_bits_be()).collect(); assert!(cs.is_satisfied()); @@ -343,27 +298,26 @@ mod test { #[test] fn test_full_block() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let iv = get_sha256_iv(); let mut cs = TestConstraintSystem::::new(); - let input_bits: Vec<_> = (0..512).map(|i| { - Boolean::from( - AllocatedBit::alloc( - cs.namespace(|| format!("input bit {}", i)), - Some(rng.next_u32() % 2 != 0) - ).unwrap() - ) - }).collect(); + let input_bits: Vec<_> = (0..512) + .map(|i| { + Boolean::from( + AllocatedBit::alloc( + cs.namespace(|| format!("input bit {}", i)), + Some(rng.next_u32() % 2 != 0), + ) + .unwrap(), + ) + }) + .collect(); - sha256_compression_function( - cs.namespace(|| "sha256"), - &input_bits, - &iv - ).unwrap(); + sha256_compression_function(cs.namespace(|| "sha256"), &input_bits, &iv).unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints() - 512, 25840); @@ -374,12 +328,11 @@ mod test { use sha2::{Digest, Sha256}; let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); - for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) - { + for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { let mut h = Sha256::new(); let data: Vec = (0..input_len).map(|_| rng.next_u32() as u8).collect(); h.input(&data); @@ -392,7 +345,11 @@ mod test { for bit_i in (0..8).rev() { let cs = cs.namespace(|| format!("input bit {} {}", byte_i, bit_i)); - input_bits.push(AllocatedBit::alloc(cs, Some((input_byte >> bit_i) & 1u8 == 1u8)).unwrap().into()); + input_bits.push( + AllocatedBit::alloc(cs, Some((input_byte >> bit_i) & 1u8 == 1u8)) + .unwrap() + .into(), + ); } } @@ -400,17 +357,19 @@ mod test { assert!(cs.is_satisfied()); - let mut s = hash_result.as_ref().iter() - .flat_map(|&byte| (0..8).rev().map(move |i| (byte >> i) & 1u8 == 1u8)); + let mut s = hash_result + .as_ref() + .iter() + .flat_map(|&byte| (0..8).rev().map(move |i| (byte >> i) & 1u8 == 1u8)); for b in r { match b { Boolean::Is(b) => { assert!(s.next().unwrap() == b.get_value().unwrap()); - }, + } Boolean::Not(b) => { assert!(s.next().unwrap() != b.get_value().unwrap()); - }, + } Boolean::Constant(b) => { assert!(input_len == 0); assert!(s.next().unwrap() == b); diff --git a/bellman/src/gadgets/test/mod.rs b/bellman/src/gadgets/test/mod.rs index dc6adbf..58ba040 100644 --- a/bellman/src/gadgets/test/mod.rs +++ b/bellman/src/gadgets/test/mod.rs @@ -1,13 +1,7 @@ use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::Engine; -use crate::{ - LinearCombination, - SynthesisError, - ConstraintSystem, - Variable, - Index -}; +use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable}; use std::collections::HashMap; use std::fmt::Write; @@ -22,7 +16,7 @@ use blake2s_simd::{Params as Blake2sParams, State as Blake2sState}; enum NamedObject { Constraint(usize), Var(Variable), - Namespace + Namespace, } /// Constraint system for testing purposes. @@ -33,10 +27,10 @@ pub struct TestConstraintSystem { LinearCombination, LinearCombination, LinearCombination, - String + String, )>, inputs: Vec<(E::Fr, String)>, - aux: Vec<(E::Fr, String)> + aux: Vec<(E::Fr, String)>, } #[derive(Clone, Copy)] @@ -48,7 +42,7 @@ impl PartialEq for OrderedVariable { match (self.0.get_unchecked(), other.0.get_unchecked()) { (Index::Input(ref a), Index::Input(ref b)) => a == b, (Index::Aux(ref a), Index::Aux(ref b)) => a == b, - _ => false + _ => false, } } } @@ -63,20 +57,17 @@ impl Ord for OrderedVariable { (Index::Input(ref a), Index::Input(ref b)) => a.cmp(b), (Index::Aux(ref a), Index::Aux(ref b)) => a.cmp(b), (Index::Input(_), Index::Aux(_)) => Ordering::Less, - (Index::Aux(_), Index::Input(_)) => Ordering::Greater + (Index::Aux(_), Index::Input(_)) => Ordering::Greater, } } } -fn proc_lc( - terms: &[(Variable, E::Fr)], -) -> BTreeMap -{ +fn proc_lc(terms: &[(Variable, E::Fr)]) -> BTreeMap { let mut map = BTreeMap::new(); for &(var, coeff) in terms { map.entry(OrderedVariable(var)) - .or_insert(E::Fr::zero()) - .add_assign(&coeff); + .or_insert(E::Fr::zero()) + .add_assign(&coeff); } // Remove terms that have a zero coefficient to normalize @@ -94,11 +85,7 @@ fn proc_lc( map } -fn hash_lc( - terms: &[(Variable, E::Fr)], - h: &mut Blake2sState -) -{ +fn hash_lc(terms: &[(Variable, E::Fr)], h: &mut Blake2sState) { let map = proc_lc::(terms); let mut buf = [0u8; 9 + 32]; @@ -110,13 +97,13 @@ fn hash_lc( Index::Input(i) => { buf[0] = b'I'; BigEndian::write_u64(&mut buf[1..9], i as u64); - }, + } Index::Aux(i) => { buf[0] = b'A'; BigEndian::write_u64(&mut buf[1..9], i as u64); } } - + coeff.into_repr().write_be(&mut buf[9..]).unwrap(); h.update(&buf); @@ -126,15 +113,14 @@ fn hash_lc( fn eval_lc( terms: &[(Variable, E::Fr)], inputs: &[(E::Fr, String)], - aux: &[(E::Fr, String)] -) -> E::Fr -{ + aux: &[(E::Fr, String)], +) -> E::Fr { let mut acc = E::Fr::zero(); for &(var, ref coeff) in terms { let mut tmp = match var.get_unchecked() { Index::Input(index) => inputs[index].0, - Index::Aux(index) => aux[index].0 + Index::Aux(index) => aux[index].0, }; tmp.mul_assign(&coeff); @@ -147,14 +133,17 @@ fn eval_lc( impl TestConstraintSystem { pub fn new() -> TestConstraintSystem { let mut map = HashMap::new(); - map.insert("ONE".into(), NamedObject::Var(TestConstraintSystem::::one())); + map.insert( + "ONE".into(), + NamedObject::Var(TestConstraintSystem::::one()), + ); TestConstraintSystem { named_objects: map, current_namespace: vec![], constraints: vec![], inputs: vec![(E::Fr::one(), "ONE".into())], - aux: vec![] + aux: vec![], } } @@ -167,9 +156,9 @@ impl TestConstraintSystem { tmp }; - let powers_of_two = (0..E::Fr::NUM_BITS).map(|i| { - E::Fr::from_str("2").unwrap().pow(&[i as u64]) - }).collect::>(); + let powers_of_two = (0..E::Fr::NUM_BITS) + .map(|i| E::Fr::from_str("2").unwrap().pow(&[i as u64])) + .collect::>(); let pp = |s: &mut String, lc: &LinearCombination| { write!(s, "(").unwrap(); @@ -196,7 +185,7 @@ impl TestConstraintSystem { match var.0.get_unchecked() { Index::Input(i) => { write!(s, "`{}`", &self.inputs[i].1).unwrap(); - }, + } Index::Aux(i) => { write!(s, "`{}`", &self.aux[i].1).unwrap(); } @@ -259,45 +248,41 @@ impl TestConstraintSystem { a.mul_assign(&b); if a != c { - return Some(&*path) + return Some(&*path); } } None } - pub fn is_satisfied(&self) -> bool - { + pub fn is_satisfied(&self) -> bool { self.which_is_unsatisfied().is_none() } - pub fn num_constraints(&self) -> usize - { + pub fn num_constraints(&self) -> usize { self.constraints.len() } - pub fn set(&mut self, path: &str, to: E::Fr) - { + pub fn set(&mut self, path: &str, to: E::Fr) { match self.named_objects.get(path) { - Some(&NamedObject::Var(ref v)) => { - match v.get_unchecked() { - Index::Input(index) => self.inputs[index].0 = to, - Index::Aux(index) => self.aux[index].0 = to - } - } - Some(e) => panic!("tried to set path `{}` to value, but `{:?}` already exists there.", path, e), - _ => panic!("no variable exists at path: {}", path) + Some(&NamedObject::Var(ref v)) => match v.get_unchecked() { + Index::Input(index) => self.inputs[index].0 = to, + Index::Aux(index) => self.aux[index].0 = to, + }, + Some(e) => panic!( + "tried to set path `{}` to value, but `{:?}` already exists there.", + path, e + ), + _ => panic!("no variable exists at path: {}", path), } } - pub fn verify(&self, expected: &[E::Fr]) -> bool - { + pub fn verify(&self, expected: &[E::Fr]) -> bool { assert_eq!(expected.len() + 1, self.inputs.len()); - for (a, b) in self.inputs.iter().skip(1).zip(expected.iter()) - { + for (a, b) in self.inputs.iter().skip(1).zip(expected.iter()) { if &a.0 != b { - return false + return false; } } @@ -308,8 +293,7 @@ impl TestConstraintSystem { self.inputs.len() } - pub fn get_input(&mut self, index: usize, path: &str) -> E::Fr - { + pub fn get_input(&mut self, index: usize, path: &str) -> E::Fr { let (assignment, name) = self.inputs[index].clone(); assert_eq!(path, name); @@ -317,17 +301,17 @@ impl TestConstraintSystem { assignment } - pub fn get(&mut self, path: &str) -> E::Fr - { + pub fn get(&mut self, path: &str) -> E::Fr { match self.named_objects.get(path) { - Some(&NamedObject::Var(ref v)) => { - match v.get_unchecked() { - Index::Input(index) => self.inputs[index].0, - Index::Aux(index) => self.aux[index].0 - } - } - Some(e) => panic!("tried to get value of path `{}`, but `{:?}` exists there (not a variable)", path, e), - _ => panic!("no variable exists at path: {}", path) + Some(&NamedObject::Var(ref v)) => match v.get_unchecked() { + Index::Input(index) => self.inputs[index].0, + Index::Aux(index) => self.aux[index].0, + }, + Some(e) => panic!( + "tried to get value of path `{}`, but `{:?}` exists there (not a variable)", + path, e + ), + _ => panic!("no variable exists at path: {}", path), } } @@ -348,8 +332,7 @@ fn compute_path(ns: &[String], this: String) -> String { let mut name = String::new(); let mut needs_separation = false; - for ns in ns.iter().chain(Some(&this).into_iter()) - { + for ns in ns.iter().chain(Some(&this).into_iter()) { if needs_separation { name += "/"; } @@ -364,12 +347,11 @@ fn compute_path(ns: &[String], this: String) -> String { impl ConstraintSystem for TestConstraintSystem { type Root = Self; - fn alloc( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { let index = self.aux.len(); let path = compute_path(&self.current_namespace, annotation().into()); @@ -380,12 +362,11 @@ impl ConstraintSystem for TestConstraintSystem { Ok(var) } - fn alloc_input( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc_input(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { let index = self.inputs.len(); let path = compute_path(&self.current_namespace, annotation().into()); @@ -396,17 +377,13 @@ impl ConstraintSystem for TestConstraintSystem { Ok(var) } - fn enforce( - &mut self, - annotation: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, { let path = compute_path(&self.current_namespace, annotation().into()); let index = self.constraints.len(); @@ -420,7 +397,9 @@ impl ConstraintSystem for TestConstraintSystem { } fn push_namespace(&mut self, name_fn: N) - where NR: Into, N: FnOnce() -> NR + where + NR: Into, + N: FnOnce() -> NR, { let name = name_fn().into(); let path = compute_path(&self.current_namespace, name.clone()); @@ -428,13 +407,11 @@ impl ConstraintSystem for TestConstraintSystem { self.current_namespace.push(name); } - fn pop_namespace(&mut self) - { + fn pop_namespace(&mut self) { assert!(self.current_namespace.pop().is_some()); } - fn get_root(&mut self) -> &mut Self::Root - { + fn get_root(&mut self) -> &mut Self::Root { self } } @@ -447,28 +424,26 @@ fn test_cs() { let mut cs = TestConstraintSystem::::new(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 0); - let a = cs.namespace(|| "a").alloc(|| "var", || Ok(Fr::from_str("10").unwrap())).unwrap(); - let b = cs.namespace(|| "b").alloc(|| "var", || Ok(Fr::from_str("4").unwrap())).unwrap(); - let c = cs.alloc(|| "product", || Ok(Fr::from_str("40").unwrap())).unwrap(); + let a = cs + .namespace(|| "a") + .alloc(|| "var", || Ok(Fr::from_str("10").unwrap())) + .unwrap(); + let b = cs + .namespace(|| "b") + .alloc(|| "var", || Ok(Fr::from_str("4").unwrap())) + .unwrap(); + let c = cs + .alloc(|| "product", || Ok(Fr::from_str("40").unwrap())) + .unwrap(); - cs.enforce( - || "mult", - |lc| lc + a, - |lc| lc + b, - |lc| lc + c - ); + cs.enforce(|| "mult", |lc| lc + a, |lc| lc + b, |lc| lc + c); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 1); cs.set("a/var", Fr::from_str("4").unwrap()); let one = TestConstraintSystem::::one(); - cs.enforce( - || "eq", - |lc| lc + a, - |lc| lc + one, - |lc| lc + b - ); + cs.enforce(|| "eq", |lc| lc + a, |lc| lc + one, |lc| lc + b); assert!(!cs.is_satisfied()); assert!(cs.which_is_unsatisfied() == Some("mult")); diff --git a/bellman/src/gadgets/uint32.rs b/bellman/src/gadgets/uint32.rs index 90f8d7e..4c0d376 100644 --- a/bellman/src/gadgets/uint32.rs +++ b/bellman/src/gadgets/uint32.rs @@ -1,16 +1,9 @@ use ff::{Field, PrimeField}; use pairing::Engine; -use crate::{ - SynthesisError, - ConstraintSystem, - LinearCombination -}; +use crate::{ConstraintSystem, LinearCombination, SynthesisError}; -use super::boolean::{ - Boolean, - AllocatedBit -}; +use super::boolean::{AllocatedBit, Boolean}; use super::multieq::MultiEq; @@ -20,13 +13,12 @@ use super::multieq::MultiEq; pub struct UInt32 { // Least significant bit first bits: Vec, - value: Option + value: Option, } impl UInt32 { /// Construct a constant `UInt32` from a `u32` - pub fn constant(value: u32) -> Self - { + pub fn constant(value: u32) -> Self { let mut bits = Vec::with_capacity(32); let mut tmp = value; @@ -42,17 +34,15 @@ impl UInt32 { UInt32 { bits: bits, - value: Some(value) + value: Some(value), } } /// Allocate a `UInt32` in the constraint system - pub fn alloc( - mut cs: CS, - value: Option - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn alloc(mut cs: CS, value: Option) -> Result + where + E: Engine, + CS: ConstraintSystem, { let values = match value { Some(mut val) => { @@ -64,23 +54,24 @@ impl UInt32 { } v - }, - None => vec![None; 32] + } + None => vec![None; 32], }; - let bits = values.into_iter() - .enumerate() - .map(|(i, v)| { - Ok(Boolean::from(AllocatedBit::alloc( - cs.namespace(|| format!("allocated bit {}", i)), - v - )?)) - }) - .collect::, SynthesisError>>()?; + let bits = values + .into_iter() + .enumerate() + .map(|(i, v)| { + Ok(Boolean::from(AllocatedBit::alloc( + cs.namespace(|| format!("allocated bit {}", i)), + v, + )?)) + }) + .collect::, SynthesisError>>()?; Ok(UInt32 { bits: bits, - value: value + value: value, }) } @@ -96,19 +87,22 @@ impl UInt32 { value.as_mut().map(|v| *v <<= 1); match b.get_value() { - Some(true) => { value.as_mut().map(|v| *v |= 1); }, - Some(false) => {}, - None => { value = None; } + Some(true) => { + value.as_mut().map(|v| *v |= 1); + } + Some(false) => {} + None => { + value = None; + } } } UInt32 { value: value, - bits: bits.iter().rev().cloned().collect() + bits: bits.iter().rev().cloned().collect(), } } - /// Turns this `UInt32` into its little-endian byte order representation. pub fn into_bits(&self) -> Vec { self.bits.clone() @@ -116,8 +110,7 @@ impl UInt32 { /// Converts a little-endian byte order representation of bits into a /// `UInt32`. - pub fn from_bits(bits: &[Boolean]) -> Self - { + pub fn from_bits(bits: &[Boolean]) -> Self { assert_eq!(bits.len(), 32); let new_bits = bits.to_vec(); @@ -131,43 +124,45 @@ impl UInt32 { if b { value.as_mut().map(|v| *v |= 1); } - }, - &Boolean::Is(ref b) => { - match b.get_value() { - Some(true) => { value.as_mut().map(|v| *v |= 1); }, - Some(false) => {}, - None => { value = None } - } - }, - &Boolean::Not(ref b) => { - match b.get_value() { - Some(false) => { value.as_mut().map(|v| *v |= 1); }, - Some(true) => {}, - None => { value = None } - } } + &Boolean::Is(ref b) => match b.get_value() { + Some(true) => { + value.as_mut().map(|v| *v |= 1); + } + Some(false) => {} + None => value = None, + }, + &Boolean::Not(ref b) => match b.get_value() { + Some(false) => { + value.as_mut().map(|v| *v |= 1); + } + Some(true) => {} + None => value = None, + }, } } UInt32 { value: value, - bits: new_bits + bits: new_bits, } } pub fn rotr(&self, by: usize) -> Self { let by = by % 32; - let new_bits = self.bits.iter() - .skip(by) - .chain(self.bits.iter()) - .take(32) - .cloned() - .collect(); + let new_bits = self + .bits + .iter() + .skip(by) + .chain(self.bits.iter()) + .take(32) + .cloned() + .collect(); UInt32 { bits: new_bits, - value: self.value.map(|v| v.rotate_right(by as u32)) + value: self.value.map(|v| v.rotate_right(by as u32)), } } @@ -176,17 +171,18 @@ impl UInt32 { let fill = Boolean::constant(false); - let new_bits = self.bits - .iter() // The bits are least significant first - .skip(by) // Skip the bits that will be lost during the shift - .chain(Some(&fill).into_iter().cycle()) // Rest will be zeros - .take(32) // Only 32 bits needed! - .cloned() - .collect(); + let new_bits = self + .bits + .iter() // The bits are least significant first + .skip(by) // Skip the bits that will be lost during the shift + .chain(Some(&fill).into_iter().cycle()) // Rest will be zeros + .take(32) // Only 32 bits needed! + .cloned() + .collect(); UInt32 { bits: new_bits, - value: self.value.map(|v| v >> by as u32) + value: self.value.map(|v| v >> by as u32), } } @@ -196,121 +192,99 @@ impl UInt32 { b: &Self, c: &Self, tri_fn: F, - circuit_fn: U + circuit_fn: U, ) -> Result - where E: Engine, - CS: ConstraintSystem, - F: Fn(u32, u32, u32) -> u32, - U: Fn(&mut CS, usize, &Boolean, &Boolean, &Boolean) -> Result + where + E: Engine, + CS: ConstraintSystem, + F: Fn(u32, u32, u32) -> u32, + U: Fn(&mut CS, usize, &Boolean, &Boolean, &Boolean) -> Result, { let new_value = match (a.value, b.value, c.value) { - (Some(a), Some(b), Some(c)) => { - Some(tri_fn(a, b, c)) - }, - _ => None + (Some(a), Some(b), Some(c)) => Some(tri_fn(a, b, c)), + _ => None, }; - let bits = a.bits.iter() - .zip(b.bits.iter()) - .zip(c.bits.iter()) - .enumerate() - .map(|(i, ((a, b), c))| circuit_fn(&mut cs, i, a, b, c)) - .collect::>()?; + let bits = a + .bits + .iter() + .zip(b.bits.iter()) + .zip(c.bits.iter()) + .enumerate() + .map(|(i, ((a, b), c))| circuit_fn(&mut cs, i, a, b, c)) + .collect::>()?; Ok(UInt32 { bits: bits, - value: new_value + value: new_value, }) } /// Compute the `maj` value (a and b) xor (a and c) xor (b and c) /// during SHA256. - pub fn sha256_maj( - cs: CS, - a: &Self, - b: &Self, - c: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn sha256_maj(cs: CS, a: &Self, b: &Self, c: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { - Self::triop(cs, a, b, c, |a, b, c| (a & b) ^ (a & c) ^ (b & c), - |cs, i, a, b, c| { - Boolean::sha256_maj( - cs.namespace(|| format!("maj {}", i)), - a, - b, - c - ) - } + Self::triop( + cs, + a, + b, + c, + |a, b, c| (a & b) ^ (a & c) ^ (b & c), + |cs, i, a, b, c| Boolean::sha256_maj(cs.namespace(|| format!("maj {}", i)), a, b, c), ) } /// Compute the `ch` value `(a and b) xor ((not a) and c)` /// during SHA256. - pub fn sha256_ch( - cs: CS, - a: &Self, - b: &Self, - c: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn sha256_ch(cs: CS, a: &Self, b: &Self, c: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { - Self::triop(cs, a, b, c, |a, b, c| (a & b) ^ ((!a) & c), - |cs, i, a, b, c| { - Boolean::sha256_ch( - cs.namespace(|| format!("ch {}", i)), - a, - b, - c - ) - } + Self::triop( + cs, + a, + b, + c, + |a, b, c| (a & b) ^ ((!a) & c), + |cs, i, a, b, c| Boolean::sha256_ch(cs.namespace(|| format!("ch {}", i)), a, b, c), ) } /// XOR this `UInt32` with another `UInt32` - pub fn xor( - &self, - mut cs: CS, - other: &Self - ) -> Result - where E: Engine, - CS: ConstraintSystem + pub fn xor(&self, mut cs: CS, other: &Self) -> Result + where + E: Engine, + CS: ConstraintSystem, { let new_value = match (self.value, other.value) { - (Some(a), Some(b)) => { - Some(a ^ b) - }, - _ => None + (Some(a), Some(b)) => Some(a ^ b), + _ => None, }; - let bits = self.bits.iter() - .zip(other.bits.iter()) - .enumerate() - .map(|(i, (a, b))| { - Boolean::xor( - cs.namespace(|| format!("xor of bit {}", i)), - a, - b - ) - }) - .collect::>()?; + let bits = self + .bits + .iter() + .zip(other.bits.iter()) + .enumerate() + .map(|(i, (a, b))| Boolean::xor(cs.namespace(|| format!("xor of bit {}", i)), a, b)) + .collect::>()?; Ok(UInt32 { bits: bits, - value: new_value + value: new_value, }) } /// Perform modular addition of several `UInt32` objects. - pub fn addmany( - mut cs: M, - operands: &[Self] - ) -> Result - where E: Engine, - CS: ConstraintSystem, - M: ConstraintSystem> + pub fn addmany(mut cs: M, operands: &[Self]) -> Result + where + E: Engine, + CS: ConstraintSystem, + M: ConstraintSystem>, { // Make some arbitrary bounds for ourselves to avoid overflows // in the scalar field @@ -337,7 +311,7 @@ impl UInt32 { match op.value { Some(val) => { result_value.as_mut().map(|v| *v += val as u64); - }, + } None => { // If any of our operands have unknown value, we won't // know the value of the result @@ -381,7 +355,7 @@ impl UInt32 { // Allocate the bit let b = AllocatedBit::alloc( cs.namespace(|| format!("result bit {}", i)), - result_value.map(|v| (v >> i) & 1 == 1) + result_value.map(|v| (v >> i) & 1 == 1), )?; // Add this bit to the result combination @@ -402,32 +376,34 @@ impl UInt32 { Ok(UInt32 { bits: result_bits, - value: modular_value + value: modular_value, }) } } #[cfg(test)] mod test { - use crate::gadgets::boolean::{Boolean}; - use super::{UInt32}; - use ff::Field; - use pairing::bls12_381::{Bls12}; - use crate::gadgets::test::*; - use crate::{ConstraintSystem}; + use super::UInt32; + use crate::gadgets::boolean::Boolean; use crate::gadgets::multieq::MultiEq; + use crate::gadgets::test::*; + use crate::ConstraintSystem; + use ff::Field; + use pairing::bls12_381::Bls12; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; #[test] fn test_uint32_from_bits_be() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { - let mut v = (0..32).map(|_| Boolean::constant(rng.next_u32() % 2 != 0)).collect::>(); + let mut v = (0..32) + .map(|_| Boolean::constant(rng.next_u32() % 2 != 0)) + .collect::>(); let b = UInt32::from_bits_be(&v); @@ -435,19 +411,18 @@ mod test { match bit { &Boolean::Constant(bit) => { assert!(bit == ((b.value.unwrap() >> i) & 1 == 1)); - }, - _ => unreachable!() + } + _ => unreachable!(), } } let expected_to_be_same = b.into_bits_be(); - for x in v.iter().zip(expected_to_be_same.iter()) - { + for x in v.iter().zip(expected_to_be_same.iter()) { match x { - (&Boolean::Constant(true), &Boolean::Constant(true)) => {}, - (&Boolean::Constant(false), &Boolean::Constant(false)) => {}, - _ => unreachable!() + (&Boolean::Constant(true), &Boolean::Constant(true)) => {} + (&Boolean::Constant(false), &Boolean::Constant(false)) => {} + _ => unreachable!(), } } } @@ -456,12 +431,14 @@ mod test { #[test] fn test_uint32_from_bits() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { - let mut v = (0..32).map(|_| Boolean::constant(rng.next_u32() % 2 != 0)).collect::>(); + let mut v = (0..32) + .map(|_| Boolean::constant(rng.next_u32() % 2 != 0)) + .collect::>(); let b = UInt32::from_bits(&v); @@ -469,19 +446,18 @@ mod test { match bit { &Boolean::Constant(bit) => { assert!(bit == ((b.value.unwrap() >> i) & 1 == 1)); - }, - _ => unreachable!() + } + _ => unreachable!(), } } let expected_to_be_same = b.into_bits(); - for x in v.iter().zip(expected_to_be_same.iter()) - { + for x in v.iter().zip(expected_to_be_same.iter()) { match x { - (&Boolean::Constant(true), &Boolean::Constant(true)) => {}, - (&Boolean::Constant(false), &Boolean::Constant(false)) => {}, - _ => unreachable!() + (&Boolean::Constant(true), &Boolean::Constant(true)) => {} + (&Boolean::Constant(false), &Boolean::Constant(false)) => {} + _ => unreachable!(), } } } @@ -490,8 +466,8 @@ mod test { #[test] fn test_uint32_xor() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -518,10 +494,10 @@ mod test { match b { &Boolean::Is(ref b) => { assert!(b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Not(ref b) => { assert!(!b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Constant(b) => { assert!(b == (expected & 1 == 1)); } @@ -535,8 +511,8 @@ mod test { #[test] fn test_uint32_addmany_constants() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -554,7 +530,8 @@ mod test { let r = { let mut cs = MultiEq::new(&mut cs); - let r = UInt32::addmany(cs.namespace(|| "addition"), &[a_bit, b_bit, c_bit]).unwrap(); + let r = + UInt32::addmany(cs.namespace(|| "addition"), &[a_bit, b_bit, c_bit]).unwrap(); r }; @@ -577,8 +554,8 @@ mod test { #[test] fn test_uint32_addmany() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -611,13 +588,11 @@ mod test { match b { &Boolean::Is(ref b) => { assert!(b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Not(ref b) => { assert!(!b.get_value().unwrap() == (expected & 1 == 1)); - }, - &Boolean::Constant(_) => { - unreachable!() } + &Boolean::Constant(_) => unreachable!(), } expected >>= 1; @@ -637,8 +612,8 @@ mod test { #[test] fn test_uint32_rotr() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let mut num = rng.next_u32(); @@ -656,8 +631,8 @@ mod test { match b { &Boolean::Constant(b) => { assert_eq!(b, tmp & 1 == 1); - }, - _ => unreachable!() + } + _ => unreachable!(), } tmp >>= 1; @@ -670,8 +645,8 @@ mod test { #[test] fn test_uint32_shr() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..50 { @@ -693,8 +668,8 @@ mod test { #[test] fn test_uint32_sha256_maj() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -720,10 +695,10 @@ mod test { match b { &Boolean::Is(ref b) => { assert!(b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Not(ref b) => { assert!(!b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Constant(b) => { assert!(b == (expected & 1 == 1)); } @@ -737,8 +712,8 @@ mod test { #[test] fn test_uint32_sha256_ch() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -764,10 +739,10 @@ mod test { match b { &Boolean::Is(ref b) => { assert!(b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Not(ref b) => { assert!(!b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Constant(b) => { assert!(b == (expected & 1 == 1)); } diff --git a/bellman/src/groth16/generator.rs b/bellman/src/groth16/generator.rs index 3e15b2b..596464f 100644 --- a/bellman/src/groth16/generator.rs +++ b/bellman/src/groth16/generator.rs @@ -6,36 +6,24 @@ use ff::{Field, PrimeField}; use group::{CurveAffine, CurveProjective, Wnaf}; use pairing::Engine; -use super::{ - Parameters, - VerifyingKey -}; +use super::{Parameters, VerifyingKey}; -use ::{ - SynthesisError, - Circuit, - ConstraintSystem, - LinearCombination, - Variable, - Index -}; +use {Circuit, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable}; -use ::domain::{ - EvaluationDomain, - Scalar -}; +use domain::{EvaluationDomain, Scalar}; -use ::multicore::{ - Worker -}; +use multicore::Worker; /// Generates a random common reference string for /// a circuit. pub fn generate_random_parameters( circuit: C, - rng: &mut R + rng: &mut R, ) -> Result, SynthesisError> - where E: Engine, C: Circuit, R: RngCore +where + E: Engine, + C: Circuit, + R: RngCore, { let g1 = E::G1::random(rng); let g2 = E::G2::random(rng); @@ -45,16 +33,7 @@ pub fn generate_random_parameters( let delta = E::Fr::random(rng); let tau = E::Fr::random(rng); - generate_parameters::( - circuit, - g1, - g2, - alpha, - beta, - gamma, - delta, - tau - ) + generate_parameters::(circuit, g1, g2, alpha, beta, gamma, delta, tau) } /// This is our assembly structure that we'll use to synthesize the @@ -68,18 +47,17 @@ struct KeypairAssembly { ct_inputs: Vec>, at_aux: Vec>, bt_aux: Vec>, - ct_aux: Vec> + ct_aux: Vec>, } impl ConstraintSystem for KeypairAssembly { type Root = Self; - fn alloc( - &mut self, - _: A, - _: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { // There is no assignment, so we don't even invoke the // function for obtaining one. @@ -94,12 +72,11 @@ impl ConstraintSystem for KeypairAssembly { Ok(Variable(Index::Aux(index))) } - fn alloc_input( - &mut self, - _: A, - _: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc_input(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { // There is no assignment, so we don't even invoke the // function for obtaining one. @@ -114,48 +91,59 @@ impl ConstraintSystem for KeypairAssembly { Ok(Variable(Index::Input(index))) } - fn enforce( - &mut self, - _: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + fn enforce(&mut self, _: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, { fn eval( l: LinearCombination, inputs: &mut [Vec<(E::Fr, usize)>], aux: &mut [Vec<(E::Fr, usize)>], - this_constraint: usize - ) - { + this_constraint: usize, + ) { for (index, coeff) in l.0 { match index { Variable(Index::Input(id)) => inputs[id].push((coeff, this_constraint)), - Variable(Index::Aux(id)) => aux[id].push((coeff, this_constraint)) + Variable(Index::Aux(id)) => aux[id].push((coeff, this_constraint)), } } } - eval(a(LinearCombination::zero()), &mut self.at_inputs, &mut self.at_aux, self.num_constraints); - eval(b(LinearCombination::zero()), &mut self.bt_inputs, &mut self.bt_aux, self.num_constraints); - eval(c(LinearCombination::zero()), &mut self.ct_inputs, &mut self.ct_aux, self.num_constraints); + eval( + a(LinearCombination::zero()), + &mut self.at_inputs, + &mut self.at_aux, + self.num_constraints, + ); + eval( + b(LinearCombination::zero()), + &mut self.bt_inputs, + &mut self.bt_aux, + self.num_constraints, + ); + eval( + c(LinearCombination::zero()), + &mut self.ct_inputs, + &mut self.ct_aux, + self.num_constraints, + ); self.num_constraints += 1; } fn push_namespace(&mut self, _: N) - where NR: Into, N: FnOnce() -> NR + where + NR: Into, + N: FnOnce() -> NR, { // Do nothing; we don't care about namespaces in this context. } - fn pop_namespace(&mut self) - { + fn pop_namespace(&mut self) { // Do nothing; we don't care about namespaces in this context. } @@ -173,9 +161,11 @@ pub fn generate_parameters( beta: E::Fr, gamma: E::Fr, delta: E::Fr, - tau: E::Fr + tau: E::Fr, ) -> Result, SynthesisError> - where E: Engine, C: Circuit +where + E: Engine, + C: Circuit, { let mut assembly = KeypairAssembly { num_inputs: 0, @@ -186,7 +176,7 @@ pub fn generate_parameters( ct_inputs: vec![], at_aux: vec![], bt_aux: vec![], - ct_aux: vec![] + ct_aux: vec![], }; // Allocate the "one" input variable @@ -198,11 +188,7 @@ pub fn generate_parameters( // Input constraints to ensure full density of IC query // x * 0 = 0 for i in 0..assembly.num_inputs { - assembly.enforce(|| "", - |lc| lc + Variable(Index::Input(i)), - |lc| lc, - |lc| lc, - ); + assembly.enforce(|| "", |lc| lc + Variable(Index::Input(i)), |lc| lc, |lc| lc); } // Create bases for blind evaluation of polynomials at tau @@ -240,10 +226,9 @@ pub fn generate_parameters( { let powers_of_tau = powers_of_tau.as_mut(); worker.scope(powers_of_tau.len(), |scope, chunk| { - for (i, powers_of_tau) in powers_of_tau.chunks_mut(chunk).enumerate() - { + for (i, powers_of_tau) in powers_of_tau.chunks_mut(chunk).enumerate() { scope.spawn(move || { - let mut current_tau_power = tau.pow(&[(i*chunk) as u64]); + let mut current_tau_power = tau.pow(&[(i * chunk) as u64]); for p in powers_of_tau { p.0 = current_tau_power; @@ -260,14 +245,15 @@ pub fn generate_parameters( // Compute the H query with multiple threads worker.scope(h.len(), |scope, chunk| { - for (h, p) in h.chunks_mut(chunk).zip(powers_of_tau.as_ref().chunks(chunk)) + for (h, p) in h + .chunks_mut(chunk) + .zip(powers_of_tau.as_ref().chunks(chunk)) { let mut g1_wnaf = g1_wnaf.shared(); scope.spawn(move || { // Set values of the H query to g1^{(tau^i * t(tau)) / delta} - for (h, p) in h.iter_mut().zip(p.iter()) - { + for (h, p) in h.iter_mut().zip(p.iter()) { // Compute final exponent let mut exp = p.0; exp.mul_assign(&coeff); @@ -320,9 +306,8 @@ pub fn generate_parameters( beta: &E::Fr, // Worker - worker: &Worker - ) - { + worker: &Worker, + ) { // Sanity check assert_eq!(a.len(), at.len()); assert_eq!(a.len(), bt.len()); @@ -333,31 +318,32 @@ pub fn generate_parameters( // Evaluate polynomials in multiple threads worker.scope(a.len(), |scope, chunk| { - for ((((((a, b_g1), b_g2), ext), at), bt), ct) in a.chunks_mut(chunk) - .zip(b_g1.chunks_mut(chunk)) - .zip(b_g2.chunks_mut(chunk)) - .zip(ext.chunks_mut(chunk)) - .zip(at.chunks(chunk)) - .zip(bt.chunks(chunk)) - .zip(ct.chunks(chunk)) + for ((((((a, b_g1), b_g2), ext), at), bt), ct) in a + .chunks_mut(chunk) + .zip(b_g1.chunks_mut(chunk)) + .zip(b_g2.chunks_mut(chunk)) + .zip(ext.chunks_mut(chunk)) + .zip(at.chunks(chunk)) + .zip(bt.chunks(chunk)) + .zip(ct.chunks(chunk)) { let mut g1_wnaf = g1_wnaf.shared(); let mut g2_wnaf = g2_wnaf.shared(); scope.spawn(move || { - for ((((((a, b_g1), b_g2), ext), at), bt), ct) in a.iter_mut() - .zip(b_g1.iter_mut()) - .zip(b_g2.iter_mut()) - .zip(ext.iter_mut()) - .zip(at.iter()) - .zip(bt.iter()) - .zip(ct.iter()) + for ((((((a, b_g1), b_g2), ext), at), bt), ct) in a + .iter_mut() + .zip(b_g1.iter_mut()) + .zip(b_g2.iter_mut()) + .zip(ext.iter_mut()) + .zip(at.iter()) + .zip(bt.iter()) + .zip(ct.iter()) { fn eval_at_tau( powers_of_tau: &[Scalar], - p: &[(E::Fr, usize)] - ) -> E::Fr - { + p: &[(E::Fr, usize)], + ) -> E::Fr { let mut acc = E::Fr::zero(); for &(ref coeff, index) in p { @@ -422,7 +408,7 @@ pub fn generate_parameters( &gamma_inverse, &alpha, &beta, - &worker + &worker, ); // Evaluate for auxiliary variables. @@ -440,7 +426,7 @@ pub fn generate_parameters( &delta_inverse, &alpha, &beta, - &worker + &worker, ); // Don't allow any elements be unconstrained, so that @@ -461,7 +447,7 @@ pub fn generate_parameters( gamma_g2: g2.mul(gamma).into_affine(), delta_g1: g1.mul(delta).into_affine(), delta_g2: g2.mul(delta).into_affine(), - ic: ic.into_iter().map(|e| e.into_affine()).collect() + ic: ic.into_iter().map(|e| e.into_affine()).collect(), }; Ok(Parameters { @@ -470,8 +456,23 @@ pub fn generate_parameters( l: Arc::new(l.into_iter().map(|e| e.into_affine()).collect()), // Filter points at infinity away from A/B queries - a: Arc::new(a.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()), - b_g1: Arc::new(b_g1.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()), - b_g2: Arc::new(b_g2.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()) + a: Arc::new( + a.into_iter() + .filter(|e| !e.is_zero()) + .map(|e| e.into_affine()) + .collect(), + ), + b_g1: Arc::new( + b_g1.into_iter() + .filter(|e| !e.is_zero()) + .map(|e| e.into_affine()) + .collect(), + ), + b_g2: Arc::new( + b_g2.into_iter() + .filter(|e| !e.is_zero()) + .map(|e| e.into_affine()) + .collect(), + ), }) } diff --git a/bellman/src/groth16/mod.rs b/bellman/src/groth16/mod.rs index 767150c..85b7952 100644 --- a/bellman/src/groth16/mod.rs +++ b/bellman/src/groth16/mod.rs @@ -1,17 +1,12 @@ use group::{CurveAffine, EncodedPoint}; -use pairing::{ - Engine, - PairingCurveAffine, -}; +use pairing::{Engine, PairingCurveAffine}; -use ::{ - SynthesisError -}; +use SynthesisError; +use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use multiexp::SourceBuilder; use std::io::{self, Read, Write}; use std::sync::Arc; -use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; #[cfg(test)] mod tests; @@ -28,23 +23,17 @@ pub use self::verifier::*; pub struct Proof { pub a: E::G1Affine, pub b: E::G2Affine, - pub c: E::G1Affine + pub c: E::G1Affine, } impl PartialEq for Proof { fn eq(&self, other: &Self) -> bool { - self.a == other.a && - self.b == other.b && - self.c == other.c + self.a == other.a && self.b == other.b && self.c == other.c } } impl Proof { - pub fn write( - &self, - mut writer: W - ) -> io::Result<()> - { + pub fn write(&self, mut writer: W) -> io::Result<()> { writer.write_all(self.a.into_compressed().as_ref())?; writer.write_all(self.b.into_compressed().as_ref())?; writer.write_all(self.c.into_compressed().as_ref())?; @@ -52,48 +41,56 @@ impl Proof { Ok(()) } - pub fn read( - mut reader: R - ) -> io::Result - { + pub fn read(mut reader: R) -> io::Result { let mut g1_repr = ::Compressed::empty(); let mut g2_repr = ::Compressed::empty(); reader.read_exact(g1_repr.as_mut())?; let a = g1_repr - .into_affine() - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) - .and_then(|e| if e.is_zero() { - Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) + .and_then(|e| { + if e.is_zero() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "point at infinity", + )) } else { Ok(e) - })?; + } + })?; reader.read_exact(g2_repr.as_mut())?; let b = g2_repr - .into_affine() - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) - .and_then(|e| if e.is_zero() { - Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) + .and_then(|e| { + if e.is_zero() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "point at infinity", + )) } else { Ok(e) - })?; + } + })?; reader.read_exact(g1_repr.as_mut())?; let c = g1_repr - .into_affine() - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) - .and_then(|e| if e.is_zero() { - Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) + .and_then(|e| { + if e.is_zero() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "point at infinity", + )) } else { Ok(e) - })?; + } + })?; - Ok(Proof { - a: a, - b: b, - c: c - }) + Ok(Proof { a: a, b: b, c: c }) } } @@ -122,27 +119,23 @@ pub struct VerifyingKey { // for all public inputs. Because all public inputs have a dummy constraint, // this is the same size as the number of inputs, and never contains points // at infinity. - pub ic: Vec + pub ic: Vec, } impl PartialEq for VerifyingKey { fn eq(&self, other: &Self) -> bool { - self.alpha_g1 == other.alpha_g1 && - self.beta_g1 == other.beta_g1 && - self.beta_g2 == other.beta_g2 && - self.gamma_g2 == other.gamma_g2 && - self.delta_g1 == other.delta_g1 && - self.delta_g2 == other.delta_g2 && - self.ic == other.ic + self.alpha_g1 == other.alpha_g1 + && self.beta_g1 == other.beta_g1 + && self.beta_g2 == other.beta_g2 + && self.gamma_g2 == other.gamma_g2 + && self.delta_g1 == other.delta_g1 + && self.delta_g2 == other.delta_g2 + && self.ic == other.ic } } impl VerifyingKey { - pub fn write( - &self, - mut writer: W - ) -> io::Result<()> - { + pub fn write(&self, mut writer: W) -> io::Result<()> { writer.write_all(self.alpha_g1.into_uncompressed().as_ref())?; writer.write_all(self.beta_g1.into_uncompressed().as_ref())?; writer.write_all(self.beta_g2.into_uncompressed().as_ref())?; @@ -157,30 +150,39 @@ impl VerifyingKey { Ok(()) } - pub fn read( - mut reader: R - ) -> io::Result - { + pub fn read(mut reader: R) -> io::Result { let mut g1_repr = ::Uncompressed::empty(); let mut g2_repr = ::Uncompressed::empty(); reader.read_exact(g1_repr.as_mut())?; - let alpha_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let alpha_g1 = g1_repr + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g1_repr.as_mut())?; - let beta_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let beta_g1 = g1_repr + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g2_repr.as_mut())?; - let beta_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let beta_g2 = g2_repr + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g2_repr.as_mut())?; - let gamma_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let gamma_g2 = g2_repr + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g1_repr.as_mut())?; - let delta_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let delta_g1 = g1_repr + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g2_repr.as_mut())?; - let delta_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let delta_g2 = g2_repr + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; let ic_len = reader.read_u32::()? as usize; @@ -189,13 +191,18 @@ impl VerifyingKey { for _ in 0..ic_len { reader.read_exact(g1_repr.as_mut())?; let g1 = g1_repr - .into_affine() - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) - .and_then(|e| if e.is_zero() { - Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) - } else { - Ok(e) - })?; + .into_affine() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) + .and_then(|e| { + if e.is_zero() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "point at infinity", + )) + } else { + Ok(e) + } + })?; ic.push(g1); } @@ -207,7 +214,7 @@ impl VerifyingKey { gamma_g2: gamma_g2, delta_g1: delta_g1, delta_g2: delta_g2, - ic: ic + ic: ic, }) } } @@ -216,7 +223,7 @@ impl VerifyingKey { pub struct Parameters { pub vk: VerifyingKey, - // Elements of the form ((tau^i * t(tau)) / delta) for i between 0 and + // Elements of the form ((tau^i * t(tau)) / delta) for i between 0 and // m-2 inclusive. Never contains points at infinity. pub h: Arc>, @@ -234,26 +241,22 @@ pub struct Parameters { // G1 and G2 for C/B queries, respectively. Never contains points at // infinity for the same reason as the "A" polynomials. pub b_g1: Arc>, - pub b_g2: Arc> + pub b_g2: Arc>, } impl PartialEq for Parameters { fn eq(&self, other: &Self) -> bool { - self.vk == other.vk && - self.h == other.h && - self.l == other.l && - self.a == other.a && - self.b_g1 == other.b_g1 && - self.b_g2 == other.b_g2 + self.vk == other.vk + && self.h == other.h + && self.l == other.l + && self.a == other.a + && self.b_g1 == other.b_g1 + && self.b_g2 == other.b_g2 } } impl Parameters { - pub fn write( - &self, - mut writer: W - ) -> io::Result<()> - { + pub fn write(&self, mut writer: W) -> io::Result<()> { self.vk.write(&mut writer)?; writer.write_u32::(self.h.len() as u32)?; @@ -284,27 +287,26 @@ impl Parameters { Ok(()) } - pub fn read( - mut reader: R, - checked: bool - ) -> io::Result - { + pub fn read(mut reader: R, checked: bool) -> io::Result { let read_g1 = |reader: &mut R| -> io::Result { let mut repr = ::Uncompressed::empty(); reader.read_exact(repr.as_mut())?; if checked { - repr - .into_affine() + repr.into_affine() } else { - repr - .into_affine_unchecked() + repr.into_affine_unchecked() } .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) - .and_then(|e| if e.is_zero() { - Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) - } else { - Ok(e) + .and_then(|e| { + if e.is_zero() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "point at infinity", + )) + } else { + Ok(e) + } }) }; @@ -313,17 +315,20 @@ impl Parameters { reader.read_exact(repr.as_mut())?; if checked { - repr - .into_affine() + repr.into_affine() } else { - repr - .into_affine_unchecked() + repr.into_affine_unchecked() } .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) - .and_then(|e| if e.is_zero() { - Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) - } else { - Ok(e) + .and_then(|e| { + if e.is_zero() { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "point at infinity", + )) + } else { + Ok(e) + } }) }; @@ -376,7 +381,7 @@ impl Parameters { l: Arc::new(l), a: Arc::new(a), b_g1: Arc::new(b_g1), - b_g2: Arc::new(b_g2) + b_g2: Arc::new(b_g2), }) } } @@ -389,39 +394,30 @@ pub struct PreparedVerifyingKey { /// -delta in G2 neg_delta_g2: ::Prepared, /// Copy of IC from `VerifiyingKey`. - ic: Vec + ic: Vec, } pub trait ParameterSource { type G1Builder: SourceBuilder; type G2Builder: SourceBuilder; - fn get_vk( - &mut self, - num_ic: usize - ) -> Result, SynthesisError>; - fn get_h( - &mut self, - num_h: usize - ) -> Result; - fn get_l( - &mut self, - num_l: usize - ) -> Result; + fn get_vk(&mut self, num_ic: usize) -> Result, SynthesisError>; + fn get_h(&mut self, num_h: usize) -> Result; + fn get_l(&mut self, num_l: usize) -> Result; fn get_a( &mut self, num_inputs: usize, - num_aux: usize + num_aux: usize, ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>; fn get_b_g1( &mut self, num_inputs: usize, - num_aux: usize + num_aux: usize, ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>; fn get_b_g2( &mut self, num_inputs: usize, - num_aux: usize + num_aux: usize, ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError>; } @@ -429,54 +425,39 @@ impl<'a, E: Engine> ParameterSource for &'a Parameters { type G1Builder = (Arc>, usize); type G2Builder = (Arc>, usize); - fn get_vk( - &mut self, - _: usize - ) -> Result, SynthesisError> - { + fn get_vk(&mut self, _: usize) -> Result, SynthesisError> { Ok(self.vk.clone()) } - fn get_h( - &mut self, - _: usize - ) -> Result - { + fn get_h(&mut self, _: usize) -> Result { Ok((self.h.clone(), 0)) } - fn get_l( - &mut self, - _: usize - ) -> Result - { + fn get_l(&mut self, _: usize) -> Result { Ok((self.l.clone(), 0)) } fn get_a( &mut self, num_inputs: usize, - _: usize - ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError> - { + _: usize, + ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError> { Ok(((self.a.clone(), 0), (self.a.clone(), num_inputs))) } fn get_b_g1( &mut self, num_inputs: usize, - _: usize - ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError> - { + _: usize, + ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError> { Ok(((self.b_g1.clone(), 0), (self.b_g1.clone(), num_inputs))) } fn get_b_g2( &mut self, num_inputs: usize, - _: usize - ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError> - { + _: usize, + ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError> { Ok(((self.b_g2.clone(), 0), (self.b_g2.clone(), num_inputs))) } } @@ -484,41 +465,38 @@ impl<'a, E: Engine> ParameterSource for &'a Parameters { #[cfg(test)] mod test_with_bls12_381 { use super::*; - use {Circuit, SynthesisError, ConstraintSystem}; + use {Circuit, ConstraintSystem, SynthesisError}; use ff::Field; - use rand::{thread_rng}; use pairing::bls12_381::{Bls12, Fr}; + use rand::thread_rng; #[test] fn serialization() { struct MySillyCircuit { a: Option, - b: Option + b: Option, } impl Circuit for MySillyCircuit { fn synthesize>( self, - cs: &mut CS - ) -> Result<(), SynthesisError> - { + cs: &mut CS, + ) -> Result<(), SynthesisError> { let a = cs.alloc(|| "a", || self.a.ok_or(SynthesisError::AssignmentMissing))?; let b = cs.alloc(|| "b", || self.b.ok_or(SynthesisError::AssignmentMissing))?; - let c = cs.alloc_input(|| "c", || { - let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?; - let b = self.b.ok_or(SynthesisError::AssignmentMissing)?; + let c = cs.alloc_input( + || "c", + || { + let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?; + let b = self.b.ok_or(SynthesisError::AssignmentMissing)?; - a.mul_assign(&b); - Ok(a) - })?; + a.mul_assign(&b); + Ok(a) + }, + )?; - cs.enforce( - || "a*b=c", - |lc| lc + a, - |lc| lc + b, - |lc| lc + c - ); + cs.enforce(|| "a*b=c", |lc| lc + a, |lc| lc + b, |lc| lc + c); Ok(()) } @@ -526,10 +504,9 @@ mod test_with_bls12_381 { let rng = &mut thread_rng(); - let params = generate_random_parameters::( - MySillyCircuit { a: None, b: None }, - rng - ).unwrap(); + let params = + generate_random_parameters::(MySillyCircuit { a: None, b: None }, rng) + .unwrap(); { let mut v = vec![]; @@ -555,11 +532,12 @@ mod test_with_bls12_381 { let proof = create_random_proof( MySillyCircuit { a: Some(a), - b: Some(b) + b: Some(b), }, ¶ms, - rng - ).unwrap(); + rng, + ) + .unwrap(); let mut v = vec![]; proof.write(&mut v).unwrap(); diff --git a/bellman/src/groth16/prover.rs b/bellman/src/groth16/prover.rs index ceb3dce..a502ac3 100644 --- a/bellman/src/groth16/prover.rs +++ b/bellman/src/groth16/prover.rs @@ -8,43 +8,23 @@ use ff::{Field, PrimeField}; use group::{CurveAffine, CurveProjective}; use pairing::Engine; -use super::{ - ParameterSource, - Proof -}; +use super::{ParameterSource, Proof}; -use ::{ - SynthesisError, - Circuit, - ConstraintSystem, - LinearCombination, - Variable, - Index -}; +use {Circuit, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable}; -use ::domain::{ - EvaluationDomain, - Scalar -}; +use domain::{EvaluationDomain, Scalar}; -use ::multiexp::{ - DensityTracker, - FullDensity, - multiexp -}; +use multiexp::{multiexp, DensityTracker, FullDensity}; -use ::multicore::{ - Worker -}; +use multicore::Worker; fn eval( lc: &LinearCombination, mut input_density: Option<&mut DensityTracker>, mut aux_density: Option<&mut DensityTracker>, input_assignment: &[E::Fr], - aux_assignment: &[E::Fr] -) -> E::Fr -{ + aux_assignment: &[E::Fr], +) -> E::Fr { let mut acc = E::Fr::zero(); for &(index, coeff) in lc.0.iter() { @@ -56,7 +36,7 @@ fn eval( if let Some(ref mut v) = input_density { v.inc(i); } - }, + } Variable(Index::Aux(i)) => { tmp = aux_assignment[i]; if let Some(ref mut v) = aux_density { @@ -66,10 +46,10 @@ fn eval( } if coeff == E::Fr::one() { - acc.add_assign(&tmp); + acc.add_assign(&tmp); } else { - tmp.mul_assign(&coeff); - acc.add_assign(&tmp); + tmp.mul_assign(&coeff); + acc.add_assign(&tmp); } } @@ -89,18 +69,17 @@ struct ProvingAssignment { // Assignments of variables input_assignment: Vec, - aux_assignment: Vec + aux_assignment: Vec, } impl ConstraintSystem for ProvingAssignment { type Root = Self; - fn alloc( - &mut self, - _: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc(&mut self, _: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { self.aux_assignment.push(f()?); self.a_aux_density.add_element(); @@ -109,12 +88,11 @@ impl ConstraintSystem for ProvingAssignment { Ok(Variable(Index::Aux(self.aux_assignment.len() - 1))) } - fn alloc_input( - &mut self, - _: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc_input(&mut self, _: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { self.input_assignment.push(f()?); self.b_input_density.add_element(); @@ -122,17 +100,13 @@ impl ConstraintSystem for ProvingAssignment { Ok(Variable(Index::Input(self.input_assignment.len() - 1))) } - fn enforce( - &mut self, - _: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + fn enforce(&mut self, _: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, { let a = a(LinearCombination::zero()); let b = b(LinearCombination::zero()); @@ -146,14 +120,14 @@ impl ConstraintSystem for ProvingAssignment { None, Some(&mut self.a_aux_density), &self.input_assignment, - &self.aux_assignment + &self.aux_assignment, ))); self.b.push(Scalar(eval( &b, Some(&mut self.b_input_density), Some(&mut self.b_aux_density), &self.input_assignment, - &self.aux_assignment + &self.aux_assignment, ))); self.c.push(Scalar(eval( &c, @@ -164,18 +138,19 @@ impl ConstraintSystem for ProvingAssignment { None, None, &self.input_assignment, - &self.aux_assignment + &self.aux_assignment, ))); } fn push_namespace(&mut self, _: N) - where NR: Into, N: FnOnce() -> NR + where + NR: Into, + N: FnOnce() -> NR, { // Do nothing; we don't care about namespaces in this context. } - fn pop_namespace(&mut self) - { + fn pop_namespace(&mut self) { // Do nothing; we don't care about namespaces in this context. } @@ -187,9 +162,12 @@ impl ConstraintSystem for ProvingAssignment { pub fn create_random_proof>( circuit: C, params: P, - rng: &mut R + rng: &mut R, ) -> Result, SynthesisError> - where E: Engine, C: Circuit, R: RngCore +where + E: Engine, + C: Circuit, + R: RngCore, { let r = E::Fr::random(rng); let s = E::Fr::random(rng); @@ -201,9 +179,11 @@ pub fn create_proof>( circuit: C, mut params: P, r: E::Fr, - s: E::Fr + s: E::Fr, ) -> Result, SynthesisError> - where E: Engine, C: Circuit +where + E: Engine, + C: Circuit, { let mut prover = ProvingAssignment { a_aux_density: DensityTracker::new(), @@ -213,7 +193,7 @@ pub fn create_proof>( b: vec![], c: vec![], input_assignment: vec![], - aux_assignment: vec![] + aux_assignment: vec![], }; prover.alloc_input(|| "", || Ok(E::Fr::one()))?; @@ -221,11 +201,7 @@ pub fn create_proof>( circuit.synthesize(&mut prover)?; for i in 0..prover.input_assignment.len() { - prover.enforce(|| "", - |lc| lc + Variable(Index::Input(i)), - |lc| lc, - |lc| lc, - ); + prover.enforce(|| "", |lc| lc + Variable(Index::Input(i)), |lc| lc, |lc| lc); } let worker = Worker::new(); @@ -259,31 +235,76 @@ pub fn create_proof>( }; // TODO: parallelize if it's even helpful - let input_assignment = Arc::new(prover.input_assignment.into_iter().map(|s| s.into_repr()).collect::>()); - let aux_assignment = Arc::new(prover.aux_assignment.into_iter().map(|s| s.into_repr()).collect::>()); + let input_assignment = Arc::new( + prover + .input_assignment + .into_iter() + .map(|s| s.into_repr()) + .collect::>(), + ); + let aux_assignment = Arc::new( + prover + .aux_assignment + .into_iter() + .map(|s| s.into_repr()) + .collect::>(), + ); - let l = multiexp(&worker, params.get_l(aux_assignment.len())?, FullDensity, aux_assignment.clone()); + let l = multiexp( + &worker, + params.get_l(aux_assignment.len())?, + FullDensity, + aux_assignment.clone(), + ); let a_aux_density_total = prover.a_aux_density.get_total_density(); - let (a_inputs_source, a_aux_source) = params.get_a(input_assignment.len(), a_aux_density_total)?; + let (a_inputs_source, a_aux_source) = + params.get_a(input_assignment.len(), a_aux_density_total)?; - let a_inputs = multiexp(&worker, a_inputs_source, FullDensity, input_assignment.clone()); - let a_aux = multiexp(&worker, a_aux_source, Arc::new(prover.a_aux_density), aux_assignment.clone()); + let a_inputs = multiexp( + &worker, + a_inputs_source, + FullDensity, + input_assignment.clone(), + ); + let a_aux = multiexp( + &worker, + a_aux_source, + Arc::new(prover.a_aux_density), + aux_assignment.clone(), + ); let b_input_density = Arc::new(prover.b_input_density); let b_input_density_total = b_input_density.get_total_density(); let b_aux_density = Arc::new(prover.b_aux_density); let b_aux_density_total = b_aux_density.get_total_density(); - let (b_g1_inputs_source, b_g1_aux_source) = params.get_b_g1(b_input_density_total, b_aux_density_total)?; + let (b_g1_inputs_source, b_g1_aux_source) = + params.get_b_g1(b_input_density_total, b_aux_density_total)?; - let b_g1_inputs = multiexp(&worker, b_g1_inputs_source, b_input_density.clone(), input_assignment.clone()); - let b_g1_aux = multiexp(&worker, b_g1_aux_source, b_aux_density.clone(), aux_assignment.clone()); + let b_g1_inputs = multiexp( + &worker, + b_g1_inputs_source, + b_input_density.clone(), + input_assignment.clone(), + ); + let b_g1_aux = multiexp( + &worker, + b_g1_aux_source, + b_aux_density.clone(), + aux_assignment.clone(), + ); - let (b_g2_inputs_source, b_g2_aux_source) = params.get_b_g2(b_input_density_total, b_aux_density_total)?; - - let b_g2_inputs = multiexp(&worker, b_g2_inputs_source, b_input_density, input_assignment); + let (b_g2_inputs_source, b_g2_aux_source) = + params.get_b_g2(b_input_density_total, b_aux_density_total)?; + + let b_g2_inputs = multiexp( + &worker, + b_g2_inputs_source, + b_input_density, + input_assignment, + ); let b_g2_aux = multiexp(&worker, b_g2_aux_source, b_aux_density, aux_assignment); if vk.delta_g1.is_zero() || vk.delta_g2.is_zero() { @@ -325,6 +346,6 @@ pub fn create_proof>( Ok(Proof { a: g_a.into_affine(), b: g_b.into_affine(), - c: g_c.into_affine() + c: g_c.into_affine(), }) } diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 654b814..4c5874d 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -1,12 +1,13 @@ use ff::{ - Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, - PrimeFieldRepr, ScalarEngine, SqrtField}; + Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, + SqrtField, +}; use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use pairing::{Engine, PairingCurveAffine}; +use rand_core::RngCore; use std::cmp::Ordering; use std::fmt; -use rand_core::RngCore; use std::num::Wrapping; const MODULUS_R: Wrapping = Wrapping(64513); @@ -80,9 +81,13 @@ impl SqrtField for Fr { fn legendre(&self) -> LegendreSymbol { // s = self^((r - 1) // 2) let s = self.pow([32256]); - if s == ::zero() { LegendreSymbol::Zero } - else if s == ::one() { LegendreSymbol::QuadraticResidue } - else { LegendreSymbol::QuadraticNonResidue } + if s == ::zero() { + LegendreSymbol::Zero + } else if s == ::one() { + LegendreSymbol::QuadraticResidue + } else { + LegendreSymbol::QuadraticNonResidue + } } fn sqrt(&self) -> Option { @@ -100,7 +105,7 @@ impl SqrtField for Fr { let mut m = Fr::S; while t != ::one() { - let mut i = 1; + let mut i = 1; { let mut t2i = t; t2i.square(); @@ -258,15 +263,18 @@ impl Engine for DummyEngine { type G2Affine = Fr; type Fq = Fr; type Fqe = Fr; - + // TODO: This should be F_645131 or something. Doesn't matter for now. type Fqk = Fr; fn miller_loop<'a, I>(i: I) -> Self::Fqk - where I: IntoIterator::Prepared, - &'a ::Prepared - )> + where + I: IntoIterator< + Item = &'a ( + &'a ::Prepared, + &'a ::Prepared, + ), + >, { let mut acc = ::zero(); @@ -280,8 +288,7 @@ impl Engine for DummyEngine { } /// Perform final exponentiation of the result of a miller loop. - fn final_exponentiation(this: &Self::Fqk) -> Option - { + fn final_exponentiation(this: &Self::Fqk) -> Option { Some(*this) } } @@ -308,9 +315,7 @@ impl CurveProjective for Fr { ::is_zero(self) } - fn batch_normalization(_: &mut [Self]) { - - } + fn batch_normalization(_: &mut [Self]) {} fn is_normalized(&self) -> bool { true @@ -332,8 +337,7 @@ impl CurveProjective for Fr { ::negate(self); } - fn mul_assign::Repr>>(&mut self, other: S) - { + fn mul_assign::Repr>>(&mut self, other: S) { let tmp = Fr::from_repr(other.into()).unwrap(); ::mul_assign(self, &tmp); @@ -415,8 +419,7 @@ impl CurveAffine for Fr { ::negate(self); } - fn mul::Repr>>(&self, other: S) -> Self::Projective - { + fn mul::Repr>>(&self, other: S) -> Self::Projective { let mut res = *self; let tmp = Fr::from_repr(other.into()).unwrap(); diff --git a/bellman/src/groth16/tests/mod.rs b/bellman/src/groth16/tests/mod.rs index 0e05c36..e6a36e4 100644 --- a/bellman/src/groth16/tests/mod.rs +++ b/bellman/src/groth16/tests/mod.rs @@ -6,86 +6,82 @@ use self::dummy_engine::*; use std::marker::PhantomData; -use ::{ - Circuit, - ConstraintSystem, - SynthesisError -}; +use {Circuit, ConstraintSystem, SynthesisError}; -use super::{ - generate_parameters, - prepare_verifying_key, - create_proof, - verify_proof -}; +use super::{create_proof, generate_parameters, prepare_verifying_key, verify_proof}; struct XORDemo { a: Option, b: Option, - _marker: PhantomData + _marker: PhantomData, } impl Circuit for XORDemo { - fn synthesize>( - self, - cs: &mut CS - ) -> Result<(), SynthesisError> - { - let a_var = cs.alloc(|| "a", || { - if self.a.is_some() { - if self.a.unwrap() { - Ok(E::Fr::one()) + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { + let a_var = cs.alloc( + || "a", + || { + if self.a.is_some() { + if self.a.unwrap() { + Ok(E::Fr::one()) + } else { + Ok(E::Fr::zero()) + } } else { - Ok(E::Fr::zero()) + Err(SynthesisError::AssignmentMissing) } - } else { - Err(SynthesisError::AssignmentMissing) - } - })?; + }, + )?; cs.enforce( || "a_boolean_constraint", |lc| lc + CS::one() - a_var, |lc| lc + a_var, - |lc| lc + |lc| lc, ); - let b_var = cs.alloc(|| "b", || { - if self.b.is_some() { - if self.b.unwrap() { - Ok(E::Fr::one()) + let b_var = cs.alloc( + || "b", + || { + if self.b.is_some() { + if self.b.unwrap() { + Ok(E::Fr::one()) + } else { + Ok(E::Fr::zero()) + } } else { - Ok(E::Fr::zero()) + Err(SynthesisError::AssignmentMissing) } - } else { - Err(SynthesisError::AssignmentMissing) - } - })?; + }, + )?; cs.enforce( || "b_boolean_constraint", |lc| lc + CS::one() - b_var, |lc| lc + b_var, - |lc| lc + |lc| lc, ); - let c_var = cs.alloc_input(|| "c", || { - if self.a.is_some() && self.b.is_some() { - if self.a.unwrap() ^ self.b.unwrap() { - Ok(E::Fr::one()) + let c_var = cs.alloc_input( + || "c", + || { + if self.a.is_some() && self.b.is_some() { + if self.a.unwrap() ^ self.b.unwrap() { + Ok(E::Fr::one()) + } else { + Ok(E::Fr::zero()) + } } else { - Ok(E::Fr::zero()) + Err(SynthesisError::AssignmentMissing) } - } else { - Err(SynthesisError::AssignmentMissing) - } - })?; + }, + )?; cs.enforce( || "c_xor_constraint", |lc| lc + a_var + a_var, |lc| lc + b_var, - |lc| lc + a_var + b_var - c_var + |lc| lc + a_var + b_var - c_var, ); Ok(()) @@ -106,19 +102,10 @@ fn test_xordemo() { let c = XORDemo:: { a: None, b: None, - _marker: PhantomData + _marker: PhantomData, }; - generate_parameters( - c, - g1, - g2, - alpha, - beta, - gamma, - delta, - tau - ).unwrap() + generate_parameters(c, g1, g2, alpha, beta, gamma, delta, tau).unwrap() }; // This will synthesize the constraint system: @@ -226,32 +213,35 @@ fn test_xordemo() { 59158 */ - let u_i = [59158, 48317, 21767, 10402].iter().map(|e| { - Fr::from_str(&format!("{}", e)).unwrap() - }).collect::>(); - let v_i = [0, 0, 60619, 30791].iter().map(|e| { - Fr::from_str(&format!("{}", e)).unwrap() - }).collect::>(); - let w_i = [0, 23320, 41193, 41193].iter().map(|e| { - Fr::from_str(&format!("{}", e)).unwrap() - }).collect::>(); + let u_i = [59158, 48317, 21767, 10402] + .iter() + .map(|e| Fr::from_str(&format!("{}", e)).unwrap()) + .collect::>(); + let v_i = [0, 0, 60619, 30791] + .iter() + .map(|e| Fr::from_str(&format!("{}", e)).unwrap()) + .collect::>(); + let w_i = [0, 23320, 41193, 41193] + .iter() + .map(|e| Fr::from_str(&format!("{}", e)).unwrap()) + .collect::>(); - for (u, a) in u_i.iter() - .zip(¶ms.a[..]) - { + for (u, a) in u_i.iter().zip(¶ms.a[..]) { assert_eq!(u, a); } - for (v, b) in v_i.iter() - .filter(|&&e| e != Fr::zero()) - .zip(¶ms.b_g1[..]) + for (v, b) in v_i + .iter() + .filter(|&&e| e != Fr::zero()) + .zip(¶ms.b_g1[..]) { assert_eq!(v, b); } - for (v, b) in v_i.iter() - .filter(|&&e| e != Fr::zero()) - .zip(¶ms.b_g2[..]) + for (v, b) in v_i + .iter() + .filter(|&&e| e != Fr::zero()) + .zip(¶ms.b_g2[..]) { assert_eq!(v, b); } @@ -296,15 +286,10 @@ fn test_xordemo() { let c = XORDemo { a: Some(true), b: Some(false), - _marker: PhantomData + _marker: PhantomData, }; - create_proof( - c, - ¶ms, - r, - s - ).unwrap() + create_proof(c, ¶ms, r, s).unwrap() }; // A(x) = @@ -320,7 +305,7 @@ fn test_xordemo() { expected_a.add_assign(&u_i[0]); // a_0 = 1 expected_a.add_assign(&u_i[1]); // a_1 = 1 expected_a.add_assign(&u_i[2]); // a_2 = 1 - // a_3 = 0 + // a_3 = 0 assert_eq!(proof.a, expected_a); } @@ -337,7 +322,7 @@ fn test_xordemo() { expected_b.add_assign(&v_i[0]); // a_0 = 1 expected_b.add_assign(&v_i[1]); // a_1 = 1 expected_b.add_assign(&v_i[2]); // a_2 = 1 - // a_3 = 0 + // a_3 = 0 assert_eq!(proof.b, expected_b); } @@ -378,7 +363,10 @@ fn test_xordemo() { expected_c.add_assign(¶ms.l[0]); // H query answer - for (i, coeff) in [5040, 11763, 10755, 63633, 128, 9747, 8739].iter().enumerate() { + for (i, coeff) in [5040, 11763, 10755, 63633, 128, 9747, 8739] + .iter() + .enumerate() + { let coeff = Fr::from_str(&format!("{}", coeff)).unwrap(); let mut tmp = params.h[i]; @@ -389,9 +377,5 @@ fn test_xordemo() { assert_eq!(expected_c, proof.c); } - assert!(verify_proof( - &pvk, - &proof, - &[Fr::one()] - ).unwrap()); + assert!(verify_proof(&pvk, &proof, &[Fr::one()]).unwrap()); } diff --git a/bellman/src/groth16/verifier.rs b/bellman/src/groth16/verifier.rs index 71c7478..926955a 100644 --- a/bellman/src/groth16/verifier.rs +++ b/bellman/src/groth16/verifier.rs @@ -2,20 +2,11 @@ use ff::PrimeField; use group::{CurveAffine, CurveProjective}; use pairing::{Engine, PairingCurveAffine}; -use super::{ - Proof, - VerifyingKey, - PreparedVerifyingKey -}; +use super::{PreparedVerifyingKey, Proof, VerifyingKey}; -use ::{ - SynthesisError -}; +use SynthesisError; -pub fn prepare_verifying_key( - vk: &VerifyingKey -) -> PreparedVerifyingKey -{ +pub fn prepare_verifying_key(vk: &VerifyingKey) -> PreparedVerifyingKey { let mut gamma = vk.gamma_g2; gamma.negate(); let mut delta = vk.delta_g2; @@ -25,16 +16,15 @@ pub fn prepare_verifying_key( alpha_g1_beta_g2: E::pairing(vk.alpha_g1, vk.beta_g2), neg_gamma_g2: gamma.prepare(), neg_delta_g2: delta.prepare(), - ic: vk.ic.clone() + ic: vk.ic.clone(), } } pub fn verify_proof<'a, E: Engine>( pvk: &'a PreparedVerifyingKey, proof: &Proof, - public_inputs: &[E::Fr] -) -> Result -{ + public_inputs: &[E::Fr], +) -> Result { if (public_inputs.len() + 1) != pvk.ic.len() { return Err(SynthesisError::MalformedVerifyingKey); } @@ -53,11 +43,14 @@ pub fn verify_proof<'a, E: Engine>( // A * B + inputs * (-gamma) + C * (-delta) = alpha * beta // which allows us to do a single final exponentiation. - Ok(E::final_exponentiation( - &E::miller_loop([ + Ok(E::final_exponentiation(&E::miller_loop( + [ (&proof.a.prepare(), &proof.b.prepare()), (&acc.into_affine().prepare(), &pvk.neg_gamma_g2), - (&proof.c.prepare(), &pvk.neg_delta_g2) - ].into_iter()) - ).unwrap() == pvk.alpha_g1_beta_g2) + (&proof.c.prepare(), &pvk.neg_delta_g2), + ] + .into_iter(), + )) + .unwrap() + == pvk.alpha_g1_beta_g2) } diff --git a/bellman/src/lib.rs b/bellman/src/lib.rs index ee6bb88..96400c9 100644 --- a/bellman/src/lib.rs +++ b/bellman/src/lib.rs @@ -4,10 +4,10 @@ extern crate group; extern crate pairing; extern crate rand_core; -extern crate futures; extern crate bit_vec; extern crate blake2s_simd; extern crate byteorder; +extern crate futures; #[cfg(feature = "multicore")] extern crate crossbeam; @@ -29,20 +29,20 @@ extern crate rand_xorshift; #[cfg(test)] extern crate sha2; -pub mod gadgets; -pub mod multicore; -mod multiexp; pub mod domain; +pub mod gadgets; #[cfg(feature = "groth16")] pub mod groth16; +pub mod multicore; +mod multiexp; use ff::{Field, ScalarEngine}; -use std::ops::{Add, Sub}; -use std::fmt; use std::error::Error; +use std::fmt; use std::io; use std::marker::PhantomData; +use std::ops::{Add, Sub}; /// Computations are expressed in terms of arithmetic circuits, in particular /// rank-1 quadratic constraint systems. The `Circuit` trait represents a @@ -50,10 +50,7 @@ use std::marker::PhantomData; /// CRS generation and during proving. pub trait Circuit { /// Synthesize the circuit into a rank-1 quadratic constraint system - fn synthesize>( - self, - cs: &mut CS - ) -> Result<(), SynthesisError>; + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError>; } /// Represents a variable in our constraint system. @@ -79,7 +76,7 @@ impl Variable { #[derive(Copy, Clone, PartialEq, Debug)] pub enum Index { Input(usize), - Aux(usize) + Aux(usize), } /// This represents a linear combination of some variables, with coefficients @@ -206,7 +203,7 @@ pub enum SynthesisError { /// During verification, our verifying key was malformed. MalformedVerifyingKey, /// During CRS generation, we observed an unconstrained auxiliary variable - UnconstrainedVariable + UnconstrainedVariable, } impl From for SynthesisError { @@ -218,14 +215,16 @@ impl From for SynthesisError { impl Error for SynthesisError { fn description(&self) -> &str { match *self { - SynthesisError::AssignmentMissing => "an assignment for a variable could not be computed", + SynthesisError::AssignmentMissing => { + "an assignment for a variable could not be computed" + } SynthesisError::DivisionByZero => "division by zero", SynthesisError::Unsatisfiable => "unsatisfiable constraint system", SynthesisError::PolynomialDegreeTooLarge => "polynomial degree is too large", SynthesisError::UnexpectedIdentity => "encountered an identity element in the CRS", SynthesisError::IoError(_) => "encountered an I/O error", SynthesisError::MalformedVerifyingKey => "malformed verifying key", - SynthesisError::UnconstrainedVariable => "auxiliary variable was unconstrained" + SynthesisError::UnconstrainedVariable => "auxiliary variable was unconstrained", } } } @@ -257,40 +256,36 @@ pub trait ConstraintSystem: Sized { /// determine the assignment of the variable. The given `annotation` function is invoked /// in testing contexts in order to derive a unique name for this variable in the current /// namespace. - fn alloc( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into; + fn alloc(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into; /// Allocate a public variable in the constraint system. The provided function is used to /// determine the assignment of the variable. - fn alloc_input( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into; + fn alloc_input(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into; /// Enforce that `A` * `B` = `C`. The `annotation` function is invoked in testing contexts /// in order to derive a unique name for the constraint in the current namespace. - fn enforce( - &mut self, - annotation: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination; + fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination; /// Create a new (sub)namespace and enter into it. Not intended /// for downstream use; use `namespace` instead. fn push_namespace(&mut self, name_fn: N) - where NR: Into, N: FnOnce() -> NR; + where + NR: Into, + N: FnOnce() -> NR; /// Exit out of the existing namespace. Not intended for /// downstream use; use `namespace` instead. @@ -301,11 +296,10 @@ pub trait ConstraintSystem: Sized { fn get_root(&mut self) -> &mut Self::Root; /// Begin a namespace for this constraint system. - fn namespace<'a, NR, N>( - &'a mut self, - name_fn: N - ) -> Namespace<'a, E, Self::Root> - where NR: Into, N: FnOnce() -> NR + fn namespace<'a, NR, N>(&'a mut self, name_fn: N) -> Namespace<'a, E, Self::Root> + where + NR: Into, + N: FnOnce() -> NR, { self.get_root().push_namespace(name_fn); @@ -324,37 +318,31 @@ impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for Name CS::one() } - fn alloc( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { self.0.alloc(annotation, f) } - fn alloc_input( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc_input(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { self.0.alloc_input(annotation, f) } - fn enforce( - &mut self, - annotation: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, { self.0.enforce(annotation, a, b, c) } @@ -364,18 +352,18 @@ impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for Name // never a root constraint system. fn push_namespace(&mut self, _: N) - where NR: Into, N: FnOnce() -> NR + where + NR: Into, + N: FnOnce() -> NR, { panic!("only the root's push_namespace should be called"); } - fn pop_namespace(&mut self) - { + fn pop_namespace(&mut self) { panic!("only the root's pop_namespace should be called"); } - fn get_root(&mut self) -> &mut Self::Root - { + fn get_root(&mut self) -> &mut Self::Root { self.0.get_root() } } @@ -395,54 +383,48 @@ impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for &'cs CS::one() } - fn alloc( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { (**self).alloc(annotation, f) } - fn alloc_input( - &mut self, - annotation: A, - f: F - ) -> Result - where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into + fn alloc_input(&mut self, annotation: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, { (**self).alloc_input(annotation, f) } - fn enforce( - &mut self, - annotation: A, - a: LA, - b: LB, - c: LC - ) - where A: FnOnce() -> AR, AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination + fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, { (**self).enforce(annotation, a, b, c) } fn push_namespace(&mut self, name_fn: N) - where NR: Into, N: FnOnce() -> NR + where + NR: Into, + N: FnOnce() -> NR, { (**self).push_namespace(name_fn) } - fn pop_namespace(&mut self) - { + fn pop_namespace(&mut self) { (**self).pop_namespace() } - fn get_root(&mut self) -> &mut Self::Root - { + fn get_root(&mut self) -> &mut Self::Root { (**self).get_root() } } diff --git a/bellman/src/multicore.rs b/bellman/src/multicore.rs index 8d0b00c..e8b2dae 100644 --- a/bellman/src/multicore.rs +++ b/bellman/src/multicore.rs @@ -6,15 +6,15 @@ #[cfg(feature = "multicore")] mod implementation { - use num_cpus; - use futures::{Future, IntoFuture, Poll}; - use futures_cpupool::{CpuPool, CpuFuture}; use crossbeam::{self, Scope}; + use futures::{Future, IntoFuture, Poll}; + use futures_cpupool::{CpuFuture, CpuPool}; + use num_cpus; #[derive(Clone)] pub struct Worker { cpus: usize, - pool: CpuPool + pool: CpuPool, } impl Worker { @@ -24,7 +24,7 @@ mod implementation { pub(crate) fn new_with_cpus(cpus: usize) -> Worker { Worker { cpus: cpus, - pool: CpuPool::new(cpus) + pool: CpuPool::new(cpus), } } @@ -36,26 +36,22 @@ mod implementation { log2_floor(self.cpus) } - pub fn compute( - &self, f: F - ) -> WorkerFuture - where F: FnOnce() -> R + Send + 'static, - R: IntoFuture + 'static, - R::Future: Send + 'static, - R::Item: Send + 'static, - R::Error: Send + 'static + pub fn compute(&self, f: F) -> WorkerFuture + where + F: FnOnce() -> R + Send + 'static, + R: IntoFuture + 'static, + R::Future: Send + 'static, + R::Item: Send + 'static, + R::Error: Send + 'static, { WorkerFuture { - future: self.pool.spawn_fn(f) + future: self.pool.spawn_fn(f), } } - pub fn scope<'a, F, R>( - &self, - elements: usize, - f: F - ) -> R - where F: FnOnce(&Scope<'a>, usize) -> R + pub fn scope<'a, F, R>(&self, elements: usize, f: F) -> R + where + F: FnOnce(&Scope<'a>, usize) -> R, { let chunk_size = if elements < self.cpus { 1 @@ -63,22 +59,19 @@ mod implementation { elements / self.cpus }; - crossbeam::scope(|scope| { - f(scope, chunk_size) - }) + crossbeam::scope(|scope| f(scope, chunk_size)) } } pub struct WorkerFuture { - future: CpuFuture + future: CpuFuture, } impl Future for WorkerFuture { type Item = T; type Error = E; - fn poll(&mut self) -> Poll - { + fn poll(&mut self) -> Poll { self.future.poll() } } @@ -88,7 +81,7 @@ mod implementation { let mut pow = 0; - while (1 << (pow+1)) <= num { + while (1 << (pow + 1)) <= num { pow += 1; } diff --git a/bellman/src/multiexp.rs b/bellman/src/multiexp.rs index c655397..fabb978 100644 --- a/bellman/src/multiexp.rs +++ b/bellman/src/multiexp.rs @@ -1,11 +1,11 @@ -use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine}; -use group::{CurveAffine, CurveProjective}; -use std::sync::Arc; -use std::io; -use bit_vec::{self, BitVec}; -use std::iter; -use futures::{Future}; use super::multicore::Worker; +use bit_vec::{self, BitVec}; +use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine}; +use futures::Future; +use group::{CurveAffine, CurveProjective}; +use std::io; +use std::iter; +use std::sync::Arc; use super::SynthesisError; @@ -19,7 +19,10 @@ pub trait SourceBuilder: Send + Sync + 'static + Clone { /// A source of bases, like an iterator. pub trait Source { /// Parses the element from the source. Fails if the point is at infinity. - fn add_assign_mixed(&mut self, to: &mut ::Projective) -> Result<(), SynthesisError>; + fn add_assign_mixed( + &mut self, + to: &mut ::Projective, + ) -> Result<(), SynthesisError>; /// Skips `amt` elements from the source, avoiding deserialization. fn skip(&mut self, amt: usize) -> Result<(), SynthesisError>; @@ -34,13 +37,20 @@ impl SourceBuilder for (Arc>, usize) { } impl Source for (Arc>, usize) { - fn add_assign_mixed(&mut self, to: &mut ::Projective) -> Result<(), SynthesisError> { + fn add_assign_mixed( + &mut self, + to: &mut ::Projective, + ) -> Result<(), SynthesisError> { if self.0.len() <= self.1 { - return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "expected more bases from source").into()); + return Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "expected more bases from source", + ) + .into()); } if self.0[self.1].is_zero() { - return Err(SynthesisError::UnexpectedIdentity) + return Err(SynthesisError::UnexpectedIdentity); } to.add_assign_mixed(&self.0[self.1]); @@ -52,7 +62,11 @@ impl Source for (Arc>, usize) { fn skip(&mut self, amt: usize) -> Result<(), SynthesisError> { if self.0.len() <= self.1 { - return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "expected more bases from source").into()); + return Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "expected more bases from source", + ) + .into()); } self.1 += amt; @@ -63,7 +77,7 @@ impl Source for (Arc>, usize) { pub trait QueryDensity { /// Returns whether the base exists. - type Iter: Iterator; + type Iter: Iterator; fn iter(self) -> Self::Iter; fn get_query_size(self) -> Option; @@ -92,7 +106,7 @@ impl<'a> QueryDensity for &'a FullDensity { pub struct DensityTracker { bv: BitVec, - total_density: usize + total_density: usize, } impl<'a> QueryDensity for &'a DensityTracker { @@ -111,7 +125,7 @@ impl DensityTracker { pub fn new() -> DensityTracker { DensityTracker { bv: BitVec::new(), - total_density: 0 + total_density: 0, } } @@ -138,12 +152,13 @@ fn multiexp_inner( exponents: Arc::Fr as PrimeField>::Repr>>, mut skip: u32, c: u32, - handle_trivial: bool -) -> Box::Projective, Error=SynthesisError>> - where for<'a> &'a Q: QueryDensity, - D: Send + Sync + 'static + Clone + AsRef, - G: CurveAffine, - S: SourceBuilder + handle_trivial: bool, +) -> Box::Projective, Error = SynthesisError>> +where + for<'a> &'a Q: QueryDensity, + D: Send + Sync + 'static + Clone + AsRef, + G: CurveAffine, + S: SourceBuilder, { // Perform this region of the multiexp let this = { @@ -212,16 +227,24 @@ fn multiexp_inner( // There's another region more significant. Calculate and join it with // this region recursively. Box::new( - this.join(multiexp_inner(pool, bases, density_map, exponents, skip, c, false)) - .map(move |(this, mut higher)| { - for _ in 0..c { - higher.double(); - } + this.join(multiexp_inner( + pool, + bases, + density_map, + exponents, + skip, + c, + false, + )) + .map(move |(this, mut higher)| { + for _ in 0..c { + higher.double(); + } - higher.add_assign(&this); + higher.add_assign(&this); - higher - }) + higher + }), ) } } @@ -232,12 +255,13 @@ pub fn multiexp( pool: &Worker, bases: S, density_map: D, - exponents: Arc::Fr as PrimeField>::Repr>> -) -> Box::Projective, Error=SynthesisError>> - where for<'a> &'a Q: QueryDensity, - D: Send + Sync + 'static + Clone + AsRef, - G: CurveAffine, - S: SourceBuilder + exponents: Arc::Fr as PrimeField>::Repr>>, +) -> Box::Projective, Error = SynthesisError>> +where + for<'a> &'a Q: QueryDensity, + D: Send + Sync + 'static + Clone + AsRef, + G: CurveAffine, + S: SourceBuilder, { let c = if exponents.len() < 32 { 3u32 @@ -260,9 +284,8 @@ pub fn multiexp( fn test_with_bls12() { fn naive_multiexp( bases: Arc>, - exponents: Arc::Repr>> - ) -> G::Projective - { + exponents: Arc::Repr>>, + ) -> G::Projective { assert_eq!(bases.len(), exponents.len()); let mut acc = G::Projective::zero(); @@ -274,25 +297,28 @@ fn test_with_bls12() { acc } - use rand; use pairing::{bls12_381::Bls12, Engine}; + use rand; const SAMPLES: usize = 1 << 14; let rng = &mut rand::thread_rng(); - let v = Arc::new((0..SAMPLES).map(|_| ::Fr::random(rng).into_repr()).collect::>()); - let g = Arc::new((0..SAMPLES).map(|_| ::G1::random(rng).into_affine()).collect::>()); + let v = Arc::new( + (0..SAMPLES) + .map(|_| ::Fr::random(rng).into_repr()) + .collect::>(), + ); + let g = Arc::new( + (0..SAMPLES) + .map(|_| ::G1::random(rng).into_affine()) + .collect::>(), + ); let naive = naive_multiexp(g.clone(), v.clone()); let pool = Worker::new(); - let fast = multiexp( - &pool, - (g, 0), - FullDensity, - v - ).wait().unwrap(); + let fast = multiexp(&pool, (g, 0), FullDensity, v).wait().unwrap(); assert_eq!(naive, fast); } diff --git a/bellman/tests/mimc.rs b/bellman/tests/mimc.rs index d08940f..18aaece 100644 --- a/bellman/tests/mimc.rs +++ b/bellman/tests/mimc.rs @@ -14,31 +14,21 @@ use ff::{Field, ScalarEngine}; use pairing::Engine; // We're going to use the BLS12-381 pairing-friendly elliptic curve. -use pairing::bls12_381::{ - Bls12 -}; +use pairing::bls12_381::Bls12; // We'll use these interfaces to construct our circuit. -use bellman::{ - Circuit, - ConstraintSystem, - SynthesisError -}; +use bellman::{Circuit, ConstraintSystem, SynthesisError}; // We're going to use the Groth16 proving system. use bellman::groth16::{ - Proof, - generate_random_parameters, - prepare_verifying_key, - create_random_proof, - verify_proof, + create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, Proof, }; const MIMC_ROUNDS: usize = 322; /// This is an implementation of MiMC, specifically a /// variant named `LongsightF322p3` for BLS12-381. -/// See http://eprint.iacr.org/2016/492 for more +/// See http://eprint.iacr.org/2016/492 for more /// information about this construction. /// /// ``` @@ -49,12 +39,7 @@ const MIMC_ROUNDS: usize = 322; /// return xL /// } /// ``` -fn mimc( - mut xl: E::Fr, - mut xr: E::Fr, - constants: &[E::Fr] -) -> E::Fr -{ +fn mimc(mut xl: E::Fr, mut xr: E::Fr, constants: &[E::Fr]) -> E::Fr { assert_eq!(constants.len(), MIMC_ROUNDS); for i in 0..MIMC_ROUNDS { @@ -76,31 +61,29 @@ fn mimc( struct MiMCDemo<'a, E: Engine> { xl: Option, xr: Option, - constants: &'a [E::Fr] + constants: &'a [E::Fr], } /// Our demo circuit implements this `Circuit` trait which /// is used during paramgen and proving in order to /// synthesize the constraint system. impl<'a, E: Engine> Circuit for MiMCDemo<'a, E> { - fn synthesize>( - self, - cs: &mut CS - ) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { assert_eq!(self.constants.len(), MIMC_ROUNDS); // Allocate the first component of the preimage. let mut xl_value = self.xl; - let mut xl = cs.alloc(|| "preimage xl", || { - xl_value.ok_or(SynthesisError::AssignmentMissing) - })?; + let mut xl = cs.alloc( + || "preimage xl", + || xl_value.ok_or(SynthesisError::AssignmentMissing), + )?; // Allocate the second component of the preimage. let mut xr_value = self.xr; - let mut xr = cs.alloc(|| "preimage xr", || { - xr_value.ok_or(SynthesisError::AssignmentMissing) - })?; + let mut xr = cs.alloc( + || "preimage xr", + || xr_value.ok_or(SynthesisError::AssignmentMissing), + )?; for i in 0..MIMC_ROUNDS { // xL, xR := xR + (xL + Ci)^3, xL @@ -112,15 +95,16 @@ impl<'a, E: Engine> Circuit for MiMCDemo<'a, E> { e.square(); e }); - let mut tmp = cs.alloc(|| "tmp", || { - tmp_value.ok_or(SynthesisError::AssignmentMissing) - })?; + let mut tmp = cs.alloc( + || "tmp", + || tmp_value.ok_or(SynthesisError::AssignmentMissing), + )?; cs.enforce( || "tmp = (xL + Ci)^2", |lc| lc + xl + (self.constants[i], CS::one()), |lc| lc + xl + (self.constants[i], CS::one()), - |lc| lc + tmp + |lc| lc + tmp, ); // new_xL = xR + (xL + Ci)^3 @@ -133,23 +117,25 @@ impl<'a, E: Engine> Circuit for MiMCDemo<'a, E> { e }); - let mut new_xl = if i == (MIMC_ROUNDS-1) { + let mut new_xl = if i == (MIMC_ROUNDS - 1) { // This is the last round, xL is our image and so // we allocate a public input. - cs.alloc_input(|| "image", || { - new_xl_value.ok_or(SynthesisError::AssignmentMissing) - })? + cs.alloc_input( + || "image", + || new_xl_value.ok_or(SynthesisError::AssignmentMissing), + )? } else { - cs.alloc(|| "new_xl", || { - new_xl_value.ok_or(SynthesisError::AssignmentMissing) - })? + cs.alloc( + || "new_xl", + || new_xl_value.ok_or(SynthesisError::AssignmentMissing), + )? }; cs.enforce( || "new_xL = xR + (xL + Ci)^3", |lc| lc + tmp, |lc| lc + xl + (self.constants[i], CS::one()), - |lc| lc + new_xl - xr + |lc| lc + new_xl - xr, ); // xR = xL @@ -172,7 +158,9 @@ fn test_mimc() { let rng = &mut thread_rng(); // Generate the MiMC round constants - let constants = (0..MIMC_ROUNDS).map(|_| ::Fr::random(rng)).collect::>(); + let constants = (0..MIMC_ROUNDS) + .map(|_| ::Fr::random(rng)) + .collect::>(); println!("Creating parameters..."); @@ -181,7 +169,7 @@ fn test_mimc() { let c = MiMCDemo:: { xl: None, xr: None, - constants: &constants + constants: &constants, }; generate_random_parameters(c, rng).unwrap() @@ -216,7 +204,7 @@ fn test_mimc() { let c = MiMCDemo { xl: Some(xl), xr: Some(xr), - constants: &constants + constants: &constants, }; // Create a groth16 proof with our parameters. @@ -230,20 +218,16 @@ fn test_mimc() { let start = Instant::now(); let proof = Proof::read(&proof_vec[..]).unwrap(); // Check the proof - assert!(verify_proof( - &pvk, - &proof, - &[image] - ).unwrap()); + assert!(verify_proof(&pvk, &proof, &[image]).unwrap()); total_verifying += start.elapsed(); } let proving_avg = total_proving / SAMPLES; - let proving_avg = proving_avg.subsec_nanos() as f64 / 1_000_000_000f64 - + (proving_avg.as_secs() as f64); + let proving_avg = + proving_avg.subsec_nanos() as f64 / 1_000_000_000f64 + (proving_avg.as_secs() as f64); let verifying_avg = total_verifying / SAMPLES; - let verifying_avg = verifying_avg.subsec_nanos() as f64 / 1_000_000_000f64 - + (verifying_avg.as_secs() as f64); + let verifying_avg = + verifying_avg.subsec_nanos() as f64 / 1_000_000_000f64 + (verifying_avg.as_secs() as f64); println!("Average proving time: {:?} seconds", proving_avg); println!("Average verifying time: {:?} seconds", verifying_avg); From 81c58172c30678fc0aa86b0ef747ca6cc8412e18 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 15 Aug 2019 10:39:55 -0600 Subject: [PATCH 068/105] cargo fmt zcash_primitives --- zcash_primitives/benches/pedersen_hash.rs | 12 +- zcash_primitives/src/constants.rs | 28 +- zcash_primitives/src/group_hash.rs | 19 +- zcash_primitives/src/jubjub/edwards.rs | 125 ++-- zcash_primitives/src/jubjub/fs.rs | 560 ++++++++++++++---- zcash_primitives/src/jubjub/mod.rs | 139 +++-- zcash_primitives/src/jubjub/montgomery.rs | 87 +-- zcash_primitives/src/jubjub/tests.rs | 49 +- zcash_primitives/src/keys.rs | 6 +- zcash_primitives/src/note_encryption.rs | 22 +- zcash_primitives/src/pedersen_hash.rs | 22 +- zcash_primitives/src/primitives.rs | 168 +++--- zcash_primitives/src/prover.rs | 2 +- zcash_primitives/src/redjubjub.rs | 48 +- zcash_primitives/src/sapling.rs | 6 +- zcash_primitives/src/transaction/builder.rs | 6 +- .../src/transaction/components.rs | 2 +- zcash_primitives/src/zip32.rs | 5 +- 18 files changed, 786 insertions(+), 520 deletions(-) diff --git a/zcash_primitives/benches/pedersen_hash.rs b/zcash_primitives/benches/pedersen_hash.rs index a8f944e..b647740 100644 --- a/zcash_primitives/benches/pedersen_hash.rs +++ b/zcash_primitives/benches/pedersen_hash.rs @@ -1,14 +1,14 @@ #![feature(test)] +extern crate pairing; extern crate rand_core; extern crate rand_os; extern crate test; -extern crate pairing; extern crate zcash_primitives; +use pairing::bls12_381::Bls12; use rand_core::RngCore; use rand_os::OsRng; -use pairing::bls12_381::Bls12; use zcash_primitives::jubjub::JubjubBls12; use zcash_primitives::pedersen_hash::{pedersen_hash, Personalization}; @@ -16,10 +16,10 @@ use zcash_primitives::pedersen_hash::{pedersen_hash, Personalization}; fn bench_pedersen_hash(b: &mut test::Bencher) { let params = JubjubBls12::new(); let rng = &mut OsRng; - let bits = (0..510).map(|_| (rng.next_u32() % 2) != 0).collect::>(); + let bits = (0..510) + .map(|_| (rng.next_u32() % 2) != 0) + .collect::>(); let personalization = Personalization::MerkleTree(31); - b.iter(|| { - pedersen_hash::(personalization, bits.clone(), ¶ms) - }); + b.iter(|| pedersen_hash::(personalization, bits.clone(), ¶ms)); } diff --git a/zcash_primitives/src/constants.rs b/zcash_primitives/src/constants.rs index dfdd36f..c21184d 100644 --- a/zcash_primitives/src/constants.rs +++ b/zcash_primitives/src/constants.rs @@ -2,39 +2,31 @@ /// This is chosen to be some random string that we couldn't have anticipated when we designed /// the algorithm, for rigidity purposes. /// We deliberately use an ASCII hex string of 32 bytes here. -pub const GH_FIRST_BLOCK: &'static [u8; 64] - = b"096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0"; +pub const GH_FIRST_BLOCK: &'static [u8; 64] = + b"096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0"; // BLAKE2s invocation personalizations /// BLAKE2s Personalization for CRH^ivk = BLAKE2s(ak | nk) -pub const CRH_IVK_PERSONALIZATION: &'static [u8; 8] - = b"Zcashivk"; +pub const CRH_IVK_PERSONALIZATION: &'static [u8; 8] = b"Zcashivk"; /// BLAKE2s Personalization for PRF^nf = BLAKE2s(nk | rho) -pub const PRF_NF_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_nf"; +pub const PRF_NF_PERSONALIZATION: &'static [u8; 8] = b"Zcash_nf"; // Group hash personalizations /// BLAKE2s Personalization for Pedersen hash generators. -pub const PEDERSEN_HASH_GENERATORS_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_PH"; +pub const PEDERSEN_HASH_GENERATORS_PERSONALIZATION: &'static [u8; 8] = b"Zcash_PH"; /// BLAKE2s Personalization for the group hash for key diversification -pub const KEY_DIVERSIFICATION_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_gd"; +pub const KEY_DIVERSIFICATION_PERSONALIZATION: &'static [u8; 8] = b"Zcash_gd"; /// BLAKE2s Personalization for the spending key base point -pub const SPENDING_KEY_GENERATOR_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_G_"; +pub const SPENDING_KEY_GENERATOR_PERSONALIZATION: &'static [u8; 8] = b"Zcash_G_"; /// BLAKE2s Personalization for the proof generation key base point -pub const PROOF_GENERATION_KEY_BASE_GENERATOR_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_H_"; +pub const PROOF_GENERATION_KEY_BASE_GENERATOR_PERSONALIZATION: &'static [u8; 8] = b"Zcash_H_"; /// BLAKE2s Personalization for the value commitment generator for the value -pub const VALUE_COMMITMENT_GENERATOR_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_cv"; +pub const VALUE_COMMITMENT_GENERATOR_PERSONALIZATION: &'static [u8; 8] = b"Zcash_cv"; /// BLAKE2s Personalization for the nullifier position generator (for computing rho) -pub const NULLIFIER_POSITION_IN_TREE_GENERATOR_PERSONALIZATION: &'static [u8; 8] - = b"Zcash_J_"; +pub const NULLIFIER_POSITION_IN_TREE_GENERATOR_PERSONALIZATION: &'static [u8; 8] = b"Zcash_J_"; diff --git a/zcash_primitives/src/group_hash.rs b/zcash_primitives/src/group_hash.rs index 7369e04..dec59cd 100644 --- a/zcash_primitives/src/group_hash.rs +++ b/zcash_primitives/src/group_hash.rs @@ -1,12 +1,6 @@ -use jubjub::{ - JubjubEngine, - PrimeOrder, - edwards -}; +use jubjub::{edwards, JubjubEngine, PrimeOrder}; -use ff::{ - PrimeField -}; +use ff::PrimeField; use blake2s_simd::Params; use constants; @@ -17,9 +11,8 @@ use constants; pub fn group_hash( tag: &[u8], personalization: &[u8], - params: &E::Params -) -> Option> -{ + params: &E::Params, +) -> Option> { assert_eq!(personalization.len(), 8); // Check to see that scalar field is 255 bits @@ -42,7 +35,7 @@ pub fn group_hash( } else { None } - }, - Err(_) => None + } + Err(_) => None, } } diff --git a/zcash_primitives/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs index e912aca..b3cdd64 100644 --- a/zcash_primitives/src/jubjub/edwards.rs +++ b/zcash_primitives/src/jubjub/edwards.rs @@ -1,22 +1,12 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; -use super::{ - JubjubEngine, - JubjubParams, - Unknown, - PrimeOrder, - montgomery -}; +use super::{montgomery, JubjubEngine, JubjubParams, PrimeOrder, Unknown}; use rand_core::RngCore; use std::marker::PhantomData; -use std::io::{ - self, - Write, - Read -}; +use std::io::{self, Read, Write}; // Represents the affine point (X/Z, Y/Z) via the extended // twisted Edwards coordinates. @@ -29,46 +19,38 @@ pub struct Point { y: E::Fr, t: E::Fr, z: E::Fr, - _marker: PhantomData + _marker: PhantomData, } -fn convert_subgroup(from: &Point) -> Point -{ +fn convert_subgroup(from: &Point) -> Point { Point { x: from.x, y: from.y, t: from.t, z: from.z, - _marker: PhantomData + _marker: PhantomData, } } -impl From<&Point> for Point -{ - fn from(p: &Point) -> Point - { +impl From<&Point> for Point { + fn from(p: &Point) -> Point { p.clone() } } -impl From> for Point -{ - fn from(p: Point) -> Point - { +impl From> for Point { + fn from(p: Point) -> Point { convert_subgroup(&p) } } -impl From<&Point> for Point -{ - fn from(p: &Point) -> Point - { +impl From<&Point> for Point { + fn from(p: &Point) -> Point { convert_subgroup(p) } } -impl Clone for Point -{ +impl Clone for Point { fn clone(&self) -> Self { convert_subgroup(self) } @@ -99,11 +81,7 @@ impl PartialEq for Point { } impl Point { - pub fn read( - reader: R, - params: &E::Params - ) -> io::Result - { + pub fn read(reader: R, params: &E::Params) -> io::Result { let mut y_repr = ::Repr::default(); y_repr.read_le(reader)?; @@ -111,22 +89,18 @@ impl Point { y_repr.as_mut()[3] &= 0x7fffffffffffffff; match E::Fr::from_repr(y_repr) { - Ok(y) => { - match Self::get_for_y(y, x_sign, params) { - Some(p) => Ok(p), - None => { - Err(io::Error::new(io::ErrorKind::InvalidInput, "not on curve")) - } - } + Ok(y) => match Self::get_for_y(y, x_sign, params) { + Some(p) => Ok(p), + None => Err(io::Error::new(io::ErrorKind::InvalidInput, "not on curve")), }, - Err(_) => { - Err(io::Error::new(io::ErrorKind::InvalidInput, "y is not in field")) - } + Err(_) => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "y is not in field", + )), } } - pub fn get_for_y(y: E::Fr, sign: bool, params: &E::Params) -> Option - { + pub fn get_for_y(y: E::Fr, sign: bool, params: &E::Params) -> Option { // Given a y on the curve, x^2 = (y^2 - 1) / (dy^2 + 1) // This is defined for all valid y-coordinates, // as dy^2 + 1 = 0 has no solution in Fr. @@ -162,29 +136,25 @@ impl Point { y: y, t: t, z: E::Fr::one(), - _marker: PhantomData + _marker: PhantomData, }) - }, - None => None + } + None => None, } - }, - None => None + } + None => None, } } /// This guarantees the point is in the prime order subgroup #[must_use] - pub fn mul_by_cofactor(&self, params: &E::Params) -> Point - { - let tmp = self.double(params) - .double(params) - .double(params); + pub fn mul_by_cofactor(&self, params: &E::Params) -> Point { + let tmp = self.double(params).double(params).double(params); convert_subgroup(&tmp) } - pub fn rand(rng: &mut R, params: &E::Params) -> Self - { + pub fn rand(rng: &mut R, params: &E::Params) -> Self { loop { let y = E::Fr::random(rng); let sign = rng.next_u32() % 2 != 0; @@ -197,11 +167,7 @@ impl Point { } impl Point { - pub fn write( - &self, - writer: W - ) -> io::Result<()> - { + pub fn write(&self, writer: W) -> io::Result<()> { let (x, y) = self.into_xy(); assert_eq!(E::Fr::NUM_BITS, 255); @@ -216,16 +182,12 @@ impl Point { } /// Convert from a Montgomery point - pub fn from_montgomery( - m: &montgomery::Point, - params: &E::Params - ) -> Self - { + pub fn from_montgomery(m: &montgomery::Point, params: &E::Params) -> Self { match m.into_xy() { None => { // Map the point at infinity to the neutral element. Point::zero() - }, + } Some((x, y)) => { // The map from a Montgomery curve is defined as: // (x, y) -> (u, v) where @@ -258,7 +220,7 @@ impl Point { y: neg1, t: E::Fr::zero(), z: E::Fr::one(), - _marker: PhantomData + _marker: PhantomData, } } else { // Otherwise, as stated above, the mapping is still @@ -317,7 +279,7 @@ impl Point { y: v, t: t, z: z, - _marker: PhantomData + _marker: PhantomData, } } } @@ -340,12 +302,11 @@ impl Point { y: E::Fr::one(), t: E::Fr::zero(), z: E::Fr::one(), - _marker: PhantomData + _marker: PhantomData, } } - pub fn into_xy(&self) -> (E::Fr, E::Fr) - { + pub fn into_xy(&self) -> (E::Fr, E::Fr) { let zinv = self.z.inverse().unwrap(); let mut x = self.x; @@ -432,13 +393,12 @@ impl Point { y: y3, t: t3, z: z3, - _marker: PhantomData + _marker: PhantomData, } } #[must_use] - pub fn add(&self, other: &Self, params: &E::Params) -> Self - { + pub fn add(&self, other: &Self, params: &E::Params) -> Self { // See "Twisted Edwards Curves Revisited" // Huseyin Hisil, Kenneth Koon-Ho Wong, Gary Carter, and Ed Dawson // 3.1 Unified Addition in E^e @@ -505,17 +465,12 @@ impl Point { y: y3, t: t3, z: z3, - _marker: PhantomData + _marker: PhantomData, } } #[must_use] - pub fn mul::Repr>>( - &self, - scalar: S, - params: &E::Params - ) -> Self - { + pub fn mul::Repr>>(&self, scalar: S, params: &E::Params) -> Self { // Standard double-and-add scalar multiplication let mut res = Self::zero(); diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index baa16ef..768bd83 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -9,7 +9,12 @@ use rand_core::RngCore; use super::ToUniform; // s = 6554484396890773809930967563523245729705921265872317281365359162392183254199 -const MODULUS: FsRepr = FsRepr([0xd0970e5ed6f72cb7, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9]); +const MODULUS: FsRepr = FsRepr([ + 0xd0970e5ed6f72cb7, + 0xa6682093ccc81082, + 0x6673b0101343b00, + 0xe7db4ea6533afa9, +]); // The number of bits needed to represent the modulus. const MODULUS_BITS: u32 = 252; @@ -19,32 +24,56 @@ const MODULUS_BITS: u32 = 252; const REPR_SHAVE_BITS: u32 = 4; // R = 2**256 % s -const R: FsRepr = FsRepr([0x25f80bb3b99607d9, 0xf315d62f66b6e750, 0x932514eeeb8814f4, 0x9a6fc6f479155c6]); +const R: FsRepr = FsRepr([ + 0x25f80bb3b99607d9, + 0xf315d62f66b6e750, + 0x932514eeeb8814f4, + 0x9a6fc6f479155c6, +]); // R2 = R^2 % s -const R2: FsRepr = FsRepr([0x67719aa495e57731, 0x51b0cef09ce3fc26, 0x69dab7fac026e9a5, 0x4f6547b8d127688]); +const R2: FsRepr = FsRepr([ + 0x67719aa495e57731, + 0x51b0cef09ce3fc26, + 0x69dab7fac026e9a5, + 0x4f6547b8d127688, +]); // INV = -(s^{-1} mod 2^64) mod s const INV: u64 = 0x1ba3a358ef788ef9; // GENERATOR = 6 (multiplicative generator of r-1 order, that is also quadratic nonresidue) -const GENERATOR: FsRepr = FsRepr([0x720b1b19d49ea8f1, 0xbf4aa36101f13a58, 0x5fa8cc968193ccbb, 0xe70cbdc7dccf3ac]); +const GENERATOR: FsRepr = FsRepr([ + 0x720b1b19d49ea8f1, + 0xbf4aa36101f13a58, + 0x5fa8cc968193ccbb, + 0xe70cbdc7dccf3ac, +]); // 2^S * t = MODULUS - 1 with t odd const S: u32 = 1; // 2^S root of unity computed by GENERATOR^t -const ROOT_OF_UNITY: FsRepr = FsRepr([0xaa9f02ab1d6124de, 0xb3524a6466112932, 0x7342261215ac260b, 0x4d6b87b1da259e2]); +const ROOT_OF_UNITY: FsRepr = FsRepr([ + 0xaa9f02ab1d6124de, + 0xb3524a6466112932, + 0x7342261215ac260b, + 0x4d6b87b1da259e2, +]); // -((2**256) mod s) mod s -const NEGATIVE_ONE: Fs = Fs(FsRepr([0xaa9f02ab1d6124de, 0xb3524a6466112932, 0x7342261215ac260b, 0x4d6b87b1da259e2])); +const NEGATIVE_ONE: Fs = Fs(FsRepr([ + 0xaa9f02ab1d6124de, + 0xb3524a6466112932, + 0x7342261215ac260b, + 0x4d6b87b1da259e2, +])); /// This is the underlying representation of an element of `Fs`. #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] pub struct FsRepr(pub [u64; 4]); -impl ::std::fmt::Display for FsRepr -{ +impl ::std::fmt::Display for FsRepr { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { try!(write!(f, "0x")); for i in self.0.iter().rev() { @@ -83,9 +112,9 @@ impl Ord for FsRepr { fn cmp(&self, other: &FsRepr) -> ::std::cmp::Ordering { for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { if a < b { - return ::std::cmp::Ordering::Less + return ::std::cmp::Ordering::Less; } else if a > b { - return ::std::cmp::Ordering::Greater + return ::std::cmp::Ordering::Greater; } } @@ -227,8 +256,7 @@ impl PrimeFieldRepr for FsRepr { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Fs(FsRepr); -impl ::std::fmt::Display for Fs -{ +impl ::std::fmt::Display for Fs { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, "Fs({})", self.into_repr()) } @@ -256,9 +284,16 @@ impl PrimeField for Fs { fn into_repr(&self) -> FsRepr { let mut r = *self; - r.mont_reduce((self.0).0[0], (self.0).0[1], - (self.0).0[2], (self.0).0[3], - 0, 0, 0, 0); + r.mont_reduce( + (self.0).0[0], + (self.0).0[1], + (self.0).0[2], + (self.0).0[3], + 0, + 0, + 0, + 0, + ); r.0 } @@ -296,7 +331,7 @@ impl Field for Fs { tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; if tmp.is_valid() { - return tmp + return tmp; } } } @@ -414,8 +449,7 @@ impl Field for Fs { } #[inline] - fn mul_assign(&mut self, other: &Fs) - { + fn mul_assign(&mut self, other: &Fs) { let mut carry = 0; let r0 = mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); let r1 = mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); @@ -444,8 +478,7 @@ impl Field for Fs { } #[inline] - fn square(&mut self) - { + fn square(&mut self) { let mut carry = 0; let r1 = mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); let r2 = mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); @@ -507,9 +540,8 @@ impl Fs { mut r4: u64, mut r5: u64, mut r6: u64, - mut r7: u64 - ) - { + mut r7: u64, + ) { // The Montgomery reduction here is based on Algorithm 14.32 in // Handbook of Applied Cryptography // . @@ -579,13 +611,21 @@ impl ToUniform for Fs { } impl SqrtField for Fs { - fn legendre(&self) -> LegendreSymbol { // s = self^((s - 1) // 2) - let s = self.pow([0x684b872f6b7b965b, 0x53341049e6640841, 0x83339d80809a1d80, 0x73eda753299d7d4]); - if s == Self::zero() { Zero } - else if s == Self::one() { QuadraticResidue } - else { QuadraticNonResidue } + let s = self.pow([ + 0x684b872f6b7b965b, + 0x53341049e6640841, + 0x83339d80809a1d80, + 0x73eda753299d7d4, + ]); + if s == Self::zero() { + Zero + } else if s == Self::one() { + QuadraticResidue + } else { + QuadraticNonResidue + } } fn sqrt(&self) -> Option { @@ -593,24 +633,25 @@ impl SqrtField for Fs { // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) // a1 = self^((s - 3) // 4) - let mut a1 = self.pow([0xb425c397b5bdcb2d, 0x299a0824f3320420, 0x4199cec0404d0ec0, 0x39f6d3a994cebea]); + let mut a1 = self.pow([ + 0xb425c397b5bdcb2d, + 0x299a0824f3320420, + 0x4199cec0404d0ec0, + 0x39f6d3a994cebea, + ]); let mut a0 = a1; a0.square(); a0.mul_assign(self); - if a0 == NEGATIVE_ONE - { + if a0 == NEGATIVE_ONE { None - } - else - { + } else { a1.mul_assign(self); Some(a1) } } } - #[test] fn test_neg_one() { let mut o = Fs::one(); @@ -636,12 +677,30 @@ fn test_fs_repr_ordering() { assert!(b > a); } - assert_equality(FsRepr([9999, 9999, 9999, 9999]), FsRepr([9999, 9999, 9999, 9999])); - assert_equality(FsRepr([9999, 9998, 9999, 9999]), FsRepr([9999, 9998, 9999, 9999])); - assert_equality(FsRepr([9999, 9999, 9999, 9997]), FsRepr([9999, 9999, 9999, 9997])); - assert_lt(FsRepr([9999, 9997, 9999, 9998]), FsRepr([9999, 9997, 9999, 9999])); - assert_lt(FsRepr([9999, 9997, 9998, 9999]), FsRepr([9999, 9997, 9999, 9999])); - assert_lt(FsRepr([9, 9999, 9999, 9997]), FsRepr([9999, 9999, 9999, 9997])); + assert_equality( + FsRepr([9999, 9999, 9999, 9999]), + FsRepr([9999, 9999, 9999, 9999]), + ); + assert_equality( + FsRepr([9999, 9998, 9999, 9999]), + FsRepr([9999, 9998, 9999, 9999]), + ); + assert_equality( + FsRepr([9999, 9999, 9999, 9997]), + FsRepr([9999, 9999, 9999, 9997]), + ); + assert_lt( + FsRepr([9999, 9997, 9999, 9998]), + FsRepr([9999, 9997, 9999, 9999]), + ); + assert_lt( + FsRepr([9999, 9997, 9998, 9999]), + FsRepr([9999, 9997, 9999, 9999]), + ); + assert_lt( + FsRepr([9, 9999, 9999, 9997]), + FsRepr([9999, 9999, 9999, 9997]), + ); } #[test] @@ -670,13 +729,34 @@ fn test_fs_repr_is_zero() { #[test] fn test_fs_repr_div2() { - let mut a = FsRepr([0xbd2920b19c972321, 0x174ed0466a3be37e, 0xd468d5e3b551f0b5, 0xcb67c072733beefc]); + let mut a = FsRepr([ + 0xbd2920b19c972321, + 0x174ed0466a3be37e, + 0xd468d5e3b551f0b5, + 0xcb67c072733beefc, + ]); a.div2(); - assert_eq!(a, FsRepr([0x5e949058ce4b9190, 0x8ba76823351df1bf, 0x6a346af1daa8f85a, 0x65b3e039399df77e])); + assert_eq!( + a, + FsRepr([ + 0x5e949058ce4b9190, + 0x8ba76823351df1bf, + 0x6a346af1daa8f85a, + 0x65b3e039399df77e + ]) + ); for _ in 0..10 { a.div2(); } - assert_eq!(a, FsRepr([0x6fd7a524163392e4, 0x16a2e9da08cd477c, 0xdf9a8d1abc76aa3e, 0x196cf80e4e677d])); + assert_eq!( + a, + FsRepr([ + 0x6fd7a524163392e4, + 0x16a2e9da08cd477c, + 0xdf9a8d1abc76aa3e, + 0x196cf80e4e677d + ]) + ); for _ in 0..200 { a.div2(); } @@ -695,32 +775,46 @@ fn test_fs_repr_div2() { #[test] fn test_fs_repr_shr() { - let mut a = FsRepr([0xb33fbaec482a283f, 0x997de0d3a88cb3df, 0x9af62d2a9a0e5525, 0x36003ab08de70da1]); + let mut a = FsRepr([ + 0xb33fbaec482a283f, + 0x997de0d3a88cb3df, + 0x9af62d2a9a0e5525, + 0x36003ab08de70da1, + ]); a.shr(0); assert_eq!( a, - FsRepr([0xb33fbaec482a283f, 0x997de0d3a88cb3df, 0x9af62d2a9a0e5525, 0x36003ab08de70da1]) + FsRepr([ + 0xb33fbaec482a283f, + 0x997de0d3a88cb3df, + 0x9af62d2a9a0e5525, + 0x36003ab08de70da1 + ]) ); a.shr(1); assert_eq!( a, - FsRepr([0xd99fdd762415141f, 0xccbef069d44659ef, 0xcd7b16954d072a92, 0x1b001d5846f386d0]) + FsRepr([ + 0xd99fdd762415141f, + 0xccbef069d44659ef, + 0xcd7b16954d072a92, + 0x1b001d5846f386d0 + ]) ); a.shr(50); assert_eq!( a, - FsRepr([0xbc1a7511967bf667, 0xc5a55341caa4b32f, 0x75611bce1b4335e, 0x6c0]) + FsRepr([ + 0xbc1a7511967bf667, + 0xc5a55341caa4b32f, + 0x75611bce1b4335e, + 0x6c0 + ]) ); a.shr(130); - assert_eq!( - a, - FsRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0]) - ); + assert_eq!(a, FsRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0])); a.shr(64); - assert_eq!( - a, - FsRepr([0x1b0, 0x0, 0x0, 0x0]) - ); + assert_eq!(a, FsRepr([0x1b0, 0x0, 0x0, 0x0])); } #[test] @@ -765,9 +859,26 @@ fn test_fs_repr_sub_noborrow() { 0xe5, ]); - let mut t = FsRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495]); - t.sub_noborrow(&FsRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf])); - assert!(t == FsRepr([0xb813415048991c1f, 0x10ad07ae88725d92, 0x5a7b851271759961, 0x36850eedd30c39c5])); + let mut t = FsRepr([ + 0x8e62a7e85264e2c3, + 0xb23d34c1941d3ca, + 0x5976930b7502dd15, + 0x600f3fb517bf5495, + ]); + t.sub_noborrow(&FsRepr([ + 0xd64f669809cbc6a4, + 0xfa76cb9d90cf7637, + 0xfefb0df9038d43b3, + 0x298a30c744b31acf, + ])); + assert!( + t == FsRepr([ + 0xb813415048991c1f, + 0x10ad07ae88725d92, + 0x5a7b851271759961, + 0x36850eedd30c39c5 + ]) + ); for _ in 0..1000 { let mut a = Fs::random(&mut rng).into_repr(); @@ -801,9 +912,19 @@ fn test_fs_legendre() { assert_eq!(QuadraticResidue, Fs::one().legendre()); assert_eq!(Zero, Fs::zero().legendre()); - let e = FsRepr([0x8385eec23df1f88e, 0x9a01fb412b2dba16, 0x4c928edcdd6c22f, 0x9f2df7ef69ecef9]); + let e = FsRepr([ + 0x8385eec23df1f88e, + 0x9a01fb412b2dba16, + 0x4c928edcdd6c22f, + 0x9f2df7ef69ecef9, + ]); assert_eq!(QuadraticResidue, Fs::from_repr(e).unwrap().legendre()); - let e = FsRepr([0xe8ed9f299da78568, 0x35efdebc88b2209, 0xc82125cb1f916dbe, 0x6813d2b38c39bd0]); + let e = FsRepr([ + 0xe8ed9f299da78568, + 0x35efdebc88b2209, + 0xc82125cb1f916dbe, + 0x6813d2b38c39bd0, + ]); assert_eq!(QuadraticNonResidue, Fs::from_repr(e).unwrap().legendre()); } @@ -814,9 +935,27 @@ fn test_fr_repr_add_nocarry() { 0xe5, ]); - let mut t = FsRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf]); - t.add_nocarry(&FsRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495])); - assert_eq!(t, FsRepr([0x64b20e805c30a967, 0x59a9ee9aa114a02, 0x5871a104789020c9, 0x8999707c5c726f65])); + let mut t = FsRepr([ + 0xd64f669809cbc6a4, + 0xfa76cb9d90cf7637, + 0xfefb0df9038d43b3, + 0x298a30c744b31acf, + ]); + t.add_nocarry(&FsRepr([ + 0x8e62a7e85264e2c3, + 0xb23d34c1941d3ca, + 0x5976930b7502dd15, + 0x600f3fb517bf5495, + ])); + assert_eq!( + t, + FsRepr([ + 0x64b20e805c30a967, + 0x59a9ee9aa114a02, + 0x5871a104789020c9, + 0x8999707c5c726f65 + ]) + ); // Test for the associativity of addition. for _ in 0..1000 { @@ -868,8 +1007,20 @@ fn test_fs_is_valid() { a.0.sub_noborrow(&FsRepr::from(1)); assert!(a.is_valid()); assert!(Fs(FsRepr::from(0)).is_valid()); - assert!(Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])).is_valid()); - assert!(!Fs(FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])).is_valid()); + assert!(Fs(FsRepr([ + 0xd0970e5ed6f72cb6, + 0xa6682093ccc81082, + 0x6673b0101343b00, + 0xe7db4ea6533afa9 + ])) + .is_valid()); + assert!(!Fs(FsRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])) + .is_valid()); let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -886,25 +1037,80 @@ fn test_fs_is_valid() { fn test_fs_add_assign() { { // Random number - let mut tmp = Fs::from_str("4577408157467272683998459759522778614363623736323078995109579213719612604198").unwrap(); + let mut tmp = Fs::from_str( + "4577408157467272683998459759522778614363623736323078995109579213719612604198", + ) + .unwrap(); assert!(tmp.is_valid()); // Test that adding zero has no effect. tmp.add_assign(&Fs(FsRepr::from(0))); - assert_eq!(tmp, Fs(FsRepr([0x8e6bfff4722d6e67, 0x5643da5c892044f9, 0x9465f4b281921a69, 0x25f752d3edd7162]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0x8e6bfff4722d6e67, + 0x5643da5c892044f9, + 0x9465f4b281921a69, + 0x25f752d3edd7162 + ])) + ); // Add one and test for the result. tmp.add_assign(&Fs(FsRepr::from(1))); - assert_eq!(tmp, Fs(FsRepr([0x8e6bfff4722d6e68, 0x5643da5c892044f9, 0x9465f4b281921a69, 0x25f752d3edd7162]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0x8e6bfff4722d6e68, + 0x5643da5c892044f9, + 0x9465f4b281921a69, + 0x25f752d3edd7162 + ])) + ); // Add another random number that exercises the reduction. - tmp.add_assign(&Fs(FsRepr([0xb634d07bc42d4a70, 0xf724f0c008411f5f, 0x456d4053d865af34, 0x24ce814e8c63027]))); - assert_eq!(tmp, Fs(FsRepr([0x44a0d070365ab8d8, 0x4d68cb1c91616459, 0xd9d3350659f7c99e, 0x4ac5d4227a3a189]))); + tmp.add_assign(&Fs(FsRepr([ + 0xb634d07bc42d4a70, + 0xf724f0c008411f5f, + 0x456d4053d865af34, + 0x24ce814e8c63027, + ]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0x44a0d070365ab8d8, + 0x4d68cb1c91616459, + 0xd9d3350659f7c99e, + 0x4ac5d4227a3a189 + ])) + ); // Add one to (s - 1) and test for the result. - tmp = Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])); + tmp = Fs(FsRepr([ + 0xd0970e5ed6f72cb6, + 0xa6682093ccc81082, + 0x6673b0101343b00, + 0xe7db4ea6533afa9, + ])); tmp.add_assign(&Fs(FsRepr::from(1))); assert!(tmp.0.is_zero()); // Add a random number to another one such that the result is s - 1 - tmp = Fs(FsRepr([0xa11fda5950ce3636, 0x922e0dbccfe0ca0e, 0xacebb6e215b82d4a, 0x97ffb8cdc3aee93])); - tmp.add_assign(&Fs(FsRepr([0x2f7734058628f680, 0x143a12d6fce74674, 0x597b841eeb7c0db6, 0x4fdb95d88f8c115]))); - assert_eq!(tmp, Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9]))); + tmp = Fs(FsRepr([ + 0xa11fda5950ce3636, + 0x922e0dbccfe0ca0e, + 0xacebb6e215b82d4a, + 0x97ffb8cdc3aee93, + ])); + tmp.add_assign(&Fs(FsRepr([ + 0x2f7734058628f680, + 0x143a12d6fce74674, + 0x597b841eeb7c0db6, + 0x4fdb95d88f8c115, + ]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0xd0970e5ed6f72cb6, + 0xa6682093ccc81082, + 0x6673b0101343b00, + 0xe7db4ea6533afa9 + ])) + ); // Add one to the result and test for it. tmp.add_assign(&Fs(FsRepr::from(1))); assert!(tmp.0.is_zero()); @@ -941,23 +1147,72 @@ fn test_fs_add_assign() { fn test_fs_sub_assign() { { // Test arbitrary subtraction that tests reduction. - let mut tmp = Fs(FsRepr([0xb384d9f6877afd99, 0x4442513958e1a1c1, 0x352c4b8a95eccc3f, 0x2db62dee4b0f2])); - tmp.sub_assign(&Fs(FsRepr([0xec5bd2d13ed6b05a, 0x2adc0ab3a39b5fa, 0x82d3360a493e637e, 0x53ccff4a64d6679]))); - assert_eq!(tmp, Fs(FsRepr([0x97c015841f9b79f6, 0xe7fcb121eb6ffc49, 0xb8c050814de2a3c1, 0x943c0589dcafa21]))); + let mut tmp = Fs(FsRepr([ + 0xb384d9f6877afd99, + 0x4442513958e1a1c1, + 0x352c4b8a95eccc3f, + 0x2db62dee4b0f2, + ])); + tmp.sub_assign(&Fs(FsRepr([ + 0xec5bd2d13ed6b05a, + 0x2adc0ab3a39b5fa, + 0x82d3360a493e637e, + 0x53ccff4a64d6679, + ]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0x97c015841f9b79f6, + 0xe7fcb121eb6ffc49, + 0xb8c050814de2a3c1, + 0x943c0589dcafa21 + ])) + ); // Test the opposite subtraction which doesn't test reduction. - tmp = Fs(FsRepr([0xec5bd2d13ed6b05a, 0x2adc0ab3a39b5fa, 0x82d3360a493e637e, 0x53ccff4a64d6679])); - tmp.sub_assign(&Fs(FsRepr([0xb384d9f6877afd99, 0x4442513958e1a1c1, 0x352c4b8a95eccc3f, 0x2db62dee4b0f2]))); - assert_eq!(tmp, Fs(FsRepr([0x38d6f8dab75bb2c1, 0xbe6b6f71e1581439, 0x4da6ea7fb351973e, 0x539f491c768b587]))); + tmp = Fs(FsRepr([ + 0xec5bd2d13ed6b05a, + 0x2adc0ab3a39b5fa, + 0x82d3360a493e637e, + 0x53ccff4a64d6679, + ])); + tmp.sub_assign(&Fs(FsRepr([ + 0xb384d9f6877afd99, + 0x4442513958e1a1c1, + 0x352c4b8a95eccc3f, + 0x2db62dee4b0f2, + ]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0x38d6f8dab75bb2c1, + 0xbe6b6f71e1581439, + 0x4da6ea7fb351973e, + 0x539f491c768b587 + ])) + ); // Test for sensible results with zero tmp = Fs(FsRepr::from(0)); tmp.sub_assign(&Fs(FsRepr::from(0))); assert!(tmp.is_zero()); - tmp = Fs(FsRepr([0x361e16aef5cce835, 0x55bbde2536e274c1, 0x4dc77a63fd15ee75, 0x1e14bb37c14f230])); + tmp = Fs(FsRepr([ + 0x361e16aef5cce835, + 0x55bbde2536e274c1, + 0x4dc77a63fd15ee75, + 0x1e14bb37c14f230, + ])); tmp.sub_assign(&Fs(FsRepr::from(0))); - assert_eq!(tmp, Fs(FsRepr([0x361e16aef5cce835, 0x55bbde2536e274c1, 0x4dc77a63fd15ee75, 0x1e14bb37c14f230]))); + assert_eq!( + tmp, + Fs(FsRepr([ + 0x361e16aef5cce835, + 0x55bbde2536e274c1, + 0x4dc77a63fd15ee75, + 0x1e14bb37c14f230 + ])) + ); } let mut rng = XorShiftRng::from_seed([ @@ -983,9 +1238,26 @@ fn test_fs_sub_assign() { #[test] fn test_fs_mul_assign() { - let mut tmp = Fs(FsRepr([0xb433b01287f71744, 0x4eafb86728c4d108, 0xfdd52c14b9dfbe65, 0x2ff1f3434821118])); - tmp.mul_assign(&Fs(FsRepr([0xdae00fc63c9fa90f, 0x5a5ed89b96ce21ce, 0x913cd26101bd6f58, 0x3f0822831697fe9]))); - assert!(tmp == Fs(FsRepr([0xb68ecb61d54d2992, 0x5ff95874defce6a6, 0x3590eb053894657d, 0x53823a118515933]))); + let mut tmp = Fs(FsRepr([ + 0xb433b01287f71744, + 0x4eafb86728c4d108, + 0xfdd52c14b9dfbe65, + 0x2ff1f3434821118, + ])); + tmp.mul_assign(&Fs(FsRepr([ + 0xdae00fc63c9fa90f, + 0x5a5ed89b96ce21ce, + 0x913cd26101bd6f58, + 0x3f0822831697fe9, + ]))); + assert!( + tmp == Fs(FsRepr([ + 0xb68ecb61d54d2992, + 0x5ff95874defce6a6, + 0x3590eb053894657d, + 0x53823a118515933 + ])) + ); let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -1035,10 +1307,24 @@ fn test_fs_mul_assign() { #[test] fn test_fr_squaring() { - let mut a = Fs(FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xe7db4ea6533afa8])); + let mut a = Fs(FsRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xe7db4ea6533afa8, + ])); assert!(a.is_valid()); a.square(); - assert_eq!(a, Fs::from_repr(FsRepr([0x12c7f55cbc52fbaa, 0xdedc98a0b5e6ce9e, 0xad2892726a5396a, 0x9fe82af8fee77b3])).unwrap()); + assert_eq!( + a, + Fs::from_repr(FsRepr([ + 0x12c7f55cbc52fbaa, + 0xdedc98a0b5e6ce9e, + 0xad2892726a5396a, + 0x9fe82af8fee77b3 + ])) + .unwrap() + ); let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, @@ -1185,17 +1471,38 @@ fn test_fs_sqrt() { #[test] fn test_fs_from_into_repr() { // r + 1 should not be in the field - assert!(Fs::from_repr(FsRepr([0xd0970e5ed6f72cb8, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])).is_err()); + assert!(Fs::from_repr(FsRepr([ + 0xd0970e5ed6f72cb8, + 0xa6682093ccc81082, + 0x6673b0101343b00, + 0xe7db4ea6533afa9 + ])) + .is_err()); // r should not be in the field assert!(Fs::from_repr(Fs::char()).is_err()); // Multiply some arbitrary representations to see if the result is as expected. - let a = FsRepr([0x5f2d0c05d0337b71, 0xa1df2b0f8a20479, 0xad73785e71bb863, 0x504a00480c9acec]); + let a = FsRepr([ + 0x5f2d0c05d0337b71, + 0xa1df2b0f8a20479, + 0xad73785e71bb863, + 0x504a00480c9acec, + ]); let mut a_fs = Fs::from_repr(a).unwrap(); - let b = FsRepr([0x66356ff51e477562, 0x60a92ab55cf7603, 0x8e4273c7364dd192, 0x36df8844a344dc5]); + let b = FsRepr([ + 0x66356ff51e477562, + 0x60a92ab55cf7603, + 0x8e4273c7364dd192, + 0x36df8844a344dc5, + ]); let b_fs = Fs::from_repr(b).unwrap(); - let c = FsRepr([0x7eef61708f4f2868, 0x747a7e6cf52946fb, 0x83dd75d7c9120017, 0x762f5177f0f3df7]); + let c = FsRepr([ + 0x7eef61708f4f2868, + 0x747a7e6cf52946fb, + 0x83dd75d7c9120017, + 0x762f5177f0f3df7, + ]); a_fs.mul_assign(&b_fs); assert_eq!(a_fs.into_repr(), c); @@ -1222,15 +1529,39 @@ fn test_fs_from_into_repr() { #[test] fn test_fs_repr_display() { assert_eq!( - format!("{}", FsRepr([0xa296db59787359df, 0x8d3e33077430d318, 0xd1abf5c606102eb7, 0xcbc33ee28108f0])), + format!( + "{}", + FsRepr([ + 0xa296db59787359df, + 0x8d3e33077430d318, + 0xd1abf5c606102eb7, + 0xcbc33ee28108f0 + ]) + ), "0x00cbc33ee28108f0d1abf5c606102eb78d3e33077430d318a296db59787359df".to_string() ); assert_eq!( - format!("{}", FsRepr([0x14cb03535054a620, 0x312aa2bf2d1dff52, 0x970fe98746ab9361, 0xc1e18acf82711e6])), + format!( + "{}", + FsRepr([ + 0x14cb03535054a620, + 0x312aa2bf2d1dff52, + 0x970fe98746ab9361, + 0xc1e18acf82711e6 + ]) + ), "0x0c1e18acf82711e6970fe98746ab9361312aa2bf2d1dff5214cb03535054a620".to_string() ); assert_eq!( - format!("{}", FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])), + format!( + "{}", + FsRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ]) + ), "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string() ); assert_eq!( @@ -1242,11 +1573,29 @@ fn test_fs_repr_display() { #[test] fn test_fs_display() { assert_eq!( - format!("{}", Fs::from_repr(FsRepr([0x5528efb9998a01a3, 0x5bd2add5cb357089, 0xc061fa6adb491f98, 0x70db9d143db03d9])).unwrap()), + format!( + "{}", + Fs::from_repr(FsRepr([ + 0x5528efb9998a01a3, + 0x5bd2add5cb357089, + 0xc061fa6adb491f98, + 0x70db9d143db03d9 + ])) + .unwrap() + ), "Fs(0x070db9d143db03d9c061fa6adb491f985bd2add5cb3570895528efb9998a01a3)".to_string() ); assert_eq!( - format!("{}", Fs::from_repr(FsRepr([0xd674745e2717999e, 0xbeb1f52d3e96f338, 0x9c7ae147549482b9, 0x999706024530d22])).unwrap()), + format!( + "{}", + Fs::from_repr(FsRepr([ + 0xd674745e2717999e, + 0xbeb1f52d3e96f338, + 0x9c7ae147549482b9, + 0x999706024530d22 + ])) + .unwrap() + ), "Fs(0x0999706024530d229c7ae147549482b9beb1f52d3e96f338d674745e2717999e)".to_string() ); } @@ -1260,14 +1609,19 @@ fn test_fs_num_bits() { #[test] fn test_fs_root_of_unity() { assert_eq!(Fs::S, 1); - assert_eq!(Fs::multiplicative_generator(), Fs::from_repr(FsRepr::from(6)).unwrap()); assert_eq!( - Fs::multiplicative_generator().pow([0x684b872f6b7b965b, 0x53341049e6640841, 0x83339d80809a1d80, 0x73eda753299d7d4]), + Fs::multiplicative_generator(), + Fs::from_repr(FsRepr::from(6)).unwrap() + ); + assert_eq!( + Fs::multiplicative_generator().pow([ + 0x684b872f6b7b965b, + 0x53341049e6640841, + 0x83339d80809a1d80, + 0x73eda753299d7d4 + ]), Fs::root_of_unity() ); - assert_eq!( - Fs::root_of_unity().pow([1 << Fs::S]), - Fs::one() - ); + assert_eq!(Fs::root_of_unity().pow([1 << Fs::S]), Fs::one()); assert!(Fs::multiplicative_generator().sqrt().is_none()); } diff --git a/zcash_primitives/src/jubjub/mod.rs b/zcash_primitives/src/jubjub/mod.rs index 71e1875..7ab0d0e 100644 --- a/zcash_primitives/src/jubjub/mod.rs +++ b/zcash_primitives/src/jubjub/mod.rs @@ -24,10 +24,7 @@ use group_hash::group_hash; use constants; -use pairing::bls12_381::{ - Bls12, - Fr -}; +use pairing::bls12_381::{Bls12, Fr}; /// This is an implementation of the twisted Edwards Jubjub curve. pub mod edwards; @@ -44,11 +41,11 @@ pub mod tests; /// Point of unknown order. #[derive(Debug)] -pub enum Unknown { } +pub enum Unknown {} /// Point of prime order. #[derive(Debug)] -pub enum PrimeOrder { } +pub enum PrimeOrder {} /// Fixed generators of the Jubjub curve of unknown /// exponent. @@ -80,7 +77,7 @@ pub enum FixedGenerators { /// base at spend time. SpendingKeyGenerator = 5, - Max = 6 + Max = 6, } pub trait ToUniform { @@ -151,10 +148,18 @@ pub struct JubjubBls12 { } impl JubjubParams for JubjubBls12 { - fn edwards_d(&self) -> &Fr { &self.edwards_d } - fn montgomery_a(&self) -> &Fr { &self.montgomery_a } - fn montgomery_2a(&self) -> &Fr { &self.montgomery_2a } - fn scale(&self) -> &Fr { &self.scale } + fn edwards_d(&self) -> &Fr { + &self.edwards_d + } + fn montgomery_a(&self) -> &Fr { + &self.montgomery_a + } + fn montgomery_2a(&self) -> &Fr { + &self.montgomery_2a + } + fn scale(&self) -> &Fr { + &self.scale + } fn pedersen_hash_generators(&self) -> &[edwards::Point] { &self.pedersen_hash_generators } @@ -170,12 +175,10 @@ impl JubjubParams for JubjubBls12 { fn pedersen_circuit_generators(&self) -> &[Vec>] { &self.pedersen_circuit_generators } - fn generator(&self, base: FixedGenerators) -> &edwards::Point - { + fn generator(&self, base: FixedGenerators) -> &edwards::Point { &self.fixed_base_generators[base as usize] } - fn circuit_generators(&self, base: FixedGenerators) -> &[Vec<(Fr, Fr)>] - { + fn circuit_generators(&self, base: FixedGenerators) -> &[Vec<(Fr, Fr)>] { &self.fixed_base_circuit_generators[base as usize][..] } fn pedersen_hash_exp_window_size() -> u32 { @@ -191,13 +194,19 @@ impl JubjubBls12 { let mut tmp_params = JubjubBls12 { // d = -(10240/10241) - edwards_d: Fr::from_str("19257038036680949359750312669786877991949435402254120286184196891950884077233").unwrap(), + edwards_d: Fr::from_str( + "19257038036680949359750312669786877991949435402254120286184196891950884077233", + ) + .unwrap(), // A = 40962 montgomery_a: montgomery_a, // 2A = 2.A montgomery_2a: montgomery_2a, // scaling factor = sqrt(4 / (a - d)) - scale: Fr::from_str("17814886934372412843466061268024708274627479829237077604635722030778476050649").unwrap(), + scale: Fr::from_str( + "17814886934372412843466061268024708274627479829237077604635722030778476050649", + ) + .unwrap(), // We'll initialize these below pedersen_hash_generators: vec![], @@ -210,19 +219,14 @@ impl JubjubBls12 { fn find_group_hash( m: &[u8], personalization: &[u8; 8], - params: &E::Params - ) -> edwards::Point - { + params: &E::Params, + ) -> edwards::Point { let mut tag = m.to_vec(); let i = tag.len(); tag.push(0u8); loop { - let gh = group_hash( - &tag, - personalization, - params - ); + let gh = group_hash(&tag, personalization, params); // We don't want to overflow and start reusing generators assert!(tag[i] != u8::max_value()); @@ -239,18 +243,18 @@ impl JubjubBls12 { let mut pedersen_hash_generators = vec![]; for m in 0..5 { - use byteorder::{WriteBytesExt, LittleEndian}; + use byteorder::{LittleEndian, WriteBytesExt}; let mut segment_number = [0u8; 4]; - (&mut segment_number[0..4]).write_u32::(m).unwrap(); + (&mut segment_number[0..4]) + .write_u32::(m) + .unwrap(); - pedersen_hash_generators.push( - find_group_hash( - &segment_number, - constants::PEDERSEN_HASH_GENERATORS_PERSONALIZATION, - &tmp_params - ) - ); + pedersen_hash_generators.push(find_group_hash( + &segment_number, + constants::PEDERSEN_HASH_GENERATORS_PERSONALIZATION, + &tmp_params, + )); } // Check for duplicates, far worse than spec inconsistencies! @@ -259,7 +263,7 @@ impl JubjubBls12 { panic!("Neutral element!"); } - for p2 in pedersen_hash_generators.iter().skip(i+1) { + for p2 in pedersen_hash_generators.iter().skip(i + 1) { if p1 == p2 { panic!("Duplicate generator!"); } @@ -307,25 +311,46 @@ impl JubjubBls12 { // Create the bases for other parts of the protocol { - let mut fixed_base_generators = vec![edwards::Point::zero(); FixedGenerators::Max as usize]; + let mut fixed_base_generators = + vec![edwards::Point::zero(); FixedGenerators::Max as usize]; - fixed_base_generators[FixedGenerators::ProofGenerationKey as usize] = - find_group_hash(&[], constants::PROOF_GENERATION_KEY_BASE_GENERATOR_PERSONALIZATION, &tmp_params); + fixed_base_generators[FixedGenerators::ProofGenerationKey as usize] = find_group_hash( + &[], + constants::PROOF_GENERATION_KEY_BASE_GENERATOR_PERSONALIZATION, + &tmp_params, + ); fixed_base_generators[FixedGenerators::NoteCommitmentRandomness as usize] = - find_group_hash(b"r", constants::PEDERSEN_HASH_GENERATORS_PERSONALIZATION, &tmp_params); + find_group_hash( + b"r", + constants::PEDERSEN_HASH_GENERATORS_PERSONALIZATION, + &tmp_params, + ); - fixed_base_generators[FixedGenerators::NullifierPosition as usize] = - find_group_hash(&[], constants::NULLIFIER_POSITION_IN_TREE_GENERATOR_PERSONALIZATION, &tmp_params); + fixed_base_generators[FixedGenerators::NullifierPosition as usize] = find_group_hash( + &[], + constants::NULLIFIER_POSITION_IN_TREE_GENERATOR_PERSONALIZATION, + &tmp_params, + ); - fixed_base_generators[FixedGenerators::ValueCommitmentValue as usize] = - find_group_hash(b"v", constants::VALUE_COMMITMENT_GENERATOR_PERSONALIZATION, &tmp_params); + fixed_base_generators[FixedGenerators::ValueCommitmentValue as usize] = find_group_hash( + b"v", + constants::VALUE_COMMITMENT_GENERATOR_PERSONALIZATION, + &tmp_params, + ); fixed_base_generators[FixedGenerators::ValueCommitmentRandomness as usize] = - find_group_hash(b"r", constants::VALUE_COMMITMENT_GENERATOR_PERSONALIZATION, &tmp_params); + find_group_hash( + b"r", + constants::VALUE_COMMITMENT_GENERATOR_PERSONALIZATION, + &tmp_params, + ); - fixed_base_generators[FixedGenerators::SpendingKeyGenerator as usize] = - find_group_hash(&[], constants::SPENDING_KEY_GENERATOR_PERSONALIZATION, &tmp_params); + fixed_base_generators[FixedGenerators::SpendingKeyGenerator as usize] = find_group_hash( + &[], + constants::SPENDING_KEY_GENERATOR_PERSONALIZATION, + &tmp_params, + ); // Check for duplicates, far worse than spec inconsistencies! for (i, p1) in fixed_base_generators.iter().enumerate() { @@ -333,7 +358,7 @@ impl JubjubBls12 { panic!("Neutral element!"); } - for p2 in fixed_base_generators.iter().skip(i+1) { + for p2 in fixed_base_generators.iter().skip(i + 1) { if p1 == p2 { panic!("Duplicate generator!"); } @@ -413,10 +438,14 @@ fn test_jubjub_bls12() { let test_repr = hex!("9d12b88b08dcbef8a11ee0712d94cb236ee2f4ca17317075bfafc82ce3139d31"); let p = edwards::Point::::read(&test_repr[..], ¶ms).unwrap(); let q = edwards::Point::::get_for_y( - Fr::from_str("22440861827555040311190986994816762244378363690614952020532787748720529117853").unwrap(), + Fr::from_str( + "22440861827555040311190986994816762244378363690614952020532787748720529117853", + ) + .unwrap(), false, - ¶ms - ).unwrap(); + ¶ms, + ) + .unwrap(); assert!(p == q); @@ -424,10 +453,14 @@ fn test_jubjub_bls12() { let test_repr = hex!("9d12b88b08dcbef8a11ee0712d94cb236ee2f4ca17317075bfafc82ce3139db1"); let p = edwards::Point::::read(&test_repr[..], ¶ms).unwrap(); let q = edwards::Point::::get_for_y( - Fr::from_str("22440861827555040311190986994816762244378363690614952020532787748720529117853").unwrap(), + Fr::from_str( + "22440861827555040311190986994816762244378363690614952020532787748720529117853", + ) + .unwrap(), true, - ¶ms - ).unwrap(); + ¶ms, + ) + .unwrap(); assert!(p == q); } diff --git a/zcash_primitives/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs index 9bd6023..e0bc4bf 100644 --- a/zcash_primitives/src/jubjub/montgomery.rs +++ b/zcash_primitives/src/jubjub/montgomery.rs @@ -1,12 +1,6 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; -use super::{ - JubjubEngine, - JubjubParams, - Unknown, - PrimeOrder, - edwards -}; +use super::{edwards, JubjubEngine, JubjubParams, PrimeOrder, Unknown}; use rand_core::RngCore; @@ -17,29 +11,25 @@ pub struct Point { x: E::Fr, y: E::Fr, infinity: bool, - _marker: PhantomData + _marker: PhantomData, } -fn convert_subgroup(from: &Point) -> Point -{ +fn convert_subgroup(from: &Point) -> Point { Point { x: from.x, y: from.y, infinity: from.infinity, - _marker: PhantomData + _marker: PhantomData, } } -impl From> for Point -{ - fn from(p: Point) -> Point - { +impl From> for Point { + fn from(p: Point) -> Point { convert_subgroup(&p) } } -impl Clone for Point -{ +impl Clone for Point { fn clone(&self) -> Self { convert_subgroup(self) } @@ -50,16 +40,13 @@ impl PartialEq for Point { match (self.infinity, other.infinity) { (true, true) => true, (true, false) | (false, true) => false, - (false, false) => { - self.x == other.x && self.y == other.y - } + (false, false) => self.x == other.x && self.y == other.y, } } } impl Point { - pub fn get_for_x(x: E::Fr, sign: bool, params: &E::Params) -> Option - { + pub fn get_for_x(x: E::Fr, sign: bool, params: &E::Params) -> Option { // Given an x on the curve, y = sqrt(x^3 + A*x^2 + x) let mut x2 = x; @@ -81,34 +68,28 @@ impl Point { x: x, y: y, infinity: false, - _marker: PhantomData - }) - }, - None => None + _marker: PhantomData, + }); + } + None => None, } } /// This guarantees the point is in the prime order subgroup #[must_use] - pub fn mul_by_cofactor(&self, params: &E::Params) -> Point - { - let tmp = self.double(params) - .double(params) - .double(params); + pub fn mul_by_cofactor(&self, params: &E::Params) -> Point { + let tmp = self.double(params).double(params).double(params); convert_subgroup(&tmp) } - pub fn rand(rng: &mut R, params: &E::Params) -> Self - { + pub fn rand(rng: &mut R, params: &E::Params) -> Self { loop { let x = E::Fr::random(rng); let sign = rng.next_u32() % 2 != 0; match Self::get_for_x(x, sign, params) { - Some(p) => { - return p - }, + Some(p) => return p, None => {} } } @@ -117,11 +98,7 @@ impl Point { impl Point { /// Convert from an Edwards point - pub fn from_edwards( - e: &edwards::Point, - params: &E::Params - ) -> Self - { + pub fn from_edwards(e: &edwards::Point, params: &E::Params) -> Self { let (x, y) = e.into_xy(); if y == E::Fr::one() { @@ -149,7 +126,7 @@ impl Point { x: E::Fr::zero(), y: E::Fr::zero(), infinity: false, - _marker: PhantomData + _marker: PhantomData, } } else { // The mapping is defined as above. @@ -176,7 +153,7 @@ impl Point { x: u, y: v, infinity: false, - _marker: PhantomData + _marker: PhantomData, } } } @@ -197,12 +174,11 @@ impl Point { x: E::Fr::zero(), y: E::Fr::zero(), infinity: true, - _marker: PhantomData + _marker: PhantomData, } } - pub fn into_xy(&self) -> Option<(E::Fr, E::Fr)> - { + pub fn into_xy(&self) -> Option<(E::Fr, E::Fr)> { if self.infinity { None } else { @@ -272,13 +248,12 @@ impl Point { x: x3, y: y3, infinity: false, - _marker: PhantomData + _marker: PhantomData, } } #[must_use] - pub fn add(&self, other: &Self, params: &E::Params) -> Self - { + pub fn add(&self, other: &Self, params: &E::Params) -> Self { // This is a standard affine point addition formula // See 4.3.2 The group law for Weierstrass curves // Montgomery curves and the Montgomery Ladder @@ -301,7 +276,10 @@ impl Point { { let mut tmp = other.x; tmp.sub_assign(&self.x); - delta.mul_assign(&tmp.inverse().expect("self.x != other.x, so this must be nonzero")); + delta.mul_assign( + &tmp.inverse() + .expect("self.x != other.x, so this must be nonzero"), + ); } let mut x3 = delta; @@ -320,7 +298,7 @@ impl Point { x: x3, y: y3, infinity: false, - _marker: PhantomData + _marker: PhantomData, } } } @@ -328,12 +306,7 @@ impl Point { } #[must_use] - pub fn mul::Repr>>( - &self, - scalar: S, - params: &E::Params - ) -> Self - { + pub fn mul::Repr>>(&self, scalar: S, params: &E::Params) -> Self { // Standard double-and-add scalar multiplication let mut res = Self::zero(); diff --git a/zcash_primitives/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs index e15b81e..1b4f8d1 100644 --- a/zcash_primitives/src/jubjub/tests.rs +++ b/zcash_primitives/src/jubjub/tests.rs @@ -1,18 +1,6 @@ -use super::{ - JubjubEngine, - JubjubParams, - PrimeOrder, - montgomery, - edwards -}; +use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder}; -use ff::{ - Field, - PrimeField, - PrimeFieldRepr, - SqrtField, - LegendreSymbol -}; +use ff::{Field, LegendreSymbol, PrimeField, PrimeFieldRepr, SqrtField}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -30,12 +18,7 @@ pub fn test_suite(params: &E::Params) { test_read_write::(params); } -fn is_on_mont_curve>( - x: E::Fr, - y: E::Fr, - params: &P -) -> bool -{ +fn is_on_mont_curve>(x: E::Fr, y: E::Fr, params: &P) -> bool { let mut lhs = y; lhs.square(); @@ -56,9 +39,8 @@ fn is_on_mont_curve>( fn is_on_twisted_edwards_curve>( x: E::Fr, y: E::Fr, - params: &P -) -> bool -{ + params: &P, +) -> bool { let mut x2 = x; x2.square(); @@ -156,7 +138,9 @@ fn test_order(params: &E::Params) { ]); // The neutral element is in the prime order subgroup. - assert!(Point::::zero().as_prime_order(params).is_some()); + assert!(Point::::zero() + .as_prime_order(params) + .is_some()); for _ in 0..50 { // Pick a random point and multiply it by the cofactor @@ -256,11 +240,7 @@ fn test_get_for(params: &E::Params) { if let Some(mut p) = edwards::Point::::get_for_y(y, sign, params) { assert!(p.into_xy().0.into_repr().is_odd() == sign); p = p.negate(); - assert!( - edwards::Point::::get_for_y(y, !sign, params).unwrap() - == - p - ); + assert!(edwards::Point::::get_for_y(y, !sign, params).unwrap() == p); } } } @@ -321,13 +301,9 @@ fn test_back_and_forth(params: &E::Params) { let mont = mont_p1.add(&mont_p2, params).mul(s, params); let edwards = edwards_p1.add(&edwards_p2, params).mul(s, params); - assert!( - montgomery::Point::from_edwards(&edwards, params) == mont - ); + assert!(montgomery::Point::from_edwards(&edwards, params) == mont); - assert!( - edwards::Point::from_montgomery(&mont, params) == edwards - ); + assert!(edwards::Point::from_montgomery(&mont, params) == edwards); } } @@ -411,8 +387,7 @@ fn test_jubjub_params(params: &E::Params) { let mut pacc = E::Fs::zero().into_repr(); let mut nacc = E::Fs::char(); - for _ in 0..params.pedersen_hash_chunks_per_generator() - { + for _ in 0..params.pedersen_hash_chunks_per_generator() { // tmp = cur * 4 let mut tmp = cur; tmp.mul2(); diff --git a/zcash_primitives/src/keys.rs b/zcash_primitives/src/keys.rs index ae2c77a..ad86059 100644 --- a/zcash_primitives/src/keys.rs +++ b/zcash_primitives/src/keys.rs @@ -2,12 +2,12 @@ //! //! Implements section 4.2.2 of the Zcash Protocol Specification. -use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; -use ff::{PrimeField, PrimeFieldRepr}; use crate::{ jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, ToUniform, Unknown}, primitives::{ProofGenerationKey, ViewingKey}, }; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; +use ff::{PrimeField, PrimeFieldRepr}; use std::io::{self, Read, Write}; pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed"; @@ -187,8 +187,8 @@ impl FullViewingKey { #[cfg(test)] mod tests { - use pairing::bls12_381::Bls12; use crate::jubjub::{edwards, FixedGenerators, JubjubParams, PrimeOrder}; + use pairing::bls12_381::Bls12; use std::error::Error; use super::FullViewingKey; diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index e6804cf..5412945 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -1,11 +1,5 @@ //! Implementation of in-band secret distribution for Zcash transactions. -use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; -use ff::{PrimeField, PrimeFieldRepr}; -use pairing::bls12_381::{Bls12, Fr}; -use rand_core::{CryptoRng, RngCore}; use crate::{ jubjub::{ edwards, @@ -14,6 +8,12 @@ use crate::{ }, primitives::{Diversifier, Note, PaymentAddress}, }; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr}; +use rand_core::{CryptoRng, RngCore}; use std::fmt; use std::str; @@ -544,11 +544,6 @@ pub fn try_sapling_output_recovery( #[cfg(test)] mod tests { - use crypto_api_chachapoly::ChachaPolyIetf; - use ff::{Field, PrimeField, PrimeFieldRepr}; - use pairing::bls12_381::{Bls12, Fr, FrRepr}; - use rand_core::{CryptoRng, RngCore}; - use rand_os::OsRng; use crate::{ jubjub::{ edwards, @@ -557,6 +552,11 @@ mod tests { }, primitives::{Diversifier, PaymentAddress, ValueCommitment}, }; + use crypto_api_chachapoly::ChachaPolyIetf; + use ff::{Field, PrimeField, PrimeFieldRepr}; + use pairing::bls12_381::{Bls12, Fr, FrRepr}; + use rand_core::{CryptoRng, RngCore}; + use rand_os::OsRng; use super::{ kdf_sapling, prf_ock, sapling_ka_agree, try_sapling_compact_note_decryption, diff --git a/zcash_primitives/src/pedersen_hash.rs b/zcash_primitives/src/pedersen_hash.rs index aacca37..f21b17b 100644 --- a/zcash_primitives/src/pedersen_hash.rs +++ b/zcash_primitives/src/pedersen_hash.rs @@ -4,14 +4,13 @@ use jubjub::*; #[derive(Copy, Clone)] pub enum Personalization { NoteCommitment, - MerkleTree(usize) + MerkleTree(usize), } impl Personalization { pub fn get_bits(&self) -> Vec { match *self { - Personalization::NoteCommitment => - vec![true, true, true, true, true, true], + Personalization::NoteCommitment => vec![true, true, true, true, true, true], Personalization::MerkleTree(num) => { assert!(num < 63); @@ -24,12 +23,16 @@ impl Personalization { pub fn pedersen_hash( personalization: Personalization, bits: I, - params: &E::Params + params: &E::Params, ) -> edwards::Point - where I: IntoIterator, - E: JubjubEngine +where + I: IntoIterator, + E: JubjubEngine, { - let mut bits = personalization.get_bits().into_iter().chain(bits.into_iter()); + let mut bits = personalization + .get_bits() + .into_iter() + .chain(bits.into_iter()); let mut result = edwards::Point::zero(); let mut generators = params.pedersen_hash_exp_table().iter(); @@ -79,12 +82,13 @@ pub fn pedersen_hash( break; } - let mut table: &[Vec>] = &generators.next().expect("we don't have enough generators"); + let mut table: &[Vec>] = + &generators.next().expect("we don't have enough generators"); let window = JubjubBls12::pedersen_hash_exp_window_size(); let window_mask = (1 << window) - 1; let mut acc = acc.into_repr(); - + let mut tmp = edwards::Point::zero(); while !acc.is_zero() { diff --git a/zcash_primitives/src/primitives.rs b/zcash_primitives/src/primitives.rs index 4026392..d1282b7 100644 --- a/zcash_primitives/src/primitives.rs +++ b/zcash_primitives/src/primitives.rs @@ -4,60 +4,47 @@ use constants; use group_hash::group_hash; -use pedersen_hash::{ - pedersen_hash, - Personalization -}; +use pedersen_hash::{pedersen_hash, Personalization}; -use byteorder::{ - LittleEndian, - WriteBytesExt -}; +use byteorder::{LittleEndian, WriteBytesExt}; -use jubjub::{ - JubjubEngine, - JubjubParams, - edwards, - PrimeOrder, - FixedGenerators -}; +use jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, PrimeOrder}; use blake2s_simd::Params as Blake2sParams; #[derive(Clone)] pub struct ValueCommitment { pub value: u64, - pub randomness: E::Fs + pub randomness: E::Fs, } impl ValueCommitment { - pub fn cm( - &self, - params: &E::Params - ) -> edwards::Point - { - params.generator(FixedGenerators::ValueCommitmentValue) - .mul(self.value, params) - .add( - ¶ms.generator(FixedGenerators::ValueCommitmentRandomness) - .mul(self.randomness, params), - params - ) + pub fn cm(&self, params: &E::Params) -> edwards::Point { + params + .generator(FixedGenerators::ValueCommitmentValue) + .mul(self.value, params) + .add( + ¶ms + .generator(FixedGenerators::ValueCommitmentRandomness) + .mul(self.randomness, params), + params, + ) } } #[derive(Clone)] pub struct ProofGenerationKey { pub ak: edwards::Point, - pub nsk: E::Fs + pub nsk: E::Fs, } impl ProofGenerationKey { pub fn into_viewing_key(&self, params: &E::Params) -> ViewingKey { ViewingKey { ak: self.ak.clone(), - nk: params.generator(FixedGenerators::ProofGenerationKey) - .mul(self.nsk, params) + nk: params + .generator(FixedGenerators::ProofGenerationKey) + .mul(self.nsk, params), } } } @@ -65,19 +52,16 @@ impl ProofGenerationKey { #[derive(Debug)] pub struct ViewingKey { pub ak: edwards::Point, - pub nk: edwards::Point + pub nk: edwards::Point, } impl ViewingKey { - pub fn rk( - &self, - ar: E::Fs, - params: &E::Params - ) -> edwards::Point { + pub fn rk(&self, ar: E::Fs, params: &E::Params) -> edwards::Point { self.ak.add( - ¶ms.generator(FixedGenerators::SpendingKeyGenerator) - .mul(ar, params), - params + ¶ms + .generator(FixedGenerators::SpendingKeyGenerator) + .mul(ar, params), + params, ) } @@ -88,11 +72,13 @@ impl ViewingKey { self.nk.write(&mut preimage[32..64]).unwrap(); let mut h = [0; 32]; - h.copy_from_slice(Blake2sParams::new() - .hash_length(32) - .personal(constants::CRH_IVK_PERSONALIZATION) - .hash(&preimage) - .as_bytes()); + h.copy_from_slice( + Blake2sParams::new() + .hash_length(32) + .personal(constants::CRH_IVK_PERSONALIZATION) + .hash(&preimage) + .as_bytes(), + ); // Drop the most significant five bits, so it can be interpreted as a scalar. h[31] &= 0b0000_0111; @@ -106,15 +92,14 @@ impl ViewingKey { pub fn into_payment_address( &self, diversifier: Diversifier, - params: &E::Params - ) -> Option> - { + params: &E::Params, + ) -> Option> { diversifier.g_d(params).map(|g_d| { let pk_d = g_d.mul(self.ivk(), params); PaymentAddress { pk_d: pk_d, - diversifier: diversifier + diversifier: diversifier, } }) } @@ -126,17 +111,20 @@ pub struct Diversifier(pub [u8; 11]); impl Diversifier { pub fn g_d( &self, - params: &E::Params - ) -> Option> - { - group_hash::(&self.0, constants::KEY_DIVERSIFICATION_PERSONALIZATION, params) + params: &E::Params, + ) -> Option> { + group_hash::( + &self.0, + constants::KEY_DIVERSIFICATION_PERSONALIZATION, + params, + ) } } #[derive(Clone, Debug)] pub struct PaymentAddress { pub pk_d: edwards::Point, - pub diversifier: Diversifier + pub diversifier: Diversifier, } impl PartialEq for PaymentAddress { @@ -146,11 +134,7 @@ impl PartialEq for PaymentAddress { } impl PaymentAddress { - pub fn g_d( - &self, - params: &E::Params - ) -> Option> - { + pub fn g_d(&self, params: &E::Params) -> Option> { self.diversifier.g_d(params) } @@ -158,16 +142,13 @@ impl PaymentAddress { &self, value: u64, randomness: E::Fs, - params: &E::Params - ) -> Option> - { - self.g_d(params).map(|g_d| { - Note { - value: value, - r: randomness, - g_d: g_d, - pk_d: self.pk_d.clone() - } + params: &E::Params, + ) -> Option> { + self.g_d(params).map(|g_d| Note { + value: value, + r: randomness, + g_d: g_d, + pk_d: self.pk_d.clone(), }) } } @@ -181,7 +162,7 @@ pub struct Note { /// The public key of the address, g_d^ivk pub pk_d: edwards::Point, /// The commitment randomness - pub r: E::Fs + pub r: E::Fs, } impl PartialEq for Note { @@ -204,13 +185,14 @@ impl Note { } /// Computes the note commitment, returning the full point. - fn cm_full_point(&self, params: &E::Params) -> edwards::Point - { + fn cm_full_point(&self, params: &E::Params) -> edwards::Point { // Calculate the note contents, as bytes let mut note_contents = vec![]; // Writing the value in little endian - (&mut note_contents).write_u64::(self.value).unwrap(); + (&mut note_contents) + .write_u64::(self.value) + .unwrap(); // Write g_d self.g_d.write(&mut note_contents).unwrap(); @@ -223,36 +205,29 @@ impl Note { // Compute the Pedersen hash of the note contents let hash_of_contents = pedersen_hash( Personalization::NoteCommitment, - note_contents.into_iter() - .flat_map(|byte| { - (0..8).map(move |i| ((byte >> i) & 1) == 1) - }), - params + note_contents + .into_iter() + .flat_map(|byte| (0..8).map(move |i| ((byte >> i) & 1) == 1)), + params, ); // Compute final commitment - params.generator(FixedGenerators::NoteCommitmentRandomness) - .mul(self.r, params) - .add(&hash_of_contents, params) + params + .generator(FixedGenerators::NoteCommitmentRandomness) + .mul(self.r, params) + .add(&hash_of_contents, params) } /// Computes the nullifier given the viewing key and /// note position - pub fn nf( - &self, - viewing_key: &ViewingKey, - position: u64, - params: &E::Params - ) -> Vec - { + pub fn nf(&self, viewing_key: &ViewingKey, position: u64, params: &E::Params) -> Vec { // Compute rho = cm + position.G - let rho = self - .cm_full_point(params) - .add( - ¶ms.generator(FixedGenerators::NullifierPosition) - .mul(position, params), - params - ); + let rho = self.cm_full_point(params).add( + ¶ms + .generator(FixedGenerators::NullifierPosition) + .mul(position, params), + params, + ); // Compute nf = BLAKE2s(nk | rho) let mut nf_preimage = [0u8; 64]; @@ -267,8 +242,7 @@ impl Note { } /// Computes the note commitment - pub fn cm(&self, params: &E::Params) -> E::Fr - { + pub fn cm(&self, params: &E::Params) -> E::Fr { // The commitment is in the prime order subgroup, so mapping the // commitment to the x-coordinate is an injective encoding. self.cm_full_point(params).into_xy().0 diff --git a/zcash_primitives/src/prover.rs b/zcash_primitives/src/prover.rs index a434b4e..7c66737 100644 --- a/zcash_primitives/src/prover.rs +++ b/zcash_primitives/src/prover.rs @@ -1,10 +1,10 @@ //! Abstractions over the proving system and parameters. -use pairing::bls12_381::{Bls12, Fr}; use crate::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, }; +use pairing::bls12_381::{Bls12, Fr}; use crate::{ merkle_tree::CommitmentTreeWitness, diff --git a/zcash_primitives/src/redjubjub.rs b/zcash_primitives/src/redjubjub.rs index b709419..370f63d 100644 --- a/zcash_primitives/src/redjubjub.rs +++ b/zcash_primitives/src/redjubjub.rs @@ -1,11 +1,9 @@ //! Implementation of RedJubjub, a specialization of RedDSA to the Jubjub curve. //! See section 5.4.6 of the Sapling protocol specification. +use crate::jubjub::{edwards::Point, FixedGenerators, JubjubEngine, JubjubParams, Unknown}; use ff::{Field, PrimeField, PrimeFieldRepr}; use rand_core::RngCore; -use crate::jubjub::{ - edwards::Point, FixedGenerators, JubjubEngine, JubjubParams, Unknown, -}; use std::io::{self, Read, Write}; use util::hash_to_scalar; @@ -150,10 +148,15 @@ impl PublicKey { Err(_) => return false, }; // 0 = h_G(-S . P_G + R + c . vk) - self.0.mul(c, params).add(&r, params).add( - ¶ms.generator(p_g).mul(s, params).negate().into(), - params - ).mul_by_cofactor(params).eq(&Point::zero()) + self.0 + .mul(c, params) + .add(&r, params) + .add( + ¶ms.generator(p_g).mul(s, params).negate().into(), + params, + ) + .mul_by_cofactor(params) + .eq(&Point::zero()) } } @@ -170,8 +173,7 @@ pub fn batch_verify<'a, E: JubjubEngine, R: RngCore>( batch: &[BatchEntry<'a, E>], p_g: FixedGenerators, params: &E::Params, -) -> bool -{ +) -> bool { let mut acc = Point::::zero(); for entry in batch { @@ -218,8 +220,8 @@ mod tests { #[test] fn test_batch_verify() { let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let params = &JubjubBls12::new(); let p_g = FixedGenerators::SpendingKeyGenerator; @@ -237,8 +239,16 @@ mod tests { assert!(vk2.verify(msg2, &sig2, p_g, params)); let mut batch = vec![ - BatchEntry { vk: vk1, msg: msg1, sig: sig1 }, - BatchEntry { vk: vk2, msg: msg2, sig: sig2 } + BatchEntry { + vk: vk1, + msg: msg1, + sig: sig1, + }, + BatchEntry { + vk: vk2, + msg: msg2, + sig: sig2, + }, ]; assert!(batch_verify(rng, &batch, p_g, params)); @@ -251,8 +261,8 @@ mod tests { #[test] fn cofactor_check() { let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let params = &JubjubBls12::new(); let zero = edwards::Point::zero(); @@ -286,8 +296,8 @@ mod tests { #[test] fn round_trip_serialization() { let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let p_g = FixedGenerators::SpendingKeyGenerator; let params = &JubjubBls12::new(); @@ -322,8 +332,8 @@ mod tests { #[test] fn random_signatures() { let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let p_g = FixedGenerators::SpendingKeyGenerator; let params = &JubjubBls12::new(); diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 4590c79..02282d3 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -1,13 +1,13 @@ //! Structs and constants specific to the Sapling shielded pool. -use ff::{BitIterator, PrimeField, PrimeFieldRepr}; -use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use rand_core::{CryptoRng, RngCore}; use crate::{ jubjub::{fs::Fs, FixedGenerators, JubjubBls12}, pedersen_hash::{pedersen_hash, Personalization}, primitives::Note, }; +use ff::{BitIterator, PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use rand_core::{CryptoRng, RngCore}; use std::io::{self, Read, Write}; use crate::merkle_tree::Hashable; diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index f32af7a..b0e96f5 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -1,12 +1,12 @@ //! Structs for building transactions. -use ff::Field; -use pairing::bls12_381::{Bls12, Fr}; -use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore}; use crate::{ jubjub::fs::Fs, primitives::{Diversifier, Note, PaymentAddress}, }; +use ff::Field; +use pairing::bls12_381::{Bls12, Fr}; +use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore}; use zip32::ExtendedSpendingKey; use crate::{ diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index c8cfadc..7d2ffbb 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -1,7 +1,7 @@ +use crate::jubjub::{edwards, Unknown}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; -use crate::jubjub::{edwards, Unknown}; use std::io::{self, Read, Write}; use legacy::Script; diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index 44b55f5..7412406 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -135,7 +135,10 @@ impl DiversifierKey { /// Returns the first index starting from j that generates a valid /// diversifier, along with the corresponding diversifier. Returns /// an error if the diversifier space is exhausted. - pub fn diversifier(&self, mut j: DiversifierIndex) -> Result<(DiversifierIndex, Diversifier), ()> { + pub fn diversifier( + &self, + mut j: DiversifierIndex, + ) -> Result<(DiversifierIndex, Diversifier), ()> { let ff = FF1::::new(&self.0, 2).unwrap(); loop { // Generate d_j From 272be622128eb3dfabe63f9abb8fe91c77257e2c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 15 Aug 2019 10:40:07 -0600 Subject: [PATCH 069/105] cargo fmt zcash_proofs --- zcash_proofs/examples/bench.rs | 69 +-- zcash_proofs/src/circuit/ecc.rs | 547 +++++++----------- zcash_proofs/src/circuit/pedersen_hash.rs | 109 ++-- zcash_proofs/src/circuit/sapling.rs | 287 ++++----- zcash_proofs/src/circuit/sprout/commitment.rs | 21 +- zcash_proofs/src/circuit/sprout/input.rs | 113 ++-- zcash_proofs/src/circuit/sprout/mod.rs | 194 +++---- zcash_proofs/src/circuit/sprout/output.rs | 36 +- zcash_proofs/src/circuit/sprout/prfs.rs | 60 +- zcash_proofs/src/prover.rs | 2 +- zcash_proofs/src/sapling/prover.rs | 4 +- 11 files changed, 595 insertions(+), 847 deletions(-) diff --git a/zcash_proofs/examples/bench.rs b/zcash_proofs/examples/bench.rs index a187ec6..a5c8a13 100644 --- a/zcash_proofs/examples/bench.rs +++ b/zcash_proofs/examples/bench.rs @@ -1,30 +1,20 @@ -extern crate ff; extern crate bellman; +extern crate ff; extern crate pairing; extern crate rand_core; extern crate rand_xorshift; extern crate zcash_primitives; extern crate zcash_proofs; -use ff::Field; -use std::time::{Duration, Instant}; -use zcash_primitives::jubjub::{ - JubjubBls12, - edwards, - fs, -}; -use zcash_proofs::circuit::sapling::{ - Spend -}; -use zcash_primitives::primitives::{ - Diversifier, - ProofGenerationKey, - ValueCommitment -}; use bellman::groth16::*; +use ff::Field; +use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; -use pairing::bls12_381::{Bls12, Fr}; +use std::time::{Duration, Instant}; +use zcash_primitives::jubjub::{edwards, fs, JubjubBls12}; +use zcash_primitives::primitives::{Diversifier, ProofGenerationKey, ValueCommitment}; +use zcash_proofs::circuit::sapling::Spend; const TREE_DEPTH: usize = 32; @@ -45,10 +35,11 @@ fn main() { commitment_randomness: None, ar: None, auth_path: vec![None; TREE_DEPTH], - anchor: None + anchor: None, }, - rng - ).unwrap(); + rng, + ) + .unwrap(); const SAMPLES: u32 = 50; @@ -56,7 +47,7 @@ fn main() { for _ in 0..SAMPLES { let value_commitment = ValueCommitment { value: 1, - randomness: fs::Fs::random(rng) + randomness: fs::Fs::random(rng), }; let nsk = fs::Fs::random(rng); @@ -64,7 +55,7 @@ fn main() { let proof_generation_key = ProofGenerationKey { ak: ak.clone(), - nsk: nsk.clone() + nsk: nsk.clone(), }; let viewing_key = proof_generation_key.into_viewing_key(jubjub_params); @@ -78,11 +69,7 @@ fn main() { Diversifier(d) }; - if let Some(p) = viewing_key.into_payment_address( - diversifier, - jubjub_params - ) - { + if let Some(p) = viewing_key.into_payment_address(diversifier, jubjub_params) { payment_address = p; break; } @@ -94,21 +81,25 @@ fn main() { let anchor = Fr::random(rng); let start = Instant::now(); - let _ = create_random_proof(Spend { - params: jubjub_params, - value_commitment: Some(value_commitment), - proof_generation_key: Some(proof_generation_key), - payment_address: Some(payment_address), - commitment_randomness: Some(commitment_randomness), - ar: Some(ar), - auth_path: auth_path, - anchor: Some(anchor) - }, &groth_params, rng).unwrap(); + let _ = create_random_proof( + Spend { + params: jubjub_params, + value_commitment: Some(value_commitment), + proof_generation_key: Some(proof_generation_key), + payment_address: Some(payment_address), + commitment_randomness: Some(commitment_randomness), + ar: Some(ar), + auth_path: auth_path, + anchor: Some(anchor), + }, + &groth_params, + rng, + ) + .unwrap(); total_time += start.elapsed(); } let avg = total_time / SAMPLES; - let avg = avg.subsec_nanos() as f64 / 1_000_000_000f64 - + (avg.as_secs() as f64); + let avg = avg.subsec_nanos() as f64 / 1_000_000_000f64 + (avg.as_secs() as f64); println!("Average proving time (in seconds): {}", avg); } diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index 593c57d..4c07829 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -1,37 +1,22 @@ use ff::Field; use pairing::Engine; -use bellman::{ - SynthesisError, - ConstraintSystem -}; +use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::{ - Assignment -}; +use bellman::gadgets::Assignment; -use bellman::gadgets::num::{ - AllocatedNum, - Num -}; +use bellman::gadgets::num::{AllocatedNum, Num}; -use zcash_primitives::jubjub::{ - edwards, - JubjubEngine, - JubjubParams, - FixedGenerators -}; +use zcash_primitives::jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams}; -use bellman::gadgets::lookup::{ - lookup3_xy -}; +use bellman::gadgets::lookup::lookup3_xy; use bellman::gadgets::boolean::Boolean; #[derive(Clone)] pub struct EdwardsPoint { x: AllocatedNum, - y: AllocatedNum + y: AllocatedNum, } /// Perform a fixed-base scalar multiplication with @@ -40,32 +25,40 @@ pub fn fixed_base_multiplication( mut cs: CS, base: FixedGenerators, by: &[Boolean], - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where CS: ConstraintSystem, - E: JubjubEngine +where + CS: ConstraintSystem, + E: JubjubEngine, { // Represents the result of the multiplication let mut result = None; - for (i, (chunk, window)) in by.chunks(3) - .zip(params.circuit_generators(base).iter()) - .enumerate() + for (i, (chunk, window)) in by + .chunks(3) + .zip(params.circuit_generators(base).iter()) + .enumerate() { - let chunk_a = chunk.get(0).map(|e| e.clone()).unwrap_or(Boolean::constant(false)); - let chunk_b = chunk.get(1).map(|e| e.clone()).unwrap_or(Boolean::constant(false)); - let chunk_c = chunk.get(2).map(|e| e.clone()).unwrap_or(Boolean::constant(false)); + let chunk_a = chunk + .get(0) + .map(|e| e.clone()) + .unwrap_or(Boolean::constant(false)); + let chunk_b = chunk + .get(1) + .map(|e| e.clone()) + .unwrap_or(Boolean::constant(false)); + let chunk_c = chunk + .get(2) + .map(|e| e.clone()) + .unwrap_or(Boolean::constant(false)); let (x, y) = lookup3_xy( cs.namespace(|| format!("window table lookup {}", i)), &[chunk_a, chunk_b, chunk_c], - window + window, )?; - let p = EdwardsPoint { - x: x, - y: y - }; + let p = EdwardsPoint { x: x, y: y }; if result.is_none() { result = Some(p); @@ -73,7 +66,7 @@ pub fn fixed_base_multiplication( result = Some(result.unwrap().add( cs.namespace(|| format!("addition {}", i)), &p, - params + params, )?); } } @@ -93,22 +86,14 @@ impl EdwardsPoint { pub fn assert_not_small_order( &self, mut cs: CS, - params: &E::Params + params: &E::Params, ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + where + CS: ConstraintSystem, { - let tmp = self.double( - cs.namespace(|| "first doubling"), - params - )?; - let tmp = tmp.double( - cs.namespace(|| "second doubling"), - params - )?; - let tmp = tmp.double( - cs.namespace(|| "third doubling"), - params - )?; + let tmp = self.double(cs.namespace(|| "first doubling"), params)?; + let tmp = tmp.double(cs.namespace(|| "second doubling"), params)?; + let tmp = tmp.double(cs.namespace(|| "third doubling"), params)?; // (0, -1) is a small order point, but won't ever appear here // because cofactor is 2^3, and we performed three doublings. @@ -119,11 +104,9 @@ impl EdwardsPoint { Ok(()) } - pub fn inputize( - &self, - mut cs: CS - ) -> Result<(), SynthesisError> - where CS: ConstraintSystem + pub fn inputize(&self, mut cs: CS) -> Result<(), SynthesisError> + where + CS: ConstraintSystem, { self.x.inputize(cs.namespace(|| "x"))?; self.y.inputize(cs.namespace(|| "y"))?; @@ -132,21 +115,15 @@ impl EdwardsPoint { } /// This converts the point into a representation. - pub fn repr( - &self, - mut cs: CS - ) -> Result, SynthesisError> - where CS: ConstraintSystem + pub fn repr(&self, mut cs: CS) -> Result, SynthesisError> + where + CS: ConstraintSystem, { let mut tmp = vec![]; - let x = self.x.into_bits_le_strict( - cs.namespace(|| "unpack x") - )?; + let x = self.x.into_bits_le_strict(cs.namespace(|| "unpack x"))?; - let y = self.y.into_bits_le_strict( - cs.namespace(|| "unpack y") - )?; + let y = self.y.into_bits_le_strict(cs.namespace(|| "unpack y"))?; tmp.extend(y); tmp.push(x[0].clone()); @@ -159,34 +136,20 @@ impl EdwardsPoint { pub fn witness( mut cs: CS, p: Option>, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { let p = p.map(|p| p.into_xy()); // Allocate x - let x = AllocatedNum::alloc( - cs.namespace(|| "x"), - || { - Ok(p.get()?.0) - } - )?; + let x = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(p.get()?.0))?; // Allocate y - let y = AllocatedNum::alloc( - cs.namespace(|| "y"), - || { - Ok(p.get()?.1) - } - )?; + let y = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(p.get()?.1))?; - Self::interpret( - cs.namespace(|| "point interpretation"), - &x, - &y, - params - ) + Self::interpret(cs.namespace(|| "point interpretation"), &x, &y, params) } /// Returns `self` if condition is true, and the neutral @@ -194,9 +157,10 @@ impl EdwardsPoint { pub fn conditionally_select( &self, mut cs: CS, - condition: &Boolean + condition: &Boolean, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute x' = self.x if condition, and 0 otherwise let x_prime = AllocatedNum::alloc(cs.namespace(|| "x'"), || { @@ -215,7 +179,7 @@ impl EdwardsPoint { || "x' computation", |lc| lc + self.x.get_variable(), |_| condition.lc(one, E::Fr::one()), - |lc| lc + x_prime.get_variable() + |lc| lc + x_prime.get_variable(), ); // Compute y' = self.y if condition, and 1 otherwise @@ -234,13 +198,12 @@ impl EdwardsPoint { || "y' computation", |lc| lc + self.y.get_variable(), |_| condition.lc(one, E::Fr::one()), - |lc| lc + y_prime.get_variable() - - &condition.not().lc(one, E::Fr::one()) + |lc| lc + y_prime.get_variable() - &condition.not().lc(one, E::Fr::one()), ); Ok(EdwardsPoint { x: x_prime, - y: y_prime + y: y_prime, }) } @@ -251,9 +214,10 @@ impl EdwardsPoint { &self, mut cs: CS, by: &[Boolean], - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Represents the current "magnitude" of the base // that we're operating over. Starts at self, @@ -269,8 +233,9 @@ impl EdwardsPoint { } else { // Double the previous value curbase = Some( - curbase.unwrap() - .double(cs.namespace(|| format!("doubling {}", i)), params)? + curbase + .unwrap() + .double(cs.namespace(|| format!("doubling {}", i)), params)?, ); } @@ -278,12 +243,10 @@ impl EdwardsPoint { // is true, this will return `curbase`. Otherwise it will // return the neutral element, which will have no effect on // the result. - let thisbase = curbase.as_ref() - .unwrap() - .conditionally_select( - cs.namespace(|| format!("selection {}", i)), - bit - )?; + let thisbase = curbase + .as_ref() + .unwrap() + .conditionally_select(cs.namespace(|| format!("selection {}", i)), bit)?; if result.is_none() { result = Some(thisbase); @@ -291,7 +254,7 @@ impl EdwardsPoint { result = Some(result.unwrap().add( cs.namespace(|| format!("addition {}", i)), &thisbase, - params + params, )?); } } @@ -303,9 +266,10 @@ impl EdwardsPoint { mut cs: CS, x: &AllocatedNum, y: &AllocatedNum, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // -x^2 + y^2 = 1 + dx^2y^2 @@ -316,25 +280,20 @@ impl EdwardsPoint { let one = CS::one(); cs.enforce( || "on curve check", - |lc| lc - x2.get_variable() - + y2.get_variable(), + |lc| lc - x2.get_variable() + y2.get_variable(), |lc| lc + one, - |lc| lc + one - + (*params.edwards_d(), x2y2.get_variable()) + |lc| lc + one + (*params.edwards_d(), x2y2.get_variable()), ); Ok(EdwardsPoint { x: x.clone(), - y: y.clone() + y: y.clone(), }) } - pub fn double( - &self, - mut cs: CS, - params: &E::Params - ) -> Result - where CS: ConstraintSystem + pub fn double(&self, mut cs: CS, params: &E::Params) -> Result + where + CS: ConstraintSystem, { // Compute T = (x1 + y1) * (x1 + y1) let t = AllocatedNum::alloc(cs.namespace(|| "T"), || { @@ -351,11 +310,9 @@ impl EdwardsPoint { cs.enforce( || "T computation", - |lc| lc + self.x.get_variable() - + self.y.get_variable(), - |lc| lc + self.x.get_variable() - + self.y.get_variable(), - |lc| lc + t.get_variable() + |lc| lc + self.x.get_variable() + self.y.get_variable(), + |lc| lc + self.x.get_variable() + self.y.get_variable(), + |lc| lc + t.get_variable(), ); // Compute A = x1 * y1 @@ -374,7 +331,7 @@ impl EdwardsPoint { || "C computation", |lc| lc + (*params.edwards_d(), a.get_variable()), |lc| lc + a.get_variable(), - |lc| lc + c.get_variable() + |lc| lc + c.get_variable(), ); // Compute x3 = (2.A) / (1 + C) @@ -390,10 +347,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -402,8 +357,7 @@ impl EdwardsPoint { || "x3 computation", |lc| lc + one + c.get_variable(), |lc| lc + x3.get_variable(), - |lc| lc + a.get_variable() - + a.get_variable() + |lc| lc + a.get_variable() + a.get_variable(), ); // Compute y3 = (U - 2.A) / (1 - C) @@ -421,10 +375,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -432,15 +384,10 @@ impl EdwardsPoint { || "y3 computation", |lc| lc + one - c.get_variable(), |lc| lc + y3.get_variable(), - |lc| lc + t.get_variable() - - a.get_variable() - - a.get_variable() + |lc| lc + t.get_variable() - a.get_variable() - a.get_variable(), ); - Ok(EdwardsPoint { - x: x3, - y: y3 - }) + Ok(EdwardsPoint { x: x3, y: y3 }) } /// Perform addition between any two points @@ -448,9 +395,10 @@ impl EdwardsPoint { &self, mut cs: CS, other: &Self, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute U = (x1 + y1) * (x2 + y2) let u = AllocatedNum::alloc(cs.namespace(|| "U"), || { @@ -467,11 +415,9 @@ impl EdwardsPoint { cs.enforce( || "U computation", - |lc| lc + self.x.get_variable() - + self.y.get_variable(), - |lc| lc + other.x.get_variable() - + other.y.get_variable(), - |lc| lc + u.get_variable() + |lc| lc + self.x.get_variable() + self.y.get_variable(), + |lc| lc + other.x.get_variable() + other.y.get_variable(), + |lc| lc + u.get_variable(), ); // Compute A = y2 * x1 @@ -493,7 +439,7 @@ impl EdwardsPoint { || "C computation", |lc| lc + (*params.edwards_d(), a.get_variable()), |lc| lc + b.get_variable(), - |lc| lc + c.get_variable() + |lc| lc + c.get_variable(), ); // Compute x3 = (A + B) / (1 + C) @@ -509,10 +455,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -521,8 +465,7 @@ impl EdwardsPoint { || "x3 computation", |lc| lc + one + c.get_variable(), |lc| lc + x3.get_variable(), - |lc| lc + a.get_variable() - + b.get_variable() + |lc| lc + a.get_variable() + b.get_variable(), ); // Compute y3 = (U - A - B) / (1 - C) @@ -539,10 +482,8 @@ impl EdwardsPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -550,21 +491,16 @@ impl EdwardsPoint { || "y3 computation", |lc| lc + one - c.get_variable(), |lc| lc + y3.get_variable(), - |lc| lc + u.get_variable() - - a.get_variable() - - b.get_variable() + |lc| lc + u.get_variable() - a.get_variable() - b.get_variable(), ); - Ok(EdwardsPoint { - x: x3, - y: y3 - }) + Ok(EdwardsPoint { x: x3, y: y3 }) } } pub struct MontgomeryPoint { x: Num, - y: Num + y: Num, } impl MontgomeryPoint { @@ -574,9 +510,10 @@ impl MontgomeryPoint { pub fn into_edwards( &self, mut cs: CS, - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute u = (scale*x) / y let u = AllocatedNum::alloc(cs.namespace(|| "u"), || { @@ -588,10 +525,8 @@ impl MontgomeryPoint { t0.mul_assign(&invy); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; @@ -599,7 +534,7 @@ impl MontgomeryPoint { || "u computation", |lc| lc + &self.y.lc(E::Fr::one()), |lc| lc + u.get_variable(), - |lc| lc + &self.x.lc(*params.scale()) + |lc| lc + &self.x.lc(*params.scale()), ); // Compute v = (x - 1) / (x + 1) @@ -614,42 +549,28 @@ impl MontgomeryPoint { t0.mul_assign(&t1); Ok(t0) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; let one = CS::one(); cs.enforce( || "v computation", - |lc| lc + &self.x.lc(E::Fr::one()) - + one, + |lc| lc + &self.x.lc(E::Fr::one()) + one, |lc| lc + v.get_variable(), - |lc| lc + &self.x.lc(E::Fr::one()) - - one, + |lc| lc + &self.x.lc(E::Fr::one()) - one, ); - Ok(EdwardsPoint { - x: u, - y: v - }) + Ok(EdwardsPoint { x: u, y: v }) } /// Interprets an (x, y) pair as a point /// in Montgomery, does not check that it's /// on the curve. Useful for constants and /// window table lookups. - pub fn interpret_unchecked( - x: Num, - y: Num - ) -> Self - { - MontgomeryPoint { - x: x, - y: y - } + pub fn interpret_unchecked(x: Num, y: Num) -> Self { + MontgomeryPoint { x: x, y: y } } /// Performs an affine point addition, not defined for @@ -658,9 +579,10 @@ impl MontgomeryPoint { &self, mut cs: CS, other: &Self, - params: &E::Params + params: &E::Params, ) -> Result - where CS: ConstraintSystem + where + CS: ConstraintSystem, { // Compute lambda = (y' - y) / (x' - x) let lambda = AllocatedNum::alloc(cs.namespace(|| "lambda"), || { @@ -674,22 +596,16 @@ impl MontgomeryPoint { Some(d) => { n.mul_assign(&d); Ok(n) - }, - None => { - Err(SynthesisError::DivisionByZero) } + None => Err(SynthesisError::DivisionByZero), } })?; cs.enforce( || "evaluate lambda", - |lc| lc + &other.x.lc(E::Fr::one()) - - &self.x.lc(E::Fr::one()), - + |lc| lc + &other.x.lc(E::Fr::one()) - &self.x.lc(E::Fr::one()), |lc| lc + lambda.get_variable(), - - |lc| lc + &other.y.lc(E::Fr::one()) - - &self.y.lc(E::Fr::one()) + |lc| lc + &other.y.lc(E::Fr::one()) - &self.y.lc(E::Fr::one()), ); // Compute x'' = lambda^2 - A - x - x' @@ -709,10 +625,12 @@ impl MontgomeryPoint { || "evaluate xprime", |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), - |lc| lc + (*params.montgomery_a(), one) + |lc| { + lc + (*params.montgomery_a(), one) + &self.x.lc(E::Fr::one()) + &other.x.lc(E::Fr::one()) + xprime.get_variable() + }, ); // Compute y' = -(y + lambda(x' - x)) @@ -729,57 +647,41 @@ impl MontgomeryPoint { // y' + y = lambda(x - x') cs.enforce( || "evaluate yprime", - |lc| lc + &self.x.lc(E::Fr::one()) - - xprime.get_variable(), - + |lc| lc + &self.x.lc(E::Fr::one()) - xprime.get_variable(), |lc| lc + lambda.get_variable(), - - |lc| lc + yprime.get_variable() - + &self.y.lc(E::Fr::one()) + |lc| lc + yprime.get_variable() + &self.y.lc(E::Fr::one()), ); Ok(MontgomeryPoint { x: xprime.into(), - y: yprime.into() + y: yprime.into(), }) } } #[cfg(test)] mod test { - use bellman::{ConstraintSystem}; + use bellman::ConstraintSystem; use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use bellman::gadgets::test::*; - use zcash_primitives::jubjub::{ - montgomery, - edwards, - JubjubBls12, - JubjubParams, - FixedGenerators - }; use zcash_primitives::jubjub::fs::Fs; + use zcash_primitives::jubjub::{ + edwards, montgomery, FixedGenerators, JubjubBls12, JubjubParams, + }; - use super::{ - MontgomeryPoint, - EdwardsPoint, - AllocatedNum, - fixed_base_multiplication - }; - use bellman::gadgets::boolean::{ - Boolean, - AllocatedBit - }; + use super::{fixed_base_multiplication, AllocatedNum, EdwardsPoint, MontgomeryPoint}; + use bellman::gadgets::boolean::{AllocatedBit, Boolean}; #[test] fn test_into_edwards() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -789,12 +691,8 @@ mod test { let (u, v) = edwards::Point::from_montgomery(&p, params).into_xy(); let (x, y) = p.into_xy().unwrap(); - let numx = AllocatedNum::alloc(cs.namespace(|| "mont x"), || { - Ok(x) - }).unwrap(); - let numy = AllocatedNum::alloc(cs.namespace(|| "mont y"), || { - Ok(y) - }).unwrap(); + let numx = AllocatedNum::alloc(cs.namespace(|| "mont x"), || Ok(x)).unwrap(); + let numy = AllocatedNum::alloc(cs.namespace(|| "mont y"), || Ok(y)).unwrap(); let p = MontgomeryPoint::interpret_unchecked(numx.into(), numy.into()); @@ -820,19 +718,15 @@ mod test { fn test_interpret() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { let p = edwards::Point::::rand(rng, ¶ms); let mut cs = TestConstraintSystem::::new(); - let q = EdwardsPoint::witness( - &mut cs, - Some(p.clone()), - ¶ms - ).unwrap(); + let q = EdwardsPoint::witness(&mut cs, Some(p.clone()), ¶ms).unwrap(); let p = p.into_xy(); @@ -846,12 +740,8 @@ mod test { let (x, y) = p.into_xy(); let mut cs = TestConstraintSystem::::new(); - let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || { - Ok(x) - }).unwrap(); - let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || { - Ok(y) - }).unwrap(); + let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(x)).unwrap(); + let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(y)).unwrap(); let p = EdwardsPoint::interpret(&mut cs, &numx, &numy, ¶ms).unwrap(); @@ -866,12 +756,8 @@ mod test { let y = Fr::random(rng); let mut cs = TestConstraintSystem::::new(); - let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || { - Ok(x) - }).unwrap(); - let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || { - Ok(y) - }).unwrap(); + let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(x)).unwrap(); + let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(y)).unwrap(); EdwardsPoint::interpret(&mut cs, &numx, &numy, ¶ms).unwrap(); @@ -880,11 +766,11 @@ mod test { } #[test] - fn test_edwards_fixed_base_multiplication() { + fn test_edwards_fixed_base_multiplication() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -899,18 +785,23 @@ mod test { s_bits.reverse(); s_bits.truncate(Fs::NUM_BITS as usize); - let s_bits = s_bits.into_iter() - .enumerate() - .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)).unwrap()) - .map(|v| Boolean::from(v)) - .collect::>(); + let s_bits = s_bits + .into_iter() + .enumerate() + .map(|(i, b)| { + AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)) + .unwrap() + }) + .map(|v| Boolean::from(v)) + .collect::>(); let q = fixed_base_multiplication( cs.namespace(|| "multiplication"), FixedGenerators::NoteCommitmentRandomness, &s_bits, - params - ).unwrap(); + params, + ) + .unwrap(); assert_eq!(q.x.get_value().unwrap(), x1); assert_eq!(q.y.get_value().unwrap(), y1); @@ -921,8 +812,8 @@ mod test { fn test_edwards_multiplication() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -935,45 +826,37 @@ mod test { let (x0, y0) = p.into_xy(); let (x1, y1) = q.into_xy(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); let p = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let mut s_bits = BitIterator::new(s.into_repr()).collect::>(); s_bits.reverse(); s_bits.truncate(Fs::NUM_BITS as usize); - let s_bits = s_bits.into_iter() - .enumerate() - .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)).unwrap()) - .map(|v| Boolean::from(v)) - .collect::>(); + let s_bits = s_bits + .into_iter() + .enumerate() + .map(|(i, b)| { + AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)) + .unwrap() + }) + .map(|v| Boolean::from(v)) + .collect::>(); - let q = p.mul( - cs.namespace(|| "scalar mul"), - &s_bits, - params - ).unwrap(); + let q = p + .mul(cs.namespace(|| "scalar mul"), &s_bits, params) + .unwrap(); assert!(cs.is_satisfied()); - assert_eq!( - q.x.get_value().unwrap(), - x1 - ); + assert_eq!(q.x.get_value().unwrap(), x1); - assert_eq!( - q.y.get_value().unwrap(), - y1 - ); + assert_eq!(q.y.get_value().unwrap(), y1); } } @@ -981,8 +864,8 @@ mod test { fn test_conditionally_select() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..1000 { @@ -992,26 +875,22 @@ mod test { let (x0, y0) = p.into_xy(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); let p = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let mut should_we_select = rng.next_u32() % 2 != 0; // Conditionally allocate let mut b = if rng.next_u32() % 2 != 0 { - Boolean::from(AllocatedBit::alloc( - cs.namespace(|| "condition"), - Some(should_we_select) - ).unwrap()) + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| "condition"), Some(should_we_select)) + .unwrap(), + ) } else { Boolean::constant(should_we_select) }; @@ -1022,7 +901,9 @@ mod test { should_we_select = !should_we_select; } - let q = p.conditionally_select(cs.namespace(|| "select"), &b).unwrap(); + let q = p + .conditionally_select(cs.namespace(|| "select"), &b) + .unwrap(); assert!(cs.is_satisfied()); @@ -1050,8 +931,8 @@ mod test { fn test_edwards_addition() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -1066,28 +947,20 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); - let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || { - Ok(x1) - }).unwrap(); - let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || { - Ok(y1) - }).unwrap(); + let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || Ok(x1)).unwrap(); + let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || Ok(y1)).unwrap(); let p1 = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let p2 = EdwardsPoint { x: num_x1, - y: num_y1 + y: num_y1, }; let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap(); @@ -1121,8 +994,8 @@ mod test { fn test_edwards_doubling() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -1134,16 +1007,12 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); let p1 = EdwardsPoint { x: num_x0, - y: num_y0 + y: num_y0, }; let p2 = p1.double(cs.namespace(|| "doubling"), params).unwrap(); @@ -1159,8 +1028,8 @@ mod test { fn test_montgomery_addition() { let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); for _ in 0..100 { @@ -1190,28 +1059,20 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || { - Ok(x0) - }).unwrap(); - let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || { - Ok(y0) - }).unwrap(); + let num_x0 = AllocatedNum::alloc(cs.namespace(|| "x0"), || Ok(x0)).unwrap(); + let num_y0 = AllocatedNum::alloc(cs.namespace(|| "y0"), || Ok(y0)).unwrap(); - let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || { - Ok(x1) - }).unwrap(); - let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || { - Ok(y1) - }).unwrap(); + let num_x1 = AllocatedNum::alloc(cs.namespace(|| "x1"), || Ok(x1)).unwrap(); + let num_y1 = AllocatedNum::alloc(cs.namespace(|| "y1"), || Ok(y1)).unwrap(); let p1 = MontgomeryPoint { x: num_x0.into(), - y: num_y0.into() + y: num_y0.into(), }; let p2 = MontgomeryPoint { x: num_x1.into(), - y: num_y1.into() + y: num_y1.into(), }; let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap(); diff --git a/zcash_proofs/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs index 0b67597..21c0bf5 100644 --- a/zcash_proofs/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -1,17 +1,13 @@ -use super::ecc::{ - MontgomeryPoint, - EdwardsPoint -}; +use super::ecc::{EdwardsPoint, MontgomeryPoint}; use bellman::gadgets::boolean::Boolean; -use zcash_primitives::jubjub::*; -use bellman::{ - ConstraintSystem, SynthesisError -}; use bellman::gadgets::lookup::*; +use bellman::{ConstraintSystem, SynthesisError}; +use zcash_primitives::jubjub::*; pub use zcash_primitives::pedersen_hash::Personalization; fn get_constant_bools(person: &Personalization) -> Vec { - person.get_bits() + person + .get_bits() .into_iter() .map(|e| Boolean::constant(e)) .collect() @@ -21,9 +17,10 @@ pub fn pedersen_hash( mut cs: CS, personalization: Personalization, bits: &[Boolean], - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where CS: ConstraintSystem +where + CS: ConstraintSystem, { let personalization = get_constant_bools(&personalization); assert_eq!(personalization.len(), 6); @@ -36,8 +33,7 @@ pub fn pedersen_hash( let mut segment_i = 0; loop { let mut segment_result = None; - let mut segment_windows = &segment_generators.next() - .expect("enough segments")[..]; + let mut segment_windows = &segment_generators.next().expect("enough segments")[..]; let mut window_i = 0; while let Some(a) = bits.next() { @@ -47,7 +43,7 @@ pub fn pedersen_hash( let tmp = lookup3_xy_with_conditional_negation( cs.namespace(|| format!("segment {}, window {}", segment_i, window_i)), &[a.clone(), b.clone(), c.clone()], - &segment_windows[0] + &segment_windows[0], )?; let tmp = MontgomeryPoint::interpret_unchecked(tmp.0, tmp.1); @@ -55,12 +51,14 @@ pub fn pedersen_hash( match segment_result { None => { segment_result = Some(tmp); - }, + } Some(ref mut segment_result) => { *segment_result = tmp.add( - cs.namespace(|| format!("addition of segment {}, window {}", segment_i, window_i)), + cs.namespace(|| { + format!("addition of segment {}, window {}", segment_i, window_i) + }), segment_result, - params + params, )?; } } @@ -79,22 +77,24 @@ pub fn pedersen_hash( // Convert this segment into twisted Edwards form. let segment_result = segment_result.into_edwards( cs.namespace(|| format!("conversion of segment {} into edwards", segment_i)), - params + params, )?; match edwards_result { Some(ref mut edwards_result) => { *edwards_result = segment_result.add( - cs.namespace(|| format!("addition of segment {} to accumulator", segment_i)), + cs.namespace(|| { + format!("addition of segment {} to accumulator", segment_i) + }), edwards_result, - params + params, )?; - }, + } None => { edwards_result = Some(segment_result); } } - }, + } None => { // We didn't process any new bits. break; @@ -110,37 +110,44 @@ pub fn pedersen_hash( #[cfg(test)] mod test { use super::*; + use bellman::gadgets::boolean::{AllocatedBit, Boolean}; use bellman::gadgets::test::*; - use bellman::gadgets::boolean::{Boolean, AllocatedBit}; - use zcash_primitives::pedersen_hash; use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; + use zcash_primitives::pedersen_hash; #[test] fn test_pedersen_hash_constraints() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let params = &JubjubBls12::new(); let mut cs = TestConstraintSystem::::new(); - let input: Vec = (0..(Fr::NUM_BITS * 2)).map(|_| rng.next_u32() % 2 != 0).collect(); + let input: Vec = (0..(Fr::NUM_BITS * 2)) + .map(|_| rng.next_u32() % 2 != 0) + .collect(); - let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { - Boolean::from( - AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap() - ) - }).collect(); + let input_bools: Vec = input + .iter() + .enumerate() + .map(|(i, b)| { + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap(), + ) + }) + .collect(); pedersen_hash( cs.namespace(|| "pedersen hash"), Personalization::NoteCommitment, &input_bools, - params - ).unwrap(); + params, + ) + .unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 1377); @@ -149,8 +156,8 @@ mod test { #[test] fn test_pedersen_hash() { let mut rng = XorShiftRng::from_seed([ - 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, - 0xe5, + 0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, + 0xbc, 0xe5, ]); let params = &JubjubBls12::new(); @@ -160,26 +167,33 @@ mod test { let mut cs = TestConstraintSystem::::new(); - let input_bools: Vec = input.iter().enumerate().map(|(i, b)| { - Boolean::from( - AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)).unwrap() - ) - }).collect(); + let input_bools: Vec = input + .iter() + .enumerate() + .map(|(i, b)| { + Boolean::from( + AllocatedBit::alloc(cs.namespace(|| format!("input {}", i)), Some(*b)) + .unwrap(), + ) + }) + .collect(); let res = pedersen_hash( cs.namespace(|| "pedersen hash"), Personalization::MerkleTree(1), &input_bools, - params - ).unwrap(); + params, + ) + .unwrap(); assert!(cs.is_satisfied()); let expected = pedersen_hash::pedersen_hash::( Personalization::MerkleTree(1), input.clone().into_iter(), - params - ).into_xy(); + params, + ) + .into_xy(); assert_eq!(res.get_x().get_value().unwrap(), expected.0); assert_eq!(res.get_y().get_value().unwrap(), expected.1); @@ -188,8 +202,9 @@ mod test { let unexpected = pedersen_hash::pedersen_hash::( Personalization::MerkleTree(0), input.into_iter(), - params - ).into_xy(); + params, + ) + .into_xy(); assert!(res.get_x().get_value().unwrap() != unexpected.0); assert!(res.get_y().get_value().unwrap() != unexpected.1); diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index 1349c8c..0554ff4 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -1,31 +1,20 @@ use ff::{Field, PrimeField, PrimeFieldRepr}; -use bellman::{ - SynthesisError, - ConstraintSystem, - Circuit -}; +use bellman::{Circuit, ConstraintSystem, SynthesisError}; -use zcash_primitives::jubjub::{ - JubjubEngine, - FixedGenerators -}; +use zcash_primitives::jubjub::{FixedGenerators, JubjubEngine}; use zcash_primitives::constants; -use zcash_primitives::primitives::{ - ValueCommitment, - ProofGenerationKey, - PaymentAddress -}; +use zcash_primitives::primitives::{PaymentAddress, ProofGenerationKey, ValueCommitment}; -use bellman::gadgets::Assignment; -use bellman::gadgets::boolean; use super::ecc; use super::pedersen_hash; use bellman::gadgets::blake2s; -use bellman::gadgets::num; +use bellman::gadgets::boolean; use bellman::gadgets::multipack; +use bellman::gadgets::num; +use bellman::gadgets::Assignment; pub const TREE_DEPTH: usize = zcash_primitives::sapling::SAPLING_COMMITMENT_TREE_DEPTH; @@ -54,7 +43,7 @@ pub struct Spend<'a, E: JubjubEngine> { /// The anchor; the root of the tree. If the note being /// spent is zero-value, this can be anything. - pub anchor: Option + pub anchor: Option, } /// This is an output circuit instance. @@ -71,7 +60,7 @@ pub struct Output<'a, E: JubjubEngine> { pub commitment_randomness: Option, /// The ephemeral secret key for DH with recipient - pub esk: Option + pub esk: Option, } /// Exposes a Pedersen commitment to the value as an @@ -79,15 +68,16 @@ pub struct Output<'a, E: JubjubEngine> { fn expose_value_commitment( mut cs: CS, value_commitment: Option>, - params: &E::Params + params: &E::Params, ) -> Result, SynthesisError> - where E: JubjubEngine, - CS: ConstraintSystem +where + E: JubjubEngine, + CS: ConstraintSystem, { // Booleanize the value into little-endian bit order let value_bits = boolean::u64_into_boolean_vec_le( cs.namespace(|| "value"), - value_commitment.as_ref().map(|c| c.value) + value_commitment.as_ref().map(|c| c.value), )?; // Compute the note value in the exponent @@ -95,7 +85,7 @@ fn expose_value_commitment( cs.namespace(|| "compute the value in the exponent"), FixedGenerators::ValueCommitmentValue, &value_bits, - params + params, )?; // Booleanize the randomness. This does not ensure @@ -103,7 +93,7 @@ fn expose_value_commitment( // it doesn't matter for security. let rcv = boolean::field_into_boolean_vec_le( cs.namespace(|| "rcv"), - value_commitment.as_ref().map(|c| c.randomness) + value_commitment.as_ref().map(|c| c.randomness), )?; // Compute the randomness in the exponent @@ -111,15 +101,11 @@ fn expose_value_commitment( cs.namespace(|| "computation of rcv"), FixedGenerators::ValueCommitmentRandomness, &rcv, - params + params, )?; // Compute the Pedersen commitment to the value - let cv = value.add( - cs.namespace(|| "computation of cv"), - &rcv, - params - )?; + let cv = value.add(cs.namespace(|| "computation of cv"), &rcv, params)?; // Expose the commitment as an input to the circuit cv.inputize(cs.namespace(|| "commitment point"))?; @@ -128,43 +114,32 @@ fn expose_value_commitment( } impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { - fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { // Prover witnesses ak (ensures that it's on the curve) let ak = ecc::EdwardsPoint::witness( cs.namespace(|| "ak"), self.proof_generation_key.as_ref().map(|k| k.ak.clone()), - self.params + self.params, )?; // There are no sensible attacks on small order points // of ak (that we're aware of!) but it's a cheap check, // so we do it. - ak.assert_not_small_order( - cs.namespace(|| "ak not small order"), - self.params - )?; + ak.assert_not_small_order(cs.namespace(|| "ak not small order"), self.params)?; // Rerandomize ak and expose it as an input to the circuit { - let ar = boolean::field_into_boolean_vec_le( - cs.namespace(|| "ar"), - self.ar - )?; + let ar = boolean::field_into_boolean_vec_le(cs.namespace(|| "ar"), self.ar)?; // Compute the randomness in the exponent let ar = ecc::fixed_base_multiplication( cs.namespace(|| "computation of randomization for the signing key"), FixedGenerators::SpendingKeyGenerator, &ar, - self.params + self.params, )?; - let rk = ak.add( - cs.namespace(|| "computation of rk"), - &ar, - self.params - )?; + let rk = ak.add(cs.namespace(|| "computation of rk"), &ar, self.params)?; rk.inputize(cs.namespace(|| "rk"))?; } @@ -175,7 +150,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // Witness nsk as bits let nsk = boolean::field_into_boolean_vec_le( cs.namespace(|| "nsk"), - self.proof_generation_key.as_ref().map(|k| k.nsk.clone()) + self.proof_generation_key.as_ref().map(|k| k.nsk.clone()), )?; // NB: We don't ensure that the bit representation of nsk @@ -188,7 +163,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "computation of nk"), FixedGenerators::ProofGenerationKey, &nsk, - self.params + self.params, )?; } @@ -196,9 +171,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let mut ivk_preimage = vec![]; // Place ak in the preimage for CRH^ivk - ivk_preimage.extend( - ak.repr(cs.namespace(|| "representation of ak"))? - ); + ivk_preimage.extend(ak.repr(cs.namespace(|| "representation of ak"))?); // This is the nullifier preimage for PRF^nf let mut nf_preimage = vec![]; @@ -206,9 +179,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // Extend ivk and nf preimages with the representation of // nk. { - let repr_nk = nk.repr( - cs.namespace(|| "representation of nk") - )?; + let repr_nk = nk.repr(cs.namespace(|| "representation of nk"))?; ivk_preimage.extend(repr_nk.iter().cloned()); nf_preimage.extend(repr_nk); @@ -221,7 +192,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let mut ivk = blake2s::blake2s( cs.namespace(|| "computation of ivk"), &ivk_preimage, - constants::CRH_IVK_PERSONALIZATION + constants::CRH_IVK_PERSONALIZATION, )?; // drop_5 to ensure it's in the field @@ -239,7 +210,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { ecc::EdwardsPoint::witness( cs.namespace(|| "witness g_d"), self.payment_address.as_ref().and_then(|a| a.g_d(params)), - self.params + self.params, )? }; @@ -247,17 +218,10 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // is already done in the Output circuit, and this proof ensures // g_d is bound to a product of that check, but for defense in // depth let's check it anyway. It's cheap. - g_d.assert_not_small_order( - cs.namespace(|| "g_d not small order"), - self.params - )?; + g_d.assert_not_small_order(cs.namespace(|| "g_d not small order"), self.params)?; // Compute pk_d = g_d^ivk - let pk_d = g_d.mul( - cs.namespace(|| "compute pk_d"), - &ivk, - self.params - )?; + let pk_d = g_d.mul(cs.namespace(|| "compute pk_d"), &ivk, self.params)?; // Compute note contents: // value (in big endian) followed by g_d and pk_d @@ -271,18 +235,14 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let value_bits = expose_value_commitment( cs.namespace(|| "value commitment"), self.value_commitment, - self.params + self.params, )?; // Compute the note's value as a linear combination // of the bits. let mut coeff = E::Fr::one(); for bit in &value_bits { - value_num = value_num.add_bool_with_coeff( - CS::one(), - bit, - coeff - ); + value_num = value_num.add_bool_with_coeff(CS::one(), bit, coeff); coeff.double(); } @@ -291,14 +251,10 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { } // Place g_d in the note - note_contents.extend( - g_d.repr(cs.namespace(|| "representation of g_d"))? - ); + note_contents.extend(g_d.repr(cs.namespace(|| "representation of g_d"))?); // Place pk_d in the note - note_contents.extend( - pk_d.repr(cs.namespace(|| "representation of pk_d"))? - ); + note_contents.extend(pk_d.repr(cs.namespace(|| "representation of pk_d"))?); assert_eq!( note_contents.len(), @@ -312,14 +268,14 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "note content hash"), pedersen_hash::Personalization::NoteCommitment, ¬e_contents, - self.params + self.params, )?; { // Booleanize the randomness for the note commitment let rcm = boolean::field_into_boolean_vec_le( cs.namespace(|| "rcm"), - self.commitment_randomness + self.commitment_randomness, )?; // Compute the note commitment randomness in the exponent @@ -327,7 +283,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "computation of commitment randomness"), FixedGenerators::NoteCommitmentRandomness, &rcm, - self.params + self.params, )?; // Randomize the note commitment. Pedersen hashes are not @@ -335,7 +291,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cm = cm.add( cs.namespace(|| "randomization of note commitment"), &rcm, - self.params + self.params, )?; } @@ -356,7 +312,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // depth of the tree. let cur_is_right = boolean::Boolean::from(boolean::AllocatedBit::alloc( cs.namespace(|| "position bit"), - e.map(|e| e.1) + e.map(|e| e.1), )?); // Push this boolean for nullifier computation later @@ -364,19 +320,15 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { // Witness the authentication path element adjacent // at this depth. - let path_element = num::AllocatedNum::alloc( - cs.namespace(|| "path element"), - || { - Ok(e.get()?.0) - } - )?; + let path_element = + num::AllocatedNum::alloc(cs.namespace(|| "path element"), || Ok(e.get()?.0))?; // Swap the two if the current subtree is on the right let (xl, xr) = num::AllocatedNum::conditionally_reverse( cs.namespace(|| "conditional reversal of preimage"), &cur, &path_element, - &cur_is_right + &cur_is_right, )?; // We don't need to be strict, because the function is @@ -392,20 +344,19 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "computation of pedersen hash"), pedersen_hash::Personalization::MerkleTree(i), &preimage, - self.params - )?.get_x().clone(); // Injective encoding + self.params, + )? + .get_x() + .clone(); // Injective encoding } { let real_anchor_value = self.anchor; // Allocate the "real" anchor that will be exposed. - let rt = num::AllocatedNum::alloc( - cs.namespace(|| "conditional anchor"), - || { - Ok(*real_anchor_value.get()?) - } - )?; + let rt = num::AllocatedNum::alloc(cs.namespace(|| "conditional anchor"), || { + Ok(*real_anchor_value.get()?) + })?; // (cur - rt) * value = 0 // if value is zero, cur and rt can be different @@ -414,7 +365,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { || "conditionally enforce correct root", |lc| lc + cur.get_variable() - rt.get_variable(), |lc| lc + &value_num.lc(E::Fr::one()), - |lc| lc + |lc| lc, ); // Expose the anchor @@ -430,29 +381,27 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { cs.namespace(|| "g^position"), FixedGenerators::NullifierPosition, &position_bits, - self.params + self.params, )?; // Add the position to the commitment rho = rho.add( cs.namespace(|| "faerie gold prevention"), &position, - self.params + self.params, )?; } - + // Let's compute nf = BLAKE2s(nk || rho) - nf_preimage.extend( - rho.repr(cs.namespace(|| "representation of rho"))? - ); + nf_preimage.extend(rho.repr(cs.namespace(|| "representation of rho"))?); assert_eq!(nf_preimage.len(), 512); - + // Compute nf let nf = blake2s::blake2s( cs.namespace(|| "nf computation"), &nf_preimage, - constants::PRF_NF_PERSONALIZATION + constants::PRF_NF_PERSONALIZATION, )?; multipack::pack_into_inputs(cs.namespace(|| "pack nullifier"), &nf) @@ -460,8 +409,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { } impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { - fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { // Let's start to construct our note, which contains // value (big endian) let mut note_contents = vec![]; @@ -471,7 +419,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { note_contents.extend(expose_value_commitment( cs.namespace(|| "value commitment"), self.value_commitment, - self.params + self.params, )?); // Let's deal with g_d @@ -483,7 +431,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { let g_d = ecc::EdwardsPoint::witness( cs.namespace(|| "witness g_d"), self.payment_address.as_ref().and_then(|a| a.g_d(params)), - self.params + self.params, )?; // g_d is ensured to be large order. The relationship @@ -495,29 +443,17 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { // // Further, if it were small order, epk would be // small order too! - g_d.assert_not_small_order( - cs.namespace(|| "g_d not small order"), - self.params - )?; + g_d.assert_not_small_order(cs.namespace(|| "g_d not small order"), self.params)?; // Extend our note contents with the representation of // g_d. - note_contents.extend( - g_d.repr(cs.namespace(|| "representation of g_d"))? - ); + note_contents.extend(g_d.repr(cs.namespace(|| "representation of g_d"))?); // Booleanize our ephemeral secret key - let esk = boolean::field_into_boolean_vec_le( - cs.namespace(|| "esk"), - self.esk - )?; + let esk = boolean::field_into_boolean_vec_le(cs.namespace(|| "esk"), self.esk)?; // Create the ephemeral public key from g_d. - let epk = g_d.mul( - cs.namespace(|| "epk computation"), - &esk, - self.params - )?; + let epk = g_d.mul(cs.namespace(|| "epk computation"), &esk, self.params)?; // Expose epk publicly. epk.inputize(cs.namespace(|| "epk"))?; @@ -534,13 +470,13 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { // endian bits (to match the representation) let y_contents = boolean::field_into_boolean_vec_le( cs.namespace(|| "pk_d bits of y"), - pk_d.map(|e| e.1) + pk_d.map(|e| e.1), )?; // Witness the sign bit let sign_bit = boolean::Boolean::from(boolean::AllocatedBit::alloc( cs.namespace(|| "pk_d bit of x"), - pk_d.map(|e| e.0.into_repr().is_odd()) + pk_d.map(|e| e.0.into_repr().is_odd()), )?); // Extend the note with pk_d representation @@ -560,14 +496,14 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { cs.namespace(|| "note content hash"), pedersen_hash::Personalization::NoteCommitment, ¬e_contents, - self.params + self.params, )?; { // Booleanize the randomness let rcm = boolean::field_into_boolean_vec_le( cs.namespace(|| "rcm"), - self.commitment_randomness + self.commitment_randomness, )?; // Compute the note commitment randomness in the exponent @@ -575,14 +511,14 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { cs.namespace(|| "computation of commitment randomness"), FixedGenerators::NoteCommitmentRandomness, &rcm, - self.params + self.params, )?; // Randomize our note commitment cm = cm.add( cs.namespace(|| "randomization of note commitment"), &rcm, - self.params + self.params, )?; } @@ -604,7 +540,7 @@ fn test_input_circuit_with_bls12_381() { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use zcash_primitives::{ - jubjub::{JubjubBls12, fs, edwards}, + jubjub::{edwards, fs, JubjubBls12}, pedersen_hash, primitives::{Diversifier, Note, ProofGenerationKey}, }; @@ -628,7 +564,7 @@ fn test_input_circuit_with_bls12_381() { let proof_generation_key = ProofGenerationKey { ak: ak.clone(), - nsk: nsk.clone() + nsk: nsk.clone(), }; let viewing_key = proof_generation_key.into_viewing_key(params); @@ -642,11 +578,7 @@ fn test_input_circuit_with_bls12_381() { Diversifier(d) }; - if let Some(p) = viewing_key.into_payment_address( - diversifier, - params - ) - { + if let Some(p) = viewing_key.into_payment_address(diversifier, params) { payment_address = p; break; } @@ -664,15 +596,14 @@ fn test_input_circuit_with_bls12_381() { value: value_commitment.value, g_d: g_d.clone(), pk_d: payment_address.pk_d.clone(), - r: commitment_randomness.clone() + r: commitment_randomness.clone(), }; let mut position = 0u64; let cm: Fr = note.cm(params); let mut cur = cm.clone(); - for (i, val) in auth_path.clone().into_iter().enumerate() - { + for (i, val) in auth_path.clone().into_iter().enumerate() { let (uncle, b) = val.unwrap(); let mut lhs = cur; @@ -691,10 +622,12 @@ fn test_input_circuit_with_bls12_381() { cur = pedersen_hash::pedersen_hash::( pedersen_hash::Personalization::MerkleTree(i), lhs.into_iter() - .take(Fr::NUM_BITS as usize) - .chain(rhs.into_iter().take(Fr::NUM_BITS as usize)), - params - ).into_xy().0; + .take(Fr::NUM_BITS as usize) + .chain(rhs.into_iter().take(Fr::NUM_BITS as usize)), + params, + ) + .into_xy() + .0; if b { position |= 1 << i; @@ -716,14 +649,17 @@ fn test_input_circuit_with_bls12_381() { commitment_randomness: Some(commitment_randomness), ar: Some(ar), auth_path: auth_path.clone(), - anchor: Some(cur) + anchor: Some(cur), }; instance.synthesize(&mut cs).unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 98777); - assert_eq!(cs.hash(), "d37c738e83df5d9b0bb6495ac96abf21bcb2697477e2c15c2c7916ff7a3b6a89"); + assert_eq!( + cs.hash(), + "d37c738e83df5d9b0bb6495ac96abf21bcb2697477e2c15c2c7916ff7a3b6a89" + ); assert_eq!(cs.get("randomization of note commitment/x3/num"), cm); @@ -731,8 +667,14 @@ fn test_input_circuit_with_bls12_381() { assert_eq!(cs.get_input(0, "ONE"), Fr::one()); assert_eq!(cs.get_input(1, "rk/x/input variable"), rk.0); assert_eq!(cs.get_input(2, "rk/y/input variable"), rk.1); - assert_eq!(cs.get_input(3, "value commitment/commitment point/x/input variable"), expected_value_cm.0); - assert_eq!(cs.get_input(4, "value commitment/commitment point/y/input variable"), expected_value_cm.1); + assert_eq!( + cs.get_input(3, "value commitment/commitment point/x/input variable"), + expected_value_cm.0 + ); + assert_eq!( + cs.get_input(4, "value commitment/commitment point/y/input variable"), + expected_value_cm.1 + ); assert_eq!(cs.get_input(5, "anchor/input variable"), cur); assert_eq!(cs.get_input(6, "pack nullifier/input 0"), expected_nf[0]); assert_eq!(cs.get_input(7, "pack nullifier/input 1"), expected_nf[1]); @@ -748,7 +690,7 @@ fn test_output_circuit_with_bls12_381() { use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use zcash_primitives::{ - jubjub::{JubjubBls12, fs, edwards}, + jubjub::{edwards, fs, JubjubBls12}, primitives::{Diversifier, ProofGenerationKey}, }; @@ -769,7 +711,7 @@ fn test_output_circuit_with_bls12_381() { let proof_generation_key = ProofGenerationKey { ak: ak.clone(), - nsk: nsk.clone() + nsk: nsk.clone(), }; let viewing_key = proof_generation_key.into_viewing_key(params); @@ -783,11 +725,7 @@ fn test_output_circuit_with_bls12_381() { Diversifier(d) }; - if let Some(p) = viewing_key.into_payment_address( - diversifier, - params - ) - { + if let Some(p) = viewing_key.into_payment_address(diversifier, params) { payment_address = p; break; } @@ -804,30 +742,41 @@ fn test_output_circuit_with_bls12_381() { value_commitment: Some(value_commitment.clone()), payment_address: Some(payment_address.clone()), commitment_randomness: Some(commitment_randomness), - esk: Some(esk.clone()) + esk: Some(esk.clone()), }; instance.synthesize(&mut cs).unwrap(); assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 7827); - assert_eq!(cs.hash(), "c26d5cdfe6ccd65c03390902c02e11393ea6bb96aae32a7f2ecb12eb9103faee"); + assert_eq!( + cs.hash(), + "c26d5cdfe6ccd65c03390902c02e11393ea6bb96aae32a7f2ecb12eb9103faee" + ); - let expected_cm = payment_address.create_note( - value_commitment.value, - commitment_randomness, - params - ).expect("should be valid").cm(params); + let expected_cm = payment_address + .create_note(value_commitment.value, commitment_randomness, params) + .expect("should be valid") + .cm(params); let expected_value_cm = value_commitment.cm(params).into_xy(); - let expected_epk = payment_address.g_d(params).expect("should be valid").mul(esk, params); + let expected_epk = payment_address + .g_d(params) + .expect("should be valid") + .mul(esk, params); let expected_epk_xy = expected_epk.into_xy(); assert_eq!(cs.num_inputs(), 6); assert_eq!(cs.get_input(0, "ONE"), Fr::one()); - assert_eq!(cs.get_input(1, "value commitment/commitment point/x/input variable"), expected_value_cm.0); - assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm.1); + assert_eq!( + cs.get_input(1, "value commitment/commitment point/x/input variable"), + expected_value_cm.0 + ); + assert_eq!( + cs.get_input(2, "value commitment/commitment point/y/input variable"), + expected_value_cm.1 + ); assert_eq!(cs.get_input(3, "epk/x/input variable"), expected_epk_xy.0); assert_eq!(cs.get_input(4, "epk/y/input variable"), expected_epk_xy.1); assert_eq!(cs.get_input(5, "commitment/input variable"), expected_cm); diff --git a/zcash_proofs/src/circuit/sprout/commitment.rs b/zcash_proofs/src/circuit/sprout/commitment.rs index ba889a3..fba1217 100644 --- a/zcash_proofs/src/circuit/sprout/commitment.rs +++ b/zcash_proofs/src/circuit/sprout/commitment.rs @@ -1,20 +1,18 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::Boolean; +use bellman::gadgets::sha256::sha256; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::sha256::{ - sha256 -}; -use bellman::gadgets::boolean::{ - Boolean -}; +use pairing::Engine; pub fn note_comm( cs: CS, a_pk: &[Boolean], value: &[Boolean], rho: &[Boolean], - r: &[Boolean] + r: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(a_pk.len(), 256); assert_eq!(value.len(), 64); @@ -35,8 +33,5 @@ pub fn note_comm( image.extend(rho.iter().cloned()); image.extend(r.iter().cloned()); - sha256( - cs, - &image - ) + sha256(cs, &image) } diff --git a/zcash_proofs/src/circuit/sprout/input.rs b/zcash_proofs/src/circuit/sprout/input.rs index a84e3a6..ad6091f 100644 --- a/zcash_proofs/src/circuit/sprout/input.rs +++ b/zcash_proofs/src/circuit/sprout/input.rs @@ -1,16 +1,11 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::{AllocatedBit, Boolean}; +use bellman::gadgets::sha256::sha256_block_no_padding; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::sha256::{ - sha256_block_no_padding -}; -use bellman::gadgets::boolean::{ - AllocatedBit, - Boolean -}; +use pairing::Engine; -use super::*; -use super::prfs::*; use super::commitment::note_comm; +use super::prfs::*; +use super::*; pub struct InputNote { pub nf: Vec, @@ -27,49 +22,33 @@ impl InputNote { h_sig: &[Boolean], nonce: bool, auth_path: [Option<([u8; 32], bool)>; TREE_DEPTH], - rt: &[Boolean] + rt: &[Boolean], ) -> Result - where E: Engine, CS: ConstraintSystem + where + E: Engine, + CS: ConstraintSystem, { let a_sk = witness_u252( cs.namespace(|| "a_sk"), - a_sk.as_ref().map(|a_sk| &a_sk.0[..]) + a_sk.as_ref().map(|a_sk| &a_sk.0[..]), )?; - let rho = witness_u256( - cs.namespace(|| "rho"), - rho.as_ref().map(|rho| &rho.0[..]) - )?; + let rho = witness_u256(cs.namespace(|| "rho"), rho.as_ref().map(|rho| &rho.0[..]))?; - let r = witness_u256( - cs.namespace(|| "r"), - r.as_ref().map(|r| &r.0[..]) - )?; + let r = witness_u256(cs.namespace(|| "r"), r.as_ref().map(|r| &r.0[..]))?; - let a_pk = prf_a_pk( - cs.namespace(|| "a_pk computation"), - &a_sk - )?; + let a_pk = prf_a_pk(cs.namespace(|| "a_pk computation"), &a_sk)?; - let nf = prf_nf( - cs.namespace(|| "nf computation"), - &a_sk, - &rho - )?; + let nf = prf_nf(cs.namespace(|| "nf computation"), &a_sk, &rho)?; - let mac = prf_pk( - cs.namespace(|| "mac computation"), - &a_sk, - h_sig, - nonce - )?; + let mac = prf_pk(cs.namespace(|| "mac computation"), &a_sk, h_sig, nonce)?; let cm = note_comm( cs.namespace(|| "cm computation"), &a_pk, &value.bits_le(), &rho, - &r + &r, )?; // Witness into the merkle tree @@ -80,13 +59,13 @@ impl InputNote { let cur_is_right = AllocatedBit::alloc( cs.namespace(|| "cur is right"), - layer.as_ref().map(|&(_, p)| p) + layer.as_ref().map(|&(_, p)| p), )?; let lhs = cur; let rhs = witness_u256( cs.namespace(|| "sibling"), - layer.as_ref().map(|&(ref sibling, _)| &sibling[..]) + layer.as_ref().map(|&(ref sibling, _)| &sibling[..]), )?; // Conditionally swap if cur is right @@ -94,19 +73,16 @@ impl InputNote { cs.namespace(|| "conditional swap"), &lhs[..], &rhs[..], - &cur_is_right + &cur_is_right, )?; - cur = sha256_block_no_padding( - cs.namespace(|| "hash of this layer"), - &preimage - )?; + cur = sha256_block_no_padding(cs.namespace(|| "hash of this layer"), &preimage)?; } // enforce must be true if the value is nonzero let enforce = AllocatedBit::alloc( cs.namespace(|| "enforce"), - value.get_value().map(|n| n != 0) + value.get_value().map(|n| n != 0), )?; // value * (1 - enforce) = 0 @@ -116,7 +92,7 @@ impl InputNote { || "enforce validity", |_| value.lc(), |lc| lc + CS::one() - enforce.get_variable(), - |lc| lc + |lc| lc, ); assert_eq!(cur.len(), rt.len()); @@ -132,14 +108,11 @@ impl InputNote { || format!("conditionally enforce correct root for bit {}", i), |_| cur.lc(CS::one(), E::Fr::one()) - &rt.lc(CS::one(), E::Fr::one()), |lc| lc + enforce.get_variable(), - |lc| lc + |lc| lc, ); } - Ok(InputNote { - mac: mac, - nf: nf - }) + Ok(InputNote { mac: mac, nf: nf }) } } @@ -149,9 +122,11 @@ pub fn conditionally_swap_u256( mut cs: CS, lhs: &[Boolean], rhs: &[Boolean], - condition: &AllocatedBit + condition: &AllocatedBit, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(lhs.len(), 256); assert_eq!(rhs.len(), 256); @@ -164,13 +139,9 @@ pub fn conditionally_swap_u256( let x = Boolean::from(AllocatedBit::alloc( cs.namespace(|| "x"), - condition.get_value().and_then(|v| { - if v { - rhs.get_value() - } else { - lhs.get_value() - } - }) + condition + .get_value() + .and_then(|v| if v { rhs.get_value() } else { lhs.get_value() }), )?); // x = (1-condition)lhs + (condition)rhs @@ -184,33 +155,25 @@ pub fn conditionally_swap_u256( // x = rhs cs.enforce( || "conditional swap for x", - |lc| lc + &rhs.lc(CS::one(), E::Fr::one()) - - &lhs.lc(CS::one(), E::Fr::one()), + |lc| lc + &rhs.lc(CS::one(), E::Fr::one()) - &lhs.lc(CS::one(), E::Fr::one()), |lc| lc + condition.get_variable(), - |lc| lc + &x.lc(CS::one(), E::Fr::one()) - - &lhs.lc(CS::one(), E::Fr::one()) + |lc| lc + &x.lc(CS::one(), E::Fr::one()) - &lhs.lc(CS::one(), E::Fr::one()), ); let y = Boolean::from(AllocatedBit::alloc( cs.namespace(|| "y"), - condition.get_value().and_then(|v| { - if v { - lhs.get_value() - } else { - rhs.get_value() - } - }) + condition + .get_value() + .and_then(|v| if v { lhs.get_value() } else { rhs.get_value() }), )?); // y = (1-condition)rhs + (condition)lhs // y - rhs = condition (lhs - rhs) cs.enforce( || "conditional swap for y", - |lc| lc + &lhs.lc(CS::one(), E::Fr::one()) - - &rhs.lc(CS::one(), E::Fr::one()), + |lc| lc + &lhs.lc(CS::one(), E::Fr::one()) - &rhs.lc(CS::one(), E::Fr::one()), |lc| lc + condition.get_variable(), - |lc| lc + &y.lc(CS::one(), E::Fr::one()) - - &rhs.lc(CS::one(), E::Fr::one()) + |lc| lc + &y.lc(CS::one(), E::Fr::one()) - &rhs.lc(CS::one(), E::Fr::one()), ); new_lhs.push(x); diff --git a/zcash_proofs/src/circuit/sprout/mod.rs b/zcash_proofs/src/circuit/sprout/mod.rs index c28b8d7..358e1bb 100644 --- a/zcash_proofs/src/circuit/sprout/mod.rs +++ b/zcash_proofs/src/circuit/sprout/mod.rs @@ -1,16 +1,13 @@ +use bellman::gadgets::boolean::{AllocatedBit, Boolean}; +use bellman::gadgets::multipack::pack_into_inputs; +use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError}; use ff::Field; use pairing::Engine; -use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination}; -use bellman::gadgets::boolean::{ - AllocatedBit, - Boolean -}; -use bellman::gadgets::multipack::pack_into_inputs; -mod prfs; mod commitment; mod input; mod output; +mod prfs; use self::input::*; use self::output::*; @@ -37,39 +34,29 @@ pub struct JSInput { pub a_sk: Option, pub rho: Option, pub r: Option, - pub auth_path: [Option<([u8; 32], bool)>; TREE_DEPTH] + pub auth_path: [Option<([u8; 32], bool)>; TREE_DEPTH], } pub struct JSOutput { pub value: Option, pub a_pk: Option, - pub r: Option + pub r: Option, } impl Circuit for JoinSplit { - fn synthesize>( - self, - cs: &mut CS - ) -> Result<(), SynthesisError> - { + fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { assert_eq!(self.inputs.len(), 2); assert_eq!(self.outputs.len(), 2); // vpub_old is the value entering the // JoinSplit from the "outside" value // pool - let vpub_old = NoteValue::new( - cs.namespace(|| "vpub_old"), - self.vpub_old - )?; + let vpub_old = NoteValue::new(cs.namespace(|| "vpub_old"), self.vpub_old)?; // vpub_new is the value leaving the // JoinSplit into the "outside" value // pool - let vpub_new = NoteValue::new( - cs.namespace(|| "vpub_new"), - self.vpub_new - )?; + let vpub_new = NoteValue::new(cs.namespace(|| "vpub_new"), self.vpub_new)?; // The left hand side of the balance equation // vpub_old + inputs[0].value + inputs[1].value @@ -80,22 +67,17 @@ impl Circuit for JoinSplit { let mut rhs = vpub_new.lc(); // Witness rt (merkle tree root) - let rt = witness_u256( - cs.namespace(|| "rt"), - self.rt.as_ref().map(|v| &v[..]) - ).unwrap(); + let rt = witness_u256(cs.namespace(|| "rt"), self.rt.as_ref().map(|v| &v[..])).unwrap(); // Witness h_sig let h_sig = witness_u256( cs.namespace(|| "h_sig"), - self.h_sig.as_ref().map(|v| &v[..]) - ).unwrap(); + self.h_sig.as_ref().map(|v| &v[..]), + ) + .unwrap(); // Witness phi - let phi = witness_u252( - cs.namespace(|| "phi"), - self.phi.as_ref().map(|v| &v[..]) - ).unwrap(); + let phi = witness_u252(cs.namespace(|| "phi"), self.phi.as_ref().map(|v| &v[..])).unwrap(); let mut input_notes = vec![]; let mut lhs_total = self.vpub_old; @@ -110,17 +92,14 @@ impl Circuit for JoinSplit { } // Allocate the value of the note - let value = NoteValue::new( - cs.namespace(|| "value"), - input.value - )?; + let value = NoteValue::new(cs.namespace(|| "value"), input.value)?; // Compute the nonce (for PRF inputs) which is false // for the first input, and true for the second input. let nonce = match i { 0 => false, 1 => true, - _ => unreachable!() + _ => unreachable!(), }; // Perform input note computations @@ -133,7 +112,7 @@ impl Circuit for JoinSplit { &h_sig, nonce, input.auth_path, - &rt + &rt, )?); // Add the note value to the left hand side of @@ -148,10 +127,8 @@ impl Circuit for JoinSplit { { // Expected sum of the left hand side of the balance // equation, expressed as a 64-bit unsigned integer - let lhs_total = NoteValue::new( - cs.namespace(|| "total value of left hand side"), - lhs_total - )?; + let lhs_total = + NoteValue::new(cs.namespace(|| "total value of left hand side"), lhs_total)?; // Enforce that the left hand side can be expressed as a 64-bit // integer @@ -159,7 +136,7 @@ impl Circuit for JoinSplit { || "left hand side can be expressed as a 64-bit unsigned integer", |_| lhs.clone(), |lc| lc + CS::one(), - |_| lhs_total.lc() + |_| lhs_total.lc(), ); } @@ -169,17 +146,14 @@ impl Circuit for JoinSplit { for (i, output) in self.outputs.into_iter().enumerate() { let cs = &mut cs.namespace(|| format!("output {}", i)); - let value = NoteValue::new( - cs.namespace(|| "value"), - output.value - )?; + let value = NoteValue::new(cs.namespace(|| "value"), output.value)?; // Compute the nonce (for PRF inputs) which is false // for the first output, and true for the second output. let nonce = match i { 0 => false, 1 => true, - _ => unreachable!() + _ => unreachable!(), }; // Perform output note computations @@ -190,7 +164,7 @@ impl Circuit for JoinSplit { output.r, &phi, &h_sig, - nonce + nonce, )?); // Add the note value to the right hand side of @@ -203,7 +177,7 @@ impl Circuit for JoinSplit { || "balance equation", |_| lhs.clone(), |lc| lc + CS::one(), - |_| rhs + |_| rhs, ); let mut public_inputs = vec![]; @@ -229,15 +203,14 @@ impl Circuit for JoinSplit { pub struct NoteValue { value: Option, // Least significant digit first - bits: Vec + bits: Vec, } impl NoteValue { - fn new( - mut cs: CS, - value: Option - ) -> Result - where E: Engine, CS: ConstraintSystem, + fn new(mut cs: CS, value: Option) -> Result + where + E: Engine, + CS: ConstraintSystem, { let mut values; match value { @@ -247,7 +220,7 @@ impl NoteValue { values.push(Some(val & 1 == 1)); val >>= 1; } - }, + } None => { values = vec![None; 64]; } @@ -255,28 +228,27 @@ impl NoteValue { let mut bits = vec![]; for (i, value) in values.into_iter().enumerate() { - bits.push( - AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - value - )? - ); + bits.push(AllocatedBit::alloc( + cs.namespace(|| format!("bit {}", i)), + value, + )?); } Ok(NoteValue { value: value, - bits: bits + bits: bits, }) } /// Encodes the bits of the value into little-endian /// byte order. fn bits_le(&self) -> Vec { - self.bits.chunks(8) - .flat_map(|v| v.iter().rev()) - .cloned() - .map(|e| Boolean::from(e)) - .collect() + self.bits + .chunks(8) + .flat_map(|v| v.iter().rev()) + .cloned() + .map(|e| Boolean::from(e)) + .collect() } /// Computes this value as a linear combination of @@ -304,15 +276,18 @@ fn witness_bits( mut cs: CS, value: Option<&[u8]>, num_bits: usize, - skip_bits: usize + skip_bits: usize, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +where + E: Engine, + CS: ConstraintSystem, { let bit_values = if let Some(value) = value { let mut tmp = vec![]; - for b in value.iter() - .flat_map(|&m| (0..8).rev().map(move |i| m >> i & 1 == 1)) - .skip(skip_bits) + for b in value + .iter() + .flat_map(|&m| (0..8).rev().map(move |i| m >> i & 1 == 1)) + .skip(skip_bits) { tmp.push(Some(b)); } @@ -327,37 +302,35 @@ fn witness_bits( for (i, value) in bit_values.into_iter().enumerate() { bits.push(Boolean::from(AllocatedBit::alloc( cs.namespace(|| format!("bit {}", i)), - value + value, )?)); } Ok(bits) } -fn witness_u256( - cs: CS, - value: Option<&[u8]>, -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +fn witness_u256(cs: CS, value: Option<&[u8]>) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { witness_bits(cs, value, 256, 0) } -fn witness_u252( - cs: CS, - value: Option<&[u8]>, -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem, +fn witness_u252(cs: CS, value: Option<&[u8]>) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { witness_bits(cs, value, 252, 4) } #[test] fn test_sprout_constraints() { - use pairing::bls12_381::{Bls12}; use bellman::gadgets::test::*; + use pairing::bls12_381::Bls12; - use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; + use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; let test_vector = include_bytes!("test_vectors.dat"); let mut test_vector = &test_vector[..]; @@ -393,9 +366,7 @@ fn test_sprout_constraints() { } let mut position = test_vector.read_u64::().unwrap(); for i in 0..TREE_DEPTH { - auth_path[i].as_mut().map(|p| { - p.1 = (position & 1) == 1 - }); + auth_path[i].as_mut().map(|p| p.1 = (position & 1) == 1); position >>= 1; } @@ -407,15 +378,13 @@ fn test_sprout_constraints() { let r = Some(CommitmentRandomness(get_u256(&mut test_vector))); let a_sk = Some(SpendingKey(get_u256(&mut test_vector))); - inputs.push( - JSInput { - value: value, - a_sk: a_sk, - rho: rho, - r: r, - auth_path: auth_path - } - ); + inputs.push(JSInput { + value: value, + a_sk: a_sk, + rho: rho, + r: r, + auth_path: auth_path, + }); } let mut outputs = vec![]; @@ -426,13 +395,11 @@ fn test_sprout_constraints() { get_u256(&mut test_vector); let r = Some(CommitmentRandomness(get_u256(&mut test_vector))); - outputs.push( - JSOutput { - value: value, - a_pk: a_pk, - r: r - } - ); + outputs.push(JSOutput { + value: value, + a_pk: a_pk, + r: r, + }); } let vpub_old = Some(test_vector.read_u64::().unwrap()); @@ -454,7 +421,7 @@ fn test_sprout_constraints() { phi: phi, inputs: inputs, outputs: outputs, - rt: rt + rt: rt, }; js.synthesize(&mut cs).unwrap(); @@ -465,7 +432,10 @@ fn test_sprout_constraints() { assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 1989085); assert_eq!(cs.num_inputs(), 10); - assert_eq!(cs.hash(), "1a228d3c6377130d1778c7885811dc8b8864049cb5af8aff7e6cd46c5bc4b84c"); + assert_eq!( + cs.hash(), + "1a228d3c6377130d1778c7885811dc8b8864049cb5af8aff7e6cd46c5bc4b84c" + ); let mut expected_inputs = vec![]; expected_inputs.extend(rt.unwrap().to_vec()); @@ -476,8 +446,12 @@ fn test_sprout_constraints() { expected_inputs.extend(mac2.to_vec()); expected_inputs.extend(cm1.to_vec()); expected_inputs.extend(cm2.to_vec()); - expected_inputs.write_u64::(vpub_old.unwrap()).unwrap(); - expected_inputs.write_u64::(vpub_new.unwrap()).unwrap(); + expected_inputs + .write_u64::(vpub_old.unwrap()) + .unwrap(); + expected_inputs + .write_u64::(vpub_new.unwrap()) + .unwrap(); use bellman::gadgets::multipack; diff --git a/zcash_proofs/src/circuit/sprout/output.rs b/zcash_proofs/src/circuit/sprout/output.rs index f2e504a..a9a1e48 100644 --- a/zcash_proofs/src/circuit/sprout/output.rs +++ b/zcash_proofs/src/circuit/sprout/output.rs @@ -1,13 +1,13 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::Boolean; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::boolean::{Boolean}; +use pairing::Engine; -use super::*; -use super::prfs::*; use super::commitment::note_comm; +use super::prfs::*; +use super::*; pub struct OutputNote { - pub cm: Vec + pub cm: Vec, } impl OutputNote { @@ -18,37 +18,29 @@ impl OutputNote { r: Option, phi: &[Boolean], h_sig: &[Boolean], - nonce: bool + nonce: bool, ) -> Result - where E: Engine, CS: ConstraintSystem, + where + E: Engine, + CS: ConstraintSystem, { - let rho = prf_rho( - cs.namespace(|| "rho"), - phi, - h_sig, - nonce - )?; + let rho = prf_rho(cs.namespace(|| "rho"), phi, h_sig, nonce)?; let a_pk = witness_u256( cs.namespace(|| "a_pk"), - a_pk.as_ref().map(|a_pk| &a_pk.0[..]) + a_pk.as_ref().map(|a_pk| &a_pk.0[..]), )?; - let r = witness_u256( - cs.namespace(|| "r"), - r.as_ref().map(|r| &r.0[..]) - )?; + let r = witness_u256(cs.namespace(|| "r"), r.as_ref().map(|r| &r.0[..]))?; let cm = note_comm( cs.namespace(|| "cm computation"), &a_pk, &value.bits_le(), &rho, - &r + &r, )?; - Ok(OutputNote { - cm: cm - }) + Ok(OutputNote { cm: cm }) } } diff --git a/zcash_proofs/src/circuit/sprout/prfs.rs b/zcash_proofs/src/circuit/sprout/prfs.rs index 0b3e42c..ea87b08 100644 --- a/zcash_proofs/src/circuit/sprout/prfs.rs +++ b/zcash_proofs/src/circuit/sprout/prfs.rs @@ -1,11 +1,7 @@ -use pairing::{Engine}; +use bellman::gadgets::boolean::Boolean; +use bellman::gadgets::sha256::sha256_block_no_padding; use bellman::{ConstraintSystem, SynthesisError}; -use bellman::gadgets::sha256::{ - sha256_block_no_padding -}; -use bellman::gadgets::boolean::{ - Boolean -}; +use pairing::Engine; fn prf( cs: CS, @@ -14,9 +10,11 @@ fn prf( c: bool, d: bool, x: &[Boolean], - y: &[Boolean] + y: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { assert_eq!(x.len(), 252); assert_eq!(y.len(), 256); @@ -31,27 +29,35 @@ fn prf( assert_eq!(image.len(), 512); - sha256_block_no_padding( - cs, - &image - ) + sha256_block_no_padding(cs, &image) } -pub fn prf_a_pk( - cs: CS, - a_sk: &[Boolean] -) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +pub fn prf_a_pk(cs: CS, a_sk: &[Boolean]) -> Result, SynthesisError> +where + E: Engine, + CS: ConstraintSystem, { - prf(cs, true, true, false, false, a_sk, &(0..256).map(|_| Boolean::constant(false)).collect::>()) + prf( + cs, + true, + true, + false, + false, + a_sk, + &(0..256) + .map(|_| Boolean::constant(false)) + .collect::>(), + ) } pub fn prf_nf( cs: CS, a_sk: &[Boolean], - rho: &[Boolean] + rho: &[Boolean], ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { prf(cs, true, true, true, false, a_sk, rho) } @@ -60,9 +66,11 @@ pub fn prf_pk( cs: CS, a_sk: &[Boolean], h_sig: &[Boolean], - nonce: bool + nonce: bool, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { prf(cs, false, nonce, false, false, a_sk, h_sig) } @@ -71,9 +79,11 @@ pub fn prf_rho( cs: CS, phi: &[Boolean], h_sig: &[Boolean], - nonce: bool + nonce: bool, ) -> Result, SynthesisError> - where E: Engine, CS: ConstraintSystem +where + E: Engine, + CS: ConstraintSystem, { prf(cs, false, nonce, true, false, phi, h_sig) } diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 1c1a972..6dd5767 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -3,11 +3,11 @@ use bellman::groth16::{Parameters, PreparedVerifyingKey}; use directories::BaseDirs; use pairing::bls12_381::{Bls12, Fr}; +use std::path::Path; use zcash_primitives::{ jubjub::{edwards, fs::Fs, Unknown}, primitives::{Diversifier, PaymentAddress, ProofGenerationKey}, }; -use std::path::Path; use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, prover::TxProver, diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index e914171..283e76b 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -1,8 +1,6 @@ use bellman::{ gadgets::multipack, - groth16::{ - create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, - }, + groth16::{create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof}, }; use ff::Field; use pairing::bls12_381::{Bls12, Fr}; From a7c5993597c93dd4839f51c639d13faa71fd6022 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 15 Aug 2019 10:41:48 -0600 Subject: [PATCH 070/105] cargo fmt --- ff/ff_derive/src/lib.rs | 127 ++++++++++++++------------- librustzcash/src/rustzcash.rs | 4 +- zcash_client_backend/src/encoding.rs | 4 +- 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index df2625b..5f8e642 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -52,13 +52,8 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let mut gen = proc_macro2::TokenStream::new(); - let (constants_impl, sqrt_impl) = prime_field_constants_and_sqrt( - &ast.ident, - &repr_ident, - modulus, - limbs, - generator, - ); + let (constants_impl, sqrt_impl) = + prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator); gen.extend(constants_impl); gen.extend(prime_field_repr_impl(&repr_ident, limbs)); @@ -359,7 +354,8 @@ fn biguint_num_bits(mut v: BigUint) -> u32 { fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { let mut ret = BigUint::one(); - for i in exp.to_bytes_be() + for i in exp + .to_bytes_be() .into_iter() .flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd())) { @@ -380,11 +376,13 @@ fn test_exp() { &BigUint::from_str("5489673498567349856734895").unwrap(), &BigUint::from_str( "52435875175126190479447740508185965837690552500527637822603658699938581184513" - ).unwrap() + ) + .unwrap() ), BigUint::from_str( "4371221214068404307866768905142520595925044802278091865033317963560480051536" - ).unwrap() + ) + .unwrap() ); } @@ -423,7 +421,7 @@ fn prime_field_constants_and_sqrt( let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); - let legendre_impl = quote!{ + let legendre_impl = quote! { fn legendre(&self) -> ::ff::LegendreSymbol { // s = self^((modulus - 1) // 2) let s = self.pow(#mod_minus_1_over_2); @@ -445,7 +443,7 @@ fn prime_field_constants_and_sqrt( // Compute -R as (m - r) let rneg = biguint_to_u64_vec(&modulus - &r, limbs); - quote!{ + quote! { impl ::ff::SqrtField for #name { #legendre_impl @@ -472,7 +470,7 @@ fn prime_field_constants_and_sqrt( let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs); let t = biguint_to_u64_vec(t.clone(), limbs); - quote!{ + quote! { impl ::ff::SqrtField for #name { #legendre_impl @@ -519,7 +517,7 @@ fn prime_field_constants_and_sqrt( } } } else { - quote!{} + quote! {} }; // Compute R^2 mod m @@ -536,36 +534,39 @@ fn prime_field_constants_and_sqrt( } inv = inv.wrapping_neg(); - (quote! { - /// This is the modulus m of the prime field - const MODULUS: #repr = #repr([#(#modulus,)*]); + ( + quote! { + /// This is the modulus m of the prime field + const MODULUS: #repr = #repr([#(#modulus,)*]); - /// The number of bits needed to represent the modulus. - const MODULUS_BITS: u32 = #modulus_num_bits; + /// The number of bits needed to represent the modulus. + const MODULUS_BITS: u32 = #modulus_num_bits; - /// The number of bits that must be shaved from the beginning of - /// the representation when randomly sampling. - const REPR_SHAVE_BITS: u32 = #repr_shave_bits; + /// The number of bits that must be shaved from the beginning of + /// the representation when randomly sampling. + const REPR_SHAVE_BITS: u32 = #repr_shave_bits; - /// 2^{limbs*64} mod m - const R: #repr = #repr(#r); + /// 2^{limbs*64} mod m + const R: #repr = #repr(#r); - /// 2^{limbs*64*2} mod m - const R2: #repr = #repr(#r2); + /// 2^{limbs*64*2} mod m + const R2: #repr = #repr(#r2); - /// -(m^{-1} mod m) mod m - const INV: u64 = #inv; + /// -(m^{-1} mod m) mod m + const INV: u64 = #inv; - /// Multiplicative generator of `MODULUS` - 1 order, also quadratic - /// nonresidue. - const GENERATOR: #repr = #repr(#generator); + /// Multiplicative generator of `MODULUS` - 1 order, also quadratic + /// nonresidue. + const GENERATOR: #repr = #repr(#generator); - /// 2^s * t = MODULUS - 1 with t odd - const S: u32 = #s; + /// 2^s * t = MODULUS - 1 with t odd + const S: u32 = #s; - /// 2^s root of unity computed by GENERATOR^t - const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); - }, sqrt_impl) + /// 2^s root of unity computed by GENERATOR^t + const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); + }, + sqrt_impl, + ) } /// Implement PrimeField for the derived type. @@ -585,9 +586,9 @@ fn prime_field_impl( mont_paramlist.append_separated( (0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { if i != 0 { - quote!{mut #x: u64} + quote! {mut #x: u64} } else { - quote!{#x: u64} + quote! {#x: u64} } }), proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), @@ -600,7 +601,7 @@ fn prime_field_impl( for i in 0..limbs { { let temp = get_temp(i); - gen.extend(quote!{ + gen.extend(quote! { let k = #temp.wrapping_mul(INV); let mut carry = 0; ::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); @@ -609,7 +610,7 @@ fn prime_field_impl( for j in 1..limbs { let temp = get_temp(i + j); - gen.extend(quote!{ + gen.extend(quote! { #temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); }); } @@ -617,17 +618,17 @@ fn prime_field_impl( let temp = get_temp(i + limbs); if i == 0 { - gen.extend(quote!{ + gen.extend(quote! { #temp = ::ff::adc(#temp, 0, &mut carry); }); } else { - gen.extend(quote!{ + gen.extend(quote! { #temp = ::ff::adc(#temp, carry2, &mut carry); }); } if i != (limbs - 1) { - gen.extend(quote!{ + gen.extend(quote! { let carry2 = carry; }); } @@ -636,7 +637,7 @@ fn prime_field_impl( for i in 0..limbs { let temp = get_temp(limbs + i); - gen.extend(quote!{ + gen.extend(quote! { (self.0).0[#i] = #temp; }); } @@ -648,14 +649,14 @@ fn prime_field_impl( let mut gen = proc_macro2::TokenStream::new(); for i in 0..(limbs - 1) { - gen.extend(quote!{ + gen.extend(quote! { let mut carry = 0; }); for j in (i + 1)..limbs { let temp = get_temp(i + j); if i == 0 { - gen.extend(quote!{ + gen.extend(quote! { let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); }); } else { @@ -667,7 +668,7 @@ fn prime_field_impl( let temp = get_temp(i + limbs); - gen.extend(quote!{ + gen.extend(quote! { let #temp = carry; }); } @@ -677,21 +678,21 @@ fn prime_field_impl( let temp1 = get_temp(limbs * 2 - i - 1); if i == 1 { - gen.extend(quote!{ + gen.extend(quote! { let #temp0 = #temp1 >> 63; }); } else if i == (limbs * 2 - 1) { - gen.extend(quote!{ + gen.extend(quote! { let #temp0 = #temp0 << 1; }); } else { - gen.extend(quote!{ + gen.extend(quote! { let #temp0 = (#temp0 << 1) | (#temp1 >> 63); }); } } - gen.extend(quote!{ + gen.extend(quote! { let mut carry = 0; }); @@ -699,7 +700,7 @@ fn prime_field_impl( let temp0 = get_temp(i * 2); let temp1 = get_temp(i * 2 + 1); if i == 0 { - gen.extend(quote!{ + gen.extend(quote! { let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); }); } else { @@ -708,7 +709,7 @@ fn prime_field_impl( }); } - gen.extend(quote!{ + gen.extend(quote! { let #temp1 = ::ff::adc(#temp1, 0, &mut carry); }); } @@ -719,7 +720,7 @@ fn prime_field_impl( proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), ); - gen.extend(quote!{ + gen.extend(quote! { self.mont_reduce(#mont_calling); }); @@ -734,7 +735,7 @@ fn prime_field_impl( let mut gen = proc_macro2::TokenStream::new(); for i in 0..limbs { - gen.extend(quote!{ + gen.extend(quote! { let mut carry = 0; }); @@ -742,7 +743,7 @@ fn prime_field_impl( let temp = get_temp(i + j); if i == 0 { - gen.extend(quote!{ + gen.extend(quote! { let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); }); } else { @@ -754,7 +755,7 @@ fn prime_field_impl( let temp = get_temp(i + limbs); - gen.extend(quote!{ + gen.extend(quote! { let #temp = carry; }); } @@ -765,29 +766,29 @@ fn prime_field_impl( proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), ); - gen.extend(quote!{ + gen.extend(quote! { self.mont_reduce(#mont_calling); }); gen } - let squaring_impl = sqr_impl(quote!{self}, limbs); - let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs); + let squaring_impl = sqr_impl(quote! {self}, limbs); + let multiply_impl = mul_impl(quote! {self}, quote! {other}, limbs); let montgomery_impl = mont_impl(limbs); // (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ... let mut into_repr_params = proc_macro2::TokenStream::new(); into_repr_params.append_separated( (0..limbs) - .map(|i| quote!{ (self.0).0[#i] }) - .chain((0..limbs).map(|_| quote!{0})), + .map(|i| quote! { (self.0).0[#i] }) + .chain((0..limbs).map(|_| quote! {0})), proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), ); let top_limb_index = limbs - 1; - quote!{ + quote! { impl ::std::marker::Copy for #name { } impl ::std::clone::Clone for #name { diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index b1e0a30..0697272 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -59,9 +59,7 @@ use std::os::windows::ffi::OsStringExt; use zcash_primitives::{ merkle_tree::CommitmentTreeWitness, note_encryption::sapling_ka_agree, - primitives::{ - Diversifier, Note, PaymentAddress, ProofGenerationKey, ViewingKey, - }, + primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ViewingKey}, redjubjub::{self, Signature}, sapling::{merkle_hash, spend_sig}, transaction::components::Amount, diff --git a/zcash_client_backend/src/encoding.rs b/zcash_client_backend/src/encoding.rs index e84defa..d39973d 100644 --- a/zcash_client_backend/src/encoding.rs +++ b/zcash_client_backend/src/encoding.rs @@ -5,11 +5,11 @@ use bech32::{self, Error, FromBase32, ToBase32}; use pairing::bls12_381::Bls12; +use std::io::{self, Write}; use zcash_primitives::{ jubjub::edwards, primitives::{Diversifier, PaymentAddress}, }; -use std::io::{self, Write}; use zcash_primitives::{ zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, JUBJUB, @@ -187,11 +187,11 @@ mod tests { use pairing::bls12_381::Bls12; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; + use zcash_primitives::JUBJUB; use zcash_primitives::{ jubjub::edwards, primitives::{Diversifier, PaymentAddress}, }; - use zcash_primitives::JUBJUB; use super::{decode_payment_address, encode_payment_address}; use crate::constants; From 7461f8936d2da1a98ef405ae9163f6af121132d8 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 15 Aug 2019 10:45:24 -0600 Subject: [PATCH 071/105] Update travis to require formatting --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9ddae8a..399eaf1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,9 @@ rust: cache: cargo +before_script: + - rustup component add rustfmt + script: + - cargo fmt --all -- --check - cargo test --verbose --release --all From ff5775418be7cdb102e730a50f1dffed0cb6e512 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 31 Jul 2019 16:17:08 +0100 Subject: [PATCH 072/105] legacy::Script::address This is the counterpart to legacy::TransparentAddress::script. --- zcash_primitives/src/legacy.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/src/legacy.rs b/zcash_primitives/src/legacy.rs index d1d7c1a..18d0388 100644 --- a/zcash_primitives/src/legacy.rs +++ b/zcash_primitives/src/legacy.rs @@ -38,6 +38,31 @@ impl Script { pub fn write(&self, mut writer: W) -> io::Result<()> { Vector::write(&mut writer, &self.0, |w, e| w.write_u8(*e)) } + + /// Returns the address that this Script contains, if any. + pub fn address(&self) -> Option { + if self.0.len() == 25 + && self.0[0] == OpCode::Dup as u8 + && self.0[1] == OpCode::Hash160 as u8 + && self.0[2] == 0x14 + && self.0[23] == OpCode::EqualVerify as u8 + && self.0[24] == OpCode::CheckSig as u8 + { + let mut hash = [0; 20]; + hash.copy_from_slice(&self.0[3..23]); + Some(TransparentAddress::PublicKey(hash)) + } else if self.0.len() == 23 + && self.0[0] == OpCode::Hash160 as u8 + && self.0[1] == 0x14 + && self.0[22] == OpCode::Equal as u8 + { + let mut hash = [0; 20]; + hash.copy_from_slice(&self.0[2..22]); + Some(TransparentAddress::Script(hash)) + } else { + None + } + } } impl Shl for Script { @@ -151,7 +176,8 @@ mod tests { 0x76, 0xa9, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x88, 0xac, ] - ) + ); + assert_eq!(addr.script().address(), Some(addr)); } #[test] @@ -163,6 +189,7 @@ mod tests { 0xa9, 0x14, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x87, ] - ) + ); + assert_eq!(addr.script().address(), Some(addr)); } } From 2a8748582bd8030932bc1b78574d027270dc2071 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 31 Jul 2019 16:18:31 +0100 Subject: [PATCH 073/105] Pass Script to signature_hash by reference --- zcash_primitives/src/transaction/sighash.rs | 4 +- zcash_primitives/src/transaction/tests.rs | 48 ++++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index b4e9a69..1b88ef8 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -154,7 +154,7 @@ pub fn signature_hash_data( tx: &TransactionData, consensus_branch_id: u32, hash_type: u32, - transparent_input: Option<(usize, Script, Amount)>, + transparent_input: Option<(usize, &Script, Amount)>, ) -> Vec { let sigversion = SigHashVersion::from_tx(tx); match sigversion { @@ -232,7 +232,7 @@ pub fn signature_hash( tx: &Transaction, consensus_branch_id: u32, hash_type: u32, - transparent_input: Option<(usize, Script, Amount)>, + transparent_input: Option<(usize, &Script, Amount)>, ) -> Vec { signature_hash_data(tx, consensus_branch_id, hash_type, transparent_input) } diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 7c770c5..80f0900 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -212,7 +212,7 @@ fn tx_write_rejects_unexpected_binding_sig() { fn zip_0143() { struct TestVector { tx: Vec, - script_code: Vec, + script_code: Script, transparent_input: Option, hash_type: u32, amount: i64, @@ -229,7 +229,7 @@ fn zip_0143() { 0xb2, 0x83, 0x5a, 0x08, 0x05, 0x75, 0x02, 0x00, 0x02, 0x51, 0x51, 0x48, 0x1c, 0xdd, 0x86, 0xb3, 0xcc, 0x43, 0x18, 0x00, ], - script_code: vec![0x6a, 0x00, 0x00, 0x00, 0x63, 0xac, 0x53], + script_code: Script(vec![0x6a, 0x00, 0x00, 0x00, 0x63, 0xac, 0x53]), transparent_input: None, hash_type: 1, amount: 1672704339313879, @@ -518,7 +518,7 @@ fn zip_0143() { 0xb1, 0xfa, 0x45, 0xad, 0x61, 0xce, 0x9a, 0x1c, 0x47, 0x27, 0xb7, 0xaa, 0xa5, 0x35, 0x62, 0xf5, 0x23, 0xe7, 0x39, 0x52, ], - script_code: vec![0x53], + script_code: Script(vec![0x53]), transparent_input: Some(1), hash_type: 3, amount: 365293780364847, @@ -678,7 +678,7 @@ fn zip_0143() { 0x62, 0x91, 0x85, 0x00, 0x2c, 0x72, 0xc0, 0x12, 0xc4, 0x14, 0xd2, 0x38, 0x2a, 0x6d, 0x47, 0xc7, 0xb3, 0xde, 0xab, 0xa7, ], - script_code: vec![0xac, 0x00], + script_code: Script(vec![0xac, 0x00]), transparent_input: Some(0), hash_type: 3, amount: 711752082734717, @@ -960,7 +960,7 @@ fn zip_0143() { 0xce, 0x1f, 0xca, 0x2c, 0x63, 0xfe, 0x06, 0xb7, 0x98, 0x9d, 0x58, 0x4f, 0xa7, 0xd7, 0x82, 0xa8, 0x8c, 0x1e, 0x7d, 0x64, 0xb6, 0xfb, 0xf5, 0x5e, 0x35, ], - script_code: vec![0x6a, 0x53, 0x53, 0x63], + script_code: Script(vec![0x6a, 0x53, 0x53, 0x63]), transparent_input: None, hash_type: 1, amount: 379068098637835, @@ -1119,7 +1119,7 @@ fn zip_0143() { 0xc1, 0xc4, 0xf2, 0xca, 0xcd, 0xa3, 0x0b, 0xdb, 0x69, 0x30, 0x65, 0x3c, 0x0c, 0xc4, 0x48, 0x6e, 0x60, 0xe8, 0x9f, 0xa8, 0x49, 0xb3, ], - script_code: vec![0x53, 0x52], + script_code: Script(vec![0x53, 0x52]), transparent_input: Some(0), hash_type: 3, amount: 1437866676382615, @@ -1139,7 +1139,7 @@ fn zip_0143() { 0x08, 0xf0, 0x83, 0x05, 0x00, 0x09, 0x63, 0x6a, 0x52, 0x63, 0x51, 0x63, 0x00, 0x6a, 0xac, 0x9a, 0xbc, 0xef, 0x2a, 0x99, 0x08, 0x73, 0x19, 0x00, ], - script_code: vec![0x63], + script_code: Script(vec![0x63]), transparent_input: None, hash_type: 1, amount: 1993227025071196, @@ -1162,7 +1162,7 @@ fn zip_0143() { 0x87, 0x01, 0xff, 0x01, 0x86, 0xd2, 0x6f, 0xee, 0x28, 0xca, 0x06, 0x00, 0x01, 0xac, 0x5a, 0xa7, 0x27, 0xab, 0x79, 0x85, 0xda, 0x0e, 0x00, ], - script_code: vec![0x65, 0x53, 0x51], + script_code: Script(vec![0x65, 0x53, 0x51]), transparent_input: Some(1), hash_type: 130, amount: 449567650863240, @@ -1444,7 +1444,7 @@ fn zip_0143() { 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, ], - script_code: vec![0x65, 0x6a, 0x65, 0x51, 0x52, 0x65, 0x63], + script_code: Script(vec![0x65, 0x6a, 0x65, 0x51, 0x52, 0x65, 0x63]), transparent_input: None, hash_type: 1, amount: 1712463999734827, @@ -1602,7 +1602,7 @@ fn zip_0143() { 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, 0x45, 0x57, ], - script_code: vec![0x53, 0x52, 0x00], + script_code: Script(vec![0x53, 0x52, 0x00]), transparent_input: Some(1), hash_type: 1, amount: 1564816348934332, @@ -1885,7 +1885,7 @@ fn zip_0143() { 0x54, 0xa7, 0x89, 0x73, 0x5b, 0x03, 0x49, 0xc4, 0xd5, 0x1c, 0x88, 0x9d, 0x08, 0x95, 0x2d, 0xdd, 0x54, 0x88, 0xbe, 0x95, 0x56, 0x05, 0x94, 0xe6, ], - script_code: vec![0x52, 0x63, 0x53, 0x51, 0x65], + script_code: Script(vec![0x52, 0x63, 0x53, 0x51, 0x65]), transparent_input: Some(0), hash_type: 2, amount: 483959951916902, @@ -1903,7 +1903,7 @@ fn zip_0143() { let transparent_input = if let Some(n) = tv.transparent_input { Some(( n as usize, - Script(tv.script_code), + &tv.script_code, Amount::from_nonnegative_i64(tv.amount).unwrap(), )) } else { @@ -1921,7 +1921,7 @@ fn zip_0143() { fn zip_0243() { struct TestVector { tx: Vec, - script_code: Vec, + script_code: Script, transparent_input: Option, hash_type: u32, amount: i64, @@ -2229,7 +2229,7 @@ fn zip_0243() { 0xe4, 0x62, 0xef, 0xf9, 0xba, 0x8b, 0x3f, 0x4b, 0xfa, 0xa1, 0x30, 0x0c, 0x26, 0x92, 0x5a, 0x87, ], - script_code: vec![0x63], + script_code: Script(vec![0x63]), transparent_input: None, hash_type: 1, amount: 1969273897303781, @@ -2462,7 +2462,7 @@ fn zip_0243() { 0xed, 0x6a, 0x9f, 0x08, 0x46, 0x4d, 0x56, 0x55, 0x93, 0xe1, 0xa6, 0x3b, 0x93, 0x85, 0x36, 0xb4, 0x92, 0x44, 0xe9, 0x7d, ], - script_code: vec![], + script_code: Script(vec![]), transparent_input: Some(1), hash_type: 2, amount: 652655344020909, @@ -3048,7 +3048,7 @@ fn zip_0243() { 0x76, 0xc5, 0x3b, 0x4d, 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, ], - script_code: vec![0x53, 0x63, 0x63, 0x51, 0xac, 0x00, 0x51], + script_code: Script(vec![0x53, 0x63, 0x63, 0x51, 0xac, 0x00, 0x51]), transparent_input: None, hash_type: 1, amount: 1345602751504862, @@ -3369,7 +3369,7 @@ fn zip_0243() { 0xde, 0x7f, 0x8e, 0x6a, 0x5c, 0x62, 0xa7, 0x77, 0xd1, 0x75, 0x00, 0x2a, 0x13, 0x7d, 0xe8, 0x5b, 0x88, ], - script_code: vec![], + script_code: Script(vec![]), transparent_input: None, hash_type: 1, amount: 1039204199089370, @@ -3519,7 +3519,7 @@ fn zip_0243() { 0xb5, 0x58, 0x02, 0x9a, 0x36, 0x02, 0x4d, 0x2e, 0x79, 0x0f, 0xc6, 0xfd, 0x66, 0x7f, 0x17, 0x6e, 0x0a, 0xa9, 0x9d, 0xd1, 0xd7, 0x2b, 0x57, ], - script_code: vec![0x6a, 0x51, 0x65, 0xac], + script_code: Script(vec![0x6a, 0x51, 0x65, 0xac]), transparent_input: None, hash_type: 1, amount: 691732482992802, @@ -3919,7 +3919,7 @@ fn zip_0243() { 0x30, 0x3a, 0x3a, 0xb9, 0xbb, 0x2e, 0xe3, 0x79, 0xb9, 0xaf, 0xcd, 0x1f, 0x6a, 0x3c, 0xb9, 0x00, 0x0b, 0xb1, 0x4e, ], - script_code: vec![0x53, 0x63, 0x63, 0xac, 0x63, 0x52], + script_code: Script(vec![0x53, 0x63, 0x63, 0xac, 0x63, 0x52]), transparent_input: None, hash_type: 1, amount: 1152393991505765, @@ -4083,7 +4083,7 @@ fn zip_0243() { 0x53, 0xf1, 0xd0, 0xc8, 0x65, 0xa9, 0x4a, 0xa4, 0x56, 0xdc, 0xd1, 0x8a, 0x39, 0xe2, 0xf5, 0x85, 0xd9, 0xbe, 0xa8, ], - script_code: vec![0x63, 0x00, 0x6a, 0x53, 0x63, 0x6a, 0xac, 0x00], + script_code: Script(vec![0x63, 0x00, 0x6a, 0x53, 0x63, 0x6a, 0xac, 0x00]), transparent_input: None, hash_type: 1, amount: 1788797765223798, @@ -4681,7 +4681,7 @@ fn zip_0243() { 0x31, 0xbd, 0x7c, 0x52, 0x22, 0xb6, 0x70, 0x61, 0x6e, 0x4b, 0x6c, 0xa8, 0xa2, 0x35, 0x50, 0xca, 0xd8, 0xac, 0x0d, 0xdb, 0x76, 0x45, 0xe2, 0xb9, 0x71, 0x3b, 0xe7, ], - script_code: vec![0x6a, 0x00, 0x00, 0x65, 0x53, 0xac, 0x63, 0x53, 0x63], + script_code: Script(vec![0x6a, 0x00, 0x00, 0x65, 0x53, 0xac, 0x63, 0x53, 0x63]), transparent_input: None, hash_type: 1, amount: 1871432121379810, @@ -5190,7 +5190,7 @@ fn zip_0243() { 0x1b, 0x48, 0x09, 0x8e, 0xba, 0x2c, 0x2e, 0xc2, 0x0a, 0x0a, 0xc0, 0x44, 0x3b, 0xa8, 0xe9, 0x48, 0x7b, 0xcf, 0x7d, ], - script_code: vec![0xac, 0x53, 0x63, 0x52, 0x6a, 0x51, 0xac], + script_code: Script(vec![0xac, 0x53, 0x63, 0x52, 0x6a, 0x51, 0xac]), transparent_input: None, hash_type: 1, amount: 1501997449504444, @@ -5380,7 +5380,7 @@ fn zip_0243() { 0xfb, 0x34, 0x1e, 0xf5, 0xff, 0xb4, 0x2b, 0xc2, 0xab, 0xc5, 0x08, 0xff, 0x23, 0x12, 0x48, 0xf2, 0xc2, 0xdc, 0x15, 0x77, 0x0d, 0x33, 0x72, 0x2b, 0x9c, 0x9d, 0xae, ], - script_code: vec![0xac, 0x65], + script_code: Script(vec![0xac, 0x65]), transparent_input: Some(0), hash_type: 3, amount: 391892287957268, @@ -5398,7 +5398,7 @@ fn zip_0243() { let transparent_input = if let Some(n) = tv.transparent_input { Some(( n as usize, - Script(tv.script_code), + &tv.script_code, Amount::from_nonnegative_i64(tv.amount).unwrap(), )) } else { From 388a5855159c3c3502691deac19bc51ecbfe68d6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 31 Jul 2019 16:20:13 +0100 Subject: [PATCH 074/105] transaction::Builder::add_transparent_input() --- Cargo.lock | 28 +++++ zcash_primitives/Cargo.toml | 5 + zcash_primitives/src/lib.rs | 6 + zcash_primitives/src/transaction/builder.rs | 108 +++++++++++++++++- .../src/transaction/components.rs | 11 +- 5 files changed, 155 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6f658a..2d66dba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,6 +144,11 @@ dependencies = [ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cc" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.9" @@ -460,6 +465,24 @@ dependencies = [ "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "secp256k1" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha2" version = "0.8.0" @@ -540,6 +563,8 @@ dependencies = [ "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -576,6 +601,7 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" @@ -611,6 +637,8 @@ dependencies = [ "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967" "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" +"checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" +"checksum secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0344a794ff109f85547039536028e12f313178ac1545e49fdf16a530d900a7b" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index b3173b7..d591535 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -19,8 +19,13 @@ pairing = { path = "../pairing" } rand = "0.7" rand_core = "0.5" rand_os = "0.2" +ripemd160 = { version = "0.8", optional = true } +secp256k1 = { version = "=0.15.0", optional = true } sha2 = "0.8" [dev-dependencies] hex-literal = "0.1" rand_xorshift = "0.2" + +[features] +transparent-inputs = ["ripemd160", "secp256k1"] diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 1d4806e..0c55023 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -15,6 +15,12 @@ extern crate rand_core; extern crate rand_os; extern crate sha2; +#[cfg(feature = "transparent-inputs")] +extern crate ripemd160; + +#[cfg(feature = "transparent-inputs")] +extern crate secp256k1; + #[cfg(test)] #[macro_use] extern crate hex_literal; diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index f32af7a..4e219ee 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -24,6 +24,12 @@ use crate::{ JUBJUB, }; +#[cfg(feature = "transparent-inputs")] +use crate::{ + legacy::Script, + transaction::components::{OutPoint, TxIn}, +}; + const DEFAULT_TX_EXPIRY_DELTA: u32 = 20; /// If there are any shielded inputs, always have at least two shielded outputs, padding @@ -130,6 +136,50 @@ impl SaplingOutput { } } +#[cfg(feature = "transparent-inputs")] +struct TransparentInputInfo { + sk: secp256k1::SecretKey, + pubkey: [u8; secp256k1::constants::PUBLIC_KEY_SIZE], + coin: TxOut, +} + +#[cfg(feature = "transparent-inputs")] +struct TransparentInputs { + secp: secp256k1::Secp256k1, + inputs: Vec, +} + +#[cfg(feature = "transparent-inputs")] +impl Default for TransparentInputs { + fn default() -> Self { + TransparentInputs { + secp: secp256k1::Secp256k1::gen_new(), + inputs: Default::default(), + } + } +} + +#[cfg(not(feature = "transparent-inputs"))] +#[derive(Default)] +struct TransparentInputs; + +impl TransparentInputs { + fn input_sum(&self) -> Amount { + #[cfg(feature = "transparent-inputs")] + { + self.inputs + .iter() + .map(|input| input.coin.value) + .sum::() + } + + #[cfg(not(feature = "transparent-inputs"))] + { + Amount::zero() + } + } +} + /// Metadata about a transaction created by a [`Builder`]. #[derive(Debug, PartialEq)] pub struct TransactionMetadata { @@ -176,6 +226,7 @@ pub struct Builder { anchor: Option, spends: Vec, outputs: Vec, + legacy: TransparentInputs, change_address: Option<(OutgoingViewingKey, PaymentAddress)>, } @@ -215,6 +266,7 @@ impl Builder { anchor: None, spends: vec![], outputs: vec![], + legacy: TransparentInputs::default(), change_address: None, } } @@ -273,6 +325,39 @@ impl Builder { Ok(()) } + /// Adds a transparent coin to be spent in this transaction. + #[cfg(feature = "transparent-inputs")] + pub fn add_transparent_input( + &mut self, + sk: secp256k1::SecretKey, + utxo: OutPoint, + coin: TxOut, + ) -> Result<(), Error> { + if coin.value.is_negative() { + return Err(Error::InvalidAmount); + } + + let pubkey = secp256k1::PublicKey::from_secret_key(&self.legacy.secp, &sk).serialize(); + match coin.script_pubkey.address() { + Some(TransparentAddress::PublicKey(hash)) => { + use ripemd160::Ripemd160; + use sha2::{Digest, Sha256}; + + if &hash[..] != &Ripemd160::digest(&Sha256::digest(&pubkey))[..] { + return Err(Error::InvalidAddress); + } + } + _ => return Err(Error::InvalidAddress), + } + + self.mtx.vin.push(TxIn::new(utxo)); + self.legacy + .inputs + .push(TransparentInputInfo { sk, pubkey, coin }); + + Ok(()) + } + /// Adds a transparent address to send funds to. pub fn add_transparent_output( &mut self, @@ -320,8 +405,7 @@ impl Builder { // // Valid change - let change = self.mtx.value_balance - - self.fee + let change = self.mtx.value_balance - self.fee + self.legacy.input_sum() - self .mtx .vout @@ -523,6 +607,26 @@ impl Builder { .map_err(|()| Error::BindingSig)?, ); + // Transparent signatures + #[cfg(feature = "transparent-inputs")] + { + for (i, info) in self.legacy.inputs.iter().enumerate() { + sighash.copy_from_slice(&signature_hash_data( + &self.mtx, + consensus_branch_id, + SIGHASH_ALL, + Some((i, &info.coin.script_pubkey, info.coin.value)), + )); + + let msg = secp256k1::Message::from_slice(&sighash).expect("32 bytes"); + let sig = self.legacy.secp.sign(&msg, &info.sk); + + // P2PKH scriptSig + self.mtx.vin[i].script_sig = + Script::default() << &sig.serialize_compact()[..] << &info.pubkey[..]; + } + } + Ok(( self.mtx.freeze().expect("Transaction should be complete"), tx_metadata, diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index c8cfadc..00b28b1 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -42,11 +42,20 @@ impl OutPoint { #[derive(Debug)] pub struct TxIn { pub prevout: OutPoint, - script_sig: Script, + pub script_sig: Script, pub sequence: u32, } impl TxIn { + #[cfg(feature = "transparent-inputs")] + pub fn new(prevout: OutPoint) -> Self { + TxIn { + prevout, + script_sig: Script::default(), + sequence: std::u32::MAX, + } + } + pub fn read(mut reader: &mut R) -> io::Result { let prevout = OutPoint::read(&mut reader)?; let script_sig = Script::read(&mut reader)?; From 40f768ed606d04f372bfb55c5a06361a72d2b0f3 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sat, 17 Aug 2019 11:58:22 +0200 Subject: [PATCH 075/105] Fix off-by-one so pedersen_hash doesn't consume too many generators. --- zcash_proofs/src/circuit/pedersen_hash.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcash_proofs/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs index 21c0bf5..3cd9367 100644 --- a/zcash_proofs/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -26,12 +26,12 @@ where assert_eq!(personalization.len(), 6); let mut edwards_result = None; - let mut bits = personalization.iter().chain(bits.iter()); + let mut bits = personalization.iter().chain(bits.iter()).peekable(); let mut segment_generators = params.pedersen_circuit_generators().iter(); let boolean_false = Boolean::constant(false); let mut segment_i = 0; - loop { + while bits.peek().is_some() { let mut segment_result = None; let mut segment_windows = &segment_generators.next().expect("enough segments")[..]; From d4b6c0e1a2084335b89f0e16baabfba829eecf8c Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 19 Aug 2019 14:04:41 +0200 Subject: [PATCH 076/105] Use expect to remove unreachable break. --- zcash_proofs/src/circuit/pedersen_hash.rs | 40 ++++++++++------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/zcash_proofs/src/circuit/pedersen_hash.rs b/zcash_proofs/src/circuit/pedersen_hash.rs index 3cd9367..9558acc 100644 --- a/zcash_proofs/src/circuit/pedersen_hash.rs +++ b/zcash_proofs/src/circuit/pedersen_hash.rs @@ -72,32 +72,28 @@ where window_i += 1; } - match segment_result { - Some(segment_result) => { - // Convert this segment into twisted Edwards form. - let segment_result = segment_result.into_edwards( - cs.namespace(|| format!("conversion of segment {} into edwards", segment_i)), + let segment_result = segment_result.expect( + "bits is not exhausted due to while condition; + thus there must be a segment window; + thus there must be a segment result", + ); + + // Convert this segment into twisted Edwards form. + let segment_result = segment_result.into_edwards( + cs.namespace(|| format!("conversion of segment {} into edwards", segment_i)), + params, + )?; + + match edwards_result { + Some(ref mut edwards_result) => { + *edwards_result = segment_result.add( + cs.namespace(|| format!("addition of segment {} to accumulator", segment_i)), + edwards_result, params, )?; - - match edwards_result { - Some(ref mut edwards_result) => { - *edwards_result = segment_result.add( - cs.namespace(|| { - format!("addition of segment {} to accumulator", segment_i) - }), - edwards_result, - params, - )?; - } - None => { - edwards_result = Some(segment_result); - } - } } None => { - // We didn't process any new bits. - break; + edwards_result = Some(segment_result); } } From 2dd2fc620e3e1747f8a887e31765a2ef238199db Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 12 Oct 2018 18:22:58 +0100 Subject: [PATCH 077/105] Build protobufs for compact formats --- Cargo.lock | 27 +++++++++++ zcash_client_backend/.gitignore | 2 + zcash_client_backend/Cargo.toml | 4 ++ zcash_client_backend/build.rs | 11 +++++ .../proto/compact_formats.proto | 47 +++++++++++++++++++ zcash_client_backend/src/lib.rs | 1 + zcash_client_backend/src/proto/mod.rs | 3 ++ 7 files changed, 95 insertions(+) create mode 100644 zcash_client_backend/.gitignore create mode 100644 zcash_client_backend/build.rs create mode 100644 zcash_client_backend/proto/compact_formats.proto create mode 100644 zcash_client_backend/src/proto/mod.rs diff --git a/Cargo.lock b/Cargo.lock index d6f658a..ae85297 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -398,6 +398,28 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "protobuf" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "protobuf-codegen" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "protobuf-codegen-pure" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf-codegen 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.13" @@ -516,6 +538,8 @@ version = "0.0.0" dependencies = [ "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", + "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf-codegen-pure 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_primitives 0.0.0", @@ -604,6 +628,9 @@ dependencies = [ "checksum proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "463bf29e7f11344e58c9e01f171470ab15c925c6822ad75028cc1c0e1d1eb63b" "checksum proc-macro-hack-impl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38c47dcb1594802de8c02f3b899e2018c78291168a22c281be21ea0fb4796842" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8aefcec9f142b524d98fc81d07827743be89dd6586a1ba6ab21fa66a500b3fa5" +"checksum protobuf-codegen 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31539be8028d6b9e8e1b3b7c74e2fa3555302e27b2cc20dbaee6ffba648f75e2" +"checksum protobuf-codegen-pure 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00993dc5fbbfcf9d8a005f6b6c29fd29fd6d86deba3ae3f41fd20c624c414616" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" diff --git a/zcash_client_backend/.gitignore b/zcash_client_backend/.gitignore new file mode 100644 index 0000000..7025829 --- /dev/null +++ b/zcash_client_backend/.gitignore @@ -0,0 +1,2 @@ +# Protobufs +src/proto/ diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 9996a47..446c1ee 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -9,8 +9,12 @@ edition = "2018" [dependencies] bech32 = "0.7" pairing = { path = "../pairing" } +protobuf = "2" zcash_primitives = { path = "../zcash_primitives" } +[build-dependencies] +protobuf-codegen-pure = "2" + [dev-dependencies] rand_core = "0.5" rand_xorshift = "0.2" diff --git a/zcash_client_backend/build.rs b/zcash_client_backend/build.rs new file mode 100644 index 0000000..41e0214 --- /dev/null +++ b/zcash_client_backend/build.rs @@ -0,0 +1,11 @@ +use protobuf_codegen_pure; + +fn main() { + protobuf_codegen_pure::run(protobuf_codegen_pure::Args { + out_dir: "src/proto", + input: &["proto/compact_formats.proto"], + includes: &["proto"], + customize: Default::default(), + }) + .expect("protoc"); +} diff --git a/zcash_client_backend/proto/compact_formats.proto b/zcash_client_backend/proto/compact_formats.proto new file mode 100644 index 0000000..d65b658 --- /dev/null +++ b/zcash_client_backend/proto/compact_formats.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; +package cash.z.wallet.sdk.rpc; +option go_package = "walletrpc"; + +// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. +// bytes fields of hashes are in canonical little-endian format. + +// CompactBlock is a packaging of ONLY the data from a block that's needed to: +// 1. Detect a payment to your shielded Sapling address +// 2. Detect a spend of your shielded Sapling notes +// 3. Update your witnesses to generate new Sapling spend proofs. +message CompactBlock { + uint32 protoVersion = 1; // the version of this wire format, for storage + uint64 height = 2; // the height of this block + bytes hash = 3; + uint32 time = 4; + bytes header = 5; // (hash and time) OR (full header) + repeated CompactTx vtx = 6; // compact transactions from this block +} + +message CompactTx { + // Index and hash will allow the receiver to call out to chain + // explorers or other data structures to retrieve more information + // about this transaction. + uint64 index = 1; + bytes hash = 2; + + // The transaction fee: present if server can provide. In the case of a + // stateless server and a transaction with transparent inputs, this will be + // unset because the calculation requires reference to prior transactions. + // in a pure-Sapling context, the fee will be calculable as: + // valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut)) + uint32 fee = 3; + + repeated CompactSpend spends = 4; + repeated CompactOutput outputs = 5; +} + +message CompactSpend { + bytes nf = 1; +} + +message CompactOutput { + bytes cmu = 1; + bytes epk = 2; + bytes ciphertext = 3; +} diff --git a/zcash_client_backend/src/lib.rs b/zcash_client_backend/src/lib.rs index 02de4b4..cb0be13 100644 --- a/zcash_client_backend/src/lib.rs +++ b/zcash_client_backend/src/lib.rs @@ -6,3 +6,4 @@ pub mod constants; pub mod encoding; pub mod keys; +pub mod proto; diff --git a/zcash_client_backend/src/proto/mod.rs b/zcash_client_backend/src/proto/mod.rs new file mode 100644 index 0000000..e24ef5c --- /dev/null +++ b/zcash_client_backend/src/proto/mod.rs @@ -0,0 +1,3 @@ +//! Generated code for handling light client protobuf structs. + +pub mod compact_formats; From 5ec94b5db5c9fe17dd08ab072e45cc1a1dca0390 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 12 Oct 2018 18:24:25 +0100 Subject: [PATCH 078/105] Parse compact blocks to find wallet transactions --- Cargo.lock | 3 + zcash_client_backend/Cargo.toml | 3 + zcash_client_backend/src/lib.rs | 2 + zcash_client_backend/src/wallet.rs | 32 ++++ zcash_client_backend/src/welding_rig.rs | 194 ++++++++++++++++++++++++ 5 files changed, 234 insertions(+) create mode 100644 zcash_client_backend/src/wallet.rs create mode 100644 zcash_client_backend/src/welding_rig.rs diff --git a/Cargo.lock b/Cargo.lock index ae85297..9ac6c2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -537,10 +537,13 @@ name = "zcash_client_backend" version = "0.0.0" dependencies = [ "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf-codegen-pure 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_primitives 0.0.0", ] diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 446c1ee..a95e5a0 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -8,6 +8,8 @@ edition = "2018" [dependencies] bech32 = "0.7" +ff = { path = "../ff" } +hex = "0.3" pairing = { path = "../pairing" } protobuf = "2" zcash_primitives = { path = "../zcash_primitives" } @@ -17,4 +19,5 @@ protobuf-codegen-pure = "2" [dev-dependencies] rand_core = "0.5" +rand_os = "0.2" rand_xorshift = "0.2" diff --git a/zcash_client_backend/src/lib.rs b/zcash_client_backend/src/lib.rs index cb0be13..7f2af0a 100644 --- a/zcash_client_backend/src/lib.rs +++ b/zcash_client_backend/src/lib.rs @@ -7,3 +7,5 @@ pub mod constants; pub mod encoding; pub mod keys; pub mod proto; +pub mod wallet; +pub mod welding_rig; diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs new file mode 100644 index 0000000..4e85eef --- /dev/null +++ b/zcash_client_backend/src/wallet.rs @@ -0,0 +1,32 @@ +//! Structs representing transaction data scanned from the block chain by a wallet or +//! light client. + +use pairing::bls12_381::{Bls12, Fr}; +use zcash_primitives::{ + jubjub::{edwards, PrimeOrder}, + transaction::TxId, +}; + +pub struct EncCiphertextFrag(pub [u8; 52]); + +/// A subset of a [`Transaction`] relevant to wallets and light clients. +/// +/// [`Transaction`]: zcash_primitives::transaction::Transaction +pub struct WalletTx { + pub txid: TxId, + pub num_spends: usize, + pub num_outputs: usize, + pub shielded_outputs: Vec, +} + +/// A subset of an [`OutputDescription`] relevant to wallets and light clients. +/// +/// [`OutputDescription`]: zcash_primitives::transaction::components::OutputDescription +pub struct WalletShieldedOutput { + pub index: usize, + pub cmu: Fr, + pub epk: edwards::Point, + pub enc_ct: EncCiphertextFrag, + pub account: usize, + pub value: u64, +} diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs new file mode 100644 index 0000000..26273e5 --- /dev/null +++ b/zcash_client_backend/src/welding_rig.rs @@ -0,0 +1,194 @@ +//! Tools for scanning a compact representation of the Zcash block chain. + +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use zcash_primitives::{ + jubjub::{edwards, fs::Fs}, + note_encryption::try_sapling_compact_note_decryption, + transaction::TxId, + zip32::ExtendedFullViewingKey, + JUBJUB, +}; + +use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactTx}; +use crate::wallet::{EncCiphertextFrag, WalletShieldedOutput, WalletTx}; + +/// Scans a [`CompactOutput`] with a set of [`ExtendedFullViewingKey`]s. +/// +/// Returns a [`WalletShieldedOutput`] if this output belongs to any of the given +/// [`ExtendedFullViewingKey`]s. +fn scan_output( + (index, output): (usize, CompactOutput), + ivks: &[Fs], +) -> Option { + let mut repr = FrRepr::default(); + if repr.read_le(&output.cmu[..]).is_err() { + return None; + } + let cmu = match Fr::from_repr(repr) { + Ok(cmu) => cmu, + Err(_) => return None, + }; + + let epk = match edwards::Point::::read(&output.epk[..], &JUBJUB) { + Ok(p) => match p.as_prime_order(&JUBJUB) { + Some(epk) => epk, + None => return None, + }, + Err(_) => return None, + }; + + let ct = output.ciphertext; + + for (account, ivk) in ivks.iter().enumerate() { + let value = match try_sapling_compact_note_decryption(ivk, &epk, &cmu, &ct) { + Some((note, _)) => note.value, + None => continue, + }; + + // It's ours, so let's copy the ciphertext fragment and return + let mut enc_ct = EncCiphertextFrag([0u8; 52]); + enc_ct.0.copy_from_slice(&ct); + + return Some(WalletShieldedOutput { + index, + cmu, + epk, + enc_ct, + account, + value, + }); + } + None +} + +/// Scans a [`CompactTx`] with a set of [`ExtendedFullViewingKey`]s. +/// +/// Returns a [`WalletTx`] if this transaction belongs to any of the given +/// [`ExtendedFullViewingKey`]s. +fn scan_tx(tx: CompactTx, extfvks: &[ExtendedFullViewingKey]) -> Option { + let num_spends = tx.spends.len(); + let num_outputs = tx.outputs.len(); + + // Check for incoming notes + let shielded_outputs: Vec = { + let ivks: Vec<_> = extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); + tx.outputs + .into_iter() + .enumerate() + .filter_map(|(index, output)| scan_output((index, output), &ivks)) + .collect() + }; + + if shielded_outputs.is_empty() { + None + } else { + let mut txid = TxId([0u8; 32]); + txid.0.copy_from_slice(&tx.hash); + Some(WalletTx { + txid, + num_spends, + num_outputs, + shielded_outputs, + }) + } +} + +/// Scans a [`CompactBlock`] for transactions belonging to a set of +/// [`ExtendedFullViewingKey`]s. +/// +/// Returns a vector of [`WalletTx`]s belonging to any of the given +/// [`ExtendedFullViewingKey`]s. +pub fn scan_block(block: CompactBlock, extfvks: &[ExtendedFullViewingKey]) -> Vec { + block + .vtx + .into_iter() + .filter_map(|tx| scan_tx(tx, extfvks)) + .collect() +} + +#[cfg(test)] +mod tests { + use ff::{Field, PrimeField, PrimeFieldRepr}; + use pairing::bls12_381::Bls12; + use rand_core::RngCore; + use rand_os::OsRng; + use zcash_primitives::{ + jubjub::fs::Fs, + note_encryption::{Memo, SaplingNoteEncryption}, + primitives::Note, + transaction::components::Amount, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + JUBJUB, + }; + + use super::scan_block; + use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactTx}; + + /// Create a fake CompactBlock at the given height, containing a single output paying + /// the given address. Returns the CompactBlock and the nullifier for the new note. + fn fake_compact_block( + height: i32, + extfvk: ExtendedFullViewingKey, + value: Amount, + ) -> CompactBlock { + let to = extfvk.default_address().unwrap().1; + + // Create a fake Note for the account + let mut rng = OsRng; + let note = Note { + g_d: to.diversifier.g_d::(&JUBJUB).unwrap(), + pk_d: to.pk_d.clone(), + value: value.into(), + r: Fs::random(&mut rng), + }; + let encryptor = SaplingNoteEncryption::new( + extfvk.fvk.ovk, + note.clone(), + to.clone(), + Memo::default(), + &mut rng, + ); + let mut cmu = vec![]; + note.cm(&JUBJUB).into_repr().write_le(&mut cmu).unwrap(); + let mut epk = vec![]; + encryptor.epk().write(&mut epk).unwrap(); + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + + // Create a fake CompactBlock containing the note + let mut cb = CompactBlock::new(); + cb.set_height(height as u64); + + let mut cout = CompactOutput::new(); + cout.set_cmu(cmu); + cout.set_epk(epk); + cout.set_ciphertext(enc_ciphertext[..52].to_vec()); + let mut ctx = CompactTx::new(); + let mut txid = vec![0; 32]; + rng.fill_bytes(&mut txid); + ctx.set_hash(txid); + ctx.outputs.push(cout); + cb.vtx.push(ctx); + + cb + } + + #[test] + fn scan_block_with_my_tx() { + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + + let cb = fake_compact_block(1, extfvk.clone(), Amount::from_u64(5).unwrap()); + + let txs = scan_block(cb, &[extfvk]); + assert_eq!(txs.len(), 1); + + let tx = &txs[0]; + assert_eq!(tx.num_spends, 0); + assert_eq!(tx.num_outputs, 1); + assert_eq!(tx.shielded_outputs.len(), 1); + assert_eq!(tx.shielded_outputs[0].index, 0); + assert_eq!(tx.shielded_outputs[0].account, 0); + assert_eq!(tx.shielded_outputs[0].value, 5); + } +} From c3a30b9597dce0e1812ece6654bea85e80985b1b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 2 Dec 2018 12:14:02 +0000 Subject: [PATCH 079/105] Increment the commitment tree and witnesses while scanning blocks --- zcash_client_backend/src/welding_rig.rs | 180 ++++++++++++++++-------- 1 file changed, 123 insertions(+), 57 deletions(-) diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 26273e5..253419c 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -4,23 +4,31 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use zcash_primitives::{ jubjub::{edwards, fs::Fs}, + merkle_tree::{CommitmentTree, IncrementalWitness}, note_encryption::try_sapling_compact_note_decryption, + sapling::Node, transaction::TxId, zip32::ExtendedFullViewingKey, JUBJUB, }; -use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactTx}; +use crate::proto::compact_formats::{CompactBlock, CompactOutput}; use crate::wallet::{EncCiphertextFrag, WalletShieldedOutput, WalletTx}; /// Scans a [`CompactOutput`] with a set of [`ExtendedFullViewingKey`]s. /// -/// Returns a [`WalletShieldedOutput`] if this output belongs to any of the given -/// [`ExtendedFullViewingKey`]s. +/// Returns a [`WalletShieldedOutput`] and corresponding [`IncrementalWitness`] if this +/// output belongs to any of the given [`ExtendedFullViewingKey`]s. +/// +/// The given [`CommitmentTree`] and existing [`IncrementalWitness`]es are incremented +/// with this output's commitment. fn scan_output( (index, output): (usize, CompactOutput), ivks: &[Fs], -) -> Option { + tree: &mut CommitmentTree, + existing_witnesses: &mut [&mut IncrementalWitness], + new_witnesses: &mut [IncrementalWitness], +) -> Option<(WalletShieldedOutput, IncrementalWitness)> { let mut repr = FrRepr::default(); if repr.read_le(&output.cmu[..]).is_err() { return None; @@ -40,6 +48,16 @@ fn scan_output( let ct = output.ciphertext; + // Increment tree and witnesses + let node = Node::new(cmu.into_repr()); + for witness in existing_witnesses { + witness.append(node).unwrap(); + } + for witness in new_witnesses { + witness.append(node).unwrap(); + } + tree.append(node).unwrap(); + for (account, ivk) in ivks.iter().enumerate() { let value = match try_sapling_compact_note_decryption(ivk, &epk, &cmu, &ct) { Some((note, _)) => note.value, @@ -50,71 +68,80 @@ fn scan_output( let mut enc_ct = EncCiphertextFrag([0u8; 52]); enc_ct.0.copy_from_slice(&ct); - return Some(WalletShieldedOutput { - index, - cmu, - epk, - enc_ct, - account, - value, - }); + return Some(( + WalletShieldedOutput { + index, + cmu, + epk, + enc_ct, + account, + value, + }, + IncrementalWitness::from_tree(tree), + )); } None } -/// Scans a [`CompactTx`] with a set of [`ExtendedFullViewingKey`]s. -/// -/// Returns a [`WalletTx`] if this transaction belongs to any of the given -/// [`ExtendedFullViewingKey`]s. -fn scan_tx(tx: CompactTx, extfvks: &[ExtendedFullViewingKey]) -> Option { - let num_spends = tx.spends.len(); - let num_outputs = tx.outputs.len(); - - // Check for incoming notes - let shielded_outputs: Vec = { - let ivks: Vec<_> = extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); - tx.outputs - .into_iter() - .enumerate() - .filter_map(|(index, output)| scan_output((index, output), &ivks)) - .collect() - }; - - if shielded_outputs.is_empty() { - None - } else { - let mut txid = TxId([0u8; 32]); - txid.0.copy_from_slice(&tx.hash); - Some(WalletTx { - txid, - num_spends, - num_outputs, - shielded_outputs, - }) - } -} - -/// Scans a [`CompactBlock`] for transactions belonging to a set of -/// [`ExtendedFullViewingKey`]s. +/// Scans a [`CompactBlock`] with a set of [`ExtendedFullViewingKey`]s. /// /// Returns a vector of [`WalletTx`]s belonging to any of the given -/// [`ExtendedFullViewingKey`]s. -pub fn scan_block(block: CompactBlock, extfvks: &[ExtendedFullViewingKey]) -> Vec { - block - .vtx - .into_iter() - .filter_map(|tx| scan_tx(tx, extfvks)) - .collect() +/// [`ExtendedFullViewingKey`]s, and the corresponding new [`IncrementalWitness`]es. +/// +/// The given [`CommitmentTree`] and existing [`IncrementalWitness`]es are +/// incremented appropriately. +pub fn scan_block( + block: CompactBlock, + extfvks: &[ExtendedFullViewingKey], + tree: &mut CommitmentTree, + existing_witnesses: &mut [&mut IncrementalWitness], +) -> Vec<(WalletTx, Vec>)> { + let mut wtxs = vec![]; + let ivks: Vec<_> = extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); + + for tx in block.vtx.into_iter() { + let num_spends = tx.spends.len(); + let num_outputs = tx.outputs.len(); + + // Check for incoming notes while incrementing tree and witnesses + let mut shielded_outputs = vec![]; + let mut new_witnesses = vec![]; + for to_scan in tx.outputs.into_iter().enumerate() { + if let Some((output, new_witness)) = + scan_output(to_scan, &ivks, tree, existing_witnesses, &mut new_witnesses) + { + shielded_outputs.push(output); + new_witnesses.push(new_witness); + } + } + + if !shielded_outputs.is_empty() { + let mut txid = TxId([0u8; 32]); + txid.0.copy_from_slice(&tx.hash); + wtxs.push(( + WalletTx { + txid, + num_spends, + num_outputs, + shielded_outputs, + }, + new_witnesses, + )); + } + } + + wtxs } #[cfg(test)] mod tests { use ff::{Field, PrimeField, PrimeFieldRepr}; - use pairing::bls12_381::Bls12; + use pairing::bls12_381::{Bls12, Fr}; use rand_core::RngCore; use rand_os::OsRng; use zcash_primitives::{ - jubjub::fs::Fs, + jubjub::{fs::Fs, FixedGenerators, JubjubParams, ToUniform}, + merkle_tree::CommitmentTree, note_encryption::{Memo, SaplingNoteEncryption}, primitives::Note, transaction::components::Amount, @@ -125,6 +152,36 @@ mod tests { use super::scan_block; use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactTx}; + fn random_compact_tx(rng: &mut R) -> CompactTx { + let fake_cmu = { + let fake_cmu = Fr::random(rng); + let mut bytes = vec![]; + fake_cmu.into_repr().write_le(&mut bytes).unwrap(); + bytes + }; + let fake_epk = { + let mut buffer = vec![0; 64]; + rng.fill_bytes(&mut buffer); + let fake_esk = Fs::to_uniform(&buffer[..]); + let fake_epk = JUBJUB + .generator(FixedGenerators::SpendingKeyGenerator) + .mul(fake_esk, &JUBJUB); + let mut bytes = vec![]; + fake_epk.write(&mut bytes).unwrap(); + bytes + }; + let mut cout = CompactOutput::new(); + cout.set_cmu(fake_cmu); + cout.set_epk(fake_epk); + cout.set_ciphertext(vec![0; 52]); + let mut ctx = CompactTx::new(); + let mut txid = vec![0; 32]; + rng.fill_bytes(&mut txid); + ctx.set_hash(txid); + ctx.outputs.push(cout); + ctx + } + /// Create a fake CompactBlock at the given height, containing a single output paying /// the given address. Returns the CompactBlock and the nullifier for the new note. fn fake_compact_block( @@ -159,6 +216,9 @@ mod tests { let mut cb = CompactBlock::new(); cb.set_height(height as u64); + // Add a random Sapling tx before ours + cb.vtx.push(random_compact_tx(&mut rng)); + let mut cout = CompactOutput::new(); cout.set_cmu(cmu); cout.set_epk(epk); @@ -179,16 +239,22 @@ mod tests { let extfvk = ExtendedFullViewingKey::from(&extsk); let cb = fake_compact_block(1, extfvk.clone(), Amount::from_u64(5).unwrap()); + assert_eq!(cb.vtx.len(), 2); - let txs = scan_block(cb, &[extfvk]); + let mut tree = CommitmentTree::new(); + let txs = scan_block(cb, &[extfvk], &mut tree, &mut []); assert_eq!(txs.len(), 1); - let tx = &txs[0]; + let (tx, new_witnesses) = &txs[0]; assert_eq!(tx.num_spends, 0); assert_eq!(tx.num_outputs, 1); assert_eq!(tx.shielded_outputs.len(), 1); assert_eq!(tx.shielded_outputs[0].index, 0); assert_eq!(tx.shielded_outputs[0].account, 0); assert_eq!(tx.shielded_outputs[0].value, 5); + + // Check that the witness root matches + assert_eq!(new_witnesses.len(), 1); + assert_eq!(new_witnesses[0].root(), tree.root()); } } From 8b353b3d55643761902d74c2f0c541bff7d006ce Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 2 Dec 2018 19:15:04 +0000 Subject: [PATCH 080/105] Return the entire note and recipient address when scanning an output --- zcash_client_backend/src/wallet.rs | 7 +++---- zcash_client_backend/src/welding_rig.rs | 16 ++++++---------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs index 4e85eef..a20b09f 100644 --- a/zcash_client_backend/src/wallet.rs +++ b/zcash_client_backend/src/wallet.rs @@ -4,11 +4,10 @@ use pairing::bls12_381::{Bls12, Fr}; use zcash_primitives::{ jubjub::{edwards, PrimeOrder}, + primitives::{Note, PaymentAddress}, transaction::TxId, }; -pub struct EncCiphertextFrag(pub [u8; 52]); - /// A subset of a [`Transaction`] relevant to wallets and light clients. /// /// [`Transaction`]: zcash_primitives::transaction::Transaction @@ -26,7 +25,7 @@ pub struct WalletShieldedOutput { pub index: usize, pub cmu: Fr, pub epk: edwards::Point, - pub enc_ct: EncCiphertextFrag, pub account: usize, - pub value: u64, + pub note: Note, + pub to: PaymentAddress, } diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 253419c..745efab 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -13,7 +13,7 @@ use zcash_primitives::{ }; use crate::proto::compact_formats::{CompactBlock, CompactOutput}; -use crate::wallet::{EncCiphertextFrag, WalletShieldedOutput, WalletTx}; +use crate::wallet::{WalletShieldedOutput, WalletTx}; /// Scans a [`CompactOutput`] with a set of [`ExtendedFullViewingKey`]s. /// @@ -59,23 +59,19 @@ fn scan_output( tree.append(node).unwrap(); for (account, ivk) in ivks.iter().enumerate() { - let value = match try_sapling_compact_note_decryption(ivk, &epk, &cmu, &ct) { - Some((note, _)) => note.value, + let (note, to) = match try_sapling_compact_note_decryption(ivk, &epk, &cmu, &ct) { + Some(ret) => ret, None => continue, }; - // It's ours, so let's copy the ciphertext fragment and return - let mut enc_ct = EncCiphertextFrag([0u8; 52]); - enc_ct.0.copy_from_slice(&ct); - return Some(( WalletShieldedOutput { index, cmu, epk, - enc_ct, account, - value, + note, + to, }, IncrementalWitness::from_tree(tree), )); @@ -251,7 +247,7 @@ mod tests { assert_eq!(tx.shielded_outputs.len(), 1); assert_eq!(tx.shielded_outputs[0].index, 0); assert_eq!(tx.shielded_outputs[0].account, 0); - assert_eq!(tx.shielded_outputs[0].value, 5); + assert_eq!(tx.shielded_outputs[0].note.value, 5); // Check that the witness root matches assert_eq!(new_witnesses.len(), 1); From 9c51f3426b117354e540ea09cac84aff60107dd0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 4 Dec 2018 14:03:12 +0000 Subject: [PATCH 081/105] Check for spent notes while scanning blocks --- zcash_client_backend/src/wallet.rs | 9 ++++ zcash_client_backend/src/welding_rig.rs | 72 ++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs index a20b09f..c120ba5 100644 --- a/zcash_client_backend/src/wallet.rs +++ b/zcash_client_backend/src/wallet.rs @@ -15,9 +15,18 @@ pub struct WalletTx { pub txid: TxId, pub num_spends: usize, pub num_outputs: usize, + pub shielded_spends: Vec, pub shielded_outputs: Vec, } +/// A subset of a [`SpendDescription`] relevant to wallets and light clients. +/// +/// [`SpendDescription`]: zcash_primitives::transaction::components::SpendDescription +pub struct WalletShieldedSpend { + pub index: usize, + pub nf: Vec, +} + /// A subset of an [`OutputDescription`] relevant to wallets and light clients. /// /// [`OutputDescription`]: zcash_primitives::transaction::components::OutputDescription diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 745efab..1354b6e 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -13,7 +13,7 @@ use zcash_primitives::{ }; use crate::proto::compact_formats::{CompactBlock, CompactOutput}; -use crate::wallet::{WalletShieldedOutput, WalletTx}; +use crate::wallet::{WalletShieldedOutput, WalletShieldedSpend, WalletTx}; /// Scans a [`CompactOutput`] with a set of [`ExtendedFullViewingKey`]s. /// @@ -89,6 +89,7 @@ fn scan_output( pub fn scan_block( block: CompactBlock, extfvks: &[ExtendedFullViewingKey], + nullifiers: &[&[u8]], tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], ) -> Vec<(WalletTx, Vec>)> { @@ -99,6 +100,23 @@ pub fn scan_block( let num_spends = tx.spends.len(); let num_outputs = tx.outputs.len(); + // Check for spent notes + let shielded_spends: Vec<_> = tx + .spends + .into_iter() + .enumerate() + .filter_map(|(index, spend)| { + if nullifiers.contains(&&spend.nf[..]) { + Some(WalletShieldedSpend { + index, + nf: spend.nf, + }) + } else { + None + } + }) + .collect(); + // Check for incoming notes while incrementing tree and witnesses let mut shielded_outputs = vec![]; let mut new_witnesses = vec![]; @@ -111,7 +129,7 @@ pub fn scan_block( } } - if !shielded_outputs.is_empty() { + if !(shielded_spends.is_empty() && shielded_outputs.is_empty()) { let mut txid = TxId([0u8; 32]); txid.0.copy_from_slice(&tx.hash); wtxs.push(( @@ -119,6 +137,7 @@ pub fn scan_block( txid, num_spends, num_outputs, + shielded_spends, shielded_outputs, }, new_witnesses, @@ -146,9 +165,14 @@ mod tests { }; use super::scan_block; - use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactTx}; + use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactSpend, CompactTx}; fn random_compact_tx(rng: &mut R) -> CompactTx { + let fake_nf = { + let mut nf = vec![0; 32]; + rng.fill_bytes(&mut nf); + nf + }; let fake_cmu = { let fake_cmu = Fr::random(rng); let mut bytes = vec![]; @@ -166,6 +190,8 @@ mod tests { fake_epk.write(&mut bytes).unwrap(); bytes }; + let mut cspend = CompactSpend::new(); + cspend.set_nf(fake_nf); let mut cout = CompactOutput::new(); cout.set_cmu(fake_cmu); cout.set_epk(fake_epk); @@ -174,14 +200,17 @@ mod tests { let mut txid = vec![0; 32]; rng.fill_bytes(&mut txid); ctx.set_hash(txid); + ctx.spends.push(cspend); ctx.outputs.push(cout); ctx } - /// Create a fake CompactBlock at the given height, containing a single output paying - /// the given address. Returns the CompactBlock and the nullifier for the new note. + /// Create a fake CompactBlock at the given height, with a transaction containing a + /// single spend of the given nullifier and a single output paying the given address. + /// Returns the CompactBlock. fn fake_compact_block( height: i32, + nf: [u8; 32], extfvk: ExtendedFullViewingKey, value: Amount, ) -> CompactBlock { @@ -215,6 +244,8 @@ mod tests { // Add a random Sapling tx before ours cb.vtx.push(random_compact_tx(&mut rng)); + let mut cspend = CompactSpend::new(); + cspend.set_nf(nf.to_vec()); let mut cout = CompactOutput::new(); cout.set_cmu(cmu); cout.set_epk(epk); @@ -223,6 +254,7 @@ mod tests { let mut txid = vec![0; 32]; rng.fill_bytes(&mut txid); ctx.set_hash(txid); + ctx.spends.push(cspend); ctx.outputs.push(cout); cb.vtx.push(ctx); @@ -234,16 +266,17 @@ mod tests { let extsk = ExtendedSpendingKey::master(&[]); let extfvk = ExtendedFullViewingKey::from(&extsk); - let cb = fake_compact_block(1, extfvk.clone(), Amount::from_u64(5).unwrap()); + let cb = fake_compact_block(1, [0; 32], extfvk.clone(), Amount::from_u64(5).unwrap()); assert_eq!(cb.vtx.len(), 2); let mut tree = CommitmentTree::new(); - let txs = scan_block(cb, &[extfvk], &mut tree, &mut []); + let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []); assert_eq!(txs.len(), 1); let (tx, new_witnesses) = &txs[0]; - assert_eq!(tx.num_spends, 0); + assert_eq!(tx.num_spends, 1); assert_eq!(tx.num_outputs, 1); + assert_eq!(tx.shielded_spends.len(), 0); assert_eq!(tx.shielded_outputs.len(), 1); assert_eq!(tx.shielded_outputs[0].index, 0); assert_eq!(tx.shielded_outputs[0].account, 0); @@ -253,4 +286,27 @@ mod tests { assert_eq!(new_witnesses.len(), 1); assert_eq!(new_witnesses[0].root(), tree.root()); } + + #[test] + fn scan_block_with_my_spend() { + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + let nf = [7; 32]; + + let cb = fake_compact_block(1, nf, extfvk, Amount::from_u64(5).unwrap()); + assert_eq!(cb.vtx.len(), 2); + + let mut tree = CommitmentTree::new(); + let txs = scan_block(cb, &[], &[&nf], &mut tree, &mut []); + assert_eq!(txs.len(), 1); + + let (tx, new_witnesses) = &txs[0]; + assert_eq!(tx.num_spends, 1); + assert_eq!(tx.num_outputs, 1); + assert_eq!(tx.shielded_spends.len(), 1); + assert_eq!(tx.shielded_outputs.len(), 0); + assert_eq!(tx.shielded_spends[0].index, 0); + assert_eq!(tx.shielded_spends[0].nf, nf); + assert_eq!(new_witnesses.len(), 0); + } } From c1e6b1844c7ddf87552b118c4d801544dd0647f7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 11 Jan 2019 14:26:54 -0800 Subject: [PATCH 082/105] Detect change notes while scanning blocks --- zcash_client_backend/src/wallet.rs | 2 + zcash_client_backend/src/welding_rig.rs | 69 ++++++++++++++++++------- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs index c120ba5..22df1cb 100644 --- a/zcash_client_backend/src/wallet.rs +++ b/zcash_client_backend/src/wallet.rs @@ -25,6 +25,7 @@ pub struct WalletTx { pub struct WalletShieldedSpend { pub index: usize, pub nf: Vec, + pub account: usize, } /// A subset of an [`OutputDescription`] relevant to wallets and light clients. @@ -37,4 +38,5 @@ pub struct WalletShieldedOutput { pub account: usize, pub note: Note, pub to: PaymentAddress, + pub is_change: bool, } diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 1354b6e..f6310a7 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -2,6 +2,7 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use std::collections::HashSet; use zcash_primitives::{ jubjub::{edwards, fs::Fs}, merkle_tree::{CommitmentTree, IncrementalWitness}, @@ -25,6 +26,7 @@ use crate::wallet::{WalletShieldedOutput, WalletShieldedSpend, WalletTx}; fn scan_output( (index, output): (usize, CompactOutput), ivks: &[Fs], + spent_from_accounts: &HashSet, tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], new_witnesses: &mut [IncrementalWitness], @@ -64,6 +66,14 @@ fn scan_output( None => continue, }; + // A note is marked as "change" if the account that received it + // also spent notes in the same transaction. This will catch, + // for instance: + // - Change created by spending fractions of notes. + // - Notes created by consolidation transactions. + // - Notes sent from one account to itself. + let is_change = spent_from_accounts.contains(&account); + return Some(( WalletShieldedOutput { index, @@ -72,6 +82,7 @@ fn scan_output( account, note, to, + is_change, }, IncrementalWitness::from_tree(tree), )); @@ -89,7 +100,7 @@ fn scan_output( pub fn scan_block( block: CompactBlock, extfvks: &[ExtendedFullViewingKey], - nullifiers: &[&[u8]], + nullifiers: &[(&[u8], usize)], tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], ) -> Vec<(WalletTx, Vec>)> { @@ -101,29 +112,45 @@ pub fn scan_block( let num_outputs = tx.outputs.len(); // Check for spent notes - let shielded_spends: Vec<_> = tx - .spends - .into_iter() - .enumerate() - .filter_map(|(index, spend)| { - if nullifiers.contains(&&spend.nf[..]) { - Some(WalletShieldedSpend { - index, - nf: spend.nf, - }) - } else { - None - } - }) - .collect(); + let shielded_spends: Vec<_> = + tx.spends + .into_iter() + .enumerate() + .filter_map(|(index, spend)| { + if let Some(account) = nullifiers.iter().find_map(|&(nf, acc)| { + if nf == &spend.nf[..] { + Some(acc) + } else { + None + } + }) { + Some(WalletShieldedSpend { + index, + nf: spend.nf, + account, + }) + } else { + None + } + }) + .collect(); + + // Collect the set of accounts that were spent from in this transaction + let spent_from_accounts: HashSet<_> = + shielded_spends.iter().map(|spend| spend.account).collect(); // Check for incoming notes while incrementing tree and witnesses let mut shielded_outputs = vec![]; let mut new_witnesses = vec![]; for to_scan in tx.outputs.into_iter().enumerate() { - if let Some((output, new_witness)) = - scan_output(to_scan, &ivks, tree, existing_witnesses, &mut new_witnesses) - { + if let Some((output, new_witness)) = scan_output( + to_scan, + &ivks, + &spent_from_accounts, + tree, + existing_witnesses, + &mut new_witnesses, + ) { shielded_outputs.push(output); new_witnesses.push(new_witness); } @@ -292,12 +319,13 @@ mod tests { let extsk = ExtendedSpendingKey::master(&[]); let extfvk = ExtendedFullViewingKey::from(&extsk); let nf = [7; 32]; + let account = 12; let cb = fake_compact_block(1, nf, extfvk, Amount::from_u64(5).unwrap()); assert_eq!(cb.vtx.len(), 2); let mut tree = CommitmentTree::new(); - let txs = scan_block(cb, &[], &[&nf], &mut tree, &mut []); + let txs = scan_block(cb, &[], &[(&nf, account)], &mut tree, &mut []); assert_eq!(txs.len(), 1); let (tx, new_witnesses) = &txs[0]; @@ -307,6 +335,7 @@ mod tests { assert_eq!(tx.shielded_outputs.len(), 0); assert_eq!(tx.shielded_spends[0].index, 0); assert_eq!(tx.shielded_spends[0].nf, nf); + assert_eq!(tx.shielded_spends[0].account, account); assert_eq!(new_witnesses.len(), 0); } } From 36f1ef62de4a74de19493990517c7b71551b2dc5 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 24 Jan 2019 23:26:14 +0000 Subject: [PATCH 083/105] Add tx index within block to WalletTx struct --- zcash_client_backend/src/wallet.rs | 1 + zcash_client_backend/src/welding_rig.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs index 22df1cb..dd5229b 100644 --- a/zcash_client_backend/src/wallet.rs +++ b/zcash_client_backend/src/wallet.rs @@ -13,6 +13,7 @@ use zcash_primitives::{ /// [`Transaction`]: zcash_primitives::transaction::Transaction pub struct WalletTx { pub txid: TxId, + pub index: usize, pub num_spends: usize, pub num_outputs: usize, pub shielded_spends: Vec, diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index f6310a7..226ae29 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -162,6 +162,7 @@ pub fn scan_block( wtxs.push(( WalletTx { txid, + index: tx.index as usize, num_spends, num_outputs, shielded_spends, @@ -269,7 +270,11 @@ mod tests { cb.set_height(height as u64); // Add a random Sapling tx before ours - cb.vtx.push(random_compact_tx(&mut rng)); + { + let mut tx = random_compact_tx(&mut rng); + tx.index = cb.vtx.len() as u64; + cb.vtx.push(tx); + } let mut cspend = CompactSpend::new(); cspend.set_nf(nf.to_vec()); @@ -283,6 +288,7 @@ mod tests { ctx.set_hash(txid); ctx.spends.push(cspend); ctx.outputs.push(cout); + ctx.index = cb.vtx.len() as u64; cb.vtx.push(ctx); cb @@ -301,6 +307,7 @@ mod tests { assert_eq!(txs.len(), 1); let (tx, new_witnesses) = &txs[0]; + assert_eq!(tx.index, 1); assert_eq!(tx.num_spends, 1); assert_eq!(tx.num_outputs, 1); assert_eq!(tx.shielded_spends.len(), 0); @@ -329,6 +336,7 @@ mod tests { assert_eq!(txs.len(), 1); let (tx, new_witnesses) = &txs[0]; + assert_eq!(tx.index, 1); assert_eq!(tx.num_spends, 1); assert_eq!(tx.num_outputs, 1); assert_eq!(tx.shielded_spends.len(), 1); From 2e038207f009fabf03621b408db805ec6395a23b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 14 Feb 2019 18:06:50 +0000 Subject: [PATCH 084/105] Update new witnesses with subsequent transactions in the same block --- zcash_client_backend/src/welding_rig.rs | 91 +++++++++++++++++++++---- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 226ae29..565e6d8 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -29,6 +29,7 @@ fn scan_output( spent_from_accounts: &HashSet, tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], + block_witnesses: &mut [&mut IncrementalWitness], new_witnesses: &mut [IncrementalWitness], ) -> Option<(WalletShieldedOutput, IncrementalWitness)> { let mut repr = FrRepr::default(); @@ -55,6 +56,9 @@ fn scan_output( for witness in existing_witnesses { witness.append(node).unwrap(); } + for witness in block_witnesses { + witness.append(node).unwrap(); + } for witness in new_witnesses { witness.append(node).unwrap(); } @@ -104,7 +108,7 @@ pub fn scan_block( tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], ) -> Vec<(WalletTx, Vec>)> { - let mut wtxs = vec![]; + let mut wtxs: Vec<(WalletTx, Vec>)> = vec![]; let ivks: Vec<_> = extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); for tx in block.vtx.into_iter() { @@ -142,17 +146,29 @@ pub fn scan_block( // Check for incoming notes while incrementing tree and witnesses let mut shielded_outputs = vec![]; let mut new_witnesses = vec![]; - for to_scan in tx.outputs.into_iter().enumerate() { - if let Some((output, new_witness)) = scan_output( - to_scan, - &ivks, - &spent_from_accounts, - tree, - existing_witnesses, - &mut new_witnesses, - ) { - shielded_outputs.push(output); - new_witnesses.push(new_witness); + { + // Grab mutable references to new witnesses from previous transactions + // in this block so that we can update them. Scoped so we don't hold + // mutable references to wtxs for too long. + let mut block_witnesses: Vec<_> = wtxs + .iter_mut() + .map(|(_, w)| w.iter_mut().collect::>()) + .flatten() + .collect(); + + for to_scan in tx.outputs.into_iter().enumerate() { + if let Some((output, new_witness)) = scan_output( + to_scan, + &ivks, + &spent_from_accounts, + tree, + existing_witnesses, + &mut block_witnesses, + &mut new_witnesses, + ) { + shielded_outputs.push(output); + new_witnesses.push(new_witness); + } } } @@ -241,6 +257,7 @@ mod tests { nf: [u8; 32], extfvk: ExtendedFullViewingKey, value: Amount, + tx_after: bool, ) -> CompactBlock { let to = extfvk.default_address().unwrap().1; @@ -291,6 +308,13 @@ mod tests { ctx.index = cb.vtx.len() as u64; cb.vtx.push(ctx); + // Optionally add another random Sapling tx after ours + if tx_after { + let mut tx = random_compact_tx(&mut rng); + tx.index = cb.vtx.len() as u64; + cb.vtx.push(tx); + } + cb } @@ -299,7 +323,13 @@ mod tests { let extsk = ExtendedSpendingKey::master(&[]); let extfvk = ExtendedFullViewingKey::from(&extsk); - let cb = fake_compact_block(1, [0; 32], extfvk.clone(), Amount::from_u64(5).unwrap()); + let cb = fake_compact_block( + 1, + [0; 32], + extfvk.clone(), + Amount::from_u64(5).unwrap(), + false, + ); assert_eq!(cb.vtx.len(), 2); let mut tree = CommitmentTree::new(); @@ -321,6 +351,39 @@ mod tests { assert_eq!(new_witnesses[0].root(), tree.root()); } + #[test] + fn scan_block_with_txs_after_my_tx() { + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + + let cb = fake_compact_block( + 1, + [0; 32], + extfvk.clone(), + Amount::from_u64(5).unwrap(), + true, + ); + assert_eq!(cb.vtx.len(), 3); + + let mut tree = CommitmentTree::new(); + let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []); + assert_eq!(txs.len(), 1); + + let (tx, new_witnesses) = &txs[0]; + assert_eq!(tx.index, 1); + assert_eq!(tx.num_spends, 1); + assert_eq!(tx.num_outputs, 1); + assert_eq!(tx.shielded_spends.len(), 0); + assert_eq!(tx.shielded_outputs.len(), 1); + assert_eq!(tx.shielded_outputs[0].index, 0); + assert_eq!(tx.shielded_outputs[0].account, 0); + assert_eq!(tx.shielded_outputs[0].note.value, 5); + + // Check that the witness root matches + assert_eq!(new_witnesses.len(), 1); + assert_eq!(new_witnesses[0].root(), tree.root()); + } + #[test] fn scan_block_with_my_spend() { let extsk = ExtendedSpendingKey::master(&[]); @@ -328,7 +391,7 @@ mod tests { let nf = [7; 32]; let account = 12; - let cb = fake_compact_block(1, nf, extfvk, Amount::from_u64(5).unwrap()); + let cb = fake_compact_block(1, nf, extfvk, Amount::from_u64(5).unwrap(), false); assert_eq!(cb.vtx.len(), 2); let mut tree = CommitmentTree::new(); From fd87121244d94454cfb3b40e99760beeb0cca8ea Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 1 May 2019 00:08:54 +0100 Subject: [PATCH 085/105] Compute and store BlockHash inside BlockHeader --- zcash_primitives/src/block.rs | 39 +++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/zcash_primitives/src/block.rs b/zcash_primitives/src/block.rs index 05b65e0..deeab19 100644 --- a/zcash_primitives/src/block.rs +++ b/zcash_primitives/src/block.rs @@ -1,5 +1,6 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use hex; +use sha2::{Digest, Sha256}; use std::fmt; use std::io::{self, Read, Write}; use std::ops::Deref; @@ -18,13 +19,16 @@ impl fmt::Display for BlockHash { } /// A Zcash block header. -pub struct BlockHeader(BlockHeaderData); +pub struct BlockHeader { + hash: BlockHash, + data: BlockHeaderData, +} impl Deref for BlockHeader { type Target = BlockHeaderData; fn deref(&self) -> &BlockHeaderData { - &self.0 + &self.data } } @@ -40,12 +44,31 @@ pub struct BlockHeaderData { } impl BlockHeaderData { - pub fn freeze(self) -> BlockHeader { - BlockHeader(self) + pub fn freeze(self) -> io::Result { + BlockHeader::from_data(self) } } impl BlockHeader { + fn from_data(data: BlockHeaderData) -> io::Result { + let mut header = BlockHeader { + hash: BlockHash([0; 32]), + data, + }; + let mut raw = vec![]; + header.write(&mut raw)?; + header + .hash + .0 + .copy_from_slice(&Sha256::digest(&Sha256::digest(&raw))); + Ok(header) + } + + /// Returns the hash of this header. + pub fn hash(&self) -> BlockHash { + self.hash + } + pub fn read(mut reader: R) -> io::Result { let version = reader.read_i32::()?; @@ -66,7 +89,7 @@ impl BlockHeader { let solution = Vector::read(&mut reader, |r| r.read_u8())?; - Ok(BlockHeader(BlockHeaderData { + BlockHeader::from_data(BlockHeaderData { version, prev_block, merkle_root, @@ -75,7 +98,7 @@ impl BlockHeader { bits, nonce, solution, - })) + }) } pub fn write(&self, mut writer: W) -> io::Result<()> { @@ -202,6 +225,10 @@ mod tests { #[test] fn header_read_write() { let header = BlockHeader::read(&HEADER_MAINNET_415000[..]).unwrap(); + assert_eq!( + format!("{}", header.hash()), + "0000000001ab37793ce771262b2ffa082519aa3fe891250a1adb43baaf856168" + ); let mut encoded = Vec::with_capacity(HEADER_MAINNET_415000.len()); header.write(&mut encoded).unwrap(); assert_eq!(&HEADER_MAINNET_415000[..], &encoded[..]); From 2774d2730ffc97c6136aa101eb7ccf74a5da5c23 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 1 May 2019 13:21:48 +0100 Subject: [PATCH 086/105] Add prevHash field to CompactBlock This enables basic verification of chain validity when CompactBlocks are received without the full header. --- .../proto/compact_formats.proto | 7 +-- zcash_client_backend/src/proto/mod.rs | 51 +++++++++++++++++++ zcash_primitives/src/block.rs | 14 +++++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/zcash_client_backend/proto/compact_formats.proto b/zcash_client_backend/proto/compact_formats.proto index d65b658..7e1bc54 100644 --- a/zcash_client_backend/proto/compact_formats.proto +++ b/zcash_client_backend/proto/compact_formats.proto @@ -13,9 +13,10 @@ message CompactBlock { uint32 protoVersion = 1; // the version of this wire format, for storage uint64 height = 2; // the height of this block bytes hash = 3; - uint32 time = 4; - bytes header = 5; // (hash and time) OR (full header) - repeated CompactTx vtx = 6; // compact transactions from this block + bytes prevHash = 4; + uint32 time = 5; + bytes header = 6; // (hash, prevHash, and time) OR (full header) + repeated CompactTx vtx = 7; // compact transactions from this block } message CompactTx { diff --git a/zcash_client_backend/src/proto/mod.rs b/zcash_client_backend/src/proto/mod.rs index e24ef5c..50d562b 100644 --- a/zcash_client_backend/src/proto/mod.rs +++ b/zcash_client_backend/src/proto/mod.rs @@ -1,3 +1,54 @@ //! Generated code for handling light client protobuf structs. +use zcash_primitives::block::{BlockHash, BlockHeader}; + pub mod compact_formats; + +impl compact_formats::CompactBlock { + /// Returns the [`BlockHash`] for this block. + /// + /// # Panics + /// + /// This function will panic if [`CompactBlock.header`] is not set and + /// [`CompactBlock.hash`] is not exactly 32 bytes. + /// + /// [`CompactBlock.header`]: #structfield.header + /// [`CompactBlock.hash`]: #structfield.hash + pub fn hash(&self) -> BlockHash { + if let Some(header) = self.header() { + header.hash() + } else { + BlockHash::from_slice(&self.hash) + } + } + + /// Returns the [`BlockHash`] for this block's parent. + /// + /// # Panics + /// + /// This function will panic if [`CompactBlock.header`] is not set and + /// [`CompactBlock.prevHash`] is not exactly 32 bytes. + /// + /// [`CompactBlock.header`]: #structfield.header + /// [`CompactBlock.prevHash`]: #structfield.prevHash + pub fn prev_hash(&self) -> BlockHash { + if let Some(header) = self.header() { + header.prev_block + } else { + BlockHash::from_slice(&self.prevHash) + } + } + + /// Returns the [`BlockHeader`] for this block if present. + /// + /// A convenience method that parses [`CompactBlock.header`] if present. + /// + /// [`CompactBlock.header`]: #structfield.header + pub fn header(&self) -> Option { + if self.header.is_empty() { + None + } else { + BlockHeader::read(&self.header[..]).ok() + } + } +} diff --git a/zcash_primitives/src/block.rs b/zcash_primitives/src/block.rs index deeab19..dc9181d 100644 --- a/zcash_primitives/src/block.rs +++ b/zcash_primitives/src/block.rs @@ -18,6 +18,20 @@ impl fmt::Display for BlockHash { } } +impl BlockHash { + /// Constructs a [`BlockHash`] from the given slice. + /// + /// # Panics + /// + /// This function will panic if the slice is not exactly 32 bytes. + pub fn from_slice(bytes: &[u8]) -> Self { + assert_eq!(bytes.len(), 32); + let mut hash = [0; 32]; + hash.copy_from_slice(&bytes); + BlockHash(hash) + } +} + /// A Zcash block header. pub struct BlockHeader { hash: BlockHash, From 2bafc688ff5701d1f5531680b9ecd231ced543e1 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 22 Aug 2019 00:57:04 +0100 Subject: [PATCH 087/105] Test nullifiers in constant time Checking for spent notes in a block is still not completely constant time, due to filtering out negative results of the constant-time comparison. Part of #84. --- Cargo.lock | 7 ++++ zcash_client_backend/Cargo.toml | 1 + zcash_client_backend/src/welding_rig.rs | 46 +++++++++++++------------ 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9ac6c2a..f51d21b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,6 +493,11 @@ dependencies = [ "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" version = "0.14.9" @@ -545,6 +550,7 @@ dependencies = [ "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_primitives 0.0.0", ] @@ -642,6 +648,7 @@ dependencies = [ "checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967" "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index a95e5a0..ed6e502 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -12,6 +12,7 @@ ff = { path = "../ff" } hex = "0.3" pairing = { path = "../pairing" } protobuf = "2" +subtle = "2" zcash_primitives = { path = "../zcash_primitives" } [build-dependencies] diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 565e6d8..4cf64c9 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -3,6 +3,7 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::{Bls12, Fr, FrRepr}; use std::collections::HashSet; +use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_primitives::{ jubjub::{edwards, fs::Fs}, merkle_tree::{CommitmentTree, IncrementalWitness}, @@ -116,28 +117,29 @@ pub fn scan_block( let num_outputs = tx.outputs.len(); // Check for spent notes - let shielded_spends: Vec<_> = - tx.spends - .into_iter() - .enumerate() - .filter_map(|(index, spend)| { - if let Some(account) = nullifiers.iter().find_map(|&(nf, acc)| { - if nf == &spend.nf[..] { - Some(acc) - } else { - None - } - }) { - Some(WalletShieldedSpend { - index, - nf: spend.nf, - account, - }) - } else { - None - } - }) - .collect(); + // The only step that is not constant-time is the filter() at the end. + let shielded_spends: Vec<_> = tx + .spends + .into_iter() + .enumerate() + .map(|(index, spend)| { + // Find the first tracked nullifier that matches this spend, and produce + // a WalletShieldedSpend if there is a match, in constant time. + nullifiers + .iter() + .map(|&(nf, account)| CtOption::new(account as u64, nf.ct_eq(&spend.nf[..]))) + .fold(CtOption::new(0, 0.into()), |first, next| { + CtOption::conditional_select(&next, &first, first.is_some()) + }) + .map(|account| WalletShieldedSpend { + index, + nf: spend.nf, + account: account as usize, + }) + }) + .filter(|spend| spend.is_some().into()) + .map(|spend| spend.unwrap()) + .collect(); // Collect the set of accounts that were spent from in this transaction let spent_from_accounts: HashSet<_> = From 789e2ff216c7cb7f553fc03f6d220be277ddaf39 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 22 Aug 2019 15:18:50 +0100 Subject: [PATCH 088/105] Travis CI: Build before formatting check cargo fmt does not build the code, and running it in a fresh clone of the codebase will fail because the protobuf code has not been generated. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 399eaf1..4f444f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,6 @@ before_script: - rustup component add rustfmt script: + - cargo build --verbose --release --all - cargo fmt --all -- --check - cargo test --verbose --release --all From 8cd6666e56124fbe0a9749bc46fef76c539dcb86 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 26 Aug 2019 11:59:07 +0100 Subject: [PATCH 089/105] Move cmu and epk parsing onto CompactOutput struct --- zcash_client_backend/src/proto/mod.rs | 31 ++++++++++++++++++++++++- zcash_client_backend/src/welding_rig.rs | 25 ++++---------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/zcash_client_backend/src/proto/mod.rs b/zcash_client_backend/src/proto/mod.rs index 50d562b..0ab1b6d 100644 --- a/zcash_client_backend/src/proto/mod.rs +++ b/zcash_client_backend/src/proto/mod.rs @@ -1,6 +1,12 @@ //! Generated code for handling light client protobuf structs. -use zcash_primitives::block::{BlockHash, BlockHeader}; +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use zcash_primitives::{ + block::{BlockHash, BlockHeader}, + jubjub::{edwards, PrimeOrder}, + JUBJUB, +}; pub mod compact_formats; @@ -52,3 +58,26 @@ impl compact_formats::CompactBlock { } } } + +impl compact_formats::CompactOutput { + /// Returns the note commitment for this output. + /// + /// A convenience method that parses [`CompactOutput.cmu`]. + /// + /// [`CompactOutput.cmu`]: #structfield.cmu + pub fn cmu(&self) -> Result { + let mut repr = FrRepr::default(); + repr.read_le(&self.cmu[..]).map_err(|_| ())?; + Fr::from_repr(repr).map_err(|_| ()) + } + + /// Returns the ephemeral public key for this output. + /// + /// A convenience method that parses [`CompactOutput.epk`]. + /// + /// [`CompactOutput.epk`]: #structfield.epk + pub fn epk(&self) -> Result, ()> { + let p = edwards::Point::::read(&self.epk[..], &JUBJUB).map_err(|_| ())?; + p.as_prime_order(&JUBJUB).ok_or(()) + } +} diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index 4cf64c9..dd804c7 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -1,17 +1,15 @@ //! Tools for scanning a compact representation of the Zcash block chain. -use ff::{PrimeField, PrimeFieldRepr}; -use pairing::bls12_381::{Bls12, Fr, FrRepr}; +use ff::PrimeField; use std::collections::HashSet; use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_primitives::{ - jubjub::{edwards, fs::Fs}, + jubjub::fs::Fs, merkle_tree::{CommitmentTree, IncrementalWitness}, note_encryption::try_sapling_compact_note_decryption, sapling::Node, transaction::TxId, zip32::ExtendedFullViewingKey, - JUBJUB, }; use crate::proto::compact_formats::{CompactBlock, CompactOutput}; @@ -33,23 +31,8 @@ fn scan_output( block_witnesses: &mut [&mut IncrementalWitness], new_witnesses: &mut [IncrementalWitness], ) -> Option<(WalletShieldedOutput, IncrementalWitness)> { - let mut repr = FrRepr::default(); - if repr.read_le(&output.cmu[..]).is_err() { - return None; - } - let cmu = match Fr::from_repr(repr) { - Ok(cmu) => cmu, - Err(_) => return None, - }; - - let epk = match edwards::Point::::read(&output.epk[..], &JUBJUB) { - Ok(p) => match p.as_prime_order(&JUBJUB) { - Some(epk) => epk, - None => return None, - }, - Err(_) => return None, - }; - + let cmu = output.cmu().ok()?; + let epk = output.epk().ok()?; let ct = output.ciphertext; // Increment tree and witnesses From 99aef0531887b9bb3b55d28701291e84346e73bb Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 26 Aug 2019 12:12:32 +0100 Subject: [PATCH 090/105] Store witness inside WalletShieldedOutput --- zcash_client_backend/src/wallet.rs | 3 + zcash_client_backend/src/welding_rig.rs | 82 +++++++++++++------------ 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs index dd5229b..dc46a86 100644 --- a/zcash_client_backend/src/wallet.rs +++ b/zcash_client_backend/src/wallet.rs @@ -4,7 +4,9 @@ use pairing::bls12_381::{Bls12, Fr}; use zcash_primitives::{ jubjub::{edwards, PrimeOrder}, + merkle_tree::IncrementalWitness, primitives::{Note, PaymentAddress}, + sapling::Node, transaction::TxId, }; @@ -40,4 +42,5 @@ pub struct WalletShieldedOutput { pub note: Note, pub to: PaymentAddress, pub is_change: bool, + pub witness: IncrementalWitness, } diff --git a/zcash_client_backend/src/welding_rig.rs b/zcash_client_backend/src/welding_rig.rs index dd804c7..4d133d4 100644 --- a/zcash_client_backend/src/welding_rig.rs +++ b/zcash_client_backend/src/welding_rig.rs @@ -29,8 +29,8 @@ fn scan_output( tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], block_witnesses: &mut [&mut IncrementalWitness], - new_witnesses: &mut [IncrementalWitness], -) -> Option<(WalletShieldedOutput, IncrementalWitness)> { + new_witnesses: &mut [&mut IncrementalWitness], +) -> Option { let cmu = output.cmu().ok()?; let epk = output.epk().ok()?; let ct = output.ciphertext; @@ -62,18 +62,16 @@ fn scan_output( // - Notes sent from one account to itself. let is_change = spent_from_accounts.contains(&account); - return Some(( - WalletShieldedOutput { - index, - cmu, - epk, - account, - note, - to, - is_change, - }, - IncrementalWitness::from_tree(tree), - )); + return Some(WalletShieldedOutput { + index, + cmu, + epk, + account, + note, + to, + is_change, + witness: IncrementalWitness::from_tree(tree), + }); } None } @@ -91,8 +89,8 @@ pub fn scan_block( nullifiers: &[(&[u8], usize)], tree: &mut CommitmentTree, existing_witnesses: &mut [&mut IncrementalWitness], -) -> Vec<(WalletTx, Vec>)> { - let mut wtxs: Vec<(WalletTx, Vec>)> = vec![]; +) -> Vec { + let mut wtxs: Vec = vec![]; let ivks: Vec<_> = extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); for tx in block.vtx.into_iter() { @@ -129,20 +127,31 @@ pub fn scan_block( shielded_spends.iter().map(|spend| spend.account).collect(); // Check for incoming notes while incrementing tree and witnesses - let mut shielded_outputs = vec![]; - let mut new_witnesses = vec![]; + let mut shielded_outputs: Vec = vec![]; { // Grab mutable references to new witnesses from previous transactions // in this block so that we can update them. Scoped so we don't hold // mutable references to wtxs for too long. let mut block_witnesses: Vec<_> = wtxs .iter_mut() - .map(|(_, w)| w.iter_mut().collect::>()) + .map(|tx| { + tx.shielded_outputs + .iter_mut() + .map(|output| &mut output.witness) + }) .flatten() .collect(); for to_scan in tx.outputs.into_iter().enumerate() { - if let Some((output, new_witness)) = scan_output( + // Grab mutable references to new witnesses from previous outputs + // in this transaction so that we can update them. Scoped so we + // don't hold mutable references to shielded_outputs for too long. + let mut new_witnesses: Vec<_> = shielded_outputs + .iter_mut() + .map(|output| &mut output.witness) + .collect(); + + if let Some(output) = scan_output( to_scan, &ivks, &spent_from_accounts, @@ -152,7 +161,6 @@ pub fn scan_block( &mut new_witnesses, ) { shielded_outputs.push(output); - new_witnesses.push(new_witness); } } } @@ -160,17 +168,14 @@ pub fn scan_block( if !(shielded_spends.is_empty() && shielded_outputs.is_empty()) { let mut txid = TxId([0u8; 32]); txid.0.copy_from_slice(&tx.hash); - wtxs.push(( - WalletTx { - txid, - index: tx.index as usize, - num_spends, - num_outputs, - shielded_spends, - shielded_outputs, - }, - new_witnesses, - )); + wtxs.push(WalletTx { + txid, + index: tx.index as usize, + num_spends, + num_outputs, + shielded_spends, + shielded_outputs, + }); } } @@ -321,7 +326,7 @@ mod tests { let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []); assert_eq!(txs.len(), 1); - let (tx, new_witnesses) = &txs[0]; + let tx = &txs[0]; assert_eq!(tx.index, 1); assert_eq!(tx.num_spends, 1); assert_eq!(tx.num_outputs, 1); @@ -332,8 +337,7 @@ mod tests { assert_eq!(tx.shielded_outputs[0].note.value, 5); // Check that the witness root matches - assert_eq!(new_witnesses.len(), 1); - assert_eq!(new_witnesses[0].root(), tree.root()); + assert_eq!(tx.shielded_outputs[0].witness.root(), tree.root()); } #[test] @@ -354,7 +358,7 @@ mod tests { let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []); assert_eq!(txs.len(), 1); - let (tx, new_witnesses) = &txs[0]; + let tx = &txs[0]; assert_eq!(tx.index, 1); assert_eq!(tx.num_spends, 1); assert_eq!(tx.num_outputs, 1); @@ -365,8 +369,7 @@ mod tests { assert_eq!(tx.shielded_outputs[0].note.value, 5); // Check that the witness root matches - assert_eq!(new_witnesses.len(), 1); - assert_eq!(new_witnesses[0].root(), tree.root()); + assert_eq!(tx.shielded_outputs[0].witness.root(), tree.root()); } #[test] @@ -383,7 +386,7 @@ mod tests { let txs = scan_block(cb, &[], &[(&nf, account)], &mut tree, &mut []); assert_eq!(txs.len(), 1); - let (tx, new_witnesses) = &txs[0]; + let tx = &txs[0]; assert_eq!(tx.index, 1); assert_eq!(tx.num_spends, 1); assert_eq!(tx.num_outputs, 1); @@ -392,6 +395,5 @@ mod tests { assert_eq!(tx.shielded_spends[0].index, 0); assert_eq!(tx.shielded_spends[0].nf, nf); assert_eq!(tx.shielded_spends[0].account, account); - assert_eq!(new_witnesses.len(), 0); } } From bee4d6a92bd9b417fe399e5a648bd3545b15d6d2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 9 Mar 2019 02:16:00 +0000 Subject: [PATCH 091/105] SQLite database structure and initialisation --- Cargo.lock | 133 ++++++++++++++ Cargo.toml | 1 + zcash_client_sqlite/Cargo.toml | 15 ++ zcash_client_sqlite/README.md | 21 +++ zcash_client_sqlite/src/error.rs | 41 +++++ zcash_client_sqlite/src/init.rs | 286 +++++++++++++++++++++++++++++++ zcash_client_sqlite/src/lib.rs | 33 ++++ 7 files changed, 530 insertions(+) create mode 100644 zcash_client_sqlite/Cargo.toml create mode 100644 zcash_client_sqlite/README.md create mode 100644 zcash_client_sqlite/src/error.rs create mode 100644 zcash_client_sqlite/src/init.rs create mode 100644 zcash_client_sqlite/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f51d21b..91941b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,6 +78,11 @@ name = "bit-vec" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "blake2b_simd" version = "0.5.6" @@ -144,6 +149,11 @@ dependencies = [ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cc" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.9" @@ -194,6 +204,16 @@ name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ff" version = "0.4.0" @@ -317,6 +337,34 @@ dependencies = [ "zcash_proofs 0.0.0", ] +[[package]] +name = "libsqlite3-sys" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nodrop" version = "0.1.13" @@ -372,6 +420,11 @@ dependencies = [ "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pkg-config" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ppv-lite86" version = "0.2.5" @@ -482,6 +535,33 @@ dependencies = [ "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rusqlite" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha2" version = "0.8.0" @@ -508,6 +588,29 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typenum" version = "1.10.0" @@ -518,6 +621,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vcpkg" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.7" @@ -554,6 +662,16 @@ dependencies = [ "zcash_primitives 0.0.0", ] +[[package]] +name = "zcash_client_sqlite" +version = "0.0.0" +dependencies = [ + "rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_client_backend 0.0.0", + "zcash_primitives 0.0.0", +] + [[package]] name = "zcash_primitives" version = "0.0.0" @@ -601,6 +719,7 @@ dependencies = [ "checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" "checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2" "checksum blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3a84d2614b18a5367d357331a90fd533d5ceb1e86abc319320df2104ab744c2a" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" @@ -609,6 +728,7 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" @@ -617,6 +737,8 @@ dependencies = [ "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +"checksum fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" "checksum fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21988a326139165b75e3196bc6962ca638e5fb0c95102fbf152a3743174b01e4" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" @@ -627,12 +749,17 @@ dependencies = [ "checksum hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "520870c3213943eb8d7803e80180d12a6c7ceb4ae74602544529d1643dc4ddda" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)" = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa" +"checksum libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5b95e89c330291768dc840238db7f9e204fd208511ab6319b56193a7f2ae25" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "463bf29e7f11344e58c9e01f171470ab15c925c6822ad75028cc1c0e1d1eb63b" "checksum proc-macro-hack-impl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38c47dcb1594802de8c02f3b899e2018c78291168a22c281be21ea0fb4796842" @@ -647,11 +774,17 @@ dependencies = [ "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967" "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a194373ef527035645a1bc21b10dc2125f73497e6e155771233eb187aedd051" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 69639cf..0eba4cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "librustzcash", "pairing", "zcash_client_backend", + "zcash_client_sqlite", "zcash_primitives", "zcash_proofs", ] diff --git a/zcash_client_sqlite/Cargo.toml b/zcash_client_sqlite/Cargo.toml new file mode 100644 index 0000000..c7a9c64 --- /dev/null +++ b/zcash_client_sqlite/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "zcash_client_sqlite" +version = "0.0.0" +authors = [ + "Jack Grigg ", +] +edition = "2018" + +[dependencies] +rusqlite = { version = "0.20", features = ["bundled"] } +zcash_client_backend = { path = "../zcash_client_backend" } +zcash_primitives = { path = "../zcash_primitives" } + +[dev-dependencies] +tempfile = "3" diff --git a/zcash_client_sqlite/README.md b/zcash_client_sqlite/README.md new file mode 100644 index 0000000..2c244f8 --- /dev/null +++ b/zcash_client_sqlite/README.md @@ -0,0 +1,21 @@ +# zcash_client_sqlite + +This library contains APIs that collectively implement a Zcash light client in +an SQLite database. + +## License + +Licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs new file mode 100644 index 0000000..514b6f8 --- /dev/null +++ b/zcash_client_sqlite/src/error.rs @@ -0,0 +1,41 @@ +use std::error; +use std::fmt; + +#[derive(Debug)] +pub enum ErrorKind { + TableNotEmpty, + Database(rusqlite::Error), +} + +#[derive(Debug)] +pub struct Error(pub(crate) ErrorKind); + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self.0 { + ErrorKind::TableNotEmpty => write!(f, "Table is not empty"), + ErrorKind::Database(e) => write!(f, "{}", e), + } + } +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match &self.0 { + ErrorKind::Database(e) => Some(e), + _ => None, + } + } +} + +impl From for Error { + fn from(e: rusqlite::Error) -> Self { + Error(ErrorKind::Database(e)) + } +} + +impl Error { + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} diff --git a/zcash_client_sqlite/src/init.rs b/zcash_client_sqlite/src/init.rs new file mode 100644 index 0000000..c5ea793 --- /dev/null +++ b/zcash_client_sqlite/src/init.rs @@ -0,0 +1,286 @@ +//! Functions for initializing the various databases. + +use rusqlite::{types::ToSql, Connection, NO_PARAMS}; +use std::path::Path; +use zcash_client_backend::{ + constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + encoding::encode_extended_full_viewing_key, +}; +use zcash_primitives::{block::BlockHash, zip32::ExtendedFullViewingKey}; + +use crate::{ + address_from_extfvk, + error::{Error, ErrorKind}, +}; + +/// Sets up the internal structure of the cache database. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_client_sqlite::init::init_cache_database; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db_cache = data_file.path(); +/// init_cache_database(&db_cache).unwrap(); +/// ``` +pub fn init_cache_database>(db_cache: P) -> Result<(), Error> { + let cache = Connection::open(db_cache)?; + cache.execute( + "CREATE TABLE IF NOT EXISTS compactblocks ( + height INTEGER PRIMARY KEY, + data BLOB NOT NULL + )", + NO_PARAMS, + )?; + Ok(()) +} + +/// Sets up the internal structure of the data database. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_client_sqlite::init::init_data_database; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db_data = data_file.path(); +/// init_data_database(&db_data).unwrap(); +/// ``` +pub fn init_data_database>(db_data: P) -> Result<(), Error> { + let data = Connection::open(db_data)?; + data.execute( + "CREATE TABLE IF NOT EXISTS accounts ( + account INTEGER PRIMARY KEY, + extfvk TEXT NOT NULL, + address TEXT NOT NULL + )", + NO_PARAMS, + )?; + data.execute( + "CREATE TABLE IF NOT EXISTS blocks ( + height INTEGER PRIMARY KEY, + hash BLOB NOT NULL, + time INTEGER NOT NULL, + sapling_tree BLOB NOT NULL + )", + NO_PARAMS, + )?; + data.execute( + "CREATE TABLE IF NOT EXISTS transactions ( + id_tx INTEGER PRIMARY KEY, + txid BLOB NOT NULL UNIQUE, + created TEXT, + block INTEGER, + tx_index INTEGER, + expiry_height INTEGER, + raw BLOB, + FOREIGN KEY (block) REFERENCES blocks(height) + )", + NO_PARAMS, + )?; + data.execute( + "CREATE TABLE IF NOT EXISTS received_notes ( + id_note INTEGER PRIMARY KEY, + tx INTEGER NOT NULL, + output_index INTEGER NOT NULL, + account INTEGER NOT NULL, + diversifier BLOB NOT NULL, + value INTEGER NOT NULL, + rcm BLOB NOT NULL, + nf BLOB NOT NULL UNIQUE, + is_change BOOLEAN NOT NULL, + memo BLOB, + spent INTEGER, + FOREIGN KEY (tx) REFERENCES transactions(id_tx), + FOREIGN KEY (account) REFERENCES accounts(account), + FOREIGN KEY (spent) REFERENCES transactions(id_tx), + CONSTRAINT tx_output UNIQUE (tx, output_index) + )", + NO_PARAMS, + )?; + data.execute( + "CREATE TABLE IF NOT EXISTS sapling_witnesses ( + id_witness INTEGER PRIMARY KEY, + note INTEGER NOT NULL, + block INTEGER NOT NULL, + witness BLOB NOT NULL, + FOREIGN KEY (note) REFERENCES received_notes(id_note), + FOREIGN KEY (block) REFERENCES blocks(height), + CONSTRAINT witness_height UNIQUE (note, block) + )", + NO_PARAMS, + )?; + data.execute( + "CREATE TABLE IF NOT EXISTS sent_notes ( + id_note INTEGER PRIMARY KEY, + tx INTEGER NOT NULL, + output_index INTEGER NOT NULL, + from_account INTEGER NOT NULL, + address TEXT NOT NULL, + value INTEGER NOT NULL, + memo BLOB, + FOREIGN KEY (tx) REFERENCES transactions(id_tx), + FOREIGN KEY (from_account) REFERENCES accounts(account), + CONSTRAINT tx_output UNIQUE (tx, output_index) + )", + NO_PARAMS, + )?; + Ok(()) +} + +/// Initialises the data database with the given [`ExtendedFullViewingKey`]s. +/// +/// The [`ExtendedFullViewingKey`]s are stored internally and used by other APIs such as +/// [`get_address`], [`scan_cached_blocks`], and [`create_to_address`]. `extfvks` **MUST** +/// be arranged in account-order; that is, the [`ExtendedFullViewingKey`] for ZIP 32 +/// account `i` **MUST** be at `extfvks[i]`. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_client_sqlite::init::{init_accounts_table, init_data_database}; +/// use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db_data = data_file.path(); +/// init_data_database(&db_data).unwrap(); +/// +/// let extsk = ExtendedSpendingKey::master(&[]); +/// let extfvks = [ExtendedFullViewingKey::from(&extsk)]; +/// init_accounts_table(&db_data, &extfvks).unwrap(); +/// ``` +/// +/// [`get_address`]: crate::query::get_address +/// [`scan_cached_blocks`]: crate::scan::scan_cached_blocks +/// [`create_to_address`]: crate::transact::create_to_address +pub fn init_accounts_table>( + db_data: P, + extfvks: &[ExtendedFullViewingKey], +) -> Result<(), Error> { + let data = Connection::open(db_data)?; + + let mut empty_check = data.prepare("SELECT * FROM accounts LIMIT 1")?; + if empty_check.exists(NO_PARAMS)? { + return Err(Error(ErrorKind::TableNotEmpty)); + } + + // Insert accounts atomically + data.execute("BEGIN IMMEDIATE", NO_PARAMS)?; + for (account, extfvk) in extfvks.iter().enumerate() { + let address = address_from_extfvk(extfvk); + let extfvk = + encode_extended_full_viewing_key(HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, extfvk); + data.execute( + "INSERT INTO accounts (account, extfvk, address) + VALUES (?, ?, ?)", + &[ + (account as u32).to_sql()?, + extfvk.to_sql()?, + address.to_sql()?, + ], + )?; + } + data.execute("COMMIT", NO_PARAMS)?; + + Ok(()) +} + +/// Initialises the data database with the given block. +/// +/// This enables a newly-created database to be immediately-usable, without needing to +/// synchronise historic blocks. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_sqlite::init::init_blocks_table; +/// use zcash_primitives::block::BlockHash; +/// +/// // The block height. +/// let height = 500_000; +/// // The hash of the block header. +/// let hash = BlockHash([0; 32]); +/// // The nTime field from the block header. +/// let time = 12_3456_7890; +/// // The serialized Sapling commitment tree as of this block. +/// // Pre-compute and hard-code, or obtain from a service. +/// let sapling_tree = &[]; +/// +/// init_blocks_table("/path/to/data.db", height, hash, time, sapling_tree); +/// ``` +pub fn init_blocks_table>( + db_data: P, + height: i32, + hash: BlockHash, + time: u32, + sapling_tree: &[u8], +) -> Result<(), Error> { + let data = Connection::open(db_data)?; + + let mut empty_check = data.prepare("SELECT * FROM blocks LIMIT 1")?; + if empty_check.exists(NO_PARAMS)? { + return Err(Error(ErrorKind::TableNotEmpty)); + } + + data.execute( + "INSERT INTO blocks (height, hash, time, sapling_tree) + VALUES (?, ?, ?, ?)", + &[ + height.to_sql()?, + hash.0.to_sql()?, + time.to_sql()?, + sapling_tree.to_sql()?, + ], + )?; + + Ok(()) +} + +#[cfg(test)] +mod tests { + use tempfile::NamedTempFile; + use zcash_primitives::{ + block::BlockHash, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + }; + + use super::{init_accounts_table, init_blocks_table, init_data_database}; + + #[test] + fn init_accounts_table_only_works_once() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // We can call the function as many times as we want with no data + init_accounts_table(&db_data, &[]).unwrap(); + init_accounts_table(&db_data, &[]).unwrap(); + + // First call with data should initialise the accounts table + let extfvks = [ExtendedFullViewingKey::from(&ExtendedSpendingKey::master( + &[], + ))]; + init_accounts_table(&db_data, &extfvks).unwrap(); + + // Subsequent calls should return an error + init_accounts_table(&db_data, &[]).unwrap_err(); + init_accounts_table(&db_data, &extfvks).unwrap_err(); + } + + #[test] + fn init_blocks_table_only_works_once() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // First call with data should initialise the blocks table + init_blocks_table(&db_data, 1, BlockHash([1; 32]), 1, &[]).unwrap(); + + // Subsequent calls should return an error + init_blocks_table(&db_data, 2, BlockHash([2; 32]), 2, &[]).unwrap_err(); + } +} diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs new file mode 100644 index 0000000..767b582 --- /dev/null +++ b/zcash_client_sqlite/src/lib.rs @@ -0,0 +1,33 @@ +//! *An SQLite-based Zcash light client.* +//! +//! `zcash_client_backend` contains a set of APIs that collectively implement an +//! SQLite-based light client for the Zcash network. +//! +//! # Design +//! +//! The light client is built around two SQLite databases: +//! +//! - A cache database, used to inform the light client about new [`CompactBlock`]s. It is +//! read-only within all light client APIs *except* for [`init_cache_database`] which +//! can be used to initialize the database. +//! +//! - A data database, where the light client's state is stored. It is read-write within +//! the light client APIs, and **assumed to be read-only outside these APIs**. Callers +//! **MUST NOT** write to the database without using these APIs. Callers **MAY** read +//! the database directly in order to extract information for display to users. +//! +//! [`CompactBlock`]: zcash_client_backend::proto::compact_formats::CompactBlock +//! [`init_cache_database`]: crate::init::init_cache_database + +use zcash_client_backend::{ + constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, encoding::encode_payment_address, +}; +use zcash_primitives::zip32::ExtendedFullViewingKey; + +pub mod error; +pub mod init; + +fn address_from_extfvk(extfvk: &ExtendedFullViewingKey) -> String { + let addr = extfvk.default_address().unwrap().1; + encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &addr) +} From 0bf1fad0edb46abe3c9be9d5181565e7b5be971d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 9 Mar 2019 02:23:31 +0000 Subject: [PATCH 092/105] zcash_client_sqlite::query::get_address() --- zcash_client_sqlite/src/init.rs | 21 +++++++++++++++++++++ zcash_client_sqlite/src/lib.rs | 1 + zcash_client_sqlite/src/query.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 zcash_client_sqlite/src/query.rs diff --git a/zcash_client_sqlite/src/init.rs b/zcash_client_sqlite/src/init.rs index c5ea793..e457ad9 100644 --- a/zcash_client_sqlite/src/init.rs +++ b/zcash_client_sqlite/src/init.rs @@ -243,12 +243,16 @@ pub fn init_blocks_table>( #[cfg(test)] mod tests { use tempfile::NamedTempFile; + use zcash_client_backend::{ + constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, encoding::decode_payment_address, + }; use zcash_primitives::{ block::BlockHash, zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, }; use super::{init_accounts_table, init_blocks_table, init_data_database}; + use crate::query::get_address; #[test] fn init_accounts_table_only_works_once() { @@ -283,4 +287,21 @@ mod tests { // Subsequent calls should return an error init_blocks_table(&db_data, 2, BlockHash([2; 32]), 2, &[]).unwrap_err(); } + + #[test] + fn init_accounts_table_stores_correct_address() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvks = [ExtendedFullViewingKey::from(&extsk)]; + init_accounts_table(&db_data, &extfvks).unwrap(); + + // The account's address should be in the data DB + let addr = get_address(&db_data, 0).unwrap(); + let pa = decode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &addr).unwrap(); + assert_eq!(pa.unwrap(), extsk.default_address().unwrap().1); + } } diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 767b582..32ebc1f 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -26,6 +26,7 @@ use zcash_primitives::zip32::ExtendedFullViewingKey; pub mod error; pub mod init; +pub mod query; fn address_from_extfvk(extfvk: &ExtendedFullViewingKey) -> String { let addr = extfvk.default_address().unwrap().1; diff --git a/zcash_client_sqlite/src/query.rs b/zcash_client_sqlite/src/query.rs new file mode 100644 index 0000000..be585d9 --- /dev/null +++ b/zcash_client_sqlite/src/query.rs @@ -0,0 +1,28 @@ +//! Functions for querying information in the data database. + +use rusqlite::Connection; +use std::path::Path; + +use crate::error::Error; + +/// Returns the address for the account. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_sqlite::query::get_address; +/// +/// let addr = get_address("/path/to/data.db", 0); +/// ``` +pub fn get_address>(db_data: P, account: u32) -> Result { + let data = Connection::open(db_data)?; + + let addr = data.query_row( + "SELECT address FROM accounts + WHERE account = ?", + &[account], + |row| row.get(0), + )?; + + Ok(addr) +} From 68291090c644a2041d193ac7fd917c01109c44ca Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 9 Mar 2019 02:53:38 +0000 Subject: [PATCH 093/105] zcash_client_sqlite::query::{get_balance, get_verified_balance} --- zcash_client_sqlite/src/error.rs | 4 ++ zcash_client_sqlite/src/lib.rs | 31 +++++++++ zcash_client_sqlite/src/query.rs | 107 ++++++++++++++++++++++++++++++- 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index 514b6f8..b33b5c2 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -3,6 +3,8 @@ use std::fmt; #[derive(Debug)] pub enum ErrorKind { + CorruptedData(&'static str), + ScanRequired, TableNotEmpty, Database(rusqlite::Error), } @@ -13,6 +15,8 @@ pub struct Error(pub(crate) ErrorKind); impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &self.0 { + ErrorKind::CorruptedData(reason) => write!(f, "Data DB is corrupted: {}", reason), + ErrorKind::ScanRequired => write!(f, "Must scan blocks first"), ErrorKind::TableNotEmpty => write!(f, "Table is not empty"), ErrorKind::Database(e) => write!(f, "{}", e), } diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 32ebc1f..cb52144 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -19,6 +19,8 @@ //! [`CompactBlock`]: zcash_client_backend::proto::compact_formats::CompactBlock //! [`init_cache_database`]: crate::init::init_cache_database +use rusqlite::{Connection, NO_PARAMS}; +use std::cmp; use zcash_client_backend::{ constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, encoding::encode_payment_address, }; @@ -28,7 +30,36 @@ pub mod error; pub mod init; pub mod query; +const ANCHOR_OFFSET: u32 = 10; + fn address_from_extfvk(extfvk: &ExtendedFullViewingKey) -> String { let addr = extfvk.default_address().unwrap().1; encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &addr) } + +/// Determines the target height for a transaction, and the height from which to +/// select anchors, based on the current synchronised block chain. +fn get_target_and_anchor_heights(data: &Connection) -> Result<(u32, u32), error::Error> { + data.query_row_and_then( + "SELECT MIN(height), MAX(height) FROM blocks", + NO_PARAMS, + |row| match (row.get::<_, u32>(0), row.get::<_, u32>(1)) { + // If there are no blocks, the query returns NULL. + (Err(rusqlite::Error::InvalidColumnType(_, _, _)), _) + | (_, Err(rusqlite::Error::InvalidColumnType(_, _, _))) => { + Err(error::Error(error::ErrorKind::ScanRequired)) + } + (Err(e), _) | (_, Err(e)) => Err(e.into()), + (Ok(min_height), Ok(max_height)) => { + let target_height = max_height + 1; + + // Select an anchor ANCHOR_OFFSET back from the target block, + // unless that would be before the earliest block we have. + let anchor_height = + cmp::max(target_height.saturating_sub(ANCHOR_OFFSET), min_height); + + Ok((target_height, anchor_height)) + } + }, + ) +} diff --git a/zcash_client_sqlite/src/query.rs b/zcash_client_sqlite/src/query.rs index be585d9..7806b8d 100644 --- a/zcash_client_sqlite/src/query.rs +++ b/zcash_client_sqlite/src/query.rs @@ -2,8 +2,12 @@ use rusqlite::Connection; use std::path::Path; +use zcash_primitives::transaction::components::Amount; -use crate::error::Error; +use crate::{ + error::{Error, ErrorKind}, + get_target_and_anchor_heights, +}; /// Returns the address for the account. /// @@ -26,3 +30,104 @@ pub fn get_address>(db_data: P, account: u32) -> Result>(db_data: P, account: u32) -> Result { + let data = Connection::open(db_data)?; + + let balance = data.query_row( + "SELECT SUM(value) FROM received_notes + INNER JOIN transactions ON transactions.id_tx = received_notes.tx + WHERE account = ? AND spent IS NULL AND transactions.block IS NOT NULL", + &[account], + |row| row.get(0).or(Ok(0)), + )?; + + match Amount::from_i64(balance) { + Ok(amount) if !amount.is_negative() => Ok(amount), + _ => Err(Error(ErrorKind::CorruptedData( + "Sum of values in received_notes is out of range", + ))), + } +} + +/// Returns the verified balance for the account, which ignores notes that have been +/// received too recently and are not yet deemed spendable. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_sqlite::query::get_verified_balance; +/// +/// let addr = get_verified_balance("/path/to/data.db", 0); +/// ``` +pub fn get_verified_balance>(db_data: P, account: u32) -> Result { + let data = Connection::open(db_data)?; + + let (_, anchor_height) = get_target_and_anchor_heights(&data)?; + + let balance = data.query_row( + "SELECT SUM(value) FROM received_notes + INNER JOIN transactions ON transactions.id_tx = received_notes.tx + WHERE account = ? AND spent IS NULL AND transactions.block <= ?", + &[account, anchor_height], + |row| row.get(0).or(Ok(0)), + )?; + + match Amount::from_i64(balance) { + Ok(amount) if !amount.is_negative() => Ok(amount), + _ => Err(Error(ErrorKind::CorruptedData( + "Sum of values in received_notes is out of range", + ))), + } +} + +#[cfg(test)] +mod tests { + use tempfile::NamedTempFile; + use zcash_primitives::{ + transaction::components::Amount, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + }; + + use super::{get_address, get_balance, get_verified_balance}; + use crate::{ + error::ErrorKind, + init::{init_accounts_table, init_data_database}, + }; + + #[test] + fn empty_database_has_no_balance() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvks = [ExtendedFullViewingKey::from(&extsk)]; + init_accounts_table(&db_data, &extfvks).unwrap(); + + // The account should be empty + assert_eq!(get_balance(db_data, 0).unwrap(), Amount::zero()); + + // The account should have no verified balance, as we haven't scanned any blocks + let e = get_verified_balance(db_data, 0).unwrap_err(); + match e.kind() { + ErrorKind::ScanRequired => (), + _ => panic!("Unexpected error: {:?}", e), + } + + // An invalid account has zero balance + assert!(get_address(db_data, 1).is_err()); + assert_eq!(get_balance(db_data, 1).unwrap(), Amount::zero()); + } +} From 9a742d25ea26b94e737f8aaf59f9c6a8246d079c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 9 Mar 2019 03:12:31 +0000 Subject: [PATCH 094/105] zcash_client_sqlite::scan::scan_cached_blocks() --- Cargo.lock | 6 + zcash_client_sqlite/Cargo.toml | 6 + zcash_client_sqlite/src/error.rs | 48 +++ zcash_client_sqlite/src/lib.rs | 176 +++++++++++ zcash_client_sqlite/src/scan.rs | 501 +++++++++++++++++++++++++++++++ 5 files changed, 737 insertions(+) create mode 100644 zcash_client_sqlite/src/scan.rs diff --git a/Cargo.lock b/Cargo.lock index 91941b7..aa11a84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -666,6 +666,12 @@ dependencies = [ name = "zcash_client_sqlite" version = "0.0.0" dependencies = [ + "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", + "pairing 0.14.2", + "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_client_backend 0.0.0", diff --git a/zcash_client_sqlite/Cargo.toml b/zcash_client_sqlite/Cargo.toml index c7a9c64..d572a38 100644 --- a/zcash_client_sqlite/Cargo.toml +++ b/zcash_client_sqlite/Cargo.toml @@ -7,9 +7,15 @@ authors = [ edition = "2018" [dependencies] +bech32 = "0.7" +ff = { path = "../ff" } +protobuf = "2" rusqlite = { version = "0.20", features = ["bundled"] } zcash_client_backend = { path = "../zcash_client_backend" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] +pairing = { path = "../pairing" } +rand_core = "0.5" +rand_os = "0.2" tempfile = "3" diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index b33b5c2..fcdc1a0 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -1,12 +1,20 @@ use std::error; use std::fmt; +use zcash_primitives::{sapling::Node, transaction::TxId}; #[derive(Debug)] pub enum ErrorKind { CorruptedData(&'static str), + IncorrectHRPExtFVK, + InvalidHeight(i32, i32), + InvalidNewWitnessAnchor(usize, TxId, i32, Node), + InvalidWitnessAnchor(i64, i32), ScanRequired, TableNotEmpty, + Bech32(bech32::Error), Database(rusqlite::Error), + Io(std::io::Error), + Protobuf(protobuf::ProtobufError), } #[derive(Debug)] @@ -16,9 +24,28 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &self.0 { ErrorKind::CorruptedData(reason) => write!(f, "Data DB is corrupted: {}", reason), + ErrorKind::IncorrectHRPExtFVK => write!(f, "Incorrect HRP for extfvk"), + ErrorKind::InvalidHeight(expected, actual) => write!( + f, + "Expected height of next CompactBlock to be {}, but was {}", + expected, actual + ), + ErrorKind::InvalidNewWitnessAnchor(output, txid, last_height, anchor) => write!( + f, + "New witness for output {} in tx {} has incorrect anchor after scanning block {}: {:?}", + output, txid, last_height, anchor, + ), + ErrorKind::InvalidWitnessAnchor(id_note, last_height) => write!( + f, + "Witness for note {} has incorrect anchor after scanning block {}", + id_note, last_height + ), ErrorKind::ScanRequired => write!(f, "Must scan blocks first"), ErrorKind::TableNotEmpty => write!(f, "Table is not empty"), + ErrorKind::Bech32(e) => write!(f, "{}", e), ErrorKind::Database(e) => write!(f, "{}", e), + ErrorKind::Io(e) => write!(f, "{}", e), + ErrorKind::Protobuf(e) => write!(f, "{}", e), } } } @@ -26,18 +53,39 @@ impl fmt::Display for Error { impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match &self.0 { + ErrorKind::Bech32(e) => Some(e), ErrorKind::Database(e) => Some(e), + ErrorKind::Io(e) => Some(e), + ErrorKind::Protobuf(e) => Some(e), _ => None, } } } +impl From for Error { + fn from(e: bech32::Error) -> Self { + Error(ErrorKind::Bech32(e)) + } +} + impl From for Error { fn from(e: rusqlite::Error) -> Self { Error(ErrorKind::Database(e)) } } +impl From for Error { + fn from(e: std::io::Error) -> Self { + Error(ErrorKind::Io(e)) + } +} + +impl From for Error { + fn from(e: protobuf::ProtobufError) -> Self { + Error(ErrorKind::Protobuf(e)) + } +} + impl Error { pub fn kind(&self) -> &ErrorKind { &self.0 diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index cb52144..c9fa4c8 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -29,8 +29,10 @@ use zcash_primitives::zip32::ExtendedFullViewingKey; pub mod error; pub mod init; pub mod query; +pub mod scan; const ANCHOR_OFFSET: u32 = 10; +const SAPLING_ACTIVATION_HEIGHT: i32 = 280_000; fn address_from_extfvk(extfvk: &ExtendedFullViewingKey) -> String { let addr = extfvk.default_address().unwrap().1; @@ -63,3 +65,177 @@ fn get_target_and_anchor_heights(data: &Connection) -> Result<(u32, u32), error: }, ) } + +#[cfg(test)] +mod tests { + use ff::{Field, PrimeField, PrimeFieldRepr}; + use pairing::bls12_381::Bls12; + use protobuf::Message; + use rand_core::RngCore; + use rand_os::OsRng; + use rusqlite::{types::ToSql, Connection}; + use std::path::Path; + use zcash_client_backend::proto::compact_formats::{ + CompactBlock, CompactOutput, CompactSpend, CompactTx, + }; + use zcash_primitives::{ + block::BlockHash, + jubjub::fs::Fs, + note_encryption::{Memo, SaplingNoteEncryption}, + primitives::{Note, PaymentAddress}, + transaction::components::Amount, + zip32::ExtendedFullViewingKey, + JUBJUB, + }; + + /// Create a fake CompactBlock at the given height, containing a single output paying + /// the given address. Returns the CompactBlock and the nullifier for the new note. + pub(crate) fn fake_compact_block( + height: i32, + prev_hash: BlockHash, + extfvk: ExtendedFullViewingKey, + value: Amount, + ) -> (CompactBlock, Vec) { + let to = extfvk.default_address().unwrap().1; + + // Create a fake Note for the account + let mut rng = OsRng; + let note = Note { + g_d: to.diversifier.g_d::(&JUBJUB).unwrap(), + pk_d: to.pk_d.clone(), + value: value.into(), + r: Fs::random(&mut rng), + }; + let encryptor = SaplingNoteEncryption::new( + extfvk.fvk.ovk, + note.clone(), + to.clone(), + Memo::default(), + &mut rng, + ); + let mut cmu = vec![]; + note.cm(&JUBJUB).into_repr().write_le(&mut cmu).unwrap(); + let mut epk = vec![]; + encryptor.epk().write(&mut epk).unwrap(); + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + + // Create a fake CompactBlock containing the note + let mut cout = CompactOutput::new(); + cout.set_cmu(cmu); + cout.set_epk(epk); + cout.set_ciphertext(enc_ciphertext[..52].to_vec()); + let mut ctx = CompactTx::new(); + let mut txid = vec![0; 32]; + rng.fill_bytes(&mut txid); + ctx.set_hash(txid); + ctx.outputs.push(cout); + let mut cb = CompactBlock::new(); + cb.set_height(height as u64); + cb.hash.resize(32, 0); + rng.fill_bytes(&mut cb.hash); + cb.prevHash.extend_from_slice(&prev_hash.0); + cb.vtx.push(ctx); + (cb, note.nf(&extfvk.fvk.vk, 0, &JUBJUB)) + } + + /// Create a fake CompactBlock at the given height, spending a single note from the + /// given address. + pub(crate) fn fake_compact_block_spending( + height: i32, + prev_hash: BlockHash, + (nf, in_value): (Vec, Amount), + extfvk: ExtendedFullViewingKey, + to: PaymentAddress, + value: Amount, + ) -> CompactBlock { + let mut rng = OsRng; + + // Create a fake CompactBlock containing the note + let mut cspend = CompactSpend::new(); + cspend.set_nf(nf); + let mut ctx = CompactTx::new(); + let mut txid = vec![0; 32]; + rng.fill_bytes(&mut txid); + ctx.set_hash(txid); + ctx.spends.push(cspend); + + // Create a fake Note for the payment + ctx.outputs.push({ + let note = Note { + g_d: to.diversifier.g_d::(&JUBJUB).unwrap(), + pk_d: to.pk_d.clone(), + value: value.into(), + r: Fs::random(&mut rng), + }; + let encryptor = SaplingNoteEncryption::new( + extfvk.fvk.ovk, + note.clone(), + to, + Memo::default(), + &mut rng, + ); + let mut cmu = vec![]; + note.cm(&JUBJUB).into_repr().write_le(&mut cmu).unwrap(); + let mut epk = vec![]; + encryptor.epk().write(&mut epk).unwrap(); + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + + let mut cout = CompactOutput::new(); + cout.set_cmu(cmu); + cout.set_epk(epk); + cout.set_ciphertext(enc_ciphertext[..52].to_vec()); + cout + }); + + // Create a fake Note for the change + ctx.outputs.push({ + let change_addr = extfvk.default_address().unwrap().1; + let note = Note { + g_d: change_addr.diversifier.g_d::(&JUBJUB).unwrap(), + pk_d: change_addr.pk_d.clone(), + value: (in_value - value).into(), + r: Fs::random(&mut rng), + }; + let encryptor = SaplingNoteEncryption::new( + extfvk.fvk.ovk, + note.clone(), + change_addr, + Memo::default(), + &mut rng, + ); + let mut cmu = vec![]; + note.cm(&JUBJUB).into_repr().write_le(&mut cmu).unwrap(); + let mut epk = vec![]; + encryptor.epk().write(&mut epk).unwrap(); + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + + let mut cout = CompactOutput::new(); + cout.set_cmu(cmu); + cout.set_epk(epk); + cout.set_ciphertext(enc_ciphertext[..52].to_vec()); + cout + }); + + let mut cb = CompactBlock::new(); + cb.set_height(height as u64); + cb.hash.resize(32, 0); + rng.fill_bytes(&mut cb.hash); + cb.prevHash.extend_from_slice(&prev_hash.0); + cb.vtx.push(ctx); + cb + } + + /// Insert a fake CompactBlock into the cache DB. + pub(crate) fn insert_into_cache>(db_cache: P, cb: &CompactBlock) { + let cb_bytes = cb.write_to_bytes().unwrap(); + let cache = Connection::open(&db_cache).unwrap(); + cache + .prepare("INSERT INTO compactblocks (height, data) VALUES (?, ?)") + .unwrap() + .execute(&[ + (cb.height as i32).to_sql().unwrap(), + cb_bytes.to_sql().unwrap(), + ]) + .unwrap(); + } +} diff --git a/zcash_client_sqlite/src/scan.rs b/zcash_client_sqlite/src/scan.rs new file mode 100644 index 0000000..44ec1cb --- /dev/null +++ b/zcash_client_sqlite/src/scan.rs @@ -0,0 +1,501 @@ +//! Functions for scanning the chain and extracting relevant information. + +use ff::{PrimeField, PrimeFieldRepr}; +use protobuf::parse_from_bytes; +use rusqlite::{types::ToSql, Connection, NO_PARAMS}; +use std::path::Path; +use zcash_client_backend::{ + constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + encoding::decode_extended_full_viewing_key, proto::compact_formats::CompactBlock, + welding_rig::scan_block, +}; +use zcash_primitives::{ + merkle_tree::{CommitmentTree, IncrementalWitness}, + sapling::Node, + JUBJUB, +}; + +use crate::{ + error::{Error, ErrorKind}, + SAPLING_ACTIVATION_HEIGHT, +}; + +struct CompactBlockRow { + height: i32, + data: Vec, +} + +#[derive(Clone)] +struct WitnessRow { + id_note: i64, + witness: IncrementalWitness, +} + +/// Scans new blocks added to the cache for any transactions received by the tracked +/// accounts. +/// +/// This function pays attention only to cached blocks with heights greater than the +/// highest scanned block in `db_data`. Cached blocks with lower heights are not verified +/// against previously-scanned blocks. In particular, this function **assumes** that the +/// caller is handling rollbacks. +/// +/// For brand-new light client databases, this function starts scanning from the Sapling +/// activation height. This height can be fast-forwarded to a more recent block by calling +/// [`init_blocks_table`] before this function. +/// +/// Scanned blocks are required to be height-sequential. If a block is missing from the +/// cache, an error will be returned with kind [`ErrorKind::InvalidHeight`]. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_sqlite::scan::scan_cached_blocks; +/// +/// scan_cached_blocks("/path/to/cache.db", "/path/to/data.db"); +/// ``` +/// +/// [`init_blocks_table`]: crate::init::init_blocks_table +pub fn scan_cached_blocks, Q: AsRef>( + db_cache: P, + db_data: Q, +) -> Result<(), Error> { + let cache = Connection::open(db_cache)?; + let data = Connection::open(db_data)?; + + // Recall where we synced up to previously. + // If we have never synced, use sapling activation height to select all cached CompactBlocks. + let mut last_height = data.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| { + row.get(0).or(Ok(SAPLING_ACTIVATION_HEIGHT - 1)) + })?; + + // Fetch the CompactBlocks we need to scan + let mut stmt_blocks = cache + .prepare("SELECT height, data FROM compactblocks WHERE height > ? ORDER BY height ASC")?; + let rows = stmt_blocks.query_map(&[last_height], |row| { + Ok(CompactBlockRow { + height: row.get(0)?, + data: row.get(1)?, + }) + })?; + + // Fetch the ExtendedFullViewingKeys we are tracking + let mut stmt_fetch_accounts = + data.prepare("SELECT extfvk FROM accounts ORDER BY account ASC")?; + let extfvks = stmt_fetch_accounts.query_map(NO_PARAMS, |row| { + row.get(0).map(|extfvk: String| { + decode_extended_full_viewing_key(HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, &extfvk) + }) + })?; + // Raise SQL errors from the query, IO errors from parsing, and incorrect HRP errors. + let extfvks: Vec<_> = extfvks + .collect::, _>, _>>()?? + .ok_or(Error(ErrorKind::IncorrectHRPExtFVK))?; + + // Get the most recent CommitmentTree + let mut stmt_fetch_tree = data.prepare("SELECT sapling_tree FROM blocks WHERE height = ?")?; + let mut tree = stmt_fetch_tree + .query_row(&[last_height], |row| { + row.get(0).map(|data: Vec<_>| { + CommitmentTree::read(&data[..]).unwrap_or_else(|_| CommitmentTree::new()) + }) + }) + .unwrap_or_else(|_| CommitmentTree::new()); + + // Get most recent incremental witnesses for the notes we are tracking + let mut stmt_fetch_witnesses = + data.prepare("SELECT note, witness FROM sapling_witnesses WHERE block = ?")?; + let witnesses = stmt_fetch_witnesses.query_map(&[last_height], |row| { + let id_note = row.get(0)?; + let data: Vec<_> = row.get(1)?; + Ok(IncrementalWitness::read(&data[..]).map(|witness| WitnessRow { id_note, witness })) + })?; + let mut witnesses: Vec<_> = witnesses.collect::, _>>()??; + + // Get the nullifiers for the notes we are tracking + let mut stmt_fetch_nullifiers = + data.prepare("SELECT id_note, nf, account FROM received_notes WHERE spent IS NULL")?; + let nullifiers = stmt_fetch_nullifiers.query_map(NO_PARAMS, |row| { + let nf: Vec<_> = row.get(1)?; + let account: i64 = row.get(2)?; + Ok((nf, account as usize)) + })?; + let mut nullifiers: Vec<_> = nullifiers.collect::>()?; + + // Prepare per-block SQL statements + let mut stmt_insert_block = data.prepare( + "INSERT INTO blocks (height, hash, time, sapling_tree) + VALUES (?, ?, ?, ?)", + )?; + let mut stmt_update_tx = data.prepare( + "UPDATE transactions + SET block = ?, tx_index = ? WHERE txid = ?", + )?; + let mut stmt_insert_tx = data.prepare( + "INSERT INTO transactions (txid, block, tx_index) + VALUES (?, ?, ?)", + )?; + let mut stmt_select_tx = data.prepare("SELECT id_tx FROM transactions WHERE txid = ?")?; + let mut stmt_mark_spent_note = + data.prepare("UPDATE received_notes SET spent = ? WHERE nf = ?")?; + let mut stmt_insert_note = data.prepare( + "INSERT INTO received_notes (tx, output_index, account, diversifier, value, rcm, nf, is_change) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + )?; + let mut stmt_insert_witness = data.prepare( + "INSERT INTO sapling_witnesses (note, block, witness) + VALUES (?, ?, ?)", + )?; + let mut stmt_prune_witnesses = data.prepare("DELETE FROM sapling_witnesses WHERE block < ?")?; + let mut stmt_update_expired = data.prepare( + "UPDATE received_notes SET spent = NULL WHERE EXISTS ( + SELECT id_tx FROM transactions + WHERE id_tx = received_notes.spent AND block IS NULL AND expiry_height < ? + )", + )?; + + for row in rows { + let row = row?; + + // Start an SQL transaction for this block. + data.execute("BEGIN IMMEDIATE", NO_PARAMS)?; + + // Scanned blocks MUST be height-sequential. + if row.height != (last_height + 1) { + return Err(Error(ErrorKind::InvalidHeight(last_height + 1, row.height))); + } + last_height = row.height; + + let block: CompactBlock = parse_from_bytes(&row.data)?; + let block_hash = block.hash.clone(); + let block_time = block.time; + + let txs = { + let nf_refs: Vec<_> = nullifiers.iter().map(|(nf, acc)| (&nf[..], *acc)).collect(); + let mut witness_refs: Vec<_> = witnesses.iter_mut().map(|w| &mut w.witness).collect(); + scan_block( + block, + &extfvks[..], + &nf_refs, + &mut tree, + &mut witness_refs[..], + ) + }; + + // Enforce that all roots match. This is slow, so only include in debug builds. + #[cfg(debug_assertions)] + { + let cur_root = tree.root(); + for row in &witnesses { + if row.witness.root() != cur_root { + return Err(Error(ErrorKind::InvalidWitnessAnchor( + row.id_note, + last_height, + ))); + } + } + for tx in &txs { + for output in tx.shielded_outputs.iter() { + if output.witness.root() != cur_root { + return Err(Error(ErrorKind::InvalidNewWitnessAnchor( + output.index, + tx.txid, + last_height, + output.witness.root(), + ))); + } + } + } + } + + // Insert the block into the database. + let mut encoded_tree = Vec::new(); + tree.write(&mut encoded_tree) + .expect("Should be able to write to a Vec"); + stmt_insert_block.execute(&[ + row.height.to_sql()?, + block_hash.to_sql()?, + block_time.to_sql()?, + encoded_tree.to_sql()?, + ])?; + + for tx in txs { + // First try update an existing transaction in the database. + let txid = tx.txid.0.to_vec(); + let tx_row = if stmt_update_tx.execute(&[ + row.height.to_sql()?, + (tx.index as i64).to_sql()?, + txid.to_sql()?, + ])? == 0 + { + // It isn't there, so insert our transaction into the database. + stmt_insert_tx.execute(&[ + txid.to_sql()?, + row.height.to_sql()?, + (tx.index as i64).to_sql()?, + ])?; + data.last_insert_rowid() + } else { + // It was there, so grab its row number. + stmt_select_tx.query_row(&[txid], |row| row.get(0))? + }; + + // Mark notes as spent and remove them from the scanning cache + for spend in &tx.shielded_spends { + stmt_mark_spent_note.execute(&[tx_row.to_sql()?, spend.nf.to_sql()?])?; + } + nullifiers = nullifiers + .into_iter() + .filter(|(nf, _acc)| { + tx.shielded_spends + .iter() + .find(|spend| &spend.nf == nf) + .is_none() + }) + .collect(); + + for output in tx.shielded_outputs { + let mut rcm = [0; 32]; + output.note.r.into_repr().write_le(&mut rcm[..])?; + let nf = output.note.nf( + &extfvks[output.account].fvk.vk, + output.witness.position() as u64, + &JUBJUB, + ); + + // Insert received note into the database. + // Assumptions: + // - A transaction will not contain more than 2^63 shielded outputs. + // - A note value will never exceed 2^63 zatoshis. + stmt_insert_note.execute(&[ + tx_row.to_sql()?, + (output.index as i64).to_sql()?, + (output.account as i64).to_sql()?, + output.to.diversifier.0.to_sql()?, + (output.note.value as i64).to_sql()?, + rcm.to_sql()?, + nf.to_sql()?, + output.is_change.to_sql()?, + ])?; + let note_row = data.last_insert_rowid(); + + // Save witness for note. + witnesses.push(WitnessRow { + id_note: note_row, + witness: output.witness, + }); + + // Cache nullifier for note (to detect subsequent spends in this scan). + nullifiers.push((nf, output.account)); + } + } + + // Insert current witnesses into the database. + let mut encoded = Vec::new(); + for witness_row in witnesses.iter() { + encoded.clear(); + witness_row + .witness + .write(&mut encoded) + .expect("Should be able to write to a Vec"); + stmt_insert_witness.execute(&[ + witness_row.id_note.to_sql()?, + last_height.to_sql()?, + encoded.to_sql()?, + ])?; + } + + // Prune the stored witnesses (we only expect rollbacks of at most 100 blocks). + stmt_prune_witnesses.execute(&[last_height - 100])?; + + // Update now-expired transactions that didn't get mined. + stmt_update_expired.execute(&[last_height])?; + + // Commit the SQL transaction, writing this block's data atomically. + data.execute("COMMIT", NO_PARAMS)?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use tempfile::NamedTempFile; + use zcash_primitives::{ + block::BlockHash, + transaction::components::Amount, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + }; + + use super::scan_cached_blocks; + use crate::{ + init::{init_accounts_table, init_cache_database, init_data_database}, + query::get_balance, + tests::{fake_compact_block, fake_compact_block_spending, insert_into_cache}, + SAPLING_ACTIVATION_HEIGHT, + }; + + #[test] + fn scan_cached_blocks_requires_sequential_blocks() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Create a block with height SAPLING_ACTIVATION_HEIGHT + let value = Amount::from_u64(50000).unwrap(); + let (cb1, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb1); + scan_cached_blocks(db_cache, db_data).unwrap(); + assert_eq!(get_balance(db_data, 0).unwrap(), value); + + // We cannot scan a block of height SAPLING_ACTIVATION_HEIGHT + 2 next + let (cb2, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 1, + cb1.hash(), + extfvk.clone(), + value, + ); + let (cb3, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 2, + cb2.hash(), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb3); + match scan_cached_blocks(db_cache, db_data) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!( + e.to_string(), + format!( + "Expected height of next CompactBlock to be {}, but was {}", + SAPLING_ACTIVATION_HEIGHT + 1, + SAPLING_ACTIVATION_HEIGHT + 2 + ) + ), + } + + // If we add a block of height SAPLING_ACTIVATION_HEIGHT + 1, we can now scan both + insert_into_cache(db_cache, &cb2); + scan_cached_blocks(db_cache, db_data).unwrap(); + assert_eq!( + get_balance(db_data, 0).unwrap(), + Amount::from_u64(150_000).unwrap() + ); + } + + #[test] + fn scan_cached_blocks_finds_received_notes() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Account balance should be zero + assert_eq!(get_balance(db_data, 0).unwrap(), Amount::zero()); + + // Create a fake CompactBlock sending value to the address + let value = Amount::from_u64(5).unwrap(); + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + + // Scan the cache + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Account balance should reflect the received note + assert_eq!(get_balance(db_data, 0).unwrap(), value); + + // Create a second fake CompactBlock sending more value to the address + let value2 = Amount::from_u64(7).unwrap(); + let (cb2, _) = fake_compact_block(SAPLING_ACTIVATION_HEIGHT + 1, cb.hash(), extfvk, value2); + insert_into_cache(db_cache, &cb2); + + // Scan the cache again + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Account balance should reflect both received notes + assert_eq!(get_balance(db_data, 0).unwrap(), value + value2); + } + + #[test] + fn scan_cached_blocks_finds_change_notes() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Account balance should be zero + assert_eq!(get_balance(db_data, 0).unwrap(), Amount::zero()); + + // Create a fake CompactBlock sending value to the address + let value = Amount::from_u64(5).unwrap(); + let (cb, nf) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + + // Scan the cache + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Account balance should reflect the received note + assert_eq!(get_balance(db_data, 0).unwrap(), value); + + // Create a second fake CompactBlock spending value from the address + let extsk2 = ExtendedSpendingKey::master(&[0]); + let to2 = extsk2.default_address().unwrap().1; + let value2 = Amount::from_u64(2).unwrap(); + insert_into_cache( + db_cache, + &fake_compact_block_spending( + SAPLING_ACTIVATION_HEIGHT + 1, + cb.hash(), + (nf, value), + extfvk, + to2, + value2, + ), + ); + + // Scan the cache again + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Account balance should equal the change + assert_eq!(get_balance(db_data, 0).unwrap(), value - value2); + } +} From 4c1237fa501717061c2d4ef3ecf4896b81e836f5 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 9 Mar 2019 03:20:32 +0000 Subject: [PATCH 095/105] zcash_client_sqlite::transact::create_to_address() --- Cargo.lock | 2 + zcash_client_backend/src/constants.rs | 4 + zcash_client_sqlite/Cargo.toml | 4 +- zcash_client_sqlite/src/error.rs | 29 +- zcash_client_sqlite/src/lib.rs | 1 + zcash_client_sqlite/src/transact.rs | 661 ++++++++++++++++++++ zcash_primitives/src/transaction/builder.rs | 23 + 7 files changed, 722 insertions(+), 2 deletions(-) create mode 100644 zcash_client_sqlite/src/transact.rs diff --git a/Cargo.lock b/Cargo.lock index aa11a84..6fd7629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -674,8 +674,10 @@ dependencies = [ "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_client_backend 0.0.0", "zcash_primitives 0.0.0", + "zcash_proofs 0.0.0", ] [[package]] diff --git a/zcash_client_backend/src/constants.rs b/zcash_client_backend/src/constants.rs index 8e5727c..ee858a1 100644 --- a/zcash_client_backend/src/constants.rs +++ b/zcash_client_backend/src/constants.rs @@ -2,3 +2,7 @@ pub mod mainnet; pub mod testnet; + +pub const SPROUT_CONSENSUS_BRANCH_ID: u32 = 0; +pub const OVERWINTER_CONSENSUS_BRANCH_ID: u32 = 0x5ba8_1b19; +pub const SAPLING_CONSENSUS_BRANCH_ID: u32 = 0x76b8_09bb; diff --git a/zcash_client_sqlite/Cargo.toml b/zcash_client_sqlite/Cargo.toml index d572a38..167068f 100644 --- a/zcash_client_sqlite/Cargo.toml +++ b/zcash_client_sqlite/Cargo.toml @@ -9,13 +9,15 @@ edition = "2018" [dependencies] bech32 = "0.7" ff = { path = "../ff" } +pairing = { path = "../pairing" } protobuf = "2" rusqlite = { version = "0.20", features = ["bundled"] } +time = "0.1" zcash_client_backend = { path = "../zcash_client_backend" } zcash_primitives = { path = "../zcash_primitives" } [dev-dependencies] -pairing = { path = "../pairing" } rand_core = "0.5" rand_os = "0.2" tempfile = "3" +zcash_proofs = { path = "../zcash_proofs" } diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index fcdc1a0..52ff230 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -1,17 +1,25 @@ use std::error; use std::fmt; -use zcash_primitives::{sapling::Node, transaction::TxId}; +use zcash_primitives::{ + sapling::Node, + transaction::{builder, TxId}, +}; #[derive(Debug)] pub enum ErrorKind { CorruptedData(&'static str), IncorrectHRPExtFVK, + InsufficientBalance(u64, u64), + InvalidExtSK(u32), InvalidHeight(i32, i32), + InvalidMemo(std::str::Utf8Error), InvalidNewWitnessAnchor(usize, TxId, i32, Node), + InvalidNote, InvalidWitnessAnchor(i64, i32), ScanRequired, TableNotEmpty, Bech32(bech32::Error), + Builder(builder::Error), Database(rusqlite::Error), Io(std::io::Error), Protobuf(protobuf::ProtobufError), @@ -25,16 +33,26 @@ impl fmt::Display for Error { match &self.0 { ErrorKind::CorruptedData(reason) => write!(f, "Data DB is corrupted: {}", reason), ErrorKind::IncorrectHRPExtFVK => write!(f, "Incorrect HRP for extfvk"), + ErrorKind::InsufficientBalance(have, need) => write!( + f, + "Insufficient balance (have {}, need {} including fee)", + have, need + ), + ErrorKind::InvalidExtSK(account) => { + write!(f, "Incorrect ExtendedSpendingKey for account {}", account) + } ErrorKind::InvalidHeight(expected, actual) => write!( f, "Expected height of next CompactBlock to be {}, but was {}", expected, actual ), + ErrorKind::InvalidMemo(e) => write!(f, "{}", e), ErrorKind::InvalidNewWitnessAnchor(output, txid, last_height, anchor) => write!( f, "New witness for output {} in tx {} has incorrect anchor after scanning block {}: {:?}", output, txid, last_height, anchor, ), + ErrorKind::InvalidNote => write!(f, "Invalid note"), ErrorKind::InvalidWitnessAnchor(id_note, last_height) => write!( f, "Witness for note {} has incorrect anchor after scanning block {}", @@ -43,6 +61,7 @@ impl fmt::Display for Error { ErrorKind::ScanRequired => write!(f, "Must scan blocks first"), ErrorKind::TableNotEmpty => write!(f, "Table is not empty"), ErrorKind::Bech32(e) => write!(f, "{}", e), + ErrorKind::Builder(e) => write!(f, "{:?}", e), ErrorKind::Database(e) => write!(f, "{}", e), ErrorKind::Io(e) => write!(f, "{}", e), ErrorKind::Protobuf(e) => write!(f, "{}", e), @@ -53,7 +72,9 @@ impl fmt::Display for Error { impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match &self.0 { + ErrorKind::InvalidMemo(e) => Some(e), ErrorKind::Bech32(e) => Some(e), + ErrorKind::Builder(e) => Some(e), ErrorKind::Database(e) => Some(e), ErrorKind::Io(e) => Some(e), ErrorKind::Protobuf(e) => Some(e), @@ -68,6 +89,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: builder::Error) -> Self { + Error(ErrorKind::Builder(e)) + } +} + impl From for Error { fn from(e: rusqlite::Error) -> Self { Error(ErrorKind::Database(e)) diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index c9fa4c8..1da09d5 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -30,6 +30,7 @@ pub mod error; pub mod init; pub mod query; pub mod scan; +pub mod transact; const ANCHOR_OFFSET: u32 = 10; const SAPLING_ACTIVATION_HEIGHT: i32 = 280_000; diff --git a/zcash_client_sqlite/src/transact.rs b/zcash_client_sqlite/src/transact.rs new file mode 100644 index 0000000..eb9cd68 --- /dev/null +++ b/zcash_client_sqlite/src/transact.rs @@ -0,0 +1,661 @@ +//! Functions for creating transactions. + +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::Bls12; +use rusqlite::{types::ToSql, Connection, NO_PARAMS}; +use std::path::Path; +use zcash_client_backend::{ + constants::testnet::{HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS}, + encoding::{encode_extended_full_viewing_key, encode_payment_address}, +}; +use zcash_primitives::{ + jubjub::fs::{Fs, FsRepr}, + merkle_tree::IncrementalWitness, + note_encryption::Memo, + primitives::{Diversifier, Note, PaymentAddress}, + prover::TxProver, + sapling::Node, + transaction::{ + builder::Builder, + components::{amount::DEFAULT_FEE, Amount}, + }, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + JUBJUB, +}; + +use crate::{ + error::{Error, ErrorKind}, + get_target_and_anchor_heights, +}; + +struct SelectedNoteRow { + diversifier: Diversifier, + note: Note, + witness: IncrementalWitness, +} + +/// Creates a transaction paying the specified address from the given account. +/// +/// Returns the row index of the newly-created transaction in the `transactions` table +/// within the data database. The caller can read the raw transaction bytes from the `raw` +/// column in order to broadcast the transaction to the network. +/// +/// Do not call this multiple times in parallel, or you will generate transactions that +/// double-spend the same notes. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_backend::{ +/// constants::{testnet::COIN_TYPE, SAPLING_CONSENSUS_BRANCH_ID}, +/// keys::spending_key, +/// }; +/// use zcash_client_sqlite::transact::create_to_address; +/// use zcash_primitives::transaction::components::Amount; +/// use zcash_proofs::prover::LocalTxProver; +/// +/// let tx_prover = match LocalTxProver::with_default_location() { +/// Some(tx_prover) => tx_prover, +/// None => { +/// panic!("Cannot locate the Zcash parameters. Please run zcash-fetch-params or fetch-params.sh to download the parameters, and then re-run the tests."); +/// } +/// }; +/// +/// let account = 0; +/// let extsk = spending_key(&[0; 32][..], COIN_TYPE, account); +/// let to = extsk.default_address().unwrap().1; +/// match create_to_address( +/// "/path/to/data.db", +/// SAPLING_CONSENSUS_BRANCH_ID, +/// tx_prover, +/// (account, &extsk), +/// &to, +/// Amount::from_u64(1).unwrap(), +/// None, +/// ) { +/// Ok(tx_row) => (), +/// Err(e) => (), +/// } +/// ``` +pub fn create_to_address>( + db_data: P, + consensus_branch_id: u32, + prover: impl TxProver, + (account, extsk): (u32, &ExtendedSpendingKey), + to: &PaymentAddress, + value: Amount, + memo: Option, +) -> Result { + let data = Connection::open(db_data)?; + + // Check that the ExtendedSpendingKey we have been given corresponds to the + // ExtendedFullViewingKey for the account we are spending from. + let extfvk = ExtendedFullViewingKey::from(extsk); + if !data + .prepare("SELECT * FROM accounts WHERE account = ? AND extfvk = ?")? + .exists(&[ + account.to_sql()?, + encode_extended_full_viewing_key(HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, &extfvk) + .to_sql()?, + ])? + { + return Err(Error(ErrorKind::InvalidExtSK(account))); + } + let ovk = extfvk.fvk.ovk; + + // Target the next block, assuming we are up-to-date. + let (height, anchor_height) = { + let (target_height, anchor_height) = get_target_and_anchor_heights(&data)?; + (target_height, i64::from(anchor_height)) + }; + + // The goal of this SQL statement is to select the oldest notes until the required + // value has been reached, and then fetch the witnesses at the desired height for the + // selected notes. This is achieved in several steps: + // + // 1) Use a window function to create a view of all notes, ordered from oldest to + // newest, with an additional column containing a running sum: + // - Unspent notes accumulate the values of all unspent notes in that note's + // account, up to itself. + // - Spent notes accumulate the values of all notes in the transaction they were + // spent in, up to itself. + // + // 2) Select all unspent notes in the desired account, along with their running sum. + // + // 3) Select all notes for which the running sum was less than the required value, as + // well as a single note for which the sum was greater than or equal to the + // required value, bringing the sum of all selected notes across the threshold. + // + // 4) Match the selected notes against the witnesses at the desired height. + let target_value = i64::from(value + DEFAULT_FEE); + let mut stmt_select_notes = data.prepare( + "WITH selected AS ( + WITH eligible AS ( + SELECT id_note, diversifier, value, rcm, + SUM(value) OVER + (PARTITION BY account, spent ORDER BY id_note) AS so_far + FROM received_notes + INNER JOIN transactions ON transactions.id_tx = received_notes.tx + WHERE account = ? AND spent IS NULL AND transactions.block <= ? + ) + SELECT * FROM eligible WHERE so_far < ? + UNION + SELECT * FROM (SELECT * FROM eligible WHERE so_far >= ? LIMIT 1) + ), witnesses AS ( + SELECT note, witness FROM sapling_witnesses + WHERE block = ? + ) + SELECT selected.diversifier, selected.value, selected.rcm, witnesses.witness + FROM selected + INNER JOIN witnesses ON selected.id_note = witnesses.note", + )?; + + // Select notes + let notes = stmt_select_notes.query_and_then::<_, Error, _, _>( + &[ + i64::from(account), + anchor_height, + target_value, + target_value, + anchor_height, + ], + |row| { + let diversifier = { + let d: Vec<_> = row.get(0)?; + if d.len() != 11 { + return Err(Error(ErrorKind::CorruptedData( + "Invalid diversifier length", + ))); + } + let mut tmp = [0; 11]; + tmp.copy_from_slice(&d); + Diversifier(tmp) + }; + + let note_value: i64 = row.get(1)?; + + let rcm = { + let d: Vec<_> = row.get(2)?; + let mut tmp = FsRepr::default(); + tmp.read_le(&d[..])?; + Fs::from_repr(tmp).map_err(|_| Error(ErrorKind::InvalidNote))? + }; + + let from = extfvk + .fvk + .vk + .into_payment_address(diversifier, &JUBJUB) + .unwrap(); + let note = from.create_note(note_value as u64, rcm, &JUBJUB).unwrap(); + + let witness = { + let d: Vec<_> = row.get(3)?; + IncrementalWitness::read(&d[..])? + }; + + Ok(SelectedNoteRow { + diversifier, + note, + witness, + }) + }, + )?; + let notes: Vec = notes.collect::>()?; + + // Confirm we were able to select sufficient value + let selected_value = notes + .iter() + .fold(0, |acc, selected| acc + selected.note.value); + if selected_value < target_value as u64 { + return Err(Error(ErrorKind::InsufficientBalance( + selected_value, + target_value as u64, + ))); + } + + // Create the transaction + let mut builder = Builder::new(height); + for selected in notes { + builder.add_sapling_spend( + extsk.clone(), + selected.diversifier, + selected.note, + selected.witness, + )?; + } + builder.add_sapling_output(ovk, to.clone(), value, memo.clone())?; + let (tx, tx_metadata) = builder.build(consensus_branch_id, prover)?; + // We only called add_sapling_output() once. + let output_index = match tx_metadata.output_index(0) { + Some(idx) => idx as i64, + None => panic!("Output 0 should exist in the transaction"), + }; + let created = time::get_time(); + + // Update the database atomically, to ensure the result is internally consistent. + data.execute("BEGIN IMMEDIATE", NO_PARAMS)?; + + // Save the transaction in the database. + let mut raw_tx = vec![]; + tx.write(&mut raw_tx)?; + let mut stmt_insert_tx = data.prepare( + "INSERT INTO transactions (txid, created, expiry_height, raw) + VALUES (?, ?, ?, ?)", + )?; + stmt_insert_tx.execute(&[ + tx.txid().0.to_sql()?, + created.to_sql()?, + tx.expiry_height.to_sql()?, + raw_tx.to_sql()?, + ])?; + let id_tx = data.last_insert_rowid(); + + // Mark notes as spent. + // + // This locks the notes so they aren't selected again by a subsequent call to + // create_to_address() before this transaction has been mined (at which point the notes + // get re-marked as spent). + // + // Assumes that create_to_address() will never be called in parallel, which is a + // reasonable assumption for a light client such as a mobile phone. + let mut stmt_mark_spent_note = + data.prepare("UPDATE received_notes SET spent = ? WHERE nf = ?")?; + for spend in &tx.shielded_spends { + stmt_mark_spent_note.execute(&[id_tx.to_sql()?, spend.nullifier.to_sql()?])?; + } + + // Save the sent note in the database. + let to_str = encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, to); + if let Some(memo) = memo { + let mut stmt_insert_sent_note = data.prepare( + "INSERT INTO sent_notes (tx, output_index, from_account, address, value, memo) + VALUES (?, ?, ?, ?, ?, ?)", + )?; + stmt_insert_sent_note.execute(&[ + id_tx.to_sql()?, + output_index.to_sql()?, + account.to_sql()?, + to_str.to_sql()?, + i64::from(value).to_sql()?, + memo.as_bytes().to_sql()?, + ])?; + } else { + let mut stmt_insert_sent_note = data.prepare( + "INSERT INTO sent_notes (tx, output_index, from_account, address, value) + VALUES (?, ?, ?, ?, ?)", + )?; + stmt_insert_sent_note.execute(&[ + id_tx.to_sql()?, + output_index.to_sql()?, + account.to_sql()?, + to_str.to_sql()?, + i64::from(value).to_sql()?, + ])?; + } + + data.execute("COMMIT", NO_PARAMS)?; + + // Return the row number of the transaction, so the caller can fetch it for sending. + Ok(id_tx) +} + +#[cfg(test)] +mod tests { + use tempfile::NamedTempFile; + use zcash_primitives::{ + block::BlockHash, + prover::TxProver, + transaction::components::Amount, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + }; + use zcash_proofs::prover::LocalTxProver; + + use super::create_to_address; + use crate::{ + init::{init_accounts_table, init_blocks_table, init_cache_database, init_data_database}, + query::{get_balance, get_verified_balance}, + scan::scan_cached_blocks, + tests::{fake_compact_block, insert_into_cache}, + SAPLING_ACTIVATION_HEIGHT, + }; + + fn test_prover() -> impl TxProver { + match LocalTxProver::with_default_location() { + Some(tx_prover) => tx_prover, + None => { + panic!("Cannot locate the Zcash parameters. Please run zcash-fetch-params or fetch-params.sh to download the parameters, and then re-run the tests."); + } + } + } + + #[test] + fn create_to_address_fails_on_incorrect_extsk() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add two accounts to the wallet + let extsk0 = ExtendedSpendingKey::master(&[]); + let extsk1 = ExtendedSpendingKey::master(&[0]); + let extfvks = [ + ExtendedFullViewingKey::from(&extsk0), + ExtendedFullViewingKey::from(&extsk1), + ]; + init_accounts_table(&db_data, &extfvks).unwrap(); + let to = extsk0.default_address().unwrap().1; + + // Invalid extsk for the given account should cause an error + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk1), + &to, + Amount::from_u64(1).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!(e.to_string(), "Incorrect ExtendedSpendingKey for account 0"), + } + match create_to_address( + db_data, + 1, + test_prover(), + (1, &extsk0), + &to, + Amount::from_u64(1).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!(e.to_string(), "Incorrect ExtendedSpendingKey for account 1"), + } + } + + #[test] + fn create_to_address_fails_with_no_blocks() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvks = [ExtendedFullViewingKey::from(&extsk)]; + init_accounts_table(&db_data, &extfvks).unwrap(); + let to = extsk.default_address().unwrap().1; + + // We cannot do anything if we aren't synchronised + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(1).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!(e.to_string(), "Must scan blocks first"), + } + } + + #[test] + fn create_to_address_fails_on_insufficient_balance() { + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + init_blocks_table(&db_data, 1, BlockHash([1; 32]), 1, &[]).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvks = [ExtendedFullViewingKey::from(&extsk)]; + init_accounts_table(&db_data, &extfvks).unwrap(); + let to = extsk.default_address().unwrap().1; + + // Account balance should be zero + assert_eq!(get_balance(db_data, 0).unwrap(), Amount::zero()); + + // We cannot spend anything + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(1).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!( + e.to_string(), + "Insufficient balance (have 0, need 10001 including fee)" + ), + } + } + + #[test] + fn create_to_address_fails_on_unverified_notes() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Add funds to the wallet in a single note + let value = Amount::from_u64(50000).unwrap(); + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Verified balance matches total balance + assert_eq!(get_balance(db_data, 0).unwrap(), value); + assert_eq!(get_verified_balance(db_data, 0).unwrap(), value); + + // Add more funds to the wallet in a second note + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 1, + cb.hash(), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Verified balance does not include the second note + assert_eq!(get_balance(db_data, 0).unwrap(), value + value); + assert_eq!(get_verified_balance(db_data, 0).unwrap(), value); + + // Spend fails because there are insufficient verified notes + let extsk2 = ExtendedSpendingKey::master(&[]); + let to = extsk2.default_address().unwrap().1; + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(70000).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!( + e.to_string(), + "Insufficient balance (have 50000, need 80000 including fee)" + ), + } + + // Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second + // note is verified + for i in 2..10 { + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + i, + cb.hash(), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + } + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Second spend still fails + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(70000).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!( + e.to_string(), + "Insufficient balance (have 50000, need 80000 including fee)" + ), + } + + // Mine block 11 so that the second note becomes verified + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 10, + cb.hash(), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Second spend should now succeed + create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(70000).unwrap(), + None, + ) + .unwrap(); + } + + #[test] + fn create_to_address_fails_on_locked_notes() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Add funds to the wallet in a single note + let value = Amount::from_u64(50000).unwrap(); + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + value, + ); + insert_into_cache(db_cache, &cb); + scan_cached_blocks(db_cache, db_data).unwrap(); + assert_eq!(get_balance(db_data, 0).unwrap(), value); + + // Send some of the funds to another address + let extsk2 = ExtendedSpendingKey::master(&[]); + let to = extsk2.default_address().unwrap().1; + create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(15000).unwrap(), + None, + ) + .unwrap(); + + // A second spend fails because there are no usable notes + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(2000).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!( + e.to_string(), + "Insufficient balance (have 0, need 12000 including fee)" + ), + } + + // Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds) + // until just before the first transaction expires + for i in 1..22 { + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + i, + cb.hash(), + ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])), + value, + ); + insert_into_cache(db_cache, &cb); + } + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Second spend still fails + match create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(2000).unwrap(), + None, + ) { + Ok(_) => panic!("Should have failed"), + Err(e) => assert_eq!( + e.to_string(), + "Insufficient balance (have 0, need 12000 including fee)" + ), + } + + // Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 22, + cb.hash(), + ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])), + value, + ); + insert_into_cache(db_cache, &cb); + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Second spend should now succeed + create_to_address( + db_data, + 1, + test_prover(), + (0, &extsk), + &to, + Amount::from_u64(2000).unwrap(), + None, + ) + .unwrap(); + } +} diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index b0e96f5..63e27cd 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -7,6 +7,8 @@ use crate::{ use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore}; +use std::error; +use std::fmt; use zip32::ExtendedSpendingKey; use crate::{ @@ -42,6 +44,27 @@ pub enum Error { SpendProof, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::AnchorMismatch => { + write!(f, "Anchor mismatch (anchors for all spends must be equal)") + } + Error::BindingSig => write!(f, "Failed to create bindingSig"), + Error::ChangeIsNegative(amount) => { + write!(f, "Change is negative ({:?} zatoshis)", amount) + } + Error::InvalidAddress => write!(f, "Invalid address"), + Error::InvalidAmount => write!(f, "Invalid amount"), + Error::InvalidWitness => write!(f, "Invalid note witness"), + Error::NoChangeAddress => write!(f, "No change address specified or discoverable"), + Error::SpendProof => write!(f, "Failed to create Sapling spend proof"), + } + } +} + +impl error::Error for Error {} + struct SpendDescriptionInfo { extsk: ExtendedSpendingKey, diversifier: Diversifier, From cfaa0cf067934f31898282c007be919026d79c95 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 9 Mar 2019 03:22:35 +0000 Subject: [PATCH 096/105] zcash_client_sqlite::query::get_*_memo_as_utf8() --- zcash_client_sqlite/src/query.rs | 70 +++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/zcash_client_sqlite/src/query.rs b/zcash_client_sqlite/src/query.rs index 7806b8d..656e692 100644 --- a/zcash_client_sqlite/src/query.rs +++ b/zcash_client_sqlite/src/query.rs @@ -2,7 +2,7 @@ use rusqlite::Connection; use std::path::Path; -use zcash_primitives::transaction::components::Amount; +use zcash_primitives::{note_encryption::Memo, transaction::components::Amount}; use crate::{ error::{Error, ErrorKind}, @@ -91,6 +91,74 @@ pub fn get_verified_balance>(db_data: P, account: u32) -> Result< } } +/// Returns the memo for a received note, if it is known and a valid UTF-8 string. +/// +/// The note is identified by its row index in the `received_notes` table within the data +/// database. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_sqlite::query::get_received_memo_as_utf8; +/// +/// let memo = get_received_memo_as_utf8("/path/to/data.db", 27); +pub fn get_received_memo_as_utf8>( + db_data: P, + id_note: i64, +) -> Result, Error> { + let data = Connection::open(db_data)?; + + let memo: Vec<_> = data.query_row( + "SELECT memo FROM received_notes + WHERE id_note = ?", + &[id_note], + |row| row.get(0), + )?; + + match Memo::from_bytes(&memo) { + Some(memo) => match memo.to_utf8() { + Some(Ok(res)) => Ok(Some(res)), + Some(Err(e)) => Err(Error(ErrorKind::InvalidMemo(e))), + None => Ok(None), + }, + None => Ok(None), + } +} + +/// Returns the memo for a sent note, if it is known and a valid UTF-8 string. +/// +/// The note is identified by its row index in the `sent_notes` table within the data +/// database. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_sqlite::query::get_sent_memo_as_utf8; +/// +/// let memo = get_sent_memo_as_utf8("/path/to/data.db", 12); +pub fn get_sent_memo_as_utf8>( + db_data: P, + id_note: i64, +) -> Result, Error> { + let data = Connection::open(db_data)?; + + let memo: Vec<_> = data.query_row( + "SELECT memo FROM sent_notes + WHERE id_note = ?", + &[id_note], + |row| row.get(0), + )?; + + match Memo::from_bytes(&memo) { + Some(memo) => match memo.to_utf8() { + Some(Ok(res)) => Ok(Some(res)), + Some(Err(e)) => Err(Error(ErrorKind::InvalidMemo(e))), + None => Ok(None), + }, + None => Ok(None), + } +} + #[cfg(test)] mod tests { use tempfile::NamedTempFile; From 2419c6648cd150724a2bb8a7171e873b7b62847e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 13 Mar 2019 05:46:17 +0000 Subject: [PATCH 097/105] Add security disclaimer to README --- zcash_client_sqlite/README.md | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/zcash_client_sqlite/README.md b/zcash_client_sqlite/README.md index 2c244f8..b5fc4f1 100644 --- a/zcash_client_sqlite/README.md +++ b/zcash_client_sqlite/README.md @@ -1,3 +1,43 @@ +# Security Disclaimer + +#### :warning: WARNING: This is an *early preview* + +---- + +In the spirit of transparency, we provide this as a window into what we are actively +developing. This is an alpha build, not yet intended for 3rd party use. Please be advised +of the following: + +* 🛑 This code currently is not audited. 🛑 +* ❌ This is a public, active branch with **no support**. +* ❌ The code **does not have** documentation that is reviewed and approved by our Documentation team. +* ❌ The code **does not have** adequate unit tests, acceptance tests and stress tests. +* ❌ The code **does not have** automated tests that use the officially supported CI system. +* ❌ The code **has not been subjected to thorough review** by engineers at the Electric Coin Company. +* :warning: This library **is** compatible with the latest version of zcashd, but there **is no** automated testing of this. +* :heavy_check_mark: The library **is not** majorly broken in some way. +* ❌ The library **only runs** on testnet. +* ❌ The library **does not run** on mainnet or regtest. +* ❌ We **are actively rebasing** this branch and adding features where/when needed. +* ❌ We **do not** undertake appropriate security coverage (threat models, review, response, etc.). +* :heavy_check_mark: There is a product manager for this library. +* :heavy_check_mark: Electric Coin Company maintains the library as we discover bugs and do network upgrades/minor releases. +* :heavy_check_mark: Users can expect to get a response within a few weeks after submitting an issue. +* ❌ The User Support team **has not yet been briefed** on the features provided to users and the functionality of the associated test-framework. +* ❌ The code is **not fully-documented**. + + +### 🛑 Use of this code may lead to a loss of funds 🛑 + +Use of this code in its current form or with modifications may lead to loss of funds, loss +of "expected" privacy, or denial of service for a large portion of users, or a bug which +could leverage any of those kinds of attacks (especially a "0 day" where we suspect few +people know about the vulnerability). + +### :eyes: At this time, this is for preview purposes only. :eyes: + +---- + # zcash_client_sqlite This library contains APIs that collectively implement a Zcash light client in From 98db781931a228e2dabd8c20c0cec3d0f23d49ec Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 8 Apr 2019 12:24:49 +0100 Subject: [PATCH 098/105] Add mainnet support to zcash_client_sqlite via a feature flag --- zcash_client_sqlite/Cargo.toml | 3 +++ zcash_client_sqlite/README.md | 3 +-- zcash_client_sqlite/src/init.rs | 12 ++++-------- zcash_client_sqlite/src/lib.rs | 24 +++++++++++++++++++++--- zcash_client_sqlite/src/scan.rs | 3 +-- zcash_client_sqlite/src/transact.rs | 8 +++----- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/zcash_client_sqlite/Cargo.toml b/zcash_client_sqlite/Cargo.toml index 167068f..697cb12 100644 --- a/zcash_client_sqlite/Cargo.toml +++ b/zcash_client_sqlite/Cargo.toml @@ -21,3 +21,6 @@ rand_core = "0.5" rand_os = "0.2" tempfile = "3" zcash_proofs = { path = "../zcash_proofs" } + +[features] +mainnet = [] diff --git a/zcash_client_sqlite/README.md b/zcash_client_sqlite/README.md index b5fc4f1..d73e3fe 100644 --- a/zcash_client_sqlite/README.md +++ b/zcash_client_sqlite/README.md @@ -16,8 +16,7 @@ of the following: * ❌ The code **has not been subjected to thorough review** by engineers at the Electric Coin Company. * :warning: This library **is** compatible with the latest version of zcashd, but there **is no** automated testing of this. * :heavy_check_mark: The library **is not** majorly broken in some way. -* ❌ The library **only runs** on testnet. -* ❌ The library **does not run** on mainnet or regtest. +* :heavy_check_mark: The library **does run** on mainnet and testnet. * ❌ We **are actively rebasing** this branch and adding features where/when needed. * ❌ We **do not** undertake appropriate security coverage (threat models, review, response, etc.). * :heavy_check_mark: There is a product manager for this library. diff --git a/zcash_client_sqlite/src/init.rs b/zcash_client_sqlite/src/init.rs index e457ad9..e6eeaff 100644 --- a/zcash_client_sqlite/src/init.rs +++ b/zcash_client_sqlite/src/init.rs @@ -2,15 +2,13 @@ use rusqlite::{types::ToSql, Connection, NO_PARAMS}; use std::path::Path; -use zcash_client_backend::{ - constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, - encoding::encode_extended_full_viewing_key, -}; +use zcash_client_backend::encoding::encode_extended_full_viewing_key; use zcash_primitives::{block::BlockHash, zip32::ExtendedFullViewingKey}; use crate::{ address_from_extfvk, error::{Error, ErrorKind}, + HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, }; /// Sets up the internal structure of the cache database. @@ -243,16 +241,14 @@ pub fn init_blocks_table>( #[cfg(test)] mod tests { use tempfile::NamedTempFile; - use zcash_client_backend::{ - constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, encoding::decode_payment_address, - }; + use zcash_client_backend::encoding::decode_payment_address; use zcash_primitives::{ block::BlockHash, zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, }; use super::{init_accounts_table, init_blocks_table, init_data_database}; - use crate::query::get_address; + use crate::{query::get_address, HRP_SAPLING_PAYMENT_ADDRESS}; #[test] fn init_accounts_table_only_works_once() { diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 1da09d5..b26df3e 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -16,16 +16,29 @@ //! **MUST NOT** write to the database without using these APIs. Callers **MAY** read //! the database directly in order to extract information for display to users. //! +//! # Features +//! +//! The `mainnet` feature configures the light client for use with the Zcash mainnet. By +//! default, the light client is configured for use with the Zcash testnet. +//! //! [`CompactBlock`]: zcash_client_backend::proto::compact_formats::CompactBlock //! [`init_cache_database`]: crate::init::init_cache_database use rusqlite::{Connection, NO_PARAMS}; use std::cmp; -use zcash_client_backend::{ - constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, encoding::encode_payment_address, -}; +use zcash_client_backend::encoding::encode_payment_address; use zcash_primitives::zip32::ExtendedFullViewingKey; +#[cfg(feature = "mainnet")] +use zcash_client_backend::constants::mainnet::{ + HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS, +}; + +#[cfg(not(feature = "mainnet"))] +use zcash_client_backend::constants::testnet::{ + HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS, +}; + pub mod error; pub mod init; pub mod query; @@ -33,6 +46,11 @@ pub mod scan; pub mod transact; const ANCHOR_OFFSET: u32 = 10; + +#[cfg(feature = "mainnet")] +const SAPLING_ACTIVATION_HEIGHT: i32 = 419_200; + +#[cfg(not(feature = "mainnet"))] const SAPLING_ACTIVATION_HEIGHT: i32 = 280_000; fn address_from_extfvk(extfvk: &ExtendedFullViewingKey) -> String { diff --git a/zcash_client_sqlite/src/scan.rs b/zcash_client_sqlite/src/scan.rs index 44ec1cb..75fd9ca 100644 --- a/zcash_client_sqlite/src/scan.rs +++ b/zcash_client_sqlite/src/scan.rs @@ -5,7 +5,6 @@ use protobuf::parse_from_bytes; use rusqlite::{types::ToSql, Connection, NO_PARAMS}; use std::path::Path; use zcash_client_backend::{ - constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, encoding::decode_extended_full_viewing_key, proto::compact_formats::CompactBlock, welding_rig::scan_block, }; @@ -17,7 +16,7 @@ use zcash_primitives::{ use crate::{ error::{Error, ErrorKind}, - SAPLING_ACTIVATION_HEIGHT, + HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, SAPLING_ACTIVATION_HEIGHT, }; struct CompactBlockRow { diff --git a/zcash_client_sqlite/src/transact.rs b/zcash_client_sqlite/src/transact.rs index eb9cd68..936cc9f 100644 --- a/zcash_client_sqlite/src/transact.rs +++ b/zcash_client_sqlite/src/transact.rs @@ -4,10 +4,7 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; use rusqlite::{types::ToSql, Connection, NO_PARAMS}; use std::path::Path; -use zcash_client_backend::{ - constants::testnet::{HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS}, - encoding::{encode_extended_full_viewing_key, encode_payment_address}, -}; +use zcash_client_backend::encoding::{encode_extended_full_viewing_key, encode_payment_address}; use zcash_primitives::{ jubjub::fs::{Fs, FsRepr}, merkle_tree::IncrementalWitness, @@ -25,7 +22,8 @@ use zcash_primitives::{ use crate::{ error::{Error, ErrorKind}, - get_target_and_anchor_heights, + get_target_and_anchor_heights, HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + HRP_SAPLING_PAYMENT_ADDRESS, }; struct SelectedNoteRow { From 601e88c633cc647568eb56f923417e108ae917b9 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 May 2019 11:27:43 +0100 Subject: [PATCH 099/105] Chain validity and reorg handling --- zcash_client_sqlite/src/chain.rs | 469 +++++++++++++++++++++++++++++++ zcash_client_sqlite/src/error.rs | 4 + zcash_client_sqlite/src/lib.rs | 1 + 3 files changed, 474 insertions(+) create mode 100644 zcash_client_sqlite/src/chain.rs diff --git a/zcash_client_sqlite/src/chain.rs b/zcash_client_sqlite/src/chain.rs new file mode 100644 index 0000000..faa1219 --- /dev/null +++ b/zcash_client_sqlite/src/chain.rs @@ -0,0 +1,469 @@ +//! Functions for enforcing chain validity and handling chain reorgs. +//! +//! # Examples +//! +//! ``` +//! use zcash_client_sqlite::{ +//! chain::{rewind_to_height, validate_combined_chain}, +//! error::ErrorKind, +//! scan::scan_cached_blocks, +//! }; +//! +//! let db_cache = "/path/to/cache.db"; +//! let db_data = "/path/to/data.db"; +//! +//! // 1) Download new CompactBlocks into db_cache. +//! +//! // 2) Run the chain validator on the received blocks. +//! // +//! // Given that we assume the server always gives us correct-at-the-time blocks, any +//! // errors are in the blocks we have previously cached or scanned. +//! if let Err(e) = validate_combined_chain(&db_cache, &db_data) { +//! match e.kind() { +//! ErrorKind::InvalidChain(upper_bound, _) => { +//! // a) Pick a height to rewind to. +//! // +//! // This might be informed by some external chain reorg information, or +//! // heuristics such as the platform, available bandwidth, size of recent +//! // CompactBlocks, etc. +//! let rewind_height = upper_bound - 10; +//! +//! // b) Rewind scanned block information. +//! rewind_to_height(&db_data, rewind_height); +//! +//! // c) Delete cached blocks from rewind_height onwards. +//! // +//! // This does imply that assumed-valid blocks will be re-downloaded, but it +//! // is also possible that in the intervening time, a chain reorg has +//! // occurred that orphaned some of those blocks. +//! +//! // d) If there is some separate thread or service downloading +//! // CompactBlocks, tell it to go back and download from rewind_height +//! // onwards. +//! } +//! _ => { +//! // Handle other errors. +//! } +//! } +//! } +//! +//! // 3) Scan (any remaining) cached blocks. +//! // +//! // At this point, the cache and scanned data are locally consistent (though not +//! // necessarily consistent with the latest chain tip - this would be discovered the +//! // next time this codepath is executed after new blocks are received). +//! scan_cached_blocks(&db_cache, &db_data); +//! ``` + +use protobuf::parse_from_bytes; +use rusqlite::{Connection, NO_PARAMS}; +use std::path::Path; +use zcash_client_backend::proto::compact_formats::CompactBlock; + +use crate::{ + error::{Error, ErrorKind}, + SAPLING_ACTIVATION_HEIGHT, +}; + +#[derive(Debug)] +pub enum ChainInvalidCause { + PrevHashMismatch, +} + +struct CompactBlockRow { + height: i32, + data: Vec, +} + +/// Checks that the scanned blocks in the data database, when combined with the recent +/// `CompactBlock`s in the cache database, form a valid chain. +/// +/// This function is built on the core assumption that the information provided in the +/// cache database is more likely to be accurate than the previously-scanned information. +/// This follows from the design (and trust) assumption that the `lightwalletd` server +/// provides accurate block information as of the time it was requested. +/// +/// Returns: +/// - `Ok(())` if the combined chain is valid. +/// - `Err(ErrorKind::InvalidChain(upper_bound, cause))` if the combined chain is invalid. +/// `upper_bound` is the height of the highest invalid block (on the assumption that the +/// highest block in the cache database is correct). +/// - `Err(e)` if there was an error during validation unrelated to chain validity. +/// +/// This function does not mutate either of the databases. +pub fn validate_combined_chain, Q: AsRef>( + db_cache: P, + db_data: Q, +) -> Result<(), Error> { + let cache = Connection::open(db_cache)?; + let data = Connection::open(db_data)?; + + // Recall where we synced up to previously. + // If we have never synced, use Sapling activation height to select all cached CompactBlocks. + let (have_scanned, last_scanned_height) = + data.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| { + row.get(0) + .map(|h| (true, h)) + .or(Ok((false, SAPLING_ACTIVATION_HEIGHT - 1))) + })?; + + // Fetch the CompactBlocks we need to validate + let mut stmt_blocks = cache + .prepare("SELECT height, data FROM compactblocks WHERE height > ? ORDER BY height DESC")?; + let mut rows = stmt_blocks.query_map(&[last_scanned_height], |row| { + Ok(CompactBlockRow { + height: row.get(0)?, + data: row.get(1)?, + }) + })?; + + // Take the highest cached block as accurate. + let (mut last_height, mut last_prev_hash) = { + let assumed_correct = match rows.next() { + Some(row) => row?, + None => { + // No cached blocks, and we've already validated the blocks we've scanned, + // so there's nothing to validate. + // TODO: Maybe we still want to check if there are cached blocks that are + // at heights we previously scanned? Check scanning flow again. + return Ok(()); + } + }; + let block: CompactBlock = parse_from_bytes(&assumed_correct.data)?; + (block.height as i32, block.prev_hash()) + }; + + for row in rows { + let row = row?; + + // Scanned blocks MUST be height-sequential. + if row.height != (last_height - 1) { + return Err(Error(ErrorKind::InvalidHeight(last_height - 1, row.height))); + } + last_height = row.height; + + let block: CompactBlock = parse_from_bytes(&row.data)?; + + // Cached blocks MUST be hash-chained. + if block.hash() != last_prev_hash { + return Err(Error(ErrorKind::InvalidChain( + last_height, + ChainInvalidCause::PrevHashMismatch, + ))); + } + last_prev_hash = block.prev_hash(); + } + + if have_scanned { + // Cached blocks MUST hash-chain to the last scanned block. + let last_scanned_hash = data.query_row( + "SELECT hash FROM blocks WHERE height = ?", + &[last_scanned_height], + |row| row.get::<_, Vec<_>>(0), + )?; + if &last_scanned_hash[..] != &last_prev_hash.0[..] { + return Err(Error(ErrorKind::InvalidChain( + last_scanned_height, + ChainInvalidCause::PrevHashMismatch, + ))); + } + } + + // All good! + Ok(()) +} + +/// Rewinds the data database to the given height. +/// +/// If the requested height is greater than or equal to the height of the last scanned +/// block, this function does nothing. +pub fn rewind_to_height>(db_data: P, height: i32) -> Result<(), Error> { + let data = Connection::open(db_data)?; + + // Recall where we synced up to previously. + // If we have never synced, use Sapling activation height. + let last_scanned_height = + data.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| { + row.get(0).or(Ok(SAPLING_ACTIVATION_HEIGHT - 1)) + })?; + + if height >= last_scanned_height { + // Nothing to do. + return Ok(()); + } + + // Start an SQL transaction for rewinding. + data.execute("BEGIN IMMEDIATE", NO_PARAMS)?; + + // Decrement witnesses. + data.execute("DELETE FROM sapling_witnesses WHERE block > ?", &[height])?; + + // Un-mine transactions. + data.execute( + "UPDATE transactions SET block = NULL, tx_index = NULL WHERE block > ?", + &[height], + )?; + + // Now that they aren't depended on, delete scanned blocks. + data.execute("DELETE FROM blocks WHERE height > ?", &[height])?; + + // Commit the SQL transaction, rewinding atomically. + data.execute("COMMIT", NO_PARAMS)?; + + Ok(()) +} + +#[cfg(test)] +mod tests { + use tempfile::NamedTempFile; + use zcash_primitives::{ + block::BlockHash, + transaction::components::Amount, + zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, + }; + + use super::{rewind_to_height, validate_combined_chain}; + use crate::{ + error::ErrorKind, + init::{init_accounts_table, init_cache_database, init_data_database}, + query::get_balance, + scan::scan_cached_blocks, + tests::{fake_compact_block, insert_into_cache}, + SAPLING_ACTIVATION_HEIGHT, + }; + + #[test] + fn valid_chain_states() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Empty chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + + // Create a fake CompactBlock sending value to the address + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + Amount::from_u64(5).unwrap(), + ); + insert_into_cache(db_cache, &cb); + + // Cache-only chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + + // Scan the cache + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Data-only chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + + // Create a second fake CompactBlock sending more value to the address + let (cb2, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 1, + cb.hash(), + extfvk, + Amount::from_u64(7).unwrap(), + ); + insert_into_cache(db_cache, &cb2); + + // Data+cache chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + + // Scan the cache again + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Data-only chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + } + + #[test] + fn invalid_chain_cache_disconnected() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Create some fake CompactBlocks + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + Amount::from_u64(5).unwrap(), + ); + let (cb2, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 1, + cb.hash(), + extfvk.clone(), + Amount::from_u64(7).unwrap(), + ); + insert_into_cache(db_cache, &cb); + insert_into_cache(db_cache, &cb2); + + // Scan the cache + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Data-only chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + + // Create more fake CompactBlocks that don't connect to the scanned ones + let (cb3, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 2, + BlockHash([1; 32]), + extfvk.clone(), + Amount::from_u64(8).unwrap(), + ); + let (cb4, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 3, + cb3.hash(), + extfvk.clone(), + Amount::from_u64(3).unwrap(), + ); + insert_into_cache(db_cache, &cb3); + insert_into_cache(db_cache, &cb4); + + // Data+cache chain should be invalid at the data/cache boundary + match validate_combined_chain(db_cache, db_data) { + Err(e) => match e.kind() { + ErrorKind::InvalidChain(upper_bound, _) => { + assert_eq!(*upper_bound, SAPLING_ACTIVATION_HEIGHT + 1) + } + _ => panic!(), + }, + _ => panic!(), + } + } + + #[test] + fn invalid_chain_cache_reorg() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Create some fake CompactBlocks + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + Amount::from_u64(5).unwrap(), + ); + let (cb2, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 1, + cb.hash(), + extfvk.clone(), + Amount::from_u64(7).unwrap(), + ); + insert_into_cache(db_cache, &cb); + insert_into_cache(db_cache, &cb2); + + // Scan the cache + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Data-only chain should be valid + validate_combined_chain(db_cache, db_data).unwrap(); + + // Create more fake CompactBlocks that contain a reorg + let (cb3, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 2, + cb2.hash(), + extfvk.clone(), + Amount::from_u64(8).unwrap(), + ); + let (cb4, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT + 3, + BlockHash([1; 32]), + extfvk.clone(), + Amount::from_u64(3).unwrap(), + ); + insert_into_cache(db_cache, &cb3); + insert_into_cache(db_cache, &cb4); + + // Data+cache chain should be invalid inside the cache + match validate_combined_chain(db_cache, db_data) { + Err(e) => match e.kind() { + ErrorKind::InvalidChain(upper_bound, _) => { + assert_eq!(*upper_bound, SAPLING_ACTIVATION_HEIGHT + 2) + } + _ => panic!(), + }, + _ => panic!(), + } + } + + #[test] + fn data_db_rewinding() { + let cache_file = NamedTempFile::new().unwrap(); + let db_cache = cache_file.path(); + init_cache_database(&db_cache).unwrap(); + + let data_file = NamedTempFile::new().unwrap(); + let db_data = data_file.path(); + init_data_database(&db_data).unwrap(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + init_accounts_table(&db_data, &[extfvk.clone()]).unwrap(); + + // Account balance should be zero + assert_eq!(get_balance(db_data, 0).unwrap(), Amount::zero()); + + // Create fake CompactBlocks sending value to the address + let value = Amount::from_u64(5).unwrap(); + let value2 = Amount::from_u64(7).unwrap(); + let (cb, _) = fake_compact_block( + SAPLING_ACTIVATION_HEIGHT, + BlockHash([0; 32]), + extfvk.clone(), + value, + ); + let (cb2, _) = fake_compact_block(SAPLING_ACTIVATION_HEIGHT + 1, cb.hash(), extfvk, value2); + insert_into_cache(db_cache, &cb); + insert_into_cache(db_cache, &cb2); + + // Scan the cache + scan_cached_blocks(db_cache, db_data).unwrap(); + + // Account balance should reflect both received notes + assert_eq!(get_balance(db_data, 0).unwrap(), value + value2); + + // "Rewind" to height of last scanned block + rewind_to_height(db_data, SAPLING_ACTIVATION_HEIGHT + 1).unwrap(); + + // Account balance should be unaltered + assert_eq!(get_balance(db_data, 0).unwrap(), value + value2); + + // Rewind so that one block is dropped + rewind_to_height(db_data, SAPLING_ACTIVATION_HEIGHT).unwrap(); + + // Account balance should only contain the first received note + assert_eq!(get_balance(db_data, 0).unwrap(), value); + } +} diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index 52ff230..b0dfb47 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -10,6 +10,7 @@ pub enum ErrorKind { CorruptedData(&'static str), IncorrectHRPExtFVK, InsufficientBalance(u64, u64), + InvalidChain(i32, crate::chain::ChainInvalidCause), InvalidExtSK(u32), InvalidHeight(i32, i32), InvalidMemo(std::str::Utf8Error), @@ -38,6 +39,9 @@ impl fmt::Display for Error { "Insufficient balance (have {}, need {} including fee)", have, need ), + ErrorKind::InvalidChain(upper_bound, cause) => { + write!(f, "Invalid chain (upper bound: {}): {:?}", upper_bound, cause) + } ErrorKind::InvalidExtSK(account) => { write!(f, "Incorrect ExtendedSpendingKey for account {}", account) } diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index b26df3e..5424466 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -39,6 +39,7 @@ use zcash_client_backend::constants::testnet::{ HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS, }; +pub mod chain; pub mod error; pub mod init; pub mod query; From 1c60a79ec199ffeacf8fc810c598dbc3dbed1e31 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 24 May 2019 15:17:36 +0100 Subject: [PATCH 100/105] Implement TransparentAddress encoding and decoding --- Cargo.lock | 10 ++ zcash_client_backend/Cargo.toml | 1 + zcash_client_backend/src/constants/mainnet.rs | 10 ++ zcash_client_backend/src/constants/testnet.rs | 10 ++ zcash_client_backend/src/encoding.rs | 109 ++++++++++++++++++ 5 files changed, 140 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6fd7629..a785792 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,6 +130,14 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bs58" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "byte-tools" version = "0.3.1" @@ -650,6 +658,7 @@ name = "zcash_client_backend" version = "0.0.0" dependencies = [ "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", @@ -733,6 +742,7 @@ dependencies = [ "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" +"checksum bs58 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0d9644ad62ff4df43da2e057febbbce576f7124cb5cd8e90e0ce7027f38aa2dd" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index ed6e502..b522e28 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] bech32 = "0.7" +bs58 = { version = "0.2", features = ["check"] } ff = { path = "../ff" } hex = "0.3" pairing = { path = "../pairing" } diff --git a/zcash_client_backend/src/constants/mainnet.rs b/zcash_client_backend/src/constants/mainnet.rs index ed90697..b004c0c 100644 --- a/zcash_client_backend/src/constants/mainnet.rs +++ b/zcash_client_backend/src/constants/mainnet.rs @@ -26,3 +26,13 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviews"; /// [`PaymentAddress`]: sapling_crypto::primitives::PaymentAddress /// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "zs"; + +/// The prefix for a Base58Check-encoded mainnet [`TransparentAddress::PublicKey`]. +/// +/// [`TransparentAddress::PublicKey`]: zcash_primitives::legacy::TransparentAddress::PublicKey +pub const B58_PUBKEY_ADDRESS_PREFIX: [u8; 2] = [0x1c, 0xb8]; + +/// The prefix for a Base58Check-encoded mainnet [`TransparentAddress::Script`]. +/// +/// [`TransparentAddress::Script`]: zcash_primitives::legacy::TransparentAddress::Script +pub const B58_SCRIPT_ADDRESS_PREFIX: [u8; 2] = [0x1c, 0xbd]; diff --git a/zcash_client_backend/src/constants/testnet.rs b/zcash_client_backend/src/constants/testnet.rs index f151110..012c2d0 100644 --- a/zcash_client_backend/src/constants/testnet.rs +++ b/zcash_client_backend/src/constants/testnet.rs @@ -26,3 +26,13 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewtestsapling"; /// [`PaymentAddress`]: sapling_crypto::primitives::PaymentAddress /// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "ztestsapling"; + +/// The prefix for a Base58Check-encoded testnet [`TransparentAddress::PublicKey`]. +/// +/// [`TransparentAddress::PublicKey`]: zcash_primitives::legacy::TransparentAddress::PublicKey +pub const B58_PUBKEY_ADDRESS_PREFIX: [u8; 2] = [0x1d, 0x25]; + +/// The prefix for a Base58Check-encoded testnet [`TransparentAddress::Script`]. +/// +/// [`TransparentAddress::Script`]: zcash_primitives::legacy::TransparentAddress::Script +pub const B58_SCRIPT_ADDRESS_PREFIX: [u8; 2] = [0x1c, 0xba]; diff --git a/zcash_client_backend/src/encoding.rs b/zcash_client_backend/src/encoding.rs index d39973d..0bd1644 100644 --- a/zcash_client_backend/src/encoding.rs +++ b/zcash_client_backend/src/encoding.rs @@ -4,6 +4,7 @@ //! module. use bech32::{self, Error, FromBase32, ToBase32}; +use bs58::{self, decode::DecodeError}; use pairing::bls12_381::Bls12; use std::io::{self, Write}; use zcash_primitives::{ @@ -11,6 +12,7 @@ use zcash_primitives::{ primitives::{Diversifier, PaymentAddress}, }; use zcash_primitives::{ + legacy::TransparentAddress, zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, JUBJUB, }; @@ -182,6 +184,113 @@ pub fn decode_payment_address(hrp: &str, s: &str) -> Result String { + let decoded = match addr { + TransparentAddress::PublicKey(key_id) => { + let mut decoded = vec![0; pubkey_version.len() + 20]; + decoded[..pubkey_version.len()].copy_from_slice(pubkey_version); + decoded[pubkey_version.len()..].copy_from_slice(key_id); + decoded + } + TransparentAddress::Script(script_id) => { + let mut decoded = vec![0; script_version.len() + 20]; + decoded[..script_version.len()].copy_from_slice(script_version); + decoded[script_version.len()..].copy_from_slice(script_id); + decoded + } + }; + bs58::encode(decoded).with_check().into_string() +} + +/// Decodes a [`TransparentAddress`] from a Base58Check-encoded string. +/// +/// # Examples +/// +/// ``` +/// use zcash_client_backend::{ +/// constants::testnet::{B58_PUBKEY_ADDRESS_PREFIX, B58_SCRIPT_ADDRESS_PREFIX}, +/// encoding::decode_transparent_address, +/// }; +/// use zcash_primitives::legacy::TransparentAddress; +/// +/// assert_eq!( +/// decode_transparent_address( +/// &B58_PUBKEY_ADDRESS_PREFIX, +/// &B58_SCRIPT_ADDRESS_PREFIX, +/// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma", +/// ), +/// Ok(Some(TransparentAddress::PublicKey([0; 20]))), +/// ); +/// +/// assert_eq!( +/// decode_transparent_address( +/// &B58_PUBKEY_ADDRESS_PREFIX, +/// &B58_SCRIPT_ADDRESS_PREFIX, +/// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2", +/// ), +/// Ok(Some(TransparentAddress::Script([0; 20]))), +/// ); +/// ``` +pub fn decode_transparent_address( + pubkey_version: &[u8], + script_version: &[u8], + s: &str, +) -> Result, DecodeError> { + let decoded = bs58::decode(s).with_check(None).into_vec()?; + if &decoded[..pubkey_version.len()] == pubkey_version { + if decoded.len() == pubkey_version.len() + 20 { + let mut data = [0; 20]; + data.copy_from_slice(&decoded[pubkey_version.len()..]); + Ok(Some(TransparentAddress::PublicKey(data))) + } else { + Ok(None) + } + } else if &decoded[..script_version.len()] == script_version { + if decoded.len() == script_version.len() + 20 { + let mut data = [0; 20]; + data.copy_from_slice(&decoded[script_version.len()..]); + Ok(Some(TransparentAddress::Script(data))) + } else { + Ok(None) + } + } else { + Ok(None) + } +} + #[cfg(test)] mod tests { use pairing::bls12_381::Bls12; From 1cbeac9d593d65938870797fb8dbafa352644d34 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 24 May 2019 15:59:18 +0100 Subject: [PATCH 101/105] zcash_client_sqlite: Support sending to t-addrs --- Cargo.lock | 1 + zcash_client_sqlite/Cargo.toml | 1 + zcash_client_sqlite/src/address.rs | 63 +++++++++++++++++++++++++++++ zcash_client_sqlite/src/error.rs | 8 ++++ zcash_client_sqlite/src/lib.rs | 1 + zcash_client_sqlite/src/transact.rs | 30 ++++++++------ 6 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 zcash_client_sqlite/src/address.rs diff --git a/Cargo.lock b/Cargo.lock index a785792..810c246 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,6 +676,7 @@ name = "zcash_client_sqlite" version = "0.0.0" dependencies = [ "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/zcash_client_sqlite/Cargo.toml b/zcash_client_sqlite/Cargo.toml index 697cb12..042a43b 100644 --- a/zcash_client_sqlite/Cargo.toml +++ b/zcash_client_sqlite/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] bech32 = "0.7" +bs58 = { version = "0.2", features = ["check"] } ff = { path = "../ff" } pairing = { path = "../pairing" } protobuf = "2" diff --git a/zcash_client_sqlite/src/address.rs b/zcash_client_sqlite/src/address.rs new file mode 100644 index 0000000..f72512f --- /dev/null +++ b/zcash_client_sqlite/src/address.rs @@ -0,0 +1,63 @@ +//! Structs for handling supported address types. + +use pairing::bls12_381::Bls12; +use zcash_client_backend::encoding::{ + decode_payment_address, decode_transparent_address, encode_payment_address, + encode_transparent_address, +}; +use zcash_primitives::{legacy::TransparentAddress, primitives::PaymentAddress}; + +#[cfg(feature = "mainnet")] +use zcash_client_backend::constants::mainnet::{ + B58_PUBKEY_ADDRESS_PREFIX, B58_SCRIPT_ADDRESS_PREFIX, HRP_SAPLING_PAYMENT_ADDRESS, +}; + +#[cfg(not(feature = "mainnet"))] +use zcash_client_backend::constants::testnet::{ + B58_PUBKEY_ADDRESS_PREFIX, B58_SCRIPT_ADDRESS_PREFIX, HRP_SAPLING_PAYMENT_ADDRESS, +}; + +/// An address that funds can be sent to. +pub enum RecipientAddress { + Shielded(PaymentAddress), + Transparent(TransparentAddress), +} + +impl From> for RecipientAddress { + fn from(addr: PaymentAddress) -> Self { + RecipientAddress::Shielded(addr) + } +} + +impl From for RecipientAddress { + fn from(addr: TransparentAddress) -> Self { + RecipientAddress::Transparent(addr) + } +} + +impl RecipientAddress { + pub fn from_str(s: &str) -> Option { + if let Ok(Some(pa)) = decode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, s) { + Some(pa.into()) + } else if let Ok(Some(addr)) = + decode_transparent_address(&B58_PUBKEY_ADDRESS_PREFIX, &B58_SCRIPT_ADDRESS_PREFIX, s) + { + Some(addr.into()) + } else { + None + } + } + + pub fn to_string(&self) -> String { + match self { + RecipientAddress::Shielded(pa) => { + encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, pa) + } + RecipientAddress::Transparent(addr) => encode_transparent_address( + &B58_PUBKEY_ADDRESS_PREFIX, + &B58_SCRIPT_ADDRESS_PREFIX, + addr, + ), + } + } +} diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index b0dfb47..12b2d98 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -20,6 +20,7 @@ pub enum ErrorKind { ScanRequired, TableNotEmpty, Bech32(bech32::Error), + Base58(bs58::decode::DecodeError), Builder(builder::Error), Database(rusqlite::Error), Io(std::io::Error), @@ -65,6 +66,7 @@ impl fmt::Display for Error { ErrorKind::ScanRequired => write!(f, "Must scan blocks first"), ErrorKind::TableNotEmpty => write!(f, "Table is not empty"), ErrorKind::Bech32(e) => write!(f, "{}", e), + ErrorKind::Base58(e) => write!(f, "{}", e), ErrorKind::Builder(e) => write!(f, "{:?}", e), ErrorKind::Database(e) => write!(f, "{}", e), ErrorKind::Io(e) => write!(f, "{}", e), @@ -93,6 +95,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: bs58::decode::DecodeError) -> Self { + Error(ErrorKind::Base58(e)) + } +} + impl From for Error { fn from(e: builder::Error) -> Self { Error(ErrorKind::Builder(e)) diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 5424466..9e4d947 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -39,6 +39,7 @@ use zcash_client_backend::constants::testnet::{ HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS, }; +pub mod address; pub mod chain; pub mod error; pub mod init; diff --git a/zcash_client_sqlite/src/transact.rs b/zcash_client_sqlite/src/transact.rs index 936cc9f..ad95bc9 100644 --- a/zcash_client_sqlite/src/transact.rs +++ b/zcash_client_sqlite/src/transact.rs @@ -4,12 +4,12 @@ use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; use rusqlite::{types::ToSql, Connection, NO_PARAMS}; use std::path::Path; -use zcash_client_backend::encoding::{encode_extended_full_viewing_key, encode_payment_address}; +use zcash_client_backend::encoding::encode_extended_full_viewing_key; use zcash_primitives::{ jubjub::fs::{Fs, FsRepr}, merkle_tree::IncrementalWitness, note_encryption::Memo, - primitives::{Diversifier, Note, PaymentAddress}, + primitives::{Diversifier, Note}, prover::TxProver, sapling::Node, transaction::{ @@ -21,9 +21,9 @@ use zcash_primitives::{ }; use crate::{ + address::RecipientAddress, error::{Error, ErrorKind}, get_target_and_anchor_heights, HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, - HRP_SAPLING_PAYMENT_ADDRESS, }; struct SelectedNoteRow { @@ -61,7 +61,7 @@ struct SelectedNoteRow { /// /// let account = 0; /// let extsk = spending_key(&[0; 32][..], COIN_TYPE, account); -/// let to = extsk.default_address().unwrap().1; +/// let to = extsk.default_address().unwrap().1.into(); /// match create_to_address( /// "/path/to/data.db", /// SAPLING_CONSENSUS_BRANCH_ID, @@ -80,7 +80,7 @@ pub fn create_to_address>( consensus_branch_id: u32, prover: impl TxProver, (account, extsk): (u32, &ExtendedSpendingKey), - to: &PaymentAddress, + to: &RecipientAddress, value: Amount, memo: Option, ) -> Result { @@ -221,7 +221,12 @@ pub fn create_to_address>( selected.witness, )?; } - builder.add_sapling_output(ovk, to.clone(), value, memo.clone())?; + match to { + RecipientAddress::Shielded(to) => { + builder.add_sapling_output(ovk, to.clone(), value, memo.clone()) + } + RecipientAddress::Transparent(to) => builder.add_transparent_output(&to, value), + }?; let (tx, tx_metadata) = builder.build(consensus_branch_id, prover)?; // We only called add_sapling_output() once. let output_index = match tx_metadata.output_index(0) { @@ -263,7 +268,8 @@ pub fn create_to_address>( } // Save the sent note in the database. - let to_str = encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, to); + // TODO: Decide how to save transparent output information. + let to_str = to.to_string(); if let Some(memo) = memo { let mut stmt_insert_sent_note = data.prepare( "INSERT INTO sent_notes (tx, output_index, from_account, address, value, memo) @@ -340,7 +346,7 @@ mod tests { ExtendedFullViewingKey::from(&extsk1), ]; init_accounts_table(&db_data, &extfvks).unwrap(); - let to = extsk0.default_address().unwrap().1; + let to = extsk0.default_address().unwrap().1.into(); // Invalid extsk for the given account should cause an error match create_to_address( @@ -379,7 +385,7 @@ mod tests { let extsk = ExtendedSpendingKey::master(&[]); let extfvks = [ExtendedFullViewingKey::from(&extsk)]; init_accounts_table(&db_data, &extfvks).unwrap(); - let to = extsk.default_address().unwrap().1; + let to = extsk.default_address().unwrap().1.into(); // We cannot do anything if we aren't synchronised match create_to_address( @@ -407,7 +413,7 @@ mod tests { let extsk = ExtendedSpendingKey::master(&[]); let extfvks = [ExtendedFullViewingKey::from(&extsk)]; init_accounts_table(&db_data, &extfvks).unwrap(); - let to = extsk.default_address().unwrap().1; + let to = extsk.default_address().unwrap().1.into(); // Account balance should be zero assert_eq!(get_balance(db_data, 0).unwrap(), Amount::zero()); @@ -476,7 +482,7 @@ mod tests { // Spend fails because there are insufficient verified notes let extsk2 = ExtendedSpendingKey::master(&[]); - let to = extsk2.default_address().unwrap().1; + let to = extsk2.default_address().unwrap().1.into(); match create_to_address( db_data, 1, @@ -575,7 +581,7 @@ mod tests { // Send some of the funds to another address let extsk2 = ExtendedSpendingKey::master(&[]); - let to = extsk2.default_address().unwrap().1; + let to = extsk2.default_address().unwrap().1.into(); create_to_address( db_data, 1, From be84cd8e0569bb8e3849a942cd0acd03c16ee7ff Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 5 Sep 2019 13:40:26 -0700 Subject: [PATCH 102/105] Fix cargo.lock --- Cargo.lock | 205 ++++++++++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 853bef3..61d0316 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,7 +44,7 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -57,18 +57,18 @@ name = "bellman" version = "0.1.0" dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "group 0.1.0", "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -85,22 +85,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2b_simd" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "blake2s_simd" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -132,7 +132,7 @@ dependencies = [ [[package]] name = "bs58" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -153,17 +153,13 @@ name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -<<<<<<< HEAD -version = "1.0.41" -======= -version = "1.0.40" ->>>>>>> 388a5855159c3c3502691deac19bc51ecbfe68d6 +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -173,7 +169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "constant_time_eq" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -207,8 +203,8 @@ name = "directories" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -232,14 +228,14 @@ version = "0.4.0" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff_derive 0.3.0", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ff_derive" version = "0.3.0" dependencies = [ - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -254,14 +250,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -269,7 +265,7 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -278,16 +274,17 @@ name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -323,12 +320,12 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.61" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -336,15 +333,15 @@ name = "librustzcash" version = "0.1.0" dependencies = [ "bellman 0.1.0", - "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_primitives 0.0.0", "zcash_proofs 0.0.0", ] @@ -354,7 +351,7 @@ name = "libsqlite3-sys" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -384,9 +381,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num-bigint" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -396,7 +394,7 @@ name = "num-integer" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -405,7 +403,7 @@ name = "num-traits" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -413,7 +411,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -428,7 +426,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "group 0.1.0", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -498,10 +496,10 @@ name = "rand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -511,15 +509,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -527,16 +525,16 @@ name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -544,7 +542,7 @@ name = "rand_xorshift" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -557,7 +555,17 @@ name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -574,6 +582,14 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "secp256k1" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha2" version = "0.8.0" @@ -606,11 +622,11 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -618,14 +634,14 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "typenum" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -638,9 +654,14 @@ name = "vcpkg" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -662,14 +683,14 @@ name = "zcash_client_backend" version = "0.0.0" dependencies = [ "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf-codegen-pure 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_primitives 0.0.0", @@ -680,12 +701,12 @@ name = "zcash_client_sqlite" version = "0.0.0" dependencies = [ "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -699,19 +720,19 @@ name = "zcash_primitives" version = "0.0.0" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -723,13 +744,13 @@ name = "zcash_proofs" version = "0.0.0" dependencies = [ "bellman 0.1.0", - "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_primitives 0.0.0", ] @@ -740,26 +761,22 @@ dependencies = [ "checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" "checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2" -"checksum blake2s_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3a84d2614b18a5367d357331a90fd533d5ceb1e86abc319320df2104ab744c2a" +"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" +"checksum blake2s_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "979da0ce13c897d6be19e005ea77ac12b0fea0157aeeee7feb8c49f91386f0ea" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bs58 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0d9644ad62ff4df43da2e057febbbce576f7124cb5cd8e90e0ce7027f38aa2dd" +"checksum bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c95ee6bba9d950218b6cc910cf62bc9e0a171d0f4537e3627b0f54d08549b188" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -<<<<<<< HEAD -"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" -======= -"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" ->>>>>>> 388a5855159c3c3502691deac19bc51ecbfe68d6 +"checksum cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "a61c7bce55cd2fae6ec8cb935ebd76256c2959a1f95790f6118a441c2cd5b406" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crypto_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102" "checksum crypto_api_chachapoly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "95b2ad7cab08fd71addba81df5077c49df208effdfb3118a1519f9cdeac5aaf2" @@ -769,21 +786,21 @@ dependencies = [ "checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" "checksum fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" "checksum fpe 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21988a326139165b75e3196bc6962ca638e5fb0c95102fbf152a3743174b01e4" -"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" +"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc2928beef125e519d69ae1baa8c37ea2e0d3848545217f6db0179c5eb1d639" "checksum hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "520870c3213943eb8d7803e80180d12a6c7ceb4ae74602544529d1643dc4ddda" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)" = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5b95e89c330291768dc840238db7f9e204fd208511ab6319b56193a7f2ae25" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" @@ -799,26 +816,24 @@ dependencies = [ "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_os 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb525a78d3a0b0e05b6fe0f7df14d7a4dc957944c7b403911ba5a0f1c694967" +"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" "checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" -<<<<<<< HEAD "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a194373ef527035645a1bc21b10dc2125f73497e6e155771233eb187aedd051" -======= "checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" +"checksum rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a194373ef527035645a1bc21b10dc2125f73497e6e155771233eb187aedd051" "checksum secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0344a794ff109f85547039536028e12f313178ac1545e49fdf16a530d900a7b" ->>>>>>> 388a5855159c3c3502691deac19bc51ecbfe68d6 "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" From 99d0f786361355d638ecb998180c50c27723070c Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 6 Sep 2019 13:37:42 -0700 Subject: [PATCH 103/105] Make mod serialize public --- zcash_primitives/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 0c55023..1384117 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -41,7 +41,7 @@ pub mod primitives; pub mod prover; pub mod redjubjub; pub mod sapling; -mod serialize; +pub mod serialize; pub mod transaction; mod util; pub mod zip32; From 1056db3bea5cb827a4f650dc919fab6c46c18e59 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 10 Sep 2019 10:00:24 -0700 Subject: [PATCH 104/105] Make OutPoint fields pub --- zcash_primitives/src/transaction/components.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index 0148e8c..6a872ce 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -21,8 +21,8 @@ const ZC_NUM_JS_OUTPUTS: usize = 2; #[derive(Debug)] pub struct OutPoint { - hash: [u8; 32], - n: u32, + pub hash: [u8; 32], + pub n: u32, } impl OutPoint { From 3ee778de594695c1fe6fca06b873e8e6e2ac6cc7 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 10 Sep 2019 10:01:13 -0700 Subject: [PATCH 105/105] transparent inputs should use serialize_der() --- zcash_primitives/src/transaction/builder.rs | 72 +++++++++++---------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 50dee55..b9f77ba 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -479,7 +479,6 @@ impl Builder { // let mut ctx = prover.new_sapling_proving_context(); - let anchor = self.anchor.expect("anchor was set if spends were added"); // Pad Sapling outputs let orig_outputs_len = outputs.len(); @@ -495,41 +494,44 @@ impl Builder { tx_metadata.spend_indices.resize(spends.len(), 0); tx_metadata.output_indices.resize(orig_outputs_len, 0); - // Create Sapling SpendDescriptions - for (i, (pos, spend)) in spends.iter().enumerate() { - let proof_generation_key = spend.extsk.expsk.proof_generation_key(&JUBJUB); + if spends.len() > 0 { + let anchor = self.anchor.expect("anchor was set if spends were added"); + // Create Sapling SpendDescriptions + for (i, (pos, spend)) in spends.iter().enumerate() { + let proof_generation_key = spend.extsk.expsk.proof_generation_key(&JUBJUB); - let mut nullifier = [0u8; 32]; - nullifier.copy_from_slice(&spend.note.nf( - &proof_generation_key.into_viewing_key(&JUBJUB), - spend.witness.position, - &JUBJUB, - )); + let mut nullifier = [0u8; 32]; + nullifier.copy_from_slice(&spend.note.nf( + &proof_generation_key.into_viewing_key(&JUBJUB), + spend.witness.position, + &JUBJUB, + )); - let (zkproof, cv, rk) = prover - .spend_proof( - &mut ctx, - proof_generation_key, - spend.diversifier, - spend.note.r, - spend.alpha, - spend.note.value, - anchor, - spend.witness.clone(), - ) - .map_err(|()| Error::SpendProof)?; + let (zkproof, cv, rk) = prover + .spend_proof( + &mut ctx, + proof_generation_key, + spend.diversifier, + spend.note.r, + spend.alpha, + spend.note.value, + anchor, + spend.witness.clone(), + ) + .map_err(|()| Error::SpendProof)?; - self.mtx.shielded_spends.push(SpendDescription { - cv, - anchor: anchor, - nullifier, - rk, - zkproof, - spend_auth_sig: None, - }); + self.mtx.shielded_spends.push(SpendDescription { + cv, + anchor: anchor, + nullifier, + rk, + zkproof, + spend_auth_sig: None, + }); - // Record the post-randomized spend location - tx_metadata.spend_indices[*pos] = i; + // Record the post-randomized spend location + tx_metadata.spend_indices[*pos] = i; + } } // Create Sapling OutputDescriptions @@ -644,9 +646,13 @@ impl Builder { let msg = secp256k1::Message::from_slice(&sighash).expect("32 bytes"); let sig = self.legacy.secp.sign(&msg, &info.sk); + // Signature has to have "SIGHASH_ALL" appended to it + let mut sig_bytes: Vec = sig.serialize_der()[..].to_vec(); + sig_bytes.extend(&[SIGHASH_ALL as u8]); + // P2PKH scriptSig self.mtx.vin[i].script_sig = - Script::default() << &sig.serialize_compact()[..] << &info.pubkey[..]; + Script::default() << &sig_bytes[..] << &info.pubkey[..]; } }