user5406: 
I'm trying to test the Bitcoin Dev Kit Electrum client with Electrs 0.9.1 for the case of a 1-block reorg. I use
invalidateblock on my single regtest bitcoind 22.0, but I don't see my
test transaction unconfirmed. Is there a better way to simulate a 1-block reorg?

Slightly edited from this question by Steve Myers.

user1296: 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


5406: <blockquote>
<p>I'm trying to test the Bitcoin Dev Kit Electrum client with Electrs 0.9.1 for the case of a 1-block reorg. I use
<code>invalidateblock</code> on my single regtest bitcoind 22.0, but I don't see my
test transaction unconfirmed. Is there a better way to simulate a 1-block reorg?</p>
</blockquote>
<p>Slightly edited from this <a href="https://twitter.com/notmandatory/status/1535655719881433088" rel="nofollow noreferrer">question</a> by Steve Myers.</p>
 1296: <p>I was able to successfully get <code>electrs</code> to change a transaction from confirmed to unconfirmed by using a second mining node, as <a href="https://twitter.com/murchandamus/status/1535657478150561794" rel="nofollow noreferrer">suggested</a> by Murch on twitter. My test setup looks like this:</p>
<p>electrum -&gt; electrs -&gt; bitcoind(1) -&gt; bitcoind(2) (generates/invalidates blocks)</p>
<p>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.</p>
<p>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:</p>
<h2>Install electrs</h2>
<pre><code>sudo apt-get update
sudo apt-get install librocksdb-dev wget
sudo apt-get install -qqy cargo clang cmake build-essential
</code></pre>
<p>From electrs git repo being tested:</p>
<pre><code>ROCKSDB_INCLUDE_DIR=/usr/include
ROCKSDB_LIB_DIR=/usr/lib
cargo install --locked --path .
electrs --version
</code></pre>
<h2>Install bitcoind</h2>
<pre><code>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 .
</code></pre>
<h2>Install electrum client</h2>
<pre><code>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
</code></pre>
<h2>Remove old data</h2>
<pre><code>rm -rf data/
mkdir -p data/{bitcoin1,bitcoin2,electrum,electrs}
</code></pre>
<h2>Start bitcoind node 1 and fund wallet</h2>
<pre><code>./bitcoind -version
./bitcoind -regtest -regtest -txindex=1 -datadir=data/bitcoin1 -printtoconsole=0 -fallbackfee=0.0001 &amp;
BITCOIND1_PID=$!
</code></pre>
<h2>Start and fund mining bitcoind node 2 and add to node 1</h2>
<pre><code>./bitcoind -regtest -txindex=1 -datadir=data/bitcoin2 -port=28444 -rpcport=28443 -printtoconsole=0 -fallbackfee=0.0001 &amp;
BITCOIND2_PID=$!

./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 createwallet &quot;test&quot;
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 &quot;127.0.0.1:18444&quot; &quot;add&quot;

./bitcoin-cli -regtest -datadir=data/bitcoin1 getpeerinfo
./bitcoin-cli -regtest -datadir=data/bitcoin2 -rpcport=28443 getpeerinfo
</code></pre>
<h3>Status of bitcoind nodes</h3>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>node #</th>
<th>tip height</th>
<th>confirmed</th>
<th>mempool</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>101</td>
<td>none</td>
<td>none</td>
</tr>
<tr>
<td>2</td>
<td>101</td>
<td>none</td>
<td>none</td>
</tr>
</tbody>
</table>
</div><h2>Start electrs and electrum</h2>
<pre><code>export RUST_LOG=electrs=debug
electrs \
  --db-dir=data/electrs \
  --daemon-dir=data/bitcoin1 \
  --network=regtest \
  2&gt; data/electrs/regtest-debug.log &amp;
ELECTRS_PID=$!

electrum --regtest daemon --server localhost:60401:t -1 -vDEBUG 2&gt; data/electrum/regtest-debug.log &amp;
ELECTRUM_PID=$!

</code></pre>
<h2>Fund electrum wallet</h2>
<pre><code>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 &quot;test1&quot;`

./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
</code></pre>
<h3>Status of bitcoind nodes</h3>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>node #</th>
<th>tip height</th>
<th>confirmed</th>
<th>mempool</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>102</td>
<td>TX1</td>
<td>none</td>
</tr>
<tr>
<td>2</td>
<td>102</td>
<td>TX1</td>
<td>none</td>
</tr>
</tbody>
</table>
</div><h3>Status of electrum wallet</h3>
<p>confirmed: 1.11</p>
<h2>Invalidate 1st block on node 2</h2>
<pre><code>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
</code></pre>
<h3>Status of bitcoind nodes</h3>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>node #</th>
<th>tip height</th>
<th>confirmed</th>
<th>mempool</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>102</td>
<td>TX1</td>
<td>none</td>
</tr>
<tr>
<td>2</td>
<td>101</td>
<td>none</td>
<td>TX1</td>
</tr>
</tbody>
</table>
</div><h3>Status of electrum wallet</h3>
<p>confirmed: 1.11</p>
<h2>Invalidate 2nd block on node 2</h2>
<pre><code>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
</code></pre>
<h3>Status of bitcoind nodes</h3>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>node #</th>
<th>tip height</th>
<th>confirmed</th>
<th>mempool</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>102</td>
<td>TX1</td>
<td>none</td>
</tr>
<tr>
<td>2</td>
<td>100</td>
<td>none</td>
<td>none</td>
</tr>
</tbody>
</table>
</div><h3>Status of electrum wallet</h3>
<p>confirmed: 1.11</p>
<h2>Generate 3 new blocks on node 2</h2>
<pre><code>
./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
</code></pre>
<h3>Status of bitcoind nodes</h3>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>node #</th>
<th>tip height</th>
<th>confirmed</th>
<th>mempool</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>103</td>
<td>none</td>
<td>TX1</td>
</tr>
<tr>
<td>2</td>
<td>103</td>
<td>none</td>
<td>none</td>
</tr>
</tbody>
</table>
</div><h3>Status of electrum wallet</h3>
<p>confirmed: 0<br />
unconfirmed: 1.11</p>
<h2>Stop daemons</h2>
<pre><code>
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
</code></pre>
