Skip to content

Commit 976b919

Browse files
authored
feat: op consumer chain slashing (#92)
## 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 ```
1 parent 95a2db7 commit 976b919

File tree

9 files changed

+251
-72
lines changed

9 files changed

+251
-72
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ integration = "./scripts/integration_test.sh"
2222

2323
[workspace.dependencies]
2424
anybuf = { version = "0.5.0" }
25+
babylon-apis = { path = "./packages/apis" }
2526
babylon-proto = { path = "./packages/proto" }
2627
babylon-bitcoin = { path = "./packages/bitcoin" }
2728
babylon-btcstaking = { path = "./packages/btcstaking" }

contracts/op-finality-gadget/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ library = []
2424
[dependencies]
2525
babylon-apis = { path = "../../packages/apis" }
2626
babylon-merkle = { path = "../../packages/merkle" }
27+
babylon-bindings = { path = "../../packages/bindings" }
28+
babylon-bitcoin = { path = "../../packages/bitcoin" }
29+
babylon-proto = { path = "../../packages/proto" }
2730
cosmwasm-schema = { workspace = true }
2831
cosmwasm-std = { workspace = true }
2932
cw-controllers = { workspace = true }
@@ -33,8 +36,15 @@ eots = { path = "../../packages/eots" }
3336
hex = { workspace = true }
3437
k256 = { workspace = true }
3538
thiserror = { workspace = true }
39+
prost = { workspace = true }
3640
anybuf = { workspace = true }
3741

3842
[dev-dependencies]
43+
babylon-bindings-test = { path = "../../packages/bindings-test" }
44+
btc-staking = { path = "../btc-staking", features = [ "library" ] }
3945
cosmwasm-vm = { workspace = true }
4046
test-utils = { path = "../../packages/test-utils" }
47+
anyhow = { workspace = true }
48+
derivative = { workspace = true }
49+
50+
cw-multi-test = { workspace = true }

contracts/op-finality-gadget/src/contract.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use crate::error::ContractError;
22
use crate::exec::admin::set_enabled;
3-
use crate::exec::finality::{handle_finality_signature, handle_public_randomness_commit};
3+
use crate::exec::finality::{
4+
handle_finality_signature, handle_public_randomness_commit, handle_slashing,
5+
};
46
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
57
use crate::queries::{
68
query_block_voters, query_config, query_first_pub_rand_commit, query_last_pub_rand_commit,
79
};
810
use crate::state::config::{Config, ADMIN, CONFIG, IS_ENABLED};
11+
use babylon_bindings::BabylonMsg;
912
use cosmwasm_std::{
1013
to_json_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, StdResult,
1114
};
@@ -16,7 +19,7 @@ pub fn instantiate(
1619
_env: Env,
1720
_info: MessageInfo,
1821
msg: InstantiateMsg,
19-
) -> StdResult<Response> {
22+
) -> StdResult<Response<BabylonMsg>> {
2023
let api = deps.api;
2124
ADMIN.set(deps.branch(), Some(api.addr_validate(&msg.admin)?))?;
2225
IS_ENABLED.save(deps.storage, &msg.is_enabled)?;
@@ -51,7 +54,7 @@ pub fn execute(
5154
env: Env,
5255
info: MessageInfo,
5356
msg: ExecuteMsg,
54-
) -> Result<Response, ContractError> {
57+
) -> Result<Response<BabylonMsg>, ContractError> {
5558
let api = deps.api;
5659

5760
match msg {
@@ -86,6 +89,7 @@ pub fn execute(
8689
&block_hash,
8790
&signature,
8891
),
92+
ExecuteMsg::Slashing { evidence } => handle_slashing(&evidence),
8993
ExecuteMsg::SetEnabled { enabled } => set_enabled(deps, info, enabled),
9094
ExecuteMsg::UpdateAdmin { admin } => ADMIN
9195
.execute_update_admin(deps, info, Some(api.addr_validate(&admin)?))
@@ -145,7 +149,6 @@ pub(crate) mod tests {
145149
let mut deps = mock_dependencies();
146150
let init_admin = deps.api.addr_make(INIT_ADMIN);
147151
let new_admin = deps.api.addr_make(NEW_ADMIN);
148-
149152
// Create an InstantiateMsg with admin set to Some(INIT_ADMIN.into())
150153
let instantiate_msg = InstantiateMsg {
151154
admin: init_admin.to_string(), // Admin provided

contracts/op-finality-gadget/src/error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ pub enum ContractError {
1818
HexError(#[from] FromHexError),
1919
#[error("The inclusion proof for height {0} does not correspond to the given height ({1})")]
2020
InvalidFinalitySigHeight(u64, u64),
21+
#[error("Contract already has an open IBC channel")]
22+
IbcChannelAlreadyOpen {},
23+
#[error("The contract only supports ordered channels")]
24+
IbcUnorderedChannel {},
25+
#[error("Counterparty version must be `{version}`")]
26+
IbcInvalidCounterPartyVersion { version: String },
27+
#[error("IBC method is not supported")]
28+
IbcUnsupportedMethod {},
29+
#[error("IBC send timed out: dest: channel {0}, port {1}")]
30+
IbcTimeout(String, String),
2131
#[error("The total amount of public randomnesses in the proof ({0}) does not match the amount of public committed randomness ({1})")]
2232
InvalidFinalitySigAmount(u64, u64),
2333
#[error("The start height ({0}) has overlap with the height of the highest public randomness committed ({1})")]
@@ -30,6 +40,8 @@ pub enum ContractError {
3040
MissingPubRandCommit(String, u64),
3141
#[error("{0}")]
3242
SecP256K1Error(String), // TODO: inherit errors from k256
43+
#[error("Failed to extract secret key: {0}")]
44+
SecretKeyExtractionError(String),
3345
#[error("{0}")]
3446
StdError(#[from] StdError),
3547
#[error("Failed to query block voters for block {0} with hash {1}. {2}")]

contracts/op-finality-gadget/src/exec/admin.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use babylon_bindings::BabylonMsg;
12
use cosmwasm_std::{DepsMut, MessageInfo, Response};
23

34
use crate::{
@@ -14,7 +15,7 @@ pub fn set_enabled(
1415
deps: DepsMut,
1516
info: MessageInfo,
1617
enabled: bool,
17-
) -> Result<Response, ContractError> {
18+
) -> Result<Response<BabylonMsg>, ContractError> {
1819
// Check caller is admin
1920
check_admin(&deps, info)?;
2021
// Check if the finality gadget is already in the desired state

0 commit comments

Comments
 (0)