mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-10 15:07:24 +00:00
@@ -15,6 +15,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
- P2P Protocol
|
||||
|
||||
- Go API
|
||||
- [evidence] [\#5499](https://github.com/tendermint/tendermint/pull/5449) `MaxNum` evidence consensus parameter has been changed to `MaxBytes` (@cmwaters)
|
||||
|
||||
- Blockchain Protocol
|
||||
|
||||
|
||||
@@ -515,7 +515,7 @@ var testGenesisFmt = `{
|
||||
"evidence": {
|
||||
"max_age_num_blocks": "100000",
|
||||
"max_age_duration": "172800000000000",
|
||||
"max_num": 50
|
||||
"max_bytes": "1048576"
|
||||
},
|
||||
"validator": {
|
||||
"pub_key_types": [
|
||||
|
||||
@@ -167,11 +167,11 @@ func TestReactorWithEvidence(t *testing.T) {
|
||||
// mock the evidence pool
|
||||
// everyone includes evidence of another double signing
|
||||
vIdx := (i + 1) % nValidators
|
||||
ev := types.NewMockDuplicateVoteEvidenceWithValidator(1, defaultTestTime, privVals[vIdx], config.ChainID())
|
||||
evpool := &statemocks.EvidencePool{}
|
||||
evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil)
|
||||
evpool.On("PendingEvidence", mock.AnythingOfType("uint32")).Return([]types.Evidence{
|
||||
types.NewMockDuplicateVoteEvidenceWithValidator(1, defaultTestTime, privVals[vIdx], config.ChainID()),
|
||||
})
|
||||
evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return([]types.Evidence{
|
||||
ev}, int64(len(ev.Bytes())))
|
||||
evpool.On("Update", mock.AnythingOfType("state.State")).Return()
|
||||
evpool.On("ABCIEvidence", mock.AnythingOfType("int64"), mock.AnythingOfType("[]types.Evidence")).Return(
|
||||
[]abci.Evidence{})
|
||||
|
||||
@@ -32,7 +32,7 @@ All evidence is proto encoded to disk.
|
||||
Proposing
|
||||
|
||||
When a new block is being proposed (in state/execution.go#CreateProposalBlock),
|
||||
`PendingEvidence(maxNum)` is called to send up to the maxNum number of uncommitted evidence, from the evidence store,
|
||||
`PendingEvidence(maxBytes)` is called to send up to the maxBytes of uncommitted evidence, from the evidence store,
|
||||
prioritized in order of age. All evidence is checked for expiration.
|
||||
|
||||
When a node receives evidence in a block it will use the evidence module as a cache first to see if it has
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Code generated by mockery v2.1.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
state "github.com/tendermint/tendermint/state"
|
||||
|
||||
types "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// StateStore is an autogenerated mock type for the StateStore type
|
||||
type StateStore struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// LoadState provides a mock function with given fields:
|
||||
func (_m *StateStore) LoadState() state.State {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 state.State
|
||||
if rf, ok := ret.Get(0).(func() state.State); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(state.State)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadValidators provides a mock function with given fields: height
|
||||
func (_m *StateStore) LoadValidators(height int64) (*types.ValidatorSet, error) {
|
||||
ret := _m.Called(height)
|
||||
|
||||
var r0 *types.ValidatorSet
|
||||
if rf, ok := ret.Get(0).(func(int64) *types.ValidatorSet); ok {
|
||||
r0 = rf(height)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.ValidatorSet)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(int64) error); ok {
|
||||
r1 = rf(height)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
@@ -64,19 +64,16 @@ func NewPool(evidenceDB dbm.DB, stateDB sm.Store, blockStore BlockStore) (*Pool,
|
||||
logger: log.NewNopLogger(),
|
||||
evidenceStore: evidenceDB,
|
||||
evidenceList: clist.New(),
|
||||
evidenceSize: 0,
|
||||
pruningHeight: state.LastBlockHeight,
|
||||
pruningTime: state.LastBlockTime,
|
||||
}
|
||||
|
||||
// if pending evidence already in db, in event of prior failure, then check for expiration,
|
||||
// update the size and load it back to the evidenceList
|
||||
pool.removeExpiredPendingEvidence()
|
||||
evList, err := pool.listEvidence(baseKeyPending, -1)
|
||||
pool.pruningHeight, pool.pruningTime = pool.removeExpiredPendingEvidence()
|
||||
evList, _, err := pool.listEvidence(baseKeyPending, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
atomic.AddUint32(&pool.evidenceSize, uint32(len(evList)))
|
||||
atomic.StoreUint32(&pool.evidenceSize, uint32(len(evList)))
|
||||
for _, ev := range evList {
|
||||
pool.evidenceList.PushBack(ev)
|
||||
}
|
||||
@@ -85,12 +82,15 @@ func NewPool(evidenceDB dbm.DB, stateDB sm.Store, blockStore BlockStore) (*Pool,
|
||||
}
|
||||
|
||||
// PendingEvidence is used primarily as part of block proposal and returns up to maxNum of uncommitted evidence.
|
||||
func (evpool *Pool) PendingEvidence(maxNum uint32) []types.Evidence {
|
||||
evidence, err := evpool.listEvidence(baseKeyPending, int64(maxNum))
|
||||
func (evpool *Pool) PendingEvidence(maxBytes int64) ([]types.Evidence, int64) {
|
||||
if atomic.LoadUint32(&evpool.evidenceSize) == 0 {
|
||||
return []types.Evidence{}, 0
|
||||
}
|
||||
evidence, size, err := evpool.listEvidence(baseKeyPending, maxBytes)
|
||||
if err != nil {
|
||||
evpool.logger.Error("Unable to retrieve pending evidence", "err", err)
|
||||
}
|
||||
return evidence
|
||||
return evidence, size
|
||||
}
|
||||
|
||||
// Update pulls the latest state to be used for expiration and evidence params and then prunes all expired evidence
|
||||
@@ -330,6 +330,7 @@ type info struct {
|
||||
Time time.Time
|
||||
Validators []*types.Validator
|
||||
TotalVotingPower int64
|
||||
ByteSize int64
|
||||
}
|
||||
|
||||
// ToProto encodes into protobuf
|
||||
@@ -381,6 +382,7 @@ func infoFromProto(proto *evproto.Info) (info, error) {
|
||||
Time: proto.Time,
|
||||
Validators: vals,
|
||||
TotalVotingPower: proto.TotalVotingPower,
|
||||
ByteSize: int64(proto.Evidence.Size()),
|
||||
}, nil
|
||||
|
||||
}
|
||||
@@ -489,31 +491,32 @@ func (evpool *Pool) removePendingEvidence(evidence types.Evidence) {
|
||||
}
|
||||
}
|
||||
|
||||
// listEvidence lists up to maxNum pieces of evidence for the given prefix key.
|
||||
// If maxNum is -1, there's no cap on the size of returned evidence.
|
||||
func (evpool *Pool) listEvidence(prefixKey byte, maxNum int64) ([]types.Evidence, error) {
|
||||
var count int64
|
||||
// listEvidence retrieves lists evidence from oldest to newest within maxBytes.
|
||||
// If maxBytes is -1, there's no cap on the size of returned evidence.
|
||||
func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Evidence, int64, error) {
|
||||
var totalSize int64
|
||||
var evidence []types.Evidence
|
||||
iter, err := dbm.IteratePrefix(evpool.evidenceStore, []byte{prefixKey})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("database error: %v", err)
|
||||
return nil, totalSize, fmt.Errorf("database error: %v", err)
|
||||
}
|
||||
defer iter.Close()
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
if count == maxNum {
|
||||
return evidence, nil
|
||||
}
|
||||
count++
|
||||
|
||||
evInfo, err := bytesToInfo(iter.Value())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, totalSize, err
|
||||
}
|
||||
|
||||
totalSize += evInfo.ByteSize
|
||||
|
||||
if maxBytes != -1 && totalSize > maxBytes {
|
||||
return evidence, totalSize - evInfo.ByteSize, nil
|
||||
}
|
||||
|
||||
evidence = append(evidence, evInfo.Evidence)
|
||||
}
|
||||
|
||||
return evidence, nil
|
||||
return evidence, totalSize, nil
|
||||
}
|
||||
|
||||
func (evpool *Pool) removeExpiredPendingEvidence() (int64, time.Time) {
|
||||
@@ -534,7 +537,8 @@ func (evpool *Pool) removeExpiredPendingEvidence() (int64, time.Time) {
|
||||
if len(blockEvidenceMap) != 0 {
|
||||
evpool.removeEvidenceFromList(blockEvidenceMap)
|
||||
}
|
||||
// return the time with which this evidence will have expired so we know when to prune next
|
||||
|
||||
// return the height and time with which this evidence will have expired so we know when to prune next
|
||||
return evInfo.Evidence.Height() + evpool.State().ConsensusParams.Evidence.MaxAgeNumBlocks + 1,
|
||||
evInfo.Time.Add(evpool.State().ConsensusParams.Evidence.MaxAgeDuration).Add(time.Second)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@ func TestMain(m *testing.M) {
|
||||
|
||||
const evidenceChainID = "test_chain"
|
||||
|
||||
var defaultEvidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
var (
|
||||
defaultEvidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
defaultEvidenceMaxBytes int64 = 1000
|
||||
)
|
||||
|
||||
func TestEvidencePoolBasic(t *testing.T) {
|
||||
var (
|
||||
@@ -52,10 +55,12 @@ func TestEvidencePoolBasic(t *testing.T) {
|
||||
|
||||
pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore)
|
||||
require.NoError(t, err)
|
||||
pool.SetLogger(log.TestingLogger())
|
||||
|
||||
// evidence not seen yet:
|
||||
evs := pool.PendingEvidence(10)
|
||||
evs, size := pool.PendingEvidence(defaultEvidenceMaxBytes)
|
||||
assert.Equal(t, 0, len(evs))
|
||||
assert.Zero(t, size)
|
||||
|
||||
ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, privVals[0], evidenceChainID)
|
||||
|
||||
@@ -78,12 +83,14 @@ func TestEvidencePoolBasic(t *testing.T) {
|
||||
next := pool.EvidenceFront()
|
||||
assert.Equal(t, ev, next.Value.(types.Evidence))
|
||||
|
||||
evs = pool.PendingEvidence(10)
|
||||
evs, size = pool.PendingEvidence(defaultEvidenceMaxBytes)
|
||||
assert.Equal(t, 1, len(evs))
|
||||
assert.Equal(t, int64(357), size) // check that the size of the single evidence in bytes is correct
|
||||
|
||||
// shouldn't be able to add evidence twice
|
||||
assert.Error(t, pool.AddEvidence(ev))
|
||||
assert.Equal(t, 1, len(pool.PendingEvidence(10)))
|
||||
evs, _ = pool.PendingEvidence(defaultEvidenceMaxBytes)
|
||||
assert.Equal(t, 1, len(evs))
|
||||
|
||||
}
|
||||
|
||||
@@ -183,12 +190,15 @@ func TestEvidencePoolUpdate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expectedByzVals, byzVals)
|
||||
assert.Equal(t, 1, len(pool.PendingEvidence(10)))
|
||||
evList, _ := pool.PendingEvidence(defaultEvidenceMaxBytes)
|
||||
assert.Equal(t, 1, len(evList))
|
||||
|
||||
pool.Update(state)
|
||||
|
||||
// a) Update marks evidence as committed so pending evidence should be empty
|
||||
assert.Empty(t, pool.PendingEvidence(10))
|
||||
evList, evSize := pool.PendingEvidence(defaultEvidenceMaxBytes)
|
||||
assert.Empty(t, evList)
|
||||
assert.Zero(t, evSize)
|
||||
|
||||
// b) If we try to check this evidence again it should fail because it has already been committed
|
||||
err = pool.CheckEvidence(types.EvidenceList{ev})
|
||||
@@ -293,7 +303,6 @@ func TestCheckEvidenceWithLightClientAttack(t *testing.T) {
|
||||
|
||||
func TestRecoverPendingEvidence(t *testing.T) {
|
||||
height := int64(10)
|
||||
expiredEvidenceTime := time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
val := types.NewMockPV()
|
||||
valAddress := val.PrivKey.PubKey().Address()
|
||||
evidenceDB := dbm.NewMemDB()
|
||||
@@ -301,21 +310,24 @@ func TestRecoverPendingEvidence(t *testing.T) {
|
||||
state, err := stateStore.Load()
|
||||
require.NoError(t, err)
|
||||
blockStore := initializeBlockStore(dbm.NewMemDB(), state, valAddress)
|
||||
// create previous pool and populate it
|
||||
pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore)
|
||||
require.NoError(t, err)
|
||||
pool.SetLogger(log.TestingLogger())
|
||||
goodEvidence := types.NewMockDuplicateVoteEvidenceWithValidator(height,
|
||||
defaultEvidenceTime, val, evidenceChainID)
|
||||
expiredEvidence := types.NewMockDuplicateVoteEvidenceWithValidator(int64(1),
|
||||
expiredEvidenceTime, val, evidenceChainID)
|
||||
defaultEvidenceTime, val, evidenceChainID)
|
||||
err = pool.AddEvidence(goodEvidence)
|
||||
require.NoError(t, err)
|
||||
err = pool.AddEvidence(expiredEvidence)
|
||||
require.NoError(t, err)
|
||||
|
||||
// now recover from the previous pool at a different time
|
||||
newStateStore := &smmocks.Store{}
|
||||
newStateStore.On("Load").Return(sm.State{
|
||||
LastBlockTime: defaultEvidenceTime.Add(49 * time.Hour),
|
||||
LastBlockHeight: height + 12,
|
||||
LastBlockTime: defaultEvidenceTime.Add(25 * time.Minute),
|
||||
LastBlockHeight: height + 15,
|
||||
ConsensusParams: tmproto.ConsensusParams{
|
||||
Block: tmproto.BlockParams{
|
||||
MaxBytes: 22020096,
|
||||
@@ -323,14 +335,15 @@ func TestRecoverPendingEvidence(t *testing.T) {
|
||||
},
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 20,
|
||||
MaxAgeDuration: 1 * time.Hour,
|
||||
MaxNum: 50,
|
||||
MaxAgeDuration: 20 * time.Minute,
|
||||
MaxBytes: 1000,
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
newPool, err := evidence.NewPool(evidenceDB, newStateStore, blockStore)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(newPool.PendingEvidence(10)))
|
||||
evList, _ := newPool.PendingEvidence(defaultEvidenceMaxBytes)
|
||||
assert.Equal(t, 1, len(evList))
|
||||
next := newPool.EvidenceFront()
|
||||
assert.Equal(t, goodEvidence, next.Value.(types.Evidence))
|
||||
|
||||
@@ -356,7 +369,7 @@ func initializeStateFromValidatorSet(valSet *types.ValidatorSet, height int64) s
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 20,
|
||||
MaxAgeDuration: 20 * time.Minute,
|
||||
MaxNum: 50,
|
||||
MaxBytes: 1000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -106,14 +106,17 @@ func _waitForEvidence(
|
||||
pools []*evidence.Pool,
|
||||
) {
|
||||
evpool := pools[poolIdx]
|
||||
for len(evpool.PendingEvidence(uint32(len(evs)))) != len(evs) {
|
||||
var evList []types.Evidence
|
||||
currentPoolSize := 0
|
||||
for currentPoolSize != len(evs) {
|
||||
evList, _ = evpool.PendingEvidence(int64(len(evs) * 500)) // each evidence should not be more than 500 bytes
|
||||
currentPoolSize = len(evList)
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
|
||||
reapedEv := evpool.PendingEvidence(uint32(len(evs)))
|
||||
// put the reaped evidence in a map so we can quickly check we got everything
|
||||
evMap := make(map[string]types.Evidence)
|
||||
for _, e := range reapedEv {
|
||||
for _, e := range evList {
|
||||
evMap[string(e.Hash())] = e
|
||||
}
|
||||
for i, expectedEv := range evs {
|
||||
|
||||
@@ -102,7 +102,7 @@ func TestVerifyLightClientAttack_Lunatic(t *testing.T) {
|
||||
err = pool.CheckEvidence(evList)
|
||||
assert.NoError(t, err)
|
||||
|
||||
pendingEvs := pool.PendingEvidence(2)
|
||||
pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
|
||||
assert.Equal(t, 1, len(pendingEvs))
|
||||
|
||||
pubKey, err := newPrivVal.GetPubKey()
|
||||
@@ -206,7 +206,7 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) {
|
||||
err = pool.CheckEvidence(evList)
|
||||
assert.NoError(t, err)
|
||||
|
||||
pendingEvs := pool.PendingEvidence(2)
|
||||
pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
|
||||
assert.Equal(t, 1, len(pendingEvs))
|
||||
|
||||
pubKey, err := conflictingPrivVals[0].GetPubKey()
|
||||
@@ -303,7 +303,7 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) {
|
||||
err = pool.CheckEvidence(evList)
|
||||
assert.NoError(t, err)
|
||||
|
||||
pendingEvs := pool.PendingEvidence(2)
|
||||
pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
|
||||
assert.Equal(t, 1, len(pendingEvs))
|
||||
|
||||
pubKey, err := conflictingPrivVals[0].GetPubKey()
|
||||
|
||||
@@ -234,9 +234,9 @@ func TestCreateProposalBlock(t *testing.T) {
|
||||
state, stateDB, privVals := state(1, height)
|
||||
stateStore := sm.NewStore(stateDB)
|
||||
maxBytes := 16384
|
||||
maxEvidence := 10
|
||||
maxEvidenceBytes := int64(maxBytes / 2)
|
||||
state.ConsensusParams.Block.MaxBytes = int64(maxBytes)
|
||||
state.ConsensusParams.Evidence.MaxNum = uint32(maxEvidence)
|
||||
state.ConsensusParams.Evidence.MaxBytes = maxEvidenceBytes
|
||||
proposerAddr, _ := state.Validators.GetByIndex(0)
|
||||
|
||||
// Make Mempool
|
||||
@@ -260,8 +260,10 @@ func TestCreateProposalBlock(t *testing.T) {
|
||||
|
||||
// fill the evidence pool with more evidence
|
||||
// than can fit in a block
|
||||
for i := 0; i <= maxEvidence; i++ {
|
||||
var currentBytes int64 = 0
|
||||
for currentBytes <= maxEvidenceBytes {
|
||||
ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[0], "test-chain")
|
||||
currentBytes += int64(len(ev.Bytes()))
|
||||
err := evidencePool.AddEvidenceFromConsensus(ev, time.Now(), state.Validators)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -179,11 +179,10 @@ type EvidenceParams struct {
|
||||
// mechanism for handling [Nothing-At-Stake
|
||||
// attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed).
|
||||
MaxAgeDuration time.Duration `protobuf:"bytes,2,opt,name=max_age_duration,json=maxAgeDuration,proto3,stdduration" json:"max_age_duration"`
|
||||
// This sets the maximum number of evidence that can be committed in a single block.
|
||||
// and should fall comfortably under the max block bytes when we consider the size of
|
||||
// each evidence (See MaxEvidenceBytes). The maximum number is MaxEvidencePerBlock.
|
||||
// Default is 50
|
||||
MaxNum uint32 `protobuf:"varint,3,opt,name=max_num,json=maxNum,proto3" json:"max_num,omitempty"`
|
||||
// This sets the maximum size of total evidence in bytes that can be committed in a single block.
|
||||
// and should fall comfortably under the max block bytes.
|
||||
// Default is 1048576 or 1MB
|
||||
MaxBytes int64 `protobuf:"varint,3,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EvidenceParams) Reset() { *m = EvidenceParams{} }
|
||||
@@ -233,9 +232,9 @@ func (m *EvidenceParams) GetMaxAgeDuration() time.Duration {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *EvidenceParams) GetMaxNum() uint32 {
|
||||
func (m *EvidenceParams) GetMaxBytes() int64 {
|
||||
if m != nil {
|
||||
return m.MaxNum
|
||||
return m.MaxBytes
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -398,42 +397,41 @@ func init() {
|
||||
func init() { proto.RegisterFile("tendermint/types/params.proto", fileDescriptor_e12598271a686f57) }
|
||||
|
||||
var fileDescriptor_e12598271a686f57 = []byte{
|
||||
// 545 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x4f, 0x6f, 0xd3, 0x30,
|
||||
0x1c, 0xad, 0xd7, 0xb2, 0xb5, 0xbf, 0xae, 0xeb, 0x64, 0x21, 0x51, 0x86, 0x96, 0x94, 0x1c, 0xd0,
|
||||
0x24, 0xa4, 0x44, 0x82, 0x03, 0x62, 0x97, 0x89, 0xc0, 0x34, 0x10, 0xea, 0x84, 0x22, 0xe0, 0xb0,
|
||||
0x4b, 0xe4, 0xb4, 0x26, 0x8b, 0x56, 0xc7, 0x51, 0x6c, 0x57, 0xed, 0xb7, 0xe0, 0xb8, 0xe3, 0x2e,
|
||||
0x48, 0x7c, 0x04, 0x3e, 0xc2, 0x8e, 0x3b, 0x72, 0x02, 0xd4, 0x5e, 0xf8, 0x18, 0x28, 0x4e, 0x4d,
|
||||
0xff, 0x6c, 0xb7, 0xe4, 0xf7, 0x7b, 0xef, 0xd9, 0xef, 0x3d, 0x19, 0xf6, 0x25, 0x4d, 0x07, 0x34,
|
||||
0x67, 0x49, 0x2a, 0x3d, 0x39, 0xc9, 0xa8, 0xf0, 0x32, 0x92, 0x13, 0x26, 0xdc, 0x2c, 0xe7, 0x92,
|
||||
0xe3, 0xdd, 0xc5, 0xda, 0xd5, 0xeb, 0xbd, 0xfb, 0x31, 0x8f, 0xb9, 0x5e, 0x7a, 0xc5, 0x57, 0x89,
|
||||
0xdb, 0xb3, 0x62, 0xce, 0xe3, 0x21, 0xf5, 0xf4, 0x5f, 0xa4, 0xbe, 0x78, 0x03, 0x95, 0x13, 0x99,
|
||||
0xf0, 0xb4, 0xdc, 0x3b, 0x97, 0x1b, 0xd0, 0x7e, 0xcd, 0x53, 0x41, 0x53, 0xa1, 0xc4, 0x07, 0x7d,
|
||||
0x02, 0x7e, 0x09, 0xf7, 0xa2, 0x21, 0xef, 0x5f, 0x74, 0x50, 0x17, 0x1d, 0x34, 0x9f, 0xed, 0xbb,
|
||||
0xeb, 0x67, 0xb9, 0x7e, 0xb1, 0x2e, 0xd1, 0x7e, 0xed, 0xfa, 0x97, 0x5d, 0x09, 0x4a, 0x06, 0xf6,
|
||||
0xa1, 0x4e, 0x47, 0xc9, 0x80, 0xa6, 0x7d, 0xda, 0xd9, 0xd0, 0xec, 0xee, 0x6d, 0xf6, 0xf1, 0x1c,
|
||||
0xb1, 0x22, 0xf0, 0x9f, 0x87, 0x8f, 0xa1, 0x31, 0x22, 0xc3, 0x64, 0x40, 0x24, 0xcf, 0x3b, 0x55,
|
||||
0x2d, 0xf2, 0xf8, 0xb6, 0xc8, 0x67, 0x03, 0x59, 0x51, 0x59, 0x30, 0xf1, 0x11, 0x6c, 0x8d, 0x68,
|
||||
0x2e, 0x12, 0x9e, 0x76, 0x6a, 0x5a, 0xc4, 0xbe, 0x43, 0xa4, 0x04, 0xac, 0x48, 0x18, 0x96, 0x43,
|
||||
0xa1, 0xb9, 0xe4, 0x13, 0x3f, 0x82, 0x06, 0x23, 0xe3, 0x30, 0x9a, 0x48, 0x2a, 0x74, 0x32, 0xd5,
|
||||
0xa0, 0xce, 0xc8, 0xd8, 0x2f, 0xfe, 0xf1, 0x03, 0xd8, 0x2a, 0x96, 0x31, 0x11, 0xda, 0x76, 0x35,
|
||||
0xd8, 0x64, 0x64, 0x7c, 0x42, 0x04, 0xee, 0xc2, 0xb6, 0x4c, 0x18, 0x0d, 0x13, 0x2e, 0x49, 0xc8,
|
||||
0x84, 0xf6, 0x53, 0x0d, 0xa0, 0x98, 0xbd, 0xe3, 0x92, 0xf4, 0x84, 0xf3, 0x0d, 0xc1, 0xce, 0x6a,
|
||||
0x22, 0xf8, 0x29, 0xe0, 0x42, 0x8d, 0xc4, 0x34, 0x4c, 0x15, 0x0b, 0x75, 0xb4, 0xe6, 0xcc, 0x36,
|
||||
0x23, 0xe3, 0x57, 0x31, 0x3d, 0x55, 0x4c, 0x5f, 0x4e, 0xe0, 0x1e, 0xec, 0x1a, 0xb0, 0xe9, 0x76,
|
||||
0x1e, 0xfd, 0x43, 0xb7, 0x2c, 0xdf, 0x35, 0xe5, 0xbb, 0x6f, 0xe6, 0x00, 0xbf, 0x5e, 0x58, 0xbd,
|
||||
0xfc, 0x6d, 0xa3, 0x60, 0xa7, 0xd4, 0x33, 0x1b, 0xe3, 0x24, 0x55, 0x4c, 0xdf, 0xb5, 0xa5, 0x9d,
|
||||
0x9c, 0x2a, 0xe6, 0x1c, 0x41, 0x7b, 0x2d, 0x73, 0xec, 0x40, 0x2b, 0x53, 0x51, 0x78, 0x41, 0x27,
|
||||
0xa1, 0xce, 0xb3, 0x83, 0xba, 0xd5, 0x83, 0x46, 0xd0, 0xcc, 0x54, 0xf4, 0x9e, 0x4e, 0x3e, 0x16,
|
||||
0xa3, 0xc3, 0xfa, 0x8f, 0x2b, 0x1b, 0xfd, 0xbd, 0xb2, 0x91, 0x73, 0x08, 0xad, 0x95, 0xbc, 0xb1,
|
||||
0x0d, 0x4d, 0x92, 0x65, 0xa1, 0x69, 0xa9, 0xf0, 0x57, 0x0b, 0x80, 0x64, 0xd9, 0x1c, 0xb6, 0xc4,
|
||||
0x3d, 0x83, 0xed, 0xb7, 0x44, 0x9c, 0xd3, 0xc1, 0x9c, 0xfa, 0x04, 0xda, 0x3a, 0x95, 0x70, 0xbd,
|
||||
0x92, 0x96, 0x1e, 0xf7, 0x4c, 0x2f, 0x0e, 0xb4, 0x16, 0xb8, 0x45, 0x3b, 0x4d, 0x83, 0x3a, 0x21,
|
||||
0xc2, 0xff, 0xf4, 0x7d, 0x6a, 0xa1, 0xeb, 0xa9, 0x85, 0x6e, 0xa6, 0x16, 0xfa, 0x33, 0xb5, 0xd0,
|
||||
0xd7, 0x99, 0x55, 0xb9, 0x99, 0x59, 0x95, 0x9f, 0x33, 0xab, 0x72, 0xf6, 0x22, 0x4e, 0xe4, 0xb9,
|
||||
0x8a, 0xdc, 0x3e, 0x67, 0xde, 0xf2, 0x93, 0x5c, 0x7c, 0x96, 0x6f, 0x6e, 0xfd, 0xb9, 0x46, 0x9b,
|
||||
0x7a, 0xfe, 0xfc, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x53, 0x0a, 0x6c, 0x0d, 0xc9, 0x03, 0x00,
|
||||
0x00,
|
||||
// 537 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x31, 0x6f, 0xd3, 0x40,
|
||||
0x18, 0xcd, 0xd5, 0xa5, 0x4d, 0xbe, 0x34, 0x4d, 0x75, 0x42, 0x22, 0x14, 0xd5, 0x0e, 0x1e, 0x50,
|
||||
0x25, 0x24, 0x5b, 0x82, 0x01, 0xd1, 0xa5, 0xc2, 0x50, 0x15, 0x84, 0x82, 0x90, 0x05, 0x0c, 0x5d,
|
||||
0xac, 0x73, 0x72, 0xb8, 0x56, 0x73, 0x3e, 0xcb, 0x77, 0x8e, 0x92, 0x7f, 0xc1, 0xd8, 0xb1, 0x23,
|
||||
0xfc, 0x03, 0x7e, 0x42, 0xc7, 0x8e, 0x4c, 0x80, 0x92, 0x85, 0x9f, 0x81, 0x7c, 0xce, 0xe1, 0x38,
|
||||
0x65, 0xf3, 0x7d, 0xdf, 0x7b, 0xef, 0xfc, 0xde, 0xd3, 0xc1, 0x81, 0xa4, 0xc9, 0x88, 0x66, 0x2c,
|
||||
0x4e, 0xa4, 0x2b, 0x67, 0x29, 0x15, 0x6e, 0x4a, 0x32, 0xc2, 0x84, 0x93, 0x66, 0x5c, 0x72, 0xbc,
|
||||
0x57, 0xad, 0x1d, 0xb5, 0xde, 0xbf, 0x1b, 0xf1, 0x88, 0xab, 0xa5, 0x5b, 0x7c, 0x95, 0xb8, 0x7d,
|
||||
0x33, 0xe2, 0x3c, 0x1a, 0x53, 0x57, 0x9d, 0xc2, 0xfc, 0xb3, 0x3b, 0xca, 0x33, 0x22, 0x63, 0x9e,
|
||||
0x94, 0x7b, 0xfb, 0x72, 0x03, 0xba, 0x2f, 0x79, 0x22, 0x68, 0x22, 0x72, 0xf1, 0x5e, 0xdd, 0x80,
|
||||
0x9f, 0xc3, 0x9d, 0x70, 0xcc, 0x87, 0x17, 0x3d, 0xd4, 0x47, 0x87, 0xed, 0x27, 0x07, 0xce, 0xfa,
|
||||
0x5d, 0x8e, 0x57, 0xac, 0x4b, 0xb4, 0xb7, 0x79, 0xfd, 0xd3, 0x6a, 0xf8, 0x25, 0x03, 0x7b, 0xd0,
|
||||
0xa4, 0x93, 0x78, 0x44, 0x93, 0x21, 0xed, 0x6d, 0x28, 0x76, 0xff, 0x36, 0xfb, 0x64, 0x89, 0xa8,
|
||||
0x09, 0xfc, 0xe3, 0xe1, 0x13, 0x68, 0x4d, 0xc8, 0x38, 0x1e, 0x11, 0xc9, 0xb3, 0x9e, 0xa1, 0x44,
|
||||
0x1e, 0xde, 0x16, 0xf9, 0xa4, 0x21, 0x35, 0x95, 0x8a, 0x89, 0x8f, 0x61, 0x7b, 0x42, 0x33, 0x11,
|
||||
0xf3, 0xa4, 0xb7, 0xa9, 0x44, 0xac, 0xff, 0x88, 0x94, 0x80, 0x9a, 0x84, 0x66, 0xd9, 0x14, 0xda,
|
||||
0x2b, 0x3e, 0xf1, 0x03, 0x68, 0x31, 0x32, 0x0d, 0xc2, 0x99, 0xa4, 0x42, 0x25, 0x63, 0xf8, 0x4d,
|
||||
0x46, 0xa6, 0x5e, 0x71, 0xc6, 0xf7, 0x60, 0xbb, 0x58, 0x46, 0x44, 0x28, 0xdb, 0x86, 0xbf, 0xc5,
|
||||
0xc8, 0xf4, 0x94, 0x08, 0xdc, 0x87, 0x1d, 0x19, 0x33, 0x1a, 0xc4, 0x5c, 0x92, 0x80, 0x09, 0xe5,
|
||||
0xc7, 0xf0, 0xa1, 0x98, 0xbd, 0xe1, 0x92, 0x0c, 0x84, 0xfd, 0x0d, 0xc1, 0x6e, 0x3d, 0x11, 0xfc,
|
||||
0x18, 0x70, 0xa1, 0x46, 0x22, 0x1a, 0x24, 0x39, 0x0b, 0x54, 0xb4, 0xfa, 0xce, 0x2e, 0x23, 0xd3,
|
||||
0x17, 0x11, 0x7d, 0x97, 0x33, 0xf5, 0x73, 0x02, 0x0f, 0x60, 0x4f, 0x83, 0x75, 0xb7, 0xcb, 0xe8,
|
||||
0xef, 0x3b, 0x65, 0xf9, 0x8e, 0x2e, 0xdf, 0x79, 0xb5, 0x04, 0x78, 0xcd, 0xc2, 0xea, 0xe5, 0x2f,
|
||||
0x0b, 0xf9, 0xbb, 0xa5, 0x9e, 0xde, 0xd4, 0x6d, 0x1a, 0x75, 0x9b, 0xf6, 0x31, 0x74, 0xd7, 0x72,
|
||||
0xc7, 0x36, 0x74, 0xd2, 0x3c, 0x0c, 0x2e, 0xe8, 0x2c, 0x50, 0x99, 0xf6, 0x50, 0xdf, 0x38, 0x6c,
|
||||
0xf9, 0xed, 0x34, 0x0f, 0xdf, 0xd2, 0xd9, 0x87, 0x62, 0x74, 0xd4, 0xfc, 0x7e, 0x65, 0xa1, 0x3f,
|
||||
0x57, 0x16, 0xb2, 0x8f, 0xa0, 0x53, 0xcb, 0x1c, 0x5b, 0xd0, 0x26, 0x69, 0x1a, 0xe8, 0xa6, 0x0a,
|
||||
0x8f, 0x9b, 0x3e, 0x90, 0x34, 0x5d, 0xc2, 0x56, 0xb8, 0x67, 0xb0, 0xf3, 0x9a, 0x88, 0x73, 0x3a,
|
||||
0x5a, 0x52, 0x1f, 0x41, 0x57, 0x25, 0x13, 0xac, 0xd7, 0xd2, 0x51, 0xe3, 0x81, 0xee, 0xc6, 0x86,
|
||||
0x4e, 0x85, 0xab, 0x1a, 0x6a, 0x6b, 0xd4, 0x29, 0x11, 0xde, 0xc7, 0xaf, 0x73, 0x13, 0x5d, 0xcf,
|
||||
0x4d, 0x74, 0x33, 0x37, 0xd1, 0xef, 0xb9, 0x89, 0xbe, 0x2c, 0xcc, 0xc6, 0xcd, 0xc2, 0x6c, 0xfc,
|
||||
0x58, 0x98, 0x8d, 0xb3, 0x67, 0x51, 0x2c, 0xcf, 0xf3, 0xd0, 0x19, 0x72, 0xe6, 0xae, 0x3e, 0xcb,
|
||||
0xea, 0xb3, 0x7c, 0x77, 0xeb, 0x4f, 0x36, 0xdc, 0x52, 0xf3, 0xa7, 0x7f, 0x03, 0x00, 0x00, 0xff,
|
||||
0xff, 0xfe, 0xe0, 0x3d, 0x9c, 0xcd, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (this *ConsensusParams) Equal(that interface{}) bool {
|
||||
@@ -524,7 +522,7 @@ func (this *EvidenceParams) Equal(that interface{}) bool {
|
||||
if this.MaxAgeDuration != that1.MaxAgeDuration {
|
||||
return false
|
||||
}
|
||||
if this.MaxNum != that1.MaxNum {
|
||||
if this.MaxBytes != that1.MaxBytes {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -730,8 +728,8 @@ func (m *EvidenceParams) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.MaxNum != 0 {
|
||||
i = encodeVarintParams(dAtA, i, uint64(m.MaxNum))
|
||||
if m.MaxBytes != 0 {
|
||||
i = encodeVarintParams(dAtA, i, uint64(m.MaxBytes))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
@@ -993,8 +991,8 @@ func (m *EvidenceParams) Size() (n int) {
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxAgeDuration)
|
||||
n += 1 + l + sovParams(uint64(l))
|
||||
if m.MaxNum != 0 {
|
||||
n += 1 + sovParams(uint64(m.MaxNum))
|
||||
if m.MaxBytes != 0 {
|
||||
n += 1 + sovParams(uint64(m.MaxBytes))
|
||||
}
|
||||
return n
|
||||
}
|
||||
@@ -1425,9 +1423,9 @@ func (m *EvidenceParams) Unmarshal(dAtA []byte) error {
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field MaxNum", wireType)
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType)
|
||||
}
|
||||
m.MaxNum = 0
|
||||
m.MaxBytes = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowParams
|
||||
@@ -1437,7 +1435,7 @@ func (m *EvidenceParams) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.MaxNum |= uint32(b&0x7F) << shift
|
||||
m.MaxBytes |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -48,11 +48,10 @@ message EvidenceParams {
|
||||
google.protobuf.Duration max_age_duration = 2
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
|
||||
|
||||
// This sets the maximum number of evidence that can be committed in a single block.
|
||||
// and should fall comfortably under the max block bytes when we consider the size of
|
||||
// each evidence (See MaxEvidenceBytes). The maximum number is MaxEvidencePerBlock.
|
||||
// Default is 50
|
||||
uint32 max_num = 3;
|
||||
// This sets the maximum size of total evidence in bytes that can be committed in a single block.
|
||||
// and should fall comfortably under the max block bytes.
|
||||
// Default is 1048576 or 1MB
|
||||
int64 max_bytes = 3;
|
||||
}
|
||||
|
||||
// ValidatorParams restrict the public key types validators can use.
|
||||
|
||||
@@ -100,10 +100,10 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
|
||||
maxBytes := state.ConsensusParams.Block.MaxBytes
|
||||
maxGas := state.ConsensusParams.Block.MaxGas
|
||||
|
||||
evidence := blockExec.evpool.PendingEvidence(state.ConsensusParams.Evidence.MaxNum)
|
||||
evidence, evSize := blockExec.evpool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
|
||||
|
||||
// Fetch a limited amount of valid txs
|
||||
maxDataBytes := types.MaxDataBytes(maxBytes, state.Validators.Size(), len(evidence))
|
||||
maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Validators.Size())
|
||||
txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas)
|
||||
|
||||
return state.MakeBlock(height, txs, commit, evidence, proposerAddr)
|
||||
|
||||
@@ -61,11 +61,11 @@ func (_m *EvidencePool) CheckEvidence(_a0 types.EvidenceList) error {
|
||||
}
|
||||
|
||||
// PendingEvidence provides a mock function with given fields: _a0
|
||||
func (_m *EvidencePool) PendingEvidence(_a0 uint32) []types.Evidence {
|
||||
func (_m *EvidencePool) PendingEvidence(_a0 int64) ([]types.Evidence, int64) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
var r0 []types.Evidence
|
||||
if rf, ok := ret.Get(0).(func(uint32) []types.Evidence); ok {
|
||||
if rf, ok := ret.Get(0).(func(int64) []types.Evidence); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
@@ -73,7 +73,14 @@ func (_m *EvidencePool) PendingEvidence(_a0 uint32) []types.Evidence {
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
var r1 int64
|
||||
if rf, ok := ret.Get(1).(func(int64) int64); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Get(1).(int64)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: _a0
|
||||
|
||||
@@ -43,7 +43,7 @@ type BlockStore interface {
|
||||
|
||||
// EvidencePool defines the EvidencePool interface used by State.
|
||||
type EvidencePool interface {
|
||||
PendingEvidence(uint32) []types.Evidence
|
||||
PendingEvidence(maxBytes int64) (ev []types.Evidence, size int64)
|
||||
AddEvidence(types.Evidence) error
|
||||
Update(State)
|
||||
CheckEvidence(types.EvidenceList) error
|
||||
@@ -54,7 +54,9 @@ type EvidencePool interface {
|
||||
// to the consensus evidence pool interface
|
||||
type EmptyEvidencePool struct{}
|
||||
|
||||
func (EmptyEvidencePool) PendingEvidence(uint32) []types.Evidence { return nil }
|
||||
func (EmptyEvidencePool) PendingEvidence(maxBytes int64) (ev []types.Evidence, size int64) {
|
||||
return nil, 0
|
||||
}
|
||||
func (EmptyEvidencePool) AddEvidence(types.Evidence) error { return nil }
|
||||
func (EmptyEvidencePool) Update(State) {}
|
||||
func (EmptyEvidencePool) CheckEvidence(evList types.EvidenceList) error { return nil }
|
||||
|
||||
@@ -8,10 +8,9 @@ import (
|
||||
// TxPreCheck returns a function to filter transactions before processing.
|
||||
// The function limits the size of a transaction to the block's maximum data size.
|
||||
func TxPreCheck(state State) mempl.PreCheckFunc {
|
||||
maxDataBytes := types.MaxDataBytesUnknownEvidence(
|
||||
maxDataBytes := types.MaxDataBytesNoEvidence(
|
||||
state.ConsensusParams.Block.MaxBytes,
|
||||
state.Validators.Size(),
|
||||
state.ConsensusParams.Evidence.MaxNum,
|
||||
)
|
||||
return mempl.PreCheckMaxBytes(maxDataBytes)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
func TestTxFilter(t *testing.T) {
|
||||
genDoc := randomGenesisDoc()
|
||||
genDoc.ConsensusParams.Block.MaxBytes = 3000
|
||||
genDoc.ConsensusParams.Evidence.MaxNum = 1
|
||||
genDoc.ConsensusParams.Evidence.MaxBytes = 1500
|
||||
|
||||
// Max size of Txs is much smaller than size of block,
|
||||
// since we need to account for commits and evidence.
|
||||
@@ -25,8 +25,8 @@ func TestTxFilter(t *testing.T) {
|
||||
tx types.Tx
|
||||
isErr bool
|
||||
}{
|
||||
{types.Tx(tmrand.Bytes(1680)), false},
|
||||
{types.Tx(tmrand.Bytes(1853)), true},
|
||||
{types.Tx(tmrand.Bytes(2154)), false},
|
||||
{types.Tx(tmrand.Bytes(2155)), true},
|
||||
{types.Tx(tmrand.Bytes(3000)), true},
|
||||
}
|
||||
|
||||
|
||||
@@ -142,8 +142,8 @@ func validateBlock(evidencePool EvidencePool, state State, block *types.Block) e
|
||||
block.Height, state.InitialHeight)
|
||||
}
|
||||
|
||||
// Check evidence doesn't exceed the limit. MaxNumEvidence is capped at uint16, so conversion is always safe.
|
||||
if max, got := int(state.ConsensusParams.Evidence.MaxNum), len(block.Evidence.Evidence); got > max {
|
||||
// Check evidence doesn't exceed the limit amount of bytes.
|
||||
if max, got := state.ConsensusParams.Evidence.MaxBytes, block.Evidence.ByteSize(); got > max {
|
||||
return types.NewErrEvidenceOverflow(max, got)
|
||||
}
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ func TestValidateBlockEvidence(t *testing.T) {
|
||||
evpool.On("ABCIEvidence", mock.AnythingOfType("int64"), mock.AnythingOfType("[]types.Evidence")).Return(
|
||||
[]abci.Evidence{})
|
||||
|
||||
state.ConsensusParams.Evidence.MaxNum = 3
|
||||
state.ConsensusParams.Evidence.MaxBytes = 1000
|
||||
blockExec := sm.NewBlockExecutor(
|
||||
stateStore,
|
||||
log.TestingLogger(),
|
||||
@@ -234,17 +234,19 @@ func TestValidateBlockEvidence(t *testing.T) {
|
||||
|
||||
for height := int64(1); height < validationTestsStopHeight; height++ {
|
||||
proposerAddr := state.Validators.GetProposer().Address
|
||||
maxNumEvidence := state.ConsensusParams.Evidence.MaxNum
|
||||
maxBytesEvidence := state.ConsensusParams.Evidence.MaxBytes
|
||||
if height > 1 {
|
||||
/*
|
||||
A block with too much evidence fails
|
||||
*/
|
||||
require.True(t, maxNumEvidence > 2)
|
||||
evidence := make([]types.Evidence, 0)
|
||||
// one more than the maximum allowed evidence
|
||||
for i := uint32(0); i <= maxNumEvidence; i++ {
|
||||
evidence = append(evidence, types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(),
|
||||
privVals[proposerAddr.String()], chainID))
|
||||
var currentBytes int64 = 0
|
||||
// more bytes than the maximum allowed for evidence
|
||||
for currentBytes <= maxBytesEvidence {
|
||||
newEv := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(),
|
||||
privVals[proposerAddr.String()], chainID)
|
||||
evidence = append(evidence, newEv)
|
||||
currentBytes += int64(len(newEv.Bytes()))
|
||||
}
|
||||
block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr)
|
||||
err := blockExec.ValidateBlock(state, block)
|
||||
@@ -257,14 +259,17 @@ func TestValidateBlockEvidence(t *testing.T) {
|
||||
/*
|
||||
A good block with several pieces of good evidence passes
|
||||
*/
|
||||
require.True(t, maxNumEvidence > 2)
|
||||
evidence := make([]types.Evidence, 0)
|
||||
var currentBytes int64 = 0
|
||||
// precisely the amount of allowed evidence
|
||||
for i := int32(0); uint32(i) < maxNumEvidence; i++ {
|
||||
// make different evidence for each validator
|
||||
_, val := state.Validators.GetByIndex(i)
|
||||
evidence = append(evidence, types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime,
|
||||
privVals[val.Address.String()], chainID))
|
||||
for {
|
||||
newEv := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime,
|
||||
privVals[proposerAddr.String()], chainID)
|
||||
currentBytes += int64(len(newEv.Bytes()))
|
||||
if currentBytes >= maxBytesEvidence {
|
||||
break
|
||||
}
|
||||
evidence = append(evidence, newEv)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
@@ -273,12 +273,12 @@ func BlockFromProto(bp *tmproto.Block) (*Block, error) {
|
||||
// MaxDataBytes returns the maximum size of block's data.
|
||||
//
|
||||
// XXX: Panics on negative result.
|
||||
func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
|
||||
func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 {
|
||||
maxDataBytes := maxBytes -
|
||||
MaxOverheadForBlock -
|
||||
MaxHeaderBytes -
|
||||
int64(valsCount)*MaxVoteBytes -
|
||||
int64(evidenceCount)*MaxEvidenceBytes
|
||||
evidenceBytes
|
||||
|
||||
if maxDataBytes < 0 {
|
||||
panic(fmt.Sprintf(
|
||||
@@ -292,18 +292,16 @@ func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
|
||||
|
||||
}
|
||||
|
||||
// MaxDataBytesUnknownEvidence returns the maximum size of block's data when
|
||||
// MaxDataBytesNoEvidence returns the maximum size of block's data when
|
||||
// evidence count is unknown. MaxEvidencePerBlock will be used for the size
|
||||
// of evidence.
|
||||
//
|
||||
// XXX: Panics on negative result.
|
||||
func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int, maxNumEvidence uint32) int64 {
|
||||
maxEvidenceBytes := int64(maxNumEvidence) * MaxEvidenceBytes
|
||||
func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 {
|
||||
maxDataBytes := maxBytes -
|
||||
MaxOverheadForBlock -
|
||||
MaxHeaderBytes -
|
||||
int64(valsCount)*MaxVoteBytes -
|
||||
maxEvidenceBytes
|
||||
int64(valsCount)*MaxVoteBytes
|
||||
|
||||
if maxDataBytes < 0 {
|
||||
panic(fmt.Sprintf(
|
||||
@@ -1073,8 +1071,9 @@ func DataFromProto(dp *tmproto.Data) (Data, error) {
|
||||
type EvidenceData struct {
|
||||
Evidence EvidenceList `json:"evidence"`
|
||||
|
||||
// Volatile
|
||||
hash tmbytes.HexBytes
|
||||
// Volatile. Used as cache
|
||||
hash tmbytes.HexBytes
|
||||
byteSize int64
|
||||
}
|
||||
|
||||
// Hash returns the hash of the data.
|
||||
@@ -1085,6 +1084,20 @@ func (data *EvidenceData) Hash() tmbytes.HexBytes {
|
||||
return data.hash
|
||||
}
|
||||
|
||||
// ByteSize returns the total byte size of all the evidence
|
||||
func (data *EvidenceData) ByteSize() int64 {
|
||||
if data.byteSize == 0 && len(data.Evidence) != 0 {
|
||||
for _, ev := range data.Evidence {
|
||||
pb, err := EvidenceToProto(ev)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data.byteSize += int64(pb.Size())
|
||||
}
|
||||
}
|
||||
return data.byteSize
|
||||
}
|
||||
|
||||
// StringIndented returns a string representation of the evidence.
|
||||
func (data *EvidenceData) StringIndented(indent string) string {
|
||||
if data == nil {
|
||||
@@ -1142,11 +1155,10 @@ func (data *EvidenceData) FromProto(eviData *tmproto.EvidenceData) error {
|
||||
return err
|
||||
}
|
||||
eviBzs[i] = evi
|
||||
data.byteSize += int64(eviData.Evidence[i].Size())
|
||||
}
|
||||
data.Evidence = eviBzs
|
||||
|
||||
data.hash = eviData.GetHash()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ func TestBlockMaxDataBytes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
maxBytes int64
|
||||
valsCount int
|
||||
evidenceCount int
|
||||
evidenceBytes int64
|
||||
panics bool
|
||||
result int64
|
||||
}{
|
||||
@@ -416,43 +416,41 @@ func TestBlockMaxDataBytes(t *testing.T) {
|
||||
tc := tc
|
||||
if tc.panics {
|
||||
assert.Panics(t, func() {
|
||||
MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount)
|
||||
MaxDataBytes(tc.maxBytes, tc.evidenceBytes, tc.valsCount)
|
||||
}, "#%v", i)
|
||||
} else {
|
||||
assert.Equal(t,
|
||||
tc.result,
|
||||
MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount),
|
||||
MaxDataBytes(tc.maxBytes, tc.evidenceBytes, tc.valsCount),
|
||||
"#%v", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
|
||||
func TestBlockMaxDataBytesNoEvidence(t *testing.T) {
|
||||
testCases := []struct {
|
||||
maxBytes int64
|
||||
maxEvidence uint32
|
||||
valsCount int
|
||||
panics bool
|
||||
result int64
|
||||
maxBytes int64
|
||||
valsCount int
|
||||
panics bool
|
||||
result int64
|
||||
}{
|
||||
0: {-10, 0, 1, true, 0},
|
||||
1: {10, 0, 1, true, 0},
|
||||
2: {845, 0, 1, true, 0},
|
||||
3: {846, 0, 1, false, 0},
|
||||
4: {1290, 1, 1, false, 0},
|
||||
5: {1291, 1, 1, false, 1},
|
||||
0: {-10, 1, true, 0},
|
||||
1: {10, 1, true, 0},
|
||||
2: {845, 1, true, 0},
|
||||
3: {846, 1, false, 0},
|
||||
4: {847, 1, false, 1},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
tc := tc
|
||||
if tc.panics {
|
||||
assert.Panics(t, func() {
|
||||
MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount, tc.maxEvidence)
|
||||
MaxDataBytesNoEvidence(tc.maxBytes, tc.valsCount)
|
||||
}, "#%v", i)
|
||||
} else {
|
||||
assert.Equal(t,
|
||||
tc.result,
|
||||
MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount, tc.maxEvidence),
|
||||
MaxDataBytesNoEvidence(tc.maxBytes, tc.valsCount),
|
||||
"#%v", i)
|
||||
}
|
||||
}
|
||||
@@ -620,7 +618,7 @@ func TestBlockProtoBuf(t *testing.T) {
|
||||
require.NoError(t, err, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Header, block.Header, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Data, block.Data, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Evidence, block.Evidence, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Evidence.Evidence, block.Evidence.Evidence, tc.msg)
|
||||
require.EqualValues(t, *tc.b1.LastCommit, *block.LastCommit, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
@@ -653,6 +651,7 @@ func TestDataProtoBuf(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestEvidenceDataProtoBuf ensures parity in converting to and from proto.
|
||||
func TestEvidenceDataProtoBuf(t *testing.T) {
|
||||
val := NewMockPV()
|
||||
blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
|
||||
@@ -662,7 +661,7 @@ func TestEvidenceDataProtoBuf(t *testing.T) {
|
||||
v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, time.Now())
|
||||
ev := NewDuplicateVoteEvidence(v2, v)
|
||||
data := &EvidenceData{Evidence: EvidenceList{ev}}
|
||||
_ = data.Hash()
|
||||
_ = data.ByteSize()
|
||||
testCases := []struct {
|
||||
msg string
|
||||
data1 *EvidenceData
|
||||
|
||||
@@ -25,11 +25,6 @@ type Evidence interface {
|
||||
String() string // string format of the evidence
|
||||
}
|
||||
|
||||
const (
|
||||
// MaxEvidenceBytes is a maximum size of any evidence (including amino overhead).
|
||||
MaxEvidenceBytes int64 = 444
|
||||
)
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// DuplicateVoteEvidence contains evidence a validator signed two conflicting
|
||||
@@ -365,20 +360,20 @@ func (err *ErrInvalidEvidence) Error() string {
|
||||
return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.Reason, err.Evidence)
|
||||
}
|
||||
|
||||
// ErrEvidenceOverflow is for when there is too much evidence in a block.
|
||||
// ErrEvidenceOverflow is for when there the amount of evidence exceeds the max bytes.
|
||||
type ErrEvidenceOverflow struct {
|
||||
MaxNum int
|
||||
GotNum int
|
||||
Max int64
|
||||
Got int64
|
||||
}
|
||||
|
||||
// NewErrEvidenceOverflow returns a new ErrEvidenceOverflow where got > max.
|
||||
func NewErrEvidenceOverflow(max, got int) *ErrEvidenceOverflow {
|
||||
func NewErrEvidenceOverflow(max, got int64) *ErrEvidenceOverflow {
|
||||
return &ErrEvidenceOverflow{max, got}
|
||||
}
|
||||
|
||||
// Error returns a string representation of the error.
|
||||
func (err *ErrEvidenceOverflow) Error() string {
|
||||
return fmt.Sprintf("Too much evidence: Max %d, got %d", err.MaxNum, err.GotNum)
|
||||
return fmt.Sprintf("Too much evidence: Max %d, got %d", err.Max, err.Got)
|
||||
}
|
||||
|
||||
//-------------------------------------------- MOCKING --------------------------------------
|
||||
|
||||
@@ -27,37 +27,6 @@ func TestEvidenceList(t *testing.T) {
|
||||
assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
|
||||
}
|
||||
|
||||
func TestMaxEvidenceBytes(t *testing.T) {
|
||||
val := NewMockPV()
|
||||
blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
|
||||
blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash")))
|
||||
maxTime := time.Date(9999, 0, 0, 0, 0, 0, 0, time.UTC)
|
||||
const chainID = "mychain"
|
||||
ev := &DuplicateVoteEvidence{
|
||||
VoteA: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID, maxTime),
|
||||
VoteB: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, math.MaxInt64, blockID2, maxTime),
|
||||
}
|
||||
|
||||
//TODO: Add other types of evidence to test and set MaxEvidenceBytes accordingly
|
||||
|
||||
testCases := []struct {
|
||||
testName string
|
||||
evidence Evidence
|
||||
}{
|
||||
{"DuplicateVote", ev},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
pb, err := EvidenceToProto(tt.evidence)
|
||||
require.NoError(t, err, tt.testName)
|
||||
bz, err := pb.Marshal()
|
||||
require.NoError(t, err, tt.testName)
|
||||
|
||||
assert.LessOrEqual(t, int64(len(bz)), MaxEvidenceBytes, tt.testName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func randomDuplicateVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
|
||||
val := NewMockPV()
|
||||
blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
|
||||
|
||||
@@ -19,9 +19,6 @@ const (
|
||||
|
||||
// MaxBlockPartsCount is the maximum number of block parts.
|
||||
MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1
|
||||
|
||||
// Restrict the upper bound of the amount of evidence (uses uint16 for safe conversion)
|
||||
MaxEvidencePerBlock = 65535
|
||||
)
|
||||
|
||||
// DefaultConsensusParams returns a default ConsensusParams.
|
||||
@@ -48,7 +45,7 @@ func DefaultEvidenceParams() tmproto.EvidenceParams {
|
||||
return tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
|
||||
MaxAgeDuration: 48 * time.Hour,
|
||||
MaxNum: 50,
|
||||
MaxBytes: 1048576, // 1MB
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,23 +95,23 @@ func ValidateConsensusParams(params tmproto.ConsensusParams) error {
|
||||
}
|
||||
|
||||
if params.Evidence.MaxAgeNumBlocks <= 0 {
|
||||
return fmt.Errorf("evidenceParams.MaxAgeNumBlocks must be greater than 0. Got %d",
|
||||
return fmt.Errorf("evidence.MaxAgeNumBlocks must be greater than 0. Got %d",
|
||||
params.Evidence.MaxAgeNumBlocks)
|
||||
}
|
||||
|
||||
if params.Evidence.MaxAgeDuration <= 0 {
|
||||
return fmt.Errorf("evidenceParams.MaxAgeDuration must be grater than 0 if provided, Got %v",
|
||||
return fmt.Errorf("evidence.MaxAgeDuration must be grater than 0 if provided, Got %v",
|
||||
params.Evidence.MaxAgeDuration)
|
||||
}
|
||||
|
||||
if params.Evidence.MaxNum > MaxEvidencePerBlock {
|
||||
return fmt.Errorf("evidenceParams.MaxNumEvidence is greater than upper bound, %d > %d",
|
||||
params.Evidence.MaxNum, MaxEvidencePerBlock)
|
||||
if params.Evidence.MaxBytes > params.Block.MaxBytes {
|
||||
return fmt.Errorf("evidence.MaxBytesEvidence is greater than upper bound, %d > %d",
|
||||
params.Evidence.MaxBytes, params.Block.MaxBytes)
|
||||
}
|
||||
|
||||
if int64(params.Evidence.MaxNum)*MaxEvidenceBytes > params.Block.MaxBytes {
|
||||
return fmt.Errorf("total possible evidence size is bigger than block.MaxBytes, %d > %d",
|
||||
int64(params.Evidence.MaxNum)*MaxEvidenceBytes, params.Block.MaxBytes)
|
||||
if params.Evidence.MaxBytes < 0 {
|
||||
return fmt.Errorf("evidence.MaxBytes must be non negative. Got: %d",
|
||||
params.Evidence.MaxBytes)
|
||||
}
|
||||
|
||||
if len(params.Validator.PubKeyTypes) == 0 {
|
||||
@@ -174,7 +171,7 @@ func UpdateConsensusParams(params tmproto.ConsensusParams, params2 *abci.Consens
|
||||
if params2.Evidence != nil {
|
||||
res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks
|
||||
res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration
|
||||
res.Evidence.MaxNum = params2.Evidence.MaxNum
|
||||
res.Evidence.MaxBytes = params2.Evidence.MaxBytes
|
||||
}
|
||||
if params2.Validator != nil {
|
||||
// Copy params2.Validator.PubkeyTypes, and set result's value to the copy.
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestConsensusParamsValidation(t *testing.T) {
|
||||
8: {makeParams(1, 0, -10, 2, 0, valEd25519), false},
|
||||
// test evidence params
|
||||
9: {makeParams(1, 0, 10, 0, 0, valEd25519), false},
|
||||
10: {makeParams(1, 0, 10, 2, 1, valEd25519), false},
|
||||
10: {makeParams(1, 0, 10, 2, 2, valEd25519), false},
|
||||
11: {makeParams(1000, 0, 10, 2, 1, valEd25519), true},
|
||||
12: {makeParams(1, 0, 10, -1, 0, valEd25519), false},
|
||||
// test no pubkey type provided
|
||||
@@ -54,7 +54,7 @@ func makeParams(
|
||||
blockBytes, blockGas int64,
|
||||
blockTimeIotaMs int64,
|
||||
evidenceAge int64,
|
||||
maxEvidence uint32,
|
||||
maxEvidenceBytes int64,
|
||||
pubkeyTypes []string,
|
||||
) tmproto.ConsensusParams {
|
||||
return tmproto.ConsensusParams{
|
||||
@@ -66,7 +66,7 @@ func makeParams(
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: evidenceAge,
|
||||
MaxAgeDuration: time.Duration(evidenceAge),
|
||||
MaxNum: maxEvidence,
|
||||
MaxBytes: maxEvidenceBytes,
|
||||
},
|
||||
Validator: tmproto.ValidatorParams{
|
||||
PubKeyTypes: pubkeyTypes,
|
||||
@@ -124,7 +124,7 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
Evidence: &tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 300,
|
||||
MaxAgeDuration: time.Duration(300),
|
||||
MaxNum: 50,
|
||||
MaxBytes: 50,
|
||||
},
|
||||
Validator: &tmproto.ValidatorParams{
|
||||
PubKeyTypes: valEd25519,
|
||||
|
||||
@@ -121,7 +121,7 @@ func (psh PartSetHeader) ValidateBasic() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToProto converts BloPartSetHeaderckID to protobuf
|
||||
// ToProto converts PartSetHeader to protobuf
|
||||
func (psh *PartSetHeader) ToProto() tmproto.PartSetHeader {
|
||||
if psh == nil {
|
||||
return tmproto.PartSetHeader{}
|
||||
|
||||
Reference in New Issue
Block a user