-
Notifications
You must be signed in to change notification settings - Fork 15
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
Feat: decouple CFE from SC events #4382
Conversation
match_event! {event, { | ||
CfeEvent::EthThresholdSignatureRequest(req) => { | ||
handle_signing_request::<_, _, _, EthereumInstance>( | ||
scope, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting
571210a
to
77e996c
Compare
fcdb6df
to
39098a5
Compare
39098a5
to
b546f91
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙌 product team requests to update events can be accommodated much more easily now
state-chain/runtime/src/lib.rs
Outdated
@@ -756,6 +770,7 @@ construct_runtime!( | |||
{ | |||
System: frame_system, | |||
Timestamp: pallet_timestamp, | |||
CfeEventEmitter: pallet_cf_cfe_event_emitter, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussion here: https://discord.com/channels/775961728608895008/1195210668819878030
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved back to the end of the list (now using custom order of pallet execution instead)
So just to summarise, in this PR we need a way to clear events at exact block boundary (so that if we request storage for a block hash, we only get events generated at that block). The current solution is/was to put the CFE events pallet before any pallet that might emit a CFE event and clear the events in on_initialize. However, as discussed on discord, this is prolematic as we don't want to change the indexes of the existing pallets. I see a few options as to how to proceed: a) Go back to the original approach where we store events in a map so that events from different blocks can be queried separately (i.e. reverting 9760930) b) Clear events in the earliest pallet that currently emits CFE events, so that we can be sure that no new events are lost. @AlastairHolmes also suggested modifying the existing system pallet to do something similar (or even moving the storage for the CFE events there). Any other suggestions? Kyle suggested that you might have some thoughts @dandanlen. |
We can customise the execution order of the hooks. In the runtime.rs we have: pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
PalletMigrations,
>; We can replace The only downsides I can think is that we need to remember to maintain this, ie. when we add a new pallet, the hooks need to be added to the custom tuple. This also applies to eg. integration tests: we need to replicate the same execution order instead of relying on the default. edit: another downside is that the hooks are executed after runtime upgrades, meaning we would be unable to emit any cfe events during a runtime upgrade. For this reason, the system events are in fact deleted before anything else (before any hooks and before the runtime upgrade). We should consider doing the same for the cfe events as Alastair suggested, but this would involve editing either The benefit is that we don't need to worry about re-ordering pallets in the runtime declaration - as you mentioned @msgmaxim this will continue to cause issues whenever we want to add eg. a new chain. A third option would be to make the breaking change and re-order the pallets, but to use some pre-defined explicit ranges with some gaps for future additions, ie.: construct_runtime!(
pub struct Runtime
{
System: frame_system = 0,
Timestamp: pallet_timestamp,
CfeEventEmitter: pallet_cf_cfe_event_emitter,
// 3: TBC
// 4: TBC
Environment: pallet_cf_environment = 5,
Flip: pallet_cf_flip,
Emissions: pallet_cf_emissions,
// etc..
}
); This would buy us some time but will eventually also run into the same limitation (at some point we might run out of free indices between pallets). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I would prefer a less restrictive pallet name, for example cfe-interface - long term, we might use this pallet for things other than events, for example to group cfe-specific storage values, or to host cfe-specific extrinsics (for example the version number for compatibility checks, or submitting/storing the peer info, which is used only by the cfe, not by the runtime).
|
||
benchmarks! { | ||
|
||
clear_events { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will break when we generate new benchmarks: it needs to be called remove_events_for_block
or alternatively, the method in WeightInfo
needs to be renamed to clear_events
. (I actually prefer the latter given that you removed the index per-block).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 0b710a2
payload: broadcast_attempt.transaction_payload.clone(), | ||
}); | ||
|
||
// TODO: consider removing this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we not remove it? I guess polkaJS, debugging?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
edit - I saw there was another comment thread about this, think I agree with keeping it for now
state-chain/traits/src/lib.rs
Outdated
} | ||
} | ||
|
||
pub trait CfeEventEmitterT<T: Chainflip> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not something like CfePeerRegistration
?
We don't need to assume that the underlying implementation emits events.
Similarly for the other traits. Could be CfeMultisigRequest
, CfeBroadcastRequest
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking was that the same trait would be used for many potentially unrelated events (ideally all of them, but because some pallets are generic over either Crypto
or Chain
, I had to create separate traits for them). I see that CfeMultisigRequest
is likely to cover any current/future Crypto
related events, but I wonder if we would want to add more events from non-generic pallets to CfeEventEmitterT
. Would we then prefer separate traits for different events? (I don't really mind either way.)
I will rename the traits like you are suggesting (considering that we can easily rename them again if needed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I would prefer more granular traits over a single 'god trait'. Makes it easier to mock, makes the intent clearer etc.
I also feel like it's worth distinguishing the interface from the implementation. It doesn't matter that it emits an event - for example you mentioned we might remove peer registration events in favour of storage writes. What matters is that when you use an implementation of this trait, you expect to notify the engine of a peer update. Whether it's an event or a storage write, or some mock that simply writes to a log, is not really relevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed traits in d2fdc66
If we forget, does this mean the hooks for that pallet won't be executed? If that's the case, then I don't think it is a really big deal, since we will certaintly notice that something doesn't work.
Do you mean in migration code? Seems unlikely that there will be a need for that. Even if do we need something like that, I imagine it wouldn't be too difficult to come up with a workaround.
Sould like a reasonable approach. Should I go ahead with this or do we want to think about this more? @dandanlen |
I think a custom tuple gives us the quickest win right now. Also, we'll need this anyway whenever we add a new chain. We will need to remain aware of the runtime upgrade weirdness: For example say we want to trigger a threshold signature or a broadcast during a runtime upgrade, the current approach would not allow this. I'll open a Linear issue to customize the executor/system pallet events reset mechanism. |
Made this change here: |
It looks like some integration tests are failing. Could be related to the change in ordering... either way, it looks like all the tests are failing at the same assertion, so should (hopefully!) be a simple fix. @syan095 might be able to help out here, he's quite familiar with the integration tests. (Also it looks like his recent PR conflicts with this one). |
LGTM otherwise 🎉 |
Fixed integration tests in 71b2087 and resolved the conflict with main @dandanlen. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kylezs still needs to approve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙌
…itness-swap * origin/main: (24 commits) fix: restore correct restriction on redemption expiry (PRO-1072) Feat/migrate-to-polkadot-sdk-repo (#4361) chore: fix RUSTSEC-2024-0003 (#4426) Feat: decouple CFE from SC events (#4382) chore: add docker tag prefix to `chainflip-ingress-egress-tacker` 🏷️ (#4427) refactor/PRO-1101: rid of swapping minimum swap amount (#4419) refactor(ingress-egress-tracker): remove unnecessary fields (#4425) Improved the retry queue storage (#4420) fix: bump spec version command only bumps when necessary (#4422) refactor: use yargs for all try_runtime_command options (#4423) fix: await finalisation before starting broker (#4412) chore: debug logs to see get_raw_txs query (#4413) doc: correct env vars (#4416) fix: pool_orders rpc filters empty orders (PRO-1039) (#4377) Produce an event in case the swap yields a zero egress amount (#4410) fix: don't have conflicting redis port with localnet (#4415) Ability to specify output for the subcommands, other than `/dev/null` (#4411) chore: increase limit on max number of bitcoin payloads in a ceremony to theoretical maximum (#4396) refactor(ingress-egress-tracker): configurable expiry times [WEB-761] (#4406) fix: use existing script for upgrade job (#4403) ... # Conflicts: # Cargo.lock # state-chain/primitives/Cargo.toml
Pull Request
Closes PRO-1091
Checklist
Please conduct a thorough self-review before opening the PR.
Summary
After discussion with @dandanlen I decided to create a separate pallet for CFE events, so that all events are in the same place and we don't need to repeat the mechanism for cleaning up events etc (the alternative I first considered was having CFE read storage items from separate pallets).
All events are stored in the CfeEvents storage item, which can be queried by block number. In SC Observer, once we receive a new finalized header, we now query all events for that block. Events are stored for 20 blocks after which they are removed, which should give the CFE enough time to retrieve them.
All events are defined in the CfeEvent enum. I imagine we can create simple tests decoding/encoding each variant from/to some hardcoded values to ensure that we don't accidentally make incompatible changes (probably in a separate PR).
I created a few traits, some of which are generic over chain or crypto, so that our generic code (broadcaster, threshold signature etc) can use them while running slightly different code for each. I think for the most part I was able to avoid duplicating code where possible.
I'm pretty sure this doesn't require a runtime storage migration, but let me know if I'm wrong. I did test upgrading runtime from main to this branch and it worked as expected, initialising CfeEvents with the default value (empty container).