Skip to content

Commit

Permalink
feat: op consumer chain slashing (#92)
Browse files Browse the repository at this point in the history
## Summary

This PR implements slashing for op stack consumer chain.

It updates the cw contract as follows:

- allow FPs to equivocate by submitting mutiple signatures for a block
- add new state to index voted block hashes and equivocation evidences
- add new handlers to slash finality providers and send notifying
message to Babylon, similar to the Cosmos consumer chain implementation

It also updates and add a new test case. We need to add additional
integration tests to check the e2e flow with Babylon node.

## Test plan
```bash
# build the contract
cargo build
cargo optimize

# test it
cargo test
cargo integration
```
  • Loading branch information
parketh authored Dec 11, 2024
1 parent cecda61 commit 166fda9
Show file tree
Hide file tree
Showing 16 changed files with 285 additions and 76 deletions.
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ integration = "./scripts/integration_test.sh"

[workspace.dependencies]
anybuf = { version = "0.5.0" }
babylon-apis = { path = "./packages/apis" }
babylon-proto = { path = "./packages/proto" }
babylon-bitcoin = { path = "./packages/bitcoin" }
babylon-btcstaking = { path = "./packages/btcstaking" }
Expand Down
10 changes: 10 additions & 0 deletions contracts/op-finality-gadget/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ library = []
[dependencies]
babylon-apis = { path = "../../packages/apis" }
babylon-merkle = { path = "../../packages/merkle" }
babylon-bindings = { path = "../../packages/bindings" }
babylon-bitcoin = { path = "../../packages/bitcoin" }
babylon-proto = { path = "../../packages/proto" }
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw-controllers = { workspace = true }
Expand All @@ -33,8 +36,15 @@ eots = { path = "../../packages/eots" }
hex = { workspace = true }
k256 = { workspace = true }
thiserror = { workspace = true }
prost = { workspace = true }
anybuf = { workspace = true }

[dev-dependencies]
babylon-bindings-test = { path = "../../packages/bindings-test" }
btc-staking = { path = "../btc-staking", features = [ "library" ] }
cosmwasm-vm = { workspace = true }
test-utils = { path = "../../packages/test-utils" }
anyhow = { workspace = true }
derivative = { workspace = true }

cw-multi-test = { workspace = true }
11 changes: 7 additions & 4 deletions contracts/op-finality-gadget/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use crate::error::ContractError;
use crate::exec::admin::set_enabled;
use crate::exec::finality::{handle_finality_signature, handle_public_randomness_commit};
use crate::exec::finality::{
handle_finality_signature, handle_public_randomness_commit, handle_slashing,
};
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use crate::queries::{
query_block_voters, query_config, query_first_pub_rand_commit, query_last_pub_rand_commit,
};
use crate::state::config::{Config, ADMIN, CONFIG, IS_ENABLED};
use babylon_bindings::BabylonMsg;
use cosmwasm_std::{
to_json_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, StdResult,
};
Expand All @@ -16,7 +19,7 @@ pub fn instantiate(
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
) -> StdResult<Response<BabylonMsg>> {
let api = deps.api;
ADMIN.set(deps.branch(), Some(api.addr_validate(&msg.admin)?))?;
IS_ENABLED.save(deps.storage, &msg.is_enabled)?;
Expand Down Expand Up @@ -51,7 +54,7 @@ pub fn execute(
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
) -> Result<Response<BabylonMsg>, ContractError> {
let api = deps.api;

match msg {
Expand Down Expand Up @@ -86,6 +89,7 @@ pub fn execute(
&block_hash,
&signature,
),
ExecuteMsg::Slashing { evidence } => handle_slashing(&evidence),
ExecuteMsg::SetEnabled { enabled } => set_enabled(deps, info, enabled),
ExecuteMsg::UpdateAdmin { admin } => ADMIN
.execute_update_admin(deps, info, Some(api.addr_validate(&admin)?))
Expand Down Expand Up @@ -145,7 +149,6 @@ pub(crate) mod tests {
let mut deps = mock_dependencies();
let init_admin = deps.api.addr_make(INIT_ADMIN);
let new_admin = deps.api.addr_make(NEW_ADMIN);

// Create an InstantiateMsg with admin set to Some(INIT_ADMIN.into())
let instantiate_msg = InstantiateMsg {
admin: init_admin.to_string(), // Admin provided
Expand Down
12 changes: 12 additions & 0 deletions contracts/op-finality-gadget/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ pub enum ContractError {
HexError(#[from] FromHexError),
#[error("The inclusion proof for height {0} does not correspond to the given height ({1})")]
InvalidFinalitySigHeight(u64, u64),
#[error("Contract already has an open IBC channel")]
IbcChannelAlreadyOpen {},
#[error("The contract only supports ordered channels")]
IbcUnorderedChannel {},
#[error("Counterparty version must be `{version}`")]
IbcInvalidCounterPartyVersion { version: String },
#[error("IBC method is not supported")]
IbcUnsupportedMethod {},
#[error("IBC send timed out: dest: channel {0}, port {1}")]
IbcTimeout(String, String),
#[error("The total amount of public randomnesses in the proof ({0}) does not match the amount of public committed randomness ({1})")]
InvalidFinalitySigAmount(u64, u64),
#[error("The start height ({0}) has overlap with the height of the highest public randomness committed ({1})")]
Expand All @@ -30,6 +40,8 @@ pub enum ContractError {
MissingPubRandCommit(String, u64),
#[error("{0}")]
SecP256K1Error(String), // TODO: inherit errors from k256
#[error("Failed to extract secret key: {0}")]
SecretKeyExtractionError(String),
#[error("{0}")]
StdError(#[from] StdError),
#[error("Failed to query block voters for block {0} with hash {1}. {2}")]
Expand Down
3 changes: 2 additions & 1 deletion contracts/op-finality-gadget/src/exec/admin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use babylon_bindings::BabylonMsg;
use cosmwasm_std::{DepsMut, MessageInfo, Response};

use crate::{
Expand All @@ -14,7 +15,7 @@ pub fn set_enabled(
deps: DepsMut,
info: MessageInfo,
enabled: bool,
) -> Result<Response, ContractError> {
) -> Result<Response<BabylonMsg>, ContractError> {
// Check caller is admin
check_admin(&deps, info)?;
// Check if the finality gadget is already in the desired state
Expand Down
Loading

0 comments on commit 166fda9

Please sign in to comment.