Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eth-bytecode-db: allow partial values for the verification metadata #566

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading