diff --git a/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs b/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs index 34496f4501..da2531dbd7 100644 --- a/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs +++ b/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs @@ -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, @@ -608,23 +614,63 @@ impl LMDBDatabase { ) } + fn input_with_output_data( + &self, + txn: &WriteTransaction<'_>, + input: TransactionInput, + ) -> Result { + let input_with_output_data = match input.spent_output { + SpentOutput::OutputData { .. } => input, + 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, + script_signature: input.script_signature, + }, + 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<'_>, height: u64, header_timestamp: u64, header_hash: &HashOutput, - input: &TransactionInput, + 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, @@ -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, @@ -1189,34 +1235,38 @@ 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())?; + for input in inputs { + 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, )?; }