Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
rebase main& resolve conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
DreamWuGit committed Sep 11, 2023
2 parents 9fa7d9e + 588b8b8 commit 1d267b6
Show file tree
Hide file tree
Showing 102 changed files with 17,714 additions and 490 deletions.
68 changes: 68 additions & 0 deletions .github/workflows/github-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
# Runs on pushes targeting the default branch
push:
branches: ['main']

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: 'pages'
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
- name: Setup Pages
uses: actions/configure-pages@v3
# Create a index.html outside of the subdirectories for requirement of GitHub pages
- name: Generate Docs
run: |
cargo doc --no-deps
echo "<meta http-equiv=\"refresh\" content=\"0; url=zkevm_circuits\">" > target/doc/index.html
# Archive the artifact with the correct permissions
# https://github.com/actions/deploy-pages/issues/188
- name: Archive artifact
shell: sh
run: |
chmod -c -R +rX "target/doc" |
while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
tar \
--dereference --hard-dereference \
--directory "target/doc" \
-cvf "$RUNNER_TEMP/artifact.tar" \
--exclude=.git \
--exclude=.github \
.
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: 'target/doc'

deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
60 changes: 38 additions & 22 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,8 +977,17 @@ impl<'a> CircuitInputStateRef<'a> {
if !self.call()?.is_root {
let (offset, length) = match step.op {
OpcodeId::RETURN | OpcodeId::REVERT => {
let offset = step.stack.nth_last(0)?.as_usize();
let length = step.stack.nth_last(1)?.as_usize();
let (offset, length) = if step.error.is_some()
|| (self.call()?.is_create() && self.call()?.is_success)
{
(0, 0)
} else {
(
step.stack.nth_last(0)?.as_usize(),
step.stack.nth_last(1)?.as_usize(),
)
};

// At the moment it conflicts with `call_ctx` and `caller_ctx`.
let callee_memory = self.call_ctx()?.memory.clone();
let caller_ctx = self.caller_ctx_mut()?;
Expand Down Expand Up @@ -1063,8 +1072,9 @@ impl<'a> CircuitInputStateRef<'a> {
let geth_step = steps
.get(0)
.ok_or(Error::InternalError("invalid index 0"))?;
let is_revert_or_return_call_success = geth_step.op == OpcodeId::REVERT
|| geth_step.op == OpcodeId::RETURN && exec_step.error.is_none();
let is_revert_or_return_call_success = (geth_step.op == OpcodeId::REVERT
|| geth_step.op == OpcodeId::RETURN)
&& exec_step.error.is_none();

if !is_revert_or_return_call_success && !call.is_success {
// add call failure ops for exception cases
Expand Down Expand Up @@ -1118,25 +1128,29 @@ impl<'a> CircuitInputStateRef<'a> {
_ => [Word::zero(), Word::zero()],
};

let curr_memory_word_size = (exec_step.memory_size as u64) / 32;
let next_memory_word_size = if !last_callee_return_data_length.is_zero() {
std::cmp::max(
(last_callee_return_data_offset + last_callee_return_data_length + 31).as_u64()
/ 32,
curr_memory_word_size,
)
let gas_refund = if exec_step.error.is_some() {
0
} else {
curr_memory_word_size
};
let curr_memory_word_size = (exec_step.memory_size as u64) / 32;
let next_memory_word_size = if !last_callee_return_data_length.is_zero() {
std::cmp::max(
(last_callee_return_data_offset + last_callee_return_data_length + 31).as_u64()
/ 32,
curr_memory_word_size,
)
} else {
curr_memory_word_size
};

let memory_expansion_gas_cost =
memory_expansion_gas_cost(curr_memory_word_size, next_memory_word_size);
let code_deposit_cost = if call.is_create() && call.is_success {
GasCost::CODE_DEPOSIT_BYTE_COST * last_callee_return_data_length.as_u64()
} else {
0
let memory_expansion_gas_cost =
memory_expansion_gas_cost(curr_memory_word_size, next_memory_word_size);
let code_deposit_cost = if call.is_create() && call.is_success {
GasCost::CODE_DEPOSIT_BYTE_COST * last_callee_return_data_length.as_u64()
} else {
0
};
geth_step.gas - memory_expansion_gas_cost - code_deposit_cost
};
let gas_refund = geth_step.gas - memory_expansion_gas_cost - code_deposit_cost;

let caller_gas_left = if is_revert_or_return_call_success || call.is_success {
geth_step_next.gas - gas_refund
Expand Down Expand Up @@ -1170,19 +1184,21 @@ impl<'a> CircuitInputStateRef<'a> {
}

// EIP-211: CREATE/CREATE2 call successful case should set RETURNDATASIZE = 0
let discard_return_data =
call.is_create() && geth_step.op == OpcodeId::RETURN || exec_step.error.is_some();
for (field, value) in [
(CallContextField::LastCalleeId, call.call_id.into()),
(
CallContextField::LastCalleeReturnDataOffset,
if call.is_create() && call.is_success {
if discard_return_data {
U256::zero()
} else {
last_callee_return_data_offset
},
),
(
CallContextField::LastCalleeReturnDataLength,
if call.is_create() && call.is_success {
if discard_return_data {
U256::zero()
} else {
last_callee_return_data_length
Expand Down
10 changes: 4 additions & 6 deletions bus-mapping/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ pub enum OogError {
SloadSstore,
/// Out of Gas for CALL, CALLCODE, DELEGATECALL and STATICCALL
Call,
/// Out of Gas for CREATE2
Create2,
/// Out of Gas for CREATE and CREATE2
Create,
/// Out of Gas for SELFDESTRUCT
SelfDestruct,
}
Expand All @@ -105,9 +105,7 @@ impl From<&OpcodeId> for OogError {
OpcodeId::MLOAD | OpcodeId::MSTORE | OpcodeId::MSTORE8 => {
OogError::StaticMemoryExpansion
}
OpcodeId::CREATE | OpcodeId::RETURN | OpcodeId::REVERT => {
OogError::DynamicMemoryExpansion
}
OpcodeId::RETURN | OpcodeId::REVERT => OogError::DynamicMemoryExpansion,
OpcodeId::CALLDATACOPY
| OpcodeId::CODECOPY
| OpcodeId::EXTCODECOPY
Expand All @@ -124,7 +122,7 @@ impl From<&OpcodeId> for OogError {
OogError::Call
}
OpcodeId::SLOAD | OpcodeId::SSTORE => OogError::SloadSstore,
OpcodeId::CREATE2 => OogError::Create2,
OpcodeId::CREATE | OpcodeId::CREATE2 => OogError::Create,
OpcodeId::SELFDESTRUCT => OogError::SelfDestruct,
_ => OogError::Constant,
}
Expand Down
21 changes: 18 additions & 3 deletions bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,13 @@ type FnGenAssociatedOps = fn(
) -> Result<Vec<ExecStep>, Error>;

fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
if opcode_id.is_push() {
if opcode_id.is_push_with_data() {
return StackOnlyOpcode::<0, 1>::gen_associated_ops;
}

match opcode_id {
OpcodeId::STOP => Stop::gen_associated_ops,
OpcodeId::PUSH0 => StackOnlyOpcode::<0, 1>::gen_associated_ops,
OpcodeId::ADD => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::MUL => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::SUB => StackOnlyOpcode::<2, 1>::gen_associated_ops,
Expand Down Expand Up @@ -269,15 +270,29 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
}
}

fn fn_gen_error_state_associated_ops(error: &ExecError) -> Option<FnGenAssociatedOps> {
fn fn_gen_error_state_associated_ops(
geth_step: &GethExecStep,
error: &ExecError,
) -> Option<FnGenAssociatedOps> {
match error {
ExecError::InvalidJump => Some(InvalidJump::gen_associated_ops),
ExecError::InvalidOpcode => Some(ErrorSimple::gen_associated_ops),
ExecError::OutOfGas(OogError::Call) => Some(OOGCall::gen_associated_ops),
ExecError::OutOfGas(OogError::Constant) => Some(ErrorSimple::gen_associated_ops),
ExecError::OutOfGas(OogError::Create) => match geth_step.op {
OpcodeId::CREATE => Some(StackOnlyOpcode::<3, 0, true>::gen_associated_ops),
OpcodeId::CREATE2 => Some(StackOnlyOpcode::<4, 0, true>::gen_associated_ops),
op => unreachable!("OOG Create cannot occur in {op}"),
},
ExecError::OutOfGas(OogError::Exp) => Some(OOGExp::gen_associated_ops),
ExecError::OutOfGas(OogError::Log) => Some(ErrorOOGLog::gen_associated_ops),
ExecError::OutOfGas(OogError::MemoryCopy) => Some(OOGMemoryCopy::gen_associated_ops),
ExecError::OutOfGas(OogError::DynamicMemoryExpansion) => {
Some(StackOnlyOpcode::<2, 0, true>::gen_associated_ops)
}
ExecError::OutOfGas(OogError::StaticMemoryExpansion) => {
Some(StackOnlyOpcode::<1, 0, true>::gen_associated_ops)
}
ExecError::OutOfGas(OogError::SloadSstore) => Some(OOGSloadSstore::gen_associated_ops),
ExecError::OutOfGas(OogError::AccountAccess) => {
Some(ErrorOOGAccountAccess::gen_associated_ops)
Expand Down Expand Up @@ -363,7 +378,7 @@ pub fn gen_associated_ops(
// TODO: after more error state handled, refactor all error handling in
// fn_gen_error_state_associated_ops method
// For exceptions that have been implemented
if let Some(fn_gen_error_ops) = fn_gen_error_state_associated_ops(&exec_error) {
if let Some(fn_gen_error_ops) = fn_gen_error_state_associated_ops(geth_step, &exec_error) {
return fn_gen_error_ops(state, geth_steps);
} else {
// For exceptions that fail to enter next call context, we need
Expand Down
24 changes: 22 additions & 2 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,29 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Error>
if !found {
return Err(Error::AccountNotFound(state.block.coinbase));
}
let coinbase_account = coinbase_account.clone();
let coinbase_balance_prev = coinbase_account.balance;
let coinbase_balance =
coinbase_balance_prev + effective_tip * (state.tx.gas() - exec_step.gas_left);
let coinbase_transfer_value = effective_tip * (state.tx.gas() - exec_step.gas_left);
let coinbase_balance = coinbase_balance_prev + coinbase_transfer_value;
state.account_read(
&mut exec_step,
state.block.coinbase,
AccountField::CodeHash,
if coinbase_account.is_empty() {
Word::zero()
} else {
coinbase_account.code_hash.to_word()
},
);
if coinbase_account.is_empty() {
state.account_write(
&mut exec_step,
state.block.coinbase,
AccountField::CodeHash,
CodeDB::empty_code_hash().to_word(),
Word::zero(),
)?;
}
state.account_write(
&mut exec_step,
state.block.coinbase,
Expand Down
27 changes: 16 additions & 11 deletions bus-mapping/src/evm/opcodes/callop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
)?;

let callee_code_hash = call.code_hash;
let callee_exists = !state.sdb.get_account(&callee_address).1.is_empty();
let callee = state.sdb.get_account(&callee_address).1.clone();
let callee_exists = !callee.is_empty();

let (callee_code_hash_word, is_empty_code_hash) = if callee_exists {
(
Expand Down Expand Up @@ -145,11 +146,13 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
debug_assert!(found);

let caller_balance = sender_account.balance;

let is_call_or_callcode = call.kind == CallKind::Call || call.kind == CallKind::CallCode;
let is_sufficient = caller_balance >= call.value;
let is_valid_depth = geth_step.depth < 1025;

// Precheck is OK when depth is in range and caller balance is sufficient
let is_precheck_ok =
geth_step.depth < 1025 && (!is_call_or_callcode || caller_balance >= call.value);
let is_precheck_ok = is_valid_depth && (is_sufficient || !is_call_or_callcode);

log::debug!(
"is_precheck_ok: {}, call type: {:?}, sender_account: {:?} ",
Expand All @@ -173,9 +176,11 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
let is_precompile = code_address
.map(|ref addr| is_precompiled(addr))
.unwrap_or(false);
// TODO: What about transfer for CALLCODE?
// Transfer value only for CALL opcode, is_precheck_ok = true.
if call.kind == CallKind::Call && is_precheck_ok {
// Transfer value only when all these conditions met:
// - The opcode is CALL
// - The precheck passed
// - The value to send is not zero
if call.kind == CallKind::Call && is_precheck_ok && !call.value.is_zero() {
state.transfer(
&mut exec_step,
call.caller_address,
Expand Down Expand Up @@ -221,9 +226,9 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {

// There are 4 branches from here.
// add failure case for insufficient balance or error depth in the future.
match (!is_precheck_ok, is_precompile, is_empty_code_hash) {
match (is_precheck_ok, is_precompile, is_empty_code_hash) {
// 1. Call to precompiled.
(false, true, _) => {
(true, true, _) => {
assert!(call.is_success, "call to precompile should not fail");
let caller_ctx = state.caller_ctx_mut()?;
let code_address = code_address.unwrap();
Expand Down Expand Up @@ -275,7 +280,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
Ok(vec![exec_step])
}
// 2. Call to account with empty code.
(false, _, true) => {
(true, _, true) => {
for (field, value) in [
(CallContextField::LastCalleeId, 0.into()),
(CallContextField::LastCalleeReturnDataOffset, 0.into()),
Expand All @@ -287,7 +292,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
Ok(vec![exec_step])
}
// 3. Call to account with non-empty code.
(false, _, false) => {
(true, _, false) => {
for (field, value) in [
(CallContextField::ProgramCounter, (geth_step.pc + 1).into()),
(
Expand Down Expand Up @@ -349,7 +354,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
}

// 4. insufficient balance or error depth cases.
(true, _, _) => {
(false, _, _) => {
for (field, value) in [
(CallContextField::LastCalleeId, 0.into()),
(CallContextField::LastCalleeReturnDataOffset, 0.into()),
Expand Down
1 change: 0 additions & 1 deletion bus-mapping/src/evm/opcodes/return_revert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use eth_types::{evm_types::INVALID_INIT_CODE_FIRST_BYTE, Bytecode, GethExecStep,
#[derive(Debug, Copy, Clone)]
pub(crate) struct ReturnRevert;

// TODO: rename to indicate this handles REVERT (and maybe STOP)?
impl Opcode for ReturnRevert {
fn gen_associated_ops(
state: &mut CircuitInputStateRef,
Expand Down
13 changes: 13 additions & 0 deletions bus-mapping/src/evm/opcodes/stackonlyop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,17 @@ mod stackonlyop_tests {
vec![StackOp::new(1, StackAddress(1023), *MOCK_BASEFEE)],
);
}

#[test]
fn push0_opcode_impl() {
stack_only_opcode_impl::<0, 1>(
OpcodeId::PUSH0,
bytecode! {
PUSH0
STOP
},
vec![],
vec![StackOp::new(1, StackAddress(1023), Word::zero())],
);
}
}
Loading

0 comments on commit 1d267b6

Please sign in to comment.