diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs
index 0e67e648..f6239a48 100644
--- a/core/src/core/transaction.rs
+++ b/core/src/core/transaction.rs
@@ -31,7 +31,6 @@ use crate::{consensus, global};
use enum_primitive::FromPrimitive;
use std::cmp::Ordering;
use std::cmp::{max, min};
-use std::collections::HashSet;
use std::sync::Arc;
use std::{error, fmt};
@@ -647,14 +646,21 @@ impl TransactionBody {
}
// Verify that no input is spending an output from the same block.
+ // Assumes inputs and outputs are sorted
fn verify_cut_through(&self) -> Result<(), Error> {
- let mut out_set = HashSet::new();
- for out in &self.outputs {
- out_set.insert(out.commitment());
- }
- for inp in &self.inputs {
- if out_set.contains(&inp.commitment()) {
- return Err(Error::CutThrough);
+ let mut inputs = self.inputs.iter().map(|x| x.hash()).peekable();
+ let mut outputs = self.outputs.iter().map(|x| x.hash()).peekable();
+ while let (Some(ih), Some(oh)) = (inputs.peek(), outputs.peek()) {
+ match ih.cmp(oh) {
+ Ordering::Less => {
+ inputs.next();
+ }
+ Ordering::Greater => {
+ outputs.next();
+ }
+ Ordering::Equal => {
+ return Err(Error::CutThrough);
+ }
}
}
Ok(())
@@ -968,24 +974,34 @@ impl Transaction {
/// and outputs.
pub fn cut_through(inputs: &mut Vec, outputs: &mut Vec