Closed bestatigen closed 5 years ago
@junderw and with that... TransactionBuilder shall become a closure...
@dcousens sigh... Yeah...
@devey You don't even need the TransactionBuilder to get it.
Something like the below should work... kinda hacky though. Not tested.
import {
TransactionBuilder as bitcoinTransactionBuilder,
Transaction as BitcoinTransaction,
payments as BitcoinPayments,
} from 'bitcoinjs-lib';
let tx = BitcoinTransaction.fromHex(transactionHex)
let addresses = tx.outs.map(output => {
let payment, address, isDone
Object.keys(BitcoinPayments).forEach(type => {
if (isDone) return
try {
payment = BitcoinPayments[type]({output: output.script})
} catch(e) {
console.log('Not ' + type + ' keep trying...')
return
}
try {
address = payment.address
if (!address) throw new Error('oops')
} catch(e) {
address = '[NO ADDRESS (Legacy P2PK, OP_RETURN etc.)]'
}
isDone = true
})
return address
})
console.log(addresses)
maybe want to just copy paste all the payment type names in an array and iterate on them in order of prevalence... as imo the default order starts with some obscure ones that don't even have addresses iirc.
Thanks for the time @junderw; spot on, just needed to pass network too:
payment = BitcoinPayments[type]({
output: output0Script,
network,
});
Hi junderw,
I tried your code above and I don't get any address for blocks read from hard disk (blkxxxxx.dat) as explained in this issue: https://github.com/bitcoinjs/bitcoinjs-lib/issues/1286
I modified the code like this:
const block = bitcoin.Block.fromBuffer(rawblock)
const script = block.transactions[0].outs[0].script
let payment, address, isDone
Object.keys(bitcoin.payments).forEach(type => {
if (isDone) return
try {
payment = bitcoin.payments[type]({output: script})
} catch(e) {
console.log('Not ' + type + ' keep trying...')
return
}
try {
address = payment.address
if (!address) throw new Error('oops')
} catch(e) {
address = '[NO ADDRESS (Legacy P2PK, OP_RETURN etc.)]'
}
isDone = true
})
console.log("address:", address)
Please help me to obtain the address.
Thanks.
what do you get?
an error? what does the error say?
be specific or no one can help you.
This is the tx I get when reading from blk00000.dat
Transaction {
version: 1,
locktime: 0,
ins:
[ { hash: <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,
index: 4294967295,
script: <Buffer 04 ff ff 00 1d 01 04 45 54 68 65 20 54 69 6d 65 73 20 30 33 2f 4a 61 6e 2f 32 30 30 39 20 43 68 61 6e 63 65 6c 6c 6f 72 20 6f 6e 20 62 72 69 6e 6b 20 ... >,
sequence: 4294967295,
witness: [] } ],
outs:
[ { value: 5000000000,
script: <Buffer 41 04 67 8a fd b0 fe 55 48 27 19 67 f1 a6 71 30 b7 10 5c d6 a8 28 e0 39 09 a6 79 62 e0 ea 1f 61 de b6 49 f6 bc 3f 4c ef 38 c4 f3 55 04 e5 1e c1 12 de ... > } ] }
As you can see script is in buffer form so payments classes (p2pk, ...) reject it at the very beginning:
function p2pk (a, opts) {
if (
!a.input &&
!a.output &&
!a.pubkey &&
!a.input &&
!a.signature
) throw new TypeError('Not enough data')
So I get: 'Not enough data'
error.
But when I get a block from the node by calling client.getBlockByHash
I get:
...
vout:
[ { value: 0.00040514, n: 0, scriptPubKey: [Object] },
{ value: 2.86177728, n: 1, scriptPubKey: [Object] } ],
The script is an object so it has the attributes that payments classes expect.
So what it's happening is that when calling bitcoin.Block.fromBuffer
the scripts are not processed at all and bitcoinjs-lib don't know how to read data from them.
Thanks.
More info.
This is most confusing cause when I get notified a transaction from the node by using:
let tx_sock = zmq.socket('sub')
let tx_addr = 'tcp://127.0.0.1:'+process.env.BITCOIN_TX_NOTIFY
tx_sock.connect(tx_addr)
tx_sock.subscribe('rawtx')
tx_sock.on('message', async function(topic, message) {
let tx = bitcoin.Transaction.fromBuffer(message)
The tx received is:
{ version: 1,
locktime: 0,
ins:
[ { hash: <Buffer eb 05 f6 b5 90 d1 58 2f e2 3d 79 78 5a 1e 6a 77 c8 2e a5 38 10 32 59 94 92 b6 30 55 a3 6e a6 9a>,
index: 0,
script: <Buffer 48 30 45 02 21 00 ff 06 96 77 49 bd b2 b6 d4 49 b ... >,
sequence: 4294967295,
witness: [] } ],
outs:
[ { value: 0,
script: <Buffer 6a 4c 50 00 00 59 2f 00 01 9f b6 5a db ca ... > },
{ value: 773995,
script: <Buffer 76 a9 14 7f dc 10 9b c7 9a a5 c3 4f 9b 19 a6 7d eb 25 89 20 ... }
As you can see the script is in buffer form again. But this time calling:
tx.outs.forEach( (vout, index) => { // UTXO
try {
let address = bitcoin.address.fromOutputScript(vout.script, network)
works ok and I get the address.
So I don't understand why with this script in buffer form it works but with the block read from blk00000.dat it doesn't.
Thanks.
I made it work!!!!
I had to modify the library.
1) address.js I added:
try { return payments.p2pk({ output, network }).address } catch (e) {}
2) payments.p2pk I added:
const crypto = require('../crypto')
const bs58check = require('bs58check')
and after
lazy.prop(o, 'pubkey', function () {
if (!a.output) return
return a.output.slice(1, -1)
})
I added:
lazy.prop(o, 'hash', function () {
if (a.pubkey || o.pubkey) return crypto.hash160(a.pubkey || o.pubkey)
})
lazy.prop(o, 'address', function () {
if (!o.hash) return
const payload = Buffer.allocUnsafe(21)
payload.writeUInt8(network.pubKeyHash, 0)
o.hash.copy(payload, 1)
return bs58check.encode(payload)
})
It works but I would appreciate a proper update of the library as I did copy/paste and a lot of guessing. Thanks.
P2PK does not have an address.
Your modification is incorrect.
Yes. You are right in the strict sense that a p2pk script is just the publick key + op_checksig.
But how do I know which address the bitcoins were sent to when the script is p2pk?
Doing this modification I got the real addresses (the satoshi 1st address)
Thanks.
Block Explorers started showing P2PKH addresses for P2PK outputs because they are irresponsible and don't care if people lose money.
You should show the pubkey and OP_CHECKSIG using toAsm
Ok. Thanks.
I believe this is concluded. Please re-open if needed.
Description:
I'm trying to retrieve the output addresses from a hex transaction created this way:
as in https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/transaction_builder.js#L106.
On
transaction__tx.outs[0]
I have:Is the output address encoded in
script
? If so what is the process to extract it?