wip
This commit is contained in:
parent
57f82934f2
commit
3e1a926aa6
|
@ -1,6 +1,5 @@
|
|||
use crate::bank::BankError;
|
||||
use crate::bank::Result;
|
||||
use crate::checkpoint::Checkpoint;
|
||||
use crate::counter::Counter;
|
||||
use crate::status_deque::{StatusDeque, StatusDequeError};
|
||||
use bincode::serialize;
|
||||
|
@ -11,7 +10,6 @@ use solana_sdk::hash::{hash, Hash};
|
|||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::{Mutex, RwLock};
|
||||
|
||||
|
@ -35,9 +33,6 @@ pub struct AccountsDB {
|
|||
/// Mapping of known public keys/IDs to accounts
|
||||
pub accounts: HashMap<Pubkey, Account>,
|
||||
|
||||
/// list of prior states
|
||||
checkpoints: VecDeque<(HashMap<Pubkey, Account>, u64)>,
|
||||
|
||||
/// The number of transactions the bank has processed without error since the
|
||||
/// start of the ledger.
|
||||
transaction_count: u64,
|
||||
|
@ -55,7 +50,6 @@ impl Default for AccountsDB {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
accounts: HashMap::new(),
|
||||
checkpoints: VecDeque::new(),
|
||||
transaction_count: 0,
|
||||
}
|
||||
}
|
||||
|
@ -91,24 +85,12 @@ impl AccountsDB {
|
|||
if let Some(account) = self.accounts.get(pubkey) {
|
||||
return Some(account);
|
||||
}
|
||||
|
||||
for (accounts, _) in &self.checkpoints {
|
||||
if let Some(account) = accounts.get(pubkey) {
|
||||
return Some(account);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn store(&mut self, pubkey: &Pubkey, account: &Account) {
|
||||
if account.tokens == 0 {
|
||||
if self.checkpoints.is_empty() {
|
||||
// purge if balance is 0 and no checkpoints
|
||||
self.accounts.remove(pubkey);
|
||||
} else {
|
||||
// store default account if balance is 0 and there's a checkpoint
|
||||
self.accounts.insert(pubkey.clone(), Account::default());
|
||||
}
|
||||
self.accounts.remove(pubkey);
|
||||
} else {
|
||||
self.accounts.insert(pubkey.clone(), account.clone());
|
||||
}
|
||||
|
@ -266,15 +248,6 @@ impl AccountsDB {
|
|||
pub fn transaction_count(&self) -> u64 {
|
||||
self.transaction_count
|
||||
}
|
||||
|
||||
pub fn checkpoint_and_copy(&mut self) -> AccountsDB {
|
||||
self.checkpoint();
|
||||
let (accounts, tx_count) = self.checkpoints.front().unwrap();
|
||||
let mut copy = AccountsDB::default();
|
||||
copy.accounts = accounts.clone();
|
||||
copy.transaction_count = *tx_count;
|
||||
copy
|
||||
}
|
||||
}
|
||||
|
||||
impl Accounts {
|
||||
|
@ -392,66 +365,6 @@ impl Accounts {
|
|||
pub fn transaction_count(&self) -> u64 {
|
||||
self.accounts_db.read().unwrap().transaction_count()
|
||||
}
|
||||
|
||||
pub fn checkpoint(&self) {
|
||||
self.accounts_db.write().unwrap().checkpoint()
|
||||
}
|
||||
|
||||
pub fn rollback(&self) {
|
||||
self.accounts_db.write().unwrap().rollback()
|
||||
}
|
||||
|
||||
pub fn purge(&self, depth: usize) {
|
||||
self.accounts_db.write().unwrap().purge(depth)
|
||||
}
|
||||
|
||||
pub fn depth(&self) -> usize {
|
||||
self.accounts_db.read().unwrap().depth()
|
||||
}
|
||||
|
||||
pub fn checkpoint_and_copy(&self) -> Accounts {
|
||||
let db = self.accounts_db.write().unwrap().checkpoint_and_copy();
|
||||
let mut copy = Accounts::default();
|
||||
copy.accounts_db = RwLock::new(db);
|
||||
copy
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkpoint for AccountsDB {
|
||||
fn checkpoint(&mut self) {
|
||||
let accounts = self.accounts.clone();
|
||||
|
||||
self.checkpoints
|
||||
.push_front((accounts, self.transaction_count()));
|
||||
}
|
||||
|
||||
fn rollback(&mut self) {
|
||||
let (accounts, transaction_count) = self.checkpoints.pop_front().unwrap();
|
||||
self.accounts = accounts;
|
||||
self.transaction_count = transaction_count;
|
||||
}
|
||||
|
||||
fn purge(&mut self, depth: usize) {
|
||||
fn merge(into: &mut HashMap<Pubkey, Account>, purge: &mut HashMap<Pubkey, Account>) {
|
||||
purge.retain(|pubkey, _| !into.contains_key(pubkey));
|
||||
into.extend(purge.drain());
|
||||
into.retain(|_, account| account.tokens != 0);
|
||||
}
|
||||
|
||||
while self.depth() > depth {
|
||||
let (mut purge, _) = self.checkpoints.pop_back().unwrap();
|
||||
|
||||
if let Some((into, _)) = self.checkpoints.back_mut() {
|
||||
merge(into, &mut purge);
|
||||
continue;
|
||||
}
|
||||
merge(&mut self.accounts, &mut purge);
|
||||
}
|
||||
}
|
||||
|
||||
fn depth(&self) -> usize {
|
||||
self.checkpoints.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
238
src/bank.rs
238
src/bank.rs
|
@ -4,7 +4,6 @@
|
|||
//! already been signed and verified.
|
||||
|
||||
use crate::accounts::{Accounts, ErrorCounters, InstructionAccounts, InstructionLoaders};
|
||||
use crate::checkpoint::Checkpoint;
|
||||
use crate::counter::Counter;
|
||||
use crate::entry::Entry;
|
||||
use crate::entry::EntrySlice;
|
||||
|
@ -138,48 +137,6 @@ impl Bank {
|
|||
*sub = subscriptions
|
||||
}
|
||||
|
||||
/// Checkpoint this bank and return a copy of it
|
||||
pub fn checkpoint_and_copy(&self) -> Bank {
|
||||
let last_ids_cp = self.last_ids.write().unwrap().checkpoint_and_copy();
|
||||
let accounts = self.accounts.checkpoint_and_copy();
|
||||
|
||||
let mut copy = Bank::default();
|
||||
copy.accounts = accounts;
|
||||
copy.last_ids = RwLock::new(last_ids_cp);
|
||||
copy.leader_scheduler =
|
||||
Arc::new(RwLock::new(self.leader_scheduler.read().unwrap().clone()));
|
||||
copy.confirmation_time = AtomicUsize::new(self.confirmation_time.load(Ordering::Relaxed));
|
||||
copy
|
||||
}
|
||||
|
||||
pub fn checkpoint(&self) {
|
||||
self.accounts.checkpoint();
|
||||
self.last_ids.write().unwrap().checkpoint();
|
||||
}
|
||||
pub fn purge(&self, depth: usize) {
|
||||
self.accounts.purge(depth);
|
||||
self.last_ids.write().unwrap().purge(depth);
|
||||
}
|
||||
|
||||
pub fn rollback(&self) {
|
||||
let rolled_back_pubkeys: Vec<Pubkey> = self.accounts.keys();
|
||||
self.accounts.rollback();
|
||||
|
||||
rolled_back_pubkeys.iter().for_each(|pubkey| {
|
||||
if let Some(account) = self.accounts.load_slow(&pubkey) {
|
||||
self.subscriptions
|
||||
.read()
|
||||
.unwrap()
|
||||
.check_account(&pubkey, &account)
|
||||
}
|
||||
});
|
||||
|
||||
self.last_ids.write().unwrap().rollback();
|
||||
}
|
||||
pub fn checkpoint_depth(&self) -> usize {
|
||||
self.accounts.depth()
|
||||
}
|
||||
|
||||
fn process_genesis_block(&self, genesis_block: &GenesisBlock) {
|
||||
assert!(genesis_block.mint_id != Pubkey::default());
|
||||
assert!(genesis_block.tokens >= genesis_block.bootstrap_leader_tokens);
|
||||
|
@ -869,8 +826,6 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::entry::{next_entries, next_entry, Entry};
|
||||
use crate::gen_keys::GenKeys;
|
||||
use crate::status_deque;
|
||||
use crate::status_deque::StatusDequeError;
|
||||
use bincode::serialize;
|
||||
use hashbrown::HashSet;
|
||||
use solana_sdk::hash::hash;
|
||||
|
@ -1577,199 +1532,6 @@ mod tests {
|
|||
assert!(ids.into_iter().all(move |id| unique.insert(id)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_purge() {
|
||||
let (genesis_block, alice) = GenesisBlock::new(10_000);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let bob = Keypair::new();
|
||||
let charlie = Keypair::new();
|
||||
|
||||
// bob should have 500
|
||||
bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
|
||||
bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
|
||||
bank.checkpoint();
|
||||
bank.checkpoint();
|
||||
assert_eq!(bank.checkpoint_depth(), 2);
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
assert_eq!(bank.get_balance(&alice.pubkey()), 9_000);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 2);
|
||||
|
||||
// transfer money back, so bob has zero
|
||||
bank.transfer(500, &bob, alice.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
// this has to be stored as zero in the top accounts hashmap ;)
|
||||
assert!(bank.accounts.load_slow(&bob.pubkey()).is_some());
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 0);
|
||||
// double-checks
|
||||
assert_eq!(bank.get_balance(&alice.pubkey()), 9_500);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 3);
|
||||
bank.purge(1);
|
||||
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 0);
|
||||
// double-checks
|
||||
assert_eq!(bank.get_balance(&alice.pubkey()), 9_500);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 3);
|
||||
assert_eq!(bank.checkpoint_depth(), 1);
|
||||
|
||||
bank.purge(0);
|
||||
|
||||
// bob should still have 0, alice should have 10_000
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 0);
|
||||
assert!(bank.accounts.load_slow(&bob.pubkey()).is_none());
|
||||
// double-checks
|
||||
assert_eq!(bank.get_balance(&alice.pubkey()), 9_500);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 3);
|
||||
assert_eq!(bank.checkpoint_depth(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_checkpoint_zero_balance() {
|
||||
let (genesis_block, alice) = GenesisBlock::new(1_000);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let bob = Keypair::new();
|
||||
let charlie = Keypair::new();
|
||||
|
||||
// bob should have 500
|
||||
bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
assert_eq!(bank.checkpoint_depth(), 0);
|
||||
|
||||
let account = bank.get_account(&alice.pubkey()).unwrap();
|
||||
let default_account = Account::default();
|
||||
assert_eq!(account.userdata, default_account.userdata);
|
||||
assert_eq!(account.owner, default_account.owner);
|
||||
assert_eq!(account.executable, default_account.executable);
|
||||
assert_eq!(account.loader, default_account.loader);
|
||||
|
||||
bank.checkpoint();
|
||||
assert_eq!(bank.checkpoint_depth(), 1);
|
||||
|
||||
// charlie should have 500, alice should have 0
|
||||
bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.get_balance(&alice.pubkey()), 0);
|
||||
|
||||
let account = bank.get_account(&alice.pubkey()).unwrap();
|
||||
assert_eq!(account.tokens, default_account.tokens);
|
||||
assert_eq!(account.userdata, default_account.userdata);
|
||||
assert_eq!(account.owner, default_account.owner);
|
||||
assert_eq!(account.executable, default_account.executable);
|
||||
assert_eq!(account.loader, default_account.loader);
|
||||
}
|
||||
|
||||
fn reserve_signature_with_last_id_test(
|
||||
bank: &Bank,
|
||||
sig: &Signature,
|
||||
last_id: &Hash,
|
||||
) -> status_deque::Result<()> {
|
||||
let mut last_ids = bank.last_ids.write().unwrap();
|
||||
last_ids.reserve_signature_with_last_id(last_id, sig)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_checkpoint_rollback() {
|
||||
let (genesis_block, alice) = GenesisBlock::new(10_000);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let bob = Keypair::new();
|
||||
let charlie = Keypair::new();
|
||||
|
||||
// bob should have 500
|
||||
bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.checkpoint_depth(), 0);
|
||||
|
||||
bank.checkpoint();
|
||||
bank.checkpoint();
|
||||
assert_eq!(bank.checkpoint_depth(), 2);
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 2);
|
||||
|
||||
// transfer money back, so bob has zero
|
||||
bank.transfer(500, &bob, alice.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
// this has to be stored as zero in the top accounts hashmap ;)
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 0);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 3);
|
||||
bank.rollback();
|
||||
|
||||
// bob should have 500 again
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.transaction_count(), 2);
|
||||
assert_eq!(bank.checkpoint_depth(), 1);
|
||||
|
||||
let signature = Signature::default();
|
||||
for i in 0..MAX_ENTRY_IDS + 1 {
|
||||
let last_id = hash(&serialize(&i).unwrap()); // Unique hash
|
||||
bank.register_tick(&last_id);
|
||||
}
|
||||
assert_eq!(bank.tick_height(), MAX_ENTRY_IDS as u64 + 2);
|
||||
assert_eq!(
|
||||
reserve_signature_with_last_id_test(&bank, &signature, &genesis_block.last_id()),
|
||||
Err(StatusDequeError::LastIdNotFound)
|
||||
);
|
||||
bank.rollback();
|
||||
assert_eq!(bank.tick_height(), 1);
|
||||
assert_eq!(
|
||||
reserve_signature_with_last_id_test(&bank, &signature, &genesis_block.last_id()),
|
||||
Ok(())
|
||||
);
|
||||
bank.checkpoint();
|
||||
assert_eq!(
|
||||
reserve_signature_with_last_id_test(&bank, &signature, &genesis_block.last_id()),
|
||||
Err(StatusDequeError::DuplicateSignature)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_checkpoint_and_copy() {
|
||||
let (genesis_block, alice) = GenesisBlock::new(10_000);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let bob = Keypair::new();
|
||||
let charlie = Keypair::new();
|
||||
|
||||
// bob should have 500
|
||||
bank.transfer(500, &alice, bob.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&bob.pubkey()), 500);
|
||||
bank.transfer(500, &alice, charlie.pubkey(), genesis_block.last_id())
|
||||
.unwrap();
|
||||
assert_eq!(bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(bank.checkpoint_depth(), 0);
|
||||
|
||||
let cp_bank = bank.checkpoint_and_copy();
|
||||
assert_eq!(cp_bank.get_balance(&bob.pubkey()), 500);
|
||||
assert_eq!(cp_bank.get_balance(&charlie.pubkey()), 500);
|
||||
assert_eq!(cp_bank.checkpoint_depth(), 0);
|
||||
assert_eq!(bank.checkpoint_depth(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_bank_rollback_panic() {
|
||||
let (genesis_block, _) = GenesisBlock::new(10_000);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
bank.rollback();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_record_transactions() {
|
||||
let (genesis_block, mint_keypair) = GenesisBlock::new(10_000);
|
||||
|
|
|
@ -213,7 +213,7 @@ impl BroadcastService {
|
|||
if let Err(e) = broadcast.run(&broadcast_table, receiver, sock, leader_scheduler) {
|
||||
match e {
|
||||
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => {
|
||||
return BroadcastServiceReturnType::ChannelDisconnected
|
||||
return BroadcastServiceReturnType::ChannelDisconnected;
|
||||
}
|
||||
Error::RecvTimeoutError(RecvTimeoutError::Timeout) => (),
|
||||
Error::ClusterInfoError(ClusterInfoError::NoPeers) => (), // TODO: Why are the unit-tests throwing hundreds of these?
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
pub trait Checkpoint {
|
||||
/// add a checkpoint to this data at current state
|
||||
fn checkpoint(&mut self);
|
||||
|
||||
/// rollback to previous state, panics if no prior checkpoint
|
||||
fn rollback(&mut self);
|
||||
|
||||
/// cull checkpoints to depth, that is depth of zero means
|
||||
/// no checkpoints, only current state
|
||||
fn purge(&mut self, depth: usize);
|
||||
|
||||
/// returns the number of checkpoints
|
||||
fn depth(&self) -> usize;
|
||||
}
|
|
@ -278,7 +278,7 @@ impl Fullnode {
|
|||
};
|
||||
|
||||
let tpu = Tpu::new(
|
||||
&Arc::new(bank.checkpoint_and_copy()),
|
||||
&bank,
|
||||
Default::default(),
|
||||
node.sockets
|
||||
.tpu
|
||||
|
@ -360,7 +360,7 @@ impl Fullnode {
|
|||
let (to_validator_sender, to_validator_receiver) = channel();
|
||||
self.role_notifiers.1 = to_validator_receiver;
|
||||
self.node_services.tpu.switch_to_leader(
|
||||
&Arc::new(self.bank.checkpoint_and_copy()),
|
||||
&self.bank,
|
||||
Default::default(),
|
||||
self.tpu_sockets
|
||||
.iter()
|
||||
|
|
|
@ -19,7 +19,6 @@ pub mod broadcast_service;
|
|||
pub mod chacha;
|
||||
#[cfg(all(feature = "chacha", feature = "cuda"))]
|
||||
pub mod chacha_cuda;
|
||||
pub mod checkpoint;
|
||||
pub mod client;
|
||||
pub mod crds;
|
||||
pub mod crds_gossip;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use crate::checkpoint::Checkpoint;
|
||||
use crate::poh_service::NUM_TICKS_PER_SECOND;
|
||||
use hashbrown::HashMap;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::signature::Signature;
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::collections::VecDeque;
|
||||
use std::result;
|
||||
|
||||
/// The number of most recent `last_id` values that the bank will track the signatures
|
||||
|
@ -67,8 +65,6 @@ pub struct StatusDeque<T> {
|
|||
/// reject transactions with signatures it's seen before and to reject
|
||||
/// transactions that are too old (nth is too small)
|
||||
entries: StatusEntryMap<T>,
|
||||
|
||||
checkpoints: VecDeque<(u64, Option<Hash>, StatusEntryMap<T>)>,
|
||||
}
|
||||
|
||||
impl<T> Default for StatusDeque<T> {
|
||||
|
@ -77,32 +73,10 @@ impl<T> Default for StatusDeque<T> {
|
|||
tick_height: 0,
|
||||
last_id: None,
|
||||
entries: HashMap::new(),
|
||||
checkpoints: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Checkpoint for StatusDeque<T> {
|
||||
fn checkpoint(&mut self) {
|
||||
self.checkpoints
|
||||
.push_front((self.tick_height, self.last_id, self.entries.clone()));
|
||||
}
|
||||
fn rollback(&mut self) {
|
||||
let (tick_height, last_id, entries) = self.checkpoints.pop_front().unwrap();
|
||||
self.tick_height = tick_height;
|
||||
self.last_id = last_id;
|
||||
self.entries = entries;
|
||||
}
|
||||
fn purge(&mut self, depth: usize) {
|
||||
while self.depth() > depth {
|
||||
self.checkpoints.pop_back().unwrap();
|
||||
}
|
||||
}
|
||||
fn depth(&self) -> usize {
|
||||
self.checkpoints.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> StatusDeque<T> {
|
||||
pub fn update_signature_status_with_last_id(
|
||||
&mut self,
|
||||
|
@ -116,15 +90,6 @@ impl<T: Clone> StatusDeque<T> {
|
|||
.insert(*signature, Status::Complete(result.clone()));
|
||||
}
|
||||
}
|
||||
pub fn checkpoint_and_copy(&mut self) -> StatusDeque<T> {
|
||||
self.checkpoint();
|
||||
let (tick_height, last_id, entries) = self.checkpoints.front().unwrap().clone();
|
||||
let mut copy = StatusDeque::default();
|
||||
copy.tick_height = tick_height;
|
||||
copy.last_id = last_id;
|
||||
copy.entries = entries;
|
||||
copy
|
||||
}
|
||||
pub fn reserve_signature_with_last_id(
|
||||
&mut self,
|
||||
last_id: &Hash,
|
||||
|
@ -264,23 +229,6 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duplicate_transaction_signature_checkpoint() {
|
||||
let sig = Default::default();
|
||||
let last_id = Default::default();
|
||||
let mut status_deque: StatusDeque<()> = StatusDeque::default();
|
||||
status_deque.register_tick(&last_id);
|
||||
assert_eq!(
|
||||
status_deque.reserve_signature_with_last_id(&last_id, &sig),
|
||||
Ok(())
|
||||
);
|
||||
status_deque.checkpoint();
|
||||
assert_eq!(
|
||||
status_deque.reserve_signature_with_last_id(&last_id, &sig),
|
||||
Err(StatusDequeError::DuplicateSignature)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear_signatures() {
|
||||
let signature = Signature::default();
|
||||
|
@ -297,23 +245,6 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear_signatures_checkpoint() {
|
||||
let signature = Signature::default();
|
||||
let last_id = Default::default();
|
||||
let mut status_deque: StatusDeque<()> = StatusDeque::default();
|
||||
status_deque.register_tick(&last_id);
|
||||
status_deque
|
||||
.reserve_signature_with_last_id(&last_id, &signature)
|
||||
.unwrap();
|
||||
status_deque.checkpoint();
|
||||
status_deque.clear_signatures();
|
||||
assert_eq!(
|
||||
status_deque.reserve_signature_with_last_id(&last_id, &signature),
|
||||
Ok(())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_signature_status() {
|
||||
let signature = Signature::default();
|
||||
|
|
Loading…
Reference in New Issue