Skip to content

Commit 304b0d3

Browse files
authored
Merge pull request #4 from octopus-network/support-cleaning-state
Support cleaning state and add a view function.
2 parents a2f8a6d + e2a0490 commit 304b0d3

7 files changed

+271
-11
lines changed

near-ibc/src/context.rs

+57
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,60 @@ impl Debug for NearIbcStore {
9494
write!(f, "NearIbcStore {{ ... }}")
9595
}
9696
}
97+
98+
impl NearIbcStore {
99+
///
100+
pub fn remove_client(&mut self, client_id: &ClientId) {
101+
if let Some(vector) = self.client_connections.get_mut(client_id) {
102+
vector.clear();
103+
}
104+
self.client_connections.remove(client_id);
105+
if let Some(queue) = self.client_processed_heights.get_mut(client_id) {
106+
queue.clear();
107+
}
108+
self.client_processed_heights.remove(client_id);
109+
if let Some(queue) = self.client_processed_times.get_mut(client_id) {
110+
queue.clear();
111+
}
112+
self.client_processed_times.remove(client_id);
113+
if let Some(queue) = self.consensus_states.get_mut(client_id) {
114+
queue.clear();
115+
}
116+
self.consensus_states.remove(client_id);
117+
self.client_states.remove(client_id);
118+
self.client_types.remove(client_id);
119+
}
120+
///
121+
pub fn remove_connection(&mut self, connection_id: &ConnectionId) {
122+
if let Some(vector) = self.connection_channels.get_mut(connection_id) {
123+
vector.clear();
124+
}
125+
self.connection_channels.remove(connection_id);
126+
self.connections.remove(connection_id);
127+
}
128+
///
129+
pub fn remove_channel(&mut self, channel_end: &(PortId, ChannelId)) {
130+
if let Some(queue) = self.packet_receipts.get_mut(channel_end) {
131+
queue.clear();
132+
}
133+
self.packet_receipts.remove(channel_end);
134+
if let Some(queue) = self.packet_commitments.get_mut(channel_end) {
135+
queue.clear();
136+
}
137+
self.packet_commitments.remove(channel_end);
138+
if let Some(queue) = self.packet_acknowledgements.get_mut(channel_end) {
139+
queue.clear();
140+
}
141+
self.packet_acknowledgements.remove(channel_end);
142+
self.next_sequence_send.remove(channel_end);
143+
self.next_sequence_recv.remove(channel_end);
144+
self.next_sequence_ack.remove(channel_end);
145+
self.channels.remove(channel_end);
146+
}
147+
///
148+
pub fn clear_counters(&mut self) {
149+
self.client_ids_counter = 0;
150+
self.connection_ids_counter = 0;
151+
self.channel_ids_counter = 0;
152+
}
153+
}

near-ibc/src/indexed_lookup_queue.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,14 @@ where
108108
for index in self.start_index..self.end_index + 1 {
109109
if let Some(key) = self.index_map.get(&index) {
110110
env::storage_remove(
111-
migration::get_storage_key_in_lookup_array(
111+
migration::get_storage_key_of_lookup_map(
112112
&StorageKey::IbcEventsHistoryKey,
113113
&key,
114114
)
115115
.as_slice(),
116116
);
117117
env::storage_remove(
118-
migration::get_storage_key_in_lookup_array(
118+
migration::get_storage_key_of_lookup_map(
119119
&StorageKey::IbcEventsHistoryIndex,
120120
&index,
121121
)
@@ -146,6 +146,10 @@ where
146146
pub fn max_length(&self) -> u64 {
147147
self.max_length
148148
}
149+
///
150+
pub fn latest_key(&self) -> Option<K> {
151+
self.index_map.get(&self.end_index).map(|k| k.clone())
152+
}
149153
/// Get current length of the queue.
150154
pub fn len(&self) -> u64 {
151155
if self.end_index < self.start_index {

near-ibc/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ pub mod events;
4848
pub mod ibc_impl;
4949
pub mod indexed_lookup_queue;
5050
pub mod migration;
51+
pub mod testnet_functions;
52+
pub mod types;
5153
pub mod viewer;
5254

5355
pub const DEFAULT_COMMITMENT_PREFIX: &str = "ibc";
@@ -174,7 +176,8 @@ impl Contract {
174176
pub fn deliver(&mut self, messages: Vec<Any>) {
175177
assert!(
176178
env::attached_deposit() >= utils::MINIMUM_DEPOSIT_FOR_DELEVER_MSG,
177-
"Need to attach at least 0.1 NEAR to cover the possible storage cost."
179+
"Need to attach at least {} yocto NEAR to cover the possible storage cost.",
180+
utils::MINIMUM_DEPOSIT_FOR_DELEVER_MSG
178181
);
179182
let used_bytes = env::storage_usage();
180183
// Deliver messages to `ibc-rs`

near-ibc/src/migration.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ impl Contract {
2828
}
2929
}
3030

31-
pub fn get_storage_key_in_lookup_array<T: BorshSerialize>(
32-
prefix: &StorageKey,
33-
index: &T,
34-
) -> Vec<u8> {
31+
pub fn get_storage_key_of_lookup_map<T: BorshSerialize>(prefix: &StorageKey, index: &T) -> Vec<u8> {
3532
[prefix.try_to_vec().unwrap(), index.try_to_vec().unwrap()].concat()
3633
}

near-ibc/src/testnet_functions.rs

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use crate::{viewer::Viewer, *};
2+
use near_sdk::near_bindgen;
3+
4+
///
5+
fn assert_testnet() {
6+
assert!(
7+
env::current_account_id().to_string().ends_with("testnet"),
8+
"This method is only available on testnet"
9+
);
10+
}
11+
12+
#[near_bindgen]
13+
impl Contract {
14+
///
15+
pub fn clear_ibc_events_history(&mut self) {
16+
assert_testnet();
17+
self.assert_governance();
18+
self.ibc_events_history.clear();
19+
}
20+
///
21+
pub fn clear_ibc_store_counters(&mut self) {
22+
assert_testnet();
23+
self.assert_governance();
24+
let mut near_ibc_store = self.near_ibc_store.get().unwrap();
25+
near_ibc_store.clear_counters();
26+
self.near_ibc_store.set(&near_ibc_store);
27+
}
28+
///
29+
pub fn remove_client(&mut self, client_id: ClientId) {
30+
assert_testnet();
31+
self.assert_governance();
32+
let mut near_ibc_store = self.near_ibc_store.get().unwrap();
33+
let connections = self.get_client_connections(client_id.clone());
34+
for connection_id in connections {
35+
let channels = self.get_connection_channels(connection_id.clone());
36+
for channel in channels {
37+
near_ibc_store.remove_channel(&(channel.port_id, channel.channel_id));
38+
}
39+
near_ibc_store.remove_connection(&connection_id);
40+
}
41+
near_ibc_store.remove_client(&client_id);
42+
self.near_ibc_store.set(&near_ibc_store);
43+
}
44+
///
45+
pub fn remove_connection(&mut self, connection_id: ConnectionId) {
46+
assert_testnet();
47+
self.assert_governance();
48+
let mut near_ibc_store = self.near_ibc_store.get().unwrap();
49+
let channels = self.get_connection_channels(connection_id.clone());
50+
for channel in channels {
51+
near_ibc_store.remove_channel(&(channel.port_id, channel.channel_id));
52+
}
53+
near_ibc_store.remove_connection(&connection_id);
54+
self.near_ibc_store.set(&near_ibc_store);
55+
}
56+
///
57+
pub fn remove_channel(&mut self, channel_end: (PortId, ChannelId)) {
58+
assert_testnet();
59+
self.assert_governance();
60+
let mut near_ibc_store = self.near_ibc_store.get().unwrap();
61+
near_ibc_store.remove_channel(&channel_end);
62+
self.near_ibc_store.set(&near_ibc_store);
63+
}
64+
}

near-ibc/src/types.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use ibc::{
2+
core::{
3+
ics04_channel::packet::Sequence,
4+
ics24_host::identifier::{ChannelId, PortId},
5+
},
6+
events::WithBlockDataType,
7+
Height,
8+
};
9+
use near_sdk::serde::{Deserialize, Serialize};
10+
11+
#[derive(Clone, Debug, Serialize, Deserialize)]
12+
#[serde(crate = "near_sdk::serde")]
13+
pub enum QueryHeight {
14+
Latest,
15+
Specific(Height),
16+
}
17+
18+
#[derive(Clone, Debug, Serialize, Deserialize)]
19+
#[serde(crate = "near_sdk::serde")]
20+
pub enum Qualified<T> {
21+
SmallerEqual(T),
22+
Equal(T),
23+
}
24+
25+
#[derive(Clone, Debug, Serialize, Deserialize)]
26+
#[serde(crate = "near_sdk::serde")]
27+
pub struct QueryPacketEventDataRequest {
28+
pub event_id: WithBlockDataType,
29+
pub source_channel_id: ChannelId,
30+
pub source_port_id: PortId,
31+
pub destination_channel_id: ChannelId,
32+
pub destination_port_id: PortId,
33+
pub sequences: Vec<Sequence>,
34+
pub height: Qualified<QueryHeight>,
35+
}

near-ibc/src/viewer.rs

+104-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use crate::Contract;
1+
use crate::types::{Qualified, QueryHeight};
22
use crate::*;
3+
use crate::{types::QueryPacketEventDataRequest, Contract};
4+
use ibc::events::{IbcEventType, WithBlockDataType};
35
use ibc::{
46
core::{
57
ics03_connection::connection::{ConnectionEnd, IdentifiedConnectionEnd},
@@ -13,7 +15,6 @@ use ibc::{
1315
},
1416
Height,
1517
};
16-
use ibc_proto::ibc::core::channel::v1::QueryChannelsRequest;
1718

1819
pub trait Viewer {
1920
/// Get the latest height of the host chain.
@@ -48,7 +49,7 @@ pub trait Viewer {
4849
/// Get all connections associated with the given client id.
4950
fn get_client_connections(&self, client_id: ClientId) -> Vec<ConnectionId>;
5051
/// Get the channel ends associated with the given query request.
51-
fn get_channels(&self, request: QueryChannelsRequest) -> Vec<IdentifiedChannelEnd>;
52+
fn get_channels(&self) -> Vec<IdentifiedChannelEnd>;
5253
/// Get the channel ends associated with the given connection id.
5354
fn get_connection_channels(&self, connection_id: ConnectionId) -> Vec<IdentifiedChannelEnd>;
5455
/// Get the packet commitment stored on this host.
@@ -74,6 +75,11 @@ pub trait Viewer {
7475
fn get_packet_acknowledgements(&self, port_id: PortId, channel_id: ChannelId) -> Vec<Sequence>;
7576
/// Get the commitment packet stored on this host.
7677
fn get_commitment_prefix(&self) -> CommitmentPrefix;
78+
/// Get the packet events associated with the given query request.
79+
fn get_packet_events(
80+
&self,
81+
request: QueryPacketEventDataRequest,
82+
) -> Vec<(Height, Vec<IbcEvent>)>;
7783
/// Get the heights that ibc events happened on.
7884
fn get_ibc_events_heights(&self) -> Vec<u64>;
7985
/// Get ibc events happened on the given height.
@@ -236,7 +242,7 @@ impl Viewer for Contract {
236242
)
237243
}
238244

239-
fn get_channels(&self, request: QueryChannelsRequest) -> Vec<IdentifiedChannelEnd> {
245+
fn get_channels(&self) -> Vec<IdentifiedChannelEnd> {
240246
let near_ibc_store = self.near_ibc_store.get().unwrap();
241247
near_ibc_store
242248
.channels
@@ -261,6 +267,7 @@ impl Viewer for Contract {
261267
|channels| {
262268
channels
263269
.iter()
270+
.filter(|key| near_ibc_store.channels.contains_key(key))
264271
.map(|(port_id, channel_id)| IdentifiedChannelEnd {
265272
port_id: port_id.clone(),
266273
channel_id: channel_id.clone(),
@@ -356,6 +363,55 @@ impl Viewer for Contract {
356363
.unwrap_or_default()
357364
}
358365

366+
fn get_packet_events(
367+
&self,
368+
request: QueryPacketEventDataRequest,
369+
) -> Vec<(Height, Vec<IbcEvent>)> {
370+
let mut result: Vec<(Height, Vec<IbcEvent>)> = Vec::new();
371+
let (target_height, need_to_search_in_range) = match &request.height {
372+
Qualified::SmallerEqual(query_height) => match query_height {
373+
QueryHeight::Latest => (self.ibc_events_history.latest_key(), true),
374+
QueryHeight::Specific(height) => (Some(height.revision_height()), true),
375+
},
376+
Qualified::Equal(query_height) => match query_height {
377+
QueryHeight::Latest => (self.ibc_events_history.latest_key(), false),
378+
QueryHeight::Specific(height) => (Some(height.revision_height()), false),
379+
},
380+
};
381+
if need_to_search_in_range {
382+
if let Some(height) = target_height {
383+
self.ibc_events_history
384+
.keys()
385+
.iter()
386+
.filter(|key| key.is_some())
387+
.map(|key| key.unwrap())
388+
.filter(|key| *key <= height)
389+
.for_each(|key| {
390+
gether_ibc_events_with_height(
391+
&mut result,
392+
key,
393+
self.ibc_events_history
394+
.get_value_by_key(&key)
395+
.map(|events| {
396+
Vec::<IbcEvent>::try_from_slice(&events)
397+
.unwrap_or_else(|_| vec![])
398+
})
399+
.unwrap_or_else(|| vec![]),
400+
&request,
401+
);
402+
});
403+
}
404+
} else {
405+
let events = self
406+
.ibc_events_history
407+
.get_value_by_key(&target_height.unwrap())
408+
.map_or_else(|| vec![], |events| events);
409+
let ibc_events = Vec::<IbcEvent>::try_from_slice(&events).unwrap_or_else(|_| vec![]);
410+
gether_ibc_events_with_height(&mut result, target_height.unwrap(), ibc_events, &request)
411+
}
412+
result
413+
}
414+
359415
fn get_ibc_events_heights(&self) -> Vec<u64> {
360416
self.ibc_events_history
361417
.keys()
@@ -373,3 +429,47 @@ impl Viewer for Contract {
373429
Vec::<IbcEvent>::try_from_slice(&raw_events).unwrap_or_else(|_| vec![])
374430
}
375431
}
432+
433+
fn gether_ibc_events_with_height(
434+
result: &mut Vec<(Height, Vec<IbcEvent>)>,
435+
height: u64,
436+
ibc_events: Vec<IbcEvent>,
437+
request: &QueryPacketEventDataRequest,
438+
) {
439+
let events = ibc_events
440+
.iter()
441+
.filter(|event| match request.event_id {
442+
WithBlockDataType::CreateClient => event.event_type() == IbcEventType::CreateClient,
443+
WithBlockDataType::UpdateClient => event.event_type() == IbcEventType::UpdateClient,
444+
WithBlockDataType::SendPacket => event.event_type() == IbcEventType::SendPacket,
445+
WithBlockDataType::WriteAck => event.event_type() == IbcEventType::WriteAck,
446+
})
447+
.filter(|event| match event {
448+
IbcEvent::CreateClient(_) => true,
449+
IbcEvent::UpdateClient(_) => true,
450+
IbcEvent::ReceivePacket(receive_packet) => {
451+
request.source_port_id.eq(receive_packet.src_port_id())
452+
&& request
453+
.source_channel_id
454+
.eq(receive_packet.src_channel_id())
455+
&& request.destination_port_id.eq(receive_packet.dst_port_id())
456+
&& request
457+
.destination_channel_id
458+
.eq(receive_packet.dst_channel_id())
459+
&& request.sequences.contains(&receive_packet.sequence())
460+
}
461+
IbcEvent::WriteAcknowledgement(write_ack) => {
462+
request.source_port_id.eq(write_ack.src_port_id())
463+
&& request.source_channel_id.eq(write_ack.src_channel_id())
464+
&& request.destination_port_id.eq(write_ack.dst_port_id())
465+
&& request
466+
.destination_channel_id
467+
.eq(write_ack.dst_channel_id())
468+
&& request.sequences.contains(&write_ack.sequence())
469+
}
470+
_ => false,
471+
})
472+
.map(|event| event.clone())
473+
.collect_vec();
474+
result.push((Height::new(0, height).unwrap(), events));
475+
}

0 commit comments

Comments
 (0)