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

# はじめに

https://qiita.com/shu-kob/items/1a26eb7ec21fcf43cf68

上記の記事ではNatice SegwitのP2WPKHのUTXOをInputに持つトランザクションを作成する手順を書きましたが、

今回は、P2SH-P2WPKHのUTXOをInputに持つトランザクションを作成していきます。

# 準備

## フルノード

https://qiita.com/shu-kob/items/1a26eb7ec21fcf43cf68#%E3%83%95%E3%83%AB%E3%83%8E%E3%83%BC%E3%83%89

上記記事と同様、DockerでSignetノードを立ち上げますが、

```
vi ~/docker-signet/bitcoin.conf
```

```
txindex=1
```

を[signet]の下に追記して起動します。

txindexなしで起動したことがあるなら、reindexするかブロックチェーンデータを消すなりしてください。

## 鍵

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

https://qiita.com/shu-kob/items/1a26eb7ec21fcf43cf68#%E9%8D%B5%E3%81%AE%E6%BA%96%E5%82%99

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

https://qiita.com/shu-kob/items/63fa8aafa06cac1c7cda

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

```
P2SH-P2WPKH:
2N7XBZfKVZ3h9ysFyZLroQpQ5cwxzY25tWE
```

https://explorer.bc-2.jp/tx/bb52d8788b686b52c31b1c9998176207a295c513b3254b8e793eb015c22f2ade

TXは
bb52d8788b686b52c31b1c9998176207a295c513b3254b8e793eb015c22f2ade

Indexは１です。

## RawTxを取得

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

```
$ bcli getrawtransaction bb52d8788b686b52c31b1c9998176207a295c513b3254b8e793eb015c22f2ade
```

```
02000000000101387eee5dd96c6349fb16ceef466c0b9265e029cd71abe47d7ee0a08621424c360100000000feffffff02b379920000000000160014a13008ccc2f7b83463984b5b4afa65fbbdf87851a08601000000000017a9149c966478e58697e07ba4aec10fa6f3508f4325fa870247304402205dd9a3c774fc720dd7855c79baa19a28b025ff9596959b05dd2767fa22bbe24602201969d84c378222af595bf2addeb929a2dd74e906dc806b2418e47622b18ca8e0012102a37d8b815cea0042b01ce49c9f83ab942c8e4b8a85b3c7aca5b641120d654ea179ce0000
```

# トランザクション作成

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

```
const previousRawTx = '02000000000101387eee5dd96c6349fb16ceef466c0b9265e029cd71abe47d7ee0a08621424c360100000000feffffff02b379920000000000160014a13008ccc2f7b83463984b5b4afa65fbbdf87851a08601000000000017a9149c966478e58697e07ba4aec10fa6f3508f4325fa870247304402205dd9a3c774fc720dd7855c79baa19a28b025ff9596959b05dd2767fa22bbe24602201969d84c378222af595bf2addeb929a2dd74e906dc806b2418e47622b18ca8e0012102a37d8b815cea0042b01ce49c9f83ab942c8e4b8a85b3c7aca5b641120d654ea179ce0000';
```

TXが
bb52d8788b686b52c31b1c9998176207a295c513b3254b8e793eb015c22f2ade
Index:１を入れます。

```
psbt.addInput({
    hash: 'bb52d8788b686b52c31b1c9998176207a295c513b3254b8e793eb015c22f2ade',
    index: 1,
```

```p2shP2wpkhTx.js
const bitcoin = require('bitcoinjs-lib');
const bip32 = require('bip32');
const bip39 = require('bip39');
const wif = require('wif');
const { xpub } = require('./xpub.json');
const MAINNET = bitcoin.networks.bitcoin;
const TESTNET = bitcoin.networks.testnet;
// let bitcoinNetwork = MAINNET;
let bitcoinNetwork = TESTNET;

const { xpriv } = require('./xpriv.json');

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);

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 pubkey = getPubkeyFromXpub(xpub);

const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: pubkey, network: bitcoinNetwork, });

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

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

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

const previousRawTx = '02000000000101387eee5dd96c6349fb16ceef466c0b9265e029cd71abe47d7ee0a08621424c360100000000feffffff02b379920000000000160014a13008ccc2f7b83463984b5b4afa65fbbdf87851a08601000000000017a9149c966478e58697e07ba4aec10fa6f3508f4325fa870247304402205dd9a3c774fc720dd7855c79baa19a28b025ff9596959b05dd2767fa22bbe24602201969d84c378222af595bf2addeb929a2dd74e906dc806b2418e47622b18ca8e0012102a37d8b815cea0042b01ce49c9f83ab942c8e4b8a85b3c7aca5b641120d654ea179ce0000';

psbt.addInput({
    hash: 'bb52d8788b686b52c31b1c9998176207a295c513b3254b8e793eb015c22f2ade',
    index: 1,
    redeemScript: p2wpkh.output,
    nonWitnessUtxo: Buffer.from(previousRawTx, 'hex'),
});
psbt.addOutput({
    address: "tb1q2adzgyzuy3msvjjfn3pkghf5fnwtwmxcglw3cuk5gvvv3ahmt63qqqa3n6",
    value: 30000,
});
psbt.addOutput({
    address: "tb1qzwwvqxr2m8l0kt8trnnhaa48awtq45zauflz5y",
    value: 69824,
});

const obj = wif.decode(privateKey_wif);

const privKey = bitcoin.ECPair.fromPrivateKey(obj.privateKey);

psbt.signInput(0, privKey);

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

console.log(txHex);
```

```
$ node p2shP2wpkhTx.js 
privateKey_wif:
cVa9bD3JAoc6hJHfU68PkLWrYmn6AN81PJs7kG6BHR1TeA4nKJtF
P2SH-P2WPKH address
2N7XBZfKVZ3h9ysFyZLroQpQ5cwxzY25tWE
02000000000101de2a2fc215b03e798e4b25b313c595a207621798991c1bc3526b688b78d852bb0100000017160014139cc0186ad9fefb2ceb1ce77ef6a7eb960ad05dffffffff023075000000000000220020575a24105c2477064a499c43645d344cdcb76cd847dd1c72d44318c8f6fb5ea2c010010000000000160014139cc0186ad9fefb2ceb1ce77ef6a7eb960ad05d02483045022100eaab6fc6e9f30c0010ebfc2c4aa87a0ab3a0d638916a5eba60ed8d09b2dcd16302204389db680cb65affb50f811a7786a0ef3bfc282e8e19b4ae2beee1119fcd77280121034c30836747cd7d7a50db1de9ceb1c953a4c308bbf2669c620d62a4370f63b47200000000
```

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

```
$ bcli sendrawtransaction 02000000000101de2a2fc215b03e798e4b25b313c595a207621798991c1bc3526b688b78d852bb0100000017160014139cc0186ad9fefb2ceb1ce77ef6a7eb960ad05dffffffff023075000000000000220020575a24105c2477064a499c43645d344cdcb76cd847dd1c72d44318c8f6fb5ea2c010010000000000160014139cc0186ad9fefb2ceb1ce77ef6a7eb960ad05d02483045022100eaab6fc6e9f30c0010ebfc2c4aa87a0ab3a0d638916a5eba60ed8d09b2dcd16302204389db680cb65affb50f811a7786a0ef3bfc282e8e19b4ae2beee1119fcd77280121034c30836747cd7d7a50db1de9ceb1c953a4c308bbf2669c620d62a4370f63b47200000000
```

```
46fbfca1236acf4cfcdc8eb97856370cc4294eb1578f9fd00ed2a6be5536b50b
```

送金できました。

https://explorer.bc-2.jp/tx/46fbfca1236acf4cfcdc8eb97856370cc4294eb1578f9fd00ed2a6be5536b50b