diff --git a/Cargo.lock b/Cargo.lock index 2f8efbb2..1d0d62b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,19 +13,13 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ - "gimli 0.29.0", + "gimli 0.31.0", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -87,9 +81,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "arbitrary" @@ -152,7 +146,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -234,7 +228,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -245,7 +239,7 @@ checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -267,7 +261,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -323,17 +317,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ - "addr2line 0.22.0", - "cc", + "addr2line 0.24.1", "cfg-if", "libc", - "miniz_oxide 0.7.4", - "object 0.36.3", + "miniz_oxide", + "object 0.36.4", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -515,7 +509,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "syn_derive", ] @@ -710,7 +704,7 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -737,9 +731,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ "shlex", ] @@ -934,9 +928,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1259,7 +1253,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1356,7 +1350,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1464,7 +1458,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1704,7 +1698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1805,7 +1799,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1906,9 +1900,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "glob" @@ -1950,7 +1944,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.4.0", + "indexmap 2.5.0", "slab", "tokio", "tokio-util", @@ -4469,9 +4463,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -4719,7 +4713,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -4781,7 +4775,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.35", + "rustix 0.38.37", ] [[package]] @@ -4861,15 +4855,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -5048,7 +5033,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5141,7 +5126,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5153,7 +5138,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5170,9 +5155,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -5390,9 +5375,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" dependencies = [ "memchr", "thiserror", @@ -5401,9 +5386,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" dependencies = [ "pest", "pest_generator", @@ -5411,22 +5396,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" dependencies = [ "once_cell", "pest", @@ -5440,7 +5425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.4.0", + "indexmap 2.5.0", ] [[package]] @@ -5495,7 +5480,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5826,7 +5811,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5846,9 +5831,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "psm" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" dependencies = [ "cc", ] @@ -6259,9 +6244,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -6436,7 +6421,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -6824,7 +6809,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -6837,7 +6822,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -6876,9 +6861,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.76" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -6894,7 +6879,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -6977,7 +6962,7 @@ dependencies = [ "cfg-if", "fastrand", "once_cell", - "rustix 0.38.35", + "rustix 0.38.37", "windows-sys 0.59.0", ] @@ -7030,7 +7015,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -7115,9 +7100,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -7149,7 +7134,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -7192,9 +7177,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -7203,9 +7188,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -7227,7 +7212,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "toml_datetime", "winnow 0.5.40", ] @@ -7238,7 +7223,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "toml_datetime", "winnow 0.6.18", ] @@ -7337,7 +7322,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -7443,9 +7428,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -7588,7 +7573,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -7610,7 +7595,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7632,9 +7617,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.216.0" +version = "0.217.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c23aebea22c8a75833ae08ed31ccc020835b12a41999e58c31464271b94a88" +checksum = "7b88b0814c9a2b323a9b46c687e726996c255ac8b64aa237dd11c81ed4854760" dependencies = [ "leb128", ] @@ -7655,7 +7640,7 @@ version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bf9564f29de2890ee34406af52d2a92dec6ef044c8ddfc5add5db8dcfd36e6c" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "semver", ] @@ -7839,22 +7824,22 @@ dependencies = [ [[package]] name = "wast" -version = "216.0.0" +version = "217.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7eb1f2eecd913fdde0dc6c3439d0f24530a98ac6db6cb3d14d92a5328554a08" +checksum = "79004ecebded92d3c710d4841383368c7f04b63d0992ddd6b0c7d5029b7629b7" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.216.0", + "wasm-encoder 0.217.0", ] [[package]] name = "wat" -version = "1.216.0" +version = "1.217.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac0409090fb5154f95fb5ba3235675fd9e579e731524d63b6a2f653e1280c82a" +checksum = "c126271c3d92ca0f7c63e4e462e40c69cca52fd4245fcda730d1cf558fb55088" dependencies = [ "wast", ] @@ -7878,7 +7863,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.35", + "rustix 0.38.37", ] [[package]] @@ -8180,7 +8165,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -8200,5 +8185,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] diff --git a/candid/evm_rpc.did b/candid/evm_rpc.did index 7c2c26d0..e6b3ce94 100644 --- a/candid/evm_rpc.did +++ b/candid/evm_rpc.did @@ -188,7 +188,7 @@ type RpcError = variant { type RpcApi = record { url : text; headers : opt vec HttpHeader }; type RpcService = variant { Chain : nat64; - Provider : nat64; + Provider : ProviderId; Custom : RpcApi; EthSepolia : EthSepoliaService; EthMainnet : EthMainnetService; diff --git a/src/constants.rs b/src/constants.rs index a278a309..30982288 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -24,7 +24,6 @@ pub const RPC_URL_COST_BYTES: u32 = 256; pub const MINIMUM_WITHDRAWAL_CYCLES: u128 = 1_000_000_000; -pub const STRING_STORABLE_MAX_SIZE: u32 = 100; pub const API_KEY_MAX_SIZE: u32 = 512; pub const PROVIDER_MAX_SIZE: u32 = 256; pub const RPC_SERVICE_MAX_SIZE: u32 = 256; diff --git a/src/lib.rs b/src/lib.rs index 8691ff58..06b533a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -pub use candid::Principal; - pub mod accounting; pub mod candid_rpc; pub mod constants; diff --git a/src/main.rs b/src/main.rs index c7ac28a1..aa3d61ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ use candid::candid_method; -use cketh_common::eth_rpc::RpcError; use cketh_common::eth_rpc_client::providers::RpcService; use cketh_common::eth_rpc_client::RpcConfig; @@ -9,11 +8,12 @@ use evm_rpc::candid_rpc::CandidRpcClient; use evm_rpc::constants::NODES_IN_SUBNET; use evm_rpc::http::get_http_response_body; use evm_rpc::memory::{ - insert_api_key, is_api_key_principal, remove_api_key, set_api_key_principals, set_demo_active, + insert_api_key, is_api_key_principal, is_demo_active, remove_api_key, set_api_key_principals, + set_demo_active, }; use evm_rpc::metrics::encode_metrics; use evm_rpc::providers::{find_provider, resolve_rpc_service, PROVIDERS, SERVICE_PROVIDER_MAP}; -use evm_rpc::types::{Provider, ProviderId, RpcAccess}; +use evm_rpc::types::{Provider, ProviderId, RpcAccess, RpcResult}; use ic_canister_log::log; use ic_canisters_http_types::{ HttpRequest as AssetHttpRequest, HttpResponse as AssetHttpResponse, HttpResponseBuilder, @@ -127,7 +127,7 @@ async fn request( service: RpcService, json_rpc_payload: String, max_response_bytes: u64, -) -> Result { +) -> RpcResult { let response = json_rpc_request( resolve_rpc_service(service)?, MetricRpcMethod("request".to_string()), @@ -144,11 +144,15 @@ fn request_cost( _service: RpcService, json_rpc_payload: String, max_response_bytes: u64, -) -> Result { - Ok(get_cost_with_collateral(get_http_request_cost( - json_rpc_payload.len() as u64, - max_response_bytes, - ))) +) -> RpcResult { + if is_demo_active() { + Ok(0) + } else { + Ok(get_cost_with_collateral(get_http_request_cost( + json_rpc_payload.len() as u64, + max_response_bytes, + ))) + } } #[query(name = "getProviders")] diff --git a/src/types.rs b/src/types.rs index 1c9c36a3..3aa26921 100644 --- a/src/types.rs +++ b/src/types.rs @@ -13,12 +13,12 @@ use std::borrow::Cow; use std::collections::HashMap; use std::fmt; -use crate::constants::{API_KEY_MAX_SIZE, API_KEY_REPLACE_STRING, STRING_STORABLE_MAX_SIZE}; +use crate::constants::{API_KEY_MAX_SIZE, API_KEY_REPLACE_STRING}; use crate::memory::get_api_key; use crate::util::hostname_from_url; use crate::validate::validate_api_key; -#[derive(Clone, Debug, CandidType, Deserialize)] +#[derive(Clone, Debug, Default, CandidType, Deserialize)] pub struct InitArgs { pub demo: Option, #[serde(rename = "manageApiKeys")] @@ -177,7 +177,7 @@ impl Storable for BoolStorable { bytes.len() == 1, "Unexpected byte length for `BoolStorable`" ); - BoolStorable(bytes[0] == 0) + BoolStorable(bytes[0] != 0) } fn to_bytes(&self) -> Cow<[u8]> { @@ -185,25 +185,6 @@ impl Storable for BoolStorable { } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct StringStorable(pub String); - -impl Storable for StringStorable { - fn to_bytes(&self) -> Cow<[u8]> { - // String already implements `Storable`. - self.0.to_bytes() - } - - fn from_bytes(bytes: Cow<[u8]>) -> Self { - Self(String::from_bytes(bytes)) - } -} - -impl BoundedStorable for StringStorable { - const MAX_SIZE: u32 = STRING_STORABLE_MAX_SIZE; - const IS_FIXED_SIZE: bool = false; -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct PrincipalStorable(pub Principal); @@ -445,12 +426,14 @@ pub enum RpcServices { #[cfg(test)] mod test { + use candid::Principal; use cketh_common::{ eth_rpc::RpcError, eth_rpc_client::providers::{EthMainnetService, RpcService}, }; + use ic_stable_structures::Storable; - use crate::types::{ApiKey, MultiRpcResult}; + use crate::types::{ApiKey, BoolStorable, MultiRpcResult, PrincipalStorable}; #[test] fn test_multi_rpc_result_map() { @@ -517,4 +500,27 @@ mod test { let api_key = ApiKey("55555".to_string()); assert!(format!("{api_key:?}") == "{API_KEY}"); } + + #[test] + fn test_bool_storable() { + for value in [true, false] { + let storable = BoolStorable(value); + assert_eq!(storable.0, BoolStorable::from_bytes(storable.to_bytes()).0); + } + } + + #[test] + fn test_principal_storable() { + for value in [ + Principal::anonymous(), + Principal::management_canister(), + Principal::from_text("7hfb6-caaaa-aaaar-qadga-cai").unwrap(), + ] { + let storable = PrincipalStorable(value); + assert_eq!( + storable.0, + PrincipalStorable::from_bytes(storable.to_bytes()).0 + ); + } + } } diff --git a/tests/tests.rs b/tests/tests.rs index 008e0f3e..ebfe2a39 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -34,7 +34,7 @@ use evm_rpc::{ InitArgs, Metrics, MultiRpcResult, ProviderId, RpcAccess, RpcMethod, RpcResult, RpcServices, }, }; -use evm_rpc_types::{Hex, Hex32, Nat256}; +use evm_rpc_types::{Hex, Hex20, Hex32, Nat256}; use mock::{MockOutcall, MockOutcallBuilder}; const DEFAULT_CALLER_TEST_ID: u64 = 10352385; @@ -49,6 +49,7 @@ const MOCK_REQUEST_URL: &str = "https://cloudflare-eth.com"; const MOCK_REQUEST_PAYLOAD: &str = r#"{"id":1,"jsonrpc":"2.0","method":"eth_gasPrice"}"#; const MOCK_REQUEST_RESPONSE: &str = r#"{"id":1,"jsonrpc":"2.0","result":"0x00112233"}"#; const MOCK_REQUEST_RESPONSE_BYTES: u64 = 1000; +const MOCK_API_KEY: &str = "mock-api-key"; const MOCK_TRANSACTION: &str="0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"; const MOCK_TRANSACTION_HASH: &str = @@ -133,6 +134,12 @@ impl EvmRpcSetup { } } + pub fn upgrade_canister(&self, args: InitArgs) { + self.env + .upgrade_canister(self.canister_id, evm_rpc_wasm(), Encode!(&args).unwrap()) + .expect("Error while upgrading canister"); + } + /// Shorthand for deriving an `EvmRpcSetup` with the caller as the canister controller. pub fn as_controller(mut self) -> Self { self.caller = self.controller; @@ -197,7 +204,7 @@ impl EvmRpcSetup { source: RpcService, json_rpc_payload: &str, max_response_bytes: u64, - ) -> Nat { + ) -> RpcResult { self.call_query( "requestCost", Encode!(&source, &json_rpc_payload, &max_response_bytes).unwrap(), @@ -296,7 +303,7 @@ impl EvmRpcSetup { Some(( provider.provider_id, match provider.access { - RpcAccess::Authenticated { .. } => Some("mock-api-key".to_string()), + RpcAccess::Authenticated { .. } => Some(MOCK_API_KEY.to_string()), RpcAccess::Unauthenticated { .. } => None?, }, )) @@ -634,74 +641,6 @@ fn should_decode_transaction_receipt() { ); } -#[test] -fn should_use_fallback_public_url() { - let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); - let setup = EvmRpcSetup::with_args(InitArgs { - demo: Some(true), - manage_api_keys: Some(vec![authorized_caller.0]), - }); - let response = setup - .eth_get_transaction_count( - RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), - None, - evm_rpc_types::GetTransactionCountArgs { - address: "0xdAC17F958D2ee523a2206206994597C13D831ec7" - .parse() - .unwrap(), - block: evm_rpc_types::BlockTag::Latest, - }, - ) - .mock_http( - MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) - .with_url("https://rpc.ankr.com/eth"), - ) - .wait() - .expect_consistent() - .unwrap(); - assert_eq!(response, 1_u8.into()); -} - -#[test] -fn should_insert_api_keys() { - let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); - let setup = EvmRpcSetup::with_args(InitArgs { - demo: Some(true), - manage_api_keys: Some(vec![authorized_caller.0]), - }); - let provider_id = 1; - setup - .clone() - .as_caller(authorized_caller) - .update_api_keys(&[(provider_id, Some("test-api-key".to_string()))]); - let response = setup - .eth_get_transaction_count( - RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), - None, - evm_rpc_types::GetTransactionCountArgs { - address: "0xdAC17F958D2ee523a2206206994597C13D831ec7" - .parse() - .unwrap(), - block: evm_rpc_types::BlockTag::Latest, - }, - ) - .mock_http( - MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) - .with_url("https://rpc.ankr.com/eth/test-api-key"), - ) - .wait() - .expect_consistent() - .unwrap(); - assert_eq!(response, 1_u8.into()); -} - -#[test] -#[should_panic(expected = "You are not authorized")] -fn should_prevent_unauthorized_update_api_keys() { - let setup = EvmRpcSetup::new(); - setup.update_api_keys(&[(0, Some("unauthorized-api-key".to_string()))]); -} - #[test] fn eth_get_logs_should_succeed() { for source in RPC_SERVICES { @@ -1410,3 +1349,315 @@ fn should_use_custom_response_size_estimate() { .expect_consistent(); assert_matches!(response, Ok(_)); } + +#[test] +fn should_use_fallback_public_url() { + let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); + let setup = EvmRpcSetup::with_args(InitArgs { + demo: Some(true), + manage_api_keys: Some(vec![authorized_caller.0]), + }); + let response = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: Hex20::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url("https://rpc.ankr.com/eth"), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response, 1u32.into()); +} + +#[test] +fn should_insert_api_keys() { + let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); + let setup = EvmRpcSetup::with_args(InitArgs { + demo: Some(true), + manage_api_keys: Some(vec![authorized_caller.0]), + }); + let provider_id = 1; + setup + .clone() + .as_caller(authorized_caller) + .update_api_keys(&[(provider_id, Some("test-api-key".to_string()))]); + let response = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: "0xdAC17F958D2ee523a2206206994597C13D831ec7" + .parse() + .unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url("https://rpc.ankr.com/eth/test-api-key"), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response, 1_u8.into()); +} + +#[test] +fn should_update_api_key() { + let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); + let setup = EvmRpcSetup::with_args(InitArgs { + demo: Some(true), + manage_api_keys: Some(vec![authorized_caller.0]), + }) + .as_caller(authorized_caller); + let provider_id = 1; // Ankr / mainnet + let api_key = "test-api-key"; + setup.update_api_keys(&[(provider_id, Some(api_key.to_string()))]); + let response = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: Hex20::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url(format!("https://rpc.ankr.com/eth/{api_key}")), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response, 1u32.into()); + + setup.update_api_keys(&[(provider_id, None)]); + let response_public = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: Hex20::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url("https://rpc.ankr.com/eth"), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response_public, 1u32.into()); +} + +#[test] +fn should_update_bearer_token() { + let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); + let setup = EvmRpcSetup::with_args(InitArgs { + demo: Some(true), + manage_api_keys: Some(vec![authorized_caller.0]), + }); + let provider_id = 8; // Alchemy / mainnet + let api_key = "test-api-key"; + setup + .clone() + .as_caller(authorized_caller) + .update_api_keys(&[(provider_id, Some(api_key.to_string()))]); + let response = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Alchemy])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: Hex20::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url("https://eth-mainnet.g.alchemy.com/v2") + .with_request_headers(vec![ + ("Content-Type", "application/json"), + ("Authorization", &format!("Bearer {api_key}")), + ]), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response, 1u32.into()); +} + +#[test] +#[should_panic(expected = "You are not authorized")] +fn should_prevent_unauthorized_update_api_keys() { + let setup = EvmRpcSetup::new(); + setup.update_api_keys(&[(0, Some("unauthorized-api-key".to_string()))]); +} + +#[test] +#[should_panic(expected = "Trying to set API key for unauthenticated provider")] +fn should_prevent_unauthenticated_update_api_keys() { + let setup = EvmRpcSetup::new(); + setup.as_controller().update_api_keys(&[( + 2, /* PublicNode / mainnet */ + Some("invalid-api-key".to_string()), + )]); +} + +#[test] +#[should_panic(expected = "Provider not found")] +fn should_prevent_unknown_provider_update_api_keys() { + let setup = EvmRpcSetup::new(); + setup + .as_controller() + .update_api_keys(&[(5555, Some("unknown-provider-api-key".to_string()))]); +} + +#[test] +fn upgrade_should_keep_api_keys() { + let setup = EvmRpcSetup::new(); + let provider_id = 1; // Ankr / mainnet + let api_key = "test-api-key"; + setup + .clone() + .as_controller() + .update_api_keys(&[(provider_id, Some(api_key.to_string()))]); + let response = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: Hex20::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url(format!("https://rpc.ankr.com/eth/{api_key}")), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response, 1u32.into()); + + setup.upgrade_canister(InitArgs::default()); + + let response_post_upgrade = setup + .eth_get_transaction_count( + RpcServices::EthMainnet(Some(vec![EthMainnetService::Ankr])), + None, + evm_rpc_types::GetTransactionCountArgs { + address: Hex20::from_str("0xdAC17F958D2ee523a2206206994597C13D831ec7").unwrap(), + block: evm_rpc_types::BlockTag::Latest, + }, + ) + .mock_http( + MockOutcallBuilder::new(200, r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#) + .with_url(format!("https://rpc.ankr.com/eth/{api_key}")), + ) + .wait() + .expect_consistent() + .unwrap(); + assert_eq!(response_post_upgrade, 1u32.into()); +} + +#[test] +fn upgrade_should_keep_demo() { + let setup = EvmRpcSetup::with_args(InitArgs { + demo: Some(true), + ..Default::default() + }); + assert_eq!( + setup + .request_cost( + RpcService::Chain(0x1), + r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#, + 1000 + ) + .unwrap(), + 0 + ); + setup.upgrade_canister(InitArgs::default()); + assert_eq!( + setup + .request_cost( + RpcService::Chain(0x1), + r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#, + 1000 + ) + .unwrap(), + 0 + ); +} + +#[test] +fn upgrade_should_change_demo() { + let setup = EvmRpcSetup::with_args(InitArgs { + demo: Some(true), + ..Default::default() + }); + assert_eq!( + setup + .request_cost( + RpcService::Chain(0x1), + r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#, + 1000 + ) + .unwrap(), + 0 + ); + setup.upgrade_canister(InitArgs { + demo: Some(false), + ..Default::default() + }); + assert_ne!( + setup + .request_cost( + RpcService::Chain(0x1), + r#"{"jsonrpc":"2.0","id":0,"result":"0x1"}"#, + 1000 + ) + .unwrap(), + 0 + ); +} + +#[test] +fn upgrade_should_keep_manage_api_key_principals() { + let authorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); + let setup = EvmRpcSetup::with_args(InitArgs { + manage_api_keys: Some(vec![authorized_caller.0]), + ..Default::default() + }); + setup.upgrade_canister(InitArgs { + manage_api_keys: None, + ..Default::default() + }); + setup + .as_caller(authorized_caller) + .update_api_keys(&[(0, Some("authorized-api-key".to_string()))]); +} + +#[test] +#[should_panic(expected = "You are not authorized")] +fn upgrade_should_change_manage_api_key_principals() { + let deauthorized_caller = PrincipalId::new_user_test_id(ADDITIONAL_TEST_ID); + let setup = EvmRpcSetup::with_args(InitArgs { + manage_api_keys: Some(vec![deauthorized_caller.0]), + ..Default::default() + }); + setup.upgrade_canister(InitArgs { + manage_api_keys: Some(vec![]), + ..Default::default() + }); + setup + .as_caller(deauthorized_caller) + .update_api_keys(&[(0, Some("unauthorized-api-key".to_string()))]); +}