I had a bunch of small transactions accumulated from mining, change, the various free-bitcoin sources, etc. and wanted to consolidate all of them onto one address. I tried sweeping them with Armory, but it choked on the transaction when I went to offline-sign it. Even before that, though, it said it was going to cost
BTC0.024 to send, which seems a bit out of line. I tried importing the privkeys to bitcoind and sending them directly from there, but it also insisted on a hefty fee. I tried the
bitcoin-nftf fork; it didn't work any better.
I then tried crafting a raw transaction of 66 inputs totaling about
BTC0.025, one output, and a
BTC0.0001 fee. bitcoind accepted it; after about three hours, it was confirmed. I'm not in a hurry, so this is acceptable. If you need faster turnaround, this script is probably not for you.
What follows is a shell script to automate this process. You pick one or more source addresses from your wallet and a destination address that may or may not be in your wallet. The fee is up to you. By default, it will sweep inputs with at least 6 confirmations to the destination address; if you're sweeping from an address that receives generated coin from P2Pool, you'll probably want to include "-c 120" to avoid trying to send immature coin. The only dependency is a running bitcoind (0.7 or later). The rest is fairly standard shell-script programming, with grep, sed, tr, and bc doing most of the munging.
#!/bin/bash
# CheapSweep v0.1
# Scott Alfter
#
[email protected]# Donations: 1TipSAXbE6owdU24bcBDJKmL8JRxQe5Yu
help()
{
cat <
&2
Usage: $0 [options] -d destaddr addr1 addr2 ...
options: -d|--destaddr destination address (REQUIRED)
-f|--fee fee to subtract from inputs (default: 0)
-c|--confirm minimum confirmations to include input (default: 6)
-n|--no-send don't send; dump the raw transaction to stdout
EOF
}
fee=0.0
minconfirm=6
OPTS=$(getopt -o d:f:c:hn --long destaddr:,fee:,confirm:,help,no-send -- "$@")
eval set -- "$OPTS"
while true; do
case "$1" in
-d|--destaddr) destaddr="$2"; shift 2;;
-f|--fee) fee="$2"; shift 2;;
-c|--confirm) minconfirm="$2"; shift 2;;
-n|--no-send) nosend=1; shift 1;;
-h|--help) help; exit 1;;
--) shift; break;;
*) echo "Internal error"; exit 1;;
esac
done
if [ "$destaddr" == "" ]
then
help
exit 1
fi
addrs=$(echo $* | sed "s/^/[\"/;s/ /\",\"/g;s/\$/\"]/")
total=$(bitcoind listunspent $minconfirm 21000000 $addrs | grep amount | sed "s/.*: //;s/,//" | tr "\n" "+" | sed "s/+\$/\n/" | bc)
total=$(echo $total - $fee | bc)
tx=$(bitcoind signrawtransaction $(bitcoind createrawtransaction [$(bitcoind listunspent $minconfirm 21000000 $addrs | egrep "txid|vout" | sed "s/\"txid/{\"txid/;s/\"vout\" : \([0-9]*\),/\"vout\" : \1},/" | tr -d "\n" | tr -d " " | sed "s/,\$//")] {\"$destaddr\":$total}) | grep \"hex\" | sed "s/.*: \"//;s/\",//")
if [ "$nosend" != "" ]
then
echo $tx
else
bitcoind sendrawtransaction $tx
fi