Skip to content

Commit 081e22d

Browse files
committed
repair merged contract APIs and storage types
1 parent b6c4eaa commit 081e22d

12 files changed

Lines changed: 296 additions & 191 deletions

File tree

contracts/ledgerlens-score/src/event_causality.rs

Lines changed: 86 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@
3838
/// - Logged in event data for recovery
3939
/// - Computed deterministically from stable inputs
4040
/// - Documented in event sequences for human auditors
41-
use soroban_sdk::{crypto::Hash, Address, Bytes, Env, Symbol};
41+
extern crate alloc;
42+
43+
use alloc::{vec, vec::Vec};
44+
use soroban_sdk::{xdr::ToXdr, Address, Bytes, Env, Symbol};
4245

4346
/// Correlation ID uniquely identifying a causal workflow
4447
/// This is a 32-byte hash computed from workflow parameters
@@ -60,12 +63,16 @@ impl EventCausality {
6063
asset_pair: &Symbol,
6164
timestamp: u64,
6265
) -> CorrelationId {
63-
Self::hash_bytes(&[
64-
b"score_submit".as_slice(),
65-
wallet.to_xdr(&Env::default()).to_bytes().as_slice(),
66-
asset_pair.to_xdr(&Env::default()).to_bytes().as_slice(),
67-
timestamp.to_le_bytes().as_slice(),
68-
])
66+
let env = Env::default();
67+
Self::hash_bytes(
68+
&env,
69+
&[
70+
Bytes::from_slice(&env, b"score_submit"),
71+
wallet.to_xdr(&env),
72+
asset_pair.to_xdr(&env),
73+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
74+
],
75+
)
6976
}
7077

7178
/// Generate correlation ID for admin transfer workflow
@@ -80,12 +87,16 @@ impl EventCausality {
8087
to: &Address,
8188
timestamp: u64,
8289
) -> CorrelationId {
83-
Self::hash_bytes(&[
84-
b"admin_xfer".as_slice(),
85-
from.to_xdr(&Env::default()).to_bytes().as_slice(),
86-
to.to_xdr(&Env::default()).to_bytes().as_slice(),
87-
timestamp.to_le_bytes().as_slice(),
88-
])
90+
let env = Env::default();
91+
Self::hash_bytes(
92+
&env,
93+
&[
94+
Bytes::from_slice(&env, b"admin_xfer"),
95+
from.to_xdr(&env),
96+
to.to_xdr(&env),
97+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
98+
],
99+
)
89100
}
90101

91102
/// Generate correlation ID for upgrade workflow
@@ -95,11 +106,15 @@ impl EventCausality {
95106
/// - `new_wasm_hash`: The new contract WASM hash being proposed
96107
/// - `timestamp`: The proposal timestamp
97108
pub fn upgrade_correlation_id(new_wasm_hash: &[u8; 32], timestamp: u64) -> CorrelationId {
98-
Self::hash_bytes(&[
99-
b"upgrade_prop".as_slice(),
100-
new_wasm_hash.as_slice(),
101-
timestamp.to_le_bytes().as_slice(),
102-
])
109+
let env = Env::default();
110+
Self::hash_bytes(
111+
&env,
112+
&[
113+
Bytes::from_slice(&env, b"upgrade_prop"),
114+
Bytes::from_array(&env, new_wasm_hash),
115+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
116+
],
117+
)
103118
}
104119

105120
/// Generate correlation ID for parameter change workflow
@@ -114,12 +129,16 @@ impl EventCausality {
114129
param_key: &Symbol,
115130
timestamp: u64,
116131
) -> CorrelationId {
117-
Self::hash_bytes(&[
118-
b"param_change".as_slice(),
119-
proposal_id.to_le_bytes().as_slice(),
120-
param_key.to_xdr(&Env::default()).to_bytes().as_slice(),
121-
timestamp.to_le_bytes().as_slice(),
122-
])
132+
let env = Env::default();
133+
Self::hash_bytes(
134+
&env,
135+
&[
136+
Bytes::from_slice(&env, b"param_change"),
137+
Bytes::from_array(&env, &proposal_id.to_le_bytes()),
138+
param_key.to_xdr(&env),
139+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
140+
],
141+
)
123142
}
124143

125144
/// Generate correlation ID for dispute workflow
@@ -134,12 +153,16 @@ impl EventCausality {
134153
asset_pair: &Symbol,
135154
timestamp: u64,
136155
) -> CorrelationId {
137-
Self::hash_bytes(&[
138-
b"dispute_open".as_slice(),
139-
challenger.to_xdr(&Env::default()).to_bytes().as_slice(),
140-
asset_pair.to_xdr(&Env::default()).to_bytes().as_slice(),
141-
timestamp.to_le_bytes().as_slice(),
142-
])
156+
let env = Env::default();
157+
Self::hash_bytes(
158+
&env,
159+
&[
160+
Bytes::from_slice(&env, b"dispute_open"),
161+
challenger.to_xdr(&env),
162+
asset_pair.to_xdr(&env),
163+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
164+
],
165+
)
143166
}
144167

145168
/// Generate correlation ID for governance action chain
@@ -149,11 +172,15 @@ impl EventCausality {
149172
/// - `action_index`: Sequential index of this action in the governance chain
150173
/// - `timestamp`: The action timestamp
151174
pub fn governance_chain_correlation_id(action_index: u64, timestamp: u64) -> CorrelationId {
152-
Self::hash_bytes(&[
153-
b"gov_chain".as_slice(),
154-
action_index.to_le_bytes().as_slice(),
155-
timestamp.to_le_bytes().as_slice(),
156-
])
175+
let env = Env::default();
176+
Self::hash_bytes(
177+
&env,
178+
&[
179+
Bytes::from_slice(&env, b"gov_chain"),
180+
Bytes::from_array(&env, &action_index.to_le_bytes()),
181+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
182+
],
183+
)
157184
}
158185

159186
/// Generate correlation ID for consensus score workflow
@@ -168,12 +195,16 @@ impl EventCausality {
168195
asset_pair: &Symbol,
169196
round_id: u64,
170197
) -> CorrelationId {
171-
Self::hash_bytes(&[
172-
b"consensus_round".as_slice(),
173-
wallet.to_xdr(&Env::default()).to_bytes().as_slice(),
174-
asset_pair.to_xdr(&Env::default()).to_bytes().as_slice(),
175-
round_id.to_le_bytes().as_slice(),
176-
])
198+
let env = Env::default();
199+
Self::hash_bytes(
200+
&env,
201+
&[
202+
Bytes::from_slice(&env, b"consensus_round"),
203+
wallet.to_xdr(&env),
204+
asset_pair.to_xdr(&env),
205+
Bytes::from_array(&env, &round_id.to_le_bytes()),
206+
],
207+
)
177208
}
178209

179210
/// Generate correlation ID for escalation workflow
@@ -188,25 +219,25 @@ impl EventCausality {
188219
asset_pair: &Symbol,
189220
timestamp: u64,
190221
) -> CorrelationId {
191-
Self::hash_bytes(&[
192-
b"escalation".as_slice(),
193-
wallet.to_xdr(&Env::default()).to_bytes().as_slice(),
194-
asset_pair.to_xdr(&Env::default()).to_bytes().as_slice(),
195-
timestamp.to_le_bytes().as_slice(),
196-
])
222+
let env = Env::default();
223+
Self::hash_bytes(
224+
&env,
225+
&[
226+
Bytes::from_slice(&env, b"escalation"),
227+
wallet.to_xdr(&env),
228+
asset_pair.to_xdr(&env),
229+
Bytes::from_array(&env, &timestamp.to_le_bytes()),
230+
],
231+
)
197232
}
198233

199234
/// Internal: Hash multiple byte sequences to produce a correlation ID
200-
fn hash_bytes(parts: &[&[u8]]) -> CorrelationId {
201-
let mut combined = Vec::new();
235+
fn hash_bytes(env: &Env, parts: &[Bytes]) -> CorrelationId {
236+
let mut combined = Bytes::new(env);
202237
for part in parts {
203-
combined.extend_from_slice(part);
238+
combined.append(part);
204239
}
205-
// Use SHA-256 to produce a deterministic 32-byte ID
206-
let hash_result = Hash::sha256(&Bytes::from_slice(&Env::default(), &combined));
207-
let mut result = [0u8; 32];
208-
result.copy_from_slice(hash_result.as_slice());
209-
result
240+
env.crypto().sha256(&combined).to_array()
210241
}
211242
}
212243

contracts/ledgerlens-score/src/event_stability.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
/// 2. Document the breaking change in CHANGELOG.md
1818
/// 3. Add migration notes in the PR and event documentation
1919
/// 4. Update off-chain indexers to handle both versions during the transition window
20-
use soroban_sdk::Symbol;
21-
2220
/// Stability level for event topics
2321
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2422
pub enum EventStability {

contracts/ledgerlens-score/src/events.rs

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ use soroban_sdk::{contracttype, symbol_short, Address, Bytes, BytesN, Env, Symbo
22

33
use crate::types::{AlertAckRecord, AlertType, Policy, RiskScore};
44

5+
pub fn alert_acknowledged(env: &Env, alert_type: &AlertType, record: &AlertAckRecord) {
6+
env.events()
7+
.publish((symbol_short!("alrt_ack"), EVENT_VERSION, alert_type.clone()), record.clone());
8+
}
9+
10+
pub fn parameter_change_cleanup(env: &Env, count: u32, oldest_kept: u64) {
11+
env.events().publish((symbol_short!("pc_clean"),), (count, oldest_kept));
12+
}
13+
514
/// Event Schema Versioning
615
///
716
/// All events emitted by this contract carry an explicit schema version in their topic array.
@@ -313,39 +322,39 @@ pub enum BatchRejectionCategory {
313322
/// Emitted when a batch entry is rejected due to contract pause.
314323
/// Topics: ("bat_rej_pause",) Data: (count)
315324
pub fn batch_rejected_contract_paused(env: &Env, count: u32) {
316-
env.events().publish((symbol_short!("bat_rej_pa"),), count);
325+
env.events().publish((Symbol::new(env, "bat_rej_pa"),), count);
317326
}
318327

319328
/// Emitted when batch entries are rejected due to data quality issues.
320329
/// Topics: ("bat_rej_data",) Data: (reason_code, count)
321330
/// reason_code: 1 = invalid_score, 2 = invalid_confidence, 3 = invalid_timestamp
322331
pub fn batch_rejected_data_quality(env: &Env, reason_code: u32, count: u32) {
323-
env.events().publish((symbol_short!("bat_rej_dq"),), (reason_code, count));
332+
env.events().publish((Symbol::new(env, "bat_rej_dq"),), (reason_code, count));
324333
}
325334

326335
/// Emitted when batch entries are rejected due to model version issues.
327336
/// Topics: ("bat_rej_model",) Data: (reason_code, count)
328337
/// reason_code: 1 = not_registered, 2 = deprecated
329338
pub fn batch_rejected_model_version(env: &Env, reason_code: u32, count: u32) {
330-
env.events().publish((symbol_short!("bat_rej_mv"),), (reason_code, count));
339+
env.events().publish((Symbol::new(env, "bat_rej_mv"),), (reason_code, count));
331340
}
332341

333342
/// Emitted when batch entries exceed rate limits.
334343
/// Topics: ("bat_rej_ratelimit",) Data: (count)
335344
pub fn batch_rejected_rate_limit(env: &Env, count: u32) {
336-
env.events().publish((symbol_short!("bat_rej_rl"),), count);
345+
env.events().publish((Symbol::new(env, "bat_rej_rl"),), count);
337346
}
338347

339348
/// Emitted when batch entries fail attestation validation.
340349
/// Topics: ("bat_rej_attest",) Data: (count)
341350
pub fn batch_rejected_attestation(env: &Env, count: u32) {
342-
env.events().publish((symbol_short!("bat_rej_at"),), count);
351+
env.events().publish((Symbol::new(env, "bat_rej_at"),), count);
343352
}
344353

345354
/// Emitted when batch entries fail gate enforcement.
346355
/// Topics: ("bat_rej_gate",) Data: (count)
347356
pub fn batch_rejected_gate_failure(env: &Env, count: u32) {
348-
env.events().publish((symbol_short!("bat_rej_gt"),), count);
357+
env.events().publish((Symbol::new(env, "bat_rej_gt"),), count);
349358
}
350359

351360
/// Summary event emitted after batch processing completes.
@@ -745,7 +754,7 @@ pub fn governance_action_appended(env: &Env, new_head: &soroban_sdk::BytesN<32>)
745754
/// Data: `(action_id: u32, action_name: Symbol, new_head: BytesN<32>)`
746755
pub fn gov_action(env: &Env, action_id: u8, action_name: &str, new_head: &soroban_sdk::BytesN<32>) {
747756
env.events().publish(
748-
(symbol_short!("gov_action"), EVENT_VERSION),
757+
(Symbol::new(env, "gov_action"), EVENT_VERSION),
749758
(action_id as u32, soroban_sdk::Symbol::new(env, action_name), new_head.clone()),
750759
);
751760
}
@@ -928,37 +937,6 @@ pub fn wallet_cluster_assigned(env: &Env, wallet: &Address, cluster: u32) {
928937
env.events().publish((symbol_short!("wc_asgn"), wallet.clone()), cluster);
929938
}
930939

931-
pub fn escalation_triggered(
932-
env: &Env,
933-
wallet: &Address,
934-
asset_pair: &Symbol,
935-
breach_count: u32,
936-
score: u32,
937-
escalation_threshold: u32,
938-
) {
939-
env.events().publish(
940-
(symbol_short!("esc_trig"), wallet.clone(), asset_pair.clone()),
941-
(breach_count, score, escalation_threshold),
942-
);
943-
}
944-
945-
pub fn escalation_resolved(
946-
env: &Env,
947-
wallet: &Address,
948-
asset_pair: &Symbol,
949-
breach_count: u32,
950-
score: u32,
951-
) {
952-
env.events().publish(
953-
(symbol_short!("esc_res"), wallet.clone(), asset_pair.clone()),
954-
(breach_count, score),
955-
);
956-
}
957-
958-
pub fn escalation_threshold_updated(env: &Env, old_threshold: u32, new_threshold: u32) {
959-
env.events().publish((symbol_short!("esc_thr"),), (old_threshold, new_threshold));
960-
}
961-
962940
// ── #631: Post-incident replay & reconciliation ──────────────────────────────
963941

964942
/// Emitted when an admin takes a deterministic state snapshot via

0 commit comments

Comments
 (0)