Skip to content

Verbose blockchain.transaction.get response disagrees with peer Electrum implementations in 4 fields #778

@echennells

Description

@echennells

Summary

blockchain.transaction.get with verbose=true returns a response that disagrees with Fulcrum and electrs (other Electrum-protocol implementations) in the following fields:

Field bs returns Fulcrum / electrs return
top-level hash (witness txs) "0000...0000" wtxid (sha256d of full witness-included serialization)
top-level size (witness txs) stripped serialization length full witness-included length
vout[i].scriptPubKey.type "nonstandard" for standard outputs "pubkeyhash", "scripthash", "witness_v0_keyhash", "nulldata", etc.
vout[i].scriptPubKey.address (missing) base58check / bech32 / bech32m string
vout[i].scriptPubKey.asm lowercase opcodes, bracketed push data uppercase opcodes, space-separated push data
vout[i].scriptPubKey.addresses array containing the Electrum scripthash (omitted)

The Electrum protocol spec for this method specifies the verbose response as "whatever bitcoind returns when asked for a verbose form of the raw transaction" (spesmilo/electrum-protocol/docs/protocol-methods.rst). Fulcrum and electrs both follow this.

Code path: src/protocols/electrum/protocol_electrum_transactions.cpp:218 calls value_from(bitcoind(*tx)), the JSON builder where the deviations originate.

Reproduction

Tested against bs running mainnet and testnet3 (libbitcoin-server head 1c3908c8).

Testnet3 tx 09afbaf60152b867782f35a202b935b6a20362e68812bd31fbaf6859939c200b at h=1,000,000 (witness-bearing coinbase with a P2PKH output).

Top-level diff:

Field bs Fulcrum / electrs
hash 0000000000000000000000000000000000000000000000000000000000000000 461091484b8fb4f9e8a9fe7e23b8a4b1fcfd26e1ec3f318c38501f278c374bb9
size 176 212
vsize 176 212
weight 740 848
txid 09afbaf6...0b (agree) 09afbaf6...0b

bs vout[0] (P2PKH output for script 76a914d427a9318bc60db2766f9b02b7bbd470b78fa7a488ac):

{
    "value": 3.125,
    "n": 0,
    "scriptPubKey": {
        "asm": "dup hash160 [d427a9318bc60db2766f9b02b7bbd470b78fa7a4] equalverify checksig",
        "hex": "76a914d427a9318bc60db2766f9b02b7bbd470b78fa7a488ac",
        "type": "nonstandard",
        "addresses": ["3fa0b7dc3bb7737a9ccb170df1d1d6a4f32f290b18d92826f3dfe77cbe2dd033"]
    }
}

Fulcrum / electrs vout[0] for the same script:

{
    "value": 3.125,
    "n": 0,
    "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 d427a9318bc60db2766f9b02b7bbd470b78fa7a4 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914d427a9318bc60db2766f9b02b7bbd470b78fa7a488ac",
        "type": "pubkeyhash",
        "address": "mzrj4QmPhk98vc2yQw42uCsgwfBjVzPPLM"
    }
}

The 64-character hex string in bs's addresses field is the Electrum scripthash of the output script (reverse(sha256(scriptPubKey))):

script bytes:    76a914d427a9318bc60db2766f9b02b7bbd470b78fa7a488ac
sha256(script):  33d02dbe7ce7dff32628d9180b292ff3a4d6d1f10d17cb9c7a73b73bdcb7a03f
reversed:        3fa0b7dc3bb7737a9ccb170df1d1d6a4f32f290b18d92826f3dfe77cbe2dd033

The Electrum scripthash is the key used in blockchain.scripthash.* methods; bs is emitting it in place of a base58check / bech32 / bech32m address.

Same shape reproduces on mainnet bs against block 800000's coinbase (b75ca3106ed100521aa50e3ec267a06431c6319538898b25e1b757a5736f5fb4).

Wallet consumer compatibility

Two real-world wallets consume the verbose response with typed deserializers:

Trezor Suite (packages/blockchain-link/src/workers/electrum/utils/transaction.ts) requests blockchain.transaction.get(txid, true) for every transaction in the wallet's history. Its parseAddresses function falls back to the addresses array when address is missing and the type !== 'nulldata' branch is not taken. Against bs's response, Trezor displays the Electrum scripthash in the address column for each output.

Sparrow Wallet (net/VerboseTransaction.java) reads nine top-level fields (blockhash, blocktime, confirmations, hash, hex, locktime, size, txid, version) and decodes the raw hex locally for vout rendering. Against bs's response, Sparrow stores 0000...0000 as the tx hash for witness-bearing transactions and uses stripped serialization size for fee-rate display.

Electrum (spesmilo/electrum) sends only the non-verbose form of blockchain.transaction.get, so it is unaffected.

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions