Skip to content

Commit

Permalink
Prevent compact error input
Browse files Browse the repository at this point in the history
Prevented compact error input where a runtime error occurs when commitment
cannot be retrieved form a compact input.
  • Loading branch information
hansieodendaal committed Jan 25, 2024
1 parent 8f56874 commit bf38774
Showing 1 changed file with 62 additions and 12 deletions.
74 changes: 62 additions & 12 deletions base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ use crate::{
consensus::{ConsensusConstants, ConsensusManager},
transactions::{
aggregated_body::AggregateBody,
transaction_components::{TransactionInput, TransactionKernel, TransactionOutput, ValidatorNodeRegistration},
transaction_components::{
SpentOutput,
TransactionInput,
TransactionKernel,
TransactionOutput,
ValidatorNodeRegistration,
},
},
OutputSmt,
PrunedKernelMmr,
Expand Down Expand Up @@ -608,6 +614,45 @@ impl LMDBDatabase {
)
}

fn input_with_output_data(
&self,
txn: &WriteTransaction<'_>,
input: &TransactionInput,
) -> Result<TransactionInput, ChainStorageError> {
let input_with_output_data = match input.spent_output {
SpentOutput::OutputData { .. } => input.clone(),
SpentOutput::OutputHash(output_hash) => match self.fetch_output_in_txn(txn, output_hash.as_slice()) {
Ok(Some(utxo_mined_info)) => TransactionInput {
version: input.version,
spent_output: SpentOutput::create_from_output(utxo_mined_info.output),
input_data: input.input_data.clone(),
script_signature: input.script_signature.clone(),
},
Ok(None) => {
error!(
target: LOG_TARGET,
"Could not retrieve output data from input's output_hash `{}`",
output_hash.to_hex()
);
return Err(ChainStorageError::ValueNotFound {
entity: "UTXO",
field: "hash",
value: output_hash.to_hex(),
});
},
Err(e) => {
error!(
target: LOG_TARGET,
"Could not retrieve output data from input's output_hash `{}` ({})",
output_hash.to_hex(), e
);
return Err(e);
},
},
};
Ok(input_with_output_data)
}

fn insert_input(
&self,
txn: &WriteTransaction<'_>,
Expand All @@ -616,15 +661,16 @@ impl LMDBDatabase {
header_hash: &HashOutput,
input: &TransactionInput,
) -> Result<(), ChainStorageError> {
let input_with_output_data = self.input_with_output_data(txn, input)?;
lmdb_delete(
txn,
&self.utxo_commitment_index,
input.commitment()?.as_bytes(),
input_with_output_data.commitment()?.as_bytes(),
"utxo_commitment_index",
)?;

let hash = input.canonical_hash();
let output_hash = input.output_hash();
let hash = input_with_output_data.canonical_hash();
let output_hash = input_with_output_data.output_hash();
let key = InputKey::new(header_hash, &hash)?;
lmdb_insert(
txn,
Expand All @@ -639,7 +685,7 @@ impl LMDBDatabase {
&self.inputs_db,
&key.convert_to_comp_key(),
&TransactionInputRowDataRef {
input: &input.to_compact(),
input: &input_with_output_data.to_compact(),
header_hash,
spent_timestamp: header_timestamp,
spent_height: height,
Expand Down Expand Up @@ -1190,33 +1236,37 @@ impl LMDBDatabase {

// unique_id_index expects inputs to be inserted before outputs
for input in &inputs {
let smt_key = NodeKey::try_from(input.commitment()?.as_bytes())?;
let input_with_output_data = self.input_with_output_data(txn, input)?;
let smt_key = NodeKey::try_from(input_with_output_data.commitment()?.as_bytes())?;
match output_smt.delete(&smt_key)? {
DeleteResult::Deleted(_value_hash) => {},
DeleteResult::KeyNotFound => return Err(ChainStorageError::UnspendableInput),
};

let features = input.features()?;
let features = input_with_output_data.features()?;
if let Some(vn_reg) = features
.sidechain_feature
.as_ref()
.and_then(|f| f.validator_node_registration())
{
self.validator_node_store(txn)
.delete(header.height, vn_reg.public_key(), input.commitment()?)?;
self.validator_node_store(txn).delete(
header.height,
vn_reg.public_key(),
input_with_output_data.commitment()?,
)?;
}
trace!(
target: LOG_TARGET,
"Inserting input (`{}`, `{}`)",
input.commitment()?.to_hex(),
input.output_hash().to_hex()
input_with_output_data.commitment()?.to_hex(),
input_with_output_data.output_hash().to_hex()
);
self.insert_input(
txn,
current_header_at_height.height,
current_header_at_height.timestamp.as_u64(),
&block_hash,
input,
&input_with_output_data,
)?;
}

Expand Down

0 comments on commit bf38774

Please sign in to comment.