Skip to content

Commit

Permalink
fix deleted_txo_mmr_position_to_height_index key exists error
Browse files Browse the repository at this point in the history
add test
  • Loading branch information
SWvheerden committed Nov 16, 2022
1 parent 39d53c8 commit 2abb58d
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 6 deletions.
14 changes: 8 additions & 6 deletions base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,9 +1031,17 @@ impl LMDBDatabase {
for row in inputs {
// If input spends an output in this block, don't add it to the utxo set
let output_hash = row.input.output_hash();

lmdb_delete(
txn,
&self.deleted_txo_mmr_position_to_height_index,
&row.mmr_position,
"deleted_txo_mmr_position_to_height_index",
)?;
if output_rows.iter().any(|r| r.hash == output_hash) {
continue;
}

let mut input = row.input.clone();

let utxo_mined_info = self.fetch_output_in_txn(txn, output_hash.as_slice())?.ok_or_else(|| {
Expand Down Expand Up @@ -1073,12 +1081,6 @@ impl LMDBDatabase {
&input.output_hash(),
"utxo_commitment_index",
)?;
lmdb_delete(
txn,
&self.deleted_txo_mmr_position_to_height_index,
&row.mmr_position,
"deleted_txo_mmr_position_to_height_index",
)?;
}
Ok(())
}
Expand Down
152 changes: 152 additions & 0 deletions base_layer/core/tests/chain_storage_tests/chain_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ use crate::helpers::{
create_chain_header,
create_genesis_block,
find_header_with_achieved_difficulty,
generate_block_with_achieved_difficulty,
generate_new_block,
generate_new_block_with_achieved_difficulty,
generate_new_block_with_coinbase,
Expand Down Expand Up @@ -319,6 +320,157 @@ fn test_rewind_past_horizon_height() {
assert_eq!(metadata.height_of_longest_chain(), 0);
}

#[test]
fn test_handle_tip_reorg_with_zero_conf() {
// GB --> A1 --> A2 --> A3(Low PoW) [Main Chain]
// \--> B2 --> B3 -- B4 --> B5(Highest PoW) [Forked Chain]

// Create Main Chain
let network = Network::LocalNet;
let (mut store, mut blocks, mut outputs, consensus_manager) = create_new_blockchain(network);
// Block A1
let txs = vec![txn_schema!(
from: vec![outputs[0][0].clone()],
to: vec![10 * T, 10 * T, 10 * T, 10 * T]
)];
generate_new_block_with_achieved_difficulty(
&mut store,
&mut blocks,
&mut outputs,
txs,
Difficulty::from(1),
&consensus_manager,
)
.unwrap();
// Block A2
let txs_1 = txn_schema!(from: vec![outputs[1][3].clone()], to: vec![6 * T]);
let (tx_1, utxos_1) = spend_utxos(txs_1);
// create zero conf
let txs_2 = txn_schema!(from: vec![utxos_1[0].clone()], to: vec![4 * T]);
let (tx_2, utxos_2) = spend_utxos(txs_2);
let txns = vec![tx_1, tx_2];

outputs.push(utxos_2);
generate_block_with_achieved_difficulty(&mut store, &mut blocks, txns, Difficulty::from(3), &consensus_manager)
.unwrap();

// Block A3
let txs = vec![txn_schema!(from: vec![outputs[2][0].clone()], to: vec![2 * T])];
assert!(generate_new_block_with_achieved_difficulty(
&mut store,
&mut blocks,
&mut outputs,
txs,
Difficulty::from(1),
&consensus_manager
)
.is_ok());
assert_eq!(store.get_chain_metadata().unwrap().height_of_longest_chain(), 3);

// Create Forked Chain

let mut orphan_store = create_store_with_consensus(consensus_manager.clone());
orphan_store.add_block(blocks[1].to_arc_block()).unwrap();
let mut orphan_blocks = vec![blocks[0].clone(), blocks[1].clone()];
let mut orphan_outputs = vec![outputs[0].clone(), outputs[1].clone()];
// Block B2
let txs = vec![txn_schema!(
from: vec![
orphan_outputs[1][0].clone(),
orphan_outputs[1][1].clone(),
orphan_outputs[1][2].clone(),
orphan_outputs[1][3].clone(),
orphan_outputs[1][4].clone(),
],
to: vec![5 * T, 5 * T, 5 * T, 5 * T, 5 * T]
)];
generate_new_block_with_achieved_difficulty(
&mut orphan_store,
&mut orphan_blocks,
&mut orphan_outputs,
txs,
Difficulty::from(7),
&consensus_manager,
)
.unwrap();

// Adding B2 to the main chain will produce a reorg to GB->A1->B2.
if let Ok(BlockAddResult::ChainReorg { .. }) = store.add_block(orphan_blocks[2].to_arc_block()) {
} else {
panic!();
}

assert_eq!(store.fetch_tip_header().unwrap().header(), orphan_blocks[2].header());

// Check that B2 was removed from the block orphans and A2 has been orphaned.
assert!(store.fetch_orphan(*orphan_blocks[2].hash()).is_err());
assert!(store.fetch_orphan(*blocks[2].hash()).is_ok());
assert_eq!(store.get_chain_metadata().unwrap().height_of_longest_chain(), 2);

// Block B3
let txs = vec![
txn_schema!(from: vec![orphan_outputs[2][0].clone()], to: vec![3 * T]),
txn_schema!(from: vec![orphan_outputs[2][1].clone()], to: vec![3 * T]),
txn_schema!(from: vec![orphan_outputs[2][2].clone()], to: vec![3 * T]),
txn_schema!(from: vec![orphan_outputs[2][3].clone()], to: vec![3 * T]),
txn_schema!(from: vec![orphan_outputs[2][4].clone()], to: vec![3 * T]),
txn_schema!(from: vec![orphan_outputs[2][5].clone()], to: vec![3 * T]),
];
assert!(generate_new_block_with_achieved_difficulty(
&mut orphan_store,
&mut orphan_blocks,
&mut orphan_outputs,
txs,
Difficulty::from(1),
&consensus_manager
)
.is_ok());

if let Ok(BlockAddResult::Ok { .. }) = store.add_block(orphan_blocks[3].to_arc_block()) {
} else {
panic!();
}
// Block B4
let txs = vec![
txn_schema!(from: vec![orphan_outputs[3][0].clone()], to: vec![1500000 * uT]),
txn_schema!(from: vec![orphan_outputs[3][1].clone()], to: vec![1500000 * uT]),
];
assert!(generate_new_block_with_achieved_difficulty(
&mut orphan_store,
&mut orphan_blocks,
&mut orphan_outputs,
txs,
Difficulty::from(1),
&consensus_manager
)
.is_ok());

if let Ok(BlockAddResult::Ok { .. }) = store.add_block(orphan_blocks[4].to_arc_block()) {
} else {
panic!();
}

// Block B5
let txs = vec![
txn_schema!(from: vec![orphan_outputs[4][0].clone()], to: vec![50000 * uT]),
txn_schema!(from: vec![orphan_outputs[4][1].clone()], to: vec![50000 * uT]),
];
assert!(generate_new_block_with_achieved_difficulty(
&mut orphan_store,
&mut orphan_blocks,
&mut orphan_outputs,
txs,
Difficulty::from(1),
&consensus_manager
)
.is_ok());

if let Ok(BlockAddResult::Ok { .. }) = store.add_block(orphan_blocks[5].to_arc_block()) {
} else {
panic!();
}
assert_eq!(store.get_chain_metadata().unwrap().height_of_longest_chain(), 5);
}
#[test]
fn test_handle_tip_reorg() {
// GB --> A1 --> A2(Low PoW) [Main Chain]
Expand Down

0 comments on commit 2abb58d

Please sign in to comment.