diff --git a/contracts/op-finality-gadget/src/contract.rs b/contracts/op-finality-gadget/src/contract.rs index 714604d7..f0a1d085 100644 --- a/contracts/op-finality-gadget/src/contract.rs +++ b/contracts/op-finality-gadget/src/contract.rs @@ -82,6 +82,7 @@ pub fn execute( } => handle_finality_signature( deps, env, + info, &fp_pubkey_hex, height, &pub_rand, @@ -89,7 +90,7 @@ pub fn execute( &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)?)) diff --git a/contracts/op-finality-gadget/src/exec/finality.rs b/contracts/op-finality-gadget/src/exec/finality.rs index 3a255014..d0e5f07c 100644 --- a/contracts/op-finality-gadget/src/exec/finality.rs +++ b/contracts/op-finality-gadget/src/exec/finality.rs @@ -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}; @@ -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], @@ -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); } @@ -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> { @@ -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 { @@ -357,12 +362,22 @@ fn slash_finality_provider( Ok((wasm_msg, ev)) } -pub(crate) fn handle_slashing(evidence: &Evidence) -> Result, ContractError> { +pub(crate) fn handle_slashing( + sender: &Addr, + evidence: &Evidence, +) -> Result, 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 @@ -376,8 +391,9 @@ pub(crate) fn handle_slashing(evidence: &Evidence) -> Result(&msg).unwrap(); match msg_evidence { ExecuteMsg::Slashing { + sender: _, evidence: msg_evidence, } => { assert_eq!(evidence, msg_evidence); diff --git a/contracts/op-finality-gadget/src/msg.rs b/contracts/op-finality-gadget/src/msg.rs index 42436878..7b82a16d 100644 --- a/contracts/op-finality-gadget/src/msg.rs +++ b/contracts/op-finality-gadget/src/msg.rs @@ -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; @@ -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. diff --git a/packages/bindings/src/msg.rs b/packages/bindings/src/msg.rs index 9cb09eb7..3b3c8d39 100644 --- a/packages/bindings/src/msg.rs +++ b/packages/bindings/src/msg.rs @@ -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 @@ -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, + /// `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, + /// `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, + /// `canonical_app_hash` is the AppHash of the canonical block + canonical_app_hash: Vec, + /// `fork_app_hash` is the AppHash of the fork block + fork_app_hash: Vec, + /// `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, + /// `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, }, }