canonize/decanonize database update
This commit is contained in:
parent
0052703c0a
commit
c1e44e86db
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue