address comments

This commit is contained in:
mossid 2018-11-06 18:11:10 +01:00
parent 1a339fdd6e
commit 2420536bfa
5 changed files with 67 additions and 28 deletions

View File

@ -10,7 +10,6 @@ import (
"github.com/tendermint/tendermint/abci/types"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
tmtypes "github.com/tendermint/tendermint/types"
)
var (
@ -69,23 +68,6 @@ func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.Respon
return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size)}
}
// handle evidence
func (app *KVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
for _, evidence := range req.ByzantineValidators {
switch evidence.Type {
case tmtypes.ABCIEvidenceTypeDuplicateVote:
key := prefixKey(evidence.Validator.Address)
// Do nothing, just store it in the state to check from outside
app.state.db.Set(key, []byte{})
app.state.Size += 1
}
}
return types.ResponseBeginBlock{
Tags: []cmn.KVPair{{Key: []byte("height"), Value: []byte(fmt.Sprintf("%d", req.Header.Height))}},
}
}
// tx is either "key=value" or just arbitrary bytes
func (app *KVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
var key, value []byte

View File

@ -9,8 +9,10 @@ import (
"github.com/tendermint/tendermint/abci/example/code"
"github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
)
const (
@ -27,6 +29,8 @@ type PersistentKVStoreApplication struct {
// validator set
ValUpdates []types.ValidatorUpdate
relation map[string]types.PubKey // address to pubkey
logger log.Logger
}
@ -40,8 +44,9 @@ func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication
state := loadState(db)
return &PersistentKVStoreApplication{
app: &KVStoreApplication{state: state},
logger: log.NewNopLogger(),
app: &KVStoreApplication{state: state},
relation: make(map[string]types.PubKey),
logger: log.NewNopLogger(),
}
}
@ -83,8 +88,18 @@ func (app *PersistentKVStoreApplication) Commit() types.ResponseCommit {
return app.app.Commit()
}
func (app *PersistentKVStoreApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery {
return app.app.Query(reqQuery)
func (app *PersistentKVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
switch reqQuery.Path {
case "/val":
key := []byte("val:" + string(reqQuery.Data))
value := app.app.state.db.Get(key)
resQuery.Key = reqQuery.Data
resQuery.Value = value
return
default:
return app.app.Query(reqQuery)
}
}
// Save the validators in the merkle tree
@ -102,6 +117,17 @@ func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) t
func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
// reset valset changes
app.ValUpdates = make([]types.ValidatorUpdate, 0)
for _, ev := range req.ByzantineValidators {
switch ev.Type {
case tmtypes.ABCIEvidenceTypeDuplicateVote:
// decrease voting power by 1
app.updateValidator(types.ValidatorUpdate{
PubKey: app.relation[string(ev.Validator.Address)],
Power: ev.TotalVotingPower - 1,
})
}
}
return types.ResponseBeginBlock{}
}
@ -173,6 +199,10 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon
// add, update, or remove a validator
func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx {
key := []byte("val:" + string(v.PubKey.Data))
pubkey := ed25519.PubKeyEd25519{}
copy(pubkey[:], v.PubKey.Data)
if v.Power == 0 {
// remove validator
if !app.app.state.db.Has(key) {
@ -181,6 +211,9 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate
Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)}
}
app.app.state.db.Delete(key)
delete(app.relation, string(pubkey.Address()))
} else {
// add or update validator
value := bytes.NewBuffer(make([]byte, 0))
@ -190,6 +223,8 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate
Log: fmt.Sprintf("Error encoding validator: %v", err)}
}
app.app.state.db.Set(key, value.Bytes())
app.relation[string(pubkey.Address())] = v.PubKey
}
// we only update the changes array if we successfully updated the tree

View File

@ -1,6 +1,8 @@
package client_test
import (
"fmt"
"io/ioutil"
"os"
"testing"
@ -13,7 +15,12 @@ var node *nm.Node
func TestMain(m *testing.M) {
// start a tendermint node (and kvstore) in the background to test against
app := kvstore.NewKVStoreApplication()
dir, err := ioutil.TempDir("/tmp", "abci-rpc-client-test")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
app := kvstore.NewPersistentKVStoreApplication(dir)
node = rpctest.StartTendermint(app)
code := m.Run()

View File

@ -1,6 +1,7 @@
package client_test
import (
"bytes"
"fmt"
"math/rand"
"strings"
@ -11,6 +12,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/rpc/client"
rpctest "github.com/tendermint/tendermint/rpc/test"
@ -427,7 +429,7 @@ func makeEvidences(t *testing.T, val *privval.FilePV, chainID string) (ev types.
ev = newEvidence(t, val, vote, vote2, chainID)
fakes = make([]types.DuplicateVoteEvidence, 41)
fakes = make([]types.DuplicateVoteEvidence, 42)
// different address
vote2 = deepcpVote(vote)
@ -457,6 +459,9 @@ func makeEvidences(t *testing.T, val *privval.FilePV, chainID string) (ev types.
vote2 = deepcpVote(vote)
vote2.Type = types.VoteTypePrecommit
fakes[40] = newEvidence(t, val, vote, vote2, chainID)
// exactly same vote
vote2 = deepcpVote(vote)
fakes[41] = newEvidence(t, val, vote, vote2, chainID)
return
}
@ -479,12 +484,19 @@ func TestBroadcastDuplicateVote(t *testing.T) {
require.Equal(t, ev.Hash(), result.Hash, "Invalid response, evidence %v, result %+v", ev.String(), result)
result2, err := c.ABCIQuery("/key", ev.PubKey.Address())
ed25519pub := ev.PubKey.(ed25519.PubKeyEd25519)
rawpub := ed25519pub[:]
result2, err := c.ABCIQuery("/val", rawpub)
require.Nil(t, err, "Error querying evidence, evidence %v", ev.String())
qres := result2.Response
require.True(t, qres.IsOK(), "Response not OK, evidence %v", ev.String())
require.EqualValues(t, []byte{}, qres.Value, "Value not equal with expected, evidence %v, value %v", ev.String(), string(qres.Value))
var v abci.ValidatorUpdate
err = abci.ReadMessage(bytes.NewReader(qres.Value), &v)
require.NoError(t, err, "Error reading query result, value %v", qres.Value)
require.EqualValues(t, rawpub, v.PubKey.Data, "Stored PubKey not equal with expected, evidence %v, value %v", ev.String(), string(qres.Value))
require.Equal(t, int64(9), v.Power, "Stored Power not equal with expected, evidence %v, value %v", ev.String(), string(qres.Value))
for _, fake := range fakes {
_, err := c.BroadcastDuplicateVote(fake.PubKey, *fake.VoteA, *fake.VoteB)

View File

@ -19,12 +19,15 @@ func BroadcastDuplicateVote(pubkey crypto.PubKey, vote1 types.Vote, vote2 types.
chainID := p2pTransport.NodeInfo().Network
ev := &types.DuplicateVoteEvidence{pubkey, &vote1, &vote2}
if err := vote1.Verify(chainID, pubkey); err != nil {
return nil, fmt.Errorf("Error broadcasting evidence: %v", err)
return nil, fmt.Errorf("Error broadcasting evidence, invalid vote1: %v", err)
}
if err := vote2.Verify(chainID, pubkey); err != nil {
return nil, fmt.Errorf("Error broadcasting evidence, invalid vote2: %v", err)
}
err := evidencePool.AddEvidence(ev)
if err != nil {
return nil, fmt.Errorf("Error broadcasting evidence: %v", err)
return nil, fmt.Errorf("Error broadcasting evidence, adding evidence: %v", err)
}
return &ctypes.ResultBroadcastDuplicateVote{ev.Hash()}, nil
}