-
Notifications
You must be signed in to change notification settings - Fork 25
Add flashtestations builder transaction #268
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
base: main
Are you sure you want to change the base?
Conversation
fb9ed66
to
64be228
Compare
let tee_address_bytes: [u8; 20] = tee_service_signer.address.into(); | ||
|
||
// Calculate keccak256 hash of empty bytes (32 bytes) | ||
let ext_data = Bytes::from(b""); |
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.
it is always empty?
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.
https://github.com/flashbots/rollup-boost/blob/main/specs/flashtestations.md#extended-registration-data empty for now as we don't have operator keys
// Builder proof version | ||
builder_proof_version: u8, | ||
// Whether the workload and address has been registered | ||
registered: Arc<AtomicBool>, |
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.
OnceLock would be nice in here, but it's nit
|
||
if !self.registered.load(Ordering::Relaxed) { | ||
info!(target: "flashtestations", "tee service not registered yet, attempting to register"); | ||
self.set_registered(state_provider, ctx); |
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 is the purpose of this? If we set_registered to true in here we would still create tx in register_tee_service_tx, right?
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.
this function simulates the registration in the evm and we want to minimise the number of calls to this by only checking while we are not registered. The self.register_tee_service_tx will return None if there is an already registered error from the evm
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 see that side effect of set_registered is self.registered.store(registered, Ordering::Relaxed);
Should we do let (register_tx, _) = self.register_tee_service_tx(ctx, &mut evm)?; first and then set_registered?
Or maybe we should do self.set_registered(state_provider, ctx); and then check self.registered again, in case it's registered already and we don't need to register
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.
Should we do let (register_tx, _) = self.register_tee_service_tx(ctx, &mut evm)?; first and then set_registered
the order doesn't matter since self.register_tee_service_tx(ctx, &mut evm)? simulates against the block state that has been built thus far and self.set_registered is simulated against the committed state. this is to prevent registered set to true when the register tx is committed at the top of the block and then ends up not being included in the canonical chain. It would also not guard against reorgs
let verify_block_proof_tx = self.signed_block_builder_proof_tx( | ||
block_content_hash, | ||
ctx, | ||
gas_used * 64 / 63, |
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.
Little bit confused in here
If we want to add buffer of size gas_used / 64, then we need to do
gas_used * 65 / 64
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.
so if the contract call uses 1000 gas and only 63/64 is forwarded:
needed = 1000 gas
forwarded = 1000 * 63 / 64 = 984.375
to adjust the needed gas limit equal to the forwarded amount:
(1000 * 64 / 63) * (63 / 64) = 1000
let nonce = get_nonce(evm.db_mut(), self.tee_service_signer.address)?; | ||
let register_tx = self.signed_register_tee_service_tx( | ||
self.attestation.clone(), | ||
gas_used * 64 / 63, // Due to EIP-150, 63/64 of available gas is forwarded to external calls so need to add a buffer |
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.
same as below
warn!(target: "flashtestations", %err, "register tee service tx failed"); | ||
return Ok(TxSimulateResult::default()); |
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 it okay to ignore the error here?
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.
they are not fatal errors should be handled separately (nonce, balance, gas issues)
warn!(target: "flashtestations", "transaction did not emit TEEServiceRegistered log, FlashtestationRegistry contract address may be incorrect"); | ||
Ok((None, false)) |
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.
not propagating the error here seems like it could get messy, why not propagate the errors and handle them in the caller?
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.
only fatal errors were returned as it was being propagated to the payload builder and stopping blocks being built. It should not fail on reverts / operational errors (e.g. insufficient balance).
if !self.registered.get().unwrap_or(&false) { | ||
info!(target: "flashtestations", "tee service not registered yet, attempting to register"); | ||
builder_txs.extend(self.fund_tee_service_tx(ctx, &mut evm)?); | ||
let (register_tx, _) = self.register_tee_service_tx(ctx, &mut evm)?; |
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 fact that this can silently fail and self.set_registered(..)
is still called seems bad. also, set_registered() also calls
register_tee_service_tx` internally, are these duplicate calls?
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.
see #268 (comment)
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.
self.register_tee_service_tx
is only a simulation of the potential state that is going into the built block while self.set_registered is simulated against the committed state. We don't want to be stuck in a bad state where registered = true when self.register_tee_service_tx succeeds and the builder block doesn't end up being included, and it never attempts registration again
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'll move set_registered away from generating the transactions to avoid this confusion
sol!( | ||
#[sol(rpc, abi)] | ||
#[derive(Debug)] | ||
interface IFlashtestationRegistry { |
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.
please add link to specific commit
Co-authored-by: Solar Mithril <mikawamp@gmail.com>
Co-authored-by: noot <36753753+noot@users.noreply.github.com>
Co-authored-by: noot <36753753+noot@users.noreply.github.com>
6b72d3e
to
bf944d7
Compare
pub signed_tx: Recovered<OpTransactionSigned>, | ||
// whether the transaction should be a top of block or | ||
// bottom of block transaction | ||
pub is_top_of_block: bool, |
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 switch to bottom of every flashblock how difficult will it be to change this? Not sure if we want something like this configurable or not but it might be easier to start that way
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 construction of each transaction added to builder_tx just flip the boolean
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.
How do you flip it? Is it a code change? Then it needs to be built and released and it's a lot more difficult to 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.
oh you mean configuring via cli / env? I'm not sure this is something we want to change very often since changes to the builder tx position breaks external integrations / observability. Also the same builder tx have different positions in the block depending on whether the flashblock contract call is enabled or not etc. and the complexity would easily cause misconfiguration.
π Summary
--debug-url
with--quote_provider
argπ‘ Motivation and Context
β I have completed the following steps:
make lint
make test