[TASK] Queue Proposals and implement Policy-based validation #513
Labels
difficulty: challenging 🏴☠️
feature ➕
Tasks that are functional additions or enhancements
p0 🔥
Critical issues that need to be resolved immediately
task ✔️
Note: Part of Smart Anchor Updates v2
Overview of the Current Approach of handling the Proposals
For any proposal, that implements the following trait:
We have a
ProposalSigningBackend
defined like the following:When we want to execute some proposal
P
we send it to the Proposal Signing backend to be signed then sent to the target system to be executed. In our example we have a Proposal Type calledAnchorUpdate
Proposal, and is defined as following (For EVM Chains):And for convince, here is how any
ProposalHeader
looks like:So, Imagine we have 3 Chains here (Goerli, Mumbai, and Rinkeby), each have a different resource Id composed of their Anchor Smart contract address + Typed Chain Id. When some user updates the MerkleTree on Goerli, the relayer have to create
2
Anchor Update Proposals one that targets Mumbai, and another one that targets Rinkeby, sends both of these two proposals to the be signed by the proposals signing backend, and once signed they will be sent as transactions to another smart contract calledSignatureBridge
that only accepts signed proposals. This all good if we have one update every now and then, but imagine we have a lot of updates that happens more frequently? this means we are going to create a lot of Anchor Update proposals and hence a lot of txs. However, Note that we only need to relay the last merkle root, so that means we do not need send each proposal to be signed and to be executed, we could make a better job here to optimize this and save up the resources and gas fees.To optimize the handling of Anchor Update Proposals and reduce gas fees and resource usage, we can introduce a queuing mechanism and implement a policy-based approach for determining when to sign and execute proposals. Here's an outline of the proposed solution:
Proposal Queue: Create a proposal queue to store incoming Anchor Update Proposals. The queue should keep track of the most recent proposal for each resource ID.
Policy-based Approach: Introduce a policy-based architecture to determine whether a proposal should be signed and executed based on various conditions. We'll define a
ProposalPolicy
trait with methods for checking if a proposal should be signed and executed. We can chain multiple policies together to create a flexible decision-making process.Example policies:
NoncePolicy
: Checks if the proposal has a higher nonce than the most recent proposal for the same resource ID.TimeDelayPolicy
: Considers the time elapsed since the last proposal for a resource ID and determines whether it's appropriate to send a new proposal based on a delay threshold.SignatureBridge Integration: Modify the
ProposalSigningBackend
to work with the queuing mechanism and policies. Thehandle_proposal
method will enqueue the proposal if it satisfies the policies. The queuing mechanism will ensure that only the most recent proposal for each resource ID is stored.Background Worker: Run a background worker that periodically checks the proposal queue and processes proposals that satisfy the policies. This worker will handle signing and executing proposals based on the policies and interact with the
SignatureBridge
smart contract.The worker can utilize the policies to determine the order and timing of proposal execution. For example, it can prioritize proposals based on nonce, waiting for the appropriate time delay, and execute them accordingly.
The worker can be implemented using async tasks and timers, ensuring efficient resource utilization.
By implementing the above solution, we ensure that only the most recent proposals are processed, and redundant proposals with old nonces are discarded. The policies allow for flexible decision-making based on various constraints, and the background worker ensures efficient processing and utilization of resources.
To implement the
TimeDelayPolicy
that adjusts the delay dynamically based on the number of incoming proposals, you can use a sliding window algorithm. Here's an example of how you can implement it in Rust:In this implementation, we maintain a sliding window of the
delays
vector, which keeps track of the delays of the most recent proposals. We initialize it with theINITIAL_DELAY
value.The
update_delay
method is responsible for updating the delay value based on the number of incoming proposals. It calculates the average delay from the sliding window and adjusts the current delay based on the average and the number of proposals. The adjusted delay is capped betweenMIN_DELAY
andMAX_DELAY
.The
get_delay
method returns the current delay as aDuration
type, which can be used for waiting or scheduling tasks.To use the
TimeDelayPolicy
in your code, you can call theupdate_delay
method whenever a new proposal arrives and pass the number of proposals received so far. Then, you can retrieve the current delay by callingget_delay
.The text was updated successfully, but these errors were encountered: