Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SYS-3965: added first stage migration of processed events mechanism to eth-bridge #390

Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
76d87a2
Sys 3931 identify events (#368)
ivan-cholakov Mar 20, 2024
22252f3
SYS-3635: extends the voting mechanism
thadouk Mar 14, 2024
668ec6b
SYS-3930: Extends validate unsigned for new extrinsic (#370)
thadouk Mar 21, 2024
31f33bf
SYS-3930: Implement Vote Processing (#371)
thadouk Apr 9, 2024
5d718a7
feat: added runtime-api for eth-event polling (#376)
ivan-cholakov Apr 10, 2024
ad9c0ff
feat: added runtime-api for eth-event polling (#376)
ivan-cholakov Apr 10, 2024
88f7000
SYS-3932 - implement initial version of polling mechanism (#378)
ivan-cholakov Apr 16, 2024
b535a33
added functionality
MBrozhko34 Apr 24, 2024
bc8a0fd
tests, mock, more changes
MBrozhko34 May 2, 2024
9af749d
Introduces initial range consesnus mechanism (#391)
thadouk May 2, 2024
61cb434
Exposes initial range voting via the runtime API (#393)
thadouk May 2, 2024
13b32f3
SYS-3930 Adds unit tests for event votes (#372)
thadouk May 2, 2024
787caa3
Merge branch 'feat/SYS-3560-add-event-listener' into SYS-3965-migrati…
MBrozhko34 May 2, 2024
0bf2b26
tidy-up, add comments
MBrozhko34 May 2, 2024
5b1abf1
fix merge issue, add more comments
MBrozhko34 May 2, 2024
c483d18
SYS-3930 Cleanup and finalises interface with runtime (#396)
thadouk May 3, 2024
842e507
Merge remote-tracking branch 'origin/feat/SYS-3560-add-event-listener…
thadouk May 3, 2024
41933c7
Squashed commit of the following:
thadouk May 3, 2024
e87e939
Merge branch 'test-squash-thadouk-michaels-work' into SYS-3965-migrat…
thadouk May 3, 2024
e807d3c
rename event and update
nahuseyoum May 3, 2024
0cc35cb
Merge branch 'SYS-3965-migration-processed-events-mechanism-first' of…
nahuseyoum May 3, 2024
c0c44f9
update code and fix tests
nahuseyoum May 13, 2024
5b8b876
Change error handling in process events, fmt code
MBrozhko34 May 14, 2024
0b52c39
re-add accepted and rejected events
MBrozhko34 May 15, 2024
3a41efd
fix error handling
MBrozhko34 May 16, 2024
e19db3b
revert error handling, do not throw errors
MBrozhko34 May 21, 2024
4b74809
revert again
MBrozhko34 May 21, 2024
f527116
small tests fix
MBrozhko34 May 21, 2024
66e0143
Update pallets/eth-bridge/src/lib.rs
MBrozhko34 May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions pallets/avn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,13 +703,15 @@ impl<ValidatorId: Member> Enforcer<ValidatorId> for () {
}

pub trait ProcessedEventsChecker {
fn check_event(event_id: &EthEventId) -> bool;
fn processed_event_exists(event_id: &EthEventId) -> bool;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

fn add_processed_event(event_id: &EthEventId, accepted: bool);
}

impl ProcessedEventsChecker for () {
fn check_event(_event_id: &EthEventId) -> bool {
return false
}
fn processed_event_exists(_event_id: &EthEventId) -> bool { false }

fn add_processed_event(_event_id: &EthEventId, _accepted: bool) {}
}

pub trait OnGrowthLiftedHandler<Balance> {
Expand Down Expand Up @@ -749,7 +751,7 @@ pub trait BridgeInterfaceNotification {
fn process_lower_proof_result(_: u32, _: Vec<u8>, _: Result<Vec<u8>, ()>) -> DispatchResult {
Ok(())
}
fn on_event_processed(_event: &EthEvent) -> DispatchResult {
fn on_incoming_event_processed(_event: &EthEvent) -> DispatchResult {
Ok(())
}
}
Expand All @@ -770,8 +772,8 @@ impl BridgeInterfaceNotification for Tuple {
Ok(())
}

fn on_event_processed(_event: &EthEvent) -> DispatchResult {
for_tuples!( #( Tuple::on_event_processed(_event)?; )* );
fn on_incoming_event_processed(_event: &EthEvent) -> DispatchResult {
for_tuples!( #( Tuple::on_incoming_event_processed(_event)?; )* );
Ok(())
}
}
Expand Down
46 changes: 28 additions & 18 deletions pallets/eth-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use frame_system::{
pallet_prelude::{BlockNumberFor, OriginFor},
};
use pallet_avn::{
self as avn, BridgeInterface, BridgeInterfaceNotification, Error as avn_error, LowerParams,
self as avn, BridgeInterface, BridgeInterfaceNotification, ProcessedEventsChecker, Error as avn_error, LowerParams,
MAX_VALIDATOR_ACCOUNTS,
};

Expand Down Expand Up @@ -111,6 +111,9 @@ mod mock;
#[cfg(test)]
#[path = "tests/tests.rs"]
mod tests;
#[cfg(test)]
#[path = "tests/incoming_events_tests.rs"]
mod incoming_events_tests;

pub use pallet::*;
pub mod default_weights;
Expand Down Expand Up @@ -183,6 +186,7 @@ pub mod pallet {
IdentificationTuple<Self>,
CorroborationOffence<IdentificationTuple<Self>>,
>;
type ProcessedEventsChecker: ProcessedEventsChecker;
type EthereumEventsFilter: EthereumEventsFilterTrait;
}

Expand Down Expand Up @@ -303,6 +307,7 @@ pub mod pallet {
ExceedsConfirmationLimit,
ExceedsCorroborationLimit,
ExceedsFunctionNameLimit,
EventAlreadyProcessed,
FunctionEncodingError,
FunctionNameError,
HandlePublishingResultFailed,
Expand Down Expand Up @@ -565,6 +570,7 @@ pub mod pallet {
);

let mut votes = EthereumEvents::<T>::get(&events_partition);

votes.try_insert(author.account_id).map_err(|_| Error::<T>::EventVotesFull)?;

if votes.len() < AVN::<T>::quorum() as usize {
Expand Down Expand Up @@ -801,14 +807,12 @@ pub mod pallet {
match ValidEvents::try_from(&discovered_event.event.event_id.signature) {
Some(valid_event) =>
if active_range.event_types_filter.contains(&valid_event) {
process_ethereum_event::<T>(&discovered_event.event);
let _ = process_ethereum_event::<T>(&discovered_event.event);
} else {
log::warn!("Ethereum event signature ({:?}) included in approved range ({:?}), but not part of the expected ones {:?}", &discovered_event.event.event_id.signature, active_range.range, active_range.event_types_filter);
},
None => log::warn!(
"Unknown Ethereum event signature in range {:?}",
&discovered_event.event.event_id.signature
),
None => log::warn!("Unknown Ethereum event signature in range {:?}", &discovered_event.event.event_id.signature)

};
}

Expand All @@ -819,23 +823,29 @@ pub mod pallet {
}
}

fn process_ethereum_event<T: Config>(event: &EthEvent) {
// TODO: re-add the `Accepted and Rejected events
fn process_ethereum_event<T: Config>(event: &EthEvent) -> Result<(), DispatchError> {
// TODO before processing ensure that the event has not already been processed
match T::BridgeInterfaceNotification::on_event_processed(&event) {
Ok(_) => {
<Pallet<T>>::deposit_event(Event::<T>::EventProcessed {
accepted: true,
eth_event_id: event.event_id.clone(),
});
},
// Do the check that is not processed via ProcessedEventsChecker

ensure!(false == T::ProcessedEventsChecker::processed_event_exists(&event.event_id.clone()), Error::<T>::EventAlreadyProcessed);
let mut event_accepted = false;

match T::BridgeInterfaceNotification::on_incoming_event_processed(&event) {
Ok(_) => { event_accepted = true },
Err(err) => {
log::error!("💔 Processing ethereum event failed: {:?}", err);
<Pallet<T>>::deposit_event(Event::<T>::EventProcessed {
accepted: false,
eth_event_id: event.event_id.clone(),
});
},
};

<Pallet<T>>::deposit_event(Event::<T>::EventProcessed {
accepted: event_accepted,
eth_event_id: event.event_id.clone(),
});
// Add record of succesful processing via ProcessedEventsChecker
T::ProcessedEventsChecker::add_processed_event(&event.event_id.clone(), event_accepted);

Ok(())
}

#[pallet::validate_unsigned]
Expand Down
91 changes: 91 additions & 0 deletions pallets/eth-bridge/src/tests/incoming_events_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2023 Aventus Network Systems (UK) Ltd.

#![cfg(test)]
use crate::{eth::generate_send_calldata, mock::*, request::*, *};
use frame_support::{
assert_err, assert_noop, assert_ok, dispatch::DispatchResultWithPostInfo, error::BadOrigin,
};
use sp_runtime::{testing::UintAuthorityId, DispatchError};
pub extern crate alloc;
use alloc::collections::BTreeSet;
use sp_avn_common::event_discovery::EthBridgeEventsFilter;

const ROOT_HASH: &str = "30b83f0d722d1d4308ab4660a72dbaf0a7392d5674eca3cd21d57256d42df7a0";
const REWARDS: &[u8] = b"15043665996000000000";
const AVG_STAKED: &[u8] = b"9034532443555111110000";
const PERIOD: &[u8] = b"3";
const T2_PUB_KEY: &str = "14aeac90dbd3573458f9e029eb2de122ee94f2f0bc5ee4b6c6c5839894f1a547";
const T1_PUB_KEY: &str = "23d79f6492dddecb436333a5e7a4cfcc969f568e01283fa2964aae15327fb8a3b685a4d0f3ef9b3c2adb20f681dbc74b7f82c1cf8438d37f2c10e9c79591e9ea";

// Added this function as in event_listener_tests to initialize the active event range
fn init_active_range() {
ActiveEthereumRange::<TestRuntime>::put(ActiveEthRange {
range: EthBlockRange { start_block: 1, length: 1000 },
partition: 0,
event_types_filter: EthBridgeEventsFilter::try_from(vec![
ValidEvents::AddedValidator,
ValidEvents::Lifted,
ValidEvents::AvtGrowthLifted,
ValidEvents::AvtLowerClaimed,
]
.into_iter()
.collect::<BTreeSet<ValidEvents>>()).unwrap()
});
}

mod process_events {
use sp_avn_common::event_types::EthEventId;
use super::*;

// succesfully process the specified ethereum_event
#[test]
fn succesful_event_processing_accepted() {
let mut ext = ExtBuilder::build_default().with_validators().as_externality();
ext.execute_with(|| {
let context = setup_context();
init_active_range();

// Two calls needed as upon the first there are not enough votes to pass the condition in lib.rs line 563, to reach the call of process_ethereum_events_partition()
assert_ok!(EthBridge::submit_ethereum_events(RuntimeOrigin::none(), context.author.clone(), context.mock_event_partition.clone(), context.test_signature.clone()));
assert_ok!(EthBridge::submit_ethereum_events(RuntimeOrigin::none(), context.author_two.clone(), context.mock_event_partition.clone(), context.test_signature_two.clone()));

assert!(System::events().iter().any(|record| record.event ==
mock::RuntimeEvent::EthBridge(Event::<TestRuntime>::EventProcessed {
accepted: true,
eth_event_id: context.eth_event_id.clone(),
})));
});
}


// This test should fail processing the ethereum_event and emit the specified event
#[test]
fn succesful_event_processing_not_accepted() {
let mut ext = ExtBuilder::build_default().with_validators().as_externality();
ext.execute_with(|| {
let context = setup_context();
init_active_range();
assert_ok!(EthBridge::submit_ethereum_events(RuntimeOrigin::none(), context.author.clone(), context.bad_mock_event_partition.clone(), context.test_signature.clone()));
assert_ok!(EthBridge::submit_ethereum_events(RuntimeOrigin::none(), context.author_two.clone(), context.bad_mock_event_partition.clone(), context.test_signature.clone()));


assert!(System::events().iter().any(|record| record.event ==
mock::RuntimeEvent::EthBridge(Event::<TestRuntime>::EventProcessed {
accepted: false,
eth_event_id: context.bad_eth_event_id.clone(),
})));
});
}


// This test should fail on the check T::ProcessedEventsChecker::processed_event_exists(&event.event_id.clone()), if the event is already in the system
#[test]
fn event_already_processed() {
let mut ext = ExtBuilder::build_default().with_validators().as_externality();
ext.execute_with(|| {
let context = setup_context();
init_active_range();
assert_ok!(EthBridge::submit_ethereum_events(RuntimeOrigin::none(), context.author, context.mock_event_partition, context.test_signature));
});
}
}
Loading