-
Notifications
You must be signed in to change notification settings - Fork 136
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(zk): zksolc linking #800
base: main
Are you sure you want to change the base?
Conversation
chore: identify action to deploy libs in EraVM
crates/forge/src/multi_runner.rs
Outdated
.find(|(id, _)| id.source == needle.source && id.name == needle.name) | ||
.map(|(_, evm)| (needle, zk, evm)) | ||
}) | ||
.filter(|(_, zk, evm)| zk.bytecode.is_some() && evm.bytecode.is_some()) |
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.
Shouldn't this be more of an assertion than a filter? Is it ok to keep on executing if we are missing some of the bytecodes?
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 would simply not be added to the dual_compiled_contracts
like it was before if it was unlinked (read as invalid bytecode)
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.
Ok, I am just worried we would filter something we should be aware it's missing (for example what happened when using zksolc previous to 1.5.7
and trying to just deserialize the eravm field to get the bytecode) and then this fails later when trying to get the bytecode and takes a bit to debug and track it is being filetred here. If this cannot happen then we are good.
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 are also some contracts which aren't meant to have bytecode like interfaces etc... Not sure the implications here tbh
fix(strategy): remove get_mut for `DualCompiledContracts`
fix(zk:link): use version from config refactor(zk:config): extract config -> zksolc compiler logic into function chore: lints
feat(script:zk): link with zksolc
test(zk:link): use 1.5.9 for deploy-time linking feat(zk:link): detect factory dependencies as link references for library lookup fix(zk:link): require 1.5.9 for deploy-time-linking
fix(link:zk): consistent artifact id prefixes chore: formatting refactor(link:zk): improve link targets filtering
fix(link:zk): don't preemptively strip file prefixes fix(link:zk): better factory dep detection chore: formatting
feat(strategy): return "broadcastable" tx feat(link:zk): populate newly linked factory deps feat(script): use `deploy_library`
fix(lib:zk): remove EVM lib deployments from broadcastable txs
refactor(artifact:zk): `all_factory_deps` method chore: formatting
feat(link:script): register target & deps
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.
Great job as always
@@ -68,9 +109,32 @@ pub trait ExecutorStrategyRunner: Debug + Send + Sync + ExecutorStrategyExt { | |||
amount: U256, | |||
) -> BackendResult<()>; | |||
|
|||
fn get_balance(&self, executor: &mut Executor, address: Address) -> BackendResult<U256>; |
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.
Where do we use this?
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.
during zksync library deployment, I made our strategy to snapshot the nonce&balance before the lib deployment, to then restore them for EraVM, so the "co-deployment" happens with the same input parameters
|
||
// manually increase nonce when performing CALLs | ||
executor | ||
.set_nonce(from, nonce + 1) |
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 keep in mind that when the nonce PR from @nbaztec is merged we have to change this don't we?
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 was migrated from upstream's code, but the meaning is that EVM won't increase the nonce for just calls (only create or full tx, but here it's not a full tx), so foundry increments the nonce manually to account for that, since here it's a call to the deployer
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.
Left comments to perhaps clarify some logic or choices
@@ -48,6 +61,34 @@ pub struct ExecutorStrategy { | |||
pub context: Box<dyn ExecutorStrategyContext>, | |||
} | |||
|
|||
pub struct LinkOutput { |
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 personally would like to move this stuff to a separate module, perhaps even a separate trait from the ExecutorStrategy
?
fn set_nonce(&self, executor: &mut Executor, address: Address, nonce: u64) | ||
-> BackendResult<()>; | ||
|
||
fn get_nonce(&self, executor: &mut Executor, address: Address) -> BackendResult<u64>; | ||
|
||
fn link( |
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 used in MultiContractRunnerBuilder::build
only, as scripts do not make use of a strategy
|
||
let linked_contracts = linker.get_linked_artifacts(&libraries)?; | ||
|
||
// Create a mapping of name => (abi, deployment code, Vec<library deployment code>) |
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.
migrated from existing code, but to me the comment looks outdated (no library deployment code)
crates/forge/bin/cmd/create.rs
Outdated
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.
other than clarifying a comment, optimizations
@@ -40,7 +40,7 @@ pub const ZKSOLC: &str = "zksolc"; | |||
/// ZKsync solc release used for all ZKsync solc versions | |||
pub const ZKSYNC_SOLC_RELEASE: Version = Version::new(1, 0, 1); | |||
/// Default zksolc version | |||
pub const ZKSOLC_VERSION: Version = Version::new(1, 5, 7); | |||
pub const ZKSOLC_VERSION: Version = Version::new(1, 5, 8); |
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, waiting for base to be >=1.5.9 as default
@@ -54,13 +54,15 @@ pub enum ZkSolcError { | |||
/// `sendtransfer` error: Using `send()` or `transfer()` methods on `address payable` instead | |||
/// of `call()`. | |||
SendTransfer, | |||
AssemblyCreate, |
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.
Added just to be able to use 1.5.9 in tests
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.
Won't be needed once #840 is merged with base
@@ -69,7 +73,7 @@ impl<'a> FindBytecodeResult<'a> { | |||
/// A collection of `[DualCompiledContract]`s | |||
#[derive(Debug, Default, Clone)] | |||
pub struct DualCompiledContracts { | |||
contracts: Vec<DualCompiledContract>, | |||
contracts: HashMap<ContractInfo, DualCompiledContract>, |
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 was done to make searching easier, mostly for linking where we don't have full bytecodes but mostly paths & names
I also don't think it hurts to convert this to a map, helps to avoid duplicates (which were possible before)
} | ||
|
||
/// Compute a CREATE2 address according to zksync | ||
pub fn compute_create2_address( |
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.
didn't find an equivalent for this unlinke create
@@ -51,7 +51,10 @@ where | |||
let caller = env.tx.caller; | |||
let nonce = ZKVMData::new(&mut ecx).get_tx_nonce(caller); | |||
let (transact_to, is_create) = match env.tx.transact_to { | |||
TransactTo::Call(to) => (to.to_h160(), false), | |||
TransactTo::Call(to) => { |
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.
had to change this one since transact may get deployments of the libs now, and we need to have the outcome parsed appropriately
technically speaking this is also helpful for broadcastable txs, as those could also contain deployments in this form
fix(test:zk): default to zksolc 1.5.9
fix(script): avoid unpacking create2 result fix(script): avoid marking create2 result address as persistent
What 💻
zksolc --link
CREATE
only)Why ✋
Notes 📝
There's a simple merge conflicts due to the lack of access to
DualCompiledContracts
during theMultiContractRunner
instantiation.This is a working yet incomplete implementation, as such there are a few quirks, in particular: unlinked factory deps are not supported (zksolc 1.5.9 should have some extra info that we can use), linking via
CREATE2
is not supported either yet.Currently there's an issue with trying to actually run the library, I believe due to a missing storage migration: