Skip to content

Commit

Permalink
Merge branch 'master' into petarjuki7/cli-context-update
Browse files Browse the repository at this point in the history
  • Loading branch information
petarjuki7 authored Nov 14, 2024
2 parents 240211a + d303ad1 commit 9b9e529
Show file tree
Hide file tree
Showing 61 changed files with 2,323 additions and 809 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
uses: easimon/maximize-build-space@v10
with:
build-mount-path: ${{ env.STAGE_DIR }}
root-reserve-mb: 4096
root-reserve-mb: 8192

- name: Relocate environment
run: |
Expand Down
43 changes: 40 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ members = [
"./crates/config",
"./crates/context",
"./crates/context/config",
"./crates/crypto",
"./crates/meroctl",
"./crates/merod",
"./crates/network",
Expand All @@ -34,10 +35,12 @@ members = [
"./apps/visited",
"./apps/blockchain",

"./contracts/context-config",
"./contracts/registry",
"./contracts/proxy-lib",
"./contracts/test-counter",
"./contracts/context-config",
"./contracts/registry",
"./contracts/proxy-lib",
"./contracts/test-counter",

"./e2e-tests",
]

[workspace.dependencies]
Expand All @@ -56,6 +59,7 @@ claims = "0.7.1"
clap = "4.4.18"
color-eyre = "0.6.2"
const_format = "0.2.32"
curve25519-dalek = "4.1.3"
dirs = "5.0.1"
ed25519-dalek = "2.1.1"
either = "1.13.0"
Expand Down Expand Up @@ -92,6 +96,7 @@ quote = "1.0.37"
rand = "0.8.5"
rand_chacha = "0.3.1"
reqwest = "0.12.2"
ring = "0.17.8"
rocksdb = "0.22.0"
rust-embed = "8.5.0"
sha2 = "0.10.8"
Expand Down
1 change: 0 additions & 1 deletion contracts/context-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ crate-type = ["rlib", "cdylib"]

[dependencies]
near-sdk = { workspace = true, features = ["unstable"] }
hex.workspace = true
calimero-context-config = { path = "../../crates/context/config" }

[dev-dependencies]
Expand Down
129 changes: 64 additions & 65 deletions contracts/context-config/src/mutate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use calimero_context_config::types::{
use calimero_context_config::{ContextRequest, ContextRequestKind, Request, RequestKind};
use near_sdk::serde_json::{self, json};
use near_sdk::store::IterableSet;
use near_sdk::{
env, near, require, AccountId, Gas, NearToken, Promise, PromiseError, PromiseResult,
};
use near_sdk::{env, near, require, AccountId, Gas, NearToken, Promise, PromiseError};

use super::{
parse_input, Context, ContextConfigs, ContextConfigsExt, ContextPrivilegeScope, Guard, Prefix,
Expand All @@ -18,7 +16,6 @@ use super::{

#[near]
impl ContextConfigs {
#[payable]
pub fn mutate(&mut self) {
parse_input!(request: Signed<Request<'_>>);

Expand All @@ -40,7 +37,8 @@ impl ContextConfigs {
author_id,
application,
} => {
self.add_context(&request.signer_id, context_id, author_id, application);
let _is_sent_on_drop =
self.add_context(&request.signer_id, context_id, author_id, application);
}
ContextRequestKind::UpdateApplication { application } => {
self.update_application(&request.signer_id, context_id, application);
Expand All @@ -58,7 +56,8 @@ impl ContextConfigs {
self.revoke(&request.signer_id, context_id, capabilities.into_owned());
}
ContextRequestKind::UpdateProxyContract => {
self.update_proxy_contract(&request.signer_id, context_id);
let _is_sent_on_drop =
self.update_proxy_contract(&request.signer_id, context_id);
}
},
}
Expand Down Expand Up @@ -125,9 +124,9 @@ impl ContextConfigs {
env::panic_str("context already exists");
}

// Initiate proxy contract deployment with a callback for when it completes
self.deploy_proxy_contract(context_id, account_id)
.then(Self::ext(env::current_account_id()).add_context_callback(context_id))
env::log_str(&format!("Context `{}` added", context_id));

self.init_proxy_contract(context_id, account_id)
}

fn update_application(
Expand Down Expand Up @@ -301,35 +300,61 @@ impl ContextConfigs {
}
}

pub fn deploy_proxy_contract(
// take the proxy code from LazyOption's cache
// without it assuming we're removing the value
fn get_proxy_code(&self) -> Vec<u8> {
let code_ref = self.proxy_code.get();

let code_ptr = std::ptr::from_ref(code_ref) as usize + 0;

let code_mut = unsafe { &mut *(code_ptr as *mut Option<Vec<u8>>) };

code_mut.take().expect("proxy code not set")
}

pub fn init_proxy_contract(
&mut self,
context_id: Repr<ContextId>,
account_id: AccountId,
) -> Promise {
// Deploy and initialize the proxy contract
// Known constants from NEAR protocol
const ACCOUNT_CREATION_COST: NearToken = NearToken::from_millinear(1); // 0.001 NEAR
const MIN_ACCOUNT_BALANCE: NearToken = NearToken::from_millinear(35).saturating_div(10); // 0.0035 NEAR
const STORAGE_TIP: NearToken = NearToken::from_near(1).saturating_div(10); // 0.1 NEAR

let contract_bytes = self.get_proxy_code();
let storage_cost = env::storage_byte_cost().saturating_mul(contract_bytes.len() as u128);

let required_deposit = ACCOUNT_CREATION_COST
.saturating_add(MIN_ACCOUNT_BALANCE)
.saturating_add(STORAGE_TIP)
.saturating_add(storage_cost);

require!(
env::account_balance() >= required_deposit,
"Insufficient contract balance for deployment"
);

let init_args = serde_json::to_vec(&json!({ "context_id": context_id })).unwrap();

Promise::new(account_id.clone())
.create_account()
.transfer(env::attached_deposit())
.deploy_contract(self.proxy_code.get().clone().unwrap())
.transfer(required_deposit)
.deploy_contract(contract_bytes)
.function_call(
"init".to_owned(),
serde_json::to_vec(&json!({
"context_id": context_id,
"context_config_account_id": env::current_account_id()
}))
.unwrap(),
NearToken::from_near(0),
Gas::from_tgas(30),
init_args,
NearToken::default(),
Gas::from_tgas(1),
)
.then(Self::ext(env::current_account_id()).proxy_deployment_callback())
.then(Self::ext(env::current_account_id()).proxy_contract_callback())
}

fn update_proxy_contract(
&mut self,
signer_id: &SignerId,
context_id: Repr<ContextId>,
) -> Promise {
// Get the context and verify proxy contract exists
let context = self
.contexts
.get_mut(&context_id)
Expand All @@ -339,63 +364,37 @@ impl ContextConfigs {
.proxy
.get(signer_id)
.expect("unable to update contract")
.get_mut();
.get_mut()
.clone();

let contract_bytes = self.get_proxy_code();
let storage_cost = env::storage_byte_cost().saturating_mul(contract_bytes.len() as u128);

let new_code = self.proxy_code.get().clone().unwrap();
require!(
env::account_balance() >= storage_cost,
"Insufficient contract balance for deployment"
);

// Call the update method on the proxy contract
Promise::new(proxy_account_id.clone())
Promise::new(proxy_account_id)
.function_call(
"update_contract".to_owned(),
new_code,
NearToken::from_near(0),
contract_bytes,
storage_cost,
Gas::from_tgas(100),
)
.then(Self::ext(env::current_account_id()).update_proxy_callback())
.then(Self::ext(env::current_account_id()).proxy_contract_callback())
}
}

#[near]
impl ContextConfigs {
pub fn proxy_deployment_callback(
#[private]
pub fn proxy_contract_callback(
&mut self,
#[callback_result] call_result: Result<(), PromiseError>,
) {
if let Err(e) = call_result {
panic!("Failed to deploy proxy contract: {:?}", e);
}
}

pub fn add_context_callback(&mut self, context_id: Repr<ContextId>) {
require!(
env::promise_results_count() == 1,
"Expected 1 promise result"
);
call_result.expect("Failed to update proxy contract");

match env::promise_result(0) {
PromiseResult::Successful(_) => {
env::log_str(&format!("Context `{context_id}` added"));
}
_ => {
panic!("Failed to deploy proxy contract for context");
}
}
}

#[private]
#[handle_result]
pub fn update_contract_callback(&mut self) -> Result<(), &'static str> {
require!(
env::promise_results_count() == 1,
"Expected 1 promise result"
);

match env::promise_result(0) {
PromiseResult::Successful(_) => {
env::log_str("Successfully updated proxy contract code");
Ok(())
}
_ => Err("Failed to update proxy contract code"),
}
env::log_str("Successfully deployed proxy contract");
}
}
4 changes: 2 additions & 2 deletions contracts/context-config/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ impl ContextConfigs {
context.application.revision()
}

pub fn proxy_contract(&self, context_id: Repr<ContextId>) -> AccountId {
pub fn proxy_contract(&self, context_id: Repr<ContextId>) -> &AccountId {
let context = self
.contexts
.get(&context_id)
.expect("context does not exist");

context.proxy.clone()
&context.proxy
}

pub fn members(
Expand Down
12 changes: 5 additions & 7 deletions contracts/context-config/src/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ impl ContextConfigs {
env::log_str("Erasing contract");

for (_, context) in self.contexts.drain() {
drop(context.application.into_inner());
let _ignored = context.application.into_inner();
context.members.into_inner().clear();
let _ignored = context.proxy.into_inner();
}

self.proxy_code.set(None);

env::log_str(&format!(
"Post-erase storage usage: {}",
env::storage_usage()
Expand Down Expand Up @@ -84,15 +87,10 @@ impl ContextConfigs {
}
}

#[private]
pub fn update_proxy_callback(&mut self) {
env::log_str("Successfully updated proxy contract");
}

#[private]
pub fn set_proxy_code(&mut self) {
self.proxy_code
.set(Some(env::input().expect("Expected proxy code").to_vec()));
.set(Some(env::input().expect("Expected proxy code")));
}
}

Expand Down
Loading

0 comments on commit 9b9e529

Please sign in to comment.