From c1e44e86db929daf9f961597a6c5012a7fad5a8d Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 3 Dec 2018 14:29:04 +0300 Subject: [PATCH] canonize/decanonize database update --- db/src/block_chain_db.rs | 43 ++++++++++++++++++++++++++++++++++++---- storage/src/error.rs | 3 +++ storage/src/nullifier.rs | 2 +- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/db/src/block_chain_db.rs b/db/src/block_chain_db.rs index 00b41953..be883aab 100644 --- a/db/src/block_chain_db.rs +++ b/db/src/block_chain_db.rs @@ -7,14 +7,15 @@ use bytes::Bytes; use primitives::compact::Compact; use chain::{ IndexedBlock, IndexedBlockHeader, IndexedTransaction, BlockHeader, Block, Transaction, - OutPoint, TransactionOutput + OutPoint, TransactionOutput, SAPLING_TX_VERSION_GROUP_ID, }; use ser::{ deserialize, serialize, List }; use kv::{ KeyValueDatabase, OverlayDatabase, Transaction as DBTransaction, Value, DiskDatabase, - DatabaseConfig, MemoryDatabase, AutoFlushingOverlayDatabase, KeyValue, Key, KeyState, CacheDatabase + DatabaseConfig, MemoryDatabase, AutoFlushingOverlayDatabase, KeyValue, Key, KeyState, + CacheDatabase, }; use kv::{ COL_COUNT, COL_BLOCK_HASHES, COL_BLOCK_HEADERS, COL_BLOCK_TRANSACTIONS, COL_TRANSACTIONS, @@ -24,6 +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, }; const KEY_BEST_BLOCK_NUMBER: &'static str = "best_block_number"; @@ -285,8 +287,25 @@ impl BlockChainDatabase where T: KeyValueDatabase { } for tx in block.transactions.iter().skip(1) { + let is_sapling_group = tx.raw.version_group_id == SAPLING_TX_VERSION_GROUP_ID; + modified_meta.insert(tx.hash.clone(), TransactionMeta::new(new_best_block.number, tx.raw.outputs.len())); + if let Some(ref js) = tx.raw.join_split { + for js_descriptor in js.descriptions.iter() { + for nullifier in &js_descriptor.nullifiers[..] { + let nullifier_key = Nullifier::new( + if is_sapling_group { NullifierTag::Sapling } else { NullifierTag::Sprout }, + H256::from(&nullifier[..]) + ); + if self.contains_nullifier(nullifier_key) { + return Err(Error::CannotCanonize); + } + update.insert(KeyValue::Nullifier(nullifier_key)); + } + } + } + for input in &tx.raw.inputs { use std::collections::hash_map::Entry; @@ -343,6 +362,22 @@ impl BlockChainDatabase where T: KeyValueDatabase { let mut modified_meta: HashMap = HashMap::new(); for tx in block.transactions.iter().skip(1) { + let is_sapling_group = tx.raw.version_group_id == SAPLING_TX_VERSION_GROUP_ID; + if let Some(ref js) = tx.raw.join_split { + for js_descriptor in js.descriptions.iter() { + for nullifier in &js_descriptor.nullifiers[..] { + let nullifier_key = Nullifier::new( + if is_sapling_group { NullifierTag::Sapling } else { NullifierTag::Sprout }, + H256::from(&nullifier[..]) + ); + if !self.contains_nullifier(nullifier_key) { + return Err(Error::CannotDecanonize); + } + update.delete(Key::Nullifier(nullifier_key)); + } + } + } + for input in &tx.raw.inputs { use std::collections::hash_map::Entry; @@ -510,8 +545,8 @@ impl TransactionOutputProvider for BlockChainDatabase where T: KeyValueDat } impl NullifierTracker for BlockChainDatabase where T: KeyValueDatabase { - fn contains(&self, _nullifier: Nullifier) -> bool { - false + fn contains_nullifier(&self, nullifier: Nullifier) -> bool { + self.get(Key::Nullifier(nullifier)).is_some() } } diff --git a/storage/src/error.rs b/storage/src/error.rs index 0e11a137..43585d89 100644 --- a/storage/src/error.rs +++ b/storage/src/error.rs @@ -12,6 +12,9 @@ pub enum Error { /// Ancient fork #[display(fmt = "Fork is too long to proceed")] AncientFork, + /// Invalid block + #[display(fmt = "Cannot decanonize block (invalid database state)")] + CannotDecanonize, } impl From for String { diff --git a/storage/src/nullifier.rs b/storage/src/nullifier.rs index d8909575..f484c54f 100644 --- a/storage/src/nullifier.rs +++ b/storage/src/nullifier.rs @@ -21,7 +21,7 @@ pub struct Nullifier { /// Trait to query existing nullifier. pub trait NullifierTracker { - fn contains(&self, nullifier: Nullifier) -> bool; + fn contains_nullifier(&self, nullifier: Nullifier) -> bool; } impl Nullifier {