From f4aa8eb4d3c3db6a4522f6ce927d32e94176023c Mon Sep 17 00:00:00 2001 From: Rim Rakhimov Date: Sat, 14 Oct 2023 12:46:06 +0300 Subject: [PATCH] eth-bytecode-db: update server to support verifier alliance database (#620) * Add integration tests for the verifier alliance test cases * Actual implementation of verifier alliance database insertion * Extened verification metadata struct in the API. Add test cases for authorized requests * Add deployement data storage in case of authorized request * Copy verifier alliance tests into server implementation. Update api verification endpoints and implementations to support verifier alliance setup * Add missing dependencies --- eth-bytecode-db/Cargo.lock | 40 +- .../proto/v2/eth-bytecode-db.proto | 12 + .../swagger/v2/eth-bytecode-db.swagger.yaml | 20 + .../eth-bytecode-db-server/Cargo.toml | 6 +- .../eth-bytecode-db-server/src/server.rs | 22 +- .../src/services/mod.rs | 24 + .../src/services/solidity_verifier.rs | 18 +- .../src/services/vyper_verifier.rs | 18 +- .../eth-bytecode-db-server/src/settings.rs | 21 + .../src/types/verification_metadata.rs | 79 ++- .../constructor_arguments.json | 72 +++ .../tests/alliance_test_cases/full_match.json | 64 +++ .../tests/alliance_test_cases/immutables.json | 75 +++ .../libraries_linked_by_compiler.json | 70 +++ .../libraries_manually_linked.json | 88 ++++ .../metadata_hash_absent.json | 67 +++ .../alliance_test_cases/partial_match.json | 88 ++++ .../partial_match_double_auxdata.json | 97 ++++ .../database_helpers.rs | 47 +- .../tests/verification_test_helpers/mod.rs | 103 +++- .../verifier_alliance_types.rs | 210 ++++++++ .../tests/verifier_alliance.rs | 460 ++++++++++++++++++ .../verification/db/verifier_alliance_db.rs | 112 ++++- .../src/verification/handlers/mod.rs | 106 +++- .../handlers/solidity_multi_part.rs | 8 +- .../handlers/solidity_standard_json.rs | 9 +- .../verification/handlers/vyper_multi_part.rs | 8 +- .../handlers/vyper_standard_json.rs | 8 +- .../eth-bytecode-db/src/verification/types.rs | 11 +- .../database_helpers.rs | 10 +- .../tests/verification_test_helpers/mod.rs | 6 + .../verifier_alliance_types.rs | 20 +- .../tests/verifier_alliance.rs | 263 ++++++++-- 33 files changed, 2087 insertions(+), 175 deletions(-) create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/constructor_arguments.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/full_match.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/immutables.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_linked_by_compiler.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_manually_linked.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/metadata_hash_absent.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match_double_auxdata.json create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/verifier_alliance_types.rs create mode 100644 eth-bytecode-db/eth-bytecode-db-server/tests/verifier_alliance.rs diff --git a/eth-bytecode-db/Cargo.lock b/eth-bytecode-db/Cargo.lock index 105855119..cbd28f1db 100644 --- a/eth-bytecode-db/Cargo.lock +++ b/eth-bytecode-db/Cargo.lock @@ -981,9 +981,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -1754,7 +1754,7 @@ dependencies = [ "pretty_assertions", "prometheus", "reqwest", - "rstest 0.18.2", + "rstest", "sea-orm", "semver", "serde", @@ -1798,17 +1798,19 @@ dependencies = [ "async-trait", "blockscout-display-bytes", "blockscout-service-launcher", + "bytes", "config", "eth-bytecode-db", "eth-bytecode-db-proto", "ethers", "hex", + "keccak-hash", "migration", "mockall", "pretty_assertions", "rand", "reqwest", - "rstest 0.16.0", + "rstest", "sea-orm", "serde", "serde_json", @@ -1819,6 +1821,8 @@ dependencies = [ "tokio-stream", "tonic", "tracing", + "verifier-alliance-entity", + "verifier-alliance-migration", ] [[package]] @@ -4552,18 +4556,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rstest" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07f2d176c472198ec1e6551dc7da28f1c089652f66a7b722676c2238ebc0edf" -dependencies = [ - "futures", - "futures-timer", - "rstest_macros 0.16.0", - "rustc_version", -] - [[package]] name = "rstest" version = "0.18.2" @@ -4572,24 +4564,10 @@ checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" dependencies = [ "futures", "futures-timer", - "rstest_macros 0.18.2", + "rstest_macros", "rustc_version", ] -[[package]] -name = "rstest_macros" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7229b505ae0706e64f37ffc54a9c163e11022a6636d58fe1f3f52018257ff9f7" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", - "unicode-ident", -] - [[package]] name = "rstest_macros" version = "0.18.2" diff --git a/eth-bytecode-db/eth-bytecode-db-proto/proto/v2/eth-bytecode-db.proto b/eth-bytecode-db/eth-bytecode-db-proto/proto/v2/eth-bytecode-db.proto index d5406e21d..a0af98485 100644 --- a/eth-bytecode-db/eth-bytecode-db-proto/proto/v2/eth-bytecode-db.proto +++ b/eth-bytecode-db/eth-bytecode-db-proto/proto/v2/eth-bytecode-db.proto @@ -98,6 +98,18 @@ message VerificationMetadata { optional string chain_id = 1; /// The address of the contract to be verified optional string contract_address = 2; + /// The hash of the transaction the contract has been created at + optional string transaction_hash = 3; + /// The number of the block containing the creation transaction + optional int64 block_number = 4; + /// The position number transaction has been added into a block + optional int64 transaction_index = 5; + /// The address which actually deployed the contract (i.e. called the create/create2 opcode) + optional string deployer = 6; + /// The bytecode from the calldata (for eoa deployments) or given to create/create2 + optional string creation_code = 7; + // The bytecode actually stored in the blockchain for the given contract + optional string runtime_code = 8; } message VerifySolidityMultiPartRequest { diff --git a/eth-bytecode-db/eth-bytecode-db-proto/swagger/v2/eth-bytecode-db.swagger.yaml b/eth-bytecode-db/eth-bytecode-db-proto/swagger/v2/eth-bytecode-db.swagger.yaml index 73f2ac218..44fa1773b 100644 --- a/eth-bytecode-db/eth-bytecode-db-proto/swagger/v2/eth-bytecode-db.swagger.yaml +++ b/eth-bytecode-db/eth-bytecode-db-proto/swagger/v2/eth-bytecode-db.swagger.yaml @@ -408,12 +408,32 @@ definitions: v2VerificationMetadata: type: object properties: + blockNumber: + type: string + format: int64 + title: / The number of the block containing the creation transaction chainId: type: string title: / Id of the chain the contract is verified on contractAddress: type: string title: / The address of the contract to be verified + creationCode: + type: string + title: / The bytecode from the calldata (for eoa deployments) or given to create/create2 + deployer: + type: string + title: / The address which actually deployed the contract (i.e. called the create/create2 opcode) + runtimeCode: + type: string + title: The bytecode actually stored in the blockchain for the given contract + transactionHash: + type: string + title: / The hash of the transaction the contract has been created at + transactionIndex: + type: string + format: int64 + title: / The position number transaction has been added into a block v2VerifyFromEtherscanSourcifyRequest: type: object properties: diff --git a/eth-bytecode-db/eth-bytecode-db-server/Cargo.toml b/eth-bytecode-db/eth-bytecode-db-server/Cargo.toml index 0f539f90d..5bec356a4 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/Cargo.toml +++ b/eth-bytecode-db/eth-bytecode-db-server/Cargo.toml @@ -29,12 +29,16 @@ tracing = "0.1" [dev-dependencies] smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "2480b20" } +verifier-alliance-entity = { path = "../eth-bytecode-db/verifier-alliance-entity" } +verifier-alliance-migration = { path = "../eth-bytecode-db/verifier-alliance-migration" } +bytes = "1.5.0" hex = "0.4.3" mockall = "0.11" +keccak-hash = "0.10.0" pretty_assertions = "1.3" reqwest = { version = "0.11", features = ["json"]} rand = "0.8" -rstest = "0.16" +rstest = "0.18.2" sea-orm = { version = "*", features = [ "sqlx-sqlite" ]} tokio-stream = { version = "0.1", features = ["net"] } \ No newline at end of file diff --git a/eth-bytecode-db/eth-bytecode-db-server/src/server.rs b/eth-bytecode-db/eth-bytecode-db-server/src/server.rs index 8dabbcbfa..96614535e 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/src/server.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/src/server.rs @@ -16,7 +16,7 @@ use crate::{ use blockscout_service_launcher::{database, launcher, launcher::LaunchSettings, tracing}; use eth_bytecode_db::verification::Client; use migration::Migrator; -use std::sync::Arc; +use std::{collections::HashSet, sync::Arc}; const SERVICE_NAME: &str = "eth_bytecode_db"; @@ -84,7 +84,12 @@ pub async fn run(settings: Settings) -> Result<(), anyhow::Error> { .await?; let db_connection = Arc::new(sea_orm::Database::connect(settings.database.url).await?); - let client = Client::new_arc(db_connection.clone(), settings.verifier.uri).await?; + let mut client = Client::new_arc(db_connection.clone(), settings.verifier.uri).await?; + if settings.verifier_alliance_database.enabled { + let alliance_db_connection = + sea_orm::Database::connect(settings.verifier_alliance_database.url).await?; + client = client.with_alliance_db(alliance_db_connection); + } let sourcify_client = sourcify::ClientBuilder::default() .try_base_url(&settings.sourcify.base_url) @@ -93,8 +98,17 @@ pub async fn run(settings: Settings) -> Result<(), anyhow::Error> { .build(); let database = Arc::new(DatabaseService::new_arc(client.clone(), sourcify_client)); - let solidity_verifier = Arc::new(SolidityVerifierService::new(client.clone())); - let vyper_verifier = Arc::new(VyperVerifierService::new(client.clone())); + let authorized_keys: HashSet<_> = settings + .authorized_keys + .into_values() + .map(|key| key.key) + .collect(); + + let solidity_verifier = Arc::new( + SolidityVerifierService::new(client.clone()).with_authorized_keys(authorized_keys.clone()), + ); + let vyper_verifier = + Arc::new(VyperVerifierService::new(client.clone()).with_authorized_keys(authorized_keys)); let sourcify_verifier = Arc::new(SourcifyVerifierService::new(client.clone())); let router = Router { diff --git a/eth-bytecode-db/eth-bytecode-db-server/src/services/mod.rs b/eth-bytecode-db/eth-bytecode-db-server/src/services/mod.rs index c8ca73567..50729e6cf 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/src/services/mod.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/src/services/mod.rs @@ -10,3 +10,27 @@ pub use health::HealthService; pub use solidity_verifier::SolidityVerifierService; pub use sourcify_verifier::SourcifyVerifierService; pub use vyper_verifier::VyperVerifierService; + +/****************************************************************************/ + +const API_KEY_NAME: &str = "x-api-key"; + +fn is_key_authorized( + authorized_keys: &std::collections::HashSet, + metadata: tonic::metadata::MetadataMap, +) -> Result { + let api_key = metadata + .get(API_KEY_NAME) + .map(|api_key| api_key.to_str()) + .transpose() + .map_err(|err| { + tonic::Status::invalid_argument(format!( + "invalid api key value ({API_KEY_NAME}): {err}" + )) + })?; + + let is_authorized = api_key + .map(|key| authorized_keys.contains(key)) + .unwrap_or_default(); + Ok(is_authorized) +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/src/services/solidity_verifier.rs b/eth-bytecode-db/eth-bytecode-db-server/src/services/solidity_verifier.rs index bc40c5be2..99c548524 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/src/services/solidity_verifier.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/src/services/solidity_verifier.rs @@ -11,14 +11,24 @@ use async_trait::async_trait; use eth_bytecode_db::verification::{ compiler_versions, solidity_multi_part, solidity_standard_json, Client, VerificationRequest, }; +use std::collections::HashSet; pub struct SolidityVerifierService { client: Client, + authorized_keys: HashSet, } impl SolidityVerifierService { pub fn new(client: Client) -> Self { - Self { client } + Self { + client, + authorized_keys: Default::default(), + } + } + + pub fn with_authorized_keys(mut self, authorized_keys: HashSet) -> Self { + self.authorized_keys = authorized_keys; + self } } @@ -28,7 +38,7 @@ impl solidity_verifier_server::SolidityVerifier for SolidityVerifierService { &self, request: tonic::Request, ) -> Result, tonic::Status> { - let request = request.into_inner(); + let (metadata, _, request) = request.into_parts(); let bytecode_type = request.bytecode_type(); let verification_request = VerificationRequest { @@ -45,6 +55,7 @@ impl solidity_verifier_server::SolidityVerifier for SolidityVerifierService { .metadata .map(|metadata| VerificationMetadataWrapper::from_inner(metadata).try_into()) .transpose()?, + is_authorized: super::is_key_authorized(&self.authorized_keys, metadata)?, }; let result = solidity_multi_part::verify(self.client.clone(), verification_request).await; @@ -55,7 +66,7 @@ impl solidity_verifier_server::SolidityVerifier for SolidityVerifierService { &self, request: tonic::Request, ) -> Result, tonic::Status> { - let request = request.into_inner(); + let (metadata, _, request) = request.into_parts(); let bytecode_type = request.bytecode_type(); let verification_request = VerificationRequest { @@ -69,6 +80,7 @@ impl solidity_verifier_server::SolidityVerifier for SolidityVerifierService { .metadata .map(|metadata| VerificationMetadataWrapper::from_inner(metadata).try_into()) .transpose()?, + is_authorized: super::is_key_authorized(&self.authorized_keys, metadata)?, }; let result = solidity_standard_json::verify(self.client.clone(), verification_request).await; diff --git a/eth-bytecode-db/eth-bytecode-db-server/src/services/vyper_verifier.rs b/eth-bytecode-db/eth-bytecode-db-server/src/services/vyper_verifier.rs index db2430c74..0bc4d3560 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/src/services/vyper_verifier.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/src/services/vyper_verifier.rs @@ -11,14 +11,24 @@ use async_trait::async_trait; use eth_bytecode_db::verification::{ compiler_versions, vyper_multi_part, vyper_standard_json, Client, VerificationRequest, }; +use std::collections::HashSet; pub struct VyperVerifierService { client: Client, + authorized_keys: HashSet, } impl VyperVerifierService { pub fn new(client: Client) -> Self { - Self { client } + Self { + client, + authorized_keys: Default::default(), + } + } + + pub fn with_authorized_keys(mut self, authorized_keys: HashSet) -> Self { + self.authorized_keys = authorized_keys; + self } } @@ -28,7 +38,7 @@ impl vyper_verifier_server::VyperVerifier for VyperVerifierService { &self, request: tonic::Request, ) -> Result, tonic::Status> { - let request = request.into_inner(); + let (metadata, _, request) = request.into_parts(); let bytecode_type = request.bytecode_type(); let verification_request = VerificationRequest { @@ -44,6 +54,7 @@ impl vyper_verifier_server::VyperVerifier for VyperVerifierService { .metadata .map(|metadata| VerificationMetadataWrapper::from_inner(metadata).try_into()) .transpose()?, + is_authorized: super::is_key_authorized(&self.authorized_keys, metadata)?, }; let result = vyper_multi_part::verify(self.client.clone(), verification_request).await; @@ -54,7 +65,7 @@ impl vyper_verifier_server::VyperVerifier for VyperVerifierService { &self, request: tonic::Request, ) -> Result, tonic::Status> { - let request = request.into_inner(); + let (metadata, _, request) = request.into_parts(); let bytecode_type = request.bytecode_type(); let verification_request = VerificationRequest { @@ -68,6 +79,7 @@ impl vyper_verifier_server::VyperVerifier for VyperVerifierService { .metadata .map(|metadata| VerificationMetadataWrapper::from_inner(metadata).try_into()) .transpose()?, + is_authorized: super::is_key_authorized(&self.authorized_keys, metadata)?, }; let result = vyper_standard_json::verify(self.client.clone(), verification_request).await; diff --git a/eth-bytecode-db/eth-bytecode-db-server/src/settings.rs b/eth-bytecode-db/eth-bytecode-db-server/src/settings.rs index 295e62eac..56ec91f11 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/src/settings.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/src/settings.rs @@ -5,6 +5,7 @@ use blockscout_service_launcher::{ use config::{Config, File}; use serde::{de, Deserialize}; use serde_with::{serde_as, DisplayFromStr}; +use std::collections::HashMap; /// Wrapper under [`serde::de::IgnoredAny`] which implements /// [`PartialEq`] and [`Eq`] for fields to be ignored. @@ -36,6 +37,11 @@ pub struct Settings { pub verifier: VerifierSettings, #[serde(default)] pub sourcify: SourcifySettings, + #[serde(default)] + pub verifier_alliance_database: VerifierAllianceDatabaseSettings, + + #[serde(default)] + pub authorized_keys: HashMap, // Is required as we deny unknown fields, but allow users provide // path to config through PREFIX__CONFIG env variable. If removed, @@ -79,6 +85,19 @@ impl Default for SourcifySettings { } } +#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)] +#[serde(default, deny_unknown_fields)] +pub struct VerifierAllianceDatabaseSettings { + pub enabled: bool, + pub url: String, +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq)] +#[serde(deny_unknown_fields)] +pub struct ApiKey { + pub key: String, +} + impl Settings { pub fn new() -> anyhow::Result { let config_path = std::env::var("ETH_BYTECODE_DB__CONFIG"); @@ -109,6 +128,8 @@ impl Settings { }, verifier: VerifierSettings { uri: verifier_uri }, sourcify: Default::default(), + verifier_alliance_database: Default::default(), + authorized_keys: Default::default(), config_path: Default::default(), } } diff --git a/eth-bytecode-db/eth-bytecode-db-server/src/types/verification_metadata.rs b/eth-bytecode-db/eth-bytecode-db-server/src/types/verification_metadata.rs index c5cb3e8cd..86c4337fb 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/src/types/verification_metadata.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/src/types/verification_metadata.rs @@ -13,52 +13,87 @@ impl TryFrom for verification::VerificationMetadata fn try_from(value: VerificationMetadataWrapper) -> Result { let value = value.0; - let chain_id = if let Some(chain_id) = &value.chain_id { - Some( - i64::from_str(chain_id) - .map_err(|_err| tonic::Status::invalid_argument("Invalid metadata.chain_id"))?, - ) - } else { - None - }; - - let contract_address = if let Some(contract_address) = &value.contract_address { - Some( - DisplayBytes::from_str(contract_address) - .map_err(|_err| tonic::Status::invalid_argument("Invalid contract address"))? - .0, - ) - } else { - None - }; + let chain_id = from_optional_string(value.chain_id, "metadata.chain_id")?; + let contract_address = from_optional_string::( + value.contract_address, + "metadata.contract_address", + )? + .map(|v| v.0); + let transaction_hash = from_optional_string::( + value.transaction_hash, + "metadata.transaction_hash", + )? + .map(|v| v.0); + let deployer = + from_optional_string::(value.deployer, "metadata.deployer")?.map(|v| v.0); + let creation_code = + from_optional_string::(value.creation_code, "metadata.creation_code")? + .map(|v| v.0); + let runtime_code = + from_optional_string::(value.runtime_code, "metadata.runtime_code")? + .map(|v| v.0); Ok(verification::VerificationMetadata { chain_id, contract_address, - transaction_hash: None, + transaction_hash, + block_number: value.block_number, + transaction_index: value.transaction_index, + deployer, + creation_code, + runtime_code, }) } } +fn from_optional_string( + value: Option, + arg_name: &str, +) -> Result, tonic::Status> { + value + .map(|v| { + T::from_str(&v) + .map_err(|_err| tonic::Status::invalid_argument(format!("Invalid {arg_name}"))) + }) + .transpose() +} + #[cfg(test)] mod tests { use super::*; #[test] fn from_proto_to_verification_metadata() { + let bytes_from_str = |s: &str| DisplayBytes::from_str(s).unwrap().0; + let proto_type = proto::VerificationMetadata { chain_id: Some("1".into()), contract_address: Some("0xcafecafecafecafecafecafecafecafecafecafe".into()), + transaction_hash: Some( + "0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f".into(), + ), + block_number: Some(1), + transaction_index: Some(1), + deployer: Some("0x000102030405060708090a0b0c0d0e0f10111213".into()), + creation_code: Some("0xcafecafecafecafe1234567890abcdef".into()), + runtime_code: Some("0x1234567890abcdef".into()), }; let expected = verification::VerificationMetadata { chain_id: Some(1), - contract_address: Some( - DisplayBytes::from_str("0xcafecafecafecafecafecafecafecafecafecafe") + contract_address: Some(bytes_from_str("0xcafecafecafecafecafecafecafecafecafecafe")), + transaction_hash: Some(bytes_from_str( + "0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", + )), + block_number: Some(1), + transaction_index: Some(1), + deployer: Some( + DisplayBytes::from_str("0x000102030405060708090a0b0c0d0e0f10111213") .unwrap() .0, ), - transaction_hash: None, + creation_code: Some(bytes_from_str("0xcafecafecafecafe1234567890abcdef")), + runtime_code: Some(bytes_from_str("0x1234567890abcdef")), }; let wrapper: VerificationMetadataWrapper = proto_type.into(); diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/constructor_arguments.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/constructor_arguments.json new file mode 100644 index 000000000..edc00665f --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/constructor_arguments.json @@ -0,0 +1,72 @@ +{ + "deployed_creation_code": "0x608060405234801561001057600080fd5b506040516101e93803806101e98339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b610133806100b66000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea2646970667358221220dd712ec4cb31d63cd32d3152e52e890b087769e9e4d6746844608039b5015d6a64736f6c634300081200330000000000000000000000000000000000000000000000000000000000003039", + "deployed_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea2646970667358221220dd712ec4cb31d63cd32d3152e52e890b087769e9e4d6746844608039b5015d6a64736f6c63430008120033", + + "compiled_creation_code": "0x608060405234801561001057600080fd5b506040516101e93803806101e98339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b610133806100b66000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea2646970667358221220dd712ec4cb31d63cd32d3152e52e890b087769e9e4d6746844608039b5015d6a64736f6c63430008120033", + "compiled_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea2646970667358221220dd712ec4cb31d63cd32d3152e52e890b087769e9e4d6746844608039b5015d6a64736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n constructor(uint256 num) {\n number = num;\n }\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":4,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "141:262:0:-:0;;;192:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;236:3;227:6;:12;;;;192:54;141:262;;88:117:1;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:143::-;602:5;633:6;627:13;618:22;;649:33;676:5;649:33;:::i;:::-;545:143;;;;:::o;694:351::-;764:6;813:2;801:9;792:7;788:23;784:32;781:119;;;819:79;;:::i;:::-;781:119;939:1;964:64;1020:7;1011:6;1000:9;996:22;964:64;:::i;:::-;954:74;;910:128;694:351;;;;:::o;141:262:0:-;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 436, + "value": "0xa2646970667358221220dd712ec4cb31d63cd32d3152e52e890b087769e9e4d6746844608039b5015d6a64736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {}, + "sourceMap": "141:262:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;337:64;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;164:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;337:64;391:3;382:6;:12;;;;337:64;:::o;164:21::-;;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 254, + "value": "0xa2646970667358221220dd712ec4cb31d63cd32d3152e52e890b087769e9e4d6746844608039b5015d6a64736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": { + "constructorArguments": "0x0000000000000000000000000000000000000000000000000000000000003039" + }, + "creation_transformations": [ + { + "type": "insert", + "reason": "constructor", + "offset": 489 + } + ], + + "runtime_match": true, + "runtime_values": {}, + "runtime_transformations": [] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/full_match.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/full_match.json new file mode 100644 index 000000000..db2349a08 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/full_match.json @@ -0,0 +1,64 @@ +{ + "deployed_creation_code": "0x608060405234801561001057600080fd5b50610133806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033", + "deployed_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033", + + "compiled_creation_code": "0x608060405234801561001057600080fd5b50610133806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033", + "compiled_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":4,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "141:202:0:-:0;;;;;;;;;;;;;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 286, + "value": "0xa26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {}, + "sourceMap": "141:202:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;277:64;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;164:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;277:64;331:3;322:6;:12;;;;277:64;:::o;164:21::-;;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 254, + "value": "0xa26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": {}, + "creation_transformations": [], + + "runtime_match": true, + "runtime_values": {}, + "runtime_transformations": [] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/immutables.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/immutables.json new file mode 100644 index 000000000..812c9b735 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/immutables.json @@ -0,0 +1,75 @@ +{ + "deployed_creation_code": "0x60a0604052606460809081525034801561001857600080fd5b5060805161019a610033600039600060b0015261019a6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a146100625780639fe44c4a14610080575b600080fd5b610060600480360381019061005b919061010d565b61009e565b005b61006a6100a8565b6040516100779190610149565b60405180910390f35b6100886100ae565b6040516100959190610149565b60405180910390f35b8060008190555050565b60005481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600080fd5b6000819050919050565b6100ea816100d7565b81146100f557600080fd5b50565b600081359050610107816100e1565b92915050565b600060208284031215610123576101226100d2565b5b6000610131848285016100f8565b91505092915050565b610143816100d7565b82525050565b600060208201905061015e600083018461013a565b9291505056fea26469706673582212205fff17b2676425e48225435ac15579ccae1af038ff8ffb334fc372526b94722664736f6c63430008120033", + "deployed_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a146100625780639fe44c4a14610080575b600080fd5b610060600480360381019061005b919061010d565b61009e565b005b61006a6100a8565b6040516100779190610149565b60405180910390f35b6100886100ae565b6040516100959190610149565b60405180910390f35b8060008190555050565b60005481565b7f000000000000000000000000000000000000000000000000000000000000006481565b600080fd5b6000819050919050565b6100ea816100d7565b81146100f557600080fd5b50565b600081359050610107816100e1565b92915050565b600060208284031215610123576101226100d2565b5b6000610131848285016100f8565b91505092915050565b610143816100d7565b82525050565b600060208201905061015e600083018461013a565b9291505056fea26469706673582212205fff17b2676425e48225435ac15579ccae1af038ff8ffb334fc372526b94722664736f6c63430008120033", + + "compiled_creation_code": "0x60a0604052606460809081525034801561001857600080fd5b5060805161019a610033600039600060b0015261019a6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a146100625780639fe44c4a14610080575b600080fd5b610060600480360381019061005b919061010d565b61009e565b005b61006a6100a8565b6040516100779190610149565b60405180910390f35b6100886100ae565b6040516100959190610149565b60405180910390f35b8060008190555050565b60005481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600080fd5b6000819050919050565b6100ea816100d7565b81146100f557600080fd5b50565b600081359050610107816100e1565b92915050565b600060208284031215610123576101226100d2565b5b6000610131848285016100f8565b91505092915050565b610143816100d7565b82525050565b600060208201905061015e600083018461013a565b9291505056fea26469706673582212205fff17b2676425e48225435ac15579ccae1af038ff8ffb334fc372526b94722664736f6c63430008120033", + "compiled_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a146100625780639fe44c4a14610080575b600080fd5b610060600480360381019061005b919061010d565b61009e565b005b61006a6100a8565b6040516100779190610149565b60405180910390f35b6100886100ae565b6040516100959190610149565b60405180910390f35b8060008190555050565b60005481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600080fd5b6000819050919050565b6100ea816100d7565b81146100f557600080fd5b50565b600081359050610107816100e1565b92915050565b600060208284031215610123576101226100d2565b5b6000610131848285016100f8565b91505092915050565b610143816100d7565b82525050565b600060208201905061015e600083018461013a565b9291505056fea26469706673582212205fff17b2676425e48225435ac15579ccae1af038ff8ffb334fc372526b94722664736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n uint256 public immutable imm_number = 100;\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[],"name":"imm_number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":4,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "141:250:0:-:0;;;230:3;192:41;;;;;141:250;;;;;;;;;;;;;;;;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 408, + "value": "0xa26469706673582212205fff17b2676425e48225435ac15579ccae1af038ff8ffb334fc372526b94722664736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {"7":[{"length":32,"start":176}]}, + "linkReferences": {}, + "sourceMap": "141:250:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;325:64;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;164:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;325:64;379:3;370:6;:12;;;;325:64;:::o;164:21::-;;;;:::o;192:41::-;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 357, + "value": "0xa26469706673582212205fff17b2676425e48225435ac15579ccae1af038ff8ffb334fc372526b94722664736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": {}, + "creation_transformations": [], + + "runtime_match": true, + "runtime_values": { + "immutables": { + "7": "0x0000000000000000000000000000000000000000000000000000000000000064" + } + }, + "runtime_transformations": [ + { + "type": "replace", + "reason": "immutable", + "offset": 176, + "id": "7" + } + ] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_linked_by_compiler.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_linked_by_compiler.json new file mode 100644 index 000000000..67b4c9938 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_linked_by_compiler.json @@ -0,0 +1,70 @@ +{ + "_comment": "Libraries have been linked using compiler settings. The placeholders are already replaced inside the compiled bytecode, and no link references provided", + + "deployed_creation_code": "0x608060405234801561001057600080fd5b50610249806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550737d53f102f4d4aa014db4e10d6deec2009b3cda6b632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea2646970667358221220a89051eba557a7a71a7afa4c5011918b95b51d314ed350221cb7a2f34703340364736f6c63430008120033", + "deployed_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550737d53f102f4d4aa014db4e10d6deec2009b3cda6b632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea2646970667358221220a89051eba557a7a71a7afa4c5011918b95b51d314ed350221cb7a2f34703340364736f6c63430008120033", + + "compiled_creation_code": "0x608060405234801561001057600080fd5b50610249806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550737d53f102f4d4aa014db4e10d6deec2009b3cda6b632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea2646970667358221220a89051eba557a7a71a7afa4c5011918b95b51d314ed350221cb7a2f34703340364736f6c63430008120033", + "compiled_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550737d53f102f4d4aa014db4e10d6deec2009b3cda6b632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea2646970667358221220a89051eba557a7a71a7afa4c5011918b95b51d314ed350221cb7a2f34703340364736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\nlibrary Journal {\n function record(mapping(uint256 => uint256) storage journal, uint256 num) public {\n journal[block.number] = num;\n }\n}\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n mapping(uint256 => uint256) public journal;\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n Journal.record(journal, num);\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": { + "contracts/1_Storage.sol": { + "Journal": "0x7d53f102f4d4aa014db4e10d6deec2009b3cda6b" + } + }, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"journal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":22,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"},{"astId":26,"contract":"contracts/1_Storage.sol:Storage","label":"journal","offset":0,"slot":"1","type":"t_mapping(t_uint256,t_uint256)"}],"types":{"t_mapping(t_uint256,t_uint256)":{"encoding":"mapping","key":"t_uint256","label":"mapping(uint256 => uint256)","numberOfBytes":"32","value":"t_uint256"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "292:289:0:-:0;;;;;;;;;;;;;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 564, + "value": "0xa2646970667358221220a89051eba557a7a71a7afa4c5011918b95b51d314ed350221cb7a2f34703340364736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {}, + "sourceMap": "292:289:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;477:102;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;315:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;343:42;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;477:102;531:3;522:6;:12;;;;544:7;:14;559:7;568:3;544:28;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;477:102;:::o;315:21::-;;;;:::o;343:42::-;;;;;;;;;;;;;;;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o;1377:132::-;1497:5;1492:3;1485:18;1377:132;;:::o;1515:126::-;1610:24;1628:5;1610:24;:::i;:::-;1605:3;1598:37;1515:126;;:::o;1647:406::-;1801:4;1839:2;1828:9;1824:18;1816:26;;1852:104;1953:1;1942:9;1938:17;1929:6;1852:104;:::i;:::-;1966:80;2042:2;2031:9;2027:18;2018:6;1966:80;:::i;:::-;1647:406;;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 532, + "value": "0xa2646970667358221220a89051eba557a7a71a7afa4c5011918b95b51d314ed350221cb7a2f34703340364736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": {}, + "creation_transformations": [], + + "runtime_match": true, + "runtime_values": {}, + "runtime_transformations": [] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_manually_linked.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_manually_linked.json new file mode 100644 index 000000000..3de58811d --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/libraries_manually_linked.json @@ -0,0 +1,88 @@ +{ + "_comment": "Libraries have been linked manually instead of using compiler settings. Placeholders are replaced with zero addresses", + + "deployed_creation_code": "0x608060405234801561001057600080fd5b50610249806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550737d53f102f4d4aa014db4e10d6deec2009b3cda6b632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea26469706673582212205d40d1517b560d915e1b7c005887b93fcce9ec65c0a38a80ee147739551bdd7264736f6c63430008120033", + "deployed_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550737d53f102f4d4aa014db4e10d6deec2009b3cda6b632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea26469706673582212205d40d1517b560d915e1b7c005887b93fcce9ec65c0a38a80ee147739551bdd7264736f6c63430008120033", + + "compiled_creation_code": "0x608060405234801561001057600080fd5b50610249806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550730000000000000000000000000000000000000000632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea26469706673582212205d40d1517b560d915e1b7c005887b93fcce9ec65c0a38a80ee147739551bdd7264736f6c63430008120033", + "compiled_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636057361d146100465780638381f58a14610062578063e2e2a85a14610080575b600080fd5b610060600480360381019061005b919061017d565b6100b0565b005b61006a610124565b60405161007791906101b9565b60405180910390f35b61009a6004803603810190610095919061017d565b61012a565b6040516100a791906101b9565b60405180910390f35b80600081905550730000000000000000000000000000000000000000632be59dd56001836040518363ffffffff1660e01b81526004016100f19291906101ea565b60006040518083038186803b15801561010957600080fd5b505af415801561011d573d6000803e3d6000fd5b5050505050565b60005481565b60016020528060005260406000206000915090505481565b600080fd5b6000819050919050565b61015a81610147565b811461016557600080fd5b50565b60008135905061017781610151565b92915050565b60006020828403121561019357610192610142565b5b60006101a184828501610168565b91505092915050565b6101b381610147565b82525050565b60006020820190506101ce60008301846101aa565b92915050565b8082525050565b6101e481610147565b82525050565b60006040820190506101ff60008301856101d4565b61020c60208301846101db565b939250505056fea26469706673582212205d40d1517b560d915e1b7c005887b93fcce9ec65c0a38a80ee147739551bdd7264736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\nlibrary Journal {\n function record(mapping(uint256 => uint256) storage journal, uint256 num) public {\n journal[block.number] = num;\n }\n}\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n mapping(uint256 => uint256) public journal;\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n Journal.record(journal, num);\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"journal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":22,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"},{"astId":26,"contract":"contracts/1_Storage.sol:Storage","label":"journal","offset":0,"slot":"1","type":"t_mapping(t_uint256,t_uint256)"}],"types":{"t_mapping(t_uint256,t_uint256)":{"encoding":"mapping","key":"t_uint256","label":"mapping(uint256 => uint256)","numberOfBytes":"32","value":"t_uint256"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {"contracts/1_Storage.sol":{"Journal":[{"length":20,"start":217}]}}, + "sourceMap": "292:289:0:-:0;;;;;;;;;;;;;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 564, + "value": "0xa26469706673582212205d40d1517b560d915e1b7c005887b93fcce9ec65c0a38a80ee147739551bdd7264736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {"contracts/1_Storage.sol":{"Journal":[{"length":20,"start":185}]}}, + "sourceMap": "292:289:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;477:102;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;315:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;343:42;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;477:102;531:3;522:6;:12;;;;544:7;:14;559:7;568:3;544:28;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;477:102;:::o;315:21::-;;;;:::o;343:42::-;;;;;;;;;;;;;;;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o;1377:132::-;1497:5;1492:3;1485:18;1377:132;;:::o;1515:126::-;1610:24;1628:5;1610:24;:::i;:::-;1605:3;1598:37;1515:126;;:::o;1647:406::-;1801:4;1839:2;1828:9;1824:18;1816:26;;1852:104;1953:1;1942:9;1938:17;1929:6;1852:104;:::i;:::-;1966:80;2042:2;2031:9;2027:18;2018:6;1966:80;:::i;:::-;1647:406;;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 532, + "value": "0xa26469706673582212205d40d1517b560d915e1b7c005887b93fcce9ec65c0a38a80ee147739551bdd7264736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": { + "libraries": { + "contracts/1_Storage.sol:Journal": "0x7d53f102f4d4aa014db4e10d6deec2009b3cda6b" + } + }, + "creation_transformations": [ + { + "type": "replace", + "reason": "library", + "offset": 217, + "id": "contracts/1_Storage.sol:Journal" + } + ], + + "runtime_match": true, + "runtime_values": { + "libraries": { + "contracts/1_Storage.sol:Journal": "0x7d53f102f4d4aa014db4e10d6deec2009b3cda6b" + } + }, + "runtime_transformations": [ + { + "type": "replace", + "reason": "library", + "offset": 185, + "id": "contracts/1_Storage.sol:Journal" + } + ] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/metadata_hash_absent.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/metadata_hash_absent.json new file mode 100644 index 000000000..0c0e5a6e6 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/metadata_hash_absent.json @@ -0,0 +1,67 @@ +{ + "deployed_creation_code": "0x608060405234801561001057600080fd5b5061010a806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea164736f6c6343000812000a", + "deployed_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea164736f6c6343000812000a", + + "compiled_creation_code": "0x608060405234801561001057600080fd5b5061010a806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea164736f6c6343000812000a", + "compiled_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea164736f6c6343000812000a", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "metadata": { + "bytecodeHash": "none" + }, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":4,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "141:202:0:-:0;;;;;;;;;;;;;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 286, + "value": "0xa164736f6c6343000812000a" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {}, + "sourceMap": "141:202:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;277:64;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;164:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;277:64;331:3;322:6;:12;;;;277:64;:::o;164:21::-;;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 254, + "value": "0xa164736f6c6343000812000a" + } + } + }, + + "creation_match": true, + "creation_values": {}, + "creation_transformations": [], + + "runtime_match": true, + "runtime_values": {}, + "runtime_transformations": [] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match.json new file mode 100644 index 000000000..9f1f37833 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match.json @@ -0,0 +1,88 @@ +{ + "_comment": "Argument `store.num` has been updated to `store.modified_num` to change the metadata hash", + + "deployed_creation_code": "0x608060405234801561001057600080fd5b50610133806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033", + "deployed_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033", + + "compiled_creation_code": "0x608060405234801561001057600080fd5b50610133806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212203863ce629eb61798cd34ba5d73d729ef1f86d2529ee1bdfc20e7eda860c4260564736f6c63430008120033", + "compiled_runtime_code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d1460375780638381f58a14604f575b600080fd5b604d60048036038101906049919060af565b6069565b005b60556073565b6040516060919060e4565b60405180910390f35b8060008190555050565b60005481565b600080fd5b6000819050919050565b608f81607e565b8114609957600080fd5b50565b60008135905060a9816088565b92915050565b60006020828403121560c25760c16079565b5b600060ce84828501609c565b91505092915050565b60de81607e565b82525050565b600060208201905060f7600083018460d7565b9291505056fea26469706673582212203863ce629eb61798cd34ba5d73d729ef1f86d2529ee1bdfc20e7eda860c4260564736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n /**\n * @dev Store value in variable\n * @param modified_num value to store\n */\n function store(uint256 modified_num) public {\n number = modified_num;\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"modified_num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"modified_num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":4,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "141:229:0:-:0;;;;;;;;;;;;;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 286, + "value": "0xa26469706673582212203863ce629eb61798cd34ba5d73d729ef1f86d2529ee1bdfc20e7eda860c4260564736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {}, + "sourceMap": "141:229:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;286:82;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;164:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;286:82;349:12;340:6;:21;;;;286:82;:::o;164:21::-;;;;:::o;88:117:1:-;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:118::-;1112:24;1130:5;1112:24;:::i;:::-;1107:3;1100:37;1025:118;;:::o;1149:222::-;1242:4;1280:2;1269:9;1265:18;1257:26;;1293:71;1361:1;1350:9;1346:17;1337:6;1293:71;:::i;:::-;1149:222;;;;:::o", + "cborAuxdata": { + "1": { + "offset": 254, + "value": "0xa26469706673582212203863ce629eb61798cd34ba5d73d729ef1f86d2529ee1bdfc20e7eda860c4260564736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": { + "cborAuxdata": { + "1": "0xa26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033" + } + }, + "creation_transformations": [ + { + "type": "replace", + "reason": "auxdata", + "offset": 286, + "id": "1" + } + ], + + "runtime_match": true, + "runtime_values": { + "cborAuxdata": { + "1": "0xa26469706673582212204ac0ce5f82b26331fa3e9ae959291a55624ffaf90fcd509deafcc21a5f1da21e64736f6c63430008120033" + } + }, + "runtime_transformations": [ + { + "type": "replace", + "reason": "auxdata", + "offset": 254, + "id": "1" + } + ] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match_double_auxdata.json b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match_double_auxdata.json new file mode 100644 index 000000000..ec64cd3d4 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/alliance_test_cases/partial_match_double_auxdata.json @@ -0,0 +1,97 @@ +{ + "deployed_creation_code": "0x60806040526040518060200161001490610049565b6020820181038252601f19601f820116604052506001908161003691906102a5565b5034801561004357600080fd5b50610377565b605c8061069c83390190565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806100d657607f821691505b6020821081036100e9576100e861008f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610114565b61015b8683610114565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006101a261019d61019884610173565b61017d565b610173565b9050919050565b6000819050919050565b6101bc83610187565b6101d06101c8826101a9565b848454610121565b825550505050565b600090565b6101e56101d8565b6101f08184846101b3565b505050565b5b81811015610214576102096000826101dd565b6001810190506101f6565b5050565b601f8211156102595761022a816100ef565b61023384610104565b81016020851015610242578190505b61025661024e85610104565b8301826101f5565b50505b505050565b600082821c905092915050565b600061027c6000198460080261025e565b1980831691505092915050565b6000610295838361026b565b9150826002028217905092915050565b6102ae82610055565b67ffffffffffffffff8111156102c7576102c6610060565b5b6102d182546100be565b6102dc828285610218565b600060209050601f83116001811461030f57600084156102fd578287015190505b6103078582610289565b86555061036f565b601f19841661031d866100ef565b60005b8281101561034557848901518255600182019150602085019450602081019050610320565b86831015610362578489015161035e601f89168261026b565b8355505b6001600288020188555050505b505050505050565b610316806103866000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806324c12bf6146100465780636057361d146100645780638381f58a14610080575b600080fd5b61004e61009e565b60405161005b91906101cc565b60405180910390f35b61007e60048036038101906100799190610229565b61012c565b005b610088610136565b6040516100959190610265565b60405180910390f35b600180546100ab906102af565b80601f01602080910402602001604051908101604052809291908181526020018280546100d7906102af565b80156101245780601f106100f957610100808354040283529160200191610124565b820191906000526020600020905b81548152906001019060200180831161010757829003601f168201915b505050505081565b8060008190555050565b60005481565b600081519050919050565b600082825260208201905092915050565b60005b8381101561017657808201518184015260208101905061015b565b60008484015250505050565b6000601f19601f8301169050919050565b600061019e8261013c565b6101a88185610147565b93506101b8818560208601610158565b6101c181610182565b840191505092915050565b600060208201905081810360008301526101e68184610193565b905092915050565b600080fd5b6000819050919050565b610206816101f3565b811461021157600080fd5b50565b600081359050610223816101fd565b92915050565b60006020828403121561023f5761023e6101ee565b5b600061024d84828501610214565b91505092915050565b61025f816101f3565b82525050565b600060208201905061027a6000830184610256565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806102c757607f821691505b6020821081036102da576102d9610280565b5b5091905056fea2646970667358221220bc2c6d72c52842d4077bb24c307576e44a078831aaa16da6611ef342fd052ec764736f6c634300081200336080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220f13d144a826a3f18798a534a4b10029a3284d9f4620ccc79750cdc48442cdaad64736f6c63430008120033", + "deployed_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806324c12bf6146100465780636057361d146100645780638381f58a14610080575b600080fd5b61004e61009e565b60405161005b91906101cc565b60405180910390f35b61007e60048036038101906100799190610229565b61012c565b005b610088610136565b6040516100959190610265565b60405180910390f35b600180546100ab906102af565b80601f01602080910402602001604051908101604052809291908181526020018280546100d7906102af565b80156101245780601f106100f957610100808354040283529160200191610124565b820191906000526020600020905b81548152906001019060200180831161010757829003601f168201915b505050505081565b8060008190555050565b60005481565b600081519050919050565b600082825260208201905092915050565b60005b8381101561017657808201518184015260208101905061015b565b60008484015250505050565b6000601f19601f8301169050919050565b600061019e8261013c565b6101a88185610147565b93506101b8818560208601610158565b6101c181610182565b840191505092915050565b600060208201905081810360008301526101e68184610193565b905092915050565b600080fd5b6000819050919050565b610206816101f3565b811461021157600080fd5b50565b600081359050610223816101fd565b92915050565b60006020828403121561023f5761023e6101ee565b5b600061024d84828501610214565b91505092915050565b61025f816101f3565b82525050565b600060208201905061027a6000830184610256565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806102c757607f821691505b6020821081036102da576102d9610280565b5b5091905056fea2646970667358221220bc2c6d72c52842d4077bb24c307576e44a078831aaa16da6611ef342fd052ec764736f6c63430008120033", + + "compiled_creation_code": "0x60806040526040518060200161001490610049565b6020820181038252601f19601f820116604052506001908161003691906102a5565b5034801561004357600080fd5b50610377565b605c8061069c83390190565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806100d657607f821691505b6020821081036100e9576100e861008f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610114565b61015b8683610114565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006101a261019d61019884610173565b61017d565b610173565b9050919050565b6000819050919050565b6101bc83610187565b6101d06101c8826101a9565b848454610121565b825550505050565b600090565b6101e56101d8565b6101f08184846101b3565b505050565b5b81811015610214576102096000826101dd565b6001810190506101f6565b5050565b601f8211156102595761022a816100ef565b61023384610104565b81016020851015610242578190505b61025661024e85610104565b8301826101f5565b50505b505050565b600082821c905092915050565b600061027c6000198460080261025e565b1980831691505092915050565b6000610295838361026b565b9150826002028217905092915050565b6102ae82610055565b67ffffffffffffffff8111156102c7576102c6610060565b5b6102d182546100be565b6102dc828285610218565b600060209050601f83116001811461030f57600084156102fd578287015190505b6103078582610289565b86555061036f565b601f19841661031d866100ef565b60005b8281101561034557848901518255600182019150602085019450602081019050610320565b86831015610362578489015161035e601f89168261026b565b8355505b6001600288020188555050505b505050505050565b610316806103866000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806324c12bf6146100465780636057361d146100645780638381f58a14610080575b600080fd5b61004e61009e565b60405161005b91906101cc565b60405180910390f35b61007e60048036038101906100799190610229565b61012c565b005b610088610136565b6040516100959190610265565b60405180910390f35b600180546100ab906102af565b80601f01602080910402602001604051908101604052809291908181526020018280546100d7906102af565b80156101245780601f106100f957610100808354040283529160200191610124565b820191906000526020600020905b81548152906001019060200180831161010757829003601f168201915b505050505081565b8060008190555050565b60005481565b600081519050919050565b600082825260208201905092915050565b60005b8381101561017657808201518184015260208101905061015b565b60008484015250505050565b6000601f19601f8301169050919050565b600061019e8261013c565b6101a88185610147565b93506101b8818560208601610158565b6101c181610182565b840191505092915050565b600060208201905081810360008301526101e68184610193565b905092915050565b600080fd5b6000819050919050565b610206816101f3565b811461021157600080fd5b50565b600081359050610223816101fd565b92915050565b60006020828403121561023f5761023e6101ee565b5b600061024d84828501610214565b91505092915050565b61025f816101f3565b82525050565b600060208201905061027a6000830184610256565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806102c757607f821691505b6020821081036102da576102d9610280565b5b5091905056fea264697066735822122005d1b64ca59de3c6d96eee72b6fef65fc503bfbf8d9719fb047fafce2ebdc29764736f6c634300081200336080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220aebf48746b808da25305449bba6945baacf1c2185dfcc58a94b1506b8b5a6dfa64736f6c63430008120033", + "compiled_runtime_code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806324c12bf6146100465780636057361d146100645780638381f58a14610080575b600080fd5b61004e61009e565b60405161005b91906101cc565b60405180910390f35b61007e60048036038101906100799190610229565b61012c565b005b610088610136565b6040516100959190610265565b60405180910390f35b600180546100ab906102af565b80601f01602080910402602001604051908101604052809291908181526020018280546100d7906102af565b80156101245780601f106100f957610100808354040283529160200191610124565b820191906000526020600020905b81548152906001019060200180831161010757829003601f168201915b505050505081565b8060008190555050565b60005481565b600081519050919050565b600082825260208201905092915050565b60005b8381101561017657808201518184015260208101905061015b565b60008484015250505050565b6000601f19601f8301169050919050565b600061019e8261013c565b6101a88185610147565b93506101b8818560208601610158565b6101c181610182565b840191505092915050565b600060208201905081810360008301526101e68184610193565b905092915050565b600080fd5b6000819050919050565b610206816101f3565b811461021157600080fd5b50565b600081359050610223816101fd565b92915050565b60006020828403121561023f5761023e6101ee565b5b600061024d84828501610214565b91505092915050565b61025f816101f3565b82525050565b600060208201905061027a6000830184610256565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806102c757607f821691505b6020821081036102da576102d9610280565b5b5091905056fea264697066735822122005d1b64ca59de3c6d96eee72b6fef65fc503bfbf8d9719fb047fafce2ebdc29764736f6c63430008120033", + "compiler": "solc", + "version": "v0.8.18+commit.87f61d96", + "language": "solidity", + "name": "Storage", + "fully_qualified_name": "contracts/1_Storage.sol:Storage", + "sources": { + "contracts/1_Storage.sol": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.7.0 <0.9.0;\n\ncontract A {}\n\n/**\n * @title Storage\n * @dev Store & retrieve value in a variable\n */\ncontract Storage {\n uint256 public number;\n\n // Comment to update metadata hash\n bytes public code = type(A).creationCode;\n\n /**\n * @dev Store value in variable\n * @param num value to store\n */\n function store(uint256 num) public {\n number = num;\n }\n}" + }, + "compiler_settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "libraries": {}, + "outputSelection": { + "*": { + "*": [ + "*" + ] + } + } + }, + "compilation_artifacts": { + "abi": [{"inputs":[],"name":"code","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}], + "devdoc": {"details":"Store & retrieve value in a variable","kind":"dev","methods":{"store(uint256)":{"details":"Store value in variable","params":{"num":"value to store"}}},"title":"Storage","version":1}, + "userdoc": {"kind":"user","methods":{},"version":1}, + "storageLayout": {"storage":[{"astId":5,"contract":"contracts/1_Storage.sol:Storage","label":"number","offset":0,"slot":"0","type":"t_uint256"},{"astId":11,"contract":"contracts/1_Storage.sol:Storage","label":"code","offset":0,"slot":"1","type":"t_bytes_storage"}],"types":{"t_bytes_storage":{"encoding":"bytes","label":"bytes","numberOfBytes":"32"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}} + }, + "creation_code_artifacts": { + "linkReferences": {}, + "sourceMap": "156:288:0:-:0;;;266:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;246:40;;;;;;;:::i;:::-;;156:288;;;;;;;;;;;;;;;;;;;;:::o;7:98:1:-;58:6;92:5;86:12;76:22;;7:98;;;:::o;111:180::-;159:77;156:1;149:88;256:4;253:1;246:15;280:4;277:1;270:15;297:180;345:77;342:1;335:88;442:4;439:1;432:15;466:4;463:1;456:15;483:320;527:6;564:1;558:4;554:12;544:22;;611:1;605:4;601:12;632:18;622:81;;688:4;680:6;676:17;666:27;;622:81;750:2;742:6;739:14;719:18;716:38;713:84;;769:18;;:::i;:::-;713:84;534:269;483:320;;;:::o;809:140::-;857:4;880:3;872:11;;903:3;900:1;893:14;937:4;934:1;924:18;916:26;;809:140;;;:::o;955:93::-;992:6;1039:2;1034;1027:5;1023:14;1019:23;1009:33;;955:93;;;:::o;1054:107::-;1098:8;1148:5;1142:4;1138:16;1117:37;;1054:107;;;;:::o;1167:393::-;1236:6;1286:1;1274:10;1270:18;1309:97;1339:66;1328:9;1309:97;:::i;:::-;1427:39;1457:8;1446:9;1427:39;:::i;:::-;1415:51;;1499:4;1495:9;1488:5;1484:21;1475:30;;1548:4;1538:8;1534:19;1527:5;1524:30;1514:40;;1243:317;;1167:393;;;;;:::o;1566:77::-;1603:7;1632:5;1621:16;;1566:77;;;:::o;1649:60::-;1677:3;1698:5;1691:12;;1649:60;;;:::o;1715:142::-;1765:9;1798:53;1816:34;1825:24;1843:5;1825:24;:::i;:::-;1816:34;:::i;:::-;1798:53;:::i;:::-;1785:66;;1715:142;;;:::o;1863:75::-;1906:3;1927:5;1920:12;;1863:75;;;:::o;1944:269::-;2054:39;2085:7;2054:39;:::i;:::-;2115:91;2164:41;2188:16;2164:41;:::i;:::-;2156:6;2149:4;2143:11;2115:91;:::i;:::-;2109:4;2102:105;2020:193;1944:269;;;:::o;2219:73::-;2264:3;2219:73;:::o;2298:189::-;2375:32;;:::i;:::-;2416:65;2474:6;2466;2460:4;2416:65;:::i;:::-;2351:136;2298:189;;:::o;2493:186::-;2553:120;2570:3;2563:5;2560:14;2553:120;;;2624:39;2661:1;2654:5;2624:39;:::i;:::-;2597:1;2590:5;2586:13;2577:22;;2553:120;;;2493:186;;:::o;2685:541::-;2785:2;2780:3;2777:11;2774:445;;;2819:37;2850:5;2819:37;:::i;:::-;2902:29;2920:10;2902:29;:::i;:::-;2892:8;2888:44;3085:2;3073:10;3070:18;3067:49;;;3106:8;3091:23;;3067:49;3129:80;3185:22;3203:3;3185:22;:::i;:::-;3175:8;3171:37;3158:11;3129:80;:::i;:::-;2789:430;;2774:445;2685:541;;;:::o;3232:117::-;3286:8;3336:5;3330:4;3326:16;3305:37;;3232:117;;;;:::o;3355:169::-;3399:6;3432:51;3480:1;3476:6;3468:5;3465:1;3461:13;3432:51;:::i;:::-;3428:56;3513:4;3507;3503:15;3493:25;;3406:118;3355:169;;;;:::o;3529:295::-;3605:4;3751:29;3776:3;3770:4;3751:29;:::i;:::-;3743:37;;3813:3;3810:1;3806:11;3800:4;3797:21;3789:29;;3529:295;;;;:::o;3829:1390::-;3944:36;3976:3;3944:36;:::i;:::-;4045:18;4037:6;4034:30;4031:56;;;4067:18;;:::i;:::-;4031:56;4111:38;4143:4;4137:11;4111:38;:::i;:::-;4196:66;4255:6;4247;4241:4;4196:66;:::i;:::-;4289:1;4313:4;4300:17;;4345:2;4337:6;4334:14;4362:1;4357:617;;;;5018:1;5035:6;5032:77;;;5084:9;5079:3;5075:19;5069:26;5060:35;;5032:77;5135:67;5195:6;5188:5;5135:67;:::i;:::-;5129:4;5122:81;4991:222;4327:886;;4357:617;4409:4;4405:9;4397:6;4393:22;4443:36;4474:4;4443:36;:::i;:::-;4501:1;4515:208;4529:7;4526:1;4523:14;4515:208;;;4608:9;4603:3;4599:19;4593:26;4585:6;4578:42;4659:1;4651:6;4647:14;4637:24;;4706:2;4695:9;4691:18;4678:31;;4552:4;4549:1;4545:12;4540:17;;4515:208;;;4751:6;4742:7;4739:19;4736:179;;;4809:9;4804:3;4800:19;4794:26;4852:48;4894:4;4886:6;4882:17;4871:9;4852:48;:::i;:::-;4844:6;4837:64;4759:156;4736:179;4961:1;4957;4949:6;4945:14;4941:22;4935:4;4928:36;4364:610;;;4327:886;;3919:1300;;;3829:1390;;:::o;156:288:0:-;;;;;;;", + "cborAuxdata": { + "1": { + "offset": 1639, + "value": "0xa264697066735822122005d1b64ca59de3c6d96eee72b6fef65fc503bfbf8d9719fb047fafce2ebdc29764736f6c63430008120033" + }, + "2": { + "offset": 1731, + "value": "0xa2646970667358221220aebf48746b808da25305449bba6945baacf1c2185dfcc58a94b1506b8b5a6dfa64736f6c63430008120033" + } + } + }, + "runtime_code_artifacts": { + "immutableReferences": {}, + "linkReferences": {}, + "sourceMap": "156:288:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;246:40;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;378:64;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;179:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;246:40;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;378:64::-;432:3;423:6;:12;;;;378:64;:::o;179:21::-;;;;:::o;7:98:1:-;58:6;92:5;86:12;76:22;;7:98;;;:::o;111:168::-;194:11;228:6;223:3;216:19;268:4;263:3;259:14;244:29;;111:168;;;;:::o;285:246::-;366:1;376:113;390:6;387:1;384:13;376:113;;;475:1;470:3;466:11;460:18;456:1;451:3;447:11;440:39;412:2;409:1;405:10;400:15;;376:113;;;523:1;514:6;509:3;505:16;498:27;347:184;285:246;;;:::o;537:102::-;578:6;629:2;625:7;620:2;613:5;609:14;605:28;595:38;;537:102;;;:::o;645:373::-;731:3;759:38;791:5;759:38;:::i;:::-;813:70;876:6;871:3;813:70;:::i;:::-;806:77;;892:65;950:6;945:3;938:4;931:5;927:16;892:65;:::i;:::-;982:29;1004:6;982:29;:::i;:::-;977:3;973:39;966:46;;735:283;645:373;;;;:::o;1024:309::-;1135:4;1173:2;1162:9;1158:18;1150:26;;1222:9;1216:4;1212:20;1208:1;1197:9;1193:17;1186:47;1250:76;1321:4;1312:6;1250:76;:::i;:::-;1242:84;;1024:309;;;;:::o;1420:117::-;1529:1;1526;1519:12;1666:77;1703:7;1732:5;1721:16;;1666:77;;;:::o;1749:122::-;1822:24;1840:5;1822:24;:::i;:::-;1815:5;1812:35;1802:63;;1861:1;1858;1851:12;1802:63;1749:122;:::o;1877:139::-;1923:5;1961:6;1948:20;1939:29;;1977:33;2004:5;1977:33;:::i;:::-;1877:139;;;;:::o;2022:329::-;2081:6;2130:2;2118:9;2109:7;2105:23;2101:32;2098:119;;;2136:79;;:::i;:::-;2098:119;2256:1;2281:53;2326:7;2317:6;2306:9;2302:22;2281:53;:::i;:::-;2271:63;;2227:117;2022:329;;;;:::o;2357:118::-;2444:24;2462:5;2444:24;:::i;:::-;2439:3;2432:37;2357:118;;:::o;2481:222::-;2574:4;2612:2;2601:9;2597:18;2589:26;;2625:71;2693:1;2682:9;2678:17;2669:6;2625:71;:::i;:::-;2481:222;;;;:::o;2709:180::-;2757:77;2754:1;2747:88;2854:4;2851:1;2844:15;2878:4;2875:1;2868:15;2895:320;2939:6;2976:1;2970:4;2966:12;2956:22;;3023:1;3017:4;3013:12;3044:18;3034:81;;3100:4;3092:6;3088:17;3078:27;;3034:81;3162:2;3154:6;3151:14;3131:18;3128:38;3125:84;;3181:18;;:::i;:::-;3125:84;2946:269;2895:320;;;:::o", + "cborAuxdata": { + "1": { + "offset": 737, + "value": "0xa264697066735822122005d1b64ca59de3c6d96eee72b6fef65fc503bfbf8d9719fb047fafce2ebdc29764736f6c63430008120033" + } + } + }, + + "creation_match": true, + "creation_values": { + "cborAuxdata": { + "1": "0xa2646970667358221220bc2c6d72c52842d4077bb24c307576e44a078831aaa16da6611ef342fd052ec764736f6c63430008120033", + "2": "0xa2646970667358221220f13d144a826a3f18798a534a4b10029a3284d9f4620ccc79750cdc48442cdaad64736f6c63430008120033" + } + }, + "creation_transformations": [ + { + "type": "replace", + "reason": "auxdata", + "offset": 1639, + "id": "1" + }, + { + "type": "replace", + "reason": "auxdata", + "offset": 1731, + "id": "2" + } + ], + + "runtime_match": true, + "runtime_values": { + "cborAuxdata": { + "1": "0xa2646970667358221220bc2c6d72c52842d4077bb24c307576e44a078831aaa16da6611ef342fd052ec764736f6c63430008120033" + } + }, + "runtime_transformations": [ + { + "type": "replace", + "reason": "auxdata", + "offset": 737, + "id": "1" + } + ] +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/database_helpers.rs b/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/database_helpers.rs index 0fc4507eb..257df1ea3 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/database_helpers.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/database_helpers.rs @@ -11,7 +11,7 @@ pub struct TestDbGuard { } impl TestDbGuard { - pub async fn new(db_name: &str, db_url: Option) -> Self { + pub async fn new(db_name: &str, db_url: Option) -> Self { let db_url = db_url.unwrap_or_else(|| { std::env::var("DATABASE_URL").expect( "Database url should either be provided explicitly, or \ @@ -19,8 +19,30 @@ impl TestDbGuard { ) }); + // We use a hash, as the name itself may be quite long and be trimmed. + let db_name = format!("_{:x}", keccak_hash::keccak(db_name)); + let (db_url, conn_with_db) = Self::init_database::(&db_url, &db_name).await; + + TestDbGuard { + conn_with_db: Arc::new(conn_with_db), + db_url, + } + } + + pub fn client(&self) -> Arc { + self.conn_with_db.clone() + } + + pub fn db_url(&self) -> &str { + &self.db_url + } + + async fn init_database( + base_db_url: &str, + db_name: &str, + ) -> (String, DatabaseConnection) { // Create database - let conn_without_db = Database::connect(&db_url) + let conn_without_db = Database::connect(base_db_url) .await .expect("Connection to postgres (without database) failed"); Self::drop_database(&conn_without_db, db_name) @@ -31,26 +53,15 @@ impl TestDbGuard { .expect("Database creation failed"); // Migrate database - let db_url = format!("{db_url}/{db_name}"); + let db_url = format!("{base_db_url}/{db_name}"); let conn_with_db = Database::connect(&db_url) .await .expect("Connection to postgres (with database) failed"); - Self::run_migrations(&conn_with_db) + Self::run_migrations::(&conn_with_db) .await .expect("Database migration failed"); - TestDbGuard { - conn_with_db: Arc::new(conn_with_db), - db_url, - } - } - - pub fn client(&self) -> Arc { - self.conn_with_db.clone() - } - - pub fn db_url(&self) -> &str { - &self.db_url + (db_url, conn_with_db) } async fn create_database(db: &DatabaseConnection, db_name: &str) -> Result<(), DbErr> { @@ -73,7 +84,7 @@ impl TestDbGuard { Ok(()) } - async fn run_migrations(db: &DatabaseConnection) -> Result<(), DbErr> { - ::up(db, None).await + async fn run_migrations(db: &DatabaseConnection) -> Result<(), DbErr> { + Migrator::up(db, None).await } } diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/mod.rs b/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/mod.rs index 7408799a4..9559f245a 100644 --- a/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/mod.rs +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/mod.rs @@ -5,15 +5,19 @@ mod database_helpers; pub mod smart_contract_verifer_mock; pub mod test_input_data; +pub mod verifier_alliance_types; + +pub use database_helpers::TestDbGuard; + use async_trait::async_trait; -use database_helpers::TestDbGuard; use eth_bytecode_db::verification::SourceType; use eth_bytecode_db_proto::blockscout::eth_bytecode_db::v2 as eth_bytecode_db_v2; use eth_bytecode_db_server::Settings; +use migration::MigratorTrait; use reqwest::Url; use smart_contract_verifer_mock::SmartContractVerifierServer; use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2 as smart_contract_verifier_v2; -use std::{net::SocketAddr, str::FromStr}; +use std::{collections::HashMap, net::SocketAddr, str::FromStr}; use tonic::transport::Uri; const DB_PREFIX: &str = "server"; @@ -28,12 +32,24 @@ pub trait VerifierService { } pub async fn init_db(test_suite_name: &str, test_name: &str) -> TestDbGuard { + init_db_raw::(test_suite_name, test_name).await +} + +pub async fn init_alliance_db(test_suite_name: &str, test_name: &str) -> TestDbGuard { + let test_name = format!("{test_name}_alliance"); + init_db_raw::(test_suite_name, &test_name).await +} + +async fn init_db_raw( + test_suite_name: &str, + test_name: &str, +) -> TestDbGuard { #[allow(unused_variables)] let db_url: Option = None; // Uncomment if providing url explicitly is more convenient // let db_url = Some("postgres://postgres:admin@localhost:9432/".into()); let db_name = format!("{DB_PREFIX}_{test_suite_name}_{test_name}"); - TestDbGuard::new(db_name.as_str(), db_url).await + TestDbGuard::new::(db_name.as_str(), db_url).await } pub async fn init_verifier_server( @@ -48,6 +64,20 @@ where } pub async fn init_eth_bytecode_db_server(db_url: &str, verifier_addr: SocketAddr) -> Url { + let no_op_settings_setup = |settings: Settings| settings; + + init_eth_bytecode_db_server_with_settings_setup(db_url, verifier_addr, no_op_settings_setup) + .await +} + +pub async fn init_eth_bytecode_db_server_with_settings_setup( + db_url: &str, + verifier_addr: SocketAddr, + settings_setup: F, +) -> Url +where + F: Fn(Settings) -> Settings, +{ let verifier_uri = Uri::from_str(&format!("http://{verifier_addr}")).unwrap(); let settings = { @@ -60,7 +90,8 @@ pub async fn init_eth_bytecode_db_server(db_url: &str, verifier_addr: SocketAddr settings.metrics.enabled = false; settings.tracing.enabled = false; settings.jaeger.enabled = false; - settings + + settings_setup(settings) }; let _server_handle = { @@ -87,20 +118,51 @@ pub async fn init_eth_bytecode_db_server(db_url: &str, verifier_addr: SocketAddr base } +pub struct RequestWrapper<'a, Request> { + inner: &'a Request, + headers: reqwest::header::HeaderMap, +} + +impl<'a, Request> From<&'a Request> for RequestWrapper<'a, Request> { + fn from(value: &'a Request) -> Self { + Self { + inner: value, + headers: Default::default(), + } + } +} + +impl<'a, Request> RequestWrapper<'a, Request> { + pub fn header(&mut self, key: &str, value: &str) { + let key = reqwest::header::HeaderName::from_str(key) + .expect("Error converting key string into header name"); + let value = reqwest::header::HeaderValue::from_str(value) + .expect("Error converting value string into header value"); + self.headers.insert(key, value); + } + + pub fn headers(&mut self, headers: HashMap) { + for (key, value) in headers { + self.header(&key, &value); + } + } +} + pub async fn send_annotated_request< Request: serde::Serialize, Response: for<'a> serde::Deserialize<'a>, >( eth_bytecode_db_base: &Url, route: &str, - request: &Request, + request: &RequestWrapper<'_, Request>, annotation: Option<&str>, ) -> Response { let annotation = annotation.map(|v| format!("({v}) ")).unwrap_or_default(); let response = reqwest::Client::new() .post(eth_bytecode_db_base.join(route).unwrap()) - .json(&request) + .json(&request.inner) + .headers(request.headers.clone()) .send() .await .unwrap_or_else(|_| panic!("{annotation}Failed to send request")); @@ -117,12 +179,17 @@ pub async fn send_annotated_request< .await .unwrap_or_else(|_| panic!("({annotation})Response deserialization failed")) } -pub async fn send_request serde::Deserialize<'a>>( +pub async fn send_request< + 'a, + Request: serde::Serialize, + Response: for<'b> serde::Deserialize<'b>, +>( eth_bytecode_db_base: &Url, route: &str, - request: &Request, + request: &'a Request, ) -> Response { - send_annotated_request(eth_bytecode_db_base, route, request, None).await + let wrapped_request: RequestWrapper<'a, Request> = request.into(); + send_annotated_request(eth_bytecode_db_base, route, &wrapped_request, None).await } pub mod test_cases { @@ -194,7 +261,7 @@ pub mod test_cases { send_annotated_request( ð_bytecode_db_base, DB_SEARCH_ROUTE, - &request, + &(&request).into(), Some("Creation input search"), ) .await @@ -210,7 +277,7 @@ pub mod test_cases { send_annotated_request( ð_bytecode_db_base, DB_SEARCH_ROUTE, - &request, + &(&request).into(), Some("Deployed bytecode search"), ) .await @@ -273,7 +340,7 @@ pub mod test_cases { send_annotated_request( ð_bytecode_db_base, DB_SEARCH_ROUTE, - &request, + &(&request).into(), Some("Creation input search"), ) .await @@ -348,7 +415,7 @@ pub mod test_cases { send_annotated_request( ð_bytecode_db_base, DB_SEARCH_ROUTE, - &request, + &(&request).into(), Some("Creation input search"), ) .await @@ -402,9 +469,13 @@ pub mod test_cases { }; let annotation = format!("Metadata: {metadata_to_print}"); - let _: eth_bytecode_db_v2::VerifyResponse = - send_annotated_request(ð_bytecode_db_base, route, &request, Some(&annotation)) - .await; + let _: eth_bytecode_db_v2::VerifyResponse = send_annotated_request( + ð_bytecode_db_base, + route, + &(&request).into(), + Some(&annotation), + ) + .await; }; // `chain_id` is provided, but `contract_address` is missed from the verification metadata diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/verifier_alliance_types.rs b/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/verifier_alliance_types.rs new file mode 100644 index 000000000..3b641a836 --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/verification_test_helpers/verifier_alliance_types.rs @@ -0,0 +1,210 @@ +use super::test_input_data::TestInputData; +use blockscout_display_bytes::Bytes as DisplayBytes; +use bytes::Bytes; +use eth_bytecode_db::verification::{BytecodeType, VerificationMetadata, VerificationRequest}; +use eth_bytecode_db_proto::blockscout::eth_bytecode_db::v2 as eth_bytecode_db_v2; +use serde::Deserialize; +use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2 as smart_contract_verifier_v2; +use std::{collections::BTreeMap, path::Path, str::FromStr}; + +#[derive(Debug, Clone, Deserialize)] +pub struct TestCase { + pub deployed_creation_code: DisplayBytes, + pub deployed_runtime_code: DisplayBytes, + + pub compiled_creation_code: DisplayBytes, + pub compiled_runtime_code: DisplayBytes, + pub compiler: String, + pub version: String, + pub language: String, + pub name: String, + pub fully_qualified_name: String, + pub sources: BTreeMap, + pub compiler_settings: serde_json::Value, + pub compilation_artifacts: serde_json::Value, + pub creation_code_artifacts: serde_json::Value, + pub runtime_code_artifacts: serde_json::Value, + + pub creation_match: bool, + pub creation_values: serde_json::Value, + pub creation_transformations: serde_json::Value, + + pub runtime_match: bool, + pub runtime_values: serde_json::Value, + pub runtime_transformations: serde_json::Value, + + #[serde(skip_deserializing)] + #[serde(default = "default_chain_id")] + pub chain_id: usize, + #[serde(skip_deserializing)] + #[serde(default = "default_address")] + pub address: DisplayBytes, + #[serde(skip_deserializing)] + #[serde(default = "default_transaction_hash")] + pub transaction_hash: DisplayBytes, + #[serde(skip_deserializing)] + #[serde(default = "default_block_number")] + pub block_number: usize, + #[serde(skip_deserializing)] + #[serde(default = "default_transaction_index")] + pub transaction_index: usize, + #[serde(skip_deserializing)] + #[serde(default = "default_deployer")] + pub deployer: DisplayBytes, +} + +fn default_chain_id() -> usize { + 5 +} +fn default_address() -> DisplayBytes { + DisplayBytes::from_str("0xcafecafecafecafecafecafecafecafecafecafe").unwrap() +} +fn default_transaction_hash() -> DisplayBytes { + DisplayBytes::from_str("0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe") + .unwrap() +} +fn default_block_number() -> usize { + 1 +} +fn default_transaction_index() -> usize { + 0 +} +fn default_deployer() -> DisplayBytes { + DisplayBytes::from_str("0xfacefacefacefacefacefacefacefacefaceface").unwrap() +} + +impl TestCase { + pub fn from_file>(path: P) -> Self { + let content = std::fs::read_to_string(path).expect("failed to read file"); + serde_json::from_str(&content).expect("invalid test case format") + } + + pub fn to_test_input_data(&self) -> TestInputData { + let eth_bytecode_db_source = self.to_eth_bytecode_db_source(); + let verifier_extra_data = self.to_verifier_extra_data(); + + TestInputData::from_source_and_extra_data(eth_bytecode_db_source, verifier_extra_data) + } + + fn to_eth_bytecode_db_source(&self) -> eth_bytecode_db_v2::Source { + let file_name = self + .fully_qualified_name + .split(':') + .next() + .expect("':' should be used as a separator in the `fully_qualified_name`"); + let source_type = match self.language.as_str() { + "solidity" => smart_contract_verifier_v2::source::SourceType::Solidity, + "yul" => smart_contract_verifier_v2::source::SourceType::Yul, + "vyper" => smart_contract_verifier_v2::source::SourceType::Vyper, + language => panic!("Invalid language: {language}"), + }; + let abi = self + .compilation_artifacts + .as_object() + .expect("`compilation_artifacts` must be an object") + .get("abi") + .map(|abi| abi.to_string()); + let constructor_arguments = self + .creation_values + .as_object() + .expect("`creation_values` must be an object") + .get("constructorArguments") + .map(|args| { + args.as_str() + .expect("`constructorArguments` must be a string") + .to_string() + }); + let match_type = if self + .creation_values + .as_object() + .unwrap() + .get("cborAuxdata") + .is_some() + { + smart_contract_verifier_v2::source::MatchType::Partial + } else { + smart_contract_verifier_v2::source::MatchType::Full + }; + + eth_bytecode_db_v2::Source { + file_name: file_name.to_string(), + contract_name: self.name.clone(), + compiler_version: self.version.clone(), + compiler_settings: self.compiler_settings.to_string(), + source_type: source_type.into(), + source_files: self.sources.clone(), + abi, + constructor_arguments, + match_type: match_type.into(), + compilation_artifacts: Some(self.compilation_artifacts.to_string()), + creation_input_artifacts: Some(self.creation_code_artifacts.to_string()), + deployed_bytecode_artifacts: Some(self.runtime_code_artifacts.to_string()), + } + } + + fn to_verifier_extra_data(&self) -> smart_contract_verifier_v2::verify_response::ExtraData { + let parse_code_parts = |code: Bytes, code_artifacts: serde_json::Value| { + #[derive(Clone, Debug, Deserialize)] + #[serde(rename_all = "camelCase")] + struct CborAuxdata { + pub offset: usize, + pub value: DisplayBytes, + } + + #[derive(Clone, Debug, Deserialize)] + #[serde(rename_all = "camelCase")] + struct CodeArtifacts { + pub cbor_auxdata: BTreeMap, + } + + let code_artifacts: CodeArtifacts = + serde_json::from_value(code_artifacts).expect("parsing code artifacts failed"); + let ordered_auxdata = { + let mut auxdata = code_artifacts + .cbor_auxdata + .into_values() + .collect::>(); + auxdata.sort_by_key(|auxdata| auxdata.offset); + auxdata + }; + let ordered_auxdata_ranges = ordered_auxdata + .into_iter() + .map(|auxdata| (auxdata.offset..auxdata.offset + auxdata.value.len())) + .collect::>(); + + let mut parts = Vec::new(); + let mut main_range_start = 0; + for range in ordered_auxdata_ranges { + if !(main_range_start..range.start).is_empty() { + let main_part = + smart_contract_verifier_v2::verify_response::extra_data::BytecodePart { + r#type: "main".to_string(), + data: DisplayBytes::from(code[main_range_start..range.start].to_vec()) + .to_string(), + }; + parts.push(main_part); + } + main_range_start = range.end; + + let metadata_part = + smart_contract_verifier_v2::verify_response::extra_data::BytecodePart { + r#type: "meta".to_string(), + data: DisplayBytes::from(code[range].to_vec()).to_string(), + }; + parts.push(metadata_part); + } + parts + }; + + smart_contract_verifier_v2::verify_response::ExtraData { + local_creation_input_parts: parse_code_parts( + self.compiled_creation_code.0.clone(), + self.creation_code_artifacts.clone(), + ), + local_deployed_bytecode_parts: parse_code_parts( + self.compiled_runtime_code.0.clone(), + self.runtime_code_artifacts.clone(), + ), + } + } +} diff --git a/eth-bytecode-db/eth-bytecode-db-server/tests/verifier_alliance.rs b/eth-bytecode-db/eth-bytecode-db-server/tests/verifier_alliance.rs new file mode 100644 index 000000000..503250a8e --- /dev/null +++ b/eth-bytecode-db/eth-bytecode-db-server/tests/verifier_alliance.rs @@ -0,0 +1,460 @@ +mod verification_test_helpers; + +use crate::verification_test_helpers::{send_annotated_request, RequestWrapper}; +use async_trait::async_trait; +use eth_bytecode_db_proto::blockscout::eth_bytecode_db::v2 as eth_bytecode_db_v2; +use eth_bytecode_db_server::Settings; +use rstest::rstest; +use sea_orm::{ + prelude::{Decimal, Uuid}, + ActiveModelTrait, + ActiveValue::Set, + DatabaseConnection, DatabaseTransaction, EntityTrait, TransactionTrait, +}; +use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2 as smart_contract_verifier_v2; +use std::{future::Future, path::PathBuf, sync::Arc}; +use tonic::Response; +use verification_test_helpers::{ + init_alliance_db, init_db, init_eth_bytecode_db_server_with_settings_setup, + init_verifier_server, + smart_contract_verifer_mock::{MockSolidityVerifierService, SmartContractVerifierServer}, + verifier_alliance_types::TestCase, + TestDbGuard, VerifierService, +}; +use verifier_alliance_entity::{ + code, compiled_contracts, contract_deployments, contracts, verified_contracts, +}; + +#[async_trait] +impl VerifierService for MockSolidityVerifierService { + fn add_into_service(&mut self, response: smart_contract_verifier_v2::VerifyResponse) { + self.expect_verify_standard_json() + .returning(move |_| Ok(Response::new(response.clone()))); + } + + fn build_server(self) -> SmartContractVerifierServer { + SmartContractVerifierServer::new().solidity_service(self) + } +} + +const TEST_SUITE_NAME: &str = "verifier_alliance"; + +const ROUTE: &str = "/api/v2/verifier/solidity/sources:verify-standard-json"; + +const API_KEY_NAME: &str = "x-api-key"; + +const API_KEY: &str = "some api key"; + +fn verify_request(test_case: &TestCase) -> eth_bytecode_db_v2::VerifySolidityStandardJsonRequest { + let metadata = eth_bytecode_db_v2::VerificationMetadata { + chain_id: Some(format!("{}", test_case.chain_id)), + contract_address: Some(test_case.address.to_string()), + transaction_hash: Some(test_case.transaction_hash.to_string()), + block_number: Some(test_case.block_number as i64), + transaction_index: Some(test_case.transaction_index as i64), + deployer: Some(test_case.deployer.to_string()), + creation_code: Some(test_case.deployed_creation_code.to_string()), + runtime_code: Some(test_case.deployed_runtime_code.to_string()), + }; + + eth_bytecode_db_v2::VerifySolidityStandardJsonRequest { + bytecode: "".to_string(), + bytecode_type: eth_bytecode_db_v2::BytecodeType::CreationInput.into(), + compiler_version: "".to_string(), + input: "".to_string(), + metadata: Some(metadata), + } +} + +async fn setup>( + test_prefix: &str, + test_case_path: PathBuf, + setup_db: F, + is_authorized: bool, +) -> (TestDbGuard, TestCase) +where + F: FnOnce(Arc, TestCase) -> Fut, +{ + let service = MockSolidityVerifierService::new(); + + // e.g. "tests/alliance_test_cases/full_match.json" => "full_match" + let test_name = format!( + "{test_prefix}_{}", + test_case_path + .file_stem() + .as_ref() + .unwrap() + .to_str() + .unwrap() + ); + + let db = init_db(TEST_SUITE_NAME, &test_name).await; + let alliance_db = init_alliance_db(TEST_SUITE_NAME, &test_name).await; + + let test_case = TestCase::from_file(test_case_path); + let test_input_data = test_case.to_test_input_data(); + + setup_db(alliance_db.client(), test_case.clone()).await; + + let db_url = db.db_url(); + let verifier_addr = init_verifier_server(service, test_input_data.verifier_response).await; + + let settings_setup = |mut settings: Settings| { + settings.verifier_alliance_database.enabled = true; + settings.verifier_alliance_database.url = alliance_db.db_url().to_string(); + + settings.authorized_keys = + serde_json::from_value(serde_json::json!({"blockscout": {"key": API_KEY}})).unwrap(); + settings + }; + let eth_bytecode_db_base = + init_eth_bytecode_db_server_with_settings_setup(db_url, verifier_addr, settings_setup) + .await; + // Fill the database with existing value + { + let dummy_request = verify_request(&test_case); + let mut wrapped_request: RequestWrapper<_> = (&dummy_request).into(); + if is_authorized { + wrapped_request.header(API_KEY_NAME, API_KEY); + } + let _verification_response: eth_bytecode_db_v2::VerifyResponse = + send_annotated_request(ð_bytecode_db_base, ROUTE, &wrapped_request, None).await; + } + + (alliance_db, test_case) +} + +#[rstest] +#[tokio::test] +#[ignore = "Needs database to run"] +pub async fn success_with_existing_deployment( + #[files("tests/alliance_test_cases/*.json")] test_case_path: PathBuf, +) { + const TEST_PREFIX: &str = "success_with_existing_deployment"; + + let prepare_alliance_database = |db: Arc, test_case: TestCase| async move { + let txn = db.begin().await.expect("starting a transaction failed"); + let _contract_deployment_id = insert_contract_deployment(&txn, &test_case).await; + txn.commit().await.expect("committing transaction failed"); + }; + + let (alliance_db, test_case) = setup( + TEST_PREFIX, + test_case_path, + prepare_alliance_database, + false, + ) + .await; + + check_compiled_contract(alliance_db.client().as_ref(), &test_case).await; + check_verified_contract(alliance_db.client().as_ref(), &test_case).await; +} + +#[rstest] +#[tokio::test] +#[ignore = "Needs database to run"] +pub async fn success_without_existing_deployment( + #[files("tests/alliance_test_cases/full_match.json")] test_case_path: PathBuf, +) { + const TEST_PREFIX: &str = "success_without_existing_deployment"; + + let prepare_alliance_database = |_db: Arc, _test_case: TestCase| async {}; + + let (alliance_db, test_case) = + setup(TEST_PREFIX, test_case_path, prepare_alliance_database, true).await; + + check_contract_deployment(alliance_db.client().as_ref(), &test_case).await; + check_compiled_contract(alliance_db.client().as_ref(), &test_case).await; + check_verified_contract(alliance_db.client().as_ref(), &test_case).await; +} + +#[rstest] +#[tokio::test] +#[ignore = "Needs database to run"] +pub async fn failure_without_existing_deployment_not_authorized( + #[files("tests/alliance_test_cases/full_match.json")] test_case_path: PathBuf, +) { + const TEST_PREFIX: &str = "failure_without_existing_deployment_not_authorized"; + + let prepare_alliance_database = |_db: Arc, _test_case: TestCase| async {}; + + let (alliance_db, _test_case) = setup( + TEST_PREFIX, + test_case_path, + prepare_alliance_database, + false, + ) + .await; + + assert_eq!( + None, + retrieve_contract_deployment(alliance_db.client().as_ref()).await, + "`contract_deployment` inserted" + ); + assert_eq!( + None, + retrieve_compiled_contract(alliance_db.client().as_ref()).await, + "`compiled_contract` inserted" + ); + assert_eq!( + None, + retrieve_verified_contract(alliance_db.client().as_ref()).await, + "`verified_contract` inserted" + ); +} + +async fn insert_contract_deployment(txn: &DatabaseTransaction, test_case: &TestCase) -> Uuid { + let contract_id = insert_contract( + txn, + test_case.deployed_creation_code.to_vec(), + test_case.deployed_runtime_code.to_vec(), + ) + .await; + + contract_deployments::ActiveModel { + id: Default::default(), + chain_id: Set(test_case.chain_id.into()), + address: Set(test_case.address.to_vec()), + transaction_hash: Set(test_case.transaction_hash.to_vec()), + block_number: Set(Some(test_case.block_number.into())), + txindex: Set(Some(test_case.transaction_index.into())), + deployer: Set(Some(test_case.deployer.to_vec())), + contract_id: Set(contract_id), + } + .insert(txn) + .await + .unwrap_or_else(|err| { + panic!( + "insertion of a contract deployment failed; \ + contract_id: {contract_id}, \ + err: {err}" + ) + }) + .id +} + +async fn insert_contract( + txn: &DatabaseTransaction, + creation_code: Vec, + runtime_code: Vec, +) -> Uuid { + let creation_code_hash = insert_code(txn, creation_code).await; + let runtime_code_hash = insert_code(txn, runtime_code).await; + + contracts::ActiveModel { + id: Default::default(), + creation_code_hash: Set(creation_code_hash.0.to_vec()), + runtime_code_hash: Set(runtime_code_hash.0.to_vec()), + } + .insert(txn) + .await + .unwrap_or_else(|err| { + panic!( + "insertion of a contract failed; \ + creation_code_hash: {creation_code_hash}, \ + runtime_code_hash: {runtime_code_hash}, \ + err: {err}" + ) + }) + .id +} + +async fn insert_code(txn: &DatabaseTransaction, code: Vec) -> keccak_hash::H256 { + let code_hash = keccak_hash::keccak(&code); + code::ActiveModel { + code_hash: Set(code_hash.0.to_vec()), + code: Set(Some(code)), + } + .insert(txn) + .await + .unwrap_or_else(|err| panic!("insertion of a code failed; code_hash: {code_hash}, err: {err}")); + code_hash +} + +async fn check_contract(db: &DatabaseConnection, contract: contracts::Model, test_case: &TestCase) { + let creation_code = code::Entity::find_by_id(contract.creation_code_hash) + .one(db) + .await + .unwrap() + .unwrap(); + assert_eq!( + Some(test_case.deployed_creation_code.to_vec()), + creation_code.code, + "Invalid creation_code for deployed contract" + ); + + let runtime_code = code::Entity::find_by_id(contract.runtime_code_hash) + .one(db) + .await + .unwrap() + .unwrap(); + assert_eq!( + Some(test_case.deployed_runtime_code.to_vec()), + runtime_code.code, + "Invalid runtime_code for deployed contract" + ); +} + +async fn retrieve_contract_deployment( + db: &DatabaseConnection, +) -> Option { + contract_deployments::Entity::find() + .one(db) + .await + .expect("Error while retrieving contract deployment") +} +async fn check_contract_deployment(db: &DatabaseConnection, test_case: &TestCase) { + let contract_deployment = retrieve_contract_deployment(db) + .await + .expect("The data has not been added into `contract_deployments` table"); + + let test_case_chain_id: Decimal = test_case.chain_id.into(); + let test_case_block_number: Decimal = test_case.block_number.into(); + let test_case_transaction_index: Decimal = test_case.transaction_index.into(); + assert_eq!( + test_case_chain_id, contract_deployment.chain_id, + "Invalid contract_deployments.chain_id" + ); + assert_eq!( + test_case.address.to_vec(), + contract_deployment.address, + "Invalid contract_deployments.address" + ); + assert_eq!( + test_case.transaction_hash.to_vec(), + contract_deployment.transaction_hash, + "Invalid contract_deployments.transaction_hash" + ); + assert_eq!( + Some(test_case_block_number), + contract_deployment.block_number, + "Invalid contract_deployments.block_number" + ); + assert_eq!( + Some(test_case_transaction_index), + contract_deployment.txindex, + "Invalid contract_deployments.txindex" + ); + assert_eq!( + Some(test_case.deployer.to_vec()), + contract_deployment.deployer, + "Invalid contract_deployments.deployer" + ); + + let contract = contracts::Entity::find_by_id(contract_deployment.contract_id) + .one(db) + .await + .unwrap() + .unwrap(); + check_contract(db, contract, test_case).await; +} + +async fn retrieve_compiled_contract(db: &DatabaseConnection) -> Option { + compiled_contracts::Entity::find() + .one(db) + .await + .expect("Error while retrieving compiled contract") +} + +async fn check_compiled_contract(db: &DatabaseConnection, test_case: &TestCase) { + let compiled_contract = retrieve_compiled_contract(db) + .await + .expect("The data has not been added into `compiled_contracts` table"); + + let test_case_sources = serde_json::to_value(test_case.sources.clone()).unwrap(); + let test_case_creation_code_hash = keccak_hash::keccak(&test_case.compiled_creation_code) + .0 + .to_vec(); + let test_case_runtime_code_hash = keccak_hash::keccak(&test_case.compiled_runtime_code) + .0 + .to_vec(); + + assert_eq!( + test_case.compiler, compiled_contract.compiler, + "Invalid compiler" + ); + assert_eq!( + test_case.version, compiled_contract.version, + "Invalid version" + ); + assert_eq!( + test_case.language, compiled_contract.language, + "Invalid language" + ); + assert_eq!(test_case.name, compiled_contract.name, "Invalid name"); + assert_eq!( + test_case.fully_qualified_name, compiled_contract.fully_qualified_name, + "Invalid fully_qualified_name" + ); + assert_eq!( + test_case_sources, compiled_contract.sources, + "Invalid sources" + ); + assert_eq!( + test_case.compiler_settings, compiled_contract.compiler_settings, + "Invalid compiler_settings" + ); + assert_eq!( + test_case.compilation_artifacts, compiled_contract.compilation_artifacts, + "Invalid compilation_artifacts" + ); + assert_eq!( + test_case_creation_code_hash, compiled_contract.creation_code_hash, + "Invalid creation_code_hash" + ); + assert_eq!( + test_case.creation_code_artifacts, compiled_contract.creation_code_artifacts, + "Invalid creation_code_artifacts" + ); + assert_eq!( + test_case_runtime_code_hash, compiled_contract.runtime_code_hash, + "Invalid runtime_code_hash" + ); + assert_eq!( + test_case.runtime_code_artifacts, compiled_contract.runtime_code_artifacts, + "Invalid runtime_code_artifacts" + ); +} + +async fn retrieve_verified_contract(db: &DatabaseConnection) -> Option { + verified_contracts::Entity::find() + .one(db) + .await + .expect("Error while retrieving verified contract") +} + +async fn check_verified_contract(db: &DatabaseConnection, test_case: &TestCase) { + let verified_contract = retrieve_verified_contract(db) + .await + .expect("The data has not been added into `verified_contracts` table"); + + let test_case_creation_values = Some(test_case.creation_values.clone()); + let test_case_creation_transformations = Some(test_case.creation_transformations.clone()); + let test_case_runtime_values = Some(test_case.runtime_values.clone()); + let test_case_runtime_transformations = Some(test_case.runtime_transformations.clone()); + + assert_eq!( + test_case.creation_match, verified_contract.creation_match, + "Invalid creation_match" + ); + assert_eq!( + test_case_creation_values, verified_contract.creation_values, + "Invalid creation_values" + ); + assert_eq!( + test_case_creation_transformations, verified_contract.creation_transformations, + "Invalid creation_transformations" + ); + assert_eq!( + test_case.runtime_match, verified_contract.runtime_match, + "Invalid runtime_match" + ); + assert_eq!( + test_case_runtime_values, verified_contract.runtime_values, + "Invalid runtime_values" + ); + assert_eq!( + test_case_runtime_transformations, verified_contract.runtime_transformations, + "Invalid runtime_transformations" + ); +} diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/db/verifier_alliance_db.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/db/verifier_alliance_db.rs index d695c5f8c..969381ec2 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/db/verifier_alliance_db.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/db/verifier_alliance_db.rs @@ -12,12 +12,17 @@ use verifier_alliance_entity::{ code, compiled_contracts, contract_deployments, contracts, verified_contracts, }; +#[derive(Clone, Default)] pub(crate) struct ContractDeploymentData { pub chain_id: i64, pub contract_address: Vec, pub transaction_hash: Vec, + pub block_number: Option, + pub transaction_index: Option, + pub deployer: Option>, + pub creation_code: Option>, + pub runtime_code: Option>, } - pub(crate) async fn insert_data( db_client: &DatabaseConnection, source_response: types::DatabaseReadySource, @@ -53,6 +58,32 @@ pub(crate) async fn insert_data( Ok(()) } +pub(crate) async fn insert_deployment_data( + db_client: &DatabaseConnection, + mut deployment_data: ContractDeploymentData, +) -> Result<(), anyhow::Error> { + let txn = db_client + .begin() + .await + .context("begin database transaction")?; + + let contract = insert_contract( + &txn, + deployment_data.creation_code.take(), + deployment_data.runtime_code.take(), + ) + .await + .context("insert contract")?; + + let _contract_deployment = insert_contract_deployment(&txn, deployment_data, &contract) + .await + .context("insert contract deployment")?; + + txn.commit().await.context("commit transaction")?; + + Ok(()) +} + async fn retrieve_contract( txn: &DatabaseTransaction, deployment_data: &ContractDeploymentData, @@ -243,6 +274,85 @@ async fn insert_compiled_contract( Ok(compiled_contract) } +async fn insert_contract_deployment( + txn: &DatabaseTransaction, + deployment_data: ContractDeploymentData, + contract: &contracts::Model, +) -> Result { + let active_model = contract_deployments::ActiveModel { + id: Default::default(), + chain_id: Set(deployment_data.chain_id.into()), + address: Set(deployment_data.contract_address.clone()), + transaction_hash: Set(deployment_data.transaction_hash.clone()), + block_number: Set(deployment_data.block_number.map(|v| v.into())), + txindex: Set(deployment_data.transaction_index.map(|v| v.into())), + deployer: Set(deployment_data.deployer), + contract_id: Set(contract.id), + }; + let (contract_deployment, _inserted) = insert_then_select!( + txn, + contract_deployments, + active_model, + [ + (ChainId, deployment_data.chain_id), + (Address, deployment_data.contract_address), + (TransactionHash, deployment_data.transaction_hash) + ] + )?; + + Ok(contract_deployment) +} + +async fn insert_contract( + txn: &DatabaseTransaction, + creation_code: Option>, + runtime_code: Option>, +) -> Result { + if creation_code.is_none() && runtime_code.is_none() { + return Err(anyhow::anyhow!( + "at least one of creation or runtime code must not be null" + )); + } + let creation_code = if let Some(creation_code) = creation_code { + Some( + insert_code(txn, creation_code) + .await + .context("insert creation code")?, + ) + } else { + None + }; + let runtime_code = if let Some(runtime_code) = runtime_code { + Some( + insert_code(txn, runtime_code) + .await + .context("insert runtime code")?, + ) + } else { + None + }; + + let creation_code_hash = creation_code.map(|code| code.code_hash).unwrap_or_default(); + let runtime_code_hash = runtime_code.map(|code| code.code_hash).unwrap_or_default(); + + let active_model = contracts::ActiveModel { + id: Default::default(), + creation_code_hash: Set(creation_code_hash.clone()), + runtime_code_hash: Set(runtime_code_hash.clone()), + }; + let (contract, _inserted) = insert_then_select!( + txn, + contracts, + active_model, + [ + (CreationCodeHash, creation_code_hash), + (RuntimeCodeHash, runtime_code_hash) + ] + )?; + + Ok(contract) +} + async fn insert_code( txn: &DatabaseTransaction, code: Vec, diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/mod.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/mod.rs index 2cea8726e..af47db9be 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/mod.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/mod.rs @@ -37,17 +37,25 @@ enum VerifierAllianceDbAction<'a> { contract_address: bytes::Bytes, transaction_hash: bytes::Bytes, }, + SaveWithDeploymentData { + db_client: &'a DatabaseConnection, + chain_id: i64, + contract_address: bytes::Bytes, + transaction_hash: bytes::Bytes, + block_number: Option, + transaction_index: Option, + deployer: Option, + creation_code: Option, + runtime_code: Option, + }, } impl<'a> VerifierAllianceDbAction<'a> { pub fn from_db_client_and_metadata( db_client: Option<&'a DatabaseConnection>, verification_metadata: Option, + is_authorized: bool, ) -> Self { - if db_client.is_none() { - return Self::IgnoreDb; - } - match (db_client, verification_metadata) { ( Some(db_client), @@ -55,13 +63,34 @@ impl<'a> VerifierAllianceDbAction<'a> { chain_id: Some(chain_id), contract_address: Some(contract_address), transaction_hash: Some(transaction_hash), + block_number, + transaction_index, + deployer, + creation_code, + runtime_code, }), - ) => Self::SaveIfDeploymentExists { - db_client, - chain_id, - contract_address, - transaction_hash, - }, + ) => { + if is_authorized { + Self::SaveWithDeploymentData { + db_client, + chain_id, + contract_address, + transaction_hash, + block_number, + transaction_index, + deployer, + creation_code, + runtime_code, + } + } else { + Self::SaveIfDeploymentExists { + db_client, + chain_id, + contract_address, + transaction_hash, + } + } + } _ => Self::IgnoreDb, } } @@ -84,9 +113,11 @@ async fn process_verify_response( let (process_eth_bytecode_db_result, process_alliance_db_result) = futures::future::join(process_eth_bytecode_db_future, process_alliance_db_future).await; let _ = process_eth_bytecode_db_result.map_err(|err: anyhow::Error| { + println!("Error while inserting contract data into database: {err:#}"); tracing::error!("Error while inserting contract data into database: {err:#}") }); let _ = process_alliance_db_result.map_err(|err: anyhow::Error| { + println!("Error while inserting contract data into verifier alliance database: {err:#}"); tracing::error!( "Error while inserting contract data into verifier alliance database: {err:#}" ) @@ -163,7 +194,7 @@ async fn process_verifier_alliance_db_action( match action { VerifierAllianceDbAction::IgnoreDb => {} VerifierAllianceDbAction::SaveIfDeploymentExists { - db_client: alliance_db_client, + db_client, chain_id, contract_address, transaction_hash, @@ -175,14 +206,53 @@ async fn process_verifier_alliance_db_action( chain_id, contract_address: contract_address.to_vec(), transaction_hash: transaction_hash.to_vec(), + ..Default::default() }; - db::verifier_alliance_db::insert_data( - alliance_db_client, - database_source, - deployment_data, - ) - .await - .context("Insert data into verifier alliance database")?; + db::verifier_alliance_db::insert_data(db_client, database_source, deployment_data) + .await + .context("Insert data into verifier alliance database")?; + } + VerifierAllianceDbAction::SaveWithDeploymentData { + db_client, + chain_id, + contract_address, + transaction_hash, + block_number, + transaction_index, + deployer, + creation_code, + runtime_code, + } => { + let database_source = DatabaseReadySource::try_from(source) + .context("Converting source into database ready version")?; + + let deployment_data = db::verifier_alliance_db::ContractDeploymentData { + chain_id, + contract_address: contract_address.to_vec(), + transaction_hash: transaction_hash.to_vec(), + block_number, + transaction_index, + deployer: deployer.map(|deployer| deployer.to_vec()), + creation_code: creation_code + .as_ref() + .map(|creation_code| creation_code.to_vec()), + runtime_code: runtime_code + .as_ref() + .map(|runtime_code| runtime_code.to_vec()), + }; + + // At least one of creation and runtime code should exist to add the contract into the database. + if creation_code.is_some() || runtime_code.is_some() { + db::verifier_alliance_db::insert_deployment_data( + db_client, + deployment_data.clone(), + ) + .await + .context("Insert deployment data into verifier alliance database")?; + } + db::verifier_alliance_db::insert_data(db_client, database_source, deployment_data) + .await + .context("Insert data into verifier alliance database")?; } } diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_multi_part.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_multi_part.rs index 4d9c1b99f..82c762a32 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_multi_part.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_multi_part.rs @@ -37,6 +37,7 @@ pub async fn verify( mut client: Client, request: VerificationRequest, ) -> Result { + let is_authorized = request.is_authorized; let bytecode_type = request.bytecode_type; let raw_request_bytecode = hex::decode(request.bytecode.clone().trim_start_matches("0x")) .map_err(|err| Error::InvalidArgument(format!("invalid bytecode: {err}")))?; @@ -54,6 +55,7 @@ pub async fn verify( let verifier_alliance_db_action = VerifierAllianceDbAction::from_db_client_and_metadata( client.alliance_db_client.as_deref(), verification_metadata.clone(), + is_authorized, ); process_verify_response( response, @@ -96,8 +98,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifySolidityMultiPartRequest { bytecode: "0x1234".to_string(), @@ -140,8 +143,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifySolidityMultiPartRequest { bytecode: "0x1234".to_string(), diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_standard_json.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_standard_json.rs index 2699690eb..65eec8d12 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_standard_json.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/solidity_standard_json.rs @@ -30,6 +30,8 @@ pub async fn verify( mut client: Client, request: VerificationRequest, ) -> Result { + let is_authorized = request.is_authorized; + println!("\n\nRAFLA: is_authorized={is_authorized}\n\n"); let bytecode_type = request.bytecode_type; let raw_request_bytecode = hex::decode(request.bytecode.clone().trim_start_matches("0x")) .map_err(|err| Error::InvalidArgument(format!("invalid bytecode: {err}")))?; @@ -47,6 +49,7 @@ pub async fn verify( let verifier_alliance_db_action = VerifierAllianceDbAction::from_db_client_and_metadata( client.alliance_db_client.as_deref(), verification_metadata.clone(), + is_authorized, ); process_verify_response( response, @@ -83,8 +86,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifySolidityStandardJsonRequest { bytecode: "0x1234".to_string(), @@ -115,8 +119,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifySolidityStandardJsonRequest { bytecode: "0x1234".to_string(), diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_multi_part.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_multi_part.rs index 32a64a8bf..79628dcf6 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_multi_part.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_multi_part.rs @@ -35,6 +35,7 @@ pub async fn verify( mut client: Client, request: VerificationRequest, ) -> Result { + let is_authorized = request.is_authorized; let bytecode_type = request.bytecode_type; let raw_request_bytecode = hex::decode(request.bytecode.clone().trim_start_matches("0x")) .map_err(|err| Error::InvalidArgument(format!("invalid bytecode: {err}")))?; @@ -52,6 +53,7 @@ pub async fn verify( let verifier_alliance_db_action = VerifierAllianceDbAction::from_db_client_and_metadata( client.alliance_db_client.as_deref(), verification_metadata.clone(), + is_authorized, ); process_verify_response( response, @@ -96,8 +98,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifyVyperMultiPartRequest { bytecode: "0x1234".to_string(), @@ -144,8 +147,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifyVyperMultiPartRequest { bytecode: "0x1234".to_string(), diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_standard_json.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_standard_json.rs index 86a2c3d8b..a9054c464 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_standard_json.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/handlers/vyper_standard_json.rs @@ -29,6 +29,7 @@ pub async fn verify( mut client: Client, request: VerificationRequest, ) -> Result { + let is_authorized = request.is_authorized; let bytecode_type = request.bytecode_type; let raw_request_bytecode = hex::decode(request.bytecode.clone().trim_start_matches("0x")) .map_err(|err| Error::InvalidArgument(format!("invalid bytecode: {err}")))?; @@ -46,6 +47,7 @@ pub async fn verify( let verifier_alliance_db_action = VerifierAllianceDbAction::from_db_client_and_metadata( client.alliance_db_client.as_deref(), verification_metadata.clone(), + is_authorized, ); process_verify_response( response, @@ -82,8 +84,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifyVyperStandardJsonRequest { bytecode: "0x1234".to_string(), @@ -114,8 +117,9 @@ mod tests { metadata: Some(types::VerificationMetadata { chain_id: Some(1), contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])), - transaction_hash: None, + ..Default::default() }), + is_authorized: false, }; let expected = VerifyVyperStandardJsonRequest { bytecode: "0x1234".to_string(), diff --git a/eth-bytecode-db/eth-bytecode-db/src/verification/types.rs b/eth-bytecode-db/eth-bytecode-db/src/verification/types.rs index c7cced6fd..dae4331b6 100644 --- a/eth-bytecode-db/eth-bytecode-db/src/verification/types.rs +++ b/eth-bytecode-db/eth-bytecode-db/src/verification/types.rs @@ -311,11 +311,16 @@ impl TryFrom for DatabaseReadySource { /********** Verification Request **********/ -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct VerificationMetadata { pub chain_id: Option, pub contract_address: Option, pub transaction_hash: Option, + pub block_number: Option, + pub transaction_index: Option, + pub deployer: Option, + pub creation_code: Option, + pub runtime_code: Option, } impl From for smart_contract_verifier::VerificationMetadata { @@ -331,7 +336,7 @@ impl From for smart_contract_verifier::VerificationMetadat } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct VerificationRequest { pub bytecode: String, pub bytecode_type: BytecodeType, @@ -339,6 +344,8 @@ pub struct VerificationRequest { #[serde(flatten)] pub content: T, pub metadata: Option, + #[serde(skip_serializing)] + pub is_authorized: bool, } /********** Verification Type **********/ diff --git a/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/database_helpers.rs b/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/database_helpers.rs index e6e8b1ed9..b2a6a5569 100644 --- a/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/database_helpers.rs +++ b/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/database_helpers.rs @@ -58,15 +58,19 @@ impl TestDbGuard { let conn_without_db = Database::connect(base_db_url) .await .expect("Connection to postgres (without database) failed"); - Self::drop_database(&conn_without_db, db_name) + + // We use a hash, as the name itself may be quite long and be trimmed. + let hashed_db_name = format!("_{:x}", keccak_hash::keccak(db_name)); + + Self::drop_database(&conn_without_db, &hashed_db_name) .await .expect("Database drop failed"); - Self::create_database(&conn_without_db, db_name) + Self::create_database(&conn_without_db, &hashed_db_name) .await .expect("Database creation failed"); // Migrate database - let db_url = format!("{base_db_url}/{db_name}"); + let db_url = format!("{base_db_url}/{hashed_db_name}"); let conn_with_db = Database::connect(&db_url) .await .expect("Connection to postgres (with database) failed"); diff --git a/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/mod.rs b/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/mod.rs index 4b084d0c8..ff1f823c1 100644 --- a/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/mod.rs +++ b/eth-bytecode-db/eth-bytecode-db/tests/verification_test_helpers/mod.rs @@ -54,6 +54,7 @@ pub fn generate_verification_request( compiler_version: "compiler_version".to_string(), content, metadata, + is_authorized: false, } } @@ -499,6 +500,11 @@ pub async fn test_historical_data_saves_chain_id_and_contract_address(&self, content: C) -> TestInputData> { - let eth_bytecode_db_request = self.to_eth_bytecode_db_request(content); + pub fn to_test_input_data( + &self, + content: C, + is_authorized: bool, + ) -> TestInputData> { + let eth_bytecode_db_request = self.to_eth_bytecode_db_request(content, is_authorized); let verifier_source = self.to_verifier_source(); let verifier_extra_data = self.to_verifier_extra_data(); @@ -90,7 +94,11 @@ impl TestCase { ) } - fn to_eth_bytecode_db_request(&self, content: C) -> VerificationRequest { + fn to_eth_bytecode_db_request( + &self, + content: C, + is_authorized: bool, + ) -> VerificationRequest { VerificationRequest { bytecode: self.deployed_creation_code.to_string(), bytecode_type: BytecodeType::CreationInput, @@ -100,7 +108,13 @@ impl TestCase { chain_id: Some(self.chain_id as i64), contract_address: Some(self.address.0.clone()), transaction_hash: Some(self.transaction_hash.0.clone()), + block_number: Some(self.block_number as i64), + transaction_index: Some(self.transaction_index as i64), + deployer: Some(self.deployer.0.clone()), + creation_code: Some(self.deployed_creation_code.0.clone()), + runtime_code: Some(self.deployed_runtime_code.0.clone()), }), + is_authorized, } } diff --git a/eth-bytecode-db/eth-bytecode-db/tests/verifier_alliance.rs b/eth-bytecode-db/eth-bytecode-db/tests/verifier_alliance.rs index 6ab70ba15..0aecb1e81 100644 --- a/eth-bytecode-db/eth-bytecode-db/tests/verifier_alliance.rs +++ b/eth-bytecode-db/eth-bytecode-db/tests/verifier_alliance.rs @@ -9,13 +9,15 @@ use eth_bytecode_db::verification::{ use pretty_assertions::assert_eq; use rstest::rstest; use sea_orm::{ - prelude::Uuid, ActiveModelTrait, ActiveValue::Set, DatabaseConnection, DatabaseTransaction, - EntityTrait, TransactionTrait, + prelude::{Decimal, Uuid}, + ActiveModelTrait, + ActiveValue::Set, + DatabaseConnection, DatabaseTransaction, EntityTrait, TransactionTrait, }; use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2::{ VerifyResponse, VerifySolidityStandardJsonRequest, }; -use std::{path::PathBuf, sync::Arc}; +use std::{future::Future, path::PathBuf, sync::Arc}; use verification_test_helpers::{ init_db, smart_contract_veriifer_mock::{MockSolidityVerifierService, SmartContractVerifierServer}, @@ -68,24 +70,30 @@ impl VerifierService> for MockSolidityVerifier } } -#[rstest] -#[tokio::test] -#[ignore = "Needs database to run"] -pub async fn success(#[files("tests/alliance_test_cases/*.json")] test_case_path: PathBuf) { - // let test_case_path = PathBuf::from("tests/alliance_test_cases/immutables.json"); +async fn setup>( + test_prefix: &str, + test_case_path: PathBuf, + setup_db: F, + is_authorized: bool, +) -> (Client, TestCase) +where + F: FnOnce(Arc, TestCase) -> Fut, +{ let service = MockSolidityVerifierService::new(); // e.g. "tests/alliance_test_cases/full_match.json" => "full_match" - let test_name = test_case_path - .file_stem() - .as_ref() - .unwrap() - .to_str() - .unwrap() - .to_string(); + let test_name = format!( + "{test_prefix}_{}", + test_case_path + .file_stem() + .as_ref() + .unwrap() + .to_str() + .unwrap() + ); let test_case = TestCase::from_file(test_case_path); - let input_data = input_data(&test_case); + let input_data = input_data(&test_case, is_authorized); let db = init_db(DB_PREFIX, &test_name) .await @@ -93,42 +101,113 @@ pub async fn success(#[files("tests/alliance_test_cases/*.json")] test_case_path .await; let alliance_db_client = db.alliance_client().unwrap(); - prepare_alliance_database(alliance_db_client.clone(), &test_case).await; + setup_db(alliance_db_client.clone(), test_case.clone()).await; let client = start_server_and_init_client(db.client().clone(), service, vec![input_data.clone()]) .await .with_alliance_db_arc(alliance_db_client.clone()); - let _source = MockSolidityVerifierService::verify(client, input_data.eth_bytecode_db_request) - .await - .expect("verification failed"); + let _source = + MockSolidityVerifierService::verify(client.clone(), input_data.eth_bytecode_db_request) + .await + .expect("verification failed"); - let compiled_contract = compiled_contracts::Entity::find() - .one(alliance_db_client.as_ref()) - .await - .expect("Error while retrieving compiled contract") - .expect("The data has not been added into `compiled_contracts` table"); - check_compiled_contract(compiled_contract, &test_case); + (client, test_case) +} - let verified_contract = verified_contracts::Entity::find() - .one(alliance_db_client.as_ref()) - .await - .expect("Error while retrieving verified contract") - .expect("The data has not been added into `verified_contracts` table"); - check_verified_contract(verified_contract, &test_case); +#[rstest] +#[tokio::test] +#[ignore = "Needs database to run"] +pub async fn success_with_existing_deployment( + #[files("tests/alliance_test_cases/*.json")] test_case_path: PathBuf, +) { + const TEST_PREFIX: &str = "success_with_existing_deployment"; + + let prepare_alliance_database = |db: Arc, test_case: TestCase| async move { + let txn = db.begin().await.expect("starting a transaction failed"); + let _contract_deployment_id = insert_contract_deployment(&txn, &test_case).await; + txn.commit().await.expect("committing transaction failed"); + }; + + let (client, test_case) = setup( + TEST_PREFIX, + test_case_path, + prepare_alliance_database, + false, + ) + .await; + let alliance_db_client = client.alliance_db_client.unwrap(); + + check_compiled_contract(alliance_db_client.as_ref(), &test_case).await; + check_verified_contract(alliance_db_client.as_ref(), &test_case).await; } -fn input_data(test_case: &TestCase) -> TestInputData> { - test_case.to_test_input_data(StandardJson { - input: "".to_string(), - }) +#[rstest] +#[tokio::test] +#[ignore = "Needs database to run"] +pub async fn success_without_existing_deployment( + #[files("tests/alliance_test_cases/full_match.json")] test_case_path: PathBuf, +) { + const TEST_PREFIX: &str = "success_without_existing_deployment"; + + let prepare_alliance_database = |_db: Arc, _test_case: TestCase| async {}; + + let (client, test_case) = + setup(TEST_PREFIX, test_case_path, prepare_alliance_database, true).await; + let alliance_db_client = client.alliance_db_client.unwrap(); + + check_contract_deployment(alliance_db_client.as_ref(), &test_case).await; + check_compiled_contract(alliance_db_client.as_ref(), &test_case).await; + check_verified_contract(alliance_db_client.as_ref(), &test_case).await; } -async fn prepare_alliance_database(db: Arc, test_case: &TestCase) { - let txn = db.begin().await.expect("starting a transaction failed"); - let _contract_deployment_id = insert_contract_deployment(&txn, test_case).await; - txn.commit().await.expect("committing transaction failed"); +#[rstest] +#[tokio::test] +#[ignore = "Needs database to run"] +pub async fn failure_without_existing_deployment_not_authorized( + #[files("tests/alliance_test_cases/full_match.json")] test_case_path: PathBuf, +) { + const TEST_PREFIX: &str = "failure_without_existing_deployment_not_authorized"; + + let prepare_alliance_database = |_db: Arc, _test_case: TestCase| async {}; + + let (client, _test_case) = setup( + TEST_PREFIX, + test_case_path, + prepare_alliance_database, + false, + ) + .await; + let alliance_db_client = client.alliance_db_client.unwrap(); + + assert_eq!( + None, + retrieve_contract_deployment(alliance_db_client.as_ref()).await, + "`contract_deployment` inserted" + ); + assert_eq!( + None, + retrieve_compiled_contract(alliance_db_client.as_ref()).await, + "`compiled_contract` inserted" + ); + assert_eq!( + None, + retrieve_verified_contract(alliance_db_client.as_ref()).await, + "`verified_contract` inserted" + ); +} + +fn input_data( + test_case: &TestCase, + is_authorized: bool, +) -> TestInputData> { + test_case.to_test_input_data( + StandardJson { + input: "".to_string(), + }, + is_authorized, + ) } async fn insert_contract_deployment(txn: &DatabaseTransaction, test_case: &TestCase) -> Uuid { @@ -199,7 +278,96 @@ async fn insert_code(txn: &DatabaseTransaction, code: Vec) -> keccak_hash::H code_hash } -fn check_compiled_contract(compiled_contract: compiled_contracts::Model, test_case: &TestCase) { +async fn check_contract(db: &DatabaseConnection, contract: contracts::Model, test_case: &TestCase) { + let creation_code = code::Entity::find_by_id(contract.creation_code_hash) + .one(db) + .await + .unwrap() + .unwrap(); + assert_eq!( + Some(test_case.deployed_creation_code.to_vec()), + creation_code.code, + "Invalid creation_code for deployed contract" + ); + + let runtime_code = code::Entity::find_by_id(contract.runtime_code_hash) + .one(db) + .await + .unwrap() + .unwrap(); + assert_eq!( + Some(test_case.deployed_runtime_code.to_vec()), + runtime_code.code, + "Invalid runtime_code for deployed contract" + ); +} + +async fn retrieve_contract_deployment( + db: &DatabaseConnection, +) -> Option { + contract_deployments::Entity::find() + .one(db) + .await + .expect("Error while retrieving contract deployment") +} +async fn check_contract_deployment(db: &DatabaseConnection, test_case: &TestCase) { + let contract_deployment = retrieve_contract_deployment(db) + .await + .expect("The data has not been added into `contract_deployments` table"); + + let test_case_chain_id: Decimal = test_case.chain_id.into(); + let test_case_block_number: Decimal = test_case.block_number.into(); + let test_case_transaction_index: Decimal = test_case.transaction_index.into(); + assert_eq!( + test_case_chain_id, contract_deployment.chain_id, + "Invalid contract_deployments.chain_id" + ); + assert_eq!( + test_case.address.to_vec(), + contract_deployment.address, + "Invalid contract_deployments.address" + ); + assert_eq!( + test_case.transaction_hash.to_vec(), + contract_deployment.transaction_hash, + "Invalid contract_deployments.transaction_hash" + ); + assert_eq!( + Some(test_case_block_number), + contract_deployment.block_number, + "Invalid contract_deployments.block_number" + ); + assert_eq!( + Some(test_case_transaction_index), + contract_deployment.txindex, + "Invalid contract_deployments.txindex" + ); + assert_eq!( + Some(test_case.deployer.to_vec()), + contract_deployment.deployer, + "Invalid contract_deployments.deployer" + ); + + let contract = contracts::Entity::find_by_id(contract_deployment.contract_id) + .one(db) + .await + .unwrap() + .unwrap(); + check_contract(db, contract, test_case).await; +} + +async fn retrieve_compiled_contract(db: &DatabaseConnection) -> Option { + compiled_contracts::Entity::find() + .one(db) + .await + .expect("Error while retrieving compiled contract") +} + +async fn check_compiled_contract(db: &DatabaseConnection, test_case: &TestCase) { + let compiled_contract = retrieve_compiled_contract(db) + .await + .expect("The data has not been added into `compiled_contracts` table"); + let test_case_sources = serde_json::to_value(test_case.sources.clone()).unwrap(); let test_case_creation_code_hash = keccak_hash::keccak(&test_case.compiled_creation_code) .0 @@ -255,7 +423,18 @@ fn check_compiled_contract(compiled_contract: compiled_contracts::Model, test_ca ); } -fn check_verified_contract(verified_contract: verified_contracts::Model, test_case: &TestCase) { +async fn retrieve_verified_contract(db: &DatabaseConnection) -> Option { + verified_contracts::Entity::find() + .one(db) + .await + .expect("Error while retrieving verified contract") +} + +async fn check_verified_contract(db: &DatabaseConnection, test_case: &TestCase) { + let verified_contract = retrieve_verified_contract(db) + .await + .expect("The data has not been added into `verified_contracts` table"); + let test_case_creation_values = Some(test_case.creation_values.clone()); let test_case_creation_transformations = Some(test_case.creation_transformations.clone()); let test_case_runtime_values = Some(test_case.runtime_values.clone());