為“無多重簽名/無隔離見證”的 P2SH 交易提供資金和支出
我受到這個執行緒的啟發:
假設我想盡可能“隱藏”我的地址。所以我想要一個 P2SH tx,它只在區塊鏈上顯示一個兌換腳本(我的公鑰的雜湊),直到用完為止。我嘗試模擬多重簽名,但僅使用公鑰作為兌換腳本。資金 tx 將散列 160 公鑰,並將其用作贖回腳本。這將是對“類型 3 地址”的付款,此程式碼在“tx_out pkscript”中。
A9: OP_HASH160 14: OP_Data14 (= decimal 20 and the redeem hash) 87: OP_EQUAL
支出交易會在它的腳本中包含這個嗎?
<sig><pubkey><OP_CHECKSIG>
<sig><pubkey 1-n><OP_CHECKMULTISIG>
(而不是在多重簽名中完成的方式:)看看堆棧上發生了什麼:
sig pubkey <OP_CHECKSIG> <OP_HASH160> redeem hash <OP_Equal>
為此,
<OP_HASH160>
操作碼必須知道 pubkey 和<OP_CHECKSIG>
需要一起散列(與 for 之後的redeemscript散列進行比較<OP_Equal>
)……我認為同樣的問題也適用於多重簽名。只有兩個或多個 pubkey 後跟
<OP_CHECKMULTISIG>
(而不是<OP_CHECKSIG>
)。
現在我明白了,為什麼沒有答案 - 它真的很長:-)
所以我自己回答。我在 OpenBSD (ksh) 和 OSX (bash v3) 上使用比特幣核心 (getinfo) 版本 150100:
我在 testnet 上解決了它,並讓 tx 通過。來自@nick
我想知道,如果這是真的:
為此,
<OP_HASH160>
操作碼必須知道 pubkey 和<OP_CHECKSIG>
需要一起散列顯然是的。這是整個週期…首先我嘗試使用輸入和輸出腳本查看堆棧(根據上面的連結):
sigscript: <sig> <redeem script> pubkey script: OP_HASH160 <RedeemScriptHash> OP_EQUAL
根據上面的連結並查看堆棧,它將通過以下步驟執行:
- 輸入 SigScript(將數據推送到堆棧)堆棧:
- 執行 pubkey 腳本 這將首先將 pubkey 腳本的第一個 OPCODE 推送到堆棧上並執行 STACK: OP_HASH160
灣。此命令消耗頂部堆棧元素,並替換為雜湊堆棧:
C。pubkey 腳本的下一個元素被推送到堆棧堆棧:OP_EQUAL 3. OP_Equal 驗證棧頂兩個元素,如果不正確 –> 無效 4. 如果為真,則腳本在堆棧堆棧頂部以“真”結尾: 5. 驗證腳本是否為 P2SH(…好吧,它是 P2SH …) 6. 清理堆棧,然後再次執行 sigscript STACK: 7. 彈出棧頂元素,並將其作為腳本執行。贖回腳本的頂部元素是 OP_CHECKSIG STACK: OP_CHECKSIG
灣。CHECKSIG 將驗證 pubkey 和 sig,並返回 true …
要查看這是否正確,請在 testnet/regtest 上收集資金交易。使用 coinbase tx(挖出的區塊)時,需要 >100 次確認!首先為此 tx 創建一個兌換腳本和地址:
NEWADDRESS=$( bitcoin-cli -regtest getnewaddress ) echo $NEWADDRESS PUBKEY=$( bitcoin-cli -regtest validateaddress $NEWADDRESS | awk -F '\"' '/pubkey/ { print $4 }' ) REDEEMSCRIPT=$( printf "21%sac" $PUBKEY ) # creating the hash of the REDEEMSCRIPT printf $( echo $REDEEMSCRIPT | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_fn.hex openssl dgst -sha256 -binary <tmp_fn.hex >tmp_sha256.hex REDEEMSCRIPTHASH=$( openssl dgst -ripemd160 <tmp_sha256.hex | cut -d " " -f2 ) # convert redeemscripthash to bitcoin address (testnet!), with "C4" Prefix PRFX_REDEEMSCRIPT=$( printf "c4%s" $REDEEMSCRIPTHASH ) # double sha256 the hex value printf $( echo $PRFX_REDEEMSCRIPT | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_fn.hex openssl dgst -sha256 -binary <tmp_fn.hex >tmp_sha256.hex openssl dgst -sha256 <tmp_sha256.hex | cut -d " " -f2 >tmp_dsha256.txt # checksum and append result=$( cat tmp_dsha256.txt | cut -b 1-8 ) result=$( printf "%s%s" $PRFX_REDEEMSCRIPT $result | tr "[:lower:]" "[:upper:]" ) # and base58 base58str="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" REDEEMSCRIPTADDR=$( dc -e "16i $result [3A ~r d0<x]dsxx +f" | while read -r n; do j=$(( n + 1 )) echo $base58str | cut -b $j done | tr -d '\n' ) bitcoin-cli -regtest importaddress "$REDEEMSCRIPTADDR" p2sh bitcoin-cli -regtest importaddress "$REDEEMSCRIPTADDR" rescan bitcoin-cli -regtest validateaddress "$REDEEMSCRIPTADDR" bitcoin-cli -regtest listunspent
贖回腳本的地址將在測試網上以“2”開頭。現在創建資金交易。搜尋一個我們可以使用的 UTXO,並記下 tx 和 vout。
UTXO_TXID=d260e120647360dcfc8606e242c6389acece3ee585d5e0d76a26b87b08b322e0 UTXO_VOUT=0 VALUE=49.9997 RAW_TX=$( bitcoin-cli -regtest createrawtransaction '''[{"txid":"'$UTXO_TXID'","vout":'$UTXO_VOUT'}]''' '''{"'$REDEEMSCRIPTADDR'":'$VALUE'}''' ) bitcoin-cli -regtest decoderawtransaction $RAW_TX SIGNED_TX=$( bitcoin-cli -regtest signrawtransaction $RAW_TX | awk -F '\"' '{ print $4 }' ) bitcoin-cli -regtest decoderawtransaction $SIGNED_TX UTXO_TXID=$( bitcoin-cli -regtest sendrawtransaction $SIGNED_TX ) bitcoin-cli -regtest getrawmempool bitcoin-cli -regtest generate 1 # verify new address has funds: bitcoin-cli -regtest validateaddress "$REDEEMSCRIPTADDR" bitcoin-cli -regtest getreceivedbyaddress "$REDEEMSCRIPTADDR"
此時,發送資金交易。現在是支出 tx,我們需要一個新地址來接收來自 P2SH 地址的資金:
RCVADDRESS=$( bitcoin-cli -regtest getnewaddress ) echo $RCVADDRESS # verify that tx from $REDEEMSCRIPTADDR has funds RAW_TX=$( bitcoin-cli -regtest getrawtransaction $UTXO_TXID ) bitcoin-cli -regtest decoderawtransaction $RAW_TX # to send funds from $REDEEMSCRIPTADDR to a new address, need the privkey: NEWADDRESS_PRIVKEY=$( bitcoin-cli -regtest dumpprivkey $NEWADDRESS )
創建原始交易,簽名並發送(可能需要更新金額):
UTXO_VOUT=0 UTXO_OUTPUT_SCRIPT=$( bitcoin-cli -regtest validateaddress "$REDEEMSCRIPTADDR" | awk -F '\"' '/scriptPubKey/ { print $4 }' ) VALUE=7.7699 RAW_TX=$( bitcoin-cli -regtest createrawtransaction '''[{"txid":"'$UTXO_TXID'","vout":'$UTXO_VOUT'}]''' '''{"'$RCVADDRESS'":'$VALUE'}''' ) bitcoin-cli -regtest decoderawtransaction $RAW_TX SIGNED_TX=$( bitcoin-cli -regtest signrawtransaction $RAW_TX '''[{"txid": "'$UTXO_TXID'","vout": '$UTXO_VOUT',"scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'","redeemScript": "'$REDEEMSCRIPT'"}]''' '''["'$NEWADDRESS_PRIVKEY'"]''' | awk -F '\"' '{ print $4 }' ) UTXO_TXID=$( bitcoin-cli -regtest sendrawtransaction $SIGNED_TX ) bitcoin-cli -regtest getrawmempool bitcoin-cli -regtest generate 1
此時我可以看到,我新生成的 RCVADDRESS 包含值(bitcoin-cli -regtest listunspent | grep -A5 -B5 $RCVADDRESS):
…“金額”:7.76990000
我有一個較小的觀察結果,但對我來說還不是很清楚:scriptsig 在最終的 tx 中發生了變化。它有簽名,後面應該跟著redeemscript。此兌換腳本以這種方式“擴展”:
23210355ef94c6e097752f303d685e4011b9dba8c1cd1382f8fa68bf2de0d523f18fffac
開頭的 23 將是以下公鑰的長度指示符,但這將包括“ac”……不確定,為什麼比特幣核心以這種方式擴展它。
現在我可以使用簡單的 P2SH,我可以嘗試 SegWit-P2SH :-)