Skip to content

Commit

Permalink
feat: attatch nonce to mutate calls
Browse files Browse the repository at this point in the history
  • Loading branch information
frdomovic committed Dec 19, 2024
1 parent 80ac0ff commit 0a958e0
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 8 deletions.
6 changes: 2 additions & 4 deletions crates/context/config/src/client/env/config/mutate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,10 @@ impl<'a> Method<Icp> for Mutate<'a> {
}

impl<'a, T: Transport> ContextConfigMutateRequest<'a, T> {
pub async fn send(self, signing_key: [u8; 32]) -> Result<(), ClientError<T>> {
pub async fn send(self, signing_key: [u8; 32], nonce: u64) -> Result<(), ClientError<T>> {
let request = Mutate {
signing_key,
// todo! when nonces are implemented in context
// todo! config contract, we fetch it here first
nonce: 0,
nonce,
kind: self.kind,
};

Expand Down
14 changes: 14 additions & 0 deletions crates/context/config/src/client/env/config/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod members;
pub mod members_revision;
pub mod privileges;
pub mod proxy_contract;
pub mod fetch_nonce;

#[derive(Debug)]
pub struct ContextConfigQuery<'a, T> {
Expand Down Expand Up @@ -101,4 +102,17 @@ impl<'a, T: Transport> ContextConfigQuery<'a, T> {

utils::send(&self.client, Operation::Read(params)).await
}

pub async fn fetch_nonce(
&self,
context_id: ContextId,
member_id: ContextIdentity,
) -> Result<u64, ClientError<T>> {
let params = fetch_nonce::FetchNonceRequest {
context_id: Repr::new(context_id),
member: Repr::new(member_id),
};

utils::send(&self.client, Operation::Read(params)).await
}
}
104 changes: 104 additions & 0 deletions crates/context/config/src/client/env/config/query/fetch_nonce.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use candid::{Decode, Encode};
use serde::Serialize;
use starknet::core::codec::Encode as StarknetEncode;

use crate::client::env::config::types::starknet::{
CallData, ContextId as StarknetContextId, ContextIdentity as StarknetContextIdentity,
};
use crate::client::env::Method;
use crate::client::protocol::icp::Icp;
use crate::client::protocol::near::Near;
use crate::client::protocol::starknet::Starknet;
use crate::icp::repr::ICRepr;
use crate::repr::Repr;
use crate::types::{ContextId, ContextIdentity};

#[derive(Copy, Clone, Debug, Serialize)]
pub(super) struct FetchNonceRequest {
pub(super) context_id: Repr<ContextId>,
pub(super) member: Repr<ContextIdentity>,
}

impl FetchNonceRequest {
pub const fn new(context_id: ContextId, member: ContextIdentity) -> Self {

Self {
context_id: Repr::new(context_id),
member: Repr::new(member),
}
}
}

impl Method<Near> for FetchNonceRequest {
const METHOD: &'static str = "fetch_nonce";

type Returns = u64;

fn encode(self) -> eyre::Result<Vec<u8>> {
serde_json::to_vec(&self).map_err(Into::into)
}

fn decode(response: Vec<u8>) -> eyre::Result<Self::Returns> {
let nonce: u64 =
serde_json::from_slice(&response)?;

Ok(nonce)
}
}

impl Method<Starknet> for FetchNonceRequest {
type Returns = u64;

const METHOD: &'static str = "fetch_nonce";

fn encode(self) -> eyre::Result<Vec<u8>> {
let mut call_data = CallData::default();

// Dereference Repr and encode context_id
let context_id: StarknetContextId = (*self.context_id).into();
context_id.encode(&mut call_data)?;

let member: StarknetContextIdentity = (*self.member).into();
member.encode(&mut call_data)?;

Ok(call_data.0)
}

fn decode(response: Vec<u8>) -> eyre::Result<Self::Returns> {
if response.len() != 8 {
return Err(eyre::eyre!(
"Invalid response length: expected 8 bytes, got {}",
response.len()
));
}

let nonce = u64::from_be_bytes(
response
.try_into()
.map_err(|_| eyre::eyre!("Failed to convert response to u64"))?,
);

Ok(nonce)
}
}

impl Method<Icp> for FetchNonceRequest {
type Returns = u64;

const METHOD: &'static str = "fetch_nonce";

fn encode(self) -> eyre::Result<Vec<u8>> {
let context_id = ICRepr::new(*self.context_id);
let member = ICRepr::new(*self.member);

let payload = (context_id, member);

Encode!(&payload).map_err(Into::into)
}

fn decode(response: Vec<u8>) -> eyre::Result<Self::Returns> {
let decoded = Decode!(&response, u64)?;

Ok(decoded)
}
}
53 changes: 49 additions & 4 deletions crates/context/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use calimero_context_config::client::{AnyTransport, Client as ExternalClient};
use calimero_context_config::repr::{Repr, ReprBytes, ReprTransmute};
use calimero_context_config::types::{
Application as ApplicationConfig, ApplicationMetadata as ApplicationMetadataConfig,
ApplicationSource as ApplicationSourceConfig, ContextIdentity, ProposalId,
ApplicationSource as ApplicationSourceConfig, ContextId as IdentityContextId, ContextIdentity,
ProposalId,
};
use calimero_context_config::{Proposal, ProposalAction, ProposalWithApprovals};
use calimero_network::client::NetworkClient;
Expand Down Expand Up @@ -217,6 +218,23 @@ impl ContextManager {
)
}

let context_id: IdentityContextId = context.id.rt().expect("infallible conversion");
let member_id = identity_secret
.public_key()
.rt()
.expect("infallible conversion");

let nonce: u64 = this
.config_client
.query::<ContextConfigEnv>(
this.client_config.new.protocol.as_str().into(),
this.client_config.new.network.as_str().into(),
this.client_config.new.contract_id.as_str().into(),
)
.fetch_nonce(context_id, member_id)
.await?;
let nonce = nonce + 1;

this.config_client
.mutate::<ContextConfigEnv>(
this.client_config.new.protocol.as_str().into(),
Expand All @@ -237,7 +255,7 @@ impl ContextManager {
ApplicationMetadataConfig(Repr::new(application.metadata.into())),
),
)
.send(*context_secret)
.send(*context_secret, nonce)
.await?;

let proxy_contract = this
Expand Down Expand Up @@ -411,6 +429,19 @@ impl ContextManager {
return Ok(None);
};

let member_id = inviter_id.rt().expect("infallible conversion");

let nonce: u64 = self
.config_client
.query::<ContextConfigEnv>(
context_config.protocol.as_ref().into(),
context_config.network.as_ref().into(),
context_config.contract.as_ref().into(),
)
.fetch_nonce(context_id.rt().expect("infallible conversion"), member_id)
.await?;
let nonce = nonce + 1;

self.config_client
.mutate::<ContextConfigEnv>(
context_config.protocol.as_ref().into(),
Expand All @@ -421,7 +452,7 @@ impl ContextManager {
context_id.rt().expect("infallible conversion"),
&[invitee_id.rt().expect("infallible conversion")],
)
.send(requester_secret)
.send(requester_secret, nonce)
.await?;

let invitation_payload = ContextInvitationPayload::new(
Expand Down Expand Up @@ -928,6 +959,20 @@ impl ContextManager {
context_id
);
};

let member_id = signer_id.rt().expect("infallible conversion");

let nonce: u64 = self
.config_client
.query::<ContextConfigEnv>(
context_config.protocol.as_ref().into(),
context_config.network.as_ref().into(),
context_config.contract.as_ref().into(),
)
.fetch_nonce(context_id.rt().expect("infallible conversion"), member_id)
.await?;
let nonce = nonce + 1;

let _ = self
.config_client
.mutate::<ContextConfigEnv>(
Expand All @@ -945,7 +990,7 @@ impl ContextManager {
ApplicationMetadataConfig(Repr::new(application.metadata.into())),
),
)
.send(requester_secret)
.send(requester_secret, nonce)
.await?;

context_meta.application = ApplicationMetaKey::new(application_id);
Expand Down

0 comments on commit 0a958e0

Please sign in to comment.