#!/bin/bash
PRIVATE_KEY_1="39dc0a9f0b185a2ee56349691f34716e6e0cda06a7f9707742ac113c4e2317bf"
PRIVATE_KEY_2="5077ccd9c558b7d04a81920d38aa11b4a9f9de3b23fa645c3ef28039920fd6d"
REDEEM_SCRIPT_HEX="5221032ff8c5df0bc00fe1ac2319c3b8070d6d1e04cfbf4fedda499ae7b775185ad53b21039bbca824f89ebc44c5b01f9806658316a6b2440023117c3c03a4975b04dd5652ae"
INPUT_TXID="0000000000000000000000000000000000000000000000000000000000000000"
INPUT_VOUT=0
OUTPUT_ADDRESS="325UUecEQuyrTd28Xs2hvAxdAjHM7XzqVF"
VALUE="0.001"
SEQUENCE="0xffffffff"
UNSIGNED_TX=$(bitcoin-cli -regtest -rpcuser=alice -rpcpassword=password createrawtransaction '[{"txid":"'$INPUT_TXID'","vout":'$INPUT_VOUT',"sequence":'$SEQUENCE'}]' '{"'$OUTPUT_ADDRESS'":'$VALUE'}')
SIGNED_TX=$(bitcoin-cli -regtest -rpcuser=alice -rpcpassword=password signrawtransactionwithkey "$UNSIGNED_TX" '["'$PRIVATE_KEY_1'", "'$PRIVATE_KEY_2'"]' '[{"txid":"'$INPUT_TXID'","vout":'$INPUT_VOUT',"scriptPubKey":"'$REDEEM_SCRIPT_HEX'","redeemScript":"'$REDEEM_SCRIPT_HEX'"}]')
FINAL_TX=$(echo "$SIGNED_TX" | jq -r '.hex')
echo "$FINAL_TX" > out.txt
echo "Transaction successfully created and saved to out.txt"
What is wrong with my script
Top Answer/Comment:
There are a few issues with the provided Bash script for creating and signing a Bitcoin transaction using bitcoin-cli.
Here's a detailed breakdown of the problems and suggested fixes:
Private Key Format:
Issue: The PRIVATE_KEY_1 and PRIVATE_KEY_2 are provided as 64-character hexadecimal strings. However, bitcoin-cli expects private keys in Wallet Import Format (WIF), which typically starts with a K, L, or 5 and is Base58 encoded. Fix: Convert the hexadecimal private keys to WIF format. You can use tools like bitcoin-tool or online converters, but ensure you're operating in a secure environment to protect the keys.
Example Conversion Using bitcoin-cli:
# Convert HEX to WIF for PRIVATE_KEY_1
WIF_PRIVATE_KEY_1=$(bitcoin-cli -regtest dumpprivkey <address_associated_with_PRIVATE_KEY_1>)
# Convert HEX to WIF for PRIVATE_KEY_2
WIF_PRIVATE_KEY_2=$(bitcoin-cli -regtest dumpprivkey <address_associated_with_PRIVATE_KEY_2>)
Replace <address_associated_with_PRIVATE_KEY_1> and <address_associated_with_PRIVATE_KEY_2> with the actual Bitcoin addresses linked to your private keys.
Invalid INPUT_TXID:
Issue: The INPUT_TXID is set to all zeroes (0000...0000), which is not a valid transaction ID. This will cause the createrawtransaction command to fail because it references a non-existent transaction.
Fix: Use a valid transaction ID from your blockchain (especially since you're operating in regtest, ensure the transaction exists there).
Example:
INPUT_TXID="your_valid_txid_here"
ScriptPubKey Format:
Issue: The REDEEM_SCRIPT_HEX provided seems to be intended for a multisig setup, but ensure it matches the actual script of the UTXO you're trying to spend.
Fix: Verify that the REDEEM_SCRIPT_HEX corresponds correctly to the locking script of the UTXO. If it's a standard P2SH or P2WSH script, ensure the format aligns with expected patterns.
Deprecated signrawtransactionwithkey Command:
Issue: Depending on your bitcoin-cli version, the signrawtransactionwithkey command might be deprecated.
Fix: Use signrawtransactionwithkey if supported. Otherwise, consider using signrawtransactionwithwallet or updating your script according to the latest bitcoin-cli documentation.
Output Address Validation:
Issue: The OUTPUT_ADDRESS starts with 3, which isn't a standard prefix on regtest. On regtest, addresses typically start with different characters.
Regtest Prefixes:
Legacy addresses start with: m or n P2SH addresses start with: 2 Bech32 addresses start with: bcrt1
The address 325UUecEQuyrTd28Xs2hvAxdAjHM7XzqVF does NOT conform to standard regtest address formats.
Fix: Ensure the OUTPUT_ADDRESS is a valid address for your regtest environment. You can generate a new address using:
# Generate a new legacy address in regtest
bitcoin-cli -regtest getnewaddress "" legacy
# Generate a new P2SH address in regtest
bitcoin-cli -regtest getnewaddress "" p2sh
# Generate a new bech32 address in regtest
bitcoin-cli -regtest getnewaddress "" bech32
Replace the address 325UUecEQuyrTd28Xs2hvAxdAjHM7XzqVF with an address generated directly from your regtest Bitcoin node using the commands above.
Dependencies and Tools:
Issue: The script uses jq to parse JSON. Ensure that jq is installed on your system.
Fix: Install jq if it's not already present.
# sudo apt-get install jq
Sequence Number Usage:
Issue: The SEQUENCE is set to 0xffffffff, which is the default and might not be necessary unless you're implementing specific features like Replace-By-Fee (RBF).
Fix: If not needed, you can omit the sequence field in the input object.
Overall Script Enhancements:
Security: Avoid hardcoding private keys in scripts. Consider using environment variables or secure key management systems.
Error Handling: Add checks to ensure each command executes successfully before proceeding to the next step. This can help in debugging issues more effectively.
Example:
# Create raw transaction
UNSIGNED_TX=$(bitcoin-cli -regtest -rpcuser=alice -rpcpassword=password createrawtransaction '[{"txid":"'$INPUT_TXID'","vout":'$INPUT_VOUT'}]' '{"'$OUTPUT_ADDRESS'":'$VALUE'}')
if [ $? -ne 0 ]; then
echo "Failed to create raw transaction."
exit 1
fi
# Sign transaction
SIGNED_TX=$(bitcoin-cli -regtest -rpcuser=alice -rpcpassword=password signrawtransactionwithkey "$UNSIGNED_TX" '["'$WIF_PRIVATE_KEY_1'", "'$WIF_PRIVATE_KEY_2'"]' '[{"txid":"'$INPUT_TXID'","vout":'$INPUT_VOUT',"scriptPubKey":"'$REDEEM_SCRIPT_HEX'","redeemScript":"'$REDEEM_SCRIPT_HEX'"}]')
if [ $? -ne 0 ]; then
echo "Failed to sign transaction."
exit 1
fi
By addressing these issues, your script should function correctly in creating and signing a Bitcoin transaction within your regtest environment.