Skip to content

Commit

Permalink
Merge branch 'development' into philip-saf-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
aviator-app[bot] authored Aug 10, 2021
2 parents 03c5146 + 05f7813 commit ebe3f44
Show file tree
Hide file tree
Showing 45 changed files with 1,372 additions and 435 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::ui::{components::Component, state::AppState};
use tari_wallet::base_node_service::service::OnlineState;
use tari_wallet::connectivity_service::OnlineStatus;
use tui::{
backend::Backend,
layout::Rect,
Expand All @@ -45,17 +45,17 @@ impl<B: Backend> Component<B> for BaseNode {
let base_node_state = app_state.get_base_node_state();

let chain_info = match base_node_state.online {
OnlineState::Connecting => Spans::from(vec![
OnlineStatus::Connecting => Spans::from(vec![
Span::styled("Chain Tip:", Style::default().fg(Color::Magenta)),
Span::raw(" "),
Span::styled("Connecting...", Style::default().fg(Color::Reset)),
]),
OnlineState::Offline => Spans::from(vec![
OnlineStatus::Offline => Spans::from(vec![
Span::styled("Chain Tip:", Style::default().fg(Color::Magenta)),
Span::raw(" "),
Span::styled("Offline", Style::default().fg(Color::Red)),
]),
OnlineState::Online => {
OnlineStatus::Online => {
if let Some(metadata) = base_node_state.clone().chain_metadata {
let tip = metadata.height_of_longest_chain();

Expand Down
91 changes: 38 additions & 53 deletions applications/tari_console_wallet/src/ui/state/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ use tari_wallet::{
util::emoji::EmojiId,
WalletSqlite,
};
use tokio::sync::{watch, RwLock};
use tokio::{
sync::{watch, RwLock},
task,
};

const LOG_TARGET: &str = "wallet::console_wallet::app_state";

Expand Down Expand Up @@ -665,15 +668,7 @@ impl AppStateInner {
)
.await?;

if let Err(e) = self
.wallet
.transaction_service
.validate_transactions(ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating transactions: {}", e);
}
self.validate_outputs().await;
self.spawn_transaction_revalidation_task();

self.data.base_node_previous = self.data.base_node_selected.clone();
self.data.base_node_selected = peer.clone();
Expand Down Expand Up @@ -701,15 +696,7 @@ impl AppStateInner {
)
.await?;

if let Err(e) = self
.wallet
.transaction_service
.validate_transactions(ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating transactions: {}", e);
}
self.validate_outputs().await;
self.spawn_transaction_revalidation_task();

self.data.base_node_previous = self.data.base_node_selected.clone();
self.data.base_node_selected = peer.clone();
Expand Down Expand Up @@ -751,15 +738,7 @@ impl AppStateInner {
)
.await?;

if let Err(e) = self
.wallet
.transaction_service
.validate_transactions(ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating transactions: {}", e);
}
self.validate_outputs().await;
self.spawn_transaction_revalidation_task();

self.data.base_node_peer_custom = None;
self.data.base_node_selected = previous;
Expand All @@ -778,33 +757,39 @@ impl AppStateInner {
Ok(())
}

pub async fn validate_outputs(&mut self) {
if let Err(e) = self
.wallet
.output_manager_service
.validate_txos(TxoValidationType::Unspent, ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating UTXOs: {}", e);
}
pub fn spawn_transaction_revalidation_task(&mut self) {
let mut txn_service = self.wallet.transaction_service.clone();
let mut output_manager_service = self.wallet.output_manager_service.clone();

if let Err(e) = self
.wallet
.output_manager_service
.validate_txos(TxoValidationType::Spent, ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating STXOs: {}", e);
}
task::spawn(async move {
if let Err(e) = txn_service
.validate_transactions(ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating transactions: {}", e);
}

if let Err(e) = self
.wallet
.output_manager_service
.validate_txos(TxoValidationType::Invalid, ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating Invalid TXOs: {}", e);
}
if let Err(e) = output_manager_service
.validate_txos(TxoValidationType::Unspent, ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating UTXOs: {}", e);
}

if let Err(e) = output_manager_service
.validate_txos(TxoValidationType::Spent, ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating STXOs: {}", e);
}

if let Err(e) = output_manager_service
.validate_txos(TxoValidationType::Invalid, ValidationRetryStrategy::UntilSuccess)
.await
{
error!(target: LOG_TARGET, "Problem validating Invalid TXOs: {}", e);
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ impl CrosstermEvents {
) {
Ok(true) => {
if let Ok(CEvent::Key(key)) = event::read() {
tx.send(Event::Input(key)).unwrap();
if let Err(e) = tx.send(Event::Input(key)) {
warn!(target: LOG_TARGET, "Error sending Tick event on MPSC channel: {}", e);
}
}
},
Ok(false) => {},
Expand Down
15 changes: 10 additions & 5 deletions base_layer/core/src/base_node/comms_interface/inbound_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
OutboundNodeCommsInterface,
},
blocks::{block_header::BlockHeader, Block, NewBlock, NewBlockTemplate},
chain_storage::{async_db::AsyncBlockchainDb, BlockAddResult, BlockchainBackend, ChainBlock},
chain_storage::{async_db::AsyncBlockchainDb, BlockAddResult, BlockchainBackend, ChainBlock, PrunedOutput},
consensus::{ConsensusConstants, ConsensusManager},
mempool::{async_mempool, Mempool},
proof_of_work::{Difficulty, PowAlgorithm},
Expand Down Expand Up @@ -224,12 +224,14 @@ where T: BlockchainBackend + 'static
},
NodeCommsRequest::FetchMatchingUtxos(utxo_hashes) => {
let mut res = Vec::with_capacity(utxo_hashes.len());
for (output, spent) in (self.blockchain_db.fetch_utxos(utxo_hashes).await?)
for (pruned_output, spent) in (self.blockchain_db.fetch_utxos(utxo_hashes).await?)
.into_iter()
.flatten()
{
if !spent {
res.push(output);
if let PrunedOutput::NotPruned { output } = pruned_output {
if !spent {
res.push(output);
}
}
}
Ok(NodeCommsResponse::TransactionOutputs(res))
Expand All @@ -240,7 +242,10 @@ where T: BlockchainBackend + 'static
.fetch_utxos(hashes)
.await?
.into_iter()
.filter_map(|opt| opt.map(|(output, _)| output))
.filter_map(|opt| match opt {
Some((PrunedOutput::NotPruned { output }, _)) => Some(output),
_ => None,
})
.collect();
Ok(NodeCommsResponse::TransactionOutputs(res))
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::{
chain_storage::HistoricalBlock,
proof_of_work::PowAlgorithm,
transactions::{
transaction::{TransactionKernel, TransactionOutput},
transaction::TransactionKernel,
types::{Commitment, HashOutput, Signature},
},
};
Expand All @@ -43,7 +43,10 @@ use tokio::sync::broadcast;

pub type BlockEventSender = broadcast::Sender<Arc<BlockEvent>>;
pub type BlockEventReceiver = broadcast::Receiver<Arc<BlockEvent>>;
use crate::base_node::comms_interface::comms_request::GetNewBlockTemplateRequest;
use crate::{
base_node::comms_interface::comms_request::GetNewBlockTemplateRequest,
transactions::transaction::TransactionOutput,
};

/// The InboundNodeCommsInterface provides an interface to request information from the current local node by other
/// internal services.
Expand Down
10 changes: 6 additions & 4 deletions base_layer/core/src/base_node/rpc/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

use crate::{
base_node::{rpc::BaseNodeWalletService, state_machine_service::states::StateInfo, StateMachineHandle},
chain_storage::{async_db::AsyncBlockchainDb, BlockchainBackend},
chain_storage::{async_db::AsyncBlockchainDb, BlockchainBackend, PrunedOutput},
mempool::{service::MempoolHandle, TxStorageResponse},
proto::{
base_node::{
Expand Down Expand Up @@ -288,15 +288,17 @@ impl<B: BlockchainBackend + 'static> BaseNodeWalletService for BaseNodeWalletRpc

let db = self.db();
let mut res = Vec::with_capacity(message.output_hashes.len());
for (output, spent) in (db
for (pruned_output, spent) in (db
.fetch_utxos(message.output_hashes)
.await
.map_err(RpcStatus::log_internal_error(LOG_TARGET))?)
.into_iter()
.flatten()
{
if !spent {
res.push(output);
if let PrunedOutput::NotPruned { output } = pruned_output {
if !spent {
res.push(output);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions base_layer/core/src/chain_storage/async_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ impl<B: BlockchainBackend + 'static> AsyncBlockchainDb<B> {
make_async_fn!(fetch_horizon_data() -> Option<HorizonData>, "fetch_horizon_data");

//---------------------------------- TXO --------------------------------------------//
make_async_fn!(fetch_utxo(hash: HashOutput) -> Option<TransactionOutput>, "fetch_utxo");
make_async_fn!(fetch_utxo(hash: HashOutput) -> Option<PrunedOutput>, "fetch_utxo");

make_async_fn!(fetch_utxos(hashes: Vec<HashOutput>) -> Vec<Option<(TransactionOutput, bool)>>, "fetch_utxos");
make_async_fn!(fetch_utxos(hashes: Vec<HashOutput>) -> Vec<Option<(PrunedOutput, bool)>>, "fetch_utxos");

make_async_fn!(fetch_utxos_by_mmr_position(start: u64, end: u64, deleted: Arc<Bitmap>) -> (Vec<PrunedOutput>, Bitmap), "fetch_utxos_by_mmr_position");

Expand Down
7 changes: 2 additions & 5 deletions base_layer/core/src/chain_storage/blockchain_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
MmrTree,
},
transactions::{
transaction::{TransactionInput, TransactionKernel, TransactionOutput},
transaction::{TransactionInput, TransactionKernel},
types::{HashOutput, Signature},
},
};
Expand Down Expand Up @@ -103,10 +103,7 @@ pub trait BlockchainBackend: Send + Sync {
) -> Result<(Vec<PrunedOutput>, Bitmap), ChainStorageError>;

/// Fetch a specific output. Returns the output and the leaf index in the output MMR
fn fetch_output(
&self,
output_hash: &HashOutput,
) -> Result<Option<(TransactionOutput, u32, u64)>, ChainStorageError>;
fn fetch_output(&self, output_hash: &HashOutput) -> Result<Option<(PrunedOutput, u32, u64)>, ChainStorageError>;

/// Fetch all outputs in a block
fn fetch_outputs_in_block(&self, header_hash: &HashOutput) -> Result<Vec<PrunedOutput>, ChainStorageError>;
Expand Down
9 changes: 3 additions & 6 deletions base_layer/core/src/chain_storage/blockchain_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use crate::{
proof_of_work::{monero_rx::MoneroPowData, PowAlgorithm, TargetDifficultyWindow},
tari_utilities::epoch_time::EpochTime,
transactions::{
transaction::{TransactionKernel, TransactionOutput},
transaction::TransactionKernel,
types::{Commitment, HashDigest, HashOutput, Signature},
},
validation::{DifficultyCalculator, HeaderValidation, OrphanValidation, PostOrphanBodyValidation, ValidationError},
Expand Down Expand Up @@ -284,18 +284,15 @@ where B: BlockchainBackend
}

// Fetch the utxo
pub fn fetch_utxo(&self, hash: HashOutput) -> Result<Option<TransactionOutput>, ChainStorageError> {
pub fn fetch_utxo(&self, hash: HashOutput) -> Result<Option<PrunedOutput>, ChainStorageError> {
let db = self.db_read_access()?;
Ok(db.fetch_output(&hash)?.map(|(out, _index, _)| out))
}

/// Return a list of matching utxos, with each being `None` if not found. If found, the transaction
/// output, and a boolean indicating if the UTXO was spent as of the block hash specified or the tip if not
/// specified.
pub fn fetch_utxos(
&self,
hashes: Vec<HashOutput>,
) -> Result<Vec<Option<(TransactionOutput, bool)>>, ChainStorageError> {
pub fn fetch_utxos(&self, hashes: Vec<HashOutput>) -> Result<Vec<Option<(PrunedOutput, bool)>>, ChainStorageError> {
let db = self.db_read_access()?;
let deleted = db.fetch_deleted_bitmap()?;

Expand Down
46 changes: 28 additions & 18 deletions base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1616,10 +1616,7 @@ impl BlockchainBackend for LMDBDatabase {
Ok((result, difference_bitmap))
}

fn fetch_output(
&self,
output_hash: &HashOutput,
) -> Result<Option<(TransactionOutput, u32, u64)>, ChainStorageError> {
fn fetch_output(&self, output_hash: &HashOutput) -> Result<Option<(PrunedOutput, u32, u64)>, ChainStorageError> {
debug!(target: LOG_TARGET, "Fetch output: {}", output_hash.to_hex());
let txn = self.read_transaction()?;
if let Some((index, key)) =
Expand All @@ -1632,20 +1629,33 @@ impl BlockchainBackend for LMDBDatabase {
index,
key
);
if let Some(output) = lmdb_get::<_, TransactionOutputRowData>(&txn, &self.utxos_db, key.as_str())? {
if output.output.is_none() {
error!(
target: LOG_TARGET,
"Tried to fetch pruned output: {} ({}, {})",
output_hash.to_hex(),
index,
key
);
unimplemented!("Output has been pruned");
}
Ok(Some((output.output.unwrap(), output.mmr_position, output.mined_height)))
} else {
Ok(None)
match lmdb_get::<_, TransactionOutputRowData>(&txn, &self.utxos_db, key.as_str())? {
Some(TransactionOutputRowData {
output: Some(o),
mmr_position,
mined_height,
..
}) => Ok(Some((
PrunedOutput::NotPruned { output: o },
mmr_position,
mined_height,
))),
Some(TransactionOutputRowData {
output: None,
mmr_position,
mined_height,
hash,
witness_hash,
..
}) => Ok(Some((
PrunedOutput::Pruned {
output_hash: hash,
witness_hash,
},
mmr_position,
mined_height,
))),
_ => Ok(None),
}
} else {
debug!(
Expand Down
1 change: 1 addition & 0 deletions base_layer/core/src/chain_storage/pruned_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use crate::transactions::{transaction::TransactionOutput, types::HashOutput};

#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq)]
pub enum PrunedOutput {
Pruned {
output_hash: HashOutput,
Expand Down
Loading

0 comments on commit ebe3f44

Please sign in to comment.