Closed Overtorment closed 6 years ago
You can restore address only if spent output was P2WPKH.
const bitcoin = require('bitcoinjs-lib')
const pubKey = Buffer.from('035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8', 'hex')
const pubKeyHash = bitcoin.crypto.hash160(pubKey)
const scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash)
const address = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.bitcoin)
console.log(address) // => bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv
Please fix me if I'm wrong.
@fanatid is right if it is bech32 P2WPKH, but if it is base58 P2SH-P2WPKH (aka it had a redeemscript in the scriptSig) it would be the below:
const bitcoin = require('bitcoinjs-lib')
const pubKey = Buffer.from('035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8', 'hex')
const pubKeyHash = bitcoin.crypto.hash160(pubKey)
const redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash)
const address1 = bitcoin.address.fromOutputScript(redeemScript, bitcoin.networks.bitcoin)
console.log(address1) // => bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv
// P2WPKH
const redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
const scriptPubkey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
const address2 = bitcoin.address.fromOutputScript(scriptPubkey, bitcoin.networks.bitcoin)
console.log(address2) // 34ZVGb3gT8xMLT6fpqC6dNVqJtJmvdjbD7
// P2SH-P2WPKH
So if you want to parse a segwit input, taking the above data from a transaction api, it would be like:
const tx = JSON.parse(apiResponseAbove)
let inputAddresses = []
let inputs = tx.transaction.inputs
inputs.forEach(input => {
let scriptSigChunks = input.script_sig.asm.split(/\s+/)
if (scriptSigChunks[0] === '') scriptSigChunks = []
if(input.witness === null) {
console.log('not segwit')
return
} else if(scriptSigChunks.length > 1) {
console.log('unknown input type: scriptSig is not P2SH but has witness')
return
} else if(scriptSigChunks.length === 0) {
// is not P2SH
let witnessScript = input.witness[input.witness.length - 1]
let witnessType
let pubKey
if (witnessScript.match(/^0[23][0-9a-fA-F]{64}$/)) {
pubKey = witnessScript
witnessType = 'P2WPKH'
} else {
witnessType = 'P2WSH'
}
// get address from the hash160 of pubKey OR the sha256 of witnessScript depending on P2WPKH or P2WSH respectively
} else {
// is P2SH
let redeemScript = scriptSigChunks[0]
let witnessScript = input.witness[input.witness.length - 1]
let witnessType
if (witnessScript.match(/^0[23][0-9a-fA-F]{64}$/)) {
witnessType = 'P2SH-P2WPKH'
} else {
witnessType = 'P2SH-P2WSH'
}
// get address from redeemScript hash160
}
})
thanks all!
Or using the new payments
API (https://github.com/bitcoinjs/bitcoinjs-lib/pull/1096), aka 4.0.0
:
let bjs = require('bitcoinjs-lib')
let witness = [
Buffer.from('30450221009f696a5c1bb1735bb3f1f64276ac6838c4e04b6c89b5eda84e86d24022d4f7ab02207caae352a19fe830dea60be2cd0a73af27e40124ca7f57ff9451887e81a7569d01', 'hex'),
Buffer.from('035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8', 'hex')
]
let obj = bjs.payments.p2wpkh({ witness })
console.log(obj.address)
// bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv
If it was p2sh(p2wpkh)
:
let bjs = require('bitcoinjs-lib')
let input = Buffer.from('160014e5e6cc9c155da3c9df725c3c4d9987c374e29987', 'hex')
let witness = [
Buffer.from('30450221009f696a5c1bb1735bb3f1f64276ac6838c4e04b6c89b5eda84e86d24022d4f7ab02207caae352a19fe830dea60be2cd0a73af27e40124ca7f57ff9451887e81a7569d01', 'hex'),
Buffer.from('035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8', 'hex')
]
let p2sh = bjs.payments.p2sh({ input, witness })
console.log(p2sh.address)
// 34ZVGb3gT8xMLT6fpqC6dNVqJtJmvdjbD7
let redeem = bjs.payments.p2wpkh(p2sh.redeem)
console.log(redeem.address)
// bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv
:heart_eyes:
Im sorry if tihs is a dumb question. I already looked at #669 but still cant figure out how to recover a bech32 address from transaction input witness script
Given:
Can you please help me? Thanks!