Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
lispc committed Apr 23, 2024
1 parent 9b9ab8d commit 322c742
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 120 deletions.
2 changes: 0 additions & 2 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ pub use transaction::{
Transaction, TransactionContext, TxL1Fee, TX_L1_COMMIT_EXTRA_COST, TX_L1_FEE_PRECISION,
};


/// Setup parameters for ECC-related precompile calls.
#[derive(Debug, Clone, Copy)]
pub struct PrecompileEcParams {
Expand Down Expand Up @@ -620,7 +619,6 @@ impl<'a> CircuitInputBuilder {
state_ref.call_ctx()?.memory.len(),
geth_step.refund.0,
{
//#[cfg(feature = "enable-stack")]
let stack = &state_ref.call_ctx()?.stack;
if geth_step.op.is_push_with_data() {
#[cfg(feature = "enable-stack")]
Expand Down
1 change: 0 additions & 1 deletion external-tracer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ pub fn trace(config: &TraceConfig) -> Result<Vec<GethExecTrace>, Error> {
serde::Deserialize::deserialize(deserializer).map_err(Error::SerdeError)
}


/// Creates a l2-trace for the specified config
#[cfg(feature = "scroll")]
pub fn l2trace(config: &TraceConfig) -> Result<BlockTrace, Error> {
Expand Down
2 changes: 1 addition & 1 deletion testool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ urlencoding = "2.1.2"
ctor.workspace = true

[features]
default = ["skip-self-destruct", "shanghai", "bus-mapping/strict-ccc", "enable-stack"]
default = ["ignore-test-docker", "skip-self-destruct", "shanghai", "bus-mapping/strict-ccc"]
onephase = ["zkevm-circuits/onephase"]
ignore-test-docker = []
skip-self-destruct = []
Expand Down
24 changes: 8 additions & 16 deletions testool/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ use eth_types::{Bytes, U256};
/// encodes an abi call (e.g. "f(uint) 1")
pub fn encode_funccall(spec: &str) -> Result<Bytes> {
use ethers_core::abi::{Function, Param, ParamType, StateMutability, Token};
//log::error!("spec {spec}");

// split parts into `func_name` ([`func_params`]) `args`

let tokens: Vec<_> = spec.split(' ').collect();
let func = tokens[0];
let args = &tokens[1..];

let func_name_params: Vec<_> = func.split([',', '(', ')']).filter(|s| !s.is_empty()).collect();
let func_name_params: Vec<_> = func
.split([',', '(', ')'])
.filter(|s| !s.is_empty())
.collect();
let func_name = func_name_params[0];
let func_params = if func_name_params.len() == 1 {
vec![]
} else {
func_name_params[1..func_name_params.len()].to_vec()
};
//log::error!("func_name_params {func_name_params:?}");
// transform func_params and args into the appropiate types

let map_type = |t| match t {
Expand All @@ -28,17 +30,11 @@ pub fn encode_funccall(spec: &str) -> Result<Bytes> {
_ => panic!("unimplemented abi type {t:?}"),
};

let encode_type = |t, v: &str| {
//log::error!("encode_type {t:?} {v:?}");
match t {

let encode_type = |t, v: &str| match t {
ParamType::Uint(256) => {
if let Some(hex) = v.strip_prefix("0x") {
//log::error!("from_str_radix hex");
let split_idx = if hex.len() > 64 { hex.len() - 64 } else { 0 };
let r = U256::from_str_radix(&hex[split_idx..], 16);
//log::error!("r {r:?}");
r.map(Token::Uint)
U256::from_str_radix(&hex[split_idx..], 16).map(Token::Uint)
} else {
U256::from_str_radix(v, 10).map(Token::Uint)
}
Expand All @@ -49,10 +45,8 @@ pub fn encode_funccall(spec: &str) -> Result<Bytes> {
_ => panic!("unexpected boolean '{v}'"),
},
_ => unimplemented!(),
}
};
};

//log::error!("func_params {func_params:?}");
let func_params: Vec<_> = func_params
.iter()
.enumerate()
Expand All @@ -69,7 +63,6 @@ pub fn encode_funccall(spec: &str) -> Result<Bytes> {
.map(|(typ, val)| encode_type(typ.kind.clone(), val))
.collect::<std::result::Result<_, _>>()?;

//log::error!("args {args:?}");
// generate and return calldata

#[allow(deprecated)]
Expand All @@ -80,7 +73,6 @@ pub fn encode_funccall(spec: &str) -> Result<Bytes> {
state_mutability: StateMutability::Payable,
constant: Some(false),
};
//log::error!("func {:?}", func);

Ok(Bytes::from(func.encode_input(&args)?))
}
Expand Down
86 changes: 47 additions & 39 deletions testool/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,48 +267,50 @@ impl Compiler {
Ok(bytecode)
}

/// compiles YUL code
/// compiles YUL code. Sometimes this method cannot emit bytecode successfully.
/// For example, for selfdestruct, it can only output warning without bytecode.
#[deprecated]
#[allow(dead_code)]
pub fn yul2(&self, src: &str, evm_version: Option<&str>) -> Result<Bytes> {
log::error!("yul {evm_version:?}");
self.solc(Language::Yul, src, evm_version)
}

/// ..
/// compiles YUL code, this is the exact script used in retesteth
pub fn yul(&self, src: &str, evm_version: Option<&str>) -> Result<Bytes> {

if let Some(bytecode) = self
.cache
.as_ref()
.and_then(|c| c.lock().unwrap().get(src).cloned())
{
return Ok(bytecode);
}
if !self.compile {
bail!("No way to compile Yul for '{}'", src)
}
let stdout = match evm_version {
Some(evm_version) => Self::exec(
&["run", "-i", "--rm", "solc",
"--evm-version", evm_version,
"--strict-assembly",
"--optimize", "--yul-optimizations=:",
"-"],
src,
)?,
None => Self::exec(
&["run", "-i", "--rm", "solc", "--strict-assembly",
"--optimize", "--yul-optimizations=:",
"-"],
src,
)?};
let placeholder = "Binary representation:\n";
let from_pos = stdout.find(placeholder);
let len = from_pos.and_then(|pos| stdout[pos + placeholder.len()..].find('\n'));
.cache
.as_ref()
.and_then(|c| c.lock().unwrap().get(src).cloned())
{
return Ok(bytecode);
}

if !self.compile {
bail!("No way to compile Yul for '{}'", src)
}
let mut cmd = vec![
"run",
"-i",
"--rm",
"solc",
"--strict-assembly",
"--optimize",
"--yul-optimizations=:",
];
if let Some(evm_version) = evm_version {
cmd.push("--evm-version");
cmd.push(evm_version);
}
cmd.push("-");

let stdout = Self::exec(&cmd, src)?;
let placeholder = "Binary representation:\n";
let from_pos = stdout.find(placeholder);
let len = from_pos.and_then(|pos| stdout[pos + placeholder.len()..].find('\n'));
let bytecode = if let (Some(from_pos), Some(len)) = (from_pos, len) {
let hex = &stdout[from_pos + placeholder.len()..from_pos + placeholder.len() + len];
Bytes::from(hex::decode(&hex)?)
Bytes::from(hex::decode(hex)?)
} else {
bail!("Unable to compile: {}", src);
};
Expand Down Expand Up @@ -336,15 +338,16 @@ impl Compiler {
bail!("No way to compile {:?} for '{}'", language, src)
}
let compiler_input = CompilerInput::new_default(language, src, evm_version);
let compiler_input = serde_json::to_string(&compiler_input).unwrap();
let stdin = serde_json::to_string(&compiler_input).unwrap();
let stdout = Self::exec(
&["run", "-i", "--rm", "solc", "--standard-json", "-"],
compiler_input.as_str(),
stdin.as_str(),
)?;
log::error!("stdout {stdout}");
let mut compilation_result: CompilationResult = serde_json::from_str(&stdout)
.map_err(|e| {
println!("---\n{language:?}\n{src}\n{evm_version:?}\n{e:?}\n{compiler_input}\n{stdout}\n-----")
println!(
"---\n{language:?}\n{src}\n{evm_version:?}\n{e:?}\n{stdin}\n{stdout}\n-----"
)
})
.unwrap();
let bytecode = compilation_result
Expand Down Expand Up @@ -386,7 +389,7 @@ mod test {
#[test]
#[cfg(not(feature = "ignore-test-docker"))]
fn test_docker_yul() -> anyhow::Result<()> {
let out = super::Compiler::new(true, None)?.yul2(
let out = super::Compiler::new(true, None)?.yul(
r#"
{
function power(base, exponent) -> result
Expand All @@ -398,8 +401,12 @@ mod test {
}
}
}
"#, None
"#,
None,
)?;
// This test will fail, since recent solc will completely ignore the used `power` function
// and emit `STOP`
// FIXME
assert_eq!(
hex::encode(out),
"6020565b8381101560195782820291506001810190506003565b5092915050565b"
Expand All @@ -410,6 +417,7 @@ mod test {
#[cfg(not(feature = "ignore-test-docker"))]
fn test_docker_solidity() -> anyhow::Result<()> {
let out = super::Compiler::new(true, None)?.solidity("contract A{}", None)?;
// Recent solc emit different codes. FIXME
assert_eq!(
hex::encode(out),
"6080604052348015600f57600080fd5b50603c80601d6000396000f3fe6080604052600080fdfea164736f6c637828302e382e31332d646576656c6f702e323032322e352e31312b636f6d6d69742e61626161356330650030"
Expand Down
4 changes: 1 addition & 3 deletions testool/src/statetest/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ fn into_traceconfig(st: StateTest) -> (String, TraceConfig, StateTestResult) {
let v = st.normalize_sig_v(sig.v);
let rlp_signed = tx.rlp_signed(&sig).to_vec();
let tx_hash = keccak256(tx.rlp_signed(&sig));
let accounts: std::collections::BTreeMap<eth_types::H160, geth_types::Account> = st.pre.into_iter().filter(|(k, v)| {
!v.balance.is_zero() || !v.nonce.is_zero() || !v.code.is_empty()
}).collect();
let accounts = st.pre;

(
st.id,
Expand Down
17 changes: 11 additions & 6 deletions testool/src/statetest/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,13 @@ impl<'a> JsonStateTestBuilder<'a> {
let max_priority_fee_per_gas = test
.transaction
.max_priority_fee_per_gas
.map_or(Ok(None), |s| parse::parse_u256(&s).map(Some)).unwrap();
.map_or(Ok(None), |s| parse::parse_u256(&s).map(Some))
.unwrap();
let max_fee_per_gas = test
.transaction
.max_fee_per_gas
.map_or(Ok(None), |s| parse::parse_u256(&s).map(Some)).unwrap();
.map_or(Ok(None), |s| parse::parse_u256(&s).map(Some))
.unwrap();

// Set gas price to `min(max_priority_fee_per_gas + base_fee, max_fee_per_gas)` for
// EIP-1559 transaction.
Expand All @@ -158,21 +160,24 @@ impl<'a> JsonStateTestBuilder<'a> {
.data
.iter()
.map(|item| parse::parse_calldata(self.compiler, item, access_list))
.collect::<Result<_>>().unwrap();
.collect::<Result<_>>()
.unwrap();

let gas_limit_s: Vec<_> = test
.transaction
.gas_limit
.iter()
.map(|item| parse::parse_u64(item))
.collect::<Result<_>>().unwrap();
.collect::<Result<_>>()
.unwrap();

let value_s: Vec<_> = test
.transaction
.value
.iter()
.map(|item| parse::parse_u256(item))
.collect::<Result<_>>().unwrap();
.collect::<Result<_>>()
.unwrap();

let mut expects = Vec::new();
for expect in test.expect {
Expand Down Expand Up @@ -327,7 +332,7 @@ impl<'a> JsonStateTestBuilder<'a> {
fn parse_refs(value: &serde_json::Value) -> Result<Refs> {
let mut refs = Vec::new();
if value.is_null() {
return Ok(Refs(vec![Ref::Any]))
return Ok(Refs(vec![Ref::Any]));
}
if let Some(index) = value.as_i64() {
if index == -1 {
Expand Down
31 changes: 12 additions & 19 deletions testool/src/statetest/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ impl Calldata {
}
}

static YUL_FRAGMENT_PARSER: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r#"\s*(?P<version>\w+)?\s*(?P<version2>\w+)*\s*(?P<code>\{[\S\s]*)"#).unwrap());
static YUL_FRAGMENT_PARSER: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#"\s*(?P<version>\w+)?\s*(?P<version2>\w+)*\s*(?P<code>\{[\S\s]*)"#).unwrap()
});

/// returns the element as an address
pub fn parse_address(as_str: &str) -> Result<Address> {
Expand All @@ -62,9 +63,7 @@ pub fn parse_to_address(as_str: &str) -> Result<Option<Address>> {
if as_str.trim().is_empty() {
return Ok(None);
}
let x = parse_address(as_str).map(|x| Ok(Some(x)))?;
//log::error!("parse_to_address {as_str} {x:?}");
x
parse_address(as_str).map(|x| Ok(Some(x)))?
}

/// returns the element as an array of bytes
Expand Down Expand Up @@ -142,26 +141,20 @@ pub fn parse_code(compiler: &Compiler, as_str: &str) -> Result<Bytes> {
bail!("do not know what to do with code(3) '{:?}'", as_str);
}
} else if let Some(yul) = tags.get(":yul") {
let (src, evm_version) = if yul.starts_with("{") {
let (src, evm_version) = if yul.starts_with('{') {
(yul.to_string(), None)
} else {
let re = Regex::new(r"\s").unwrap();
let mut parts = re.splitn(&yul, 2);
let mut parts = re.splitn(yul, 2);

let version = parts.next().unwrap();
let src = parts.next().unwrap();
let version = parts.next().unwrap();
let src = parts.next().unwrap();

//let (version, src) = yul.split_once(" ").unwrap();
// TODO: what is this "optimise" mean?
let src = src.strip_prefix("optimise").unwrap_or(src).to_string();
(src, Some(version.to_string()))
};
//let caps = YUL_FRAGMENT_PARSER
// .captures(yul)
// .ok_or_else(|| anyhow::anyhow!("do not know what to do with code(4) '{:?}'", as_str))?;
compiler.yul(
&src, //caps.name("code").unwrap().as_str(),
evm_version.as_ref().map(|s| &**s), //caps.name("version").map(|m| m.as_str()),
)?
compiler.yul(&src, evm_version.as_deref())?
} else if let Some(solidity) = tags.get(":solidity") {
debug!(target: "testool", "SOLIDITY: >>>{}<<< => {:?}", solidity, as_str);
compiler.solidity(solidity, None)?
Expand All @@ -178,7 +171,7 @@ pub fn parse_code(compiler: &Compiler, as_str: &str) -> Result<Bytes> {
pub fn parse_hash(value: &str) -> Result<H256> {
let hex = value.strip_prefix("0x").unwrap_or(value);
if hex.is_empty() {
return Ok(H256::zero())
return Ok(H256::zero());
}
Ok(H256::from_slice(&hex::decode(hex).context("parse_hash")?))
}
Expand Down Expand Up @@ -222,7 +215,7 @@ fn parse_call_bytes(compiler: &Compiler, tags: HashMap<String, String>) -> Resul
}
} else if let Some(raw) = tags.get(":raw") {
if let Some(hex) = raw.strip_prefix("0x") {
Ok(Bytes::from(hex::decode(hex.replace(" ", "")).unwrap()))
Ok(Bytes::from(hex::decode(hex.replace(' ', "")).unwrap()))
} else {
bail!("bad encoded calldata (3) {:?}", tags)
}
Expand Down
Loading

0 comments on commit 322c742

Please sign in to comment.