-
Notifications
You must be signed in to change notification settings - Fork 552
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: implement EIP-4844 #668
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.
just adding some comments on how we might be able to configure the trusted setup from reth
crates/precompile/build.rs
Outdated
fn generate_kzg_settings() { | ||
let in_path = "src/kzg/trusted_setup.txt"; | ||
let out_path = "src/kzg/generated_settings.rs"; | ||
|
||
let in_path = Path::new(in_path); | ||
println!("cargo:rerun-if-changed={}", in_path.display()); | ||
assert!(in_path.exists()); | ||
let contents = format_kzg_settings(in_path); | ||
fs::write(out_path, contents).unwrap(); | ||
} |
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.
makes sense - generating consts here makes creating the default kzgsettings easy, and does not require reading the file on startup etc
crates/precompile/src/kzg/mod.rs
Outdated
fn get_kzg_settings() -> &'static KzgSettings { | ||
static SETTINGS: OnceCell<KzgSettings> = OnceCell::new(); | ||
SETTINGS.get_or_init(|| { | ||
c_kzg::KzgSettings::load_trusted_setup( | ||
generated_settings::G1_POINTS, | ||
generated_settings::G2_POINTS, | ||
) | ||
.expect("failed to load trusted setup") | ||
}) | ||
} |
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 makes sense given how the precompiles have to access the kzgsettings, but we need to be able to configure this from reth as well somehow.
Maybe we could have a static mut
and use a pattern similar to this:
https://github.com/tokio-rs/tracing/blob/bf05c61b7234eb1a196ef8d30f773d3ea6b60ce9/tracing-core/src/dispatch.rs#L329-L366
To provide a way to set the KzgSettings
in reth?
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 believe they use static mut
and manual atomic operations because of MSRV restrictions, once_cell
is probably better
just flagging that it probably should be Arc because KzgSettings is not clone ref |
crates/precompile/src/lib.rs
Outdated
static INSTANCE: OnceCell<Precompiles> = OnceCell::new(); | ||
INSTANCE.get_or_init(|| { | ||
let mut precompiles = Self::berlin().clone(); |
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.
for precompiles, we should consider either an enum
enum Precompile {
Fun(fn(&[u8], u64) -> PrecompileResult),
Fn(Arc<dyn Send + Sync + Fn(&[u8], u64) -> PrecompileResult)
}
or always use the Arc variant,
and a static mut Precompile list that supports configuring global defaults
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 is in my TODO list :)
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.
hm we can simplify a lot of things about initialization by adding function signature that has CfgEnv
input
No global initialization at all, and we set KzgSettings
inside CfgEnv
.
@DaniPopes @mattsse @Rjected wdyt?
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.
No global initialization at all, and we set KzgSettings inside CfgEnv.
I am open to that, as long as we can set a default that's hard-coded to Cancun/Sepolia/.. mainnet?
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.
No global initialization at all, and we set KzgSettings inside CfgEnv.
I am open to that, as long as we can set a default that's hard-coded to Cancun/Sepolia/.. mainnet?
yeah this seems much nicer than messing around with globals
@mattsse |
we need the KzgSettings in multiple locations (for example tx pool validation) and ideally, we just want to load it once. |
hmm, the way precompiles are currently used
it's only really useful to allow custom default precompiles starting with cancun hardfork, pre-cancun this doesn't really make sense. so actually not sure yet what the ideal static mut should look like. or perhaps just use the kzg settings in a static mut |
You can store a local See #668 (comment) for |
okay @Rjected I figured out how the hardfork precompiles are currently instantiated, and since we only need to access the KzgSettings once, a |
@@ -0,0 +1,33 @@ | |||
use c_kzg::KzgSettings; |
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.
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 tend not to usemod
inside revm
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 it makes sense here for now, kzg_settings::set_global
like tracing::subscriber::set_global_default
. It's equivalent of a ZST struct with the module functions as static methods on it. In the future we can think of a better solution.
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 EnvCfg
path of setting kzg setting, this is unnecessary.
crates/precompile/build.rs
Outdated
// TODO: We can use `hex_literal` to reduce file size | ||
// load g1 points | ||
let mut g1_points = Vec::with_capacity(n_g1); | ||
for _ in 0..n_g1 { | ||
let line = lines.next().unwrap(); | ||
let mut bytes = [0; BYTES_PER_G1_POINT]; | ||
hex::decode_to_slice(line, &mut bytes).unwrap(); | ||
g1_points.push(bytes); | ||
} | ||
|
||
// load g2 points | ||
let mut g2_points = Vec::with_capacity(n_g2); | ||
for _ in 0..n_g2 { | ||
let line = lines.next().unwrap(); | ||
let mut bytes = [0; BYTES_PER_G2_POINT]; | ||
hex::decode_to_slice(line, &mut bytes).unwrap(); | ||
g2_points.push(bytes); | ||
} |
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.
Nit but as discussed you don't need to read all the points 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.
It's done at compile-time. There's only 2 methods exposed to init a KzgSettings
, with the points bytes, or with a file path.
crates/precompile/build.rs
Outdated
/* | ||
/// Pros: | ||
/// - no need to call `load_trusted_setup` at runtime | ||
/// | ||
/// Cons: | ||
/// - larger runtime static size (722K = `4096*32 + 4096*144 + 65*288`) | ||
/// - larger generated file size (2M) | ||
/// - possibly unsafe? `as_ptr() as *mut _` | ||
/// - depends on `c_kzg`; this might not matter much | ||
fn format_kzg_settings_large(in_path: &Path) -> String { |
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.
We should check about this w/ the c-kzg folks.
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 I'll delete the second option, it's way too big to have at runtime
crates/precompile/src/lib.rs
Outdated
static INSTANCE: OnceCell<Precompiles> = OnceCell::new(); | ||
INSTANCE.get_or_init(|| { | ||
let mut precompiles = Self::berlin().clone(); |
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.
No global initialization at all, and we set KzgSettings inside CfgEnv.
I am open to that, as long as we can set a default that's hard-coded to Cancun/Sepolia/.. mainnet?
this would require non-optional KzgSettings config, which would also make the static default for the cancun precompile redundant, I'd prefer this. Similar to how the default chain id is set to mainnet.
ah yes, as @Rjected already mentioned sorry, for derailing this, I overlooked some of @rakita previous comments here. To which I agree, having reread them. So we can get rid of the get_global_or_default etc., by adding having non configurable default for the settings is fine I think, even if it requires more work in reth. the issue with the precompiles remains, either we support |
Unresolved things:
|
Added @DaniPopes @mattsse can you take a look at the changes |
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 doc nits
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.
small qs/nits, overall looks good to me i think
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
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.
lgtm
/// The input is encoded as follows: | ||
/// | versioned_hash | z | y | commitment | proof | | ||
/// | 32 | 32 | 32 | 48 | 48 | |
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.
nice!
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.
lgtm
Just to mention here, we have disabled some of Those tests are:
Will treat this as tests not being aligned on what evm should do, and will check later. Additionally asked on Eth R&D discord here: https://discord.com/channels/595666850260713488/753271902520213625/1152206478816583770 |
* feat: point evaluation precompile * feat: BLOBHASH opcode * refactor: revme runner * renames * export global kzg settings * feat: include kzg settings bytes with `include_bytes!` * build.rs: remove second option, update docs * revme: remove unused files and dead code * feat: implement remaining block and tx env fields * Add tests for helper functions, update constants * Add EIP-4844 EF tests to CI, skip outdated ones * chore: make skip_test more readable * Fix tests * Fix fmt * Fix lints, review * fix: validate new tx, block fields; add to balance check * Restore `load_access_list` * chore: drop c-kzg fork * test: update tests from Geth See: <ethereum/go-ethereum#28026> * chore: revert `is_create` change * chore: fmt toml * chore: unnecessary import * remove unsafe from fake_exponential * Remove kzg global settings, and move it to CfgEnv * enable kzg only in std. main README updated * fmt and clippy * Update README.md Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> * nits and docs * disable exception eip4844 tests, small refactor * revert back last commit refactor --------- Co-authored-by: rakita <dragan0rakita@gmail.com> Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> Co-authored-by: Waylon Jepsen <57912727+0xJepsen@users.noreply.github.com>
Implements EIP-4844.
cc @rakita @Rjected
Closes #526.
Supersedes #536.