From 55e0c661a11585c8afd7d59251d3ad45f194c5e4 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 24 Dec 2018 18:24:12 +0300 Subject: [PATCH 01/11] refactor nullifier tag to epoch tag --- db/src/block_chain_db.rs | 10 +++++----- db/src/kv/memorydb.rs | 14 +++++++------- db/src/kv/transaction.rs | 10 +++++----- storage/src/commitments.rs | 12 ++++++++++++ storage/src/lib.rs | 14 +++++++++++++- storage/src/nullifier.rs | 23 ++++++----------------- verification/src/accept_transaction.rs | 6 +++--- 7 files changed, 51 insertions(+), 38 deletions(-) create mode 100644 storage/src/commitments.rs diff --git a/db/src/block_chain_db.rs b/db/src/block_chain_db.rs index 3098125a..854f4262 100644 --- a/db/src/block_chain_db.rs +++ b/db/src/block_chain_db.rs @@ -25,7 +25,7 @@ use storage::{ BlockRef, Error, BlockHeaderProvider, BlockProvider, BlockOrigin, TransactionMeta, IndexedBlockProvider, TransactionMetaProvider, TransactionProvider, TransactionOutputProvider, BlockChain, Store, SideChainOrigin, ForkChain, Forkable, CanonStore, ConfigStore, BestBlock, NullifierTracker, Nullifier, - NullifierTag, + EpochTag, }; const KEY_BEST_BLOCK_NUMBER: &'static str = "best_block_number"; @@ -293,7 +293,7 @@ impl BlockChainDatabase where T: KeyValueDatabase { for js_descriptor in js.descriptions.iter() { for nullifier in &js_descriptor.nullifiers[..] { let nullifier_key = Nullifier::new( - NullifierTag::Sprout, + EpochTag::Sprout, H256::from(&nullifier[..]) ); if self.contains_nullifier(nullifier_key) { @@ -308,7 +308,7 @@ impl BlockChainDatabase where T: KeyValueDatabase { if let Some(ref sapling) = tx.raw.sapling { for spend in &sapling.spends { let nullifier_key = Nullifier::new( - NullifierTag::Sapling, + EpochTag::Sapling, H256::from(&spend.nullifier[..]) ); if self.contains_nullifier(nullifier_key) { @@ -379,7 +379,7 @@ impl BlockChainDatabase where T: KeyValueDatabase { for js_descriptor in js.descriptions.iter() { for nullifier in &js_descriptor.nullifiers[..] { let nullifier_key = Nullifier::new( - NullifierTag::Sprout, + EpochTag::Sprout, H256::from(&nullifier[..]) ); if !self.contains_nullifier(nullifier_key) { @@ -394,7 +394,7 @@ impl BlockChainDatabase where T: KeyValueDatabase { if let Some(ref sapling) = tx.raw.sapling { for spend in &sapling.spends { let nullifier_key = Nullifier::new( - NullifierTag::Sapling, + EpochTag::Sapling, H256::from(&spend.nullifier[..]) ); if !self.contains_nullifier(nullifier_key) { diff --git a/db/src/kv/memorydb.rs b/db/src/kv/memorydb.rs index 85cfb74f..29d8f19d 100644 --- a/db/src/kv/memorydb.rs +++ b/db/src/kv/memorydb.rs @@ -7,7 +7,7 @@ use bytes::Bytes; use ser::List; use chain::{Transaction as ChainTransaction, BlockHeader}; use kv::{Transaction, Key, KeyState, Operation, Value, KeyValueDatabase, KeyValue}; -use storage::{TransactionMeta, NullifierTag}; +use storage::{TransactionMeta, EpochTag}; #[derive(Default, Debug)] struct InnerDatabase { @@ -84,8 +84,8 @@ impl KeyValueDatabase for MemoryDatabase { KeyValue::BlockNumber(key, value) => { db.block_number.insert(key, KeyState::Insert(value)); }, KeyValue::Configuration(key, value) => { db.configuration.insert(key, KeyState::Insert(value)); }, KeyValue::Nullifier(key) => match key.tag() { - NullifierTag::Sprout => { db.sprout_nullifiers.insert(*key.hash(), KeyState::Insert(())); }, - NullifierTag::Sapling => { db.sapling_nullifiers.insert(*key.hash(), KeyState::Insert(())); }, + EpochTag::Sprout => { db.sprout_nullifiers.insert(*key.hash(), KeyState::Insert(())); }, + EpochTag::Sapling => { db.sapling_nullifiers.insert(*key.hash(), KeyState::Insert(())); }, }, }, Operation::Delete(delete) => match delete { @@ -98,8 +98,8 @@ impl KeyValueDatabase for MemoryDatabase { Key::BlockNumber(key) => { db.block_number.insert(key, KeyState::Delete); } Key::Configuration(key) => { db.configuration.insert(key, KeyState::Delete); } Key::Nullifier(key) => match key.tag() { - NullifierTag::Sprout => { db.sprout_nullifiers.insert(*key.hash(), KeyState::Delete); }, - NullifierTag::Sapling => { db.sapling_nullifiers.insert(*key.hash(), KeyState::Delete); }, + EpochTag::Sprout => { db.sprout_nullifiers.insert(*key.hash(), KeyState::Delete); }, + EpochTag::Sapling => { db.sapling_nullifiers.insert(*key.hash(), KeyState::Delete); }, }, }, } @@ -119,8 +119,8 @@ impl KeyValueDatabase for MemoryDatabase { Key::BlockNumber(ref key) => db.block_number.get(key).cloned().unwrap_or_default().map(Value::BlockNumber), Key::Configuration(ref key) => db.configuration.get(key).cloned().unwrap_or_default().map(Value::Configuration), Key::Nullifier(ref key) => match key.tag() { - NullifierTag::Sprout => db.sprout_nullifiers.get(key.hash()).cloned().unwrap_or_default().map(|_| Value::Empty), - NullifierTag::Sapling => db.sapling_nullifiers.get(key.hash()).cloned().unwrap_or_default().map(|_| Value::Empty), + EpochTag::Sprout => db.sprout_nullifiers.get(key.hash()).cloned().unwrap_or_default().map(|_| Value::Empty), + EpochTag::Sapling => db.sapling_nullifiers.get(key.hash()).cloned().unwrap_or_default().map(|_| Value::Empty), } }; diff --git a/db/src/kv/transaction.rs b/db/src/kv/transaction.rs index 527640fa..1aea1969 100644 --- a/db/src/kv/transaction.rs +++ b/db/src/kv/transaction.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use hash::H256; use ser::{serialize, List, deserialize}; use chain::{Transaction as ChainTransaction, BlockHeader}; -use storage::{TransactionMeta, Nullifier, NullifierTag}; +use storage::{TransactionMeta, Nullifier, EpochTag}; pub const COL_COUNT: u32 = 16; pub const COL_META: u32 = 0; @@ -233,8 +233,8 @@ impl<'a> From<&'a KeyValue> for RawKeyValue { KeyValue::Transaction(ref key, ref value) => (COL_TRANSACTIONS, serialize(key), serialize(value)), KeyValue::TransactionMeta(ref key, ref value) => (COL_TRANSACTIONS_META, serialize(key), serialize(value)), KeyValue::Nullifier(ref key) => match key.tag() { - NullifierTag::Sprout => (COL_SPROUT_NULLIFIERS, serialize(key.hash()), Bytes::new()), - NullifierTag::Sapling => (COL_SAPLING_NULLIFIERS, serialize(key.hash()), Bytes::new()), + EpochTag::Sprout => (COL_SPROUT_NULLIFIERS, serialize(key.hash()), Bytes::new()), + EpochTag::Sapling => (COL_SAPLING_NULLIFIERS, serialize(key.hash()), Bytes::new()), }, KeyValue::BlockNumber(ref key, ref value) => (COL_BLOCK_NUMBERS, serialize(key), serialize(value)), KeyValue::Configuration(ref key, ref value) => (COL_CONFIGURATION, serialize(key), serialize(value)), @@ -272,8 +272,8 @@ impl<'a> From<&'a Key> for RawKey { Key::Transaction(ref key) => (COL_TRANSACTIONS, serialize(key)), Key::TransactionMeta(ref key) => (COL_TRANSACTIONS_META, serialize(key)), Key::Nullifier(ref key) => match key.tag() { - NullifierTag::Sprout => (COL_SPROUT_NULLIFIERS, serialize(key.hash())), - NullifierTag::Sapling => (COL_SAPLING_NULLIFIERS, serialize(key.hash())), + EpochTag::Sprout => (COL_SPROUT_NULLIFIERS, serialize(key.hash())), + EpochTag::Sapling => (COL_SAPLING_NULLIFIERS, serialize(key.hash())), }, Key::BlockNumber(ref key) => (COL_BLOCK_NUMBERS, serialize(key)), Key::Configuration(ref key) => (COL_CONFIGURATION, serialize(key)), diff --git a/storage/src/commitments.rs b/storage/src/commitments.rs new file mode 100644 index 00000000..1faf65a1 --- /dev/null +++ b/storage/src/commitments.rs @@ -0,0 +1,12 @@ +use EpochTag; +use hash::H256; + +/// Trait to query sequence of blockchain commitments; +pub trait CommitmentProvider : Sync { + /// Total amount of stored commitments + fn commitments_count(&self, tag: EpochTag) -> u64; + /// Commitment at given position + fn commitment_at(&self, index: u64, tag: EpochTag) -> H256; + /// Root of all stored commitments + fn commitments_merkle_root(&self, tag: EpochTag) -> H256; +} diff --git a/storage/src/lib.rs b/storage/src/lib.rs index e063ce12..ef2e0e3a 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -36,4 +36,16 @@ pub use error::Error; pub use store::{AsSubstore, Store, SharedStore, CanonStore, ConfigStore}; pub use transaction_meta::TransactionMeta; pub use transaction_provider::{TransactionProvider, TransactionOutputProvider, TransactionMetaProvider}; -pub use nullifier::{Nullifier, NullifierTracker, Tag as NullifierTag}; +pub use nullifier::{Nullifier, NullifierTracker}; + +/// Epoch tag. +/// +/// Sprout and Sapling nullifiers/commitments are considered disjoint, +/// even if they have the same bit pattern. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum EpochTag { + /// Sprout nullifier. + Sprout, + /// Sapling nullifier. + Sapling, +} diff --git a/storage/src/nullifier.rs b/storage/src/nullifier.rs index 586ff84e..7dc0123b 100644 --- a/storage/src/nullifier.rs +++ b/storage/src/nullifier.rs @@ -1,21 +1,10 @@ use hash::H256; - -/// Nullifier epoch (tag). -/// -/// Sprout and Sapling nullifiers are considered disjoint, -/// even if they have the same bit pattern. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Tag { - /// Sprout nullifier. - Sprout, - /// Sapling nullifier. - Sapling, -} +use EpochTag; /// Nullifier. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Nullifier { - tag: Tag, + tag: EpochTag, hash: H256, } @@ -26,7 +15,7 @@ pub trait NullifierTracker : Sync { impl Nullifier { /// New nullifer. - pub fn new(tag: Tag, hash: H256) -> Self { + pub fn new(tag: EpochTag, hash: H256) -> Self { Nullifier { tag: tag, hash: hash, @@ -34,7 +23,7 @@ impl Nullifier { } /// Nullifer tag - pub fn tag(&self) -> Tag { + pub fn tag(&self) -> EpochTag { self.tag } @@ -44,8 +33,8 @@ impl Nullifier { } } -impl From<(Tag, H256)> for Nullifier { - fn from(tuple: (Tag, H256)) -> Self { +impl From<(EpochTag, H256)> for Nullifier { + fn from(tuple: (EpochTag, H256)) -> Self { Nullifier { tag: tuple.0, hash: tuple.1, diff --git a/verification/src/accept_transaction.rs b/verification/src/accept_transaction.rs index 41a7973d..5d619210 100644 --- a/verification/src/accept_transaction.rs +++ b/verification/src/accept_transaction.rs @@ -1,6 +1,6 @@ use ser::Serializable; use crypto::Groth16VerifyingKey; -use storage::{TransactionMetaProvider, TransactionOutputProvider, Nullifier, NullifierTag, NullifierTracker}; +use storage::{TransactionMetaProvider, TransactionOutputProvider, Nullifier, EpochTag, NullifierTracker}; use network::{ConsensusParams}; use script::{Script, verify_script, VerificationFlags, TransactionSignatureChecker, TransactionInputSigner, SighashBase}; use duplex_store::DuplexTransactionOutputProvider; @@ -615,7 +615,7 @@ impl<'a> JoinSplitNullifiers<'a> { if let Some(ref join_split) = self.transaction.raw.join_split { for description in join_split.descriptions.iter() { for nullifier in &description.nullifiers[..] { - let check = Nullifier::new(NullifierTag::Sprout, H256::from(&nullifier[..])); + let check = Nullifier::new(EpochTag::Sprout, H256::from(&nullifier[..])); if self.tracker.contains_nullifier(check) { return Err(TransactionError::JoinSplitDeclared(*check.hash())) @@ -664,7 +664,7 @@ impl<'a> SaplingNullifiers<'a> { fn check(&self) -> Result<(), TransactionError> { if let Some(ref sapling) = self.transaction.raw.sapling { for spend in &sapling.spends { - let check = Nullifier::new(NullifierTag::Sapling, H256::from(&spend.nullifier[..])); + let check = Nullifier::new(EpochTag::Sapling, H256::from(&spend.nullifier[..])); if self.tracker.contains_nullifier(check) { return Err(TransactionError::SaplingDeclared(*check.hash())) From c970b17fe987b73198cefca52066f9e1142c4441 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 27 Dec 2018 17:56:21 +0300 Subject: [PATCH 02/11] commitments tracker initial --- Cargo.lock | 5 ++--- Cargo.toml | 3 +++ storage/src/commitments.rs | 3 ++- storage/src/lib.rs | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 621c656a..c43392b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,7 +126,7 @@ dependencies = [ "bn 0.4.4 (git+https://github.com/paritytech/bn)", "pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36", "rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1 (git+https://github.com/zcash-hackworks/sapling-crypto.git?rev=21084bde2019c04bd34208e63c3560fe2c02fb0e)", "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1152,7 +1152,6 @@ dependencies = [ [[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.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1341,6 +1340,7 @@ name = "storage" version = "0.1.0" dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcrypto 0.1.0", "chain 0.1.0", "display_derive 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1787,7 +1787,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)" = "" "checksum rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)" = "" -"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" diff --git a/Cargo.toml b/Cargo.toml index fc4e8255..a6a04cf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,3 +44,6 @@ name = "pzec" [workspace] members = ["bencher"] + +[patch.crates-io] +rust-crypto = { path = "./../rust-crypto" } \ No newline at end of file diff --git a/storage/src/commitments.rs b/storage/src/commitments.rs index 1faf65a1..724dec1f 100644 --- a/storage/src/commitments.rs +++ b/storage/src/commitments.rs @@ -1,12 +1,13 @@ use EpochTag; use hash::H256; +use crypto::{Sha256, Digest}; /// Trait to query sequence of blockchain commitments; pub trait CommitmentProvider : Sync { /// Total amount of stored commitments fn commitments_count(&self, tag: EpochTag) -> u64; /// Commitment at given position - fn commitment_at(&self, index: u64, tag: EpochTag) -> H256; + fn commitment_at(&self, tag: EpochTag, index: u64) -> H256; /// Root of all stored commitments fn commitments_merkle_root(&self, tag: EpochTag) -> H256; } diff --git a/storage/src/lib.rs b/storage/src/lib.rs index ef2e0e3a..b81702bc 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -8,6 +8,7 @@ extern crate display_derive; extern crate primitives; extern crate serialization as ser; extern crate chain; +extern crate bitcrypto as crypto; mod best_block; mod block_ancestors; @@ -22,6 +23,7 @@ mod store; mod transaction_meta; mod transaction_provider; mod nullifier; +mod commitments; pub use primitives::{hash, bytes}; From 1157929fd00b0c309f628a1fc949a2015136abfe Mon Sep 17 00:00:00 2001 From: NikVolf Date: Fri, 28 Dec 2018 17:17:18 +0300 Subject: [PATCH 03/11] tree state --- Cargo.lock | 2 + storage/Cargo.toml | 2 + storage/src/commitments.rs | 199 +++++++++++++++++++++++++++++++++++-- storage/src/lib.rs | 2 + 4 files changed, 196 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81776125..156a6d72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1342,9 +1342,11 @@ name = "storage" version = "0.1.0" dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcrypto 0.1.0", "chain 0.1.0", "display_derive 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", diff --git a/storage/Cargo.toml b/storage/Cargo.toml index 650df00e..ce16f6c4 100644 --- a/storage/Cargo.toml +++ b/storage/Cargo.toml @@ -12,3 +12,5 @@ primitives = { path = "../primitives" } serialization = { path = "../serialization" } chain = { path = "../chain" } display_derive = "0.0.0" +bitcrypto = { path = "../crypto" } +lazy_static = "*" \ No newline at end of file diff --git a/storage/src/commitments.rs b/storage/src/commitments.rs index 55cfde34..8e28fcb7 100644 --- a/storage/src/commitments.rs +++ b/storage/src/commitments.rs @@ -1,12 +1,193 @@ -use EpochTag; use hash::H256; +use crypto::sha256_compress; -/// Trait to query sequence of blockchain commitments; -pub trait CommitmentProvider : Sync { - /// Total amount of stored commitments - fn commitments_count(&self, tag: EpochTag) -> u64; - /// Commitment at given position - fn commitment_at(&self, tag: EpochTag, index: u64) -> H256; - /// Root of all stored commitments - fn commitments_merkle_root(&self, tag: EpochTag) -> H256; +lazy_static! { + static ref EMPTY_ROOTS: Vec = [ + H256::from("0000000000000000000000000000000000000000000000000000000000000000"), + H256::from("da5698be17b9b46962335799779fbeca8ce5d491c0d26243bafef9ea1837a9d8"), + H256::from("dc766fab492ccf3d1e49d4f374b5235fa56506aac2224d39f943fcd49202974c"), + H256::from("3f0a406181105968fdaee30679e3273c66b72bf9a7f5debbf3b5a0a26e359f92"), + H256::from("26b0052694fc42fdff93e6fb5a71d38c3dd7dc5b6ad710eb048c660233137fab"), + H256::from("0109ecc0722659ff83450b8f7b8846e67b2859f33c30d9b7acd5bf39cae54e31"), + H256::from("3f909b8ce3d7ffd8a5b30908f605a03b0db85169558ddc1da7bbbcc9b09fd325"), + H256::from("40460fa6bc692a06f47521a6725a547c028a6a240d8409f165e63cb54da2d23f"), + H256::from("8c085674249b43da1b9a31a0e820e81e75f342807b03b6b9e64983217bc2b38e"), + H256::from("a083450c1ba2a3a7be76fad9d13bc37be4bf83bd3e59fc375a36ba62dc620298"), + H256::from("1ddddabc2caa2de9eff9e18c8c5a39406d7936e889bc16cfabb144f5c0022682"), + H256::from("c22d8f0b5e4056e5f318ba22091cc07db5694fbeb5e87ef0d7e2c57ca352359e"), + H256::from("89a434ae1febd7687eceea21d07f20a2512449d08ce2eee55871cdb9d46c1233"), + H256::from("7333dbffbd11f09247a2b33a013ec4c4342029d851e22ba485d4461851370c15"), + H256::from("5dad844ab9466b70f745137195ca221b48f346abd145fb5efc23a8b4ba508022"), + H256::from("507e0dae81cbfbe457fd370ef1ca4201c2b6401083ddab440e4a038dc1e358c4"), + H256::from("bdcdb3293188c9807d808267018684cfece07ac35a42c00f2c79b4003825305d"), + H256::from("bab5800972a16c2c22530c66066d0a5867e987bed21a6d5a450b683cf1cfd709"), + H256::from("11aa0b4ad29b13b057a31619d6500d636cd735cdd07d811ea265ec4bcbbbd058"), + H256::from("5145b1b055c2df02b95675e3797b91de1b846d25003c0a803d08900728f2cd6a"), + H256::from("0323f2850bf3444f4b4c5c09a6057ec7169190f45acb9e46984ab3dfcec4f06a"), + H256::from("671546e26b1da1af754531e26d8a6a51073a57ddd72dc472efb43fcb257cffff"), + H256::from("bb23a9bba56de57cb284b0d2b01c642cf79c9a5563f0067a21292412145bd78a"), + H256::from("f30cc836b9f71b4e7ee3c72b1fd253268af9a27e9d7291a23d02821b21ddfd16"), + H256::from("58a2753dade103cecbcda50b5ebfce31e12d41d5841dcc95620f7b3d50a1b9a1"), + H256::from("925e6d474a5d8d3004f29da0dd78d30ae3824ce79dfe4934bb29ec3afaf3d521"), + H256::from("08f279618616bcdd4eadc9c7a9062691a59b43b07e2c1e237f17bd189cd6a8fe"), + H256::from("c92b32db42f42e2bf0a59df9055be5c669d3242df45357659b75ae2c27a76f50"), + H256::from("c0db2a74998c50eb7ba6534f6d410efc27c4bb88acb0222c7906ea28a327b511"), + H256::from("d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259"), + H256::from("b22370106c67a17209f6130bc09f735d83aa2c04fc4fe72ea5d80b216723e7ce"), + H256::from("9f67d5f664664c901940eee3d02dd5b3e4b92e7b42820c42fc5159e91b41172a"), + H256::from("ac58cd1388fec290d398f1944b564449a63c815880566bd1d189f7839e3b0c8c"), + H256::from("5698eae7c8515ed05a70339bdf7c1028e7acca13a4fa97d9538f01ac8d889ae3"), + H256::from("2d4995770a76fb93314ca74b3524ea1db5688ad0a76183ea17204a8f024a9f3b"), + H256::from("5e8992c1b072c16e9e28a85358fb5fb6901a81587766dadb7aa0b973ded2f264"), + H256::from("e95db71e1f7291ba5499461bc715203e29b84bfa4283e3bb7f470a15d0e1584e"), + H256::from("41f078bd1824c8a4b71964f394aa595084d8eb17b97a3630433af70d10e0eff6"), + H256::from("a1913fe6b20132312f8c1f00ddd63cec7a03f5f1d7d83492fa284c0b5d6320b0"), + H256::from("ba9440c4dbfcf55ceb605a5b8990fc11f8ef22870d8d12e130f986491eae84b3"), + H256::from("49db2d5e22b8015cae4810d75e54014c5469862738e161ec96ec20218718828a"), + H256::from("d4851fb8431edfbb8b1e85ada6895967c2dac87df344992a05faf1ecf836eec9"), + H256::from("e4ab9f4470f00cd196d47c75c82e7adaf06fe17e042e3953d93bb5d56d8cd8fb"), + H256::from("7e4320434849ecb357f1afaaba21a54400ef2d11cff83b937d87fdafa49f8199"), + H256::from("020adc98d96cfbbcca15fc3aa03760ed286686c35b5d92c7cb64a999b394a854"), + H256::from("3a26b29fe1acfdd6c6a151bcc3dbcb95a10ebe2f0553f80779569b67b7244e77"), + H256::from("ec2d0986e6a0ddf43897b2d4f23bb034f538ffe00827f310dc4963f3267f0bfb"), + H256::from("d48073f8819f81f0358e3fc35a047cc74082ae1cb7ee22fb609c01649342d0e6"), + H256::from("ad8037601793f172441ecb00dc138d9fc5957125ecc382ec65e36f817dc799fb"), + H256::from("ca500a5441f36f4df673d6b8ed075d36dae2c7e6481428c70a5a76b7a9bebce8"), + H256::from("422b6ddd473231dc4d56fe913444ccd56f7c61f747ba57ca946d5fef72d840a0"), + H256::from("ab41f4ecb7d7089615800e19fcc53b8379ed05ee35c82567095583fd90ff3035"), + H256::from("bbf7618248354ceb1bc1fc9dbc42c426a4e2c1e0d443c5683a9256c62ecdc26f"), + H256::from("e50ae71479fc8ec569192a13072e011afc249f471af09500ea39f75d0af856bf"), + H256::from("e74c0b9220147db2d50a3b58d413775d16c984690be7d90f0bc43d99dba1b689"), + H256::from("29324a0a48d11657a51ba08b004879bfcfc66a1acb7ce36dfe478d2655484b48"), + H256::from("88952e3d0ac06cb16b665201122249659a22325e01c870f49e29da6b1757e082"), + H256::from("cdf879f2435b95af042a3bf7b850f7819246c805285803d67ffbf4f295bed004"), + H256::from("e005e324200b4f428c62bc3331e695c373607cd0faa9790341fa3ba1ed228bc5"), + H256::from("354447727aa9a53dd8345b6b6c693443e56ef4aeba13c410179fc8589e7733d5"), + H256::from("da52dda91f2829c15c0e58d29a95360b86ab30cf0cac8101832a29f38c3185f1"), + H256::from("c7da7814e228e1144411d78b536092fe920bcdfcc36cf19d1259047b267d58b5"), + H256::from("aba1f68b6c2b4db6cc06a7340e12313c4b4a4ea6deb17deb3e1e66cd8eacf32b"), + H256::from("c160ae4f64ab764d864a52ad5e33126c4b5ce105a47deedd75bc70199a5247ef"), + H256::from("eadf23fc99d514dd8ea204d223e98da988831f9b5d1940274ca520b7fb173d8a"), + H256::from("5b8e14facac8a7c7a3bfee8bae71f2f7793d3ad5fe3383f93ab6061f2a11bb02") + ].to_vec(); } + +struct TreeState { + height: u32, + left: Option, + right: Option, + parents: Vec>, +} + +impl TreeState { + + fn new(height: u32) -> Self { + TreeState { + height: height, + left: None, + right: None, + parents: vec![None; height as usize], + } + } + + fn append(&mut self, hash: H256) -> Result<(), &'static str> { + if self.left.is_none() { + self.left = Some(hash); + } else if self.right.is_none() { + self.right = Some(hash); + } else { + let former_left = ::std::mem::replace(&mut self.left, Some(hash)) + .expect("none variant is handled in the branch above; qed"); + let former_right = self.right.take() + .expect("none variant is handled in the branch above; qed"); + + let mut combined = sha256_compress(&*former_left, &*former_right); + for i in 0..self.height { + let parent_slot = self.parents.get_mut(i as usize) + .expect("Vector is at least self.height in size"); + + if parent_slot.is_none() { + *parent_slot = Some(combined); + break; + } else { + let former_parent_slot = parent_slot.take().expect("None variant checked above; qed"); + combined = sha256_compress(&*former_parent_slot, &*combined); + } + } + + return Err("Appending to full tree"); + } + Ok(()) + } + + fn root(&self) -> H256 { + let left = self.left.as_ref().unwrap_or(&EMPTY_ROOTS[0]); + let right = self.right.as_ref().unwrap_or(&EMPTY_ROOTS[0]); + + let mut root = sha256_compress(&**left, &**right); + + for i in 1..self.height { + match &self.parents[i as usize] { + &None => { root = sha256_compress(&*root, &*EMPTY_ROOTS[i as usize]); }, + &Some(ref parent) => { root = sha256_compress(&**parent, &*root); } + } + } + + root + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use EpochTag; + + #[test] + fn single_root() { + let mut tree = TreeState::new(1); + tree.append(EMPTY_ROOTS[0].clone()).unwrap(); + + assert_eq!( + tree.root(), + H256::from("da5698be17b9b46962335799779fbeca8ce5d491c0d26243bafef9ea1837a9d8") + ); + } + + #[test] + fn single_elem_in_double_tree() { + let mut tree = TreeState::new(2); + tree.append(EMPTY_ROOTS[0].clone()).unwrap(); + + assert_eq!( + tree.root(), + H256::from("dc766fab492ccf3d1e49d4f374b5235fa56506aac2224d39f943fcd49202974c") + ); + } + + #[test] + fn commitment_1() { + let mut tree = TreeState::new(4); + tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62")) + .unwrap(); + + assert_eq!( + tree.root(), + H256::from("95bf71d8e803b8601c14b5949d0f92690181154ef9d82eb3e24852266823317a") + ); + } + + #[test] + fn commitment_2() { + let mut tree = TreeState::new(4); + tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62")) + .unwrap(); + tree.append(H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68")) + .unwrap(); + + assert_eq!( + tree.root(), + H256::from("73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1") + ); + } +} \ No newline at end of file diff --git a/storage/src/lib.rs b/storage/src/lib.rs index c2f20f9a..a6d7637e 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -8,6 +8,8 @@ extern crate display_derive; extern crate primitives; extern crate serialization as ser; extern crate chain; +extern crate bitcrypto as crypto; +#[macro_use] extern crate lazy_static; mod best_block; mod block_ancestors; From f51399feaedb006654fe4e4c5d7e5c4c78a633da Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 29 Dec 2018 19:19:06 +0300 Subject: [PATCH 04/11] augment tree state --- serialization/src/impls.rs | 22 +++ serialization/src/stream.rs | 2 +- storage/src/lib.rs | 2 +- storage/src/{commitments.rs => tree_state.rs} | 152 ++++++++++++++++-- 4 files changed, 163 insertions(+), 15 deletions(-) rename storage/src/{commitments.rs => tree_state.rs} (60%) diff --git a/serialization/src/impls.rs b/serialization/src/impls.rs index 07ee169b..1948e9b2 100644 --- a/serialization/src/impls.rs +++ b/serialization/src/impls.rs @@ -247,6 +247,28 @@ impl Deserializable for Compact { } } +impl Serializable for Option { + fn serialize(&self, stream: &mut Stream) { + match *self { + None => { stream.append(&false); }, + Some(ref t) => { stream.append(&true); stream.append(t); }, + } + } +} + +impl Deserializable for Option { + fn deserialize(reader: &mut Reader) -> Result where R: io::Read { + let has_value = reader.read::()?; + Ok( + if has_value { + Some(reader.read::()?) + } else { + None + } + ) + } +} + #[cfg(test)] mod tests { use bytes::Bytes; diff --git a/serialization/src/stream.rs b/serialization/src/stream.rs index 2b0ffee5..8f52da15 100644 --- a/serialization/src/stream.rs +++ b/serialization/src/stream.rs @@ -4,7 +4,7 @@ use std::borrow::Borrow; use compact_integer::CompactInteger; use bytes::Bytes; -pub fn serialize(t: &T) -> Bytes where T: Serializable{ +pub fn serialize(t: &T) -> Bytes where T: Serializable { let mut stream = Stream::new(); stream.append(t); stream.out() diff --git a/storage/src/lib.rs b/storage/src/lib.rs index a6d7637e..e42d690f 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -24,7 +24,7 @@ mod store; mod transaction_meta; mod transaction_provider; mod nullifier; -mod commitments; +mod tree_state; pub use primitives::{hash, bytes}; diff --git a/storage/src/commitments.rs b/storage/src/tree_state.rs similarity index 60% rename from storage/src/commitments.rs rename to storage/src/tree_state.rs index 8e28fcb7..aff7a5dd 100644 --- a/storage/src/commitments.rs +++ b/storage/src/tree_state.rs @@ -72,21 +72,40 @@ lazy_static! { ].to_vec(); } -struct TreeState { - height: u32, +pub trait Dim { + fn height() -> u32; +} + +pub struct H4; + +impl Dim for H4 { + fn height() -> u32 { + 4 + } +} + +pub struct H32; + +impl Dim for H32 { + fn height() -> u32 { + 32 + } +} + +pub struct TreeState { + _phantom: ::std::marker::PhantomData, left: Option, right: Option, parents: Vec>, } -impl TreeState { - - fn new(height: u32) -> Self { +impl TreeState { + fn new() -> Self { TreeState { - height: height, + _phantom: ::std::marker::PhantomData, left: None, right: None, - parents: vec![None; height as usize], + parents: vec![None; D::height() as usize], } } @@ -102,7 +121,7 @@ impl TreeState { .expect("none variant is handled in the branch above; qed"); let mut combined = sha256_compress(&*former_left, &*former_right); - for i in 0..self.height { + for i in 0..D::height() { let parent_slot = self.parents.get_mut(i as usize) .expect("Vector is at least self.height in size"); @@ -126,7 +145,7 @@ impl TreeState { let mut root = sha256_compress(&**left, &**right); - for i in 1..self.height { + for i in 1..D::height() { match &self.parents[i as usize] { &None => { root = sha256_compress(&*root, &*EMPTY_ROOTS[i as usize]); }, &Some(ref parent) => { root = sha256_compress(&**parent, &*root); } @@ -137,15 +156,55 @@ impl TreeState { } } +pub type TestTreeState = TreeState

; +pub type RegularTreeState = TreeState; + +impl serialization::Serializable for TreeState { + fn serialize(&self, stream: &mut serialization::Stream) { + stream.append(&self.left); + stream.append(&self.right); + stream.append_list(&self.parents); + } +} + +impl serialization::Deserializable for TreeState { + fn deserialize(reader: &mut serialization::Reader) + -> Result + { + let mut tree_state = TreeState::::new(); + tree_state.left = reader.read()?; + tree_state.right = reader.read()?; + tree_state.parents = reader.read_list()?; + + Ok(tree_state) + } +} + #[cfg(test)] mod tests { use super::*; use EpochTag; + pub struct H1; + + impl Dim for H1 { + fn height() -> u32 { + 1 + } + } + + pub struct H2; + + impl Dim for H2 { + fn height() -> u32 { + 2 + } + } + #[test] fn single_root() { - let mut tree = TreeState::new(1); + let mut tree = TreeState::

::new(); tree.append(EMPTY_ROOTS[0].clone()).unwrap(); assert_eq!( @@ -156,7 +215,7 @@ mod tests { #[test] fn single_elem_in_double_tree() { - let mut tree = TreeState::new(2); + let mut tree = TreeState::

::new(); tree.append(EMPTY_ROOTS[0].clone()).unwrap(); assert_eq!( @@ -167,7 +226,7 @@ mod tests { #[test] fn commitment_1() { - let mut tree = TreeState::new(4); + let mut tree = TestTreeState::new(); tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62")) .unwrap(); @@ -179,7 +238,7 @@ mod tests { #[test] fn commitment_2() { - let mut tree = TreeState::new(4); + let mut tree = TestTreeState::new(); tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62")) .unwrap(); tree.append(H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68")) @@ -190,4 +249,71 @@ mod tests { H256::from("73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1") ); } + + #[test] + fn glass() { + let mut tree = TestTreeState::new(); + tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62")) + .unwrap(); + tree.append(H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68")) + .unwrap(); + tree.append(H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083")) + .unwrap(); + + assert_eq!( + tree.root(), + H256::from("73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1") + ); + } + + #[test] + fn commitments_full() { + let commitments_list = [ + H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62"), + H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68"), + H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083"), + H256::from_reversed_str("e44a57cd544018937680d385817be3a3e35bb5b87ceeea93d536ea95828a4992"), + H256::from_reversed_str("43f48bfb9ab6f12ef91ce83e8f9190ce5dff2721784c90e08a50a67403367cff"), + H256::from_reversed_str("fce910561c3c7ebf14ed5d712e6838cdc6f1145c87eec256b7181f9df6d0c468"), + H256::from_reversed_str("b1e7016392805b227b11e58ba629f9a6684a0b4c34306e85e47548c43ecd168b"), + H256::from_reversed_str("2d9a49d9425449a449cc62d16febaf9c7f8b32349752ecc39191c36130b4c050"), + H256::from_reversed_str("53969b31a862b893dde857b8b7d4f53ce0e2c21a0f70d48ba1aef3a05fddff70"), + H256::from_reversed_str("17f8fabd440fdf9e2eafd75a3407e8bbde048d2d2232cd803d5763004af61ed8"), + H256::from_reversed_str("9b7805cb5e8ef337c13c73cab58ee719bf33a4a80ecc161bfe714269eca4928b"), + H256::from_reversed_str("a3ebada94d4329899ae136391604799d8cea39c0c331f9aaaa4a1e73ab63e904"), + H256::from_reversed_str("12091a20c9ebe67c2793bb71a6fdddb0ffe3ca781fcf1e192428161f186c3fbe"), + H256::from_reversed_str("e9c65749638df548b8909c0ea1d0f79079a6bb3235c649a8806322c87f968018"), + H256::from_reversed_str("8e8fddf0438a4263bc926fcfa6733dc201633959f294103533a2cb9328bb65c4"), + H256::from_reversed_str("206a202bd08dd31f77afc7114b17850192b83948cff5828df0d638cbe734c884") + ]; + + let root_list = [ + H256::from("95bf71d8e803b8601c14b5949d0f92690181154ef9d82eb3e24852266823317a"), + H256::from("73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1"), + H256::from("dcde8a273c9672bee1a894d7f7f4abb81078f52b498e095f2a87d0aec5addf25"), + H256::from("4677d481ec6d1e97969afbc530958d1cbb4f1c047af6fdad4687cd10830e02bd"), + H256::from("74cd9d82de30c4222a06d420b75522ae1273729c1d8419446adf1184df61dc69"), + H256::from("2ff57f5468c6afdad30ec0fb6c2cb67289f12584e2c20c4e0065f66748697d77"), + H256::from("27e4ce010670801911c5765a003b15f75cde31d7378bd36540f593c8a44b3011"), + H256::from("62231ef2ec8c4da461072871ab7bc9de10253fcb40e164ddbad05b47e0b7fb69"), + H256::from("733a4ce688fdf07efb9e9f5a4b2dafff87cfe198fbe1dff71e028ef4cdee1f1b"), + H256::from("df39ed31924facdd69a93db07311d45fceac7a4987c091648044f37e6ecbb0d2"), + H256::from("87795c069bdb55281c666b9cb872d13174334ce135c12823541e9536489a9107"), + H256::from("438c80f532903b283230446514e400c329b29483db4fe9e279fdfc79e8f4347d"), + H256::from("08afb2813eda17e94aba1ab28ec191d4af99283cd4f1c5a04c0c2bc221bc3119"), + H256::from("a8b3ab3284f3288f7caa21bd2b69789a159ab4188b0908825b34723305c1228c"), + H256::from("db9b289e620de7dca2ae8fdac96808752e32e7a2c6d97ce0755dcebaa03123ab"), + H256::from("0bf622cb9f901b7532433ea2e7c1b7632f5935899b62dcf897a71551997dc8cc"), + ]; + + let mut tree = TestTreeState::new(); + + for i in 0..commitments_list.len() { + tree.append(commitments_list[i].clone()).expect(&format!("Failed to add commitment #{}", i)); + assert_eq!(&tree.root(), &root_list[i]); + } + + // should return error because tree is full + assert!(tree.append(H256::from("0bf622cb9f901b7532433ea2e7c1b7632f5935899b62dcf897a71551997dc8cc")).is_err()); + } } \ No newline at end of file From 19b06b93a73b31624b5bf41aa507719a0283c412 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 29 Dec 2018 21:24:05 +0300 Subject: [PATCH 05/11] fix root calc --- storage/src/tree_state.rs | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/storage/src/tree_state.rs b/storage/src/tree_state.rs index aff7a5dd..4efba8a7 100644 --- a/storage/src/tree_state.rs +++ b/storage/src/tree_state.rs @@ -105,7 +105,7 @@ impl TreeState { _phantom: ::std::marker::PhantomData, left: None, right: None, - parents: vec![None; D::height() as usize], + parents: vec![None; D::height() as usize - 1], } } @@ -121,13 +121,13 @@ impl TreeState { .expect("none variant is handled in the branch above; qed"); let mut combined = sha256_compress(&*former_left, &*former_right); - for i in 0..D::height() { + for i in 0..D::height()-1 { let parent_slot = self.parents.get_mut(i as usize) .expect("Vector is at least self.height in size"); if parent_slot.is_none() { *parent_slot = Some(combined); - break; + return Ok(()); } else { let former_parent_slot = parent_slot.take().expect("None variant checked above; qed"); combined = sha256_compress(&*former_parent_slot, &*combined); @@ -145,10 +145,10 @@ impl TreeState { let mut root = sha256_compress(&**left, &**right); - for i in 1..D::height() { + for i in 0..D::height()-1 { match &self.parents[i as usize] { - &None => { root = sha256_compress(&*root, &*EMPTY_ROOTS[i as usize]); }, &Some(ref parent) => { root = sha256_compress(&**parent, &*root); } + &None => { root = sha256_compress(&*root, &*EMPTY_ROOTS[i as usize + 1]); }, } } @@ -260,9 +260,32 @@ mod tests { tree.append(H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083")) .unwrap(); + // left should be last added hash + assert_eq!(tree.left, Some(H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083"))); + + // right should be none + assert_eq!(tree.right, None); + + // parent#0 should 1st and 2nd combined + assert_eq!( + tree.parents[0], + Some( + sha256_compress( + &*H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62"), + &*H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68") + ) + ) + ); + + // parent#1 should not be set + assert_eq!( + tree.parents[1], + None, + ); + assert_eq!( tree.root(), - H256::from("73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1") + H256::from("dcde8a273c9672bee1a894d7f7f4abb81078f52b498e095f2a87d0aec5addf25") ); } From 6c858f207ce822316c96c0199e3337ae4f2ec886 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 29 Dec 2018 21:32:18 +0300 Subject: [PATCH 06/11] more glass assertions --- storage/src/tree_state.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/storage/src/tree_state.rs b/storage/src/tree_state.rs index 4efba8a7..f3bb3ad0 100644 --- a/storage/src/tree_state.rs +++ b/storage/src/tree_state.rs @@ -287,6 +287,44 @@ mod tests { tree.root(), H256::from("dcde8a273c9672bee1a894d7f7f4abb81078f52b498e095f2a87d0aec5addf25") ); + + tree.append(H256::from_reversed_str("e44a57cd544018937680d385817be3a3e35bb5b87ceeea93d536ea95828a4992")) + .unwrap(); + + // left should be unaffeted + assert_eq!(tree.left, Some(H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083"))); + + // right should be last added hash + assert_eq!(tree.right, Some(H256::from_reversed_str("e44a57cd544018937680d385817be3a3e35bb5b87ceeea93d536ea95828a4992"))); + + // *** FINAL ROUND *** + tree.append(H256::from_reversed_str("43f48bfb9ab6f12ef91ce83e8f9190ce5dff2721784c90e08a50a67403367cff")) + .unwrap(); + + // left should be last added hash + assert_eq!(tree.left, Some(H256::from_reversed_str("43f48bfb9ab6f12ef91ce83e8f9190ce5dff2721784c90e08a50a67403367cff"))); + + // right should be none now + assert_eq!(tree.right, None); + + // parent #0 should be None + assert_eq!(tree.parents[0], None); + + // parent #1 should be combined what? + assert_eq!(tree.parents[1], Some( + sha256_compress( + // this was parent[0] + &*sha256_compress( + &*H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62"), + &*H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68") + ), + // this is left and right + &*sha256_compress( + &*H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083"), + &*H256::from_reversed_str("e44a57cd544018937680d385817be3a3e35bb5b87ceeea93d536ea95828a4992") + ), + ) + )); } #[test] From 557985b92da475f23d5aa58de665b2f973bb6827 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 29 Dec 2018 21:35:21 +0300 Subject: [PATCH 07/11] Fix warnings --- storage/src/lib.rs | 1 + storage/src/tree_state.rs | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/storage/src/lib.rs b/storage/src/lib.rs index e42d690f..7ae2e94a 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -40,6 +40,7 @@ pub use store::{AsSubstore, Store, SharedStore, CanonStore, ConfigStore}; pub use transaction_meta::TransactionMeta; pub use transaction_provider::{TransactionProvider, TransactionOutputProvider, TransactionMetaProvider}; pub use nullifier::{Nullifier, NullifierTracker}; +pub use tree_state::{TreeState, H32 as H32TreeDim, Dim as TreeDim, RegularTreeState}; /// Epoch tag. /// diff --git a/storage/src/tree_state.rs b/storage/src/tree_state.rs index f3bb3ad0..53c72029 100644 --- a/storage/src/tree_state.rs +++ b/storage/src/tree_state.rs @@ -76,14 +76,6 @@ pub trait Dim { fn height() -> u32; } -pub struct H4; - -impl Dim for H4 { - fn height() -> u32 { - 4 - } -} - pub struct H32; impl Dim for H32 { @@ -100,7 +92,7 @@ pub struct TreeState { } impl TreeState { - fn new() -> Self { + pub fn new() -> Self { TreeState { _phantom: ::std::marker::PhantomData, left: None, @@ -109,7 +101,7 @@ impl TreeState { } } - fn append(&mut self, hash: H256) -> Result<(), &'static str> { + pub fn append(&mut self, hash: H256) -> Result<(), &'static str> { if self.left.is_none() { self.left = Some(hash); } else if self.right.is_none() { @@ -139,7 +131,7 @@ impl TreeState { Ok(()) } - fn root(&self) -> H256 { + pub fn root(&self) -> H256 { let left = self.left.as_ref().unwrap_or(&EMPTY_ROOTS[0]); let right = self.right.as_ref().unwrap_or(&EMPTY_ROOTS[0]); @@ -156,7 +148,6 @@ impl TreeState { } } -pub type TestTreeState = TreeState

; pub type RegularTreeState = TreeState; impl serialization::Serializable for TreeState { @@ -184,7 +175,16 @@ impl serialization::Deserializable for TreeState { mod tests { use super::*; - use EpochTag; + + pub struct H4; + + impl Dim for H4 { + fn height() -> u32 { + 4 + } + } + + type TestTreeState = TreeState

; pub struct H1; From a2bfdfbbed50c76c78e19bf98ceda5c32b1971aa Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 29 Dec 2018 21:44:33 +0300 Subject: [PATCH 08/11] remove patch --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a6a04cf6..fc4e8255 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,3 @@ name = "pzec" [workspace] members = ["bencher"] - -[patch.crates-io] -rust-crypto = { path = "./../rust-crypto" } \ No newline at end of file From 0ef99a62a40c2b0b11b0848a558c65419795a9e1 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 29 Dec 2018 23:32:36 +0300 Subject: [PATCH 09/11] refactor to const --- Cargo.lock | 4 ---- storage/src/tree_state.rs | 24 ++++++++---------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 156a6d72..ca70a4d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1680,10 +1680,6 @@ name = "yaml-rust" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[patch.unused]] -name = "rust-crypto" -version = "0.2.36" - [metadata] "checksum abstract-ns 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2f451afbdf8ed8c8f8a98433055bb9a6b7a72aef4baff16227d2a43dd547f43b" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" diff --git a/storage/src/tree_state.rs b/storage/src/tree_state.rs index 53c72029..7051a8a7 100644 --- a/storage/src/tree_state.rs +++ b/storage/src/tree_state.rs @@ -73,15 +73,13 @@ lazy_static! { } pub trait Dim { - fn height() -> u32; + const HEIGHT: usize; } pub struct H32; impl Dim for H32 { - fn height() -> u32 { - 32 - } + const HEIGHT: usize = 32; } pub struct TreeState { @@ -97,7 +95,7 @@ impl TreeState { _phantom: ::std::marker::PhantomData, left: None, right: None, - parents: vec![None; D::height() as usize - 1], + parents: vec![None; D::HEIGHT - 1], } } @@ -113,7 +111,7 @@ impl TreeState { .expect("none variant is handled in the branch above; qed"); let mut combined = sha256_compress(&*former_left, &*former_right); - for i in 0..D::height()-1 { + for i in 0..D::HEIGHT-1 { let parent_slot = self.parents.get_mut(i as usize) .expect("Vector is at least self.height in size"); @@ -137,7 +135,7 @@ impl TreeState { let mut root = sha256_compress(&**left, &**right); - for i in 0..D::height()-1 { + for i in 0..D::HEIGHT-1 { match &self.parents[i as usize] { &Some(ref parent) => { root = sha256_compress(&**parent, &*root); } &None => { root = sha256_compress(&*root, &*EMPTY_ROOTS[i as usize + 1]); }, @@ -179,9 +177,7 @@ mod tests { pub struct H4; impl Dim for H4 { - fn height() -> u32 { - 4 - } + const HEIGHT: usize = 4; } type TestTreeState = TreeState

; @@ -189,17 +185,13 @@ mod tests { pub struct H1; impl Dim for H1 { - fn height() -> u32 { - 1 - } + const HEIGHT: usize = 1; } pub struct H2; impl Dim for H2 { - fn height() -> u32 { - 2 - } + const HEIGHT: usize = 2; } #[test] From d8b8d6710c24a0020290eebc5b70732ccacca9f3 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sun, 30 Dec 2018 01:08:30 +0300 Subject: [PATCH 10/11] simplify logic a bit --- storage/src/tree_state.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/storage/src/tree_state.rs b/storage/src/tree_state.rs index 7051a8a7..f720af68 100644 --- a/storage/src/tree_state.rs +++ b/storage/src/tree_state.rs @@ -112,15 +112,16 @@ impl TreeState { let mut combined = sha256_compress(&*former_left, &*former_right); for i in 0..D::HEIGHT-1 { - let parent_slot = self.parents.get_mut(i as usize) - .expect("Vector is at least self.height in size"); + let parent_slot = &mut self.parents[i as usize]; - if parent_slot.is_none() { - *parent_slot = Some(combined); - return Ok(()); - } else { - let former_parent_slot = parent_slot.take().expect("None variant checked above; qed"); - combined = sha256_compress(&*former_parent_slot, &*combined); + match parent_slot.take() { + None => { + *parent_slot = Some(combined); + return Ok(()); + }, + Some(former) => { + combined = sha256_compress(&*former, &*combined) + }, } } From 201994dd8485b935f30def1c6f36e0d8e2236ef5 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sun, 30 Dec 2018 19:43:37 +0300 Subject: [PATCH 11/11] serialization/deserialization test --- storage/src/tree_state.rs | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/storage/src/tree_state.rs b/storage/src/tree_state.rs index f720af68..a6ea1673 100644 --- a/storage/src/tree_state.rs +++ b/storage/src/tree_state.rs @@ -320,9 +320,8 @@ mod tests { )); } - #[test] - fn commitments_full() { - let commitments_list = [ + lazy_static! { + static ref TEST_COMMITMENTS: Vec = [ H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62"), H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68"), H256::from_reversed_str("fb92a6142315bb3396b693222bf2d0e260b448cda74e189063cf774048456083"), @@ -339,7 +338,11 @@ mod tests { H256::from_reversed_str("e9c65749638df548b8909c0ea1d0f79079a6bb3235c649a8806322c87f968018"), H256::from_reversed_str("8e8fddf0438a4263bc926fcfa6733dc201633959f294103533a2cb9328bb65c4"), H256::from_reversed_str("206a202bd08dd31f77afc7114b17850192b83948cff5828df0d638cbe734c884") - ]; + ].to_vec(); + } + + #[test] + fn commitments_full() { let root_list = [ H256::from("95bf71d8e803b8601c14b5949d0f92690181154ef9d82eb3e24852266823317a"), @@ -362,12 +365,32 @@ mod tests { let mut tree = TestTreeState::new(); - for i in 0..commitments_list.len() { - tree.append(commitments_list[i].clone()).expect(&format!("Failed to add commitment #{}", i)); + for i in 0..TEST_COMMITMENTS.len() { + tree.append(TEST_COMMITMENTS[i].clone()).expect(&format!("Failed to add commitment #{}", i)); assert_eq!(&tree.root(), &root_list[i]); } // should return error because tree is full assert!(tree.append(H256::from("0bf622cb9f901b7532433ea2e7c1b7632f5935899b62dcf897a71551997dc8cc")).is_err()); } + + #[test] + fn serde() { + let mut tree = TestTreeState::new(); + for i in 0..TEST_COMMITMENTS.len() { + tree.append(TEST_COMMITMENTS[i].clone()).expect(&format!("Failed to add commitment #{}", i)); + } + + assert_eq!(tree.root(), H256::from("0bf622cb9f901b7532433ea2e7c1b7632f5935899b62dcf897a71551997dc8cc")); + + let mut stream = serialization::Stream::new(); + stream.append(&tree); + + let bytes = stream.out(); + + let mut reader = serialization::Reader::new(&bytes[..]); + let deserialized_tree: TestTreeState = reader.read().expect("Failed to deserialize"); + + assert_eq!(deserialized_tree.root(), H256::from("0bf622cb9f901b7532433ea2e7c1b7632f5935899b62dcf897a71551997dc8cc")); + } } \ No newline at end of file