Replay should respect order of register_ticks with respect to blockhashes (#6805)
This commit is contained in:
parent
f8e64aad5b
commit
66a0f54097
|
@ -115,8 +115,18 @@ fn process_entries_with_callback(
|
||||||
let mut tick_hashes = vec![];
|
let mut tick_hashes = vec![];
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
if entry.is_tick() {
|
if entry.is_tick() {
|
||||||
// if its a tick, save it for later
|
// If it's a tick, save it for later
|
||||||
tick_hashes.push(entry.hash);
|
tick_hashes.push(entry.hash);
|
||||||
|
if bank.is_block_boundary(bank.tick_height() + tick_hashes.len() as u64) {
|
||||||
|
// If it's a tick that will cause a new blockhash to be created,
|
||||||
|
// execute the group and register the tick
|
||||||
|
execute_batches(bank, &batches, entry_callback)?;
|
||||||
|
batches.clear();
|
||||||
|
for hash in &tick_hashes {
|
||||||
|
bank.register_tick(hash);
|
||||||
|
}
|
||||||
|
tick_hashes.clear();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// else loop on processing the entry
|
// else loop on processing the entry
|
||||||
|
@ -2016,6 +2026,33 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process_ledger_ticks_ordering() {
|
||||||
|
let GenesisBlockInfo {
|
||||||
|
genesis_block,
|
||||||
|
mint_keypair,
|
||||||
|
..
|
||||||
|
} = create_genesis_block(100);
|
||||||
|
let bank0 = Arc::new(Bank::new(&genesis_block));
|
||||||
|
let genesis_hash = genesis_block.hash();
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
|
||||||
|
// Simulate a slot of virtual ticks, creates a new blockhash
|
||||||
|
let mut entries = create_ticks(genesis_block.ticks_per_slot, 1, genesis_hash);
|
||||||
|
|
||||||
|
// The new blockhash is going to be the hash of the last tick in the block
|
||||||
|
let new_blockhash = entries.last().unwrap().hash;
|
||||||
|
// Create an transaction that references the new blockhash, should still
|
||||||
|
// be able to find the blockhash if we process transactions all in the same
|
||||||
|
// batch
|
||||||
|
let tx = system_transaction::transfer(&mint_keypair, &keypair.pubkey(), 1, new_blockhash);
|
||||||
|
let entry = next_entry(&new_blockhash, 1, vec![tx]);
|
||||||
|
entries.push(entry);
|
||||||
|
|
||||||
|
process_entries_with_callback(&bank0, &entries, true, None).unwrap();
|
||||||
|
assert_eq!(bank0.get_balance(&keypair.pubkey()), 1)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_epoch_schedule(
|
fn get_epoch_schedule(
|
||||||
genesis_block: &GenesisBlock,
|
genesis_block: &GenesisBlock,
|
||||||
account_paths: Option<String>,
|
account_paths: Option<String>,
|
||||||
|
|
|
@ -796,7 +796,7 @@ impl Bank {
|
||||||
// assert!(!self.is_frozen());
|
// assert!(!self.is_frozen());
|
||||||
inc_new_counter_debug!("bank-register_tick-registered", 1);
|
inc_new_counter_debug!("bank-register_tick-registered", 1);
|
||||||
let current_tick_height = self.tick_height.fetch_add(1, Ordering::Relaxed) as u64;
|
let current_tick_height = self.tick_height.fetch_add(1, Ordering::Relaxed) as u64;
|
||||||
if current_tick_height % self.ticks_per_slot == self.ticks_per_slot - 1 {
|
if self.is_block_boundary(current_tick_height + 1) {
|
||||||
self.blockhash_queue
|
self.blockhash_queue
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -804,6 +804,10 @@ impl Bank {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_block_boundary(&self, tick_height: u64) -> bool {
|
||||||
|
tick_height % self.ticks_per_slot == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Process a Transaction. This is used for unit tests and simply calls the vector
|
/// Process a Transaction. This is used for unit tests and simply calls the vector
|
||||||
/// Bank::process_transactions method
|
/// Bank::process_transactions method
|
||||||
pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
|
pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
|
||||||
|
|
Loading…
Reference in New Issue