mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-15 12:31:42 +00:00
Compare commits
29 Commits
v0.19.0-rc
...
zarko/add-
Author | SHA1 | Date | |
---|---|---|---|
4accdb5f59 | |||
ece3f678da | |||
45a05b4726 | |||
1706ce6f7f | |||
d0beaba7e8 | |||
c28784de5e | |||
d06390638d | |||
3a0edc561d | |||
f8ed578325 | |||
5babaf9a88 | |||
c0610b2c32 | |||
1db2224241 | |||
0323b03daf | |||
379f9f875b | |||
ab00bf7c8b | |||
64879c1e6a | |||
7c22e47629 | |||
384b3ea065 | |||
6a48bd0c88 | |||
d93e177a69 | |||
cef053386b | |||
cca1dd8e3e | |||
26c38e770e | |||
609452958c | |||
c954fca376 | |||
9be16d56ba | |||
2b732bc11a | |||
dcd00b0e68 | |||
ff3f35c5f4 |
18
CHANGELOG.md
18
CHANGELOG.md
@ -24,6 +24,24 @@ BUG FIXES:
|
||||
- Graceful handling/recovery for apps that have non-determinism or fail to halt
|
||||
- Graceful handling/recovery for violations of safety, or liveness
|
||||
|
||||
## 0.19.0 (April 13th, 2018)
|
||||
|
||||
BREAKING:
|
||||
- [cmd] improved `testnet` command; now it can fill in `persistent_peers` for you in the config file and much more (see `tendermint testnet --help` for details)
|
||||
- [cmd] `show_node_id` now returns an error if there is no node key
|
||||
- [rpc]: changed the output format for the `/status` endpoint (see https://godoc.org/github.com/tendermint/tendermint/rpc/core#Status)
|
||||
|
||||
Upgrade from go-wire to go-amino. This is a sweeping change that breaks everything that is
|
||||
serialized to disk or over the network.
|
||||
|
||||
See github.com/tendermint/go-amino for details on the new format.
|
||||
|
||||
See `scripts/wire2amino.go` for a tool to upgrade
|
||||
genesis/priv_validator/node_key JSON files.
|
||||
|
||||
FEATURES:
|
||||
- [cmd] added `gen_node_key` command
|
||||
|
||||
## 0.18.0 (April 6th, 2018)
|
||||
|
||||
BREAKING:
|
||||
|
23
Gopkg.lock
generated
23
Gopkg.lock
generated
@ -191,8 +191,8 @@
|
||||
[[projects]]
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
||||
version = "v1.0.0"
|
||||
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/viper"
|
||||
@ -238,8 +238,8 @@
|
||||
"server",
|
||||
"types"
|
||||
]
|
||||
revision = "c62aed95f2ce399ec815b0cafe478af002cdc4e6"
|
||||
version = "v0.10.3-dev"
|
||||
revision = "78a8905690ef54f9d57e3b2b0ee7ad3a04ef3f1f"
|
||||
version = "v0.10.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -260,8 +260,8 @@
|
||||
[[projects]]
|
||||
name = "github.com/tendermint/go-crypto"
|
||||
packages = ["."]
|
||||
revision = "5d5f580f49ca66c13400938c64334186068c8b7c"
|
||||
version = "v0.6.1"
|
||||
revision = "915416979bf70efa4bcbf1c6cd5d64c5fff9fc19"
|
||||
version = "v0.6.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/tendermint/go-wire"
|
||||
@ -285,8 +285,8 @@
|
||||
"pubsub/query",
|
||||
"test"
|
||||
]
|
||||
revision = "2e24b64fc121dcdf1cabceab8dc2f7257675483c"
|
||||
version = "0.8.1"
|
||||
revision = "97e1f1ad3f510048929a51475811a18686c894df"
|
||||
version = "0.8.2-rc0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -301,7 +301,7 @@
|
||||
"ripemd160",
|
||||
"salsa20/salsa"
|
||||
]
|
||||
revision = "b2aa35443fbc700ab74c586ae79b81c171851023"
|
||||
revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -348,7 +348,7 @@
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "ce84044298496ef4b54b4a0a0909ba593cc60e30"
|
||||
revision = "51d0944304c3cbce4afe9e5247e21100037bff78"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
@ -372,7 +372,6 @@
|
||||
"transport"
|
||||
]
|
||||
revision = "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e"
|
||||
source = "github.com/grpc/grpc-go"
|
||||
version = "v1.7.5"
|
||||
|
||||
[[projects]]
|
||||
@ -384,6 +383,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "e5e6c7942710846bdb5589fba10c90a869773f2685da825b955510afe0d7c5a4"
|
||||
inputs-digest = "e70f8692c825e80ae8510546e297840b9560d00e11b2272749a55cc2ffd147f0"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
13
Gopkg.toml
13
Gopkg.toml
@ -71,25 +71,22 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/abci"
|
||||
version = "0.10.3-dev"
|
||||
version = "~0.10.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/go-crypto"
|
||||
version = "0.6.1"
|
||||
version = "~0.6.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/go-amino"
|
||||
version = "0.9.6"
|
||||
version = "~0.9.6"
|
||||
|
||||
[[override]]
|
||||
# [[constraint]]
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/tmlibs"
|
||||
version = "~0.8.1"
|
||||
# branch = "develop"
|
||||
version = "~0.8.2-rc0"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
source = "github.com/grpc/grpc-go"
|
||||
version = "~1.7.3"
|
||||
|
||||
[prune]
|
||||
|
20
Makefile
20
Makefile
@ -178,7 +178,25 @@ metalinter_all:
|
||||
@echo "--> Running linter (all)"
|
||||
gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./...
|
||||
|
||||
###########################################################
|
||||
### Local testnet using docker
|
||||
|
||||
# Build linux binary on other platforms
|
||||
build-linux:
|
||||
GOOS=linux GOARCH=amd64 $(MAKE) build
|
||||
|
||||
# Run a 4-node testnet locally
|
||||
docker-start:
|
||||
@echo "Wait until 'Attaching to node0, node1, node2, node3' message appears"
|
||||
@if ! [ -f build/node0/config/genesis.json ]; then docker run --rm -v `pwd`/build:/tendermint:Z tendermint/localnode testnet --v 4 --o . --populate-persistent-peers --starting-ip-address 192.167.10.2 ; fi
|
||||
docker-compose up
|
||||
|
||||
# Stop testnet
|
||||
docker-stop:
|
||||
docker-compose down
|
||||
|
||||
# To avoid unintended conflicts with file names, always add to .PHONY
|
||||
# unless there is a reason not to.
|
||||
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||
.PHONY: check build build_race dist install check_tools get_tools update_tools get_vendor_deps draw_deps test_cover test_apps test_persistence test_p2p test test_race test_integrations test_release test100 vagrant_test fmt
|
||||
.PHONY: check build build_race dist install check_tools get_tools update_tools get_vendor_deps draw_deps test_cover test_apps test_persistence test_p2p test test_race test_integrations test_release test100 vagrant_test fmt build-linux docker-start docker-stop
|
||||
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
|
||||
proto "github.com/tendermint/tendermint/benchmarks/proto"
|
||||
@ -16,20 +16,24 @@ func BenchmarkEncodeStatusWire(b *testing.B) {
|
||||
b.StopTimer()
|
||||
cdc := amino.NewCodec()
|
||||
ctypes.RegisterAmino(cdc)
|
||||
pubKey := crypto.GenPrivKeyEd25519().PubKey()
|
||||
nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()}
|
||||
status := &ctypes.ResultStatus{
|
||||
NodeInfo: p2p.NodeInfo{
|
||||
PubKey: pubKey,
|
||||
ID: nodeKey.ID(),
|
||||
Moniker: "SOMENAME",
|
||||
Network: "SOMENAME",
|
||||
ListenAddr: "SOMEADDR",
|
||||
Version: "SOMEVER",
|
||||
Other: []string{"SOMESTRING", "OTHERSTRING"},
|
||||
},
|
||||
PubKey: pubKey,
|
||||
LatestBlockHash: []byte("SOMEBYTES"),
|
||||
LatestBlockHeight: 123,
|
||||
LatestBlockTime: time.Unix(0, 1234),
|
||||
SyncInfo: ctypes.SyncInfo{
|
||||
LatestBlockHash: []byte("SOMEBYTES"),
|
||||
LatestBlockHeight: 123,
|
||||
LatestBlockTime: time.Unix(0, 1234),
|
||||
},
|
||||
ValidatorInfo: ctypes.ValidatorInfo{
|
||||
PubKey: nodeKey.PubKey(),
|
||||
},
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
@ -48,9 +52,9 @@ func BenchmarkEncodeNodeInfoWire(b *testing.B) {
|
||||
b.StopTimer()
|
||||
cdc := amino.NewCodec()
|
||||
ctypes.RegisterAmino(cdc)
|
||||
pubKey := crypto.GenPrivKeyEd25519().PubKey()
|
||||
nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()}
|
||||
nodeInfo := p2p.NodeInfo{
|
||||
PubKey: pubKey,
|
||||
ID: nodeKey.ID(),
|
||||
Moniker: "SOMENAME",
|
||||
Network: "SOMENAME",
|
||||
ListenAddr: "SOMEADDR",
|
||||
@ -73,9 +77,9 @@ func BenchmarkEncodeNodeInfoBinary(b *testing.B) {
|
||||
b.StopTimer()
|
||||
cdc := amino.NewCodec()
|
||||
ctypes.RegisterAmino(cdc)
|
||||
pubKey := crypto.GenPrivKeyEd25519().PubKey()
|
||||
nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()}
|
||||
nodeInfo := p2p.NodeInfo{
|
||||
PubKey: pubKey,
|
||||
ID: nodeKey.ID(),
|
||||
Moniker: "SOMENAME",
|
||||
Network: "SOMENAME",
|
||||
ListenAddr: "SOMEADDR",
|
||||
@ -94,15 +98,20 @@ func BenchmarkEncodeNodeInfoBinary(b *testing.B) {
|
||||
|
||||
func BenchmarkEncodeNodeInfoProto(b *testing.B) {
|
||||
b.StopTimer()
|
||||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519)
|
||||
pubKey2 := &proto.PubKey{Ed25519: &proto.PubKeyEd25519{Bytes: pubKey[:]}}
|
||||
nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()}
|
||||
nodeID := string(nodeKey.ID())
|
||||
someName := "SOMENAME"
|
||||
someAddr := "SOMEADDR"
|
||||
someVer := "SOMEVER"
|
||||
someString := "SOMESTRING"
|
||||
otherString := "OTHERSTRING"
|
||||
nodeInfo := proto.NodeInfo{
|
||||
PubKey: pubKey2,
|
||||
Moniker: "SOMENAME",
|
||||
Network: "SOMENAME",
|
||||
ListenAddr: "SOMEADDR",
|
||||
Version: "SOMEVER",
|
||||
Other: []string{"SOMESTRING", "OTHERSTRING"},
|
||||
Id: &proto.ID{Id: &nodeID},
|
||||
Moniker: &someName,
|
||||
Network: &someName,
|
||||
ListenAddr: &someAddr,
|
||||
Version: &someVer,
|
||||
Other: []string{someString, otherString},
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
|
26
benchmarks/experiments/Makefile
Normal file
26
benchmarks/experiments/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
DIST_DIRS := find * -type d -exec
|
||||
VERSION := $(shell perl -ne '/^var version.*"([^"]+)".*$$/ && print "v$$1\n"' main.go)
|
||||
GOTOOLS = \
|
||||
github.com/mitchellh/gox
|
||||
|
||||
tools:
|
||||
go get $(GOTOOLS)
|
||||
|
||||
get_vendor_deps:
|
||||
@hash glide 2>/dev/null || go get github.com/Masterminds/glide
|
||||
glide install
|
||||
|
||||
build:
|
||||
go build
|
||||
|
||||
install:
|
||||
go install
|
||||
|
||||
test:
|
||||
go test -race
|
||||
|
||||
clean:
|
||||
rm -f ./experiments
|
||||
rm -rf ./dist
|
||||
|
||||
.PHONY: tools get_vendor_deps build install test clean
|
12
benchmarks/experiments/glide.yaml
Normal file
12
benchmarks/experiments/glide.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
package: github.com/tendermint/tendermint/benchmarks/experiments
|
||||
import:
|
||||
- package: github.com/tendermint/tendermint
|
||||
version: v0.16.0
|
||||
subpackages:
|
||||
- rpc/client
|
||||
- rpc/lib/types
|
||||
- types
|
||||
- package: github.com/tendermint/tmlibs
|
||||
version: v0.7.0
|
||||
subpackages:
|
||||
- log
|
126
benchmarks/experiments/main.go
Normal file
126
benchmarks/experiments/main.go
Normal file
@ -0,0 +1,126 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/tendermint/tendermint/rpc/client"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
)
|
||||
|
||||
var logger = log.NewNopLogger()
|
||||
var finishedTasks = 0
|
||||
var mutex = &sync.Mutex{}
|
||||
|
||||
func main() {
|
||||
|
||||
var endpoint = "tcp://0.0.0.0:46657"
|
||||
|
||||
var httpClient = getHTTPClient(endpoint)
|
||||
|
||||
var res, err = httpClient.Status()
|
||||
if err != nil {
|
||||
logger.Info("something wrong happens", err)
|
||||
}
|
||||
logger.Info("received status", res)
|
||||
|
||||
go monitorTask(endpoint)
|
||||
|
||||
txCount := 10
|
||||
var clientNumber = 10
|
||||
for i := 0; i < clientNumber; i++ {
|
||||
go clientTask(i, txCount, endpoint)
|
||||
}
|
||||
for finishedTasks < clientNumber+1 {
|
||||
}
|
||||
fmt.Printf("Done: %d\n", finishedTasks)
|
||||
}
|
||||
|
||||
func clientTask(id, txCount int, endpoint string) {
|
||||
var httpClient = getHTTPClient(endpoint)
|
||||
for i := 0; i < txCount; i++ {
|
||||
var _, err = httpClient.BroadcastTxSync(generateTx(id, rand.Int()))
|
||||
if err != nil {
|
||||
fmt.Printf("Something wrong happened: %s\n", err)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Finished client task: %d\n", id)
|
||||
|
||||
mutex.Lock()
|
||||
finishedTasks++
|
||||
mutex.Unlock()
|
||||
}
|
||||
|
||||
func getHTTPClient(rpcAddr string) *client.HTTP {
|
||||
return client.NewHTTP(rpcAddr, "/websocket")
|
||||
}
|
||||
|
||||
func generateTx(i, valI int) []byte {
|
||||
// a tx encodes the validator index, the tx number, and some random junk
|
||||
tx := make([]byte, 250)
|
||||
binary.PutUvarint(tx[:32], uint64(valI))
|
||||
binary.PutUvarint(tx[32:64], uint64(i))
|
||||
if _, err := rand.Read(tx[65:]); err != nil {
|
||||
fmt.Println("err reading from crypto/rand", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return tx
|
||||
}
|
||||
|
||||
func monitorTask(endpoint string) {
|
||||
fmt.Println("Monitor task started...")
|
||||
var duration = 5 * time.Second
|
||||
|
||||
const subscriber = "monitor"
|
||||
ctx, cancel := context.WithTimeout(context.Background(), duration)
|
||||
defer cancel()
|
||||
evts := make(chan interface{})
|
||||
|
||||
var httpClient = getHTTPClient(endpoint)
|
||||
httpClient.Start()
|
||||
|
||||
evtTyp := types.EventNewBlockHeader
|
||||
|
||||
// register for the next event of this type
|
||||
query := types.QueryForEvent(evtTyp)
|
||||
err := httpClient.Subscribe(ctx, subscriber, query, evts)
|
||||
if err != nil {
|
||||
fmt.Println("error when subscribing", err)
|
||||
}
|
||||
|
||||
// make sure to unregister after the test is over
|
||||
defer httpClient.UnsubscribeAll(ctx, subscriber)
|
||||
|
||||
totalNumOfCommittedTxs := int64(0)
|
||||
|
||||
for {
|
||||
fmt.Println("Starting main loop", err)
|
||||
select {
|
||||
case evt := <-evts:
|
||||
event := evt.(types.TMEventData)
|
||||
header, ok := event.Unwrap().(types.EventDataNewBlockHeader)
|
||||
if ok {
|
||||
fmt.Println("received header\n", header.Header.StringIndented(""))
|
||||
} else {
|
||||
fmt.Println("not able to unwrap header")
|
||||
}
|
||||
// Do some metric computation with header
|
||||
totalNumOfCommittedTxs += header.Header.NumTxs
|
||||
|
||||
case <-ctx.Done():
|
||||
fmt.Printf("Finished monitor task. Received %d transactions \n", totalNumOfCommittedTxs)
|
||||
|
||||
mutex.Lock()
|
||||
finishedTasks++
|
||||
mutex.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ message ResultStatus {
|
||||
}
|
||||
|
||||
message NodeInfo {
|
||||
required PubKey pubKey = 1;
|
||||
required ID id = 1;
|
||||
required string moniker = 2;
|
||||
required string network = 3;
|
||||
required string remoteAddr = 4;
|
||||
@ -16,6 +16,10 @@ message NodeInfo {
|
||||
repeated string other = 7;
|
||||
}
|
||||
|
||||
message ID {
|
||||
required string id = 1;
|
||||
}
|
||||
|
||||
message PubKey {
|
||||
optional PubKeyEd25519 ed25519 = 1;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
|
@ -1,7 +1,7 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
32
cmd/tendermint/commands/gen_node_key.go
Normal file
32
cmd/tendermint/commands/gen_node_key.go
Normal file
@ -0,0 +1,32 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
// GenNodeKeyCmd allows the generation of a node key. It prints node's ID to
|
||||
// the standard output.
|
||||
var GenNodeKeyCmd = &cobra.Command{
|
||||
Use: "gen_node_key",
|
||||
Short: "Generate a node key for this node and print its ID",
|
||||
RunE: genNodeKey,
|
||||
}
|
||||
|
||||
func genNodeKey(cmd *cobra.Command, args []string) error {
|
||||
nodeKeyFile := config.NodeKeyFile()
|
||||
if cmn.FileExists(nodeKeyFile) {
|
||||
return fmt.Errorf("node key at %s already exists", nodeKeyFile)
|
||||
}
|
||||
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(nodeKeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(nodeKey.ID())
|
||||
return nil
|
||||
}
|
@ -3,6 +3,8 @@ package commands
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
pvm "github.com/tendermint/tendermint/types/priv_validator"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
@ -12,10 +14,14 @@ import (
|
||||
var InitFilesCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize Tendermint",
|
||||
Run: initFiles,
|
||||
RunE: initFiles,
|
||||
}
|
||||
|
||||
func initFiles(cmd *cobra.Command, args []string) {
|
||||
func initFiles(cmd *cobra.Command, args []string) error {
|
||||
return initFilesWithConfig(config)
|
||||
}
|
||||
|
||||
func initFilesWithConfig(config *cfg.Config) error {
|
||||
// private validator
|
||||
privValFile := config.PrivValidatorFile()
|
||||
var pv *pvm.FilePV
|
||||
@ -28,6 +34,16 @@ func initFiles(cmd *cobra.Command, args []string) {
|
||||
logger.Info("Generated private validator", "path", privValFile)
|
||||
}
|
||||
|
||||
nodeKeyFile := config.NodeKeyFile()
|
||||
if cmn.FileExists(nodeKeyFile) {
|
||||
logger.Info("Found node key", "path", nodeKeyFile)
|
||||
} else {
|
||||
if _, err := p2p.LoadOrGenNodeKey(nodeKeyFile); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info("Generated node key", "path", nodeKeyFile)
|
||||
}
|
||||
|
||||
// genesis file
|
||||
genFile := config.GenesisFile()
|
||||
if cmn.FileExists(genFile) {
|
||||
@ -42,8 +58,10 @@ func initFiles(cmd *cobra.Command, args []string) {
|
||||
}}
|
||||
|
||||
if err := genDoc.SaveAs(genFile); err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
logger.Info("Generated genesis file", "path", genFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -16,10 +16,12 @@ var ShowNodeIDCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func showNodeID(cmd *cobra.Command, args []string) error {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
|
||||
nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(nodeKey.ID())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
privval "github.com/tendermint/tendermint/types/priv_validator"
|
||||
|
@ -2,60 +2,103 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
pvm "github.com/tendermint/tendermint/types/priv_validator"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
//flags
|
||||
var (
|
||||
nValidators int
|
||||
dataDir string
|
||||
nValidators int
|
||||
nNonValidators int
|
||||
outputDir string
|
||||
nodeDirPrefix string
|
||||
|
||||
populatePersistentPeers bool
|
||||
hostnamePrefix string
|
||||
startingIPAddress string
|
||||
p2pPort int
|
||||
)
|
||||
|
||||
const (
|
||||
nodeDirPerm = 0755
|
||||
)
|
||||
|
||||
func init() {
|
||||
TestnetFilesCmd.Flags().IntVar(&nValidators, "n", 4,
|
||||
TestnetFilesCmd.Flags().IntVar(&nValidators, "v", 4,
|
||||
"Number of validators to initialize the testnet with")
|
||||
TestnetFilesCmd.Flags().StringVar(&dataDir, "dir", "mytestnet",
|
||||
TestnetFilesCmd.Flags().IntVar(&nNonValidators, "n", 0,
|
||||
"Number of non-validators to initialize the testnet with")
|
||||
TestnetFilesCmd.Flags().StringVar(&outputDir, "o", "./mytestnet",
|
||||
"Directory to store initialization data for the testnet")
|
||||
TestnetFilesCmd.Flags().StringVar(&nodeDirPrefix, "node-dir-prefix", "node",
|
||||
"Prefix the directory name for each node with (node results in node0, node1, ...)")
|
||||
|
||||
TestnetFilesCmd.Flags().BoolVar(&populatePersistentPeers, "populate-persistent-peers", true,
|
||||
"Update config of each node with the list of persistent peers build using either hostname-prefix or starting-ip-address")
|
||||
TestnetFilesCmd.Flags().StringVar(&hostnamePrefix, "hostname-prefix", "node",
|
||||
"Hostname prefix (node results in persistent peers list ID0@node0:46656, ID1@node1:46656, ...)")
|
||||
TestnetFilesCmd.Flags().StringVar(&startingIPAddress, "starting-ip-address", "",
|
||||
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||
TestnetFilesCmd.Flags().IntVar(&p2pPort, "p2p-port", 46656,
|
||||
"P2P Port")
|
||||
}
|
||||
|
||||
// TestnetFilesCmd allows initialisation of files for a
|
||||
// Tendermint testnet.
|
||||
// TestnetFilesCmd allows initialisation of files for a Tendermint testnet.
|
||||
var TestnetFilesCmd = &cobra.Command{
|
||||
Use: "testnet",
|
||||
Short: "Initialize files for a Tendermint testnet",
|
||||
Run: testnetFiles,
|
||||
RunE: testnetFiles,
|
||||
}
|
||||
|
||||
func testnetFiles(cmd *cobra.Command, args []string) {
|
||||
|
||||
func testnetFiles(cmd *cobra.Command, args []string) error {
|
||||
config := cfg.DefaultConfig()
|
||||
genVals := make([]types.GenesisValidator, nValidators)
|
||||
defaultConfig := cfg.DefaultBaseConfig()
|
||||
|
||||
// Initialize core dir and priv_validator.json's
|
||||
for i := 0; i < nValidators; i++ {
|
||||
mach := cmn.Fmt("mach%d", i)
|
||||
err := initMachCoreDirectory(dataDir, mach)
|
||||
nodeDirName := cmn.Fmt("%s%d", nodeDirPrefix, i)
|
||||
nodeDir := filepath.Join(outputDir, nodeDirName)
|
||||
config.SetRoot(nodeDir)
|
||||
|
||||
err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
// Read priv_validator.json to populate vals
|
||||
pvFile := filepath.Join(dataDir, mach, defaultConfig.PrivValidator)
|
||||
|
||||
initFilesWithConfig(config)
|
||||
|
||||
pvFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidator)
|
||||
pv := pvm.LoadFilePV(pvFile)
|
||||
genVals[i] = types.GenesisValidator{
|
||||
PubKey: pv.GetPubKey(),
|
||||
Power: 1,
|
||||
Name: mach,
|
||||
Name: nodeDirName,
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < nNonValidators; i++ {
|
||||
nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i+nValidators))
|
||||
config.SetRoot(nodeDir)
|
||||
|
||||
err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
initFilesWithConfig(config)
|
||||
}
|
||||
|
||||
// Generate genesis doc from generated validators
|
||||
genDoc := &types.GenesisDoc{
|
||||
GenesisTime: time.Now(),
|
||||
@ -64,36 +107,65 @@ func testnetFiles(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
// Write genesis file.
|
||||
for i := 0; i < nValidators; i++ {
|
||||
mach := cmn.Fmt("mach%d", i)
|
||||
if err := genDoc.SaveAs(filepath.Join(dataDir, mach, defaultConfig.Genesis)); err != nil {
|
||||
panic(err)
|
||||
for i := 0; i < nValidators+nNonValidators; i++ {
|
||||
nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i))
|
||||
if err := genDoc.SaveAs(filepath.Join(nodeDir, config.BaseConfig.Genesis)); err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(cmn.Fmt("Successfully initialized %v node directories", nValidators))
|
||||
}
|
||||
|
||||
// Initialize per-machine core directory
|
||||
func initMachCoreDirectory(base, mach string) error {
|
||||
// Create priv_validator.json file if not present
|
||||
defaultConfig := cfg.DefaultBaseConfig()
|
||||
dir := filepath.Join(base, mach)
|
||||
pvPath := filepath.Join(dir, defaultConfig.PrivValidator)
|
||||
dir = filepath.Dir(pvPath)
|
||||
err := cmn.EnsureDir(dir, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
if populatePersistentPeers {
|
||||
err := populatePersistentPeersInConfigAndWriteIt(config)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
}
|
||||
ensurePrivValidator(pvPath)
|
||||
|
||||
fmt.Printf("Successfully initialized %v node directories\n", nValidators+nNonValidators)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func ensurePrivValidator(file string) {
|
||||
if cmn.FileExists(file) {
|
||||
return
|
||||
func hostnameOrIP(i int) string {
|
||||
if startingIPAddress != "" {
|
||||
ip := net.ParseIP(startingIPAddress)
|
||||
ip = ip.To4()
|
||||
if ip == nil {
|
||||
fmt.Printf("%v: non ipv4 address\n", startingIPAddress)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
ip[3]++
|
||||
}
|
||||
return ip.String()
|
||||
}
|
||||
pv := pvm.GenFilePV(file)
|
||||
pv.Save()
|
||||
|
||||
return fmt.Sprintf("%s%d", hostnamePrefix, i)
|
||||
}
|
||||
|
||||
func populatePersistentPeersInConfigAndWriteIt(config *cfg.Config) error {
|
||||
persistentPeers := make([]string, nValidators+nNonValidators)
|
||||
for i := 0; i < nValidators+nNonValidators; i++ {
|
||||
nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i))
|
||||
config.SetRoot(nodeDir)
|
||||
nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
persistentPeers[i] = p2p.IDAddressString(nodeKey.ID(), fmt.Sprintf("%s:%d", hostnameOrIP(i), p2pPort))
|
||||
}
|
||||
persistentPeersList := strings.Join(persistentPeers, ",")
|
||||
|
||||
for i := 0; i < nValidators+nNonValidators; i++ {
|
||||
nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i))
|
||||
config.SetRoot(nodeDir)
|
||||
config.P2P.PersistentPeers = persistentPeersList
|
||||
|
||||
// overwrite default config
|
||||
cfg.WriteConfigFile(filepath.Join(nodeDir, "config", "config.toml"), config)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
@ -25,6 +25,7 @@ func main() {
|
||||
cmd.ShowValidatorCmd,
|
||||
cmd.TestnetFilesCmd,
|
||||
cmd.ShowNodeIDCmd,
|
||||
cmd.GenNodeKeyCmd,
|
||||
cmd.VersionCmd)
|
||||
|
||||
// NOTE:
|
||||
|
@ -37,16 +37,21 @@ func EnsureRoot(rootDir string) {
|
||||
|
||||
// Write default config file if missing.
|
||||
if !cmn.FileExists(configFilePath) {
|
||||
writeConfigFile(configFilePath)
|
||||
writeDefaultCondigFile(configFilePath)
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: this func should probably be called by cmd/tendermint/commands/init.go
|
||||
// alongside the writing of the genesis.json and priv_validator.json
|
||||
func writeConfigFile(configFilePath string) {
|
||||
func writeDefaultCondigFile(configFilePath string) {
|
||||
WriteConfigFile(configFilePath, DefaultConfig())
|
||||
}
|
||||
|
||||
// WriteConfigFile renders config using the template and writes it to configFilePath.
|
||||
func WriteConfigFile(configFilePath string, config *Config) {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
if err := configTemplate.Execute(&buffer, DefaultConfig()); err != nil {
|
||||
if err := configTemplate.Execute(&buffer, config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -124,11 +129,11 @@ unsafe = {{ .RPC.Unsafe }}
|
||||
laddr = "{{ .P2P.ListenAddress }}"
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
seeds = ""
|
||||
seeds = "{{ .P2P.Seeds }}"
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
# Do not add private peers to this list if you don't want them advertised
|
||||
persistent_peers = ""
|
||||
persistent_peers = "{{ .P2P.PersistentPeers }}"
|
||||
|
||||
# Path to address book
|
||||
addr_book_file = "{{ .P2P.AddrBook }}"
|
||||
@ -262,7 +267,7 @@ func ResetTestRoot(testName string) *Config {
|
||||
|
||||
// Write default config file if missing.
|
||||
if !cmn.FileExists(configFilePath) {
|
||||
writeConfigFile(configFilePath)
|
||||
writeDefaultCondigFile(configFilePath)
|
||||
}
|
||||
if !cmn.FileExists(genesisFilePath) {
|
||||
cmn.MustWriteFile(genesisFilePath, []byte(testGenesis), 0644)
|
||||
|
@ -395,7 +395,7 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF
|
||||
|
||||
func getSwitchIndex(switches []*p2p.Switch, peer p2p.Peer) int {
|
||||
for i, s := range switches {
|
||||
if bytes.Equal(peer.NodeInfo().PubKey.Address(), s.NodeInfo().PubKey.Address()) {
|
||||
if peer.NodeInfo().ID == s.NodeInfo().ID {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
@ -838,8 +838,8 @@ var (
|
||||
ErrPeerStateInvalidStartTime = errors.New("Error peer state invalid startTime")
|
||||
)
|
||||
|
||||
// PeerState contains the known state of a peer, including its connection
|
||||
// and threadsafe access to its PeerRoundState.
|
||||
// PeerState contains the known state of a peer, including its connection and
|
||||
// threadsafe access to its PeerRoundState.
|
||||
type PeerState struct {
|
||||
Peer p2p.Peer
|
||||
logger log.Logger
|
||||
@ -878,12 +878,14 @@ func NewPeerState(peer p2p.Peer) *PeerState {
|
||||
}
|
||||
}
|
||||
|
||||
// SetLogger allows to set a logger on the peer state. Returns the peer state
|
||||
// itself.
|
||||
func (ps *PeerState) SetLogger(logger log.Logger) *PeerState {
|
||||
ps.logger = logger
|
||||
return ps
|
||||
}
|
||||
|
||||
// GetRoundState returns an atomic snapshot of the PeerRoundState.
|
||||
// GetRoundState returns an shallow copy of the PeerRoundState.
|
||||
// There's no point in mutating it since it won't change PeerState.
|
||||
func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState {
|
||||
ps.mtx.Lock()
|
||||
@ -893,6 +895,14 @@ func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState {
|
||||
return &prs
|
||||
}
|
||||
|
||||
// GetRoundStateJSON returns a json of PeerRoundState, marshalled using go-amino.
|
||||
func (ps *PeerState) GetRoundStateJSON() ([]byte, error) {
|
||||
ps.mtx.Lock()
|
||||
defer ps.mtx.Unlock()
|
||||
|
||||
return cdc.MarshalJSON(ps.PeerRoundState)
|
||||
}
|
||||
|
||||
// GetHeight returns an atomic snapshot of the PeerRoundState's height
|
||||
// used by the mempool to ensure peers are caught up before broadcasting new txs
|
||||
func (ps *PeerState) GetHeight() int64 {
|
||||
@ -1055,7 +1065,7 @@ func (ps *PeerState) ensureCatchupCommitRound(height int64, round int, numValida
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureVoteVitArrays ensures the bit-arrays have been allocated for tracking
|
||||
// EnsureVoteBitArrays ensures the bit-arrays have been allocated for tracking
|
||||
// what votes this peer has received.
|
||||
// NOTE: It's important to make sure that numValidators actually matches
|
||||
// what the node sees as the number of validators for height.
|
||||
|
@ -168,18 +168,23 @@ func (cs *ConsensusState) GetState() sm.State {
|
||||
return cs.state.Copy()
|
||||
}
|
||||
|
||||
// GetRoundState returns a copy of the internal consensus state.
|
||||
// GetRoundState returns a shallow copy of the internal consensus state.
|
||||
func (cs *ConsensusState) GetRoundState() *cstypes.RoundState {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
return cs.getRoundState()
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) getRoundState() *cstypes.RoundState {
|
||||
rs := cs.RoundState // copy
|
||||
return &rs
|
||||
}
|
||||
|
||||
// GetRoundStateJSON returns a json of RoundState, marshalled using go-amino.
|
||||
func (cs *ConsensusState) GetRoundStateJSON() ([]byte, error) {
|
||||
cs.mtx.Lock()
|
||||
defer cs.mtx.Unlock()
|
||||
|
||||
return cdc.MarshalJSON(cs.RoundState)
|
||||
}
|
||||
|
||||
// GetValidators returns a copy of the current validators.
|
||||
func (cs *ConsensusState) GetValidators() (int64, []*types.Validator) {
|
||||
cs.mtx.Lock()
|
||||
|
@ -52,9 +52,6 @@ func (rs RoundStepType) String() string {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// RoundState defines the internal consensus state.
|
||||
// It is Immutable when returned from ConsensusState.GetRoundState()
|
||||
// TODO: Actually, only the top pointer is copied,
|
||||
// so access to field pointers is still racey
|
||||
// NOTE: Not thread safe. Should only be manipulated by functions downstream
|
||||
// of the cs.receiveRoutine
|
||||
type RoundState struct {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
auto "github.com/tendermint/tmlibs/autofile"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@ -117,7 +116,7 @@ func makePathname() string {
|
||||
func randPort() int {
|
||||
// returns between base and base + spread
|
||||
base, spread := 20000, 20000
|
||||
return base + rand.Intn(spread)
|
||||
return base + cmn.RandIntn(spread)
|
||||
}
|
||||
|
||||
func makeAddrs() (string, string, string) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
68
docker-compose.yml
Normal file
68
docker-compose.yml
Normal file
@ -0,0 +1,68 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
node0:
|
||||
container_name: node0
|
||||
image: "tendermint/localnode"
|
||||
ports:
|
||||
- "46656-46657:46656-46657"
|
||||
environment:
|
||||
- ID=0
|
||||
- LOG=${LOG:-tendermint.log}
|
||||
volumes:
|
||||
- ${FOLDER:-./build}:/tendermint:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.167.10.2
|
||||
|
||||
node1:
|
||||
container_name: node1
|
||||
image: "tendermint/localnode"
|
||||
ports:
|
||||
- "46659-46660:46656-46657"
|
||||
environment:
|
||||
- ID=1
|
||||
- LOG=${LOG:-tendermint.log}
|
||||
volumes:
|
||||
- ${FOLDER:-./build}:/tendermint:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.167.10.3
|
||||
|
||||
node2:
|
||||
container_name: node2
|
||||
image: "tendermint/localnode"
|
||||
environment:
|
||||
- ID=2
|
||||
- LOG=${LOG:-tendermint.log}
|
||||
ports:
|
||||
- "46661-46662:46656-46657"
|
||||
volumes:
|
||||
- ${FOLDER:-./build}:/tendermint:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.167.10.4
|
||||
|
||||
node3:
|
||||
container_name: node3
|
||||
image: "tendermint/localnode"
|
||||
environment:
|
||||
- ID=3
|
||||
- LOG=${LOG:-tendermint.log}
|
||||
ports:
|
||||
- "46663-46664:46656-46657"
|
||||
volumes:
|
||||
- ${FOLDER:-./build}:/tendermint:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.167.10.5
|
||||
|
||||
networks:
|
||||
localnet:
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
-
|
||||
subnet: 192.167.10.0/16
|
||||
|
7
docker-compose/Makefile
Normal file
7
docker-compose/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# Makefile for the "localnode" docker image.
|
||||
|
||||
all:
|
||||
docker build --tag tendermint/localnode localnode
|
||||
|
||||
.PHONY: all
|
||||
|
40
docker-compose/README.rst
Normal file
40
docker-compose/README.rst
Normal file
@ -0,0 +1,40 @@
|
||||
localnode
|
||||
=========
|
||||
|
||||
It is assumed that you have already `setup docker <https://docs.docker.com/engine/installation/>`__.
|
||||
|
||||
Description
|
||||
-----------
|
||||
Image for local testnets.
|
||||
|
||||
Add the tendermint binary to the image by attaching it in a folder to the `/tendermint` mount point.
|
||||
|
||||
It assumes that the configuration was created by the `tendermint testnet` command and it is also attached to the `/tendermint` mount point.
|
||||
|
||||
Example:
|
||||
This example builds a linux tendermint binary under the `build/` folder, creates tendermint configuration for a single-node validator and runs the node:
|
||||
```
|
||||
cd $GOPATH/src/github.com/tendermint/tendermint
|
||||
|
||||
#Build binary
|
||||
make build-linux
|
||||
|
||||
#Create configuration
|
||||
docker run -e LOG="stdout" -v `pwd`/build:/tendermint tendermint/localnode testnet --o . --v 1
|
||||
|
||||
#Run the node
|
||||
docker run -v `pwd`/build:/tendermint tendermint/localnode
|
||||
```
|
||||
|
||||
Logging
|
||||
-------
|
||||
Log is saved under the attached volume, in the `tendermint.log` file. If the `LOG` environment variable is set to `stdout` at start, the log is not saved, but printed on the screen.
|
||||
|
||||
Special binaries
|
||||
----------------
|
||||
If you have multiple binaries with different names, you can specify which one to run with the BINARY environment variable. The path of the binary is relative to the attached volume.
|
||||
|
||||
docker-compose.yml
|
||||
==================
|
||||
This file creates a 4-node network using the localnode image. The nodes of the network are exposed to the host machine on ports 46656-46657, 46659-46660, 46661-46662, 46663-46664 respectively.
|
||||
|
16
docker-compose/localnode/Dockerfile
Normal file
16
docker-compose/localnode/Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
FROM alpine:3.7
|
||||
MAINTAINER Greg Szabo <greg@tendermint.com>
|
||||
|
||||
RUN apk update && \
|
||||
apk upgrade && \
|
||||
apk --no-cache add curl jq file
|
||||
|
||||
VOLUME [ /tendermint ]
|
||||
WORKDIR /tendermint
|
||||
EXPOSE 46656 46657
|
||||
ENTRYPOINT ["/usr/bin/wrapper.sh"]
|
||||
CMD ["node", "--proxy_app dummy"]
|
||||
STOPSIGNAL SIGTERM
|
||||
|
||||
COPY wrapper.sh /usr/bin/wrapper.sh
|
||||
|
33
docker-compose/localnode/wrapper.sh
Executable file
33
docker-compose/localnode/wrapper.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##
|
||||
## Input parameters
|
||||
##
|
||||
BINARY=/tendermint/${BINARY:-tendermint}
|
||||
ID=${ID:-0}
|
||||
LOG=${LOG:-tendermint.log}
|
||||
|
||||
##
|
||||
## Assert linux binary
|
||||
##
|
||||
if ! [ -f "${BINARY}" ]; then
|
||||
echo "The binary `basename ${BINARY}` cannot be found. Please add the binary to the shared folder. Please use the BINARY environment variable if the name of the binary is not 'tendermint' E.g.: -e BINARY=tendermint_my_test_version"
|
||||
exit 1
|
||||
fi
|
||||
BINARY_CHECK="`file $BINARY | grep 'ELF 64-bit LSB executable, x86-64'`"
|
||||
if [ -z "${BINARY_CHECK}" ]; then
|
||||
echo "Binary needs to be OS linux, ARCH amd64"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
##
|
||||
## Run binary with all parameters
|
||||
##
|
||||
export TMHOME="/tendermint/node${ID}"
|
||||
|
||||
if [ -d "${TMHOME}/${LOG}" ]; then
|
||||
"$BINARY" $@ | tee "${TMHOME}/${LOG}"
|
||||
else
|
||||
"$BINARY" $@
|
||||
fi
|
||||
|
@ -11,26 +11,26 @@ Manual Deployments
|
||||
|
||||
It's relatively easy to setup a Tendermint cluster manually. The only
|
||||
requirements for a particular Tendermint node are a private key for the
|
||||
validator, stored as ``priv_validator.json``, and a list of the public
|
||||
keys of all validators, stored as ``genesis.json``. These files should
|
||||
be stored in ``~/.tendermint/config``, or wherever the ``$TMHOME`` variable
|
||||
might be set to.
|
||||
validator, stored as ``priv_validator.json``, a node key, stored as
|
||||
``node_key.json`` and a list of the public keys of all validators, stored as
|
||||
``genesis.json``. These files should be stored in ``~/.tendermint/config``, or
|
||||
wherever the ``$TMHOME`` variable might be set to.
|
||||
|
||||
Here are the steps to setting up a testnet manually:
|
||||
|
||||
1) Provision nodes on your cloud provider of choice
|
||||
2) Install Tendermint and the application of interest on all nodes
|
||||
3) Generate a private key for each validator using
|
||||
``tendermint gen_validator``
|
||||
3) Generate a private key and a node key for each validator using
|
||||
``tendermint init``
|
||||
4) Compile a list of public keys for each validator into a
|
||||
``genesis.json`` file.
|
||||
``genesis.json`` file and replace the existing file with it.
|
||||
5) Run ``tendermint node --p2p.persistent_peers=< peer addresses >`` on each node,
|
||||
where ``< peer addresses >`` is a comma separated list of the IP:PORT
|
||||
combination for each node. The default port for Tendermint is
|
||||
``46656``. Thus, if the IP addresses of your nodes were
|
||||
``192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4``, the command
|
||||
would look like:
|
||||
``tendermint node --p2p.persistent_peers=192.168.0.1:46656,192.168.0.2:46656,192.168.0.3:46656,192.168.0.4:46656``.
|
||||
``tendermint node --p2p.persistent_peers=96663a3dd0d7b9d17d4c8211b191af259621c693@192.168.0.1:46656, 429fcf25974313b95673f58d77eacdd434402665@192.168.0.2:46656, 0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@192.168.0.3:46656, f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@192.168.0.4:46656``.
|
||||
|
||||
After a few seconds, all the nodes should connect to each other and start
|
||||
making blocks! For more information, see the Tendermint Networks section
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This is a quick start guide. If you have a vague idea about how Tendermint works
|
||||
and want to get started right away, continue. Otherwise, [review the documentation](http://tendermint.readthedocs.io/en/master/)
|
||||
This is a quick start guide. If you have a vague idea about how Tendermint
|
||||
works and want to get started right away, continue. Otherwise, [review the
|
||||
documentation](http://tendermint.readthedocs.io/en/master/).
|
||||
|
||||
## Install
|
||||
|
||||
@ -42,7 +43,7 @@ Confirm installation:
|
||||
|
||||
```
|
||||
$ tendermint version
|
||||
0.15.0-381fe19
|
||||
0.18.0-XXXXXXX
|
||||
```
|
||||
|
||||
## Initialization
|
||||
@ -117,7 +118,9 @@ where the value is returned in hex.
|
||||
|
||||
## Cluster of Nodes
|
||||
|
||||
First create four Ubuntu cloud machines. The following was tested on Digital Ocean Ubuntu 16.04 x64 (3GB/1CPU, 20GB SSD). We'll refer to their respective IP addresses below as IP1, IP2, IP3, IP4.
|
||||
First create four Ubuntu cloud machines. The following was tested on Digital
|
||||
Ocean Ubuntu 16.04 x64 (3GB/1CPU, 20GB SSD). We'll refer to their respective IP
|
||||
addresses below as IP1, IP2, IP3, IP4.
|
||||
|
||||
Then, `ssh` into each machine, and execute [this script](https://git.io/vNLfY):
|
||||
|
||||
@ -131,12 +134,16 @@ This will install `go` and other dependencies, get the Tendermint source code, t
|
||||
Next, `cd` into `docs/examples`. Each command below should be run from each node, in sequence:
|
||||
|
||||
```
|
||||
tendermint node --home ./node1 --proxy_app=kvstore --p2p.seeds IP1:46656,IP2:46656,IP3:46656,IP4:46656
|
||||
tendermint node --home ./node2 --proxy_app=kvstore --p2p.seeds IP1:46656,IP2:46656,IP3:46656,IP4:46656
|
||||
tendermint node --home ./node3 --proxy_app=kvstore --p2p.seeds IP1:46656,IP2:46656,IP3:46656,IP4:46656
|
||||
tendermint node --home ./node4 --proxy_app=kvstore --p2p.seeds IP1:46656,IP2:46656,IP3:46656,IP4:46656
|
||||
tendermint node --home ./node1 --proxy_app=kvstore --p2p.persistent_peers="3a558bd6f8c97453aa6c2372bb800e8b6ed8e6db@IP1:46656,ccf30d873fddda10a495f42687c8f33472a6569f@IP2:46656,9a4c3de5d6788a76c6ee3cd9ff41e3b45b4cfd14@IP3:46656,58e6f2ab297b3ceae107ba4c8c2898da5c009ff4@IP4:46656"
|
||||
tendermint node --home ./node2 --proxy_app=kvstore --p2p.persistent_peers="3a558bd6f8c97453aa6c2372bb800e8b6ed8e6db@IP1:46656,ccf30d873fddda10a495f42687c8f33472a6569f@IP2:46656,9a4c3de5d6788a76c6ee3cd9ff41e3b45b4cfd14@IP3:46656,58e6f2ab297b3ceae107ba4c8c2898da5c009ff4@IP4:46656"
|
||||
tendermint node --home ./node3 --proxy_app=kvstore --p2p.persistent_peers="3a558bd6f8c97453aa6c2372bb800e8b6ed8e6db@IP1:46656,ccf30d873fddda10a495f42687c8f33472a6569f@IP2:46656,9a4c3de5d6788a76c6ee3cd9ff41e3b45b4cfd14@IP3:46656,58e6f2ab297b3ceae107ba4c8c2898da5c009ff4@IP4:46656"
|
||||
tendermint node --home ./node4 --proxy_app=kvstore --p2p.persistent_peers="3a558bd6f8c97453aa6c2372bb800e8b6ed8e6db@IP1:46656,ccf30d873fddda10a495f42687c8f33472a6569f@IP2:46656,9a4c3de5d6788a76c6ee3cd9ff41e3b45b4cfd14@IP3:46656,58e6f2ab297b3ceae107ba4c8c2898da5c009ff4@IP4:46656"
|
||||
```
|
||||
|
||||
Note that after the third node is started, blocks will start to stream in because >2/3 of validators (defined in the `genesis.json`) have come online. Seeds can also be specified in the `config.toml`. See [this PR](https://github.com/tendermint/tendermint/pull/792) for more information about configuration options.
|
||||
Note that after the third node is started, blocks will start to stream in
|
||||
because >2/3 of validators (defined in the `genesis.json`) have come online.
|
||||
Seeds can also be specified in the `config.toml`. See [this
|
||||
PR](https://github.com/tendermint/tendermint/pull/792) for more information
|
||||
about configuration options.
|
||||
|
||||
Transactions can then be sent as covered in the single, local node example above.
|
||||
|
@ -26,7 +26,7 @@ go get $REPO
|
||||
cd $GOPATH/src/$REPO
|
||||
|
||||
## build
|
||||
git checkout v0.17.0
|
||||
git checkout v0.18.0
|
||||
make get_tools
|
||||
make get_vendor_deps
|
||||
make install
|
||||
|
6
docs/examples/node1/node_key.json
Normal file
6
docs/examples/node1/node_key.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"priv_key" : {
|
||||
"data" : "DA9BAABEA7211A6D93D9A1986B4279EAB3021FAA1653D459D53E6AB4D1CFB4C69BF7D52E48CF00AC5779AA0A6D3C368955D5636A677F72370B8ED19989714CFC",
|
||||
"type" : "ed25519"
|
||||
}
|
||||
}
|
6
docs/examples/node2/node_key.json
Normal file
6
docs/examples/node2/node_key.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"priv_key" : {
|
||||
"data" : "F7BCABA165DFC0DDD50AE563EFB285BAA236EA805D35612504238A36EFA105958756442B1D9F942D7ABD259F2D59671657B6378E9C7194342A7AAA47A66D1E95",
|
||||
"type" : "ed25519"
|
||||
}
|
||||
}
|
6
docs/examples/node3/node_key.json
Normal file
6
docs/examples/node3/node_key.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"priv_key" : {
|
||||
"data" : "95136FCC97E4446B3141EDF9841078107ECE755E99925D79CCBF91085492680B3CA1034D9917DF1DED4E4AB2D9BC225919F6CB2176F210D2368697CC339DF4E7",
|
||||
"type" : "ed25519"
|
||||
}
|
||||
}
|
6
docs/examples/node4/node_key.json
Normal file
6
docs/examples/node4/node_key.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"priv_key" : {
|
||||
"data" : "8895D6C9A1B46AB83A8E2BAE2121B8C3E245B9E9126EBD797FEAC5058285F2F64FDE2E8182C88AD5185A49D837C581465D57BD478C41865A66D7D9742D8AEF57",
|
||||
"type" : "ed25519"
|
||||
}
|
||||
}
|
@ -81,9 +81,8 @@ Tendermint node as follows:
|
||||
|
||||
curl -s localhost:46657/status
|
||||
|
||||
The ``-s`` just silences ``curl``. For nicer output, pipe the result
|
||||
into a tool like `jq <https://stedolan.github.io/jq/>`__ or
|
||||
`jsonpp <https://github.com/jmhodges/jsonpp>`__.
|
||||
The ``-s`` just silences ``curl``. For nicer output, pipe the result into a
|
||||
tool like `jq <https://stedolan.github.io/jq/>`__ or ``json_pp``.
|
||||
|
||||
Now let's send some transactions to the kvstore.
|
||||
|
||||
@ -104,17 +103,23 @@ like:
|
||||
"id": "",
|
||||
"result": {
|
||||
"check_tx": {
|
||||
"code": 0,
|
||||
"data": "",
|
||||
"log": ""
|
||||
"fee": {}
|
||||
},
|
||||
"deliver_tx": {
|
||||
"code": 0,
|
||||
"data": "",
|
||||
"log": ""
|
||||
"tags": [
|
||||
{
|
||||
"key": "YXBwLmNyZWF0b3I=",
|
||||
"value": "amFl"
|
||||
},
|
||||
{
|
||||
"key": "YXBwLmtleQ==",
|
||||
"value": "YWJjZA=="
|
||||
}
|
||||
],
|
||||
"fee": {}
|
||||
},
|
||||
"hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF",
|
||||
"height": 154
|
||||
"hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39",
|
||||
"height": 14
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,20 +139,17 @@ The result should look like:
|
||||
"id": "",
|
||||
"result": {
|
||||
"response": {
|
||||
"code": 0,
|
||||
"index": 0,
|
||||
"key": "",
|
||||
"value": "61626364",
|
||||
"proof": "",
|
||||
"height": 0,
|
||||
"log": "exists"
|
||||
"log": "exists",
|
||||
"index": "-1",
|
||||
"key": "YWJjZA==",
|
||||
"value": "YWJjZA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Note the ``value`` in the result (``61626364``); this is the
|
||||
hex-encoding of the ASCII of ``abcd``. You can verify this in
|
||||
a python 2 shell by running ``"61626364".decode('hex')`` or in python 3 shell by running ``import codecs; codecs.decode("61626364", 'hex').decode('ascii')``. Stay
|
||||
Note the ``value`` in the result (``YWJjZA==``); this is the
|
||||
base64-encoding of the ASCII of ``abcd``. You can verify this in
|
||||
a python 2 shell by running ``"61626364".decode('base64')`` or in python 3 shell by running ``import codecs; codecs.decode("61626364", 'base64').decode('ascii')``. Stay
|
||||
tuned for a future release that `makes this output more human-readable <https://github.com/tendermint/abci/issues/32>`__.
|
||||
|
||||
Now let's try setting a different key and value:
|
||||
@ -157,7 +159,7 @@ Now let's try setting a different key and value:
|
||||
curl -s 'localhost:46657/broadcast_tx_commit?tx="name=satoshi"'
|
||||
|
||||
Now if we query for ``name``, we should get ``satoshi``, or
|
||||
``7361746F736869`` in hex:
|
||||
``c2F0b3NoaQ==`` in base64:
|
||||
|
||||
::
|
||||
|
||||
@ -226,17 +228,15 @@ the number ``1``. If instead, we try to send a ``5``, we get an error:
|
||||
"id": "",
|
||||
"result": {
|
||||
"check_tx": {
|
||||
"code": 0,
|
||||
"data": "",
|
||||
"log": ""
|
||||
"fee": {}
|
||||
},
|
||||
"deliver_tx": {
|
||||
"code": 3,
|
||||
"data": "",
|
||||
"log": "Invalid nonce. Expected 1, got 5"
|
||||
"code": 2,
|
||||
"log": "Invalid nonce. Expected 1, got 5",
|
||||
"fee": {}
|
||||
},
|
||||
"hash": "33B93DFF98749B0D6996A70F64071347060DC19C",
|
||||
"height": 38
|
||||
"height": 34
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,17 +250,13 @@ But if we send a ``1``, it works again:
|
||||
"id": "",
|
||||
"result": {
|
||||
"check_tx": {
|
||||
"code": 0,
|
||||
"data": "",
|
||||
"log": ""
|
||||
"fee": {}
|
||||
},
|
||||
"deliver_tx": {
|
||||
"code": 0,
|
||||
"data": "",
|
||||
"log": ""
|
||||
"fee": {}
|
||||
},
|
||||
"hash": "F17854A977F6FA7EEA1BD758E296710B86F72F3D",
|
||||
"height": 87
|
||||
"height": 60
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ Next we replay all the messages from the WAL.
|
||||
::
|
||||
|
||||
I[10-04|13:54:30.391] Starting RPC HTTP server on tcp socket 0.0.0.0:46657 module=rpc-server
|
||||
I[10-04|13:54:30.392] Started node module=main nodeInfo="NodeInfo{pk: PubKeyEd25519{DF22D7C92C91082324A1312F092AA1DA197FA598DBBFB6526E177003C4D6FD66}, moniker: anonymous, network: test-chain-3MNw2N [remote , listen 10.0.2.15:46656], version: 0.11.0-10f361fc ([wire_version=0.6.2 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:46657])}"
|
||||
I[10-04|13:54:30.392] Started node module=main nodeInfo="NodeInfo{id: DF22D7C92C91082324A1312F092AA1DA197FA598DBBFB6526E, moniker: anonymous, network: test-chain-3MNw2N [remote , listen 10.0.2.15:46656], version: 0.11.0-10f361fc ([wire_version=0.6.2 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:46657])}"
|
||||
|
||||
Next follows a standard block creation cycle, where we enter a new round,
|
||||
propose a block, receive more than 2/3 of prevotes, then precommits and finally
|
||||
|
@ -4,7 +4,7 @@ Install Tendermint
|
||||
From Binary
|
||||
-----------
|
||||
|
||||
To download pre-built binaries, see the `Download page <https://tendermint.com/download>`__.
|
||||
To download pre-built binaries, see the `Download page <https://tendermint.com/downloads>`__.
|
||||
|
||||
From Source
|
||||
-----------
|
||||
@ -37,13 +37,13 @@ First, install ``dep``:
|
||||
|
||||
::
|
||||
|
||||
cd $GOPATH/src/github.com/tendermint/tendermint
|
||||
make get_tools
|
||||
|
||||
Now we can fetch the correct versions of each dependency by running:
|
||||
|
||||
::
|
||||
|
||||
cd $GOPATH/src/github.com/tendermint/tendermint
|
||||
make get_vendor_deps
|
||||
make install
|
||||
|
||||
@ -96,6 +96,7 @@ If ``go get`` failing bothers you, fetch the code using ``git``:
|
||||
mkdir -p $GOPATH/src/github.com/tendermint
|
||||
git clone https://github.com/tendermint/tendermint $GOPATH/src/github.com/tendermint/tendermint
|
||||
cd $GOPATH/src/github.com/tendermint/tendermint
|
||||
make get_tools
|
||||
make get_vendor_deps
|
||||
make install
|
||||
|
||||
|
@ -18,8 +18,8 @@ Fields
|
||||
- ``power``: The validator's voting power.
|
||||
- ``name``: Name of the validator (optional).
|
||||
- ``app_hash``: The expected application hash (as returned by the
|
||||
``Commit`` ABCI message) upon genesis. If the app's hash does not
|
||||
match, a warning message is printed.
|
||||
``ResponseInfo`` ABCI message) upon genesis. If the app's hash does not
|
||||
match, Tendermint will panic.
|
||||
- ``app_state``: The application state (e.g. initial distribution of tokens).
|
||||
|
||||
Sample genesis.json
|
||||
|
@ -83,7 +83,7 @@ The Tendermint Version Handshake allows the peers to exchange their NodeInfo:
|
||||
|
||||
```golang
|
||||
type NodeInfo struct {
|
||||
PubKey crypto.PubKey
|
||||
ID p2p.ID
|
||||
Moniker string
|
||||
Network string
|
||||
RemoteAddr string
|
||||
@ -95,7 +95,7 @@ type NodeInfo struct {
|
||||
```
|
||||
|
||||
The connection is disconnected if:
|
||||
- `peer.NodeInfo.PubKey != peer.PubKey`
|
||||
- `peer.NodeInfo.ID` is not equal `peerConn.ID`
|
||||
- `peer.NodeInfo.Version` is not formatted as `X.X.X` where X are integers known as Major, Minor, and Revision
|
||||
- `peer.NodeInfo.Version` Major is not the same as ours
|
||||
- `peer.NodeInfo.Version` Minor is not the same as ours
|
||||
|
@ -62,6 +62,13 @@ such as the Web-of-Trust or Certificate Authorities. In our case, we can
|
||||
use the blockchain itself as a certificate authority to ensure that we
|
||||
are connected to at least one validator.
|
||||
|
||||
Config
|
||||
------
|
||||
|
||||
Authenticated encryption is enabled by default. If you wish to use another
|
||||
authentication scheme or your peers are connected via VPN, you can turn it off
|
||||
by setting ``auth_enc`` to ``false`` in the config file.
|
||||
|
||||
Additional Reading
|
||||
------------------
|
||||
|
||||
|
@ -74,20 +74,17 @@ RPC server, for example:
|
||||
|
||||
curl http://localhost:46657/broadcast_tx_commit?tx=\"abcd\"
|
||||
|
||||
For handling responses, we recommend you `install the jsonpp
|
||||
tool <http://jmhodges.github.io/jsonpp/>`__ to pretty print the JSON.
|
||||
|
||||
We can see the chain's status at the ``/status`` end-point:
|
||||
|
||||
::
|
||||
|
||||
curl http://localhost:46657/status | jsonpp
|
||||
curl http://localhost:46657/status | json_pp
|
||||
|
||||
and the ``latest_app_hash`` in particular:
|
||||
|
||||
::
|
||||
|
||||
curl http://localhost:46657/status | jsonpp | grep app_hash
|
||||
curl http://localhost:46657/status | json_pp | grep latest_app_hash
|
||||
|
||||
Visit http://localhost:46657 in your browser to see the list of other
|
||||
endpoints. Some take no arguments (like ``/status``), while others
|
||||
@ -185,7 +182,7 @@ once per second, it is possible to disable empty blocks or set a block creation
|
||||
interval. In the former case, blocks will be created when there are new
|
||||
transactions or when the AppHash changes.
|
||||
|
||||
To configure Tendermint to not produce empty blocks unless there are
|
||||
To configure Tendermint to not produce empty blocks unless there are
|
||||
transactions or the app hash changes, run Tendermint with this additional flag:
|
||||
|
||||
::
|
||||
@ -260,19 +257,19 @@ When ``tendermint init`` is run, both a ``genesis.json`` and
|
||||
::
|
||||
|
||||
{
|
||||
"app_hash": "",
|
||||
"chain_id": "test-chain-HZw6TB",
|
||||
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||
"validators": [
|
||||
{
|
||||
"power": 10,
|
||||
"name": "",
|
||||
"pub_key": [
|
||||
1,
|
||||
"5770B4DD55B3E08B7F5711C48B516347D8C33F47C30C226315D21AA64E0DFF2E"
|
||||
]
|
||||
}
|
||||
]
|
||||
"validators" : [
|
||||
{
|
||||
"pub_key" : {
|
||||
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
||||
"type" : "AC26791624DE60"
|
||||
},
|
||||
"power" : 10,
|
||||
"name" : ""
|
||||
}
|
||||
],
|
||||
"app_hash" : "",
|
||||
"chain_id" : "test-chain-rDlYSN",
|
||||
"genesis_time" : "0001-01-01T00:00:00Z"
|
||||
}
|
||||
|
||||
And the ``priv_validator.json``:
|
||||
@ -280,20 +277,18 @@ And the ``priv_validator.json``:
|
||||
::
|
||||
|
||||
{
|
||||
"address": "4F4D895F882A18E1D1FC608D102601DA8D3570E5",
|
||||
"last_height": 0,
|
||||
"last_round": 0,
|
||||
"last_signature": null,
|
||||
"last_signbytes": "",
|
||||
"last_step": 0,
|
||||
"priv_key": [
|
||||
1,
|
||||
"F9FA3CD435BDAE54D0BCA8F1BC289D718C23D855C6DB21E8543F5E4F457E62805770B4DD55B3E08B7F5711C48B516347D8C33F47C30C226315D21AA64E0DFF2E"
|
||||
],
|
||||
"pub_key": [
|
||||
1,
|
||||
"5770B4DD55B3E08B7F5711C48B516347D8C33F47C30C226315D21AA64E0DFF2E"
|
||||
]
|
||||
"last_step" : 0,
|
||||
"last_round" : 0,
|
||||
"address" : "B788DEDE4F50AD8BC9462DE76741CCAFF87D51E2",
|
||||
"pub_key" : {
|
||||
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
||||
"type" : "AC26791624DE60"
|
||||
},
|
||||
"last_height" : 0,
|
||||
"priv_key" : {
|
||||
"value" : "JPivl82x+LfVkp8i3ztoTjY6c6GJ4pBxQexErOCyhwqHeGT5ATxzpAtPJKnxNx/NyUnD8Ebv3OIYH+kgD4N88Q==",
|
||||
"type" : "954568A3288910"
|
||||
}
|
||||
}
|
||||
|
||||
The ``priv_validator.json`` actually contains a private key, and should
|
||||
@ -334,14 +329,14 @@ For instance,
|
||||
|
||||
::
|
||||
|
||||
tendermint node --p2p.seeds "1.2.3.4:46656,5.6.7.8:46656"
|
||||
tendermint node --p2p.seeds "f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:46656,0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:46656"
|
||||
|
||||
Alternatively, you can use the ``/dial_seeds`` endpoint of the RPC to
|
||||
specify seeds for a running node to connect to:
|
||||
|
||||
::
|
||||
|
||||
curl 'localhost:46657/dial_seeds?seeds=\["1.2.3.4:46656","5.6.7.8:46656"\]'
|
||||
curl 'localhost:46657/dial_seeds?seeds=\["f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:46656","0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:46656"\]'
|
||||
|
||||
Note, if the peer-exchange protocol (PEX) is enabled (default), you should not
|
||||
normally need seeds after the first start. Peers will be gossipping about known
|
||||
@ -355,8 +350,8 @@ core instance.
|
||||
|
||||
::
|
||||
|
||||
tendermint node --p2p.persistent_peers "10.11.12.13:46656,10.11.12.14:46656"
|
||||
curl 'localhost:46657/dial_peers?persistent=true&peers=\["1.2.3.4:46656","5.6.7.8:46656"\]'
|
||||
tendermint node --p2p.persistent_peers "429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:46656,96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:46656"
|
||||
curl 'localhost:46657/dial_peers?persistent=true&peers=\["429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:46656","96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:46656"\]'
|
||||
|
||||
Adding a Non-Validator
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -387,20 +382,18 @@ Now we can update our genesis file. For instance, if the new
|
||||
::
|
||||
|
||||
{
|
||||
"address": "AC379688105901436A34A65F185C115B8BB277A1",
|
||||
"last_height": 0,
|
||||
"last_round": 0,
|
||||
"last_signature": null,
|
||||
"last_signbytes": "",
|
||||
"last_step": 0,
|
||||
"priv_key": [
|
||||
1,
|
||||
"0D2ED337D748ADF79BE28559B9E59EBE1ABBA0BAFE6D65FCB9797985329B950C8F2B5AACAACC9FCE41881349743B0CFDE190DF0177744568D4E82A18F0B7DF94"
|
||||
],
|
||||
"pub_key": [
|
||||
1,
|
||||
"8F2B5AACAACC9FCE41881349743B0CFDE190DF0177744568D4E82A18F0B7DF94"
|
||||
]
|
||||
"address" : "5AF49D2A2D4F5AD4C7C8C4CC2FB020131E9C4902",
|
||||
"pub_key" : {
|
||||
"value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=",
|
||||
"type" : "AC26791624DE60"
|
||||
},
|
||||
"priv_key" : {
|
||||
"value" : "EDJY9W6zlAw+su6ITgTKg2nTZcHAH1NMTW5iwlgmNDuX1f35+OR4HMN88ZtQzsAwhETq4k3vzM3n6WTk5ii16Q==",
|
||||
"type" : "954568A3288910"
|
||||
},
|
||||
"last_step" : 0,
|
||||
"last_round" : 0,
|
||||
"last_height" : 0
|
||||
}
|
||||
|
||||
then the new ``genesis.json`` will be:
|
||||
@ -408,27 +401,27 @@ then the new ``genesis.json`` will be:
|
||||
::
|
||||
|
||||
{
|
||||
"app_hash": "",
|
||||
"chain_id": "test-chain-HZw6TB",
|
||||
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||
"validators": [
|
||||
{
|
||||
"power": 10,
|
||||
"name": "",
|
||||
"pub_key": [
|
||||
1,
|
||||
"5770B4DD55B3E08B7F5711C48B516347D8C33F47C30C226315D21AA64E0DFF2E"
|
||||
]
|
||||
},
|
||||
{
|
||||
"power": 10,
|
||||
"name": "",
|
||||
"pub_key": [
|
||||
1,
|
||||
"8F2B5AACAACC9FCE41881349743B0CFDE190DF0177744568D4E82A18F0B7DF94"
|
||||
]
|
||||
}
|
||||
]
|
||||
"validators" : [
|
||||
{
|
||||
"pub_key" : {
|
||||
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
||||
"type" : "AC26791624DE60"
|
||||
},
|
||||
"power" : 10,
|
||||
"name" : ""
|
||||
},
|
||||
{
|
||||
"pub_key" : {
|
||||
"value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=",
|
||||
"type" : "AC26791624DE60"
|
||||
},
|
||||
"power" : 10,
|
||||
"name" : ""
|
||||
}
|
||||
],
|
||||
"app_hash" : "",
|
||||
"chain_id" : "test-chain-rDlYSN",
|
||||
"genesis_time" : "0001-01-01T00:00:00Z"
|
||||
}
|
||||
|
||||
Update the ``genesis.json`` in ``~/.tendermint/config``. Copy the genesis file
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
|
@ -1,7 +1,7 @@
|
||||
package evidence
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
@ -93,7 +93,7 @@ func (p *provider) GetLatestCommit() (*ctypes.ResultCommit, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.node.Commit(&status.LatestBlockHeight)
|
||||
return p.node.Commit(&status.SyncInfo.LatestBlockHeight)
|
||||
}
|
||||
|
||||
// CommitFromResult ...
|
||||
|
@ -1,7 +1,7 @@
|
||||
package files
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,7 @@ package proxy
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tmlibs/clist"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
)
|
||||
import amino "github.com/tendermint/go-amino"
|
||||
|
||||
var cdc = amino.NewCodec()
|
||||
|
||||
|
@ -405,7 +405,7 @@ func (n *Node) OnStart() error {
|
||||
}
|
||||
n.Logger.Info("P2P Node ID", "ID", nodeKey.ID(), "file", n.config.NodeKeyFile())
|
||||
|
||||
nodeInfo := n.makeNodeInfo(nodeKey.PubKey())
|
||||
nodeInfo := n.makeNodeInfo(nodeKey.ID())
|
||||
n.sw.SetNodeInfo(nodeInfo)
|
||||
n.sw.SetNodeKey(nodeKey)
|
||||
|
||||
@ -579,13 +579,13 @@ func (n *Node) ProxyApp() proxy.AppConns {
|
||||
return n.proxyApp
|
||||
}
|
||||
|
||||
func (n *Node) makeNodeInfo(pubKey crypto.PubKey) p2p.NodeInfo {
|
||||
func (n *Node) makeNodeInfo(nodeID p2p.ID) p2p.NodeInfo {
|
||||
txIndexerStatus := "on"
|
||||
if _, ok := n.txIndexer.(*null.TxIndex); ok {
|
||||
txIndexerStatus = "off"
|
||||
}
|
||||
nodeInfo := p2p.NodeInfo{
|
||||
PubKey: pubKey,
|
||||
ID: nodeID,
|
||||
Network: n.genesisDoc.ChainID,
|
||||
Version: version.Version,
|
||||
Channels: []byte{
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package conn
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -124,7 +125,7 @@ func (fc *FuzzedConnection) SetWriteDeadline(t time.Time) error {
|
||||
|
||||
func (fc *FuzzedConnection) randomDuration() time.Duration {
|
||||
maxDelayMillis := int(fc.config.MaxDelay.Nanoseconds() / 1000)
|
||||
return time.Millisecond * time.Duration(rand.Int()%maxDelayMillis) // nolint: gas
|
||||
return time.Millisecond * time.Duration(cmn.RandInt()%maxDelayMillis) // nolint: gas
|
||||
}
|
||||
|
||||
// implements the fuzz (delay, kill conn)
|
||||
@ -137,7 +138,7 @@ func (fc *FuzzedConnection) fuzz() bool {
|
||||
switch fc.config.Mode {
|
||||
case FuzzModeDrop:
|
||||
// randomly drop the r/w, drop the conn, or sleep
|
||||
r := rand.Float64()
|
||||
r := cmn.RandFloat64()
|
||||
if r <= fc.config.ProbDropRW {
|
||||
return true
|
||||
} else if r < fc.config.ProbDropRW+fc.config.ProbDropConn {
|
||||
|
@ -47,7 +47,7 @@ func PubKeyToID(pubKey crypto.PubKey) ID {
|
||||
// If the file does not exist, it generates and saves a new NodeKey.
|
||||
func LoadOrGenNodeKey(filePath string) (*NodeKey, error) {
|
||||
if cmn.FileExists(filePath) {
|
||||
nodeKey, err := loadNodeKey(filePath)
|
||||
nodeKey, err := LoadNodeKey(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -56,7 +56,7 @@ func LoadOrGenNodeKey(filePath string) (*NodeKey, error) {
|
||||
return genNodeKey(filePath)
|
||||
}
|
||||
|
||||
func loadNodeKey(filePath string) (*NodeKey, error) {
|
||||
func LoadNodeKey(filePath string) (*NodeKey, error) {
|
||||
jsonBytes, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -3,8 +3,6 @@ package p2p
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -20,8 +18,8 @@ func MaxNodeInfoSize() int {
|
||||
// between two peers during the Tendermint P2P handshake.
|
||||
type NodeInfo struct {
|
||||
// Authenticate
|
||||
PubKey crypto.PubKey `json:"pub_key"` // authenticated pubkey
|
||||
ListenAddr string `json:"listen_addr"` // accepting incoming
|
||||
ID ID `json:"id"` // authenticated identifier
|
||||
ListenAddr string `json:"listen_addr"` // accepting incoming
|
||||
|
||||
// Check compatibility
|
||||
Network string `json:"network"` // network/chain ID
|
||||
@ -107,19 +105,12 @@ OUTER_LOOP:
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns node's ID.
|
||||
func (info NodeInfo) ID() ID {
|
||||
return PubKeyToID(info.PubKey)
|
||||
}
|
||||
|
||||
// NetAddress returns a NetAddress derived from the NodeInfo -
|
||||
// it includes the authenticated peer ID and the self-reported
|
||||
// ListenAddr. Note that the ListenAddr is not authenticated and
|
||||
// may not match that address actually dialed if its an outbound peer.
|
||||
func (info NodeInfo) NetAddress() *NetAddress {
|
||||
id := PubKeyToID(info.PubKey)
|
||||
addr := info.ListenAddr
|
||||
netAddr, err := NewNetAddressString(IDAddressString(id, addr))
|
||||
netAddr, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
|
||||
if err != nil {
|
||||
panic(err) // everything should be well formed by now
|
||||
}
|
||||
@ -127,7 +118,8 @@ func (info NodeInfo) NetAddress() *NetAddress {
|
||||
}
|
||||
|
||||
func (info NodeInfo) String() string {
|
||||
return fmt.Sprintf("NodeInfo{pk: %v, moniker: %v, network: %v [listen %v], version: %v (%v)}", info.PubKey, info.Moniker, info.Network, info.ListenAddr, info.Version, info.Other)
|
||||
return fmt.Sprintf("NodeInfo{id: %v, moniker: %v, network: %v [listen %v], version: %v (%v)}",
|
||||
info.ID, info.Moniker, info.Network, info.ListenAddr, info.Version, info.Other)
|
||||
}
|
||||
|
||||
func splitVersion(version string) (string, string, string, error) {
|
||||
|
@ -202,7 +202,7 @@ func (p *peer) OnStop() {
|
||||
|
||||
// ID returns the peer's ID - the hex encoded hash of its pubkey.
|
||||
func (p *peer) ID() ID {
|
||||
return p.nodeInfo.ID()
|
||||
return p.nodeInfo.ID
|
||||
}
|
||||
|
||||
// IsOutbound returns true if the connection is outbound, false otherwise.
|
||||
|
@ -13,11 +13,11 @@ import (
|
||||
|
||||
// Returns an empty kvstore peer
|
||||
func randPeer() *peer {
|
||||
pubKey := crypto.GenPrivKeyEd25519().PubKey()
|
||||
nodeKey := NodeKey{PrivKey: crypto.GenPrivKeyEd25519()}
|
||||
return &peer{
|
||||
nodeInfo: NodeInfo{
|
||||
ID: nodeKey.ID(),
|
||||
ListenAddr: cmn.Fmt("%v.%v.%v.%v:46656", rand.Int()%256, rand.Int()%256, rand.Int()%256, rand.Int()%256),
|
||||
PubKey: pubKey,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func createOutboundPeerAndPerformHandshake(addr *NetAddress, config *PeerConfig)
|
||||
return nil, err
|
||||
}
|
||||
nodeInfo, err := pc.HandshakeTimeout(NodeInfo{
|
||||
PubKey: pk.PubKey(),
|
||||
ID: addr.ID,
|
||||
Moniker: "host_peer",
|
||||
Network: "testing",
|
||||
Version: "123.123.123",
|
||||
@ -152,7 +152,7 @@ func (p *remotePeer) accept(l net.Listener) {
|
||||
golog.Fatalf("Failed to create a peer: %+v", err)
|
||||
}
|
||||
_, err = pc.HandshakeTimeout(NodeInfo{
|
||||
PubKey: p.PrivKey.PubKey(),
|
||||
ID: p.Addr().ID,
|
||||
Moniker: "remote_peer",
|
||||
Network: "testing",
|
||||
Version: "123.123.123",
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
@ -82,7 +81,7 @@ type addrBook struct {
|
||||
|
||||
// accessed concurrently
|
||||
mtx sync.Mutex
|
||||
rand *rand.Rand
|
||||
rand *cmn.Rand
|
||||
ourAddrs map[string]struct{}
|
||||
addrLookup map[p2p.ID]*knownAddress // new & old
|
||||
bucketsOld []map[string]*knownAddress
|
||||
@ -97,7 +96,7 @@ type addrBook struct {
|
||||
// Use Start to begin processing asynchronous address updates.
|
||||
func NewAddrBook(filePath string, routabilityStrict bool) *addrBook {
|
||||
am := &addrBook{
|
||||
rand: rand.New(rand.NewSource(time.Now().UnixNano())), // TODO: seed from outside
|
||||
rand: cmn.NewRand(),
|
||||
ourAddrs: make(map[string]struct{}),
|
||||
addrLookup: make(map[p2p.ID]*knownAddress),
|
||||
filePath: filePath,
|
||||
@ -320,7 +319,7 @@ func (a *addrBook) GetSelection() []*p2p.NetAddress {
|
||||
// XXX: What's the point of this if we already loop randomly through addrLookup ?
|
||||
for i := 0; i < numAddresses; i++ {
|
||||
// pick a number between current index and the end
|
||||
j := rand.Intn(len(allAddr)-i) + i
|
||||
j := cmn.RandIntn(len(allAddr)-i) + i
|
||||
allAddr[i], allAddr[j] = allAddr[j], allAddr[i]
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,12 @@ package pex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
@ -288,7 +287,7 @@ func (r *PEXReactor) SetEnsurePeersPeriod(d time.Duration) {
|
||||
// Ensures that sufficient peers are connected. (continuous)
|
||||
func (r *PEXReactor) ensurePeersRoutine() {
|
||||
var (
|
||||
seed = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
seed = cmn.NewRand()
|
||||
jitter = seed.Int63n(r.ensurePeersPeriod.Nanoseconds())
|
||||
)
|
||||
|
||||
@ -375,7 +374,7 @@ func (r *PEXReactor) ensurePeers() {
|
||||
peers := r.Switch.Peers().List()
|
||||
peersCount := len(peers)
|
||||
if peersCount > 0 {
|
||||
peer := peers[rand.Int()%peersCount] // nolint: gas
|
||||
peer := peers[cmn.RandInt()%peersCount] // nolint: gas
|
||||
r.Logger.Info("We need more addresses. Sending pexRequest to random peer", "peer", peer)
|
||||
r.RequestAddrs(peer)
|
||||
}
|
||||
@ -404,7 +403,7 @@ func (r *PEXReactor) dialPeer(addr *p2p.NetAddress) {
|
||||
|
||||
// exponential backoff if it's not our first attempt to dial given address
|
||||
if attempts > 0 {
|
||||
jitterSeconds := time.Duration(rand.Float64() * float64(time.Second)) // 1s == (1e9 ns)
|
||||
jitterSeconds := time.Duration(cmn.RandFloat64() * float64(time.Second)) // 1s == (1e9 ns)
|
||||
backoffDuration := jitterSeconds + ((1 << uint(attempts)) * time.Second)
|
||||
sinceLastDialed := time.Since(lastDialed)
|
||||
if sinceLastDialed < backoffDuration {
|
||||
@ -457,7 +456,7 @@ func (r *PEXReactor) dialSeeds() {
|
||||
}
|
||||
seedAddrs, _ := p2p.NewNetAddressStrings(r.config.Seeds)
|
||||
|
||||
perm := rand.Perm(lSeeds)
|
||||
perm := cmn.RandPerm(lSeeds)
|
||||
// perm := r.Switch.rng.Perm(lSeeds)
|
||||
for _, i := range perm {
|
||||
// dial a random seed
|
||||
|
@ -289,7 +289,7 @@ func TestPEXReactorCrawlStatus(t *testing.T) {
|
||||
func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) {
|
||||
peer := p2p.CreateRandomPeer(false)
|
||||
|
||||
pexR, book := createReactor(&PEXReactorConfig{PrivatePeerIDs: []string{string(peer.NodeInfo().ID())}})
|
||||
pexR, book := createReactor(&PEXReactorConfig{PrivatePeerIDs: []string{string(peer.NodeInfo().ID)}})
|
||||
defer teardownReactor(book)
|
||||
|
||||
// we have to send a request to receive responses
|
||||
@ -356,12 +356,12 @@ func newMockPeer() mockPeer {
|
||||
return mp
|
||||
}
|
||||
|
||||
func (mp mockPeer) ID() p2p.ID { return p2p.PubKeyToID(mp.pubKey) }
|
||||
func (mp mockPeer) ID() p2p.ID { return mp.addr.ID }
|
||||
func (mp mockPeer) IsOutbound() bool { return mp.outbound }
|
||||
func (mp mockPeer) IsPersistent() bool { return mp.persistent }
|
||||
func (mp mockPeer) NodeInfo() p2p.NodeInfo {
|
||||
return p2p.NodeInfo{
|
||||
PubKey: mp.pubKey,
|
||||
ID: mp.addr.ID,
|
||||
ListenAddr: mp.addr.DialString(),
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package pex
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
)
|
||||
import amino "github.com/tendermint/go-amino"
|
||||
|
||||
var cdc *amino.Codec = amino.NewCodec()
|
||||
|
||||
|
@ -3,7 +3,6 @@ package p2p
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
@ -67,7 +66,7 @@ type Switch struct {
|
||||
filterConnByAddr func(net.Addr) error
|
||||
filterConnByID func(ID) error
|
||||
|
||||
rng *rand.Rand // seed for randomizing dial times and orders
|
||||
rng *cmn.Rand // seed for randomizing dial times and orders
|
||||
}
|
||||
|
||||
// NewSwitch creates a new Switch with the given config.
|
||||
@ -82,9 +81,8 @@ func NewSwitch(config *cfg.P2PConfig) *Switch {
|
||||
dialing: cmn.NewCMap(),
|
||||
}
|
||||
|
||||
// Ensure we have a completely undeterministic PRNG. cmd.RandInt64() draws
|
||||
// from a seed that's initialized with OS entropy on process start.
|
||||
sw.rng = rand.New(rand.NewSource(cmn.RandInt64()))
|
||||
// Ensure we have a completely undeterministic PRNG.
|
||||
sw.rng = cmn.NewRand()
|
||||
|
||||
// TODO: collapse the peerConfig into the config ?
|
||||
sw.peerConfig.MConfig.FlushThrottle = time.Duration(config.FlushThrottleTimeout) * time.Millisecond
|
||||
@ -361,7 +359,9 @@ func (sw *Switch) DialPeersAsync(addrBook AddrBook, peers []string, persistent b
|
||||
for _, netAddr := range netAddrs {
|
||||
// do not add our address or ID
|
||||
if !netAddr.Same(ourAddr) {
|
||||
addrBook.AddAddress(netAddr, ourAddr)
|
||||
if err := addrBook.AddAddress(netAddr, ourAddr); err != nil {
|
||||
sw.Logger.Error("Can't add peer's address to addrbook", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Persist some peers to disk right away.
|
||||
@ -515,7 +515,7 @@ func (sw *Switch) addPeer(pc peerConn) error {
|
||||
return err
|
||||
}
|
||||
|
||||
peerID := peerNodeInfo.ID()
|
||||
peerID := peerNodeInfo.ID
|
||||
|
||||
// ensure connection key matches self reported key
|
||||
if pc.config.AuthEnc {
|
||||
|
@ -221,14 +221,14 @@ func TestConnIDFilter(t *testing.T) {
|
||||
c1, c2 := conn.NetPipe()
|
||||
|
||||
s1.SetIDFilter(func(id ID) error {
|
||||
if id == PubKeyToID(s2.nodeInfo.PubKey) {
|
||||
if id == s2.nodeInfo.ID {
|
||||
return fmt.Errorf("Error: pipe is blacklisted")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
s2.SetIDFilter(func(id ID) error {
|
||||
if id == PubKeyToID(s1.nodeInfo.PubKey) {
|
||||
if id == s1.nodeInfo.ID {
|
||||
return fmt.Errorf("Error: pipe is blacklisted")
|
||||
}
|
||||
return nil
|
||||
|
@ -1,7 +1,6 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"net"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
@ -23,8 +22,8 @@ func CreateRandomPeer(outbound bool) *peer {
|
||||
outbound: outbound,
|
||||
},
|
||||
nodeInfo: NodeInfo{
|
||||
ID: netAddr.ID,
|
||||
ListenAddr: netAddr.DialString(),
|
||||
PubKey: crypto.GenPrivKeyEd25519().PubKey(),
|
||||
},
|
||||
mconn: &conn.MConnection{},
|
||||
}
|
||||
@ -35,7 +34,7 @@ func CreateRandomPeer(outbound bool) *peer {
|
||||
func CreateRoutableAddr() (addr string, netAddr *NetAddress) {
|
||||
for {
|
||||
var err error
|
||||
addr = cmn.Fmt("%X@%v.%v.%v.%v:46656", cmn.RandBytes(20), rand.Int()%256, rand.Int()%256, rand.Int()%256, rand.Int()%256)
|
||||
addr = cmn.Fmt("%X@%v.%v.%v.%v:46656", cmn.RandBytes(20), cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256)
|
||||
netAddr, err = NewNetAddressString(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -137,11 +136,11 @@ func MakeSwitch(cfg *cfg.P2PConfig, i int, network, version string, initSwitch f
|
||||
sw.SetLogger(log.TestingLogger())
|
||||
sw = initSwitch(i, sw)
|
||||
ni := NodeInfo{
|
||||
PubKey: nodeKey.PubKey(),
|
||||
ID: nodeKey.ID(),
|
||||
Moniker: cmn.Fmt("switch%d", i),
|
||||
Network: network,
|
||||
Version: version,
|
||||
ListenAddr: cmn.Fmt("%v:%v", network, rand.Intn(64512)+1023),
|
||||
ListenAddr: cmn.Fmt("%v:%v", network, cmn.RandIntn(64512)+1023),
|
||||
}
|
||||
for ch := range sw.reactorsByCh {
|
||||
ni.Channels = append(ni.Channels, ch)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
@ -41,7 +41,7 @@ func WaitForHeight(c StatusClient, h int64, waiter Waiter) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delta = h - s.LatestBlockHeight
|
||||
delta = h - s.SyncInfo.LatestBlockHeight
|
||||
// wait for the time, or abort early
|
||||
if err := waiter(delta); err != nil {
|
||||
return err
|
||||
|
@ -32,7 +32,7 @@ func TestWaitForHeight(t *testing.T) {
|
||||
|
||||
// now set current block height to 10
|
||||
m.Call = mock.Call{
|
||||
Response: &ctypes.ResultStatus{LatestBlockHeight: 10},
|
||||
Response: &ctypes.ResultStatus{SyncInfo: ctypes.SyncInfo{LatestBlockHeight: 10}},
|
||||
}
|
||||
|
||||
// we will not wait for more than 10 blocks
|
||||
@ -52,7 +52,7 @@ func TestWaitForHeight(t *testing.T) {
|
||||
// we use the callback to update the status height
|
||||
myWaiter := func(delta int64) error {
|
||||
// update the height for the next call
|
||||
m.Call.Response = &ctypes.ResultStatus{LatestBlockHeight: 15}
|
||||
m.Call.Response = &ctypes.ResultStatus{SyncInfo: ctypes.SyncInfo{LatestBlockHeight: 15}}
|
||||
return client.DefaultWaitStrategy(delta)
|
||||
}
|
||||
|
||||
@ -66,11 +66,11 @@ func TestWaitForHeight(t *testing.T) {
|
||||
require.Nil(pre.Error)
|
||||
prer, ok := pre.Response.(*ctypes.ResultStatus)
|
||||
require.True(ok)
|
||||
assert.Equal(int64(10), prer.LatestBlockHeight)
|
||||
assert.Equal(int64(10), prer.SyncInfo.LatestBlockHeight)
|
||||
|
||||
post := r.Calls[4]
|
||||
require.Nil(post.Error)
|
||||
postr, ok := post.Response.(*ctypes.ResultStatus)
|
||||
require.True(ok)
|
||||
assert.Equal(int64(15), postr.LatestBlockHeight)
|
||||
assert.Equal(int64(15), postr.SyncInfo.LatestBlockHeight)
|
||||
}
|
||||
|
@ -17,9 +17,11 @@ func TestStatus(t *testing.T) {
|
||||
m := &mock.StatusMock{
|
||||
Call: mock.Call{
|
||||
Response: &ctypes.ResultStatus{
|
||||
LatestBlockHash: cmn.HexBytes("block"),
|
||||
LatestAppHash: cmn.HexBytes("app"),
|
||||
LatestBlockHeight: 10,
|
||||
SyncInfo: ctypes.SyncInfo{
|
||||
LatestBlockHash: cmn.HexBytes("block"),
|
||||
LatestAppHash: cmn.HexBytes("app"),
|
||||
LatestBlockHeight: 10,
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
@ -29,8 +31,8 @@ func TestStatus(t *testing.T) {
|
||||
// make sure response works proper
|
||||
status, err := r.Status()
|
||||
require.Nil(err, "%+v", err)
|
||||
assert.EqualValues("block", status.LatestBlockHash)
|
||||
assert.EqualValues(10, status.LatestBlockHeight)
|
||||
assert.EqualValues("block", status.SyncInfo.LatestBlockHash)
|
||||
assert.EqualValues(10, status.SyncInfo.LatestBlockHeight)
|
||||
|
||||
// make sure recorder works properly
|
||||
require.Equal(1, len(r.Calls))
|
||||
@ -41,6 +43,6 @@ func TestStatus(t *testing.T) {
|
||||
require.NotNil(rs.Response)
|
||||
st, ok := rs.Response.(*ctypes.ResultStatus)
|
||||
require.True(ok)
|
||||
assert.EqualValues("block", st.LatestBlockHash)
|
||||
assert.EqualValues(10, st.LatestBlockHeight)
|
||||
assert.EqualValues("block", st.SyncInfo.LatestBlockHash)
|
||||
assert.EqualValues(10, st.SyncInfo.LatestBlockHeight)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func TestInfo(t *testing.T) {
|
||||
info, err := c.ABCIInfo()
|
||||
require.Nil(t, err, "%d: %+v", i, err)
|
||||
// TODO: this is not correct - fix merkleeyes!
|
||||
// assert.EqualValues(t, status.LatestBlockHeight, info.Response.LastBlockHeight)
|
||||
// assert.EqualValues(t, status.SyncInfo.LatestBlockHeight, info.Response.LastBlockHeight)
|
||||
assert.True(t, strings.Contains(info.Response.Data, "size"))
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ func TestAppCalls(t *testing.T) {
|
||||
s, err := c.Status()
|
||||
require.Nil(err, "%d: %+v", i, err)
|
||||
// sh is start height or status height
|
||||
sh := s.LatestBlockHeight
|
||||
sh := s.SyncInfo.LatestBlockHeight
|
||||
|
||||
// look for the future
|
||||
h := sh + 2
|
||||
|
@ -1,8 +1,9 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
cm "github.com/tendermint/tendermint/consensus"
|
||||
cstypes "github.com/tendermint/tendermint/consensus/types"
|
||||
p2p "github.com/tendermint/tendermint/p2p"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
@ -58,7 +59,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) {
|
||||
return &ctypes.ResultValidators{height, validators.Validators}, nil
|
||||
}
|
||||
|
||||
// Dump consensus state.
|
||||
// DumpConsensusState dumps consensus state.
|
||||
//
|
||||
// ```shell
|
||||
// curl 'localhost:46657/dump_consensus_state'
|
||||
@ -83,11 +84,18 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) {
|
||||
// }
|
||||
// ```
|
||||
func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
|
||||
peerRoundStates := make(map[p2p.ID]*cstypes.PeerRoundState)
|
||||
peerRoundStates := make(map[p2p.ID]json.RawMessage)
|
||||
for _, peer := range p2pSwitch.Peers().List() {
|
||||
peerState := peer.Get(types.PeerStateKey).(*cm.PeerState)
|
||||
peerRoundState := peerState.GetRoundState()
|
||||
peerRoundState, err := peerState.GetRoundStateJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
peerRoundStates[peer.ID()] = peerRoundState
|
||||
}
|
||||
return &ctypes.ResultDumpConsensusState{consensusState.GetRoundState(), peerRoundStates}, nil
|
||||
roundState, err := consensusState.GetRoundStateJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ctypes.ResultDumpConsensusState{roundState, peerRoundStates}, nil
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ func NetInfo() (*ctypes.ResultNetInfo, error) {
|
||||
for _, peer := range p2pSwitch.Peers().List() {
|
||||
peers = append(peers, ctypes.Peer{
|
||||
NodeInfo: peer.NodeInfo(),
|
||||
ID: peer.ID(),
|
||||
IsOutbound: peer.IsOutbound(),
|
||||
ConnectionStatus: peer.Status(),
|
||||
})
|
||||
|
@ -3,9 +3,8 @@ package core
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-crypto"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/tendermint/consensus"
|
||||
cstypes "github.com/tendermint/tendermint/consensus/types"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
@ -23,7 +22,7 @@ var subscribeTimeout = 5 * time.Second
|
||||
type Consensus interface {
|
||||
GetState() sm.State
|
||||
GetValidators() (int64, []*types.Validator)
|
||||
GetRoundState() *cstypes.RoundState
|
||||
GetRoundStateJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
type P2P interface {
|
||||
|
@ -27,15 +27,20 @@ import (
|
||||
// ```json
|
||||
// {
|
||||
// "result": {
|
||||
// "syncing": false,
|
||||
// "latest_block_time": "2017-12-07T18:19:47.617Z",
|
||||
// "latest_block_height": 6,
|
||||
// "latest_app_hash": "",
|
||||
// "latest_block_hash": "A63D0C3307DEDCCFCC82ED411AE9108B70B29E02",
|
||||
// "pub_key": {
|
||||
// "data": "8C9A68070CBE33F9C445862BA1E9D96A75CEB68C0CF6ADD3652D07DCAC5D0380",
|
||||
// "type": "ed25519"
|
||||
// },
|
||||
// "sync_info": {
|
||||
// "syncing": false,
|
||||
// "latest_block_time": "2017-12-07T18:19:47.617Z",
|
||||
// "latest_block_height": 6,
|
||||
// "latest_app_hash": "",
|
||||
// "latest_block_hash": "A63D0C3307DEDCCFCC82ED411AE9108B70B29E02",
|
||||
// }
|
||||
// "validator_info": {
|
||||
// "pub_key": {
|
||||
// "data": "8C9A68070CBE33F9C445862BA1E9D96A75CEB68C0CF6ADD3652D07DCAC5D0380",
|
||||
// "type": "ed25519"
|
||||
// },
|
||||
// "voting_power": 10
|
||||
// }
|
||||
// "node_info": {
|
||||
// "other": [
|
||||
// "wire_version=0.7.2",
|
||||
@ -51,9 +56,6 @@ import (
|
||||
// "network": "test-chain-qhVCa2",
|
||||
// "moniker": "vagrant-ubuntu-trusty-64",
|
||||
// "pub_key": "844981FE99ABB19F7816F2D5E94E8A74276AB1153760A7799E925C75401856C6",
|
||||
// "validator_status": {
|
||||
// "voting_power": 10
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "id": "",
|
||||
@ -78,20 +80,20 @@ func Status() (*ctypes.ResultStatus, error) {
|
||||
latestBlockTime := time.Unix(0, latestBlockTimeNano)
|
||||
|
||||
result := &ctypes.ResultStatus{
|
||||
NodeInfo: p2pSwitch.NodeInfo(),
|
||||
PubKey: pubKey,
|
||||
LatestBlockHash: latestBlockHash,
|
||||
LatestAppHash: latestAppHash,
|
||||
LatestBlockHeight: latestHeight,
|
||||
LatestBlockTime: latestBlockTime,
|
||||
Syncing: consensusReactor.FastSync(),
|
||||
NodeInfo: p2pSwitch.NodeInfo(),
|
||||
SyncInfo: ctypes.SyncInfo{
|
||||
LatestBlockHash: latestBlockHash,
|
||||
LatestAppHash: latestAppHash,
|
||||
LatestBlockHeight: latestHeight,
|
||||
LatestBlockTime: latestBlockTime,
|
||||
Syncing: consensusReactor.FastSync(),
|
||||
},
|
||||
ValidatorInfo: ctypes.ValidatorInfo{PubKey: pubKey},
|
||||
}
|
||||
|
||||
// add ValidatorStatus if node is a validator
|
||||
if val := validatorAtHeight(latestHeight); val != nil {
|
||||
result.ValidatorStatus = ctypes.ValidatorStatus{
|
||||
VotingPower: val.VotingPower,
|
||||
}
|
||||
result.ValidatorInfo.VotingPower = val.VotingPower
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
@ -1,6 +1,7 @@
|
||||
package core_types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -8,7 +9,6 @@ import (
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
cstypes "github.com/tendermint/tendermint/consensus/types"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
@ -54,19 +54,23 @@ func NewResultCommit(header *types.Header, commit *types.Commit,
|
||||
}
|
||||
}
|
||||
|
||||
type ValidatorStatus struct {
|
||||
VotingPower int64 `json:"voting_power"`
|
||||
type SyncInfo struct {
|
||||
LatestBlockHash cmn.HexBytes `json:"latest_block_hash"`
|
||||
LatestAppHash cmn.HexBytes `json:"latest_app_hash"`
|
||||
LatestBlockHeight int64 `json:"latest_block_height"`
|
||||
LatestBlockTime time.Time `json:"latest_block_time"`
|
||||
Syncing bool `json:"syncing"`
|
||||
}
|
||||
|
||||
type ValidatorInfo struct {
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
VotingPower int64 `json:"voting_power"`
|
||||
}
|
||||
|
||||
type ResultStatus struct {
|
||||
NodeInfo p2p.NodeInfo `json:"node_info"`
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
LatestBlockHash cmn.HexBytes `json:"latest_block_hash"`
|
||||
LatestAppHash cmn.HexBytes `json:"latest_app_hash"`
|
||||
LatestBlockHeight int64 `json:"latest_block_height"`
|
||||
LatestBlockTime time.Time `json:"latest_block_time"`
|
||||
Syncing bool `json:"syncing"`
|
||||
ValidatorStatus ValidatorStatus `json:"validator_status,omitempty"`
|
||||
NodeInfo p2p.NodeInfo `json:"node_info"`
|
||||
SyncInfo SyncInfo `json:"sync_info"`
|
||||
ValidatorInfo ValidatorInfo `json:"validator_info"`
|
||||
}
|
||||
|
||||
func (s *ResultStatus) TxIndexEnabled() bool {
|
||||
@ -98,7 +102,6 @@ type ResultDialPeers struct {
|
||||
|
||||
type Peer struct {
|
||||
p2p.NodeInfo `json:"node_info"`
|
||||
p2p.ID `json:"node_id"`
|
||||
IsOutbound bool `json:"is_outbound"`
|
||||
ConnectionStatus p2p.ConnectionStatus `json:"connection_status"`
|
||||
}
|
||||
@ -109,8 +112,8 @@ type ResultValidators struct {
|
||||
}
|
||||
|
||||
type ResultDumpConsensusState struct {
|
||||
RoundState *cstypes.RoundState `json:"round_state"`
|
||||
PeerRoundStates map[p2p.ID]*cstypes.PeerRoundState `json:"peer_round_states"`
|
||||
RoundState json.RawMessage `json:"round_state"`
|
||||
PeerRoundStates map[p2p.ID]json.RawMessage `json:"peer_round_states"`
|
||||
}
|
||||
|
||||
type ResultBroadcastTx struct {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package core_types
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
@ -5,8 +5,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
)
|
||||
|
||||
type Tx []byte
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tendermint/go-amino"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
types "github.com/tendermint/tendermint/rpc/lib/types"
|
||||
)
|
||||
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@ -14,7 +13,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
metrics "github.com/rcrowley/go-metrics"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
types "github.com/tendermint/tendermint/rpc/lib/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
@ -266,7 +265,7 @@ func (c *WSClient) reconnect() error {
|
||||
}()
|
||||
|
||||
for {
|
||||
jitterSeconds := time.Duration(rand.Float64() * float64(time.Second)) // 1s == (1e9 ns)
|
||||
jitterSeconds := time.Duration(cmn.RandFloat64() * float64(time.Second)) // 1s == (1e9 ns)
|
||||
backoffDuration := jitterSeconds + ((1 << uint(attempt)) * time.Second)
|
||||
|
||||
c.Logger.Info("reconnecting", "attempt", attempt+1, "backoff_duration", backoffDuration)
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
types "github.com/tendermint/tendermint/rpc/lib/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
rs "github.com/tendermint/tendermint/rpc/lib/server"
|
||||
types "github.com/tendermint/tendermint/rpc/lib/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
tmpubsub "github.com/tendermint/tmlibs/pubsub"
|
||||
)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
)
|
||||
|
||||
type SampleResult struct {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
)
|
||||
import amino "github.com/tendermint/go-amino"
|
||||
|
||||
var cdc = amino.NewCodec()
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ for i in $(seq 1 "$N"); do
|
||||
addr=$(test/p2p/ip.sh "$i"):46657
|
||||
|
||||
# current state
|
||||
HASH1=$(curl -s "$addr/status" | jq .result.latest_app_hash)
|
||||
HASH1=$(curl -s "$addr/status" | jq .result.sync_info.latest_app_hash)
|
||||
|
||||
# - send a tx
|
||||
TX=aadeadbeefbeefbeef0$i
|
||||
@ -26,11 +26,11 @@ for i in $(seq 1 "$N"); do
|
||||
echo ""
|
||||
|
||||
# we need to wait another block to get the new app_hash
|
||||
h1=$(curl -s "$addr/status" | jq .result.latest_block_height)
|
||||
h1=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height)
|
||||
h2=$h1
|
||||
while [ "$h2" == "$h1" ]; do
|
||||
sleep 1
|
||||
h2=$(curl -s "$addr/status" | jq .result.latest_block_height)
|
||||
h2=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height)
|
||||
done
|
||||
|
||||
# wait for all other peers to get to this height
|
||||
@ -39,16 +39,16 @@ for i in $(seq 1 "$N"); do
|
||||
if [[ "$i" != "$j" ]]; then
|
||||
addrJ=$(test/p2p/ip.sh "$j"):46657
|
||||
|
||||
h=$(curl -s "$addrJ/status" | jq .result.latest_block_height)
|
||||
h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height)
|
||||
while [ "$h" -lt "$minHeight" ]; do
|
||||
sleep 1
|
||||
h=$(curl -s "$addrJ/status" | jq .result.latest_block_height)
|
||||
h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height)
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# check that hash was updated
|
||||
HASH2=$(curl -s "$addr/status" | jq .result.latest_app_hash)
|
||||
HASH2=$(curl -s "$addr/status" | jq .result.sync_info.latest_app_hash)
|
||||
if [[ "$HASH1" == "$HASH2" ]]; then
|
||||
echo "Expected state hash to update from $HASH1. Got $HASH2"
|
||||
exit 1
|
||||
@ -58,7 +58,7 @@ for i in $(seq 1 "$N"); do
|
||||
for j in $(seq 1 "$N"); do
|
||||
if [[ "$i" != "$j" ]]; then
|
||||
addrJ=$(test/p2p/ip.sh "$j"):46657
|
||||
HASH3=$(curl -s "$addrJ/status" | jq .result.latest_app_hash)
|
||||
HASH3=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_app_hash)
|
||||
|
||||
if [[ "$HASH2" != "$HASH3" ]]; then
|
||||
echo "App hash for node $j doesn't match. Got $HASH3, expected $HASH2"
|
||||
|
@ -54,12 +54,12 @@ for i in `seq 1 $N`; do
|
||||
done
|
||||
|
||||
# - assert block height is greater than 1
|
||||
BLOCK_HEIGHT=`curl -s $addr/status | jq .result.latest_block_height`
|
||||
BLOCK_HEIGHT=`curl -s $addr/status | jq .result.sync_info.latest_block_height`
|
||||
COUNT=0
|
||||
while [ "$BLOCK_HEIGHT" -le 1 ]; do
|
||||
echo "Waiting for node $i to commit a block ..."
|
||||
sleep 1
|
||||
BLOCK_HEIGHT=`curl -s $addr/status | jq .result.latest_block_height`
|
||||
BLOCK_HEIGHT=`curl -s $addr/status | jq .result.sync_info.latest_block_height`
|
||||
COUNT=$((COUNT+1))
|
||||
if [ "$COUNT" -gt "$MAX_SLEEP" ]; then
|
||||
echo "Waited too long for node $i to commit a block"
|
||||
|
@ -15,10 +15,10 @@ peerID=$(( $(($ID % 4)) + 1 )) # 1->2 ... 3->4 ... 4->1
|
||||
peer_addr=$(test/p2p/ip.sh $peerID):46657
|
||||
|
||||
# get another peer's height
|
||||
h1=`curl -s $peer_addr/status | jq .result.latest_block_height`
|
||||
h1=`curl -s $peer_addr/status | jq .result.sync_info.latest_block_height`
|
||||
|
||||
# get another peer's state
|
||||
root1=`curl -s $peer_addr/status | jq .result.latest_app_hash`
|
||||
root1=`curl -s $peer_addr/status | jq .result.sync_info.latest_app_hash`
|
||||
|
||||
echo "Other peer is on height $h1 with state $root1"
|
||||
echo "Waiting for peer $ID to catch up"
|
||||
@ -29,12 +29,12 @@ set +o pipefail
|
||||
h2="0"
|
||||
while [[ "$h2" -lt "$(($h1+3))" ]]; do
|
||||
sleep 1
|
||||
h2=`curl -s $addr/status | jq .result.latest_block_height`
|
||||
h2=`curl -s $addr/status | jq .result.sync_info.latest_block_height`
|
||||
echo "... $h2"
|
||||
done
|
||||
|
||||
# check the app hash
|
||||
root2=`curl -s $addr/status | jq .result.latest_app_hash`
|
||||
root2=`curl -s $addr/status | jq .result.sync_info.latest_app_hash`
|
||||
|
||||
if [[ "$root1" != "$root2" ]]; then
|
||||
echo "App hash after fast sync does not match. Got $root2; expected $root1"
|
||||
|
@ -23,7 +23,7 @@ set -e
|
||||
|
||||
# get the first peer's height
|
||||
addr=$(test/p2p/ip.sh 1):46657
|
||||
h1=$(curl -s "$addr/status" | jq .result.latest_block_height)
|
||||
h1=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height)
|
||||
echo "1st peer is on height $h1"
|
||||
|
||||
echo "Waiting until other peers reporting a height higher than the 1st one"
|
||||
@ -33,7 +33,7 @@ for i in $(seq 2 "$NUM_OF_PEERS"); do
|
||||
|
||||
while [[ $hi -le $h1 ]] ; do
|
||||
addr=$(test/p2p/ip.sh "$i"):46657
|
||||
hi=$(curl -s "$addr/status" | jq .result.latest_block_height)
|
||||
hi=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height)
|
||||
|
||||
echo "... peer $i is on height $hi"
|
||||
|
||||
|
@ -31,7 +31,7 @@ function start_procs(){
|
||||
if [[ "$CIRCLECI" == true ]]; then
|
||||
$TM_CMD &
|
||||
else
|
||||
$TM_CMD &> "tendermint_${name}.log" &
|
||||
$TM_CMD &> "tendermint_${name}.log" &
|
||||
fi
|
||||
PID_TENDERMINT=$!
|
||||
else
|
||||
@ -60,8 +60,8 @@ function wait_for_port() {
|
||||
i=0
|
||||
while [ "$ERR" == 0 ]; do
|
||||
echo "... port $port is still bound. waiting ..."
|
||||
sleep 1
|
||||
nc -z 127.0.0.1 $port
|
||||
sleep 1
|
||||
nc -z 127.0.0.1 $port
|
||||
ERR=$?
|
||||
i=$((i + 1))
|
||||
if [[ $i == 10 ]]; then
|
||||
@ -97,7 +97,7 @@ for failIndex in $(seq $failsStart $failsEnd); do
|
||||
ERR=$?
|
||||
i=0
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 1
|
||||
sleep 1
|
||||
curl -s --unix-socket "$RPC_ADDR" http://localhost/status > /dev/null
|
||||
ERR=$?
|
||||
i=$((i + 1))
|
||||
@ -108,11 +108,11 @@ for failIndex in $(seq $failsStart $failsEnd); do
|
||||
done
|
||||
|
||||
# wait for a new block
|
||||
h1=$(curl -s --unix-socket "$RPC_ADDR" http://localhost/status | jq .result.latest_block_height)
|
||||
h1=$(curl -s --unix-socket "$RPC_ADDR" http://localhost/status | jq .result.sync_info.latest_block_height)
|
||||
h2=$h1
|
||||
while [ "$h2" == "$h1" ]; do
|
||||
sleep 1
|
||||
h2=$(curl -s --unix-socket "$RPC_ADDR" http://localhost/status | jq .result.latest_block_height)
|
||||
h2=$(curl -s --unix-socket "$RPC_ADDR" http://localhost/status | jq .result.sync_info.latest_block_height)
|
||||
done
|
||||
|
||||
kill_procs
|
||||
|
@ -46,7 +46,7 @@ curl -s $addr/status > /dev/null
|
||||
ERR=$?
|
||||
i=0
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 1
|
||||
sleep 1
|
||||
curl -s $addr/status > /dev/null
|
||||
ERR=$?
|
||||
i=$(($i + 1))
|
||||
@ -57,11 +57,11 @@ while [ "$ERR" != 0 ]; do
|
||||
done
|
||||
|
||||
# wait for a new block
|
||||
h1=`curl -s $addr/status | jq .result.latest_block_height`
|
||||
h1=`curl -s $addr/status | jq .result.sync_info.latest_block_height`
|
||||
h2=$h1
|
||||
while [ "$h2" == "$h1" ]; do
|
||||
sleep 1
|
||||
h2=`curl -s $addr/status | jq .result.latest_block_height`
|
||||
h2=`curl -s $addr/status | jq .result.sync_info.latest_block_height`
|
||||
done
|
||||
|
||||
kill_procs
|
||||
|
@ -3,7 +3,7 @@ package types
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user