Skip to main content

Run a local epicbox relay

An epicbox relay on your own machine, and a transfer between your two usernet wallets across it.

Linux, with the rig from run a local network: a node producing blocks, wallet_alice with a spendable balance, and wallet_bob. Building the relay needs Rust and Node.js.

In Docker instead: run a relay.

A transfer across a relay on localhost:3423, one listener at a time.

Epicbox transfer over a local relay. Step 1 of 7. Alice posts the slate to the relay

1. Build the address helper

The relay calls epicboxlib for signature and address checks. Its Cargo manifest depends on the wallet's libwallet through a submodule, so populate that before building.

git clone https://github.com/EpicCash/epic-epicbox-docker.git ~/epicbox
cd ~/epicbox
git submodule update --init epicboxlib_source/epic-wallet
cd epicboxlib_source
CARGO_TARGET_DIR=~/epic-build/epicboxlib cargo build --release
cp ~/epic-build/epicboxlib/release/epicboxlib ~/epicbox/

Check the binary answers:

cd ~/epicbox && ./epicboxlib verifyaddress foo bar
false

2. Start MongoDB

The relay keeps slates in MongoDB. The official tarball runs as your own user.

cd ~/epicbox
curl -sSL -o mongodb.tgz \
https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.26.tgz
tar xzf mongodb.tgz && mv mongodb-linux-x86_64-ubuntu2204-6.0.26 mongodb
mkdir -p data
mongodb/bin/mongod --dbpath data --port 27019 --bind_ip 127.0.0.1 \
--fork --logpath mongod.log
child process started successfully, parent exiting

3. Create the slate indexes

The relay creates none, and the 6.0 tarball ships no mongosh. Create them with the driver the relay itself uses: queue drain order, the delivery lookup, and the 7-day expiry on createdat.

~/epicbox/index-slates.mjs
import {MongoClient} from 'mongodb';

const client = new MongoClient('mongodb://127.0.0.1:27019');
await client.connect();
const slates = client.db('epicbox').collection('slates');
await slates.createIndex({queue: 1, made: 1, createdat: 1});
await slates.createIndex({messageid: 1, made: 1});
await slates.createIndex({createdat: 1}, {expireAfterSeconds: 604800});
await client.close();
npm install
node index-slates.mjs

4. Start the relay

epicbox_domain and epicbox_port are what a wallet address is minted from, and the relay keeps only slates addressed to its own domain and port (app_mongo.js:582). Set path_to_epicboxlib_exec_file to an absolute path.

~/epicbox/config.json
{
"mongo_url": "mongodb://127.0.0.1:27019",
"mongo_dbName": "epicbox",
"mongo_collection_name": "slates",
"epicbox_domain": "localhost",
"epicbox_port": 3423,
"local_epicbox_service_port": 3423,
"path_to_epicboxlib_exec_file": "/home/you/epicbox/epicboxlib",
"challenge_interval": 60000,
"debug": false,
"stats": true
}
node app_mongo.js --config config.json
Epicbox ready to work.

The relay listens on 3423.

5. Point both wallets at it

The same block in both wallet directories, matching the relay's config:

wallet_alice/epic-wallet.toml and wallet_bob/epic-wallet.toml
[epicbox]
epicbox_domain = "localhost"
epicbox_port = 3423
epicbox_protocol_unsecure = true
epicbox_address_index = 0

epicbox_protocol_unsecure = true makes the wallet connect over ws:// (impls/src/adapters/epicbox.rs:158).

Read Bob's address, and add the port to it:

cd wallet_bob && epic-wallet --usernet address
esWNVrjr…@localhost

Send to esWNVrjr…@localhost:3423. address prints the domain alone (controller/src/command.rs:1360), and the relay reads a destination with no port as 443 (app_mongo.js:581).

6. Send, one listener at a time

Can spend funds The send reserves Alice's inputs when it builds the slate. They stay reserved until the transfer confirms or she runs cancel -i <id>.

# wallet_bob
epic-wallet --usernet listen -m epicbox
# wallet_alice
epic-wallet --usernet send -m epicbox \
-d esWNVrjr…@localhost:3423 --min_conf 3 5
epic-wallet --usernet listen -m epicbox

The second command is what completes the transfer. Bob's signed slate comes back through the relay rather than as a reply, so it is Alice's own subscription that finalises it:

INFO Finalize transaction (owner::finalize_tx)
INFO Slate [563e2b1a-…] finalized successfully

Bob's listener can stop as soon as it has posted the reply, and Alice's can start afterwards. The relay holds each side's slate until that side subscribes.

Then read the balance in wallet_bob, with nothing listening:

epic-wallet --usernet info --min_conf 3

If the slate does not arrive

SymptomCause
send returns after about 40 seconds reporting success, and nothing arrivesThe destination had no port, so the relay looked for another relay on 443
The relay logs the slate, the recipient never gets itThe wallets' epicbox_domain or epicbox_port differs from the relay's config
A wallet reconnects every 5 secondsThe relay is not running, or epicbox_protocol_unsecure is unset and the wallet is dialling wss://
Nothing happens, and no error anywhereThe slate is queued. Start the recipient's listener
The relay never prints Epicbox ready to work.MongoDB is not reachable on 27019
txs times disagree with the relay logtxs prints UTC, the relay log prints local time

Anything else: diagnose a stuck transaction.

Stop it

pkill -f app_mongo.js
cd ~/epicbox && mongodb/bin/mongod --dbpath data --shutdown

Undelivered slates survive a restart, and expire 7 days after they were posted. Deleting ~/epicbox/data clears them, and the three indexes then have to be created again.

Next