changes for gui wallets

This commit is contained in:
viraladmin 2026-06-19 12:36:01 -06:00
parent 504207c424
commit e479b8e5df
18 changed files with 97 additions and 63 deletions

View File

@ -399,7 +399,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[sender, receiver, &miner],
&[sender, receiver],
block_number,
tx_index,
&decode(hash)?,
@ -466,7 +466,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[creator, &miner],
&[creator],
block_number,
tx_index,
&decode(hash)?,
@ -504,7 +504,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[creator, &miner],
&[creator],
block_number,
tx_index,
&decode(hash)?,
@ -539,7 +539,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[address, &miner],
&[address],
block_number,
tx_index,
&decode(hash)?,
@ -612,7 +612,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[creator, &miner],
&[creator],
block_number,
tx_index,
&decode(hash)?,
@ -638,7 +638,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[advertiser, &miner],
&[advertiser],
block_number,
tx_index,
&decode(hash)?,
@ -668,7 +668,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[address, &miner],
&[address],
block_number,
tx_index,
&decode(hash)?,
@ -748,7 +748,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[sender1, sender2, &miner],
&[sender1, sender2],
block_number,
tx_index,
&decode(hash)?,
@ -817,7 +817,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[lender, borrower, &miner],
&[lender, borrower],
block_number,
tx_index,
&decode(hash)?,
@ -886,7 +886,7 @@ pub async fn apply_selected_transaction_math(
let lender_address = binary_to_string(lender.clone());
index_selected_wallet_transaction(
pending_effects,
&[address, &lender_address, &miner],
&[address, &lender_address],
block_number,
tx_index,
&decode(hash)?,
@ -941,7 +941,7 @@ pub async fn apply_selected_transaction_math(
);
index_selected_wallet_transaction(
pending_effects,
&[address, &miner],
&[address],
block_number,
tx_index,
&decode(hash)?,

View File

@ -109,11 +109,7 @@ pub async fn process_borrower(
pending_effects.set_tree("txid", txkey, txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[
&transaction.unsigned_contract_payment.address,
&lender,
&miner,
],
&[&transaction.unsigned_contract_payment.address, &lender],
block_header_number,
**index as u32,
&txhash_bytes,

View File

@ -73,7 +73,7 @@ pub async fn process_burn(
pending_effects.set_tree("txid", txkey, txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&transaction.unsigned_burn.address, &miner],
&[&transaction.unsigned_burn.address],
block_header_number,
**index as u32,
&txhash_bytes,

View File

@ -99,7 +99,7 @@ pub async fn process_collateral(
pending_effects.set_tree("txid", txkey, txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&transaction.unsigned_collateral_claim.address, &miner],
&[&transaction.unsigned_collateral_claim.address],
block_header_number,
**index as u32,
&txhash_bytes,

View File

@ -70,7 +70,7 @@ pub async fn process_issue_token(
pending_effects.set_tree("txid", txkey.clone(), txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&transaction.unsigned_issue_token.creator, &miner],
&[&transaction.unsigned_issue_token.creator],
block_header_number,
**index as u32,
&txkey,

View File

@ -81,7 +81,6 @@ pub async fn process_lender(
&[
&transaction.unsigned_loan_contract.lender,
&transaction.unsigned_loan_contract.borrower,
&miner,
],
block_header_number,
**index as u32,

View File

@ -54,7 +54,7 @@ pub async fn process_marketing(
pending_effects.set_tree("txid", txkey, txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&transaction.unsigned_marketing.advertiser, &miner],
&[&transaction.unsigned_marketing.advertiser],
block_header_number,
**index as u32,
&txhash_bytes,

View File

@ -100,7 +100,7 @@ pub async fn process_nft(
pending_effects.set_tree("txid", txkey, txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&transaction.unsigned_create_nft.creator, &miner],
&[&transaction.unsigned_create_nft.creator],
block_header_number,
**index as u32,
&txhash_bytes,

View File

@ -6,7 +6,7 @@ use crate::records::balance_sheet::operations::balance_sheet_operation_with_db;
use crate::records::block_height::get_block_height::get_height;
use crate::records::memory::mempool::BASECOIN;
use crate::records::record_chain::pending_effects::PendingEffects;
use crate::records::record_chain::wallet_tx_index::index_wallet_transaction;
use crate::records::record_chain::wallet_tx_index::index_wallet_transaction_direct;
use crate::records::unpack_block::load_by_block_number::load_block;
use crate::sled::Db;
use crate::Arc;
@ -21,6 +21,8 @@ struct ImmatureReward {
block_height: u32,
miner: String,
amount: u64,
txid: Vec<u8>,
entry_index: u32,
}
lazy_static! {
@ -63,6 +65,13 @@ fn credit_matured_reward(db: &Db, reward: ImmatureReward) -> Result<(), String>
.map_err(|e| format!("Failed to finalize reward balance: {e}"))?;
}
index_wallet_transaction_direct(
db,
&reward.miner,
reward.block_height,
reward.entry_index,
&reward.txid,
)?;
mark_reward_credit_applied(db, reward.block_height)
}
@ -71,6 +80,8 @@ pub async fn record_saved_reward(
block_height: u32,
miner: String,
amount: u64,
txid: Vec<u8>,
entry_index: u32,
) -> Result<(), String> {
let matured = {
let mut rewards = IMMATURE_REWARDS.lock().await;
@ -79,6 +90,8 @@ pub async fn record_saved_reward(
block_height,
miner,
amount,
txid,
entry_index,
});
if rewards.len() > IMMATURE_REWARD_WINDOW {
@ -112,12 +125,18 @@ pub async fn rebuild_immature_reward_window(db: &Db) -> Result<(), String> {
};
let miner = block.vrf_block.unmined_block.miner;
for transaction in block.transactions {
for (position, transaction) in block.transactions.into_iter().enumerate() {
if let Transaction::Rewards(rewards) = transaction {
let txid = decode(rewards.unsigned.hash().await)
.map_err(|e| format!("Error decoding rebuilt reward txid key: {e}"))?;
let entry_index = u32::try_from(position + 1)
.map_err(|_| "Reward transaction index overflowed".to_string())?;
rebuilt.push_back(ImmatureReward {
block_height,
miner,
amount: rewards.unsigned.value,
txid,
entry_index,
});
break;
}
@ -138,7 +157,7 @@ pub async fn process_rewards(
mut binary_data: Vec<u8>,
_db: &Db,
index_counter: Arc<Mutex<&mut usize>>,
miner: String,
_miner: String,
block_header_number: u32,
pending_effects: &mut PendingEffects,
) -> Result<Vec<u8>, String> {
@ -157,16 +176,9 @@ pub async fn process_rewards(
binary_data.extend(transaction_bytes);
// Reward processing records the txid location for later lookup by
// block/index, but does not make the reward spendable yet.
// block/index, but does not index it into wallet history until maturity.
let txkey = decode(txhash).map_err(|e| format!("Error decoding rewards txid key: {e}"))?;
let txvalue = format!("{block_header_number}:{}", **index);
pending_effects.set_tree("txid", txkey.clone(), txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&miner],
block_header_number,
**index as u32,
&txkey,
)?;
pending_effects.set_tree("txid", txkey, txvalue.into_bytes());
Ok(binary_data)
}

View File

@ -15,7 +15,7 @@ use crate::records::memory::chain_state::{
cached_tip_hash, cached_tip_header, update_chain_state_after_save,
};
use crate::records::memory::mempool::{
apply_selected_transaction_math, ensure_db_connection, mark_processed_by_signatures,
apply_selected_transaction_math, mark_processed_by_signatures,
mark_selected_transactions_processed, restore_processed_by_signatures,
restore_selected_transactions_processed, select_transactions_for_block,
spawn_processed_cleanup, stream_selected_transaction_originals,
@ -75,10 +75,6 @@ pub async fn save_block(params: SaveBlockParams) -> Result<(), String> {
}
}
ensure_db_connection()
.await
.map_err(|err| format!("Postgres reconnect failed before block save: {err}"))?;
let header_bytes = block
.vrf_block
.to_bytes()
@ -150,13 +146,17 @@ pub async fn save_block(params: SaveBlockParams) -> Result<(), String> {
)
.await?;
let saved_reward_amount = block
.transactions
.iter()
.find_map(|transaction| match transaction {
Transaction::Rewards(rewards) => Some(rewards.unsigned.value),
_ => None,
});
let mut saved_reward = None;
for (position, transaction) in block.transactions.iter().enumerate() {
if let Transaction::Rewards(rewards) = transaction {
let txid = decode(rewards.unsigned.hash().await)
.map_err(|e| format!("Error decoding saved reward txid key: {e}"))?;
let entry_index = u32::try_from(position + 1)
.map_err(|_| "Reward transaction index overflowed".to_string())?;
saved_reward = Some((rewards.unsigned.value, txid, entry_index));
break;
}
}
let start_index = {
let index = index_mutex.lock().await;
@ -219,8 +219,16 @@ pub async fn save_block(params: SaveBlockParams) -> Result<(), String> {
.await?;
}
if let Some(amount) = saved_reward_amount {
if let Err(err) = record_saved_reward(&db, block_header_number, miner.clone(), amount).await
if let Some((amount, txid, entry_index)) = saved_reward {
if let Err(err) = record_saved_reward(
&db,
block_header_number,
miner.clone(),
amount,
txid,
entry_index,
)
.await
{
error!(
"Failed to update immature reward window for block {block_header_number}: {err}"

View File

@ -126,7 +126,6 @@ pub async fn process_swap(
&[
&transaction.unsigned_swap.sender1,
&transaction.unsigned_swap.sender2,
&miner,
],
block_header_number,
**index as u32,

View File

@ -81,7 +81,7 @@ pub async fn process_token(
pending_effects.set_tree("txid", txkey.clone(), txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[&transaction.unsigned_create_token.creator, &miner],
&[&transaction.unsigned_create_token.creator],
block_header_number,
**index as u32,
&txkey,

View File

@ -75,7 +75,6 @@ pub async fn process_transfer(
&[
&transaction.unsigned_transfer.sender,
&transaction.unsigned_transfer.receiver,
&miner,
],
block_header_number,
**index as u32,

View File

@ -59,7 +59,7 @@ pub async fn process_vanity(
pending_effects.set_tree("txid", txkey.clone(), txvalue.into_bytes());
index_wallet_transaction(
pending_effects,
&[owner_address, &miner],
&[owner_address],
block_header_number,
**index as u32,
&txkey,

View File

@ -45,6 +45,22 @@ pub fn index_wallet_transaction(
Ok(())
}
pub fn index_wallet_transaction_direct(
db: &Db,
address: &str,
block_height: u32,
entry_index: u32,
txid: &[u8],
) -> Result<(), String> {
let key = wallet_tx_index_key(address, block_height, entry_index)?;
let tree = db
.open_tree(WALLET_TX_INDEX_TREE)
.map_err(|err| format!("Failed to open wallet transaction index: {err}"))?;
tree.insert(key, txid.to_vec())
.map_err(|err| format!("Failed to insert wallet transaction index: {err}"))?;
Ok(())
}
fn txid_block_height(db: &Db, txid: &[u8]) -> Result<Option<u32>, String> {
let tree = db
.open_tree("txid")

View File

@ -34,6 +34,11 @@ use crate::Arc;
use crate::Mutex;
const LIVE_SYNC_HEIGHT_GAP: u32 = 10;
const STALE_NEXT_HEIGHT_ERROR: &str = "Incoming block is no longer the next expected height.";
fn is_stale_next_height_error(error: &str) -> bool {
error.contains(STALE_NEXT_HEIGHT_ERROR)
}
pub fn should_trigger_orphan_check(error: &str) -> bool {
// These errors mean the incoming torrent may belong to a competing
@ -41,7 +46,6 @@ pub fn should_trigger_orphan_check(error: &str) -> bool {
error.contains("Incorrect previous_block_hash.")
|| error.contains("Candidate parent is not current chain parent.")
|| error.contains("Difficulty mismatch with the blockchain data.")
|| error.contains("Incoming block is no longer the next expected height.")
|| error.contains("Unable to read block")
}
@ -299,6 +303,12 @@ pub async fn torrent_submission(
.await;
}
Err(e) => {
if is_stale_next_height_error(&e) {
info!(
"[broadcast] ignored stale downloaded block: height={height} err={e}"
);
return;
}
error!("[broadcast] setup_download error: height={height} err={e}");
if should_trigger_orphan_check(&e) {
trigger_orphan_check(

View File

@ -1,9 +1,8 @@
use crate::common::check_genesis::genesis_checkup;
use crate::common::skein::skein_128_hash_bytes;
use crate::log::{error, warn};
use crate::log::{error, info, warn};
use crate::miner::flag::is_reorganizing_mode;
use crate::records::block_height::get_block_height::get_height;
use crate::records::memory::mempool::ensure_db_connection;
use crate::records::record_chain::save::save_block;
use crate::records::record_chain::structs::{SaveBlockParams, SaveType};
use crate::records::unpack_block::load_by_binary_data::load_block_from_binary;
@ -98,10 +97,6 @@ async fn verify_and_save_block_payload(
return Err("Candidate previous hash does not match torrent metadata.".to_string());
}
ensure_db_connection()
.await
.map_err(|err| format!("Postgres reconnect failed before block verification: {err}"))?;
// Run full block verification before allowing the chain save path to persist the downloaded block.
let signatures = match loaded_block
.verify(&params.db, params.verification_service.clone())
@ -178,7 +173,7 @@ async fn ensure_next_expected_height(params: &DownloadSave) -> Result<(), String
};
if params.block_number < expected_height {
warn!(
info!(
"[download] block is no longer next expected height: block_number={} current_height={} expected_height={}",
params.block_number,
current_height,

View File

@ -17,7 +17,7 @@ use crate::wallets::structures::Wallet;
use crate::Arc;
use crate::Utc;
const ALLOWED_FUTURE_BLOCK_SECONDS: u32 = 1;
const ALLOWED_FUTURE_BLOCK_SECONDS: u32 = 3;
impl Block {
pub async fn verify(
@ -82,7 +82,7 @@ impl Block {
// validate hash
Self::validate_hash_difficulty(db, hash).await?;
// Allow the same one-second clock skew tolerated during handshake,
// Allow the same three-second clock skew tolerated during handshake,
// while the parent timestamp check below still enforces block spacing.
if timestamp > current_timestamp.saturating_add(ALLOWED_FUTURE_BLOCK_SECONDS) {
return Err("Timestamp in the block is in the future.".to_string());
@ -148,7 +148,7 @@ impl Block {
}
// validate that the current timestamp is greater the previous
// block timestamp plus 2 seconds
// block timestamp plus 1 second
let current_timestamp = Utc::now().timestamp() as u32;
if current_timestamp < previous_block.unmined_block.timestamp + 1 {
return Err("Mining to quickly".to_string());