Why does bitcore-lib not decode my bitcoin transaction hex correctly?

1.6k views Asked by At

I am using bitcore-lib to decode transactions encoded in hexadecimal, but I'm getting a weird result. For comparison, I've used bitcoinjs-lib and it seems to be working just fine.

Example

Transaction

Network: bitcoin testnet

Hash: 1eadc4a09c6abc8f024f04031334941ee455cd4fb112850788214da5f631a3d5

Transaction hex:

01000000000101a0bc55f51d3da3c30b0e92cd37effff17264c3d89057e1e041644606d2a703b5010000001716001482681fa5f944a92d53deacb38850ebba2dd44d44ffffffff0240d2df03000000001976a9147ab6ee8c168f32077c1cc83facb49a91d7ee5dae88aca5a2ecae0800000017a914ca21182b9eca3c99175dd89ce548b72db3244db08702483045022100d4485d23e5d0d3d14a40f0fa9c404f24d55d3db77091bbfb96232610e6b3a5220220712e7736a4229ade64a69e712e842f0a3020cf8209b5f2641114c39a4e9a669201210236443d966162716f76a632e487db80511ce795b68e192e9890bc435ca3e50c1f00000000

Try the hex code here: https://live.blockcypher.com/btc/decodetx/

Snippet:

const bitcore = require('bitcore-lib')
const bitcoinjs = require('bitcoinjs-lib')

const TX_HEX = '01000000000101a0bc55f51d3da3c30b0e92cd37effff17264c3d89057e1e041644606d2a703b5010000001716001482681fa5f944a92d53deacb38850ebba2dd44d44ffffffff0240d2df03000000001976a9147ab6ee8c168f32077c1cc83facb49a91d7ee5dae88aca5a2ecae0800000017a914ca21182b9eca3c99175dd89ce548b72db3244db08702483045022100d4485d23e5d0d3d14a40f0fa9c404f24d55d3db77091bbfb96232610e6b3a5220220712e7736a4229ade64a69e712e842f0a3020cf8209b5f2641114c39a4e9a669201210236443d966162716f76a632e487db80511ce795b68e192e9890bc435ca3e50c1f00000000'

const bitcoreTx = new bitcore.Transaction(Buffer.from(TX_HEX, 'hex'))
const bitcoinjsTx = bitcoinjs.Transaction.fromHex(Buffer.from(TX_HEX, 'hex'))

console.log(bitcoreTx.toJSON())
console.log(bitcoinjsTx)

Results

bitcore (incorrect)

{ hash: '5f10810f9c514ab3f69b940c3dd7163af2f3a993a84e0e782fa5c39f5d0667a8',
  version: 1,
  inputs: [],
  outputs: 
   [ { satoshis: 11762590741304222000,
       script: '0b0e92cd37effff17264c3d89057e1e041644606d2a703b5010000001716001482681fa5f944a92d53deacb38850ebba2dd44d44ffffffff0240d2df03000000001976a9147ab6ee8c168f32077c1cc83facb49a91d7ee5dae88aca5a2ecae0800000017a914ca21182b9eca3c99175dd89ce548b72db3244db08702483045022100d4485d23e5d0d3d14a40f0fa9c404f24d55d3db77091bbfb96232610e6b3a5220220712e7736a4229ade64a69e712e842f0a3020cf8209b5f2641114c39a4e9a66' } ],
  nLockTime: 35717522 }

bitcoinjs (correct)

Transaction {
  version: 1,
  locktime: 0,
  ins: 
   [ { hash: <Buffer a0 bc 55 f5 1d 3d a3 c3 0b 0e 92 cd 37 ef ff f1 72 64 c3 d8 90 57 e1 e0 41 64 46 06 d2 a7 03 b5>,
       index: 1,
       script: <Buffer 16 00 14 82 68 1f a5 f9 44 a9 2d 53 de ac b3 88 50 eb ba 2d d4 4d 44>,
       sequence: 4294967295,
       witness: [Array] } ],
  outs: 
   [ { value: 65000000,
       script: <Buffer 76 a9 14 7a b6 ee 8c 16 8f 32 07 7c 1c c8 3f ac b4 9a 91 d7 ee 5d ae 88 ac> },
     { value: 37294482085,
       script: <Buffer a9 14 ca 21 18 2b 9e ca 3c 99 17 5d d8 9c e5 48 b7 2d b3 24 4d b0 87> } ] }
2

There are 2 answers

1
max-lt On BEST ANSWER

Your transaction is a segwit* transaction and bitcorejs does not support it.

From reddit:

SegWit input scriptSigs will have one of these patterns:

  • 0x160014<20 bytes> (P2WPKH)
  • 0x220020<32 bytes> (P2WSH)

A great alternative to bitcorejs in my opinion is bcoin: it have the same capabilities (running a full node) plus segwit support and it has a similar architecture so it's easy to migrate to it from bitcore.

0
coolaj86 On

I'm posting this here because this is where I landed from my search for decoding a script and an address.

Decode a "normal" Script

A normal transaction output "script" looks like this:

76a9141a2e668007a28dbecb420a8e9ce8cdd1651f213d88ac

When you break that down, you get this:

76 a9 14 1a2e668007a28dbecb420a8e9ce8cdd1651f213d 88 ac
0x76 (118) OP_DUP
0x19  (25) OP_HASH160

0x14  (20) is the length of the pubKeyHash (20 bytes)
...        P2PKH (the pubKeyHash)

0x88 (136) OP_EQUALVERIFY
0xac (172) OP_CHECKSIG

Bad Address?

The P2PKH address is only part of the address as you probably intend to use it.

You probably want a Base58Check address, which includes a version prefix byte as well as a 4 check hash bytes at the end.

For example:

4c 1a2e668007a28dbecb420a8e9ce8cdd1651f213d 6496ad2a

If you then use the BaseX Base58 encoding you'll get back the friendly address you're familiar with:

Xd5GzCN6mp77BeVEe6FrgqQt8MA1ge4Fsw