Skip to content

Commit

Permalink
Eth-bytecode-db: allow partial values for the verification metadata (#…
Browse files Browse the repository at this point in the history
…566)

* Update verifier to allow partially filled verification metadata

* Add tests for partial verification metadata

* Add partially filled verification metadata support
  • Loading branch information
rimrakhimov authored Jul 18, 2023
1 parent 52c41ec commit fadd27f
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 57 deletions.
3 changes: 2 additions & 1 deletion eth-bytecode-db/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ enum BytecodeType {

message VerificationMetadata {
/// Id of the chain the contract is verified on
string chain_id = 1;
optional string chain_id = 1;
/// The address of the contract to be verified
string contract_address = 2;
optional string contract_address = 2;
}

message VerifySolidityMultiPartRequest {
Expand Down
3 changes: 2 additions & 1 deletion eth-bytecode-db/eth-bytecode-db-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ tokio = { version = "1.23", features = [ "rt-multi-thread", "macros" ] }
tonic = "0.8"

[dev-dependencies]
smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "ee52afad" }
smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "52c41ec" }

hex = "0.4.3"
mockall = "0.11"
Expand All @@ -33,5 +33,6 @@ reqwest = { version = "0.11", features = ["json"]}
rand = "0.8"
rstest = "0.16"
sea-orm = { version = "*", features = [ "sqlx-sqlite" ]}
serde_json = "1.0.96"
tokio-stream = { version = "0.1", features = ["net"] }
tracing = "0.1"
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,29 @@ impl TryFrom<VerificationMetadataWrapper> for verification::VerificationMetadata

fn try_from(value: VerificationMetadataWrapper) -> Result<Self, Self::Error> {
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
};

Ok(verification::VerificationMetadata {
chain_id: i64::from_str(&value.chain_id)
.map_err(|_err| tonic::Status::invalid_argument("Invalid metadata.chain_id"))?,
contract_address: DisplayBytes::from_str(&value.contract_address)
.map_err(|_err| tonic::Status::invalid_argument("Invalid contract address"))?
.0,
chain_id,
contract_address,
})
}
}
Expand All @@ -29,15 +46,17 @@ mod tests {
#[test]
fn from_proto_to_verification_metadata() {
let proto_type = proto::VerificationMetadata {
chain_id: "1".into(),
contract_address: "0xcafecafecafecafecafecafecafecafecafecafe".into(),
chain_id: Some("1".into()),
contract_address: Some("0xcafecafecafecafecafecafecafecafecafecafe".into()),
};

let expected = verification::VerificationMetadata {
chain_id: 1,
contract_address: DisplayBytes::from_str("0xcafecafecafecafecafecafecafecafecafecafe")
.unwrap()
.0,
chain_id: Some(1),
contract_address: Some(
DisplayBytes::from_str("0xcafecafecafecafecafecafecafecafecafecafe")
.unwrap()
.0,
),
};

let wrapper: VerificationMetadataWrapper = proto_type.into();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,28 @@ async fn test_search_returns_full_matches_only_if_any() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_accepts_partial_verification_metadata_in_input() {
let default_request = VerifySolidityMultiPartRequest {
bytecode: "".to_string(),
bytecode_type: BytecodeType::CreationInput.into(),
compiler_version: "".to_string(),
evm_version: None,
optimization_runs: None,
source_files: Default::default(),
libraries: Default::default(),
metadata: None,
};
let source_type = verification::SourceType::Solidity;
test_cases::test_accepts_partial_verification_metadata_in_input::<MockSolidityVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,25 @@ async fn test_search_returns_full_matches_only_if_any() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_accepts_partial_verification_metadata_in_input() {
let default_request = VerifySolidityStandardJsonRequest {
bytecode: "".to_string(),
bytecode_type: BytecodeType::CreationInput.into(),
compiler_version: "".to_string(),
input: "".to_string(),
metadata: None,
};
let source_type = verification::SourceType::Solidity;
test_cases::test_accepts_partial_verification_metadata_in_input::<MockSolidityVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,65 @@ pub mod test_cases {
"Sources returned on verification and search differ"
);
}

pub async fn test_accepts_partial_verification_metadata_in_input<Service, Request>(
test_suite_name: &str,
route: &str,
verification_request: Request,
source_type: SourceType,
) where
Service: Default + VerifierService<smart_contract_verifier_v2::VerifyResponse>,
Request: Serialize + Clone,
{
let db = init_db(
test_suite_name,
"test_accepts_partial_verification_metadata_in_input",
)
.await;

let test_data = test_input_data::basic(source_type, MatchType::Partial);

let db_url = db.db_url();
let verifier_addr =
init_verifier_server(Service::default(), test_data.verifier_response).await;

let eth_bytecode_db_base = init_eth_bytecode_db_server(db_url, verifier_addr).await;

let validate = |metadata: serde_json::Value| async {
let metadata_to_print = metadata.clone();
let mut request = serde_json::to_value(verification_request.clone()).unwrap();
if let Some(value) = request.as_object_mut() {
value.insert("metadata".to_string(), metadata)
} else {
panic!("Request value is not an object")
};

let response = reqwest::Client::new()
.post(eth_bytecode_db_base.join(route).unwrap())
.json(&request)
.send()
.await
.expect("Failed to send request");

// Assert that status code is success
if !response.status().is_success() {
let status = response.status();
let message = response.text().await.expect("Read body as text");
panic!(
"Invalid status code (success expected). \
Status: {status}. Message: {message}.\
Metadata: {metadata_to_print}"
)
}
};

// `chain_id` is provided, but `contract_address` is missed from the verification metadata
let metadata = serde_json::json!({ "chainId": "5" });
validate(metadata).await;

// `chain_id` is provided, but `contract_address` is missed from the verification metadata
let metadata =
serde_json::json!({ "contractAddress": "0x0123456789012345678901234567890123456789" });
validate(metadata).await;
}
}
24 changes: 24 additions & 0 deletions eth-bytecode-db/eth-bytecode-db-server/tests/vyper_multi_part.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,27 @@ async fn test_search_returns_full_matches_only_if_any() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_accepts_partial_verification_metadata_in_input() {
let default_request = VerifyVyperMultiPartRequest {
bytecode: "".to_string(),
bytecode_type: BytecodeType::CreationInput.into(),
compiler_version: "".to_string(),
evm_version: None,
source_files: Default::default(),
interfaces: Default::default(),
metadata: None,
};
let source_type = verification::SourceType::Vyper;
test_cases::test_accepts_partial_verification_metadata_in_input::<MockVyperVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,25 @@ async fn test_search_returns_full_matches_only_if_any() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_accepts_partial_verification_metadata_in_input() {
let default_request = VerifyVyperStandardJsonRequest {
bytecode: "".to_string(),
bytecode_type: BytecodeType::CreationInput.into(),
compiler_version: "".to_string(),
input: "".to_string(),
metadata: None,
};
let source_type = verification::SourceType::Vyper;
test_cases::test_accepts_partial_verification_metadata_in_input::<MockVyperVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
2 changes: 1 addition & 1 deletion eth-bytecode-db/eth-bytecode-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ prometheus = "0.13"
semver = "1.0"
serde = "1.0"
serde_json = "1.0"
smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "ee52afad" }
smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "52c41ec" }
solidity-metadata = "1.0"
thiserror = "1.0"
tokio = "1.22"
Expand Down
4 changes: 2 additions & 2 deletions eth-bytecode-db/eth-bytecode-db/src/verification/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ pub(crate) async fn insert_verified_contract_data(
let (chain_id, contract_address) = match verification_metadata {
None => (None, None),
Some(metadata) => (
Some(metadata.chain_id),
Some(metadata.contract_address.to_vec()),
metadata.chain_id,
metadata.contract_address.map(|address| address.to_vec()),
),
};
verified_contracts::ActiveModel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ mod tests {
libraries: BTreeMap::from([("lib1".into(), "0xcafe".into())]),
},
metadata: Some(types::VerificationMetadata {
chain_id: 1,
contract_address: bytes::Bytes::from_static(&[1u8; 20]),
chain_id: Some(1),
contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])),
}),
};
let expected = VerifySolidityMultiPartRequest {
Expand All @@ -105,8 +105,8 @@ mod tests {
optimization_runs: Some(200),
libraries: BTreeMap::from([("lib1".into(), "0xcafe".into())]),
metadata: Some(smart_contract_verifier::VerificationMetadata {
chain_id: "1".to_string(),
contract_address: "0x0101010101010101010101010101010101010101".to_string(),
chain_id: Some("1".to_string()),
contract_address: Some("0x0101010101010101010101010101010101010101".to_string()),
}),
};
assert_eq!(
Expand All @@ -132,8 +132,8 @@ mod tests {
libraries: BTreeMap::from([("lib1".into(), "0xcafe".into())]),
},
metadata: Some(types::VerificationMetadata {
chain_id: 1,
contract_address: bytes::Bytes::from_static(&[1u8; 20]),
chain_id: Some(1),
contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])),
}),
};
let expected = VerifySolidityMultiPartRequest {
Expand All @@ -148,8 +148,8 @@ mod tests {
optimization_runs: Some(200),
libraries: BTreeMap::from([("lib1".into(), "0xcafe".into())]),
metadata: Some(smart_contract_verifier::VerificationMetadata {
chain_id: "1".to_string(),
contract_address: "0x0101010101010101010101010101010101010101".to_string(),
chain_id: Some("1".to_string()),
contract_address: Some("0x0101010101010101010101010101010101010101".to_string()),
}),
};
assert_eq!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ mod tests {
input: "standard_json_input".to_string(),
},
metadata: Some(types::VerificationMetadata {
chain_id: 1,
contract_address: bytes::Bytes::from_static(&[1u8; 20]),
chain_id: Some(1),
contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])),
}),
};
let expected = VerifySolidityStandardJsonRequest {
Expand All @@ -86,8 +86,8 @@ mod tests {
compiler_version: "compiler_version".to_string(),
input: "standard_json_input".to_string(),
metadata: Some(smart_contract_verifier::VerificationMetadata {
chain_id: "1".to_string(),
contract_address: "0x0101010101010101010101010101010101010101".to_string(),
chain_id: Some("1".to_string()),
contract_address: Some("0x0101010101010101010101010101010101010101".to_string()),
}),
};
assert_eq!(
Expand All @@ -107,8 +107,8 @@ mod tests {
input: "standard_json_input".to_string(),
},
metadata: Some(types::VerificationMetadata {
chain_id: 1,
contract_address: bytes::Bytes::from_static(&[1u8; 20]),
chain_id: Some(1),
contract_address: Some(bytes::Bytes::from_static(&[1u8; 20])),
}),
};
let expected = VerifySolidityStandardJsonRequest {
Expand All @@ -117,8 +117,8 @@ mod tests {
compiler_version: "compiler_version".to_string(),
input: "standard_json_input".to_string(),
metadata: Some(smart_contract_verifier::VerificationMetadata {
chain_id: "1".to_string(),
contract_address: "0x0101010101010101010101010101010101010101".to_string(),
chain_id: Some("1".to_string()),
contract_address: Some("0x0101010101010101010101010101010101010101".to_string()),
}),
};
assert_eq!(
Expand Down
Loading

0 comments on commit fadd27f

Please sign in to comment.