-
Notifications
You must be signed in to change notification settings - Fork 3
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
Scroll Primitives #7
Comments
Edited to add "Type 1" to the supported transaction types. |
Relevant reth tracking issue: paradigmxyz#11239 |
OverviewThe account structure used in Scroll contains two extra fields: Propositions
Details
|
Below I will specify the changes that could be implemented in Reth Account AbstractionFirst we will introduce an pub trait AccountT {
const fn has_bytecode(&self) -> bool;
fn is_empty(&self) -> bool;
fn get_bytecode_hash(&self) -> B256;
fn get_nonce(&self) -> u64;
fn get_balance(&self) -> U256;
}
pub struct ScrollAccount {
nonce: u64,
balance: U256,
bytecode_hash: Option<B256>,
poseidon_bytecode_hash: Option<B256>,
code_size: Option<usize>,
}
impl AccountT for ScrollAccount {
const fn has_bytecode(&self) -> bool {
self.bytecode_hash.is_some()
}
fn is_empty(&self) -> bool {
self.nonce == 0 &&
self.balance.is_zero() &&
self.bytecode_hash.map_or(true, |hash| hash == KECCAK_EMPTY)
}
fn get_bytecode_hash(&self) -> B256 {
self.bytecode_hash.unwrap_or(KECCAK_EMPTY)
}
fn get_nonce(&self) -> u64 {
self.nonce
}
fn get_balance(&self) -> U256 {
self.balance
}
} We would then provide the concrete pub trait NodePrimitives {
type Account: AccountT;
}
impl NodePrimitives for ScrollPrimitives {
type Account = ScrollAccount;
} Revm
|
I agree with the second solution. Just two nits:
/// Creates a new executor for single block execution.
///
/// This is used to execute a single block and get the changed state.
fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>; and similar bound is required for execution during pipelining.
pub struct ScrollBundleState {
context: HashMap<B256, (usize, B256)>,
bundle: BundleState
} which we can re-export via the // Convenience re-exports.
pub use revm::{self, *};
#[cfg(feature = "scroll")]
pub use revm_scroll::ScrollBundleState as BundleState |
Agreed, the
Looks reasonable to me. The only question I have is do we want to unpack fields from I would propose that we open an issue in upstream |
After some research on the areas of the codebase affected by the above changes, I came across the below related to persistence:
The below details a proposed approach to abstract the Add a pub trait NodePrimitives {
/// Block primitive.
type Block;
/// Node execution primitives
type ExecutionPrimitives: NodeExecutionPrimitives;
} We then bound the pub trait NodeExecutionPrimitives {
/// Additional context extracted during execution
type Context;
/// Bundle state of values changed during execution
type BundleState: From<(revm::db::BundleState, NodeExecutionPrimitives::Context)> + BundleStateT;
}
pub trait BundleStateT {
type Reverts;
type StateChangeset;
...
} As an example, for Scroll, we would implement the following: type KeccakHash = B256;
type PoseidonHash = B256;
type CodeSize = usize;
type ScrollExecutionContext = HashMap<KeccakHash, (CodeSize, PoseidonHash)>;
pub struct ScrollBundleState {
...,
}
impl From<(revm::db::BundleState, ScrollExecutionContext)> for ScrollBundleState {
fn from(value: (BundleState, ScrollExecutionContext)) -> Self {
/// Construct `ScrollBundleState` fields from the bundle and the additional context
Self {
...,
}
}
}
pub struct ScrollExecutionPrimitives;
impl NodeExecutionPrimitives for ScrollExecutionPrimitives {
type Context = ScrollExecutionContext;
type BundleState = ScrollBundleState;
} Using the We will start implementing the above when time allows it and pushing it to upstream, but in the meantime will progress by defining our own |
This looks good to me, just a few points. Do we need to introduce For the |
I see, I think that would probably work and avoid the
Yes this was a mistake in the definition indeed. |
After some discussion, the following route has been chosen: Take advantage of the pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
type ExecutorOutput;
type BatchExecutorOutput;
type Executor<DB: Database<Error: Into<ProviderError> + Display>>: for<'a> Executor<
DB,
Input<'a> = BlockExecutionInput<'a, BlockWithSenders>,
Output = Self::ExecutorOutput,
Error = BlockExecutionError,
>;
type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>>: for<'a> BatchExecutor<
DB,
Input<'a> = BlockExecutionInput<'a, BlockWithSenders>,
Output = BatchExecutorOutput,
Error = BlockExecutionError,
>;
... This removes the need for the We will need to bound the |
Overview
Scroll introduces / modifies the transaction and transaction receipt primitives. We should implement these primitives in reth or a new primitives crate.
Transaction types
Scroll supports the following transaction types:
L1 Message Transaction (typed transaction)
L1 initiated transactions use the following transaction type associated with an EIP-2718 type of
0x7E
. There are no fees payed for this transaction type on L2 as the fees are already payed for when the transaction is submitted on L1. The encoding follows the standard EIP-2718 encodingReceipt
An additional field is added to the
TransactionReceipt
. This field includes the l1 fee. See reference here.Account
The account field has two additional fields
code_size
andposeiden_code_hash
. Also the account hashing scheme is different. In the first instance I propose we add these additional fields behind a feature flag but in the future we should provide an abstraction such as providing theAccount
object inNodePrimites
.Design
Currently the
Transaction
type (and associated types, e.g.TxType
,PooledTransactionsElement
) andReceipt
are hardcoded. Modifications to these types are currently achieved via feature flags as seen by theoptimism
feature flag. In the first instance we should implement the scroll changes behind a feature flag but we should consult with thereth
team to see if we can provide the necessary abstractions to allow for configurability of these types.The text was updated successfully, but these errors were encountered: