diff --git a/zebra-state/src/arbitrary.rs b/zebra-state/src/arbitrary.rs index f151e2c41..2a8eaa5ea 100644 --- a/zebra-state/src/arbitrary.rs +++ b/zebra-state/src/arbitrary.rs @@ -183,7 +183,8 @@ impl CheckpointVerifiedBlock { height: block::Height, ) -> Self { let transaction_hashes: Arc<[_]> = block.transactions.iter().map(|tx| tx.hash()).collect(); - let new_outputs = transparent::new_outputs_with_height(&block, height, &transaction_hashes); + let new_outputs = + transparent::new_ordered_outputs_with_height(&block, height, &transaction_hashes); Self { block, diff --git a/zebra-state/src/request.rs b/zebra-state/src/request.rs index 6ffa7d3e0..dbff91022 100644 --- a/zebra-state/src/request.rs +++ b/zebra-state/src/request.rs @@ -235,7 +235,7 @@ pub struct CheckpointVerifiedBlock { /// earlier transaction. /// /// This field can also contain unrelated outputs, which are ignored. - pub(crate) new_outputs: HashMap, + pub(crate) new_outputs: HashMap, /// A precomputed list of the hashes of the transactions in this block, /// in the same order as `block.transactions`. pub transaction_hashes: Arc<[transaction::Hash]>, @@ -369,7 +369,7 @@ impl CheckpointVerifiedBlock { .coinbase_height() .expect("coinbase height was already checked"); let transaction_hashes: Arc<[_]> = block.transactions.iter().map(|tx| tx.hash()).collect(); - let new_outputs = transparent::new_outputs(&block, &transaction_hashes); + let new_outputs = transparent::new_ordered_outputs(&block, &transaction_hashes); Self { block, @@ -405,7 +405,7 @@ impl From for CheckpointVerifiedBlock { block, hash, height, - new_outputs: utxos_from_ordered_utxos(new_outputs), + new_outputs, transaction_hashes, } } diff --git a/zebra-state/src/service.rs b/zebra-state/src/service.rs index 75d1f0ac1..f88cd2811 100644 --- a/zebra-state/src/service.rs +++ b/zebra-state/src/service.rs @@ -976,7 +976,8 @@ impl Service for StateService { // even though it is redundant for most finalized blocks. // (Finalized blocks are verified using block hash checkpoints // and transaction merkle tree block header commitments.) - self.pending_utxos.check_against(&finalized.new_outputs); + self.pending_utxos + .check_against_ordered(&finalized.new_outputs); // # Performance // diff --git a/zebra-state/src/service/finalized_state/zebra_db/block.rs b/zebra-state/src/service/finalized_state/zebra_db/block.rs index 8edc89e02..61e19100a 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/block.rs @@ -305,10 +305,10 @@ impl ZebraDb { let new_outputs_by_out_loc: BTreeMap = finalized .new_outputs .iter() - .map(|(outpoint, utxo)| { + .map(|(outpoint, ordered_utxo)| { ( lookup_out_loc(finalized.height, outpoint, &tx_hash_indexes), - utxo.clone(), + ordered_utxo.utxo.clone(), ) }) .collect(); @@ -331,7 +331,12 @@ impl ZebraDb { }), self.utxo(&outpoint) .map(|ordered_utxo| ordered_utxo.utxo) - .or_else(|| finalized.new_outputs.get(&outpoint).cloned()) + .or_else(|| { + finalized + .new_outputs + .get(&outpoint) + .map(|ordered_utxo| ordered_utxo.utxo.clone()) + }) .expect("already checked UTXO was in state or block"), ) }) @@ -350,7 +355,12 @@ impl ZebraDb { // Get the transparent addresses with changed balances/UTXOs let changed_addresses: HashSet = spent_utxos_by_out_loc .values() - .chain(finalized.new_outputs.values()) + .chain( + finalized + .new_outputs + .values() + .map(|ordered_utxo| &ordered_utxo.utxo), + ) .filter_map(|utxo| utxo.output.address(network)) .unique() .collect(); diff --git a/zebra-state/src/service/pending_utxos.rs b/zebra-state/src/service/pending_utxos.rs index 953aba4a9..c60719825 100644 --- a/zebra-state/src/service/pending_utxos.rs +++ b/zebra-state/src/service/pending_utxos.rs @@ -60,14 +60,6 @@ impl PendingUtxos { } } - /// Check the list of pending UTXO requests against the supplied [`transparent::Utxo`] index. - #[inline] - pub fn check_against(&mut self, utxos: &HashMap) { - for (outpoint, utxo) in utxos.iter() { - self.respond(outpoint, utxo.clone()) - } - } - /// Scan the set of waiting utxo requests for channels where all receivers /// have been dropped and remove the corresponding sender. pub fn prune(&mut self) { diff --git a/zebra-state/src/service/queued_blocks.rs b/zebra-state/src/service/queued_blocks.rs index 7a009605c..41e938122 100644 --- a/zebra-state/src/service/queued_blocks.rs +++ b/zebra-state/src/service/queued_blocks.rs @@ -279,8 +279,9 @@ impl SentHashes { let outpoints = block .new_outputs .iter() - .map(|(outpoint, utxo)| { - self.known_utxos.insert(*outpoint, utxo.clone()); + .map(|(outpoint, ordered_utxo)| { + self.known_utxos + .insert(*outpoint, ordered_utxo.utxo.clone()); outpoint }) .cloned() diff --git a/zebra-state/src/service/tests.rs b/zebra-state/src/service/tests.rs index 5adfaabdf..b7e55b9a9 100644 --- a/zebra-state/src/service/tests.rs +++ b/zebra-state/src/service/tests.rs @@ -419,7 +419,7 @@ proptest! { // the genesis block has a zero-valued transparent output, // which is not included in the UTXO set if block.height > block::Height(0) { - let utxos = &block.new_outputs; + let utxos = &block.new_outputs.iter().map(|(k, ordered_utxo)| (*k, ordered_utxo.utxo.clone())).collect(); let block_value_pool = &block.block.chain_value_pool_change(utxos)?; expected_finalized_value_pool += *block_value_pool; }