Skip to content

Commit f879358

Browse files
Fisherman updates and fixes (#313)
Co-authored-by: Seun Lanlege <seun@polytope.technology>
1 parent 3663d36 commit f879358

File tree

21 files changed

+352
-66
lines changed

21 files changed

+352
-66
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/ismp/pallets/asset-gateway/src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ where
234234
convert_to_erc20(amount).to_big_endian(&mut bytes);
235235
alloy_primitives::U256::from_be_bytes(bytes)
236236
},
237-
max_fee: Default::default(),
238237
asset_id,
239238
redeem: false,
240239
from: from.into(),
@@ -279,8 +278,6 @@ alloy_sol_macro::sol! {
279278
struct Body {
280279
// Amount of the asset to be sent
281280
uint256 amount;
282-
// Maximum amount to pay for liquidity fees
283-
uint256 max_fee;
284281
// The asset identifier
285282
bytes32 asset_id;
286283
// Flag to redeem the erc20 asset on the destination

modules/ismp/pallets/demo/src/lib.rs

+31-5
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ pub mod pallet {
5151
};
5252
use frame_system::pallet_prelude::*;
5353
use ismp::{
54+
consensus::{StateCommitment, StateMachineHeight},
5455
dispatcher::{DispatchGet, DispatchPost, DispatchRequest, FeeMetadata, IsmpDispatcher},
55-
host::StateMachine,
56+
host::{IsmpHost, StateMachine},
5657
};
5758

5859
#[pallet::pallet]
@@ -70,7 +71,8 @@ pub mod pallet {
7071
/// Native currency implementation
7172
type NativeCurrency: Mutate<Self::AccountId>;
7273
/// Ismp message disptacher
73-
type IsmpDispatcher: IsmpDispatcher<Account = Self::AccountId, Balance = <Self as Config>::Balance>
74+
type IsmpHost: IsmpHost
75+
+ IsmpDispatcher<Account = Self::AccountId, Balance = <Self as Config>::Balance>
7476
+ Default;
7577
}
7678

@@ -162,7 +164,7 @@ pub mod pallet {
162164
};
163165

164166
// dispatch the request
165-
let dispatcher = T::IsmpDispatcher::default();
167+
let dispatcher = T::IsmpHost::default();
166168
dispatcher
167169
.dispatch_request(
168170
DispatchRequest::Post(post),
@@ -202,7 +204,7 @@ pub mod pallet {
202204
context: Default::default(),
203205
};
204206

205-
let dispatcher = T::IsmpDispatcher::default();
207+
let dispatcher = T::IsmpHost::default();
206208
dispatcher
207209
.dispatch_request(
208210
DispatchRequest::Get(get),
@@ -224,7 +226,7 @@ pub mod pallet {
224226
timeout: params.timeout,
225227
body: b"Hello from polkadot".to_vec(),
226228
};
227-
let dispatcher = T::IsmpDispatcher::default();
229+
let dispatcher = T::IsmpHost::default();
228230
for _ in 0..params.count {
229231
// dispatch the request
230232
dispatcher
@@ -236,6 +238,30 @@ pub mod pallet {
236238
}
237239
Ok(())
238240
}
241+
242+
/// Insert an unverified state commitment into the host, this is for testing purposes only.
243+
#[pallet::weight(Weight::from_parts(1_000_000, 0))]
244+
#[pallet::call_index(3)]
245+
pub fn set_state_commitment(
246+
origin: OriginFor<T>,
247+
height: StateMachineHeight,
248+
commitment: StateCommitment,
249+
) -> DispatchResult {
250+
use ismp::events::{Event, StateMachineUpdated};
251+
ensure_root(origin)?;
252+
let host = T::IsmpHost::default();
253+
254+
// shouldn't return an error
255+
host.store_state_machine_commitment(height, commitment).unwrap();
256+
host.store_state_machine_update_time(height, host.timestamp()).unwrap();
257+
258+
// deposit the event
259+
pallet_ismp::Pallet::<T>::deposit_pallet_event(Event::StateMachineUpdated(
260+
StateMachineUpdated { state_machine_id: height.id, latest_height: height.height },
261+
));
262+
263+
Ok(())
264+
}
239265
}
240266

241267
/// Transfer payload

modules/ismp/pallets/testsuite/src/tests/pallet_asset_gateway.rs

-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ fn should_process_on_accept_module_callback_correctly() {
149149
},
150150
asset_id: pallet_asset_gateway::Pallet::<Test>::dot_asset_id().0.into(),
151151
redeem: false,
152-
max_fee: Default::default(),
153152
from: alloy_primitives::B256::from_slice(ALICE.as_slice()),
154153
to: alloy_primitives::B256::from_slice(ALICE.as_slice()),
155154
};
@@ -260,7 +259,6 @@ fn should_process_on_timeout_module_callback_correctly() {
260259
},
261260
asset_id: pallet_asset_gateway::Pallet::<Test>::dot_asset_id().0.into(),
262261
redeem: false,
263-
max_fee: Default::default(),
264262
from: alloy_primitives::FixedBytes::<32>::from_slice(ALICE.as_slice()),
265263
to: alloy_primitives::FixedBytes::<32>::from_slice(&[0u8; 32]),
266264
};

modules/ismp/pallets/testsuite/src/tests/xcm_integration_test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async fn should_dispatch_ismp_request_when_xcm_is_received() -> anyhow::Result<(
8686
)
8787
.encode_call_data(&client.metadata())?;
8888
let tx = Extrinsic::new("Sudo", "sudo", encoded_call);
89-
send_extrinsic(&client, signer, tx).await?;
89+
send_extrinsic(&client, signer, tx, None).await?;
9090
}
9191

9292
let ext = Extrinsic::new(
@@ -102,7 +102,7 @@ async fn should_dispatch_ismp_request_when_xcm_is_received() -> anyhow::Result<(
102102
.ok_or_else(|| anyhow!("Failed to fetch latest header"))?
103103
.number();
104104

105-
send_extrinsic(&client, signer, ext).await?;
105+
send_extrinsic(&client, signer, ext, None).await?;
106106

107107
let mut sub = para_client.rpc().subscribe_finalized_block_headers().await?;
108108

modules/utils/subxt/src/lib.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,14 @@ pub mod signer {
365365
client: &OnlineClient<T>,
366366
signer: InMemorySigner<T>,
367367
payload: Tx,
368+
tip: Option<PlainTip>,
368369
) -> Result<T::Hash, anyhow::Error>
369370
where
370371
<T::ExtrinsicParams as ExtrinsicParams<T::Hash>>::OtherParams:
371372
Default + Send + Sync + From<BaseExtrinsicParamsBuilder<T, PlainTip>>,
372373
T::Signature: From<MultiSignature> + Send + Sync,
373374
{
374-
let other_params = BaseExtrinsicParamsBuilder::new();
375+
let other_params = BaseExtrinsicParamsBuilder::new().tip(tip.unwrap_or_default());
375376
let ext = client.tx().create_signed(&payload, &signer, other_params.into()).await?;
376377
let progress = ext.submit_and_watch().await.context("Failed to submit signed extrinsic")?;
377378
let ext_hash = progress.extrinsic_hash();
@@ -442,3 +443,17 @@ pub fn host_params_storage_key(state_machine: StateMachine) -> Vec<u8> {
442443

443444
[pallet_prefix, storage_prefix, key_1, state_machine.encode()].concat()
444445
}
446+
447+
pub fn fisherman_storage_key(address: Vec<u8>) -> Vec<u8> {
448+
let address = {
449+
let mut dest = [0u8; 32];
450+
dest.copy_from_slice(&address);
451+
dest
452+
};
453+
let pallet_prefix = twox_128(b"Fishermen").to_vec();
454+
455+
let storage_prefix = twox_128(b"Fishermen").to_vec();
456+
let key_1 = twox_64(&address.encode()).to_vec();
457+
458+
[pallet_prefix, storage_prefix, key_1, address.encode()].concat()
459+
}

parachain/runtimes/gargantua/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ parachains-common = { workspace = true }
8282
# local modules
8383
ismp = { workspace = true }
8484
pallet-ismp = { workspace = true, features = ["unsigned"] }
85+
pallet-fishermen = { workspace = true }
8586
pallet-ismp-demo = { workspace = true }
8687
pallet-ismp-runtime-api = { workspace = true }
8788
ismp-sync-committee = { workspace = true }
@@ -135,6 +136,7 @@ std = [
135136
"pallet-transaction-payment/std",
136137
"pallet-xcm/std",
137138
"pallet-treasury/std",
139+
"pallet-fishermen/std",
138140
"pallet-asset-rate/std",
139141
"pallet-collective/std",
140142
"pallet-ismp/std",

parachain/runtimes/gargantua/src/ismp.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl pallet_ismp_demo::Config for Runtime {
112112
type RuntimeEvent = RuntimeEvent;
113113
type Balance = Balance;
114114
type NativeCurrency = Balances;
115-
type IsmpDispatcher = Ismp;
115+
type IsmpHost = Ismp;
116116
}
117117

118118
impl pallet_ismp_relayer::Config for Runtime {
@@ -134,6 +134,11 @@ impl ismp_parachain::Config for Runtime {
134134
type IsmpHost = Ismp;
135135
}
136136

137+
impl pallet_fishermen::Config for Runtime {
138+
type RuntimeEvent = RuntimeEvent;
139+
type IsmpHost = Ismp;
140+
}
141+
137142
// todo: set corrrect parameters
138143
parameter_types! {
139144
pub const AssetPalletId: PalletId = PalletId(*b"asset-tx");
@@ -193,6 +198,11 @@ impl pallet_assets::Config for Runtime {
193198
impl IsmpModule for ProxyModule {
194199
fn on_accept(&self, request: PostRequest) -> Result<(), Error> {
195200
if request.dest != HostStateMachine::get() {
201+
let token_gateway = Gateway::token_gateway_address(&request.dest);
202+
if request.source.is_substrate() && request.from == token_gateway.0.to_vec() {
203+
Err(Error::Custom("Illegal request!".into()))?
204+
}
205+
196206
Ismp::dispatch_request(
197207
Request::Post(request),
198208
FeeMetadata::<Runtime> { payer: [0u8; 32].into(), fee: Default::default() },

parachain/runtimes/gargantua/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
232232
spec_name: create_runtime_str!("gargantua"),
233233
impl_name: create_runtime_str!("gargantua"),
234234
authoring_version: 1,
235-
spec_version: 900,
235+
spec_version: 1130,
236236
impl_version: 0,
237237
apis: RUNTIME_API_VERSIONS,
238238
transaction_version: 1,
@@ -707,6 +707,7 @@ construct_runtime!(
707707
Assets: pallet_assets = 58,
708708
TokenGovernor: pallet_token_governor = 59,
709709
StateCoprocessor: pallet_state_coprocessor = 60,
710+
Fishermen: pallet_fishermen = 61,
710711

711712
// Governance
712713
TechnicalCollective: pallet_collective = 80,

parachain/runtimes/nexus/src/ismp.rs

+4
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ impl pallet_assets::Config for Runtime {
175175
impl IsmpModule for ProxyModule {
176176
fn on_accept(&self, request: PostRequest) -> Result<(), Error> {
177177
if request.dest != HostStateMachine::get() {
178+
let token_gateway = Gateway::token_gateway_address(&request.dest);
179+
if request.source.is_substrate() && request.from == token_gateway.0.to_vec() {
180+
Err(Error::Custom("Illegal request!".into()))?
181+
}
178182
Ismp::dispatch_request(
179183
Request::Post(request),
180184
FeeMetadata::<Runtime> { payer: [0u8; 32].into(), fee: Default::default() },

tesseract/evm/src/byzantine.rs

+92-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
use std::sync::Arc;
1+
use std::{sync::Arc, time::Duration};
22

3+
use anyhow::{anyhow, Error};
34
use ethers::providers::Middleware;
5+
use futures::FutureExt;
46
use ismp::{
57
consensus::{StateMachineHeight, StateMachineId},
6-
events::StateMachineUpdated,
8+
events::{Event, StateMachineUpdated},
9+
host::StateMachine,
710
};
8-
use tesseract_primitives::{ByzantineHandler, IsmpProvider};
11+
use tesseract_primitives::{BoxStream, ByzantineHandler, IsmpProvider};
912

1013
use crate::EvmClient;
1114

1215
#[async_trait::async_trait]
1316
impl ByzantineHandler for EvmClient {
1417
async fn check_for_byzantine_attack(
1518
&self,
19+
_coprocessor: StateMachine,
1620
counterparty: Arc<dyn IsmpProvider>,
1721
event: StateMachineUpdated,
1822
) -> Result<(), anyhow::Error> {
@@ -46,4 +50,89 @@ impl ByzantineHandler for EvmClient {
4650

4751
Ok(())
4852
}
53+
54+
async fn state_machine_updates(
55+
&self,
56+
_counterparty_state_id: StateMachineId,
57+
) -> Result<BoxStream<Vec<StateMachineUpdated>>, Error> {
58+
use futures::StreamExt;
59+
let (tx, recv) = tokio::sync::broadcast::channel(512);
60+
61+
let initial_height = self.client.get_block_number().await?.low_u64();
62+
let client = self.clone();
63+
let poll_interval = 5;
64+
tokio::spawn(async move {
65+
let mut latest_height = initial_height;
66+
let state_machine = client.state_machine;
67+
loop {
68+
tokio::time::sleep(Duration::from_secs(poll_interval)).await;
69+
// wait for an update with a greater height
70+
let block_number = match client.client.get_block_number().await {
71+
Ok(number) => number.low_u64(),
72+
Err(err) => {
73+
if let Err(err) = tx
74+
.send(Err(anyhow!(
75+
"Error fetching latest block height on {state_machine:?} {err:?}"
76+
).into()))
77+
{
78+
log::error!(target: "tesseract", "Failed to send message over channel on {state_machine:?} \n {err:?}");
79+
return
80+
}
81+
continue;
82+
},
83+
};
84+
85+
if block_number <= latest_height {
86+
continue;
87+
}
88+
89+
let event = StateMachineUpdated {
90+
state_machine_id: client.state_machine_id(),
91+
latest_height: block_number,
92+
};
93+
94+
let events = match client.query_ismp_events(latest_height, event).await {
95+
Ok(events) => events,
96+
Err(err) => {
97+
if let Err(err) = tx
98+
.send(Err(anyhow!(
99+
"Error encountered while querying ismp events {err:?}"
100+
).into()))
101+
{
102+
log::error!(target: "tesseract", "Failed to send message over channel on {state_machine:?} \n {err:?}");
103+
return
104+
}
105+
latest_height = block_number;
106+
continue;
107+
},
108+
};
109+
110+
let events = events
111+
.into_iter()
112+
.filter_map(|ev| match ev {
113+
Event::StateMachineUpdated(update) => Some(update),
114+
_ => None,
115+
}).collect::<Vec<_>>();
116+
117+
if !events.is_empty() {
118+
if let Err(err) = tx
119+
.send(Ok(events))
120+
{
121+
log::error!(target: "tesseract", "Failed to send message over channel on {state_machine:?} \n {err:?}");
122+
return
123+
}
124+
}
125+
latest_height = block_number;
126+
}
127+
}.boxed());
128+
129+
let stream = tokio_stream::wrappers::BroadcastStream::new(recv).filter_map(|res| async {
130+
match res {
131+
Ok(res) => Some(res),
132+
Err(err) => Some(Err(anyhow!("{err:?}").into())),
133+
}
134+
});
135+
136+
Ok(Box::pin(stream))
137+
}
49138
}

tesseract/evm/src/provider.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ impl IsmpProvider for EvmClient {
676676
let provider = Arc::new(client.clone());
677677
// Yield if the challenge period elapses and the state commitment is not vetoed
678678
tokio::select! {
679-
_res = wait_for_challenge_period(provider, state_machine_update_time, challenge_period) => {
679+
_res = wait_for_challenge_period(provider, state_machine_update_time, challenge_period, counterparty_state_id.state_id) => {
680680
match _res {
681681
Ok(_) => {
682682
if let Err(err) = tx.send(Ok(event.clone())) {

0 commit comments

Comments
 (0)