mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-16 16:41:20 +00:00
address comments
This commit is contained in:
parent
1a339fdd6e
commit
2420536bfa
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user