Raw-Transaction
使用 bitcoinjs-lib 簽署本機 P2WPKH(簽署 sighash)(非強制腳本驗證標誌)
我對 p2wsh 多重簽名配置進行了很多實驗
bitcoinjs-lib
。但是當我嘗試簽署一個標準的本地 segwit p2wpkh 到 p2wpkh 交易時,一切正常,除了bitcoin-cli sendrawtransaction
. 它說non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation)
js程式碼(
./btc
在這裡,其餘的可以npm install
編輯):const { btc, send, listunspent, getnewaddress, bech32toScriptPubKey } = require('./btc')(); const bitcoin = require('bitcoinjs-lib'); const network = bitcoin.networks.testnet; const hashtype = bitcoin.Transaction.SIGHASH_ALL; const ECPair = require('ecpair').ECPairFactory(require('tiny-secp256k1')); const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.on('close', () => process.exit(0)); const input = q => new Promise(r => rl.question(q, r)); main(); async function main() { const u = (await listunspent(0, 0, true)).filter(x => x.solvable && x.spendable && x.desc.startsWith('wpkh')); console.log(u); const v = await input('Which input to use? '); const utxo = u[parseInt(v)]; if (!utxo) { console.log('error'); process.exit(1); } var out = await input('Output address (leave empty to generate a new one) '); if (out.length == 0) { out = await getnewaddress(); } if (out.length != 42) { console.log('p2wpkh addresses are 42 chars long'); process.exit(1); } const ecpair = ECPair.fromWIF(await btc('dumpprivkey', utxo.address), network); const tx = new bitcoin.Transaction(network); tx.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.vout); const fee = 110; tx.addOutput(bech32toScriptPubKey(out), utxo.amount - fee); const sighash = tx.hashForWitnessV0( 0, Buffer.from(utxo.scriptPubKey, 'hex'), utxo.amount, hashtype ); tx.setWitness(0, [ bitcoin.script.signature.encode(ecpair.sign(sighash), hashtype), ecpair.publicKey ]); console.log(tx.toHex()); console.log(await send(tx.toHex())); }
TX 十六進制
01000000000101c690a8157bb45506b15173a3175bd3504182cf8c91f916235522522a3d1a28280100000000ffffffff01d2410f00000000001600149b959b78f09b7f7976391fd20aad3835b738e0c3024730440220120a950d96210c48a6831e7ee7f746e6119183d8512b10a6b14c60509556bba3022042359f1699e9cfb90637647ecb085e262736dc5ad9c076666cb44c29c20baafc0121027b612527ff9e157b80dd2ddac0e11555afcd517a7a425c27e5c7afbad889528e00000000
我認為我在必須包含在 sighash 中的內容上犯了一個錯誤。
scriptPubKey
p2wpkh 的 sighash 中使用了什麼?
我已經通過對 sighash 使用 P2PKH 輸出腳本解決了這個問題
const sighash = tx.hashForWitnessV0( 0, Buffer.from(utxo.scriptPubKey, 'hex'), utxo.amount, hashtype );
已更改為
const pkh = bitcoin.script.decompile(Buffer.from(utxo.scriptPubKey, 'hex'))[1]; const sighash = tx.hashForWitnessV0( 0, bitcoin.script.compile([ bitcoin.opcodes.OP_DUP, bitcoin.opcodes.OP_HASH160, pkh, bitcoin.opcodes.OP_EQUALVERIFY, bitcoin.opcodes.OP_CHECKSIG ]), utxo.amount, hashtype );
我的腳本現在可以工作並將其添加到我的比特幣東西回購
<https://github.com/antonilol/btc_stuff>
<https://github.com/antonilol/btc_stuff/blob/master/p2wpkh.js>