mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-23 16:21:57 +00:00
Compare commits
9 Commits
v0.29.1
...
2565-max-a
Author | SHA1 | Date | |
---|---|---|---|
|
a2e7494b4b | ||
|
56f943e890 | ||
|
e9f30e1f22 | ||
|
7482113547 | ||
|
42b84972f5 | ||
|
5481c6b150 | ||
|
f7e0cd1360 | ||
|
166dc01ab5 | ||
|
7e7e4c74ca |
@@ -12,10 +12,17 @@ BREAKING CHANGES:
|
||||
* [rpc] \#2298 `/abci_query` takes `prove` argument instead of `trusted` and switches the default
|
||||
behaviour to `prove=false`
|
||||
* [privval] \#2459 Split `SocketPVMsg`s implementations into Request and Response, where the Response may contain a error message (returned by the remote signer)
|
||||
* [genesis] \#2565 `consensus_params.evidence_params.max_age` is now `time.Duration` (nanosecond count)
|
||||
```json
|
||||
"evidence_params": {
|
||||
"max_age": "48h0m0s"
|
||||
}
|
||||
```
|
||||
|
||||
* Apps
|
||||
* [abci] \#2298 ResponseQuery.Proof is now a structured merkle.Proof, not just
|
||||
arbitrary bytes
|
||||
* [abci] \#2565 InitChain `ConsensusParams.EvidenceParams.MaxAge` is now `google.protobuf.Duration` (see https://developers.google.com/protocol-buffers/docs/reference/csharp/class/google/protobuf/well-known-types/duration)
|
||||
|
||||
* Go API
|
||||
* [node] Remove node.RunForever
|
||||
|
1
Gopkg.lock
generated
1
Gopkg.lock
generated
@@ -517,6 +517,7 @@
|
||||
"github.com/gogo/protobuf/proto",
|
||||
"github.com/gogo/protobuf/types",
|
||||
"github.com/golang/protobuf/proto",
|
||||
"github.com/golang/protobuf/ptypes/duration",
|
||||
"github.com/golang/protobuf/ptypes/timestamp",
|
||||
"github.com/gorilla/websocket",
|
||||
"github.com/jmhodges/levigo",
|
||||
|
2
Makefile
2
Makefile
@@ -44,7 +44,7 @@ protoc_all: protoc_libs protoc_merkle protoc_abci protoc_grpc
|
||||
## See https://stackoverflow.com/a/25518702
|
||||
## Note the $< here is substituted for the %.proto
|
||||
## Note the $@ here is substituted for the %.pb.go
|
||||
protoc $(INCLUDE) $< --gogo_out=Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,plugins=grpc:.
|
||||
protoc $(INCLUDE) $< --gogo_out=Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,plugins=grpc:.
|
||||
|
||||
########################################
|
||||
### Build ABCI
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ package types;
|
||||
// https://github.com/gogo/protobuf/blob/master/extensions.md
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "github.com/tendermint/tendermint/libs/common/types.proto";
|
||||
import "github.com/tendermint/tendermint/crypto/merkle/merkle.proto";
|
||||
|
||||
@@ -217,8 +218,8 @@ message BlockSize {
|
||||
|
||||
// EvidenceParams contains limits on the evidence.
|
||||
message EvidenceParams {
|
||||
// Note: must be greater than 0
|
||||
int64 max_age = 1;
|
||||
// Note: must be greater than 0 if provided
|
||||
google.protobuf.Duration max_age = 1 [(gogoproto.nullable)=false, (gogoproto.stdduration)=true];
|
||||
}
|
||||
|
||||
message LastCommitInfo {
|
||||
|
@@ -13,6 +13,7 @@ import golang_proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "github.com/golang/protobuf/ptypes/duration"
|
||||
import _ "github.com/golang/protobuf/ptypes/timestamp"
|
||||
import _ "github.com/tendermint/tendermint/crypto/merkle"
|
||||
import _ "github.com/tendermint/tendermint/libs/common"
|
||||
|
@@ -8,8 +8,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cstypes "github.com/tendermint/tendermint/consensus/types"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
tmevents "github.com/tendermint/tendermint/libs/events"
|
||||
@@ -948,8 +947,8 @@ func (ps *PeerState) ToJSON() ([]byte, error) {
|
||||
return cdc.MarshalJSON(ps)
|
||||
}
|
||||
|
||||
// GetHeight returns an atomic snapshot of the PeerRoundState's height
|
||||
// used by the mempool to ensure peers are caught up before broadcasting new txs
|
||||
// GetHeight returns an atomic snapshot of the PeerRoundState's height used by
|
||||
// the mempool to ensure peers are caught up before broadcasting new txs.
|
||||
func (ps *PeerState) GetHeight() int64 {
|
||||
ps.mtx.Lock()
|
||||
defer ps.mtx.Unlock()
|
||||
|
@@ -443,11 +443,10 @@ Commit are included in the header of the next block.
|
||||
### EvidenceParams
|
||||
|
||||
- **Fields**:
|
||||
- `MaxAge (int64)`: Max age of evidence, in blocks. Evidence older than this
|
||||
is considered stale and ignored.
|
||||
- `MaxAge (google.protobuf.Duration)`: Max age of evidence. Evidence older
|
||||
than this is considered stale and ignored.
|
||||
- This should correspond with an app's "unbonding period" or other
|
||||
similar mechanism for handling Nothing-At-Stake attacks.
|
||||
- NOTE: this should change to time (instead of blocks)!
|
||||
|
||||
### Proof
|
||||
|
||||
|
@@ -101,7 +101,7 @@ type BlockGossip struct {
|
||||
}
|
||||
|
||||
type EvidenceParams struct {
|
||||
MaxAge int64
|
||||
MaxAge time.Duration
|
||||
}
|
||||
```
|
||||
|
||||
@@ -129,5 +129,5 @@ size of each part is `ConsensusParams.BlockGossip.BlockPartSizeBytes`.
|
||||
For evidence in a block to be valid, it must satisfy:
|
||||
|
||||
```
|
||||
block.Header.Height - evidence.Height < ConsensusParams.EvidenceParams.MaxAge
|
||||
block.Header.Time - evidence.Time < ConsensusParams.EvidenceParams.MaxAge
|
||||
```
|
||||
|
@@ -3,6 +3,7 @@ package evidence
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
clist "github.com/tendermint/tendermint/libs/clist"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
@@ -84,7 +85,7 @@ func (evpool *EvidencePool) Update(block *types.Block, state sm.State) {
|
||||
evpool.mtx.Unlock()
|
||||
|
||||
// remove evidence from pending and mark committed
|
||||
evpool.MarkEvidenceAsCommitted(block.Height, block.Evidence.Evidence)
|
||||
evpool.MarkEvidenceAsCommitted(block.Evidence.Evidence, block.Time)
|
||||
}
|
||||
|
||||
// AddEvidence checks the evidence is valid and adds it to the pool.
|
||||
@@ -117,8 +118,9 @@ func (evpool *EvidencePool) AddEvidence(evidence types.Evidence) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkEvidenceAsCommitted marks all the evidence as committed and removes it from the queue.
|
||||
func (evpool *EvidencePool) MarkEvidenceAsCommitted(height int64, evidence []types.Evidence) {
|
||||
// MarkEvidenceAsCommitted marks all the evidence as committed and removes it
|
||||
// from the queue.
|
||||
func (evpool *EvidencePool) MarkEvidenceAsCommitted(evidence []types.Evidence, lastBlockTime time.Time) {
|
||||
// make a map of committed evidence to remove from the clist
|
||||
blockEvidenceMap := make(map[string]struct{})
|
||||
for _, ev := range evidence {
|
||||
@@ -127,20 +129,22 @@ func (evpool *EvidencePool) MarkEvidenceAsCommitted(height int64, evidence []typ
|
||||
}
|
||||
|
||||
// remove committed evidence from the clist
|
||||
maxAge := evpool.State().ConsensusParams.EvidenceParams.MaxAge
|
||||
evpool.removeEvidence(height, maxAge, blockEvidenceMap)
|
||||
|
||||
maxAge := evpool.State().ConsensusParams.EvidenceParams.MaxAge.Duration
|
||||
evpool.removeEvidence(blockEvidenceMap, lastBlockTime, maxAge)
|
||||
}
|
||||
|
||||
func (evpool *EvidencePool) removeEvidence(height, maxAge int64, blockEvidenceMap map[string]struct{}) {
|
||||
func (evpool *EvidencePool) removeEvidence(
|
||||
blockEvidenceMap map[string]struct{},
|
||||
lastBlockTime time.Time,
|
||||
maxAge time.Duration,
|
||||
) {
|
||||
for e := evpool.evidenceList.Front(); e != nil; e = e.Next() {
|
||||
ev := e.Value.(types.Evidence)
|
||||
evAge := lastBlockTime.Sub(ev.Time())
|
||||
|
||||
// Remove the evidence if it's already in a block
|
||||
// or if it's now too old.
|
||||
if _, ok := blockEvidenceMap[evMapKey(ev)]; ok ||
|
||||
ev.Height() < height-maxAge {
|
||||
|
||||
if _, ok := blockEvidenceMap[evMapKey(ev)]; ok || evAge > maxAge {
|
||||
// remove from clist
|
||||
evpool.evidenceList.Remove(e)
|
||||
e.DetachPrev()
|
||||
|
@@ -39,7 +39,7 @@ func initializeValidatorState(valAddr []byte, height int64) dbm.DB {
|
||||
LastHeightValidatorsChanged: 1,
|
||||
ConsensusParams: types.ConsensusParams{
|
||||
EvidenceParams: types.EvidenceParams{
|
||||
MaxAge: 1000000,
|
||||
MaxAge: tmtime.DurationPretty{1000000},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@@ -91,7 +91,7 @@ func (evR *EvidenceReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetEventSwitch implements events.Eventable.
|
||||
// SetEventBus implements events.Eventable.
|
||||
func (evR *EvidenceReactor) SetEventBus(b *types.EventBus) {
|
||||
evR.eventBus = b
|
||||
}
|
||||
@@ -153,28 +153,17 @@ func (evR *EvidenceReactor) broadcastEvidenceRoutine(peer p2p.Peer) {
|
||||
// Returns the message to send the peer, or nil if the evidence is invalid for the peer.
|
||||
// If message is nil, return true if we should sleep and try again.
|
||||
func (evR EvidenceReactor) checkSendEvidenceMessage(peer p2p.Peer, ev types.Evidence) (msg EvidenceMessage, retry bool) {
|
||||
|
||||
// make sure the peer is up to date
|
||||
evHeight := ev.Height()
|
||||
peerState, ok := peer.Get(types.PeerStateKey).(PeerState)
|
||||
if !ok {
|
||||
evR.Logger.Info("Found peer without PeerState", "peer", peer)
|
||||
return nil, true
|
||||
}
|
||||
|
||||
// NOTE: We only send evidence to peers where
|
||||
// peerHeight - maxAge < evidenceHeight < peerHeight
|
||||
maxAge := evR.evpool.State().ConsensusParams.EvidenceParams.MaxAge
|
||||
// NOTE: We only send evidence to peers where evidenceHeight < peerHeight
|
||||
peerHeight := peerState.GetHeight()
|
||||
if peerHeight < evHeight {
|
||||
if peerHeight < ev.Height() {
|
||||
// peer is behind. sleep while he catches up
|
||||
return nil, true
|
||||
} else if peerHeight > evHeight+maxAge {
|
||||
// evidence is too old, skip
|
||||
// NOTE: if evidence is too old for an honest peer,
|
||||
// then we're behind and either it already got committed or it never will!
|
||||
evR.Logger.Info("Not sending peer old evidence", "peerHeight", peerHeight, "evHeight", evHeight, "maxAge", maxAge, "peer", peer)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// send evidence
|
||||
|
@@ -132,7 +132,7 @@ func TestReactorBroadcastEvidence(t *testing.T) {
|
||||
// set the peer height on each reactor
|
||||
for _, r := range reactors {
|
||||
for _, peer := range r.Switch.Peers().List() {
|
||||
ps := peerState{height}
|
||||
ps := testPeerState{height}
|
||||
peer.Set(types.PeerStateKey, ps)
|
||||
}
|
||||
}
|
||||
@@ -143,11 +143,13 @@ func TestReactorBroadcastEvidence(t *testing.T) {
|
||||
waitForEvidence(t, evList, reactors)
|
||||
}
|
||||
|
||||
type peerState struct {
|
||||
type testPeerState struct {
|
||||
height int64
|
||||
}
|
||||
|
||||
func (ps peerState) GetHeight() int64 {
|
||||
var _ PeerState = (*testPeerState)(nil)
|
||||
|
||||
func (ps testPeerState) GetHeight() int64 {
|
||||
return ps.height
|
||||
}
|
||||
|
||||
@@ -165,7 +167,7 @@ func TestReactorSelectiveBroadcast(t *testing.T) {
|
||||
// make reactors from statedb
|
||||
reactors := makeAndConnectEvidenceReactors(config, []dbm.DB{stateDB1, stateDB2})
|
||||
peer := reactors[0].Switch.Peers().List()[0]
|
||||
ps := peerState{height2}
|
||||
ps := testPeerState{height2}
|
||||
peer.Set(types.PeerStateKey, ps)
|
||||
|
||||
// send a bunch of valid evidence to the first reactor's evpool
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
@@ -386,14 +388,14 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func makeParams(blockBytes, blockGas, evidenceAge int64) types.ConsensusParams {
|
||||
func makeParams(blockBytes, blockGas int64, evidenceAge time.Duration) types.ConsensusParams {
|
||||
return types.ConsensusParams{
|
||||
BlockSize: types.BlockSize{
|
||||
MaxBytes: blockBytes,
|
||||
MaxGas: blockGas,
|
||||
},
|
||||
EvidenceParams: types.EvidenceParams{
|
||||
MaxAge: evidenceAge,
|
||||
MaxAge: tmtime.DurationPretty{evidenceAge},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -403,7 +405,7 @@ func pk() []byte {
|
||||
}
|
||||
|
||||
func TestApplyUpdates(t *testing.T) {
|
||||
initParams := makeParams(1, 2, 3)
|
||||
initParams := makeParams(1, 2, 3*time.Second)
|
||||
|
||||
cases := [...]struct {
|
||||
init types.ConsensusParams
|
||||
@@ -419,14 +421,14 @@ func TestApplyUpdates(t *testing.T) {
|
||||
MaxGas: 55,
|
||||
},
|
||||
},
|
||||
makeParams(44, 55, 3)},
|
||||
makeParams(44, 55, 3*time.Second)},
|
||||
3: {initParams,
|
||||
abci.ConsensusParams{
|
||||
EvidenceParams: &abci.EvidenceParams{
|
||||
MaxAge: 66,
|
||||
MaxAge: 66 * time.Second,
|
||||
},
|
||||
},
|
||||
makeParams(1, 2, 66)},
|
||||
makeParams(1, 2, 66*time.Second)},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
|
@@ -168,13 +168,11 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error {
|
||||
// - it is internally consistent
|
||||
// - it was properly signed by the alleged equivocator
|
||||
func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence) error {
|
||||
height := state.LastBlockHeight
|
||||
|
||||
evidenceAge := height - evidence.Height()
|
||||
maxAge := state.ConsensusParams.EvidenceParams.MaxAge
|
||||
evidenceAge := state.LastBlockTime.Sub(evidence.Time())
|
||||
maxAge := state.ConsensusParams.EvidenceParams.MaxAge.Duration
|
||||
if evidenceAge > maxAge {
|
||||
return fmt.Errorf("Evidence from height %d is too old. Min height is %d",
|
||||
evidence.Height(), height-maxAge)
|
||||
return fmt.Errorf("Evidence from %v is too old. Expecting evidence no older than %v",
|
||||
evidence.Time(), state.LastBlockTime.Add(-maxAge))
|
||||
}
|
||||
|
||||
valset, err := LoadValidators(stateDB, evidence.Height())
|
||||
|
@@ -3,8 +3,10 @@ package types
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
@@ -54,6 +56,7 @@ func (err *ErrEvidenceOverflow) Error() string {
|
||||
// Evidence represents any provable malicious activity by a validator
|
||||
type Evidence interface {
|
||||
Height() int64 // height of the equivocation
|
||||
Time() time.Time // when the evidence was created
|
||||
Address() []byte // address of the equivocating validator
|
||||
Bytes() []byte // bytes which compromise the evidence
|
||||
Hash() []byte // hash of the evidence
|
||||
@@ -102,6 +105,11 @@ func (dve *DuplicateVoteEvidence) Height() int64 {
|
||||
return dve.VoteA.Height
|
||||
}
|
||||
|
||||
// Time returns the time when the evidence was created.
|
||||
func (dve *DuplicateVoteEvidence) Time() time.Time {
|
||||
return dve.VoteA.Timestamp
|
||||
}
|
||||
|
||||
// Address returns the address of the validator.
|
||||
func (dve *DuplicateVoteEvidence) Address() []byte {
|
||||
return dve.PubKey.Address()
|
||||
@@ -188,6 +196,7 @@ func NewMockGoodEvidence(height int64, idx int, address []byte) MockGoodEvidence
|
||||
}
|
||||
|
||||
func (e MockGoodEvidence) Height() int64 { return e.Height_ }
|
||||
func (e MockGoodEvidence) Time() time.Time { return tmtime.Now() }
|
||||
func (e MockGoodEvidence) Address() []byte { return e.Address_ }
|
||||
func (e MockGoodEvidence) Hash() []byte {
|
||||
return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
|
||||
|
@@ -1,9 +1,12 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,7 +32,7 @@ type BlockSize struct {
|
||||
|
||||
// EvidenceParams determine how we handle evidence of malfeasance
|
||||
type EvidenceParams struct {
|
||||
MaxAge int64 `json:"max_age"` // only accept new evidence more recent than this
|
||||
MaxAge tmtime.DurationPretty `json:"max_age"` // only accept new evidence more recent than this
|
||||
}
|
||||
|
||||
// DefaultConsensusParams returns a default ConsensusParams.
|
||||
@@ -51,7 +54,7 @@ func DefaultBlockSize() BlockSize {
|
||||
// DefaultEvidenceParams Params returns a default EvidenceParams.
|
||||
func DefaultEvidenceParams() EvidenceParams {
|
||||
return EvidenceParams{
|
||||
MaxAge: 100000, // 27.8 hrs at 1block/s
|
||||
MaxAge: tmtime.DurationPretty{48 * time.Hour},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +75,9 @@ func (params *ConsensusParams) Validate() error {
|
||||
params.BlockSize.MaxGas)
|
||||
}
|
||||
|
||||
if params.EvidenceParams.MaxAge <= 0 {
|
||||
if params.EvidenceParams.MaxAge.Duration <= 0 {
|
||||
return cmn.NewError("EvidenceParams.MaxAge must be greater than 0. Got %d",
|
||||
params.EvidenceParams.MaxAge)
|
||||
params.EvidenceParams.MaxAge.Duration)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -109,7 +112,7 @@ func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusPar
|
||||
res.BlockSize.MaxGas = params2.BlockSize.MaxGas
|
||||
}
|
||||
if params2.EvidenceParams != nil {
|
||||
res.EvidenceParams.MaxAge = params2.EvidenceParams.MaxAge
|
||||
res.EvidenceParams.MaxAge = tmtime.DurationPretty{params2.EvidenceParams.MaxAge}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@@ -4,9 +4,11 @@ import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
|
||||
func TestConsensusParamsValidation(t *testing.T) {
|
||||
@@ -15,17 +17,17 @@ func TestConsensusParamsValidation(t *testing.T) {
|
||||
valid bool
|
||||
}{
|
||||
// test block size
|
||||
0: {makeParams(1, 0, 1), true},
|
||||
1: {makeParams(0, 0, 1), false},
|
||||
2: {makeParams(47*1024*1024, 0, 1), true},
|
||||
3: {makeParams(10, 0, 1), true},
|
||||
4: {makeParams(100*1024*1024, 0, 1), true},
|
||||
5: {makeParams(101*1024*1024, 0, 1), false},
|
||||
6: {makeParams(1024*1024*1024, 0, 1), false},
|
||||
7: {makeParams(1024*1024*1024, 0, -1), false},
|
||||
0: {makeParams(1, 0, 10*time.Second), true},
|
||||
1: {makeParams(0, 0, 10*time.Second), false},
|
||||
2: {makeParams(47*1024*1024, 0, 10*time.Second), true},
|
||||
3: {makeParams(10, 0, 10*time.Second), true},
|
||||
4: {makeParams(100*1024*1024, 0, 10*time.Second), true},
|
||||
5: {makeParams(101*1024*1024, 0, 10*time.Second), false},
|
||||
6: {makeParams(1024*1024*1024, 0, 10*time.Second), false},
|
||||
7: {makeParams(1024*1024*1024, 0, -10*time.Second), false},
|
||||
// test evidence age
|
||||
8: {makeParams(1, 0, 0), false},
|
||||
9: {makeParams(1, 0, -1), false},
|
||||
9: {makeParams(1, 0, -1*time.Millisecond), false},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if tc.valid {
|
||||
@@ -36,28 +38,23 @@ func TestConsensusParamsValidation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func makeParams(blockBytes, blockGas, evidenceAge int64) ConsensusParams {
|
||||
func makeParams(blockBytes, blockGas int64, evidenceAge time.Duration) ConsensusParams {
|
||||
return ConsensusParams{
|
||||
BlockSize: BlockSize{
|
||||
MaxBytes: blockBytes,
|
||||
MaxGas: blockGas,
|
||||
},
|
||||
EvidenceParams: EvidenceParams{
|
||||
MaxAge: evidenceAge,
|
||||
MaxAge: tmtime.DurationPretty{evidenceAge},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsensusParamsHash(t *testing.T) {
|
||||
params := []ConsensusParams{
|
||||
makeParams(4, 2, 3),
|
||||
makeParams(1, 4, 3),
|
||||
makeParams(1, 2, 4),
|
||||
makeParams(2, 5, 7),
|
||||
makeParams(1, 7, 6),
|
||||
makeParams(9, 5, 4),
|
||||
makeParams(7, 8, 9),
|
||||
makeParams(4, 6, 5),
|
||||
makeParams(4, 2, 3*time.Second),
|
||||
makeParams(1, 4, 3*time.Second),
|
||||
makeParams(1, 2, 4*time.Second),
|
||||
}
|
||||
|
||||
hashes := make([][]byte, len(params))
|
||||
@@ -83,23 +80,23 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
}{
|
||||
// empty updates
|
||||
{
|
||||
makeParams(1, 2, 3),
|
||||
makeParams(1, 2, 3*time.Second),
|
||||
&abci.ConsensusParams{},
|
||||
makeParams(1, 2, 3),
|
||||
makeParams(1, 2, 3*time.Second),
|
||||
},
|
||||
// fine updates
|
||||
{
|
||||
makeParams(1, 2, 3),
|
||||
makeParams(1, 2, 3*time.Second),
|
||||
&abci.ConsensusParams{
|
||||
BlockSize: &abci.BlockSize{
|
||||
MaxBytes: 100,
|
||||
MaxGas: 200,
|
||||
},
|
||||
EvidenceParams: &abci.EvidenceParams{
|
||||
MaxAge: 300,
|
||||
MaxAge: 300 * time.Second,
|
||||
},
|
||||
},
|
||||
makeParams(100, 200, 300),
|
||||
makeParams(100, 200, 300*time.Second),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
|
||||
//-------------------------------------------------------
|
||||
@@ -119,7 +120,7 @@ func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
|
||||
MaxGas: params.BlockSize.MaxGas,
|
||||
},
|
||||
EvidenceParams: &abci.EvidenceParams{
|
||||
MaxAge: params.EvidenceParams.MaxAge,
|
||||
MaxAge: params.EvidenceParams.MaxAge.Duration,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -209,13 +210,18 @@ func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error)
|
||||
}
|
||||
|
||||
func (pb2tm) ConsensusParams(csp *abci.ConsensusParams) ConsensusParams {
|
||||
return ConsensusParams{
|
||||
BlockSize: BlockSize{
|
||||
params := ConsensusParams{}
|
||||
|
||||
// we must defensively consider any structs may be nil
|
||||
if csp.BlockSize != nil {
|
||||
params.BlockSize = BlockSize{
|
||||
MaxBytes: csp.BlockSize.MaxBytes,
|
||||
MaxGas: csp.BlockSize.MaxGas,
|
||||
},
|
||||
EvidenceParams: EvidenceParams{
|
||||
MaxAge: csp.EvidenceParams.MaxAge,
|
||||
},
|
||||
}
|
||||
}
|
||||
if csp.EvidenceParams != nil {
|
||||
params.EvidenceParams.MaxAge = tmtime.DurationPretty{csp.EvidenceParams.MaxAge}
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
@@ -68,7 +68,7 @@ func TestABCIValidators(t *testing.T) {
|
||||
|
||||
func TestABCIConsensusParams(t *testing.T) {
|
||||
cp := DefaultConsensusParams()
|
||||
cp.EvidenceParams.MaxAge = 0 // TODO add this to ABCI
|
||||
cp.EvidenceParams.MaxAge.Duration = 0 // TODO add this to ABCI
|
||||
abciCP := TM2PB.ConsensusParams(cp)
|
||||
cp2 := PB2TM.ConsensusParams(abciCP)
|
||||
|
||||
|
41
types/time/duration.go
Normal file
41
types/time/duration.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DurationPretty is a wrapper around time.Duration implementing custom
|
||||
// marshaller/unmarshaller which make it pretty (e.g. "10s", not
|
||||
// "10000000000").
|
||||
type DurationPretty struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaller.
|
||||
func (d DurationPretty) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaller.
|
||||
func (d *DurationPretty) UnmarshalJSON(b []byte) error {
|
||||
var v interface{}
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
switch value := v.(type) {
|
||||
case float64:
|
||||
d.Duration = time.Duration(value)
|
||||
return nil
|
||||
case string:
|
||||
var err error
|
||||
d.Duration, err = time.ParseDuration(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return errors.New("invalid duration")
|
||||
}
|
||||
}
|
31
types/time/duration_test.go
Normal file
31
types/time/duration_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDurationPretty(t *testing.T) {
|
||||
testCases := []struct {
|
||||
jsonBytes []byte
|
||||
expErr bool
|
||||
expValue time.Duration
|
||||
}{
|
||||
{[]byte(`"10s"`), false, 10 * time.Second},
|
||||
{[]byte(`"48h0m0s"`), false, 48 * time.Hour},
|
||||
{[]byte(`"10kkk"`), true, 0},
|
||||
{[]byte(`"kkk"`), true, 0},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
var d DurationPretty
|
||||
if tc.expErr {
|
||||
assert.Error(t, d.UnmarshalJSON(tc.jsonBytes), "#%d", i)
|
||||
} else {
|
||||
assert.NoError(t, d.UnmarshalJSON(tc.jsonBytes), "#%d", i)
|
||||
assert.Equal(t, tc.expValue, d.Duration, "#%d", i)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user