Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianElvis committed Mar 4, 2025
1 parent 50ba8d7 commit 8613a22
Show file tree
Hide file tree
Showing 17 changed files with 1,040 additions and 0 deletions.
28 changes: 28 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions contracts/btc-light-client/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --bin schema"
63 changes: 63 additions & 0 deletions contracts/btc-light-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[package]
name = "btc-light-client"
edition.workspace = true
version.workspace = true
license.workspace = true
repository.workspace = true
authors.workspace = true
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]
# See https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options
bench = false
doctest = false

[[bin]]
name = "schema"
path = "src/bin/schema.rs"
bench = false
test = false

[features]
# Add feature "cranelift" to default if you need 32 bit or ARM support
default = []
# Use cranelift backend instead of singlepass. This is required for development on 32 bit or ARM machines.
cranelift = ["cosmwasm-vm/cranelift"]
# for quicker tests, cargo test --lib
library = []

[dependencies]
babylon-apis = { path = "../../packages/apis" }
babylon-bindings = { path = "../../packages/bindings" }
babylon-proto = { path = "../../packages/proto" }
babylon-bitcoin = { path = "../../packages/bitcoin" }
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw2 = { workspace = true }
cw-storage-plus = { workspace = true }
cw-utils = { workspace = true }
hex = { workspace = true }
thiserror = { workspace = true }
prost = { workspace = true }
serde = { workspace = true, features = ["derive"] }

[dev-dependencies]
babylon-bindings-test = { path = "../../packages/bindings-test" }
test-utils = { path = "../../packages/test-utils" }

cosmwasm-vm = { workspace = true }
cw-multi-test = { workspace = true }

anyhow = { workspace = true }
assert_matches = { workspace = true }
derivative = { workspace = true }
# bench dependencies
criterion = { workspace = true }
thousands = { workspace = true }

[[bench]]
name = "main"
harness = false
169 changes: 169 additions & 0 deletions contracts/btc-light-client/benches/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
//! This benchmark tries to run and call the generated wasm.
//! It depends on a Wasm build being available, which you can create by running `cargo optimize` in
//! the workspace root.
//! Then running `cargo bench` will validate we can properly call into that generated Wasm.
//!
use criterion::{criterion_group, criterion_main, Criterion, PlottingBackend};

use std::time::Duration;
use test_utils::get_btc_lc_mainchain_resp;
use thousands::Separable;

use cosmwasm_std::{Env, MessageInfo, Response};
use cosmwasm_vm::testing::{
execute, instantiate, mock_env, mock_info, mock_instance_with_gas_limit, MockApi, MockQuerier,
MockStorage,
};
use cosmwasm_vm::Instance;

use babylon_bindings::BabylonMsg;
use btc_light_client::msg::btc_header::BtcHeader;
use btc_light_client::msg::contract::{ExecuteMsg, InstantiateMsg};

// Output of `cargo optimize`
static WASM: &[u8] = include_bytes!("../../../artifacts/btc_light_client.wasm");

// From https://github.com/CosmWasm/wasmd/blob/7ea00e2ea858ed599141e322bd68171998a3259a/x/wasm/types/gas_register.go#L33
const GAS_MULTIPLIER: u64 = 140_000_000;

const CREATOR: &str = "creator";

#[track_caller]
pub fn get_main_msg_test_headers() -> Vec<BtcHeader> {
let res = get_btc_lc_mainchain_resp();
res.headers
.iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()
.unwrap()
}

#[track_caller]
pub fn setup_instance() -> Instance<MockApi, MockStorage, MockQuerier> {
let mut deps = mock_instance_with_gas_limit(WASM, 10_000_000_000_000);
let msg = InstantiateMsg {
network: babylon_bitcoin::chain_params::Network::Regtest,
btc_confirmation_depth: 10,
};
let info = mock_info(CREATOR, &[]);
let res: Response = instantiate(&mut deps, mock_env(), info, msg).unwrap();
assert_eq!(0, res.messages.len());
deps
}

#[track_caller]
fn setup_benchmark() -> (
Instance<MockApi, MockStorage, MockQuerier>,
MessageInfo,
Env,
Vec<BtcHeader>,
) {
let mut deps = setup_instance();
let info = mock_info(CREATOR, &[]);
let env = mock_env();

let test_headers = get_main_msg_test_headers();

let benchmark_msg = ExecuteMsg::InitBtcLightClient {
headers: test_headers[0..=1].to_owned(),
};

// init call
execute::<_, _, _, _, BabylonMsg>(&mut deps, env.clone(), info.clone(), benchmark_msg.clone())
.unwrap();
(deps, info, env, test_headers)
}

fn bench_btc_light_client(c: &mut Criterion) {
let mut group = c.benchmark_group("BTC Light Client");

group.bench_function("btc_headers_verify cpu", |b| {
let (mut deps, info, env, test_headers) = setup_benchmark();

let headers_len = test_headers.len();
let mut i = 1;
b.iter(|| {
let benchmark_msg = ExecuteMsg::UpdateBtcLightClient {
headers: test_headers[i..=i + 1].to_owned(),
};
execute::<_, _, _, _, BabylonMsg>(&mut deps, env.clone(), info.clone(), benchmark_msg)
.unwrap();
i = (i + 1) % (headers_len - 1);
});
});

group.bench_function("btc_headers_verify gas", |b| {
let (mut deps, info, env, test_headers) = setup_benchmark();

let headers_len = test_headers.len();
let mut i = 1;
b.iter_custom(|iter| {
let mut gas_used = 0;
for _ in 0..iter {
let benchmark_msg = ExecuteMsg::UpdateBtcLightClient {
headers: test_headers[i..=i + 1].to_owned(),
};
let gas_before = deps.get_gas_left();
execute::<_, _, _, _, BabylonMsg>(
&mut deps,
env.clone(),
info.clone(),
benchmark_msg,
)
.unwrap();
gas_used += gas_before - deps.get_gas_left();
i = (i + 1) % (headers_len - 1);
}
println!(
"BTC header avg call gas: {}",
(gas_used / (2 * iter)).separate_with_underscores()
);
Duration::new(0, gas_used as u32 / 2)
});
});

group.bench_function("btc_headers_verify SDK gas", |b| {
let (mut deps, info, env, test_headers) = setup_benchmark();

let headers_len = test_headers.len();
let mut i = 1;
b.iter_custom(|iter| {
let mut gas_used = 0;
for _ in 0..iter {
let benchmark_msg = ExecuteMsg::UpdateBtcLightClient {
headers: test_headers[i..=i + 1].to_owned(),
};
let gas_before = deps.get_gas_left();
execute::<_, _, _, _, BabylonMsg>(
&mut deps,
env.clone(),
info.clone(),
benchmark_msg,
)
.unwrap();
gas_used += (gas_before - deps.get_gas_left()) / GAS_MULTIPLIER;
i = (i + 1) % (headers_len - 1);
}
println!("BTC header avg call SDK gas: {}", gas_used / (2 * iter));
Duration::new(0, gas_used as u32 / 2)
});
});

group.finish();
}

fn make_config() -> Criterion {
Criterion::default()
.plotting_backend(PlottingBackend::Plotters)
.without_plots()
.warm_up_time(Duration::new(0, 1_000_000))
.measurement_time(Duration::new(0, 10_000_000))
.sample_size(10)
}

criterion_group!(
name = btc_light_client;
config = make_config();
targets = bench_btc_light_client
);
criterion_main!(btc_light_client);
11 changes: 11 additions & 0 deletions contracts/btc-light-client/src/bin/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_schema::write_api;

use btc_light_client::msg::contract::{ExecuteMsg, InstantiateMsg, QueryMsg};

fn main() {
write_api! {
instantiate: InstantiateMsg,
execute: ExecuteMsg,
query: QueryMsg,
}
}
Loading

0 comments on commit 8613a22

Please sign in to comment.