canonize/decanonize database update

This commit is contained in:
NikVolf 2018-12-03 14:29:04 +03:00
parent 0052703c0a
commit c1e44e86db
3 changed files with 43 additions and 5 deletions

View File

@ -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<T> BlockChainDatabase<T> 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<T> BlockChainDatabase<T> where T: KeyValueDatabase {
let mut modified_meta: HashMap<H256, TransactionMeta> = 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<T> TransactionOutputProvider for BlockChainDatabase<T> where T: KeyValueDat
}
impl<T> NullifierTracker for BlockChainDatabase<T> where T: KeyValueDatabase {
fn contains(&self, _nullifier: Nullifier) -> bool {
false
fn contains_nullifier(&self, nullifier: Nullifier) -> bool {
self.get(Key::Nullifier(nullifier)).is_some()
}
}

View File

@ -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<Error> for String {

View File

@ -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 {