Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into bernd/1214-splitConsu…
Browse files Browse the repository at this point in the history
…merGenesis
  • Loading branch information
bermuell committed Oct 12, 2023
2 parents 6d94ef8 + ad37bcd commit 0e31c3b
Show file tree
Hide file tree
Showing 80 changed files with 2,428 additions and 4,999 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/proto-registry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bufbuild/buf-setup-action@v1.26.1
- uses: bufbuild/buf-setup-action@v1.27.0
- uses: bufbuild/buf-push-action@v1
with:
input: "proto"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/proto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bufbuild/buf-setup-action@v1.26.1
- uses: bufbuild/buf-setup-action@v1.27.0
- uses: bufbuild/buf-breaking-action@v1
with:
input: "proto"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

Add an entry to the unreleased provider section whenever merging a PR to main that is not targeted at a specific release. These entries will eventually be included in a provider release.

* (feat!) [#1230](https://github.com/cosmos/interchain-security/pull/1230) Throttle with retries provider changes.
* (feature!) [#1280](https://github.com/cosmos/interchain-security/pull/1280) provider proposal for changing reward denoms
* (feature!) [#1244](https://github.com/cosmos/interchain-security/pull/1244) Update the default consumer unbonding period to 2 weeks.
* (deps) [#1259](https://github.com/cosmos/interchain-security/pull/1259) Bump [cosmos-sdk](https://github.com/cosmos/cosmos-sdk) to [v0.47.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.5).
Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,10 @@ build-docs:
@cd docs && ./build.sh

.PHONY: build-docs

###############################################################################
### Test Traces ###
###############################################################################

e2e-traces:
cd tests/e2e; go test -timeout 30s -run ^TestWriteExamples -v
4 changes: 1 addition & 3 deletions app/consumer/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ func GetConsumerGenesisTransformCmd() *cobra.Command {
Example:
$ %s transform /path/to/ccv_consumer_genesis.json `, version.AppName),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return TransformConsumerGenesis(cmd, args)
},
RunE: TransformConsumerGenesis,
}

return cmd
Expand Down
107 changes: 81 additions & 26 deletions docs/docs/adrs/adr-005-cryptographic-equivocation-verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ title: Cryptographic verification of equivocation evidence

## Changelog
* 5/1/2023: First draft
* 7/23/23: Add light client attacks handling
* 7/23/2023: Add light client attacks handling
* 9/6/2023: Add double signing attacks handling

## Status

Expand All @@ -19,7 +20,7 @@ Every proposal needs to go through a (two weeks) voting period before it can be
Given a three-week unbonding period, this means that an equivocation proposal needs to be submitted within one week since the infraction occurred.

This ADR proposes a system to slash validators automatically for equivocation, immediately upon the provider chain's receipt of the evidence. Another thing to note is that we intend to introduce this system in stages, since even the partial ability to slash and/or tombstone is a strict improvement in security.
For the first stage of this work, we will only handle light client attacks.
The feature is implemented in two parts, each with its dedicated endpoint. One endpoint handles light client attacks, while the other handles double signing attacks.

### Light Client Attack

Expand All @@ -42,48 +43,99 @@ The types of light client attacks are defined by analyzing the differences betwe
There are three types of light client attacks: lunatic attack, equivocation attack, and amnesia attack.
For details, see the [CometBFT specification](https://github.com/cometbft/cometbft/blob/main/spec/light-client/attacks/notes-on-evidence-handling.md#evidence-handling).

When a light client agent detects two conflicting headers, it will initially verify their traces (see [cometBFT detector](https://github.com/cometbft/cometbft/blob/2af25aea6cfe6ac4ddac40ceddfb8c8eee17d0e6/light/detector.go#L28)) using its primary and witness nodes.
When a light client agent detects two conflicting headers, it will initially verify their traces (see [cometBFT detector](https://github.com/cometbft/cometbft/blob/v0.34.28/light/detector.go#L28)) using its primary and witness nodes.
If these headers pass successful verification, the Byzantine validators will be identified based on the header's commit signatures
and the type of light client attack. The agent will then transmit this information to its nodes using a [`LightClientAttackEvidence`](https://github.com/cometbft/cometbft/blob/feed0ddf564e113a840c4678505601256b93a8bc/docs/architecture/adr-047-handling-evidence-from-light-client.md) to be eventually voted on and added to a block.
and the type of light client attack. The agent will then transmit this information to its nodes using a [`LightClientAttackEvidence`](https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#light-client-attacks) evidence to be eventually voted on and added to a block.
Note that from a light client agent perspective, it is not possible to establish whether a primary or a witness node, or both, are malicious.
Therefore, it will create and send two `LightClientAttackEvidence`: one against the primary (sent to the witness), and one against the witness (sent to the primary).
Both nodes will then verify it before broadcasting it and adding it to the [evidence pool](https://github.com/cometbft/cometbft/blob/2af25aea6cfe6ac4ddac40ceddfb8c8eee17d0e6/evidence/pool.go#L28).
If a `LightClientAttackEvidence` is finally committed to a block, the chain's evidence module will execute it, resulting in the jailing and the slashing of the validators responsible for the light client attack.
Therefore, it will create and send two evidences: one against the primary (sent to the witness), and one against the witness (sent to the primary).
Both nodes will then verify it before broadcasting it and adding it to the [evidence pool](https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/pool.go#L28).
If an evidence is finally committed to a block, the chain's evidence module will execute it, resulting in the jailing and the slashing of the validators responsible for the light client attack.


Light clients are a core component of IBC. In the event of a light client attack, IBC relayers notify the affected chains by submitting an [IBC misbehavior message](https://github.com/cosmos/ibc-go/blob/2b7c969066fbcb18f90c7f5bd256439ca12535c7/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79).
A misbehavior message includes the conflicting headers that constitute a `LightClientAttackEvidence`. Upon receiving such a message,
Light clients are a core component of IBC. In the event of a light client attack, IBC relayers notify the affected chains by submitting an [IBC misbehavior message](https://github.com/cosmos/ibc-go/blob/v4.4.2/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79).
A misbehavior message includes the conflicting headers that constitute a light client attack evidence. Upon receiving such a message,
a chain will first verify whether these headers would have convinced its light client. This verification is achieved by checking
the header states against the light client consensus states (see [IBC misbehaviour handler](https://github.com/cosmos/ibc-go/blob/2b7c969066fbcb18f90c7f5bd256439ca12535c7/modules/light-clients/07-tendermint/types/misbehaviour_handle.go#L101)). If the misbehaviour is successfully verified, the chain will then "freeze" the
the header states against the light client consensus states (see [IBC misbehaviour handler](https://github.com/cosmos/ibc-go/blob/v4.4.2/modules/light-clients/07-tendermint/types/misbehaviour_handle.go#L24)). If the misbehaviour is successfully verified, the chain will then "freeze" the
light client, halting any further trust in or updating of its states.

### Double Signing Attack

A double signing attack, also known as equivocation,
occurs when a validator votes for two different blocks in the same round of the CometBFT consensus.
This consensus mechanism operates with multiple voting rounds at each block height,
and it strictly prohibits sending two votes of the same type during a round
(see [CometBFT State Machine Overview](https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/consensus.md#state-machine-overview)).

When a node observes two votes from the same peer, it will use these two votes to create
a [`DuplicateVoteEvidence`](https://github.com/cometbft/cometbft/blob/v0.34.28/types/evidence.go#L35)
evidence and gossip it to the other nodes in the network
(see [CometBFT equivocation detection](https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#detection)).
Each node will then verify the evidence according to the CometBFT rules that define a valid double signing infraction, and based on this verification, they will decide whether to add the evidence to a block.
During the evidence verification process, the signatures of the conflicting votes must be verified successfully.
Note that this is achieved using the public key of the misbehaving validator, along with the chain ID of the chain where the infraction occurred (see [CometBFT equivocation verification](https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#verification)).

Once a double signing evidence is committed to a block, the consensus layer will report the equivocation to the evidence module of the Cosmos SDK application layer.
The application will, in turn, punish the malicious validator through jailing, tombstoning and slashing
(see [handleEquivocationEvidence](https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/keeper/infraction.go#L263)).


## Decision

In the first iteration of the feature, we will introduce a new endpoint: `HandleConsumerMisbehaviour(ctx sdk.Context, misbehaviour ibctmtypes.Misbehaviour)`.
### Light Client Attack

In the first part of the feature, we introduce a new endpoint: `HandleConsumerMisbehaviour(ctx sdk.Context, misbehaviour ibctmtypes.Misbehaviour)`.
The main idea is to leverage the current IBC misbehaviour handling and update it to solely jail and slash the validators that
performed a light client attack. This update will be made under the assumption that the chain connected via this light client
share the same validator set, as it is the case with Replicated Security.
performed a light client attack. Note that in this context, we assume that chains connected via a light client
share the same validator set, as is the case with Replicated Security.

This endpoint will reuse the IBC client libraries to verify that the misbehaviour headers would have fooled the light client.
Additionally, it’s crucial that the endpoint logic result in the slashing and jailing of validators under the same conditions
as a light client agent detector. Therefore, the endpoint will ensure that the two conditions are met:
This endpoint reuses the IBC client libraries to verify that the misbehaviour headers would have fooled the light client.
Additionally, it’s crucial that the endpoint logic results in the slashing and jailing of validators under the same conditions
as a light client agent detector. Therefore, the endpoint ensures that the two conditions are met:
the headers in the misbehaviour message have the same block height, and
the light client isn’t expired.

After having successfully verified a misbehaviour, the endpoint will execute the jailing and slashing of the malicious validators similarly as in the evidence module.
After having successfully verified a misbehaviour, the endpoint executes the jailing and slashing of the malicious validators similarly as in the evidence module.

### Double Signing Attack

In the second part of the feature, we introduce a new endpoint `HandleConsumerDoubleVoting(
ctx sdk.Context, evidence *tmtypes.DuplicateVoteEvidence, chainID string, pubkey cryptotypes.PubKey)`.
Simply put, the handling logic verifies a double signing evidence against a provided
public key and chain ID and, if successful, executes the jailing of the malicious validator who double voted.

We define a new
`MsgSubmitConsumerDoubleVoting` message to report a double voting evidence observed
on a consumer chain to the endpoint of the provider chain. This message contains two fields:
a double signing evidence
`duplicate_vote_evidence` and a light client header for the infraction block height,
referred to as `infraction_block_header`.
The latter provides the malicious validator's public key and the chain ID required to verify the signature of the votes contained in the evidence.

Note that double signing evidence is not verified using the same conditions as in the implementation CometBFT (see
[`verify(evidence types.Evidence)`](https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/verify.go#L19) method). Specifically, we do not check that the evidence hasn't expired.
More details can be found in the ["Current limitations"](#current-limitations) section below.

Upon a successful equivocation verification, the misbehaving validator is jailed for the maximum time
(see [DoubleSignJailEndTime](https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/types/params.go#L11)
in the SDK evidence module).

### Current limitations:

- This only handles light client attacks, not double signing. In the future, we will add the code to also verify double signing.
### Current limitations:

- We cannot derive an infraction height from the evidence, so it is only possible to tombstone validators, not actually slash them.
- We cannot derive an infraction height from the evidence, so it is only possible to jail validators, not actually slash them.
To explain the technical reasons behind this limitation, let's recap the initial consumer initiated slashing logic.
In a nutshell, consumer heights are mapped to provider heights through VSCPackets, namely through the so called vscIDs.
When an infraction occurs on the consumer, a SlashPacket containing the vscID obtained from mapping the consumer infraction height
is sent to the provider. Upon receiving the packet, the provider maps the consumer infraction height to a local infraction height,
which is used to slash the misbehaving validator. In the context of untrusted consumer chains, all their states, including vscIDs,
could be corrupted and therefore cannot be used for slashing purposes.
In a nutshell, consumer heights are mapped to provider heights through VSCPackets, namely through the so called vscIDs.
When an infraction occurs on the consumer, a SlashPacket containing the vscID obtained from mapping the consumer infraction height
is sent to the provider. Upon receiving the packet, the provider maps the consumer infraction height to a local infraction height,
which is used to slash the misbehaving validator. In the context of untrusted consumer chains, all their states, including vscIDs,
could be corrupted and therefore cannot be used for slashing purposes.

- For the same reasons explained above, the age of a consumer double signing evidence can't be verified,
either using its infraction height or its unsigned timestamp. Note that changes the jailing behaviour, potentially leading to a validator's jailing based on some "old" evidence from a consumer, which wouldn't occur if the consumer were a standalone chain.

- In the first stage of this feature, validators are jailed indefinitely without being tombstoned.
The underlying reason is that a malicious validator could take advantage of getting tombstoned
to avoid being slashed on the provider ([see comment](https://github.com/cosmos/interchain-security/pull/1232#issuecomment-1693127641)).

- Currently, the endpoint can only handle "equivocation" light client attacks. This is because the "lunatic" attacks require the endpoint to possess the ability to dissociate which header is conflicted or trusted upon receiving a misbehavior message. Without this information, it's not possible to define the Byzantine validators from the conflicting headers (see [comment](https://github.com/cosmos/interchain-security/pull/826#discussion_r1268668684)).

Expand All @@ -92,7 +144,8 @@ could be corrupted and therefore cannot be used for slashing purposes.

### Positive

- After this ADR is applied, it will be possible for the provider chain to tombstone validators who committed a light client attack.
- It is now possible for the provider chain to jail validators who committed
light client or double signing attacks on a consumer chain.

### Negative

Expand All @@ -102,4 +155,6 @@ could be corrupted and therefore cannot be used for slashing purposes.
## References

* [ICS misbehaviour handling PR](https://github.com/cosmos/interchain-security/pull/826)
* [Consumer double voting handler PR](https://github.com/cosmos/interchain-security/pull/1232)
* [Architectural diagrams](https://docs.google.com/document/d/1fe1uSJl1ZIYWXoME3Yf4Aodvz7V597Ric875JH-rigM/edit#heading=h.rv4t8i6d6jfn)
* [ADR on equivocation slashing](https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-013-equivocation-slashing.md)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/tidwall/gjson v1.17.0
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sys v0.11.0 // indirect
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
Expand Down
15 changes: 15 additions & 0 deletions proto/interchain_security/ccv/consumer/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ option go_package = "github.com/cosmos/interchain-security/v3/x/ccv/consumer/typ

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "interchain_security/ccv/consumer/v1/consumer.proto";
import "interchain_security/ccv/v1/wire.proto";

service Query {
// ConsumerGenesis queries the genesis state needed to start a consumer chain
Expand All @@ -23,6 +25,11 @@ service Query {
rpc QueryProviderInfo(QueryProviderInfoRequest) returns (QueryProviderInfoResponse) {
option (google.api.http).get = "/interchain_security/ccv/consumer/provider-info";
}

// QueryThrottleState returns on-chain state relevant to throttled consumer packets
rpc QueryThrottleState(QueryThrottleStateRequest) returns (QueryThrottleStateResponse) {
option (google.api.http).get = "/interchain_security/ccv/consumer/throttle_state";
}
}

// NextFeeDistributionEstimate holds information about next fee distribution
Expand Down Expand Up @@ -64,6 +71,14 @@ message QueryProviderInfoResponse {
ChainInfo provider = 2 [ (gogoproto.nullable) = false ];
}

message QueryThrottleStateRequest {}

message QueryThrottleStateResponse {
SlashRecord slash_record = 1 [ (gogoproto.nullable) = true ];
repeated interchain_security.ccv.v1.ConsumerPacketData packet_data_queue = 2 [ (gogoproto.nullable) = false ];
}


message ChainInfo {
string chainID = 1;
string clientID = 2;
Expand Down
8 changes: 4 additions & 4 deletions proto/interchain_security/ccv/provider/v1/provider.proto
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ message GlobalSlashEntry {

// Params defines the parameters for CCV Provider module
message Params {

// Reserve 8th slot for removed max throttled packet param
reserved 8;

ibc.lightclients.tendermint.v1.ClientState template_client = 1;
// TrustingPeriodFraction is used to compute the consumer and provider IBC
// client's TrustingPeriod from the chain defined UnbondingPeriod
Expand Down Expand Up @@ -178,10 +182,6 @@ message Params {
// total voting power that the slash meter can hold.
string slash_meter_replenish_fraction = 7;

// The maximum amount of throttled slash or vsc matured packets
// that can be queued for a single consumer before the provider chain halts.
int64 max_throttled_packets = 8;

// The fee required to be paid to add a reward denom
cosmos.base.v1beta1.Coin consumer_reward_denom_registration_fee = 9
[ (gogoproto.nullable) = false ];
Expand Down
Loading

0 comments on commit 0e31c3b

Please sign in to comment.