mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-17 00:51: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"
|
"github.com/tendermint/tendermint/abci/types"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
dbm "github.com/tendermint/tendermint/libs/db"
|
dbm "github.com/tendermint/tendermint/libs/db"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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)}
|
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
|
// tx is either "key=value" or just arbitrary bytes
|
||||||
func (app *KVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
|
func (app *KVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
|
||||||
var key, value []byte
|
var key, value []byte
|
||||||
|
@ -9,8 +9,10 @@ import (
|
|||||||
|
|
||||||
"github.com/tendermint/tendermint/abci/example/code"
|
"github.com/tendermint/tendermint/abci/example/code"
|
||||||
"github.com/tendermint/tendermint/abci/types"
|
"github.com/tendermint/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
dbm "github.com/tendermint/tendermint/libs/db"
|
dbm "github.com/tendermint/tendermint/libs/db"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,6 +29,8 @@ type PersistentKVStoreApplication struct {
|
|||||||
// validator set
|
// validator set
|
||||||
ValUpdates []types.ValidatorUpdate
|
ValUpdates []types.ValidatorUpdate
|
||||||
|
|
||||||
|
relation map[string]types.PubKey // address to pubkey
|
||||||
|
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +45,7 @@ func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication
|
|||||||
|
|
||||||
return &PersistentKVStoreApplication{
|
return &PersistentKVStoreApplication{
|
||||||
app: &KVStoreApplication{state: state},
|
app: &KVStoreApplication{state: state},
|
||||||
|
relation: make(map[string]types.PubKey),
|
||||||
logger: log.NewNopLogger(),
|
logger: log.NewNopLogger(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,9 +88,19 @@ func (app *PersistentKVStoreApplication) Commit() types.ResponseCommit {
|
|||||||
return app.app.Commit()
|
return app.app.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *PersistentKVStoreApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery {
|
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)
|
return app.app.Query(reqQuery)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Save the validators in the merkle tree
|
// Save the validators in the merkle tree
|
||||||
func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain {
|
func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain {
|
||||||
@ -102,6 +117,17 @@ func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) t
|
|||||||
func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
|
func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
|
||||||
// reset valset changes
|
// reset valset changes
|
||||||
app.ValUpdates = make([]types.ValidatorUpdate, 0)
|
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{}
|
return types.ResponseBeginBlock{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +199,10 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon
|
|||||||
// add, update, or remove a validator
|
// add, update, or remove a validator
|
||||||
func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx {
|
func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx {
|
||||||
key := []byte("val:" + string(v.PubKey.Data))
|
key := []byte("val:" + string(v.PubKey.Data))
|
||||||
|
|
||||||
|
pubkey := ed25519.PubKeyEd25519{}
|
||||||
|
copy(pubkey[:], v.PubKey.Data)
|
||||||
|
|
||||||
if v.Power == 0 {
|
if v.Power == 0 {
|
||||||
// remove validator
|
// remove validator
|
||||||
if !app.app.state.db.Has(key) {
|
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)}
|
Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)}
|
||||||
}
|
}
|
||||||
app.app.state.db.Delete(key)
|
app.app.state.db.Delete(key)
|
||||||
|
|
||||||
|
delete(app.relation, string(pubkey.Address()))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// add or update validator
|
// add or update validator
|
||||||
value := bytes.NewBuffer(make([]byte, 0))
|
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)}
|
Log: fmt.Sprintf("Error encoding validator: %v", err)}
|
||||||
}
|
}
|
||||||
app.app.state.db.Set(key, value.Bytes())
|
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
|
// we only update the changes array if we successfully updated the tree
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package client_test
|
package client_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -13,7 +15,12 @@ var node *nm.Node
|
|||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
// start a tendermint node (and kvstore) in the background to test against
|
// 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)
|
node = rpctest.StartTendermint(app)
|
||||||
code := m.Run()
|
code := m.Run()
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package client_test
|
package client_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
"github.com/tendermint/tendermint/privval"
|
"github.com/tendermint/tendermint/privval"
|
||||||
"github.com/tendermint/tendermint/rpc/client"
|
"github.com/tendermint/tendermint/rpc/client"
|
||||||
rpctest "github.com/tendermint/tendermint/rpc/test"
|
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)
|
ev = newEvidence(t, val, vote, vote2, chainID)
|
||||||
|
|
||||||
fakes = make([]types.DuplicateVoteEvidence, 41)
|
fakes = make([]types.DuplicateVoteEvidence, 42)
|
||||||
|
|
||||||
// different address
|
// different address
|
||||||
vote2 = deepcpVote(vote)
|
vote2 = deepcpVote(vote)
|
||||||
@ -457,6 +459,9 @@ func makeEvidences(t *testing.T, val *privval.FilePV, chainID string) (ev types.
|
|||||||
vote2 = deepcpVote(vote)
|
vote2 = deepcpVote(vote)
|
||||||
vote2.Type = types.VoteTypePrecommit
|
vote2.Type = types.VoteTypePrecommit
|
||||||
fakes[40] = newEvidence(t, val, vote, vote2, chainID)
|
fakes[40] = newEvidence(t, val, vote, vote2, chainID)
|
||||||
|
// exactly same vote
|
||||||
|
vote2 = deepcpVote(vote)
|
||||||
|
fakes[41] = newEvidence(t, val, vote, vote2, chainID)
|
||||||
return
|
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)
|
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())
|
require.Nil(t, err, "Error querying evidence, evidence %v", ev.String())
|
||||||
qres := result2.Response
|
qres := result2.Response
|
||||||
require.True(t, qres.IsOK(), "Response not OK, evidence %v", ev.String())
|
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 {
|
for _, fake := range fakes {
|
||||||
_, err := c.BroadcastDuplicateVote(fake.PubKey, *fake.VoteA, *fake.VoteB)
|
_, 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
|
chainID := p2pTransport.NodeInfo().Network
|
||||||
ev := &types.DuplicateVoteEvidence{pubkey, &vote1, &vote2}
|
ev := &types.DuplicateVoteEvidence{pubkey, &vote1, &vote2}
|
||||||
if err := vote1.Verify(chainID, pubkey); err != nil {
|
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)
|
err := evidencePool.AddEvidence(ev)
|
||||||
if err != nil {
|
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
|
return &ctypes.ResultBroadcastDuplicateVote{ev.Hash()}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user