Skip to content

Commit cd048db

Browse files
Move basic EVM test from end-to-end test to linera-execution. (#4112)
## Motivation Some of the EVM tests are in `linera-service` as end-to-end test when they can be usefully moved to `linera-execution`. ## Proposal This corresponds to the `test_evm_end_to_end_basic_check`. All the other remaining tests in `linera-service` for REVM require the use of end-to-end tests and cannot be moved to `linera-execution`. ## Test Plan The CI. ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links None.
1 parent d9fee81 commit cd048db

File tree

4 files changed

+140
-78
lines changed

4 files changed

+140
-78
lines changed

linera-execution/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ revm = [
2626
"dep:alloy-sol-types",
2727
"dep:hex",
2828
"dep:tempfile",
29+
"linera-base/revm",
2930
]
3031
fs = ["tokio/fs"]
3132
metrics = ["prometheus", "linera-views/metrics"]

linera-execution/tests/revm.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,142 @@ async fn test_terminate_query_by_lack_of_fuel() -> anyhow::Result<()> {
328328

329329
Ok(())
330330
}
331+
332+
#[tokio::test]
333+
async fn test_basic_evm_features() -> anyhow::Result<()> {
334+
let module = load_solidity_example("tests/fixtures/evm_basic_check.sol")?;
335+
336+
sol! {
337+
function failing_function();
338+
function test_precompile_sha256();
339+
function check_contract_address(address evm_address);
340+
}
341+
342+
let constructor_argument = Vec::<u8>::new();
343+
let constructor_argument = serde_json::to_string(&constructor_argument)?.into_bytes();
344+
let instantiation_argument = Vec::<u8>::new();
345+
let instantiation_argument = serde_json::to_string(&instantiation_argument)?.into_bytes();
346+
let state = SystemExecutionState {
347+
description: Some(dummy_chain_description(0)),
348+
..Default::default()
349+
};
350+
let (mut app_desc, contract_blob, service_blob) = create_dummy_user_application_description(1);
351+
app_desc.parameters = constructor_argument;
352+
let chain_id = app_desc.creator_chain_id;
353+
let mut view = state
354+
.into_view_with(chain_id, ExecutionRuntimeConfig::default())
355+
.await;
356+
let app_id = From::from(&app_desc);
357+
let app_desc_blob_id = Blob::new_application_description(&app_desc).id();
358+
let contract_blob_id = contract_blob.id();
359+
let service_blob_id = service_blob.id();
360+
361+
let contract = EvmContractModule::Revm {
362+
module: module.clone(),
363+
};
364+
view.context()
365+
.extra()
366+
.user_contracts()
367+
.insert(app_id, contract.clone().into());
368+
369+
let service = EvmServiceModule::Revm { module };
370+
view.context()
371+
.extra()
372+
.user_services()
373+
.insert(app_id, service.into());
374+
375+
view.simulate_instantiation(
376+
contract.into(),
377+
Timestamp::from(2),
378+
app_desc,
379+
instantiation_argument,
380+
contract_blob,
381+
service_blob,
382+
)
383+
.await?;
384+
385+
let operation_context = OperationContext {
386+
chain_id,
387+
height: BlockHeight(0),
388+
round: Some(0),
389+
authenticated_signer: None,
390+
authenticated_caller_id: None,
391+
timestamp: Default::default(),
392+
};
393+
394+
let policy = ResourceControlPolicy {
395+
evm_fuel_unit: Amount::from_attos(1),
396+
maximum_evm_fuel_per_block: 20000,
397+
..ResourceControlPolicy::default()
398+
};
399+
let mut controller =
400+
ResourceController::new(Arc::new(policy), ResourceTracker::default(), None);
401+
let mut txn_tracker = TransactionTracker::new_replaying_blobs([
402+
app_desc_blob_id,
403+
contract_blob_id,
404+
service_blob_id,
405+
]);
406+
let query_context = QueryContext {
407+
chain_id,
408+
next_block_height: BlockHeight(0),
409+
local_time: Timestamp::from(0),
410+
};
411+
412+
// Trying a failing function, should be an error
413+
let operation = failing_functionCall {};
414+
let bytes = operation.abi_encode();
415+
let operation = Operation::User {
416+
application_id: app_id,
417+
bytes,
418+
};
419+
let result = view
420+
.execute_operation(
421+
operation_context,
422+
operation,
423+
&mut txn_tracker,
424+
&mut controller,
425+
)
426+
.await;
427+
assert!(result.is_err());
428+
429+
// Trying a call to an ethereum precompile function
430+
let query = test_precompile_sha256Call {};
431+
let query = query.abi_encode();
432+
let query = EvmQuery::Query(query);
433+
let bytes = serde_json::to_vec(&query)?;
434+
435+
let query = Query::User {
436+
application_id: app_id,
437+
bytes,
438+
};
439+
440+
let result = view.query_application(query_context, query, None).await?;
441+
442+
let QueryResponse::User(result) = result.response else {
443+
anyhow::bail!("Wrong QueryResponse result");
444+
};
445+
let result: serde_json::Value = serde_json::from_slice(&result).unwrap();
446+
assert_eq!(read_evm_u64_entry(result), 0);
447+
448+
// Testing that the created contract has the right address
449+
let evm_address = app_id.evm_address();
450+
let query = check_contract_addressCall { evm_address };
451+
let query = query.abi_encode();
452+
let query = EvmQuery::Query(query);
453+
let bytes = serde_json::to_vec(&query)?;
454+
455+
let query = Query::User {
456+
application_id: app_id,
457+
bytes,
458+
};
459+
460+
let result = view.query_application(query_context, query, None).await?;
461+
462+
let QueryResponse::User(result) = result.response else {
463+
anyhow::bail!("Wrong QueryResponse result");
464+
};
465+
let result: serde_json::Value = serde_json::from_slice(&result).unwrap();
466+
assert_eq!(read_evm_u64_entry(result), 49);
467+
468+
Ok(())
469+
}

linera-service/tests/linera_net_tests.rs

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -330,84 +330,6 @@ impl AmmApp {
330330
}
331331
}
332332

333-
#[cfg(with_revm)]
334-
#[cfg_attr(feature = "storage-service", test_case(LocalNetConfig::new_test(Database::Service, Network::Grpc) ; "storage_test_service_grpc"))]
335-
#[cfg_attr(feature = "scylladb", test_case(LocalNetConfig::new_test(Database::ScyllaDb, Network::Grpc) ; "scylladb_grpc"))]
336-
#[cfg_attr(feature = "dynamodb", test_case(LocalNetConfig::new_test(Database::DynamoDb, Network::Grpc) ; "aws_grpc"))]
337-
#[cfg_attr(feature = "kubernetes", test_case(SharedLocalKubernetesNetTestingConfig::new(Network::Grpc, BuildArg::Build) ; "kubernetes_grpc"))]
338-
#[cfg_attr(feature = "remote-net", test_case(RemoteNetTestingConfig::new(None) ; "remote_net_grpc"))]
339-
#[test_log::test(tokio::test)]
340-
async fn test_evm_end_to_end_basic_check(config: impl LineraNetConfig) -> Result<()> {
341-
use alloy_sol_types::{sol, SolCall};
342-
use linera_base::vm::EvmQuery;
343-
use linera_execution::test_utils::solidity::{get_evm_contract_path, read_evm_u64_entry};
344-
use linera_sdk::abis::evm::EvmAbi;
345-
let _guard = INTEGRATION_TEST_GUARD.lock().await;
346-
tracing::info!("Starting test {}", test_name!());
347-
348-
let (mut net, client) = config.instantiate().await?;
349-
350-
sol! {
351-
function failing_function();
352-
function test_precompile_sha256();
353-
function check_contract_address(address evm_address);
354-
}
355-
let chain = client.load_wallet()?.default_chain().unwrap();
356-
357-
let (evm_contract, _dir) = get_evm_contract_path("tests/fixtures/evm_basic_check.sol")?;
358-
359-
let constructor_argument = Vec::new();
360-
let instantiation_argument = Vec::new();
361-
let application_id = client
362-
.publish_and_create::<EvmAbi, Vec<u8>, Vec<u8>>(
363-
evm_contract.clone(),
364-
evm_contract,
365-
VmRuntime::Evm,
366-
&constructor_argument,
367-
&instantiation_argument,
368-
&[],
369-
None,
370-
)
371-
.await?;
372-
373-
let evm_address = application_id.evm_address();
374-
375-
let port = get_node_port().await;
376-
let mut node_service = client.run_node_service(port, ProcessInbox::Skip).await?;
377-
378-
let application = node_service
379-
.make_application(&chain, &application_id)
380-
.await?;
381-
382-
// Checking that failing function lead to an error
383-
let failing_function = failing_functionCall {};
384-
let failing_function = failing_function.abi_encode();
385-
let failing_function = EvmQuery::Query(failing_function);
386-
let result = application.run_json_query(failing_function).await;
387-
assert!(result.is_err());
388-
389-
// Checking that failing function lead to an error
390-
let test_sha256 = test_precompile_sha256Call {};
391-
let test_sha256 = test_sha256.abi_encode();
392-
let test_sha256 = EvmQuery::Query(test_sha256);
393-
let result = application.run_json_query(test_sha256).await?;
394-
assert_eq!(read_evm_u64_entry(result), 0);
395-
396-
// Checking that the EVM contract address matches the one of Linera
397-
let check_contract_address = check_contract_addressCall { evm_address };
398-
let check_contract_address = check_contract_address.abi_encode();
399-
let check_contract_address = EvmQuery::Query(check_contract_address);
400-
let result = application.run_json_query(check_contract_address).await?;
401-
assert_eq!(read_evm_u64_entry(result), 49);
402-
403-
node_service.ensure_is_running()?;
404-
405-
net.ensure_is_running().await?;
406-
net.terminate().await?;
407-
408-
Ok(())
409-
}
410-
411333
#[cfg(with_revm)]
412334
#[cfg_attr(feature = "storage-service", test_case(LocalNetConfig::new_test(Database::Service, Network::Grpc) ; "storage_test_service_grpc"))]
413335
#[cfg_attr(feature = "scylladb", test_case(LocalNetConfig::new_test(Database::ScyllaDb, Network::Grpc) ; "scylladb_grpc"))]

0 commit comments

Comments
 (0)