Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(FI-885) add created at time #27

Merged
merged 2 commits into from
Aug 15, 2023
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
2 changes: 2 additions & 0 deletions cycles-ledger/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub type NumCycles = Nat;
pub struct DepositArg {
pub to: Account,
pub memo: Option<Memo>,
#[serde(default)]
pub created_at_time: Option<u64>,
}

#[derive(CandidType, Deserialize, Clone, Debug, PartialEq, Eq)]
Expand Down
13 changes: 9 additions & 4 deletions cycles-ledger/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,13 @@ fn deposit(arg: endpoints::DepositArg) -> endpoints::DepositResult {
ic_cdk::trap("deposit amount is insufficient");
}
let memo = validate_memo(arg.memo);
let (txid, balance, _phash) =
storage::record_deposit(&arg.to, amount, memo, ic_cdk::api::time());
let (txid, balance, _phash) = storage::record_deposit(
&arg.to,
amount,
memo,
ic_cdk::api::time(),
arg.created_at_time,
);

// TODO(FI-766): set the certified variable.

Expand Down Expand Up @@ -175,7 +180,7 @@ fn icrc1_transfer(args: TransferArg) -> Result<Nat, TransferError> {
}
}

let (txid, _hash) = storage::transfer(&from, &args.to, amount, memo, now);
let (txid, _hash) = storage::transfer(&from, &args.to, amount, memo, now, args.created_at_time);

Ok(Nat::from(txid))
}
Expand Down Expand Up @@ -289,7 +294,7 @@ async fn send(args: endpoints::SendArg) -> Result<Nat, SendError> {
)
} else {
let now = ic_cdk::api::time();
let (send, _send_hash) = storage::send(&from, amount, memo, now);
let (send, _send_hash) = storage::send(&from, amount, memo, now, args.created_at_time);
Ok(send)
}
}
Expand Down
94 changes: 63 additions & 31 deletions cycles-ledger/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ pub struct Cache {
pub phash: Option<Hash>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Transaction {
pub operation: Operation,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "ts")]
pub created_at_time: Option<u64>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub memo: Option<Memo>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum Operation {
Mint {
Expand All @@ -38,8 +50,6 @@ pub enum Operation {
#[serde(rename = "amt")]
amount: u128,
fee: u128,
#[serde(skip_serializing_if = "Option::is_none")]
memo: Option<Memo>,
},
Transfer {
#[serde(with = "compact_account")]
Expand All @@ -49,23 +59,19 @@ pub enum Operation {
#[serde(rename = "amt")]
amount: u128,
fee: u128,
#[serde(skip_serializing_if = "Option::is_none")]
memo: Option<Memo>,
},
Burn {
#[serde(with = "compact_account")]
from: Account,
#[serde(rename = "amt")]
amount: u128,
fee: u128,
#[serde(skip_serializing_if = "Option::is_none")]
memo: Option<Memo>,
},
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Block {
op: Operation,
transaction: Transaction,
#[serde(rename = "ts")]
pub timestamp: u64,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -197,6 +203,7 @@ pub fn record_deposit(
amount: u128,
memo: Option<Memo>,
now: u64,
created_at_time: Option<u64>,
) -> (u64, u128, Hash) {
assert!(amount >= crate::config::FEE);

Expand All @@ -207,11 +214,14 @@ pub fn record_deposit(
s.balances.insert(key, new_balance);
let phash = s.last_block_hash();
let block_hash = s.emit_block(Block {
op: Operation::Mint {
to: *account,
amount,
transaction: Transaction {
operation: Operation::Mint {
to: *account,
amount,
fee: crate::config::FEE,
},
memo,
fee: crate::config::FEE,
created_at_time,
},
timestamp: now,
phash,
Expand All @@ -226,6 +236,7 @@ pub fn transfer(
amount: u128,
memo: Option<Memo>,
now: u64,
created_at_time: Option<u64>,
) -> (u64, Hash) {
let from_key = to_account_key(from);
let to_key = to_account_key(to);
Expand All @@ -247,12 +258,15 @@ pub fn transfer(

let phash = s.last_block_hash();
let block_hash = s.emit_block(Block {
op: Operation::Transfer {
from: *from,
to: *to,
amount,
transaction: Transaction {
operation: Operation::Transfer {
from: *from,
to: *to,
amount,
fee: crate::config::FEE,
},
memo,
fee: crate::config::FEE,
created_at_time,
},
timestamp: now,
phash,
Expand All @@ -276,11 +290,14 @@ pub fn penalize(from: &Account, now: u64) -> (BlockIndex, Hash) {
}
let phash = s.last_block_hash();
let block_hash = s.emit_block(Block {
op: Operation::Burn {
from: *from,
amount: 0,
transaction: Transaction {
operation: Operation::Burn {
from: *from,
amount: 0,
fee: crate::config::FEE,
},
memo: None,
fee: crate::config::FEE,
created_at_time: None,
},
timestamp: now,
phash,
Expand All @@ -289,7 +306,13 @@ pub fn penalize(from: &Account, now: u64) -> (BlockIndex, Hash) {
})
}

pub fn send(from: &Account, amount: u128, memo: Option<Memo>, now: u64) -> (BlockIndex, Hash) {
pub fn send(
from: &Account,
amount: u128,
memo: Option<Memo>,
now: u64,
created_at_time: Option<u64>,
) -> (BlockIndex, Hash) {
let from_key = to_account_key(from);

mutate_state(|s| {
Expand All @@ -306,11 +329,14 @@ pub fn send(from: &Account, amount: u128, memo: Option<Memo>, now: u64) -> (Bloc
.expect("failed to update balance");
let phash = s.last_block_hash();
let block_hash = s.emit_block(Block {
op: Operation::Burn {
from: *from,
amount,
transaction: Transaction {
operation: Operation::Burn {
from: *from,
amount,
fee: crate::config::FEE,
},
memo,
fee: crate::config::FEE,
created_at_time,
},
timestamp: now,
phash,
Expand All @@ -330,19 +356,25 @@ mod tests {
};
use num_bigint::BigUint;

use crate::ciborium_to_generic_value;
use crate::{
ciborium_to_generic_value,
storage::{Operation, Transaction},
};

use super::Block;

#[test]
fn test_block_hash() {
let block = Block {
op: super::Operation::Transfer {
from: Account::from(Principal::anonymous()),
to: Account::from(Principal::anonymous()),
amount: u128::MAX,
fee: 10_000,
transaction: Transaction {
operation: Operation::Transfer {
from: Account::from(Principal::anonymous()),
to: Account::from(Principal::anonymous()),
amount: u128::MAX,
fee: 10_000,
},
memo: Some(Memo::default()),
created_at_time: None,
},
timestamp: 1691065957,
phash: None,
Expand Down
1 change: 1 addition & 0 deletions depositor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ async fn deposit(arg: DepositArg) -> DepositResult {
let arg = cycles_ledger::endpoints::DepositArg {
to: arg.to,
memo: arg.memo,
created_at_time: Some(ic_cdk::api::time()),
};
let (result,): (DepositResult,) = call_with_payment128(ledger_id, "deposit", (arg,), cycles)
.await
Expand Down