0
Help us understand the problem. What are the problem?

posted at

updated at

bitcoinjs-libでP2SH-P2WSHのトランザクションを作る

はじめに

こちらと同じように、P2SH-P2WSHのトランザクションを作成します。

Signetフルノードの動かし方などは上記記事を参考にしてください。

準備

鍵はこちらと同じjsonファイルを使います。

BTCをアドレスに入れておく

こちらで作成したアドレスにsBTCを送っておきます。

P2SH-P2WSH:
2N9mgCypNXq8qkx1SHqBkDW4u92rXKsdJjH

TXは
f77f76cbc68444716894f5884f99e281c943e7f1832886bc8030cda5d05e803d
Indexは1です。

RawTxを取得

資金源のTxのRawTxを取得します。

bcli getrawtransaction f77f76cbc68444716894f5884f99e281c943e7f1832886bc8030cda5d05e803d
02000000000101de2a2fc215b03e798e4b25b313c595a207621798991c1bc3526b688b78d852bb0000000000feffffff0285f29000000000001600146f5fcbf72dd6bce849eb78dc5b984f5cdc69ec0ca08601000000000017a914b54460b9b1339d23d349cdd216ab44314cbeca2a870247304402206a7c7ae6b7135b8091467d72869ef6ee01b5d53ebf24c75e79b0d339c672d5af02206ed9c92a56e91c3ac8afc8abae493e84f59b6a76edbe32360091470bb00b39440121034e87fe334e75b2a1ccb6ef9a6b2beac216d7763f321eeb75c1191889ce191a498ece0000

トランザクション作成

previousRawTxに前節で得たRawTxを入れます。

const previousRawTx = '02000000000101de2a2fc215b03e798e4b25b313c595a207621798991c1bc3526b688b78d852bb0000000000feffffff0285f29000000000001600146f5fcbf72dd6bce849eb78dc5b984f5cdc69ec0ca08601000000000017a914b54460b9b1339d23d349cdd216ab44314cbeca2a870247304402206a7c7ae6b7135b8091467d72869ef6ee01b5d53ebf24c75e79b0d339c672d5af02206ed9c92a56e91c3ac8afc8abae493e84f59b6a76edbe32360091470bb00b39440121034e87fe334e75b2a1ccb6ef9a6b2beac216d7763f321eeb75c1191889ce191a498ece0000';

TX
f77f76cbc68444716894f5884f99e281c943e7f1832886bc8030cda5d05e803d
Index:1をpsbt.addInputに入れます。

psbt.addInput({
    hash: 'f77f76cbc68444716894f5884f99e281c943e7f1832886bc8030cda5d05e803d',
    index: 1,

宛先、送金額は任意でセットします。ただし、Input - OutputであるFeeが1satoshi/byteでなくてはなりません。

const bitcoin = require('bitcoinjs-lib');
const bip32 = require('bip32');
const bip39 = require('bip39');
const wif = require('wif');
const {xpub1, xpub2, xpub3} = require('./xpubs.json');
const MAINNET = bitcoin.networks.bitcoin;
const TESTNET = bitcoin.networks.testnet;
// let bitcoinNetwork = MAINNET;
let bitcoinNetwork = TESTNET;

const xpriv1 = require('./xpriv1.json').xpriv;
const xpriv2 = require('./xpriv2.json').xpriv;
const xpriv3 = require('./xpriv3.json').xpriv;

function getPrivkeyFromXpriv(xpriv) {
    const privkeyNode = bitcoin.bip32.fromBase58(xpriv, bitcoinNetwork);
    const privateKey_wif = privkeyNode.derive(1).derive(0).derive(0).derive(0).toWIF();
    console.log("privateKey_wif:");
    console.log(privateKey_wif);
    const obj = wif.decode(privateKey_wif);
    const privkey = bitcoin.ECPair.fromPrivateKey(obj.privateKey);
    return privkey;
}

const privkey1 = getPrivkeyFromXpriv(xpriv1);
const privkey2 = getPrivkeyFromXpriv(xpriv2);
const privkey3 = getPrivkeyFromXpriv(xpriv3);

function getPubkeyFromXpub(xpub) {
    const pubkeyNode = bitcoin.bip32.fromBase58(xpub, bitcoinNetwork);
    const pubkey = pubkeyNode.derive(1).derive(0).derive(0).derive(0).publicKey;
    return pubkey;
}

const pubkey1 = getPubkeyFromXpub(xpub1);
const pubkey2 = getPubkeyFromXpub(xpub2);
const pubkey3 = getPubkeyFromXpub(xpub3);

const pubkeys = [
    pubkey1,
    pubkey2,
    pubkey3,
].map(Buffer => Buffer);

const p2wsh =  bitcoin.payments.p2wsh({
        redeem: bitcoin.payments.p2ms({ m: 2, pubkeys, network: bitcoinNetwork, })
})

const p2sh = bitcoin.payments.p2sh({
    redeem: p2wsh
});

console.log('P2SH-P2WSH address')
console.log(p2sh.address) 

const psbt = new bitcoin.Psbt({ network: bitcoinNetwork });

const previousRawTx = '02000000000101de2a2fc215b03e798e4b25b313c595a207621798991c1bc3526b688b78d852bb0000000000feffffff0285f29000000000001600146f5fcbf72dd6bce849eb78dc5b984f5cdc69ec0ca08601000000000017a914b54460b9b1339d23d349cdd216ab44314cbeca2a870247304402206a7c7ae6b7135b8091467d72869ef6ee01b5d53ebf24c75e79b0d339c672d5af02206ed9c92a56e91c3ac8afc8abae493e84f59b6a76edbe32360091470bb00b39440121034e87fe334e75b2a1ccb6ef9a6b2beac216d7763f321eeb75c1191889ce191a498ece0000';

psbt.addInput({
    hash: 'f77f76cbc68444716894f5884f99e281c943e7f1832886bc8030cda5d05e803d',
    index: 1,
    redeemScript: p2wsh.output,
    witnessScript: p2wsh.redeem.output,
    nonWitnessUtxo: Buffer.from(previousRawTx, 'hex'),
});
psbt.addOutput({
    address: "tb1q2adzgyzuy3msvjjfn3pkghf5fnwtwmxcglw3cuk5gvvv3ahmt63qqqa3n6",
    value: 30000,
});
psbt.addOutput({
    address: "tb1qzwwvqxr2m8l0kt8trnnhaa48awtq45zauflz5y",
    value: 69776,
});

psbt.signInput(0, privkey2)
psbt.signInput(0, privkey3);

psbt.validateSignaturesOfInput(0, Buffer.from(pubkey2, 'hex'))
psbt.validateSignaturesOfInput(0, Buffer.from(pubkey3, 'hex'))

psbt.validateSignaturesOfInput(0);
psbt.finalizeAllInputs();
const txHex = psbt.extractTransaction().toHex();

console.log(txHex);

コードを実行します。

$ node p2shP2wshTx.js 
privateKey_wif:
cVqL1ToSfwLw2xt6AB6bXoN51MrpTKj4RawFN682mD3zockVgqXD
privateKey_wif:
cRbPqcaZ9L9hvGkFkjyALCmb5hvwfkW8j4GhVpFqN1vvmNDGJZ61
privateKey_wif:
cStFWwyLBG6SGtNsqZ5MjnaLdYpsyzu5hp5U11WrL3ZBMPAWshdc
P2SH-P2WSH address
2N9mgCypNXq8qkx1SHqBkDW4u92rXKsdJjH
020000000001013d805ed0a5cd3080bc862883f1e743c981e2994f88f59468714484c6cb767ff70100000023220020575a24105c2477064a499c43645d344cdcb76cd847dd1c72d44318c8f6fb5ea2ffffffff023075000000000000220020575a24105c2477064a499c43645d344cdcb76cd847dd1c72d44318c8f6fb5ea29010010000000000160014139cc0186ad9fefb2ceb1ce77ef6a7eb960ad05d040047304402206def24babcd21f73271892e5e20a37cf24f32c7f548405a880d50f2b4ba0490302207d6f935be1dedb3b4dd0b09231126082be75873ef07f861a51f229789d75a05d01473044022026dfcc2f82eda5cfba13745573fe4521bcc3ee50539cc5b8c605ec4749234c0e022014d665a81548dcef10643a3060239cfc4a0dce13ac292d39543db4890f443eaa01695221036791fd096f2a83f355826012c9a29bc07ea4460cdbc424f57d7b181a502121092102f94b3a35c8464d8fe3a121e685b4f56adff15f5976f57f7b3e176b3b4707ba6121039ff1a14f03925083945d1158bcd7167979f8fb73dc8af80818a178aaaf64fa7553ae00000000

得られたRawTxをブロードキャストします。

$ bcli sendrawtransaction 020000000001013d805ed0a5cd3080bc862883f1e743c981e2994f88f59468714484c6cb767ff70100000023220020575a24105c2477064a499c43645d344cdcb76cd847dd1c72d44318c8f6fb5ea2ffffffff023075000000000000220020575a24105c2477064a499c43645d344cdcb76cd847dd1c72d44318c8f6fb5ea29010010000000000160014139cc0186ad9fefb2ceb1ce77ef6a7eb960ad05d040047304402206def24babcd21f73271892e5e20a37cf24f32c7f548405a880d50f2b4ba0490302207d6f935be1dedb3b4dd0b09231126082be75873ef07f861a51f229789d75a05d01473044022026dfcc2f82eda5cfba13745573fe4521bcc3ee50539cc5b8c605ec4749234c0e022014d665a81548dcef10643a3060239cfc4a0dce13ac292d39543db4890f443eaa01695221036791fd096f2a83f355826012c9a29bc07ea4460cdbc424f57d7b181a502121092102f94b3a35c8464d8fe3a121e685b4f56adff15f5976f57f7b3e176b3b4707ba6121039ff1a14f03925083945d1158bcd7167979f8fb73dc8af80818a178aaaf64fa7553ae00000000
475c9caf689b136a3d9ad03a90d66959257812cc9df7f51865bc1df636ad8901

送金できました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
0
Help us understand the problem. What are the problem?