Skip to content

Commit

Permalink
eth-bytecode-db: update values in the database if they have already e…
Browse files Browse the repository at this point in the history
…xisted (#662)

* Make eth-bytecode-db to update values in the database if they have already existed

* Add warning in case if the model has been updated
  • Loading branch information
rimrakhimov authored Nov 3, 2023
1 parent 3a3917c commit a355700
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,28 @@ async fn test_accepts_partial_verification_metadata_in_input() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_update_source_then_search() {
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_update_source_then_search::<MockSolidityVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,25 @@ async fn test_accepts_partial_verification_metadata_in_input() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_update_source_then_search() {
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_update_source_then_search::<MockSolidityVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -383,4 +383,93 @@ pub mod test_cases {
serde_json::json!({ "contractAddress": "0x0123456789012345678901234567890123456789" });
validate(metadata).await;
}

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

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

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

let _verification_response: eth_bytecode_db_v2::VerifyResponse =
test_server::send_post_request(&eth_bytecode_db_base, route, &verification_request)
.await;
}

let updated_test_data = {
let test_input_data::TestInputData {
verifier_response,
mut eth_bytecode_db_response,
} = test_input_data::basic(source_type, MatchType::Full);
if let Some(source) = eth_bytecode_db_response.source.as_mut() {
let mut compilation_artifacts: serde_json::Value =
serde_json::from_str(source.compilation_artifacts()).unwrap();
compilation_artifacts
.as_object_mut()
.unwrap()
.insert("additionalValue".to_string(), serde_json::Value::default());
source.compilation_artifacts = Some(compilation_artifacts.to_string());
}

test_input_data::TestInputData::from_source_and_extra_data(
eth_bytecode_db_response.source.unwrap(),
verifier_response.extra_data.unwrap(),
)
};

let creation_input = updated_test_data.creation_input().unwrap();

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

let verification_response: eth_bytecode_db_v2::VerifyResponse =
test_server::send_post_request(&eth_bytecode_db_base, route, &verification_request)
.await;

assert_eq!(
verification_response, updated_test_data.eth_bytecode_db_response,
"Invalid verification response"
);

let creation_input_search_response: eth_bytecode_db_v2::SearchSourcesResponse = {
let request = {
eth_bytecode_db_v2::SearchSourcesRequest {
bytecode: creation_input,
bytecode_type: eth_bytecode_db_v2::BytecodeType::CreationInput.into(),
}
};

test_server::send_annotated_post_request(
&eth_bytecode_db_base,
DB_SEARCH_ROUTE,
&request,
"Creation input search",
)
.await
};

assert_eq!(
1,
creation_input_search_response.sources.len(),
"Invalid number of sources returned"
);
assert_eq!(
verification_response.source.unwrap(),
creation_input_search_response.sources[0],
"Sources returned on verification and search differ"
);
}
}
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 @@ -156,3 +156,27 @@ async fn test_accepts_partial_verification_metadata_in_input() {
)
.await;
}

#[rstest]
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_update_source_then_search() {
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_update_source_then_search::<MockVyperVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
source_type,
)
.await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ async fn test_search_returns_full_matches_only_if_any() {
#[tokio::test]
#[timeout(std::time::Duration::from_secs(60))]
#[ignore = "Needs database to run"]
async fn test_accepts_partial_verification_metadata_in_input() {
async fn test_update_source_then_search() {
let default_request = VerifyVyperStandardJsonRequest {
bytecode: "".to_string(),
bytecode_type: BytecodeType::CreationInput.into(),
Expand All @@ -138,7 +138,7 @@ async fn test_accepts_partial_verification_metadata_in_input() {
metadata: None,
};
let source_type = verification::SourceType::Vyper;
test_cases::test_accepts_partial_verification_metadata_in_input::<MockVyperVerifierService, _>(
test_cases::test_update_source_then_search::<MockVyperVerifierService, _>(
TEST_SUITE_NAME,
ROUTE,
default_request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,13 @@ async fn insert_files(
content: Set(content.clone()),
..Default::default()
};
let (file, _inserted) =
insert_then_select!(txn, files, active_model, [(Name, name), (Content, content)])?;
let (file, _inserted) = insert_then_select!(
txn,
files,
active_model,
true,
[(Name, name), (Content, content)]
)?;

result.push(file);
}
Expand Down Expand Up @@ -165,6 +170,7 @@ async fn insert_source_details(
txn,
sources,
active_model,
true,
[
(CompilerVersion, source.compiler_version),
(CompilerSettings, source.compiler_settings),
Expand Down Expand Up @@ -214,6 +220,7 @@ async fn insert_bytecodes(
txn,
bytecodes,
active_model,
true,
[(SourceId, source_id), (BytecodeType, bytecode_type)]
)?;
bytecode
Expand All @@ -232,6 +239,7 @@ async fn insert_bytecodes(
txn,
parts,
active_model,
true,
[(Data, part.data()), (PartType, part_type)]
)?;
part
Expand Down
44 changes: 34 additions & 10 deletions eth-bytecode-db/eth-bytecode-db/src/verification/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ pub mod verifier_alliance_db;
////////////////////////////////////////////////////////////////////////////////////////////

macro_rules! insert_then_select {
( $txn:expr, $entity_module:ident, $active_model:expr, [ $( ($column:ident, $value:expr) ),+ $(,)? ] ) => {
( $txn:expr, $entity_module:ident, $active_model:expr, $update_on_conflict:expr, [ $( ($column:ident, $value:expr) ),+ $(,)? ] ) => {
{
let result: Result<_, sea_orm::DbErr> = $entity_module::Entity::insert($active_model)
let result: Result<_, sea_orm::DbErr> = $entity_module::Entity::insert($active_model.clone())
.on_conflict(sea_orm::sea_query::OnConflict::new().do_nothing().to_owned())
.exec($txn)
.await;
Expand All @@ -28,14 +28,38 @@ macro_rules! insert_then_select {
Ok((model, true))
}
Err(sea_orm::DbErr::RecordNotInserted) => {
let model = $entity_module::Entity::find()
$(
.filter($entity_module::Column::$column.eq($value))
)*
.one($txn)
.await
.context(format!("select from \"{}\" by unique columns", stringify!($entity_module)))?
.ok_or(anyhow::anyhow!("select from \"{}\" by unique columns returned no data", stringify!($entity_module)))?;
let mut model =
$entity_module::Entity::find()
$(
.filter($entity_module::Column::$column.eq($value))
)*
.one($txn)
.await
.context(format!("select from \"{}\" by unique columns", stringify!($entity_module)))?
.ok_or(anyhow::anyhow!("select from \"{}\" by unique columns returned no data", stringify!($entity_module)))?;
// The active model have not been inserted.
// Thus, there were a value already that we need to update.
if $update_on_conflict {
let mut active_model_to_update = $active_model;
for primary_key in <$entity_module::PrimaryKey as sea_orm::Iterable>::iter() {
let column = sea_orm::PrimaryKeyToColumn::into_column(primary_key);
let value = sea_orm::ModelTrait::get(&model, column);
sea_orm::ActiveModelTrait::set(&mut active_model_to_update, column, value);
}
let updated_model = sea_orm::ActiveModelTrait::update(
active_model_to_update, $txn
).await.context(format!("update on conflict in \"{}\"", stringify!($entity_module)))?;

if updated_model != model {
tracing::warn!(
model=?model,
updated_model=?updated_model,
"the \"{}\" model has been updated",
stringify!($entity_module)
);
model = updated_model;
}
}

Ok((model, false))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ async fn insert_verified_contract(
txn,
verified_contracts,
active_model,
false,
[
(CompilationId, compiled_contract.id),
(ContractId, contract.id),
Expand Down Expand Up @@ -274,6 +275,7 @@ async fn insert_compiled_contract(
txn,
compiled_contracts,
active_model,
false,
[
(Compiler, compiler),
(Language, language),
Expand Down Expand Up @@ -304,6 +306,7 @@ async fn insert_contract_deployment(
txn,
contract_deployments,
active_model,
false,
[
(ChainId, deployment_data.chain_id),
(Address, deployment_data.contract_address),
Expand Down Expand Up @@ -355,6 +358,7 @@ async fn insert_contract(
txn,
contracts,
active_model,
false,
[
(CreationCodeHash, creation_code_hash),
(RuntimeCodeHash, runtime_code_hash)
Expand All @@ -374,8 +378,13 @@ async fn insert_code(
code_hash: Set(code_hash.0.to_vec()),
code: Set(Some(code)),
};
let (code, _inserted) =
insert_then_select!(txn, code, active_model, [(CodeHash, code_hash.0.to_vec())])?;
let (code, _inserted) = insert_then_select!(
txn,
code,
active_model,
false,
[(CodeHash, code_hash.0.to_vec())]
)?;

Ok(code)
}
10 changes: 10 additions & 0 deletions eth-bytecode-db/eth-bytecode-db/tests/solidity_multi_part.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,13 @@ async fn test_verification_of_same_source_results_stored_once(
)
.await;
}

#[rstest]
#[tokio::test]
#[ignore = "Needs database to run"]
async fn test_verification_of_updated_source_replace_the_old_result() {
verification_test_helpers::test_verification_of_updated_source_replace_the_old_result(
DB_PREFIX, service,
)
.await;
}
10 changes: 10 additions & 0 deletions eth-bytecode-db/eth-bytecode-db/tests/solidity_standard_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,13 @@ async fn test_verification_of_same_source_results_stored_once(
)
.await;
}

#[rstest]
#[tokio::test]
#[ignore = "Needs database to run"]
async fn test_verification_of_updated_source_replace_the_old_result() {
verification_test_helpers::test_verification_of_updated_source_replace_the_old_result(
DB_PREFIX, service,
)
.await;
}
Loading

0 comments on commit a355700

Please sign in to comment.