259 lines
8.2 KiB
Bash
Executable File
259 lines
8.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
# Sends a `zcash-cli` command to a Zebra and zcashd instance,
|
|
# and compares the results.
|
|
#
|
|
# Uses the configured `zcash-cli` RPC port,
|
|
# and the `zebrad` port supplied on the command-line.
|
|
|
|
function usage()
|
|
{
|
|
echo "Usage:"
|
|
echo "$0 zebra-rpc-port rpc-name [rpc-args... ]"
|
|
}
|
|
|
|
# Override the commands used by this script using these environmental variables:
|
|
ZCASH_CLI="${ZCASH_CLI:-zcash-cli}"
|
|
DIFF="${DIFF:-diff --unified --color=always}"
|
|
JQ="${JQ:-jq}"
|
|
# Zcashd authentication modes:
|
|
# - Use `-rpccookiefile=your/cookie/file` for a cookie file.
|
|
# - Use `-rpcpassword=your-password` for a password.
|
|
ZCASHD_EXTRA_ARGS="${ZCASHD_EXTRA_ARGS:-}"
|
|
|
|
if [ $# -lt 2 ]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
ZEBRAD_RPC_PORT=$1
|
|
shift
|
|
|
|
# Use an easily identified temp directory name,
|
|
# but fall back to the default temp name if `mktemp` does not understand `--suffix`.
|
|
ZCASH_RPC_TMP_DIR=$(mktemp --suffix=.rpc-diff -d 2>/dev/null || mktemp -d)
|
|
|
|
ZEBRAD_RELEASE_INFO="$ZCASH_RPC_TMP_DIR/first-check-getinfo.json"
|
|
ZCASHD_RELEASE_INFO="$ZCASH_RPC_TMP_DIR/second-check-getinfo.json"
|
|
|
|
echo "Checking first node release info..."
|
|
$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" getinfo > "$ZEBRAD_RELEASE_INFO"
|
|
|
|
ZEBRAD=$(cat "$ZEBRAD_RELEASE_INFO" | grep '"subversion"' | cut -d: -f2 | cut -d/ -f2 | \
|
|
tr 'A-Z' 'a-z' | sed 's/magicbean/zcashd/ ; s/zebra$/zebrad/')
|
|
|
|
echo "Checking second node release info..."
|
|
$ZCASH_CLI $ZCASHD_EXTRA_ARGS getinfo > "$ZCASHD_RELEASE_INFO"
|
|
|
|
ZCASHD=$(cat "$ZCASHD_RELEASE_INFO" | grep '"subversion"' | cut -d: -f2 | cut -d/ -f2 | \
|
|
tr 'A-Z' 'a-z' | sed 's/magicbean/zcashd/ ; s/zebra$/zebrad/')
|
|
|
|
echo "Connected to $ZEBRAD (port $ZEBRAD_RPC_PORT) and $ZCASHD ($ZCASH_CLI zcash.conf port)."
|
|
|
|
echo
|
|
|
|
ZEBRAD_BLOCKCHAIN_INFO="$ZCASH_RPC_TMP_DIR/$ZEBRAD-check-getblockchaininfo.json"
|
|
ZCASHD_BLOCKCHAIN_INFO="$ZCASH_RPC_TMP_DIR/$ZCASHD-check-getblockchaininfo.json"
|
|
|
|
echo "Checking $ZEBRAD network and tip height..."
|
|
$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" getblockchaininfo > "$ZEBRAD_BLOCKCHAIN_INFO"
|
|
|
|
ZEBRAD_NET=$(cat "$ZEBRAD_BLOCKCHAIN_INFO" | grep '"chain"' | cut -d: -f2 | tr -d ' ,"')
|
|
ZEBRAD_HEIGHT=$(cat "$ZEBRAD_BLOCKCHAIN_INFO" | grep '"blocks"' | cut -d: -f2 | tr -d ' ,"')
|
|
|
|
echo "Checking $ZCASHD network and tip height..."
|
|
$ZCASH_CLI $ZCASHD_EXTRA_ARGS getblockchaininfo > "$ZCASHD_BLOCKCHAIN_INFO"
|
|
|
|
ZCASHD_NET=$(cat "$ZCASHD_BLOCKCHAIN_INFO" | grep '"chain"' | cut -d: -f2 | tr -d ' ,"')
|
|
ZCASHD_HEIGHT=$(cat "$ZCASHD_BLOCKCHAIN_INFO" | grep '"blocks"' | cut -d: -f2 | tr -d ' ,"')
|
|
|
|
echo
|
|
|
|
if [ "$ZEBRAD_NET" != "$ZCASHD_NET" ]; then
|
|
echo "WARNING: comparing RPC responses from different networks:"
|
|
echo "$ZEBRAD is on: $ZEBRAD_NET"
|
|
echo "$ZCASHD is on: $ZCASHD_NET"
|
|
echo
|
|
fi
|
|
|
|
if [ "$ZEBRAD_HEIGHT" -ne "$ZCASHD_HEIGHT" ]; then
|
|
echo "WARNING: comparing RPC responses from different heights:"
|
|
echo "$ZEBRAD is at: $ZEBRAD_HEIGHT"
|
|
echo "$ZCASHD is at: $ZCASHD_HEIGHT"
|
|
echo
|
|
fi
|
|
|
|
ZEBRAD_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZEBRAD-$ZEBRAD_NET-$ZEBRAD_HEIGHT-$1.json"
|
|
ZCASHD_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZCASHD-$ZCASHD_NET-$ZCASHD_HEIGHT-$1.json"
|
|
|
|
echo "Request:"
|
|
echo "$@"
|
|
echo
|
|
|
|
echo "Querying $ZEBRAD $ZEBRAD_NET chain at height >=$ZEBRAD_HEIGHT..."
|
|
time $ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" "$@" > "$ZEBRAD_RESPONSE"
|
|
echo
|
|
|
|
echo "Querying $ZCASHD $ZCASHD_NET chain at height >=$ZCASHD_HEIGHT..."
|
|
time $ZCASH_CLI $ZCASHD_EXTRA_ARGS "$@" > "$ZCASHD_RESPONSE"
|
|
echo
|
|
|
|
echo
|
|
|
|
echo "Response diff between $ZEBRAD and $ZCASHD:"
|
|
|
|
$DIFF "$ZEBRAD_RESPONSE" "$ZCASHD_RESPONSE" \
|
|
&& ( \
|
|
echo "RPC responses were identical"; \
|
|
echo ; \
|
|
echo "$ZEBRAD_RESPONSE:"; \
|
|
cat "$ZEBRAD_RESPONSE"; \
|
|
)
|
|
|
|
EXIT_STATUS=$?
|
|
|
|
# Consistency checks between RPCs
|
|
#
|
|
# TODO:
|
|
# - sum of getaddressutxos.satoshis equals getaddressbalance
|
|
# - set of getaddressutxos.txid is a subset of getaddresstxids <addresses> 1 <max height>
|
|
# - getblockchaininfo.bestblockhash equals getbestblockhash
|
|
|
|
if [ "$1" == "getaddressutxos" ]; then
|
|
set "getaddressbalance" "$2"
|
|
elif [ "$1" == "getrawmempool" ]; then
|
|
# Call `getrawmempool` again as a dummy request (this script isn't set up to do multiple cross-check calls)
|
|
set "getrawmempool"
|
|
else
|
|
exit $EXIT_STATUS
|
|
fi
|
|
|
|
ZEBRAD_CHECK_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZEBRAD-$ZEBRAD_NET-$ZEBRAD_HEIGHT-$1.json"
|
|
ZCASHD_CHECK_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZCASHD-$ZCASHD_NET-$ZCASHD_HEIGHT-$1.json"
|
|
|
|
echo
|
|
|
|
echo "Cross-checking request:"
|
|
echo "$@"
|
|
echo
|
|
|
|
echo "Querying $ZEBRAD $ZEBRAD_NET chain at height >=$ZEBRAD_HEIGHT..."
|
|
$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" "$@" > "$ZEBRAD_CHECK_RESPONSE"
|
|
|
|
echo "Querying $ZCASHD $ZCASHD_NET chain at height >=$ZCASHD_HEIGHT..."
|
|
$ZCASH_CLI $ZCASHD_EXTRA_ARGS "$@" > "$ZCASHD_CHECK_RESPONSE"
|
|
|
|
echo
|
|
|
|
echo "$1 diff between $ZEBRAD and $ZCASHD:"
|
|
|
|
$DIFF "$ZEBRAD_CHECK_RESPONSE" "$ZCASHD_CHECK_RESPONSE" \
|
|
&& ( \
|
|
echo "RPC check responses were identical"; \
|
|
echo ; \
|
|
echo "$ZEBRAD_CHECK_RESPONSE:"; \
|
|
cat "$ZEBRAD_CHECK_RESPONSE"; \
|
|
)
|
|
|
|
CHECK_EXIT_STATUS=$?
|
|
|
|
if [ "$1" == "getaddressbalance" ]; then
|
|
echo
|
|
|
|
echo "Extracting getaddressbalance.balance..."
|
|
|
|
ZEBRAD_NUM_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZEBRAD-$ZEBRAD_NET-$ZEBRAD_HEIGHT-getaddressbalance-num.txt"
|
|
ZCASHD_NUM_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZCASHD-$ZCASHD_NET-$ZCASHD_HEIGHT-getaddressbalance-num.txt"
|
|
|
|
cat "$ZEBRAD_CHECK_RESPONSE" | $JQ '.balance' > "$ZEBRAD_NUM_RESPONSE"
|
|
cat "$ZCASHD_CHECK_RESPONSE" | $JQ '.balance' > "$ZCASHD_NUM_RESPONSE"
|
|
|
|
echo "Summing getaddressutxos.satoshis..."
|
|
|
|
ZEBRAD_SUM_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZEBRAD-$ZEBRAD_NET-$ZEBRAD_HEIGHT-getaddressutxos-sum.txt"
|
|
ZCASHD_SUM_RESPONSE="$ZCASH_RPC_TMP_DIR/$ZCASHD-$ZCASHD_NET-$ZCASHD_HEIGHT-getaddressutxos-sum.txt"
|
|
|
|
cat "$ZEBRAD_RESPONSE" | $JQ 'map(.satoshis) | add // 0' > "$ZEBRAD_SUM_RESPONSE"
|
|
cat "$ZCASHD_RESPONSE" | $JQ 'map(.satoshis) | add // 0' > "$ZCASHD_SUM_RESPONSE"
|
|
|
|
echo
|
|
|
|
echo "Balance diff between $ZEBRAD and $ZCASHD:"
|
|
echo "(for both getaddressbalance and getaddressutxos)"
|
|
|
|
$DIFF --from-file="$ZEBRAD_NUM_RESPONSE" "$ZCASHD_NUM_RESPONSE" \
|
|
"$ZEBRAD_SUM_RESPONSE" "$ZCASHD_SUM_RESPONSE" \
|
|
&& ( \
|
|
echo "RPC balances were identical"; \
|
|
echo ; \
|
|
echo "$ZEBRAD_NUM_RESPONSE:"; \
|
|
cat "$ZEBRAD_NUM_RESPONSE"; \
|
|
)
|
|
|
|
COMPARE_EXIT_STATUS=$?
|
|
|
|
if [ $COMPARE_EXIT_STATUS -ne 0 ]; then
|
|
exit $COMPARE_EXIT_STATUS
|
|
fi
|
|
fi
|
|
|
|
if [ "$1" == "getrawmempool" ] && [ $CHECK_EXIT_STATUS != 0 ]; then
|
|
set TRANSACTION_ID
|
|
set TRANSACTION_HEX_FILE
|
|
set TRANSACTION_DECODED
|
|
|
|
ZEBRAD_TRANSACTION_IDS=$(cat "$ZEBRAD_RESPONSE" | $JQ -r 'join(" ")')
|
|
ZCASHD_TRANSACTION_IDS=$(cat "$ZCASHD_RESPONSE" | $JQ -r 'join(" ")')
|
|
|
|
echo
|
|
echo "# Dumping transactions from zebrad mempool"
|
|
echo
|
|
|
|
for TRANSACTION_ID in $ZEBRAD_TRANSACTION_IDS; do
|
|
TRANSACTION_HEX_FILE="$ZCASH_RPC_TMP_DIR/$ZEBRAD-$ZEBRAD_NET-$ZEBRAD_HEIGHT-$TRANSACTION_ID.json"
|
|
|
|
$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" getrawtransaction $TRANSACTION_ID 0 > $TRANSACTION_HEX_FILE
|
|
|
|
echo "## Displaying transaction $TRANSACTION_ID from zebrad"
|
|
echo
|
|
|
|
# read the proposal data from a file, to avoid command-line length limits
|
|
TRANSACTION_DECODED=`cat "$TRANSACTION_HEX_FILE" | \
|
|
$ZCASH_CLI $ZCASHD_EXTRA_ARGS -stdin decoderawtransaction`
|
|
|
|
echo $TRANSACTION_DECODED | $JQ
|
|
echo
|
|
done
|
|
|
|
echo
|
|
echo "# Dumping transactions from zcashd mempool"
|
|
echo
|
|
|
|
for TRANSACTION_ID in $ZCASHD_TRANSACTION_IDS; do
|
|
TRANSACTION_HEX_FILE="$ZCASH_RPC_TMP_DIR/$ZCASHD-$ZCASHD_NET-$ZCASHD_HEIGHT-TRANSACTION_HEX-$TRANSACTION_ID.json"
|
|
|
|
$ZCASH_CLI $ZCASHD_EXTRA_ARGS getrawtransaction $TRANSACTION_ID 0 > $TRANSACTION_HEX_FILE
|
|
|
|
echo "## Displaying transaction $TRANSACTION_ID from zcashd"
|
|
echo
|
|
|
|
# read the proposal data from a file, to avoid command-line length limits
|
|
TRANSACTION_DECODED=`cat "$TRANSACTION_HEX_FILE" | \
|
|
$ZCASH_CLI $ZCASHD_EXTRA_ARGS -stdin decoderawtransaction`
|
|
|
|
echo $TRANSACTION_DECODED | $JQ
|
|
echo
|
|
done
|
|
|
|
fi
|
|
|
|
echo "Full RPC output is in $ZCASH_RPC_TMP_DIR"
|
|
|
|
if [ $EXIT_STATUS -ne 0 ]; then
|
|
exit $EXIT_STATUS
|
|
else
|
|
exit $CHECK_EXIT_STATUS
|
|
fi
|