From 1f4c61ad6b362426e05dc05f85680e1fcf1fc9cb Mon Sep 17 00:00:00 2001 From: EmmanuelChthonic Date: Tue, 21 Nov 2023 14:23:17 +0400 Subject: [PATCH 1/4] implement the db macro for blockchain.rs and provided.rs in coordinator/tributary --- Cargo.lock | 2 + coordinator/tributary/Cargo.toml | 2 + coordinator/tributary/src/blockchain.rs | 126 ++++++------------ coordinator/tributary/src/lib.rs | 6 +- coordinator/tributary/src/provided.rs | 106 +++++---------- coordinator/tributary/src/tests/blockchain.rs | 4 +- 6 files changed, 88 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 228b378f4..bb7c5e062 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9671,6 +9671,7 @@ name = "tributary-chain" version = "0.1.0" dependencies = [ "async-trait", + "bincode", "blake2", "ciphersuite", "flexible-transcript", @@ -9682,6 +9683,7 @@ dependencies = [ "rand_chacha", "schnorr-signatures", "serai-db", + "serde", "subtle", "tendermint-machine", "thiserror", diff --git a/coordinator/tributary/Cargo.toml b/coordinator/tributary/Cargo.toml index ff6dc1e31..afeb0c21a 100644 --- a/coordinator/tributary/Cargo.toml +++ b/coordinator/tributary/Cargo.toml @@ -29,6 +29,8 @@ log = { version = "0.4", default-features = false, features = ["std"] } serai-db = { path = "../../common/db" } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std", "derive"] } +serde = { version = "1", default-features = false, features = ["derive"] } +bincode = { version = "1", default-features = false } futures = { version = "0.3", default-features = false, features = ["std"] } tendermint = { package = "tendermint-machine", path = "./tendermint" } diff --git a/coordinator/tributary/src/blockchain.rs b/coordinator/tributary/src/blockchain.rs index 3be658e01..351ccafcf 100644 --- a/coordinator/tributary/src/blockchain.rs +++ b/coordinator/tributary/src/blockchain.rs @@ -2,14 +2,14 @@ use std::collections::{VecDeque, HashMap}; use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto}; -use serai_db::{DbTxn, Db}; +use serai_db::{DbTxn, Db, Get, create_db}; -use scale::Decode; +use scale::{Encode, Decode}; use tendermint::ext::{Network, Commit}; use crate::{ - ReadWrite, ProvidedError, ProvidedTransactions, BlockError, Block, Mempool, Transaction, + ReadWrite, ProvidedError, ProvidedTransactions, BlockQuantityDb, LocalQuantityDb, BlockError, Block, Mempool, Transaction, transaction::{Signed, TransactionKind, TransactionError, Transaction as TransactionTrait}, }; @@ -28,39 +28,21 @@ pub(crate) struct Blockchain { pub(crate) next_block_notifications: VecDeque>, } -impl Blockchain { - fn tip_key(genesis: [u8; 32]) -> Vec { - D::key(b"tributary_blockchain", b"tip", genesis) - } - fn block_number_key(&self) -> Vec { - D::key(b"tributary_blockchain", b"block_number", self.genesis) - } - fn block_key(genesis: &[u8], hash: &[u8; 32]) -> Vec { - D::key(b"tributary_blockchain", b"block", [genesis, hash].concat()) - } - fn block_hash_key(genesis: &[u8], block_number: u32) -> Vec { - D::key(b"tributary_blockchain", b"block_hash", [genesis, &block_number.to_le_bytes()].concat()) - } - fn commit_key(genesis: &[u8], hash: &[u8; 32]) -> Vec { - D::key(b"tributary_blockchain", b"commit", [genesis, hash].concat()) - } - fn block_after_key(genesis: &[u8], hash: &[u8; 32]) -> Vec { - D::key(b"tributary_blockchain", b"block_after", [genesis, hash].concat()) - } - fn unsigned_included_key(genesis: &[u8], hash: &[u8; 32]) -> Vec { - D::key(b"tributary_blockchain", b"unsigned_included", [genesis, hash].concat()) - } - fn provided_included_key(genesis: &[u8], hash: &[u8; 32]) -> Vec { - D::key(b"tributary_blockchain", b"provided_included", [genesis, hash].concat()) - } - fn next_nonce_key(&self, signer: &::G) -> Vec { - D::key( - b"tributary_blockchain", - b"next_nonce", - [self.genesis.as_ref(), signer.to_bytes().as_ref()].concat(), - ) +create_db!( + TributaryBlockchainDb { + TipsDb: (genesis: [u8; 32]) -> [u8; 32], + BlockNumberDb: (genesis: [u8; 32]) -> Vec, + BlockDb: (genesis: [u8; 32], hash: &[u8; 32]) -> Vec, + BlockHashDb: (genesis: [u8; 32], block_number: u32) -> [u8; 32], + CommitDb: (genesis: [u8; 32], block: &[u8; 32]) -> Vec, + BlockAfterDb: (genesis: [u8; 32], hash: [u8; 32]) -> [u8; 32], + UnsignedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec, + ProvidedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec, + NextNonceDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec } +); +impl Blockchain { pub(crate) fn new( db: D, genesis: [u8; 32], @@ -84,17 +66,16 @@ impl Blockchain { next_block_notifications: VecDeque::new(), }; - + let self_db = res.db.as_ref().unwrap(); if let Some((block_number, tip)) = { - let db = res.db.as_ref().unwrap(); - db.get(res.block_number_key()).map(|number| (number, db.get(Self::tip_key(genesis)).unwrap())) + BlockNumberDb::get(self_db, genesis).map(|number| (number, TipsDb::get(self_db, genesis).unwrap())) } { res.block_number = u32::from_le_bytes(block_number.try_into().unwrap()); res.tip.copy_from_slice(&tip); } for participant in participants { - if let Some(next_nonce) = res.db.as_ref().unwrap().get(res.next_nonce_key(participant)) { + if let Some(next_nonce) = NextNonceDb::get(self_db, genesis, participant.to_bytes()) { res.next_nonces.insert(*participant, u32::from_le_bytes(next_nonce.try_into().unwrap())); } } @@ -111,32 +92,16 @@ impl Blockchain { } pub(crate) fn block_from_db(db: &D, genesis: [u8; 32], block: &[u8; 32]) -> Option> { - db.get(Self::block_key(&genesis, block)) + BlockDb::get(db, genesis, block) .map(|bytes| Block::::read::<&[u8]>(&mut bytes.as_ref()).unwrap()) } - pub(crate) fn commit_from_db(db: &D, genesis: [u8; 32], block: &[u8; 32]) -> Option> { - db.get(Self::commit_key(&genesis, block)) - } - - pub(crate) fn block_hash_from_db(db: &D, genesis: [u8; 32], block: u32) -> Option<[u8; 32]> { - db.get(Self::block_hash_key(&genesis, block)).map(|h| h.try_into().unwrap()) - } - pub(crate) fn commit(&self, block: &[u8; 32]) -> Option> { - Self::commit_from_db(self.db.as_ref().unwrap(), self.genesis, block) - } - - pub(crate) fn block_hash(&self, block: u32) -> Option<[u8; 32]> { - Self::block_hash_from_db(self.db.as_ref().unwrap(), self.genesis, block) + CommitDb::get(self.db.as_ref().unwrap(), self.genesis, block) } pub(crate) fn commit_by_block_number(&self, block: u32) -> Option> { - self.commit(&self.block_hash(block)?) - } - - pub(crate) fn block_after(db: &D, genesis: [u8; 32], block: &[u8; 32]) -> Option<[u8; 32]> { - db.get(Self::block_after_key(&genesis, block)).map(|bytes| bytes.try_into().unwrap()) + CommitDb::get(self.db.as_ref().unwrap(), self.genesis, &BlockHashDb::get(self.db.as_ref().unwrap(), self.genesis, block).unwrap()) } pub(crate) fn locally_provided_txs_in_block( @@ -145,19 +110,14 @@ impl Blockchain { block: &[u8; 32], order: &str, ) -> bool { - let local_key = ProvidedTransactions::::locally_provided_quantity_key(genesis, order); - let local = - db.get(local_key).map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())).unwrap_or(0); - let block_key = - ProvidedTransactions::::block_provided_quantity_key(genesis, block, order); - let block = - db.get(block_key).map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())).unwrap_or(0); - + let order_bytes = order.as_bytes(); + let local = LocalQuantityDb::get(db, genesis, order_bytes).unwrap_or_default(); + let block = BlockQuantityDb::get(db, genesis, block, order_bytes).unwrap_or_default(); local >= block } pub(crate) fn tip_from_db(db: &D, genesis: [u8; 32]) -> [u8; 32] { - db.get(Self::tip_key(genesis)).map(|bytes| bytes.try_into().unwrap()).unwrap_or(genesis) + TipsDb::get(db, genesis).unwrap_or(genesis) } pub(crate) fn add_transaction( @@ -170,15 +130,15 @@ impl Blockchain { let genesis = self.genesis; let commit = |block: u32| -> Option> { - let hash = Self::block_hash_from_db(db, genesis, block)?; + let hash = BlockHashDb::get(db, genesis, block)?; // we must have a commit per valid hash - let commit = Self::commit_from_db(db, genesis, &hash).unwrap(); + let commit = CommitDb::get(db, genesis, &hash).unwrap(); // commit has to be valid if it is coming from our db Some(Commit::::decode(&mut commit.as_ref()).unwrap()) }; let unsigned_in_chain = - |hash: [u8; 32]| db.get(Self::unsigned_included_key(&self.genesis, &hash)).is_some(); + |hash: [u8; 32]| UnsignedIncludedDb::get(db, self.genesis, hash).is_some(); self.mempool.add::(&self.next_nonces, internal, tx, schema, unsigned_in_chain, commit) } @@ -194,7 +154,7 @@ impl Blockchain { pub(crate) fn build_block(&mut self, schema: N::SignatureScheme) -> Block { let db = self.db.as_ref().unwrap(); let unsigned_in_chain = - |hash: [u8; 32]| db.get(Self::unsigned_included_key(&self.genesis, &hash)).is_some(); + |hash: [u8; 32]| UnsignedIncludedDb::get(db, self.genesis, hash).is_some(); let block = Block::new( self.tip, @@ -214,9 +174,9 @@ impl Blockchain { ) -> Result<(), BlockError> { let db = self.db.as_ref().unwrap(); let unsigned_in_chain = - |hash: [u8; 32]| db.get(Self::unsigned_included_key(&self.genesis, &hash)).is_some(); + |hash: [u8; 32]| UnsignedIncludedDb::get(db, self.genesis, hash).is_some(); let provided_in_chain = - |hash: [u8; 32]| db.get(Self::provided_included_key(&self.genesis, &hash)).is_some(); + |hash: [u8; 32]| ProvidedIncludedDb::get(db, self.genesis, hash).is_some(); let commit = |block: u32| -> Option> { let commit = self.commit_by_block_number(block)?; // commit has to be valid if it is coming from our db @@ -259,29 +219,30 @@ impl Blockchain { let mut txn = db.txn(); self.tip = block.hash(); - txn.put(Self::tip_key(self.genesis), self.tip); + TipsDb::set(&mut txn, self.genesis, &self.tip); self.block_number += 1; - txn.put(self.block_number_key(), self.block_number.to_le_bytes()); + BlockNumberDb::set(&mut txn, self.genesis, &self.block_number.to_le_bytes()); - txn.put(Self::block_hash_key(&self.genesis, self.block_number), self.tip); + BlockHashDb::set(&mut txn, self.genesis, self.block_number, &self.tip); - txn.put(Self::block_key(&self.genesis, &self.tip), block.serialize()); - txn.put(Self::commit_key(&self.genesis, &self.tip), commit); + BlockDb::set(&mut txn, self.genesis, &self.tip, &block.serialize()); - txn.put(Self::block_after_key(&self.genesis, &block.parent()), block.hash()); + CommitDb::set(&mut txn, self.genesis, &self.tip, &commit); + + BlockAfterDb::set(&mut txn, self.genesis, block.parent(), &block.hash()); for tx in &block.transactions { match tx.kind() { TransactionKind::Provided(order) => { let hash = tx.hash(); self.provided.complete(&mut txn, order, self.tip, hash); - txn.put(Self::provided_included_key(&self.genesis, &hash), []); + ProvidedIncludedDb::set(&mut txn, self.genesis, hash, &[] as &[u8; 0]); } TransactionKind::Unsigned => { let hash = tx.hash(); // Save as included on chain - txn.put(Self::unsigned_included_key(&self.genesis, &hash), []); + UnsignedIncludedDb::set(&mut txn, self.genesis, hash, &[] as &[u8; 0]); // remove from the mempool self.mempool.remove(&hash); } @@ -294,8 +255,7 @@ impl Blockchain { if prev != *nonce { panic!("verified block had an invalid nonce"); } - - txn.put(self.next_nonce_key(signer), next_nonce.to_le_bytes()); + NextNonceDb::set(&mut txn, self.genesis, signer.to_bytes(), &next_nonce.to_le_bytes()); self.mempool.remove(&tx.hash()); } @@ -311,4 +271,4 @@ impl Blockchain { Ok(()) } -} +} \ No newline at end of file diff --git a/coordinator/tributary/src/lib.rs b/coordinator/tributary/src/lib.rs index 752178c31..dc402ab49 100644 --- a/coordinator/tributary/src/lib.rs +++ b/coordinator/tributary/src/lib.rs @@ -397,13 +397,13 @@ impl TributaryReader { Blockchain::::block_from_db(&self.0, self.1, hash) } pub fn commit(&self, hash: &[u8; 32]) -> Option> { - Blockchain::::commit_from_db(&self.0, self.1, hash) + CommitDb::get(&self.0, self.1, &hash) } pub fn parsed_commit(&self, hash: &[u8; 32]) -> Option> { self.commit(hash).map(|commit| Commit::::decode(&mut commit.as_ref()).unwrap()) } pub fn block_after(&self, hash: &[u8; 32]) -> Option<[u8; 32]> { - Blockchain::::block_after(&self.0, self.1, hash) + BlockAfterDb::get(&self.0, self.1, *hash) } pub fn time_of_block(&self, hash: &[u8; 32]) -> Option { self @@ -419,4 +419,4 @@ impl TributaryReader { pub fn tip(&self) -> [u8; 32] { Blockchain::::tip_from_db(&self.0, self.1) } -} +} \ No newline at end of file diff --git a/coordinator/tributary/src/provided.rs b/coordinator/tributary/src/provided.rs index e4e8193c3..72e109ff1 100644 --- a/coordinator/tributary/src/provided.rs +++ b/coordinator/tributary/src/provided.rs @@ -2,8 +2,8 @@ use std::collections::{VecDeque, HashMap}; use thiserror::Error; -use serai_db::{Get, DbTxn, Db}; - +use serai_db::{Get, DbTxn, Db, create_db}; +use scale::Encode; use crate::transaction::{TransactionKind, TransactionError, Transaction, verify_transaction}; #[derive(Clone, PartialEq, Eq, Debug, Error)] @@ -30,43 +30,26 @@ pub struct ProvidedTransactions { pub(crate) transactions: HashMap<&'static str, VecDeque>, } -impl ProvidedTransactions { - fn transaction_key(&self, hash: &[u8]) -> Vec { - D::key(b"tributary_provided", b"transaction", [self.genesis.as_ref(), hash].concat()) - } - fn current_provided_key(&self) -> Vec { - D::key(b"tributary_provided", b"current", self.genesis) - } - pub(crate) fn locally_provided_quantity_key(genesis: &[u8; 32], order: &str) -> Vec { - D::key(b"tributary_provided", b"local_quantity", [genesis, order.as_bytes()].concat()) - } - pub(crate) fn on_chain_provided_quantity_key(genesis: &[u8; 32], order: &str) -> Vec { - D::key(b"tributary_provided", b"on_chain_quantity", [genesis, order.as_bytes()].concat()) - } - pub(crate) fn block_provided_quantity_key( - genesis: &[u8; 32], - block: &[u8; 32], - order: &str, - ) -> Vec { - D::key(b"tributary_provided", b"block_quantity", [genesis, block, order.as_bytes()].concat()) +create_db!( + TributaryProvidedDb { + TransactionDb: (genesis: &[u8], hash: &[u8]) -> Vec, + CurrentDb: (genesis: &[u8]) -> Vec, + LocalQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, + OnChainQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, + BlockQuantityDb: (genesis: &[u8], block: &[u8], order: &[u8]) -> u32, + OnChainTxDb: (genesis: &[u8], order: &[u8], id: &[u8]) -> Vec } +); - pub(crate) fn on_chain_provided_key(genesis: &[u8; 32], order: &str, id: u32) -> Vec { - D::key( - b"tributary_provided", - b"on_chain_tx", - [genesis, order.as_bytes(), &id.to_le_bytes()].concat(), - ) - } +impl ProvidedTransactions { pub(crate) fn new(db: D, genesis: [u8; 32]) -> Self { let mut res = ProvidedTransactions { db, genesis, transactions: HashMap::new() }; - - let currently_provided = res.db.get(res.current_provided_key()).unwrap_or(vec![]); + let currently_provided = CurrentDb::get(&res.db, &genesis).unwrap_or_default(); let mut i = 0; while i < currently_provided.len() { let tx = T::read::<&[u8]>( - &mut res.db.get(res.transaction_key(¤tly_provided[i .. (i + 32)])).unwrap().as_ref(), + &mut TransactionDb::get(&res.db, &res.genesis, ¤tly_provided[i .. (i + 32)]).unwrap().as_ref() ) .unwrap(); @@ -96,50 +79,39 @@ impl ProvidedTransactions { let tx_hash = tx.hash(); // Check it wasn't already provided - let provided_key = self.transaction_key(&tx_hash); - if self.db.get(&provided_key).is_some() { + if TransactionDb::get(&self.db, &self.genesis, &tx_hash).is_some() { Err(ProvidedError::AlreadyProvided)?; } // get local and on-chain tx numbers - let local_key = Self::locally_provided_quantity_key(&self.genesis, order); - let mut local_quantity = self - .db - .get(&local_key) - .map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())) - .unwrap_or(0); - let on_chain_key = Self::on_chain_provided_quantity_key(&self.genesis, order); - let on_chain_quantity = self - .db - .get(on_chain_key) - .map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())) - .unwrap_or(0); - - let current_provided_key = self.current_provided_key(); - + let order_bytes = order.as_bytes(); + let mut local_quantity = LocalQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + let on_chain_quantity = OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + // This would have a race-condition with multiple calls to provide, though this takes &mut self // peventing multiple calls at once let mut txn = self.db.txn(); - txn.put(provided_key, tx.serialize()); + CurrentDb::set(&mut txn, &self.genesis, &tx.serialize()); + let this_provided_id = local_quantity; local_quantity += 1; - txn.put(local_key, local_quantity.to_le_bytes()); + LocalQuantityDb::set(&mut txn, &self.genesis, order_bytes, &local_quantity); if this_provided_id < on_chain_quantity { // Verify against the on-chain version if tx_hash.as_ref() != - txn.get(Self::on_chain_provided_key(&self.genesis, order, this_provided_id)).unwrap() + OnChainTxDb::get(&txn, &self.genesis, order_bytes, &this_provided_id.to_le_bytes()).unwrap() { Err(ProvidedError::LocalMismatchesOnChain)?; } txn.commit(); } else { #[allow(clippy::unwrap_or_default)] - let mut currently_provided = txn.get(¤t_provided_key).unwrap_or(vec![]); + let mut currently_provided = CurrentDb::get(&txn, &self.genesis).unwrap_or_default(); currently_provided.extend(tx_hash); - txn.put(current_provided_key, currently_provided); + CurrentDb::set(&mut txn, &self.genesis, ¤tly_provided); txn.commit(); if self.transactions.get(order).is_none() { @@ -161,9 +133,7 @@ impl ProvidedTransactions { ) { if let Some(next_tx) = self.transactions.get_mut(order).and_then(|queue| queue.pop_front()) { assert_eq!(next_tx.hash(), tx); - - let current_provided_key = self.current_provided_key(); - let mut currently_provided = txn.get(¤t_provided_key).unwrap(); + let mut currently_provided = CurrentDb::get(txn, &self.genesis).unwrap(); // Find this TX's hash let mut i = 0; @@ -178,24 +148,20 @@ impl ProvidedTransactions { panic!("couldn't find completed TX in currently provided"); } } - - txn.put(current_provided_key, currently_provided); + CurrentDb::set(txn, &self.genesis, ¤tly_provided); } // bump the on-chain tx number. - let on_chain_key = Self::on_chain_provided_quantity_key(&self.genesis, order); - let block_order_key = Self::block_provided_quantity_key(&self.genesis, &block, order); - let mut on_chain_quantity = self - .db - .get(&on_chain_key) - .map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())) - .unwrap_or(0); - + let order_bytes = order.as_bytes(); + let mut on_chain_quantity = OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); let this_provided_id = on_chain_quantity; - txn.put(Self::on_chain_provided_key(&self.genesis, order, this_provided_id), tx); + +// let block_order_key = Self::block_provided_quantity_key(&self.genesis, &block, order); + + OnChainTxDb::set(txn, &self.genesis, order_bytes, &this_provided_id.to_le_bytes(), &tx); on_chain_quantity += 1; - txn.put(on_chain_key, on_chain_quantity.to_le_bytes()); - txn.put(block_order_key, on_chain_quantity.to_le_bytes()); + OnChainQuantityDb::set(txn, &self.genesis, order_bytes, &on_chain_quantity); + BlockQuantityDb::set(txn, &self.genesis, &block, order_bytes, &on_chain_quantity); } -} +} \ No newline at end of file diff --git a/coordinator/tributary/src/tests/blockchain.rs b/coordinator/tributary/src/tests/blockchain.rs index 79f304f02..3f25504cb 100644 --- a/coordinator/tributary/src/tests/blockchain.rs +++ b/coordinator/tributary/src/tests/blockchain.rs @@ -23,7 +23,7 @@ use crate::{ tests::{ ProvidedTransaction, SignedTransaction, random_provided_transaction, p2p::DummyP2p, new_genesis, random_evidence_tx, - }, + }, blockchain::BlockAfterDb, }; type N = TendermintNetwork; @@ -53,7 +53,7 @@ fn block_addition() { assert_eq!(blockchain.tip(), block.hash()); assert_eq!(blockchain.block_number(), 1); assert_eq!( - Blockchain::::block_after(&db, genesis, &block.parent()).unwrap(), + BlockAfterDb::get(&db, genesis, block.parent()).unwrap(), block.hash() ); } From 1f48feadde7167a26277aff61599e292c98d0ee4 Mon Sep 17 00:00:00 2001 From: EmmanuelChthonic Date: Tue, 21 Nov 2023 15:02:48 +0400 Subject: [PATCH 2/4] fixes --- coordinator/tributary/src/blockchain.rs | 2 +- coordinator/tributary/src/provided.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/coordinator/tributary/src/blockchain.rs b/coordinator/tributary/src/blockchain.rs index 351ccafcf..81d5af180 100644 --- a/coordinator/tributary/src/blockchain.rs +++ b/coordinator/tributary/src/blockchain.rs @@ -37,7 +37,7 @@ create_db!( CommitDb: (genesis: [u8; 32], block: &[u8; 32]) -> Vec, BlockAfterDb: (genesis: [u8; 32], hash: [u8; 32]) -> [u8; 32], UnsignedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec, - ProvidedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec, + ProvidedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> [u8; 0], NextNonceDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec } ); diff --git a/coordinator/tributary/src/provided.rs b/coordinator/tributary/src/provided.rs index 72e109ff1..aead0340e 100644 --- a/coordinator/tributary/src/provided.rs +++ b/coordinator/tributary/src/provided.rs @@ -91,7 +91,7 @@ impl ProvidedTransactions { // This would have a race-condition with multiple calls to provide, though this takes &mut self // peventing multiple calls at once let mut txn = self.db.txn(); - CurrentDb::set(&mut txn, &self.genesis, &tx.serialize()); + TransactionDb::set(&mut txn, &self.genesis, &tx_hash, &tx.serialize()); let this_provided_id = local_quantity; From 46d1375af03622e3a4b7c239c34cb5515c5e980f Mon Sep 17 00:00:00 2001 From: EmmanuelChthonic Date: Tue, 21 Nov 2023 17:11:39 +0400 Subject: [PATCH 3/4] fix for final test + fmt +clippy --- coordinator/tributary/src/blockchain.rs | 14 ++++++--- coordinator/tributary/src/lib.rs | 4 +-- coordinator/tributary/src/provided.rs | 29 ++++++++++--------- coordinator/tributary/src/tests/blockchain.rs | 8 ++--- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/coordinator/tributary/src/blockchain.rs b/coordinator/tributary/src/blockchain.rs index 81d5af180..b019e0f5b 100644 --- a/coordinator/tributary/src/blockchain.rs +++ b/coordinator/tributary/src/blockchain.rs @@ -9,7 +9,8 @@ use scale::{Encode, Decode}; use tendermint::ext::{Network, Commit}; use crate::{ - ReadWrite, ProvidedError, ProvidedTransactions, BlockQuantityDb, LocalQuantityDb, BlockError, Block, Mempool, Transaction, + ReadWrite, ProvidedError, ProvidedTransactions, BlockQuantityDb, LocalQuantityDb, BlockError, + Block, Mempool, Transaction, transaction::{Signed, TransactionKind, TransactionError, Transaction as TransactionTrait}, }; @@ -68,7 +69,8 @@ impl Blockchain { }; let self_db = res.db.as_ref().unwrap(); if let Some((block_number, tip)) = { - BlockNumberDb::get(self_db, genesis).map(|number| (number, TipsDb::get(self_db, genesis).unwrap())) + BlockNumberDb::get(self_db, genesis) + .map(|number| (number, TipsDb::get(self_db, genesis).unwrap())) } { res.block_number = u32::from_le_bytes(block_number.try_into().unwrap()); res.tip.copy_from_slice(&tip); @@ -101,7 +103,11 @@ impl Blockchain { } pub(crate) fn commit_by_block_number(&self, block: u32) -> Option> { - CommitDb::get(self.db.as_ref().unwrap(), self.genesis, &BlockHashDb::get(self.db.as_ref().unwrap(), self.genesis, block).unwrap()) + CommitDb::get( + self.db.as_ref().unwrap(), + self.genesis, + &BlockHashDb::get(self.db.as_ref().unwrap(), self.genesis, block).unwrap(), + ) } pub(crate) fn locally_provided_txs_in_block( @@ -271,4 +277,4 @@ impl Blockchain { Ok(()) } -} \ No newline at end of file +} diff --git a/coordinator/tributary/src/lib.rs b/coordinator/tributary/src/lib.rs index dc402ab49..bc22a9e51 100644 --- a/coordinator/tributary/src/lib.rs +++ b/coordinator/tributary/src/lib.rs @@ -397,7 +397,7 @@ impl TributaryReader { Blockchain::::block_from_db(&self.0, self.1, hash) } pub fn commit(&self, hash: &[u8; 32]) -> Option> { - CommitDb::get(&self.0, self.1, &hash) + CommitDb::get(&self.0, self.1, hash) } pub fn parsed_commit(&self, hash: &[u8; 32]) -> Option> { self.commit(hash).map(|commit| Commit::::decode(&mut commit.as_ref()).unwrap()) @@ -419,4 +419,4 @@ impl TributaryReader { pub fn tip(&self) -> [u8; 32] { Blockchain::::tip_from_db(&self.0, self.1) } -} \ No newline at end of file +} diff --git a/coordinator/tributary/src/provided.rs b/coordinator/tributary/src/provided.rs index aead0340e..e76c82031 100644 --- a/coordinator/tributary/src/provided.rs +++ b/coordinator/tributary/src/provided.rs @@ -37,19 +37,20 @@ create_db!( LocalQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, OnChainQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, BlockQuantityDb: (genesis: &[u8], block: &[u8], order: &[u8]) -> u32, - OnChainTxDb: (genesis: &[u8], order: &[u8], id: &[u8]) -> Vec + OnChainTxDb: (genesis: &[u8], order: &[u8], id: u32) -> [u8; 32] } ); impl ProvidedTransactions { - pub(crate) fn new(db: D, genesis: [u8; 32]) -> Self { let mut res = ProvidedTransactions { db, genesis, transactions: HashMap::new() }; let currently_provided = CurrentDb::get(&res.db, &genesis).unwrap_or_default(); let mut i = 0; while i < currently_provided.len() { let tx = T::read::<&[u8]>( - &mut TransactionDb::get(&res.db, &res.genesis, ¤tly_provided[i .. (i + 32)]).unwrap().as_ref() + &mut TransactionDb::get(&res.db, &res.genesis, ¤tly_provided[i .. (i + 32)]) + .unwrap() + .as_ref(), ) .unwrap(); @@ -85,14 +86,15 @@ impl ProvidedTransactions { // get local and on-chain tx numbers let order_bytes = order.as_bytes(); - let mut local_quantity = LocalQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); - let on_chain_quantity = OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); - + let mut local_quantity = + LocalQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + let on_chain_quantity = + OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + // This would have a race-condition with multiple calls to provide, though this takes &mut self // peventing multiple calls at once let mut txn = self.db.txn(); TransactionDb::set(&mut txn, &self.genesis, &tx_hash, &tx.serialize()); - let this_provided_id = local_quantity; @@ -102,7 +104,7 @@ impl ProvidedTransactions { if this_provided_id < on_chain_quantity { // Verify against the on-chain version if tx_hash.as_ref() != - OnChainTxDb::get(&txn, &self.genesis, order_bytes, &this_provided_id.to_le_bytes()).unwrap() + OnChainTxDb::get(&txn, &self.genesis, order_bytes, this_provided_id).unwrap() { Err(ProvidedError::LocalMismatchesOnChain)?; } @@ -153,15 +155,16 @@ impl ProvidedTransactions { // bump the on-chain tx number. let order_bytes = order.as_bytes(); - let mut on_chain_quantity = OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + let mut on_chain_quantity = + OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); let this_provided_id = on_chain_quantity; -// let block_order_key = Self::block_provided_quantity_key(&self.genesis, &block, order); - - OnChainTxDb::set(txn, &self.genesis, order_bytes, &this_provided_id.to_le_bytes(), &tx); + // let block_order_key = Self::block_provided_quantity_key(&self.genesis, &block, order); + + OnChainTxDb::set(txn, &self.genesis, order_bytes, this_provided_id, &tx); on_chain_quantity += 1; OnChainQuantityDb::set(txn, &self.genesis, order_bytes, &on_chain_quantity); BlockQuantityDb::set(txn, &self.genesis, &block, order_bytes, &on_chain_quantity); } -} \ No newline at end of file +} diff --git a/coordinator/tributary/src/tests/blockchain.rs b/coordinator/tributary/src/tests/blockchain.rs index 3f25504cb..14f239fff 100644 --- a/coordinator/tributary/src/tests/blockchain.rs +++ b/coordinator/tributary/src/tests/blockchain.rs @@ -23,7 +23,8 @@ use crate::{ tests::{ ProvidedTransaction, SignedTransaction, random_provided_transaction, p2p::DummyP2p, new_genesis, random_evidence_tx, - }, blockchain::BlockAfterDb, + }, + blockchain::BlockAfterDb, }; type N = TendermintNetwork; @@ -52,10 +53,7 @@ fn block_addition() { assert!(blockchain.add_block::(&block, vec![], validators).is_ok()); assert_eq!(blockchain.tip(), block.hash()); assert_eq!(blockchain.block_number(), 1); - assert_eq!( - BlockAfterDb::get(&db, genesis, block.parent()).unwrap(), - block.hash() - ); + assert_eq!(BlockAfterDb::get(&db, genesis, block.parent()).unwrap(), block.hash()); } #[test] From d94970a60fc86fe747e514c46e58147ce8344cd4 Mon Sep 17 00:00:00 2001 From: EmmanuelChthonic Date: Tue, 28 Nov 2023 13:42:04 +0400 Subject: [PATCH 4/4] Made changes but tests are broken --- coordinator/tributary/src/blockchain.rs | 28 ++++++------- coordinator/tributary/src/provided.rs | 54 ++++++++++++------------- 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/coordinator/tributary/src/blockchain.rs b/coordinator/tributary/src/blockchain.rs index b019e0f5b..fb65d78b1 100644 --- a/coordinator/tributary/src/blockchain.rs +++ b/coordinator/tributary/src/blockchain.rs @@ -9,7 +9,7 @@ use scale::{Encode, Decode}; use tendermint::ext::{Network, Commit}; use crate::{ - ReadWrite, ProvidedError, ProvidedTransactions, BlockQuantityDb, LocalQuantityDb, BlockError, + ReadWrite, ProvidedError, ProvidedTransactions, BlockProvidedQuantityDb, LocalProvidedQuantityDb, BlockError, Block, Mempool, Transaction, transaction::{Signed, TransactionKind, TransactionError, Transaction as TransactionTrait}, }; @@ -32,14 +32,14 @@ pub(crate) struct Blockchain { create_db!( TributaryBlockchainDb { TipsDb: (genesis: [u8; 32]) -> [u8; 32], - BlockNumberDb: (genesis: [u8; 32]) -> Vec, + BlockNumberDb: (genesis: [u8; 32]) -> u32, BlockDb: (genesis: [u8; 32], hash: &[u8; 32]) -> Vec, BlockHashDb: (genesis: [u8; 32], block_number: u32) -> [u8; 32], CommitDb: (genesis: [u8; 32], block: &[u8; 32]) -> Vec, BlockAfterDb: (genesis: [u8; 32], hash: [u8; 32]) -> [u8; 32], - UnsignedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec, - ProvidedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> [u8; 0], - NextNonceDb: (genesis: [u8; 32], hash: [u8; 32]) -> Vec + UnsignedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> (), + ProvidedIncludedDb: (genesis: [u8; 32], hash: [u8; 32]) -> (), + NextNonceDb: (genesis: [u8; 32], signer: [u8; 32]) -> u32 } ); @@ -72,13 +72,13 @@ impl Blockchain { BlockNumberDb::get(self_db, genesis) .map(|number| (number, TipsDb::get(self_db, genesis).unwrap())) } { - res.block_number = u32::from_le_bytes(block_number.try_into().unwrap()); + res.block_number = block_number; res.tip.copy_from_slice(&tip); } for participant in participants { if let Some(next_nonce) = NextNonceDb::get(self_db, genesis, participant.to_bytes()) { - res.next_nonces.insert(*participant, u32::from_le_bytes(next_nonce.try_into().unwrap())); + res.next_nonces.insert(*participant, next_nonce); } } @@ -106,7 +106,7 @@ impl Blockchain { CommitDb::get( self.db.as_ref().unwrap(), self.genesis, - &BlockHashDb::get(self.db.as_ref().unwrap(), self.genesis, block).unwrap(), + &BlockHashDb::get(self.db.as_ref().unwrap(), self.genesis, block)?, ) } @@ -117,8 +117,8 @@ impl Blockchain { order: &str, ) -> bool { let order_bytes = order.as_bytes(); - let local = LocalQuantityDb::get(db, genesis, order_bytes).unwrap_or_default(); - let block = BlockQuantityDb::get(db, genesis, block, order_bytes).unwrap_or_default(); + let local = LocalProvidedQuantityDb::get(db, genesis, order_bytes).unwrap_or_default(); + let block = BlockProvidedQuantityDb::get(db, genesis, block, order_bytes).unwrap_or_default(); local >= block } @@ -228,7 +228,7 @@ impl Blockchain { TipsDb::set(&mut txn, self.genesis, &self.tip); self.block_number += 1; - BlockNumberDb::set(&mut txn, self.genesis, &self.block_number.to_le_bytes()); + BlockNumberDb::set(&mut txn, self.genesis, &self.block_number); BlockHashDb::set(&mut txn, self.genesis, self.block_number, &self.tip); @@ -243,12 +243,12 @@ impl Blockchain { TransactionKind::Provided(order) => { let hash = tx.hash(); self.provided.complete(&mut txn, order, self.tip, hash); - ProvidedIncludedDb::set(&mut txn, self.genesis, hash, &[] as &[u8; 0]); + ProvidedIncludedDb::set(&mut txn, self.genesis, hash, &()); } TransactionKind::Unsigned => { let hash = tx.hash(); // Save as included on chain - UnsignedIncludedDb::set(&mut txn, self.genesis, hash, &[] as &[u8; 0]); + UnsignedIncludedDb::set(&mut txn, self.genesis, hash, &()); // remove from the mempool self.mempool.remove(&hash); } @@ -261,7 +261,7 @@ impl Blockchain { if prev != *nonce { panic!("verified block had an invalid nonce"); } - NextNonceDb::set(&mut txn, self.genesis, signer.to_bytes(), &next_nonce.to_le_bytes()); + NextNonceDb::set(&mut txn, self.genesis, signer.to_bytes(), &next_nonce); self.mempool.remove(&tx.hash()); } diff --git a/coordinator/tributary/src/provided.rs b/coordinator/tributary/src/provided.rs index e76c82031..fb201dadf 100644 --- a/coordinator/tributary/src/provided.rs +++ b/coordinator/tributary/src/provided.rs @@ -32,23 +32,23 @@ pub struct ProvidedTransactions { create_db!( TributaryProvidedDb { - TransactionDb: (genesis: &[u8], hash: &[u8]) -> Vec, - CurrentDb: (genesis: &[u8]) -> Vec, - LocalQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, - OnChainQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, - BlockQuantityDb: (genesis: &[u8], block: &[u8], order: &[u8]) -> u32, - OnChainTxDb: (genesis: &[u8], order: &[u8], id: u32) -> [u8; 32] + TransactionDb: (genesis: &[u8], hash: [u8; 32]) -> Vec, + CurrentProvidedDb: (genesis: &[u8]) -> Vec<[u8; 32]>, + LocalProvidedQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, + OnChainProvidedQuantityDb: (genesis: &[u8], order: &[u8]) -> u32, + BlockProvidedQuantityDb: (genesis: &[u8], block: &[u8], order: &[u8]) -> u32, + OnChainProvidedDb: (genesis: &[u8], order: &[u8], id: u32) -> [u8; 32] } ); impl ProvidedTransactions { pub(crate) fn new(db: D, genesis: [u8; 32]) -> Self { let mut res = ProvidedTransactions { db, genesis, transactions: HashMap::new() }; - let currently_provided = CurrentDb::get(&res.db, &genesis).unwrap_or_default(); + let currently_provided = CurrentProvidedDb::get(&res.db, &genesis).unwrap_or_default(); let mut i = 0; while i < currently_provided.len() { let tx = T::read::<&[u8]>( - &mut TransactionDb::get(&res.db, &res.genesis, ¤tly_provided[i .. (i + 32)]) + &mut TransactionDb::get(&res.db, &res.genesis, currently_provided[i]) .unwrap() .as_ref(), ) @@ -80,40 +80,40 @@ impl ProvidedTransactions { let tx_hash = tx.hash(); // Check it wasn't already provided - if TransactionDb::get(&self.db, &self.genesis, &tx_hash).is_some() { + if TransactionDb::get(&self.db, &self.genesis, tx_hash).is_some() { Err(ProvidedError::AlreadyProvided)?; } // get local and on-chain tx numbers let order_bytes = order.as_bytes(); let mut local_quantity = - LocalQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + LocalProvidedQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); let on_chain_quantity = - OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + OnChainProvidedQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); // This would have a race-condition with multiple calls to provide, though this takes &mut self // peventing multiple calls at once let mut txn = self.db.txn(); - TransactionDb::set(&mut txn, &self.genesis, &tx_hash, &tx.serialize()); + TransactionDb::set(&mut txn, &self.genesis, tx_hash, &tx.serialize()); let this_provided_id = local_quantity; local_quantity += 1; - LocalQuantityDb::set(&mut txn, &self.genesis, order_bytes, &local_quantity); + LocalProvidedQuantityDb::set(&mut txn, &self.genesis, order_bytes, &local_quantity); if this_provided_id < on_chain_quantity { // Verify against the on-chain version if tx_hash.as_ref() != - OnChainTxDb::get(&txn, &self.genesis, order_bytes, this_provided_id).unwrap() + OnChainProvidedDb::get(&txn, &self.genesis, order_bytes, this_provided_id).unwrap() { Err(ProvidedError::LocalMismatchesOnChain)?; } txn.commit(); } else { #[allow(clippy::unwrap_or_default)] - let mut currently_provided = CurrentDb::get(&txn, &self.genesis).unwrap_or_default(); - currently_provided.extend(tx_hash); - CurrentDb::set(&mut txn, &self.genesis, ¤tly_provided); + let mut currently_provided = CurrentProvidedDb::get(&txn, &self.genesis).unwrap_or_default(); + currently_provided.push(tx_hash); + CurrentProvidedDb::set(&mut txn, &self.genesis, ¤tly_provided); txn.commit(); if self.transactions.get(order).is_none() { @@ -135,13 +135,13 @@ impl ProvidedTransactions { ) { if let Some(next_tx) = self.transactions.get_mut(order).and_then(|queue| queue.pop_front()) { assert_eq!(next_tx.hash(), tx); - let mut currently_provided = CurrentDb::get(txn, &self.genesis).unwrap(); + let currently_provided = CurrentProvidedDb::get(txn, &self.genesis).unwrap(); // Find this TX's hash let mut i = 0; loop { - if currently_provided[i .. (i + 32)] == tx { - assert_eq!(¤tly_provided.drain(i .. (i + 32)).collect::>(), &tx); + if currently_provided[i] == tx { + assert_eq!(currently_provided[i], tx); break; } @@ -150,21 +150,17 @@ impl ProvidedTransactions { panic!("couldn't find completed TX in currently provided"); } } - CurrentDb::set(txn, &self.genesis, ¤tly_provided); + CurrentProvidedDb::set(txn, &self.genesis, ¤tly_provided); } // bump the on-chain tx number. let order_bytes = order.as_bytes(); let mut on_chain_quantity = - OnChainQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); + OnChainProvidedQuantityDb::get(&self.db, &self.genesis, order_bytes).unwrap_or_default(); let this_provided_id = on_chain_quantity; - - // let block_order_key = Self::block_provided_quantity_key(&self.genesis, &block, order); - - OnChainTxDb::set(txn, &self.genesis, order_bytes, this_provided_id, &tx); - + OnChainProvidedDb::set(txn, &self.genesis, order_bytes, this_provided_id, &tx); on_chain_quantity += 1; - OnChainQuantityDb::set(txn, &self.genesis, order_bytes, &on_chain_quantity); - BlockQuantityDb::set(txn, &self.genesis, &block, order_bytes, &on_chain_quantity); + OnChainProvidedQuantityDb::set(txn, &self.genesis, order_bytes, &on_chain_quantity); + BlockProvidedQuantityDb::set(txn, &self.genesis, &block, order_bytes, &on_chain_quantity); } }