diff --git a/src/memory.rs b/src/memory.rs index 56dc8bb6..993e5644 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -4,7 +4,7 @@ use crate::{ types::{ApiKey, Metrics, OverrideProvider, ProviderId, StorableLogFilter}, }; use candid::Principal; -use canhttp::http::json::Id; +use canhttp::http::json::{ConstantSizeId, Id}; use canhttp::multi::Timestamp; use canlog::LogFilter; use ic_stable_structures::memory_manager::VirtualMemory; @@ -27,7 +27,7 @@ type StableMemory = VirtualMemory; thread_local! { // Unstable static data: these are reset when the canister is upgraded. pub static UNSTABLE_METRICS: RefCell = RefCell::new(Metrics::default()); - static UNSTABLE_HTTP_REQUEST_COUNTER: RefCell = const {RefCell::new(0)}; + static UNSTABLE_HTTP_REQUEST_COUNTER: RefCell = const {RefCell::new(ConstantSizeId::ZERO)}; static UNSTABLE_RPC_SERVICE_OK_RESULTS_TIMESTAMPS: RefCell = RefCell::new(SupportedRpcServiceUsage::default()); // Stable static data: these are preserved when the canister is upgraded. @@ -113,10 +113,7 @@ pub fn set_override_provider(provider: OverrideProvider) { pub fn next_request_id() -> Id { UNSTABLE_HTTP_REQUEST_COUNTER.with_borrow_mut(|counter| { - let current_request_id = *counter; - // overflow is not an issue here because we only use `next_request_id` to correlate - // requests and responses in logs. - *counter = counter.wrapping_add(1); + let current_request_id = counter.get_and_increment(); Id::from(current_request_id) }) } diff --git a/tests/mock_http_runtime/mock/json/mod.rs b/tests/mock_http_runtime/mock/json/mod.rs index 960691a4..d512302f 100644 --- a/tests/mock_http_runtime/mock/json/mod.rs +++ b/tests/mock_http_runtime/mock/json/mod.rs @@ -2,7 +2,7 @@ mod tests; use crate::mock_http_runtime::mock::CanisterHttpRequestMatcher; -use canhttp::http::json::{Id, JsonRpcRequest}; +use canhttp::http::json::{ConstantSizeId, Id, JsonRpcRequest}; use pocket_ic::common::rest::{ CanisterHttpHeader, CanisterHttpMethod, CanisterHttpReply, CanisterHttpRequest, CanisterHttpResponse, @@ -35,9 +35,13 @@ impl JsonRpcRequestMatcher { } } - pub fn with_id(self, id: impl Into) -> Self { + pub fn with_id(self, id: u64) -> Self { + self.with_raw_id(Id::from(ConstantSizeId::from(id))) + } + + pub fn with_raw_id(self, id: Id) -> Self { Self { - id: Some(id.into()), + id: Some(id), ..self } } @@ -164,8 +168,12 @@ impl From for JsonRpcResponse { } impl JsonRpcResponse { - pub fn with_id(mut self, id: impl Into) -> JsonRpcResponse { - self.body["id"] = serde_json::to_value(id.into()).expect("BUG: cannot serialize ID"); + pub fn with_id(self, id: u64) -> JsonRpcResponse { + self.with_raw_id(Id::from(ConstantSizeId::from(id))) + } + + pub fn with_raw_id(mut self, id: Id) -> JsonRpcResponse { + self.body["id"] = serde_json::to_value(id).expect("BUG: cannot serialize ID"); self } } diff --git a/tests/mock_http_runtime/mock/json/tests.rs b/tests/mock_http_runtime/mock/json/tests.rs index 379c42cd..743173d9 100644 --- a/tests/mock_http_runtime/mock/json/tests.rs +++ b/tests/mock_http_runtime/mock/json/tests.rs @@ -1,6 +1,6 @@ use crate::mock_http_runtime::mock::{json::JsonRpcRequestMatcher, CanisterHttpRequestMatcher}; use candid::Principal; -use canhttp::http::json::Id; +use canhttp::http::json::{ConstantSizeId, Id}; use evm_rpc::constants::{CONTENT_TYPE_HEADER_LOWERCASE, CONTENT_TYPE_VALUE}; use pocket_ic::common::rest::{CanisterHttpHeader, CanisterHttpMethod, CanisterHttpRequest}; use serde_json::{json, Value}; @@ -32,7 +32,7 @@ mod json_rpc_request_matcher_tests { #[test] fn should_not_match_wrong_id() { - assert!(!request_matcher().with_id(Id::Null).matches(&request())); + assert!(!request_matcher().with_raw_id(Id::Null).matches(&request())); } #[test] @@ -128,7 +128,7 @@ fn request() -> CanisterHttpRequest { body: serde_json::to_vec(&json!({ "jsonrpc": "2.0", "method": DEFAULT_RPC_METHOD, - "id": DEFAULT_RPC_ID, + "id": ConstantSizeId::from(DEFAULT_RPC_ID).to_string(), "params": DEFAULT_RPC_PARAMS, })) .unwrap(), diff --git a/tests/tests.rs b/tests/tests.rs index e5a65314..f79b9bfb 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -12,7 +12,7 @@ use alloy_primitives::{address, b256, bloom, bytes, Address, Bytes, FixedBytes, use alloy_rpc_types::{BlockNumberOrTag, BlockTransactions}; use assert_matches::assert_matches; use candid::{Encode, Principal}; -use canhttp::http::json::Id; +use canhttp::http::json::{ConstantSizeId, Id}; use evm_rpc_client::{DoubleCycles, NoRetry}; use evm_rpc_types::{ BlockTag, ConsensusStrategy, EthMainnetService, EthSepoliaService, GetLogsRpcConfig, Hex, @@ -81,7 +81,7 @@ async fn should_canonicalize_request_endpoint_response() { .given( JsonRpcRequestMatcher::with_method(MOCK_REQUEST_METHOD) .with_params(MOCK_REQUEST_PARAMS) - .with_id(MOCK_REQUEST_ID), + .with_raw_id(MOCK_REQUEST_ID), ) .respond_with(JsonRpcResponse::from(response)); let result = setup @@ -109,7 +109,7 @@ async fn should_not_modify_json_rpc_request_from_request_endpoint() { let mock_request = r#"{"id":123,"jsonrpc":"2.0","method":"eth_gasPrice"}"#; let mock_response = r#"{"jsonrpc":"2.0","id":123,"result":"0x00112233"}"#; let mocks = MockHttpOutcallsBuilder::new() - .given(JsonRpcRequestMatcher::with_method("eth_gasPrice").with_id(123_u64)) + .given(JsonRpcRequestMatcher::with_method("eth_gasPrice").with_raw_id(Id::Number(123))) .respond_with(JsonRpcResponse::from(mock_response)); let setup = EvmRpcSetup::new().await.mock_api_keys().await; @@ -149,7 +149,7 @@ async fn multi_request_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for source in RPC_SERVICES { let candid_result = setup @@ -158,7 +158,7 @@ async fn multi_request_should_succeed() { .with_candid() .build() .multi_request(json!({ - "id": 0, + "id" : ConstantSizeId::ZERO.to_string(), "jsonrpc": "2.0", "method": "eth_gasPrice", })) @@ -172,7 +172,7 @@ async fn multi_request_should_succeed() { .with_rpc_sources(source.clone()) .build() .multi_request(json!({ - "id": 0, + "id" : ConstantSizeId::ZERO.to_string(), "jsonrpc": "2.0", "method": "eth_gasPrice", })) @@ -231,7 +231,7 @@ async fn eth_get_logs_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for source in RPC_SERVICES { for (config, from_block, to_block) in [ @@ -371,7 +371,7 @@ async fn eth_get_block_by_number_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for source in RPC_SERVICES { let candid_result = setup @@ -430,7 +430,7 @@ async fn eth_get_block_by_number_pre_london_fork_should_succeed() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; - for (source, offset) in iter::zip(RPC_SERVICES, (0_u64..).step_by(3)) { + for (source, offset) in iter::zip(RPC_SERVICES, (0..).step_by(3)) { let mocks = MockHttpOutcallsBuilder::new() .given(get_block_by_number_request().with_id(offset)) .respond_with(mock_response().with_id(offset)) @@ -523,10 +523,10 @@ async fn eth_get_block_by_number_should_be_consistent_when_total_difficulty_inco let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_block_by_number_request().with_id(0_u64)) - .respond_with(mock_response(Some("0xc70d815d562d3cfa955")).with_id(0_u64)) - .given(get_block_by_number_request().with_id(1_u64)) - .respond_with(mock_response(None).with_id(1_u64)); + .given(get_block_by_number_request().with_id(0)) + .respond_with(mock_response(Some("0xc70d815d562d3cfa955")).with_id(0)) + .given(get_block_by_number_request().with_id(1)) + .respond_with(mock_response(None).with_id(1)); let response = setup .client(mocks) @@ -691,7 +691,7 @@ async fn eth_get_transaction_receipt_should_succeed() { ]; let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for (tx_hash, response, candid_receipt) in test_cases { for source in RPC_SERVICES { @@ -737,7 +737,7 @@ async fn eth_get_transaction_count_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for source in RPC_SERVICES { let candid_result = setup @@ -796,7 +796,7 @@ async fn eth_fee_history_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for source in RPC_SERVICES { let candid_result = setup @@ -838,7 +838,7 @@ async fn eth_send_raw_transaction_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for source in RPC_SERVICES { let candid_result = setup @@ -888,7 +888,7 @@ async fn eth_call_should_succeed() { } let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let mut offsets = (0_u64..).step_by(3); + let mut offsets = (0..).step_by(3); for block in [ Some(BlockTag::Latest), @@ -934,7 +934,7 @@ async fn candid_rpc_should_allow_unexpected_response_fields() { fn mock_response() -> JsonRpcResponse { JsonRpcResponse::from(json!({ "jsonrpc":"2.0", - "id": 0, + "id" : ConstantSizeId::ZERO.to_string(), "result":{ "unexpectedKey":"unexpectedValue", "blockHash": "0x5115c07eb1f20a9d6410db0916ed3df626cfdab161d3904f45c8c8b65c90d0be", @@ -958,12 +958,12 @@ async fn candid_rpc_should_allow_unexpected_response_fields() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_transaction_receipt_request().with_id(0_u64)) - .respond_with(mock_response().with_id(0_u64)) - .given(get_transaction_receipt_request().with_id(1_u64)) - .respond_with(mock_response().with_id(1_u64)) - .given(get_transaction_receipt_request().with_id(2_u64)) - .respond_with(mock_response().with_id(2_u64)); + .given(get_transaction_receipt_request().with_id(0)) + .respond_with(mock_response().with_id(0)) + .given(get_transaction_receipt_request().with_id(1)) + .respond_with(mock_response().with_id(1)) + .given(get_transaction_receipt_request().with_id(2)) + .respond_with(mock_response().with_id(2)); let response = setup .client(mocks) @@ -1017,11 +1017,11 @@ async fn candid_rpc_should_err_without_cycles() { async fn candid_rpc_should_err_when_service_unavailable() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_transaction_receipt_request().with_id(0_u64)) + .given(get_transaction_receipt_request().with_id(0)) .respond_with(CanisterHttpReply::with_status(503).with_body("Service unavailable")) - .given(get_transaction_receipt_request().with_id(1_u64)) + .given(get_transaction_receipt_request().with_id(1)) .respond_with(CanisterHttpReply::with_status(503).with_body("Service unavailable")) - .given(get_transaction_receipt_request().with_id(2_u64)) + .given(get_transaction_receipt_request().with_id(2)) .respond_with(CanisterHttpReply::with_status(503).with_body("Service unavailable")); let result = setup .client(mocks) @@ -1070,10 +1070,10 @@ async fn candid_rpc_should_recognize_json_error() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_transaction_receipt_request().with_id(0_u64)) - .respond_with(mock_response().with_id(0_u64)) - .given(get_transaction_receipt_request().with_id(1_u64)) - .respond_with(mock_response().with_id(1_u64)); + .given(get_transaction_receipt_request().with_id(0)) + .respond_with(mock_response().with_id(0)) + .given(get_transaction_receipt_request().with_id(1)) + .respond_with(mock_response().with_id(1)); let result = setup .client(mocks) .with_rpc_sources(RpcServices::EthSepolia(Some(vec![ @@ -1126,14 +1126,18 @@ async fn candid_rpc_should_reject_empty_service_list() { #[tokio::test] async fn candid_rpc_should_return_inconsistent_results() { let mocks = MockHttpOutcallsBuilder::new() - .given(send_raw_transaction_request().with_id(0_u64)) - .respond_with(JsonRpcResponse::from( - json!({ "id": 0, "jsonrpc": "2.0", "result": MOCK_TRANSACTION_HASH }), - )) - .given(send_raw_transaction_request().with_id(1_u64)) - .respond_with(JsonRpcResponse::from( - json!({ "id": 1, "jsonrpc": "2.0", "result": "NonceTooLow" }), - )); + .given(send_raw_transaction_request().with_id(0)) + .respond_with(JsonRpcResponse::from(json!({ + "id": ConstantSizeId::from(0_u64).to_string(), + "jsonrpc": "2.0", + "result": MOCK_TRANSACTION_HASH + }))) + .given(send_raw_transaction_request().with_id(1)) + .respond_with(JsonRpcResponse::from(json!({ + "id": ConstantSizeId::from(1_u64).to_string(), + "jsonrpc": "2.0", + "result": "NonceTooLow" + }))); let setup = EvmRpcSetup::new().await.mock_api_keys().await; let results = setup @@ -1178,9 +1182,11 @@ async fn candid_rpc_should_return_inconsistent_results() { #[tokio::test] async fn candid_rpc_should_return_3_out_of_4_transaction_count() { fn get_transaction_count_response(result: u64) -> JsonRpcResponse { - JsonRpcResponse::from( - json!({ "jsonrpc" : "2.0", "id" : 0, "result" : format!("0x{result:x}") }), - ) + JsonRpcResponse::from(json!({ + "jsonrpc": "2.0", + "id" : ConstantSizeId::ZERO.to_string(), + "result" : format!("0x{result:x}") + })) } let setup = EvmRpcSetup::new().await.mock_api_keys().await; @@ -1218,28 +1224,28 @@ async fn candid_rpc_should_return_3_out_of_4_transaction_count() { for (successful_mocks, offset) in [ [ - get_transaction_count_response(1).with_id(0_u64).into(), - get_transaction_count_response(1).with_id(1_u64).into(), - get_transaction_count_response(1).with_id(2_u64).into(), - get_transaction_count_response(1).with_id(3_u64).into(), + get_transaction_count_response(1).with_id(0).into(), + get_transaction_count_response(1).with_id(1).into(), + get_transaction_count_response(1).with_id(2).into(), + get_transaction_count_response(1).with_id(3).into(), ], [ - get_transaction_count_response(1).with_id(4_u64).into(), + get_transaction_count_response(1).with_id(4).into(), CanisterHttpReply::with_status(500) .with_body("OFFLINE") .into(), - get_transaction_count_response(1).with_id(6_u64).into(), - get_transaction_count_response(1).with_id(7_u64).into(), + get_transaction_count_response(1).with_id(6).into(), + get_transaction_count_response(1).with_id(7).into(), ], [ - get_transaction_count_response(1).with_id(8_u64).into(), - get_transaction_count_response(1).with_id(9_u64).into(), - get_transaction_count_response(2).with_id(10_u64).into(), - get_transaction_count_response(1).with_id(11_u64).into(), + get_transaction_count_response(1).with_id(8).into(), + get_transaction_count_response(1).with_id(9).into(), + get_transaction_count_response(2).with_id(10).into(), + get_transaction_count_response(1).with_id(11).into(), ], ] .into_iter() - .zip((0_u64..).step_by(4)) + .zip((0..).step_by(4)) { let result = eth_get_transaction_count_with_3_out_of_4(&setup, offset, successful_mocks) .await @@ -1251,12 +1257,12 @@ async fn candid_rpc_should_return_3_out_of_4_transaction_count() { for (error_mocks, offset) in [ [ - get_transaction_count_response(1).with_id(12_u64).into(), + get_transaction_count_response(1).with_id(12).into(), CanisterHttpReply::with_status(500) .with_body("OFFLINE") .into(), get_transaction_count_response(2).into(), - get_transaction_count_response(1).with_id(15_u64).into(), + get_transaction_count_response(1).with_id(15).into(), ], [ CanisterHttpReply::with_status(500) @@ -1265,18 +1271,18 @@ async fn candid_rpc_should_return_3_out_of_4_transaction_count() { CanisterHttpReply::with_status(500) .with_body("OFFLINE") .into(), - get_transaction_count_response(1).with_id(18_u64).into(), - get_transaction_count_response(1).with_id(19_u64).into(), + get_transaction_count_response(1).with_id(18).into(), + get_transaction_count_response(1).with_id(19).into(), ], [ - get_transaction_count_response(1).with_id(20_u64).into(), - get_transaction_count_response(3).with_id(21_u64).into(), - get_transaction_count_response(2).with_id(22_u64).into(), - get_transaction_count_response(1).with_id(23_u64).into(), + get_transaction_count_response(1).with_id(20).into(), + get_transaction_count_response(3).with_id(21).into(), + get_transaction_count_response(2).with_id(22).into(), + get_transaction_count_response(1).with_id(23).into(), ], ] .into_iter() - .zip((12_u64..).step_by(4)) + .zip((12..).step_by(4)) { let result = eth_get_transaction_count_with_3_out_of_4(&setup, offset, error_mocks) .await @@ -1291,12 +1297,14 @@ async fn candid_rpc_should_return_inconsistent_results_with_error() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_transaction_count_request().with_id(0_u64)) - .respond_with(get_transaction_count_response().with_id(0_u64)) - .given(get_transaction_count_request().with_id(1_u64)) - .respond_with(JsonRpcResponse::from( - json!({"jsonrpc": "2.0", "id": 1, "error" : { "code": 123, "message": "Unexpected"} }), - )); + .given(get_transaction_count_request().with_id(0)) + .respond_with(get_transaction_count_response().with_id(0)) + .given(get_transaction_count_request().with_id(1)) + .respond_with(JsonRpcResponse::from(json!({ + "jsonrpc": "2.0", + "id": ConstantSizeId::from(1_u64).to_string(), + "error" : { "code": 123, "message": "Unexpected"} + }))); let result = setup .client(mocks) @@ -1349,14 +1357,14 @@ async fn candid_rpc_should_return_inconsistent_results_with_consensus_error() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_transaction_count_request().with_id(0_u64)) + .given(get_transaction_count_request().with_id(0)) .respond_with( CanisterHttpReject::with_reject_code(RejectCode::SysTransient) .with_message(CONSENSUS_ERROR), ) - .given(get_transaction_count_request().with_id(1_u64)) - .respond_with(get_transaction_count_response().with_id(1_u64)) - .given(get_transaction_count_request().with_id(2_u64)) + .given(get_transaction_count_request().with_id(1)) + .respond_with(get_transaction_count_response().with_id(1)) + .given(get_transaction_count_request().with_id(2)) .respond_with( CanisterHttpReject::with_reject_code(RejectCode::SysTransient) .with_message(CONSENSUS_ERROR), @@ -1415,7 +1423,7 @@ async fn should_have_metrics_for_request_endpoint() { .given( JsonRpcRequestMatcher::with_method(MOCK_REQUEST_METHOD) .with_params(MOCK_REQUEST_PARAMS) - .with_id(MOCK_REQUEST_ID), + .with_raw_id(MOCK_REQUEST_ID), ) .respond_with(JsonRpcResponse::from(MOCK_REQUEST_RESPONSE)); @@ -1450,8 +1458,8 @@ async fn should_have_metrics_for_request_endpoint() { #[tokio::test] async fn should_have_metrics_for_multi_request_endpoint() { let mocks = MockHttpOutcallsBuilder::new() - .given(JsonRpcRequestMatcher::with_method("eth_gasPrice").with_id(0_u64)) - .respond_with(JsonRpcResponse::from(MOCK_REQUEST_RESPONSE).with_id(0_u64)); + .given(JsonRpcRequestMatcher::with_method("eth_gasPrice").with_id(0)) + .respond_with(JsonRpcResponse::from(MOCK_REQUEST_RESPONSE).with_id(0)); let setup = EvmRpcSetup::new().await.mock_api_keys().await; let response = setup @@ -1461,7 +1469,7 @@ async fn should_have_metrics_for_multi_request_endpoint() { ]))) .build() .multi_request(json!({ - "id": 0, + "id" : ConstantSizeId::ZERO.to_string(), "jsonrpc": "2.0", "method": "eth_gasPrice", })) @@ -1488,9 +1496,9 @@ async fn candid_rpc_should_return_inconsistent_results_with_unexpected_http_stat let setup = EvmRpcSetup::new().await.mock_api_keys().await; let mocks = MockHttpOutcallsBuilder::new() - .given(get_transaction_count_request().with_id(0_u64)) - .respond_with(get_transaction_count_response().with_id(0_u64)) - .given(get_transaction_count_request().with_id(1_u64)) + .given(get_transaction_count_request().with_id(0)) + .respond_with(get_transaction_count_response().with_id(0)) + .given(get_transaction_count_request().with_id(1)) .respond_with(CanisterHttpReply::with_status(400).with_body( json!({"jsonrpc": "2.0", "id": 1, "error": {"code": 123, "message": "Error message"}}), )); @@ -1541,14 +1549,18 @@ async fn candid_rpc_should_return_inconsistent_results_with_unexpected_http_stat #[tokio::test] async fn candid_rpc_should_handle_already_known() { let mocks = MockHttpOutcallsBuilder::new() - .given(send_raw_transaction_request().with_id(0_u64)) - .respond_with(JsonRpcResponse::from( - json!({ "id": 0, "jsonrpc": "2.0", "result": MOCK_TRANSACTION_HASH }), - )) - .given(send_raw_transaction_request().with_id(1_u64)) - .respond_with(JsonRpcResponse::from( - json!({ "id": 1, "jsonrpc": "2.0", "error": {"code": -32000, "message": "already known"} }), - )); + .given(send_raw_transaction_request().with_id(0)) + .respond_with(JsonRpcResponse::from(json!({ + "id": ConstantSizeId::from(0_u64).to_string(), + "jsonrpc": "2.0", + "result": MOCK_TRANSACTION_HASH + }))) + .given(send_raw_transaction_request().with_id(1)) + .respond_with(JsonRpcResponse::from(json!({ + "id": ConstantSizeId::from(1_u64).to_string(), + "jsonrpc": "2.0", + "error": {"code": -32000, "message": "already known"} + }))); let setup = EvmRpcSetup::new().await.mock_api_keys().await; let result = setup @@ -1576,9 +1588,9 @@ async fn candid_rpc_should_handle_already_known() { #[tokio::test] async fn candid_rpc_should_recognize_rate_limit() { let mocks = MockHttpOutcallsBuilder::new() - .given(send_raw_transaction_request().with_id(0_u64)) + .given(send_raw_transaction_request().with_id(0)) .respond_with(CanisterHttpReply::with_status(429).with_body("(Rate limit error message)")) - .given(send_raw_transaction_request().with_id(1_u64)) + .given(send_raw_transaction_request().with_id(1)) .respond_with(CanisterHttpReply::with_status(429).with_body("(Rate limit error message)")); let setup = EvmRpcSetup::new().await.mock_api_keys().await; @@ -1623,15 +1635,15 @@ async fn should_use_custom_response_size_estimate() { .given( get_logs_request(BlockNumberOrTag::Latest, BlockNumberOrTag::Latest) .with_max_response_bytes(max_response_bytes_1) - .with_id(0_u64), + .with_id(0), ) - .respond_with(get_logs_response().with_id(0_u64)) + .respond_with(get_logs_response().with_id(0)) .given( get_logs_request(BlockNumberOrTag::Latest, BlockNumberOrTag::Latest) .with_max_response_bytes(max_response_bytes_2) - .with_id(1_u64), + .with_id(1), ) - .respond_with(get_logs_response().with_id(1_u64)); + .respond_with(get_logs_response().with_id(1)); let client = setup .client(mocks) @@ -1732,10 +1744,10 @@ async fn should_update_api_key() { MockHttpOutcallsBuilder::new() .given( get_transaction_count_request() - .with_id(0_u64) + .with_id(0) .with_url(&format!("https://rpc.ankr.com/eth/{api_key}")), ) - .respond_with(get_transaction_count_response().with_id(0_u64)), + .respond_with(get_transaction_count_response().with_id(0)), ) .with_rpc_sources(RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr]))) .build() @@ -1758,10 +1770,10 @@ async fn should_update_api_key() { MockHttpOutcallsBuilder::new() .given( get_transaction_count_request() - .with_id(1_u64) + .with_id(1) .with_url("https://rpc.ankr.com/eth"), ) - .respond_with(get_transaction_count_response().with_id(1_u64)), + .respond_with(get_transaction_count_response().with_id(1)), ) .with_rpc_sources(RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr]))) .build() @@ -2198,8 +2210,8 @@ async fn should_retry_with_increasingly_more_cycles() { .client( // This mock must have the correct ID for the retry with sufficiently many cycles MockHttpOutcallsBuilder::new() - .given(get_transaction_count_request().with_id(4_u64)) - .respond_with(get_transaction_count_response().with_id(4_u64)), + .given(get_transaction_count_request().with_id(4)) + .respond_with(get_transaction_count_response().with_id(4)), ) .with_rpc_sources(RpcServices::EthMainnet(Some(vec![ EthMainnetService::Cloudflare, @@ -2224,16 +2236,16 @@ async fn should_have_different_request_ids_when_retrying_because_response_too_bi let mocks = MockHttpOutcallsBuilder::new() .given( get_transaction_count_request() - .with_id(0_u64) + .with_id(0) .with_max_response_bytes(1_u64), ) - .respond_with(get_transaction_count_response().with_id(0_u64)) + .respond_with(get_transaction_count_response().with_id(0)) .given( get_transaction_count_request() - .with_id(1_u64) + .with_id(1) .with_max_response_bytes(2048_u64), ) - .respond_with(get_transaction_count_response().with_id(1_u64)); + .respond_with(get_transaction_count_response().with_id(1)); let response = setup .client(mocks) @@ -2264,8 +2276,8 @@ async fn should_have_different_request_ids_when_retrying_because_response_too_bi async fn should_fail_when_response_id_inconsistent_with_request_id() { let setup = EvmRpcSetup::new().await.mock_api_keys().await; - let request_id = 0_u64; - let response_id = 1_u64; + let request_id = 0; + let response_id = 1; assert_ne!(request_id, response_id); let error = setup @@ -2330,8 +2342,8 @@ async fn should_log_request() { let logs = setup.http_get_logs("TRACE_HTTP").await; assert_eq!(logs.len(), 2, "Unexpected amount of logs {logs:?}"); - assert!(logs[0].message.contains("JSON-RPC request with id `0` to eth-mainnet.g.alchemy.com: JsonRpcRequest { jsonrpc: V2, method: \"eth_feeHistory\"")); - assert!(logs[1].message.contains("response for request with id `0`. Response with status 200 OK: JsonRpcResponse { jsonrpc: V2, id: Number(0), result: Ok(FeeHistory")); + assert!(logs[0].message.contains("JSON-RPC request with id `00000000000000000000` to eth-mainnet.g.alchemy.com: JsonRpcRequest { jsonrpc: V2, method: \"eth_feeHistory\"")); + assert!(logs[1].message.contains("response for request with id `00000000000000000000`. Response with status 200 OK: JsonRpcResponse { jsonrpc: V2, id: String(\"00000000000000000000\"), result: Ok(FeeHistory")); } #[tokio::test] @@ -2343,22 +2355,22 @@ async fn should_change_default_provider_when_one_keeps_failing() { MockHttpOutcallsBuilder::new() .given( get_transaction_count_request() - .with_id(0_u64) + .with_id(0) .with_host(ANKR_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(0_u64)) + .respond_with(get_transaction_count_response().with_id(0)) .given( get_transaction_count_request() - .with_id(1_u64) + .with_id(1) .with_host(BLOCKPI_ETH_HOSTNAME), ) .respond_with(CanisterHttpReply::with_status(500).with_body("Error!")) .given( get_transaction_count_request() - .with_id(2_u64) + .with_id(2) .with_host(PUBLICNODE_ETH_MAINNET_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(2_u64)), + .respond_with(get_transaction_count_response().with_id(2)), ) .with_rpc_sources(RpcServices::EthMainnet(None)) .with_consensus_strategy(ConsensusStrategy::Threshold { @@ -2381,16 +2393,16 @@ async fn should_change_default_provider_when_one_keeps_failing() { MockHttpOutcallsBuilder::new() .given( get_transaction_count_request() - .with_id(3_u64) + .with_id(3) .with_host(ALCHEMY_ETH_MAINNET_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(3_u64)) + .respond_with(get_transaction_count_response().with_id(3)) .given( get_transaction_count_request() - .with_id(4_u64) + .with_id(4) .with_host(ANKR_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(4_u64)), + .respond_with(get_transaction_count_response().with_id(4)), ) .with_rpc_sources(RpcServices::EthMainnet(Some(vec![ EthMainnetService::Ankr, @@ -2413,22 +2425,22 @@ async fn should_change_default_provider_when_one_keeps_failing() { MockHttpOutcallsBuilder::new() .given( get_transaction_count_request() - .with_id(5_u64) + .with_id(5) .with_host(ALCHEMY_ETH_MAINNET_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(5_u64)) + .respond_with(get_transaction_count_response().with_id(5)) .given( get_transaction_count_request() - .with_id(6_u64) + .with_id(6) .with_host(ANKR_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(6_u64)) + .respond_with(get_transaction_count_response().with_id(6)) .given( get_transaction_count_request() - .with_id(7_u64) + .with_id(7) .with_host(PUBLICNODE_ETH_MAINNET_HOSTNAME), ) - .respond_with(get_transaction_count_response().with_id(7_u64)), + .respond_with(get_transaction_count_response().with_id(7)), ) .with_rpc_sources(RpcServices::EthMainnet(None)) .with_consensus_strategy(ConsensusStrategy::Threshold { @@ -2456,7 +2468,7 @@ fn call_request() -> JsonRpcRequestMatcher { }, "latest" ])) - .with_id(0_u64) + .with_id(0) } mod request_cost_tests { @@ -2520,7 +2532,7 @@ mod request_cost_tests { .given( JsonRpcRequestMatcher::with_method(MOCK_REQUEST_METHOD) .with_params(MOCK_REQUEST_PARAMS) - .with_id(MOCK_REQUEST_ID), + .with_raw_id(MOCK_REQUEST_ID), ) .respond_with(JsonRpcResponse::from(MOCK_REQUEST_RESPONSE)); @@ -2599,13 +2611,13 @@ mod request_cost_tests { fn fee_history_request() -> JsonRpcRequestMatcher { JsonRpcRequestMatcher::with_method("eth_feeHistory") .with_params(json!(["0x3", "latest", []])) - .with_id(0_u64) + .with_id(0) } fn get_block_by_number_request() -> JsonRpcRequestMatcher { JsonRpcRequestMatcher::with_method("eth_getBlockByNumber") .with_params(json!(["latest", false])) - .with_id(0_u64) + .with_id(0) } fn get_logs_request( @@ -2625,7 +2637,7 @@ fn get_transaction_count_request() -> JsonRpcRequestMatcher { "0xdac17f958d2ee523a2206206994597c13d831ec7", "latest" ])) - .with_id(0_u64) + .with_id(0) } fn get_transaction_receipt_request() -> JsonRpcRequestMatcher { @@ -2633,24 +2645,26 @@ fn get_transaction_receipt_request() -> JsonRpcRequestMatcher { .with_params(json!([ "0xdd5d4b18923d7aae953c7996d791118102e889bea37b48a651157a4890e4746f" ])) - .with_id(0_u64) + .with_id(0) } fn send_raw_transaction_request() -> JsonRpcRequestMatcher { JsonRpcRequestMatcher::with_method("eth_sendRawTransaction") .with_params(json!([MOCK_TRANSACTION.to_string()])) - .with_id(0_u64) + .with_id(0) } fn call_response() -> JsonRpcResponse { - JsonRpcResponse::from( - json!({ "jsonrpc": "2.0", "id": 0, "result": "0x0000000000000000000000000000000000000000000000000000013c3ee36e89" }), - ) + JsonRpcResponse::from(json!({ + "jsonrpc": "2.0", + "id" : ConstantSizeId::ZERO.to_string(), + "result": "0x0000000000000000000000000000000000000000000000000000013c3ee36e89" + })) } fn fee_history_response() -> JsonRpcResponse { JsonRpcResponse::from(json!({ - "id" : 0, + "id" : ConstantSizeId::ZERO.to_string(), "jsonrpc" : "2.0", "result" : { "oldestBlock" : "0x11e57f5", @@ -2684,13 +2698,13 @@ fn get_block_by_number_response() -> JsonRpcResponse { "withdrawalsRoot": "0xecae44b2c53871003c5cc75285995764034c9b5978a904229d36c1280b141d48", "transactionsRoot": "0x93a1ad3d067009259b508cc95fde63b5efd7e9d8b55754314c173fdde8c0826a", }, - "id": 0 + "id" : ConstantSizeId::ZERO.to_string(), })) } fn get_logs_response() -> JsonRpcResponse { JsonRpcResponse::from(json!({ - "id" : 0, + "id" : ConstantSizeId::ZERO.to_string(), "jsonrpc" : "2.0", "result" : [ { @@ -2713,11 +2727,19 @@ fn get_logs_response() -> JsonRpcResponse { } fn get_transaction_count_response() -> JsonRpcResponse { - JsonRpcResponse::from(json!({ "jsonrpc" : "2.0", "id" : 0, "result" : "0x1" })) + JsonRpcResponse::from(json!({ + "jsonrpc": "2.0", + "id": ConstantSizeId::ZERO.to_string(), + "result": "0x1" + })) } fn send_raw_transaction_response() -> JsonRpcResponse { - JsonRpcResponse::from(json!({ "id": 0, "jsonrpc": "2.0", "result": MOCK_TRANSACTION_HASH })) + JsonRpcResponse::from(json!({ + "jsonrpc": "2.0", + "id": ConstantSizeId::ZERO.to_string(), + "result": MOCK_TRANSACTION_HASH + })) } pub fn multi_logs_for_single_transaction(num_logs: usize) -> Value {