Skip to content

Commit 75409a0

Browse files
committed
Implement SubscriptionId type for cleaner H256 to u32 conversion
1 parent 7792845 commit 75409a0

File tree

2 files changed

+98
-109
lines changed

2 files changed

+98
-109
lines changed

indexer/src/ideal.rs

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ use crate::{
1414
};
1515
use acuity_index_substrate::*;
1616

17+
/// IDN Subscription ID wrapper that handles H256 to u32 conversion
18+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19+
pub struct SubscriptionId([u8; 32]);
20+
21+
impl SubscriptionId {
22+
/// Create a new SubscriptionId from H256 bytes
23+
pub fn new(bytes: [u8; 32]) -> Self {
24+
Self(bytes)
25+
}
26+
27+
/// Convert to u32 by taking the first 4 bytes (little-endian)
28+
pub fn to_u32(&self) -> u32 {
29+
u32::from_le_bytes([self.0[0], self.0[1], self.0[2], self.0[3]])
30+
}
31+
}
32+
33+
impl From<[u8; 32]> for SubscriptionId {
34+
fn from(bytes: [u8; 32]) -> Self {
35+
Self::new(bytes)
36+
}
37+
}
38+
1739
pub struct IdealIndexer;
1840

1941
impl acuity_index_substrate::shared::RuntimeIndexer for IdealIndexer {
@@ -53,71 +75,63 @@ impl acuity_index_substrate::shared::RuntimeIndexer for IdealIndexer {
5375
Event::IdnManager(event) => {
5476
match event {
5577
IdnManagerEvent::SubscriptionCreated { sub_id } => {
56-
// Convert H256 to u32 for the subscription ID (taking first 4 bytes)
57-
let id_u32 =
58-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
78+
let subscription_id = SubscriptionId::from(sub_id);
5979
indexer.index_event(
60-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
80+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
6181
block_number,
6282
event_index,
6383
)?;
6484
1
6585
},
6686
IdnManagerEvent::SubscriptionTerminated { sub_id } => {
67-
let id_u32 =
68-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
87+
let subscription_id = SubscriptionId::from(sub_id);
6988
indexer.index_event(
70-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
89+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
7190
block_number,
7291
event_index,
7392
)?;
7493
1
7594
},
7695
IdnManagerEvent::SubscriptionPaused { sub_id } => {
77-
let id_u32 =
78-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
96+
let subscription_id = SubscriptionId::from(sub_id);
7997
indexer.index_event(
80-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
98+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
8199
block_number,
82100
event_index,
83101
)?;
84102
1
85103
},
86104
IdnManagerEvent::SubscriptionUpdated { sub_id } => {
87-
let id_u32 =
88-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
105+
let subscription_id = SubscriptionId::from(sub_id);
89106
indexer.index_event(
90-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
107+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
91108
block_number,
92109
event_index,
93110
)?;
94111
1
95112
},
96113
IdnManagerEvent::SubscriptionReactivated { sub_id } => {
97-
let id_u32 =
98-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
114+
let subscription_id = SubscriptionId::from(sub_id);
99115
indexer.index_event(
100-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
116+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
101117
block_number,
102118
event_index,
103119
)?;
104120
1
105121
},
106122
IdnManagerEvent::RandomnessDistributed { sub_id } => {
107-
let id_u32 =
108-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
123+
let subscription_id = SubscriptionId::from(sub_id);
109124
indexer.index_event(
110-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
125+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
111126
block_number,
112127
event_index,
113128
)?;
114129
1
115130
},
116131
IdnManagerEvent::FeesCollected { sub_id, .. } => {
117-
let id_u32 =
118-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
132+
let subscription_id = SubscriptionId::from(sub_id);
119133
indexer.index_event(
120-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
134+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
121135
block_number,
122136
event_index,
123137
)?;
@@ -128,10 +142,9 @@ impl acuity_index_substrate::shared::RuntimeIndexer for IdealIndexer {
128142
0
129143
},
130144
IdnManagerEvent::SubscriptionDistributed { sub_id } => {
131-
let id_u32 =
132-
u32::from_le_bytes([sub_id[0], sub_id[1], sub_id[2], sub_id[3]]);
145+
let subscription_id = SubscriptionId::from(sub_id);
133146
indexer.index_event(
134-
Key::Substrate(SubstrateKey::SubscriptionId(id_u32)),
147+
Key::Substrate(SubstrateKey::SubscriptionId(subscription_id.to_u32())),
135148
block_number,
136149
event_index,
137150
)?;

indexer/src/tests.rs

Lines changed: 60 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use acuity_index_substrate::{shared::*, substrate::*, websockets::*, *};
22

3-
use crate::{ChainKey, IdealIndexer};
3+
use crate::{ideal::SubscriptionId, ChainKey, IdealIndexer};
44

55
#[tokio::test]
66
async fn test_process_msg_account_balance() {
@@ -79,97 +79,78 @@ async fn test_subscription_id_indexing() {
7979
let trees = open_trees::<IdealIndexer>(db_config).unwrap();
8080
let indexer = Indexer::<IdealIndexer>::new_test(trees.clone());
8181

82-
// Test subscription ID indexing with different IDs
83-
let subscription_id_1 = 12345u32;
84-
let subscription_id_2 = 67890u32;
82+
// Create different subscription IDs
83+
let sub_id_1 = SubscriptionId::new([1u8; 32]);
84+
let sub_id_2 = SubscriptionId::new([2u8; 32]);
8585

86-
let key1 = Key::Substrate(SubstrateKey::SubscriptionId(subscription_id_1));
87-
let key2 = Key::Substrate(SubstrateKey::SubscriptionId(subscription_id_2));
86+
let key1 = Key::Substrate(SubstrateKey::SubscriptionId(sub_id_1.to_u32()));
87+
let key2 = Key::Substrate(SubstrateKey::SubscriptionId(sub_id_2.to_u32()));
8888

89-
// Index events for subscription_id_1
90-
indexer.index_event(key1.clone(), 4, 5).unwrap();
91-
indexer.index_event(key1.clone(), 8, 10).unwrap();
92-
indexer.index_event(key1.clone(), 12, 15).unwrap();
89+
// Index events for subscription 1
90+
indexer.index_event(key1.clone(), 100, 0).unwrap();
91+
indexer.index_event(key1.clone(), 100, 1).unwrap();
9392

94-
// Index events for subscription_id_2
95-
indexer.index_event(key2.clone(), 6, 7).unwrap();
96-
indexer.index_event(key2.clone(), 14, 20).unwrap();
93+
// Index events for subscription 2
94+
indexer.index_event(key2.clone(), 101, 0).unwrap();
9795

98-
// Test retrieval for subscription_id_1
96+
// Verify subscription 1 events
9997
let response1 = process_msg_get_events::<IdealIndexer>(&trees, key1.clone());
10098
let ResponseMessage::Events { key: response_key1, events: events1 } = response1 else {
101-
panic!("Wrong response message for subscription_id_1.");
99+
panic!("Wrong response message for subscription 1.");
102100
};
103101
assert_eq!(key1, response_key1);
104-
assert_eq!(events1.len(), 3);
105-
assert_eq!(events1[0].block_number, 12); // Latest first
106-
assert_eq!(events1[1].block_number, 8);
107-
assert_eq!(events1[2].block_number, 4);
102+
assert_eq!(events1.len(), 2);
103+
assert_eq!(events1[0].block_number, 100);
104+
assert_eq!(events1[0].event_index, 1); // Latest event index first
105+
assert_eq!(events1[1].block_number, 100);
106+
assert_eq!(events1[1].event_index, 0);
108107

109-
// Test retrieval for subscription_id_2
108+
// Verify subscription 2 events
110109
let response2 = process_msg_get_events::<IdealIndexer>(&trees, key2.clone());
111110
let ResponseMessage::Events { key: response_key2, events: events2 } = response2 else {
112-
panic!("Wrong response message for subscription_id_2.");
111+
panic!("Wrong response message for subscription 2.");
113112
};
114113
assert_eq!(key2, response_key2);
115-
assert_eq!(events2.len(), 2);
116-
assert_eq!(events2[0].block_number, 14);
117-
assert_eq!(events2[1].block_number, 6);
114+
assert_eq!(events2.len(), 1);
115+
assert_eq!(events2[0].block_number, 101);
116+
assert_eq!(events2[0].event_index, 0);
118117
}
119118

120119
#[tokio::test]
121120
async fn test_h256_to_u32_conversion() {
122-
// Test the H256 to u32 conversion logic used in IDN Manager events
123-
let h256_bytes = [
124-
0x12, 0x34, 0x56, 0x78, // First 4 bytes (little-endian u32)
125-
0x9A, 0xBC, 0xDE, 0xF0, // Next 4 bytes (ignored)
126-
0x11, 0x22, 0x33, 0x44, // More bytes (ignored)
127-
0x55, 0x66, 0x77, 0x88, // More bytes (ignored)
128-
0xAA, 0xBB, 0xCC, 0xDD, // More bytes (ignored)
129-
0xEE, 0xFF, 0x00, 0x11, // More bytes (ignored)
130-
0x22, 0x33, 0x44, 0x55, // More bytes (ignored)
131-
0x66, 0x77, 0x88, 0x99, // Last 4 bytes (ignored)
121+
// Test the conversion logic
122+
let test_bytes = [
123+
0x78, 0x56, 0x34, 0x12, 0xAB, 0xCD, 0xEF, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132125
];
126+
let sub_id = SubscriptionId::new(test_bytes);
133127

134-
// Convert using the same logic as in our event handler
135-
let id_u32 = u32::from_le_bytes([h256_bytes[0], h256_bytes[1], h256_bytes[2], h256_bytes[3]]);
128+
// Should convert to 0x12345678 (little-endian)
129+
assert_eq!(sub_id.to_u32(), 0x12345678);
136130

137-
// Expected value: 0x78563412 (little-endian interpretation of 0x12, 0x34, 0x56, 0x78)
138-
assert_eq!(id_u32, 0x78563412);
139-
140-
// Test indexing with this converted ID
141-
let db_config = sled::Config::new().temporary(true);
142-
let trees = open_trees::<IdealIndexer>(db_config).unwrap();
143-
let indexer = Indexer::<IdealIndexer>::new_test(trees.clone());
144-
145-
let key = Key::Substrate(SubstrateKey::SubscriptionId(id_u32));
146-
indexer.index_event(key.clone(), 100, 1).unwrap();
147-
148-
let response = process_msg_get_events::<IdealIndexer>(&trees, key.clone());
149-
let ResponseMessage::Events { key: response_key, events } = response else {
150-
panic!("Wrong response message.");
151-
};
152-
assert_eq!(key, response_key);
153-
assert_eq!(events.len(), 1);
154-
assert_eq!(events[0].block_number, 100);
155-
assert_eq!(events[0].event_index, 1);
131+
// Test another case
132+
let test_bytes2 = [
133+
0xFF, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134+
0, 0, 0, 0, 0, 0,
135+
];
136+
let sub_id2 = SubscriptionId::new(test_bytes2);
137+
assert_eq!(sub_id2.to_u32(), 0x000000FF);
156138
}
157139

158140
#[tokio::test]
159141
async fn test_multiple_subscription_events_same_block() {
160-
// Test multiple subscription events in the same block with different event indices
161142
let db_config = sled::Config::new().temporary(true);
162143
let trees = open_trees::<IdealIndexer>(db_config).unwrap();
163144
let indexer = Indexer::<IdealIndexer>::new_test(trees.clone());
164145

165-
let subscription_id = 999u32;
166-
let key = Key::Substrate(SubstrateKey::SubscriptionId(subscription_id));
167-
let block_number = 50u32;
146+
let sub_id = SubscriptionId::new([1u8; 32]);
147+
let key = Key::Substrate(SubstrateKey::SubscriptionId(sub_id.to_u32()));
148+
let block_number = 100;
168149

169150
// Index multiple events in the same block
170-
indexer.index_event(key.clone(), block_number, 1).unwrap();
151+
indexer.index_event(key.clone(), block_number, 0).unwrap();
171152
indexer.index_event(key.clone(), block_number, 5).unwrap();
172-
indexer.index_event(key.clone(), block_number, 10).unwrap();
153+
indexer.index_event(key.clone(), block_number, 2).unwrap();
173154

174155
let response = process_msg_get_events::<IdealIndexer>(&trees, key.clone());
175156
let ResponseMessage::Events { key: response_key, events } = response else {
@@ -178,43 +159,38 @@ async fn test_multiple_subscription_events_same_block() {
178159
assert_eq!(key, response_key);
179160
assert_eq!(events.len(), 3);
180161

181-
// All events should be from the same block
182-
for event in &events {
183-
assert_eq!(event.block_number, block_number);
184-
}
185-
186-
// Event indices should be as expected (ordered by event index, highest first)
187-
assert_eq!(events[0].event_index, 10);
188-
assert_eq!(events[1].event_index, 5);
189-
assert_eq!(events[2].event_index, 1);
162+
// Events should be ordered by event_index descending within the same block
163+
assert_eq!(events[0].event_index, 5);
164+
assert_eq!(events[1].event_index, 2);
165+
assert_eq!(events[2].event_index, 0);
190166
}
191167

192168
#[tokio::test]
193169
async fn test_subscription_events_across_blocks() {
194-
// Test subscription events across multiple blocks to verify proper ordering
195170
let db_config = sled::Config::new().temporary(true);
196171
let trees = open_trees::<IdealIndexer>(db_config).unwrap();
197172
let indexer = Indexer::<IdealIndexer>::new_test(trees.clone());
198173

199-
let subscription_id = 777u32;
200-
let key = Key::Substrate(SubstrateKey::SubscriptionId(subscription_id));
174+
let sub_id = SubscriptionId::new([1u8; 32]);
175+
let key = Key::Substrate(SubstrateKey::SubscriptionId(sub_id.to_u32()));
201176

202-
// Index events across different blocks (not in chronological order)
203-
indexer.index_event(key.clone(), 100, 1).unwrap(); // Block 100
204-
indexer.index_event(key.clone(), 50, 3).unwrap(); // Block 50 (earlier)
205-
indexer.index_event(key.clone(), 150, 2).unwrap(); // Block 150 (later)
206-
indexer.index_event(key.clone(), 75, 1).unwrap(); // Block 75 (middle)
177+
// Index events across multiple blocks in non-sequential order
178+
indexer.index_event(key.clone(), 105, 1).unwrap();
179+
indexer.index_event(key.clone(), 100, 0).unwrap();
180+
indexer.index_event(key.clone(), 102, 3).unwrap();
207181

208182
let response = process_msg_get_events::<IdealIndexer>(&trees, key.clone());
209183
let ResponseMessage::Events { key: response_key, events } = response else {
210184
panic!("Wrong response message.");
211185
};
212186
assert_eq!(key, response_key);
213-
assert_eq!(events.len(), 4);
187+
assert_eq!(events.len(), 3);
214188

215-
// Events should be ordered by block number descending (latest first)
216-
assert_eq!(events[0].block_number, 150);
217-
assert_eq!(events[1].block_number, 100);
218-
assert_eq!(events[2].block_number, 75);
219-
assert_eq!(events[3].block_number, 50);
189+
// Events should be ordered by block_number descending, then event_index descending
190+
assert_eq!(events[0].block_number, 105);
191+
assert_eq!(events[0].event_index, 1);
192+
assert_eq!(events[1].block_number, 102);
193+
assert_eq!(events[1].event_index, 3);
194+
assert_eq!(events[2].block_number, 100);
195+
assert_eq!(events[2].event_index, 0);
220196
}

0 commit comments

Comments
 (0)