I was able to successfully get electrs
to change a transaction from confirmed to unconfirmed by using a second mining node, as suggested by Murch on twitter. My test setup looks like this:
electrum -> electrs -> bitcoind(1) -> bitcoind(2) (generates/invalidates blocks)
The trick was that I had to invalidate two blocks on my mining node (2) which also removed my test transaction from the mining nodes mempool. Then I had to generate 3 more to make a new longest chain that didn’t contain my test transaction. After all that then my electrs node change the transaction from confirmed to unconfirmed.
I don’t know why electrs doesn’t mark the transaction to unconfirmed when I invalidate the block on the one node it’s connected to. I tried the same test with electrumx and it behaved the same way as electrs. For anyone else trying to repro this test all the gory details are below:
Install electrs
sudo apt-get update
sudo apt-get install librocksdb-dev wget
sudo apt-get install -qqy cargo clang cmake build-essential
From electrs git repo being tested:
ROCKSDB_INCLUDE_DIR=/usr/include
ROCKSDB_LIB_DIR=/usr/lib
cargo install --locked --path .
electrs --version
Install bitcoind
BITCOIND_VERSION=22.0
wget -q https://bitcoincore.org/bin/bitcoin-core-$BITCOIND_VERSION/bitcoin-$BITCOIND_VERSION-x86_64-linux-gnu.tar.gz
tar xvf bitcoin-$BITCOIND_VERSION-x86_64-linux-gnu.tar.gz
mv -v bitcoin-$BITCOIND_VERSION/bin/bitcoind .
mv -v bitcoin-$BITCOIND_VERSION/bin/bitcoin-cli .
Install electrum client
sudo apt-get install -qqy git libsecp256k1-0 python3-cryptography python3-setuptools python3-pip jq curl
git clone --recurse-submodules https://github.com/spesmilo/electrum/
python3 -m pip install -e electrum/
electrum version --offline
Remove old data
rm -rf data/
mkdir -p data/{bitcoin1,bitcoin2,electrum,electrs}
Start bitcoind node 1 and fund wallet
./bitcoind -version
./bitcoind -regtest -regtest -txindex=1 -datadir=data/bitcoin1 -printtoconsole=0 -fallbackfee=0.0001 &
BITCOIND1_PID=$!
Start and fund mining bitcoind node 2 and add to node 1
./bitcoind -regtest -txindex=1 -datadir=data/bitcoin2 -port=28444 -rpcport=28443 -printtoconsole=0 -fallbackfee=0.0001 &
BITCOIND2_PID=$!
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 createwallet "test"
NODE_ADDR=`./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getnewaddress`
echo $NODE_ADDR
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 generatetoaddress 101 $NODE_ADDR
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getwalletinfo
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 addnode "127.0.0.1:18444" "add"
./bitcoin-cli -regtest -datadir=data/bitcoin1 getpeerinfo
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getpeerinfo
Status of bitcoind nodes
node # | tip height | confirmed | mempool |
---|---|---|---|
1 | 101 | none | none |
2 | 101 | none | none |
Start electrs and electrum
export RUST_LOG=electrs=debug
electrs \
--db-dir=data/electrs \
--daemon-dir=data/bitcoin1 \
--network=regtest \
2> data/electrs/regtest-debug.log &
ELECTRS_PID=$!
electrum --regtest daemon --server localhost:60401:t -1 -vDEBUG 2> data/electrum/regtest-debug.log &
ELECTRUM_PID=$!
Fund electrum wallet
electrum --regtest --wallet=data/electrum/wallet getinfo
electrum --regtest --wallet=data/electrum/wallet create --seed_type=segwit
electrum --regtest --wallet=data/electrum/wallet load_wallet
electrum --regtest --wallet=data/electrum/wallet getbalance
WALLET_ADDR1=`electrum --regtest --wallet=data/electrum/wallet getunusedaddress`
echo $WALLET_ADDR1
TX1=`./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 sendtoaddress $WALLET_ADDR1 1.11 "test1"`
./bitcoin-cli -regtest -datadir=data/bitcoin1 getrawtransaction $TX1 true
electrum --regtest --wallet=data/electrum/wallet getaddresshistory $WALLET_ADDR1
electrum --regtest --wallet=data/electrum/wallet getbalance
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 generatetoaddress 1 $NODE_ADDR
./bitcoin-cli -regtest -datadir=data/bitcoin1 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getrawtransaction $TX1 true
electrum --regtest --wallet=data/electrum/wallet getaddresshistory $WALLET_ADDR1
electrum --regtest --wallet=data/electrum/wallet getbalance
Status of bitcoind nodes
node # | tip height | confirmed | mempool |
---|---|---|---|
1 | 102 | TX1 | none |
2 | 102 | TX1 | none |
Status of electrum wallet
confirmed: 1.11
Invalidate 1st block on node 2
TIP=`./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getbestblockhash`
echo $TIP
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 invalidateblock $TIP
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getmempoolinfo
./bitcoin-cli -regtest -datadir=data/bitcoin1 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin1 getmempoolinfo
electrum --regtest --wallet=data/electrum/wallet getbalance
Status of bitcoind nodes
node # | tip height | confirmed | mempool |
---|---|---|---|
1 | 102 | TX1 | none |
2 | 101 | none | TX1 |
Status of electrum wallet
confirmed: 1.11
Invalidate 2nd block on node 2
TIP=`./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getbestblockhash`
echo $TIP
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 invalidateblock $TIP
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getblockchaininfo
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getmempoolinfo
./bitcoin-cli -regtest -datadir=data/bitcoin1 getblockchaininfo
./bitcoin-cli -regtest -datadir=data/bitcoin1 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin1 getmempoolinfo
electrum --regtest --wallet=data/electrum/wallet getbalance
electrum --regtest --wallet=data/electrum/wallet listunspent
Status of bitcoind nodes
node # | tip height | confirmed | mempool |
---|---|---|---|
1 | 102 | TX1 | none |
2 | 100 | none | none |
Status of electrum wallet
confirmed: 1.11
Generate 3 new blocks on node 2
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 generatetoaddress 3 $NODE_ADDR
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getblockchaininfo
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getmempoolinfo
./bitcoin-cli -regtest -datadir=data/bitcoin1 getblockchaininfo
./bitcoin-cli -regtest -datadir=data/bitcoin1 getrawtransaction $TX1 true
./bitcoin-cli -regtest -datadir=data/bitcoin1 getmempoolinfo
electrum --regtest --wallet=data/electrum/wallet getbalance
Status of bitcoind nodes
node # | tip height | confirmed | mempool |
---|---|---|---|
1 | 103 | none | TX1 |
2 | 103 | none | none |
Status of electrum wallet
confirmed: 0
unconfirmed: 1.11
Stop daemons
electrum --regtest --wallet=data/electrum/wallet stop
wait $ELECTRUM_PID
kill -INT $ELECTRS_PID
wait $ELECTRS_PID
./bitcoin-cli -regtest -datadir=data/bitcoin1 stop
wait $BITCOIND1_PID
./bitcoin-cli -regtest -datadir=data/bitcoin2 --rpcport=28443 stop
wait $BITCOIND2_PID