dash/qa/rpc-tests/txnmall.sh
Gavin Andresen 731b89b8b5 Track and report wallet transaction clones
Adds a "walletconflicts" array to transaction info; if
a wallet transaction is mutated, the alternate transaction id
or ids are reported there (usually the array will be empty).

Metadata from the original transaction is copied to the mutant,
so the transaction time and "from" account of the mutant are
reported correctly.
2014-02-14 18:13:42 -05:00

149 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Test block generation and basic wallet sending
if [ $# -lt 1 ]; then
echo "Usage: $0 path_to_binaries"
echo "e.g. $0 ../../src"
exit 1
fi
BITCOIND=${1}/bitcoind
CLI=${1}/bitcoin-cli
DIR="${BASH_SOURCE%/*}"
SENDANDWAIT="${DIR}/send.sh"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/util.sh"
D=$(mktemp -d test.XXXXX)
# Two nodes; one will play the part of merchant, the
# other an evil transaction-mutating miner.
D1=${D}/node1
CreateDataDir $D1 port=11000 rpcport=11001
B1ARGS="-datadir=$D1 -debug"
$BITCOIND $B1ARGS &
B1PID=$!
D2=${D}/node2
CreateDataDir $D2 port=11010 rpcport=11011
B2ARGS="-datadir=$D2 -debug"
$BITCOIND $B2ARGS &
B2PID=$!
trap "kill -9 $B1PID $B2PID; rm -rf $D" EXIT
# Wait until all four nodes are at the same block number
function WaitBlocks {
while :
do
sleep 1
BLOCKS1=$( GetBlocks $B1ARGS )
BLOCKS2=$( GetBlocks $B2ARGS )
if (( $BLOCKS1 == $BLOCKS2 ))
then
break
fi
done
}
# Wait until node has $N peers
function WaitPeers {
while :
do
PEERS=$( $CLI $1 getconnectioncount )
if (( "$PEERS" == $2 ))
then
break
fi
sleep 1
done
}
# Start with B2 connected to B1:
$CLI $B2ARGS addnode 127.0.0.1:11000 onetry
WaitPeers "$B1ARGS" 1
# 1 block, 50 XBT each == 50 XBT
$CLI $B1ARGS setgenerate true 1
WaitBlocks
# 100 blocks, 0 mature == 0 XBT
$CLI $B2ARGS setgenerate true 100
WaitBlocks
CheckBalance $B1ARGS 50
CheckBalance $B2ARGS 0
# restart B2 with no connection
$CLI $B2ARGS stop > /dev/null 2>&1
wait $B2PID
$BITCOIND $B2ARGS &
B2PID=$!
B2ADDRESS=$( $CLI $B2ARGS getnewaddress )
# Have B1 create two transactions; second will
# spend change from first, since B1 starts with only a single
# 50 bitcoin output:
$CLI $B1ARGS move "" "foo" 10.0
$CLI $B1ARGS move "" "bar" 10.0
TXID1=$( $CLI $B1ARGS sendfrom foo $B2ADDRESS 1.0 0)
TXID2=$( $CLI $B1ARGS sendfrom bar $B2ADDRESS 2.0 0)
# Mutate TXID1 and add it to B2's memory pool:
RAWTX1=$( $CLI $B1ARGS getrawtransaction $TXID1 )
RAWTX2=$( $CLI $B1ARGS getrawtransaction $TXID2 )
# ... mutate RAWTX1:
# RAWTX1 is hex-encoded, serialized transaction. So each
# byte is two characters; we'll prepend the first
# "push" in the scriptsig with OP_PUSHDATA1 (0x4c),
# and add one to the length of the signature.
# Fields are fixed; from the beginning:
# 4-byte version
# 1-byte varint number-of inputs (one in this case)
# 32-byte previous txid
# 4-byte previous output
# 1-byte varint length-of-scriptsig
# 1-byte PUSH this many bytes onto stack
# ... etc
# So: to mutate, we want to get byte 41 (hex characters 82-83),
# increment it, and insert 0x4c after it.
L=${RAWTX1:82:2}
NEWLEN=$( printf "%x" $(( 16#$L + 1 )) )
MUTATEDTX1=${RAWTX1:0:82}${NEWLEN}4c${RAWTX1:84}
# ... give mutated tx1 to B2:
MUTATEDTXID=$( $CLI $B2ARGS sendrawtransaction $MUTATEDTX1 )
echo "TXID1: " $TXID1
echo "Mutated: " $MUTATEDTXID
# Re-connect nodes, and have B2 mine a block
$CLI $B2ARGS addnode 127.0.0.1:11000 onetry
WaitPeers "$B1ARGS" 1
$CLI $B2ARGS setgenerate true 3
WaitBlocks
$CLI $B1ARGS setgenerate true 3
WaitBlocks
$CLI $B2ARGS stop > /dev/null 2>&1
wait $B2PID
$CLI $B1ARGS stop > /dev/null 2>&1
wait $B1PID
trap "" EXIT
echo "Done, bitcoind's shut down. To rerun/poke around:"
echo "${1}/bitcoind -datadir=$D1 -daemon"
echo "${1}/bitcoind -datadir=$D2 -daemon -connect=127.0.0.1:11000"
echo "To cleanup:"
echo "killall bitcoind; rm -rf test.*"
exit 0
echo "Tests successful, cleaning up"
rm -rf $D
exit 0