Overview

Use the following commands to simulate common scenarios to better understand the protocol. You can create breakpoints in various files and step through the code to understand code flows.

Setup: start two independent nodes

Fresh directories for this test.

TEST_ROOT=$(mktemp -d /tmp/bitcoin-rpc-test.XXXXXX)
A_DIR="$TEST_ROOT/a"
B_DIR="$TEST_ROOT/b"
mkdir -p "$A_DIR" "$B_DIR"

bitcoind -regtest -datadir="$A_DIR" -daemon \
  -port=18444 -rpcport=18443 \
  -listen=1 -connect=0 -dnsseed=0

bitcoind -regtest -datadir="$B_DIR" -daemon \
  -port=19444 -rpcport=19443 \
  -listen=1 -connect=0 -dnsseed=0

# Convenience functions. Authentication uses each node's local cookie.
a() { bitcoin-cli -regtest -datadir="$A_DIR" -rpcport=18443 "$@"; }
b() { bitcoin-cli -regtest -datadir="$B_DIR" -rpcport=19443 "$@"; }

a -rpcwait getblockchaininfo
b -rpcwait getblockchaininfo

# Connect A to B using B's P2P port, not its RPC port.
a addnode "127.0.0.1:19444" "add"
a getpeerinfo

Create wallets and fund A

a createwallet "alice"
b createwallet "bob"

aw() { a -rpcwallet=alice "$@"; }
bw() { b -rpcwallet=bob "$@"; }

MINER_ADDR=$(aw getnewaddress "mining")

# Bootstrap funds; coinbase outputs need maturity before spending.
a generatetoaddress 101 "$MINER_ADDR"

aw getbalances

# Wait until B has the same bootstrap chain.
BOOTSTRAP_TIP=$(a getbestblockhash)
until [ "$(b getbestblockhash)" = "$BOOTSTRAP_TIP" ]; do
  sleep 1
done

Create one transaction sending to self

SELF_ADDR=$(aw getnewaddress "self")

TX_SELF=$(aw -named sendtoaddress \
  address="$SELF_ADDR" amount=1 fee_rate=2)

aw gettransaction "$TX_SELF"
a getmempoolentry "$TX_SELF"

Create one transaction sending to another wallet

BOB_ADDR=$(bw getnewaddress "from-alice")

TX_OTHER=$(aw -named sendtoaddress \
  address="$BOB_ADDR" amount=2 fee_rate=2)

a getrawmempool

Create a block containing the mempool transactions

b setnetworkactive false

BLOCK_HASH=$(a generatetoaddress 1 "$MINER_ADDR" | jq -r '.[0]')

a getblock "$BLOCK_HASH" 1 |
  jq '{hash, height, nTx, tx}'`

Transfer the block from A to B and verify chain growth

Fetch the entire serialized block from A.

BLOCK_HEX=$(a getblock "$BLOCK_HASH" 0)

Submit it through B’s RPC interface.

b submitblock "$BLOCK_HEX"

Verify that B activated it.

test "$(b getbestblockhash)" = "$BLOCK_HASH" &&
  echo "B accepted and activated A's block"

b getblockcount
b getblock "$BLOCK_HASH" 1 | jq '{height, confirmations, nTx, tx}'
bw gettransaction "$TX_OTHER" | jq '{amount, confirmations}'

For a real P2P propagation test, reconnect B and mine another block on A:

b setnetworkactive true

Wait for A’s persistent addnode connection to reconnect.

until [ "$(a getconnectioncount)" -gt 0 ]; do
  sleep 1
done

NEXT_HASH=$(a generatetoaddress 1 "$MINER_ADDR" | jq -r '.[0]')

until [ "$(b getbestblockhash)" = "$NEXT_HASH" ]; do
  sleep 1
done

b getblockcount    # 103