The Whiteblock platform allows users to provision multiple fully-functioning nodes over which they have complete control within a private test network
Documentation for the REST API can be found here.
- clone the repository
cd genesis
go get
go build
set environment variables to allow SSH commands:
ssh localhost docker
- if error
bash: docker: command not found
, move to next step
- if error
echo "PATH=$PATH" >> ~/.ssh/environment
- as root:
echo "PermitUserEnvironment yes" >> /etc/ssh/sshd_config
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load /System/Library/LaunchDaemons/ssh.plist
- run step 1. again and there should be a docker help output
- set up a go development environment
go get github.com/whiteblock/genesis
cd $GOPATH/src/github.com/whiteblock/genesis
go build
Configuration options are located in config.json
in the same directory as the binary
Option | Description |
---|---|
sshUser | The default username for ssh |
sshKey | The location of the ssh private key |
listen | The socket to listen on |
verbose | Enable or disable verbose mode |
serverBits | The bits given to each server's number |
clusterBits | The bits given to each clusters's number |
nodeBits | The bits given to each nodes's number |
threadLimit | The maximum number of threads that can be used for building |
ipPrefix | Used for the IP Scheme |
dockerOutputFile | The location instead the docker containers where the clients stdout and stderr will be captured |
influx | The influxdb endpoint |
influxUser | The influx auth username |
influxPassword | The influx auth password |
serviceNetwork | CIDR of the network for the services |
serviceNetworkName | The name for the service network |
nodePrefix | The prefix for each node name |
nodeNetworkPrefix | The prefix for each cluster network |
servicePrefix | The prefix for each service |
nodesPublicKey | Location of the public key for the nodes |
nodesPrivateKey | Location of the private key for the nodes |
handleNodeSshKeys | Should genesis handle the nodes ssh keys? |
maxNodes | Set a maximum number of nodes that a client can build |
maxNode-memory | Set the max memory per node that a client can use |
maxNodeCpu | Set the max cpus per node that a client can use |
These will override what is set in the config.json file, and allow configuration via only ENV variables
SSH_USER
SSH_KEY
LISTEN
VERBOSE
(only need to set it)SERVER_BITS
CLUSTER_BITS
NODE_BITS
THREAD_LIMIT
IP_PREFIX
DOCKER_OUTPUT_FILE
INFLUX
INFLUX_USER
INFLUX_PASSWORD
SERVICE_NETWORK
SERVICE_NETWORK_NAME
NODE_PREFIX
NODE_NETWORK_PREFIX
SERVICE_PREFIX
NODES_PUBLIC_KEY
NODES_PRIVATE_KEY
HANDLE_NODE_SSH_KEYS
(only need to set it)MAX_NODES
MAX_NODE_MEMORY
MAX_NODE_CPU
- Config order of priority ENV -> config file -> defaults
We are using ipv4 so each address will have 32 bits.
The following assumptions will be made
- Each server will have a relatively unique
serverId
- This uniqueness need only apply to servers which will contain nodes which communicate with each other
- There are going to be 3 IP addresses reserved from each subnet
- Nodes in the same docker network are able to route between each other by default
For simplicity, the following variables will be used
- A =
ipPrefix
- B =
serverBits
- C =
clusterBits
- D =
nodeBits
Note the following rules
- A,B,C, and D must be greater than 0
- ceil(log2(A)) + B + C + D <= 32
- D must be atleast 2
- (2^B) = The maximum number of servers
- (2^C) = The number of cluster in a given server
- (2^D - 3) = How many nodes are groups together in each cluster
- (2^D - 3) * (2^C) = The max number of nodes on a server
- (2^D - 3) * (2^C) * (2^B) = The maximum number of nodes that could be on the platform
Each cluster corresponds to a subnet, docker network, and vlan.
Containers in the same cluster will have minimal latency applied to them. In the majority of cases, it is best to just have one node per cluster, allowing for latency control between all of the nodes.
Given a node number X and a serverId
of Y,
Let Z be the cluster number,
I be the generated IP in big-endian,
and the earlier mentioned variables applied
Z = floor(X / (2^D - 3))) I = (A * 2^(B+C+D) ) + ( Y * 2^(B+C) ) + (Z * 2^C) + (X % (2^D - 3) + 2)
if Z == (2^C - 1) then I = I - 2
First get the cluster the node is in
Then construct the IP one segment at a time through addition
Due to the restrictions, each piece will fit neatly into place without overlap
Finally, check if it is not the last cluster on the server,
add 1 to the ip address if it is not the last cluster.
Given a node number(X) of 2 and a serverId
(Y) of 3
Given the IP Scheme of __A__ = 10, __B__ = 8, __C__ = 14, __D__ = 2
__Z__ = floor(2/(2^2 - 3))
__Z__ = 2
It is going to be in cluster 2
Now, for the construction of the IP
Visually, it can be represented as
IP = AAAAAAAA BBBBBBBB CCCCCCCC CCCCCCDD
The values are simply placed inside the bit space of the IP address as represented, with the exception of the D bits, which needs to be calculated
calculate this number as (2 % (2^2 - 3) + 2)
or 2
Then since (__Z__ != (2^__C__ - 1)) 2 != 16383
, the value remains 2
Finally, construct IP
Part A = 00001010
Part B = 00000011
Part C = 00000000000010
Part D = 10
IP = 00001010 00000011 00000000000010 10
= 00001010 00000011 00000000 00001010
= 10 3 0 10
The gateway is calculated in a similar way, except take Part D to always equal 1
Gateway IP = 00001010 00000011 00000000000010 01
= 00001010 00000011 00000000 00001001
= 10 3 0 9
Finally the subnet is 32 - D
Resulting in
IP = 10.3.0.10
Gateway IP = 10.3.0.9
Subnet = 10.3.0.8/30
Note: Any configuration option can be left out, and this entire section can even be null, the example contains all of the defaults
networkId
: The network iddifficulty
: The initial difficulty set in the genesis.conf fileinitBalance
: The initial balance for the accountsmaxPeers
: The maximum number of peers for each nodegasLimit
: The initial gas limithomesteadBlock
: Set in genesis.confeip155Block
: Set in genesis.confeip158Block
: Set in genesis.conf
{
"chainId":15468,
"networkId":15468,
"difficulty":100000,
"initBalance":100000000000000000000,
"maxPeers":1000,
"gasLimit":4000000,
"homesteadBlock":0,
"eip155Block":0,
"eip158Block":0
}
-
rpcUser
: The username credential -
rpcPass
: The password credential -
masterNodeConns
: The number of connections to set up for the master nodes -
nodeConns
: The number of connections to set up for the normal nodes -
percentMasternodes
: The percentage of the network consisting of master nodes -
options
: Options to set enabled for all nodes -
senderOptions
: Options to set enabled for senders -
receiverOptions
: Options to set enabled for receivers -
mnOptions
: Options to set enabled for master nodes -
extras
: Extra options to add to the config file for all nodes -
senderExtras
: Extra options to add to the config file for senders -
receiverExtras
: Extra options to add to the config file for receivers -
mnExtras
: Extra options to add to the config file for master nodes
{
"rpcUser":"username",
"rpcPass":"password",
"masterNodeConns":25,
"nodeConns":8,
"percentMasternodes":90,
"options":[
"server",
"regtest",
"listen",
"rest"
],
"senderOptions":[
"tpstest",
"addressindex"
],
"mnOptions":[],
"receiverOptions":[
"tpstest"
],
"extras":[],
"senderExtras":[],
"receiverExtras":[],
"mnExtras":[]
}