mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-22 10:51:20 +00:00
add terraforce deployment method
This commit is contained in:
parent
d07e164796
commit
f53fb46302
149
terraforce/README.md
Normal file
149
terraforce/README.md
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
# Stack
|
||||||
|
|
||||||
|
This is a stripped down version of https://github.com/segmentio/stack
|
||||||
|
plus some shell scripts.
|
||||||
|
|
||||||
|
It is responsible for the following:
|
||||||
|
|
||||||
|
- spin up a cluster of nodes
|
||||||
|
- copy config files for a tendermint testnet to each node
|
||||||
|
- copy linux binaries for tendermint and the app to each node
|
||||||
|
- start tendermint on every node
|
||||||
|
|
||||||
|
# How it Works
|
||||||
|
|
||||||
|
To use, a user must only provide a directory containing two files: `bins` and `run.sh`.
|
||||||
|
|
||||||
|
The `bins` file is a list of binaries, for instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
$GOPATH/bin/tendermint
|
||||||
|
$GOPATH/bin/dummy
|
||||||
|
```
|
||||||
|
|
||||||
|
and the `run.sh` specifies how those binaries ought to be started:
|
||||||
|
|
||||||
|
```
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
if [[ "$SEEDS" != "" ]]; then
|
||||||
|
SEEDS_FLAG="--seeds=$SEEDS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
./dummy --persist .tendermint/data/dummy_data >> app.log 2>&1 &
|
||||||
|
./tendermint node --log_level=info $SEEDS_FLAG >> tendermint.log 2>&1 &
|
||||||
|
```
|
||||||
|
|
||||||
|
This let's you specify exactly which versions of Tendermint and the application are to be used,
|
||||||
|
and how they ought to be started.
|
||||||
|
|
||||||
|
Note that these binaries *MUST* be compiled for Linux.
|
||||||
|
If you are not on Linux, you can compile binaries for linux using `go build` with the `GOOS` variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
GOOS=linux go build -o $GOPATH/bin/tendermint-linux $GOPATH/src/github.com/tendermint/tendermint/cmd/tendermint
|
||||||
|
```
|
||||||
|
|
||||||
|
This cross-compilation must be done for each binary you want to copy over.
|
||||||
|
|
||||||
|
If you want to use an application that requires more than just a few binaries, you may need to do more manual work,
|
||||||
|
for instance using `terraforce` to set up the development environment on every machine.
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
We use `terraform` for spinning up the machines,
|
||||||
|
and a custom rolled tool, `terraforce`,
|
||||||
|
for running commands on many machines in parallel.
|
||||||
|
You can download terraform here: https://www.terraform.io/downloads.html
|
||||||
|
To download terraforce, run `go get github.com/ebuchman/terraforce`
|
||||||
|
|
||||||
|
We use `tendermint` itself to generate files for a testnet.
|
||||||
|
You can install `tendermint` with
|
||||||
|
|
||||||
|
```
|
||||||
|
cd $GOPATH/src/github.com/tendermint/tendermint
|
||||||
|
glide install
|
||||||
|
go install ./cmd/tendermint
|
||||||
|
```
|
||||||
|
|
||||||
|
You also need to set the `DIGITALOCEAN_TOKEN` environment variables so that terraform can
|
||||||
|
spin up nodes on digital ocean.
|
||||||
|
|
||||||
|
This stack is currently some terraform and a bunch of shell scripts,
|
||||||
|
so its helpful to work out of a directory containing everything.
|
||||||
|
Either change directory to `$GOPATH/src/github.com/tendermint/tendermint/test/net`
|
||||||
|
or make a copy of that directory and change to it. All commands are expected to be executed from there.
|
||||||
|
|
||||||
|
For terraform to work, you must first run `terraform get`
|
||||||
|
|
||||||
|
# Create
|
||||||
|
|
||||||
|
To create a cluster with 4 nodes, run
|
||||||
|
|
||||||
|
```
|
||||||
|
terraform apply
|
||||||
|
```
|
||||||
|
|
||||||
|
To use a different number of nodes, change the `desired_capacity` parameter in the `main.tf`.
|
||||||
|
|
||||||
|
Note that terraform keeps track of the current state of your infrastructure,
|
||||||
|
so if you change the `desired_capacity` and run `terraform apply` again, it will add or remove nodes as necessary.
|
||||||
|
|
||||||
|
If you think that's amazing, so do we.
|
||||||
|
|
||||||
|
To get some info about the cluster, run `terraform output`.
|
||||||
|
|
||||||
|
See the [terraform docs](https://www.terraform.io/docs/index.html) for more details.
|
||||||
|
|
||||||
|
To tear down the cluster, run `terraform destroy`.
|
||||||
|
|
||||||
|
# Initialize
|
||||||
|
|
||||||
|
Now that we have a cluster up and running, let's generate the necessary files for a Tendermint node and copy them over.
|
||||||
|
A Tendermint node needs, at the least, a `priv_validator.json` and a `genesis.json`.
|
||||||
|
To generate files for the nodes, run
|
||||||
|
|
||||||
|
```
|
||||||
|
tendermint testnet 4 mytestnet
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create the directory `mytestnet`, containing one directory for each of the 4 nodes.
|
||||||
|
Each node directory contains a unique `priv_validator.json` and a `genesis.json`,
|
||||||
|
where the `genesis.json` contains the public keys of all `priv_validator.json` files.
|
||||||
|
|
||||||
|
If you want to add more files to each node for your particular app, you'll have to add them to each of the node directories.
|
||||||
|
|
||||||
|
Now we can copy everything over to the cluster.
|
||||||
|
If you are on Linux, run
|
||||||
|
|
||||||
|
```
|
||||||
|
bash scripts/init.sh 4 mytestnet examples/in-proc
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise (if you are not on Linux), make sure you ran
|
||||||
|
|
||||||
|
```
|
||||||
|
GOOS=linux go build -o $GOPATH/bin/tendermint-linux $GOPATH/src/github.com/tendermint/tendermint/cmd/tendermint
|
||||||
|
```
|
||||||
|
|
||||||
|
and now run
|
||||||
|
|
||||||
|
```
|
||||||
|
bash scripts/init.sh 4 mytestnet examples/in-proc-linux
|
||||||
|
```
|
||||||
|
|
||||||
|
# Start
|
||||||
|
|
||||||
|
Finally, to start Tendermint on all the nodes, run
|
||||||
|
|
||||||
|
```
|
||||||
|
bash scripts/start.sh 4
|
||||||
|
```
|
||||||
|
|
||||||
|
# Check
|
||||||
|
|
||||||
|
Query the status of all your nodes:
|
||||||
|
|
||||||
|
```
|
||||||
|
bash scripts/query.sh 4 status
|
||||||
|
```
|
77
terraforce/cluster/main.tf
Normal file
77
terraforce/cluster/main.tf
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Cluster on DO
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
variable "name" {
|
||||||
|
description = "The cluster name, e.g cdn"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "environment" {
|
||||||
|
description = "Environment tag, e.g prod"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image_id" {
|
||||||
|
description = "Image ID"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "regions" {
|
||||||
|
description = "Regions to launch in"
|
||||||
|
type = "list"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "key_ids" {
|
||||||
|
description = "SSH keys to use"
|
||||||
|
type = "list"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_size" {
|
||||||
|
description = "The instance size to use, e.g 2gb"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "desired_capacity" {
|
||||||
|
description = "Desired instance count"
|
||||||
|
default = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------
|
||||||
|
# Instances
|
||||||
|
|
||||||
|
resource "digitalocean_droplet" "cluster" {
|
||||||
|
# set the image and instance type
|
||||||
|
name = "${var.name}${count.index}"
|
||||||
|
image = "${var.image_id}"
|
||||||
|
size = "${var.instance_size}"
|
||||||
|
|
||||||
|
# the `element` function handles modulo
|
||||||
|
region = "${element(var.regions, count.index)}"
|
||||||
|
|
||||||
|
ssh_keys = "${var.key_ids}"
|
||||||
|
|
||||||
|
count = "${var.desired_capacity}"
|
||||||
|
lifecycle = {
|
||||||
|
prevent_destroy = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-----------------------
|
||||||
|
|
||||||
|
// The cluster name, e.g cdn
|
||||||
|
output "name" {
|
||||||
|
value = "${var.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The list of cluster instance ids
|
||||||
|
output "instances" {
|
||||||
|
value = ["${digitalocean_droplet.cluster.*.id}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// The list of cluster instance ips
|
||||||
|
output "private_ips" {
|
||||||
|
value = ["${digitalocean_droplet.cluster.*.ipv4_address_private}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// The list of cluster instance ips
|
||||||
|
output "public_ips" {
|
||||||
|
value = ["${digitalocean_droplet.cluster.*.ipv4_address}"]
|
||||||
|
}
|
2
terraforce/examples/dummy/bins
Normal file
2
terraforce/examples/dummy/bins
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$GOPATH/bin/tendermint
|
||||||
|
$GOPATH/bin/dummy
|
8
terraforce/examples/dummy/run.sh
Normal file
8
terraforce/examples/dummy/run.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
if [[ "$SEEDS" != "" ]]; then
|
||||||
|
SEEDS_FLAG="--seeds=$SEEDS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
./dummy --persist .tendermint/data/dummy_data >> app.log 2>&1 &
|
||||||
|
./tendermint node --log_level=info $SEEDS_FLAG >> tendermint.log 2>&1 &
|
1
terraforce/examples/in-proc-linux/bins
Normal file
1
terraforce/examples/in-proc-linux/bins
Normal file
@ -0,0 +1 @@
|
|||||||
|
$GOPATH/bin/tendermint-linux
|
7
terraforce/examples/in-proc-linux/run.sh
Normal file
7
terraforce/examples/in-proc-linux/run.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
if [[ "$SEEDS" != "" ]]; then
|
||||||
|
SEEDS_FLAG="--seeds=$SEEDS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
./tendermint-linux node --proxy_app=dummy --log_level=note $SEEDS_FLAG >> tendermint.log 2>&1 &
|
1
terraforce/examples/in-proc/bins
Normal file
1
terraforce/examples/in-proc/bins
Normal file
@ -0,0 +1 @@
|
|||||||
|
$GOPATH/bin/tendermint
|
7
terraforce/examples/in-proc/run.sh
Normal file
7
terraforce/examples/in-proc/run.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
if [[ "$SEEDS" != "" ]]; then
|
||||||
|
SEEDS_FLAG="--seeds=$SEEDS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
./tendermint node --proxy_app=dummy --log_level=note $SEEDS_FLAG >> tendermint.log 2>&1 &
|
30
terraforce/main.tf
Normal file
30
terraforce/main.tf
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
module "cluster" {
|
||||||
|
source = "./cluster"
|
||||||
|
environment = "test"
|
||||||
|
name = "tendermint-testnet"
|
||||||
|
|
||||||
|
# curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" "https://api.digitalocean.com/v2/account/keys"
|
||||||
|
key_ids = [8163311]
|
||||||
|
|
||||||
|
image_id = "ubuntu-14-04-x64"
|
||||||
|
desired_capacity = 4
|
||||||
|
instance_size = "2gb"
|
||||||
|
|
||||||
|
regions = ["AMS2", "FRA1", "LON1", "NYC2", "SFO2", "SGP1", "TOR1"]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
provider "digitalocean" {
|
||||||
|
}
|
||||||
|
|
||||||
|
output "public_ips" {
|
||||||
|
value = "${module.cluster.public_ips}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "private_ips" {
|
||||||
|
value = "${join(",",module.cluster.private_ips)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "seeds" {
|
||||||
|
value = "${join(":46656,",module.cluster.public_ips)}:46656"
|
||||||
|
}
|
10
terraforce/scripts/copy_run.sh
Normal file
10
terraforce/scripts/copy_run.sh
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
RUN=$2 # path to run script
|
||||||
|
|
||||||
|
N_=$((N-1))
|
||||||
|
|
||||||
|
# stop all tendermint
|
||||||
|
terraforce scp --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" $RUN run.sh
|
43
terraforce/scripts/init.sh
Normal file
43
terraforce/scripts/init.sh
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
TESTNET=$2 # path to folder containing testnet info
|
||||||
|
CONFIG=$3 # path to folder containing `bins` and `run.sh` files
|
||||||
|
|
||||||
|
if [[ ! -f $CONFIG/bins ]]; then
|
||||||
|
echo "config folder ($CONFIG) must contain bins file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f $CONFIG/run.sh ]]; then
|
||||||
|
echo "config folder ($CONFIG) must contain run.sh file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
KEY=$HOME/.ssh/id_rsa
|
||||||
|
|
||||||
|
FLAGS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
|
||||||
|
|
||||||
|
N_=$((N-1)) # 0-based index
|
||||||
|
|
||||||
|
MACH_ROOT="$TESTNET/mach?"
|
||||||
|
|
||||||
|
|
||||||
|
# mkdir
|
||||||
|
terraforce ssh --user root --ssh-key $KEY --machines "[0-$N_]" mkdir .tendermint
|
||||||
|
|
||||||
|
# copy over genesis/priv_val
|
||||||
|
terraforce scp --user root --ssh-key $KEY --iterative --machines "[0-$N_]" "$MACH_ROOT/priv_validator.json" .tendermint/priv_validator.json
|
||||||
|
terraforce scp --user root --ssh-key $KEY --iterative --machines "[0-$N_]" "$MACH_ROOT/genesis.json" .tendermint/genesis.json
|
||||||
|
|
||||||
|
# copy the run script
|
||||||
|
terraforce scp --user root --ssh-key $KEY --machines "[0-$N_]" $CONFIG/run.sh run.sh
|
||||||
|
|
||||||
|
# copy the binaries
|
||||||
|
while read line; do
|
||||||
|
local_bin=$(eval echo $line)
|
||||||
|
remote_bin=$(basename $local_bin)
|
||||||
|
echo $local_bin
|
||||||
|
terraforce scp --user root --ssh-key $KEY --machines "[0-$N_]" $local_bin $remote_bin
|
||||||
|
terraforce ssh --user root --ssh-key $KEY --machines "[0-$N_]" chmod +x $remote_bin
|
||||||
|
done <$CONFIG/bins
|
11
terraforce/scripts/query.sh
Normal file
11
terraforce/scripts/query.sh
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
QUERY=$2
|
||||||
|
|
||||||
|
N_=$((N-1))
|
||||||
|
|
||||||
|
# start all tendermint nodes
|
||||||
|
terraforce ssh --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" curl -s localhost:46657/$QUERY
|
||||||
|
|
10
terraforce/scripts/reset.sh
Normal file
10
terraforce/scripts/reset.sh
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
|
||||||
|
N_=$((N-1))
|
||||||
|
|
||||||
|
# stop all tendermint
|
||||||
|
terraforce ssh --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" rm -rf .tendermint/data
|
||||||
|
terraforce ssh --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" ./tendermint unsafe_reset_priv_validator
|
9
terraforce/scripts/restart.sh
Normal file
9
terraforce/scripts/restart.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
|
||||||
|
N_=$((N-1))
|
||||||
|
|
||||||
|
# start
|
||||||
|
terraforce ssh --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" SEEDS=$(terraform output seeds) bash run.sh
|
10
terraforce/scripts/start.sh
Normal file
10
terraforce/scripts/start.sh
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
|
||||||
|
N_=$((N-1))
|
||||||
|
|
||||||
|
# start all tendermint nodes
|
||||||
|
terraforce ssh --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" SEEDS=$(terraform output seeds) bash run.sh
|
||||||
|
|
9
terraforce/scripts/stop.sh
Normal file
9
terraforce/scripts/stop.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
N=$1 # number of nodes
|
||||||
|
|
||||||
|
N_=$((N-1))
|
||||||
|
|
||||||
|
# stop all tendermint
|
||||||
|
terraforce ssh --user root --ssh-key $HOME/.ssh/id_rsa --machines "[0-$N_]" killall tendermint
|
30
terraforce/test.sh
Normal file
30
terraforce/test.sh
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
cd $GOPATH/src/github.com/tendermint/tendermint
|
||||||
|
|
||||||
|
TEST_PATH=./test/net/new
|
||||||
|
|
||||||
|
N=4
|
||||||
|
TESTNET_DIR=mytestnet
|
||||||
|
|
||||||
|
# install deps
|
||||||
|
# TODO: we should build a Docker image and
|
||||||
|
# really do everything that follows in the container
|
||||||
|
# bash setup.sh
|
||||||
|
|
||||||
|
|
||||||
|
# launch infra
|
||||||
|
terraform get
|
||||||
|
terraform apply
|
||||||
|
|
||||||
|
# create testnet files
|
||||||
|
tendermint testnet -n $N -dir $TESTNET_DIR
|
||||||
|
|
||||||
|
# expects a linux tendermint binary to be built already
|
||||||
|
bash scripts/init.sh $N $TESTNET_DIR test/net/examples/in-proc
|
||||||
|
|
||||||
|
# testnet should now be running :)
|
||||||
|
bash scripts/start.sh 4
|
||||||
|
|
||||||
|
|
||||||
|
|
140
terraforce/transact/transact.go
Normal file
140
terraforce/transact/transact.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tendermint/go-rpc/client"
|
||||||
|
rpctypes "github.com/tendermint/go-rpc/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
args := flag.Args()
|
||||||
|
if len(args) < 2 {
|
||||||
|
fmt.Println("transact.go expects at least two arguments (ntxs, hosts)")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
nTxS, hostS := args[0], args[1]
|
||||||
|
nTxs, err := strconv.Atoi(nTxS)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("ntxs must be an integer:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts := strings.Split(hostS, ",")
|
||||||
|
|
||||||
|
errCh := make(chan error, 1000)
|
||||||
|
|
||||||
|
wg := new(sync.WaitGroup)
|
||||||
|
wg.Add(len(hosts))
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Printf("Sending %d txs on every host %v\n", nTxs, hosts)
|
||||||
|
for i, host := range hosts {
|
||||||
|
go broadcastTxsToHost(wg, errCh, i, host, nTxs, 0)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Println("Done broadcasting txs. Took", time.Since(start))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func broadcastTxsToHost(wg *sync.WaitGroup, errCh chan error, valI int, valHost string, nTxs int, txCount int) {
|
||||||
|
reconnectSleepSeconds := time.Second * 1
|
||||||
|
|
||||||
|
// thisStart := time.Now()
|
||||||
|
// cli := rpcclient.NewClientURI(valHost + ":46657")
|
||||||
|
fmt.Println("Connecting to host to broadcast txs", valI, valHost)
|
||||||
|
cli := rpcclient.NewWSClient(valHost, "/websocket")
|
||||||
|
if _, err := cli.Start(); err != nil {
|
||||||
|
if nTxs == 0 {
|
||||||
|
time.Sleep(reconnectSleepSeconds)
|
||||||
|
broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, txCount)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Error starting websocket connection to val%d (%s): %v\n", valI, valHost, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
reconnect := make(chan struct{})
|
||||||
|
go func(count int) {
|
||||||
|
LOOP:
|
||||||
|
for {
|
||||||
|
ticker := time.NewTicker(reconnectSleepSeconds)
|
||||||
|
select {
|
||||||
|
case <-cli.ResultsCh:
|
||||||
|
count += 1
|
||||||
|
// nTxs == 0 means just loop forever
|
||||||
|
if nTxs > 0 && count == nTxs {
|
||||||
|
break LOOP
|
||||||
|
}
|
||||||
|
case err := <-cli.ErrorsCh:
|
||||||
|
fmt.Println("err: val", valI, valHost, err)
|
||||||
|
case <-cli.Quit:
|
||||||
|
broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, count)
|
||||||
|
return
|
||||||
|
case <-reconnect:
|
||||||
|
broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, count)
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
if nTxs == 0 {
|
||||||
|
cli.Stop()
|
||||||
|
broadcastTxsToHost(wg, errCh, valI, valHost, nTxs, count)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("Received all responses from node %d (%s)\n", valI, valHost)
|
||||||
|
wg.Done()
|
||||||
|
}(txCount)
|
||||||
|
var i = 0
|
||||||
|
for {
|
||||||
|
/* if i%(nTxs/4) == 0 {
|
||||||
|
fmt.Printf("Have sent %d txs to node %d. Total time so far: %v\n", i, valI, time.Since(thisStart))
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if !cli.IsRunning() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := generateTx(i, valI)
|
||||||
|
if err := cli.WriteJSON(rpctypes.RPCRequest{
|
||||||
|
JSONRPC: "2.0",
|
||||||
|
ID: "",
|
||||||
|
Method: "broadcast_tx_async",
|
||||||
|
Params: []interface{}{hex.EncodeToString(tx)},
|
||||||
|
}); err != nil {
|
||||||
|
fmt.Printf("Error sending tx %d to validator %d: %v. Attempt reconnect\n", i, valI, err)
|
||||||
|
reconnect <- struct{}{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
if nTxs > 0 && i >= nTxs {
|
||||||
|
break
|
||||||
|
} else if nTxs == 0 {
|
||||||
|
time.Sleep(time.Millisecond * 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("Done sending %d txs to node s%d (%s)\n", nTxs, valI, valHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateTx(i, valI int) []byte {
|
||||||
|
// a tx encodes the validator index, the tx number, and some random junk
|
||||||
|
// TODO: read random bytes into more of the tx
|
||||||
|
tx := make([]byte, 250)
|
||||||
|
binary.PutUvarint(tx[:32], uint64(valI))
|
||||||
|
binary.PutUvarint(tx[32:64], uint64(i))
|
||||||
|
if _, err := rand.Read(tx[234:]); err != nil {
|
||||||
|
fmt.Println("err reading from crypto/rand", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return tx
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user