bitcoinjs / bitcoinjs-lib

A javascript Bitcoin library for node.js and browsers.
MIT License
5.68k stars 2.1k forks source link

v6.1.1: Recovering address from Pay-To-Taproot OutputScript #1926

Closed oprea-Alex closed 1 year ago

oprea-Alex commented 1 year ago

Hi!

I'm trying to recover the sender address for this raw transaction using bitcoin.address.fromOutputScript(output.script, network):

Raw tx: 02000000000101e36e2ba0d66df045222997b5d7d9c00ed57d2829ba76d3f73f80ed0be368b40e0200000000ffffffff02e8fd000000000000225120e2f814985f616a2ebd9d70f98e733cc8d23aad6dcd3e84c441a652ce4a2e89a97d6b2800000000002251205cb56f320a1f91913ee7901d8b23caafa8126d27bb830bf0624d44d39e42eab3014008125438aec85aa2d4b5327ec5914a322dcf1b89201a509cd23ab41f963d5cd96e19d6fec082f5e9821483c0a20b671a192c9da4cca64c70a03328cf47cbca5200000000

Pay-2-Taproot output scripts: 5120e2f814985f616a2ebd9d70f98e733cc8d23aad6dcd3e84c441a652ce4a2e89a9 51205cb56f320a1f91913ee7901d8b23caafa8126d27bb830bf0624d44d39e42eab3

network = bitcoin.networks.bitcoin // mainnet

The fromOutpuScript() function throws "Error: OP_1 5cb56f320a1f91913ee7901d8b23caafa8126d27bb830bf0624d44d39e42eab3 has no matching Address"

Link to decoded transaction on Blockcypher

The code works for any other type of transaction, except p2tr. If my approach was wrong, I'm looking for any suggestion on deserialising and recovering sender address of this type of transactions.

Thank you!

junderw commented 1 year ago

Are you using bitcoinjs-lib v6.1.0 or higher?

oprea-Alex commented 1 year ago

@junderw I've tried both v6.1.0 and 6.1.1.

oprea-Alex commented 1 year ago

51205cb56f320a1f91913ee7901d8b23caafa8126d27bb830bf0624d44d39e42eab3 (34 bytes) 5........cb56f320a1f91913ee7901d8b23caafa8126d27bb830bf0624d44d39e42eab3 (32 bytes)

I've noticed that the script thrown in the Error is 2 bytes short compared to the initial output script

junderw commented 1 year ago

Just did a quick check. It works.

> var b = require('bitcoinjs-lib')
undefined
> var ecc = require('tiny-secp256k1')
undefined
> b.initEccLib(ecc)
undefined
> b.address.fromOutputScript(Buffer.from('5120e2f814985f616a2ebd9d70f98e733cc8d23aad6dcd3e84c441a652ce4a2e89a9','hex'))
'bc1putupfxzlv94za0vawrucuueuerfr4ttde5lgf3zp5efvuj3w3x5s8sdun0'

Can you give me more info about your environment?

Did you forget to initialize the Ecc library?

junderw commented 1 year ago

If you don't initialize the ecc library, it will fail with the same error you had.

> var b = require('bitcoinjs-lib')
undefined
> b.address.fromOutputScript(Buffer.from('5120e2f814985f616a2ebd9d70f98e733cc8d23aad6dcd3e84c441a652ce4a2e89a9','hex'))
Uncaught:
Error: OP_1 e2f814985f616a2ebd9d70f98e733cc8d23aad6dcd3e84c441a652ce4a2e89a9 has no matching Address
    at Object.fromOutputScript (/home/user/git/bitcoinjs-lib/src/address.js:116:9)
junderw commented 1 year ago

When validating a p2tr address, the library needs to have an ecc library attached to it otherwise it can't verify if the 32 byte xOnly pubkey is valid.

So rather than letting you send money to a possible black hole, it fails.

oprea-Alex commented 1 year ago

@junderw Thank you, somehow I skipped tiny-secp256k1 init step when reading through your examples. Works great now!