Skip to content

Commit

Permalink
Merge branch 'development' into ho_relax_comms_limits
Browse files Browse the repository at this point in the history
  • Loading branch information
aviator-app[bot] authored Aug 20, 2021
2 parents e59e615 + f040427 commit 217ee98
Show file tree
Hide file tree
Showing 21 changed files with 1,229 additions and 300 deletions.
71 changes: 42 additions & 29 deletions base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,29 +744,63 @@ impl LMDBDatabase {
"block_accumulated_data_db",
)?;

let output_rows =
lmdb_delete_keys_starting_with::<TransactionOutputRowData>(&write_txn, &self.utxos_db, &hash_hex)?;
self.delete_block_inputs_outputs(write_txn, &hash_hex)?;
self.delete_block_kernels(write_txn, &hash_hex)?;

Ok(())
}

fn delete_block_inputs_outputs(&self, txn: &WriteTransaction<'_>, hash: &str) -> Result<(), ChainStorageError> {
let output_rows = lmdb_delete_keys_starting_with::<TransactionOutputRowData>(txn, &self.utxos_db, hash)?;
debug!(target: LOG_TARGET, "Deleted {} outputs...", output_rows.len());
let inputs = lmdb_delete_keys_starting_with::<TransactionInputRowData>(txn, &self.inputs_db, hash)?;
debug!(target: LOG_TARGET, "Deleted {} input(s)...", inputs.len());

for utxo in &output_rows {
trace!(target: LOG_TARGET, "Deleting UTXO `{}`", to_hex(&utxo.hash));
lmdb_delete(
&write_txn,
txn,
&self.txos_hash_to_index_db,
utxo.hash.as_slice(),
"txos_hash_to_index_db",
)?;
if let Some(ref output) = utxo.output {
let output_hash = output.hash();
// if an output was already spent in the block, it was never created as unspent, so dont delete it as it
// does not exist here
if inputs.iter().any(|r| r.input.output_hash() == output_hash) {
continue;
}
lmdb_delete(
&write_txn,
txn,
&*self.utxo_commitment_index,
output.commitment.as_bytes(),
"utxo_commitment_index",
)?;
}
}
let kernels =
lmdb_delete_keys_starting_with::<TransactionKernelRowData>(&write_txn, &self.kernels_db, &hash_hex)?;
// Move inputs in this block back into the unspent set, any outputs spent within this block they will be removed
// by deleting all the block's outputs below
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();
if output_rows.iter().any(|r| r.hash == output_hash) {
continue;
}
trace!(target: LOG_TARGET, "Input moved to UTXO set: {}", row.input);
lmdb_insert(
txn,
&*self.utxo_commitment_index,
row.input.commitment.as_bytes(),
&row.input.output_hash(),
"utxo_commitment_index",
)?;
}
Ok(())
}

fn delete_block_kernels(&self, txn: &WriteTransaction<'_>, hash: &str) -> Result<(), ChainStorageError> {
let kernels = lmdb_delete_keys_starting_with::<TransactionKernelRowData>(txn, &self.kernels_db, hash)?;
debug!(target: LOG_TARGET, "Deleted {} kernels...", kernels.len());
for kernel in kernels {
trace!(
Expand All @@ -775,7 +809,7 @@ impl LMDBDatabase {
kernel.kernel.excess.to_hex()
);
lmdb_delete(
&write_txn,
txn,
&self.kernel_excess_index,
kernel.kernel.excess.as_bytes(),
"kernel_excess_index",
Expand All @@ -789,33 +823,12 @@ impl LMDBDatabase {
to_hex(&excess_sig_key)
);
lmdb_delete(
&write_txn,
txn,
&self.kernel_excess_sig_index,
excess_sig_key.as_slice(),
"kernel_excess_sig_index",
)?;
}

let inputs = lmdb_delete_keys_starting_with::<TransactionInputRowData>(&write_txn, &self.inputs_db, &hash_hex)?;
debug!(target: LOG_TARGET, "Deleted {} input(s)...", inputs.len());
// Move inputs in this block back into the unspent set, any outputs spent within this block they will be removed
// by deleting all the block's outputs below
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();
if output_rows.iter().any(|r| r.hash == output_hash) {
continue;
}
trace!(target: LOG_TARGET, "Input moved to UTXO set: {}", row.input);
lmdb_insert(
&write_txn,
&*self.utxo_commitment_index,
row.input.commitment.as_bytes(),
&row.input.output_hash(),
"utxo_commitment_index",
)?;
}

Ok(())
}

Expand Down
14 changes: 13 additions & 1 deletion integration_tests/features/Mempool.feature
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,16 @@ Feature: Mempool
When I submit transaction TX3 to BN1
When I submit transaction TX4 to BN1
When I submit transaction TX5 to BN1
Then I wait until base node BN1 has 5 unconfirmed transactions in its mempool
Then I wait until base node BN1 has 5 unconfirmed transactions in its mempool

@critical
Scenario: Mempool unconfirmed transaction to mined transaction
Given I have 1 seed nodes
And I have a base node BN1 connected to all seed nodes
When I mine a block on BN1 with coinbase CB1
When I mine 2 blocks on BN1
When I create a custom fee transaction TX1 spending CB1 to UTX1 with fee 80
When I submit transaction TX1 to BN1
Then I wait until base node BN1 has 1 unconfirmed transactions in its mempool
When I mine 1 blocks on BN1
Then I wait until base node BN1 has 0 unconfirmed transactions in its mempool
43 changes: 43 additions & 0 deletions integration_tests/features/Reorgs.feature
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,49 @@ Feature: Reorgs
When I submit transaction TX2 to PNODE1
Then PNODE1 has TX2 in MEMPOOL state

@critical @reorg
Scenario: Zero-conf reorg with spending
Given I have a base node NODE1 connected to all seed nodes
Given I have a base node NODE2 connected to node NODE1
When I mine 14 blocks on NODE1
When I mine a block on NODE1 with coinbase CB1
When I mine 4 blocks on NODE1
When I create a custom fee transaction TX1 spending CB1 to UTX1 with fee 100
When I create a custom fee transaction TX11 spending UTX1 to UTX11 with fee 100
When I submit transaction TX1 to NODE1
When I submit transaction TX11 to NODE1
When I mine 1 blocks on NODE1
Then NODE1 has TX1 in MINED state
And NODE1 has TX11 in MINED state
And all nodes are at height 20
And I stop node NODE1
And node NODE2 is at height 20
When I mine a block on NODE2 with coinbase CB2
When I mine 3 blocks on NODE2
When I create a custom fee transaction TX2 spending CB2 to UTX2 with fee 100
When I create a custom fee transaction TX21 spending UTX2 to UTX21 with fee 100
When I submit transaction TX2 to NODE2
When I submit transaction TX21 to NODE2
When I mine 1 blocks on NODE2
Then node NODE2 is at height 25
And NODE2 has TX2 in MINED state
And NODE2 has TX21 in MINED state
And I stop node NODE2
When I start base node NODE1
And node NODE1 is at height 20
When I mine a block on NODE1 with coinbase CB3
When I mine 3 blocks on NODE1
When I create a custom fee transaction TX3 spending CB3 to UTX3 with fee 100
When I create a custom fee transaction TX31 spending UTX3 to UTX31 with fee 100
When I submit transaction TX3 to NODE1
When I submit transaction TX31 to NODE1
When I mine 1 blocks on NODE1
Then NODE1 has TX3 in MINED state
And NODE1 has TX31 in MINED state
And node NODE1 is at height 25
When I start base node NODE2
Then all nodes are on the same chain tip

Scenario Outline: Massive multiple reorg
#
# Chain 1a:
Expand Down
59 changes: 58 additions & 1 deletion integration_tests/features/WalletFFI.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,22 @@ Feature: Wallet FFI
Scenario: As a client I want to receive Tari via my Public Key while I am online
# It's a subtest of "As a client I want to retrieve a list of transactions I have made and received"

@long-running @broken
Scenario: As a client I want to receive Tari via my Public Key sent while I am offline when I come back online
Given I have a base node BASE
And I have wallet SENDER connected to base node BASE
And I have mining node MINER connected to base node BASE and wallet SENDER
And mining node MINER mines 4 blocks
Then I wait for wallet SENDER to have at least 1000000 uT
And I have a ffi wallet FFI_WALLET connected to base node BASE
And I stop wallet FFI_WALLET
And I wait 5 seconds
And I send 2000000 uT from wallet SENDER to wallet FFI_WALLET at fee 100
And I wait 5 seconds
And I start wallet FFI_WALLET
And wallet SENDER detects all transactions are at least Broadcast
And mining node MINER mines 10 blocks
Then I wait for ffi wallet FFI_WALLET to have at least 1000000 uT

@long-running
Scenario: As a client I want to retrieve a list of transactions I have made and received
Expand All @@ -24,12 +39,16 @@ Feature: Wallet FFI
And wallet SENDER detects all transactions are at least Broadcast
And mining node MINER mines 10 blocks
Then I wait for ffi wallet FFI_WALLET to have at least 1000000 uT
And Check callbacks for finished inbound tx on ffi wallet FFI_WALLET
And I have wallet RECEIVER connected to base node BASE
And I send 1000000 uT from ffi wallet FFI_WALLET to wallet RECEIVER at fee 100
And ffi wallet FFI_WALLET has 1 broadcast transaction
And mining node MINER mines 4 blocks
Then I wait for wallet RECEIVER to have at least 1000000 uT
And Check callbacks for finished outbound tx on ffi wallet FFI_WALLET
And I have 1 received and 1 send transaction in ffi wallet FFI_WALLET
And I start STXO validation on wallet FFI_WALLET
And I start UTXO validation on wallet FFI_WALLET

# It's just calling the encrypt function, we don't test if it's actually encrypted
Scenario: As a client I want to be able to protect my wallet with a passphrase
Expand All @@ -47,6 +66,15 @@ Feature: Wallet FFI
Then I don't have contact with alias ALIAS in ffi wallet FFI_WALLET

Scenario: As a client I want to set the base node (should be persisted)
Given I have a base node BASE1
Given I have a base node BASE2
And I have a ffi wallet FFI_WALLET connected to base node BASE1
And I set base node BASE2 for ffi wallet FFI_WALLET
Then BASE2 is connected to FFI_WALLET
And I stop wallet FFI_WALLET
And I wait 5 seconds
And I start wallet FFI_WALLET
Then BASE2 is connected to FFI_WALLET

Scenario: As a client I want to see my public_key, emoji ID, address (whoami)
Given I have a base node BASE
Expand All @@ -57,16 +85,45 @@ Feature: Wallet FFI
Scenario: As a client I want to get my balance
# It's a subtest of "As a client I want to retrieve a list of transactions I have made and received"

@long-running
Scenario: As a client I want to cancel a transaction
Given I have a base node BASE
And I have wallet SENDER connected to base node BASE
And I have mining node MINER connected to base node BASE and wallet SENDER
And mining node MINER mines 4 blocks
Then I wait for wallet SENDER to have at least 1000000 uT
And I have a ffi wallet FFI_WALLET connected to base node BASE
And I send 2000000 uT from wallet SENDER to wallet FFI_WALLET at fee 100
And wallet SENDER detects all transactions are at least Broadcast
And mining node MINER mines 10 blocks
Then I wait for ffi wallet FFI_WALLET to have at least 1000000 uT
And I have wallet RECEIVER connected to base node BASE
And I stop wallet RECEIVER
And I send 1000000 uT from ffi wallet FFI_WALLET to wallet RECEIVER at fee 100
Then I wait for ffi wallet FFI_WALLET to have 1 pending outbound transaction
Then I cancel all transactions on ffi wallet FFI_WALLET and it will cancel 1 transaction

@long-running
Scenario: As a client I want to be able to restore my wallet from seed words
Given I have a base node BASE
And I have wallet WALLET connected to base node BASE
And I have mining node MINER connected to base node BASE and wallet WALLET
And mining node MINER mines 4 blocks
Then I wait for wallet WALLET to have at least 1000000 uT
Then I recover wallet WALLET into ffi wallet FFI_WALLET from seed words on node BASE
And I wait for recovery of wallet FFI_WALLET to finish
And I wait for ffi wallet FFI_WALLET to have at least 1000000 uT

Scenario: AS a client I want to be able to initiate TXO and TX validation with the specifed base node.
Scenario: As a client I want to be able to initiate TXO and TX validation with the specifed base node.
# It's a subtest of "As a client I want to retrieve a list of transactions I have made and received"

Scenario: As a client I want async feedback about the progress of sending and receiving a transaction
# It's a subtest of "As a client I want to retrieve a list of transactions I have made and received"

Scenario: As a client I want async feedback about my connection status to the specifed Base Node

Scenario: As a client I want async feedback about the wallet restoration process
# As a client I want to be able to restore my wallet from seed words

Scenario: As a client I want async feedback about TXO and TX validation processes
# It's a subtest of "As a client I want to retrieve a list of transactions I have made and received"
Loading

0 comments on commit 217ee98

Please sign in to comment.