P2SH-wrapped P2PKHなんてできるのか?

# プロローグ
先日、StackExchangeで[こんな](https://bitcoin.stackexchange.com/questions/83103/is-p2sh-wrapped-p2pkh-possible)質問をしました。
`P2SH-wrapped P2PKH`というものですが、それが何なのかを含めて質問をしたので、その訳を書いておきます。

...ついでにやってみました。

# P2SH-wrapped P2PKHなんてできるのか? (質問の訳)

`P2SH-wrapped P2WPKH`のような、アドレスの形式があることはよく知られています。これはSegWitアドレスをP2SHにラップ(包んでしまう)するものですね。
こういったアドレスの形式を考えているうちに、こんな疑問が思い浮かびました。「`P2SH-wrapped P2PKH`なんてできるのか?」ってね。
当然、こんなのは無用な長物なんてのは自明だけど、考えるだけ考えてみたいと思います。

## Step 1: 変換するアドレスを決める

[ここ](https://en.bitcoin.it/wiki/Mini_private_key_format)にあった`1CciesT23BNionJeXrbxmjc7ywfiyM4oLW`というアドレスを例に取りましょう。

## Step 2: アドレスを「出力スクリプト」[^outputscript]に変換し、hash160でハッシュする
[^outputscript]: 「出力スクリプト」というのは"locking script"とか言われるアレです

`OP_DUP OP_HASH160 7f6ab65fa911f558ca2dde3e9d073acb02c0d5c6 OP_EQUALVERIFY OP_CHECKSIG`が得られました。
ハッシュしたら`c852ac34a1c76b63a279c97502c9ccc4e3cb9e8b`が出てきました。

## Step 3: ハッシュしたスクリプトからP2SHを作る

```
toBase58Check(c852ac34a1c76b63a279c97502c9ccc4e3cb9e8b, 5) = 3KxE77EHe1ip6WGRifwr9fZ5WBDGsLyWFz
```
この`3KxE77EHe1ip6WGRifwr9fZ5WBDGsLyWFz`が欲しいアドレスです。

[ここ](https://gist.github.com/nao20010128nao/49f1a5c94f006a49fe68200a03bf5955)に再現用のコードを置いておきます。

## 質問

`3KxE77EHe1ip6WGRifwr9fZ5WBDGsLyWFz`(P2SH-wrapped P2PKH address)に送られたコインは、普通にP2PKHから送金するように送金できますか?

# じゃあやってみよう
<!-- cPztn6Pe3LLXeqRwK6ecV46yNRRYRUsT9auATTmFK5GB6eVTySza -->
<!-- mqXLdhurwGm7mnciUm43RKejSUm8drqetx -->
...とは言ってもMainnetのコインではやりたくないので、Testnetでやります。
`mqXLdhurwGm7mnciUm43RKejSUm8drqetx`というアドレスを用意したので、これを変換します。
`2NBGcEkQnHY5DYZmRQADonnZUMdiPkKKnUy`になりました。(途中計算は[ここ](https://runkit.com/nao20010128nao/5c204124ac0ce10012a113a8))

## できたP2SHアドレスに送ってみよう
[送ってみました。](https://live.blockcypher.com/btc-testnet/tx/29ca616a0cc35c2482ccf4c0f9a563ca80504519a0798df95c1d36a7aa089ec9/)普通のP2SHなので見栄え0ですが。

## 早速spendしよう
途中計算の通り、出力スクリプト(ここではredeemScript)は`OP_DUP OP_HASH160 6dc3e7c54d2a45d79efb8f114213a2dcb893921d OP_EQUALVERIFY OP_CHECKSIG`です。

以下のコードでトランザクションを生成しました。

```javascript
const bitcoin=require('bitcoinjs-lib@3.3.2');

const testnet=bitcoin.networks.testnet;
const txb=new bitcoin.TransactionBuilder(testnet);
// see https://chain.so/tx/BTCTEST/29ca616a0cc35c2482ccf4c0f9a563ca80504519a0798df95c1d36a7aa089ec9 for what I mean
txb.addInput("29ca616a0cc35c2482ccf4c0f9a563ca80504519a0798df95c1d36a7aa089ec9", 0);

// 214 is fee: hardcode here for shortcut
// tb1qcgf5jv2028y5s0cgelk8qe97mq3upupt3wmfj6 is my address to return coin
txb.addOutput("tb1qcgf5jv2028y5s0cgelk8qe97mq3upupt3wmfj6", 10000-214);

const keyPair=bitcoin.ECPair.fromWIF("cPztn6Pe3LLXeqRwK6ecV46yNRRYRUsT9auATTmFK5GB6eVTySza", testnet);
txb.sign(0, keyPair, bitcoin.script.fromASM("OP_DUP OP_HASH160 6dc3e7c54d2a45d79efb8f114213a2dcb893921d OP_EQUALVERIFY OP_CHECKSIG"));

console.log(txb.build().toHex());
```
実行結果は[ここ](https://runkit.com/nao20010128nao/5c204acdc2665f001202b64f)。
`0100000001c99e08aaa7361d5cf98d79a01…483f08cfec7064bed823c0f02b00000000`が今回送るトランザクションになります。

## ブロードキャストしたら...
ちゃんと帰ってきました![^slowreturn]
トランザクションが[これ](https://live.blockcypher.com/btc-testnet/tx/89a277cd97dcd35dc786966d87de0ecef6de6509aeab3fcf67c2eb092f0d21dd/)。
すごい! なんとなく。

# 結論
P2SH-wrapped P2PKHなんて...**できる!**
なお需要があるはずがないので、参考程度に。[^usep2pkh]


[^slowreturn]: 1sat/byteなので承認までメチャクチャ時間かかりましたが...
[^usep2pkh]: なぜなら普通にP2PKHを使えば良いですし、P2PKHすら対応してないウォレットなんてそうそう見つけられません。また、普通のP2PKHと比べて、手数料が少し高額になります。