Skip to content

Commit

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

This is a follow-on PR from
#92 (implement
slashing for op stack consumer chains)

It updates the `EquivocationEvidence` msg to match the latest Babylon
update

## Test plan

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

# test it
cargo test
cargo integration
```
  • Loading branch information
parketh authored Dec 19, 2024
1 parent 84130eb commit 3e9f03d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 15 deletions.
3 changes: 2 additions & 1 deletion contracts/op-finality-gadget/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ pub fn execute(
} => handle_finality_signature(
deps,
env,
info,
&fp_pubkey_hex,
height,
&pub_rand,
&proof,
&block_hash,
&signature,
),
ExecuteMsg::Slashing { evidence } => handle_slashing(&evidence),
ExecuteMsg::Slashing { sender, evidence } => handle_slashing(&sender, &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
31 changes: 24 additions & 7 deletions contracts/op-finality-gadget/src/exec/finality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use babylon_bindings::BabylonMsg;

use babylon_apis::finality_api::{Evidence, PubRandCommit};
use babylon_merkle::Proof;
use cosmwasm_std::{to_json_binary, Deps, DepsMut, Env, Event, Response, WasmMsg};
use cosmwasm_std::{
to_json_binary, Addr, Deps, DepsMut, Env, Event, MessageInfo, Response, WasmMsg,
};
use k256::ecdsa::signature::Verifier;
use k256::schnorr::{Signature, VerifyingKey};
use k256::sha2::{Digest, Sha256};
Expand Down Expand Up @@ -114,6 +116,7 @@ pub(crate) fn verify_commitment_signature(
pub fn handle_finality_signature(
deps: DepsMut,
env: Env,
info: MessageInfo,
fp_btc_pk_hex: &str,
height: u64,
pub_rand: &[u8],
Expand Down Expand Up @@ -211,7 +214,7 @@ pub fn handle_finality_signature(

// slash this finality provider, including setting its voting power to
// zero, extracting its BTC SK, and emit an event
let (msg, ev) = slash_finality_provider(&env, fp_btc_pk_hex, &evidence)?;
let (msg, ev) = slash_finality_provider(&env, &info, fp_btc_pk_hex, &evidence)?;
res = res.add_message(msg);
res = res.add_event(ev);
}
Expand Down Expand Up @@ -311,6 +314,7 @@ fn check_fp_exist(deps: Deps, fp_pubkey_hex: &str) -> Result<(), ContractError>
/// its voting power to zero, extracting its BTC SK, and emitting an event
fn slash_finality_provider(
env: &Env,
info: &MessageInfo,
fp_btc_pk_hex: &str,
evidence: &Evidence,
) -> Result<(WasmMsg, Event), ContractError> {
Expand All @@ -328,6 +332,7 @@ fn slash_finality_provider(
// Emit slashing event.
// Raises slashing event to babylon over IBC.
let msg = ExecuteMsg::Slashing {
sender: info.sender.clone(),
evidence: evidence.clone(),
};
let wasm_msg: WasmMsg = WasmMsg::Execute {
Expand Down Expand Up @@ -357,12 +362,22 @@ fn slash_finality_provider(
Ok((wasm_msg, ev))
}

pub(crate) fn handle_slashing(evidence: &Evidence) -> Result<Response<BabylonMsg>, ContractError> {
pub(crate) fn handle_slashing(
sender: &Addr,
evidence: &Evidence,
) -> Result<Response<BabylonMsg>, ContractError> {
let mut res = Response::new();
// Send msg to Babylon

let msg = BabylonMsg::EquivocationEvidence {
evidence: Some(evidence.clone()),
signer: sender.to_string(),
fp_btc_pk: evidence.fp_btc_pk.clone(),
block_height: evidence.block_height,
pub_rand: evidence.pub_rand.clone(),
canonical_app_hash: evidence.canonical_app_hash.clone(),
fork_app_hash: evidence.fork_app_hash.clone(),
canonical_finality_sig: evidence.canonical_finality_sig.clone(),
fork_finality_sig: evidence.fork_finality_sig.clone(),
};

// Convert to CosmosMsg
Expand All @@ -376,8 +391,9 @@ pub(crate) fn handle_slashing(evidence: &Evidence) -> Result<Response<BabylonMsg
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use cosmwasm_std::from_json;
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::Addr;
use cosmwasm_std::{from_json, testing::message_info};
use std::collections::HashMap;

use babylon_apis::finality_api::PubRandCommit;
Expand Down Expand Up @@ -471,9 +487,9 @@ pub(crate) mod tests {

// Create mock environment
let env = mock_env(); // You'll need to add this mock helper

let info = message_info(&Addr::unchecked("test"), &[]);
// Test slash_finality_provider
let (wasm_msg, event) = slash_finality_provider(&env, &pk_hex, &evidence).unwrap();
let (wasm_msg, event) = slash_finality_provider(&env, &info, &pk_hex, &evidence).unwrap();

// Verify the WasmMsg is correctly constructed
match wasm_msg {
Expand All @@ -487,6 +503,7 @@ pub(crate) mod tests {
let msg_evidence = from_json::<ExecuteMsg>(&msg).unwrap();
match msg_evidence {
ExecuteMsg::Slashing {
sender: _,
evidence: msg_evidence,
} => {
assert_eq!(evidence, msg_evidence);
Expand Down
3 changes: 2 additions & 1 deletion contracts/op-finality-gadget/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use {

use babylon_apis::finality_api::Evidence;
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::Binary;
use cosmwasm_std::{Addr, Binary};

use babylon_merkle::Proof;

Expand Down Expand Up @@ -80,6 +80,7 @@ pub enum ExecuteMsg {
///
/// This message can be called by the admin only.
Slashing {
sender: Addr,
evidence: Evidence,
},
/// Enable or disable finality gadget.
Expand Down
33 changes: 27 additions & 6 deletions packages/bindings/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//! - ForkHeader: reporting a fork that has a valid quorum certificate
//! - FinalizedHeader: reporting a BTC-finalised header.
use babylon_apis::finality_api::Evidence;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, CosmosMsg, Empty};

/// BabylonMsg is the message that the Babylon contract can send to the Cosmos zone.
/// The Cosmos zone has to integrate https://github.com/babylonlabs-io/wasmbinding for
/// handling these messages
Expand All @@ -21,12 +21,33 @@ pub enum BabylonMsg {
/// It can only be sent from the finality contract.
/// The rewards are minted to the staking contract address, so that they
/// can be distributed across the active finality provider set
MintRewards {
amount: Coin,
recipient: String,
},
MintRewards { amount: Coin, recipient: String },
/// EquivocationEvidence is the message that the Babylon contract sends to Babylon
/// to notify it of consumer chain slashing.
EquivocationEvidence {
evidence: Option<Evidence>,
/// `signer` is the address submitting the evidence
signer: String,
/// `fp_btc_pk` is the BTC PK of the finality provider that casts this vote
fp_btc_pk: Vec<u8>,
/// `block_height` is the height of the conflicting blocks
block_height: u64,
/// `pub_rand is` the public randomness the finality provider has committed to.
/// Deserializes to `SchnorrPubRand`
pub_rand: Vec<u8>,
/// `canonical_app_hash` is the AppHash of the canonical block
canonical_app_hash: Vec<u8>,
/// `fork_app_hash` is the AppHash of the fork block
fork_app_hash: Vec<u8>,
/// `canonical_finality_sig` is the finality signature to the canonical block,
/// where finality signature is an EOTS signature, i.e.,
/// the `s` in a Schnorr signature `(r, s)`.
/// `r` is the public randomness already committed by the finality provider.
/// Deserializes to `SchnorrEOTSSig`
canonical_finality_sig: Vec<u8>,
/// `fork_finality_sig` is the finality signature to the fork block,
/// where finality signature is an EOTS signature.
/// Deserializes to `SchnorrEOTSSig`
fork_finality_sig: Vec<u8>,
},
}

Expand Down

0 comments on commit 3e9f03d

Please sign in to comment.