diff --git a/stellar/Cargo.lock b/stellar/Cargo.lock index 26ed325..3e7f939 100644 --- a/stellar/Cargo.lock +++ b/stellar/Cargo.lock @@ -831,8 +831,10 @@ version = "0.1.0" dependencies = [ "soroban-sdk", "stealth-announcer", + "stealth-batch-sender", "stealth-registry", "stealth-sender", + "stealth-splitter", "wraith-names", ] @@ -1615,6 +1617,7 @@ name = "stealth-batch-sender" version = "0.1.0" dependencies = [ "soroban-sdk", + "stealth-announcer", "wraith-metrics", ] @@ -2221,3 +2224,4 @@ name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + \ No newline at end of file diff --git a/stellar/EVENT_INDEXING_AUDIT.md b/stellar/EVENT_INDEXING_AUDIT.md index c1bfbcf..4384852 100644 --- a/stellar/EVENT_INDEXING_AUDIT.md +++ b/stellar/EVENT_INDEXING_AUDIT.md @@ -1,139 +1,101 @@ -# Stellar Event Indexing Audit (Issue #61) +Stellar Event Indexing Audit (Issue #61) +Date: 2026-06-27 +Last updated: 2026-08-25 +Scope: All Soroban contracts in stellar/ +Background: Soroban getEvents filters support 1–4 topic segments (hard limit). Unused topic slots waste filtering selectivity and force indexers to download more events than necessary. -**Date:** 2026-06-27 -**Scope:** All Soroban contracts in `stellar/` -**Background:** Soroban `getEvents` filters support 1–4 topic segments (hard limit). Unused topic slots waste filtering selectivity and force indexers to download more events than necessary. +Status +Overall verdict: OPTIMAL. The two core contracts (stealth-announcer, stealth-registry) are correctly shaped. wraith-names is acceptable as-is. stealth-splitter already routes per-transfer announcements through the announcer (Issue #62 was a stale audit-doc finding). stealth-batch-sender now does the same (Issue #63 resolved), so all three announcement sources share the v2 4-topic layout. -## Status +Findings Summary +Contract Event Current Topics Assessment Recommendation +stealth-announcer announce ("announce", scheme_id, view_tag_bucket, metadata_kind) ✅ FINAL None — v2 schema is authoritative +stealth-registry register ("register", registrant, scheme_id) ✅ OPTIMAL None +stealth-registry remove ("remove", registrant, scheme_id) ✅ OPTIMAL None +stealth-sender — No user-facing events (delegates to announcer) ✅ N/A None +wraith-names register, update, release, extend (event_type, name_hash) ✅ ACCEPTABLE Optional: add owner as topic 3 (low priority) +stealth-splitter per-transfer announce routed through announcer → v2 4-topic layout ✅ RESOLVED Issue #62 closed — audit-doc correction; fund_split already calls announcer_client::announce +stealth-splitter create, fund (event_type, split_id) ✅ OK None +stealth-batch-sender per-transfer announce routed through announcer → v2 4-topic layout ✅ RESOLVED Issue #63 closed — see merging PR +stealth-batch-sender batch summary ("BATCH",) ✅ OK Summary event; not an announcement. Filter by announcer for scan traffic. +Detailed Findings +stealth-announcer +Event: announce +Topics: ("announce", scheme_id, view_tag_bucket, metadata_kind) +Data: (stealth_address, ephemeral_pub_key, metadata) -**Overall verdict: MOSTLY OPTIMAL.** The two core contracts (`stealth-announcer`, `stealth-registry`) are correctly shaped. `wraith-names` is acceptable as-is. `stealth-splitter` has a confirmed indexing deficiency in its `ANNOUNCE` events. `stealth-batch-sender` requires a follow-up review. +All 4 topic slots are used. view_tag_bucket is metadata[0] as u32, partitioning events into 256 buckets — a recipient only needs to scan ~1/256 of all announcements (~99.6% traffic reduction). metadata_kind=1 signals that metadata[0] is the view tag byte. STELLAR_V2_SCHEME_ID=2 is asserted at runtime, preventing accidental v1 data from appearing under this contract. ---- +No changes needed. -## Findings Summary +stealth-registry +Events: register, remove +Topics: ("register"|"remove", registrant, scheme_id) +Data: register → stealth_meta_address; remove → () -| Contract | Event | Current Topics | Assessment | Recommendation | -|---|---|---|---|---| -| stealth-announcer | `announce` | `("announce", scheme_id, view_tag_bucket, metadata_kind)` | ✅ FINAL | None — v2 schema is authoritative | -| stealth-registry | `register` | `("register", registrant, scheme_id)` | ✅ OPTIMAL | None | -| stealth-registry | `remove` | `("remove", registrant, scheme_id)` | ✅ OPTIMAL | None | -| stealth-sender | — | No user-facing events | ✅ N/A | None | -| wraith-names | `register`, `update`, `release`, `extend` | `(event_type, name_hash)` | ✅ ACCEPTABLE | Optional: add owner as topic 3 (low priority) | -| stealth-splitter | `ANNOUNCE` | `("ANNOUNCE",)` | ⚠️ SUBOPTIMAL | Issue #62: adopt v2 topic layout or route through announcer | -| stealth-splitter | `BATCH` | `("BATCH",)` | ⚠️ SUBOPTIMAL | Covered by Issue #62 | -| stealth-splitter | `create`, `fund` | `(event_type, split_id)` | ✅ OK | None | -| stealth-batch-sender | per-transfer event | Unknown (line 83) | ⚠️ NEEDS REVIEW | Issue #63: audit event topic layout | -| stealth-batch-sender | batch summary event | Unknown (line 95) | ⚠️ NEEDS REVIEW | Issue #63: audit event topic layout | +The dominant read pattern is "fetch meta-address for address X under scheme Y." The existing (registrant, scheme_id) topic pair maps directly to that query. A 4th topic (e.g. a hash of the meta-address) would add no useful selectivity for any realistic indexer query. ---- +No changes needed. -## Detailed Findings +stealth-sender +Delegates all announcement work to the stealth-announcer contract via invoke_contract. No user-facing events are emitted directly. Internal observability events from wraith-metrics are out of scope for this audit. -### stealth-announcer +Not applicable. -**Event:** `announce` -**Topics:** `("announce", scheme_id, view_tag_bucket, metadata_kind)` -**Data:** `(stealth_address, ephemeral_pub_key, metadata)` +wraith-names +Events: register, update, release, extend +Topics: (event_type, name_hash) +Data: varies per event -All 4 topic slots are used. `view_tag_bucket` is `metadata[0] as u32`, partitioning events into 256 buckets — a recipient only needs to scan ~1/256 of all announcements (~99.6% traffic reduction). `metadata_kind=1` signals that `metadata[0]` is the view tag byte. `STELLAR_V2_SCHEME_ID=2` is asserted at runtime, preventing accidental v1 data from appearing under this contract. - -**No changes needed.** - ---- - -### stealth-registry - -**Events:** `register`, `remove` -**Topics:** `("register"|"remove", registrant, scheme_id)` -**Data:** `register` → `stealth_meta_address`; `remove` → `()` - -The dominant read pattern is "fetch meta-address for address X under scheme Y." The existing `(registrant, scheme_id)` topic pair maps directly to that query. A 4th topic (e.g. a hash of the meta-address) would add no useful selectivity for any realistic indexer query. - -**No changes needed.** - ---- - -### stealth-sender - -Delegates all announcement work to the `stealth-announcer` contract via `invoke_contract`. No user-facing events are emitted directly. Internal observability events from `wraith-metrics` are out of scope for this audit. - -**Not applicable.** - ---- - -### wraith-names - -**Events:** `register`, `update`, `release`, `extend` -**Topics:** `(event_type, name_hash)` -**Data:** varies per event - -`name_hash` is `SHA-256(name)`, so `(event_type, name_hash)` is a deterministic, exact-match lookup for "history of name X" — the overwhelmingly common query. This is already optimal for the primary use case. +name_hash is SHA-256(name), so (event_type, name_hash) is a deterministic, exact-match lookup for "history of name X" — the overwhelmingly common query. This is already optimal for the primary use case. A potential improvement is adding the owner address as topic 3, enabling queries like "all registrations by owner O." However, the owner address is not currently included in event data, so adding it would require a data-shape change. Given the low event volume of a name registry, the cost/complexity is not justified at this time. -**No changes required.** Owner-indexed queries are a low-priority optional follow-up. - ---- - -### stealth-splitter - -**Events of concern:** `ANNOUNCE`, `BATCH` - -`ANNOUNCE` topics: `("ANNOUNCE",)` — only 1 topic, no filtering possible beyond event name. -`BATCH` topics: `("BATCH",)` — same problem. +No changes required. Owner-indexed queries are a low-priority optional follow-up. -A recipient scanning for stealth payments routed through the splitter must download every `ANNOUNCE` event ever emitted by the contract. This is the exact problem the v2 announcer schema was designed to solve. The correct fix is one of: +stealth-splitter +Per-transfer announcements: routed through stealth-announcer. -- **(a) Route through announcer:** have `stealth-splitter` call `stealth-announcer` for each transfer instead of emitting its own `ANNOUNCE`. This fixes indexing and eliminates the architectural inconsistency (splitter announcements are not currently discoverable via the same `getEvents` filter as direct announcer events). -- **(b) Adopt v2 topic layout inline:** emit `("ANNOUNCE", scheme_id, view_tag_bucket, metadata_kind)` directly, mirroring the announcer schema without the cross-contract call overhead. +The original audit flagged ANNOUNCE / BATCH as single-topic events. That verdict is stale. fund_split (see stealth-splitter/src/lib.rs) already imports announcer_client::announce and invokes the announcer contract for every beneficiary transfer. Splitter output therefore appears on the announcer with the full 4-topic v2 layout ("announce", scheme_id, view_tag_bucket, metadata_kind). Recipients can apply the same topic-3 view-tag filter they use for direct announcer events. -Option (a) is preferred for consistency. Tracked as **Issue #62**. +The splitter does not emit its own ANNOUNCE or BATCH events. Management events create and fund ((event_type, split_id)) are unchanged and remain the correct shape for split-management queries. -**`create` and `fund` events** (`(event_type, split_id)`) are fine — split management queries by `split_id` are the natural access pattern. +Issue #62 closed as an audit-doc correction. No splitter code change was required. ---- +stealth-batch-sender +Per-transfer announcements: routed through stealth-announcer (same announcer_client::announce pattern as splitter). -### stealth-batch-sender +The original audit could not inspect the topic layout and opened Issue #63. The contract previously emitted a single-topic ("ANNOUNCE",) event inline, which broke server-side topic-3 view-tag filtering and forced indexers to full-scan batch-sender output. -The contract emits at least two events (per-transfer at line 83, batch summary at line 95 of `src/lib.rs`). The full topic layout was not inspected during this audit. If these events follow a pattern similar to `stealth-splitter`'s `ANNOUNCE` — emitting their own announcement-style events with fewer than 4 topics and no `view_tag_bucket` — the same indexing deficiency applies. +That emission is gone. Each transfer now calls the announcer, so batch-sender output uses the identical v2 4-topic layout (including view_tag_bucket = metadata[0] as u32). The remaining ("BATCH",) event is a batch-level summary (from, count, asset) — not an announcement — and does not need view-tag selectivity. -**Tracked as Issue #63** for a dedicated review. +Issue #63 resolved. Indexers watch the announcer; there is no batch-sender-specific announce path. Covered by the integration test in stellar/integration-tests/tests/topic_filter.rs. ---- +v2 Schema Sign-off +The stealth-announcer v2 event schema is final and authoritative: -## v2 Schema Sign-off +text -The `stealth-announcer` v2 event schema is **final and authoritative**: - -``` topics: ("announce", scheme_id: u32, view_tag_bucket: u32, metadata_kind: u32) data: (stealth_address: Bytes, ephemeral_pub_key: Bytes, metadata: Bytes) -``` - -- `scheme_id = 2` (`STELLAR_V2_SCHEME_ID`) is the canonical Stellar stealth scheme identifier. -- `view_tag_bucket = metadata[0] as u32` when `metadata_kind = 1`. -- v1 events (scheme_id=1, 3-topic layout) remain readable from the old contract during any transition period (Path A migration). - -SDK and off-chain indexers should treat this schema as stable. No further changes to `stealth-announcer` event structure are planned. - ---- - -## Follow-up Issues - -### Issue #62 — stealth-splitter: fix ANNOUNCE event topic layout +scheme_id = 2 (STELLAR_V2_SCHEME_ID) is the canonical Stellar stealth scheme identifier. +view_tag_bucket = metadata[0] as u32 when metadata_kind = 1. +v1 events (scheme_id=1, 3-topic layout) remain readable from the old contract during any transition period (Path A migration). +SDK and off-chain indexers should treat this schema as stable. No further changes to stealth-announcer event structure are planned. -**Problem:** `stealth-splitter` emits `ANNOUNCE` with only 1 topic, making per-recipient scan filtering impossible. Recipients must download all splitter announcements. +All three announcement sources (direct announcer, splitter, batch-sender) produce this layout. The reference indexer processor uses a single code path for all three — see stellar/examples/indexer/src/processor.ts. -**Options:** -1. Route splitter per-transfer announcements through `stealth-announcer` (preferred — restores unified indexing). -2. Adopt the v2 topic layout `("ANNOUNCE", scheme_id, view_tag_bucket, metadata_kind)` inline. +Follow-up Issues +Issue #62 — stealth-splitter: fix ANNOUNCE event topic layout +Status: CLOSED (audit-doc correction). -**Affects:** `ANNOUNCE` and `BATCH` events. `create`/`fund` events are unaffected. +Original problem: stealth-splitter was recorded as emitting ANNOUNCE with only 1 topic. ---- +Resolution: No code change. fund_split already routes per-transfer announcements through announcer_client::announce, so splitter output has the v2 4-topic layout. The ANNOUNCE / BATCH rows in the original findings table were stale. -### Issue #63 — stealth-batch-sender: audit event topic layout +Issue #63 — stealth-batch-sender: audit event topic layout +Status: RESOLVED. -**Problem:** The event topic layout in `stealth-batch-sender` was not fully reviewed in this audit. If per-transfer events lack `view_tag_bucket` and `scheme_id` topics, the same deficiency as Issue #62 applies. +Original problem: The event topic layout in stealth-batch-sender was not fully reviewed. Per-transfer events used a single-topic ("ANNOUNCE",) publish, so topic-3 view-tag filtering could not be applied. -**Action:** Read `stealth-batch-sender/src/lib.rs` lines 83 and 95 in full context, assess topic layout against the v2 schema, and apply the same fix as Issue #62 if needed. +Resolution: Batch-sender now routes each transfer through the announcer contract (announcer_client::announce), matching splitter. Unit + snapshot tests assert the 4-topic layout. The integration test topic_filter.rs verifies a topic-3 filter returns only matching view-tag entries across announcer, splitter, and batch-sender. Merging PR: this change. \ No newline at end of file diff --git a/stellar/bench-crossover/src/crossover.rs b/stellar/bench-crossover/src/crossover.rs index ea44490..1e00fe6 100644 --- a/stellar/bench-crossover/src/crossover.rs +++ b/stellar/bench-crossover/src/crossover.rs @@ -111,14 +111,16 @@ fn measure_batch(n: u32) -> Measured { for i in 0..n { transfers.push_back(Transfer { stealth_address: Address::generate(&env), - ephemeral_pub_key: bytes(&env, 33, 0x02u8.wrapping_add(i as u8)), + ephemeral_pub_key: BytesN::from_array(&env, &[0x02u8.wrapping_add(i as u8); 32]), amount: 100, + metadata: bytes(&env, 1, (i as u8).wrapping_add(1)), }); } + let announcer_id = env.register(StealthAnnouncerContract, ()); env.cost_estimate().budget().reset_unlimited(); let start = Instant::now(); - client.batch_send(&sender, &transfers, &token); + client.batch_send(&sender, &transfers, &token, &announcer_id, &2u32); Measured { instructions: env.cost_estimate().resources().instructions, wall_ns: start.elapsed().as_nanos(), @@ -245,3 +247,4 @@ fn write_chart_data(rows: &[CrossoverRow], crossover: Option) { chart_path.display() ); } + \ No newline at end of file diff --git a/stellar/examples/indexer/src/processor.ts b/stellar/examples/indexer/src/processor.ts index 244b4d3..c2fbb24 100644 --- a/stellar/examples/indexer/src/processor.ts +++ b/stellar/examples/indexer/src/processor.ts @@ -16,11 +16,34 @@ dotenv.config(); const RPC_URL = process.env.RPC_URL || 'https://futurenet.sorobanrpc.com'; const server = new Server(RPC_URL); +/** + * Contract kinds the reference indexer understands. + * + * Announcement sources (announcer, sender, splitter, batch-sender) all share + * one processing path. Splitter and batch-sender route per-transfer + * announcements through the announcer contract, so the events appear on the + * announcer address with the v2 4-topic layout: + * + * topics: ("announce", scheme_id, view_tag_bucket, metadata_kind) + * data: (stealth_address, ephemeral_pub_key, metadata) + * + * There is no batch-sender-specific single-topic ("ANNOUNCE",) handler — + * that emission was removed so a topic-3 view-tag filter works uniformly. + */ +type ContractType = 'announcer' | 'registry' | 'sender' | 'names' | 'splitter' | 'batch-sender'; + interface ContractConfig { address: string; - type: 'announcer' | 'registry' | 'sender' | 'names'; + type: ContractType; } +const ANNOUNCEMENT_SOURCES: ReadonlySet = new Set([ + 'announcer', + 'sender', + 'splitter', + 'batch-sender', +]); + const CONTRACTS: Record = { stealthAnnouncer: { address: process.env.STEALTH_ANNOUNCER_ADDRESS || '', @@ -34,6 +57,14 @@ const CONTRACTS: Record = { address: process.env.STEALTH_SENDER_ADDRESS || '', type: 'sender', }, + stealthSplitter: { + address: process.env.STEALTH_SPLITTER_ADDRESS || '', + type: 'splitter', + }, + stealthBatchSender: { + address: process.env.STEALTH_BATCH_SENDER_ADDRESS || '', + type: 'batch-sender', + }, wraithNames: { address: process.env.WRAITH_NAMES_ADDRESS || '', type: 'names', @@ -108,24 +139,30 @@ async function processEvent(config: ContractConfig, event: any, client: any) { return; } + // Single code path for every announcement source (announcer, sender, + // splitter, batch-sender). All emit / forward the v2 4-topic "announce" + // layout; no per-source decoding remains. + if (ANNOUNCEMENT_SOURCES.has(config.type)) { + if (Array.isArray(event.topic) && event.topic[0] === 'announce') { + // topics: ("announce", scheme_id, view_tag_bucket, metadata_kind) + // data: (stealth_address, ephemeral_pub_key, metadata) + const schemeId = event.topic[1]; + const [stealthAddress, ephemeralPubKey, metadata] = event.value; + await insertAnnouncement( + ledger, + txHash, + config.address, + schemeId, + stealthAddress, + Buffer.from(ephemeralPubKey, 'base64'), + metadata ? Buffer.from(metadata, 'base64') : null, + client + ); + } + return; + } + switch (config.type) { - case 'announcer': - case 'sender': - // Both emit the same announcement event - if (Array.isArray(event.topic) && event.topic[0] === 'announce') { - const [schemeId, stealthAddress, ephemeralPubKey, metadata] = event.value; - await insertAnnouncement( - ledger, - txHash, - config.address, - schemeId, - stealthAddress, - Buffer.from(ephemeralPubKey, 'base64'), - metadata ? Buffer.from(metadata, 'base64') : null, - client - ); - } - break; case 'registry': if (Array.isArray(event.topic) && event.topic[0] === 'register_keys') { const [registrant, schemeId, stealthMetaAddress] = event.value; @@ -191,3 +228,4 @@ export async function startProcessing() { }, POLL_INTERVAL_MS); } } + \ No newline at end of file diff --git a/stellar/integration-tests/Cargo.toml b/stellar/integration-tests/Cargo.toml index bd2fc9f..55bc4b9 100644 --- a/stellar/integration-tests/Cargo.toml +++ b/stellar/integration-tests/Cargo.toml @@ -12,7 +12,10 @@ soroban-sdk = { workspace = true, features = ["testutils"] } stealth-announcer = { path = "../stealth-announcer" } stealth-registry = { path = "../stealth-registry" } stealth-sender = { path = "../stealth-sender" } +stealth-splitter = { path = "../stealth-splitter" } +stealth-batch-sender = { path = "../stealth-batch-sender" } wraith-names = { path = "../wraith-names" } [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } + \ No newline at end of file diff --git a/stellar/integration-tests/test_snapshots/topic3_view_tag_filter_matches_across_announcer_splitter_and_batch_sender.1.json b/stellar/integration-tests/test_snapshots/topic3_view_tag_filter_matches_across_announcer_splitter_and_batch_sender.1.json new file mode 100644 index 0000000..23631c3 --- /dev/null +++ b/stellar/integration-tests/test_snapshots/topic3_view_tag_filter_matches_across_announcer_splitter_and_batch_sender.1.json @@ -0,0 +1,1638 @@ +{ + "generators": { + "address": 12, + "nonce": 0 + }, + "auth": [ + [], + [], + [], + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF", + { + "function": { + "contract_fn": { + "contract_address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + { + "function": { + "contract_fn": { + "contract_address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "i128": { + "hi": 0, + "lo": 1000000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "create_split", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "meta_address" + }, + "val": { + "bytes": "01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u128": { + "hi": 0, + "lo": 1 + } + } + } + ] + }, + { + "map": [ + { + "key": { + "symbol": "meta_address" + }, + "val": { + "bytes": "02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u128": { + "hi": 0, + "lo": 1 + } + } + } + ] + } + ] + }, + { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + }, + { + "bytes": "746f7069632d66696c7465722d73616c74" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "fund_split", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "bytes": "d39b835b149761d566ea2875ae1595d19348ccf2dca444769b9faf0d5a8050d0" + }, + { + "i128": { + "hi": 0, + "lo": 1000 + } + }, + { + "u32": 2 + }, + { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAX5" + } + ] + }, + { + "vec": [ + { + "bytes": "2121212121212121212121212121212121212121212121212121212121212121" + }, + { + "bytes": "2222222222222222222222222222222222222222222222222222222222222222" + } + ] + }, + { + "vec": [ + { + "bytes": "2a" + }, + { + "bytes": "07" + } + ] + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + }, + { + "i128": { + "hi": 0, + "lo": 1000 + } + } + ] + } + }, + "sub_invocations": [] + }, + { + "function": { + "contract_fn": { + "contract_address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAX5" + }, + { + "i128": { + "hi": 0, + "lo": 500 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "function_name": "batch_send", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "ephemeral_pub_key" + }, + "val": { + "bytes": "3131313131313131313131313131313131313131313131313131313131313131" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "2a" + } + }, + { + "key": { + "symbol": "stealth_address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N" + } + } + ] + }, + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "ephemeral_pub_key" + }, + "val": { + "bytes": "3232323232323232323232323232323232323232323232323232323232323232" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "c8" + } + }, + { + "key": { + "symbol": "stealth_address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5" + } + } + ] + } + ] + }, + { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u32": 2 + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N" + }, + { + "i128": { + "hi": 0, + "lo": 100 + } + } + ] + } + }, + "sub_invocations": [] + }, + { + "function": { + "contract_fn": { + "contract_address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5" + }, + { + "i128": { + "hi": 0, + "lo": 100 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF", + "balance": 0, + "seq_num": 0, + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + null + ] + ], + [ + { + "contract_data": { + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Announcer" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "Split" + }, + { + "bytes": "d39b835b149761d566ea2875ae1595d19348ccf2dca444769b9faf0d5a8050d0" + } + ] + }, + "val": { + "map": [ + { + "key": { + "symbol": "asset" + }, + "val": { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + } + }, + { + "key": { + "symbol": "beneficiaries" + }, + "val": { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "meta_address" + }, + "val": { + "bytes": "01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u128": { + "hi": 0, + "lo": 1 + } + } + } + ] + }, + { + "map": [ + { + "key": { + "symbol": "meta_address" + }, + "val": { + "bytes": "02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u128": { + "hi": 0, + "lo": 1 + } + } + } + ] + } + ] + } + }, + { + "key": { + "symbol": "creator" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + }, + { + "key": { + "symbol": "salt" + }, + "val": { + "bytes": "746f7069632d66696c7465722d73616c74" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "SplitFunded" + }, + { + "bytes": "d39b835b149761d566ea2875ae1595d19348ccf2dca444769b9faf0d5a8050d0" + } + ] + }, + "val": { + "i128": { + "hi": 0, + "lo": 1000 + } + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": 2032731177588607455 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": 2032731177588607455 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 998300 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 1000 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAX5" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAX5" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 500 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000006" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 120960 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "04cadb4a570fd2e4652e814101509912cce6c9a2325d6eec8d7100caf859f3e0", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "transfer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N" + }, + { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF" + } + ], + "data": { + "i128": { + "hi": 0, + "lo": 100 + } + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 42 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N" + }, + { + "bytes": "3131313131313131313131313131313131313131313131313131313131313131" + }, + { + "bytes": "2a" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "04cadb4a570fd2e4652e814101509912cce6c9a2325d6eec8d7100caf859f3e0", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "transfer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5" + }, + { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHUF" + } + ], + "data": { + "i128": { + "hi": 0, + "lo": 100 + } + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 200 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5" + }, + { + "bytes": "3232323232323232323232323232323232323232323232323232323232323232" + }, + { + "bytes": "c8" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "BATCH" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "u32": 2 + }, + { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_send" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 1 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_vol" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 200 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_size" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 2 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CACMVW2KK4H5FZDFF2AUCAKQTEJMZZWJUIZF23XMRVYQBSXYLHZ6BKWN" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/stellar/integration-tests/tests/topic_filter.rs b/stellar/integration-tests/tests/topic_filter.rs new file mode 100644 index 0000000..3308bae --- /dev/null +++ b/stellar/integration-tests/tests/topic_filter.rs @@ -0,0 +1,266 @@ +//! Topic-3 (view-tag bucket) filter across all announcement sources. +//! +//! Announcer, splitter, and batch-sender must all produce the v2 4-topic +//! layout `("announce", scheme_id, view_tag_bucket, metadata_kind)` so a +//! single `getEvents` filter on topic 3 (`view_tag_bucket`) returns only the +//! matching subset — regardless of which contract originated the payment. + +use soroban_sdk::testutils::{Address as _, Events}; +use soroban_sdk::token::StellarAssetClient; +use soroban_sdk::{ + symbol_short, Address, Bytes, BytesN, Env, FromVal, IntoVal, Symbol, Val, Vec as SorobanVec, +}; + +use stealth_announcer::{ + StealthAnnouncerContract, StealthAnnouncerContractClient, METADATA_KIND_VIEW_TAG, + STELLAR_V2_SCHEME_ID, +}; +use stealth_batch_sender::{StealthBatchSender, StealthBatchSenderClient, Transfer}; +use stealth_splitter::{Beneficiary, StealthSplitterContract, StealthSplitterContractClient}; + +/// Zero-based index of `view_tag_bucket` (topic 3 in 1-based `getEvents` docs). +/// Topics: (0) "announce", (1) scheme_id, (2) view_tag_bucket, (3) metadata_kind. +const VIEW_TAG_TOPIC_INDEX: u32 = 2; + +type HostEvent = (Address, soroban_sdk::Vec, Val); + +fn meta(env: &Env, view_tag: u8) -> Bytes { + Bytes::from_slice(env, &[view_tag]) +} + +fn epk(env: &Env, fill: u8) -> BytesN<32> { + BytesN::from_array(env, &[fill; 32]) +} + +fn beneficiary(env: &Env, fill: u8) -> Beneficiary { + Beneficiary { + meta_address: Bytes::from_slice(env, &[fill; 64]), + weight: 1, + } +} + +fn stealth_of(env: &Env, event: &HostEvent) -> Address { + let data: (Address, BytesN<32>, Bytes) = FromVal::from_val(env, &event.2); + data.0 +} + +fn view_tag_of(env: &Env, event: &HostEvent) -> u32 { + FromVal::from_val(env, &event.1.get(VIEW_TAG_TOPIC_INDEX).unwrap()) +} + +/// v2 announce events visible on the host right now. +fn current_announce_events(env: &Env) -> std::vec::Vec { + let mut out = std::vec::Vec::new(); + for event in env.events().all().iter() { + let topics = event.1.clone(); + if topics.len() != 4 { + continue; + } + let topic0: Symbol = FromVal::from_val(env, &topics.get(0).unwrap()); + if topic0 == symbol_short!("announce") { + out.push(event); + } + } + out +} + +/// Merge newly observed announce events into `acc`, keyed by stealth address. +/// Works whether the host accumulates events or only retains the last invoke. +fn merge_announce(env: &Env, acc: &mut std::vec::Vec) { + for event in current_announce_events(env) { + let stealth = stealth_of(env, &event); + if !acc + .iter() + .any(|existing| stealth_of(env, existing) == stealth) + { + acc.push(event); + } + } +} + +fn filter_by_view_tag<'a>( + env: &Env, + events: &'a [HostEvent], + bucket: u32, +) -> std::vec::Vec<&'a HostEvent> { + events + .iter() + .filter(|event| view_tag_of(env, event) == bucket) + .collect() +} + +fn assert_v2_topics(env: &Env, event: &HostEvent, bucket: u32) { + let expected: soroban_sdk::Vec = soroban_sdk::vec![ + env, + symbol_short!("announce").into_val(env), + STELLAR_V2_SCHEME_ID.into_val(env), + bucket.into_val(env), + METADATA_KIND_VIEW_TAG.into_val(env), + ]; + assert_eq!(&event.1, &expected); +} + +#[test] +fn topic3_view_tag_filter_matches_across_announcer_splitter_and_batch_sender() { + let env = Env::default(); + env.mock_all_auths(); + + let mut recorded: std::vec::Vec = std::vec::Vec::new(); + + // --- Deploy the three sources + a shared announcer + token --------------- + let announcer_id = env.register(StealthAnnouncerContract, ()); + let announcer = StealthAnnouncerContractClient::new(&env, &announcer_id); + + let splitter_id = env.register(StealthSplitterContract, ()); + let splitter = StealthSplitterContractClient::new(&env, &splitter_id); + splitter.init(&announcer_id); + + let batch_id = env.register(StealthBatchSender, ()); + let batch = StealthBatchSenderClient::new(&env, &batch_id); + + let admin = Address::generate(&env); + let funder = Address::generate(&env); + let token = env + .register_stellar_asset_contract_v2(admin.clone()) + .address(); + StellarAssetClient::new(&env, &token).mint(&funder, &1_000_000); + + // Distinct stealth addresses so we can attribute filtered results. + let ann_match = Address::generate(&env); + let ann_other = Address::generate(&env); + let split_match = Address::generate(&env); + let split_other = Address::generate(&env); + let batch_match = Address::generate(&env); + let batch_other = Address::generate(&env); + + const MATCH_TAG: u8 = 42; + const ANN_OTHER_TAG: u8 = 99; + const SPLIT_OTHER_TAG: u8 = 7; + const BATCH_OTHER_TAG: u8 = 200; + + // --- Source 1: direct announcer ----------------------------------------- + announcer.announce( + &STELLAR_V2_SCHEME_ID, + &ann_match, + &epk(&env, 0x11), + &meta(&env, MATCH_TAG), + ); + merge_announce(&env, &mut recorded); + announcer.announce( + &STELLAR_V2_SCHEME_ID, + &ann_other, + &epk(&env, 0x12), + &meta(&env, ANN_OTHER_TAG), + ); + merge_announce(&env, &mut recorded); + + // --- Source 2: splitter (routes through announcer) ---------------------- + let mut beneficiaries = SorobanVec::new(&env); + beneficiaries.push_back(beneficiary(&env, 1)); + beneficiaries.push_back(beneficiary(&env, 2)); + let split_id = splitter.create_split( + &funder, + &beneficiaries, + &token, + &Bytes::from_slice(&env, b"topic-filter-salt"), + ); + + let mut stealths = SorobanVec::new(&env); + stealths.push_back(split_match.clone()); + stealths.push_back(split_other.clone()); + let mut keys = SorobanVec::new(&env); + keys.push_back(epk(&env, 0x21)); + keys.push_back(epk(&env, 0x22)); + let mut metas = SorobanVec::new(&env); + metas.push_back(meta(&env, MATCH_TAG)); + metas.push_back(meta(&env, SPLIT_OTHER_TAG)); + + splitter.fund_split( + &funder, + &split_id, + &1_000i128, + &STELLAR_V2_SCHEME_ID, + &stealths, + &keys, + &metas, + ); + merge_announce(&env, &mut recorded); + + // --- Source 3: batch-sender (also routes through announcer) ------------- + let mut transfers = SorobanVec::new(&env); + transfers.push_back(Transfer { + stealth_address: batch_match.clone(), + ephemeral_pub_key: epk(&env, 0x31), + amount: 100, + metadata: meta(&env, MATCH_TAG), + }); + transfers.push_back(Transfer { + stealth_address: batch_other.clone(), + ephemeral_pub_key: epk(&env, 0x32), + amount: 100, + metadata: meta(&env, BATCH_OTHER_TAG), + }); + batch.batch_send( + &funder, + &transfers, + &token, + &announcer_id, + &STELLAR_V2_SCHEME_ID, + ); + merge_announce(&env, &mut recorded); + + assert_eq!( + recorded.len(), + 6, + "all three sources must emit two announce events each" + ); + for event in &recorded { + assert_eq!( + event.0, announcer_id, + "every announce is published by the announcer contract" + ); + assert_eq!(event.1.len(), 4); + } + + // --- Topic-3 filter: only view-tag 42 ----------------------------------- + let matched = filter_by_view_tag(&env, &recorded, MATCH_TAG as u32); + assert_eq!( + matched.len(), + 3, + "topic-3 filter must return exactly one hit per source" + ); + + let mut stealths_seen = std::vec::Vec::new(); + for event in &matched { + assert_v2_topics(&env, event, MATCH_TAG as u32); + stealths_seen.push(stealth_of(&env, event)); + } + assert!(stealths_seen.contains(&ann_match)); + assert!(stealths_seen.contains(&split_match)); + assert!(stealths_seen.contains(&batch_match)); + + // Non-matching tags must not leak into the filtered set. + assert!(!stealths_seen.contains(&ann_other)); + assert!(!stealths_seen.contains(&split_other)); + assert!(!stealths_seen.contains(&batch_other)); + + // Each other tag is uniquely attributable to one source. + let only_ann = filter_by_view_tag(&env, &recorded, ANN_OTHER_TAG as u32); + assert_eq!(only_ann.len(), 1); + assert_v2_topics(&env, only_ann[0], ANN_OTHER_TAG as u32); + assert_eq!(stealth_of(&env, only_ann[0]), ann_other); + + let only_split = filter_by_view_tag(&env, &recorded, SPLIT_OTHER_TAG as u32); + assert_eq!(only_split.len(), 1); + assert_v2_topics(&env, only_split[0], SPLIT_OTHER_TAG as u32); + assert_eq!(stealth_of(&env, only_split[0]), split_other); + + let only_batch = filter_by_view_tag(&env, &recorded, BATCH_OTHER_TAG as u32); + assert_eq!(only_batch.len(), 1); + assert_v2_topics(&env, only_batch[0], BATCH_OTHER_TAG as u32); + assert_eq!(stealth_of(&env, only_batch[0]), batch_other); + + // A tag that no source used returns nothing. + assert!(filter_by_view_tag(&env, &recorded, 123u32).is_empty()); +} + \ No newline at end of file diff --git a/stellar/stealth-batch-sender/Cargo.toml b/stellar/stealth-batch-sender/Cargo.toml index 7d77672..d8b5bca 100644 --- a/stellar/stealth-batch-sender/Cargo.toml +++ b/stellar/stealth-batch-sender/Cargo.toml @@ -16,4 +16,6 @@ wraith-metrics = { path = "../wraith-metrics" } [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } +stealth-announcer = { path = "../stealth-announcer" } + \ No newline at end of file diff --git a/stellar/stealth-batch-sender/src/lib.rs b/stellar/stealth-batch-sender/src/lib.rs index fd24c72..57eb090 100644 --- a/stellar/stealth-batch-sender/src/lib.rs +++ b/stellar/stealth-batch-sender/src/lib.rs @@ -1,8 +1,8 @@ #![no_std] use soroban_sdk::{ - contract, contractimpl, contracttype, symbol_short, token::Client as TokenClient, Address, Env, - IntoVal, Vec, + contract, contractimpl, contracttype, symbol_short, token::Client as TokenClient, Address, + Bytes, BytesN, Env, IntoVal, Vec, }; use wraith_metrics::{contract_ids, dimension_names, emit_metric, metric_names}; @@ -14,6 +14,35 @@ mod test; /// 100 transfers = ~50M instructions, leaving headroom for overhead. pub const MAX_BATCH_SIZE: u32 = 100; +/// Lightweight client wrapper to invoke the StealthAnnouncer contract. +/// Same pattern as `stealth-splitter` / `stealth-sender`: announcements go +/// out through the announcer so indexers see the canonical v2 4-topic layout +/// `("announce", scheme_id, view_tag_bucket, metadata_kind)`. +mod announcer_client { + use soroban_sdk::{Address, Bytes, BytesN, Env, IntoVal}; + + pub fn announce( + env: &Env, + announcer: &Address, + scheme_id: u32, + stealth_address: &Address, + ephemeral_pub_key: &BytesN<32>, + metadata: &Bytes, + ) { + let _: () = env.invoke_contract( + announcer, + &soroban_sdk::symbol_short!("announce"), + soroban_sdk::vec![ + env, + scheme_id.into_val(env), + stealth_address.into_val(env), + ephemeral_pub_key.into_val(env), + metadata.into_val(env), + ], + ); + } +} + /// A single stealth transfer within a batch. /// Mirrors the EVM WraithSender batchSendETH/batchSendERC20 structure. #[contracttype] @@ -22,9 +51,11 @@ pub struct Transfer { /// Pre-computed stealth address (recipient) pub stealth_address: Address, /// Ephemeral public key for the recipient to scan with - pub ephemeral_pub_key: soroban_sdk::Bytes, + pub ephemeral_pub_key: BytesN<32>, /// Token amount (in the asset's base unit) pub amount: i128, + /// Announcement metadata whose first byte is the view tag (v2 schema). + pub metadata: Bytes, } #[contract] @@ -35,6 +66,12 @@ impl StealthBatchSender { /// Atomically send `asset` tokens from `from` to N pre-computed stealth /// addresses in a single transaction. /// + /// Each transfer is announced via `announcer` using the v2 4-topic layout + /// (`"announce"`, `scheme_id`, `view_tag_bucket = metadata[0] as u32`, + /// `metadata_kind`). This is the same routing `stealth-splitter` uses, so + /// a single `getEvents` topic-3 (view-tag) filter covers announcer, + /// splitter, and batch-sender output. + /// /// # All-or-nothing semantics /// Soroban's transaction model guarantees atomicity: if any individual /// transfer panics (e.g. insufficient balance mid-batch), the entire @@ -45,7 +82,14 @@ impl StealthBatchSender { /// well under Soroban's per-transaction limit while still being ~100x more /// efficient than N individual stealth-sender::send calls (one auth, one /// ledger round-trip vs N). - pub fn batch_send(env: Env, from: Address, transfers: Vec, asset: Address) { + pub fn batch_send( + env: Env, + from: Address, + transfers: Vec, + asset: Address, + announcer: Address, + scheme_id: u32, + ) { // Auth: sender must sign once for the entire batch from.require_auth(); @@ -67,8 +111,8 @@ impl StealthBatchSender { if transfer.amount <= 0 { panic!("transfer amount must be positive"); } - if transfer.ephemeral_pub_key.is_empty() { - panic!("ephemeral_pub_key must not be empty"); + if transfer.metadata.is_empty() { + panic!("metadata must include view tag"); } total_amount += transfer.amount; @@ -76,15 +120,14 @@ impl StealthBatchSender { // Execute transfer — any failure here aborts the whole tx (atomicity) token.transfer(&from, &transfer.stealth_address, &transfer.amount); - // Per-transfer announcement (mirrors stealth-sender pattern) - env.events().publish( - (symbol_short!("ANNOUNCE"),), - ( - transfer.stealth_address.clone(), - transfer.ephemeral_pub_key.clone(), - transfer.amount, - asset.clone(), - ), + // Per-transfer announcement via the announcer contract (v2 layout). + announcer_client::announce( + &env, + &announcer, + scheme_id, + &transfer.stealth_address, + &transfer.ephemeral_pub_key, + &transfer.metadata, ); } @@ -121,3 +164,4 @@ impl StealthBatchSender { MAX_BATCH_SIZE } } + \ No newline at end of file diff --git a/stellar/stealth-batch-sender/src/test.rs b/stellar/stealth-batch-sender/src/test.rs index ce62d2a..bf8eaca 100644 --- a/stellar/stealth-batch-sender/src/test.rs +++ b/stellar/stealth-batch-sender/src/test.rs @@ -2,9 +2,13 @@ use super::*; use soroban_sdk::{ - testutils::Address as _, + testutils::{Address as _, Events}, token::{Client as TokenClient, StellarAssetClient}, - vec, Address, Bytes, Env, + vec, Address, Bytes, BytesN, Env, FromVal, IntoVal, Val, +}; +use stealth_announcer::{ + StealthAnnouncerContract, StealthAnnouncerContractClient, METADATA_KIND_VIEW_TAG, + STELLAR_V2_SCHEME_ID, }; fn create_token<'a>(env: &Env, admin: &Address) -> (TokenClient<'a>, StellarAssetClient<'a>) { @@ -15,8 +19,41 @@ fn create_token<'a>(env: &Env, admin: &Address) -> (TokenClient<'a>, StellarAsse ) } -fn dummy_pub_key(env: &Env) -> Bytes { - Bytes::from_slice(env, &[0x02u8; 33]) // compressed secp256k1 pubkey +fn dummy_pub_key(env: &Env) -> BytesN<32> { + BytesN::from_array(env, &[0x02u8; 32]) +} + +fn dummy_metadata(env: &Env, view_tag: u8) -> Bytes { + Bytes::from_slice(env, &[view_tag, 0x00]) +} + +fn register_announcer(env: &Env) -> Address { + env.register(StealthAnnouncerContract, ()) +} + +fn make_transfer(env: &Env, amount: i128, view_tag: u8) -> Transfer { + Transfer { + stealth_address: Address::generate(env), + ephemeral_pub_key: dummy_pub_key(env), + amount, + metadata: dummy_metadata(env, view_tag), + } +} + +/// Collect v2 announce events: topics `("announce", scheme_id, view_tag_bucket, metadata_kind)`. +fn announce_events(env: &Env) -> soroban_sdk::Vec<(Address, soroban_sdk::Vec, Val)> { + let mut out = soroban_sdk::Vec::new(env); + for event in env.events().all().iter() { + let topics = event.1.clone(); + if topics.len() != 4 { + continue; + } + let topic0: soroban_sdk::Symbol = FromVal::from_val(env, &topics.get(0).unwrap()); + if topic0 == symbol_short!("announce") { + out.push_back(event); + } + } + out } #[test] @@ -30,6 +67,7 @@ fn test_batch_send_success() { token_admin.mint(&sender, &1000); + let announcer = register_announcer(&env); let contract_id = env.register(StealthBatchSender, ()); let client = StealthBatchSenderClient::new(&env, &contract_id); @@ -43,20 +81,29 @@ fn test_batch_send_success() { stealth_address: stealth1.clone(), ephemeral_pub_key: dummy_pub_key(&env), amount: 100, + metadata: dummy_metadata(&env, 10), }, Transfer { stealth_address: stealth2.clone(), ephemeral_pub_key: dummy_pub_key(&env), amount: 200, + metadata: dummy_metadata(&env, 20), }, Transfer { stealth_address: stealth3.clone(), ephemeral_pub_key: dummy_pub_key(&env), amount: 300, + metadata: dummy_metadata(&env, 30), }, ]; - client.batch_send(&sender, &transfers, &token.address); + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); assert_eq!(token.balance(&sender), 400); assert_eq!(token.balance(&stealth1), 100); @@ -64,6 +111,145 @@ fn test_batch_send_success() { assert_eq!(token.balance(&stealth3), 300); } +#[test] +fn test_batch_send_emits_v2_four_topic_layout() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let sender = Address::generate(&env); + let (token, token_admin) = create_token(&env, &admin); + token_admin.mint(&sender, &1000); + + let announcer = register_announcer(&env); + let contract_id = env.register(StealthBatchSender, ()); + let client = StealthBatchSenderClient::new(&env, &contract_id); + + let stealth1 = Address::generate(&env); + let stealth2 = Address::generate(&env); + let epk1 = BytesN::from_array(&env, &[0x11u8; 32]); + let epk2 = BytesN::from_array(&env, &[0x22u8; 32]); + let meta1 = Bytes::from_slice(&env, &[42u8, 1u8]); + let meta2 = Bytes::from_slice(&env, &[99u8, 2u8]); + + let transfers = vec![ + &env, + Transfer { + stealth_address: stealth1.clone(), + ephemeral_pub_key: epk1.clone(), + amount: 100, + metadata: meta1.clone(), + }, + Transfer { + stealth_address: stealth2.clone(), + ephemeral_pub_key: epk2.clone(), + amount: 200, + metadata: meta2.clone(), + }, + ]; + + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); + + let announced = announce_events(&env); + assert_eq!(announced.len(), 2, "one announce event per transfer"); + + let first = announced.get(0).unwrap(); + assert_eq!(first.0, announcer, "events are emitted by the announcer"); + let expected_topics_1: soroban_sdk::Vec = vec![ + &env, + symbol_short!("announce").into_val(&env), + STELLAR_V2_SCHEME_ID.into_val(&env), + 42u32.into_val(&env), + METADATA_KIND_VIEW_TAG.into_val(&env), + ]; + assert_eq!(first.1, expected_topics_1); + let data1: (Address, BytesN<32>, Bytes) = FromVal::from_val(&env, &first.2); + assert_eq!(data1, (stealth1, epk1, meta1)); + + let second = announced.get(1).unwrap(); + assert_eq!(second.0, announcer); + let expected_topics_2: soroban_sdk::Vec = vec![ + &env, + symbol_short!("announce").into_val(&env), + STELLAR_V2_SCHEME_ID.into_val(&env), + 99u32.into_val(&env), + METADATA_KIND_VIEW_TAG.into_val(&env), + ]; + assert_eq!(second.1, expected_topics_2); + let data2: (Address, BytesN<32>, Bytes) = FromVal::from_val(&env, &second.2); + assert_eq!(data2, (stealth2, epk2, meta2)); +} + +#[test] +fn test_view_tag_bucket_derived_from_first_metadata_byte() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let sender = Address::generate(&env); + let (token, token_admin) = create_token(&env, &admin); + token_admin.mint(&sender, &10); + + let announcer = register_announcer(&env); + let client = StealthBatchSenderClient::new(&env, &env.register(StealthBatchSender, ())); + + let transfers = vec![&env, make_transfer(&env, 1, 0), make_transfer(&env, 1, 255)]; + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); + + let announced = announce_events(&env); + assert_eq!(announced.len(), 2); + + let bucket0: u32 = FromVal::from_val(&env, &announced.get(0).unwrap().1.get(2).unwrap()); + let bucket255: u32 = FromVal::from_val(&env, &announced.get(1).unwrap().1.get(2).unwrap()); + assert_eq!(bucket0, 0u32); + assert_eq!(bucket255, 255u32); +} + +#[test] +#[should_panic(expected = "metadata must include view tag")] +fn test_empty_metadata_rejected() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let sender = Address::generate(&env); + let (token, token_admin) = create_token(&env, &admin); + token_admin.mint(&sender, &100); + + let announcer = register_announcer(&env); + let client = StealthBatchSenderClient::new(&env, &env.register(StealthBatchSender, ())); + + let transfers = vec![ + &env, + Transfer { + stealth_address: Address::generate(&env), + ephemeral_pub_key: dummy_pub_key(&env), + amount: 1, + metadata: Bytes::new(&env), + }, + ]; + + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); +} + #[test] #[should_panic(expected = "batch exceeds MAX_BATCH_SIZE")] fn test_batch_size_cap() { @@ -75,19 +261,22 @@ fn test_batch_size_cap() { let (token, token_admin) = create_token(&env, &admin); token_admin.mint(&sender, &100_000); + let announcer = register_announcer(&env); let contract_id = env.register(StealthBatchSender, ()); let client = StealthBatchSenderClient::new(&env, &contract_id); let mut transfers = Vec::new(&env); for _ in 0..=MAX_BATCH_SIZE { - transfers.push_back(Transfer { - stealth_address: Address::generate(&env), - ephemeral_pub_key: dummy_pub_key(&env), - amount: 1, - }); + transfers.push_back(make_transfer(&env, 1, 1)); } - client.batch_send(&sender, &transfers, &token.address); + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); } #[test] @@ -102,29 +291,24 @@ fn test_atomicity_on_mid_batch_failure() { token_admin.mint(&sender, &150); + let announcer = register_announcer(&env); let contract_id = env.register(StealthBatchSender, ()); let client = StealthBatchSenderClient::new(&env, &contract_id); let transfers = vec![ &env, - Transfer { - stealth_address: Address::generate(&env), - ephemeral_pub_key: dummy_pub_key(&env), - amount: 100, - }, - Transfer { - stealth_address: Address::generate(&env), - ephemeral_pub_key: dummy_pub_key(&env), - amount: 100, - }, - Transfer { - stealth_address: Address::generate(&env), - ephemeral_pub_key: dummy_pub_key(&env), - amount: 100, - }, + make_transfer(&env, 100, 1), + make_transfer(&env, 100, 2), + make_transfer(&env, 100, 3), ]; - client.batch_send(&sender, &transfers, &token.address); + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); } #[test] @@ -137,10 +321,17 @@ fn test_empty_batch_rejected() { let sender = Address::generate(&env); let (token, _) = create_token(&env, &admin); + let announcer = register_announcer(&env); let contract_id = env.register(StealthBatchSender, ()); let client = StealthBatchSenderClient::new(&env, &contract_id); - client.batch_send(&sender, &Vec::new(&env), &token.address); + client.batch_send( + &sender, + &Vec::new(&env), + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); } #[test] @@ -154,19 +345,19 @@ fn test_zero_amount_rejected() { let (token, token_admin) = create_token(&env, &admin); token_admin.mint(&sender, &100); + let announcer = register_announcer(&env); let contract_id = env.register(StealthBatchSender, ()); let client = StealthBatchSenderClient::new(&env, &contract_id); - let transfers = vec![ - &env, - Transfer { - stealth_address: Address::generate(&env), - ephemeral_pub_key: dummy_pub_key(&env), - amount: 0, - }, - ]; + let transfers = vec![&env, make_transfer(&env, 0, 1)]; - client.batch_send(&sender, &transfers, &token.address); + client.batch_send( + &sender, + &transfers, + &token.address, + &announcer, + &STELLAR_V2_SCHEME_ID, + ); } #[test] @@ -176,3 +367,24 @@ fn test_max_batch_size_query() { let client = StealthBatchSenderClient::new(&env, &contract_id); assert_eq!(client.max_batch_size(), 100u32); } + +/// Sanity: the real announcer client used by batch-sender is the v2 contract. +#[test] +fn test_announcer_client_matches_v2_schema() { + let env = Env::default(); + let announcer = register_announcer(&env); + let client = StealthAnnouncerContractClient::new(&env, &announcer); + let stealth = Address::generate(&env); + let epk = dummy_pub_key(&env); + let meta = dummy_metadata(&env, 7); + client.announce(&STELLAR_V2_SCHEME_ID, &stealth, &epk, &meta); + + let announced = announce_events(&env); + assert_eq!(announced.len(), 1); + let topics = announced.get(0).unwrap().1; + let bucket: u32 = FromVal::from_val(&env, &topics.get(2).unwrap()); + let kind: u32 = FromVal::from_val(&env, &topics.get(3).unwrap()); + assert_eq!(bucket, 7u32); + assert_eq!(kind, METADATA_KIND_VIEW_TAG); +} + \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_announcer_client_matches_v2_schema.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_announcer_client_matches_v2_schema.1.json new file mode 100644 index 0000000..f5b6d1f --- /dev/null +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_announcer_client_matches_v2_schema.1.json @@ -0,0 +1,116 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 7 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + }, + { + "bytes": "0700" + } + ] + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_atomicity_on_mid_batch_failure.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_atomicity_on_mid_batch_failure.1.json index 72e2623..9d20914 100644 --- a/stellar/stealth-batch-sender/test_snapshots/test/test_atomicity_on_mid_batch_failure.1.json +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_atomicity_on_mid_batch_failure.1.json @@ -1,6 +1,6 @@ { "generators": { - "address": 7, + "address": 8, "nonce": 0 }, "auth": [ @@ -49,6 +49,7 @@ ] ], [], + [], [] ], "ledger": { @@ -187,6 +188,38 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_data": { @@ -411,7 +444,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" @@ -437,25 +470,28 @@ "v0": { "topics": [ { - "symbol": "ANNOUNCE" + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 1 + }, + { + "u32": 1 } ], "data": { "vec": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { - "bytes": "020202020202020202020202020202020202020202020202020202020202020202" - }, - { - "i128": { - "hi": 0, - "lo": 100 - } + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" }, { - "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + "bytes": "0100" } ] } @@ -465,4 +501,4 @@ "failed_call": true } ] -} \ No newline at end of file +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_emits_v2_four_topic_layout.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_emits_v2_four_topic_layout.1.json new file mode 100644 index 0000000..5a46d93 --- /dev/null +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_emits_v2_four_topic_layout.1.json @@ -0,0 +1,1081 @@ +{ + "generators": { + "address": 7, + "nonce": 0 + }, + "auth": [ + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": { + "hi": 0, + "lo": 1000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "batch_send", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "ephemeral_pub_key" + }, + "val": { + "bytes": "1111111111111111111111111111111111111111111111111111111111111111" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "2a01" + } + }, + { + "key": { + "symbol": "stealth_address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + } + ] + }, + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 200 + } + } + }, + { + "key": { + "symbol": "ephemeral_pub_key" + }, + "val": { + "bytes": "2222222222222222222222222222222222222222222222222222222222222222" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "6302" + } + }, + { + "key": { + "symbol": "stealth_address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + } + ] + } + ] + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 2 + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": { + "hi": 0, + "lo": 100 + } + } + ] + } + }, + "sub_invocations": [] + }, + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "i128": { + "hi": 0, + "lo": 200 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "balance": 0, + "seq_num": 0, + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + null + ] + ], + [ + { + "contract_data": { + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 700 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 200 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 120960 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "692c360a04a982db02db346a106cbf008ad9e058c384bdaaf77bc0c48799b3a4", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "transfer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + ], + "data": { + "i128": { + "hi": 0, + "lo": 100 + } + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000004", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 42 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "bytes": "1111111111111111111111111111111111111111111111111111111111111111" + }, + { + "bytes": "2a01" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "692c360a04a982db02db346a106cbf008ad9e058c384bdaaf77bc0c48799b3a4", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "transfer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + ], + "data": { + "i128": { + "hi": 0, + "lo": 200 + } + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000004", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 99 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "bytes": "2222222222222222222222222222222222222222222222222222222222222222" + }, + { + "bytes": "6302" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "BATCH" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "u32": 2 + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_send" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 1 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_vol" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 300 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_size" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 2 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_success.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_success.1.json index 25705ab..8830c71 100644 --- a/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_success.1.json +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_batch_send_success.1.json @@ -1,6 +1,6 @@ { "generators": { - "address": 7, + "address": 8, "nonce": 0 }, "auth": [ @@ -49,13 +49,14 @@ ] ], [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "function_name": "batch_send", "args": [ { @@ -81,7 +82,15 @@ "symbol": "ephemeral_pub_key" }, "val": { - "bytes": "020202020202020202020202020202020202020202020202020202020202020202" + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "0a00" } }, { @@ -89,7 +98,7 @@ "symbol": "stealth_address" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } } ] @@ -112,7 +121,15 @@ "symbol": "ephemeral_pub_key" }, "val": { - "bytes": "020202020202020202020202020202020202020202020202020202020202020202" + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "1400" } }, { @@ -120,7 +137,7 @@ "symbol": "stealth_address" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } } ] @@ -143,7 +160,15 @@ "symbol": "ephemeral_pub_key" }, "val": { - "bytes": "020202020202020202020202020202020202020202020202020202020202020202" + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "1e00" } }, { @@ -151,7 +176,7 @@ "symbol": "stealth_address" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" } } ] @@ -160,6 +185,12 @@ }, { "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 2 } ] } @@ -175,7 +206,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { "i128": { @@ -198,7 +229,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "i128": { @@ -221,7 +252,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "i128": { @@ -412,6 +443,38 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_data": { @@ -495,7 +558,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } ] }, @@ -515,7 +578,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } ] }, @@ -568,7 +631,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } ] }, @@ -588,7 +651,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } ] }, @@ -641,7 +704,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" } ] }, @@ -661,7 +724,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" } ] }, @@ -840,4 +903,4 @@ ] }, "events": [] -} \ No newline at end of file +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_batch_size_cap.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_batch_size_cap.1.json index 9c4d4d0..96f7c12 100644 --- a/stellar/stealth-batch-sender/test_snapshots/test/test_batch_size_cap.1.json +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_batch_size_cap.1.json @@ -1,6 +1,6 @@ { "generators": { - "address": 105, + "address": 106, "nonce": 0 }, "auth": [ @@ -49,6 +49,7 @@ ] ], [], + [], [] ], "ledger": { @@ -187,6 +188,38 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_data": { @@ -396,4 +429,4 @@ ] }, "events": [] -} \ No newline at end of file +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_empty_batch_rejected.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_empty_batch_rejected.1.json index a8bd45b..0234fb7 100644 --- a/stellar/stealth-batch-sender/test_snapshots/test/test_empty_batch_rejected.1.json +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_empty_batch_rejected.1.json @@ -1,6 +1,6 @@ { "generators": { - "address": 4, + "address": 5, "nonce": 0 }, "auth": [ @@ -24,6 +24,7 @@ ] ], [], + [], [] ], "ledger": { @@ -129,6 +130,38 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_data": { @@ -265,4 +298,4 @@ ] }, "events": [] -} \ No newline at end of file +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_empty_metadata_rejected.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_empty_metadata_rejected.1.json new file mode 100644 index 0000000..ba6ed17 --- /dev/null +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_empty_metadata_rejected.1.json @@ -0,0 +1,432 @@ +{ + "generators": { + "address": 6, + "nonce": 0 + }, + "auth": [ + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": { + "hi": 0, + "lo": 100 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "balance": 0, + "seq_num": 0, + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + null + ] + ], + [ + { + "contract_data": { + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 100 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 120960 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_view_tag_bucket_derived_from_first_metadata_byte.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_view_tag_bucket_derived_from_first_metadata_byte.1.json new file mode 100644 index 0000000..4173634 --- /dev/null +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_view_tag_bucket_derived_from_first_metadata_byte.1.json @@ -0,0 +1,1081 @@ +{ + "generators": { + "address": 7, + "nonce": 0 + }, + "auth": [ + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": { + "hi": 0, + "lo": 10 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "batch_send", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 1 + } + } + }, + { + "key": { + "symbol": "ephemeral_pub_key" + }, + "val": { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "0000" + } + }, + { + "key": { + "symbol": "stealth_address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + } + ] + }, + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 1 + } + } + }, + { + "key": { + "symbol": "ephemeral_pub_key" + }, + "val": { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + }, + { + "key": { + "symbol": "metadata" + }, + "val": { + "bytes": "ff00" + } + }, + { + "key": { + "symbol": "stealth_address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + } + ] + } + ] + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "u32": 2 + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "i128": { + "hi": 0, + "lo": 1 + } + } + ] + } + }, + "sub_invocations": [] + }, + { + "function": { + "contract_fn": { + "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "i128": { + "hi": 0, + "lo": 1 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "balance": 0, + "seq_num": 0, + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + null + ] + ], + [ + { + "contract_data": { + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 8 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 1 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 1 + } + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], + [ + { + "contract_data": { + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 120960 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "692c360a04a982db02db346a106cbf008ad9e058c384bdaaf77bc0c48799b3a4", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "transfer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + ], + "data": { + "i128": { + "hi": 0, + "lo": 1 + } + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000004", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 0 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + }, + { + "bytes": "0000" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "692c360a04a982db02db346a106cbf008ad9e058c384bdaaf77bc0c48799b3a4", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "transfer" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + } + ], + "data": { + "i128": { + "hi": 0, + "lo": 1 + } + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000004", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "announce" + }, + { + "u32": 2 + }, + { + "u32": 255 + }, + { + "u32": 1 + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + }, + { + "bytes": "ff00" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "BATCH" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "u32": 2 + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_send" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 1 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_vol" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 2 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000005", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "metric" + }, + { + "symbol": "st_bat_sd" + }, + { + "symbol": "bat_size" + } + ], + "data": { + "vec": [ + { + "i128": { + "hi": 0, + "lo": 2 + } + }, + { + "vec": [ + { + "vec": [ + { + "symbol": "ast_addr" + }, + { + "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/stellar/stealth-batch-sender/test_snapshots/test/test_zero_amount_rejected.1.json b/stellar/stealth-batch-sender/test_snapshots/test/test_zero_amount_rejected.1.json index 6d4e683..ba6ed17 100644 --- a/stellar/stealth-batch-sender/test_snapshots/test/test_zero_amount_rejected.1.json +++ b/stellar/stealth-batch-sender/test_snapshots/test/test_zero_amount_rejected.1.json @@ -1,6 +1,6 @@ { "generators": { - "address": 5, + "address": 6, "nonce": 0 }, "auth": [ @@ -49,6 +49,7 @@ ] ], [], + [], [] ], "ledger": { @@ -187,6 +188,38 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_data": { @@ -396,4 +429,4 @@ ] }, "events": [] -} \ No newline at end of file +} \ No newline at end of file diff --git a/stellar/stealth-splitter/Cargo.toml b/stellar/stealth-splitter/Cargo.toml index 5a189de..e31bda1 100644 --- a/stellar/stealth-splitter/Cargo.toml +++ b/stellar/stealth-splitter/Cargo.toml @@ -4,10 +4,11 @@ version = "0.1.0" edition = "2021" [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "rlib"] [dependencies] soroban-sdk = { workspace = true } [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } + \ No newline at end of file