Skip to content

deserialize for Transaction Err if there are no transaction inputs #104

@D4nte

Description

@D4nte

Hi!

Took me some time to understand why I had the issue. I have not yet investigated in rust-bitcoin code to understand the issue/propose a fix yet.

Raw transactions which do not include inputs are not properly handled.
This test fails on latest rust-bitcoin/master

#[test]
fn test_transaction_no_vin() {
    let hex_tx = hex_bytes("02000000000100ca9a3b00000000160014716f8e8fa281cb42bb6900ce35b73a13fa3e66e000000000").unwrap();
    let tx: Result<Transaction, _> = deserialize(&hex_tx);
    assert!(tx.is_ok());
}

If you replace the assert with tx.unwrap() you would get the following stack:

thread 'blockdata::transaction::tests::test_transaction_no_vin' panicked at 'called `Result::unwrap()` on an `Err` value: ByteOrder(Custom { kind: UnexpectedEof, error: StringError("failed to fill whole buffer") })', libcore/result.rs:945:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: <std::panicking::begin_panic::PanicPayload<A> as core::panic::BoxMeUp>::get
             at libstd/panicking.rs:463
   5: std::panicking::try::do_call
             at libstd/panicking.rs:350
   6: std::panicking::try::do_call
             at libstd/panicking.rs:328
   7: <&'a T as core::fmt::Display>::fmt
             at libcore/panicking.rs:71
   8: core::result::unwrap_failed
             at /Users/travis/build/rust-lang/rust/src/libcore/macros.rs:26
   9: <core::result::Result<T, E>>::unwrap
             at /Users/travis/build/rust-lang/rust/src/libcore/result.rs:782
  10: bitcoin::blockdata::transaction::tests::test_transaction_no_vin
             at src/blockdata/transaction.rs:934
  11: bitcoin::__test::TESTS::{{closure}}
             at src/blockdata/transaction.rs:931
  12: core::ops::function::FnOnce::call_once
             at /Users/travis/build/rust-lang/rust/src/libcore/ops/function.rs:223
  13: <F as alloc::boxed::FnBox<A>>::call_box
             at libtest/lib.rs:1451
             at /Users/travis/build/rust-lang/rust/src/libcore/ops/function.rs:223
             at /Users/travis/build/rust-lang/rust/src/liballoc/boxed.rs:638
  14: panic_unwind::dwarf::eh::read_encoded_pointer
             at libpanic_unwind/lib.rs:105
test blockdata::transaction::tests::test_transaction_no_vin ... FAILED

Please note that bitcoind is able to decode the said transaction:
Request

{
    "jsonrpc": "1.0", 
    "id":"curltest", 
    "method": "decoderawtransaction", 
    "params": 
["02000000000100ca9a3b00000000160014716f8e8fa281cb42bb6900ce35b73a13fa3e66e000000000"
    ]
    
}

Response

{
    "result": {
        "txid": "e8069d1704d4d194f3fd6c85081851a8bc093a9f03da1be75065b961ddee1572",
        "hash": "e8069d1704d4d194f3fd6c85081851a8bc093a9f03da1be75065b961ddee1572",
        "version": 2,
        "size": 41,
        "vsize": 41,
        "locktime": 0,
        "vin": [],
        "vout": [
            {
                "value": 10,
                "n": 0,
                "scriptPubKey": {
                    "asm": "0 716f8e8fa281cb42bb6900ce35b73a13fa3e66e0",
                    "hex": "0014716f8e8fa281cb42bb6900ce35b73a13fa3e66e0",
                    "reqSigs": 1,
                    "type": "witness_v0_keyhash",
                    "addresses": [
                        "tb1qw9hcarazs8959wmfqr8rtde6z0aruehqt6m3m7"
                    ]
                }
            }
        ]
    },
    "error": null,
    "id": "curltest"
}

Looking at struct Transaction it does not look like input must be present so at this stage I am thinking about a bug in the deserialize function.

2 proposed way forward:

  1. Support transaction without inputs
  2. Improve the failure message to make it easier to debug

Let me know how you would prefer to move forward and I may be able to look into a patch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions