-
Notifications
You must be signed in to change notification settings - Fork 90
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
Circuit breaker remove solver #2705
Conversation
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.
Let's please make sure the circuit breaker is an opt-in functionality on the autopilot (ie. it's sufficiently factored as a separate background task which can be left out e.g. in local deployments).
c2cd383
to
6e3acc1
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.
I would like to see a CircuitBreaker
struct from the get go that should store the state required to remove solvers (e.g. EOA).
Ideally this struct should be able to handle all the logic around removing solvers in a background task. If for some reason (maybe it makes the most sense to decide some things in the autopilot during the competition) that struct could expose the remove_sovler
function which the autopilot could then call if needed.
But overall I think we should try to leave the autopilot untouched if possible because for proper decentralization it should be possible to ban solvers solely based on on-chain data.
6e3acc1
to
311037c
Compare
311037c
to
bbaa7cf
Compare
So, how I understand, the flow is following:
So, bottom line, circuit breaker's smallest responsibility unit is to execute remove solver and nothing else. Edit: posting the question since afais based on the PR changes, @Mateo-mro understood that circuit breaker needs to observe onchain settlement on it's own and be completely disconnected from the EventHandler. |
Not sure if my gut makes sense but it seems strange to fit all this logic into Another thing that irks me with tying the |
Notes from the call:
@Mateo-mro can you then work on these points (except (3) as I am still working on it). You can skip this step and just mock an intention to removeSolver (for example, call it for every event for now). |
38ca09f
to
e0b47c8
Compare
crates/autopilot/src/arguments.rs
Outdated
@@ -359,6 +365,7 @@ impl std::fmt::Display for Arguments { | |||
max_settlement_transaction_wait | |||
)?; | |||
writeln!(f, "s3: {:?}", s3)?; | |||
writeln!(f, "circuit breaker: {:?}", circuit_breaker)?; |
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.
@sunce86 @MartinquaXD can we display the authenticator_eoa
here? or should we hide it?
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.
The EOA is actually a private key so it should be hidden.
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.
In practice let's please KMS for this.
registry.append(&mut events); | ||
(registry.len() > Self::MAX_REGISTRY_SIZE).then(|| { | ||
(0..(registry.len() - Self::MAX_REGISTRY_SIZE)).for_each(|_| { | ||
registry.pop_first(); | ||
}) | ||
}); | ||
} |
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.
Agreed with @sunce86 to do it by fetching 4 events from the database and keeping in memory the processed ones, but we are open to change it of course.
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.
What's more, I know this piece of code could be difficult to read (I am a .then()
and .for_each()
lover), I am open to change it.
38193ef
to
78f5397
Compare
crates/autopilot/src/arguments.rs
Outdated
impl FromStr for CircuitBreaker { | ||
type Err = anyhow::Error; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { |
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 providing a single string that configures 2 different things is a bit weird. Instead you could pass these things separately and make them both optional. Validating the input would then basically just be throwing an error if exactly 1 thing is set.
Also it could be that we require more arguments for the circuit breaker and adding more and more stuff to that string will become messy pretty quickly.
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.
@MartinquaXD This comment is on non-existing code (I deleted it).
|
||
#[allow(dead_code)] | ||
pub struct CircuitBreaker { | ||
eth: infra::blockchain::circuit_breaker::CircuitBreaker, |
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 is this called eth
?
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.
@MartinquaXD This comment is on non-existing code (I deleted it).
.unwrap() | ||
}; | ||
|
||
let settlement = contracts::GPv2Settlement::at( |
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.
IMO the decision to use a custom address or a deployed address should be done at single point in the backend. For example it doesn't make a lot of sense to have 1 component use one address for the settlement contract and another component another address. Overall I think whoever instantiates the Authenticator
should be responsible for picking the correct address.
Also the settlement contract doesn't really matter here. We only need the authenticator contract.
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 suggested this to @Mateo-mro so that Authenticator
relies less on intermediary objects built between the autopilot startup and Authenticator
constructor being called -> to be more independent of the rest of the code.
For example it doesn't make a lot of sense to have 1 component use one address for the settlement contract and another component another address.
I believe this is also irrelevant for the Authenticator
as a component that we envision running as a separate process etc. Choosing the right address would be the responsibility of Authenticator
.
.expect("authenticator address"), | ||
); | ||
|
||
let authenticator_role = contracts::Roles::at( |
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.
Also why do we effectively overriding the authenticator address but not the roles address? IMO another indicator that these dependencies should be injected.
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.
True. IMO all contracts that the Authenticator
depends on need to be received via Addresses
.
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.
but in that case shouldn't we be passing Contracts
instead of Addresses
? does it also make sense for the addresses which are specific for the circuit breaker? like the role or authenticator eoa?
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.
If we want to make the component as independent as possible, it should receive raw configuration params so it can independently build whatever it needs to work properly.
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.
With that in mind, Contracts
is an internal autopilot component and shouldn't be forwarded to Authenticator
. The reason being once we wish to move Authenticator
out of the autopilot
there would be no need to refactor constructor to not work with Contracts
.
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.
but I think that making an object depending on another object within the same crate is totally ok. In my mind, having a struct which instantiates the contracts and then those contracts are use somewhere else (in circuit breaker) would make sense 🤔
If you want to make the module as independent as possible, then we can have two builders (or new
) for it, once with raw address and the other with the contract, so if we move it out of autopilot it won't require any change.
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 don't want to bikeshed on this too much, since it's not essential for delivery of feature (and it also won't be too problematic to refactor this if needed). That said, I am ok with both versions.
f9f5910
to
4a57e96
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.
One last thing. The new authenticator
module currently lives in the infra/solvers
which seems odd. That directory holds all the code needed to talk to the solvers. /infra/blockchain
seems more appropriate since it's used to send transactions to the blockchain. 🤔
616b9a7
to
3c8d2cf
Compare
Merging since I got two approvals (counting also @sunce86 's approval here: #2705 (review)) |
Description
Related to #2667
POC implementation for using "Roles" safe module to grant special role to an EOA to sign and execute "removeSolver" function on behalf of the gpv2_authenticator manager/owner safe.
Need to add tests to see if this actually works.
Changes
Roles
smart contractremove_solver
functionHow to test
todo