Skip to content

Commit 33c96d0

Browse files
committed
refactor: move OLLog payloads to strata-checkpoint-types
1 parent 8eeb512 commit 33c96d0

File tree

5 files changed

+224
-0
lines changed

5 files changed

+224
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/checkpoint-types/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ workspace = true
88

99
[dependencies]
1010
strata-asm-manifest-types.workspace = true
11+
strata-codec.workspace = true
1112
strata-identifiers.workspace = true
1213

1314
ssz.workspace = true

crates/checkpoint-types/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
3838
mod claim;
3939
mod error;
40+
mod log_payloads;
4041
mod payload;
4142

4243
#[cfg(any(test, feature = "test-utils"))]
@@ -57,6 +58,7 @@ mod ssz_generated {
5758
}
5859

5960
// Re-export types from claim.ssz
61+
pub use log_payloads::{SimpleWithdrawalIntentLogData, SnarkAccountUpdateLogData};
6062
pub use ssz_generated::ssz::claim::{
6163
CheckpointClaim, CheckpointClaimRef, L2BlockRange, L2BlockRangeRef,
6264
};
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
//! Log payload types for orchestration layer logs.
2+
3+
use strata_codec::{Codec, VarVec};
4+
5+
/// Payload for a simple withdrawal intent log.
6+
///
7+
/// Emitted by the OL STF when a withdrawal message is processed at the bridge
8+
/// gateway account.
9+
#[derive(Debug, Clone, PartialEq, Eq, Codec)]
10+
pub struct SimpleWithdrawalIntentLogData {
11+
/// Amount being withdrawn (sats).
12+
pub amt: u64,
13+
14+
/// Destination BOSD.
15+
pub dest: VarVec<u8>,
16+
17+
/// User's selected operator index for withdrawal assignment.
18+
// TODO(STR-1861): encode as varint to reduce DA cost in checkpoint payloads.
19+
pub selected_operator: u32,
20+
}
21+
22+
impl SimpleWithdrawalIntentLogData {
23+
/// Create a new simple withdrawal intent log data instance.
24+
pub fn new(amt: u64, dest: Vec<u8>, selected_operator: u32) -> Option<Self> {
25+
let dest = VarVec::from_vec(dest)?;
26+
Some(Self {
27+
amt,
28+
dest,
29+
selected_operator,
30+
})
31+
}
32+
33+
/// Get the withdrawal amount.
34+
pub fn amt(&self) -> u64 {
35+
self.amt
36+
}
37+
38+
/// Get the destination as bytes.
39+
pub fn dest(&self) -> &[u8] {
40+
self.dest.as_ref()
41+
}
42+
}
43+
44+
/// Payload for a snark account update log.
45+
///
46+
/// This log is emitted when a snark account is updated through a transaction.
47+
/// It contains the new message index (sequence number) and any extra data
48+
/// from the update operation.
49+
#[derive(Debug, Clone, PartialEq, Eq, Codec)]
50+
pub struct SnarkAccountUpdateLogData {
51+
/// The new message index (sequence number) after the update.
52+
pub new_msg_idx: u64,
53+
54+
/// Extra data from the update operation.
55+
pub extra_data: VarVec<u8>,
56+
}
57+
58+
impl SnarkAccountUpdateLogData {
59+
/// Create a new snark account update log data instance.
60+
pub fn new(new_msg_idx: u64, extra_data: Vec<u8>) -> Option<Self> {
61+
let extra_data = VarVec::from_vec(extra_data)?;
62+
Some(Self {
63+
new_msg_idx,
64+
extra_data,
65+
})
66+
}
67+
68+
/// Get the new message index.
69+
pub fn new_msg_idx(&self) -> u64 {
70+
self.new_msg_idx
71+
}
72+
73+
/// Get the extra data as bytes.
74+
pub fn extra_data(&self) -> &[u8] {
75+
self.extra_data.as_ref()
76+
}
77+
}
78+
79+
#[cfg(test)]
80+
mod tests {
81+
use strata_codec::{decode_buf_exact, encode_to_vec};
82+
83+
use super::*;
84+
85+
#[test]
86+
fn test_simple_withdrawal_intent_log_data_codec() {
87+
// Create test data
88+
let log_data = SimpleWithdrawalIntentLogData {
89+
amt: 100_000_000, // 1 BTC
90+
dest: VarVec::from_vec(b"bc1qtest123456789".to_vec()).unwrap(),
91+
selected_operator: 42,
92+
};
93+
94+
// Encode
95+
let encoded = encode_to_vec(&log_data).unwrap();
96+
97+
// Decode
98+
let decoded: SimpleWithdrawalIntentLogData = decode_buf_exact(&encoded).unwrap();
99+
100+
// Verify round-trip
101+
assert_eq!(decoded.amt, log_data.amt);
102+
assert_eq!(decoded.dest.as_ref(), log_data.dest.as_ref());
103+
assert_eq!(decoded.selected_operator, log_data.selected_operator);
104+
}
105+
106+
#[test]
107+
fn test_simple_withdrawal_intent_empty_dest() {
108+
// Test with empty destination (probably invalid, but codec should handle it)
109+
let log_data = SimpleWithdrawalIntentLogData {
110+
amt: 50_000,
111+
dest: VarVec::from_vec(vec![]).unwrap(),
112+
selected_operator: 0,
113+
};
114+
115+
let encoded = encode_to_vec(&log_data).unwrap();
116+
let decoded: SimpleWithdrawalIntentLogData = decode_buf_exact(&encoded).unwrap();
117+
118+
assert_eq!(decoded.amt, 50_000);
119+
assert!(decoded.dest.is_empty());
120+
}
121+
122+
#[test]
123+
fn test_simple_withdrawal_intent_max_values() {
124+
// Test with maximum values
125+
let log_data = SimpleWithdrawalIntentLogData {
126+
amt: u64::MAX,
127+
dest: VarVec::from_vec(vec![255u8; 200]).unwrap(),
128+
selected_operator: u32::MAX,
129+
};
130+
131+
let encoded = encode_to_vec(&log_data).unwrap();
132+
let decoded: SimpleWithdrawalIntentLogData = decode_buf_exact(&encoded).unwrap();
133+
134+
assert_eq!(decoded.amt, u64::MAX);
135+
assert_eq!(decoded.dest.len(), 200);
136+
assert_eq!(decoded.dest.as_ref(), &vec![255u8; 200][..]);
137+
}
138+
139+
#[test]
140+
fn test_simple_withdrawal_intent_zero_amount() {
141+
// Test with zero amount
142+
let log_data = SimpleWithdrawalIntentLogData {
143+
amt: 0,
144+
dest: VarVec::from_vec(b"addr1test".to_vec()).unwrap(),
145+
selected_operator: 5,
146+
};
147+
148+
let encoded = encode_to_vec(&log_data).unwrap();
149+
let decoded: SimpleWithdrawalIntentLogData = decode_buf_exact(&encoded).unwrap();
150+
151+
assert_eq!(decoded.amt, 0);
152+
assert_eq!(decoded.dest.as_ref(), b"addr1test");
153+
}
154+
155+
#[test]
156+
fn test_snark_account_update_log_data_codec() {
157+
// Create test data
158+
let log_data = SnarkAccountUpdateLogData {
159+
new_msg_idx: 12345,
160+
extra_data: VarVec::from_vec(b"extra_test_data".to_vec()).unwrap(),
161+
};
162+
163+
// Encode
164+
let encoded = encode_to_vec(&log_data).unwrap();
165+
166+
// Decode
167+
let decoded: SnarkAccountUpdateLogData = decode_buf_exact(&encoded).unwrap();
168+
169+
// Verify round-trip
170+
assert_eq!(decoded.new_msg_idx, log_data.new_msg_idx);
171+
assert_eq!(decoded.extra_data.as_ref(), log_data.extra_data.as_ref());
172+
}
173+
174+
#[test]
175+
fn test_snark_account_update_empty_extra_data() {
176+
// Test with empty extra data
177+
let log_data = SnarkAccountUpdateLogData {
178+
new_msg_idx: 999,
179+
extra_data: VarVec::from_vec(vec![]).unwrap(),
180+
};
181+
182+
let encoded = encode_to_vec(&log_data).unwrap();
183+
let decoded: SnarkAccountUpdateLogData = decode_buf_exact(&encoded).unwrap();
184+
185+
assert_eq!(decoded.new_msg_idx, 999);
186+
assert!(decoded.extra_data.is_empty());
187+
}
188+
189+
#[test]
190+
fn test_snark_account_update_max_values() {
191+
// Test with maximum values
192+
let log_data = SnarkAccountUpdateLogData {
193+
new_msg_idx: u64::MAX,
194+
extra_data: VarVec::from_vec(vec![255u8; 250]).unwrap(),
195+
};
196+
197+
let encoded = encode_to_vec(&log_data).unwrap();
198+
let decoded: SnarkAccountUpdateLogData = decode_buf_exact(&encoded).unwrap();
199+
200+
assert_eq!(decoded.new_msg_idx, u64::MAX);
201+
assert_eq!(decoded.extra_data.len(), 250);
202+
assert_eq!(decoded.extra_data.as_ref(), &vec![255u8; 250][..]);
203+
}
204+
205+
#[test]
206+
fn test_snark_account_update_zero_msg_idx() {
207+
// Test with zero message index
208+
let log_data = SnarkAccountUpdateLogData {
209+
new_msg_idx: 0,
210+
extra_data: VarVec::from_vec(b"test".to_vec()).unwrap(),
211+
};
212+
213+
let encoded = encode_to_vec(&log_data).unwrap();
214+
let decoded: SnarkAccountUpdateLogData = decode_buf_exact(&encoded).unwrap();
215+
216+
assert_eq!(decoded.new_msg_idx, 0);
217+
assert_eq!(decoded.extra_data.as_ref(), b"test");
218+
}
219+
}

guest-builder/sp1/guest-asm/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)