Skip to content
Draft
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
11 changes: 9 additions & 2 deletions minter/src/deposit/automatic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
SchnorrPublicKey, TaskType, audit::process_event, event::EventType, mutate_state,
read_state,
},
storage::with_discovered_signatures_mut,
};
use canlog::log;
use cksol_types::UpdateBalanceError;
Expand Down Expand Up @@ -123,8 +124,14 @@ async fn poll_account<R: CanisterRuntime>(
"Failed to get signatures for address {deposit_address}: {e}"
);
}
Ok(_signatures) => {
// TODO(DEFI-2780): Process discovered deposit signatures.
Ok(signatures) => {
with_discovered_signatures_mut(|queue| {
for sig_entry in &signatures {
let sig_bytes: [u8; 64] =
solana_signature::Signature::from(sig_entry.signature.clone()).into();
queue.insert(sig_bytes, account);
}
});
}
}

Expand Down
60 changes: 60 additions & 0 deletions minter/src/deposit/automatic/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::*;
use crate::{
constants::MAX_CONCURRENT_RPC_CALLS,
state::{event::EventType, read_state},
storage::{reset_discovered_signatures, with_discovered_signatures},
test_fixtures::{
EventsAssert, account, events::start_monitoring_account, init_schnorr_master_key,
init_state, runtime::TestCanisterRuntime,
Expand All @@ -21,6 +22,17 @@ fn start_monitoring_max_number_of_accounts() {
}
}

fn confirmed_tx_status(signature_bytes: [u8; 64]) -> ConfirmedTransactionStatusWithSignature {
ConfirmedTransactionStatusWithSignature {
signature: solana_signature::Signature::from(signature_bytes).into(),
slot: 12345,
err: None,
memo: None,
block_time: None,
confirmation_status: None,
}
}

mod update_balance {
use super::*;

Expand Down Expand Up @@ -131,8 +143,56 @@ mod poll_monitored_addresses {
}
}

#[tokio::test]
async fn should_enqueue_discovered_signatures() {
setup();

let account = account(0);
start_monitoring_account(account);

let sig1: [u8; 64] = [1u8; 64];
let sig2: [u8; 64] = [2u8; 64];
let runtime = TestCanisterRuntime::new()
.with_increasing_time()
.add_stub_response(SignaturesResult::Consistent(Ok(vec![
confirmed_tx_status(sig1),
confirmed_tx_status(sig2),
])));

poll_monitored_addresses(runtime).await;

with_discovered_signatures(|queue| {
assert_eq!(queue.get(&sig1), Some(account));
assert_eq!(queue.get(&sig2), Some(account));
assert_eq!(queue.len(), 2);
});
}

#[tokio::test]
async fn should_not_enqueue_signatures_on_rpc_failure() {
setup();

let account = account(0);
start_monitoring_account(account);

let runtime = TestCanisterRuntime::new()
.with_increasing_time()
.add_stub_response(SignaturesResult::Consistent(Err(
sol_rpc_types::RpcError::ProviderError(
sol_rpc_types::ProviderError::InvalidRpcConfig("test".to_string()),
),
)));

poll_monitored_addresses(runtime).await;

with_discovered_signatures(|queue| {
assert_eq!(queue.len(), 0);
});
}

fn setup() {
init_state();
init_schnorr_master_key();
reset_discovered_signatures();
}
}
34 changes: 33 additions & 1 deletion minter/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ use crate::{
state::event::{Event, EventType},
};
use ic_stable_structures::{
DefaultMemoryImpl, StableLog,
DefaultMemoryImpl, StableBTreeMap, StableLog,
memory_manager::{MemoryId, MemoryManager, VirtualMemory},
};
use icrc_ledger_types::icrc1::account::Account;
use std::cell::RefCell;

const EVENT_LOG_INDEX_MEMORY_ID: MemoryId = MemoryId::new(0);
const EVENT_LOG_DATA_MEMORY_ID: MemoryId = MemoryId::new(1);
const DISCOVERED_SIGNATURES_MEMORY_ID: MemoryId = MemoryId::new(2);

type VMem = VirtualMemory<DefaultMemoryImpl>;
type EventLog = StableLog<Event, VMem, VMem>;
/// Maps signature bytes to the account that owns the deposit.
/// Using signature as key since Solana transaction signatures are globally unique.
type DiscoveredSignatures = StableBTreeMap<[u8; 64], Account, VMem>;

thread_local! {
static MEMORY_MANAGER: RefCell<MemoryManager<DefaultMemoryImpl>> = RefCell::new(
Expand All @@ -30,6 +35,10 @@ thread_local! {
)
);

/// Queue of discovered deposit transaction signatures awaiting processing.
static DISCOVERED_SIGNATURES: RefCell<DiscoveredSignatures> = MEMORY_MANAGER
.with(|m| RefCell::new(StableBTreeMap::init(m.borrow().get(DISCOVERED_SIGNATURES_MEMORY_ID))));

static UNSTABLE_METRICS: RefCell<Metrics> = const { RefCell::new(Metrics::new()) };
}

Expand Down Expand Up @@ -84,6 +93,20 @@ where
EVENTS.with(|events| f(Box::new(events.borrow().iter())))
}

pub fn with_discovered_signatures_mut<F, R>(f: F) -> R
where
F: FnOnce(&mut DiscoveredSignatures) -> R,
{
DISCOVERED_SIGNATURES.with(|q| f(&mut q.borrow_mut()))
}

pub fn with_discovered_signatures<F, R>(f: F) -> R
where
F: FnOnce(&DiscoveredSignatures) -> R,
{
DISCOVERED_SIGNATURES.with(|q| f(&q.borrow()))
}

#[cfg(any(test, feature = "canbench-rs"))]
pub(crate) fn reset_events() {
MEMORY_MANAGER.with(|m| {
Expand All @@ -95,3 +118,12 @@ pub(crate) fn reset_events() {
});
});
}

#[cfg(any(test, feature = "canbench-rs"))]
pub(crate) fn reset_discovered_signatures() {
MEMORY_MANAGER.with(|m| {
DISCOVERED_SIGNATURES.with(|q| {
*q.borrow_mut() = StableBTreeMap::new(m.borrow().get(DISCOVERED_SIGNATURES_MEMORY_ID));
});
});
}
Loading