From ea2c4cbd8a33f39db5fda32e4590767f217e65d2 Mon Sep 17 00:00:00 2001 From: Gurjot Date: Wed, 12 Feb 2025 13:35:26 +0530 Subject: [PATCH 1/5] bump bbn --- packages/proto/babylon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/proto/babylon b/packages/proto/babylon index 847bf14..1494433 160000 --- a/packages/proto/babylon +++ b/packages/proto/babylon @@ -1 +1 @@ -Subproject commit 847bf148ca71374badf81676b258b812ec72337b +Subproject commit 1494433d89093b4fc6ce040fa004ba36a1dfbab5 From d93b2288e5ad3982b3b84aa06f4e4e19d8d02fc8 Mon Sep 17 00:00:00 2001 From: Gurjot Date: Wed, 12 Feb 2025 13:42:16 +0530 Subject: [PATCH 2/5] update proto --- .../proto/src/gen/babylon.zoneconcierge.v1.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/proto/src/gen/babylon.zoneconcierge.v1.rs b/packages/proto/src/gen/babylon.zoneconcierge.v1.rs index 3f33103..4a9735e 100644 --- a/packages/proto/src/gen/babylon.zoneconcierge.v1.rs +++ b/packages/proto/src/gen/babylon.zoneconcierge.v1.rs @@ -153,7 +153,7 @@ pub struct ProofFinalizedChainInfo { #[derive(Clone, PartialEq, ::prost::Message)] pub struct OutboundPacket { /// packet is the actual message carried in the IBC packet - #[prost(oneof="outbound_packet::Packet", tags="1, 2")] + #[prost(oneof="outbound_packet::Packet", tags="1, 2, 3")] pub packet: ::core::option::Option, } /// Nested message and enum types in `OutboundPacket`. @@ -166,6 +166,8 @@ pub mod outbound_packet { BtcTimestamp(super::BtcTimestamp), #[prost(message, tag="2")] BtcStaking(super::super::super::btcstaking::v1::BtcStakingIbcPacket), + #[prost(message, tag="3")] + BtcHeaders(super::BtcHeaders), } } /// InboundPacket represents packets received by Babylon from other chains @@ -186,6 +188,14 @@ pub mod inbound_packet { ConsumerSlashing(super::ConsumerSlashingIbcPacket), } } +/// BTCHeaders contains BTC headers that have been verified and inserted into Babylon's BTC light client +/// These headers are forwarded to consumer chains to keep their light clients in sync with Babylon +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BtcHeaders { + #[prost(message, repeated, tag="1")] + pub headers: ::prost::alloc::vec::Vec, +} /// BTCTimestamp is a BTC timestamp that carries information of a BTC-finalised epoch /// It includes a number of BTC headers, a raw checkpoint, an epoch metadata, and /// a CZ header if there exists CZ headers checkpointed to this epoch. @@ -204,8 +214,8 @@ pub struct BtcTimestamp { /// - the block AFTER the common ancestor of BTC tip at epoch `lastFinalizedEpoch-1` and BTC tip at epoch `lastFinalizedEpoch` /// - BTC tip at epoch `lastFinalizedEpoch` /// where `lastFinalizedEpoch` is the last finalised epoch in Babylon - #[prost(message, repeated, tag="2")] - pub btc_headers: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub btc_headers: ::core::option::Option, // // Data for Babylon epoch chain From c930cea9fb7a13accd63678c8b176e58b1beda21 Mon Sep 17 00:00:00 2001 From: Gurjot Date: Wed, 12 Feb 2025 13:59:34 +0530 Subject: [PATCH 3/5] ingest new btc headers type --- contracts/babylon/src/ibc.rs | 22 +++++++++++++++++++++- contracts/babylon/src/state/mod.rs | 8 +++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/contracts/babylon/src/ibc.rs b/contracts/babylon/src/ibc.rs index 4a3732e..9252357 100644 --- a/contracts/babylon/src/ibc.rs +++ b/contracts/babylon/src/ibc.rs @@ -1,7 +1,7 @@ use crate::error::ContractError; use babylon_bindings::BabylonMsg; use babylon_proto::babylon::zoneconcierge::v1::{ - outbound_packet::Packet as OutboundPacketType, BtcTimestamp, OutboundPacket, + outbound_packet::Packet as OutboundPacketType, BtcTimestamp, OutboundPacket, BtcHeaders, }; use crate::state::config::CONFIG; @@ -138,6 +138,9 @@ pub fn ibc_packet_receive( OutboundPacketType::BtcStaking(btc_staking) => { ibc_packet::handle_btc_staking(deps, caller, &btc_staking) } + OutboundPacketType::BtcHeaders(btc_headers) => { + ibc_packet::handle_btc_headers(deps, caller, &btc_headers) + } } })() .or_else(|e| { @@ -252,6 +255,23 @@ pub(crate) mod ibc_packet { Ok(resp) } + pub fn handle_btc_headers( + deps: DepsMut, + _caller: String, + btc_headers: &BtcHeaders, + ) -> StdResult> { + deps.api.debug(&format!("CONTRACT: Received BTC headers: {:?}", btc_headers)); + + // construct response + let mut resp: IbcReceiveResponse = + IbcReceiveResponse::new(StdAck::success(vec![])); + + // add attribute to response + resp = resp.add_attribute("action", "handle_btc_headers"); + + Ok(resp) + } + pub fn slashing_msg( env: &Env, channel: &IbcChannel, diff --git a/contracts/babylon/src/state/mod.rs b/contracts/babylon/src/state/mod.rs index 1ac75aa..2fb8c4b 100644 --- a/contracts/babylon/src/state/mod.rs +++ b/contracts/babylon/src/state/mod.rs @@ -21,13 +21,15 @@ pub fn handle_btc_timestamp( btc_ts: &BtcTimestamp, ) -> Result, StdError> { // extract and init/handle BTC headers - let btc_headers = &btc_ts.btc_headers; + let btc_headers = btc_ts.btc_headers.as_ref() + .ok_or_else(|| StdError::generic_err("btc_headers is None"))?; + if btc_light_client::is_initialized(storage) { - btc_light_client::handle_btc_headers_from_babylon(storage, btc_headers).map_err(|e| { + btc_light_client::handle_btc_headers_from_babylon(storage, &btc_headers.headers).map_err(|e| { StdError::generic_err(format!("failed to handle BTC headers from Babylon: {e}")) })?; } else { - btc_light_client::init(storage, btc_headers) + btc_light_client::init(storage, &btc_headers.headers) .map_err(|e| StdError::generic_err(format!("failed to initialize BTC headers: {e}")))?; } From b46fb141ebee7098539be30ab46445687ff88f68 Mon Sep 17 00:00:00 2001 From: Gurjot Date: Wed, 12 Feb 2025 16:49:47 +0530 Subject: [PATCH 4/5] handle btc headers --- contracts/babylon/src/ibc.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/contracts/babylon/src/ibc.rs b/contracts/babylon/src/ibc.rs index 9252357..6197f9e 100644 --- a/contracts/babylon/src/ibc.rs +++ b/contracts/babylon/src/ibc.rs @@ -155,6 +155,7 @@ pub fn ibc_packet_receive( pub(crate) mod ibc_packet { use super::*; use crate::state::config::CONFIG; + use crate::state::btc_light_client; use babylon_apis::btc_staking_api::SlashedBtcDelegation; use babylon_apis::btc_staking_api::{ ActiveBtcDelegation, NewFinalityProvider, UnbondedBtcDelegation, @@ -261,15 +262,19 @@ pub(crate) mod ibc_packet { btc_headers: &BtcHeaders, ) -> StdResult> { deps.api.debug(&format!("CONTRACT: Received BTC headers: {:?}", btc_headers)); - - // construct response - let mut resp: IbcReceiveResponse = - IbcReceiveResponse::new(StdAck::success(vec![])); + + if btc_light_client::is_initialized(deps.storage) { + btc_light_client::handle_btc_headers_from_babylon(deps.storage, &btc_headers.headers) + .map_err(|e| StdError::generic_err(format!("failed to handle BTC headers from Babylon: {e}")))?; + } else { + btc_light_client::init(deps.storage, &btc_headers.headers) + .map_err(|e| StdError::generic_err(format!("failed to initialize BTC headers: {e}")))?; + } - // add attribute to response - resp = resp.add_attribute("action", "handle_btc_headers"); - - Ok(resp) + let resp = IbcReceiveResponse::new(StdAck::success(vec![])) + .add_attribute("action", "handle_btc_headers"); + + Ok(resp) } pub fn slashing_msg( From e89ce3948da78c8b20d233abcfdd5fc852ea1873 Mon Sep 17 00:00:00 2001 From: Gurjot Date: Wed, 12 Feb 2025 17:05:00 +0530 Subject: [PATCH 5/5] fix btc headers --- contracts/babylon/src/ibc.rs | 26 ++++++++++++++------------ contracts/babylon/src/state/mod.rs | 18 ++++++++++++++++-- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/contracts/babylon/src/ibc.rs b/contracts/babylon/src/ibc.rs index 6197f9e..bbfc9df 100644 --- a/contracts/babylon/src/ibc.rs +++ b/contracts/babylon/src/ibc.rs @@ -155,7 +155,6 @@ pub fn ibc_packet_receive( pub(crate) mod ibc_packet { use super::*; use crate::state::config::CONFIG; - use crate::state::btc_light_client; use babylon_apis::btc_staking_api::SlashedBtcDelegation; use babylon_apis::btc_staking_api::{ ActiveBtcDelegation, NewFinalityProvider, UnbondedBtcDelegation, @@ -262,18 +261,21 @@ pub(crate) mod ibc_packet { btc_headers: &BtcHeaders, ) -> StdResult> { deps.api.debug(&format!("CONTRACT: Received BTC headers: {:?}", btc_headers)); - - if btc_light_client::is_initialized(deps.storage) { - btc_light_client::handle_btc_headers_from_babylon(deps.storage, &btc_headers.headers) - .map_err(|e| StdError::generic_err(format!("failed to handle BTC headers from Babylon: {e}")))?; - } else { - btc_light_client::init(deps.storage, &btc_headers.headers) - .map_err(|e| StdError::generic_err(format!("failed to initialize BTC headers: {e}")))?; + let storage = deps.storage; + let cfg = CONFIG.load(storage)?; + + let msg_option = crate::state::handle_btc_headers(storage, btc_headers)?; + + let mut resp: IbcReceiveResponse = + IbcReceiveResponse::new(StdAck::success(vec![])); // TODO: design response format + resp = resp.add_attribute("action", "receive_btc_headers"); + + if let Some(msg) = msg_option { + if cfg.notify_cosmos_zone { + resp = resp.add_message(msg); + } } - - let resp = IbcReceiveResponse::new(StdAck::success(vec![])) - .add_attribute("action", "handle_btc_headers"); - + Ok(resp) } diff --git a/contracts/babylon/src/state/mod.rs b/contracts/babylon/src/state/mod.rs index 2fb8c4b..12be0b3 100644 --- a/contracts/babylon/src/state/mod.rs +++ b/contracts/babylon/src/state/mod.rs @@ -1,8 +1,7 @@ //! state is the module that manages smart contract's system state use cosmwasm_std::{StdError, Storage}; -use babylon_proto::babylon::zoneconcierge::v1::BtcTimestamp; - +use babylon_proto::babylon::zoneconcierge::v1::{BtcTimestamp, BtcHeaders}; use crate::bindings::msg_btc_finalized_header; use babylon_bindings::BabylonMsg; @@ -78,3 +77,18 @@ pub fn handle_btc_timestamp( Ok(None) } + +pub fn handle_btc_headers( + storage: &mut dyn Storage, + btc_headers: &BtcHeaders, +) -> Result, StdError> { + if btc_light_client::is_initialized(storage) { + btc_light_client::handle_btc_headers_from_babylon(storage, &btc_headers.headers) + .map_err(|e| StdError::generic_err(format!("failed to handle BTC headers: {e}")))?; + } else { + btc_light_client::init(storage, &btc_headers.headers) + .map_err(|e| StdError::generic_err(format!("failed to initialize BTC headers: {e}")))?; + } + + Ok(None) +}