Example code to forward RAILGUN transactions to the blockchain. Uses the Waku messaging protocol, while guaranteeing a Private Proof Of Innocence for all transactions.
ppoi-safe-broadcaster-example
is a node.js application that receives encrypted transactions from RAILGUN wallets equipped with Private Proof Of Innocence. The Broadcaster example verifies, signs and forwards the transactions to the blockchain. It will broadcast fees on the tokens you configure to accept at the rates defined in the config.
Private Proof Of Innocence is validated on every transaction for the safety of users and wallets.
Private Proof of Innocence is verified through a Proof Of Spendability, which verifies a merkle proof guaranteeing that the UTXOs that are spent are part of the Private Proof Of Innocence inclusion set for each list.
This means that every fee that is gathered is guaranteed to be spendable by your wallet - and RAILGUN wallets without Private Proof Of Innocence will not be able to use the broadcaster to forward any transactions.
This network runs on Waku, a secure and decentralized messaging protocol. Encrypted messages are sent over the private waku peer-to-peer network.
- node 18+
- docker, if using docker
- jq (cli utility for parsing json)
- At least 1GB of RAM, at least 20GB of disk space
- fetch the latest commits from main branch
- run
./docker/stop.sh
if you're running the docker stack - run
./broadcaster-update
- run the update script as below or manually complete the needed steps as defined in the script
This will: (docker only)
- fetch the & update your local version of the repo.
- stop your current dockers.
- build new docker images.
- restart the docker stack.
./update #run from base directory
./update-swagless #for updating swagless docker instances
This is intended as a setup-wizard for running in docker.
Only things required for setup are a capable system and a mnemonic to configure the broadcaster.
# clone repo
git clone https://github.com/Railgun-Community/ppoi-safe-broadcaster-example.git
# change to repo directory
cd ppoi-safe-broadcaster-example
# May have to do this on a VPS
docker swarm init --advertise-addr PUT.IP.ADDR.HERE
# launch SETUP script
./docker/setup
# or If your server requires root privelages to run docker, ie: (aws, azure...)
# Prerequisites:
# 1. Generate a password, this is used to encrypt the railgun-databases
# 2. Mnemonic - best to copy/paste it. input will not show on screen. (protected input)
sudo ./docker/setup
This will setup 2 naku nodes & 1 broadcaster node. Configure its base defaults, and launch.
./docker/stop.sh
- will kill the running docker-stack./docker/run.sh
- will start up the swag instance (requires fully qualified domain name)./docker/runswagless.sh
- will start up the swagless instance../docker/build.sh --no-swag
- will compile/rebuild the swagless docker-container after making any changes to code/config../docker/build.sh
- will compile/rebuild the swag docker-container after making any changes to code/config.
docker service logs broadcaster_broadcaster -f --raw
- displays running broadcaster logsdocker service logs broadcaster_nwaku1 -f --raw
- displays running nwaku node 1 logsdocker service logs broadcaster_nwaku2 -f --raw
- displays running nwaku node 2 logs
Create and edit docker/.env to define your environment. Start by copying docker/.env.empty to docker/.env, as this includes the needed fields.
cp docker/.env.empty docker/.env
The fields to configure are described below. Note that you may leave the domain and email fields empty if not using a domain name.
EXTIP
- this is the IP address at which your system can be reached by the rest of the worldLISTENIP
- if your system has its own public ip, this is the same asEXTIP
. If you are running inside docker or behind a router with NAT, this will be '0.0.0.0'
BASEDOMAIN
- If your full domain were 'broadcaster.railgun.org, this would be 'railgun.org'SUBDOMAIN
- If your domain were `broadcaster.railgun.org', this would be 'broadcaster'TZ
- timezone code; eg 'EST'EMAIL
- letsencrypt will generate an SSL certificate for your domain; an email address must be entered. Whether you enter a real email address or a fake one is up to you
Customize your node by running npm run copy-my-config
, which copies src/MY-CONFIG.ts.example
to src/MY-CONFIG.ts
.
The standard configurations are set in config files in src/server/config/
. All of these can be overridden in src/MY-CONFIG.ts
. The following are the most common fields that you might want to edit.
- configDefaults.networks.active
Configure the networks on which you want to run a broadcaster. Simply add or remove networks from configDefaults.networks.active
import { ChainType } from '@railgun-community/shared-models';
import { NetworkChainID } from './server/config/config-chain-ids';
export const myConfigOverrides = () => {
//...
configDefaults.networks.active = [
NetworkChainID.Ropsten,
NetworkChainID.Ethereum,
NetworkChainID.BNBChain,
];
//...
- configDefaults.waku.rpcURL
Specify a waku server to use for your broadcaster's p2p communication. It defaults to http://localhost:8546.
//...
configDefaults.waku.rpcURL = 'http://nwaku1:8546';
- configDefaults.wallet.mnemonic
Set the mnemonic used for the wallets
//...
configDefaults.wallet.mnemonic = 'word1 word2 ...';
- configDefaults.wallet.hdWallets
Set the derivation paths you want to use
//...
configDefaults.wallet.hdWallets = [
{
index: 0,
priority: 1,
},
];
- configNetworks
Set network provider
//...
configNetworks[ChainType.EVM][
NetworkChainID.Ethereum
].fallbackProviderConfig.providers.unshift({
provider: 'http://<IP>:<PORT>',
priority: 1,
weight: 1,
});
- configTokens
Set the tokens you want to accept as fees on each network.
//...
configTokens[ChainType.EVM][NetworkChainID.Ethereum]['0x_token_address'] = {
symbol: 'TOKEN1',
};
-
Prereqs: Install docker
-
Create the secret keys (
NODEKEY_1
&NODEKEY_2
) for your node. This is not currently used for encryption, but does establish your node's identity: runningscripts/nodekey.sh
will generate these. (see below.) -
Know your external IP (
EXTIP
) and verify that ports 60000 and 8000 are exposed to the outside world (see https://www.canyouseeme.org/ or similar). -
If you have a stable ip and domain and would like to join the community fleet of bootstrap nodes, be sure to enter your
BASEDOMAIN
and optionallySUBDOMAIN
. Theswag
service will automatically generate an SSL certificate for you through letsencrypt. -
Initialize docker swarm if you don't already have one:
docker swarm init
-
Generate
DB_ENCRYPTION_KEY
docker secret. Do not use passwordsw0rdf1sh
. This is an example. Change it to your own. This command hashes your password to 32 bytes and wrangles it into the docker secret.echo "sw0rdf1sh" -n | sha256sum | awk '{print $1}' | docker secret create DB_ENCRYPTION_KEY -
-
Generate
NODEKEY_1
&NODEKEY_2
docker secrets:
# step 1:
./scripts/nodekey.sh
# this will generate NODEKEY
# and fill them into .env if they're not already present.
# Step 2:
./scripts/nodekey.sh --set-secret
# This will run the above command, but store the secrets if they're already setup.
echo "0xaf46f851e0d9c2f520c89ad95d67b5d098f1d79fae2fef3f562102eca9310a66" | docker secret create NODEKEY_1 -
echo "0x98f1d79fae2fef3f562102eca9310a66af46f851e0d9c2f520c89ad95d67b5d0" | docker secret create NODEKEY_2 -
# DO NOT USE this hash for your NODEKEY
-
Register
MNEMONIC
docker secret. This is an example. Your actual mnemonic is not 'my mnemonic words...'echo "my mnemonic words..." | docker secret create MNEMONIC -
-
Run
docker/build.sh
to build thebroadcaster
andnwaku
docker images from yourdocker/.env
environment definition. This will compose a 'swag' version (creates SSL certs for DOMAINS, only needed if you're using a domain
) and one that just uses the$EXTIP
for its nwaku visibility.
./docker/build.sh # builds the swag docker stack
./docker/build.sh --no-swag # builds swagless docker stack
-
Deploy stack with
./docker/run.sh
: -
Deploy
SWAGLESS
stack with./docker/runswagless.sh
:$ ./docker/run.sh Creating network broadcaster_broadcaster Creating service broadcaster_broadcaster Creating service broadcaster_swag Creating service broadcaster_nwaku
If you get an error about the broadcaster_broadcaster
network not existing, just execute docker/run.sh
again until it works. This is a known issue with docker, but you may need to do it 5 times. Just press up instead of typing it again.
-
Stop stack:
docker/stop.sh
-
View logs. append with
-f
to followdocker service logs broadcaster_broadcaster # broadcaster logs docker service logs broadcaster_nwaku # nwaku network node docker service logs broadcaster_swag # letsencrypt generation
-
copy
docker/.env.empty
todocker/.env
and fill inEXTIP
,NODEKEY
,LISTENIP
(see above) -
build image and config.toml from your .env file:
docker/build.sh
-
run image interactively (useful for first setup): replace
$EXTIP
with your external IP.docker run -p 8546:8546 -p 60000:60000 -p 8000:8000 -it nwaku --config-file=./docker/nwaku/config.toml --nat="extip:$EXTIP" --nodekey=$NODEKEY --websocket-support=true
-
run image in background/detached: replace
$EXTIP
with your external IP.docker run -p 8546:8546 -p 60000:60000 -p 8000:8000 -d nwaku --config-file=./docker/nwaku/config.toml --nat="extip:$EXTIP" --nodekey=$NODEKEY --websocket-support=true
-
verify that you can communicate with your nwaku instance over json-rpc:
scripts/nwaku/whoami.sh
- verify that nwaku is connected to other nwaku nodes:
scripts/nwaku/peers.sh
- run
./scripts/nwaku/whoami.sh
and see something like:
{
"listenAddresses": [
"/dns4/broadcaster.of.holdings/tcp/60000/p2p/16Uiu2HAmMUjGmiUhJeiZgu6ZZnLRkE2VViR2JgjqtW9aTZnHQqgg",
"/dns4/broadcaster.of.holdings/tcp/8000/ws/p2p/16Uiu2HAmMUjGmiUhJeiZgu6ZZnLRkE2VViR2JgjqtW9aTZnHQqgg"
],
"enrUri": "enr:-LO4QGvrbg2hqZnqdOFxGVZnDs9U2PWMkwfQUJdbjWixYkzUC8WOAkZXSlM3E4zxC-sh0yPcrYoiwrjooS2egIqnWnsBgmlkgnY0gmlwhKdH8B6KbXVsdGlhZGRyc5wAGjYTcmVsYXllci5vZi5ob2xkaW5ncwYfQN0DiXNlY3AyNTZrMaEDgxhTW1QQXUp6rmDAj8RflocYG0_fxiW9GnU_pzl_7XWDdGNwgupghXdha3UyDw"
}
- run
./scripts/nwaku/peers.sh
and see something like:
[
{
"multiaddr": "/dns4/node-01.do-ams3.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAm6HZZr7aToTvEBPpiys4UxajCTU97zj5v7RNR2gbniy1D",
"protocol": "/vac/waku/relay/2.0.0",
"connected": true
},
{
"multiaddr": "/dns4/node-01.gc-us-central1-a.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAkwBp8T6G77kQXSNMnxgaMky1JeyML5yqoTHRM8dbeCBNb",
"protocol": "/vac/waku/relay/2.0.0",
"connected": false
},
{
"multiaddr": "/dns4/broadcaster.railgun.org/tcp/60000/p2p/16Uiu2HAmNy49QzXVWHMdhz7DQHXCpk9sHvVua99j3QcShUK8PVSD",
"protocol": "/vac/waku/relay/2.0.0",
"connected": true
}
]
-
Monitor logs with commands like
docker service logs broadcaster_nwaku
docker service logs broadcaster_broadcaster
docker service logs broadcaster_swag
-
In the event that services were restarted, the logs shown by the above commands may not be the true logs. If in doubt, execute:
docker container ps
- This will show a list of running containers. The first column is the id of the container. You can generally refernce it with the first two characters of the id.
docker logs 34
(where34
are the first two characters of the container id)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
345265257f8f broadcaster:latest "docker-entrypoint.s…" 5 hours ago Up 5 hours broadcaster_broadcaster.1.k8e9vk23lhzi79g3vcu02wtr9
8fe5803a4314 nwaku:latest "wakunode2 --config-…" 5 hours ago Up 5 hours 8545/tcp, 30303/tcp, 60000/tcp broadcaster_nwaku.1.5kfe0bcahwbb95bdqxmqgx6ak
4e76b7e1cd3d ghcr.io/linuxserver/swag:latest "/init" 5 hours ago Up 5 hours 80/tcp, 443/tcp broadcaster_swag.1.cmi0mo0r1fto3mbsz7iyfsms
yarn test
yarn test-coverage
(with code coverage visualizer)