mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 06:31:02 +00:00
factor out solc JSON interface crate (#264)
The differential testing framework will make a second consumer. There seems to be no re-usable Rust crate for this. But we already have everything here, just needs a small refactor to make it fully re-usable. - Mostly decouple the solc JSON-input-output interface types from the `solidity` frontend crate - Expose the JSON-input-output interface types in a dedicated crate --------- Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@ Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee`
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Support for solc v0.8.29
|
- Support for solc v0.8.29
|
||||||
|
- Decouples the solc JSON-input-output type definitions from the Solidity fronted and expose them via a dedicated crate.
|
||||||
- `--supported-solc-versions` for `resolc` binary to return a `semver` range of supported `solc` versions.
|
- `--supported-solc-versions` for `resolc` binary to return a `semver` range of supported `solc` versions.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
Generated
+14
@@ -8374,6 +8374,7 @@ dependencies = [
|
|||||||
"revive-common",
|
"revive-common",
|
||||||
"revive-linker",
|
"revive-linker",
|
||||||
"revive-runtime-api",
|
"revive-runtime-api",
|
||||||
|
"revive-solc-json-interface",
|
||||||
"revive-stdlib",
|
"revive-stdlib",
|
||||||
"semver 1.0.25",
|
"semver 1.0.25",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -8406,6 +8407,18 @@ dependencies = [
|
|||||||
"revive-common",
|
"revive-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "revive-solc-json-interface"
|
||||||
|
version = "0.1.0-dev.12"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"rayon",
|
||||||
|
"revive-common",
|
||||||
|
"semver 1.0.25",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-solidity"
|
name = "revive-solidity"
|
||||||
version = "0.1.0-dev.12"
|
version = "0.1.0-dev.12"
|
||||||
@@ -8424,6 +8437,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"revive-common",
|
"revive-common",
|
||||||
"revive-llvm-context",
|
"revive-llvm-context",
|
||||||
|
"revive-solc-json-interface",
|
||||||
"semver 1.0.25",
|
"semver 1.0.25",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ lld-sys = { version = "0.1.0-dev.12", path = "crates/lld-sys" }
|
|||||||
revive-llvm-context = { version = "0.1.0-dev.12", path = "crates/llvm-context" }
|
revive-llvm-context = { version = "0.1.0-dev.12", path = "crates/llvm-context" }
|
||||||
revive-runtime-api = { version = "0.1.0-dev.12", path = "crates/runtime-api" }
|
revive-runtime-api = { version = "0.1.0-dev.12", path = "crates/runtime-api" }
|
||||||
revive-runner = { version = "0.1.0-dev.12", path = "crates/runner" }
|
revive-runner = { version = "0.1.0-dev.12", path = "crates/runner" }
|
||||||
|
revive-solc-json-interface = { version = "0.1.0-dev.12", path = "crates/solc-json-interface" }
|
||||||
revive-solidity = { version = "0.1.0-dev.12", path = "crates/solidity" }
|
revive-solidity = { version = "0.1.0-dev.12", path = "crates/solidity" }
|
||||||
revive-stdlib = { version = "0.1.0-dev.12", path = "crates/stdlib" }
|
revive-stdlib = { version = "0.1.0-dev.12", path = "crates/stdlib" }
|
||||||
revive-build-utils = { version = "0.1.0-dev.12", path = "crates/build-utils" }
|
revive-build-utils = { version = "0.1.0-dev.12", path = "crates/build-utils" }
|
||||||
|
|||||||
@@ -29,3 +29,4 @@ revive-common = { workspace = true }
|
|||||||
revive-runtime-api = { workspace = true }
|
revive-runtime-api = { workspace = true }
|
||||||
revive-linker = { workspace = true }
|
revive-linker = { workspace = true }
|
||||||
revive-stdlib = { workspace = true }
|
revive-stdlib = { workspace = true }
|
||||||
|
revive-solc-json-interface = { workspace = true }
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ pub use self::polkavm::evm::memory as polkavm_evm_memory;
|
|||||||
pub use self::polkavm::evm::r#return as polkavm_evm_return;
|
pub use self::polkavm::evm::r#return as polkavm_evm_return;
|
||||||
pub use self::polkavm::evm::return_data as polkavm_evm_return_data;
|
pub use self::polkavm::evm::return_data as polkavm_evm_return_data;
|
||||||
pub use self::polkavm::evm::storage as polkavm_evm_storage;
|
pub use self::polkavm::evm::storage as polkavm_evm_storage;
|
||||||
pub use self::polkavm::metadata_hash::MetadataHash as PolkaVMMetadataHash;
|
|
||||||
pub use self::polkavm::r#const as polkavm_const;
|
pub use self::polkavm::r#const as polkavm_const;
|
||||||
pub use self::polkavm::Dependency as PolkaVMDependency;
|
pub use self::polkavm::Dependency as PolkaVMDependency;
|
||||||
pub use self::polkavm::DummyDependency as PolkaVMDummyDependency;
|
pub use self::polkavm::DummyDependency as PolkaVMDummyDependency;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
pub mod size_level;
|
pub mod size_level;
|
||||||
|
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@@ -226,3 +227,18 @@ impl std::fmt::Display for Settings {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&SolcStandardJsonInputSettingsOptimizer> for Settings {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: &SolcStandardJsonInputSettingsOptimizer) -> Result<Self, Self::Error> {
|
||||||
|
let mut result = match value.mode {
|
||||||
|
Some(mode) => Self::try_from_cli(mode)?,
|
||||||
|
None => Self::cycles(),
|
||||||
|
};
|
||||||
|
if value.fallback_to_optimizing_for_size.unwrap_or_default() {
|
||||||
|
result.enable_fallback_to_size();
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
pub mod r#const;
|
pub mod r#const;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod evm;
|
pub mod evm;
|
||||||
pub mod metadata_hash;
|
|
||||||
|
|
||||||
pub use self::r#const::*;
|
pub use self::r#const::*;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "revive-solc-json-interface"
|
||||||
|
version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
description = "Rust bindings for the solc standard JSON and combined JSON interface"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["parallel"]
|
||||||
|
parallel = ["rayon"]
|
||||||
|
resolc = [] # The resolc binary adds a bunch of custom fields to the format
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
revive-common = { workspace = true }
|
||||||
|
|
||||||
|
anyhow = { workspace = true }
|
||||||
|
rayon = { workspace = true, optional = true }
|
||||||
|
semver = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//! This crates provides (de)serializable Rust types for interacting
|
||||||
|
//! `solc` via the [JSON-input-output][0] interface.
|
||||||
|
//!
|
||||||
|
//! [0]: https://docs.soliditylang.org/en/latest/using-the-compiler.html#compiler-input-and-output-json-description
|
||||||
|
|
||||||
|
pub use self::combined_json::contract::Contract as CombinedJsonContract;
|
||||||
|
pub use self::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
|
||||||
|
pub use self::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||||
|
pub use self::standard_json::input::settings::metadata_hash::MetadataHash as SolcStandardJsonInputSettingsMetadataHash;
|
||||||
|
pub use self::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||||
|
pub use self::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag;
|
||||||
|
pub use self::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile;
|
||||||
|
pub use self::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||||
|
pub use self::standard_json::input::settings::Settings as SolcStandardJsonInputSettings;
|
||||||
|
pub use self::standard_json::input::source::Source as SolcStandardJsonInputSource;
|
||||||
|
pub use self::standard_json::input::Input as SolcStandardJsonInput;
|
||||||
|
pub use self::standard_json::output::contract::evm::bytecode::Bytecode as SolcStandardJsonOutputContractEVMBytecode;
|
||||||
|
pub use self::standard_json::output::contract::evm::EVM as SolcStandardJsonOutputContractEVM;
|
||||||
|
pub use self::standard_json::output::contract::Contract as SolcStandardJsonOutputContract;
|
||||||
|
pub use self::standard_json::output::Output as SolcStandardJsonOutput;
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
|
pub use self::warning::Warning as ResolcWarning;
|
||||||
|
|
||||||
|
pub mod combined_json;
|
||||||
|
pub mod standard_json;
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
|
pub mod warning;
|
||||||
+9
-5
@@ -8,14 +8,15 @@ use std::collections::BTreeMap;
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[cfg(feature = "parallel")]
|
#[cfg(all(feature = "parallel", feature = "resolc"))]
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
use crate::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||||
use crate::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||||
use crate::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
use crate::warning::Warning;
|
use crate::warning::Warning;
|
||||||
|
|
||||||
use self::language::Language;
|
use self::language::Language;
|
||||||
@@ -33,6 +34,7 @@ pub struct Input {
|
|||||||
/// The compiler settings.
|
/// The compiler settings.
|
||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
/// The suppressed warnings.
|
/// The suppressed warnings.
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub suppressed_warnings: Option<Vec<Warning>>,
|
pub suppressed_warnings: Option<Vec<Warning>>,
|
||||||
}
|
}
|
||||||
@@ -60,7 +62,7 @@ impl Input {
|
|||||||
output_selection: SolcStandardJsonInputSettingsSelection,
|
output_selection: SolcStandardJsonInputSettingsSelection,
|
||||||
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
||||||
metadata: Option<SolcStandardJsonInputSettingsMetadata>,
|
metadata: Option<SolcStandardJsonInputSettingsMetadata>,
|
||||||
suppressed_warnings: Option<Vec<Warning>>,
|
#[cfg(feature = "resolc")] suppressed_warnings: Option<Vec<Warning>>,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
let mut paths: BTreeSet<PathBuf> = paths.iter().cloned().collect();
|
let mut paths: BTreeSet<PathBuf> = paths.iter().cloned().collect();
|
||||||
let libraries = Settings::parse_libraries(library_map)?;
|
let libraries = Settings::parse_libraries(library_map)?;
|
||||||
@@ -89,12 +91,14 @@ impl Input {
|
|||||||
optimizer,
|
optimizer,
|
||||||
metadata,
|
metadata,
|
||||||
),
|
),
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
suppressed_warnings,
|
suppressed_warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A shortcut constructor from source code.
|
/// A shortcut constructor from source code.
|
||||||
/// Only for the integration test purposes.
|
/// Only for the integration test purposes.
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn try_from_sources(
|
pub fn try_from_sources(
|
||||||
evm_version: Option<revive_common::EVMVersion>,
|
evm_version: Option<revive_common::EVMVersion>,
|
||||||
+4
-2
@@ -3,18 +3,20 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::standard_json::input::settings::metadata_hash::MetadataHash;
|
||||||
|
|
||||||
/// The `solc --standard-json` input settings metadata.
|
/// The `solc --standard-json` input settings metadata.
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
/// The bytecode hash mode.
|
/// The bytecode hash mode.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub bytecode_hash: Option<revive_llvm_context::PolkaVMMetadataHash>,
|
pub bytecode_hash: Option<MetadataHash>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Metadata {
|
impl Metadata {
|
||||||
/// A shortcut constructor.
|
/// A shortcut constructor.
|
||||||
pub fn new(bytecode_hash: revive_llvm_context::PolkaVMMetadataHash) -> Self {
|
pub fn new(bytecode_hash: MetadataHash) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bytecode_hash: Some(bytecode_hash),
|
bytecode_hash: Some(bytecode_hash),
|
||||||
}
|
}
|
||||||
+1
@@ -1,6 +1,7 @@
|
|||||||
//! The `solc --standard-json` input settings.
|
//! The `solc --standard-json` input settings.
|
||||||
|
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
pub mod metadata_hash;
|
||||||
pub mod optimizer;
|
pub mod optimizer;
|
||||||
pub mod selection;
|
pub mod selection;
|
||||||
|
|
||||||
-15
@@ -49,18 +49,3 @@ impl Optimizer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&Optimizer> for revive_llvm_context::OptimizerSettings {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
fn try_from(value: &Optimizer) -> Result<Self, Self::Error> {
|
|
||||||
let mut result = match value.mode {
|
|
||||||
Some(mode) => Self::try_from_cli(mode)?,
|
|
||||||
None => Self::cycles(),
|
|
||||||
};
|
|
||||||
if value.fallback_to_optimizing_for_size.unwrap_or_default() {
|
|
||||||
result.enable_fallback_to_size();
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
//! The `solc <input>.sol --standard-json` interface input and output.
|
||||||
|
|
||||||
|
pub mod input;
|
||||||
|
pub mod output;
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//! The `solc --standard-json` output.
|
||||||
|
|
||||||
|
pub mod contract;
|
||||||
|
pub mod error;
|
||||||
|
pub mod source;
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
|
use crate::warning::Warning;
|
||||||
|
|
||||||
|
use self::contract::Contract;
|
||||||
|
use self::error::Error as SolcStandardJsonOutputError;
|
||||||
|
use self::source::Source;
|
||||||
|
|
||||||
|
/// The `solc --standard-json` output.
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||||
|
pub struct Output {
|
||||||
|
/// The file-contract hashmap.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub contracts: Option<BTreeMap<String, BTreeMap<String, Contract>>>,
|
||||||
|
/// The source code mapping data.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub sources: Option<BTreeMap<String, Source>>,
|
||||||
|
/// The compilation errors and warnings.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub errors: Option<Vec<SolcStandardJsonOutputError>>,
|
||||||
|
/// The `solc` compiler version.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub version: Option<String>,
|
||||||
|
/// The `solc` compiler long version.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub long_version: Option<String>,
|
||||||
|
/// The `resolc` compiler version.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub revive_version: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Output {
|
||||||
|
/// Traverses the AST and returns the list of additional errors and warnings.
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
|
pub fn preprocess_ast(&mut self, suppressed_warnings: &[Warning]) -> anyhow::Result<()> {
|
||||||
|
let sources = match self.sources.as_ref() {
|
||||||
|
Some(sources) => sources,
|
||||||
|
None => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
for (path, source) in sources.iter() {
|
||||||
|
if let Some(ast) = source.ast.as_ref() {
|
||||||
|
let mut polkavm_messages = Source::get_messages(ast, suppressed_warnings);
|
||||||
|
for message in polkavm_messages.iter_mut() {
|
||||||
|
message.push_contract_path(path.as_str());
|
||||||
|
}
|
||||||
|
messages.extend(polkavm_messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.errors = match self.errors.take() {
|
||||||
|
Some(mut errors) => {
|
||||||
|
errors.extend(messages);
|
||||||
|
Some(errors)
|
||||||
|
}
|
||||||
|
None => Some(messages),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -3,7 +3,8 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::solc::standard_json::output::error::Error as SolcStandardJsonOutputError;
|
use crate::standard_json::output::error::Error as SolcStandardJsonOutputError;
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
use crate::warning::Warning;
|
use crate::warning::Warning;
|
||||||
|
|
||||||
/// The `solc --standard-json` output source.
|
/// The `solc --standard-json` output source.
|
||||||
@@ -131,6 +132,7 @@ impl Source {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the list of messages for some specific parts of the AST.
|
/// Returns the list of messages for some specific parts of the AST.
|
||||||
|
#[cfg(feature = "resolc")]
|
||||||
pub fn get_messages(
|
pub fn get_messages(
|
||||||
ast: &serde_json::Value,
|
ast: &serde_json::Value,
|
||||||
suppressed_warnings: &[Warning],
|
suppressed_warnings: &[Warning],
|
||||||
@@ -1,26 +1,22 @@
|
|||||||
//! The compiler warning.
|
//! `resolc` custom compiler warnings.
|
||||||
|
//!
|
||||||
|
//! The revive compiler adds warnings only applicable when compilng
|
||||||
|
//! to the revive stack on Polkadot to the output.
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
/// The compiler warning.
|
// The `resolc` custom compiler warning.
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Warning {
|
pub enum Warning {
|
||||||
/// The warning for eponymous feature.
|
|
||||||
EcRecover,
|
EcRecover,
|
||||||
/// The warning for eponymous feature.
|
|
||||||
SendTransfer,
|
SendTransfer,
|
||||||
/// The warning for eponymous feature.
|
|
||||||
ExtCodeSize,
|
ExtCodeSize,
|
||||||
/// The warning for eponymous feature.
|
|
||||||
TxOrigin,
|
TxOrigin,
|
||||||
/// The warning for eponymous feature.
|
|
||||||
BlockTimestamp,
|
BlockTimestamp,
|
||||||
/// The warning for eponymous feature.
|
|
||||||
BlockNumber,
|
BlockNumber,
|
||||||
/// The warning for eponymous feature.
|
|
||||||
BlockHash,
|
BlockHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ inkwell = { workspace = true }
|
|||||||
|
|
||||||
revive-common = { workspace = true }
|
revive-common = { workspace = true }
|
||||||
revive-llvm-context = { workspace = true }
|
revive-llvm-context = { workspace = true }
|
||||||
|
revive-solc-json-interface = { workspace = true, features = ["resolc"] }
|
||||||
|
|
||||||
[target.'cfg(target_env = "musl")'.dependencies]
|
[target.'cfg(target_env = "musl")'.dependencies]
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ use std::fs::File;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use revive_solc_json_interface::CombinedJsonContract;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonOutputContract;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::solc::combined_json::contract::Contract as CombinedJsonContract;
|
|
||||||
use crate::solc::standard_json::output::contract::Contract as StandardJsonOutputContract;
|
|
||||||
|
|
||||||
/// The Solidity contract build.
|
/// The Solidity contract build.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Contract {
|
pub struct Contract {
|
||||||
@@ -131,7 +130,7 @@ impl Contract {
|
|||||||
/// Writes the contract text assembly and bytecode to the standard JSON.
|
/// Writes the contract text assembly and bytecode to the standard JSON.
|
||||||
pub fn write_to_standard_json(
|
pub fn write_to_standard_json(
|
||||||
self,
|
self,
|
||||||
standard_json_contract: &mut StandardJsonOutputContract,
|
standard_json_contract: &mut SolcStandardJsonOutputContract,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
standard_json_contract.metadata = Some(self.metadata_json);
|
standard_json_contract.metadata = Some(self.metadata_json);
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ pub mod contract;
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::solc::combined_json::CombinedJson;
|
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
|
|
||||||
use crate::solc::version::Version as SolcVersion;
|
use crate::solc::version::Version as SolcVersion;
|
||||||
use crate::ResolcVersion;
|
use crate::ResolcVersion;
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ impl Build {
|
|||||||
/// Writes all contracts assembly and bytecode to the standard JSON.
|
/// Writes all contracts assembly and bytecode to the standard JSON.
|
||||||
pub fn write_to_standard_json(
|
pub fn write_to_standard_json(
|
||||||
mut self,
|
mut self,
|
||||||
standard_json: &mut StandardJsonOutput,
|
standard_json: &mut SolcStandardJsonOutput,
|
||||||
solc_version: &SolcVersion,
|
solc_version: &SolcVersion,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let contracts = match standard_json.contracts.as_mut() {
|
let contracts = match standard_json.contracts.as_mut() {
|
||||||
|
|||||||
+25
-27
@@ -7,7 +7,6 @@ pub(crate) mod process;
|
|||||||
pub(crate) mod project;
|
pub(crate) mod project;
|
||||||
pub(crate) mod solc;
|
pub(crate) mod solc;
|
||||||
pub(crate) mod version;
|
pub(crate) mod version;
|
||||||
pub(crate) mod warning;
|
|
||||||
pub(crate) mod yul;
|
pub(crate) mod yul;
|
||||||
|
|
||||||
pub use self::build::contract::Contract as ContractBuild;
|
pub use self::build::contract::Contract as ContractBuild;
|
||||||
@@ -23,31 +22,15 @@ pub use self::process::Process;
|
|||||||
pub use self::project::contract::Contract as ProjectContract;
|
pub use self::project::contract::Contract as ProjectContract;
|
||||||
pub use self::project::Project;
|
pub use self::project::Project;
|
||||||
pub use self::r#const::*;
|
pub use self::r#const::*;
|
||||||
pub use self::solc::combined_json::contract::Contract as SolcCombinedJsonContract;
|
|
||||||
pub use self::solc::combined_json::CombinedJson as SolcCombinedJson;
|
|
||||||
#[cfg(not(target_os = "emscripten"))]
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
pub use self::solc::solc_compiler::SolcCompiler;
|
pub use self::solc::solc_compiler::SolcCompiler;
|
||||||
#[cfg(target_os = "emscripten")]
|
#[cfg(target_os = "emscripten")]
|
||||||
pub use self::solc::soljson_compiler::SoljsonCompiler;
|
pub use self::solc::soljson_compiler::SoljsonCompiler;
|
||||||
pub use self::solc::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
|
|
||||||
pub use self::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
|
||||||
pub use self::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
|
||||||
pub use self::solc::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag;
|
|
||||||
pub use self::solc::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile;
|
|
||||||
pub use self::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
|
||||||
pub use self::solc::standard_json::input::settings::Settings as SolcStandardJsonInputSettings;
|
|
||||||
pub use self::solc::standard_json::input::source::Source as SolcStandardJsonInputSource;
|
|
||||||
pub use self::solc::standard_json::input::Input as SolcStandardJsonInput;
|
|
||||||
pub use self::solc::standard_json::output::contract::evm::bytecode::Bytecode as SolcStandardJsonOutputContractEVMBytecode;
|
|
||||||
pub use self::solc::standard_json::output::contract::evm::EVM as SolcStandardJsonOutputContractEVM;
|
|
||||||
pub use self::solc::standard_json::output::contract::Contract as SolcStandardJsonOutputContract;
|
|
||||||
pub use self::solc::standard_json::output::Output as SolcStandardJsonOutput;
|
|
||||||
pub use self::solc::version::Version as SolcVersion;
|
pub use self::solc::version::Version as SolcVersion;
|
||||||
pub use self::solc::Compiler;
|
pub use self::solc::Compiler;
|
||||||
pub use self::solc::FIRST_SUPPORTED_VERSION as SolcFirstSupportedVersion;
|
pub use self::solc::FIRST_SUPPORTED_VERSION as SolcFirstSupportedVersion;
|
||||||
pub use self::solc::LAST_SUPPORTED_VERSION as SolcLastSupportedVersion;
|
pub use self::solc::LAST_SUPPORTED_VERSION as SolcLastSupportedVersion;
|
||||||
pub use self::version::Version as ResolcVersion;
|
pub use self::version::Version as ResolcVersion;
|
||||||
pub use self::warning::Warning;
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "emscripten"))]
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
pub mod test_utils;
|
pub mod test_utils;
|
||||||
@@ -57,6 +40,13 @@ use std::collections::BTreeSet;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use revive_solc_json_interface::standard_json::input::settings::metadata_hash::MetadataHash;
|
||||||
|
use revive_solc_json_interface::ResolcWarning;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInputLanguage;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection;
|
||||||
|
|
||||||
/// Runs the Yul mode.
|
/// Runs the Yul mode.
|
||||||
pub fn yul<T: Compiler>(
|
pub fn yul<T: Compiler>(
|
||||||
input_files: &[PathBuf],
|
input_files: &[PathBuf],
|
||||||
@@ -126,7 +116,7 @@ pub fn standard_output<T: Compiler>(
|
|||||||
include_paths: Vec<String>,
|
include_paths: Vec<String>,
|
||||||
allow_paths: Option<String>,
|
allow_paths: Option<String>,
|
||||||
remappings: Option<BTreeSet<String>>,
|
remappings: Option<BTreeSet<String>>,
|
||||||
suppressed_warnings: Option<Vec<Warning>>,
|
suppressed_warnings: Option<Vec<ResolcWarning>>,
|
||||||
debug_config: revive_llvm_context::DebugConfig,
|
debug_config: revive_llvm_context::DebugConfig,
|
||||||
) -> anyhow::Result<Build> {
|
) -> anyhow::Result<Build> {
|
||||||
let solc_version = solc.version()?;
|
let solc_version = solc.version()?;
|
||||||
@@ -155,7 +145,7 @@ pub fn standard_output<T: Compiler>(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let libraries = solc_input.settings.libraries.clone().unwrap_or_default();
|
let libraries = solc_input.settings.libraries.clone().unwrap_or_default();
|
||||||
let mut solc_output = solc.standard_json(solc_input, base_path, include_paths, allow_paths)?;
|
let solc_output = solc.standard_json(solc_input, base_path, include_paths, allow_paths)?;
|
||||||
|
|
||||||
if let Some(errors) = solc_output.errors.as_deref() {
|
if let Some(errors) = solc_output.errors.as_deref() {
|
||||||
let mut has_errors = false;
|
let mut has_errors = false;
|
||||||
@@ -173,8 +163,13 @@ pub fn standard_output<T: Compiler>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let project =
|
let project = Project::try_from_standard_json_output(
|
||||||
solc_output.try_to_project(source_code_files, libraries, &solc_version, &debug_config)?;
|
&solc_output,
|
||||||
|
source_code_files,
|
||||||
|
libraries,
|
||||||
|
&solc_version,
|
||||||
|
&debug_config,
|
||||||
|
)?;
|
||||||
|
|
||||||
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
|
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
|
||||||
|
|
||||||
@@ -203,9 +198,7 @@ pub fn standard_json<T: Compiler>(
|
|||||||
revive_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?;
|
revive_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?;
|
||||||
|
|
||||||
let include_metadata_hash = match solc_input.settings.metadata {
|
let include_metadata_hash = match solc_input.settings.metadata {
|
||||||
Some(ref metadata) => {
|
Some(ref metadata) => metadata.bytecode_hash != Some(MetadataHash::None),
|
||||||
metadata.bytecode_hash != Some(revive_llvm_context::PolkaVMMetadataHash::None)
|
|
||||||
}
|
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -221,8 +214,13 @@ pub fn standard_json<T: Compiler>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let project =
|
let project = Project::try_from_standard_json_output(
|
||||||
solc_output.try_to_project(source_code_files, libraries, &solc_version, &debug_config)?;
|
&solc_output,
|
||||||
|
source_code_files,
|
||||||
|
libraries,
|
||||||
|
&solc_version,
|
||||||
|
&debug_config,
|
||||||
|
)?;
|
||||||
|
|
||||||
if detect_missing_libraries {
|
if detect_missing_libraries {
|
||||||
let missing_libraries = project.get_missing_libraries();
|
let missing_libraries = project.get_missing_libraries();
|
||||||
@@ -250,7 +248,7 @@ pub fn combined_json<T: Compiler>(
|
|||||||
include_paths: Vec<String>,
|
include_paths: Vec<String>,
|
||||||
allow_paths: Option<String>,
|
allow_paths: Option<String>,
|
||||||
remappings: Option<BTreeSet<String>>,
|
remappings: Option<BTreeSet<String>>,
|
||||||
suppressed_warnings: Option<Vec<Warning>>,
|
suppressed_warnings: Option<Vec<ResolcWarning>>,
|
||||||
debug_config: revive_llvm_context::DebugConfig,
|
debug_config: revive_llvm_context::DebugConfig,
|
||||||
output_directory: Option<PathBuf>,
|
output_directory: Option<PathBuf>,
|
||||||
overwrite: bool,
|
overwrite: bool,
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
|
|
||||||
use crate::solc::version::Version as SolcVersion;
|
use crate::solc::version::Version as SolcVersion;
|
||||||
use crate::ResolcVersion;
|
use crate::ResolcVersion;
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ impl MissingLibraries {
|
|||||||
/// Writes the missing libraries to the standard JSON.
|
/// Writes the missing libraries to the standard JSON.
|
||||||
pub fn write_to_standard_json(
|
pub fn write_to_standard_json(
|
||||||
mut self,
|
mut self,
|
||||||
standard_json: &mut StandardJsonOutput,
|
standard_json: &mut SolcStandardJsonOutput,
|
||||||
solc_version: &SolcVersion,
|
solc_version: &SolcVersion,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let contracts = match standard_json.contracts.as_mut() {
|
let contracts = match standard_json.contracts.as_mut() {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use std::path::Path;
|
|||||||
|
|
||||||
#[cfg(feature = "parallel")]
|
#[cfg(feature = "parallel")]
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sha3::Digest;
|
use sha3::Digest;
|
||||||
@@ -243,6 +244,69 @@ impl Project {
|
|||||||
BTreeMap::new(),
|
BTreeMap::new(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts the `solc` JSON output into a convenient project.
|
||||||
|
pub fn try_from_standard_json_output(
|
||||||
|
output: &SolcStandardJsonOutput,
|
||||||
|
source_code_files: BTreeMap<String, String>,
|
||||||
|
libraries: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
|
solc_version: &SolcVersion,
|
||||||
|
debug_config: &revive_llvm_context::DebugConfig,
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
|
let files = match output.contracts.as_ref() {
|
||||||
|
Some(files) => files,
|
||||||
|
None => match &output.errors {
|
||||||
|
Some(errors) if errors.iter().any(|e| e.severity == "error") => {
|
||||||
|
anyhow::bail!(serde_json::to_string_pretty(errors).expect("Always valid"));
|
||||||
|
}
|
||||||
|
_ => &BTreeMap::new(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let mut project_contracts = BTreeMap::new();
|
||||||
|
|
||||||
|
for (path, contracts) in files.iter() {
|
||||||
|
for (name, contract) in contracts.iter() {
|
||||||
|
let full_path = format!("{path}:{name}");
|
||||||
|
|
||||||
|
let ir_optimized = match contract.ir_optimized.to_owned() {
|
||||||
|
Some(ir_optimized) => ir_optimized,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
if ir_optimized.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_config.dump_yul(full_path.as_str(), ir_optimized.as_str())?;
|
||||||
|
|
||||||
|
let mut lexer = Lexer::new(ir_optimized.to_owned());
|
||||||
|
let object = Object::parse(&mut lexer, None).map_err(|error| {
|
||||||
|
anyhow::anyhow!("Contract `{}` parsing error: {:?}", full_path, error)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let source = IR::new_yul(ir_optimized.to_owned(), object);
|
||||||
|
|
||||||
|
let source_code = source_code_files
|
||||||
|
.get(path.as_str())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Source code for path `{}` not found", path))?;
|
||||||
|
let source_hash = sha3::Keccak256::digest(source_code.as_bytes()).into();
|
||||||
|
|
||||||
|
let project_contract = Contract::new(
|
||||||
|
full_path.clone(),
|
||||||
|
source_hash,
|
||||||
|
solc_version.to_owned(),
|
||||||
|
source,
|
||||||
|
contract.metadata.to_owned(),
|
||||||
|
);
|
||||||
|
project_contracts.insert(full_path, project_contract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Project::new(
|
||||||
|
solc_version.to_owned(),
|
||||||
|
project_contracts,
|
||||||
|
libraries,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl revive_llvm_context::PolkaVMDependency for Project {
|
impl revive_llvm_context::PolkaVMDependency for Project {
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ fn main_inner() -> anyhow::Result<()> {
|
|||||||
let (input_files, remappings) = arguments.split_input_files_and_remappings()?;
|
let (input_files, remappings) = arguments.split_input_files_and_remappings()?;
|
||||||
|
|
||||||
let suppressed_warnings = match arguments.suppress_warnings {
|
let suppressed_warnings = match arguments.suppress_warnings {
|
||||||
Some(warnings) => Some(revive_solidity::Warning::try_from_strings(
|
Some(warnings) => Some(revive_solc_json_interface::ResolcWarning::try_from_strings(
|
||||||
warnings.as_slice(),
|
warnings.as_slice(),
|
||||||
)?),
|
)?),
|
||||||
None => None,
|
None => None,
|
||||||
@@ -142,8 +142,10 @@ fn main_inner() -> anyhow::Result<()> {
|
|||||||
let include_metadata_hash = match arguments.metadata_hash {
|
let include_metadata_hash = match arguments.metadata_hash {
|
||||||
Some(metadata_hash) => {
|
Some(metadata_hash) => {
|
||||||
let metadata =
|
let metadata =
|
||||||
revive_llvm_context::PolkaVMMetadataHash::from_str(metadata_hash.as_str())?;
|
revive_solc_json_interface::SolcStandardJsonInputSettingsMetadataHash::from_str(
|
||||||
metadata != revive_llvm_context::PolkaVMMetadataHash::None
|
metadata_hash.as_str(),
|
||||||
|
)?;
|
||||||
|
metadata != revive_solc_json_interface::SolcStandardJsonInputSettingsMetadataHash::None
|
||||||
}
|
}
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
//! The Solidity compiler.
|
//! The Solidity compiler.
|
||||||
|
|
||||||
pub mod combined_json;
|
|
||||||
#[cfg(not(target_os = "emscripten"))]
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
pub mod solc_compiler;
|
pub mod solc_compiler;
|
||||||
#[cfg(target_os = "emscripten")]
|
#[cfg(target_os = "emscripten")]
|
||||||
pub mod soljson_compiler;
|
pub mod soljson_compiler;
|
||||||
pub mod standard_json;
|
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use self::combined_json::CombinedJson;
|
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||||
use self::standard_json::input::Input as StandardJsonInput;
|
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||||
use self::standard_json::output::Output as StandardJsonOutput;
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
|
|
||||||
use self::version::Version;
|
use self::version::Version;
|
||||||
|
|
||||||
/// The first version of `solc` with the support of standard JSON interface.
|
/// The first version of `solc` with the support of standard JSON interface.
|
||||||
@@ -30,11 +29,11 @@ pub trait Compiler {
|
|||||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||||
fn standard_json(
|
fn standard_json(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: StandardJsonInput,
|
input: SolcStandardJsonInput,
|
||||||
base_path: Option<String>,
|
base_path: Option<String>,
|
||||||
include_paths: Vec<String>,
|
include_paths: Vec<String>,
|
||||||
allow_paths: Option<String>,
|
allow_paths: Option<String>,
|
||||||
) -> anyhow::Result<StandardJsonOutput>;
|
) -> anyhow::Result<SolcStandardJsonOutput>;
|
||||||
|
|
||||||
/// The `solc --combined-json abi,hashes...` mirror.
|
/// The `solc --combined-json abi,hashes...` mirror.
|
||||||
fn combined_json(
|
fn combined_json(
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ use std::io::Write;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::solc::combined_json::CombinedJson;
|
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||||
use crate::solc::standard_json::input::Input as StandardJsonInput;
|
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
|
|
||||||
use crate::solc::version::Version;
|
use crate::solc::version::Version;
|
||||||
|
|
||||||
use super::Compiler;
|
use super::Compiler;
|
||||||
@@ -39,11 +40,11 @@ impl Compiler for SolcCompiler {
|
|||||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||||
fn standard_json(
|
fn standard_json(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut input: StandardJsonInput,
|
mut input: SolcStandardJsonInput,
|
||||||
base_path: Option<String>,
|
base_path: Option<String>,
|
||||||
include_paths: Vec<String>,
|
include_paths: Vec<String>,
|
||||||
allow_paths: Option<String>,
|
allow_paths: Option<String>,
|
||||||
) -> anyhow::Result<StandardJsonOutput> {
|
) -> anyhow::Result<SolcStandardJsonOutput> {
|
||||||
let version = self.version()?.validate(&include_paths)?.default;
|
let version = self.version()?.validate(&include_paths)?.default;
|
||||||
|
|
||||||
let mut command = std::process::Command::new(self.executable.as_str());
|
let mut command = std::process::Command::new(self.executable.as_str());
|
||||||
@@ -93,7 +94,7 @@ impl Compiler for SolcCompiler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output: StandardJsonOutput =
|
let mut output: SolcStandardJsonOutput =
|
||||||
revive_common::deserialize_from_slice(output.stdout.as_slice()).map_err(|error| {
|
revive_common::deserialize_from_slice(output.stdout.as_slice()).map_err(|error| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"{} subprocess output parsing error: {}\n{}",
|
"{} subprocess output parsing error: {}\n{}",
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::solc::combined_json::CombinedJson;
|
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||||
use crate::solc::standard_json::input::Input as StandardJsonInput;
|
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
|
|
||||||
use crate::solc::version::Version;
|
use crate::solc::version::Version;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use std::ffi::{c_char, c_void, CStr, CString};
|
use std::ffi::{c_char, c_void, CStr, CString};
|
||||||
@@ -24,11 +25,11 @@ impl Compiler for SoljsonCompiler {
|
|||||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||||
fn standard_json(
|
fn standard_json(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut input: StandardJsonInput,
|
mut input: SolcStandardJsonInput,
|
||||||
base_path: Option<String>,
|
base_path: Option<String>,
|
||||||
include_paths: Vec<String>,
|
include_paths: Vec<String>,
|
||||||
allow_paths: Option<String>,
|
allow_paths: Option<String>,
|
||||||
) -> anyhow::Result<StandardJsonOutput> {
|
) -> anyhow::Result<SolcStandardJsonOutput> {
|
||||||
if !include_paths.is_empty() {
|
if !include_paths.is_empty() {
|
||||||
anyhow::bail!("configuring include paths is not supported with solJson")
|
anyhow::bail!("configuring include paths is not supported with solJson")
|
||||||
}
|
}
|
||||||
@@ -46,8 +47,8 @@ impl Compiler for SoljsonCompiler {
|
|||||||
|
|
||||||
let input_json = serde_json::to_string(&input).expect("Always valid");
|
let input_json = serde_json::to_string(&input).expect("Always valid");
|
||||||
let out = Self::compile_standard_json(input_json)?;
|
let out = Self::compile_standard_json(input_json)?;
|
||||||
let mut output: StandardJsonOutput = revive_common::deserialize_from_slice(out.as_bytes())
|
let mut output: SolcStandardJsonOutput =
|
||||||
.map_err(|error| {
|
revive_common::deserialize_from_slice(out.as_bytes()).map_err(|error| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"Soljson output parsing error: {}\n{}",
|
"Soljson output parsing error: {}\n{}",
|
||||||
error,
|
error,
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
//! The `solc <input>.sol --standard-json`.
|
|
||||||
|
|
||||||
pub mod input;
|
|
||||||
pub mod output;
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
//! The `solc --standard-json` output.
|
|
||||||
|
|
||||||
pub mod contract;
|
|
||||||
pub mod error;
|
|
||||||
pub mod source;
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
use serde::Serialize;
|
|
||||||
use sha3::Digest;
|
|
||||||
|
|
||||||
use crate::project::contract::ir::IR as ProjectContractIR;
|
|
||||||
use crate::project::contract::Contract as ProjectContract;
|
|
||||||
use crate::project::Project;
|
|
||||||
use crate::solc::version::Version as SolcVersion;
|
|
||||||
use crate::warning::Warning;
|
|
||||||
use crate::yul::lexer::Lexer;
|
|
||||||
use crate::yul::parser::statement::object::Object;
|
|
||||||
|
|
||||||
use self::contract::Contract;
|
|
||||||
use self::error::Error as SolcStandardJsonOutputError;
|
|
||||||
use self::source::Source;
|
|
||||||
/// The `solc --standard-json` output.
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
|
||||||
pub struct Output {
|
|
||||||
/// The file-contract hashmap.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub contracts: Option<BTreeMap<String, BTreeMap<String, Contract>>>,
|
|
||||||
/// The source code mapping data.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub sources: Option<BTreeMap<String, Source>>,
|
|
||||||
/// The compilation errors and warnings.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub errors: Option<Vec<SolcStandardJsonOutputError>>,
|
|
||||||
/// The `solc` compiler version.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub version: Option<String>,
|
|
||||||
/// The `solc` compiler long version.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub long_version: Option<String>,
|
|
||||||
/// The `resolc` compiler version.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub revive_version: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Output {
|
|
||||||
/// Converts the `solc` JSON output into a convenient project.
|
|
||||||
pub fn try_to_project(
|
|
||||||
&mut self,
|
|
||||||
source_code_files: BTreeMap<String, String>,
|
|
||||||
libraries: BTreeMap<String, BTreeMap<String, String>>,
|
|
||||||
solc_version: &SolcVersion,
|
|
||||||
debug_config: &revive_llvm_context::DebugConfig,
|
|
||||||
) -> anyhow::Result<Project> {
|
|
||||||
let files = match self.contracts.as_ref() {
|
|
||||||
Some(files) => files,
|
|
||||||
None => match &self.errors {
|
|
||||||
Some(errors) if errors.iter().any(|e| e.severity == "error") => {
|
|
||||||
anyhow::bail!(serde_json::to_string_pretty(errors).expect("Always valid"));
|
|
||||||
}
|
|
||||||
_ => &BTreeMap::new(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let mut project_contracts = BTreeMap::new();
|
|
||||||
|
|
||||||
for (path, contracts) in files.iter() {
|
|
||||||
for (name, contract) in contracts.iter() {
|
|
||||||
let full_path = format!("{path}:{name}");
|
|
||||||
|
|
||||||
let ir_optimized = match contract.ir_optimized.to_owned() {
|
|
||||||
Some(ir_optimized) => ir_optimized,
|
|
||||||
None => continue,
|
|
||||||
};
|
|
||||||
if ir_optimized.is_empty() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_config.dump_yul(full_path.as_str(), ir_optimized.as_str())?;
|
|
||||||
|
|
||||||
let mut lexer = Lexer::new(ir_optimized.to_owned());
|
|
||||||
let object = Object::parse(&mut lexer, None).map_err(|error| {
|
|
||||||
anyhow::anyhow!("Contract `{}` parsing error: {:?}", full_path, error)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let source = ProjectContractIR::new_yul(ir_optimized.to_owned(), object);
|
|
||||||
|
|
||||||
let source_code = source_code_files
|
|
||||||
.get(path.as_str())
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("Source code for path `{}` not found", path))?;
|
|
||||||
let source_hash = sha3::Keccak256::digest(source_code.as_bytes()).into();
|
|
||||||
|
|
||||||
let project_contract = ProjectContract::new(
|
|
||||||
full_path.clone(),
|
|
||||||
source_hash,
|
|
||||||
solc_version.to_owned(),
|
|
||||||
source,
|
|
||||||
contract.metadata.to_owned(),
|
|
||||||
);
|
|
||||||
project_contracts.insert(full_path, project_contract);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Project::new(
|
|
||||||
solc_version.to_owned(),
|
|
||||||
project_contracts,
|
|
||||||
libraries,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Traverses the AST and returns the list of additional errors and warnings.
|
|
||||||
pub fn preprocess_ast(&mut self, suppressed_warnings: &[Warning]) -> anyhow::Result<()> {
|
|
||||||
let sources = match self.sources.as_ref() {
|
|
||||||
Some(sources) => sources,
|
|
||||||
None => return Ok(()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut messages = Vec::new();
|
|
||||||
for (path, source) in sources.iter() {
|
|
||||||
if let Some(ast) = source.ast.as_ref() {
|
|
||||||
let mut polkavm_messages = Source::get_messages(ast, suppressed_warnings);
|
|
||||||
for message in polkavm_messages.iter_mut() {
|
|
||||||
message.push_contract_path(path.as_str());
|
|
||||||
}
|
|
||||||
messages.extend(polkavm_messages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.errors = match self.errors.take() {
|
|
||||||
Some(mut errors) => {
|
|
||||||
errors.extend(messages);
|
|
||||||
Some(errors)
|
|
||||||
}
|
|
||||||
None => Some(messages),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,17 +7,17 @@ use std::sync::Mutex;
|
|||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use revive_llvm_context::OptimizerSettings;
|
use revive_llvm_context::OptimizerSettings;
|
||||||
|
use revive_solc_json_interface::standard_json::output::contract::evm::bytecode::Bytecode;
|
||||||
|
use revive_solc_json_interface::standard_json::output::contract::evm::bytecode::DeployedBytecode;
|
||||||
|
use revive_solc_json_interface::warning::Warning;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection;
|
||||||
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||||
|
|
||||||
use crate::project::Project;
|
use crate::project::Project;
|
||||||
use crate::solc::solc_compiler::SolcCompiler;
|
use crate::solc::solc_compiler::SolcCompiler;
|
||||||
use crate::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
|
||||||
use crate::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
|
||||||
use crate::solc::standard_json::input::Input as SolcStandardJsonInput;
|
|
||||||
use crate::solc::standard_json::output::contract::evm::bytecode::Bytecode;
|
|
||||||
use crate::solc::standard_json::output::contract::evm::bytecode::DeployedBytecode;
|
|
||||||
use crate::solc::standard_json::output::Output as SolcStandardJsonOutput;
|
|
||||||
use crate::solc::Compiler;
|
use crate::solc::Compiler;
|
||||||
use crate::warning::Warning;
|
|
||||||
|
|
||||||
static PVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
static PVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
||||||
static EVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
static EVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
||||||
@@ -98,7 +98,13 @@ pub fn build_solidity_with_options(
|
|||||||
|
|
||||||
let mut output = solc.standard_json(input, None, vec![], None)?;
|
let mut output = solc.standard_json(input, None, vec![], None)?;
|
||||||
|
|
||||||
let project = output.try_to_project(sources, libraries, &solc_version, &DEBUG_CONFIG)?;
|
let project = Project::try_from_standard_json_output(
|
||||||
|
&output,
|
||||||
|
sources,
|
||||||
|
libraries,
|
||||||
|
&solc_version,
|
||||||
|
&DEBUG_CONFIG,
|
||||||
|
)?;
|
||||||
|
|
||||||
let build: crate::Build = project.compile(optimizer_settings, false, DEBUG_CONFIG)?;
|
let build: crate::Build = project.compile(optimizer_settings, false, DEBUG_CONFIG)?;
|
||||||
build.write_to_standard_json(&mut output, &solc_version)?;
|
build.write_to_standard_json(&mut output, &solc_version)?;
|
||||||
@@ -188,7 +194,13 @@ pub fn build_solidity_and_detect_missing_libraries(
|
|||||||
|
|
||||||
let mut output = solc.standard_json(input, None, vec![], None)?;
|
let mut output = solc.standard_json(input, None, vec![], None)?;
|
||||||
|
|
||||||
let project = output.try_to_project(sources, libraries, &solc_version, &DEBUG_CONFIG)?;
|
let project = Project::try_from_standard_json_output(
|
||||||
|
&output,
|
||||||
|
sources,
|
||||||
|
libraries,
|
||||||
|
&solc_version,
|
||||||
|
&DEBUG_CONFIG,
|
||||||
|
)?;
|
||||||
|
|
||||||
let missing_libraries = project.get_missing_libraries();
|
let missing_libraries = project.get_missing_libraries();
|
||||||
missing_libraries.write_to_standard_json(&mut output, &solc.version()?)?;
|
missing_libraries.write_to_standard_json(&mut output, &solc.version()?)?;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::warning::Warning;
|
use revive_solc_json_interface::warning::Warning;
|
||||||
|
|
||||||
pub const ECRECOVER_TEST_SOURCE: &str = r#"
|
pub const ECRECOVER_TEST_SOURCE: &str = r#"
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|||||||
Reference in New Issue
Block a user