Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
e8935fa
refactor(cketh): make the transaction pipeline generic over its request
gregorydemay Aug 18, 2026
b3b6457
refactor(cketh): keep TransactionStage as visible as its pipeline
gregorydemay Aug 20, 2026
51e3b14
refactor(cketh): let each request type name its own creation error
gregorydemay Aug 19, 2026
c99bc90
refactor(cketh): finish speaking the pipeline's vocabulary
gregorydemay Aug 20, 2026
78990bb
refactor(cketh): give the pipeline's request contract its own file
gregorydemay Aug 20, 2026
9e0e3da
refactor(cketh): require Clone, Eq and Debug where they are used
gregorydemay Aug 20, 2026
59aad5f
refactor(cketh): let the pipeline's panic messages name the id's type
gregorydemay Aug 20, 2026
18674e5
refactor(cketh): take the request out of the queue instead of cloning it
gregorydemay Aug 20, 2026
e4975f0
refactor(cketh): let the request check its own destination
gregorydemay Aug 20, 2026
2b763a2
refactor(cketh): keep WithdrawalTransactions in one impl block
gregorydemay Aug 20, 2026
a9ad117
refactor(cketh): put the reimbursement methods back where they were
gregorydemay Aug 20, 2026
641c22f
style(cketh): restore the blank lines between WithdrawalTransactions'…
gregorydemay Aug 20, 2026
a49fb14
docs(cketh): resolve the TransactionPipeline doc links in request.rs
gregorydemay Aug 24, 2026
4545f02
refactor(cketh): keep the transaction pipeline inside crate::state
gregorydemay Aug 24, 2026
0c1ac32
refactor(cketh): drop the never-called PipelineRequest::created_at
gregorydemay Aug 24, 2026
daafc74
refactor(cketh): reschedule a request by id rather than by value
gregorydemay Aug 24, 2026
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: 1 addition & 1 deletion rs/ethereum/cketh/minter/src/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ impl DashboardTemplate {

let mut withdrawal_requests: Vec<_> = state
.withdrawal_transactions
.withdrawal_requests_iter()
.requests_iter()
.cloned()
.map(|request| match request {
WithdrawalRequest::CkEth(req) | WithdrawalRequest::SweeperFunding(req) => {
Expand Down
49 changes: 27 additions & 22 deletions rs/ethereum/cketh/minter/src/dashboard/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use ic_cketh_minter::numeric::{
use ic_cketh_minter::state::audit::{EventType, apply_state_transition};
use ic_cketh_minter::state::eth_logs_scraping::LogScrapingId;
use ic_cketh_minter::state::transactions::{
Erc20WithdrawalRequest, EthWithdrawalRequest, ReimbursementIndex, WithdrawalRequest,
create_transaction,
Erc20WithdrawalRequest, EthWithdrawalRequest, PipelineRequest, ReimbursementIndex,
WithdrawalRequest,
};
use ic_cketh_minter::state::{MintedEvent, State};
use ic_cketh_minter::tx::{
Expand Down Expand Up @@ -533,10 +533,7 @@ fn should_display_pending_transactions_sorted_by_decreasing_cketh_ledger_burn_in
TransactionStatus::Success,
),
] {
apply_state_transition(
&mut state,
&req.clone().into_accepted_withdrawal_request_event(),
);
apply_state_transition(&mut state, &accepted_withdrawal_request_event(req.clone()));
apply_state_transition(
&mut state,
&EventType::CreatedTransaction {
Expand All @@ -560,7 +557,7 @@ fn should_display_pending_transactions_sorted_by_decreasing_cketh_ledger_burn_in
),
] {
let withdrawal_id = req.cketh_ledger_burn_index();
apply_state_transition(&mut state, &req.into_accepted_withdrawal_request_event());
apply_state_transition(&mut state, &accepted_withdrawal_request_event(req));
apply_state_transition(
&mut state,
&EventType::CreatedTransaction {
Expand Down Expand Up @@ -674,7 +671,7 @@ fn should_display_finalized_transactions_sorted_by_decreasing_cketh_ledger_burn_
),
] {
let id = req.cketh_ledger_burn_index();
apply_state_transition(&mut state, &req.into_accepted_withdrawal_request_event());
apply_state_transition(&mut state, &accepted_withdrawal_request_event(req));
apply_state_transition(
&mut state,
&EventType::CreatedTransaction {
Expand Down Expand Up @@ -840,10 +837,7 @@ fn should_display_reimbursed_requests() {
),
] {
let id = req.cketh_ledger_burn_index();
apply_state_transition(
&mut state,
&req.clone().into_accepted_withdrawal_request_event(),
);
apply_state_transition(&mut state, &accepted_withdrawal_request_event(req.clone()));
apply_state_transition(
&mut state,
&EventType::CreatedTransaction {
Expand Down Expand Up @@ -1223,7 +1217,7 @@ fn add_finalized_transactions(state: &mut State, num_transactions: u64) {
TransactionStatus::Success,
);
let id = req.cketh_ledger_burn_index();
apply_state_transition(state, &req.into_accepted_withdrawal_request_event());
apply_state_transition(state, &accepted_withdrawal_request_event(req));
apply_state_transition(
state,
&EventType::CreatedTransaction {
Expand Down Expand Up @@ -1274,7 +1268,7 @@ fn add_reimbursed_transactions(state: &mut State, num_transactions: u64) {
TransactionStatus::Failure,
);
let id = req.cketh_ledger_burn_index();
apply_state_transition(state, &req.into_accepted_withdrawal_request_event());
apply_state_transition(state, &accepted_withdrawal_request_event(req));
apply_state_transition(
state,
&EventType::CreatedTransaction {
Expand Down Expand Up @@ -1369,6 +1363,16 @@ pub fn ckusdt() -> CkErc20Token {
}
}

fn accepted_withdrawal_request_event(request: WithdrawalRequest) -> EventType {
match request {
WithdrawalRequest::CkEth(request) => EventType::AcceptedEthWithdrawalRequest(request),
WithdrawalRequest::CkErc20(request) => EventType::AcceptedErc20WithdrawalRequest(request),
WithdrawalRequest::SweeperFunding(request) => {
EventType::AcceptedSweeperFundingRequest(request)
}
}
}

fn cketh_withdrawal_request_with_index(ledger_burn_index: LedgerBurnIndex) -> EthWithdrawalRequest {
const DEFAULT_WITHDRAWAL_AMOUNT: u128 = 1_100_000_000_000_000;
const DEFAULT_PRINCIPAL: &str =
Expand Down Expand Up @@ -1483,14 +1487,15 @@ fn ckerc20_withdrawal_flow(
base_fee_per_gas: WeiPerGas::from(250_000_000_u64),
max_priority_fee_per_gas: WeiPerGas::from(1_500_000_000_u64),
};
let transaction = create_transaction(
&withdrawal_request.clone().into(),
nonce,
gas_fee,
GasAmount::from(65_000_u32),
EthereumNetwork::Sepolia,
)
.unwrap();
let pipeline_request: WithdrawalRequest = withdrawal_request.clone().into();
let transaction = pipeline_request
.create_transaction(
nonce,
gas_fee,
GasAmount::from(65_000_u32),
EthereumNetwork::Sepolia,
)
.unwrap();
let dummy_signature = TransactionSignature {
signature_y_parity: false,
r: Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion rs/ethereum/cketh/minter/src/guard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl RequestsGuardedByPrincipal for PendingWithdrawalRequests {
}

fn pending_requests_count(state: &State) -> usize {
state.withdrawal_transactions.withdrawal_requests_len()
state.withdrawal_transactions.requests_len()
}
}

Expand Down
2 changes: 1 addition & 1 deletion rs/ethereum/cketh/minter/src/guard/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ mod retrieve_eth_guard {
fn record_withdrawal_request(ledger_burn_index: LedgerBurnIndex) {
mutate_state(|s| {
s.withdrawal_transactions
.record_withdrawal_request(EthWithdrawalRequest {
.record_request(EthWithdrawalRequest {
withdrawal_amount: Wei::ONE,
destination: Address::ZERO,
ledger_burn_index,
Expand Down
2 changes: 1 addition & 1 deletion rs/ethereum/cketh/minter/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,7 @@ fn http_request(req: HttpRequest) -> HttpResponse {
let now_nanos = ic_cdk::api::time();
let age_nanos = now_nanos.saturating_sub(
s.withdrawal_transactions
.oldest_incomplete_withdrawal_timestamp()
.oldest_incomplete_request_timestamp()
.unwrap_or(now_nanos),
);
w.encode_gauge(
Expand Down
5 changes: 2 additions & 3 deletions rs/ethereum/cketh/minter/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,7 @@ impl State {
"BUG: unsupported ERC-20 token {}",
request.erc20_contract_address
);
self.withdrawal_transactions
.record_withdrawal_request(request);
self.withdrawal_transactions.record_request(request);
}

pub fn record_finalized_transaction(
Expand Down Expand Up @@ -420,7 +419,7 @@ impl State {
.expect("BUG: missing finalized transaction");
let withdrawal_request = self
.withdrawal_transactions
.get_processed_withdrawal_request(withdrawal_id)
.get_processed_request(withdrawal_id)
.expect("BUG: missing withdrawal request");
let charged_tx_fee = match withdrawal_request {
WithdrawalRequest::CkEth(req) | WithdrawalRequest::SweeperFunding(req) => req
Expand Down
4 changes: 2 additions & 2 deletions rs/ethereum/cketh/minter/src/state/audit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ pub fn apply_state_transition(state: &mut State, payload: &EventType) {
EventType::AcceptedEthWithdrawalRequest(request) => {
state
.withdrawal_transactions
.record_withdrawal_request(request.clone());
.record_request(request.clone());
}
EventType::AcceptedSweeperFundingRequest(request) => {
state.sweeper_funding.record_burn(request.withdrawal_amount);
// Named explicitly: the payload converts to `CkEth` on its own, which would make the
// funding reimbursable.
state
.withdrawal_transactions
.record_withdrawal_request(WithdrawalRequest::SweeperFunding(request.clone()));
.record_request(WithdrawalRequest::SweeperFunding(request.clone()));
}
EventType::CreatedTransaction {
withdrawal_id,
Expand Down
53 changes: 31 additions & 22 deletions rs/ethereum/cketh/minter/src/state/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,13 +978,13 @@ fn state_equivalence() {
ledger_burn_index: LedgerBurnIndex::new(20),
..withdrawal_request1.clone()
};
let pending_withdrawal_requests: VecDeque<WithdrawalRequest> = vec![
let pending_requests: VecDeque<WithdrawalRequest> = vec![
withdrawal_request1.clone().into(),
withdrawal_request2.clone().into(),
]
.into_iter()
.collect();
let processed_withdrawal_requests = btreemap! {
let processed_requests = btreemap! {
LedgerBurnIndex::new(4) => EthWithdrawalRequest {
withdrawal_amount: Wei::new(1_000_000_000_000),
ledger_burn_index: LedgerBurnIndex::new(4),
Expand Down Expand Up @@ -1107,8 +1107,8 @@ fn state_equivalence() {
}),
};
let builder = WithdrawalTransactionsBuilder::default()
.with_pending_withdrawal_requests(pending_withdrawal_requests)
.with_processed_withdrawal_requests(processed_withdrawal_requests)
.with_pending_requests(pending_requests)
.with_processed_requests(processed_requests)
.with_created_tx(created_tx)
.with_sent_tx(sent_tx)
.with_finalized_tx(finalized_tx)
Expand Down Expand Up @@ -1333,7 +1333,7 @@ fn state_equivalence() {
state.is_equivalent_to(&State {
withdrawal_transactions: builder
.clone()
.with_pending_withdrawal_requests(
.with_pending_requests(
vec![
withdrawal_request2.clone().into(),
withdrawal_request1.clone().into()
Expand All @@ -1352,9 +1352,7 @@ fn state_equivalence() {
state.is_equivalent_to(&State {
withdrawal_transactions: builder
.clone()
.with_pending_withdrawal_requests(
vec![withdrawal_request1.into()].into_iter().collect()
)
.with_pending_requests(vec![withdrawal_request1.into()].into_iter().collect())
.build(),
..state.clone()
}),
Expand Down Expand Up @@ -1511,7 +1509,7 @@ mod sweeper_funding {

let request = state
.withdrawal_transactions
.withdrawal_requests_iter()
.requests_iter()
.next()
.expect("BUG: the funding request was not recorded");
assert_matches!(request, WithdrawalRequest::SweeperFunding(_));
Expand All @@ -1532,7 +1530,7 @@ mod eth_balance {
use crate::state::audit::{EventType, apply_state_transition};
use crate::state::tests::checked_sub;
use crate::state::tests::{initial_state, received_eth_event};
use crate::state::transactions::{EthWithdrawalRequest, WithdrawalRequest, create_transaction};
use crate::state::transactions::{EthWithdrawalRequest, PipelineRequest, WithdrawalRequest};
use crate::state::{EthBalance, State};
use crate::test_fixtures::sweeper_funding_request;
use crate::tx::{SignedEip1559TransactionRequest, TransactionSignature};
Expand Down Expand Up @@ -2008,20 +2006,19 @@ mod eth_balance {
}

fn apply(self, state: &mut State) -> TransactionReceipt {
let accepted_withdrawal_request_event = self
.withdrawal_request
.clone()
.into_accepted_withdrawal_request_event();
let accepted_withdrawal_request_event =
accepted_withdrawal_request_event(self.withdrawal_request.clone());
apply_state_transition(state, &accepted_withdrawal_request_event);

let transaction = create_transaction(
&self.withdrawal_request,
self.nonce,
self.tx_fee,
self.gas_limit,
EthereumNetwork::Sepolia,
)
.expect("BUG: failed to create transaction");
let transaction = self
.withdrawal_request
.create_transaction(
self.nonce,
self.tx_fee,
self.gas_limit,
EthereumNetwork::Sepolia,
)
.expect("BUG: failed to create transaction");
apply_state_transition(
state,
&EventType::CreatedTransaction {
Expand Down Expand Up @@ -2072,6 +2069,18 @@ mod eth_balance {
state
}

fn accepted_withdrawal_request_event(request: WithdrawalRequest) -> EventType {
match request {
WithdrawalRequest::CkEth(request) => EventType::AcceptedEthWithdrawalRequest(request),
WithdrawalRequest::CkErc20(request) => {
EventType::AcceptedErc20WithdrawalRequest(request)
}
WithdrawalRequest::SweeperFunding(request) => {
EventType::AcceptedSweeperFundingRequest(request)
}
}
}

Comment thread
gregorydemay marked this conversation as resolved.
fn add_erc20_token(state: &mut State) {
use crate::state::CkErc20Token;
apply_state_transition(
Expand Down
Loading
Loading