Skip to content

Commit

Permalink
Add tx fee randomization
Browse files Browse the repository at this point in the history
  • Loading branch information
kristapsk committed Sep 8, 2021
1 parent 8430ddc commit c4a40e0
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 37 deletions.
7 changes: 6 additions & 1 deletion fake-coinjoin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ fi
# Values below 1000 are treated as estimated blocks to confirm,
# 1000 and above as sat/kB.
tx_fees=3
# [fraction, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200
txfee_factor=0.3
# Abort if TX fee per KB is above this number (satoshis)
absurd_fee_per_kb=150000
# Coin selection ("merge") algorithm.
Expand Down Expand Up @@ -43,9 +45,12 @@ else
exit 1
fi
fi
fee="$(randamount \
"$(bc_float_calc "$fee * (1 - $txfee_factor)")" \
"$(bc_float_calc "$fee * (1 + $txfee_factor)")")"
mempoolminfee="$(call_bitcoin_cli getmempoolinfo | jq_btc_float ".mempoolminfee")"
if is_btc_lt "$fee" "$mempoolminfee"; then
echo "Fee $fee is below minimum mempool fee, raising to $mempoolminfee"
echo "Feerate $fee is below minimum mempool fee, raising to $mempoolminfee"
fee="$mempoolminfee"
fi
if is_btc_gte "$fee" "$(bc_float_calc "$absurd_fee_per_kb * 0.00000001")"; then
Expand Down
17 changes: 17 additions & 0 deletions inc.common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,15 @@ function is_btc_lt()
$(echo "$2" | btc_amount_format | tr -d '.' | sed 's/^0*//' | sed 's/^$/0/') \
))
}
# is "$1" less than or equal to "$2"
function is_btc_lte()
{
(( \
$(echo "$1" | btc_amount_format | tr -d '.' | sed 's/^0*//' | sed 's/^$/0/') \
<= \
$(echo "$2" | btc_amount_format | tr -d '.' | sed 's/^0*//' | sed 's/^$/0/') \
))
}

function is_valid_bitcoin_address()
{
Expand Down Expand Up @@ -518,3 +527,11 @@ function bip21_get_param()
fi
fi
}

function randamount()
{
minamount="$1"
maxamount="$2"
diff="$(bc_float_calc "$maxamount - $minamount")"
bc_float_calc "$minamount + $RANDOM * $diff * 0.00003055581"
}
10 changes: 2 additions & 8 deletions randbtc.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /bin/bash
#!/usr/bin/env bash

. $(dirname $0)/inc.common.sh

Expand All @@ -7,10 +7,4 @@ if [ "$2" == "" ]; then
exit
fi

minamount=$1
maxamount=$2

diff=$(bc_float_calc "$maxamount - $minamount")

bc_float_calc "$minamount + $RANDOM * $diff * 0.00003055581"

randamount "$1" "$2"
29 changes: 19 additions & 10 deletions ricochet-send-from.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
. $(dirname $0)/inc.common.sh

if [ "$2" == "" ]; then
echo "Usage: $(basename $0) [options] source_address destination_address [hops [fee [sleeptime_min [sleeptime_max [hop_confirmations]]]]]"
echo "Usage: $(basename $0) [options] source_address destination_address [hops [txfee [sleeptime_min [sleeptime_max [hop_confirmations [txfee_factor]]]]]]"
echo "Where:"
echo " source_address - source address (all funds from that address will be send)"
echo " destination_address - destination address"
echo " hops - number of hops (default: 5)"
echo " fee - transaction fee per kW (default: \"estimatesmartfee 2\", currently $($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2) BTC)"
echo " txfee - average transaction fee per kvB (default: \"estimatesmartfee 2\", currently $($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2) BTC)"
echo " sleeptime_min - minimum sleep time between hops in seconds (default: 10)"
echo " sleeptime_max - maximum sleep time between hops in seconds (default: 15)"
echo " hop_confirmations - minimum number of confirmations between hops (default: 0)"
echo " txfee_factor - variance around average transaction fee, e.g. 0.00002000 fee, 0.2 var = fee is between 0.00001600 and 0.00002400 (default: 0.3)"
exit
fi

Expand All @@ -36,9 +37,9 @@ if [ "$3" != "" ]; then
hops=$3
fi
if [ "$4" != "" ]; then
fee=$4
txfee="$4"
else
fee=$($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2)
txfee="$($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2)"
fi
if [ "$6" != "" ]; then
sleeptime_min=$5
Expand All @@ -52,13 +53,19 @@ if [ "$7" != "" ]; then
else
hop_confirmations=0
fi
if [ "$8" != "" ]; then
txfee_factor="$8"
else
txfee_factor="0.3"
fi

# Force minimum required fee
fee="$(echo "$fee" | btc_amount_format)"
txfee_min="$(bc_float_calc "$txfee * (1 - $txfee_factor)")"
txfee_max="$(bc_float_calc "$txfee * (1 + $txfee_factor)")"
mempoolminfee="$(call_bitcoin_cli getmempoolinfo | jq_btc_float ".mempoolminfee")"
if is_btc_lt "$fee" "$mempoolminfee"; then
echo "Fee $fee is below minimum mempool fee, raising to $mempoolminfee"
fee="$mempoolminfee"
if is_btc_lt "$txfee_min" "$mempoolminfee"; then
echo "Feerate $txfee_min is below minimum mempool fee, raising minimum to $mempoolminfee"
txfee_min="$mempoolminfee"
fi

utxo="$(call_bitcoin_cli listunspent 0 999999 "[\"$source_address\"]" false)"
Expand All @@ -75,7 +82,8 @@ if [ "${#utxo_txids[@]}" == "0" ]; then
exit 2
fi

echo "Ricocheting from $source_address ($send_amount BTC) to $destination_address via $hops hops using $fee fee per KB"
txfee_average="$(bc_float_calc "($txfee_min + $txfee_max) * 0.5")"
echo "Ricocheting from $source_address ($send_amount BTC) to $destination_address via $hops hops using average $txfee_average fee per kvB"
read -p "Is this ok? " -n 1 -r
echo

Expand Down Expand Up @@ -138,6 +146,7 @@ for i in $(seq 0 $(( ${#utxo_txids[@]} - 1 )) ); do
needs_comma=1
done
rawtx_inputs="$rawtx_inputs]"
fee="$(randamount "$txfee_min" "$txfee_max")"
send_amount=$(bc_float_calc "$send_amount - $(bc_float_calc "$tx_vsize * $fee * 0.001")")
rawtx=$(call_bitcoin_cli createrawtransaction "$rawtx_inputs" "{\"${ricochet_addresses[$(( $hops - 1 ))]}\":$send_amount}")
signedtx=$(signrawtransactionwithwallet "$rawtx")
Expand Down Expand Up @@ -183,7 +192,7 @@ for i in $(seq 1 $(( $hops - 1)) | tac); do
tx_vsize=$(calc_tx_vsize 0 0 1 0 0 1)
fi
fi

fee="$(randamount "$txfee_min" "$txfee_max")"
send_amount=$(bc_float_calc "$send_amount - $(bc_float_calc "$tx_vsize * $fee * 0.001")")
echo -n "$j: ${ricochet_addresses[$i]} -> ${ricochet_addresses[$(( $i - 1 ))]} ($send_amount) - "
rawtx=$(call_bitcoin_cli createrawtransaction "[{\"txid\":\"$use_txid\",\"vout\":0}]" "{\"${ricochet_addresses[$(( $i - 1 ))]}\":$send_amount}")
Expand Down
53 changes: 35 additions & 18 deletions ricochet-send.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
. $(dirname $0)/inc.common.sh

if [ "$2" == "" ]; then
echo "Usage: $(basename $0) [options] amount destination_address [hops [fee [sleeptime_min [sleeptime_max [hop_confirmations]]]]"
echo "Usage: $(basename $0) [options] amount destination_address [hops [txfee [sleeptime_min [sleeptime_max [hop_confirmations [txfee_factor]]]]]]"
echo "Where:"
echo " amount - amount to send in BTC"
echo " destination_address - destination address"
echo " hops - number of hops (default: 5)"
echo " fee - transaction fee per kW (default: \"estimatesmartfee 2\", currently $($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2) BTC)"
echo " txfee - average transaction fee per kvB (default: \"estimatesmartfee 2\", currently $($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2) BTC)"
echo " sleeptime_min - minimum sleep time between hops in seconds (default: 10)"
echo " sleeptime_max - maximum sleep time between hops in seconds (default: 15)"
echo " hop_confirmations - minimum number of confirmations between hops (default: 0)"
echo " txfee_factor - variance around average transaction fee, e.g. 0.00002000 fee, 0.2 var = fee is between 0.00001600 and 0.00002400 (default: 0.3)"
exit
fi

Expand All @@ -32,9 +33,9 @@ if [ "$3" != "" ]; then
hops=$3
fi
if [ "$4" != "" ]; then
fee=$4
txfee="$4"
else
fee=$($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2)
txfee="$($(dirname $0)/estimatesmartfee.sh $bitcoin_cli_options 2)"
fi
if [ "$6" != "" ]; then
sleeptime_min=$5
Expand All @@ -48,16 +49,23 @@ if [ "$7" != "" ]; then
else
hop_confirmations=0
fi
if [ "$8" != "" ]; then
txfee_factor="$8"
else
txfee_factor="0.3"
fi

# Force minimum required fee
fee="$(echo "$fee" | btc_amount_format)"
txfee_min="$(bc_float_calc "$txfee * (1 - $txfee_factor)")"
txfee_max="$(bc_float_calc "$txfee * (1 + $txfee_factor)")"
mempoolminfee="$(call_bitcoin_cli getmempoolinfo | jq_btc_float ".mempoolminfee")"
if is_btc_lt "$fee" "$mempoolminfee"; then
echo "Fee $fee is below minimum mempool fee, raising to $mempoolminfee"
fee="$mempoolminfee"
if is_btc_lt "$txfee_min" "$mempoolminfee"; then
echo "Feerate $txfee_min is below minimum mempool fee, raising minimum to $mempoolminfee"
txfee_min="$mempoolminfee"
fi
txfee_average="$(bc_float_calc "($txfee_min + $txfee_max) * 0.5")"

echo "Ricocheting $amount BTC to $address via $hops hops using $fee fee per KB"
echo "Ricocheting $amount BTC to $address via $hops hops using average $txfee_average fee per kvB"
read -p "Is this ok? " -n 1 -r
echo

Expand All @@ -77,18 +85,27 @@ ricochet_addresses+=("$address")

# FixMe: TX size may vary depending on input and output address types
ricochet_tx_size=192
single_ricochet_tx_fee=$(bc_float_calc "$ricochet_tx_size * $fee * 0.001")
ricochet_fees=$(bc_float_calc "($hops - 1) * $single_ricochet_tx_fee")
send_amount=$(bc_float_calc "$amount + $ricochet_fees")
ricochet_fees=(
"$(randamount "$txfee_min" "$txfee_max")"
)
ricochet_fee_sum="0"
for i in $(seq 1 $(( $hops - 1 ))); do
fee="$(randamount "$txfee_min" "$txfee_max")"
ricochet_fees+=("$fee")
ricochet_fee_sum="$(bc_float_calc "$ricochet_fee_sum + $fee")"
done
ricochet_fees+=("0")
send_amount=$(bc_float_calc "$amount + $ricochet_fee_sum")

#echo "Richochet addresses: ${ricochet_addresses[@]}"
#echo "Ricochet fees: ${ricochet_fees[@]}"

# Send out first transaction
echo -n "0: (wallet) -> ${ricochet_addresses[0]} ($send_amount) - "
call_bitcoin_cli settxfee $fee > /dev/null
txid=$(call_bitcoin_cli sendtoaddress ${ricochet_addresses[0]} $send_amount)
call_bitcoin_cli settxfee "${ricochet_fees[0]}" > /dev/null
txid="$(call_bitcoin_cli sendtoaddress ${ricochet_addresses[0]} $send_amount)"
echo "$txid"
rawtx=$(show_tx_by_id $txid)
rawtx="$(show_tx_by_id $txid)"
#echo "$rawtx"
vout_idx=""
idx=0
Expand Down Expand Up @@ -116,10 +133,10 @@ use_txid="$txid"
echo "Preparing rest of transactions..."
signedtxes=()
for i in $(seq 1 $(( $hops - 1 ))); do
send_amount=$(bc_float_calc "$send_amount - $single_ricochet_tx_fee")
send_amount="$(bc_float_calc "$send_amount - ${ricochet_fees[$i]}")"
echo -n "$i: ${ricochet_addresses[$(( $i - 1 ))]} -> ${ricochet_addresses[$i]} ($send_amount) - "
rawtx=$(call_bitcoin_cli createrawtransaction "[{\"txid\":\"$use_txid\",\"vout\":$vout_idx}]" "{\"${ricochet_addresses[$i]}\":$send_amount}")
privkey=$(call_bitcoin_cli dumpprivkey "${ricochet_addresses[$(( $i - 1 ))]}")
rawtx="$(call_bitcoin_cli createrawtransaction "[{\"txid\":\"$use_txid\",\"vout\":$vout_idx}]" "{\"${ricochet_addresses[$i]}\":$send_amount}")"
privkey="$(call_bitcoin_cli dumpprivkey "${ricochet_addresses[$(( $i - 1 ))]}")"
signedtx="$(signrawtransactionwithkey "$rawtx" "[\"$privkey\"]" "[{\"txid\":\"$use_txid\",\"vout\":$vout_idx,\"scriptPubKey\":\"$prev_pubkey\",\"amount\":$send_amount}]")"
decodedtx="$(call_bitcoin_cli decoderawtransaction "$signedtx")"
use_txid="$(echo "$decodedtx" | jq -r ".txid")"
Expand Down
8 changes: 8 additions & 0 deletions tests/rand.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bats

. ../inc.common.sh

@test "Randomization" {
is_btc_gte "$(randamount "0.1" "0.2")" "0.1"
is_btc_lte "$(randamount "0.1" "0.2")" "0.2"
}

0 comments on commit c4a40e0

Please sign in to comment.