Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update consumer BTC light client #112

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion contracts/babylon/src/ibc.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -252,6 +255,30 @@ pub(crate) mod ibc_packet {
Ok(resp)
}

pub fn handle_btc_headers(
deps: DepsMut,
_caller: String,
btc_headers: &BtcHeaders,
) -> StdResult<IbcReceiveResponse<BabylonMsg>> {
deps.api.debug(&format!("CONTRACT: Received BTC headers: {:?}", btc_headers));
let storage = deps.storage;
let cfg = CONFIG.load(storage)?;

let msg_option = crate::state::handle_btc_headers(storage, btc_headers)?;

let mut resp: IbcReceiveResponse<BabylonMsg> =
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);
}
}

Ok(resp)
}

pub fn slashing_msg(
env: &Env,
channel: &IbcChannel,
Expand Down
26 changes: 21 additions & 5 deletions contracts/babylon/src/state/mod.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -21,13 +20,15 @@ pub fn handle_btc_timestamp(
btc_ts: &BtcTimestamp,
) -> Result<Option<BabylonMsg>, 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}")))?;
}

Expand Down Expand Up @@ -76,3 +77,18 @@ pub fn handle_btc_timestamp(

Ok(None)
}

pub fn handle_btc_headers(
storage: &mut dyn Storage,
btc_headers: &BtcHeaders,
) -> Result<Option<BabylonMsg>, 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)
}
16 changes: 13 additions & 3 deletions packages/proto/src/gen/babylon.zoneconcierge.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<outbound_packet::Packet>,
}
/// Nested message and enum types in `OutboundPacket`.
Expand All @@ -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
Expand All @@ -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<super::super::btclightclient::v1::BtcHeaderInfo>,
}
/// 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.
Expand All @@ -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<super::super::btclightclient::v1::BtcHeaderInfo>,
#[prost(message, optional, tag="2")]
pub btc_headers: ::core::option::Option<BtcHeaders>,
//
// Data for Babylon epoch chain

Expand Down
Loading