Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions Cargo.lock

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

11 changes: 10 additions & 1 deletion candid/root.did
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ type DetailValue = variant {
U64 : nat64;
Vec : vec DetailValue;
Slice : vec nat8;
TokenIdU64 : nat64;
Text : text;
True;
False;
Expand All @@ -20,6 +21,11 @@ type GetNextCanistersResponse = record {
witness : opt Witness;
canisters : vec principal;
};
type GetTokenTransactionsArg = record {
token_id : nat64;
page : opt nat32;
witness : bool;
};
type GetTransactionResponse = variant {
Delegate : record { principal; opt Witness };
Found : record { opt Event; opt Witness };
Expand All @@ -44,9 +50,13 @@ type WithIdArg = record { id : nat64; witness : bool };
type WithWitnessArg = record { witness : bool };
type Witness = record { certificate : vec nat8; tree : vec nat8 };
service : {
balance : () -> (nat64) query;
contract_id : () -> (principal) query;
get_bucket_for : (WithIdArg) -> (GetBucketResponse) query;
get_next_canisters : (WithWitnessArg) -> (GetNextCanistersResponse) query;
get_token_transactions : (GetTokenTransactionsArg) -> (
GetTransactionsResponseBorrowed,
) query;
get_transaction : (WithIdArg) -> (GetTransactionResponse) query;
get_transactions : (GetTransactionsArg) -> (
GetTransactionsResponseBorrowed,
Expand All @@ -56,7 +66,6 @@ service : {
) query;
insert : (IndefiniteEvent) -> (nat64);
migrate : (vec Event) -> ();
balance : () -> (nat64) query;
size : () -> (nat64) query;
time : () -> (nat64) query;
}
1 change: 1 addition & 0 deletions candid/sdk_example.did
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ type DetailValue = variant {
U64 : nat64;
Vec : vec DetailValue;
Slice : vec nat8;
TokenIdU64 : nat64;
Text : text;
True;
False;
Expand Down
2 changes: 1 addition & 1 deletion canisters/root/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2018"

[dependencies]
cap-common = { path= "../../common" }
ic-certified-map = "0.1.0"
certified-vars = "0.1.2"
ic-kit = "0.4.3"
ic-cdk = "0.3.1"
serde = "1.0.116"
Expand Down
80 changes: 59 additions & 21 deletions canisters/root/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use cap_common::bucket_lookup_table::BucketLookupTable;
use cap_common::canister_list::CanisterList;
use cap_common::transaction::{Event, IndefiniteEvent};
use cap_common::Bucket;
use ic_certified_map::{fork, fork_hash, AsHashTree, HashTree};
use certified_vars::{
hashtree::{fork, fork_hash},
AsHashTree, HashTree, Map, Seq,
};
use ic_kit::candid::{candid_method, export_service};
use ic_kit::{ic, Principal};
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;

use cap_common::did::*;
use ic_kit::macros::*;

mod upgrade;
pub mod upgrade;

/// Merkle tree of the canister.
///
Expand All @@ -23,11 +24,11 @@ mod upgrade;
/// / \
/// / \ 2
/// 0 1
#[derive(Serialize)]
#[derive(Serialize, Deserialize)]
struct Data {
bucket: Bucket,
buckets: BucketLookupTable,
next_canisters: CanisterList,
buckets: Map<TransactionId, Principal>,
next_canisters: Seq<BucketId>,
/// List of all the users in this token contract.
users: BTreeSet<Principal>,
cap_id: Principal,
Expand All @@ -39,13 +40,13 @@ struct Data {
impl Default for Data {
fn default() -> Self {
Self {
bucket: Bucket::new(0),
bucket: Bucket::new(Principal::management_canister(), 0),
buckets: {
let mut table = BucketLookupTable::default();
let mut table = Map::new();
table.insert(0, ic::id());
table
},
next_canisters: CanisterList::new(),
next_canisters: Seq::new(),
users: BTreeSet::new(),
cap_id: Principal::management_canister(),
contract: Principal::management_canister(),
Expand All @@ -61,6 +62,7 @@ fn init(contract: Principal, writers: BTreeSet<Principal>) {
data.cap_id = ic::caller();
data.contract = contract;
data.writers = writers;
data.bucket = Bucket::new(contract, 0);
}

#[query]
Expand All @@ -82,7 +84,7 @@ fn get_next_canisters(arg: WithWitnessArg) -> GetNextCanistersResponse {
),
};

let canisters = data.next_canisters.to_vec();
let canisters = data.next_canisters.as_vec().clone();

GetNextCanistersResponse { canisters, witness }
}
Expand Down Expand Up @@ -179,6 +181,41 @@ fn get_user_transactions(arg: GetUserTransactionsArg) -> GetTransactionsResponse
}
}

#[query]
#[candid_method(query)]
fn get_token_transactions(
arg: GetTokenTransactionsArg,
) -> GetTransactionsResponseBorrowed<'static> {
let data = ic::get::<Data>();

let page = arg
.page
.unwrap_or_else(|| data.bucket.last_page_for_token(&arg.token_id));

let witness = match arg.witness {
false => None,
true => Some(
fork(
fork(
data.bucket
.witness_transactions_for_token(&arg.token_id, page),
HashTree::Pruned(data.buckets.root_hash()),
),
HashTree::Pruned(data.next_canisters.root_hash()),
)
.into(),
),
};

let events = data.bucket.get_transactions_for_token(&arg.token_id, page);

GetTransactionsResponseBorrowed {
data: events,
page,
witness,
}
}

#[query]
#[candid_method(query)]
fn get_bucket_for(arg: WithIdArg) -> GetBucketResponse {
Expand All @@ -190,17 +227,18 @@ fn get_bucket_for(arg: WithIdArg) -> GetBucketResponse {
fork(
fork(
HashTree::Pruned(data.bucket.root_hash()),
data.buckets.gen_witness(arg.id),
data.buckets.witness(&arg.id),
),
HashTree::Pruned(data.next_canisters.root_hash()),
)
.into(),
),
};

let canister = *data.buckets.get_bucket_for(arg.id);

GetBucketResponse { canister, witness }
GetBucketResponse {
canister: ic::id(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just so I understand correctly, we are hard coding this because it's currently a single bucket and in the future when we change to multiple bucket canisters it would be based on the arg.id instead right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

witness,
}
}

#[query]
Expand Down Expand Up @@ -246,7 +284,7 @@ fn insert(event: IndefiniteEvent) -> TransactionId {
new_users,
));

let id = data.bucket.insert(&data.contract, event);
let id = data.bucket.insert(event);

data.allow_migration = false;

Expand All @@ -268,9 +306,9 @@ fn migrate(events: Vec<Event>) {
panic!("The method can only be invoked by one of the writers.");
}

if !data.allow_migration {
panic!("Migration is not allowed after an insert.")
}
// if !data.allow_migration {
// panic!("Migration is not allowed after an insert.")
// }

let mut new_users = Vec::new();

Expand All @@ -281,7 +319,7 @@ fn migrate(events: Vec<Event>) {
}
}

data.bucket.insert(&data.contract, event);
data.bucket.insert(event);
}

ic_cdk::block_on(write_new_users_to_cap(
Expand Down
Loading