Skip to content

Commit cfd1859

Browse files
authored
chore(ckbtc): remove distribute_kyt_fee and reimburse_failed_kyt (#3325)
XC-237 Since the ckBTC minter switched to using the checker canister, it no longer needs to distribute kyt fees, or reimburse failed kyt. These calls can be removed from the code, but we do still need to keep them for event and state handling during replay.
1 parent 8acef9e commit cfd1859

File tree

7 files changed

+6
-260
lines changed

7 files changed

+6
-260
lines changed

rs/bitcoin/ckbtc/minter/src/guard.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,6 @@ impl Drop for TimerLogicGuard {
8989
}
9090
}
9191

92-
#[must_use]
93-
pub struct DistributeKytFeeGuard(());
94-
95-
impl DistributeKytFeeGuard {
96-
pub fn new() -> Option<Self> {
97-
mutate_state(|s| {
98-
if s.is_distributing_fee {
99-
return None;
100-
}
101-
s.is_distributing_fee = true;
102-
Some(DistributeKytFeeGuard(()))
103-
})
104-
}
105-
}
106-
107-
impl Drop for DistributeKytFeeGuard {
108-
fn drop(&mut self) {
109-
mutate_state(|s| {
110-
s.is_distributing_fee = false;
111-
});
112-
}
113-
}
114-
11592
pub fn balance_update_guard(p: Principal) -> Result<Guard<PendingBalanceUpdates>, GuardError> {
11693
Guard::new(p)
11794
}

rs/bitcoin/ckbtc/minter/src/lib.rs

Lines changed: 1 addition & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use crate::address::BitcoinAddress;
22
use crate::logs::{P0, P1};
33
use crate::management::CallError;
4-
use crate::memo::Status;
54
use crate::queries::WithdrawalFee;
6-
use crate::state::ReimbursementReason;
75
use crate::updates::update_balance::UpdateBalanceError;
86
use async_trait::async_trait;
97
use candid::{CandidType, Deserialize, Principal};
@@ -14,8 +12,7 @@ use ic_btc_interface::{
1412
use ic_canister_log::log;
1513
use ic_management_canister_types::DerivationPath;
1614
use icrc_ledger_types::icrc1::account::Account;
17-
use icrc_ledger_types::icrc1::transfer::{Memo, TransferError};
18-
use num_traits::ToPrimitive;
15+
use icrc_ledger_types::icrc1::transfer::Memo;
1916
use scopeguard::{guard, ScopeGuard};
2017
use serde::Serialize;
2118
use serde_bytes::ByteBuf;
@@ -464,40 +461,6 @@ fn finalized_txids(candidates: &[state::SubmittedBtcTransaction], new_utxos: &[U
464461
.collect()
465462
}
466463

467-
async fn reimburse_failed_kyt() {
468-
let try_to_reimburse = state::read_state(|s| s.pending_reimbursements.clone());
469-
for (burn_block_index, entry) in try_to_reimburse {
470-
let (memo_status, kyt_fee) = match entry.reason {
471-
ReimbursementReason::TaintedDestination { kyt_fee, .. } => (Status::Rejected, kyt_fee),
472-
ReimbursementReason::CallFailed => (Status::CallFailed, 0),
473-
};
474-
let reimburse_memo = crate::memo::MintMemo::KytFail {
475-
kyt_fee: Some(kyt_fee),
476-
status: Some(memo_status),
477-
associated_burn_index: Some(burn_block_index),
478-
};
479-
if let Ok(block_index) = crate::updates::update_balance::mint(
480-
entry
481-
.amount
482-
.checked_sub(kyt_fee)
483-
.expect("reimburse underflow"),
484-
entry.account,
485-
crate::memo::encode(&reimburse_memo).into(),
486-
)
487-
.await
488-
{
489-
state::mutate_state(|s| {
490-
state::audit::reimbursed_failed_deposit(
491-
s,
492-
burn_block_index,
493-
block_index,
494-
&IC_CANISTER_RUNTIME,
495-
)
496-
});
497-
}
498-
}
499-
}
500-
501464
async fn finalize_requests() {
502465
if state::read_state(|s| s.submitted_transactions.is_empty()) {
503466
return;
@@ -1119,96 +1082,6 @@ fn distribute(amount: u64, n: u64) -> Vec<u64> {
11191082
shares
11201083
}
11211084

1122-
pub async fn distribute_kyt_fees() {
1123-
use icrc_ledger_client_cdk::CdkRuntime;
1124-
use icrc_ledger_client_cdk::ICRC1Client;
1125-
use icrc_ledger_types::icrc1::transfer::TransferArg;
1126-
1127-
enum MintError {
1128-
TransferError(TransferError),
1129-
CallError(i32, String),
1130-
}
1131-
1132-
impl std::fmt::Debug for MintError {
1133-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1134-
match self {
1135-
MintError::TransferError(e) => write!(f, "TransferError({:?})", e),
1136-
MintError::CallError(code, msg) => write!(f, "CallError({}, {:?})", code, msg),
1137-
}
1138-
}
1139-
}
1140-
1141-
async fn mint(amount: u64, to: candid::Principal, memo: Memo) -> Result<u64, MintError> {
1142-
debug_assert!(memo.0.len() <= CKBTC_LEDGER_MEMO_SIZE as usize);
1143-
1144-
let client = ICRC1Client {
1145-
runtime: CdkRuntime,
1146-
ledger_canister_id: state::read_state(|s| s.ledger_id.get().into()),
1147-
};
1148-
client
1149-
.transfer(TransferArg {
1150-
from_subaccount: None,
1151-
to: Account {
1152-
owner: to,
1153-
subaccount: None,
1154-
},
1155-
fee: None,
1156-
created_at_time: None,
1157-
memo: Some(memo),
1158-
amount: candid::Nat::from(amount),
1159-
})
1160-
.await
1161-
.map_err(|(code, msg)| MintError::CallError(code, msg))?
1162-
.map_err(MintError::TransferError)
1163-
.map(|n| n.0.to_u64().expect("nat does not fit into u64"))
1164-
}
1165-
1166-
let fees_to_distribute = state::read_state(|s| s.owed_kyt_amount.clone());
1167-
for (provider, amount) in fees_to_distribute {
1168-
let memo = crate::memo::MintMemo::Kyt;
1169-
match mint(amount, provider, crate::memo::encode(&memo).into()).await {
1170-
Ok(block_index) => {
1171-
state::mutate_state(|s| {
1172-
if let Err(state::Overdraft(overdraft)) = state::audit::distributed_kyt_fee(
1173-
s,
1174-
provider,
1175-
amount,
1176-
block_index,
1177-
&IC_CANISTER_RUNTIME,
1178-
) {
1179-
// This should never happen because:
1180-
// 1. The fee distribution task is guarded (at most one copy is active).
1181-
// 2. Fee distribution is the only way to decrease the balance.
1182-
log!(
1183-
P0,
1184-
"BUG[distribute_kyt_fees]: distributed {} to {} but the balance is only {}",
1185-
tx::DisplayAmount(amount),
1186-
provider,
1187-
tx::DisplayAmount(amount - overdraft),
1188-
);
1189-
} else {
1190-
log!(
1191-
P0,
1192-
"[distribute_kyt_fees]: minted {} to {}",
1193-
tx::DisplayAmount(amount),
1194-
provider,
1195-
);
1196-
}
1197-
});
1198-
}
1199-
Err(error) => {
1200-
log!(
1201-
P0,
1202-
"[distribute_kyt_fees]: failed to mint {} to {} with error: {:?}",
1203-
tx::DisplayAmount(amount),
1204-
provider,
1205-
error
1206-
);
1207-
}
1208-
}
1209-
}
1210-
}
1211-
12121085
pub fn timer<R: CanisterRuntime + 'static>(runtime: R) {
12131086
use tasks::{pop_if_ready, run_task};
12141087

rs/bitcoin/ckbtc/minter/src/main.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ fn init(args: MinterArg) {
5050
fn setup_tasks() {
5151
schedule_now(TaskType::ProcessLogic, &IC_CANISTER_RUNTIME);
5252
schedule_now(TaskType::RefreshFeePercentiles, &IC_CANISTER_RUNTIME);
53-
schedule_now(TaskType::DistributeKytFee, &IC_CANISTER_RUNTIME);
5453
}
5554

5655
#[cfg(feature = "self_check")]
@@ -84,16 +83,6 @@ fn check_invariants() -> Result<(), String> {
8483
})
8584
}
8685

87-
#[cfg(feature = "self_check")]
88-
#[update]
89-
async fn distribute_kyt_fee() {
90-
let _guard = match ic_ckbtc_minter::guard::DistributeKytFeeGuard::new() {
91-
Some(guard) => guard,
92-
None => return,
93-
};
94-
ic_ckbtc_minter::distribute_kyt_fees().await;
95-
}
96-
9786
#[cfg(feature = "self_check")]
9887
#[update]
9988
async fn refresh_fee_percentiles() {

rs/bitcoin/ckbtc/minter/src/memo.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(deprecated)]
12
use minicbor::Encoder;
23
use minicbor::{Decode, Encode};
34

@@ -37,9 +38,11 @@ pub enum MintMemo<'a> {
3738
kyt_fee: Option<u64>,
3839
},
3940
#[n(1)]
41+
#[deprecated]
4042
/// The minter minted accumulated check fees to the KYT provider.
4143
Kyt,
4244
#[n(2)]
45+
#[deprecated]
4346
/// The minter failed to check retrieve btc destination address
4447
/// or the destination address is tainted.
4548
KytFail {

rs/bitcoin/ckbtc/minter/src/state/audit.rs

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ use super::{
55
RetrieveBtcRequest, SubmittedBtcTransaction, SuspendedReason,
66
};
77
use crate::state::invariants::CheckInvariantsImpl;
8-
use crate::state::{ReimburseDepositTask, ReimbursedDeposit};
98
use crate::storage::record_event;
10-
use crate::{CanisterRuntime, ReimbursementReason, Timestamp};
9+
use crate::{CanisterRuntime, Timestamp};
1110
use candid::Principal;
1211
use ic_btc_interface::{Txid, Utxo};
1312
use icrc_ledger_types::icrc1::account::Account;
@@ -213,58 +212,3 @@ pub fn distributed_kyt_fee<R: CanisterRuntime>(
213212
);
214213
state.distribute_kyt_fee(kyt_provider, amount)
215214
}
216-
217-
pub fn schedule_deposit_reimbursement<R: CanisterRuntime>(
218-
state: &mut CkBtcMinterState,
219-
account: Account,
220-
amount: u64,
221-
reason: ReimbursementReason,
222-
burn_block_index: u64,
223-
runtime: &R,
224-
) {
225-
record_event(
226-
EventType::ScheduleDepositReimbursement {
227-
account,
228-
amount,
229-
reason,
230-
burn_block_index,
231-
},
232-
runtime,
233-
);
234-
state.schedule_deposit_reimbursement(
235-
burn_block_index,
236-
ReimburseDepositTask {
237-
account,
238-
amount,
239-
reason,
240-
},
241-
);
242-
}
243-
244-
pub fn reimbursed_failed_deposit<R: CanisterRuntime>(
245-
state: &mut CkBtcMinterState,
246-
burn_block_index: u64,
247-
mint_block_index: u64,
248-
runtime: &R,
249-
) {
250-
record_event(
251-
EventType::ReimbursedFailedDeposit {
252-
burn_block_index,
253-
mint_block_index,
254-
},
255-
runtime,
256-
);
257-
let reimbursed_tx = state
258-
.pending_reimbursements
259-
.remove(&burn_block_index)
260-
.expect("bug: reimbursement task should be present");
261-
state.reimbursed_transactions.insert(
262-
burn_block_index,
263-
ReimbursedDeposit {
264-
account: reimbursed_tx.account,
265-
amount: reimbursed_tx.amount,
266-
reason: reimbursed_tx.reason,
267-
mint_block_index,
268-
},
269-
);
270-
}

rs/bitcoin/ckbtc/minter/src/tasks.rs

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
#[cfg(test)]
22
mod tests;
3-
use crate::{
4-
distribute_kyt_fees, estimate_fee_per_vbyte, finalize_requests, reimburse_failed_kyt,
5-
submit_pending_requests, CanisterRuntime,
6-
};
7-
use ic_btc_interface::Network;
3+
use crate::{estimate_fee_per_vbyte, finalize_requests, submit_pending_requests, CanisterRuntime};
84
use scopeguard::guard;
95
use std::cell::{Cell, RefCell};
106
use std::collections::{BTreeMap, BTreeSet};
@@ -19,7 +15,6 @@ thread_local! {
1915
pub enum TaskType {
2016
ProcessLogic,
2117
RefreshFeePercentiles,
22-
DistributeKytFee,
2318
}
2419

2520
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
@@ -147,7 +142,6 @@ pub(crate) async fn run_task<R: CanisterRuntime>(task: Task, runtime: R) {
147142

148143
submit_pending_requests().await;
149144
finalize_requests().await;
150-
reimburse_failed_kyt().await;
151145
}
152146
TaskType::RefreshFeePercentiles => {
153147
const FEE_ESTIMATE_DELAY: Duration = Duration::from_secs(60 * 60);
@@ -165,29 +159,5 @@ pub(crate) async fn run_task<R: CanisterRuntime>(task: Task, runtime: R) {
165159
};
166160
let _ = estimate_fee_per_vbyte().await;
167161
}
168-
TaskType::DistributeKytFee => {
169-
const MAINNET_KYT_FEE_DISTRIBUTION_PERIOD: Duration = Duration::from_secs(24 * 60 * 60);
170-
171-
let _enqueue_followup_guard = guard((), |_| {
172-
schedule_after(
173-
MAINNET_KYT_FEE_DISTRIBUTION_PERIOD,
174-
TaskType::DistributeKytFee,
175-
&runtime,
176-
);
177-
});
178-
let _guard = match crate::guard::DistributeKytFeeGuard::new() {
179-
Some(guard) => guard,
180-
None => return,
181-
};
182-
183-
match crate::state::read_state(|s| s.btc_network) {
184-
Network::Mainnet | Network::Testnet => {
185-
distribute_kyt_fees().await;
186-
}
187-
// We use a debug canister build exposing an endpoint
188-
// triggering the fee distribution in tests.
189-
Network::Regtest => {}
190-
}
191-
}
192162
}
193163
}

rs/bitcoin/ckbtc/minter/src/tasks/tests.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,6 @@ async fn should_reschedule_refresh_fees() {
4848
.await;
4949
}
5050

51-
#[tokio::test]
52-
async fn should_reschedule_distribute_kyt_fee() {
53-
test_reschedule(
54-
TaskType::DistributeKytFee,
55-
|| crate::guard::DistributeKytFeeGuard::new().unwrap(),
56-
Duration::from_secs(24 * 60 * 60),
57-
)
58-
.await;
59-
}
60-
6151
async fn test_reschedule<T, G: FnOnce() -> T>(
6252
task_type: TaskType,
6353
guard: G,

0 commit comments

Comments
 (0)