For future reference, here's how I run BCH Scalenet on my shiny RPi5.
Bill of Materials
How I Tie It All Together
The Hardware
The Software
The Vallidation Setup
The Mining Setup
Bill of Materials
RPi5 (8GB RAM) with 64bit RaspberryOS (I got the "official" kit for the included reliable power supply)
Pineboards HatDrive! Bottom to be able to attach an SSD via PCIe for awesome IO speed, and the compatible Pineboards housing
A spare 256GB m.2 SSD that I had laying around (nothing special, gives me 230MB/s random read speeds, a newer drive would probably do much better)
BCHN fullnode software by the BCHN team
(slightly customized) txunami transaction generation software
(slightly customized) cpuminer mining software
How I Tie It All Together
I'll first post the general process, and then go into details of all the parts:
I'll log in to my RPi via SSH with multiple terminals
open htop or nmon in one terminal
run BCHN on Scalenet, let it fully sync
in the meanwhile, in another terminal,
tail debug.log
in another terminal run
watch -n2 bitcoin-cli getmempoolinfo
(with the correct connection parameters, datadir, ...)keep another terminal ready with cpuminer (this can be on the RPi or on another machine in the local network, as long as it can contact BCHN via RPC)
keep another terminal ready with txunami (same as above)
Once I have this all prepared:
run txunami, complete the fan-out phase
mine a block
run the second phase of txunami
monitor stats via the
watch getmempoolinfo
terminal
The Hardware
Assemble the m.2 hat, the case and a fan if you have one. I have noticed no throttling even on heavy loads, but it was still winter when I ran them, so yeah a fan is always better than no fan.
If you get an RPi5 kit, check that the preinstalled OS is 64bit, otherwise reflash your uSD with the 64bit version.
Run the initial setup. Setup SSH (outside of the scope of this writeup, but it's easy to do with raspi-config).
Out-of-the-box the PCIe needs some fiddling to get the max performance, I refer to this video for explanation.
The Software
Bitcoin Cash Node
Installing BCHN is straightforward if you follow the Debian installing guide. The following should build BCHN in ~/git
directory and should work without modification:
sudo apt-get install build-essential cmake git libboost-chrono-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libevent-dev libminiupnpc-dev libssl-dev libzmq3-dev help2man ninja-build python3
cd
mkdir git
cd git
git clone https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node.git
cd bitcoin-cash-node
git checkout v27.0.0
mkdir build
cd build
cmake -GNinja .. -DBUILD_BITCOIN_WALLET=OFF -DBUILD_BITCOIN_QT=OFF -DCMAKE_BUILD_TYPE=Release
ninja
I the run the node on Scalenet with the following script (adjust your paths to your needs)
rpi@raspberrypi5:~ $ cat run.sh
~/git/bitcoin-cash-node/build/src/bitcoind \
-daemon \
-datadir=/mnt/ssd/.bitcoin \
-assumevalid=0 \
-scalenet \
-blockmaxsize=256000000 \
-checklevel=0 \
-debug=bench -debug=rpc -debug=net -debug=db \
-logtimemicros \
-listen=1 \
-allowunconnectedmining \
-whitelist=192.168.1.255/8
You also need to set up a username and password in the bitcoin.conf file. Here is my example of the bitcoin.conf file:
rpcuser=vestal
rpcpassword=1qaz2wsx3edc4rfv
server=1
[scale]
rpcbind=192.168.1.216
rpcallowip=192.168.1.255/8
I'll generally have trouble to find peers to IBD from right off the bat. So I'll go to https://sbch.loping.net/peers and try to add the peers from there, with
$ ~/git/bitcoin-cash-node/build/src/bitcoin-cli -datadir=... -scalenet addnode IP add
$ ~/git/bitcoin-cash-node/build/src/bitcoin-cli -datadir=... -scalenet addnode IP onetry
After that it should start syncing. Moreover, sbch.loping.net has a dynamic IP, so I'll also check out it's current IP and add that too. As usual, tailf your debug.log to see if it's working.
To make BCHN run with txunami, a small check needs to be disabled. Each network message has a checksum, but TCP already has a checksum, so BU disabled this other checksum in their code, and so txunami doesn't compute the checksum. BCHN still has the check, so we need to disable it.
Just comment the lines inside the if net_processing.cpp. By doing so, there is no performance difference, because the check is still computed, but not enforced.
txunami
txunami is a performant transaction generation tool by Mr Stone. I have customized it somewhat with small quality-of-life improvements that I will be push back to upstream sometime in the future.
It depends on libbitcoin.so compiled on BitcoinUnlimited. As of 2024, BU is less maintained than a couple years ago so it will need a little fiddling to make it compile correctly.
The following should work:
Clone BU from https://gitlab.com/bitcoinunlimited/BCHUnlimited.git,
git clone https://gitlab.com/bitcoinunlimited/BCHUnlimited.git
checkout an older (compatible) tag,
git checkout BCHunlimited1.9.2.0
If it doesn't compile correctly right of the bat, there is a small modification to do, just comment out two unrelated lines that cause a compile error in src/serialize.h, line 488
// static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED || std::is_signed<I>::value,
// "Signed type required with mode NONNEGATIVE_SIGNED.");
Compile with lib, as per build guide
$ sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev
$ ./autogen.sh
$ ./configure --disable-wallet --with-gui=no --enable-shared
$ make -j 12 (or whatever your core count is)
git clone https://github.com/mtrycz/txunami.git
Copy over the generated libbitcoin.so to txunami dir
cp ./src/.libs/libbitcoincash.so ../txunami
Build txunami
make BU_DIR=../BCHUnlimited/src
Edit txunami.json as below and run txunami with
LD_LIBRARY_PATH=. ./txunami
txunami needs a special txunami.json file to instruct it on the utxos to spend and the transaction rates etc. You can find an example of the txunami.json file attached at the bottom of this article.
cpuminer
cpuminer is a proof-of-concept miner for various cryptos, including Bitcoin/SHA coins. For Bitcoin-related coins, it asks for the "blocktemplate" of the block to be mined, which contains all of the transactions, and then mines the nonce.
BCHN has a neat optimization called "getblocktemplatelight", which only provides the template of the block including only as much of the merkle tree as required for mining. It is orders of magnitude logaritmic in blocksize. This is important, because for big blocks, the template will easily blow RAM up. The template for these blocks is just a handful of kB.
Therefore I made a customized build of cpuminer (in the gbtl branch), which takes advantage of the gbtl feature, which is both fast and small. Disclaimer: this rough patch is just a proof of concept, and while it works for me, I wouldn't run it in production, it works for me.
To build cpuminer:
clone my repo
git checkout gbtl
follow build instructions in the README, most importantly install the required libraries listed at the top
it will fail with unrelated errors (undefined marcos and somesuch), you haven't installed the right libs, and need to rm and start over
To run cpuminer, I use the following script
mtrycz@Omen:~/git/cpuminer$ cat run_miner.sh
./minerd \
-a sha256d \
-o 192.168.1.80:38332 \
-u vestal \
-p 1qaz2wsx3edc4rfv \
--coinbase-sig="Imma firin mah lazors \\BCHN\\" \
--coinbase-addr=1KHEVZ2w5CbXDFTpKBitqCHT8mHd1qbeTV \
-t 1 \
$@
You'll need to adjust the IP, the username and password, and the mining address (this one works and is mine, but I can't remember how I got this encoding).
The final $@
allows me to add/ovverride parameters, for example
./run_miner.sh -t 8
will mine with eight threads, instead of the one listed in the script.
txunami.json
An example of a txunami.json file follows. It works as long on Scalenet as the configured utxos are valid. txunami works in two phases, first it will fan out one big utxo into the configured 99999. Then, it will wait for you to mine a block and press Enter.
To fill the coins
section, check out the details from ElectronCash for address, scriptPubKey and privKey.
The following would be spendable from an xpriv generated from the seed nose acid myth help maple tooth news priority orphan during cave bomb
(just import this as a new Electron Cash wallet on Scalenet).
Caveat: the rate
and rateEnd
parameters are not implemented (they are fixed and don't ramp-up/ramp-down). Set both to same value.
{
"config" :
{
"_": "Specify the number of splits to use in the 1 to many transactions that are used to create UTXOs",
"splitPerTx": 101,
"_": "Specify the network, for use in translating addresses, etc: regtest, testnet, or chain_nol",
"net": "scalenet",
"_": "Specify the network prefix: regtest = dab5bffa, nolnet = fbcec4e9. Note in byte order (swapped compared to bitcoin.conf)",
"netMagic": "c3afe1a2",
"_": "Specify the default P2P port used by this network",
"defaultPort": 38333,
"_": "Transaction fee in satoshis",
"fee": 10000,
"_": "Pre-generate this many UTXOs to use in generating transactions",
"minUtxos": 99999,
"_": "The host:port P2P address of a bitcoind server used for administrative work (like coin splitting). If port is not specified, defaultPort is used",
"bitcoind": "192.168.1.216",
"_": "An external command that will generate blocks (or wait if other miners are active) until every tx currently in the mempool is committed",
"txCommitCmd": "TBD: Your mempool cleanup command here",
"_": "An external command that will get some coins, returning the same json format as 1 entry in the coins section of this document",
"coinAccessCmd": "TBD: Command that returns a UTXO and privkey with coins"
},
"_": "This section is a list containing test phases that define transaction generation rates and targets to which to send the transactions",
"schedule": [
{
"_": "This name appears in logs",
"name": "level 1",
"_": "Start time in seconds since the epoch, or offset from the schedule beginning",
"start": 0,
"_": "End time in seconds since the epoch",
"end": 60,
"_": "Where to push transactions",
"targets": [
{
"_": "host in address:port format. Use numerical address, and port is optional",
"host": "192.168.1.216",
"_": "Starting rate in transactions per second",
"rate": 1792,
"_": "[Optional] Final rate in transactions per second",
"rateEnd": 1792,
"_": "specify the fee either as a constant or a random value within a range (of satoshis)",
"fee": 200
}
]
}
],
"_": "This section defines the initial coins that this app can use. This is a list of dictionaries containing UTXO and private key information",
"coins": [
{
"_": "These parameters come from ./bitcoin-cli listunspent. Its ok to include the other 'listunspent' dictionary values (but they will not be used)",
"txid": "99543780b671bba9c1be512a3ec5a4592ba2105cd4a6c74b4afad23608fcc6b7",
"vout": 0,
"address": "qryxgez3hme6mskvpq2rvlmsah5t60ux8u0v0f3tn9",
"scriptPubKey": "76a914c8646451bef3adc2cc0814367f70ede8bd3f863f88ac",
"satoshi": 5000000000,
"_": "This parameter comes from ./bitcoin-cli dumprivkey <address>",
"privKey": "cVc5uaiYopKBW6YvC92NDNauuQrk54fUaAp8U9j4YqpfggkPbn2p"
}
]
}