mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-07 05:46:32 +00:00
evidence: remove ConflictingHeaders type (#5317)
## Description Remove ConflictingHeaders & compositeEvidence types Ref #5288
This commit is contained in:
@@ -6,11 +6,19 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
|
||||
## BREAKING CHANGES
|
||||
|
||||
- [crypto/secp256k1] \#5280 `secp256k1` has been removed from the Tendermint repo. (@marbar3778)
|
||||
|
||||
- CLI/RPC/Config
|
||||
- [config] \#5315 Rename `prof_laddr` to `pprof_laddr` and move it to `rpc` section (@melekes)
|
||||
- [rpc] \#5315 Remove `/unsafe_start_cpu_profiler`, `/unsafe_stop_cpu_profiler` and `/unsafe_write_heap_profile`. Please use pprof functionality instead (@melekes)
|
||||
- [config] \#5315 Rename `prof_laddr` to `pprof_laddr` and move it to `rpc` section (@melekes)
|
||||
- [rpc] \#5315 Remove `/unsafe_start_cpu_profiler`, `/unsafe_stop_cpu_profiler` and `/unsafe_write_heap_profile`. Please use pprof functionality instead (@melekes)
|
||||
|
||||
- Apps
|
||||
|
||||
- P2P Protocol
|
||||
|
||||
- Go API
|
||||
- [evidence] \#5317 Remove ConflictingHeaders evidence type & CompositeEvidence Interface. (@marbar3778)
|
||||
- [crypto/secp256k1] \#5280 `secp256k1` has been removed from the Tendermint repo. (@marbar3778)
|
||||
|
||||
- Blockchain Protocol
|
||||
|
||||
## FEATURES
|
||||
|
||||
|
||||
@@ -10,14 +10,11 @@ go) which operates both the sending and receiving of evidence.
|
||||
|
||||
The `Receive` function takes a list of evidence and does the following:
|
||||
|
||||
1. Breaks it down into individual evidence if it is `Composite Evidence`
|
||||
(see types/evidence.go#ConflictingHeadersEvidence)
|
||||
1. Checks that it does not already have the evidence stored
|
||||
|
||||
2. Checks that it does not already have the evidence stored
|
||||
2. Verifies the evidence against the node's state (see state/validation.go#VerifyEvidence)
|
||||
|
||||
3. Verifies the evidence against the node's state (see state/validation.go#VerifyEvidence)
|
||||
|
||||
4. Stores the evidence to a db and a concurrent list
|
||||
3. Stores the evidence to a db and a concurrent list
|
||||
|
||||
The gossiping of evidence is initiated when a peer is added which starts a go routine to broadcast currently
|
||||
uncommitted evidence at intervals of 60 seconds (set by the by broadcastEvidenceIntervalS).
|
||||
|
||||
125
evidence/pool.go
125
evidence/pool.go
@@ -142,93 +142,64 @@ func (evpool *Pool) AddPOLC(polc *types.ProofOfLockChange) error {
|
||||
return evpool.evidenceStore.Set(key, polcBytes)
|
||||
}
|
||||
|
||||
// AddEvidence checks the evidence is valid and adds it to the pool. If
|
||||
// evidence is composite (ConflictingHeadersEvidence), it will be broken up
|
||||
// into smaller pieces.
|
||||
func (evpool *Pool) AddEvidence(evidence types.Evidence) error {
|
||||
var evList = []types.Evidence{evidence}
|
||||
// AddEvidence checks the evidence is valid and adds it to the pool.
|
||||
func (evpool *Pool) AddEvidence(ev types.Evidence) error {
|
||||
evpool.logger.Debug("Attempting to add evidence", "ev", ev)
|
||||
|
||||
evpool.logger.Debug("Attempting to add evidence", "ev", evidence)
|
||||
|
||||
valSet, err := evpool.stateDB.LoadValidators(evidence.Height())
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't load validators at height #%d: %w", evidence.Height(), err)
|
||||
if evpool.Has(ev) {
|
||||
// if it is an amnesia evidence we have but POLC is not absent then
|
||||
// we should still process it else we loop to the next piece of evidence
|
||||
if ae, ok := ev.(*types.AmnesiaEvidence); !ok || ae.Polc.IsAbsent() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Break composite evidence into smaller pieces.
|
||||
if ce, ok := evidence.(types.CompositeEvidence); ok {
|
||||
evpool.logger.Info("Breaking up composite evidence", "ev", evidence)
|
||||
// 1) Verify against state.
|
||||
if err := evpool.verify(ev); err != nil {
|
||||
return types.NewErrEvidenceInvalid(ev, err)
|
||||
}
|
||||
|
||||
blockMeta := evpool.blockStore.LoadBlockMeta(evidence.Height())
|
||||
if blockMeta == nil {
|
||||
return fmt.Errorf("don't have block meta at height #%d", evidence.Height())
|
||||
}
|
||||
|
||||
if err := ce.VerifyComposite(&blockMeta.Header, valSet); err != nil {
|
||||
// For potential amnesia evidence, if this node is indicted it shall retrieve a polc
|
||||
// to form AmensiaEvidence else start the trial period for the piece of evidence
|
||||
if pe, ok := ev.(*types.PotentialAmnesiaEvidence); ok {
|
||||
if err := evpool.handleInboundPotentialAmnesiaEvidence(pe); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
evList = ce.Split(&blockMeta.Header, valSet)
|
||||
return nil
|
||||
} else if ae, ok := ev.(*types.AmnesiaEvidence); ok {
|
||||
// we have received an new amnesia evidence that we have never seen before so we must extract out the
|
||||
// potential amnesia evidence part and run our own trial
|
||||
if ae.Polc.IsAbsent() && ae.PotentialAmnesiaEvidence.VoteA.Round <
|
||||
ae.PotentialAmnesiaEvidence.VoteB.Round {
|
||||
if err := evpool.handleInboundPotentialAmnesiaEvidence(ae.PotentialAmnesiaEvidence); err != nil {
|
||||
return fmt.Errorf("failed to handle amnesia evidence, err: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// we are going to add this amnesia evidence as it's already punishable.
|
||||
// We also check if we already have an amnesia evidence or potential
|
||||
// amnesia evidence that addesses the same case that we will need to remove
|
||||
aeWithoutPolc := types.NewAmnesiaEvidence(ae.PotentialAmnesiaEvidence, types.NewEmptyPOLC())
|
||||
if evpool.IsPending(aeWithoutPolc) {
|
||||
evpool.removePendingEvidence(aeWithoutPolc)
|
||||
} else if evpool.IsOnTrial(ae.PotentialAmnesiaEvidence) {
|
||||
key := keyAwaitingTrial(ae.PotentialAmnesiaEvidence)
|
||||
if err := evpool.evidenceStore.Delete(key); err != nil {
|
||||
evpool.logger.Error("Failed to remove potential amnesia evidence from database", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, ev := range evList {
|
||||
|
||||
if evpool.Has(ev) {
|
||||
// if it is an amnesia evidence we have but POLC is not absent then
|
||||
// we should still process it else we loop to the next piece of evidence
|
||||
if ae, ok := ev.(*types.AmnesiaEvidence); !ok || ae.Polc.IsAbsent() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// 1) Verify against state.
|
||||
if err := evpool.verify(ev); err != nil {
|
||||
return types.NewErrEvidenceInvalid(ev, err)
|
||||
}
|
||||
|
||||
// For potential amnesia evidence, if this node is indicted it shall retrieve a polc
|
||||
// to form AmensiaEvidence else start the trial period for the piece of evidence
|
||||
if pe, ok := ev.(*types.PotentialAmnesiaEvidence); ok {
|
||||
if err := evpool.handleInboundPotentialAmnesiaEvidence(pe); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
} else if ae, ok := ev.(*types.AmnesiaEvidence); ok {
|
||||
// we have received an new amnesia evidence that we have never seen before so we must extract out the
|
||||
// potential amnesia evidence part and run our own trial
|
||||
if ae.Polc.IsAbsent() && ae.PotentialAmnesiaEvidence.VoteA.Round <
|
||||
ae.PotentialAmnesiaEvidence.VoteB.Round {
|
||||
if err := evpool.handleInboundPotentialAmnesiaEvidence(ae.PotentialAmnesiaEvidence); err != nil {
|
||||
return fmt.Errorf("failed to handle amnesia evidence, err: %w", err)
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
// we are going to add this amnesia evidence as it's already punishable.
|
||||
// We also check if we already have an amnesia evidence or potential
|
||||
// amnesia evidence that addesses the same case that we will need to remove
|
||||
aeWithoutPolc := types.NewAmnesiaEvidence(ae.PotentialAmnesiaEvidence, types.NewEmptyPOLC())
|
||||
if evpool.IsPending(aeWithoutPolc) {
|
||||
evpool.removePendingEvidence(aeWithoutPolc)
|
||||
} else if evpool.IsOnTrial(ae.PotentialAmnesiaEvidence) {
|
||||
key := keyAwaitingTrial(ae.PotentialAmnesiaEvidence)
|
||||
if err := evpool.evidenceStore.Delete(key); err != nil {
|
||||
evpool.logger.Error("Failed to remove potential amnesia evidence from database", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Save to store.
|
||||
if err := evpool.addPendingEvidence(ev); err != nil {
|
||||
return fmt.Errorf("database error when adding evidence: %v", err)
|
||||
}
|
||||
|
||||
// 3) Add evidence to clist.
|
||||
evpool.evidenceList.PushBack(ev)
|
||||
|
||||
evpool.logger.Info("Verified new evidence of byzantine behavior", "evidence", ev)
|
||||
// 2) Save to store.
|
||||
if err := evpool.addPendingEvidence(ev); err != nil {
|
||||
return fmt.Errorf("database error when adding evidence: %v", err)
|
||||
}
|
||||
|
||||
// 3) Add evidence to clist.
|
||||
evpool.evidenceList.PushBack(ev)
|
||||
|
||||
evpool.logger.Info("Verified new evidence of byzantine behavior", "evidence", ev)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -931,10 +931,7 @@ func (c *Client) compareNewHeaderWithWitnesses(l *types.LightBlock, now time.Tim
|
||||
defer c.providerMutex.Unlock()
|
||||
|
||||
// 1. Make sure AT LEAST ONE witness returns the same header.
|
||||
var (
|
||||
headerMatched bool
|
||||
lastErrConfHeaders error
|
||||
)
|
||||
var headerMatched bool
|
||||
for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ {
|
||||
if len(c.witnesses) == 0 {
|
||||
return errNoWitnesses{}
|
||||
@@ -955,10 +952,6 @@ func (c *Client) compareNewHeaderWithWitnesses(l *types.LightBlock, now time.Tim
|
||||
switch e := err.(type) {
|
||||
case nil: // at least one header matched
|
||||
headerMatched = true
|
||||
case ErrConflictingHeaders: // fork detected
|
||||
c.logger.Info("FORK DETECTED", "witness", e.Witness, "err", err)
|
||||
c.sendConflictingHeadersEvidence(&types.ConflictingHeadersEvidence{H1: e.H1, H2: e.H2})
|
||||
lastErrConfHeaders = e
|
||||
case errBadWitness:
|
||||
c.logger.Info("Bad witness", "witness", c.witnesses[e.WitnessIndex], "err", err)
|
||||
// if witness sent us invalid header / vals, remove it
|
||||
@@ -973,11 +966,7 @@ func (c *Client) compareNewHeaderWithWitnesses(l *types.LightBlock, now time.Tim
|
||||
c.removeWitness(idx)
|
||||
}
|
||||
|
||||
if lastErrConfHeaders != nil {
|
||||
// NOTE: all of the potential forks will be reported, but we only return
|
||||
// the last ErrConflictingHeaders error here.
|
||||
return lastErrConfHeaders
|
||||
} else if headerMatched {
|
||||
if headerMatched {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1003,7 +992,6 @@ func (c *Client) compareNewHeaderWithWitness(errc chan error, l *types.LightBloc
|
||||
errc <- errBadWitness{bsErr, invalidLightBlock, witnessIndex}
|
||||
return
|
||||
}
|
||||
errc <- ErrConflictingHeaders{H1: l.SignedHeader, Primary: c.primary, H2: altBlock.SignedHeader, Witness: witness}
|
||||
}
|
||||
|
||||
errc <- nil
|
||||
@@ -1120,25 +1108,6 @@ func (c *Client) validateLightBlock(l *types.LightBlock, expectedHeight int64) e
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendConflictingHeadersEvidence sends evidence to all witnesses and primary
|
||||
// on best effort basis.
|
||||
//
|
||||
// Evidence needs to be submitted to all full nodes since there's no way to
|
||||
// determine which full node is correct (honest).
|
||||
func (c *Client) sendConflictingHeadersEvidence(ev *types.ConflictingHeadersEvidence) {
|
||||
err := c.primary.ReportEvidence(ev)
|
||||
if err != nil {
|
||||
c.logger.Error("Failed to report evidence to primary", "ev", ev, "primary", c.primary)
|
||||
}
|
||||
|
||||
for _, w := range c.witnesses {
|
||||
err := w.ReportEvidence(ev)
|
||||
if err != nil {
|
||||
c.logger.Error("Failed to report evidence to witness", "ev", ev, "witness", w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exponential backoff (with jitter)
|
||||
// 0.5s -> 2s -> 4.5s -> 8s -> 12.5 with 1s variation
|
||||
func backoffTimeout(attempt uint16) time.Duration {
|
||||
|
||||
@@ -973,46 +973,6 @@ func TestClient_TrustedValidatorSet(t *testing.T) {
|
||||
assert.Equal(t, 1, len(c.Witnesses()))
|
||||
}
|
||||
|
||||
func TestClientReportsConflictingHeadersEvidence(t *testing.T) {
|
||||
// fullNode2 sends us different header
|
||||
altH2 := keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals,
|
||||
hash("app_hash2"), hash("cons_hash"), hash("results_hash"),
|
||||
0, len(keys), types.BlockID{Hash: h1.Hash()})
|
||||
fullNode2 := mockp.New(
|
||||
chainID,
|
||||
map[int64]*types.SignedHeader{
|
||||
1: h1,
|
||||
2: altH2,
|
||||
},
|
||||
map[int64]*types.ValidatorSet{
|
||||
1: vals,
|
||||
2: vals,
|
||||
},
|
||||
)
|
||||
|
||||
c, err := light.NewClient(
|
||||
chainID,
|
||||
trustOptions,
|
||||
fullNode,
|
||||
[]provider.Provider{fullNode2},
|
||||
dbs.New(dbm.NewMemDB(), chainID),
|
||||
light.Logger(log.TestingLogger()),
|
||||
light.MaxRetryAttempts(1),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check verification returns an error.
|
||||
_, err = c.VerifyLightBlockAtHeight(2, bTime.Add(2*time.Hour))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "does not match one")
|
||||
}
|
||||
|
||||
// Check evidence was sent to both full nodes.
|
||||
ev := &types.ConflictingHeadersEvidence{H1: h2, H2: altH2}
|
||||
assert.True(t, fullNode2.HasEvidence(ev))
|
||||
assert.True(t, fullNode.HasEvidence(ev))
|
||||
}
|
||||
|
||||
func TestClientPrunesHeadersAndValidatorSets(t *testing.T) {
|
||||
c, err := light.NewClient(
|
||||
chainID,
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/light/provider"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
@@ -40,22 +39,6 @@ func (e ErrInvalidHeader) Error() string {
|
||||
return fmt.Sprintf("invalid header: %v", e.Reason)
|
||||
}
|
||||
|
||||
// ErrConflictingHeaders is thrown when two conflicting headers are discovered.
|
||||
type ErrConflictingHeaders struct {
|
||||
H1 *types.SignedHeader
|
||||
Primary provider.Provider
|
||||
|
||||
H2 *types.SignedHeader
|
||||
Witness provider.Provider
|
||||
}
|
||||
|
||||
func (e ErrConflictingHeaders) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"header hash %X from primary %v does not match one %X from witness %v",
|
||||
e.H1.Hash(), e.Primary,
|
||||
e.H2.Hash(), e.Witness)
|
||||
}
|
||||
|
||||
// ErrVerificationFailed means either sequential or skipping verification has
|
||||
// failed to verify from header #1 to header #2 due to some reason.
|
||||
type ErrVerificationFailed struct {
|
||||
|
||||
@@ -210,58 +210,6 @@ func (m *AmnesiaEvidence) GetPolc() *ProofOfLockChange {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ConflictingHeadersEvidence struct {
|
||||
H1 *SignedHeader `protobuf:"bytes,1,opt,name=h1,proto3" json:"h1,omitempty"`
|
||||
H2 *SignedHeader `protobuf:"bytes,2,opt,name=h2,proto3" json:"h2,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ConflictingHeadersEvidence) Reset() { *m = ConflictingHeadersEvidence{} }
|
||||
func (m *ConflictingHeadersEvidence) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConflictingHeadersEvidence) ProtoMessage() {}
|
||||
func (*ConflictingHeadersEvidence) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_6825fabc78e0a168, []int{3}
|
||||
}
|
||||
func (m *ConflictingHeadersEvidence) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *ConflictingHeadersEvidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_ConflictingHeadersEvidence.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *ConflictingHeadersEvidence) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ConflictingHeadersEvidence.Merge(m, src)
|
||||
}
|
||||
func (m *ConflictingHeadersEvidence) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *ConflictingHeadersEvidence) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ConflictingHeadersEvidence.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ConflictingHeadersEvidence proto.InternalMessageInfo
|
||||
|
||||
func (m *ConflictingHeadersEvidence) GetH1() *SignedHeader {
|
||||
if m != nil {
|
||||
return m.H1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ConflictingHeadersEvidence) GetH2() *SignedHeader {
|
||||
if m != nil {
|
||||
return m.H2
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type LunaticValidatorEvidence struct {
|
||||
Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
|
||||
Vote *Vote `protobuf:"bytes,2,opt,name=vote,proto3" json:"vote,omitempty"`
|
||||
@@ -273,7 +221,7 @@ func (m *LunaticValidatorEvidence) Reset() { *m = LunaticValidatorEviden
|
||||
func (m *LunaticValidatorEvidence) String() string { return proto.CompactTextString(m) }
|
||||
func (*LunaticValidatorEvidence) ProtoMessage() {}
|
||||
func (*LunaticValidatorEvidence) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_6825fabc78e0a168, []int{4}
|
||||
return fileDescriptor_6825fabc78e0a168, []int{3}
|
||||
}
|
||||
func (m *LunaticValidatorEvidence) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -333,7 +281,6 @@ func (m *LunaticValidatorEvidence) GetTimestamp() time.Time {
|
||||
type Evidence struct {
|
||||
// Types that are valid to be assigned to Sum:
|
||||
// *Evidence_DuplicateVoteEvidence
|
||||
// *Evidence_ConflictingHeadersEvidence
|
||||
// *Evidence_LunaticValidatorEvidence
|
||||
// *Evidence_PotentialAmnesiaEvidence
|
||||
// *Evidence_AmnesiaEvidence
|
||||
@@ -344,7 +291,7 @@ func (m *Evidence) Reset() { *m = Evidence{} }
|
||||
func (m *Evidence) String() string { return proto.CompactTextString(m) }
|
||||
func (*Evidence) ProtoMessage() {}
|
||||
func (*Evidence) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_6825fabc78e0a168, []int{5}
|
||||
return fileDescriptor_6825fabc78e0a168, []int{4}
|
||||
}
|
||||
func (m *Evidence) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -382,9 +329,6 @@ type isEvidence_Sum interface {
|
||||
type Evidence_DuplicateVoteEvidence struct {
|
||||
DuplicateVoteEvidence *DuplicateVoteEvidence `protobuf:"bytes,1,opt,name=duplicate_vote_evidence,json=duplicateVoteEvidence,proto3,oneof" json:"duplicate_vote_evidence,omitempty"`
|
||||
}
|
||||
type Evidence_ConflictingHeadersEvidence struct {
|
||||
ConflictingHeadersEvidence *ConflictingHeadersEvidence `protobuf:"bytes,2,opt,name=conflicting_headers_evidence,json=conflictingHeadersEvidence,proto3,oneof" json:"conflicting_headers_evidence,omitempty"`
|
||||
}
|
||||
type Evidence_LunaticValidatorEvidence struct {
|
||||
LunaticValidatorEvidence *LunaticValidatorEvidence `protobuf:"bytes,3,opt,name=lunatic_validator_evidence,json=lunaticValidatorEvidence,proto3,oneof" json:"lunatic_validator_evidence,omitempty"`
|
||||
}
|
||||
@@ -395,11 +339,10 @@ type Evidence_AmnesiaEvidence struct {
|
||||
AmnesiaEvidence *AmnesiaEvidence `protobuf:"bytes,5,opt,name=amnesia_evidence,json=amnesiaEvidence,proto3,oneof" json:"amnesia_evidence,omitempty"`
|
||||
}
|
||||
|
||||
func (*Evidence_DuplicateVoteEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_ConflictingHeadersEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_LunaticValidatorEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_PotentialAmnesiaEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_AmnesiaEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_DuplicateVoteEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_LunaticValidatorEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_PotentialAmnesiaEvidence) isEvidence_Sum() {}
|
||||
func (*Evidence_AmnesiaEvidence) isEvidence_Sum() {}
|
||||
|
||||
func (m *Evidence) GetSum() isEvidence_Sum {
|
||||
if m != nil {
|
||||
@@ -415,13 +358,6 @@ func (m *Evidence) GetDuplicateVoteEvidence() *DuplicateVoteEvidence {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Evidence) GetConflictingHeadersEvidence() *ConflictingHeadersEvidence {
|
||||
if x, ok := m.GetSum().(*Evidence_ConflictingHeadersEvidence); ok {
|
||||
return x.ConflictingHeadersEvidence
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Evidence) GetLunaticValidatorEvidence() *LunaticValidatorEvidence {
|
||||
if x, ok := m.GetSum().(*Evidence_LunaticValidatorEvidence); ok {
|
||||
return x.LunaticValidatorEvidence
|
||||
@@ -447,7 +383,6 @@ func (m *Evidence) GetAmnesiaEvidence() *AmnesiaEvidence {
|
||||
func (*Evidence) XXX_OneofWrappers() []interface{} {
|
||||
return []interface{}{
|
||||
(*Evidence_DuplicateVoteEvidence)(nil),
|
||||
(*Evidence_ConflictingHeadersEvidence)(nil),
|
||||
(*Evidence_LunaticValidatorEvidence)(nil),
|
||||
(*Evidence_PotentialAmnesiaEvidence)(nil),
|
||||
(*Evidence_AmnesiaEvidence)(nil),
|
||||
@@ -464,7 +399,7 @@ func (m *EvidenceData) Reset() { *m = EvidenceData{} }
|
||||
func (m *EvidenceData) String() string { return proto.CompactTextString(m) }
|
||||
func (*EvidenceData) ProtoMessage() {}
|
||||
func (*EvidenceData) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_6825fabc78e0a168, []int{6}
|
||||
return fileDescriptor_6825fabc78e0a168, []int{5}
|
||||
}
|
||||
func (m *EvidenceData) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -516,7 +451,7 @@ func (m *ProofOfLockChange) Reset() { *m = ProofOfLockChange{} }
|
||||
func (m *ProofOfLockChange) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProofOfLockChange) ProtoMessage() {}
|
||||
func (*ProofOfLockChange) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_6825fabc78e0a168, []int{7}
|
||||
return fileDescriptor_6825fabc78e0a168, []int{6}
|
||||
}
|
||||
func (m *ProofOfLockChange) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -563,7 +498,6 @@ func init() {
|
||||
proto.RegisterType((*DuplicateVoteEvidence)(nil), "tendermint.types.DuplicateVoteEvidence")
|
||||
proto.RegisterType((*PotentialAmnesiaEvidence)(nil), "tendermint.types.PotentialAmnesiaEvidence")
|
||||
proto.RegisterType((*AmnesiaEvidence)(nil), "tendermint.types.AmnesiaEvidence")
|
||||
proto.RegisterType((*ConflictingHeadersEvidence)(nil), "tendermint.types.ConflictingHeadersEvidence")
|
||||
proto.RegisterType((*LunaticValidatorEvidence)(nil), "tendermint.types.LunaticValidatorEvidence")
|
||||
proto.RegisterType((*Evidence)(nil), "tendermint.types.Evidence")
|
||||
proto.RegisterType((*EvidenceData)(nil), "tendermint.types.EvidenceData")
|
||||
@@ -573,52 +507,48 @@ func init() {
|
||||
func init() { proto.RegisterFile("tendermint/types/evidence.proto", fileDescriptor_6825fabc78e0a168) }
|
||||
|
||||
var fileDescriptor_6825fabc78e0a168 = []byte{
|
||||
// 710 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xc1, 0x4e, 0xdb, 0x4a,
|
||||
0x14, 0xb5, 0x89, 0xc9, 0x83, 0x01, 0x09, 0x9e, 0x05, 0xef, 0x59, 0x16, 0x72, 0x4a, 0xba, 0x68,
|
||||
0x85, 0xa8, 0x0d, 0x54, 0x15, 0x9b, 0x6e, 0x08, 0xb4, 0x8a, 0x04, 0x6a, 0xa9, 0xa9, 0x58, 0x74,
|
||||
0xe3, 0x8e, 0xed, 0x89, 0x3d, 0xe0, 0x78, 0xac, 0x78, 0x1c, 0x35, 0x52, 0xbf, 0xa1, 0xe2, 0x63,
|
||||
0xba, 0xe9, 0x1f, 0xb0, 0x64, 0xd9, 0x55, 0xa9, 0x60, 0xdf, 0x6f, 0xa8, 0x3c, 0x1e, 0xdb, 0x10,
|
||||
0xc7, 0xa0, 0x56, 0x55, 0x37, 0x91, 0x33, 0xf7, 0xdc, 0x7b, 0xee, 0x99, 0x39, 0x77, 0x06, 0xb4,
|
||||
0x28, 0x0a, 0x5d, 0x34, 0xe8, 0xe3, 0x90, 0x1a, 0x74, 0x14, 0xa1, 0xd8, 0x40, 0x43, 0xec, 0xa2,
|
||||
0xd0, 0x41, 0x7a, 0x34, 0x20, 0x94, 0xc8, 0x8b, 0x25, 0x40, 0x67, 0x00, 0x75, 0xc9, 0x23, 0x1e,
|
||||
0x61, 0x41, 0x23, 0xfd, 0xca, 0x70, 0x6a, 0xcb, 0x23, 0xc4, 0x0b, 0x90, 0xc1, 0xfe, 0xd9, 0x49,
|
||||
0xcf, 0xa0, 0xb8, 0x8f, 0x62, 0x0a, 0xfb, 0x11, 0x07, 0xac, 0x54, 0x98, 0xd8, 0xef, 0x84, 0xa8,
|
||||
0x33, 0x18, 0x45, 0x94, 0x18, 0xa7, 0x68, 0xc4, 0xa3, 0xed, 0x2f, 0x22, 0x58, 0xde, 0x4b, 0xa2,
|
||||
0x00, 0x3b, 0x90, 0xa2, 0x63, 0x42, 0xd1, 0x0b, 0xde, 0xa4, 0xfc, 0x04, 0x34, 0x87, 0x84, 0x22,
|
||||
0x0b, 0x2a, 0xe2, 0x03, 0xf1, 0xf1, 0xdc, 0xd6, 0x7f, 0xfa, 0x78, 0xbf, 0x7a, 0x8a, 0x37, 0xa7,
|
||||
0x53, 0xd4, 0x4e, 0x01, 0xb7, 0x95, 0xa9, 0xfb, 0xe1, 0x1d, 0xb9, 0x03, 0x66, 0x0b, 0x19, 0x4a,
|
||||
0x83, 0x65, 0xa8, 0x7a, 0x26, 0x54, 0xcf, 0x85, 0xea, 0x6f, 0x73, 0x44, 0x67, 0xe6, 0xfc, 0x5b,
|
||||
0x4b, 0x38, 0xbb, 0x6c, 0x89, 0x66, 0x99, 0xd6, 0xbe, 0x14, 0x81, 0x72, 0x48, 0x28, 0x0a, 0x29,
|
||||
0x86, 0xc1, 0x4e, 0x3f, 0x44, 0x31, 0x86, 0x7f, 0xa9, 0xfd, 0x55, 0x30, 0xef, 0x23, 0xec, 0xf9,
|
||||
0xd4, 0x2a, 0x15, 0x34, 0xcc, 0xb9, 0x6c, 0xed, 0x28, 0x5d, 0xba, 0xad, 0x50, 0xfa, 0x3d, 0x85,
|
||||
0x9f, 0x45, 0xb0, 0x30, 0x2e, 0xcc, 0x07, 0x6a, 0x94, 0x8b, 0xb6, 0x60, 0x16, 0xb4, 0x72, 0x6b,
|
||||
0x71, 0xb1, 0x6b, 0xd5, 0xee, 0xeb, 0x36, 0xca, 0x54, 0xa2, 0xba, 0x2d, 0xdc, 0x06, 0x52, 0x44,
|
||||
0x02, 0x87, 0xef, 0xc8, 0xc3, 0x09, 0x35, 0x07, 0x84, 0xf4, 0x5e, 0xf7, 0x0e, 0x88, 0x73, 0xba,
|
||||
0xeb, 0xc3, 0xd0, 0x43, 0x26, 0x4b, 0x68, 0x7f, 0x04, 0xea, 0x2e, 0x09, 0x7b, 0x01, 0x76, 0x28,
|
||||
0x0e, 0xbd, 0x2e, 0x82, 0x2e, 0x1a, 0xc4, 0x45, 0x59, 0x1d, 0x4c, 0xf9, 0x9b, 0xbc, 0x51, 0xad,
|
||||
0x5a, 0xf4, 0x08, 0x7b, 0x21, 0x72, 0xb3, 0x24, 0x73, 0xca, 0xdf, 0x64, 0xf8, 0x2d, 0xde, 0xc4,
|
||||
0xfd, 0xf8, 0xad, 0xf6, 0x0f, 0x11, 0x28, 0x07, 0x49, 0x08, 0x29, 0x76, 0x8e, 0x61, 0x80, 0x5d,
|
||||
0x48, 0xc9, 0xa0, 0x20, 0xdf, 0x00, 0x4d, 0x9f, 0x41, 0x79, 0x03, 0x4a, 0xb5, 0x20, 0x2f, 0xc5,
|
||||
0x71, 0xf2, 0x1a, 0x90, 0xd2, 0x33, 0xbf, 0xc7, 0x17, 0x0c, 0x23, 0x6f, 0x80, 0x25, 0x1c, 0x0e,
|
||||
0x53, 0x52, 0x2b, 0xcb, 0xb6, 0x7a, 0x18, 0x05, 0x2e, 0xb3, 0xc7, 0xac, 0x29, 0xf3, 0x58, 0x46,
|
||||
0xf0, 0x32, 0x8d, 0xfc, 0x11, 0x97, 0x7c, 0x92, 0xc0, 0x4c, 0x21, 0x10, 0x82, 0xff, 0xdd, 0x7c,
|
||||
0x9e, 0x2d, 0x66, 0xe9, 0x31, 0x6f, 0x3c, 0xaa, 0x2a, 0x98, 0x78, 0x01, 0x74, 0x05, 0x73, 0xd9,
|
||||
0x9d, 0x78, 0x33, 0x44, 0x60, 0xc5, 0x29, 0x8f, 0x97, 0x2b, 0x8d, 0x4b, 0x9e, 0x6c, 0xa7, 0xd6,
|
||||
0xab, 0x3c, 0xf5, 0xa6, 0xe8, 0x0a, 0xa6, 0xea, 0xd4, 0x5b, 0xe6, 0x04, 0xa8, 0x41, 0x76, 0xa2,
|
||||
0xd6, 0x30, 0x3f, 0xd2, 0x92, 0xaf, 0x51, 0xe7, 0xf9, 0x3a, 0x17, 0x74, 0x05, 0x53, 0x09, 0xea,
|
||||
0x1c, 0x72, 0x72, 0xe7, 0x7c, 0x49, 0xbf, 0x3a, 0x5f, 0x29, 0x57, 0xed, 0x84, 0xbd, 0x02, 0x8b,
|
||||
0x15, 0x86, 0x69, 0xc6, 0xb0, 0x5a, 0x65, 0xa8, 0x16, 0x5e, 0x80, 0xb7, 0x97, 0x3a, 0xd3, 0xa0,
|
||||
0x11, 0x27, 0xfd, 0xf6, 0x7b, 0x30, 0x9f, 0x2f, 0xed, 0x41, 0x0a, 0xe5, 0xe7, 0x60, 0xe6, 0x86,
|
||||
0x09, 0x1a, 0xcc, 0x63, 0x95, 0xf2, 0x45, 0x11, 0x29, 0xf5, 0x98, 0x59, 0x64, 0xc8, 0x32, 0x90,
|
||||
0x7c, 0x18, 0xfb, 0xec, 0x58, 0xe7, 0x4d, 0xf6, 0xdd, 0xfe, 0x00, 0xfe, 0xad, 0x0c, 0xbf, 0xbc,
|
||||
0x0e, 0xd8, 0xed, 0x18, 0x73, 0x8e, 0x3b, 0xaf, 0xd0, 0x58, 0x7e, 0x06, 0xfe, 0x89, 0x12, 0xdb,
|
||||
0x3a, 0x45, 0x23, 0x6e, 0x98, 0x95, 0x9b, 0xf8, 0xec, 0xa5, 0xd2, 0x0f, 0x13, 0x3b, 0xc0, 0xce,
|
||||
0x3e, 0x1a, 0x99, 0xcd, 0x28, 0xb1, 0xf7, 0xd1, 0xa8, 0xf3, 0xe6, 0xfc, 0x4a, 0x13, 0x2f, 0xae,
|
||||
0x34, 0xf1, 0xfb, 0x95, 0x26, 0x9e, 0x5d, 0x6b, 0xc2, 0xc5, 0xb5, 0x26, 0x7c, 0xbd, 0xd6, 0x84,
|
||||
0x77, 0xdb, 0x1e, 0xa6, 0x7e, 0x62, 0xeb, 0x0e, 0xe9, 0x1b, 0x37, 0x5f, 0xc4, 0xf2, 0x33, 0x7b,
|
||||
0x5a, 0xc7, 0x5f, 0x4b, 0xbb, 0xc9, 0xd6, 0x9f, 0xfe, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x84, 0x99,
|
||||
0x61, 0x70, 0xb2, 0x07, 0x00, 0x00,
|
||||
// 641 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4f, 0x4f, 0xd4, 0x40,
|
||||
0x14, 0xdf, 0xba, 0xcb, 0x0a, 0x0f, 0x12, 0xb0, 0x01, 0x6d, 0x36, 0x64, 0x57, 0xd6, 0x83, 0x86,
|
||||
0x68, 0x4b, 0x34, 0x86, 0x8b, 0x17, 0x56, 0x34, 0x24, 0x10, 0xc5, 0xd1, 0x70, 0xf0, 0x52, 0xa7,
|
||||
0xed, 0x6c, 0x3b, 0xd0, 0x76, 0x9a, 0x76, 0xba, 0xb1, 0xdf, 0x82, 0x0f, 0xe0, 0xc7, 0xf0, 0xe2,
|
||||
0x37, 0xe0, 0xc8, 0xd1, 0x93, 0x18, 0xb8, 0xfb, 0x19, 0x4c, 0xa7, 0x7f, 0x16, 0xb6, 0x5b, 0x88,
|
||||
0xc6, 0x78, 0xd9, 0x74, 0xdf, 0xfb, 0xbd, 0x3f, 0xbf, 0xf7, 0x7b, 0x33, 0x03, 0x3d, 0x4e, 0x7c,
|
||||
0x8b, 0x84, 0x1e, 0xf5, 0xb9, 0xc6, 0x93, 0x80, 0x44, 0x1a, 0x19, 0x51, 0x8b, 0xf8, 0x26, 0x51,
|
||||
0x83, 0x90, 0x71, 0x26, 0x2f, 0x8d, 0x01, 0xaa, 0x00, 0x74, 0x96, 0x6d, 0x66, 0x33, 0xe1, 0xd4,
|
||||
0xd2, 0xaf, 0x0c, 0xd7, 0xe9, 0xd9, 0x8c, 0xd9, 0x2e, 0xd1, 0xc4, 0x3f, 0x23, 0x1e, 0x6a, 0x9c,
|
||||
0x7a, 0x24, 0xe2, 0xd8, 0x0b, 0x72, 0xc0, 0x6a, 0xa5, 0x92, 0xf8, 0x9d, 0xe2, 0x35, 0xc3, 0x24,
|
||||
0xe0, 0x4c, 0x3b, 0x22, 0x49, 0xee, 0xed, 0x7f, 0x93, 0x60, 0x65, 0x3b, 0x0e, 0x5c, 0x6a, 0x62,
|
||||
0x4e, 0x0e, 0x18, 0x27, 0xaf, 0xf2, 0x26, 0xe5, 0x27, 0xd0, 0x1e, 0x31, 0x4e, 0x74, 0xac, 0x48,
|
||||
0xf7, 0xa5, 0x47, 0xf3, 0x4f, 0xef, 0xaa, 0x93, 0xfd, 0xaa, 0x29, 0x1e, 0xcd, 0xa4, 0xa8, 0xad,
|
||||
0x12, 0x6e, 0x28, 0xb7, 0x6e, 0x86, 0x0f, 0xe4, 0x01, 0xcc, 0x95, 0x34, 0x94, 0xa6, 0x88, 0xe8,
|
||||
0xa8, 0x19, 0x51, 0xb5, 0x20, 0xaa, 0x7e, 0x28, 0x10, 0x83, 0xd9, 0x93, 0x1f, 0xbd, 0xc6, 0xf1,
|
||||
0x59, 0x4f, 0x42, 0xe3, 0xb0, 0xfe, 0x99, 0x04, 0xca, 0x3e, 0xe3, 0xc4, 0xe7, 0x14, 0xbb, 0x5b,
|
||||
0x9e, 0x4f, 0x22, 0x8a, 0xff, 0x53, 0xfb, 0x6b, 0xb0, 0xe0, 0x10, 0x6a, 0x3b, 0x5c, 0x1f, 0x33,
|
||||
0x68, 0xa2, 0xf9, 0xcc, 0xf6, 0x3e, 0x35, 0x5d, 0x65, 0xd8, 0xfa, 0x3b, 0x86, 0x5f, 0x25, 0x58,
|
||||
0x9c, 0x24, 0xe6, 0x40, 0x27, 0x28, 0x48, 0xeb, 0x38, 0x73, 0xea, 0xc5, 0x6a, 0xe5, 0x64, 0xd7,
|
||||
0xab, 0xdd, 0xd7, 0x0d, 0x0a, 0x29, 0x41, 0xdd, 0x08, 0x37, 0xa1, 0x15, 0x30, 0xd7, 0xcc, 0x27,
|
||||
0xf2, 0x60, 0x4a, 0xce, 0x90, 0xb1, 0xe1, 0xdb, 0xe1, 0x1e, 0x33, 0x8f, 0x5e, 0x3a, 0xd8, 0xb7,
|
||||
0x09, 0x12, 0x01, 0xfd, 0x5f, 0x12, 0x28, 0x7b, 0xb1, 0x8f, 0x39, 0x35, 0x0f, 0xb0, 0x4b, 0x2d,
|
||||
0xcc, 0x59, 0x58, 0x66, 0xdd, 0x80, 0xb6, 0x43, 0xb0, 0x45, 0xc2, 0xbc, 0x57, 0xa5, 0x9a, 0x77,
|
||||
0x47, 0xf8, 0x51, 0x8e, 0x93, 0xd7, 0xa1, 0x95, 0x4e, 0xfd, 0x06, 0x65, 0x04, 0x46, 0xde, 0x80,
|
||||
0x65, 0xea, 0x8f, 0xd2, 0xa2, 0x7a, 0x16, 0xad, 0x0f, 0x29, 0x71, 0x2d, 0x21, 0xd0, 0x1c, 0x92,
|
||||
0x73, 0x5f, 0x56, 0xe0, 0x75, 0xea, 0xf9, 0x27, 0x3a, 0x7d, 0x69, 0xc2, 0x6c, 0x49, 0x10, 0xc3,
|
||||
0x3d, 0xab, 0x38, 0x51, 0xba, 0x58, 0xaa, 0x09, 0x75, 0x1e, 0x56, 0x19, 0x4c, 0x3d, 0x82, 0x3b,
|
||||
0x0d, 0xb4, 0x62, 0x4d, 0x3d, 0x9b, 0x87, 0xd0, 0x71, 0xb3, 0xf9, 0xea, 0xa3, 0x62, 0xc0, 0xe3,
|
||||
0x2a, 0xcd, 0xba, 0x1d, 0xa8, 0xd3, 0x64, 0xa7, 0x81, 0x14, 0xb7, 0x4e, 0xaf, 0xc3, 0x6b, 0xf7,
|
||||
0xad, 0xf5, 0xa7, 0xfb, 0x96, 0xd6, 0xaa, 0xdd, 0xb8, 0x37, 0xb0, 0x54, 0xa9, 0x30, 0x23, 0x2a,
|
||||
0xac, 0x55, 0x2b, 0x54, 0x13, 0x2f, 0xe2, 0xab, 0xa6, 0xc1, 0x0c, 0x34, 0xa3, 0xd8, 0xeb, 0x7f,
|
||||
0x82, 0x85, 0xc2, 0xb4, 0x8d, 0x39, 0x96, 0x5f, 0xc0, 0xec, 0x25, 0x49, 0x9a, 0x42, 0xf1, 0x4a,
|
||||
0xfa, 0x32, 0x49, 0x2b, 0x55, 0x1c, 0x95, 0x11, 0xb2, 0x0c, 0x2d, 0x07, 0x47, 0x8e, 0x58, 0xc7,
|
||||
0x05, 0x24, 0xbe, 0xfb, 0x9f, 0xe1, 0x4e, 0xe5, 0x30, 0xc8, 0x8f, 0x41, 0xdc, 0x16, 0x51, 0x5e,
|
||||
0xe3, 0xda, 0x2b, 0x25, 0x92, 0x9f, 0xc3, 0xed, 0x20, 0x36, 0xf4, 0x23, 0x92, 0xe4, 0x8b, 0xbe,
|
||||
0x7a, 0x19, 0x9f, 0xdd, 0xdc, 0xea, 0x7e, 0x6c, 0xb8, 0xd4, 0xdc, 0x25, 0x09, 0x6a, 0x07, 0xb1,
|
||||
0xb1, 0x4b, 0x92, 0xc1, 0xbb, 0x93, 0xf3, 0xae, 0x74, 0x7a, 0xde, 0x95, 0x7e, 0x9e, 0x77, 0xa5,
|
||||
0xe3, 0x8b, 0x6e, 0xe3, 0xf4, 0xa2, 0xdb, 0xf8, 0x7e, 0xd1, 0x6d, 0x7c, 0xdc, 0xb4, 0x29, 0x77,
|
||||
0x62, 0x43, 0x35, 0x99, 0xa7, 0x5d, 0x7e, 0x21, 0xc6, 0x9f, 0xd9, 0x53, 0x33, 0xf9, 0x7a, 0x18,
|
||||
0x6d, 0x61, 0x7f, 0xf6, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x2a, 0xcf, 0x0c, 0xc2, 0x06, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
func (m *DuplicateVoteEvidence) Marshal() (dAtA []byte, err error) {
|
||||
@@ -783,53 +713,6 @@ func (m *AmnesiaEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *ConflictingHeadersEvidence) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ConflictingHeadersEvidence) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *ConflictingHeadersEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.H2 != nil {
|
||||
{
|
||||
size, err := m.H2.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintEvidence(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.H1 != nil {
|
||||
{
|
||||
size, err := m.H1.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintEvidence(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *LunaticValidatorEvidence) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
@@ -850,12 +733,12 @@ func (m *LunaticValidatorEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
n11, err11 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp):])
|
||||
if err11 != nil {
|
||||
return 0, err11
|
||||
n9, err9 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp):])
|
||||
if err9 != nil {
|
||||
return 0, err9
|
||||
}
|
||||
i -= n11
|
||||
i = encodeVarintEvidence(dAtA, i, uint64(n11))
|
||||
i -= n9
|
||||
i = encodeVarintEvidence(dAtA, i, uint64(n9))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
if len(m.InvalidHeaderField) > 0 {
|
||||
@@ -945,27 +828,6 @@ func (m *Evidence_DuplicateVoteEvidence) MarshalToSizedBuffer(dAtA []byte) (int,
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
func (m *Evidence_ConflictingHeadersEvidence) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Evidence_ConflictingHeadersEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
if m.ConflictingHeadersEvidence != nil {
|
||||
{
|
||||
size, err := m.ConflictingHeadersEvidence.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintEvidence(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
func (m *Evidence_LunaticValidatorEvidence) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
@@ -1191,23 +1053,6 @@ func (m *AmnesiaEvidence) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ConflictingHeadersEvidence) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.H1 != nil {
|
||||
l = m.H1.Size()
|
||||
n += 1 + l + sovEvidence(uint64(l))
|
||||
}
|
||||
if m.H2 != nil {
|
||||
l = m.H2.Size()
|
||||
n += 1 + l + sovEvidence(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *LunaticValidatorEvidence) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -1255,18 +1100,6 @@ func (m *Evidence_DuplicateVoteEvidence) Size() (n int) {
|
||||
}
|
||||
return n
|
||||
}
|
||||
func (m *Evidence_ConflictingHeadersEvidence) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.ConflictingHeadersEvidence != nil {
|
||||
l = m.ConflictingHeadersEvidence.Size()
|
||||
n += 1 + l + sovEvidence(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
func (m *Evidence_LunaticValidatorEvidence) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -1807,131 +1640,6 @@ func (m *AmnesiaEvidence) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ConflictingHeadersEvidence) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEvidence
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ConflictingHeadersEvidence: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ConflictingHeadersEvidence: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field H1", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEvidence
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.H1 == nil {
|
||||
m.H1 = &SignedHeader{}
|
||||
}
|
||||
if err := m.H1.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field H2", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEvidence
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.H2 == nil {
|
||||
m.H2 = &SignedHeader{}
|
||||
}
|
||||
if err := m.H2.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipEvidence(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *LunaticValidatorEvidence) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
@@ -2186,41 +1894,6 @@ func (m *Evidence) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
m.Sum = &Evidence_DuplicateVoteEvidence{v}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ConflictingHeadersEvidence", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEvidence
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEvidence
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
v := &ConflictingHeadersEvidence{}
|
||||
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Sum = &Evidence_ConflictingHeadersEvidence{v}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LunaticValidatorEvidence", wireType)
|
||||
|
||||
@@ -13,18 +13,18 @@ import "tendermint/crypto/keys.proto";
|
||||
message DuplicateVoteEvidence {
|
||||
Vote vote_a = 1;
|
||||
Vote vote_b = 2;
|
||||
|
||||
|
||||
google.protobuf.Timestamp timestamp = 3
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
}
|
||||
|
||||
message PotentialAmnesiaEvidence {
|
||||
Vote vote_a = 1;
|
||||
Vote vote_b = 2;
|
||||
|
||||
int64 height_stamp = 3;
|
||||
google.protobuf.Timestamp timestamp = 4
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
int64 height_stamp = 3;
|
||||
google.protobuf.Timestamp timestamp = 4
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
}
|
||||
|
||||
message AmnesiaEvidence {
|
||||
@@ -32,27 +32,21 @@ message AmnesiaEvidence {
|
||||
ProofOfLockChange polc = 2;
|
||||
}
|
||||
|
||||
message ConflictingHeadersEvidence {
|
||||
SignedHeader h1 = 1;
|
||||
SignedHeader h2 = 2;
|
||||
}
|
||||
|
||||
message LunaticValidatorEvidence {
|
||||
Header header = 1;
|
||||
Vote vote = 2;
|
||||
string invalid_header_field = 3;
|
||||
|
||||
|
||||
google.protobuf.Timestamp timestamp = 4
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
}
|
||||
|
||||
message Evidence {
|
||||
oneof sum {
|
||||
DuplicateVoteEvidence duplicate_vote_evidence = 1;
|
||||
ConflictingHeadersEvidence conflicting_headers_evidence = 2;
|
||||
LunaticValidatorEvidence lunatic_validator_evidence = 3;
|
||||
PotentialAmnesiaEvidence potential_amnesia_evidence = 4;
|
||||
AmnesiaEvidence amnesia_evidence = 5;
|
||||
DuplicateVoteEvidence duplicate_vote_evidence = 1;
|
||||
LunaticValidatorEvidence lunatic_validator_evidence = 2;
|
||||
PotentialAmnesiaEvidence potential_amnesia_evidence = 3;
|
||||
AmnesiaEvidence amnesia_evidence = 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
@@ -155,75 +154,6 @@ func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBroadcastEvidence_ConflictingHeadersEvidence(t *testing.T) {
|
||||
var (
|
||||
config = rpctest.GetConfig()
|
||||
chainID = config.ChainID()
|
||||
pv = privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile())
|
||||
)
|
||||
|
||||
for i, c := range GetClients() {
|
||||
t.Logf("client %d", i)
|
||||
|
||||
h1, err := c.Commit(nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, h1.SignedHeader.Header)
|
||||
|
||||
// Create an alternative header with a different AppHash.
|
||||
h2 := &types.SignedHeader{
|
||||
Header: &types.Header{
|
||||
Version: h1.Version,
|
||||
ChainID: h1.ChainID,
|
||||
Height: h1.Height,
|
||||
Time: h1.Time,
|
||||
LastBlockID: h1.LastBlockID,
|
||||
LastCommitHash: h1.LastCommitHash,
|
||||
DataHash: h1.DataHash,
|
||||
ValidatorsHash: h1.ValidatorsHash,
|
||||
NextValidatorsHash: h1.NextValidatorsHash,
|
||||
ConsensusHash: h1.ConsensusHash,
|
||||
AppHash: crypto.CRandBytes(32),
|
||||
LastResultsHash: h1.LastResultsHash,
|
||||
EvidenceHash: h1.EvidenceHash,
|
||||
ProposerAddress: h1.ProposerAddress,
|
||||
},
|
||||
Commit: types.NewCommit(h1.Height, 1, h1.Commit.BlockID, h1.Commit.Signatures),
|
||||
}
|
||||
h2.Commit.BlockID = types.BlockID{
|
||||
Hash: h2.Hash(),
|
||||
PartSetHeader: types.PartSetHeader{Total: 1, Hash: crypto.CRandBytes(32)},
|
||||
}
|
||||
vote := &types.Vote{
|
||||
ValidatorAddress: pv.Key.Address,
|
||||
ValidatorIndex: 0,
|
||||
Height: h2.Height,
|
||||
Round: h2.Commit.Round,
|
||||
Timestamp: h2.Time,
|
||||
Type: tmproto.PrecommitType,
|
||||
BlockID: h2.Commit.BlockID,
|
||||
}
|
||||
|
||||
v := vote.ToProto()
|
||||
signBytes, err := pv.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v))
|
||||
require.NoError(t, err)
|
||||
vote.Signature = v.Signature
|
||||
|
||||
h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time)
|
||||
|
||||
t.Logf("h1 AppHash: %X", h1.AppHash)
|
||||
t.Logf("h2 AppHash: %X", h2.AppHash)
|
||||
|
||||
ev := &types.ConflictingHeadersEvidence{
|
||||
H1: &h1.SignedHeader,
|
||||
H2: h2,
|
||||
}
|
||||
|
||||
result, err := c.BroadcastEvidence(ev)
|
||||
require.NoError(t, err, "BroadcastEvidence(%s) failed", ev)
|
||||
assert.Equal(t, ev.Hash(), result.Hash, "expected result hash to match evidence hash")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBroadcastEmptyEvidence(t *testing.T) {
|
||||
for _, c := range GetClients() {
|
||||
_, err := c.BroadcastEvidence(nil)
|
||||
|
||||
@@ -87,12 +87,7 @@ func (b *Block) ValidateBasic() error {
|
||||
|
||||
// NOTE: b.Evidence.Evidence may be nil, but we're just looping.
|
||||
for i, ev := range b.Evidence.Evidence {
|
||||
switch ev.(type) {
|
||||
case *ConflictingHeadersEvidence:
|
||||
// ConflictingHeadersEvidence must be broken up in pieces and never
|
||||
// committed as a single piece.
|
||||
return fmt.Errorf("found ConflictingHeadersEvidence (#%d)", i)
|
||||
case *PotentialAmnesiaEvidence:
|
||||
if _, ok := ev.(*PotentialAmnesiaEvidence); ok {
|
||||
// PotentialAmnesiaEvidence does not contribute to anything on its own, so
|
||||
// reject it as well.
|
||||
return fmt.Errorf("found PotentialAmnesiaEvidence (#%d)", i)
|
||||
|
||||
@@ -86,9 +86,6 @@ func TestBlockValidateBasic(t *testing.T) {
|
||||
{"Tampered EvidenceHash", func(blk *Block) {
|
||||
blk.EvidenceHash = []byte("something else")
|
||||
}, true},
|
||||
{"ConflictingHeadersEvidence", func(blk *Block) {
|
||||
blk.Evidence = EvidenceData{Evidence: []Evidence{&ConflictingHeadersEvidence{}}}
|
||||
}, true},
|
||||
{"PotentialAmnesiaEvidence", func(blk *Block) {
|
||||
blk.Evidence = EvidenceData{Evidence: []Evidence{&PotentialAmnesiaEvidence{}}}
|
||||
}, true},
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||
tmmath "github.com/tendermint/tendermint/libs/math"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
@@ -31,11 +30,6 @@ type Evidence interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
type CompositeEvidence interface {
|
||||
VerifyComposite(committedHeader *Header, valSet *ValidatorSet) error
|
||||
Split(committedHeader *Header, valSet *ValidatorSet) []Evidence
|
||||
}
|
||||
|
||||
const (
|
||||
// MaxEvidenceBytes is a maximum size of any evidence (including amino overhead).
|
||||
MaxEvidenceBytes int64 = 444
|
||||
@@ -98,16 +92,6 @@ func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) {
|
||||
}
|
||||
return tp, nil
|
||||
|
||||
case *ConflictingHeadersEvidence:
|
||||
pbevi := evi.ToProto()
|
||||
|
||||
tp := &tmproto.Evidence{
|
||||
Sum: &tmproto.Evidence_ConflictingHeadersEvidence{
|
||||
ConflictingHeadersEvidence: pbevi,
|
||||
},
|
||||
}
|
||||
|
||||
return tp, nil
|
||||
case *LunaticValidatorEvidence:
|
||||
pbevi := evi.ToProto()
|
||||
|
||||
@@ -153,8 +137,6 @@ func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) {
|
||||
switch evi := evidence.Sum.(type) {
|
||||
case *tmproto.Evidence_DuplicateVoteEvidence:
|
||||
return DuplicateVoteEvidenceFromProto(evi.DuplicateVoteEvidence)
|
||||
case *tmproto.Evidence_ConflictingHeadersEvidence:
|
||||
return ConflictingHeadersEvidenceFromProto(evi.ConflictingHeadersEvidence)
|
||||
case *tmproto.Evidence_LunaticValidatorEvidence:
|
||||
return LunaticValidatorEvidenceFromProto(evi.LunaticValidatorEvidence)
|
||||
case *tmproto.Evidence_PotentialAmnesiaEvidence:
|
||||
@@ -168,7 +150,6 @@ func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) {
|
||||
|
||||
func init() {
|
||||
tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence")
|
||||
tmjson.RegisterType(&ConflictingHeadersEvidence{}, "tendermint/ConflictingHeadersEvidence")
|
||||
tmjson.RegisterType(&LunaticValidatorEvidence{}, "tendermint/LunaticValidatorEvidence")
|
||||
tmjson.RegisterType(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence")
|
||||
tmjson.RegisterType(&AmnesiaEvidence{}, "tendermint/AmnesiaEvidence")
|
||||
@@ -379,286 +360,6 @@ func DuplicateVoteEvidenceFromProto(pb *tmproto.DuplicateVoteEvidence) (*Duplica
|
||||
return dve, dve.ValidateBasic()
|
||||
}
|
||||
|
||||
// ConflictingHeadersEvidence is primarily used by the light client when it
|
||||
// observes two conflicting headers, both having 1/3+ of the voting power of
|
||||
// the currently trusted validator set.
|
||||
type ConflictingHeadersEvidence struct {
|
||||
H1 *SignedHeader `json:"h_1"`
|
||||
H2 *SignedHeader `json:"h_2"`
|
||||
}
|
||||
|
||||
var _ Evidence = &ConflictingHeadersEvidence{}
|
||||
var _ CompositeEvidence = &ConflictingHeadersEvidence{}
|
||||
|
||||
// NewConflictingHeadersEvidence creates a new instance of the respective evidence
|
||||
func NewConflictingHeadersEvidence(h1, h2 *SignedHeader) *ConflictingHeadersEvidence {
|
||||
return &ConflictingHeadersEvidence{H1: h1, H2: h2}
|
||||
}
|
||||
|
||||
// Split breaks up evidence into smaller chunks of evidence:
|
||||
// LunaticValidatorEvidence, DuplicateVoteEvidence and
|
||||
// PotentialAmnesiaEvidence.
|
||||
//
|
||||
// committedHeader - header at height H1.Height == H2.Height
|
||||
// valSet - validator set at height H1.Height == H2.Height
|
||||
func (ev *ConflictingHeadersEvidence) Split(committedHeader *Header, valSet *ValidatorSet) []Evidence {
|
||||
evList := make([]Evidence, 0)
|
||||
|
||||
var alternativeHeader *SignedHeader
|
||||
if bytes.Equal(committedHeader.Hash(), ev.H1.Hash()) {
|
||||
alternativeHeader = ev.H2
|
||||
} else {
|
||||
alternativeHeader = ev.H1
|
||||
}
|
||||
|
||||
// If ValidatorsHash, NextValidatorsHash, ConsensusHash, AppHash, and
|
||||
// LastResultsHash in alternativeHeader are different (incorrect application
|
||||
// state transition), then it is a lunatic misbehavior => immediately
|
||||
// slashable (#F5).
|
||||
var invalidField string
|
||||
switch {
|
||||
case !bytes.Equal(committedHeader.ValidatorsHash, alternativeHeader.ValidatorsHash):
|
||||
invalidField = "ValidatorsHash"
|
||||
case !bytes.Equal(committedHeader.NextValidatorsHash, alternativeHeader.NextValidatorsHash):
|
||||
invalidField = "NextValidatorsHash"
|
||||
case !bytes.Equal(committedHeader.ConsensusHash, alternativeHeader.ConsensusHash):
|
||||
invalidField = "ConsensusHash"
|
||||
case !bytes.Equal(committedHeader.AppHash, alternativeHeader.AppHash):
|
||||
invalidField = "AppHash"
|
||||
case !bytes.Equal(committedHeader.LastResultsHash, alternativeHeader.LastResultsHash):
|
||||
invalidField = "LastResultsHash"
|
||||
}
|
||||
if invalidField != "" {
|
||||
for i, sig := range alternativeHeader.Commit.Signatures {
|
||||
if sig.Absent() {
|
||||
continue
|
||||
}
|
||||
evList = append(evList, NewLunaticValidatorEvidence(
|
||||
alternativeHeader.Header,
|
||||
alternativeHeader.Commit.GetVote(int32(i)),
|
||||
invalidField,
|
||||
committedHeader.Time, //take the time of our own trusted header
|
||||
))
|
||||
}
|
||||
return evList
|
||||
}
|
||||
|
||||
// Use the fact that signatures are sorted by ValidatorAddress.
|
||||
var (
|
||||
i = 0
|
||||
j = 0
|
||||
)
|
||||
OUTER_LOOP:
|
||||
for i < len(ev.H1.Commit.Signatures) {
|
||||
sigA := ev.H1.Commit.Signatures[i]
|
||||
if sigA.Absent() {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
// FIXME: Replace with HasAddress once DuplicateVoteEvidence#PubKey is
|
||||
// removed.
|
||||
_, val := valSet.GetByAddress(sigA.ValidatorAddress)
|
||||
if val == nil {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
for j < len(ev.H2.Commit.Signatures) {
|
||||
sigB := ev.H2.Commit.Signatures[j]
|
||||
if sigB.Absent() {
|
||||
j++
|
||||
continue
|
||||
}
|
||||
|
||||
switch bytes.Compare(sigA.ValidatorAddress, sigB.ValidatorAddress) {
|
||||
case 0:
|
||||
// if H1.Round == H2.Round, and some signers signed different precommit
|
||||
// messages in both commits, then it is an equivocation misbehavior =>
|
||||
// immediately slashable (#F1).
|
||||
if ev.H1.Commit.Round == ev.H2.Commit.Round {
|
||||
evList = append(evList, NewDuplicateVoteEvidence(
|
||||
ev.H1.Commit.GetVote(int32(i)),
|
||||
ev.H2.Commit.GetVote(int32(j)),
|
||||
ev.H1.Time,
|
||||
))
|
||||
} else {
|
||||
// if H1.Round != H2.Round we need to run full detection procedure => not
|
||||
// immediately slashable.
|
||||
firstVote := ev.H1.Commit.GetVote(int32(i))
|
||||
secondVote := ev.H2.Commit.GetVote(int32(j))
|
||||
newEv := NewPotentialAmnesiaEvidence(firstVote, secondVote, committedHeader.Time)
|
||||
|
||||
// has the validator incorrectly voted for a previous round
|
||||
if newEv.VoteA.Round > newEv.VoteB.Round {
|
||||
evList = append(evList, NewAmnesiaEvidence(newEv, NewEmptyPOLC()))
|
||||
} else {
|
||||
evList = append(evList, newEv)
|
||||
}
|
||||
}
|
||||
|
||||
i++
|
||||
j++
|
||||
continue OUTER_LOOP
|
||||
case 1:
|
||||
i++
|
||||
continue OUTER_LOOP
|
||||
case -1:
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return evList
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) Height() int64 { return ev.H1.Height }
|
||||
|
||||
// Time returns time of the latest header.
|
||||
func (ev *ConflictingHeadersEvidence) Time() time.Time {
|
||||
return maxTime(ev.H1.Time, ev.H2.Time)
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) Address() []byte {
|
||||
panic("use ConflictingHeadersEvidence#Split to split evidence into individual pieces")
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) Bytes() []byte {
|
||||
pbe := ev.ToProto()
|
||||
|
||||
bz, err := pbe.Marshal()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bz
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) Hash() []byte {
|
||||
bz := make([]byte, tmhash.Size*2)
|
||||
copy(bz[:tmhash.Size-1], ev.H1.Hash().Bytes())
|
||||
copy(bz[tmhash.Size:], ev.H2.Hash().Bytes())
|
||||
return tmhash.Sum(bz)
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) Verify(chainID string, _ crypto.PubKey) error {
|
||||
panic("use ConflictingHeadersEvidence#VerifyComposite to verify composite evidence")
|
||||
}
|
||||
|
||||
// VerifyComposite verifies that both headers belong to the same chain, same
|
||||
// height and signed by 1/3+ of validators at height H1.Height == H2.Height.
|
||||
func (ev *ConflictingHeadersEvidence) VerifyComposite(committedHeader *Header, valSet *ValidatorSet) error {
|
||||
var alternativeHeader *SignedHeader
|
||||
switch {
|
||||
case bytes.Equal(committedHeader.Hash(), ev.H1.Hash()):
|
||||
alternativeHeader = ev.H2
|
||||
case bytes.Equal(committedHeader.Hash(), ev.H2.Hash()):
|
||||
alternativeHeader = ev.H1
|
||||
default:
|
||||
return errors.New("none of the headers are committed from this node's perspective")
|
||||
}
|
||||
|
||||
// ChainID must be the same
|
||||
if committedHeader.ChainID != alternativeHeader.ChainID {
|
||||
return errors.New("alt header is from a different chain")
|
||||
}
|
||||
|
||||
// Height must be the same
|
||||
if committedHeader.Height != alternativeHeader.Height {
|
||||
return errors.New("alt header is from a different height")
|
||||
}
|
||||
|
||||
// Limit the number of signatures to avoid DoS attacks where a header
|
||||
// contains too many signatures.
|
||||
//
|
||||
// Validator set size = 100 [node]
|
||||
// Max validator set size = 100 * 2 = 200 [fork?]
|
||||
maxNumValidators := valSet.Size() * 2
|
||||
if len(alternativeHeader.Commit.Signatures) > maxNumValidators {
|
||||
return fmt.Errorf("alt commit contains too many signatures: %d, expected no more than %d",
|
||||
len(alternativeHeader.Commit.Signatures),
|
||||
maxNumValidators)
|
||||
}
|
||||
|
||||
// Header must be signed by at least 1/3+ of voting power of currently
|
||||
// trusted validator set.
|
||||
if err := valSet.VerifyCommitLightTrusting(
|
||||
alternativeHeader.ChainID,
|
||||
alternativeHeader.Commit,
|
||||
tmmath.Fraction{Numerator: 1, Denominator: 3}); err != nil {
|
||||
return fmt.Errorf("alt header does not have 1/3+ of voting power of our validator set: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) Equal(ev2 Evidence) bool {
|
||||
if e2, ok := ev2.(*ConflictingHeadersEvidence); ok {
|
||||
return bytes.Equal(ev.H1.Hash(), e2.H1.Hash()) && bytes.Equal(ev.H2.Hash(), e2.H2.Hash())
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) ValidateBasic() error {
|
||||
if ev == nil {
|
||||
return errors.New("empty conflicting headers evidence")
|
||||
}
|
||||
|
||||
if ev.H1 == nil {
|
||||
return errors.New("first header is missing")
|
||||
}
|
||||
|
||||
if ev.H2 == nil {
|
||||
return errors.New("second header is missing")
|
||||
}
|
||||
|
||||
if err := ev.H1.ValidateBasic(ev.H1.ChainID); err != nil {
|
||||
return fmt.Errorf("h1: %w", err)
|
||||
}
|
||||
if err := ev.H2.ValidateBasic(ev.H2.ChainID); err != nil {
|
||||
return fmt.Errorf("h2: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) String() string {
|
||||
return fmt.Sprintf("ConflictingHeadersEvidence{H1: %d#%X, H2: %d#%X}",
|
||||
ev.H1.Height, ev.H1.Hash(),
|
||||
ev.H2.Height, ev.H2.Hash())
|
||||
}
|
||||
|
||||
func (ev *ConflictingHeadersEvidence) ToProto() *tmproto.ConflictingHeadersEvidence {
|
||||
pbh1 := ev.H1.ToProto()
|
||||
pbh2 := ev.H2.ToProto()
|
||||
|
||||
tp := &tmproto.ConflictingHeadersEvidence{
|
||||
H1: pbh1,
|
||||
H2: pbh2,
|
||||
}
|
||||
return tp
|
||||
}
|
||||
|
||||
func ConflictingHeadersEvidenceFromProto(pb *tmproto.ConflictingHeadersEvidence) (*ConflictingHeadersEvidence, error) {
|
||||
if pb == nil {
|
||||
return &ConflictingHeadersEvidence{}, errors.New("nil ConflictingHeadersEvidence")
|
||||
}
|
||||
h1, err := SignedHeaderFromProto(pb.H1)
|
||||
if err != nil {
|
||||
return &ConflictingHeadersEvidence{}, fmt.Errorf("from proto err: %w", err)
|
||||
}
|
||||
h2, err := SignedHeaderFromProto(pb.H2)
|
||||
if err != nil {
|
||||
return &ConflictingHeadersEvidence{}, fmt.Errorf("from proto err: %w", err)
|
||||
}
|
||||
|
||||
tp := &ConflictingHeadersEvidence{
|
||||
H1: h1,
|
||||
H2: h2,
|
||||
}
|
||||
|
||||
return tp, tp.ValidateBasic()
|
||||
}
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
type LunaticValidatorEvidence struct {
|
||||
@@ -1572,10 +1273,3 @@ func NewMockPOLC(height int64, time time.Time, pubKey crypto.PubKey) ProofOfLock
|
||||
PubKey: pubKey,
|
||||
}
|
||||
}
|
||||
|
||||
func maxTime(t1 time.Time, t2 time.Time) time.Time {
|
||||
if t1.After(t2) {
|
||||
return t1
|
||||
}
|
||||
return t2
|
||||
}
|
||||
|
||||
@@ -112,19 +112,12 @@ func TestMaxEvidenceBytes(t *testing.T) {
|
||||
// InvalidHeaderField: "",
|
||||
// }
|
||||
|
||||
// signedHeader := SignedHeader{Header: makeHeaderRandom(), Commit: randCommit(time.Now())}
|
||||
// evc := &ConflictingHeadersEvidence{
|
||||
// H1: &signedHeader,
|
||||
// H2: &signedHeader,
|
||||
// }
|
||||
|
||||
testCases := []struct {
|
||||
testName string
|
||||
evidence Evidence
|
||||
}{
|
||||
{"DuplicateVote", ev},
|
||||
// {"LunaticValidatorEvidence", evl},
|
||||
// {"ConflictingHeadersEvidence", evc},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
@@ -256,76 +249,6 @@ func TestLunaticValidatorEvidence(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestConflictingHeadersEvidence(t *testing.T) {
|
||||
const (
|
||||
chainID = "TestConflictingHeadersEvidence"
|
||||
height int64 = 37
|
||||
)
|
||||
|
||||
var (
|
||||
blockID = makeBlockIDRandom()
|
||||
header1 = makeHeaderRandom()
|
||||
header2 = makeHeaderRandom()
|
||||
)
|
||||
|
||||
header1.Height = height
|
||||
header1.LastBlockID = blockID
|
||||
header1.ChainID = chainID
|
||||
|
||||
header2.Height = height
|
||||
header2.LastBlockID = blockID
|
||||
header2.ChainID = chainID
|
||||
|
||||
voteSet1, valSet, vals := randVoteSet(height, 1, tmproto.PrecommitType, 10, 1)
|
||||
voteSet2 := NewVoteSet(chainID, height, 1, tmproto.PrecommitType, valSet)
|
||||
|
||||
commit1, err := MakeCommit(BlockID{
|
||||
Hash: header1.Hash(),
|
||||
PartSetHeader: PartSetHeader{
|
||||
Total: 100,
|
||||
Hash: crypto.CRandBytes(tmhash.Size),
|
||||
},
|
||||
}, height, 1, voteSet1, vals, time.Now())
|
||||
require.NoError(t, err)
|
||||
commit2, err := MakeCommit(BlockID{
|
||||
Hash: header2.Hash(),
|
||||
PartSetHeader: PartSetHeader{
|
||||
Total: 100,
|
||||
Hash: crypto.CRandBytes(tmhash.Size),
|
||||
},
|
||||
}, height, 1, voteSet2, vals, time.Now())
|
||||
require.NoError(t, err)
|
||||
|
||||
h1 := &SignedHeader{
|
||||
Header: header1,
|
||||
Commit: commit1,
|
||||
}
|
||||
h2 := &SignedHeader{
|
||||
Header: header2,
|
||||
Commit: commit2,
|
||||
}
|
||||
|
||||
ev := NewConflictingHeadersEvidence(h1, h2)
|
||||
|
||||
assert.Panics(t, func() {
|
||||
ev.Address()
|
||||
})
|
||||
|
||||
assert.Panics(t, func() {
|
||||
pubKey, _ := vals[0].GetPubKey()
|
||||
ev.Verify(chainID, pubKey)
|
||||
})
|
||||
|
||||
assert.Equal(t, height, ev.Height())
|
||||
assert.Equal(t, ev.H2.Time, ev.Time())
|
||||
assert.NotEmpty(t, ev.Hash())
|
||||
assert.NotEmpty(t, ev.Bytes())
|
||||
assert.NoError(t, ev.VerifyComposite(header1, valSet))
|
||||
assert.True(t, ev.Equal(ev))
|
||||
assert.NoError(t, ev.ValidateBasic())
|
||||
assert.NotEmpty(t, ev.String())
|
||||
}
|
||||
|
||||
func TestPotentialAmnesiaEvidence(t *testing.T) {
|
||||
const (
|
||||
chainID = "TestPotentialAmnesiaEvidence"
|
||||
@@ -643,35 +566,6 @@ func TestEvidenceProto(t *testing.T) {
|
||||
header2.LastBlockID = blockID
|
||||
header2.ChainID = chainID
|
||||
|
||||
voteSet1, valSet, vals := randVoteSet(height, 1, tmproto.PrecommitType, 10, 1)
|
||||
voteSet2 := NewVoteSet(chainID, height, 1, tmproto.PrecommitType, valSet)
|
||||
|
||||
commit1, err := MakeCommit(BlockID{
|
||||
Hash: header1.Hash(),
|
||||
PartSetHeader: PartSetHeader{
|
||||
Total: 100,
|
||||
Hash: crypto.CRandBytes(tmhash.Size),
|
||||
},
|
||||
}, height, 1, voteSet1, vals, time.Now())
|
||||
require.NoError(t, err)
|
||||
commit2, err := MakeCommit(BlockID{
|
||||
Hash: header2.Hash(),
|
||||
PartSetHeader: PartSetHeader{
|
||||
Total: 100,
|
||||
Hash: crypto.CRandBytes(tmhash.Size),
|
||||
},
|
||||
}, height, 1, voteSet2, vals, time.Now())
|
||||
require.NoError(t, err)
|
||||
|
||||
h1 := &SignedHeader{
|
||||
Header: header1,
|
||||
Commit: commit1,
|
||||
}
|
||||
h2 := &SignedHeader{
|
||||
Header: header2,
|
||||
Commit: commit2,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
testName string
|
||||
evidence Evidence
|
||||
@@ -683,10 +577,6 @@ func TestEvidenceProto(t *testing.T) {
|
||||
{"DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, false, true},
|
||||
{"DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, false, true},
|
||||
{"DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v}, false, false},
|
||||
{"ConflictingHeadersEvidence empty fail", &ConflictingHeadersEvidence{}, false, true},
|
||||
{"ConflictingHeadersEvidence nil H2", &ConflictingHeadersEvidence{H1: h1, H2: nil}, false, true},
|
||||
{"ConflictingHeadersEvidence nil H1", &ConflictingHeadersEvidence{H1: nil, H2: h2}, false, true},
|
||||
{"ConflictingHeadersEvidence success", &ConflictingHeadersEvidence{H1: h1, H2: h2}, false, false},
|
||||
{"LunaticValidatorEvidence success", &LunaticValidatorEvidence{Header: header1,
|
||||
Vote: v, InvalidHeaderField: "ValidatorsHash"}, false, true},
|
||||
{"&LunaticValidatorEvidence empty fail", &LunaticValidatorEvidence{}, false, true},
|
||||
|
||||
Reference in New Issue
Block a user