Skip to content
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

Merged
merged 34 commits into from
Sep 15, 2023
Merged

feat: implement EIP-4844 #668

merged 34 commits into from
Sep 15, 2023

Conversation

DaniPopes
Copy link
Collaborator

Implements EIP-4844.

cc @rakita @Rjected

Closes #526.
Supersedes #536.

Copy link
Collaborator

@Rjected Rjected left a 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

Comment on lines 11 to 20
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();
}
Copy link
Collaborator

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

Comment on lines 76 to 85
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")
})
}
Copy link
Collaborator

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?

Copy link
Collaborator Author

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

@mattsse
Copy link
Collaborator

mattsse commented Aug 31, 2023

just flagging that it probably should be Arc because KzgSettings is not clone

ref

https://github.com/paradigmxyz/reth/blob/893f4cf2a27034f4550d3f4443a0fa7c2cd2444b/bin/reth/src/node/mod.rs#L575-L585

Comment on lines 196 to 198
static INSTANCE: OnceCell<Precompiles> = OnceCell::new();
INSTANCE.get_or_init(|| {
let mut precompiles = Self::berlin().clone();
Copy link
Collaborator

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

Copy link
Collaborator Author

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 :)

Copy link
Member

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?

Copy link
Collaborator

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?

Copy link
Collaborator

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

@DaniPopes
Copy link
Collaborator Author

DaniPopes commented Aug 31, 2023

@mattsse
What's clone needed for? AFAIK you just need to pass the instance pointer into C, so I'm thinking just OnceCell<KzgSettings>

@mattsse
Copy link
Collaborator

mattsse commented Aug 31, 2023

What's clone needed for?

we need the KzgSettings in multiple locations (for example tx pool validation) and ideally, we just want to load it once.

@mattsse
Copy link
Collaborator

mattsse commented Aug 31, 2023

hmm, the way precompiles are currently used

let mut precompiles = Self::berlin().clone();

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.
perhaps just a single static mut specifically for the kzg precompile?

or perhaps just use the kzg settings in a static mut

@DaniPopes
Copy link
Collaborator Author

DaniPopes commented Aug 31, 2023

we need the KzgSettings in multiple locations (for example tx pool validation) and ideally, we just want to load it once.

You can store a local &'static KzgSettings or get it when needed with a global getter function. I don't think Arcs are needed here.

See #668 (comment) for static muts.

@mattsse
Copy link
Collaborator

mattsse commented Aug 31, 2023

okay @Rjected I figured out how the hardfork precompiles are currently instantiated, and since we only need to access the KzgSettings once, a static Lazy<Mutex<Arc<KzgSettings>> should be enough to support custom KzgSettings if set at the start of the program

@@ -0,0 +1,33 @@
use c_kzg::KzgSettings;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module is exported, lmk wyt @Rjected @mattsse

Copy link
Member

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

Copy link
Collaborator Author

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.

Copy link
Member

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.

@rakita rakita mentioned this pull request Aug 31, 2023
crates/precompile/build.rs Outdated Show resolved Hide resolved
Comment on lines 47 to 64
// 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);
}
Copy link
Collaborator

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?

Copy link
Collaborator Author

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.

Comment on lines 100 to 109
/*
/// 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 {
Copy link
Collaborator

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.

Copy link
Collaborator Author

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/blob/mod.rs Outdated Show resolved Hide resolved
Comment on lines 196 to 198
static INSTANCE: OnceCell<Precompiles> = OnceCell::new();
INSTANCE.get_or_init(|| {
let mut precompiles = Self::berlin().clone();
Copy link
Collaborator

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?

@rakita rakita merged commit fa13fea into bluealloy:main Sep 15, 2023
tonyke-bot pushed a commit to fuzzland/revm that referenced this pull request Sep 19, 2023
* 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>
@DaniPopes DaniPopes deleted the eip-4844 branch September 28, 2023 15:43
@github-actions github-actions bot mentioned this pull request Jan 12, 2024
This was referenced Sep 9, 2024
@github-actions github-actions bot mentioned this pull request Nov 20, 2024
This was referenced Dec 6, 2024
This was referenced Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hf-cancun Cancun hardfork
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EIP-4844: Shard Blob Transactions
6 participants