From 448b58fe347bbbaf3b9bae84dda1cb882686a749 Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Sun, 29 Jul 2018 00:50:21 +0100 Subject: [PATCH 1/9] adding voting msg to DeliveryTx and CheckTx, refactoring InitChain and BlockEnd to support validators --- jsonstore/jsonstore.go | 106 ++++++++++++++++++++++++++++++++++++++++- mint.go | 4 +- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index 3ce7baa..9dc9d29 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -21,7 +21,7 @@ import ( "gopkg.in/mgo.v2/bson" ) -var _ types.Application = (*JSONStoreApplication)(nil) +// var _ types.Application = (*JSONStoreApplication)(nil) var db *mgo.Database // Post ... @@ -74,6 +74,14 @@ type UserCommentVote struct { CommentID bson.ObjectId `bson:"commentID" json:"commentID"` } +// Validator +type Validator struct { + ID bson.ObjectId `bson:"_id" json:"_id"` + Name string `bson:"name" json:"name"` + PublicKey []byte `bson:"publicKey" json:"publicKey"` + Votes []bson.ObjectId `bson:"votes" json:"votes"` +} + // JSONStoreApplication ... type JSONStoreApplication struct { types.BaseApplication @@ -88,7 +96,7 @@ func byteToHex(input []byte) string { } func findTotalDocuments(db *mgo.Database) int64 { - collections := [5]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes"} + collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes", "validators"} var sum int64 for _, collection := range collections { @@ -235,6 +243,37 @@ func (app *JSONStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { } break + + case "upvoteValidator": + entity := body["entity"].(map[string]interface{}) + + // validate user exists + pubKeyBytes, errDecode := base64.StdEncoding.DecodeString(message["publicKey"].(string)) + + if errDecode != nil { + panic(errDecode) + } + + publicKey := strings.ToUpper(byteToHex(pubKeyBytes)) + + var user User + err := db.C("users").Find(bson.M{"publicKey": publicKey}).One(&user) + if err != nil { + panic(err) + } + + // userID := user.ID + + fmt.Println("user validated!") + // validate validator exists & update votes + + validatorID := bson.ObjectIdHex(entity["validator"].(string)) + err = db.C("validators").Update(bson.M{"_id": validatorID}, bson.M{"$addToSet": bson.M{"votes": user.ID}}) + if err != nil { + panic(err) + } + fmt.Println("validator validated!") + case "upvotePost": entity := body["entity"].(map[string]interface{}) @@ -446,6 +485,24 @@ func (app *JSONStoreApplication) CheckTx(tx []byte) types.ResponseCheckTx { // ===== Data Validation ======= switch body["type"] { + // TODO consider doing more sophisticated validations here like + // checking existance of users and validators here + // assuming tx cannot be tempered with beteen CheckTx and DeliverTx + case "upvoteValidator": + fmt.Println("received upvote start") + entity := body["entity"].(map[string]interface{}) + + if (entity["validator"] == nil) || (bson.IsObjectIdHex(entity["validator"].(string)) != true) { + codeType = code.CodeTypeBadData + break + } + fmt.Println("received upvote here") + if (entity["user"] == nil) || (bson.IsObjectIdHex(entity["user"].(string)) != true) { + codeType = code.CodeTypeBadData + break + } + fmt.Println("received upvote end") + case "createPost": entity := body["entity"].(map[string]interface{}) @@ -524,3 +581,48 @@ func (app *JSONStoreApplication) Commit() types.ResponseCommit { func (app *JSONStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { return } + +func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain { + fmt.Println("calling InitChain") + validators := req.GetValidators() + var mintValidators []interface{} + if validators != nil { + for _, element := range validators { + // pubKey, err := crypto.PubKeyFromBytes(element.GetPubKey()) + // if err != nil { + // panic(err) + // } + // fmt.Println(pubKey.Address()) + // fmt.Println(pubKey.Bytes()) + validator := Validator{ + ID: bson.NewObjectId(), + Name: "validatorName", + PublicKey: element.GetPubKey(), + Votes: []bson.ObjectId{}, + } + mintValidators = append(mintValidators, validator) + } + dbErr := db.C("validators").Insert(mintValidators...) + if dbErr != nil { + panic(dbErr) + } + } + return types.ResponseInitChain{} +} + +func (app *JSONStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { + var validators []Validator + err := db.C("validators").Find(nil).All(&validators) + if err != nil { + fmt.Println(err) + } + + var tdValidators []types.Validator + for _, validator := range validators { + // TODO power should be saved to mongo too + tdValidator := types.Validator{PubKey: validator.PublicKey, Power: 10} + tdValidators = append(tdValidators, tdValidator) + } + fmt.Println(tdValidators) + return types.ResponseEndBlock{ValidatorUpdates: tdValidators} +} diff --git a/mint.go b/mint.go index 115fdf8..bb14f65 100644 --- a/mint.go +++ b/mint.go @@ -29,7 +29,8 @@ func initJSONStore() error { db := session.DB("tendermintdb") // Clean the DB on each reboot - collections := [5]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes"} + // collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes", "validators"} + collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes"} for _, collection := range collections { db.C(collection).RemoveAll(nil) @@ -38,6 +39,7 @@ func initJSONStore() error { app = jsonstore.NewJSONStoreApplication(db) // Start the listener + srv, err := server.NewServer("tcp://0.0.0.0:46658", "socket", app) if err != nil { return err From 5a97571d184602b817c18bbc2d7fcf4dee86c065 Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Sun, 29 Jul 2018 16:45:15 +0100 Subject: [PATCH 2/9] refactoring EndBlock to only query top 4 validators --- jsonstore/jsonstore.go | 51 ++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index 9dc9d29..f27a8db 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -21,6 +21,10 @@ import ( "gopkg.in/mgo.v2/bson" ) +const ( + numActiveValidators = 4 +) + // var _ types.Application = (*JSONStoreApplication)(nil) var db *mgo.Database @@ -588,12 +592,6 @@ func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.Res var mintValidators []interface{} if validators != nil { for _, element := range validators { - // pubKey, err := crypto.PubKeyFromBytes(element.GetPubKey()) - // if err != nil { - // panic(err) - // } - // fmt.Println(pubKey.Address()) - // fmt.Println(pubKey.Bytes()) validator := Validator{ ID: bson.NewObjectId(), Name: "validatorName", @@ -611,18 +609,43 @@ func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.Res } func (app *JSONStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - var validators []Validator - err := db.C("validators").Find(nil).All(&validators) - if err != nil { - fmt.Println(err) + // TODO I've noticed that the order of elements with the same vote value is not nondeterministic + // which means last active can be swapped with first standby potentially on every query + // that could be considered an issue depending on requirements + project := bson.M{ + "$project": bson.M{ + "name": 1, + "publicKey": 1, + "votes": bson.M{"$size": "$votes"}, + }, + } + sort := bson.M{ + "$sort": bson.M{ + "votes": -1, + }, + } + limit := bson.M{ + "$limit": numActiveValidators, } + iter := db.C("validators").Pipe([]bson.M{project, sort, limit}).Iter() + defer iter.Close() + var tdValidators []types.Validator - for _, validator := range validators { - // TODO power should be saved to mongo too - tdValidator := types.Validator{PubKey: validator.PublicKey, Power: 10} - tdValidators = append(tdValidators, tdValidator) + + var dbResult bson.M + for iter.Next(&dbResult) { + // fmt.Println(dbResult) + validator := types.Validator{ + PubKey: dbResult["publicKey"].([]byte), + Power: 10, + } + tdValidators = append(tdValidators, validator) + } + if iter.Err() != nil { + panic(iter.Err()) } fmt.Println(tdValidators) + return types.ResponseEndBlock{ValidatorUpdates: tdValidators} } From e7af1a47e1355f6b9022a81b49847e6a28dc8b4b Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Mon, 30 Jul 2018 00:41:12 +0100 Subject: [PATCH 3/9] decreasing amount of active validators, adding appliation args --- jsonstore/jsonstore.go | 2 +- mint.go | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index f27a8db..088a849 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -22,7 +22,7 @@ import ( ) const ( - numActiveValidators = 4 + numActiveValidators = 3 ) // var _ types.Application = (*JSONStoreApplication)(nil) diff --git a/mint.go b/mint.go index bb14f65..8f65274 100644 --- a/mint.go +++ b/mint.go @@ -1,8 +1,10 @@ package main import ( + "fmt" "mint/jsonstore" "os" + "strconv" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" @@ -22,15 +24,16 @@ func initJSONStore() error { // Create the application var app types.Application - session, err := mgo.Dial("localhost") + fmt.Println("running aginst mongo: ", os.Getenv("MONGO_URL")) + session, err := mgo.Dial(os.Getenv("MONGO_URL")) if err != nil { panic(err) } db := session.DB("tendermintdb") // Clean the DB on each reboot - // collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes", "validators"} - collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes"} + collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes", "validators"} + // collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes"} for _, collection := range collections { db.C(collection).RemoveAll(nil) @@ -39,8 +42,16 @@ func initJSONStore() error { app = jsonstore.NewJSONStoreApplication(db) // Start the listener - - srv, err := server.NewServer("tcp://0.0.0.0:46658", "socket", app) + port := 46658 + if os.Args[1] != "" { + port, err = strconv.Atoi(os.Args[1]) + if err != nil { + panic(err) + } + } + fmt.Println(os.Args[1:]) + fmt.Println(port) + srv, err := server.NewServer(fmt.Sprintf("tcp://0.0.0.0:%d", port), "socket", app) if err != nil { return err } From b0cecf916f67527033de5f74a414f46f2192523d Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Mon, 30 Jul 2018 01:02:26 +0100 Subject: [PATCH 4/9] cleanups, adding comments --- jsonstore/jsonstore.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index 088a849..35aee45 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -25,7 +25,7 @@ const ( numActiveValidators = 3 ) -// var _ types.Application = (*JSONStoreApplication)(nil) +var _ types.Application = (*JSONStoreApplication)(nil) var db *mgo.Database // Post ... @@ -266,11 +266,9 @@ func (app *JSONStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { panic(err) } - // userID := user.ID - fmt.Println("user validated!") - // validate validator exists & update votes + // validate validator exists & update votes validatorID := bson.ObjectIdHex(entity["validator"].(string)) err = db.C("validators").Update(bson.M{"_id": validatorID}, bson.M{"$addToSet": bson.M{"votes": user.ID}}) if err != nil { @@ -609,6 +607,12 @@ func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.Res } func (app *JSONStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { + // TODO below solution needs confirmation through testing on multiple nodes. + // according to documentation "To add a new validator or update an existing one, + // simply include them in the list returned in the EndBlock response. + // To remove one, include it in the list with a power equal to 0." + // That means below solution may not be removing any validators atm! + // TODO I've noticed that the order of elements with the same vote value is not nondeterministic // which means last active can be swapped with first standby potentially on every query // that could be considered an issue depending on requirements From a9c9d4083c6b190957b4955e60d2a3aee9357c1f Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Wed, 1 Aug 2018 21:07:26 +0100 Subject: [PATCH 5/9] fixing number of active validators to 4 --- jsonstore/jsonstore.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index 35aee45..9066365 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -22,7 +22,8 @@ import ( ) const ( - numActiveValidators = 3 + // TODO should come from config file + numActiveValidators = 4 ) var _ types.Application = (*JSONStoreApplication)(nil) From e3af21a0a8f486be0c72207483da7f69e2c3dae3 Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Wed, 1 Aug 2018 23:26:59 +0100 Subject: [PATCH 6/9] adding userValidatorVote collection, adding support for downvote --- jsonstore/jsonstore.go | 91 +++++++++++++++++++++++++----------------- mint.go | 3 +- 2 files changed, 55 insertions(+), 39 deletions(-) diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index 9066365..629d851 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -81,10 +81,19 @@ type UserCommentVote struct { // Validator type Validator struct { - ID bson.ObjectId `bson:"_id" json:"_id"` - Name string `bson:"name" json:"name"` - PublicKey []byte `bson:"publicKey" json:"publicKey"` - Votes []bson.ObjectId `bson:"votes" json:"votes"` + ID bson.ObjectId `bson:"_id" json:"_id"` + Name string `bson:"name" json:"name"` + PublicKey []byte `bson:"publicKey" json:"publicKey"` + Upvotes int `bson:"upvotes" json:"upvotes"` +} + +// ValidatorsVotes +// TODO there should be an index ensured on ValidatorID, UserID and +// probs multikey index on ValidatorID and UserID +type UserValidatorVote struct { + ID bson.ObjectId `bson:"_id" json:"_id"` + ValidatorID bson.ObjectId `bson:"validatorID" json:"validatorID"` + UserID bson.ObjectId `bson:"userID" json:"userID"` } // JSONStoreApplication ... @@ -215,6 +224,7 @@ func (app *JSONStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { panic(dbErr) } + // TODO is that really needed? it's being created on upvotePost too. var document UserPostVote document.ID = bson.NewObjectId() document.UserID = user.ID @@ -266,15 +276,41 @@ func (app *JSONStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { if err != nil { panic(err) } - fmt.Println("user validated!") - // validate validator exists & update votes + userID := user.ID validatorID := bson.ObjectIdHex(entity["validator"].(string)) - err = db.C("validators").Update(bson.M{"_id": validatorID}, bson.M{"$addToSet": bson.M{"votes": user.ID}}) + + // validate validator exists + _, err = db.C("validators").Find(bson.M{"_id": validatorID}).Limit(1).Count() if err != nil { panic(err) } + + userValidatorVote := UserValidatorVote{} + var upvote int8 + err = db.C("uservalidatorvotes").Find(bson.M{"userID": userID, "validatorID": validatorID}).One(&userValidatorVote) + if err == nil { + errRemoval := db.C("uservalidatorvotes").Remove(bson.M{"userID": userID, "validatorID": validatorID}) + if errRemoval == nil { + upvote = -1 + } + } else { + var newUserValidatorVote UserValidatorVote + newUserValidatorVote.ID = bson.NewObjectId() + newUserValidatorVote.UserID = userID + newUserValidatorVote.ValidatorID = validatorID + + insertErr := db.C("uservalidatorvotes").Insert(newUserValidatorVote) + if insertErr == nil { + upvote = 1 + } + } + err = db.C("validators").Update(bson.M{"_id": validatorID}, bson.M{"$inc": bson.M{"upvotes": upvote}}) + if err != nil { + // TODO should be properly logged + fmt.Sprintf("Failed to update votes for validator %s by user %s", validatorID, userID) + } fmt.Println("validator validated!") case "upvotePost": @@ -587,6 +623,7 @@ func (app *JSONStoreApplication) Query(reqQuery types.RequestQuery) (resQuery ty func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain { fmt.Println("calling InitChain") + // TODO only used for testing atm!!! validators := req.GetValidators() var mintValidators []interface{} if validators != nil { @@ -595,7 +632,7 @@ func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.Res ID: bson.NewObjectId(), Name: "validatorName", PublicKey: element.GetPubKey(), - Votes: []bson.ObjectId{}, + Upvotes: 0, } mintValidators = append(mintValidators, validator) } @@ -614,41 +651,21 @@ func (app *JSONStoreApplication) EndBlock(req types.RequestEndBlock) types.Respo // To remove one, include it in the list with a power equal to 0." // That means below solution may not be removing any validators atm! - // TODO I've noticed that the order of elements with the same vote value is not nondeterministic - // which means last active can be swapped with first standby potentially on every query - // that could be considered an issue depending on requirements - project := bson.M{ - "$project": bson.M{ - "name": 1, - "publicKey": 1, - "votes": bson.M{"$size": "$votes"}, - }, - } - sort := bson.M{ - "$sort": bson.M{ - "votes": -1, - }, - } - limit := bson.M{ - "$limit": numActiveValidators, - } + var validators []Validator - iter := db.C("validators").Pipe([]bson.M{project, sort, limit}).Iter() - defer iter.Close() + err := db.C("validators").Find(nil).Sort("-upvotes").Limit(numActiveValidators).All(&validators) + if err != nil { + panic(err) + } var tdValidators []types.Validator - var dbResult bson.M - for iter.Next(&dbResult) { - // fmt.Println(dbResult) - validator := types.Validator{ - PubKey: dbResult["publicKey"].([]byte), + for _, validator := range validators { + tdValidator := types.Validator{ + PubKey: validator.PublicKey, Power: 10, } - tdValidators = append(tdValidators, validator) - } - if iter.Err() != nil { - panic(iter.Err()) + tdValidators = append(tdValidators, tdValidator) } fmt.Println(tdValidators) diff --git a/mint.go b/mint.go index 8f65274..242103a 100644 --- a/mint.go +++ b/mint.go @@ -32,8 +32,7 @@ func initJSONStore() error { db := session.DB("tendermintdb") // Clean the DB on each reboot - collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes", "validators"} - // collections := [6]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes"} + collections := [7]string{"posts", "comments", "users", "userpostvotes", "usercommentvotes", "validators", "uservalidatorvotes"} for _, collection := range collections { db.C(collection).RemoveAll(nil) From c8f3a264907c954dea6f0af2ed904d8f4a617606 Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Wed, 1 Aug 2018 23:34:43 +0100 Subject: [PATCH 7/9] reverting code added for testing --- mint.go | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/mint.go b/mint.go index 242103a..ca0aa02 100644 --- a/mint.go +++ b/mint.go @@ -1,10 +1,8 @@ package main import ( - "fmt" "mint/jsonstore" "os" - "strconv" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" @@ -24,8 +22,7 @@ func initJSONStore() error { // Create the application var app types.Application - fmt.Println("running aginst mongo: ", os.Getenv("MONGO_URL")) - session, err := mgo.Dial(os.Getenv("MONGO_URL")) + session, err := mgo.Dial("localhost") if err != nil { panic(err) } @@ -41,16 +38,7 @@ func initJSONStore() error { app = jsonstore.NewJSONStoreApplication(db) // Start the listener - port := 46658 - if os.Args[1] != "" { - port, err = strconv.Atoi(os.Args[1]) - if err != nil { - panic(err) - } - } - fmt.Println(os.Args[1:]) - fmt.Println(port) - srv, err := server.NewServer(fmt.Sprintf("tcp://0.0.0.0:%d", port), "socket", app) + srv, err := server.NewServer("tcp://0.0.0.0:46658", "socket", app) if err != nil { return err } From 15158e6383378c66bad1f332b2146c03be243a6d Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Fri, 3 Aug 2018 04:16:47 +0100 Subject: [PATCH 8/9] adding script to trigger multiple nodes locally --- mint.go | 14 ++++++- testing/README.md | 25 ++++++++++++ testing/launch_testnet_nodes.sh | 69 +++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 testing/README.md create mode 100755 testing/launch_testnet_nodes.sh diff --git a/mint.go b/mint.go index ca0aa02..d96dffd 100644 --- a/mint.go +++ b/mint.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "mint/jsonstore" "os" @@ -12,6 +13,10 @@ import ( "github.com/tendermint/tmlibs/log" ) +const ( + defaultMongoHost = "localhost" +) + func main() { initJSONStore() } @@ -22,7 +27,11 @@ func initJSONStore() error { // Create the application var app types.Application - session, err := mgo.Dial("localhost") + mongoHost := os.Args[2] + if mongoHost == "" { + mongoHost = defaultMongoHost + } + session, err := mgo.Dial(mongoHost) if err != nil { panic(err) } @@ -38,7 +47,8 @@ func initJSONStore() error { app = jsonstore.NewJSONStoreApplication(db) // Start the listener - srv, err := server.NewServer("tcp://0.0.0.0:46658", "socket", app) + proxyAppPort := os.Args[1] + srv, err := server.NewServer(fmt.Sprintf("tcp://0.0.0.0:%s", proxyAppPort), "socket", app) if err != nil { return err } diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 0000000..5babdce --- /dev/null +++ b/testing/README.md @@ -0,0 +1,25 @@ + +Run: + +docker run -d -p 27016:27017 -v ~/temp/mongo1:/data/db mongo +docker run -d -p 27015:27017 -v ~/temp/mongo2:/data/db mongo +docker run -d -p 27014:27017 -v ~/temp/mongo3:/data/db mongo +docker run -d -p 27013:27017 -v ~/temp/mongo4:/data/db mongo + +Run: +- tendermint testnet --starting-ip-address 192.168.0.1 +- get node_ids for each node: + example: tendermint --home mytestnet/node3/ show_node_id +- update SEEDS variable in launch_testnet_nodes.sh with appropriate node_ids +- run ./launch_testnet_nodes.sh + +Reset: +1. either wipe mytestnet folder and redo above steps +2. or do the following: +- go to each node config folder (example /mytestnet/node0) +- remove data folder, addressbook.json +- update priv_validator.json by replaing removing all fields starting with "last_*" and +adding below instead: +"last_height": 0, +"last_round": 0, +"last_step": 0, diff --git a/testing/launch_testnet_nodes.sh b/testing/launch_testnet_nodes.sh new file mode 100755 index 0000000..5076049 --- /dev/null +++ b/testing/launch_testnet_nodes.sh @@ -0,0 +1,69 @@ +# Launch multiple bash terminal tab windows by running the command `bash launch.sh` + +#!/bin/bash +# File: ~/launch.sh + +# Original Code Reference: http://dan.doezema.com/2013/04/programmatically-create-title-tabs-within-the-mac-os-x-terminal-app/ +# New-BSD License by Original Author Daniel Doezema http://dan.doezema.com/licenses/new-bsd/ + +# Modified by Luke Schoen in 2017 to include loading new tabs such as client and server and automatically open webpage in browser. +# Modified by Luke Schoen in 2018 to include launching multiple tabs for Tendermint Testnet Nodes + +function new_tab() { + TAB_NAME=$1 + DELAY=$2 + COMMAND=$3 + osascript \ + -e "tell application \"Terminal\"" \ + -e "tell application \"System Events\" to keystroke \"t\" using {command down}" \ + -e "do script \"$DELAY; printf '\\\e]1;$TAB_NAME\\\a'; $COMMAND\" in front window" \ + -e "end tell" > /dev/null +} + +IP=0.0.0.0 +AA=tcp://$IP +# SEEDS="" +SEEDS="72f768fd9e76271c43d05ce7fb32c367ac645f68@$IP:46656,5afaaa9876b8dc0628e244cb59163472ea8e0123@$IP:46666,1e467deae3d559bfc747dc9acd14a40dc00ef933@$IP:46676,47cf808a11961ac3797958042d81874d3ede9892@$IP:46686" +TESTNET_ROOT_DIR="~/go-workspace/src/mint/testing/" +TESTNET_FOLDER="mytestnet" +NODE_0_NAME="node0" +NODE_1_NAME="node1" +NODE_2_NAME="node2" +NODE_3_NAME="node3" +echo "Removing Previous Tendermint Testnet Files: $TESTNET_ROOT_DIR/$TESTNET_FOLDER" +rm -rf "$TESTNET_ROOT_DIR/$TESTNET_FOLDER" +echo "Tendermint Testnet Location: $TESTNET_ROOT_DIR/$TESTNET_FOLDER" +echo "Loading Nodes: $NODE_0_NAME, $NODE_1_NAME, $NODE_2_NAME, $NODE_3_NAME" +echo "Loading Seeds: $SEEDS" + +new_tab "node_0" \ + "echo 'Loading node_0...'" \ + "bash -c 'echo node_0; tendermint node --home "$TESTNET_ROOT_DIR/$TESTNET_FOLDER/$NODE_0_NAME" --rpc.laddr="$AA:46657" --p2p.laddr="$AA:46656" --p2p.seeds=$SEEDS --proxy_app="tcp://127.0.0.1:46658" --p2p.persistent_peers=""; exec $SHELL'" + +new_tab "mint_0" \ + "echo 'Loading mint_0...'" \ + "bash -c 'echo mint_0; cd ~/go-workspace/src/mint; ./mint 46658 'localhost:27013'; exec $SHELL'" + +new_tab "node_1" \ + "echo 'Loading node_1...'" \ + "bash -c 'echo node_1; tendermint node --home "$TESTNET_ROOT_DIR/$TESTNET_FOLDER/$NODE_1_NAME" --rpc.laddr="$AA:46667" --p2p.laddr="$AA:46666" --p2p.seeds=$SEEDS --proxy_app="tcp://127.0.0.1:46668" --p2p.persistent_peers=""; exec $SHELL'" + +new_tab "mint_1" \ + "echo 'Loading mint_1...'" \ + "bash -c 'echo mint_1; cd ~/go-workspace/src/mint; ./mint 46668 'localhost:27014'; exec $SHELL'" + +new_tab "node_2" \ + "echo 'Loading node_2...'" \ + "bash -c 'echo node_2; tendermint node --home "$TESTNET_ROOT_DIR/$TESTNET_FOLDER/$NODE_2_NAME" --rpc.laddr="$AA:46677" --p2p.laddr="$AA:46676" --p2p.seeds=$SEEDS --proxy_app="tcp://127.0.0.1:46678" --p2p.persistent_peers=""; exec $SHELL'" + +new_tab "mint_2" \ + "echo 'Loading mint_2...'" \ + "bash -c 'echo mint_2; cd ~/go-workspace/src/mint; ./mint 46678 'localhost:27015'; exec $SHELL'" + +new_tab "node_3" \ + "echo 'Loading node_3...'" \ + "bash -c 'echo node_3; tendermint node --home "$TESTNET_ROOT_DIR/$TESTNET_FOLDER/$NODE_3_NAME" --rpc.laddr="$AA:46687" --p2p.laddr="$AA:46686" --p2p.seeds=$SEEDS --proxy_app="tcp://127.0.0.1:46688" --p2p.persistent_peers=""; exec $SHELL'" + +new_tab "mint_3" \ + "echo 'Loading mint_3...'" \ + "bash -c 'echo mint_3; cd ~/go-workspace/src/mint; ./mint 46688 'localhost:27016'; exec $SHELL'" From 6d2e71a9b739a7cb98cd65b90f60ea091d4c4ff9 Mon Sep 17 00:00:00 2001 From: Bartosz Zabuski Date: Wed, 8 Aug 2018 00:46:04 +0100 Subject: [PATCH 9/9] upgrading tendermint to have proper access to Validators attributes like Address, PubKey etc., adding code for testing --- Gopkg.lock | 51 +++++++++++++++++++++--------------------- Gopkg.toml | 10 +++------ jsonstore/jsonstore.go | 39 +++++++++++++++++++------------- mint.go | 22 +++++++++++++----- 4 files changed, 68 insertions(+), 54 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 1085b42..6eaa3b2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -33,8 +33,8 @@ "sortkeys", "types" ] - revision = "1adfc126b41513cc696b209667c8656ea7aac67c" - version = "v1.0.0" + revision = "636bf0302bc95575d69441b25a2603156ffdddf1" + version = "v1.1.1" [[projects]] name = "github.com/golang/protobuf" @@ -61,23 +61,15 @@ version = "v0.8.0" [[projects]] - name = "github.com/tendermint/abci" + name = "github.com/tendermint/tendermint" packages = [ - "example/code", - "server", - "types" - ] - revision = "78a8905690ef54f9d57e3b2b0ee7ad3a04ef3f1f" - version = "v0.10.3" - -[[projects]] - name = "github.com/tendermint/tmlibs" - packages = [ - "common", - "log" + "abci/server", + "abci/types", + "libs/common", + "libs/log" ] - revision = "d970af87248a4e162590300dbb74e102183a417d" - version = "v0.8.3" + revision = "013b9cef642f875634c614019ab13b17570778ad" + version = "v0.23.0" [[projects]] branch = "master" @@ -86,10 +78,9 @@ "ed25519", "ed25519/internal/edwards25519" ] - revision = "1a580b3eff7814fc9b40602fd35256c63b50f491" + revision = "f027049dab0ad238e394a753dba2d14753473a04" [[projects]] - branch = "master" name = "golang.org/x/net" packages = [ "context", @@ -100,7 +91,7 @@ "internal/timeseries", "trace" ] - revision = "8e0cdda24ed423affc8f35c241e5e9b16180338e" + revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f" [[projects]] name = "golang.org/x/text" @@ -127,31 +118,39 @@ branch = "master" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - revision = "11a468237815f3a3ddf9f7c6e8b6b3b382a24d15" + revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" [[projects]] name = "google.golang.org/grpc" packages = [ ".", "balancer", + "balancer/base", + "balancer/roundrobin", "codes", "connectivity", "credentials", - "grpclb/grpc_lb_v1/messages", + "encoding", + "encoding/proto", "grpclog", "internal", + "internal/backoff", + "internal/channelz", + "internal/grpcrand", "keepalive", "metadata", "naming", "peer", "resolver", + "resolver/dns", + "resolver/passthrough", "stats", "status", "tap", "transport" ] - revision = "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" - version = "v1.7.5" + revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" + version = "v1.13.0" [[projects]] branch = "v2" @@ -163,11 +162,11 @@ "internal/sasl", "internal/scram" ] - revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655" + revision = "9856a29383ce1c59f308dd1cf0363a79b5bef6b5" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "894cdc23200fd590b6580355e5ca4cd4ad2b29924bb73d8be704f7c509fe3a41" + inputs-digest = "6fb21f6f6b7b6ac14487967921d9e94da72b2a89b4fcdc4765b9f09b13cf53fb" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 4b7a5da..b1ce610 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,6 +1,6 @@ # Gopkg.toml example # -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md # for detailed Gopkg.toml documentation. # # required = ["github.com/user/thing/cmd/thing"] @@ -26,12 +26,8 @@ [[constraint]] - name = "github.com/tendermint/abci" - version = "0.10.3" - -[[constraint]] - name = "github.com/tendermint/tmlibs" - version = "0.8.3" + name = "github.com/tendermint/tendermint" + version = "0.23.0" [[constraint]] branch = "master" diff --git a/jsonstore/jsonstore.go b/jsonstore/jsonstore.go index 629d851..99b377c 100644 --- a/jsonstore/jsonstore.go +++ b/jsonstore/jsonstore.go @@ -15,7 +15,7 @@ import ( "mint/code" - "github.com/tendermint/abci/types" + "github.com/tendermint/tendermint/abci/types" "golang.org/x/crypto/ed25519" mgo "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -81,10 +81,18 @@ type UserCommentVote struct { // Validator type Validator struct { - ID bson.ObjectId `bson:"_id" json:"_id"` - Name string `bson:"name" json:"name"` - PublicKey []byte `bson:"publicKey" json:"publicKey"` - Upvotes int `bson:"upvotes" json:"upvotes"` + ID []byte `bson:"_id" json:"_id"` + Name string `bson:"name" json:"name"` + PubKey types.PubKey `bson:"pubKey" json:"pubKey"` + Upvotes int `bson:"upvotes" json:"upvotes"` + Power int64 `bson:"power" json:"power"` +} + +func (v Validator) ToTDValidator() types.Validator { + return types.Validator{ + PubKey: v.PubKey, + Power: v.Power, + } } // ValidatorsVotes @@ -624,15 +632,20 @@ func (app *JSONStoreApplication) Query(reqQuery types.RequestQuery) (resQuery ty func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain { fmt.Println("calling InitChain") // TODO only used for testing atm!!! - validators := req.GetValidators() + addValidators(req.GetValidators()) + return types.ResponseInitChain{} +} + +func addValidators(validators []types.Validator) { var mintValidators []interface{} if validators != nil { for _, element := range validators { validator := Validator{ - ID: bson.NewObjectId(), - Name: "validatorName", - PublicKey: element.GetPubKey(), - Upvotes: 0, + ID: element.GetAddress(), + Name: "mintValidator", + PubKey: element.GetPubKey(), + Power: element.GetPower(), + Upvotes: 0, } mintValidators = append(mintValidators, validator) } @@ -641,7 +654,6 @@ func (app *JSONStoreApplication) InitChain(req types.RequestInitChain) types.Res panic(dbErr) } } - return types.ResponseInitChain{} } func (app *JSONStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { @@ -661,10 +673,7 @@ func (app *JSONStoreApplication) EndBlock(req types.RequestEndBlock) types.Respo var tdValidators []types.Validator for _, validator := range validators { - tdValidator := types.Validator{ - PubKey: validator.PublicKey, - Power: 10, - } + tdValidator := validator.ToTDValidator() tdValidators = append(tdValidators, tdValidator) } fmt.Println(tdValidators) diff --git a/mint.go b/mint.go index ca0aa02..20b7551 100644 --- a/mint.go +++ b/mint.go @@ -1,15 +1,20 @@ package main import ( + "fmt" "mint/jsonstore" "os" - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" + "github.com/tendermint/tendermint/abci/server" + "github.com/tendermint/tendermint/abci/types" mgo "gopkg.in/mgo.v2" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" + cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/libs/log" +) + +const ( + defaultMongoHost = "localhost" ) func main() { @@ -22,7 +27,11 @@ func initJSONStore() error { // Create the application var app types.Application - session, err := mgo.Dial("localhost") + mongoHost := os.Args[2] + if mongoHost == "" { + mongoHost = defaultMongoHost + } + session, err := mgo.Dial(mongoHost) if err != nil { panic(err) } @@ -38,7 +47,8 @@ func initJSONStore() error { app = jsonstore.NewJSONStoreApplication(db) // Start the listener - srv, err := server.NewServer("tcp://0.0.0.0:46658", "socket", app) + proxyAppPort := os.Args[1] + srv, err := server.NewServer(fmt.Sprintf("tcp://0.0.0.0:%s", proxyAppPort), "socket", app) if err != nil { return err }