If you’ve followed our complete guide series, you’ve already compiled Bitcoin Core from source, configured an RPC node, and synced the blockchain. This tutorial builds on that foundation to execute a Bitcoin transaction using your node.
Note: As covered previously, Bitcoin Core and its RPC APIs evolve rapidly. This guide uses Bitcoin v0.18 on Ubuntu.
Step-by-Step Bitcoin Transaction Process
Here’s the core workflow for creating transactions:
- Retrieve UTXOs (Unspent Transaction Outputs)
- Create Raw Transaction
- Sign the Transaction
- Broadcast to Network
1. Retrieving UTXOs
The critical first step involves fetching spendable outputs using the listunspent
RPC method. Many users encounter issues here—the API might return empty results because:
👉 Bitcoin wallets only track UTXOs for addresses they control. If your address wasn’t generated by or imported into the node’s wallet, the node won’t recognize its UTXOs.
Wallet Address Association Explained
Early Bitcoin versions used an account-based model, where addresses belonged to named accounts. Modern versions (v0.17+) replaced this with:
- Wallet-level management (identified by
name
) - Label-based address grouping within wallets
An address is unassociated if:
– It wasn’t generated by your wallet (getnewaddress
)
– Its private key wasn’t imported (importprivkey
)
How to Associate an Address
Import the private key using:
bash
bitcoin-cli importprivkey "your_private_key" "" true
The rescan
parameter rebuilds the UTXO index—this may take hours for addresses with long histories.
Alternative UTXO Access Methods
- Transaction Indexing: Launch node with
txindex=1
(required for block explorers) - Watch-only Wallets: Import addresses without private keys (read-only)
Most tutorials use
getnewaddress
to avoid these complexities since wallet-generated addresses are automatically associated.
2. Creating Raw Transactions
Use createrawtransaction
to draft transactions. Key considerations:
- Inputs must exceed outputs (the difference becomes miner fees)
- Missing change addresses create overpayment fees (use
fundrawtransaction
for automated change)
Example:
bash
bitcoin-cli createrawtransaction '[{"txid":"input_txid","vout":0}]' '{"recipient_address":amount}'
This outputs an unsigned hex string.
3. Transaction Signing
Two signing methods exist in v0.18:
Method | Command | Requires |
---|---|---|
Wallet Signing | signrawtransactionwithwallet |
Imported private key |
Manual Signing | signrawtransactionwithkey |
Private key provided |
Successful signing returns:
json
{
"hex": "signed_hex",
"complete": true
}
Warning:
"complete":true
doesn’t guarantee validity. Always verifyPrevTX
parameters if broadcasting fails.
4. Broadcasting Transactions
Submit signed transactions with:
bash
bitcoin-cli sendrawtransaction "signed_hex"
Common Broadcasting Issues
- High Fees: Add
allowhighfees=true
for transactions without change addresses - Missing Inputs: Usually indicates signature errors (recheck step 3)
👉 For test environments, use regtest mode to avoid real asset loss. Below is a complete regtest workflow:
Complete Regtest Example
“`bash
Start private chain
bitcoind -printtoconsole -regtest
Generate blocks to fund wallet
bitcoin-cli -regtest generatetoaddress 101 $(bitcoin-cli -regtest getnewaddress)
Create transaction
bitcoin-cli -regtest createrawtransaction \
‘[{“txid”:”funding_txid”,”vout”:0}]’ \
‘{“recipient_address”:20}’
Sign and broadcast
bitcoin-cli -regtest signrawtransactionwithwallet “unsigned_hex”
bitcoin-cli -regtest sendrawtransaction “signed_hex”
“`
Pro Tips
- Configuration Consistency: Ensure
bitcoin.conf
and CLI parameters don’t conflict - RPC Authentication: Bitcoin Core uses HTTP Basic Auth (username/password in
bitcoin.conf
) - Testing Priority: Always use regtest mode for development—instant mining and zero risk
Frequently Asked Questions
Why can’t my node see UTXOs for my address?
The address must be either:
– Generated by your wallet (getnewaddress
)
– Imported with its private key (importprivkey
)
How do I avoid excessive miner fees?
Use fundrawtransaction
to automatically handle change addresses instead of manual createrawtransaction
.
What does “complete”:true mean in signing results?
It confirms the node accepted your signing parameters, but doesn’t validate transaction feasibility. Always cross-check inputs.
Why does my transaction fail to broadcast?
Common causes:
– Insufficient fee (use estimatesmartfee
)
– Invalid signatures (re-sign with correct PrevTX
data)
– High fee without allowhighfees
flag
Can I use curl instead of bitcoin-cli?
Yes! All CLI commands are JSON-RPC calls. Example: