github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/docs/architecture/adr-009-evidence-module.md (about)

     1  # ADR 009: Evidence Module
     2  
     3  ## Changelog
     4  
     5  - 2019 July 31: Initial draft
     6  - 2019 October 24: Initial implementation
     7  
     8  ## Status
     9  
    10  Accepted
    11  
    12  ## Context
    13  
    14  In order to support building highly secure, robust and interoperable blockchain
    15  applications, it is vital for the Cosmos SDK to expose a mechanism in which arbitrary
    16  evidence can be submitted, evaluated and verified resulting in some agreed upon
    17  penalty for any misbehavior committed by a validator, such as equivocation (double-voting),
    18  signing when unbonded, signing an incorrect state transition (in the future), etc.
    19  Furthermore, such a mechanism is paramount for any
    20  [IBC](https://github.com/cosmos/ics/blob/master/ibc/1_IBC_ARCHITECTURE.md) or
    21  cross-chain validation protocol implementation in order to support the ability
    22  for any misbehavior to be relayed back from a collateralized chain to a primary
    23  chain so that the equivocating validator(s) can be slashed.
    24  
    25  ## Decision
    26  
    27  We will implement an evidence module in the Cosmos SDK supporting the following
    28  functionality:
    29  
    30  - Provide developers with the abstractions and interfaces necessary to define
    31  custom evidence messages, message handlers, and methods to slash and penalize
    32  accordingly for misbehavior.
    33  - Support the ability to route evidence messages to handlers in any module to
    34  determine the validity of submitted misbehavior.
    35  - Support the ability, through governance, to modify slashing penalties of any
    36  evidence type.
    37  - Querier implementation to support querying params, evidence types, params, and
    38  all submitted valid misbehavior.
    39  
    40  ### Types
    41  
    42  First, we define the `Evidence` interface type. The `x/evidence` module may implement
    43  its own types that can be used by many chains (e.g. `CounterFactualEvidence`).
    44  In addition, other modules may implement their own `Evidence` types in a similar
    45  manner in which governance is extensible. It is important to note any concrete
    46  type implementing the `Evidence` interface may include arbitrary fields such as
    47  an infraction time. We want the `Evidence` type to remain as flexible as possible.
    48  
    49  When submitting evidence to the `x/evidence` module, the concrete type must provide
    50  the validator's consensus address, which should be known by the `x/slashing`
    51  module (assuming the infraction is valid), the height at which the infraction
    52  occurred and the validator's power at same height in which the infraction occurred.
    53  
    54  ```go
    55  type Evidence interface {
    56    Route() string
    57    Type() string
    58    String() string
    59    Hash() HexBytes
    60    ValidateBasic() error
    61  
    62    // The consensus address of the malicious validator at time of infraction
    63    GetConsensusAddress() ConsAddress
    64  
    65    // Height at which the infraction occurred
    66    GetHeight() int64
    67  
    68    // The total power of the malicious validator at time of infraction
    69    GetValidatorPower() int64
    70  
    71    // The total validator set power at time of infraction
    72    GetTotalPower() int64
    73  }
    74  ```
    75  
    76  ### Routing & Handling
    77  
    78  Each `Evidence` type must map to a specific unique route and be registered with
    79  the `x/evidence` module. It accomplishes this through the `Router` implementation.
    80  
    81  ```go
    82  type Router interface {
    83    AddRoute(r string, h Handler) Router
    84    HasRoute(r string) bool
    85    GetRoute(path string) Handler
    86    Seal()
    87  }
    88  ```
    89  
    90  Upon successful routing through the `x/evidence` module, the `Evidence` type
    91  is passed through a `Handler`. This `Handler` is responsible for executing all
    92  corresponding business logic necessary for verifying the evidence as valid. In
    93  addition, the `Handler` may execute any necessary slashing and potential jailing.
    94  Since slashing fractions will typically result from some form of static functions,
    95  allow the `Handler` to do this provides the greatest flexibility. An example could
    96  be `k * evidence.GetValidatorPower()` where `k` is an on-chain parameter controlled
    97  by governance. The `Evidence` type should provide all the external information
    98  necessary in order for the `Handler` to make the necessary state transitions.
    99  If no error is returned, the `Evidence` is considered valid.
   100  
   101  ```go
   102  type Handler func(Context, Evidence) error
   103  ```
   104  
   105  ### Submission
   106  
   107  `Evidence` is submitted through a `MsgSubmitEvidence` message type which is internally
   108  handled by the `x/evidence` module's `SubmitEvidence`.
   109  
   110  ```go
   111  type MsgSubmitEvidence struct {
   112    Evidence
   113  }
   114  
   115  func handleMsgSubmitEvidence(ctx Context, keeper Keeper, msg MsgSubmitEvidence) Result {
   116    if err := keeper.SubmitEvidence(ctx, msg.Evidence); err != nil {
   117      return err.Result()
   118    }
   119  
   120    // emit events...
   121  
   122    return Result{
   123      // ...
   124    }
   125  }
   126  ```
   127  
   128  The `x/evidence` module's keeper is responsible for matching the `Evidence` against
   129  the module's router and invoking the corresponding `Handler` which may include
   130  slashing and jailing the validator. Upon success, the submitted evidence is persisted.
   131  
   132  ```go
   133  func (k Keeper) SubmitEvidence(ctx Context, evidence Evidence) error {
   134    handler := keeper.router.GetRoute(evidence.Route())
   135    if err := handler(ctx, evidence); err != nil {
   136      return ErrInvalidEvidence(keeper.codespace, err)
   137    }
   138  
   139    keeper.setEvidence(ctx, evidence)
   140    return nil
   141  }
   142  ```
   143  
   144  ### Genesis
   145  
   146  Finally, we need to represent the genesis state of the `x/evidence` module. The
   147  module only needs a list of all submitted valid infractions and any necessary params
   148  for which the module needs in order to handle submitted evidence. The `x/evidence`
   149  module will naturally define and route native evidence types for which it'll most
   150  likely need slashing penalty constants for.
   151  
   152  ```go
   153  type GenesisState struct {
   154    Params       Params
   155    Infractions  []Evidence
   156  }
   157  ```
   158  
   159  ## Consequences
   160  
   161  ### Positive
   162  
   163  - Allows the state machine to process misbehavior submitted on-chain and penalize
   164  validators based on agreed upon slashing parameters.
   165  - Allows evidence types to be defined and handled by any module. This further allows
   166  slashing and jailing to be defined by more complex mechanisms.
   167  - Does not solely rely on Tendermint to submit evidence.
   168  
   169  ### Negative
   170  
   171  - No easy way to introduce new evidence types through governance on a live chain
   172  due to the inability to introduce the new evidence type's corresponding handler
   173  
   174  ### Neutral
   175  
   176  - Should we persist infractions indefinitely? Or should we rather rely on events?
   177  
   178  ## References
   179  
   180  - [ICS](https://github.com/cosmos/ics)
   181  - [IBC Architecture](https://github.com/cosmos/ics/blob/master/ibc/1_IBC_ARCHITECTURE.md)
   182  - [Tendermint Fork Accountability](https://github.com/tendermint/spec/blob/7b3138e69490f410768d9b1ffc7a17abc23ea397/spec/consensus/fork-accountability.md)