Skip to content

Commit e094968

Browse files
Merge pull request #164 from omolobamoyinoluwa-max/Develop-Bulk-Subscription-Import-for-Enterprise-Merchants
Add batch_import_subscriptions with Ed25519 intents, Merkle event, an…
2 parents e273560 + 742a9ac commit e094968

5 files changed

Lines changed: 662 additions & 376 deletions

File tree

contracts/substream_contracts/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ soroban-sdk = { workspace = true }
1313

1414
[dev-dependencies]
1515
soroban-sdk = { workspace = true, features = ["testutils"] }
16+
ed25519-dalek = "2"
17+
stellar-strkey = "0.0.16"

contracts/substream_contracts/fuzz/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ cargo-fuzz = true
1212
[dependencies]
1313
libfuzzer-sys = "0.4"
1414
soroban-sdk = { version = "25", features = ["testutils"] }
15+
ed25519-dalek = "2"
16+
stellar-strkey = "0.0.16"
1517

1618
[dependencies.substream_contracts]
1719
path = ".."
@@ -22,3 +24,10 @@ path = "fuzz_targets/withdrawal_consistency.rs"
2224
test = false
2325
doc = false
2426
bench = false
27+
28+
[[bin]]
29+
name = "batch_import_signatures"
30+
path = "fuzz_targets/batch_import_signatures.rs"
31+
test = false
32+
doc = false
33+
bench = false
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#![no_main]
2+
3+
use ed25519_dalek::{Signer, SigningKey};
4+
use libfuzzer_sys::fuzz_target;
5+
use soroban_sdk::{testutils::Address as _, token, vec, Address, BytesN, Env, String};
6+
use stellar_strkey::{ed25519, Strkey};
7+
8+
use substream_contracts::{
9+
BulkImportItem, Plan, SubStreamContract, SubStreamContractClient, SEP12_KYC_ISSUER,
10+
};
11+
12+
const MONTH: u64 = 30 * 24 * 60 * 60;
13+
14+
fn user_from_sk(env: &Env, sk: &SigningKey) -> (Address, BytesN<32>) {
15+
let raw: [u8; 32] = sk.verifying_key().to_bytes();
16+
let pk = ed25519::PublicKey(raw);
17+
let s = Strkey::PublicKeyEd25519(pk).to_string();
18+
let addr = Address::from_str(env, s.as_str());
19+
(addr, BytesN::from_array(env, &raw))
20+
}
21+
22+
/// Exercises `batch_import_subscriptions` with **adversarial signature bytes** while the
23+
/// rest of the payload is consistent (valid merchant, plan, binding, nonce). The host should
24+
/// trap on `ed25519_verify` for almost all random inputs; `catch_unwind` keeps the fuzzer alive.
25+
fuzz_target!(|data: &[u8]| {
26+
if data.len() < 64 {
27+
return;
28+
}
29+
30+
let env = Env::default();
31+
env.mock_all_auths();
32+
33+
let admin = Address::generate(&env);
34+
let merchant = Address::generate(&env);
35+
let issuer = Address::from_str(&env, SEP12_KYC_ISSUER);
36+
let sac = env.register_stellar_asset_contract_v2(admin.clone());
37+
let t = token::Client::new(&env, &sac.address());
38+
39+
let contract_id = env.register(SubStreamContract, ());
40+
let client = SubStreamContractClient::new(&env, &contract_id);
41+
env.ledger().set_timestamp(12_000);
42+
43+
client.register_merchant_with_kyc(
44+
&merchant,
45+
soroban_sdk::vec![&env, 0u8],
46+
&issuer,
47+
);
48+
49+
let plan = Plan {
50+
plan_id: 1,
51+
name: String::from_str(&env, "Fuzz"),
52+
billing_amount: 100,
53+
billing_cycle: MONTH,
54+
has_trial: false,
55+
trial_duration: 0,
56+
is_active: true,
57+
};
58+
client.register_plan(&merchant, plan);
59+
client.set_accepted_token(&merchant, &t.address());
60+
61+
let mut seed = [11u8; 32];
62+
for (i, b) in data.iter().enumerate() {
63+
seed[i % 32] ^= *b;
64+
}
65+
let sk = SigningKey::from_bytes(&seed);
66+
let (user, pk_bn) = user_from_sk(&env, &sk);
67+
68+
let mut sig = [0u8; 64];
69+
sig.copy_from_slice(&data[..64]);
70+
71+
let item = BulkImportItem {
72+
user,
73+
user_public_key: pk_bn,
74+
plan_id: 1,
75+
nonce: 1,
76+
signature: BytesN::from_array(&env, &sig),
77+
};
78+
79+
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
80+
client.batch_import_subscriptions(&merchant, &vec![&env, item]);
81+
}));
82+
});

0 commit comments

Comments
 (0)