Skip to content

Commit

Permalink
Fisherman updates and fixes (#313)
Browse files Browse the repository at this point in the history
Co-authored-by: Seun Lanlege <[email protected]>
  • Loading branch information
Wizdave97 and seunlanlege authored Sep 23, 2024
1 parent 3663d36 commit f879358
Show file tree
Hide file tree
Showing 21 changed files with 352 additions and 66 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions modules/ismp/pallets/asset-gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ where
convert_to_erc20(amount).to_big_endian(&mut bytes);
alloy_primitives::U256::from_be_bytes(bytes)
},
max_fee: Default::default(),
asset_id,
redeem: false,
from: from.into(),
Expand Down Expand Up @@ -279,8 +278,6 @@ alloy_sol_macro::sol! {
struct Body {
// Amount of the asset to be sent
uint256 amount;
// Maximum amount to pay for liquidity fees
uint256 max_fee;
// The asset identifier
bytes32 asset_id;
// Flag to redeem the erc20 asset on the destination
Expand Down
36 changes: 31 additions & 5 deletions modules/ismp/pallets/demo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ pub mod pallet {
};
use frame_system::pallet_prelude::*;
use ismp::{
consensus::{StateCommitment, StateMachineHeight},
dispatcher::{DispatchGet, DispatchPost, DispatchRequest, FeeMetadata, IsmpDispatcher},
host::StateMachine,
host::{IsmpHost, StateMachine},
};

#[pallet::pallet]
Expand All @@ -70,7 +71,8 @@ pub mod pallet {
/// Native currency implementation
type NativeCurrency: Mutate<Self::AccountId>;
/// Ismp message disptacher
type IsmpDispatcher: IsmpDispatcher<Account = Self::AccountId, Balance = <Self as Config>::Balance>
type IsmpHost: IsmpHost
+ IsmpDispatcher<Account = Self::AccountId, Balance = <Self as Config>::Balance>
+ Default;
}

Expand Down Expand Up @@ -162,7 +164,7 @@ pub mod pallet {
};

// dispatch the request
let dispatcher = T::IsmpDispatcher::default();
let dispatcher = T::IsmpHost::default();
dispatcher
.dispatch_request(
DispatchRequest::Post(post),
Expand Down Expand Up @@ -202,7 +204,7 @@ pub mod pallet {
context: Default::default(),
};

let dispatcher = T::IsmpDispatcher::default();
let dispatcher = T::IsmpHost::default();
dispatcher
.dispatch_request(
DispatchRequest::Get(get),
Expand All @@ -224,7 +226,7 @@ pub mod pallet {
timeout: params.timeout,
body: b"Hello from polkadot".to_vec(),
};
let dispatcher = T::IsmpDispatcher::default();
let dispatcher = T::IsmpHost::default();
for _ in 0..params.count {
// dispatch the request
dispatcher
Expand All @@ -236,6 +238,30 @@ pub mod pallet {
}
Ok(())
}

/// Insert an unverified state commitment into the host, this is for testing purposes only.
#[pallet::weight(Weight::from_parts(1_000_000, 0))]
#[pallet::call_index(3)]
pub fn set_state_commitment(
origin: OriginFor<T>,
height: StateMachineHeight,
commitment: StateCommitment,
) -> DispatchResult {
use ismp::events::{Event, StateMachineUpdated};
ensure_root(origin)?;
let host = T::IsmpHost::default();

// shouldn't return an error
host.store_state_machine_commitment(height, commitment).unwrap();
host.store_state_machine_update_time(height, host.timestamp()).unwrap();

// deposit the event
pallet_ismp::Pallet::<T>::deposit_pallet_event(Event::StateMachineUpdated(
StateMachineUpdated { state_machine_id: height.id, latest_height: height.height },
));

Ok(())
}
}

/// Transfer payload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ fn should_process_on_accept_module_callback_correctly() {
},
asset_id: pallet_asset_gateway::Pallet::<Test>::dot_asset_id().0.into(),
redeem: false,
max_fee: Default::default(),
from: alloy_primitives::B256::from_slice(ALICE.as_slice()),
to: alloy_primitives::B256::from_slice(ALICE.as_slice()),
};
Expand Down Expand Up @@ -260,7 +259,6 @@ fn should_process_on_timeout_module_callback_correctly() {
},
asset_id: pallet_asset_gateway::Pallet::<Test>::dot_asset_id().0.into(),
redeem: false,
max_fee: Default::default(),
from: alloy_primitives::FixedBytes::<32>::from_slice(ALICE.as_slice()),
to: alloy_primitives::FixedBytes::<32>::from_slice(&[0u8; 32]),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ async fn should_dispatch_ismp_request_when_xcm_is_received() -> anyhow::Result<(
)
.encode_call_data(&client.metadata())?;
let tx = Extrinsic::new("Sudo", "sudo", encoded_call);
send_extrinsic(&client, signer, tx).await?;
send_extrinsic(&client, signer, tx, None).await?;
}

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

send_extrinsic(&client, signer, ext).await?;
send_extrinsic(&client, signer, ext, None).await?;

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

Expand Down
17 changes: 16 additions & 1 deletion modules/utils/subxt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,13 +365,14 @@ pub mod signer {
client: &OnlineClient<T>,
signer: InMemorySigner<T>,
payload: Tx,
tip: Option<PlainTip>,
) -> Result<T::Hash, anyhow::Error>
where
<T::ExtrinsicParams as ExtrinsicParams<T::Hash>>::OtherParams:
Default + Send + Sync + From<BaseExtrinsicParamsBuilder<T, PlainTip>>,
T::Signature: From<MultiSignature> + Send + Sync,
{
let other_params = BaseExtrinsicParamsBuilder::new();
let other_params = BaseExtrinsicParamsBuilder::new().tip(tip.unwrap_or_default());
let ext = client.tx().create_signed(&payload, &signer, other_params.into()).await?;
let progress = ext.submit_and_watch().await.context("Failed to submit signed extrinsic")?;
let ext_hash = progress.extrinsic_hash();
Expand Down Expand Up @@ -442,3 +443,17 @@ pub fn host_params_storage_key(state_machine: StateMachine) -> Vec<u8> {

[pallet_prefix, storage_prefix, key_1, state_machine.encode()].concat()
}

pub fn fisherman_storage_key(address: Vec<u8>) -> Vec<u8> {
let address = {
let mut dest = [0u8; 32];
dest.copy_from_slice(&address);
dest
};
let pallet_prefix = twox_128(b"Fishermen").to_vec();

let storage_prefix = twox_128(b"Fishermen").to_vec();
let key_1 = twox_64(&address.encode()).to_vec();

[pallet_prefix, storage_prefix, key_1, address.encode()].concat()
}
2 changes: 2 additions & 0 deletions parachain/runtimes/gargantua/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ parachains-common = { workspace = true }
# local modules
ismp = { workspace = true }
pallet-ismp = { workspace = true, features = ["unsigned"] }
pallet-fishermen = { workspace = true }
pallet-ismp-demo = { workspace = true }
pallet-ismp-runtime-api = { workspace = true }
ismp-sync-committee = { workspace = true }
Expand Down Expand Up @@ -135,6 +136,7 @@ std = [
"pallet-transaction-payment/std",
"pallet-xcm/std",
"pallet-treasury/std",
"pallet-fishermen/std",
"pallet-asset-rate/std",
"pallet-collective/std",
"pallet-ismp/std",
Expand Down
12 changes: 11 additions & 1 deletion parachain/runtimes/gargantua/src/ismp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl pallet_ismp_demo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type NativeCurrency = Balances;
type IsmpDispatcher = Ismp;
type IsmpHost = Ismp;
}

impl pallet_ismp_relayer::Config for Runtime {
Expand All @@ -134,6 +134,11 @@ impl ismp_parachain::Config for Runtime {
type IsmpHost = Ismp;
}

impl pallet_fishermen::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type IsmpHost = Ismp;
}

// todo: set corrrect parameters
parameter_types! {
pub const AssetPalletId: PalletId = PalletId(*b"asset-tx");
Expand Down Expand Up @@ -193,6 +198,11 @@ impl pallet_assets::Config for Runtime {
impl IsmpModule for ProxyModule {
fn on_accept(&self, request: PostRequest) -> Result<(), Error> {
if request.dest != HostStateMachine::get() {
let token_gateway = Gateway::token_gateway_address(&request.dest);
if request.source.is_substrate() && request.from == token_gateway.0.to_vec() {
Err(Error::Custom("Illegal request!".into()))?
}

Ismp::dispatch_request(
Request::Post(request),
FeeMetadata::<Runtime> { payer: [0u8; 32].into(), fee: Default::default() },
Expand Down
3 changes: 2 additions & 1 deletion parachain/runtimes/gargantua/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("gargantua"),
impl_name: create_runtime_str!("gargantua"),
authoring_version: 1,
spec_version: 900,
spec_version: 1130,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down Expand Up @@ -707,6 +707,7 @@ construct_runtime!(
Assets: pallet_assets = 58,
TokenGovernor: pallet_token_governor = 59,
StateCoprocessor: pallet_state_coprocessor = 60,
Fishermen: pallet_fishermen = 61,

// Governance
TechnicalCollective: pallet_collective = 80,
Expand Down
4 changes: 4 additions & 0 deletions parachain/runtimes/nexus/src/ismp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ impl pallet_assets::Config for Runtime {
impl IsmpModule for ProxyModule {
fn on_accept(&self, request: PostRequest) -> Result<(), Error> {
if request.dest != HostStateMachine::get() {
let token_gateway = Gateway::token_gateway_address(&request.dest);
if request.source.is_substrate() && request.from == token_gateway.0.to_vec() {
Err(Error::Custom("Illegal request!".into()))?
}
Ismp::dispatch_request(
Request::Post(request),
FeeMetadata::<Runtime> { payer: [0u8; 32].into(), fee: Default::default() },
Expand Down
95 changes: 92 additions & 3 deletions tesseract/evm/src/byzantine.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use std::sync::Arc;
use std::{sync::Arc, time::Duration};

use anyhow::{anyhow, Error};
use ethers::providers::Middleware;
use futures::FutureExt;
use ismp::{
consensus::{StateMachineHeight, StateMachineId},
events::StateMachineUpdated,
events::{Event, StateMachineUpdated},
host::StateMachine,
};
use tesseract_primitives::{ByzantineHandler, IsmpProvider};
use tesseract_primitives::{BoxStream, ByzantineHandler, IsmpProvider};

use crate::EvmClient;

#[async_trait::async_trait]
impl ByzantineHandler for EvmClient {
async fn check_for_byzantine_attack(
&self,
_coprocessor: StateMachine,
counterparty: Arc<dyn IsmpProvider>,
event: StateMachineUpdated,
) -> Result<(), anyhow::Error> {
Expand Down Expand Up @@ -46,4 +50,89 @@ impl ByzantineHandler for EvmClient {

Ok(())
}

async fn state_machine_updates(
&self,
_counterparty_state_id: StateMachineId,
) -> Result<BoxStream<Vec<StateMachineUpdated>>, Error> {
use futures::StreamExt;
let (tx, recv) = tokio::sync::broadcast::channel(512);

let initial_height = self.client.get_block_number().await?.low_u64();
let client = self.clone();
let poll_interval = 5;
tokio::spawn(async move {
let mut latest_height = initial_height;
let state_machine = client.state_machine;
loop {
tokio::time::sleep(Duration::from_secs(poll_interval)).await;
// wait for an update with a greater height
let block_number = match client.client.get_block_number().await {
Ok(number) => number.low_u64(),
Err(err) => {
if let Err(err) = tx
.send(Err(anyhow!(
"Error fetching latest block height on {state_machine:?} {err:?}"
).into()))
{
log::error!(target: "tesseract", "Failed to send message over channel on {state_machine:?} \n {err:?}");
return
}
continue;
},
};

if block_number <= latest_height {
continue;
}

let event = StateMachineUpdated {
state_machine_id: client.state_machine_id(),
latest_height: block_number,
};

let events = match client.query_ismp_events(latest_height, event).await {
Ok(events) => events,
Err(err) => {
if let Err(err) = tx
.send(Err(anyhow!(
"Error encountered while querying ismp events {err:?}"
).into()))
{
log::error!(target: "tesseract", "Failed to send message over channel on {state_machine:?} \n {err:?}");
return
}
latest_height = block_number;
continue;
},
};

let events = events
.into_iter()
.filter_map(|ev| match ev {
Event::StateMachineUpdated(update) => Some(update),
_ => None,
}).collect::<Vec<_>>();

if !events.is_empty() {
if let Err(err) = tx
.send(Ok(events))
{
log::error!(target: "tesseract", "Failed to send message over channel on {state_machine:?} \n {err:?}");
return
}
}
latest_height = block_number;
}
}.boxed());

let stream = tokio_stream::wrappers::BroadcastStream::new(recv).filter_map(|res| async {
match res {
Ok(res) => Some(res),
Err(err) => Some(Err(anyhow!("{err:?}").into())),
}
});

Ok(Box::pin(stream))
}
}
2 changes: 1 addition & 1 deletion tesseract/evm/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ impl IsmpProvider for EvmClient {
let provider = Arc::new(client.clone());
// Yield if the challenge period elapses and the state commitment is not vetoed
tokio::select! {
_res = wait_for_challenge_period(provider, state_machine_update_time, challenge_period) => {
_res = wait_for_challenge_period(provider, state_machine_update_time, challenge_period, counterparty_state_id.state_id) => {
match _res {
Ok(_) => {
if let Err(err) = tx.send(Ok(event.clone())) {
Expand Down
Loading

0 comments on commit f879358

Please sign in to comment.