2

I'm setting up some automated testing for a lightning wallet. At the heart of my tests is a bitcoind instance running in regtest mode. I need to be able to set the fee rate - both the fee rate reported by estimatesmartfee and the fee rate which transactions need to match in order to get confirmed.

So far, the only way I can see to do this is to mine lots of blocks filled with transactions that have the desired fee rate. I'm doing this by calling sendtoaddress (via bitcoin-cli) repeatedly in a loop to send small amounts of money into the void. This is painfully slow - it involves generating ~2500 transactions before bitcoind catches the drift that this should be the new reported fee rate. And I have to do this for every test, sometimes multiple times per test, so my CI is taking forever.

I'm wondering if there's any way to avoid doing this. Is there some way to override bitcoind's estimated fee rate and have it refuse to include transactions which pay less than that fee rate when mining blocks? If not, are there any quicker ways to pad out blocks with transactions than what I'm doing?

2 Answers 2

2

You can use a wrapper to mock the feerate.

Let's say you are writing your tests in Python. You can set up a Python RPC wrapper for the bitcoind interface, and optionally turn on a mock for specific tests (instead of calling bitcoind's estimatesmartfee it would return a preset value).

That is how it's done in C-lightning's functional tests. A good instance is this test which simulates a crash of bitcoind to test lightningd can support spurious failures of its Bitcoin backend.
See also a sample of feerate mock here.

2

I have created a bash script that is less complex than the Python script that @darosior references, but is heavily influenced by it. It keeps creating sets of 10-30 transactions until estimatesmartfee returns a fee rate.

#!/usr/bin/env bash

set -eo pipefail

cont=true
smartfee=$(bitcoin-cli estimatesmartfee 6)
if [[ "$smartfee" == *"\"feerate\":"* ]]; then
    cont=false
fi
while $cont
do
    counterb=0
    range=$(( $RANDOM % 11 + 20 ))
    while [ $counterb -lt $range ]
    do
        power=$(( $RANDOM % 29 ))
        randfee=`echo "scale=8; 0.00001 * (1.1892 ^ $power)" | bc`
        newaddress=$(bitcoin-cli getnewaddress)
        rawtx=$(bitcoin-cli createrawtransaction "[]" "[{\"$newaddress\":0.005}]")
        fundedtx=$(bitcoin-cli fundrawtransaction "$rawtx" "{\"feeRate\": \"0$randfee\"}" | jq -r ".hex")
        signedtx=$(bitcoin-cli signrawtransactionwithwallet "$fundedtx" | jq -r ".hex")
        senttx=$(bitcoin-cli sendrawtransaction "$signedtx")
        ((++counterb))
        echo "Created $counterb transactions this block"
    done
    bitcoin-cli generatetoaddress 1 "mp76nrashrCCYLy3a8cAc5HufEas11yHbh"
    smartfee=$(bitcoin-cli estimatesmartfee 6)
    if [[ "$smartfee" == *"\"feerate\":"* ]]; then
        cont=false
    fi
done
bitcoin-cli generatetoaddress 6 "mp76nrashrCCYLy3a8cAc5HufEas11yHbh"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.