mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-05-09 11:47:59 +00:00
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Baseline": 3917,
|
||||
"Computation": 7363,
|
||||
"ERC20": 52714,
|
||||
"ERC20": 50944,
|
||||
"Fibonacci": 5965,
|
||||
"Flipper": 4336
|
||||
}
|
||||
@@ -64,9 +64,11 @@ pub fn compile_blob_with_options(
|
||||
.evm
|
||||
.as_ref()
|
||||
.expect("source should produce EVM output")
|
||||
.assembly_text
|
||||
.bytecode
|
||||
.as_ref()
|
||||
.expect("source should produce assembly text");
|
||||
.expect("source should produce assembly text")
|
||||
.object
|
||||
.as_str();
|
||||
|
||||
hex::decode(bytecode).expect("hex encoding should always be valid")
|
||||
}
|
||||
|
||||
@@ -278,11 +278,11 @@ where
|
||||
)
|
||||
})?;
|
||||
|
||||
let encoded_hex_text = revive_linker::link(buffer.as_slice()).map(hex::encode)?;
|
||||
let bytecode = revive_linker::link(buffer.as_slice())?;
|
||||
|
||||
let build = match crate::polkavm::build_assembly_text(
|
||||
contract_path,
|
||||
encoded_hex_text.as_str(),
|
||||
&bytecode,
|
||||
metadata_hash,
|
||||
self.debug_config(),
|
||||
) {
|
||||
|
||||
@@ -11,7 +11,7 @@ pub use self::r#const::*;
|
||||
use crate::debug_config::DebugConfig;
|
||||
use crate::optimizer::settings::Settings as OptimizerSettings;
|
||||
|
||||
use anyhow::{anyhow, Context as AnyhowContext};
|
||||
use anyhow::Context as AnyhowContext;
|
||||
use polkavm_common::program::ProgramBlob;
|
||||
use polkavm_disassembler::{Disassembler, DisassemblyFormat};
|
||||
|
||||
@@ -26,27 +26,17 @@ pub fn initialize_target() {
|
||||
/// Builds PolkaVM assembly text.
|
||||
pub fn build_assembly_text(
|
||||
contract_path: &str,
|
||||
encoded_hex_text: &str,
|
||||
_metadata_hash: Option<[u8; revive_common::BYTE_LENGTH_WORD]>,
|
||||
bytecode: &[u8],
|
||||
metadata_hash: Option<[u8; revive_common::BYTE_LENGTH_WORD]>,
|
||||
debug_config: Option<&DebugConfig>,
|
||||
) -> anyhow::Result<Build> {
|
||||
if let Some(debug_config) = debug_config {
|
||||
debug_config.dump_assembly(contract_path, encoded_hex_text)?;
|
||||
}
|
||||
let program_blob = ProgramBlob::parse(bytecode)
|
||||
.map_err(anyhow::Error::msg)
|
||||
.with_context(|| format!("Failed to parse program blob for contract: {contract_path}"))?;
|
||||
|
||||
let bytecode = hex::decode(encoded_hex_text)
|
||||
.map_err(|e| anyhow!("Failed to decode encoded hex text:\n{}\n", e))?;
|
||||
|
||||
let program_blob = ProgramBlob::parse(bytecode.as_slice())
|
||||
.map_err(|error| anyhow!(format!("Failed to parse program blob:\n{}\n", error)))?;
|
||||
|
||||
let mut disassembler =
|
||||
Disassembler::new(&program_blob, DisassemblyFormat::Guest).map_err(|error| {
|
||||
anyhow!(format!(
|
||||
"Failed to create disassembler for contract:\n{:?}\n\nDue to:\n{}\n",
|
||||
contract_path, error
|
||||
))
|
||||
})?;
|
||||
let mut disassembler = Disassembler::new(&program_blob, DisassemblyFormat::Guest)
|
||||
.map_err(anyhow::Error::msg)
|
||||
.with_context(|| format!("Failed to create disassembler for contract: {contract_path}"))?;
|
||||
disassembler.display_gas()?;
|
||||
|
||||
let mut disassembled_code = Vec::new();
|
||||
@@ -55,15 +45,16 @@ pub fn build_assembly_text(
|
||||
.with_context(|| format!("Failed to disassemble contract: {}", contract_path))?;
|
||||
|
||||
let assembly_text = String::from_utf8(disassembled_code).with_context(|| {
|
||||
format!(
|
||||
"Failed to convert disassembled code to string for contract: {}",
|
||||
contract_path
|
||||
)
|
||||
format!("Failed to convert disassembled code to string for contract: {contract_path}")
|
||||
})?;
|
||||
|
||||
if let Some(debug_config) = debug_config {
|
||||
debug_config.dump_assembly(contract_path, &assembly_text)?;
|
||||
}
|
||||
|
||||
Ok(Build::new(
|
||||
assembly_text.to_owned(),
|
||||
Default::default(),
|
||||
metadata_hash,
|
||||
bytecode.to_owned(),
|
||||
Default::default(),
|
||||
))
|
||||
|
||||
@@ -120,35 +120,6 @@ pub fn llvm_ir(
|
||||
Ok(build)
|
||||
}
|
||||
|
||||
/// Runs the PolkaVM assembly mode.
|
||||
pub fn zkasm(
|
||||
input_files: &[PathBuf],
|
||||
include_metadata_hash: bool,
|
||||
debug_config: Option<revive_llvm_context::DebugConfig>,
|
||||
) -> anyhow::Result<Build> {
|
||||
let path = match input_files.len() {
|
||||
1 => input_files.first().expect("Always exists"),
|
||||
0 => anyhow::bail!("The input file is missing"),
|
||||
length => anyhow::bail!(
|
||||
"Only one input file is allowed in the PolkaVM assembly mode, but found {}",
|
||||
length,
|
||||
),
|
||||
};
|
||||
|
||||
let project = Project::try_from_zkasm_path(path)?;
|
||||
|
||||
let optimizer_settings = revive_llvm_context::OptimizerSettings::none();
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
false,
|
||||
include_metadata_hash,
|
||||
false,
|
||||
debug_config,
|
||||
)?;
|
||||
|
||||
Ok(build)
|
||||
}
|
||||
|
||||
/// Runs the standard output mode.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn standard_output(
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
pub mod evmla;
|
||||
pub mod llvm_ir;
|
||||
pub mod yul;
|
||||
pub mod zkasm;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -17,7 +16,6 @@ use crate::yul::parser::statement::object::Object;
|
||||
use self::evmla::EVMLA;
|
||||
use self::llvm_ir::LLVMIR;
|
||||
use self::yul::Yul;
|
||||
use self::zkasm::ZKASM;
|
||||
|
||||
/// The contract source code.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -31,8 +29,6 @@ pub enum IR {
|
||||
EVMLA(EVMLA),
|
||||
/// The LLVM IR source code.
|
||||
LLVMIR(LLVMIR),
|
||||
/// The PolkaVM assembly source code.
|
||||
ZKASM(ZKASM),
|
||||
}
|
||||
|
||||
impl IR {
|
||||
@@ -51,18 +47,12 @@ impl IR {
|
||||
Self::LLVMIR(LLVMIR::new(path, source))
|
||||
}
|
||||
|
||||
/// A shortcut constructor.
|
||||
pub fn new_zkasm(path: String, source: String) -> Self {
|
||||
Self::ZKASM(ZKASM::new(path, source))
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
match self {
|
||||
Self::Yul(inner) => inner.get_missing_libraries(),
|
||||
Self::EVMLA(inner) => inner.get_missing_libraries(),
|
||||
Self::LLVMIR(_inner) => HashSet::new(),
|
||||
Self::ZKASM(_inner) => HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +69,6 @@ where
|
||||
Self::Yul(inner) => inner.declare(context),
|
||||
Self::EVMLA(inner) => inner.declare(context),
|
||||
Self::LLVMIR(_inner) => Ok(()),
|
||||
Self::ZKASM(_inner) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +77,6 @@ where
|
||||
Self::Yul(inner) => inner.into_llvm(context),
|
||||
Self::EVMLA(inner) => inner.into_llvm(context),
|
||||
Self::LLVMIR(_inner) => Ok(()),
|
||||
Self::ZKASM(_inner) => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
//! The contract PolkaVM assembly source code.
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
/// The contract PolkaVM assembly source code.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct ZKASM {
|
||||
/// The PolkaVM assembly file path.
|
||||
pub path: String,
|
||||
/// The PolkaVM assembly source code.
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
impl ZKASM {
|
||||
/// A shortcut constructor.
|
||||
pub fn new(path: String, source: String) -> Self {
|
||||
Self { path, source }
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,6 @@ impl Contract {
|
||||
IR::Yul(ref yul) => yul.object.identifier.as_str(),
|
||||
IR::EVMLA(ref evm) => evm.assembly.full_path(),
|
||||
IR::LLVMIR(ref llvm_ir) => llvm_ir.path.as_str(),
|
||||
IR::ZKASM(ref zkasm) => zkasm.path.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +70,6 @@ impl Contract {
|
||||
IR::Yul(ref mut yul) => yul.object.factory_dependencies.drain().collect(),
|
||||
IR::EVMLA(ref mut evm) => evm.assembly.factory_dependencies.drain().collect(),
|
||||
IR::LLVMIR(_) => HashSet::new(),
|
||||
IR::ZKASM(_) => HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,21 +114,6 @@ impl Contract {
|
||||
llvm.create_module_from_ir(memory_buffer)
|
||||
.map_err(|error| anyhow::anyhow!(error.to_string()))?
|
||||
}
|
||||
IR::ZKASM(ref zkasm) => {
|
||||
let build = revive_llvm_context::polkavm_build_assembly_text(
|
||||
self.path.as_str(),
|
||||
zkasm.source.as_str(),
|
||||
metadata_hash,
|
||||
debug_config.as_ref(),
|
||||
)?;
|
||||
return Ok(ContractBuild::new(
|
||||
self.path,
|
||||
identifier,
|
||||
build,
|
||||
metadata_json,
|
||||
HashSet::new(),
|
||||
));
|
||||
}
|
||||
_ => llvm.create_module(self.path.as_str()),
|
||||
};
|
||||
let mut context = revive_llvm_context::PolkaVMContext::new(
|
||||
@@ -152,7 +135,6 @@ impl Contract {
|
||||
context.set_evmla_data(evmla_data);
|
||||
}
|
||||
IR::LLVMIR(_) => {}
|
||||
IR::ZKASM(_) => {}
|
||||
}
|
||||
|
||||
let factory_dependencies = self.drain_factory_dependencies();
|
||||
|
||||
@@ -234,36 +234,6 @@ impl Project {
|
||||
BTreeMap::new(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Parses the PolkaVM assembly source code file and returns the source data.
|
||||
pub fn try_from_zkasm_path(path: &Path) -> anyhow::Result<Self> {
|
||||
let source_code = std::fs::read_to_string(path).map_err(|error| {
|
||||
anyhow::anyhow!("PolkaVM assembly file {:?} reading error: {}", path, error)
|
||||
})?;
|
||||
let source_hash = sha3::Keccak256::digest(source_code.as_bytes()).into();
|
||||
|
||||
let source_version =
|
||||
SolcVersion::new_simple(revive_llvm_context::polkavm_const::ZKEVM_VERSION);
|
||||
let path = path.to_string_lossy().to_string();
|
||||
|
||||
let mut project_contracts = BTreeMap::new();
|
||||
project_contracts.insert(
|
||||
path.clone(),
|
||||
Contract::new(
|
||||
path.clone(),
|
||||
source_hash,
|
||||
source_version.clone(),
|
||||
IR::new_zkasm(path, source_code),
|
||||
None,
|
||||
),
|
||||
);
|
||||
|
||||
Ok(Self::new(
|
||||
source_version,
|
||||
project_contracts,
|
||||
BTreeMap::new(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl revive_llvm_context::PolkaVMDependency for Project {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "npx jest --verbose --testPathIgnorePatterns=zkasm.test.ts"
|
||||
"test": "npx jest --verbose --testPathPattern="
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Matter Labs",
|
||||
@@ -20,4 +20,4 @@
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
.text
|
||||
.file "main"
|
||||
.globl __entry
|
||||
__entry:
|
||||
.func_begin0:
|
||||
sub.s! 0, r2, r1
|
||||
jump.eq @.BB0_2
|
||||
add 32, r0, r1
|
||||
st.1 r0, r1
|
||||
st.1 r1, r0
|
||||
add @CPI0_1[0], r0, r1
|
||||
ret.ok.to_label r1, @DEFAULT_FAR_RETURN
|
||||
.BB0_2:
|
||||
add 42, r0, r1
|
||||
st.1 r0, r1
|
||||
add @CPI0_0[0], r0, r1
|
||||
ret.ok.to_label r1, @DEFAULT_FAR_RETURN
|
||||
.func_end0:
|
||||
|
||||
.note.GNU-stack
|
||||
.rodata
|
||||
CPI0_0:
|
||||
.cell 2535301200456458802993406410752
|
||||
CPI0_1:
|
||||
.cell 5070602400912917605986812821504
|
||||
@@ -5,11 +5,9 @@ const binExtension = ':C.zbin';
|
||||
const asmExtension = ':C.zasm';
|
||||
const contractSolFilename = 'contract.sol';
|
||||
const contractYulFilename = 'contract.yul';
|
||||
const contractZkasmFilename = 'contract.zkasm';
|
||||
const pathToOutputDir = path.join( __dirname, '..', outputDir);
|
||||
const pathToContracts = path.join( __dirname, '..', 'src', 'contracts');
|
||||
const pathToOutputDir = path.join(__dirname, '..', outputDir);
|
||||
const pathToContracts = path.join(__dirname, '..', 'src', 'contracts');
|
||||
const pathToBasicYulContract = path.join(pathToContracts, 'yul', contractYulFilename);
|
||||
const pathToBasicZkasmContract = path.join(pathToContracts, 'zkasm', contractZkasmFilename);
|
||||
const pathToBasicSolContract = path.join(pathToContracts, 'solidity', contractSolFilename);
|
||||
const pathToSolBinOutputFile = path.join(pathToOutputDir, contractSolFilename + binExtension);
|
||||
const pathToSolAsmOutputFile = path.join(pathToOutputDir, contractSolFilename + asmExtension);
|
||||
@@ -19,11 +17,9 @@ export const paths = {
|
||||
binExtension: binExtension,
|
||||
asmExtension: asmExtension,
|
||||
contractSolFilename: contractSolFilename,
|
||||
contractZkasmFilename: contractZkasmFilename,
|
||||
contractYulFilename: contractYulFilename,
|
||||
pathToOutputDir: pathToOutputDir,
|
||||
pathToContracts: pathToContracts,
|
||||
pathToBasicZkasmContract: pathToBasicZkasmContract,
|
||||
pathToBasicSolContract: pathToBasicSolContract,
|
||||
pathToBasicYulContract: pathToBasicYulContract,
|
||||
pathToSolBinOutputFile: pathToSolBinOutputFile,
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import {executeCommand} from "../src/helper";
|
||||
import { paths } from '../src/entities';
|
||||
|
||||
|
||||
//id1745
|
||||
describe("Run with --zkasm by default", () => {
|
||||
const command = `zksolc ${paths.pathToBasicZkasmContract} --zkasm`;
|
||||
const result = executeCommand(command);
|
||||
|
||||
it("Valid command exit code = 0", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it("--zkasm output is presented", () => {
|
||||
expect(result.output).toMatch(/(Compiler run successful)/i);
|
||||
expect(result.output).toMatch(/(No output requested)/i);
|
||||
});
|
||||
});
|
||||
@@ -113,13 +113,6 @@ pub struct Arguments {
|
||||
#[structopt(long = "llvm-ir")]
|
||||
pub llvm_ir: bool,
|
||||
|
||||
/// Switch to PolkaVM assembly mode.
|
||||
/// Only one input PolkaVM assembly file is allowed.
|
||||
/// Cannot be used with combined and standard JSON modes.
|
||||
/// Use this mode at your own risk, as PolkaVM assembly input validation is not implemented.
|
||||
#[structopt(long = "zkasm")]
|
||||
pub zkasm: bool,
|
||||
|
||||
/// Forcibly switch to EVM legacy assembly pipeline.
|
||||
/// It is useful for older revisions of `solc` 0.8, where Yul was considered highly experimental
|
||||
/// and contained more bugs than today.
|
||||
@@ -199,7 +192,6 @@ impl Arguments {
|
||||
let modes_count = [
|
||||
self.yul,
|
||||
self.llvm_ir,
|
||||
self.zkasm,
|
||||
self.combined_json.is_some(),
|
||||
self.standard_json,
|
||||
]
|
||||
@@ -210,7 +202,7 @@ impl Arguments {
|
||||
anyhow::bail!("Only one modes is allowed at the same time: Yul, LLVM IR, PolkaVM assembly, combined JSON, standard JSON.");
|
||||
}
|
||||
|
||||
if self.yul || self.llvm_ir || self.zkasm {
|
||||
if self.yul || self.llvm_ir {
|
||||
if self.base_path.is_some() {
|
||||
anyhow::bail!(
|
||||
"`base-path` is not used in Yul, LLVM IR and PolkaVM assembly modes."
|
||||
@@ -247,7 +239,7 @@ impl Arguments {
|
||||
}
|
||||
}
|
||||
|
||||
if self.llvm_ir || self.zkasm {
|
||||
if self.llvm_ir {
|
||||
if self.solc.is_some() {
|
||||
anyhow::bail!("`solc` is not used in LLVM IR and PolkaVM assembly modes.");
|
||||
}
|
||||
@@ -259,19 +251,6 @@ impl Arguments {
|
||||
}
|
||||
}
|
||||
|
||||
if self.zkasm {
|
||||
if self.optimization.is_some() {
|
||||
anyhow::bail!("LLVM optimizations are not supported in PolkaVM assembly mode.");
|
||||
}
|
||||
|
||||
if self.fallback_to_optimizing_for_size {
|
||||
anyhow::bail!("Falling back to -Oz is not supported in PolkaVM assembly mode.");
|
||||
}
|
||||
if self.disable_system_request_memoization {
|
||||
anyhow::bail!("Disabling the system request memoization is not supported in PolkaVM assembly mode.");
|
||||
}
|
||||
}
|
||||
|
||||
if self.combined_json.is_some() {
|
||||
if self.output_assembly || self.output_binary {
|
||||
anyhow::bail!(
|
||||
|
||||
@@ -119,8 +119,6 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
)
|
||||
} else if arguments.zkasm {
|
||||
revive_solidity::zkasm(input_files.as_slice(), include_metadata_hash, debug_config)
|
||||
} else if arguments.standard_json {
|
||||
revive_solidity::standard_json(
|
||||
&mut solc,
|
||||
|
||||
Reference in New Issue
Block a user