The error returned by the RPC is:
Unable to sign input, invalid stack size (possibly missing key)
It seems that this rpc alters the scriptSig of all of the inputs that were already signed.
The problem is very similar to #21151, which is already solved.
Here's an example of the broken signatures after signing:
--- 0_before.txt 2022-10-24 17:46:31.105518559 -0300
+++ 1_after.txt 2022-10-24 17:46:31.146517797 -0300
@@ -1,18 +1,18 @@
{
- "txid": "7107a82fd2d783d32e2926bf91b5dea5908203a3d81f8bb67b267f9aeab3c16d",
- "hash": "7107a82fd2d783d32e2926bf91b5dea5908203a3d81f8bb67b267f9aeab3c16d",
+ "txid": "b4b09eebed1f427f7ae80004ca1e55688567bc8e01af7608311c7d0a31ffcf83",
+ "hash": "685100e81d34140941b3c15af9598e0d2ffdbee92b3706c82561ff2232c94cbc",
"version": 1,
- "size": 406,
- "vsize": 406,
- "weight": 1624,
+ "size": 373,
+ "vsize": 291,
+ "weight": 1162,
"locktime": 0,
"vin": [
{
"txid": "c2afc743b00acb7a9a9cccc9e9b2751f0ae17206a9492dc0537ec72f44c7f6e0",
"vout": 1,
"scriptSig": {
- "asm": "0 30440220201b3d70770c2b325c8cac16593a4606cdcb29c094f67ec700d6aaadfdcc3bdf022057b70804b24d66664f1a82f7936773fbc3bcb15740a0e7b772ddf7bfe486b6fe[SINGLE|ANYONECANPAY] 3044022034eaf58c896885fc1597a848d268ad618e621b33be77bed67bcfa6180611ac31022073f947c7d2ebd81c1d52236030dd1a5d6b178c9361786ff9d6d3ef9740be1c76[SINGLE|ANYONECANPAY] 522103d28e83bfc9d2ab30f26f7b62ac4b64a932272ba124c6c4d29e901eaf8724aab7210366dc61fb53bce09777fe7c4766a55af9649cc26deb21b204ae6bf4e93413a46c2102439d6a6bc199460e4e0a6e5fdcb87162cafa5cae6ee4845d23d9dc5e840ffdb153ae",
- "hex": "004730440220201b3d70770c2b325c8cac16593a4606cdcb29c094f67ec700d6aaadfdcc3bdf022057b70804b24d66664f1a82f7936773fbc3bcb15740a0e7b772ddf7bfe486b6fe83473044022034eaf58c896885fc1597a848d268ad618e621b33be77bed67bcfa6180611ac31022073f947c7d2ebd81c1d52236030dd1a5d6b178c9361786ff9d6d3ef9740be1c76834c69522103d28e83bfc9d2ab30f26f7b62ac4b64a932272ba124c6c4d29e901eaf8724aab7210366dc61fb53bce09777fe7c4766a55af9649cc26deb21b204ae6bf4e93413a46c2102439d6a6bc199460e4e0a6e5fdcb87162cafa5cae6ee4845d23d9dc5e840ffdb153ae"
+ "asm": "0 0 522103d28e83bfc9d2ab30f26f7b62ac4b64a932272ba124c6c4d29e901eaf8724aab7210366dc61fb53bce09777fe7c4766a55af9649cc26deb21b204ae6bf4e93413a46c2102439d6a6bc199460e4e0a6e5fdcb87162cafa5cae6ee4845d23d9dc5e840ffdb153ae",
+ "hex": "00004c69522103d28e83bfc9d2ab30f26f7b62ac4b64a932272ba124c6c4d29e901eaf8724aab7210366dc61fb53bce09777fe7c4766a55af9649cc26deb21b204ae6bf4e93413a46c2102439d6a6bc199460e4e0a6e5fdcb87162cafa5cae6ee4845d23d9dc5e840ffdb153ae"
},
"sequence": 0
},
@@ -23,6 +23,10 @@
"asm": "",
"hex": ""
},
+ "txinwitness": [
+ "304402202dc3e510dc053dcdd29be701441337c93f6923686cc5ba4a915dbc17073dd26c02207aa8b76a447bde52b4cb1146781745826692d4484327f2a78a73818183e5f37f01",
+ "0379d702db49e91dd63127278c06ed99ef05b43d15f2583bb28b4f0e9b49b9f50c"
+ ],
"sequence": 0
}
],
I've prepared a bash script that reproduces it (I used hal to merge the transactions):
#!/bin/bash
#set -x
set -e
shopt -s expand_aliases
alias b-dae="~/opt/bitcoin/bin/bitcoind -datadir=$PWD -daemon=1"
alias b-cli="~/opt/bitcoin/bin/bitcoin-cli -datadir=$PWD"
declare -a privkeys
declare -a pubkeys
declare -a multisigs
declare -a addresses
declare -a redeemScripts
declare -a txs
declare -a scriptPubKeys
declare -a vouts
declare -a mergetxs
#parameters for the multisig addreesses
addresstype=legacy
multisig_n=2
multisig_m=3
multisig_count=1
#create the keypairs
for i in $(seq 0 $((multisig_count * multisig_m - 1)));do
KEYPAIR=$(hal key generate --regtest 2>/dev/null)
privkeys[$i]=$(echo $KEYPAIR | jq -r .wif_private_key)
pubkeys[$i]=$(echo $KEYPAIR | jq -r .public_key)
done
b-cli stop && sleep 5 || true
rm -rf regtest
b-dae
b-cli -rpcwait createwallet ""
echo
#create the multisig addresses
for i in $(seq 0 $((multisig_count - 1)));do
mspubkeys='['
sep=
for j in $(seq $((i * multisig_m)) $((i * multisig_m + multisig_m -1)));do
mspubkeys+="$sep\"${pubkeys[$j]}\""
sep=','
done
mspubkeys+=']'
echo b-cli createmultisig ${multisig_n} "${mspubkeys}" $addresstype
multisigs[$i]=$(b-cli -rpcwait createmultisig ${multisig_n} "${mspubkeys}" $addresstype)
addresses[$i]=$(echo "${multisigs[$i]}" | jq -r '.address')
redeemScripts[$i]=$(echo "${multisigs[$i]}" | jq -r '.redeemScript')
done
echo "pubkeys: ${pubkeys[@]}"
echo "privkeys: ${privkeys[@]}"
#generate enough blocks to unlock the reward
DEST=$(b-cli getnewaddress)
b-cli generatetoaddress 101 $DEST >/dev/null 2>&1
#send 1 btc to each multisig address
for i in $(seq 0 $((multisig_count - 1)));do
txs[$i]=$(b-cli sendtoaddress "${addresses[$i]}" 1)
scriptPubKeys[$i]=$(b-cli decoderawtransaction $(b-cli getrawtransaction ${txs[$i]})| jq -r ".vout[] .scriptPubKey | select(.address == \"${addresses[$i]}\") .hex")
vouts[$i]=$(b-cli decoderawtransaction $(b-cli getrawtransaction ${txs[$i]})| jq -r ".vout[] | select(.scriptPubKey.address == \"${addresses[$i]}\") .n")
#echo ${txs[$i]} ${scriptPubKeys[$i]}
b-cli generatetoaddress 1 $DEST >/dev/null 2>&1
done
echo
#each multisig sends its coins to a new wallet (destwallet) and signs the transaction using signrawtransactionwithkey
echo createwallet destwallet
b-cli createwallet destwallet
destaddress=$(b-cli -rpcwallet=destwallet getnewaddress)
echo unloadwallet destwallet
b-cli unloadwallet destwallet
for i in $(seq 0 $((multisig_count - 1)));do
echo "Sending utxo ${txs[$i]} to final address $destaddress"
tx=$(b-cli createrawtransaction "[{\"txid\":\"${txs[$i]}\",\"vout\":${vouts[$i]}}]" "[{\"$destaddress\":1}]")
prevtxs="[{\"txid\":\"${txs[$i]}\",\"vout\":${vouts[$i]},\"scriptPubKey\":\"${scriptPubKeys[$i]}\",\"redeemScript\":\"${redeemScripts[$i]}\",\"amount\":1}]"
#sign with keys one by one
for j in $(seq $((i * multisig_m)) $((i * multisig_m + multisig_n - 1)));do
tx=$(b-cli signrawtransactionwithkey $tx "[\"${privkeys[$j]}\"]" "$prevtxs" "SINGLE|ANYONECANPAY")
tx=$(echo $tx|jq -r '.hex')
done
mergetxs[$i]=$tx
done
echo
finalinputs=""
finaloutputs=""
#create the transaction to provide the funds to pay for the previous transactions
fee_input=$(b-cli listunspent|jq -r '.[0]')
fee_input_amount=$(echo $fee_input|jq -r '.amount')
fee=0.0001
change_amount=$(bc -l <<< "$fee_input_amount - $fee")
changeaddress=$(b-cli getnewaddress)
change_tx=$(b-cli createrawtransaction "[$fee_input]" "[{\"$changeaddress\":$change_amount}]")
mergetxs[$multisig_count]=$change_tx
sepin=""
sepout=""
#prepare a Json with the inputs, and another one with the outputs
for i in $(seq 0 $((multisig_count)));do
decodedtx=$(hal tx decode ${mergetxs[$i]})
inputno=$(echo $decodedtx| jq -r ".inputs | length -1")
for k in $(seq 0 $inputno);do
input=$(echo $decodedtx| jq -r ".inputs[$k] | del(.sequence)")
finalinputs+="$sepin$input"
sepin=","
done
outputno=$(echo $decodedtx| jq -r ".outputs | length -1")
for k in $(seq 0 $outputno);do
output=$(echo $decodedtx| jq -r ".outputs[$k] | del(.n)")
finaloutputs+="$sepout$output"
sepout=","
done
done
fulltx="
{
\"version\": 1,
\"locktime\": 0,
\"inputs\": [ $finalinputs ],
\"outputs\": [ $finaloutputs ]
}
"
echo $fulltx|jq >fulltx.txt
#create the transaction with all the inputs and outpts, and sign it using signrawtransactionwithwallet (fails...)
finaltx=$(echo $fulltx|jq|hal tx create 2>/dev/null)
b-cli decoderawtransaction $finaltx >0_before.txt
echo "tx BEFORE signrawtransactionwithwallet: $finaltx"
signedfinaltx=$(b-cli signrawtransactionwithwallet $finaltx)
echo "tx AFTER signrawtransactionwithwallet: $(echo $signedfinaltx|jq -r '.hex')"
b-cli decoderawtransaction $(echo $signedfinaltx|jq -r '.hex') >1_after.txt
diff -Naurwp 0_before.txt 1_after.txt >0.diff || true
signerror=$(echo $signedfinaltx|jq -r '.errors[0].error//empty')
if [ -n "$signerror" ];then
echo "Error signing with wallet ($signerror)"
exit -1
fi
senttx=$(b-cli sendrawtransaction $(echo $signedfinaltx|jq -r '.hex'))
b-cli gettransaction $senttx
b-cli generatetoaddress 1 $DEST >/dev/null 2>&1
b-cli gettransaction $senttx
I've tested with Bitcoin Core 23.0. Please let me know if there's anything else I can test.