From 28a20c53bf331ada69bd97a05e903dc09a301bb2 Mon Sep 17 00:00:00 2001 From: alenmestrov Date: Mon, 2 Dec 2024 21:27:44 +0100 Subject: [PATCH] fix: resolved mutate request --- Cargo.lock | 1 - contracts/icp/context-config/.env | 4 +- contracts/icp/context-config/Cargo.toml | 2 +- contracts/icp/context-config/deploy_devnet.sh | 0 contracts/icp/context-config/src/mutate.rs | 4 +- crates/context/config/Cargo.toml | 35 +++++++--- .../config/src/client/env/config/mutate.rs | 19 +++--- .../config/src/client/env/config/types/icp.rs | 12 +++- .../src/client/env/config/types/starknet.rs | 1 - .../context/config/src/client/protocol/icp.rs | 67 ++++++------------- 10 files changed, 71 insertions(+), 74 deletions(-) mode change 100644 => 100755 contracts/icp/context-config/deploy_devnet.sh diff --git a/Cargo.lock b/Cargo.lock index 28c9401e9..5ce3ffa4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -923,7 +923,6 @@ dependencies = [ "near-jsonrpc-client", "near-jsonrpc-primitives", "near-primitives", - "rand 0.8.5", "reqwest 0.12.9", "serde", "serde_json", diff --git a/contracts/icp/context-config/.env b/contracts/icp/context-config/.env index a2a7da06e..eb2c64045 100644 --- a/contracts/icp/context-config/.env +++ b/contracts/icp/context-config/.env @@ -2,7 +2,7 @@ # DFX CANISTER ENVIRONMENT VARIABLES DFX_VERSION='0.24.2' DFX_NETWORK='local' -CANISTER_ID_CONTEXT_CONTRACT='bw4dl-smaaa-aaaaa-qaacq-cai' -CANISTER_ID='bw4dl-smaaa-aaaaa-qaacq-cai' +CANISTER_ID_CONTEXT_CONTRACT='cpmcr-yeaaa-aaaaa-qaala-cai' +CANISTER_ID='cpmcr-yeaaa-aaaaa-qaala-cai' CANISTER_CANDID_PATH='/Users/alen/www/calimero/core/contracts/icp/context-config/context_contract.did' # END DFX CANISTER ENVIRONMENT VARIABLES \ No newline at end of file diff --git a/contracts/icp/context-config/Cargo.toml b/contracts/icp/context-config/Cargo.toml index ea8bb60ff..8fdcc7071 100644 --- a/contracts/icp/context-config/Cargo.toml +++ b/contracts/icp/context-config/Cargo.toml @@ -21,5 +21,5 @@ thiserror.workspace = true [dev-dependencies] pocket-ic = "6.0.0" -rand = "0.8" +rand.workspace = true ed25519-dalek = "2.0" \ No newline at end of file diff --git a/contracts/icp/context-config/deploy_devnet.sh b/contracts/icp/context-config/deploy_devnet.sh old mode 100644 new mode 100755 diff --git a/contracts/icp/context-config/src/mutate.rs b/contracts/icp/context-config/src/mutate.rs index e1aba06b4..b504c9ed6 100644 --- a/contracts/icp/context-config/src/mutate.rs +++ b/contracts/icp/context-config/src/mutate.rs @@ -16,8 +16,8 @@ pub fn mutate(signed_request: ICPSigned) -> Result<(), String> { .map_err(|e| format!("Failed to verify signature: {}", e))?; // Check request timestamp - let current_time = ic_cdk::api::time(); - if current_time.saturating_sub(request.timestamp_ms) > 1000 * 5 { + let current_time_ms = ic_cdk::api::time() / 1_000_000; // Convert nanoseconds to milliseconds + if current_time_ms.saturating_sub(request.timestamp_ms) > 5_000 { // 5 seconds threshold return Err("request expired".to_string()); } diff --git a/crates/context/config/Cargo.toml b/crates/context/config/Cargo.toml index bd4346e37..b3f7e5038 100644 --- a/crates/context/config/Cargo.toml +++ b/crates/context/config/Cargo.toml @@ -9,16 +9,15 @@ license.workspace = true [dependencies] bs58.workspace = true borsh = { workspace = true, features = ["derive"] } -candid.workspace = true -ed25519-consensus.workspace = true +candid = { workspace = true, optional = true } +ed25519-consensus = { workspace = true, optional = true } ed25519-dalek.workspace = true either = { workspace = true, optional = true } eyre = { workspace = true, optional = true } -hex.workspace = true -ic-agent.workspace = true -ic-cdk.workspace = true -ic-cdk-macros.workspace = true -rand.workspace = true +hex = { workspace = true, optional = true } +ic-agent = { workspace = true, optional = true } +ic-cdk = { workspace = true, optional = true } +ic-cdk-macros = { workspace = true, optional = true } near-crypto = { workspace = true, optional = true } near-jsonrpc-client = { workspace = true, optional = true } near-jsonrpc-primitives = { workspace = true, optional = true } @@ -37,15 +36,33 @@ workspace = true [features] client = [ + "near", + "icp", + "starknet", "dep:either", "dep:eyre", + "reqwest/json", + "url/serde", +] + +near = [ "dep:near-crypto", "dep:near-jsonrpc-client", "dep:near-jsonrpc-primitives", "dep:near-primitives", - "reqwest/json", +] + +icp = [ + "dep:candid", + "dep:ic-agent", + "dep:ic-cdk", + "dep:ic-cdk-macros", + "dep:ed25519-consensus", +] + +starknet = [ + "dep:hex", "dep:starknet", "dep:starknet-crypto", "dep:starknet-types-core", - "url/serde", ] diff --git a/crates/context/config/src/client/env/config/mutate.rs b/crates/context/config/src/client/env/config/mutate.rs index ed388319f..693803150 100644 --- a/crates/context/config/src/client/env/config/mutate.rs +++ b/crates/context/config/src/client/env/config/mutate.rs @@ -140,23 +140,22 @@ impl<'a> Method for Mutate<'a> { let request = ICPRequest::new(signer_sk.verifying_key().rt()?, self.kind.into()); let signed = ICPSigned::new(request, |b| signer_sk.sign(b))?; - - let encoded2 = Encode!(&signed)?; - + let encoded = candid::encode_one(&signed)?; - println!("encoded: {:?}", encoded); - println!("encoded2: {:?}", encoded2); - Ok(encoded) } fn decode(response: Vec) -> eyre::Result { - if !response.is_empty() { - eyre::bail!("unexpected response {:?}", response); + if response.is_empty() { + // Empty response means success + Ok(()) + } else { + // Non-empty response means there was an error message + let error_msg = String::from_utf8(response) + .map_err(|e| eyre::eyre!("Invalid UTF-8 in error message: {}", e))?; + eyre::bail!("{}", error_msg) } - - Ok(()) } } diff --git a/crates/context/config/src/client/env/config/types/icp.rs b/crates/context/config/src/client/env/config/types/icp.rs index 861dc913b..eac338b12 100644 --- a/crates/context/config/src/client/env/config/types/icp.rs +++ b/crates/context/config/src/client/env/config/types/icp.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::marker::PhantomData; +use std::time; use bs58::decode::Result as Bs58Result; use candid::CandidType; @@ -283,10 +284,19 @@ pub struct ICPRequest { impl ICPRequest { pub fn new(signer_id: ICSignerId, kind: ICPRequestKind) -> Self { + #[expect( + clippy::cast_possible_truncation, + reason = "This is never expected to overflow" + )] + let timestamp_ms = time::SystemTime::now() + .duration_since(time::UNIX_EPOCH) + .expect("Time went backwards") + .as_millis() as u64; + Self { signer_id, kind, - timestamp_ms: 0, // Default timestamp for tests + timestamp_ms, } } } diff --git a/crates/context/config/src/client/env/config/types/starknet.rs b/crates/context/config/src/client/env/config/types/starknet.rs index 23224f989..b221e9ea8 100644 --- a/crates/context/config/src/client/env/config/types/starknet.rs +++ b/crates/context/config/src/client/env/config/types/starknet.rs @@ -1,6 +1,5 @@ use std::collections::BTreeMap; -use hex; use starknet::core::codec::{Decode, Encode, Error, FeltWriter}; use starknet::core::types::Felt; diff --git a/crates/context/config/src/client/protocol/icp.rs b/crates/context/config/src/client/protocol/icp.rs index 1faeb215d..78cd8fceb 100644 --- a/crates/context/config/src/client/protocol/icp.rs +++ b/crates/context/config/src/client/protocol/icp.rs @@ -1,21 +1,16 @@ use std::borrow::Cow; use std::collections::BTreeMap; +use candid::{decode_one, Result as CandidResult}; use ed25519_consensus::SigningKey; -use ed25519_dalek::{Signer, SigningKey as DSigningKey}; use ic_agent::agent::CallResponse; use ic_agent::export::Principal; use ic_agent::Agent; -use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; use thiserror::Error; use url::Url; use super::Protocol; -use crate::client::env::config::types::icp::{ - ICApplication, ICApplicationId, ICBlobId, ICContextId, ICContextIdentity, ICPContextRequest, - ICPContextRequestKind, ICPRequest, ICPRequestKind, ICPSigned, ICSignerId, -}; use crate::client::transport::{ AssociatedTransport, Operation, ProtocolTransport, TransportRequest, }; @@ -218,37 +213,6 @@ impl Network { method: String, args: Vec, ) -> Result, IcpError> { - let current_time: u64 = 1733150708000u64; - - let sign_key = DSigningKey::from_bytes(&[0u8; 32]); - let context_pk = sign_key.verifying_key(); - - let context_id = ICContextId::new(context_pk.to_bytes()); - - let request = ICPRequest { - kind: ICPRequestKind::Context(ICPContextRequest { - context_id: context_id.clone(), - kind: ICPContextRequestKind::Add { - author_id: ICContextIdentity::new([0u8; 32]), - application: ICApplication { - id: ICApplicationId::new([0u8; 32]), - blob: ICBlobId::new([0u8; 32]), - size: 0, - source: String::new(), - metadata: vec![], - }, - }, - }), - signer_id: ICSignerId::new(context_id.as_bytes()), - timestamp_ms: current_time, - }; - - let sign_req = ICPSigned::new(request, |bytes| sign_key.sign(bytes)) - .expect("Failed to create signed request"); - - println!("Sign request: {:?}", sign_req); - - let args_encoded = candid::encode_one(sign_req).unwrap(); self.client .fetch_root_key() .await @@ -260,19 +224,28 @@ impl Network { let response = self .client .update(canister_id, method) - .with_arg(args_encoded) + .with_arg(args) .call() .await; + match response { - Ok(CallResponse::Response((data, _certificate))) => Ok(data), - Ok(CallResponse::Poll(_)) => Err(IcpError::Custom { - operation: ErrorOperation::Query, - reason: "Unexpected Poll response".to_string(), - }), - Err(err) => Err(IcpError::Custom { - operation: ErrorOperation::Query, - reason: err.to_string(), - }), + Ok(CallResponse::Response((data, _))) => { + // Now try to decode the actual data + match candid::decode_one::>(&data) { + Ok(decoded) => { + match decoded { + Ok(()) => Ok(vec![]), // Return empty vec for success + Err(err_msg) => Ok(err_msg.into_bytes()) // Return error message as bytes + } + }, + Err(e) => { + println!("Failed to decode: {}", e); + Ok(e.to_string().into_bytes()) // Return decode error as bytes + } + } + }, + Ok(CallResponse::Poll(_)) => Ok("Unexpected polling response".as_bytes().to_vec()), + Err(err) => Ok(err.to_string().into_bytes()), } } }