diff --git a/service/pool/EVM.mo b/service/pool/EVM.mo new file mode 100644 index 00000000..65ca71b6 --- /dev/null +++ b/service/pool/EVM.mo @@ -0,0 +1,320 @@ +// This is a generated Motoko binding. +// Please use `import service "ic:canister_id"` instead to call canisters on the IC if possible. + +module { + public type AccessListEntry = { storageKeys : [Text]; address : Text }; + public type Block = { + miner : Text; + totalDifficulty : ?Nat; + receiptsRoot : Text; + stateRoot : Text; + hash : Text; + difficulty : ?Nat; + size : Nat; + uncles : [Text]; + baseFeePerGas : ?Nat; + extraData : Text; + transactionsRoot : ?Text; + sha3Uncles : Text; + nonce : Nat; + number : Nat; + timestamp : Nat; + transactions : [Text]; + gasLimit : Nat; + logsBloom : Text; + parentHash : Text; + gasUsed : Nat; + mixHash : Text; + }; + public type BlockTag = { + #Earliest; + #Safe; + #Finalized; + #Latest; + #Number : Nat; + #Pending; + }; + public type CallArgs = { + transaction : TransactionRequest; + block : ?BlockTag; + }; + public type CallResult = { #Ok : Text; #Err : RpcError }; + public type ChainId = Nat64; + public type ConsensusStrategy = { + #Equality; + #Threshold : { min : Nat8; total : ?Nat8 }; + }; + public type EthMainnetService = { + #Alchemy; + #Llama; + #BlockPi; + #Cloudflare; + #PublicNode; + #Ankr; + }; + public type EthSepoliaService = { + #Alchemy; + #BlockPi; + #PublicNode; + #Ankr; + #Sepolia; + }; + public type FeeHistory = { + reward : [[Nat]]; + gasUsedRatio : [Float]; + oldestBlock : Nat; + baseFeePerGas : [Nat]; + }; + public type FeeHistoryArgs = { + blockCount : Nat; + newestBlock : BlockTag; + rewardPercentiles : ?Blob; + }; + public type FeeHistoryResult = { #Ok : FeeHistory; #Err : RpcError }; + public type GetBlockByNumberResult = { #Ok : Block; #Err : RpcError }; + public type GetLogsArgs = { + fromBlock : ?BlockTag; + toBlock : ?BlockTag; + addresses : [Text]; + topics : ?[Topic]; + }; + public type GetLogsResult = { #Ok : [LogEntry]; #Err : RpcError }; + public type GetTransactionCountArgs = { address : Text; block : BlockTag }; + public type GetTransactionCountResult = { #Ok : Nat; #Err : RpcError }; + public type GetTransactionReceiptResult = { + #Ok : ?TransactionReceipt; + #Err : RpcError; + }; + public type HttpHeader = { value : Text; name : Text }; + public type HttpOutcallError = { + #IcError : { code : RejectionCode; message : Text }; + #InvalidHttpJsonRpcResponse : { + status : Nat16; + body : Text; + parsingError : ?Text; + }; + }; + public type InstallArgs = { + logFilter : ?LogFilter; + demo : ?Bool; + manageApiKeys : ?[Principal]; + }; + public type JsonRpcError = { code : Int64; message : Text }; + public type L2MainnetService = { + #Alchemy; + #Llama; + #BlockPi; + #PublicNode; + #Ankr; + }; + public type LogEntry = { + transactionHash : ?Text; + blockNumber : ?Nat; + data : Text; + blockHash : ?Text; + transactionIndex : ?Nat; + topics : [Text]; + address : Text; + logIndex : ?Nat; + removed : Bool; + }; + public type LogFilter = { + #ShowAll; + #HideAll; + #ShowPattern : Regex; + #HidePattern : Regex; + }; + public type Metrics = { + cyclesWithdrawn : Nat; + responses : [((Text, Text, Text), Nat64)]; + errNoPermission : Nat64; + inconsistentResponses : [((Text, Text), Nat64)]; + cyclesCharged : [((Text, Text), Nat)]; + requests : [((Text, Text), Nat64)]; + errHttpOutcall : [((Text, Text), Nat64)]; + errHostNotAllowed : [(Text, Nat64)]; + }; + public type MultiCallResult = { + #Consistent : CallResult; + #Inconsistent : [(RpcService, CallResult)]; + }; + public type MultiFeeHistoryResult = { + #Consistent : FeeHistoryResult; + #Inconsistent : [(RpcService, FeeHistoryResult)]; + }; + public type MultiGetBlockByNumberResult = { + #Consistent : GetBlockByNumberResult; + #Inconsistent : [(RpcService, GetBlockByNumberResult)]; + }; + public type MultiGetLogsResult = { + #Consistent : GetLogsResult; + #Inconsistent : [(RpcService, GetLogsResult)]; + }; + public type MultiGetTransactionCountResult = { + #Consistent : GetTransactionCountResult; + #Inconsistent : [(RpcService, GetTransactionCountResult)]; + }; + public type MultiGetTransactionReceiptResult = { + #Consistent : GetTransactionReceiptResult; + #Inconsistent : [(RpcService, GetTransactionReceiptResult)]; + }; + public type MultiSendRawTransactionResult = { + #Consistent : SendRawTransactionResult; + #Inconsistent : [(RpcService, SendRawTransactionResult)]; + }; + public type Provider = { + access : RpcAccess; + alias : ?RpcService; + chainId : ChainId; + providerId : ProviderId; + }; + public type ProviderError = { + #TooFewCycles : { expected : Nat; received : Nat }; + #InvalidRpcConfig : Text; + #MissingRequiredProvider; + #ProviderNotFound; + #NoPermission; + }; + public type ProviderId = Nat64; + public type Regex = Text; + public type RejectionCode = { + #NoError; + #CanisterError; + #SysTransient; + #DestinationInvalid; + #Unknown; + #SysFatal; + #CanisterReject; + }; + public type RequestCostResult = { #Ok : Nat; #Err : RpcError }; + public type RequestResult = { #Ok : Text; #Err : RpcError }; + public type RpcAccess = { + #Authenticated : { publicUrl : ?Text; auth : RpcAuth }; + #Unauthenticated : { publicUrl : Text }; + }; + public type RpcApi = { url : Text; headers : ?[HttpHeader] }; + public type RpcAuth = { + #BearerToken : { url : Text }; + #UrlParameter : { urlPattern : Text }; + }; + public type RpcConfig = { + responseConsensus : ?ConsensusStrategy; + responseSizeEstimate : ?Nat64; + }; + public type RpcError = { + #JsonRpcError : JsonRpcError; + #ProviderError : ProviderError; + #ValidationError : ValidationError; + #HttpOutcallError : HttpOutcallError; + }; + public type RpcService = { + #EthSepolia : EthSepoliaService; + #BaseMainnet : L2MainnetService; + #Custom : RpcApi; + #OptimismMainnet : L2MainnetService; + #ArbitrumOne : L2MainnetService; + #EthMainnet : EthMainnetService; + #Provider : ProviderId; + }; + public type RpcServices = { + #EthSepolia : ?[EthSepoliaService]; + #BaseMainnet : ?[L2MainnetService]; + #Custom : { chainId : ChainId; services : [RpcApi] }; + #OptimismMainnet : ?[L2MainnetService]; + #ArbitrumOne : ?[L2MainnetService]; + #EthMainnet : ?[EthMainnetService]; + }; + public type SendRawTransactionResult = { + #Ok : SendRawTransactionStatus; + #Err : RpcError; + }; + public type SendRawTransactionStatus = { + #Ok : ?Text; + #NonceTooLow; + #NonceTooHigh; + #InsufficientFunds; + }; + public type Topic = [Text]; + public type TransactionReceipt = { + to : ?Text; + status : ?Nat; + transactionHash : Text; + blockNumber : Nat; + from : Text; + logs : [LogEntry]; + blockHash : Text; + type_ : Text; + transactionIndex : Nat; + effectiveGasPrice : Nat; + logsBloom : Text; + contractAddress : ?Text; + gasUsed : Nat; + }; + public type TransactionRequest = { + to : ?Text; + gas : ?Nat; + maxFeePerGas : ?Nat; + gasPrice : ?Nat; + value : ?Nat; + maxFeePerBlobGas : ?Nat; + from : ?Text; + type_ : ?Text; + accessList : ?[AccessListEntry]; + nonce : ?Nat; + maxPriorityFeePerGas : ?Nat; + blobs : ?[Text]; + input : ?Text; + chainId : ?Nat; + blobVersionedHashes : ?[Text]; + }; + public type ValidationError = { #Custom : Text; #InvalidHex : Text }; + public type Self = actor { + eth_call : shared ( + RpcServices, + ?RpcConfig, + CallArgs, + ) -> async MultiCallResult; + eth_feeHistory : shared ( + RpcServices, + ?RpcConfig, + FeeHistoryArgs, + ) -> async MultiFeeHistoryResult; + eth_getBlockByNumber : shared ( + RpcServices, + ?RpcConfig, + BlockTag, + ) -> async MultiGetBlockByNumberResult; + eth_getLogs : shared ( + RpcServices, + ?RpcConfig, + GetLogsArgs, + ) -> async MultiGetLogsResult; + eth_getTransactionCount : shared ( + RpcServices, + ?RpcConfig, + GetTransactionCountArgs, + ) -> async MultiGetTransactionCountResult; + eth_getTransactionReceipt : shared ( + RpcServices, + ?RpcConfig, + Text, + ) -> async MultiGetTransactionReceiptResult; + eth_sendRawTransaction : shared ( + RpcServices, + ?RpcConfig, + Text, + ) -> async MultiSendRawTransactionResult; + getMetrics : shared query () -> async Metrics; + getNodesInSubnet : shared query () -> async Nat32; + getProviders : shared query () -> async [Provider]; + getServiceProviderMap : shared query () -> async [(RpcService, ProviderId)]; + request : shared (RpcService, Text, Nat64) -> async RequestResult; + requestCost : shared query ( + RpcService, + Text, + Nat64, + ) -> async RequestCostResult; + updateApiKeys : shared [(ProviderId, ?Text)] -> async (); + } +} + diff --git a/service/pool/IC.mo b/service/pool/IC.mo index 8696c093..37167364 100644 --- a/service/pool/IC.mo +++ b/service/pool/IC.mo @@ -68,6 +68,13 @@ module { module_hash : ?Blob; reserved_cycles : Nat; }; + public type ecdsa_curve = { #secp256k1 }; + public type sign_with_ecdsa_args = { + key_id : { name : Text; curve : ecdsa_curve }; + derivation_path : [Blob]; + message_hash : Blob; + }; + public type sign_with_ecdsa_result = { signature : Blob }; public type user_id = Principal; public type wasm_module = Blob; public type Self = actor { @@ -98,6 +105,7 @@ module { amount : Nat; } -> async (); raw_rand : shared () -> async Blob; + sign_with_ecdsa : shared sign_with_ecdsa_args -> async sign_with_ecdsa_result; start_canister : shared { canister_id : canister_id } -> async (); stop_canister : shared { canister_id : canister_id } -> async (); uninstall_code : shared { canister_id : canister_id } -> async (); diff --git a/service/pool/Main.mo b/service/pool/Main.mo index 1154812a..d33b5123 100644 --- a/service/pool/Main.mo +++ b/service/pool/Main.mo @@ -13,6 +13,7 @@ import Principal "mo:base/Principal"; import Debug "mo:base/Debug"; import Types "./Types"; import ICType "./IC"; +import EVM "./EVM"; import PoW "./PoW"; import Logs "./Logs"; import Metrics "./Metrics"; @@ -20,9 +21,10 @@ import WasmUtilsType "./Wasm-utils"; shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { let IC : ICType.Self = actor "aaaaa-aa"; + let evm : EVM.Self = actor "7hfb6-caaaa-aaaar-qadga-cai"; let params = Option.get(opt_params, Types.defaultParams); let Wasm : WasmUtilsType.Self = actor(Option.get(params.wasm_utils_principal, "ozk6r-tyaaa-aaaab-qab4a-cai")); - var pool = Types.CanisterPool(params.max_num_canisters, params.canister_time_to_live, params.max_family_tree_size); + var pool = Types.CanisterPool(params); let nonceCache = PoW.NonceCache(params.nonce_time_to_live); var statsByOrigin = Logs.StatsByOrigin(); @@ -693,31 +695,28 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { public shared func load_canister_snapshot({}) : async () { throw Error.reject("Cannot call load_canister_snapshot from canister itself"); }; + public shared ({ caller }) func sign_with_ecdsa(arg: ICType.sign_with_ecdsa_args) : async ICType.sign_with_ecdsa_result { + await* pool.addCycles(caller, #method "sign_with_ecdsa"); + let res = await IC.sign_with_ecdsa(arg); + await* pool.addCycles(caller, #refund); + res + }; public shared ({ caller }) func _ttp_request(request : ICType.http_request_args) : async ICType.http_request_result { - if (not pool.findId caller) { - throw Error.reject "Only a canister managed by the Motoko Playground can call http_request"; - }; - let cycles = 250_000_000_000; - if (pool.spendCycles(caller, cycles)) { - Cycles.add cycles; - let new_request = switch (request.transform) { - case null { - { request with transform = null }; - }; - case (?transform) { - let payload = { caller; transform }; - let fake_actor: actor { __transform: ICType.transform_function } = actor(Principal.toText(Principal.fromActor this)); - let new_transform = ?{ function = fake_actor.__transform; context = to_candid(payload) }; - { request with transform = new_transform }; - }; - }; - let res = await IC.http_request(new_request); - let refunded = -Cycles.refunded(); - assert(pool.spendCycles(caller, refunded) == true); - res; - } else { - throw Error.reject "http_request exceeds cycle spend limit"; + await* pool.addCycles(caller, #method "http_request"); + let new_request = switch (request.transform) { + case null { + { request with transform = null }; + }; + case (?transform) { + let payload = { caller; transform }; + let fake_actor: actor { __transform: ICType.transform_function } = actor(Principal.toText(Principal.fromActor this)); + let new_transform = ?{ function = fake_actor.__transform; context = to_candid(payload) }; + { request with transform = new_transform }; + }; }; + let res = await IC.http_request(new_request); + await* pool.addCycles(caller, #refund); + res; }; public shared composite query({ caller }) func __transform({context: Blob; response: ICType.http_request_result}) : async ICType.http_request_result { // TODO Remove anonymous identity once https://github.com/dfinity/ic/pull/1337 is released @@ -732,6 +731,55 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { }; await raw.transform.function({ context = raw.transform.context; response }); }; + // Endpoints for EVM RPC canister + public shared ({ caller }) func eth_call(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: EVM.CallArgs) : async EVM.MultiCallResult { + await* pool.addCycles(caller, #method "eth_call"); + let res = await evm.eth_call(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func eth_feeHistory(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: EVM.FeeHistoryArgs) : async EVM.MultiFeeHistoryResult { + await* pool.addCycles(caller, #method "eth_feeHistory"); + let res = await evm.eth_feeHistory(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func eth_getBlockByNumber(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: EVM.BlockTag) : async EVM.MultiGetBlockByNumberResult { + await* pool.addCycles(caller, #method "eth_getBlockByNumber"); + let res = await evm.eth_getBlockByNumber(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func eth_getLogs(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: EVM.GetLogsArgs) : async EVM.MultiGetLogsResult { + await* pool.addCycles(caller, #method "eth_getLogs"); + let res = await evm.eth_getLogs(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func eth_getTransactionCount(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: EVM.GetTransactionCountArgs) : async EVM.MultiGetTransactionCountResult { + await* pool.addCycles(caller, #method "eth_getTransactionCount"); + let res = await evm.eth_getTransactionCount(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func eth_getTransactionReceipt(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: Text) : async EVM.MultiGetTransactionReceiptResult { + await* pool.addCycles(caller, #method "eth_getTransactionReceipt"); + let res = await evm.eth_getTransactionReceipt(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func eth_sendRawTransaction(service: EVM.RpcServices, config: ?EVM.RpcConfig, arg: Text) : async EVM.MultiSendRawTransactionResult { + await* pool.addCycles(caller, #method "eth_sendRawTransaction"); + let res = await evm.eth_sendRawTransaction(service, config, arg); + await* pool.addCycles(caller, #refund); + res + }; + public shared ({ caller }) func request(service: EVM.RpcService, arg: Text, id: Nat64) : async EVM.RequestResult { + await* pool.addCycles(caller, #method "request"); + let res = await evm.request(service, arg, id); + await* pool.addCycles(caller, #refund); + res + }; system func inspect({ caller : Principal; @@ -774,6 +822,15 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { #load_canister_snapshot : Any; #_ttp_request : Any; #__transform : Any; + #sign_with_ecdsa: Any; + #eth_call: Any; + #eth_feeHistory: Any; + #eth_getBlockByNumber: Any; + #eth_getLogs: Any; + #eth_getTransactionCount: Any; + #eth_getTransactionReceipt: Any; + #eth_sendRawTransaction: Any; + #request: Any; }; }) : Bool { switch msg { @@ -789,6 +846,15 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { case (#load_canister_snapshot _) false; case (#_ttp_request _) false; case (#__transform _) false; + case (#sign_with_ecdsa _) false; + case (#eth_call _) false; + case (#eth_feeHistory _) false; + case (#eth_getBlockByNumber _) false; + case (#eth_getLogs _) false; + case (#eth_getTransactionCount _) false; + case (#eth_getTransactionReceipt _) false; + case (#eth_sendRawTransaction _) false; + case (#request _) false; case (#canister_status _) Principal.isController(caller); case (#update_settings _) Principal.isController(caller); case _ true; diff --git a/service/pool/Types.mo b/service/pool/Types.mo index a565df2f..3e2a97c0 100644 --- a/service/pool/Types.mo +++ b/service/pool/Types.mo @@ -11,9 +11,15 @@ import Option "mo:base/Option"; import Int "mo:base/Int"; import Timer "mo:base/Timer"; import Debug "mo:base/Debug"; +import Error "mo:base/Error"; +import Cycles "mo:base/ExperimentalCycles"; import ICType "./IC"; module { + type CyclesSettings = { + max_cycles_per_call: Nat; + max_cycles_total: Nat; + }; public type InitParams = { cycles_per_canister: Nat; max_num_canisters: Nat; @@ -22,7 +28,10 @@ module { max_family_tree_size: Nat; // Used for installing asset canister. If set, will not use timer to kill expired canisters, and will not uninstall code when fetching an expired canister (unless the module hash changed). stored_module: ?{hash: Blob; arg: Blob}; + // Disable getCanisterId endpoint admin_only: ?Bool; + // Cycle add limit for whitelisted methods + cycles_settings: ?CyclesSettings; wasm_utils_principal: ?Text; }; public let defaultParams : InitParams = { @@ -33,6 +42,7 @@ module { max_family_tree_size = 5; stored_module = null; admin_only = null; + cycles_settings = null; wasm_utils_principal = ?"ozk6r-tyaaa-aaaab-qab4a-cai"; }; public type InstallArgs = { @@ -67,6 +77,9 @@ module { else if (x.timestamp == y.timestamp and x.id == y.id) { #equal } else { #greater } }; + public func getCyclesSettings(params: InitParams) : CyclesSettings { + Option.get(params.cycles_settings, { max_cycles_per_call = 250_000_000_000; max_cycles_total = 550_000_000_000 }) + }; /* * Main data structure of the playground. The splay tree is the source of truth for @@ -74,7 +87,10 @@ module { * to allow Map-style lookups on the canister data. Childrens and parents define the * controller relationships for dynmically spawned canisters by actor classes. */ - public class CanisterPool(size: Nat, ttl: Nat, max_family_tree_size: Nat) { + public class CanisterPool(params: InitParams) { + let size = params.max_num_canisters; + let ttl = params.canister_time_to_live; + let max_family_tree_size = params.max_family_tree_size; var len = 0; var tree = Splay.Splay(canisterInfoCompare); // Metadata is a replicate of splay tree, which allows lookup without timestamp. Internal use only. @@ -207,16 +223,32 @@ module { public func removeSnapshot(cid: Principal) { snapshots.delete cid; }; - public func spendCycles(cid: Principal, n: Int) : Bool { - let old = Option.get(cycles.get(cid), 0); - let new = old + n; - if (new > defaultParams.cycles_per_canister or new < 0) { - return false; + public func addCycles(cid: Principal, config: { #method: Text; #refund }) : async* () { + switch (config) { + case (#method(method)) { + if (not findId cid) { + throw Error.reject("Canister pool: Only a canister managed by the pool can call " # method); + }; + let curr = Option.get(cycles.get(cid), 0); + let settings = getCyclesSettings(params); + let new = curr + settings.max_cycles_per_call; + if (new > settings.max_cycles_total) { + throw Error.reject("Canister pool: Cycles limit exceeded when calling " # method # ". Already used " # Int.toText(curr) # " cycles. Deploy with your own wallet to avoid cycle limit."); + }; + cycles.put(cid, new); + Cycles.add(settings.max_cycles_per_call); + }; + case (#refund) { + let refund = Cycles.refunded(); + let curr = Option.get(cycles.get(cid), 0); + let new = curr - refund; + if (new < 0) { + throw Error.reject("Canister pool: Cycles refund exceeds the balance. This should not happen."); + }; + cycles.put(cid, new); + }; }; - cycles.put(cid, new); - true; }; - private func notExpired(info: CanisterInfo, now: Int) : Bool = (info.timestamp > now - ttl); // Return a list of canister IDs from which to uninstall code diff --git a/service/wasm-utils/Cargo.lock b/service/wasm-utils/Cargo.lock index d054c81a..7620980e 100644 --- a/service/wasm-utils/Cargo.lock +++ b/service/wasm-utils/Cargo.lock @@ -22,15 +22,15 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arrayvec" @@ -40,9 +40,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "binread" @@ -120,14 +120,14 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.87", ] [[package]] name = "cc" -version = "1.1.13" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "shlex", ] @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "dary_heap" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca" +checksum = "04d2cd9c18b9f454ed67da600630b021a8a80bf33f8c95896ab33aaf1c26b728" [[package]] name = "data-encoding" @@ -253,14 +253,17 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" @@ -270,9 +273,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "ic-cdk" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8ecacd682fa05a985253592963306cb9799622d7b1cce4b1edb89c6ec85be1" +checksum = "b2abdf9341da9f9f6b451a40609cb69645a05a8e9eb7784c16209f16f2c0f76f" dependencies = [ "candid", "ic-cdk-macros", @@ -283,23 +286,23 @@ dependencies = [ [[package]] name = "ic-cdk-macros" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4d857135deef20cc7ea8f3869a30cd9cfeb1392b3a81043790b2cd82adc3e0" +checksum = "b8df41980e95dead28735ab0f748c75477b0c5eab37a09a5641c78ec406a1db0" dependencies = [ "candid", "proc-macro2", "quote", "serde", "serde_tokenstream", - "syn 2.0.75", + "syn 2.0.87", ] [[package]] name = "ic-wasm" -version = "0.8.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5574bf249d201ddd2c27c3fdf178ddacb1be1c705c8a5b4c1339c393758f2bf2" +checksum = "96fcb6878ea543ad3c289602ee738c8409467894dfd89dd67160c52a678e96bc" dependencies = [ "candid", "libflate", @@ -345,12 +348,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.1", "serde", ] @@ -368,9 +371,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libflate" @@ -439,9 +442,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "paste" @@ -462,27 +465,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -501,9 +504,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "semver" @@ -513,9 +516,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -531,13 +534,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.87", ] [[package]] @@ -549,7 +552,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.75", + "syn 2.0.87", ] [[package]] @@ -577,15 +580,15 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" dependencies = [ "cc", "cfg-if", "libc", "psm", - "winapi", + "windows-sys", ] [[package]] @@ -601,9 +604,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -612,22 +615,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.87", ] [[package]] @@ -644,21 +647,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-segmentation" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "version_check" @@ -668,9 +665,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walrus" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467611cafbc8a84834b77d2b4bb191fd2f5769752def8340407e924390c6883b" +checksum = "d68aa3c7b80be75c8458fc087453e5a31a226cfffede2e9b932393b2ea1c624a" dependencies = [ "anyhow", "gimli", @@ -684,14 +681,14 @@ dependencies = [ [[package]] name = "walrus-macro" -version = "0.19.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e5bd22c71e77d60140b0bd5be56155a37e5bd14e24f5f87298040d0cc40d7" +checksum = "439ad39ff894c43c9649fa724cdde9a6fc50b855d517ef071a93e5df82fe51d3" dependencies = [ "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -725,32 +722,83 @@ dependencies = [ "ahash", "bitflags", "hashbrown 0.14.5", - "indexmap 2.4.0", + "indexmap 2.6.0", "semver", "serde", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zerocopy" @@ -769,5 +817,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.87", ] diff --git a/service/wasm-utils/Cargo.toml b/service/wasm-utils/Cargo.toml index d26d1b78..192b0327 100644 --- a/service/wasm-utils/Cargo.toml +++ b/service/wasm-utils/Cargo.toml @@ -9,11 +9,11 @@ crate-type = ["cdylib"] [dependencies] hex = "0.4.3" -ic-cdk = "0.16" +ic-cdk = "0.17" serde = "1.0" serde_bytes = "0.11" candid = "0.10" -ic-wasm = { version = "0.8.5", default-features = false } +ic-wasm = { version = "0.9.1", default-features = false } sha2 = "0.10.6" [profile.release] diff --git a/service/wasm-utils/lib.rs b/service/wasm-utils/lib.rs index 36529a9c..957b7fe4 100644 --- a/service/wasm-utils/lib.rs +++ b/service/wasm-utils/lib.rs @@ -38,7 +38,7 @@ fn transform(wasm: ByteBuf, config: Config) -> ByteBuf { } let instr_config = instrumentation::Config { trace_only_funcs: vec![], - start_address: config.start_page.map(|page| page as i32 * 65536), + start_address: config.start_page.map(|page| page as i64 * 65536), page_limit: config.page_limit.map(|x| x as i32), }; instrumentation::instrument(&mut m, instr_config).unwrap(); diff --git a/src/config/canister-set.js b/src/config/canister-set.js index 038a7bdd..69e4bba8 100644 --- a/src/config/canister-set.js +++ b/src/config/canister-set.js @@ -139,4 +139,7 @@ service ic : { "ryjl3-tyaaa-aaaaa-aaaba-cai": { name: "ledger", }, + "7hfb6-caaaa-aaaar-qadga-cai": { + name: "EVM RPC", + }, }; diff --git a/src/examples.ts b/src/examples.ts index 433d49ab..9a318382 100644 --- a/src/examples.ts +++ b/src/examples.ts @@ -25,23 +25,13 @@ export const exampleProjects: ExampleProject[] = [ name: "Counter (full stack)", repo: { dir: "motoko/minimal-counter-dapp", ...example }, }, - { - name: "Calculator", - repo: { dir: "archive/motoko/calc/src", ...example }, - readme: `${readmeArchiveURL}/calc/README.md`, - }, { name: "Who am I?", repo: { dir: "motoko/whoami/src", ...example }, readme: `${readmeURL}/whoami/README.md`, }, { - name: "Phone Book", - repo: { dir: "archive/motoko/phone-book/src/phone-book", ...example }, - readme: `${readmeArchiveURL}/phone-book/README.md`, - }, - { - name: "Super Heroes", + name: "Super Heroes (full stack)", repo: { dir: "motoko/superheroes", ...example }, }, { @@ -49,7 +39,7 @@ export const exampleProjects: ExampleProject[] = [ repo: { dir: "motoko/random_maze", ...example }, }, { - name: "Game of Life", + name: "Game of Life (full stack)", repo: { dir: "motoko/life", ...example }, }, { @@ -72,6 +62,14 @@ export const exampleProjects: ExampleProject[] = [ repo: { dir: "motoko/send_http_get/src/send_http_get_backend", ...example }, readme: `${readmeURL}/send_http_get/README.md`, }, + { + name: "Threshold ECDSA", + repo: { + dir: "motoko/threshold-ecdsa/src/ecdsa_example_motoko", + ...example, + }, + readme: `${readmeURL}/threshold-ecdsa/README.md`, + }, ]; export async function fetchExample(