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

Commit

Permalink
Merge branch 'main' into auto-build
Browse files Browse the repository at this point in the history
  • Loading branch information
adria0 authored Sep 14, 2023
2 parents 32d1fe2 + 1bc1eef commit fd79747
Show file tree
Hide file tree
Showing 40 changed files with 685 additions and 883 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
with:
cancel_others: 'true'
concurrent_skipping: 'same_content_newer'
paths_ignore: '["**/README.md"]'
paths_ignore: '["**/README.md", "mpt-witness-generator/**"]'

lints:
needs: [skip_check]
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/mpt-witness-generator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: MPT Witness Generator Checks

on:
merge_group:
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
push:
branches:
- main

jobs:
skip_check:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
cancel_others: 'true'
concurrent_skipping: 'same_content_newer'
paths: '["mpt-witness-generator/**"]'


build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Format
uses: Jerome1337/[email protected]
with:
gofmt-path: './mpt-witness-generator'
gofmt-flags: '-l -d'

- name: Build
working-directory: ./mpt-witness-generator
run: go build -v ./...

- name: Test
working-directory: ./mpt-witness-generator
env:
NO_GETH: true
run: go test -v ./...
2 changes: 1 addition & 1 deletion bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ impl CircuitInputBuilder<DynamicCParams> {
.iter()
.fold(0, |acc, c| acc + c.bytes.len())
* 2
+ 2;
+ 4; // disabled and unused rows.

let total_rws_before_padding: usize =
<RWCounter as Into<usize>>::into(self.block_ctx.rwc) - 1; // -1 since rwc start from index `1`
Expand Down
37 changes: 37 additions & 0 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,43 @@ impl<'a> CircuitInputStateRef<'a> {
)
}

/// Transfer to an address irreversibly.
pub fn transfer_to_irreversible(
&mut self,
step: &mut ExecStep,
receiver: Address,
receiver_exists: bool,
must_create: bool,
value: Word,
) -> Result<(), Error> {
// If receiver doesn't exist, create it
if (!receiver_exists && !value.is_zero()) || must_create {
self.account_write(
step,
receiver,
AccountField::CodeHash,
CodeDB::empty_code_hash().to_word(),
Word::zero(),
)?;
}
if value.is_zero() {
// Skip transfer if value == 0
return Ok(());
}
let (_found, receiver_account) = self.sdb.get_account(&receiver);
let receiver_balance_prev = receiver_account.balance;
let receiver_balance = receiver_account.balance + value;
self.account_write(
step,
receiver,
AccountField::Balance,
receiver_balance,
receiver_balance_prev,
)?;

Ok(())
}

/// Fetch and return code for the given code hash from the code DB.
pub fn code(&self, code_hash: H256) -> Result<Vec<u8>, Error> {
self.code_db
Expand Down
2 changes: 1 addition & 1 deletion bus-mapping/src/circuit_input_builder/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ impl Transaction {
code_hash,
depth: 1,
value: eth_tx.value,
call_data_length: eth_tx.input.len().try_into().unwrap(),
call_data_length: 0,
..Default::default()
}
};
Expand Down
21 changes: 5 additions & 16 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,8 @@ 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_exist = !coinbase_account.is_empty();
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,
Expand All @@ -291,21 +289,12 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Error>
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(
state.transfer_to_irreversible(
&mut exec_step,
state.block.coinbase,
AccountField::Balance,
coinbase_balance,
coinbase_balance_prev,
coinbase_exist,
false,
coinbase_transfer_value,
)?;

// handle tx receipt tag
Expand Down
35 changes: 20 additions & 15 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,14 +176,17 @@ 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 {
// CALLCODE does not need to do real transfer
// 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,
call.address,
callee_exists || is_precompile,
callee_exists,
false,
call.value,
)?;
Expand Down Expand Up @@ -221,10 +227,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, _) => {
assert!(call.is_success, "call to precompile should not fail");
(true, true, _) => {
let caller_ctx = state.caller_ctx_mut()?;
let code_address = code_address.unwrap();
let (result, contract_gas_cost) = execute_precompiled(
Expand Down Expand Up @@ -275,9 +280,9 @@ 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::LastCalleeId, call.call_id.into()),
(CallContextField::LastCalleeReturnDataOffset, 0.into()),
(CallContextField::LastCalleeReturnDataLength, 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,9 +354,9 @@ 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::LastCalleeId, call.call_id.into()),
(CallContextField::LastCalleeReturnDataOffset, 0.into()),
(CallContextField::LastCalleeReturnDataLength, 0.into()),
] {
Expand Down
13 changes: 12 additions & 1 deletion bus-mapping/src/evm/opcodes/sload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ impl Opcode for Sload {

// First stack write
state.stack_write(&mut exec_step, stack_position, value)?;
state.push_op(
&mut exec_step,
RW::READ,
TxAccessListAccountStorageOp {
tx_id: state.tx_ctx.id(),
address: contract_addr,
key,
is_warm,
is_warm_prev: is_warm,
},
);
state.push_op_reversible(
&mut exec_step,
TxAccessListAccountStorageOp {
Expand Down Expand Up @@ -189,7 +200,7 @@ mod sload_tests {
);

let access_list_op = &builder.block.container.tx_access_list_account_storage
[step.bus_mapping_instance[7].as_usize()];
[step.bus_mapping_instance[8].as_usize()];
assert_eq!(
(access_list_op.rw(), access_list_op.op()),
(
Expand Down
17 changes: 14 additions & 3 deletions bus-mapping/src/evm/opcodes/sstore.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use super::Opcode;
use crate::{
circuit_input_builder::{CircuitInputStateRef, ExecStep},
operation::{CallContextField, StorageOp, TxAccessListAccountStorageOp, TxRefundOp},
operation::{CallContextField, StorageOp, TxAccessListAccountStorageOp, TxRefundOp, RW},
Error,
};

use eth_types::{GethExecStep, ToWord, Word};

/// Placeholder structure used to implement [`Opcode`] trait over it
Expand Down Expand Up @@ -86,6 +85,17 @@ impl Opcode for Sstore {
),
)?;

state.push_op(
&mut exec_step,
RW::READ,
TxAccessListAccountStorageOp {
tx_id: state.tx_ctx.id(),
address: contract_addr,
key,
is_warm,
is_warm_prev: is_warm,
},
);
state.push_op_reversible(
&mut exec_step,
TxAccessListAccountStorageOp {
Expand Down Expand Up @@ -250,7 +260,8 @@ mod sstore_tests {
)
)
);
let refund_op = &builder.block.container.tx_refund[step.bus_mapping_instance[9].as_usize()];
let refund_op =
&builder.block.container.tx_refund[step.bus_mapping_instance[10].as_usize()];
assert_eq!(
(refund_op.rw(), refund_op.op()),
(
Expand Down
9 changes: 9 additions & 0 deletions gadgets/src/binary_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ where
}
}

/// Return the constant that represents a given value. To be compared with the value expression.
pub fn constant_expr<F: Field>(&self, value: T) -> Expression<F> {
let f = value.as_bits().iter().fold(
F::ZERO,
|result, bit| if *bit { F::ONE } else { F::ZERO } + result * F::from(2),
);
Expression::Constant(f)
}

/// Returns a function that can evaluate to a binary expression, that
/// evaluates to 1 if value is equal to value as bits. The returned
/// expression is of degree N.
Expand Down
33 changes: 0 additions & 33 deletions mpt-witness-generator/.github/workflows/go.yml

This file was deleted.

6 changes: 2 additions & 4 deletions mpt-witness-generator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ module github.com/privacy-scaling-explorations/mpt-witness-generator
go 1.16

require (
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/ethereum/go-ethereum v1.10.8 // indirect
github.com/holiman/uint256 v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
github.com/ethereum/go-ethereum v1.10.8
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
)
Loading

0 comments on commit fd79747

Please sign in to comment.