Skip to content

Commit 2e3b0f1

Browse files
committed
Add basic coin-store bench
1 parent 82493f4 commit 2e3b0f1

File tree

6 files changed

+305
-1
lines changed

6 files changed

+305
-1
lines changed

crates/coin-store/Cargo.toml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ categories.workspace = true
1616
simplicityhl = { workspace = true }
1717
contracts = { workspace = true }
1818

19+
simplicityhl-core = { workspace = true }
20+
1921
sha2 = { version = "0.10.9" }
2022

2123
futures = { version = "0.3" }
@@ -29,4 +31,22 @@ sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "migrate"] }
2931
bincode = { version = "2.0.1", features = ["alloc", "derive", "serde"] }
3032

3133
[dev-dependencies]
32-
hex = { version = "0.4.3" }
34+
35+
criterion = { version = "0.5", features = ["async_tokio"] }
36+
tokio = { version = "1", features = ["full"] }
37+
38+
[[bench]]
39+
name = "default"
40+
harness = false
41+
42+
[[bench]]
43+
name = "entropy"
44+
harness = false
45+
46+
[[bench]]
47+
name = "contracts"
48+
harness = false
49+
50+
[[bench]]
51+
name = "token"
52+
harness = false
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
use std::collections::HashMap;
2+
use std::fs;
3+
use std::str::FromStr;
4+
5+
use coin_store::executor::UtxoStore;
6+
use coin_store::filter::UtxoFilter;
7+
use coin_store::store::Store;
8+
9+
use simplicityhl::elements::confidential::{Asset, Nonce, Value as ConfidentialValue};
10+
use simplicityhl::elements::hashes::Hash;
11+
use simplicityhl::elements::pset::PartiallySignedTransaction;
12+
use simplicityhl::elements::secp256k1_zkp::SecretKey;
13+
use simplicityhl::elements::{AddressParams, AssetId, OutPoint, Script, Transaction, TxOut, TxOutWitness, Txid};
14+
use simplicityhl::simplicity::bitcoin::key::Keypair;
15+
use simplicityhl::simplicity::bitcoin::secp256k1::Secp256k1;
16+
17+
use simplicityhl_core::{LIQUID_TESTNET_BITCOIN_ASSET, LIQUID_TESTNET_TEST_ASSET_ID_STR};
18+
19+
use contracts::options::OPTION_SOURCE;
20+
use contracts::options::OptionsArguments;
21+
use contracts::sdk::build_option_creation;
22+
use contracts::sdk::taproot_pubkey_gen::{TaprootPubkeyGen, get_random_seed};
23+
24+
fn setup_tx_and_contract(
25+
keypair: &Keypair,
26+
start_time: u32,
27+
expiry_time: u32,
28+
collateral_per_contract: u64,
29+
settlement_per_contract: u64,
30+
) -> Result<((PartiallySignedTransaction, TaprootPubkeyGen), OptionsArguments), Box<dyn std::error::Error>> {
31+
let option_outpoint = OutPoint::new(Txid::from_slice(&[1; 32])?, 0);
32+
let grantor_outpoint = OutPoint::new(Txid::from_slice(&[2; 32])?, 0);
33+
34+
let issuance_asset_entropy = get_random_seed();
35+
36+
let option_arguments = OptionsArguments::new(
37+
start_time,
38+
expiry_time,
39+
collateral_per_contract,
40+
settlement_per_contract,
41+
*LIQUID_TESTNET_BITCOIN_ASSET,
42+
AssetId::from_str(LIQUID_TESTNET_TEST_ASSET_ID_STR)?,
43+
issuance_asset_entropy,
44+
(option_outpoint, false),
45+
(grantor_outpoint, false),
46+
);
47+
48+
let pst_and_tpg = build_option_creation(
49+
&keypair.public_key(),
50+
(
51+
option_outpoint,
52+
TxOut {
53+
asset: Asset::Explicit(*LIQUID_TESTNET_BITCOIN_ASSET),
54+
value: ConfidentialValue::Explicit(500),
55+
nonce: Nonce::Null,
56+
script_pubkey: Script::new(),
57+
witness: TxOutWitness::default(),
58+
},
59+
),
60+
(
61+
grantor_outpoint,
62+
TxOut {
63+
asset: Asset::Explicit(*LIQUID_TESTNET_BITCOIN_ASSET),
64+
value: ConfidentialValue::Explicit(1000),
65+
nonce: Nonce::Null,
66+
script_pubkey: Script::new(),
67+
witness: TxOutWitness::default(),
68+
},
69+
),
70+
&option_arguments,
71+
issuance_asset_entropy,
72+
100,
73+
&AddressParams::LIQUID_TESTNET,
74+
)?;
75+
76+
Ok((pst_and_tpg, option_arguments))
77+
}
78+
79+
pub async fn setup_db() -> (
80+
Store,
81+
(Vec<UtxoFilter>, Vec<UtxoFilter>, Vec<UtxoFilter>, Vec<UtxoFilter>),
82+
String,
83+
) {
84+
let path = "/tmp/benchmark_stress.db";
85+
let _ = fs::remove_file(path);
86+
87+
let mut filters_default = vec![];
88+
let mut filters_contracts = vec![];
89+
let mut filters_tokens = vec![];
90+
let mut filters_entropy = vec![];
91+
let store = Store::create(path).await.unwrap();
92+
93+
for _i in 0..10 {
94+
let secp = Secp256k1::new();
95+
let keypair = Keypair::from_secret_key(&secp, &SecretKey::from_slice(&[1u8; 32]).unwrap());
96+
let secret_key = keypair.secret_key();
97+
98+
let ((pst, tpg), opts_args) = setup_tx_and_contract(&keypair, 0, 0, 20, 25).unwrap();
99+
let tx: Transaction = pst.extract_tx().unwrap();
100+
101+
let mut blinder_keys = HashMap::new();
102+
for (i, _output) in tx.output.iter().enumerate() {
103+
blinder_keys.insert(i, keypair);
104+
}
105+
store.insert_transaction(&tx, blinder_keys).await.unwrap();
106+
107+
let source_code = OPTION_SOURCE;
108+
109+
let args = opts_args.build_option_arguments();
110+
111+
let tpg_for_db = tpg.clone();
112+
let tpg_for_filter = tpg.clone();
113+
let tpg_for_token = tpg;
114+
115+
store.add_contract(source_code, args, tpg_for_db, None).await.unwrap();
116+
117+
let option_asset_id = opts_args.option_token();
118+
119+
store
120+
.insert_contract_token(&tpg_for_token.clone(), option_asset_id, "Name of token")
121+
.await
122+
.expect("");
123+
124+
for output in tx.output.iter() {
125+
let asset_id = match output.asset {
126+
Asset::Explicit(id) => id,
127+
128+
Asset::Confidential(_) => {
129+
let unblinded = output.unblind(&secp, secret_key).expect("Missing blinding key");
130+
unblinded.asset
131+
}
132+
133+
_ => panic!("Match error"),
134+
};
135+
136+
filters_default.push(UtxoFilter::new().asset_id(asset_id).required_value(1));
137+
138+
filters_entropy.push(UtxoFilter::new().asset_id(asset_id).required_value(1).include_entropy());
139+
140+
filters_contracts.push(
141+
UtxoFilter::new()
142+
.asset_id(asset_id)
143+
.required_value(1)
144+
.include_entropy()
145+
.taproot_pubkey_gen(tpg_for_filter.clone()),
146+
);
147+
148+
filters_tokens.push(
149+
UtxoFilter::new()
150+
.asset_id(asset_id)
151+
.required_value(1)
152+
.include_entropy()
153+
.taproot_pubkey_gen(tpg_for_filter.clone())
154+
.token_tag("Name of token"),
155+
);
156+
}
157+
}
158+
159+
(
160+
store,
161+
(filters_default, filters_entropy, filters_contracts, filters_tokens),
162+
path.to_string(),
163+
)
164+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use criterion::{Criterion, black_box, criterion_group, criterion_main};
2+
use std::fs;
3+
use tokio::runtime::Runtime;
4+
5+
use coin_store::executor::UtxoStore;
6+
7+
mod common;
8+
9+
fn criterion_benchmark(c: &mut Criterion) {
10+
let rt = Runtime::new().unwrap();
11+
12+
let (store, filters, db_path) = rt.block_on(async { common::setup_db().await });
13+
14+
let mut group = c.benchmark_group("UTXO Queries (with contracts)");
15+
group.sample_size(10);
16+
group.measurement_time(std::time::Duration::from_secs(10));
17+
18+
group.bench_function("current_implementation", |b| {
19+
b.to_async(&rt).iter(|| async {
20+
store.query_utxos(black_box(&filters.2)).await.unwrap();
21+
})
22+
});
23+
24+
group.finish();
25+
26+
let _ = fs::remove_file(db_path);
27+
}
28+
29+
criterion_group!(benches, criterion_benchmark);
30+
criterion_main!(benches);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use criterion::{Criterion, black_box, criterion_group, criterion_main};
2+
use std::fs;
3+
use tokio::runtime::Runtime;
4+
5+
use coin_store::executor::UtxoStore;
6+
7+
mod common;
8+
9+
fn criterion_benchmark(c: &mut Criterion) {
10+
let rt = Runtime::new().unwrap();
11+
12+
let (store, filters, db_path) = rt.block_on(async { common::setup_db().await });
13+
14+
let mut group = c.benchmark_group("UTXO Queries (default)");
15+
group.sample_size(10);
16+
group.measurement_time(std::time::Duration::from_secs(10));
17+
18+
group.bench_function("current_implementation", |b| {
19+
b.to_async(&rt).iter(|| async {
20+
store.query_utxos(black_box(&filters.0)).await.unwrap();
21+
})
22+
});
23+
24+
group.finish();
25+
26+
let _ = fs::remove_file(db_path);
27+
}
28+
29+
criterion_group!(benches, criterion_benchmark);
30+
criterion_main!(benches);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use criterion::{Criterion, black_box, criterion_group, criterion_main};
2+
use std::fs;
3+
use tokio::runtime::Runtime;
4+
5+
use coin_store::executor::UtxoStore;
6+
7+
mod common;
8+
9+
fn criterion_benchmark(c: &mut Criterion) {
10+
let rt = Runtime::new().unwrap();
11+
12+
let (store, filters, db_path) = rt.block_on(async { common::setup_db().await });
13+
14+
let mut group = c.benchmark_group("UTXO Queries (with entropy)");
15+
group.sample_size(10);
16+
group.measurement_time(std::time::Duration::from_secs(10));
17+
18+
group.bench_function("current_implementation", |b| {
19+
b.to_async(&rt).iter(|| async {
20+
store.query_utxos(black_box(&filters.1)).await.unwrap();
21+
})
22+
});
23+
24+
group.finish();
25+
26+
let _ = fs::remove_file(db_path);
27+
}
28+
29+
criterion_group!(benches, criterion_benchmark);
30+
criterion_main!(benches);

crates/coin-store/benches/token.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use criterion::{Criterion, black_box, criterion_group, criterion_main};
2+
use std::fs;
3+
use tokio::runtime::Runtime;
4+
5+
use coin_store::executor::UtxoStore;
6+
7+
mod common;
8+
9+
fn criterion_benchmark(c: &mut Criterion) {
10+
let rt = Runtime::new().unwrap();
11+
12+
let (store, filters, db_path) = rt.block_on(async { common::setup_db().await });
13+
14+
let mut group = c.benchmark_group("UTXO Queries (with token)");
15+
group.sample_size(10);
16+
group.measurement_time(std::time::Duration::from_secs(10));
17+
18+
group.bench_function("current_implementation", |b| {
19+
b.to_async(&rt).iter(|| async {
20+
store.query_utxos(black_box(&filters.3)).await.unwrap();
21+
})
22+
});
23+
24+
group.finish();
25+
26+
let _ = fs::remove_file(db_path);
27+
}
28+
29+
criterion_group!(benches, criterion_benchmark);
30+
criterion_main!(benches);

0 commit comments

Comments
 (0)