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: add sourcify verify-from-etherscan implementation #585

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
80be01c
Initialize 'sourcify' crate. Implement 'get_source_files_any' request
rimrakhimov Jul 19, 2023
692a871
Eliminate separate error module. Make GetSourceFilesResponse public
rimrakhimov Jul 19, 2023
b7769ae
Refactor client code
rimrakhimov Jul 19, 2023
4d3b559
Make use of reqwest_retry for the requests. Refactor Error struct
rimrakhimov Jul 19, 2023
5b5f2b5
Update GetSourceFilesResponse struct to parse the raw input files
rimrakhimov Jul 31, 2023
57378b0
Update deserialization errors
rimrakhimov Jul 31, 2023
4ae3b7c
Make unexpected segments not to be errors; add tracing functionality
rimrakhimov Jul 31, 2023
a5d1bd9
Remove Internal error
rimrakhimov Aug 1, 2023
55a4420
Make client builder to use self instead of the mutable references
rimrakhimov Aug 2, 2023
80030fc
Add a special processing for the case when the chain is not supported…
rimrakhimov Aug 2, 2023
9abb78b
Rename (internal)Error to ErrorResponse
rimrakhimov Aug 2, 2023
977fd05
Add verify_from_etherscan implementation
rimrakhimov Aug 8, 2023
bd467d7
Add the definition for endpoint custom errors
rimrakhimov Aug 8, 2023
c476ddb
Move base_url check on setup step. Remove InvalidArgument error
rimrakhimov Aug 8, 2023
121a724
Add custom error handler for VerifyFromEtherscanError
rimrakhimov Aug 8, 2023
1853e5a
Add tests
rimrakhimov Aug 8, 2023
5f9c47a
Merge branch 'main' into rimrakhimov/libs/sourcify-import-etherscan
rimrakhimov Aug 8, 2023
35e6ec7
Add std::error::Error trait bound for CustomError
rimrakhimov Aug 8, 2023
aac0e28
Make EmptyCustomError available
rimrakhimov Aug 9, 2023
d9e4971
Make EmptyCustomError available
rimrakhimov Aug 9, 2023
baaa92e
Add verify_from_etherscan endpoint definition
rimrakhimov Aug 9, 2023
17b7a32
Add test case for verify_from_etherscan endpoint
rimrakhimov Aug 10, 2023
c0d60f4
Add verify_from_etherscan implementation
rimrakhimov Aug 10, 2023
9111f73
Add VerifyFromEtherscanError processing
rimrakhimov Aug 11, 2023
1a8d967
Move library defined sourcify client into SourcifyApiClient; Add call…
rimrakhimov Aug 11, 2023
e5227ac
Add evm_version parsing
rimrakhimov Aug 11, 2023
a92c838
Add comments
rimrakhimov Aug 11, 2023
e527e1b
Add api endpoint definition for verify-from-etherscan
rimrakhimov Aug 11, 2023
f874f34
Add sourcify-verify-from-etherscan implementation
rimrakhimov Aug 11, 2023
7bf73e2
Make use of structs to parse metadata
rimrakhimov Aug 13, 2023
b82704b
Merge branch 'rimrakhimov/verifier/sourcify-verify-from-etherscan' in…
rimrakhimov Aug 13, 2023
6608ea1
cargo fmt
rimrakhimov Aug 13, 2023
8944d88
cargo fmt
rimrakhimov Aug 13, 2023
54df861
Merge branch 'rimrakhimov/verifier/sourcify-verify-from-etherscan' in…
rimrakhimov Aug 13, 2023
dd623c3
Merge branch 'main' into rimrakhimov/eth-bytecode-db/sourcify-import-…
rimrakhimov Aug 14, 2023
773dfbb
Return verifier url version
rimrakhimov Aug 14, 2023
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
2 changes: 1 addition & 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 @@ -45,6 +45,10 @@ http:
post: /api/v2/verifier/sourcify/sources:verify
body: "*"

- selector: blockscout.ethBytecodeDb.v2.SourcifyVerifier.VerifyFromEtherscan
post: /api/v2/verifier/sourcify/sources:verify-from-etherscan
body: "*"

#################### Health ####################

- selector: blockscout.ethBytecodeDb.v2.Health.Check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ service VyperVerifier {

service SourcifyVerifier {
rpc Verify(VerifySourcifyRequest) returns (VerifyResponse) {}

rpc VerifyFromEtherscan(VerifyFromEtherscanSourcifyRequest) returns (VerifyResponse) {}
}

message Source {
Expand Down Expand Up @@ -184,6 +186,14 @@ message SearchSourcifySourcesRequest {
string contract_address = 2;
}

message VerifyFromEtherscanSourcifyRequest {
/// Address of the contract to be verified
string address = 1;
/// The chain (network) the contract was deployed to
/// (https://docs.sourcify.dev/docs/api/chains/)
string chain = 2;
}

message SearchSourcesResponse {
repeated Source sources = 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,26 @@ paths:
$ref: '#/definitions/v2VerifySourcifyRequest'
tags:
- SourcifyVerifier
/api/v2/verifier/sourcify/sources:verify-from-etherscan:
post:
operationId: SourcifyVerifier_VerifyFromEtherscan
responses:
"200":
description: A successful response.
schema:
$ref: '#/definitions/v2VerifyResponse'
default:
description: An unexpected error response.
schema:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: body
in: body
required: true
schema:
$ref: '#/definitions/v2VerifyFromEtherscanSourcifyRequest'
tags:
- SourcifyVerifier
/api/v2/verifier/vyper/sources:verify-multi-part:
post:
operationId: VyperVerifier_VerifyMultiPart
Expand Down Expand Up @@ -337,6 +357,17 @@ definitions:
contractAddress:
type: string
title: / The address of the contract to be verified
v2VerifyFromEtherscanSourcifyRequest:
type: object
properties:
address:
type: string
title: / Address of the contract to be verified
chain:
type: string
title: |-
/ The chain (network) the contract was deployed to
/ (https://docs.sourcify.dev/docs/api/chains/)
v2VerifyResponse:
type: object
properties:
Expand Down
2 changes: 1 addition & 1 deletion eth-bytecode-db/eth-bytecode-db-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ tonic = "0.8"
tracing = "0.1"

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

hex = "0.4.3"
mockall = "0.11"
Expand Down
6 changes: 3 additions & 3 deletions eth-bytecode-db/eth-bytecode-db-server/src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use eth_bytecode_db_proto::blockscout::eth_bytecode_db::v2::{
sourcify_verifier_server, verify_response, vyper_verifier_actix, vyper_verifier_server,
BytecodeType, HealthCheckRequest, HealthCheckResponse, ListCompilerVersionsRequest,
ListCompilerVersionsResponse, SearchSourcesRequest, SearchSourcesResponse,
SearchSourcifySourcesRequest, Source, VerificationMetadata, VerifyResponse,
VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest, VerifySourcifyRequest,
VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
SearchSourcifySourcesRequest, Source, VerificationMetadata, VerifyFromEtherscanSourcifyRequest,
VerifyResponse, VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest,
VerifySourcifyRequest, VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::verifier_base;
use crate::proto::{sourcify_verifier_server, VerifyResponse, VerifySourcifyRequest};
use async_trait::async_trait;
use eth_bytecode_db::verification::{
sourcify::{self, VerificationRequest},
Client,
use crate::proto::{
sourcify_verifier_server, VerifyFromEtherscanSourcifyRequest, VerifyResponse,
VerifySourcifyRequest,
};
use async_trait::async_trait;
use eth_bytecode_db::verification::{sourcify, sourcify_from_etherscan, Client};

pub struct SourcifyVerifierService {
client: Client,
Expand All @@ -24,7 +24,7 @@ impl sourcify_verifier_server::SourcifyVerifier for SourcifyVerifierService {
) -> Result<tonic::Response<VerifyResponse>, tonic::Status> {
let request = request.into_inner();

let verification_request = VerificationRequest {
let verification_request = sourcify::VerificationRequest {
address: request.address,
chain: request.chain,
chosen_contract: request.chosen_contract,
Expand All @@ -35,4 +35,21 @@ impl sourcify_verifier_server::SourcifyVerifier for SourcifyVerifierService {

verifier_base::process_verification_result(result)
}

async fn verify_from_etherscan(
&self,
request: tonic::Request<VerifyFromEtherscanSourcifyRequest>,
) -> Result<tonic::Response<VerifyResponse>, tonic::Status> {
let request = request.into_inner();

let verification_request = sourcify_from_etherscan::VerificationRequest {
address: request.address,
chain: request.chain,
};

let result =
sourcify_from_etherscan::verify(self.client.clone(), verification_request).await;

verifier_base::process_verification_result(result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
mod verification_test_helpers;

use async_trait::async_trait;
use eth_bytecode_db::verification;
use eth_bytecode_db_proto::blockscout::eth_bytecode_db::v2::VerifyFromEtherscanSourcifyRequest;
use rstest::{fixture, rstest};
use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2 as smart_contract_verifier_v2;
use tonic::Response;
use verification_test_helpers::{
smart_contract_verifer_mock::{MockSourcifyVerifierService, SmartContractVerifierServer},
test_cases, VerifierService,
};

const TEST_SUITE_NAME: &str = "sourcify_from_etherscan";

const ROUTE: &str = "/api/v2/verifier/sourcify/sources:verify-from-etherscan";

#[async_trait]
impl VerifierService<smart_contract_verifier_v2::VerifyResponse> for MockSourcifyVerifierService {
fn add_into_service(&mut self, response: smart_contract_verifier_v2::VerifyResponse) {
self.expect_verify_from_etherscan()
.returning(move |_| Ok(Response::new(response.clone())));
}

fn build_server(self) -> SmartContractVerifierServer {
SmartContractVerifierServer::new().sourcify_service(self)
}
}

#[fixture]
fn service() -> MockSourcifyVerifierService {
MockSourcifyVerifierService::new()
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_returns_valid_source(service: MockSourcifyVerifierService) {
let default_request = VerifyFromEtherscanSourcifyRequest {
address: "".to_string(),
chain: "".to_string(),
};
let source_type = verification::SourceType::Solidity;
test_cases::test_returns_valid_source(
TEST_SUITE_NAME,
service,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2::{
solidity_verifier_server::{SolidityVerifier, SolidityVerifierServer},
sourcify_verifier_server::{SourcifyVerifier, SourcifyVerifierServer},
vyper_verifier_server::{VyperVerifier, VyperVerifierServer},
ListCompilerVersionsRequest, ListCompilerVersionsResponse, VerifyResponse,
VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest, VerifySourcifyRequest,
VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
ListCompilerVersionsRequest, ListCompilerVersionsResponse, VerifyFromEtherscanSourcifyRequest,
VerifyResponse, VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest,
VerifySourcifyRequest, VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
};
use std::net::SocketAddr;
use tokio::net::TcpListener;
Expand Down Expand Up @@ -47,6 +47,8 @@ mock! {
#[async_trait::async_trait]
impl SourcifyVerifier for SourcifyVerifierService {
async fn verify(&self, request: tonic::Request<VerifySourcifyRequest>) -> Result<tonic::Response<VerifyResponse>, tonic::Status>;

async fn verify_from_etherscan(&self, request: tonic::Request<VerifyFromEtherscanSourcifyRequest>) -> Result<tonic::Response<VerifyResponse>, tonic::Status>;
}
}

Expand Down
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 @@ -28,7 +28,7 @@ reqwest = "0.11.18"
semver = "1.0"
serde = "1.0"
serde_json = "1.0"
smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "52c41ec" }
smart-contract-verifier-proto = { git = "https://github.com/blockscout/blockscout-rs", rev = "e003306" }
solidity-metadata = "1.0"
thiserror = "1.0"
tokio = "1.22"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod compiler_versions;
pub mod solidity_multi_part;
pub mod solidity_standard_json;
pub mod sourcify;
pub mod sourcify_from_etherscan;
pub mod vyper_multi_part;
pub mod vyper_standard_json;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::{
super::{
client::Client, errors::Error, smart_contract_verifier::VerifyFromEtherscanSourcifyRequest,
types::Source,
},
process_verify_response, ProcessResponseAction,
};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct VerificationRequest {
pub address: String,
pub chain: String,
}

impl From<VerificationRequest> for VerifyFromEtherscanSourcifyRequest {
fn from(request: VerificationRequest) -> Self {
VerifyFromEtherscanSourcifyRequest {
address: request.address,
chain: request.chain,
}
}
}

pub async fn verify(mut client: Client, request: VerificationRequest) -> Result<Source, Error> {
let request: VerifyFromEtherscanSourcifyRequest = request.into();
let response = client
.sourcify_client
.verify_from_etherscan(request)
.await
.map_err(Error::from)?
.into_inner();

process_verify_response(&client.db_client, response, ProcessResponseAction::IgnoreDb).await
}
4 changes: 2 additions & 2 deletions eth-bytecode-db/eth-bytecode-db/src/verification/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ mod types;
pub use client::Client;
pub use errors::Error;
pub use handlers::{
compiler_versions, solidity_multi_part, solidity_standard_json, sourcify, vyper_multi_part,
vyper_standard_json,
compiler_versions, solidity_multi_part, solidity_standard_json, sourcify,
sourcify_from_etherscan, vyper_multi_part, vyper_standard_json,
};
pub use types::{
BytecodePart, BytecodeType, MatchType, Source, SourceType, VerificationMetadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2::
sourcify_verifier_client,
verify_response::{extra_data::BytecodePart, Status},
vyper_verifier_client, BytecodeType, ListCompilerVersionsRequest, ListCompilerVersionsResponse,
VerificationMetadata, VerifyResponse, VerifySolidityMultiPartRequest,
VerifySolidityStandardJsonRequest, VerifySourcifyRequest, VerifyVyperMultiPartRequest,
VerifyVyperStandardJsonRequest,
VerificationMetadata, VerifyFromEtherscanSourcifyRequest, VerifyResponse,
VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest, VerifySourcifyRequest,
VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
};
64 changes: 64 additions & 0 deletions eth-bytecode-db/eth-bytecode-db/tests/sourcify_from_etherscan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
mod verification_test_helpers;

use async_trait::async_trait;
use eth_bytecode_db::verification::{
sourcify_from_etherscan, sourcify_from_etherscan::VerificationRequest, Client, Error, Source,
SourceType, VerificationMetadata,
};
use rstest::{fixture, rstest};
use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2::{
VerifyFromEtherscanSourcifyRequest, VerifyResponse,
};
use tonic::Response;
use verification_test_helpers::{
smart_contract_veriifer_mock::{MockSourcifyVerifierService, SmartContractVerifierServer},
VerifierService,
};

const DB_PREFIX: &str = "sourcify_from_etherscan";

#[async_trait]
impl VerifierService<VerificationRequest> for MockSourcifyVerifierService {
type GrpcT = VerifyFromEtherscanSourcifyRequest;

fn add_into_service(&mut self, request: Self::GrpcT, response: VerifyResponse) {
self.expect_verify_from_etherscan()
.withf(move |arg| arg.get_ref() == &request)
.returning(move |_| Ok(Response::new(response.clone())));
}

fn build_server(self) -> SmartContractVerifierServer {
SmartContractVerifierServer::new().sourcify_service(self)
}

fn generate_request(
&self,
_id: u8,
_metadata: Option<VerificationMetadata>,
) -> VerificationRequest {
VerificationRequest {
address: "0x1234".to_string(),
chain: "77".to_string(),
}
}

fn source_type(&self) -> SourceType {
SourceType::Solidity
}

async fn verify(client: Client, request: VerificationRequest) -> Result<Source, Error> {
sourcify_from_etherscan::verify(client, request).await
}
}

#[fixture]
fn service() -> MockSourcifyVerifierService {
MockSourcifyVerifierService::new()
}

#[rstest]
#[tokio::test]
#[ignore = "Needs database to run"]
async fn returns_valid_source(service: MockSourcifyVerifierService) {
verification_test_helpers::test_returns_valid_source(DB_PREFIX, service).await
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use smart_contract_verifier_proto::blockscout::smart_contract_verifier::v2::{
solidity_verifier_server::{SolidityVerifier, SolidityVerifierServer},
sourcify_verifier_server::{SourcifyVerifier, SourcifyVerifierServer},
vyper_verifier_server::{VyperVerifier, VyperVerifierServer},
ListCompilerVersionsRequest, ListCompilerVersionsResponse, VerifyResponse,
VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest, VerifySourcifyRequest,
VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
ListCompilerVersionsRequest, ListCompilerVersionsResponse, VerifyFromEtherscanSourcifyRequest,
VerifyResponse, VerifySolidityMultiPartRequest, VerifySolidityStandardJsonRequest,
VerifySourcifyRequest, VerifyVyperMultiPartRequest, VerifyVyperStandardJsonRequest,
};
use std::net::SocketAddr;
use tokio::net::TcpListener;
Expand Down Expand Up @@ -47,6 +47,8 @@ mock! {
#[async_trait::async_trait]
impl SourcifyVerifier for SourcifyVerifierService {
async fn verify(&self, request: tonic::Request<VerifySourcifyRequest>) -> Result<tonic::Response<VerifyResponse>, tonic::Status>;

async fn verify_from_etherscan(&self, request: tonic::Request<VerifyFromEtherscanSourcifyRequest>) -> Result<tonic::Response<VerifyResponse>, tonic::Status>;
}
}

Expand Down
Loading