Skip to content

Commit

Permalink
an alternative transaction validation approach
Browse files Browse the repository at this point in the history
  • Loading branch information
stringhandler committed Aug 24, 2021
1 parent f274981 commit c607d5b
Show file tree
Hide file tree
Showing 59 changed files with 2,520 additions and 992 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

22 changes: 16 additions & 6 deletions applications/tari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,26 +499,36 @@ pub async fn monitor_transactions(
}
}
},
TransactionEvent::TransactionMinedUnconfirmed(id, confirmations) if tx_ids.contains(id) => {
TransactionEvent::TransactionMinedUnconfirmed {
tx_id,
num_confirmations,
is_valid,
} if tx_ids.contains(tx_id) => {
debug!(
target: LOG_TARGET,
"tx mined unconfirmed event for tx_id: {}, confirmations: {}", *id, confirmations
"tx mined unconfirmed event for tx_id: {}, confirmations: {}, is_valid: {}",
*tx_id,
num_confirmations,
is_valid
);
if wait_stage == TransactionStage::MinedUnconfirmed {
results.push(SentTransaction {
id: *id,
id: *tx_id,
stage: TransactionStage::MinedUnconfirmed,
});
if results.len() == tx_ids.len() {
break;
}
}
},
TransactionEvent::TransactionMined(id) if tx_ids.contains(id) => {
debug!(target: LOG_TARGET, "tx mined confirmed event for tx_id: {}", *id);
TransactionEvent::TransactionMined { tx_id, is_valid } if tx_ids.contains(tx_id) => {
debug!(
target: LOG_TARGET,
"tx mined confirmed event for tx_id: {}, is_valid:{}", *tx_id, is_valid
);
if wait_stage == TransactionStage::Mined {
results.push(SentTransaction {
id: *id,
id: *tx_id,
stage: TransactionStage::Mined,
});
if results.len() == tx_ids.len() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ impl WalletEventMonitor {
self.trigger_tx_state_refresh(tx_id).await;
notifier.transaction_received(tx_id);
},
TransactionEvent::TransactionMinedUnconfirmed(tx_id, confirmations) => {
self.trigger_confirmations_refresh(tx_id, confirmations).await;
TransactionEvent::TransactionMinedUnconfirmed{tx_id, num_confirmations, is_valid: _} => {
self.trigger_confirmations_refresh(tx_id, num_confirmations).await;
self.trigger_tx_state_refresh(tx_id).await;
notifier.transaction_mined_unconfirmed(tx_id, confirmations);
notifier.transaction_mined_unconfirmed(tx_id, num_confirmations);
},
TransactionEvent::TransactionMined(tx_id) => {
TransactionEvent::TransactionMined{tx_id, is_valid: _} => {
self.trigger_confirmations_cleanup(tx_id).await;
self.trigger_tx_state_refresh(tx_id).await;
notifier.transaction_mined(tx_id);
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_console_wallet/src/ui/widgets/list_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl WindowedListState {
let i = match self.selected {
Some(i) => {
if i >= self.num_items - 1 {
0
i
} else {
i + 1
}
Expand All @@ -101,7 +101,7 @@ impl WindowedListState {
let i = match self.selected {
Some(i) => {
if i == 0 {
self.num_items - 1
i
} else {
i - 1
}
Expand Down
164 changes: 87 additions & 77 deletions applications/tari_explorer/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,102 +5,112 @@ var router = express.Router()

/* GET home page. */
router.get('/', async function (req, res, next) {
let client = createClient()
let from = parseInt(req.query.from || 0)
let limit = parseInt(req.query.limit || '20')
try {
let client = createClient()
let from = parseInt(req.query.from || 0)
let limit = parseInt(req.query.limit || '20')

let tipInfo = await client.getTipInfo({})

console.log("Getting headers");
// Algo split
let last100Headers = await client.listHeaders({ from_height: 0, num_headers: 101 })
let monero = [0, 0, 0, 0]
let sha = [0, 0, 0, 0]

console.log(last100Headers);

for (let i = 0; i < last100Headers.length - 1; i++) {
let arr = last100Headers[i].pow.pow_algo === '0' ? monero : sha
if (i < 10) {
arr[0] += 1
}
if (i < 20) {
arr[1] += 1
}
if (i < 50) {
arr[2] += 1
}
arr[3] += 1

let tipInfo = await client.getTipInfo({})

// Algo split
let last100Headers = await client.listHeaders({ from_height: 0, num_headers: 101 })
let monero = [0, 0, 0, 0]
let sha = [0, 0, 0, 0]

for (let i = 0; i < last100Headers.length - 1; i++) {
let arr = last100Headers[i].pow.pow_algo === '0' ? monero : sha
if (i < 10) {
arr[0] += 1
}
if (i < 20) {
arr[1] += 1
const algoSplit = {
monero10: monero[0],
monero20: monero[1],
monero50: monero[2],
monero100: monero[3],
sha10: sha[0],
sha20: sha[1],
sha50: sha[2],
sha100: sha[3]
}
if (i < 50) {
arr[2] += 1
}
arr[3] += 1

}
const algoSplit = {
monero10: monero[0],
monero20: monero[1],
monero50: monero[2],
monero100: monero[3],
sha10: sha[0],
sha20: sha[1],
sha50: sha[2],
sha100: sha[3]
}


console.log(algoSplit);
// Get one more header than requested so we can work out the difference in MMR_size
let headers = await client.listHeaders({ from_height: from, num_headers: limit + 1 })
for (var i = headers.length - 2; i >= 0; i--) {
headers[i].kernels = headers[i].kernel_mmr_size - headers[i + 1].kernel_mmr_size
headers[i].outputs = headers[i].output_mmr_size - headers[i + 1].output_mmr_size
}
let lastHeader = headers[headers.length - 1]
if (lastHeader.height === '0') {
// If the block is the genesis block, then the MMR sizes are the values to use
lastHeader.kernels = lastHeader.kernel_mmr_size
lastHeader.outputs = lastHeader.output_mmr_size
} else {
// Otherwise remove the last one, as we don't want to show it
headers.splice(headers.length - 1, 1)
}

// console.log(headers);
let firstHeight = parseInt(headers[0].height || '0')

// Get one more header than requested so we can work out the difference in MMR_size
let headers = await client.listHeaders({ from_height: from, num_headers: limit + 1 })
for (var i = headers.length - 2; i >= 0; i--) {
headers[i].kernels = headers[i].kernel_mmr_size - headers[i + 1].kernel_mmr_size
headers[i].outputs = headers[i].output_mmr_size - headers[i + 1].output_mmr_size
}
let lastHeader = headers[headers.length - 1]
if (lastHeader.height === '0') {
// If the block is the genesis block, then the MMR sizes are the values to use
lastHeader.kernels = lastHeader.kernel_mmr_size
lastHeader.outputs = lastHeader.output_mmr_size
} else {
// Otherwise remove the last one, as we don't want to show it
headers.splice(headers.length - 1, 1)
}

// console.log(headers);
let firstHeight = parseInt(headers[0].height || '0')

// -- mempool
let mempool = await client.getMempoolTransactions({})
// -- mempool
let mempool = await client.getMempoolTransactions({})

for (let i = 0; i < mempool.length; i++) {
let sum = 0
for (let j = 0; j < mempool[i].transaction.body.kernels.length; j++) {
sum += parseInt(mempool[i].transaction.body.kernels[j].fee)
for (let i = 0; i < mempool.length; i++) {
let sum = 0
for (let j = 0; j < mempool[i].transaction.body.kernels.length; j++) {
sum += parseInt(mempool[i].transaction.body.kernels[j].fee)
}
mempool[i].transaction.body.total_fees = sum
}
mempool[i].transaction.body.total_fees = sum
res.render('index', {
title: 'Blocks',
tipInfo: tipInfo,
mempool: mempool,
headers: headers,
pows: { '0': 'Monero', '2': 'SHA' },
nextPage: firstHeight - limit,
prevPage: firstHeight + limit,
limit: limit,
from: from,
algoSplit: algoSplit,
blockTimes: getBlockTimes(last100Headers),
moneroTimes: getBlockTimes(last100Headers, "0"),
shaTimes: getBlockTimes(last100Headers, "1")
})

} catch (error) {
res.status(500)
res.render('error', { error: error })
}
console.log(getBlockTimes(last100Headers, "0"))
res.render('index', {
title: 'Blocks',
tipInfo: tipInfo,
mempool: mempool,
headers: headers,
pows: { '0': 'Monero', '2': 'SHA' },
nextPage: firstHeight - limit,
prevPage: firstHeight + limit,
limit: limit,
from: from,
algoSplit: algoSplit,
blockTimes: getBlockTimes(last100Headers),
moneroTimes: getBlockTimes(last100Headers, "0"),
shaTimes: getBlockTimes(last100Headers, "2")
})
})


function getBlockTimes(last100Headers, algo) {
let blocktimes = []
let i = 0
if (algo === '0' || algo === '2') {
while (last100Headers[i].pow.pow_algo !== algo) {
if (algo === '0' || algo === '1') {
while (i < last100Headers.length && last100Headers[i].pow.pow_algo !== algo) {
i++;
blocktimes.push(0)
}
}
if (i >= last100Headers.length) {
// This happens if there are no blocks for a specific algorithm in last100headers
return blocktimes;
}
let lastBlockTime = parseInt(last100Headers[i].timestamp.seconds);
i++;
while (i< last100Headers.length && blocktimes.length < 60) {
Expand Down
35 changes: 35 additions & 0 deletions base_layer/core/src/base_node/proto/wallet_rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,14 @@ message TxQueryBatchResponse {
TxLocation location = 2;
google.protobuf.BytesValue block_hash = 3;
uint64 confirmations = 4;
uint64 block_height = 5;
}

message TxQueryBatchResponses {
repeated TxQueryBatchResponse responses = 1;
bool is_synced = 2;
google.protobuf.BytesValue tip_hash = 3;
uint64 height_of_longest_chain = 4;

}

Expand All @@ -60,6 +63,38 @@ message FetchUtxosResponse {
bool is_synced = 2;
}


message QueryDeletedRequest{
repeated uint64 mmr_positions = 1;
google.protobuf.BytesValue chain_must_include_header = 2;
}

message QueryDeletedResponse {
repeated uint64 deleted_positions = 1;
repeated uint64 not_deleted_positions = 2;
bytes best_block = 3;
uint64 height_of_longest_chain = 4;
}

message UtxoQueryRequest{
repeated bytes output_hashes =1;
}

message UtxoQueryResponses {
repeated UtxoQueryResponse responses =1;
bytes best_block = 3;
uint64 height_of_longest_chain = 4;
}

message UtxoQueryResponse {
tari.types.TransactionOutput output = 1;
uint64 mmr_position = 2;
uint64 mined_height =3;
bytes mined_in_block = 4;
bytes output_hash = 5;

}

message TipInfoResponse {
ChainMetadata metadata = 1;
bool is_synced = 2;
Expand Down
2 changes: 2 additions & 0 deletions base_layer/core/src/base_node/proto/wallet_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ pub struct TxQueryBatchResponse {
pub location: TxLocation,
pub block_hash: Option<BlockHash>,
pub confirmations: u64,
pub block_height: u64,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -224,6 +225,7 @@ impl TryFrom<proto::TxQueryBatchResponse> for TxQueryBatchResponse {
.ok_or_else(|| "Invalid or unrecognised `TxLocation` enum".to_string())?,
)?,
block_hash: proto_response.block_hash,
block_height: proto_response.block_height,
confirmations: proto_response.confirmations,
})
}
Expand Down
10 changes: 10 additions & 0 deletions base_layer/core/src/base_node/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use crate::{
},
};

use crate::proto::base_node::{QueryDeletedRequest, QueryDeletedResponse, UtxoQueryRequest, UtxoQueryResponses};
use tari_comms::protocol::rpc::{Request, Response, RpcStatus};
use tari_comms_rpc_macros::tari_rpc;

Expand Down Expand Up @@ -79,6 +80,15 @@ pub trait BaseNodeWalletService: Send + Sync + 'static {

#[rpc(method = 6)]
async fn get_header(&self, request: Request<u64>) -> Result<Response<proto::core::BlockHeader>, RpcStatus>;

#[rpc(method = 7)]
async fn utxo_query(&self, request: Request<UtxoQueryRequest>) -> Result<Response<UtxoQueryResponses>, RpcStatus>;

#[rpc(method = 8)]
async fn query_deleted(
&self,
request: Request<QueryDeletedRequest>,
) -> Result<Response<QueryDeletedResponse>, RpcStatus>;
}

#[cfg(feature = "base_node")]
Expand Down
Loading

0 comments on commit c607d5b

Please sign in to comment.