fix: ignore duplicate consumed inputs (#257)

This commit is contained in:
Harper 2023-05-12 13:01:44 +01:00 committed by GitHub
parent ef9dbfad64
commit 36df92f8ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 4 deletions

View file

@ -138,6 +138,36 @@ mod tests {
}
}
#[test]
fn test_duplicate_consumed_inputs() {
let tx_bytecode_hex = include_str!("../../test_data/duplicateinput.tx");
let bytecode = hex::decode(tx_bytecode_hex).unwrap();
let tx = MultiEraTx::decode(Era::Alonzo, &bytecode).unwrap();
let expected_inputs = vec![
"4d9cb6bf1c2e349f1bcd454a632d2b721d5badcf687220430c316588f39506ab#1",
"4d9cb6bf1c2e349f1bcd454a632d2b721d5badcf687220430c316588f39506ab#1",
];
let inputs: Vec<String> = tx
.inputs()
.into_iter()
.map(|x| x.output_ref().to_string())
.collect();
let expected_consumed =
vec!["4d9cb6bf1c2e349f1bcd454a632d2b721d5badcf687220430c316588f39506ab#1"];
let consumed: Vec<String> = tx
.consumes()
.into_iter()
.map(|x| x.output_ref().to_string())
.collect();
assert_eq!(inputs, expected_inputs);
assert_eq!(consumed, expected_consumed);
}
#[test]
fn test_utxo_ref_parsing() {
let valid_vectors = [

View file

@ -135,7 +135,7 @@ pub enum MultiEraSigners<'b> {
AlonzoCompatible(&'b alonzo::RequiredSigners),
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct OutputRef(Hash<32>, u64);
#[derive(Debug, Error)]

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, ops::Deref};
use std::{borrow::Cow, collections::HashSet, ops::Deref};
use pallas_codec::{minicbor, utils::KeepRaw};
use pallas_crypto::hash::Hash;
@ -114,6 +114,10 @@ impl<'b> MultiEraTx<'b> {
}
}
/// Return the transaction inputs
///
/// NOTE: It is possible for this to return duplicates. See
/// https://github.com/input-output-hk/cardano-ledger/commit/a342b74f5db3d3a75eae3e2abe358a169701b1e7
pub fn inputs(&self) -> Vec<MultiEraInput> {
match self {
MultiEraTx::AlonzoCompatible(x, _) => x
@ -137,6 +141,10 @@ impl<'b> MultiEraTx<'b> {
}
}
/// Return the transaction reference inputs
///
/// NOTE: It is possible for this to return duplicates. See
/// https://github.com/input-output-hk/cardano-ledger/commit/a342b74f5db3d3a75eae3e2abe358a169701b1e7
pub fn reference_inputs(&self) -> Vec<MultiEraInput> {
match self {
MultiEraTx::Babbage(x) => x
@ -192,6 +200,10 @@ impl<'b> MultiEraTx<'b> {
}
}
/// Return the transaction collateral inputs
///
/// NOTE: It is possible for this to return duplicates. See
/// https://github.com/input-output-hk/cardano-ledger/commit/a342b74f5db3d3a75eae3e2abe358a169701b1e7
pub fn collateral(&self) -> Vec<MultiEraInput> {
match self {
MultiEraTx::AlonzoCompatible(x, _) => x
@ -230,10 +242,17 @@ impl<'b> MultiEraTx<'b> {
/// will return the list of inputs. If the tx is invalid, it will return the
/// collateral.
pub fn consumes(&self) -> Vec<MultiEraInput> {
match self.is_valid() {
let consumed = match self.is_valid() {
true => self.inputs(),
false => self.collateral(),
}
};
let mut unique_consumed = HashSet::new();
consumed
.into_iter()
.filter(|i| unique_consumed.insert(i.output_ref()))
.collect()
}
/// Returns a list of tuples of the outputs produced by the Tx with their

View file

@ -0,0 +1 @@
84a400828258204d9cb6bf1c2e349f1bcd454a632d2b721d5badcf687220430c316588f39506ab018258204d9cb6bf1c2e349f1bcd454a632d2b721d5badcf687220430c316588f39506ab010182825839018b038a44ef966d2140c923636cea9a2a5a5db4a003c75773d95b3a2562afd01de43f13aadf7a78b27a1b836603906002ebef9963f90fc8ff1a00493e0082583901e25497038dd6d9413e3e43bbe14730130856a2a5b5e08643fc7be1cb62afd01de43f13aadf7a78b27a1b836603906002ebef9963f90fc8ff1a00eaa588021a000f4240031a033dd1fca10081825820565ede44b1980b00a8d02e09887491cb873d691f675a8715e4a0a101154872b958404164058a3e2f5ce9a2582dc8eed0259d29a7cc3bb0ab3d38d1ca219c9a5a5e32a32f798dc59ad680c53e59b04cc60a688b90c30535c93dfae38561da639d710af5f6