Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go-kosu: implement validator removal and subcommand #190

Merged
merged 5 commits into from Jul 30, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -141,8 +141,6 @@ func (app *App) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
v = app.store.Validator(nodeID)
}

v.Power = vote.Validator.Power

if vote.SignedLastBlock {
v.Active = true
v.TotalVotes++
@@ -208,8 +206,12 @@ func (app *App) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock {
updates = append(updates, update)
}

v.Applied = true
app.store.SetValidator(nodeID, v)
if v.Power == 0 {
app.store.DeleteValidator(nodeID)
} else {
v.Applied = true
app.store.SetValidator(nodeID, v)
}
})

return abci.ResponseEndBlock{
@@ -1,6 +1,8 @@
package cli

import (
"context"
"encoding/base64"
"fmt"
"go-kosu/abci"
"go-kosu/abci/types"
@@ -56,7 +58,7 @@ func (cli *CLI) RebalanceTx() *cobra.Command {
}

if res.DeliverTx.IsErr() {
printAndExit("deliver tx: %s\n", res.DeliverTx.Log)
printAndExit("deliver tx: %s\n", res.DeliverTx.Info)
}

fmt.Printf("ok: < %s>\n", tx.RoundInfo)
@@ -65,6 +67,70 @@ func (cli *CLI) RebalanceTx() *cobra.Command {
}
}

// UpdateValidators updates the validator set by sending a Validator's WitnessTx
func (cli *CLI) UpdateValidators() *cobra.Command {
return &cobra.Command{
Use: "update-validator <block> <pubkey> <address> <power>",
Short: "update validators by sending a WitnessTx",
Long: "pubkey needs to be encoded in base64. To remove a validator use power = 0",
Args: cobra.ExactArgs(4),
RunE: func(cmd *cobra.Command, args []string) error {
block, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}

pubKey, err := base64.StdEncoding.DecodeString(args[1])
if err != nil {
return err
}

addr, amount := args[2], args[3]

tx := &types.TransactionWitness{
Subject: types.TransactionWitness_VALIDATOR,
Block: block,
PublicKey: pubKey,
Address: addr,
Amount: types.NewBigIntFromString(amount, 10),
}

res, err := cli.client.BroadcastTxCommit(tx)
if err != nil {
printAndExit("%v\n", err)
}

if res.CheckTx.IsErr() {
printAndExit("check tx: %s\n", res.CheckTx.Log)
}

if res.DeliverTx.IsErr() {
printAndExit("deliver tx: %s\n", res.DeliverTx.Info)
}

ch, closer, err := cli.client.Subscribe(context.Background(), "tm.event = 'NewBlock'")
if err != nil {
printAndExit("subscribe: %v", err)
}
defer closer()

// wait for the next block
<-ch

set, err := cli.client.Validators(nil)
if err != nil {
printAndExit("validators: %v", err)
}

fmt.Println("New validator set")
for _, v := range set.Validators {
fmt.Printf("<%s power:%d>\n", v.PubKey.Address().String(), v.VotingPower)
}
return nil
},
}
}

// QueryRoundInfo queries the round info
func (cli *CLI) QueryRoundInfo() *cobra.Command {
return &cobra.Command{
@@ -96,7 +96,6 @@ func (c *Client) Subscribe(ctx context.Context, q string) (<-chan rpctypes.Resul
if err := httpC.Start(); err != nil {
return nil, nil, err
}

}
}

@@ -25,6 +25,11 @@ func (b *BigInt) MarshalText() ([]byte, error) {
return []byte(str), nil
}

// Zero returns true if the value is 0
func (b *BigInt) Zero() bool {
return b.BigInt().Cmp(big.NewInt(0)) == 0
}

var (
// ErrNoPubKeyExpected is returned when no public key was expected but it was defined
ErrNoPubKeyExpected = errors.New("expected no publicKey for poster witnesses")
@@ -9,10 +9,11 @@ import (
"go-kosu/store"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
)

func (app *App) checkWitnessTx(tx *types.TransactionWitness) error {
if app.store.LastEvent() >= tx.Block {
if app.store.LastEvent() > tx.Block {
return errors.New("transaction is older than the recorded state")
}

@@ -47,8 +48,6 @@ func (app *App) pushTransactionWitness(tx *types.TransactionWitness, nodeID []by
})
}

// TODO(gchaincl): delete witness

wTx := app.store.WitnessTx(tx.Id)

v := app.store.Validator(nodeID)
@@ -58,38 +57,31 @@ func (app *App) pushTransactionWitness(tx *types.TransactionWitness, nodeID []by
return err
}

power := scaleBalance(tx.Amount.BigInt())
app.log.Info("adding confirmations", "+power", power, "current", wTx.Confirmations)
wTx.Confirmations += uint64(power)
app.log.Info("adding confirmations", "+power", v.Power, "current", wTx.Confirmations)
wTx.Confirmations += uint64(v.Power)
app.store.SetWitnessTx(wTx)

app.log.Error("info", "threshold", app.confirmationThreshold, "conf", wTx.Confirmations)
app.log.Info("info", "threshold", app.confirmationThreshold, "conf", wTx.Confirmations)
if app.confirmationThreshold > wTx.Confirmations {
return nil
}

if tx.Amount.BigInt().Uint64() == 0 {
switch tx.Subject {
case types.TransactionWitness_POSTER:
app.store.DeletePoster(tx.Address)
case types.TransactionWitness_VALIDATOR:
app.store.DeleteValidator(nodeID)
}
return nil
}
// app.store.DeleteWitnessTx(tx.Id)

switch tx.Subject {
case types.TransactionWitness_POSTER:
app.store.SetPoster(tx.Address, types.Poster{
Balance: tx.Amount,
})
if tx.Amount.Zero() {
app.store.DeletePoster(tx.Address)
} else {
app.store.SetPoster(tx.Address, types.Poster{Balance: tx.Amount})
}
case types.TransactionWitness_VALIDATOR:
app.store.SetValidator(nodeID, &types.Validator{
id := tmhash.SumTruncated(tx.PublicKey)
app.store.SetValidator(id, &types.Validator{
Balance: tx.Amount,
Power: scaleBalance(tx.Amount.BigInt()),
PublicKey: tx.PublicKey,
EthAccount: tx.Address,
Active: false,
Power: power,
Applied: false,
})
}
return nil
@@ -57,6 +57,7 @@ func main() {
}
tx.AddCommand(
abci.RebalanceTx(),
abci.UpdateValidators(),
)

query := &cobra.Command{
@@ -164,6 +164,12 @@ func (s *Store) SetWitnessTx(tx store.TransactionWitness) {
s.Set("confs:"+string(tx.Id), s.witnessKey, tx.Confirmations)
}

// DeleteWitnessTx deletes a WitnessTx
func (s *Store) DeleteWitnessTx(id []byte) {
s.Delete("proto:"+string(id), s.witnessKey)
s.Delete("confs:"+string(id), s.witnessKey)
}

// Poster gets a Poster
func (s *Store) Poster(addr string) *types.Poster {
var v types.Poster
@@ -26,6 +26,7 @@ type Store interface {
WitnessTxExists([]byte) bool
WitnessTx([]byte) TransactionWitness
SetWitnessTx(TransactionWitness)
DeleteWitnessTx([]byte)

Poster(string) *types.Poster
SetPoster(string, types.Poster)
@@ -99,6 +99,7 @@ func TestValidator(t *testing.T, s store.Store) {
addr := []byte{0, 1, 2, 3, 4}
v := &types.Validator{
PublicKey: []byte{0, 1, 2, 3, 4},
Power: 10,
}
s.SetValidator(addr, v)

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.