Backport of sam/abci-responses (#9090) (#9159)

*backport of sam/abci-responses

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>
This commit is contained in:
samricotta
2022-08-11 10:41:41 +02:00
committed by GitHub
parent 65367d7e94
commit fbd754b4de
114 changed files with 1132 additions and 581 deletions

View File

@@ -3,7 +3,7 @@ Package evidence handles all evidence storage and gossiping from detection to bl
For the different types of evidence refer to the `evidence.go` file in the types package
or https://github.com/tendermint/spec/blob/master/spec/consensus/light-client/accountability.md.
Gossiping
# Gossiping
The core functionality begins with the evidence reactor (see reactor.
go) which operates both the sending and receiving of evidence.
@@ -29,7 +29,7 @@ There are two buckets that evidence can be stored in: Pending & Committed.
All evidence is proto encoded to disk.
Proposing
# Proposing
When a new block is being proposed (in state/execution.go#CreateProposalBlock),
`PendingEvidence(maxBytes)` is called to send up to the maxBytes of uncommitted evidence, from the evidence store,
@@ -42,12 +42,11 @@ Once the proposed evidence is submitted,
the evidence is marked as committed and is moved from the broadcasted set to the committed set.
As a result it is also removed from the concurrent list so that it is no longer gossiped.
Minor Functionality
# Minor Functionality
As all evidence (including POLC's) are bounded by an expiration date, those that exceed this are no longer needed
and hence pruned. Currently, only committed evidence in which a marker to the height that the evidence was committed
and hence very small is saved. All updates are made from the `Update(block, state)` function which should be called
when a new block is committed.
*/
package evidence

View File

@@ -58,13 +58,13 @@ func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta {
return r0
}
type NewBlockStoreT interface {
type mockConstructorTestingTNewBlockStore interface {
mock.TestingT
Cleanup(func())
}
// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewBlockStore(t NewBlockStoreT) *BlockStore {
func NewBlockStore(t mockConstructorTestingTNewBlockStore) *BlockStore {
mock := &BlockStore{}
mock.Mock.Test(t)

View File

@@ -97,11 +97,11 @@ func (evpool *Pool) PendingEvidence(maxBytes int64) ([]types.Evidence, int64) {
// Update takes both the new state and the evidence committed at that height and performs
// the following operations:
// 1. Take any conflicting votes from consensus and use the state's LastBlockTime to form
// DuplicateVoteEvidence and add it to the pool.
// 2. Update the pool's state which contains evidence params relating to expiry.
// 3. Moves pending evidence that has now been committed into the committed pool.
// 4. Removes any expired evidence based on both height and time.
// 1. Take any conflicting votes from consensus and use the state's LastBlockTime to form
// DuplicateVoteEvidence and add it to the pool.
// 2. Update the pool's state which contains evidence params relating to expiry.
// 3. Moves pending evidence that has now been committed into the committed pool.
// 4. Removes any expired evidence based on both height and time.
func (evpool *Pool) Update(state sm.State, ev types.EvidenceList) {
// sanity check
if state.LastBlockHeight <= evpool.state.LastBlockHeight {

View File

@@ -348,7 +348,9 @@ func TestRecoverPendingEvidence(t *testing.T) {
func initializeStateFromValidatorSet(valSet *types.ValidatorSet, height int64) sm.Store {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: false,
})
state := sm.State{
ChainID: evidenceChainID,
InitialHeight: 1,

View File

@@ -102,13 +102,14 @@ func (evpool *Pool) verify(evidence types.Evidence) error {
// VerifyLightClientAttack verifies LightClientAttackEvidence against the state of the full node. This involves
// the following checks:
// - the common header from the full node has at least 1/3 voting power which is also present in
// the conflicting header's commit
// - 2/3+ of the conflicting validator set correctly signed the conflicting block
// - the nodes trusted header at the same height as the conflicting header has a different hash
// - the common header from the full node has at least 1/3 voting power which is also present in
// the conflicting header's commit
// - 2/3+ of the conflicting validator set correctly signed the conflicting block
// - the nodes trusted header at the same height as the conflicting header has a different hash
//
// CONTRACT: must run ValidateBasic() on the evidence before verifying
// must check that the evidence has not expired (i.e. is outside the maximum age threshold)
//
// must check that the evidence has not expired (i.e. is outside the maximum age threshold)
func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, trustedHeader *types.SignedHeader,
commonVals *types.ValidatorSet, now time.Time, trustPeriod time.Duration) error {
// In the case of lunatic attack there will be a different commonHeader height. Therefore the node perform a single
@@ -154,10 +155,10 @@ func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, t
// VerifyDuplicateVote verifies DuplicateVoteEvidence against the state of full node. This involves the
// following checks:
// - the validator is in the validator set at the height of the evidence
// - the height, round, type and validator address of the votes must be the same
// - the block ID's must be different
// - The signatures must both be valid
// - the validator is in the validator set at the height of the evidence
// - the height, round, type and validator address of the votes must be the same
// - the block ID's must be different
// - The signatures must both be valid
func VerifyDuplicateVote(e *types.DuplicateVoteEvidence, chainID string, valSet *types.ValidatorSet) error {
_, val := valSet.GetByAddress(e.VoteA.ValidatorAddress)
if val == nil {