drk: scan cache message buffer added for allowing upstream to control message logging

This commit is contained in:
skoupidi
2025-06-16 14:21:36 +03:00
parent 1319947889
commit 6cae233f81
3 changed files with 77 additions and 44 deletions

View File

@@ -1192,9 +1192,9 @@ impl Drk {
}
// Confirm it
println!(
scan_cache.log(format!(
"[apply_dao_mint_data] Found minted DAO {new_bulla}, noting down for wallet update"
);
));
if let Err(e) = self
.confirm_dao(
new_bulla,
@@ -1241,7 +1241,9 @@ impl Drk {
};
// We managed to decrypt it. Let's place this in a proper ProposalRecord object
println!("[apply_dao_propose_data] Managed to decrypt proposal note for DAO: {dao}");
scan_cache.messages_buffer.push(format!(
"[apply_dao_propose_data] Managed to decrypt proposal note for DAO: {dao}"
));
// Check if we already got the record
let our_proposal = if scan_cache.own_proposals.contains_key(&params.proposal_bulla) {
@@ -1417,7 +1419,7 @@ impl Drk {
// Run through the transaction call data and see what we got:
match DaoFunction::try_from(data[0])? {
DaoFunction::Mint => {
println!("[apply_tx_dao_data] Found Dao::Mint call");
scan_cache.log(String::from("[apply_tx_dao_data] Found Dao::Mint call"));
let params: DaoMintParams = deserialize_async(&data[1..]).await?;
let own_tx = self
.apply_dao_mint_data(
@@ -1431,7 +1433,7 @@ impl Drk {
Ok((true, false, own_tx))
}
DaoFunction::Propose => {
println!("[apply_tx_dao_data] Found Dao::Propose call");
scan_cache.log(String::from("[apply_tx_dao_data] Found Dao::Propose call"));
let params: DaoProposeParams = deserialize_async(&data[1..]).await?;
let own_tx = self
.apply_dao_propose_data(scan_cache, &params, tx_hash, call_idx, block_height)
@@ -1439,7 +1441,7 @@ impl Drk {
Ok((false, true, own_tx))
}
DaoFunction::Vote => {
println!("[apply_tx_dao_data] Found Dao::Vote call");
scan_cache.log(String::from("[apply_tx_dao_data] Found Dao::Vote call"));
let params: DaoVoteParams = deserialize_async(&data[1..]).await?;
let own_tx = self
.apply_dao_vote_data(scan_cache, &params, tx_hash, call_idx, block_height)
@@ -1447,14 +1449,15 @@ impl Drk {
Ok((false, false, own_tx))
}
DaoFunction::Exec => {
println!("[apply_tx_dao_data] Found Dao::Exec call");
scan_cache.log(String::from("[apply_tx_dao_data] Found Dao::Exec call"));
let params: DaoExecParams = deserialize_async(&data[1..]).await?;
let own_tx =
self.apply_dao_exec_data(scan_cache, &params, tx_hash, block_height).await?;
Ok((false, false, own_tx))
}
DaoFunction::AuthMoneyTransfer => {
println!("[apply_tx_dao_data] Found Dao::AuthMoneyTransfer call");
scan_cache
.log(String::from("[apply_tx_dao_data] Found Dao::AuthMoneyTransfer call"));
// Does nothing, just verifies the other calls are correct
Ok((false, false, false))
}

View File

@@ -680,6 +680,7 @@ impl Drk {
/// notes and freezes from a transaction money call.
async fn parse_money_call(
&self,
scan_cache: &mut ScanCache,
call_idx: &usize,
calls: &[DarkLeaf<ContractCall>],
) -> Result<(Vec<Nullifier>, Vec<(Coin, AeadEncryptedNote)>, Vec<TokenId>)> {
@@ -691,25 +692,25 @@ impl Drk {
let data = &call.data.data;
match MoneyFunction::try_from(data[0])? {
MoneyFunction::FeeV1 => {
println!("[parse_money_call] Found Money::FeeV1 call");
scan_cache.log(String::from("[parse_money_call] Found Money::FeeV1 call"));
let params: MoneyFeeParamsV1 = deserialize_async(&data[9..]).await?;
nullifiers.push(params.input.nullifier);
coins.push((params.output.coin, params.output.note));
}
MoneyFunction::GenesisMintV1 => {
println!("[parse_money_call] Found Money::GenesisMintV1 call");
scan_cache.log(String::from("[parse_money_call] Found Money::GenesisMintV1 call"));
let params: MoneyGenesisMintParamsV1 = deserialize_async(&data[1..]).await?;
for output in params.outputs {
coins.push((output.coin, output.note));
}
}
MoneyFunction::PoWRewardV1 => {
println!("[parse_money_call] Found Money::PoWRewardV1 call");
scan_cache.log(String::from("[parse_money_call] Found Money::PoWRewardV1 call"));
let params: MoneyPoWRewardParamsV1 = deserialize_async(&data[1..]).await?;
coins.push((params.output.coin, params.output.note));
}
MoneyFunction::TransferV1 => {
println!("[parse_money_call] Found Money::TransferV1 call");
scan_cache.log(String::from("[parse_money_call] Found Money::TransferV1 call"));
let params: MoneyTransferParamsV1 = deserialize_async(&data[1..]).await?;
for input in params.inputs {
@@ -721,7 +722,7 @@ impl Drk {
}
}
MoneyFunction::OtcSwapV1 => {
println!("[parse_money_call] Found Money::OtcSwapV1 call");
scan_cache.log(String::from("[parse_money_call] Found Money::OtcSwapV1 call"));
let params: MoneyTransferParamsV1 = deserialize_async(&data[1..]).await?;
for input in params.inputs {
@@ -733,16 +734,18 @@ impl Drk {
}
}
MoneyFunction::AuthTokenMintV1 => {
println!("[parse_money_call] Found Money::AuthTokenMintV1 call");
scan_cache
.log(String::from("[parse_money_call] Found Money::AuthTokenMintV1 call"));
// Handled in TokenMint
}
MoneyFunction::AuthTokenFreezeV1 => {
println!("[parse_money_call] Found Money::AuthTokenFreezeV1 call");
scan_cache
.log(String::from("[parse_money_call] Found Money::AuthTokenFreezeV1 call"));
let params: MoneyAuthTokenFreezeParamsV1 = deserialize_async(&data[1..]).await?;
freezes.push(params.token_id);
}
MoneyFunction::TokenMintV1 => {
println!("[parse_money_call] Found Money::TokenMintV1 call");
scan_cache.log(String::from("[parse_money_call] Found Money::TokenMintV1 call"));
let params: MoneyTokenMintParamsV1 = deserialize_async(&data[1..]).await?;
// Grab the note from the child auth call
let child_idx = call.children_indexes[0];
@@ -764,6 +767,7 @@ impl Drk {
&self,
tree: &mut MerkleTree,
secrets: &[SecretKey],
messages_buffer: &mut Vec<String>,
coins: &[(Coin, AeadEncryptedNote)],
) -> (bool, Vec<OwnCoin>) {
// Keep track of our own coins found in the vec
@@ -783,8 +787,11 @@ impl Drk {
// Attempt to decrypt the note
for secret in secrets {
let Ok(note) = note.decrypt::<MoneyNote>(secret) else { continue };
println!("[handle_money_call_coins] Successfully decrypted a Money Note");
println!("[handle_money_call_coins] Witnessing coin in Merkle tree");
messages_buffer.push(String::from(
"[handle_money_call_coins] Successfully decrypted a Money Note",
));
messages_buffer
.push(String::from("[handle_money_call_coins] Witnessing coin in Merkle tree"));
let leaf_position = tree.mark().unwrap();
let owncoin = OwnCoin { coin: *coin, note, secret: *secret, leaf_position };
owncoins.push(owncoin);
@@ -798,11 +805,11 @@ impl Drk {
/// call.
async fn handle_money_call_owncoins(
&self,
owncoins_nullifiers: &mut BTreeMap<[u8; 32], ([u8; 32], Position)>,
scan_cache: &mut ScanCache,
coins: &[OwnCoin],
creation_height: &u32,
) -> Result<()> {
println!("Found {} OwnCoin(s) in transaction", coins.len());
scan_cache.log(format!("Found {} OwnCoin(s) in transaction", coins.len()));
// Check if we have any owncoins to process
if coins.is_empty() {
@@ -832,12 +839,14 @@ impl Drk {
// Handle our own coins
let spent_height: Option<u32> = None;
for coin in coins {
println!("OwnCoin: {:?}", coin.coin);
scan_cache.log(format!("OwnCoin: {:?}", coin.coin));
// Grab coin record key
let key = coin.coin.to_bytes();
// Push to our own coins nullifiers cache
owncoins_nullifiers.insert(coin.nullifier().to_bytes(), (key, coin.leaf_position));
scan_cache
.owncoins_nullifiers
.insert(coin.nullifier().to_bytes(), (key, coin.leaf_position));
// Execute the query
let params = rusqlite::params![
@@ -934,12 +943,14 @@ impl Drk {
block_height: &u32,
) -> Result<(bool, bool)> {
// Parse the call
let (nullifiers, coins, freezes) = self.parse_money_call(call_idx, calls).await?;
let (nullifiers, coins, freezes) =
self.parse_money_call(scan_cache, call_idx, calls).await?;
// Parse call coins and grab our own
let (update_tree, owncoins) = self.handle_money_call_coins(
&mut scan_cache.money_tree,
&scan_cache.notes_secrets,
&mut scan_cache.messages_buffer,
&coins,
);
@@ -956,12 +967,7 @@ impl Drk {
)?;
// Handle our own coins
self.handle_money_call_owncoins(
&mut scan_cache.owncoins_nullifiers,
&owncoins,
block_height,
)
.await?;
self.handle_money_call_owncoins(scan_cache, &owncoins, block_height).await?;
// Handle freezes
let wallet_freezes =

View File

@@ -76,10 +76,24 @@ pub struct ScanCache {
pub own_daos: HashMap<DaoBulla, (Option<SecretKey>, Option<SecretKey>)>,
/// Our own DAOs proposals with their corresponding DAO reference
pub own_proposals: HashMap<DaoProposalBulla, DaoBulla>,
/// Messages buffer for better downstream prints handling
pub messages_buffer: Vec<String>,
}
impl ScanCache {
/// Auxiliary function to append messages to the buffer.
pub fn log(&mut self, msg: String) {
self.messages_buffer.push(msg);
}
/// Auxiliary function to consume the messages buffer.
pub fn flush_messages(&mut self) -> Vec<String> {
self.messages_buffer.drain(..).collect()
}
}
impl Drk {
/// Auxiliarry function to generate a new [`ScanCache`] for the
/// Auxiliary function to generate a new [`ScanCache`] for the
/// wallet.
pub async fn scan_cache(&self) -> Result<ScanCache> {
let money_tree = self.get_money_tree().await?;
@@ -124,6 +138,7 @@ impl Drk {
dao_proposals_tree,
own_daos,
own_proposals,
messages_buffer: vec![],
})
}
@@ -254,22 +269,27 @@ impl Drk {
)))
}
};
if let Err(e) =
self.scan_block(&mut self.scan_cache().await?, &genesis).await
{
let mut scan_cache = self.scan_cache().await?;
if let Err(e) = self.scan_block(&mut scan_cache, &genesis).await {
return Err(Error::DatabaseError(format!(
"[subscribe_blocks] Scanning block failed: {e:?}"
)))
};
for msg in scan_cache.flush_messages() {
println!("{msg}");
}
}
}
if let Err(e) = self.scan_block(&mut self.scan_cache().await?, &block).await
{
let mut scan_cache = self.scan_cache().await?;
if let Err(e) = self.scan_block(&mut scan_cache, &block).await {
return Err(Error::DatabaseError(format!(
"[subscribe_blocks] Scanning block failed: {e:?}"
)))
}
for msg in scan_cache.flush_messages() {
println!("{msg}");
}
// Set new last scanned block height
last_scanned_height = block.header.height;
@@ -304,18 +324,18 @@ impl Drk {
let mut wallet_txs = vec![];
// Scan the block
println!("=======================================");
println!("{}", block.header);
println!("=======================================");
println!("[scan_block] Iterating over {} transactions", block.txs.len());
scan_cache.log(String::from("======================================="));
scan_cache.log(format!("{}", block.header));
scan_cache.log(String::from("======================================="));
scan_cache.log(format!("[scan_block] Iterating over {} transactions", block.txs.len()));
for tx in block.txs.iter() {
let tx_hash = tx.hash();
let tx_hash_string = tx_hash.to_string();
let mut wallet_tx = false;
println!("[scan_block] Processing transaction: {tx_hash_string}");
scan_cache.log(format!("[scan_block] Processing transaction: {tx_hash_string}"));
for (i, call) in tx.calls.iter().enumerate() {
if call.data.contract_id == *MONEY_CONTRACT_ID {
println!("[scan_block] Found Money contract in call {i}");
scan_cache.log(format!("[scan_block] Found Money contract in call {i}"));
let (update_tree, own_tx) = self
.apply_tx_money_data(
scan_cache,
@@ -335,7 +355,7 @@ impl Drk {
}
if call.data.contract_id == *DAO_CONTRACT_ID {
println!("[scan_block] Found DAO contract in call {i}");
scan_cache.log(format!("[scan_block] Found DAO contract in call {i}"));
let (update_daos_tree, update_proposals_tree, own_tx) = self
.apply_tx_dao_data(
scan_cache,
@@ -358,13 +378,14 @@ impl Drk {
}
if call.data.contract_id == *DEPLOYOOOR_CONTRACT_ID {
println!("[scan_block] Found DeployoOor contract in call {i}");
scan_cache.log(format!("[scan_block] Found DeployoOor contract in call {i}"));
// TODO: implement
continue
}
// TODO: For now we skip non-native contract calls
println!("[scan_block] Found non-native contract in call {i}, skipping.");
scan_cache
.log(format!("[scan_block] Found non-native contract in call {i}, skipping."));
}
// If this is our wallet tx we mark it for update
@@ -529,6 +550,9 @@ impl Drk {
eprintln!("[scan_blocks] Scan block failed: {e:?}");
return Err(WalletDbError::GenericError)
};
for msg in scan_cache.flush_messages() {
println!("{msg}");
}
height += 1;
}
}