Skip to content

Commit cde7f9f

Browse files
authored
fix(consensus)!: refactor execution fork handling, better finalization perf (tari-project#1425)
Description --- fix(consensus)!: refactor execution fork handling, better finalization perf Motivation and Context --- Finalizing big blocks (>2000 finalizing txs) would take around a minute in tests. This PR reduces this to < 10s for similar payloads. The finalizing step simply inserts the transaction ID into an index to mark it as finalized. How Has This Been Tested? --- Manually What process can a PR reviewer use to test or verify this change? --- Works as before Breaking Changes --- - [ ] None - [x] Requires data directory to be deleted - [ ] Other - Please specify <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added grouping support for databases and shard group display in the database inspector UI. - Introduced explicit transaction execution querying, locking, and finalization methods in storage layers. - Added new transaction validation result struct to clarify sequencing logic. - Added TypeScript interfaces for new account info and wallet transaction types. - **Improvements** - Consolidated and simplified transaction and execution data models, removing legacy fields and unifying execution handling. - Enhanced consensus and transaction pool logic for clearer transaction sequencing, validation, and execution preparation. - Streamlined abort reason handling with a refined and reduced set of abort causes. - Centralized leader fee calculation logic for consistency. - Updated transaction execution and block execution models to use richer block and transaction identifiers. - Improved error handling and logging in consensus and transaction processing flows. - Refined transaction finalization and decision assertions in tests. - Replaced explicit unwraps with safer access patterns in transaction result handling. - Replaced `chrono` with `time` crate for timestamp handling across storage and template management modules. - Updated web UI and RPC handlers to reflect new transaction execution data structures. - Simplified transaction handling by removing legacy executed transaction abstractions. - Added utility functions for current timestamp retrieval and encoding/decoding of datetime values. - Fixed template selection logic for swap and faucet templates in the tariswap test bench. - Improved transaction pool insertion to accept explicit decision parameters. - Refined leader timeout suspension handling in consensus proposal processing. - Updated consensus no-vote handling to propagate detailed reasons. - Enhanced transaction pool insertion to accept explicit decision parameters. - Adjusted transaction execution and block transaction execution models to explicitly store leaf blocks and transaction IDs. - Consolidated transaction execution retrieval and finalization logic in storage layers. - Simplified transaction record by removing execution and finalization fields, delegating to storage queries. - Updated CLI, bindings, and clients to align with new transaction execution APIs and data structures. - Improved internal documentation and code comments for clarity. - **Bug Fixes** - Removed duplicate transaction input validation during validator node bootstrap. - **Refactor** - Standardized transaction execution method signatures and storage keys, adopting richer block and transaction identifiers. - Updated test harnesses, CLI tools, and bindings to align with new transaction execution APIs and data structures. - Removed SQL-related configuration and code from consensus test builders and validators. - Modularized transaction preparation logic by input type and improved lock acquisition strategies. - Refactored consensus transaction manager and HotStuff logic to unify transaction record handling. - Cleaned up abort handling and removed redundant methods from transaction and execution models. - Reorganized database column families and queries to include block height and improve indexing. - Simplified and unified deserialization and serialization logic in wallet storage. - Removed executed transaction module and related legacy abstractions. - Renamed pacemaker failure suspension methods to timeout suspension for clarity. - Added TypeScript bindings for new types and updated existing bindings to match data model changes. - **Chores** - Removed unused dependencies including `chrono` and `strum_macros`. - Updated package scripts to separate formatting and build steps. - Cleaned up legacy code paths and imports. - Removed SQL database configuration from consensus test builders and validators. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 10e68de commit cde7f9f

File tree

132 files changed

+2709
-2436
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+2709
-2436
lines changed

Cargo.lock

Lines changed: 2 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applications/tari_dan_app_utilities/src/transaction_executor.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@ pub trait TransactionExecutor {
2929

3030
fn execute(
3131
&self,
32-
transaction: Transaction,
32+
transaction: &Transaction,
3333
state_store: ReadOnlyMemoryStateStore,
3434
virtual_substates: VirtualSubstates,
3535
) -> Result<ExecutionOutput, Self::Error>;
3636
}
3737

3838
#[derive(Debug, Clone)]
3939
pub struct ExecutionOutput {
40-
pub transaction: Transaction,
4140
pub result: ExecuteResult,
4241
}
4342

@@ -106,7 +105,7 @@ where TTemplateProvider: TemplateProvider<Template = LoadedTemplate>
106105

107106
fn execute(
108107
&self,
109-
transaction: Transaction,
108+
transaction: &Transaction,
110109
state_store: ReadOnlyMemoryStateStore,
111110
virtual_substates: VirtualSubstates,
112111
) -> Result<ExecutionOutput, Self::Error> {
@@ -136,7 +135,7 @@ where TTemplateProvider: TemplateProvider<Template = LoadedTemplate>
136135
);
137136
let result = processor.execute(transaction.clone())?;
138137

139-
Ok(ExecutionOutput { transaction, result })
138+
Ok(ExecutionOutput { result })
140139
}
141140
}
142141

applications/tari_dan_wallet_daemon/src/handlers/transaction.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -372,12 +372,7 @@ pub async fn handle_get_all(
372372
.wallet_sdk()
373373
.transaction_api()
374374
.fetch_all(req.status, req.component)?;
375-
Ok(TransactionGetAllResponse {
376-
transactions: transactions
377-
.into_iter()
378-
.map(|tx| (tx.transaction, tx.finalize, tx.status, tx.last_update_time))
379-
.collect(),
380-
})
375+
Ok(TransactionGetAllResponse { transactions })
381376
}
382377

383378
pub async fn handle_get_result(

applications/tari_dan_wallet_daemon/src/handlers/validator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub async fn handle_claim_validator_fees(
139139
let max_fee = req.max_fee.unwrap_or(DEFAULT_FEE);
140140

141141
let transaction = transaction_builder(context)
142+
.with_dry_run(req.dry_run)
142143
.with_fee_instructions_builder(|builder| {
143144
let mut bucket_names = vec![];
144145
fee_pool_addresses

applications/tari_dan_wallet_daemon/web_ui/src/routes/Transactions/Transactions.tsx

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,7 @@ import StatusChip from "../../Components/StatusChip";
4040
import { DataTableCell } from "../../Components/StyledComponents";
4141
import { useGetAllTransactions } from "../../api/hooks/useTransactions";
4242
import { emptyRows, handleChangePage, handleChangeRowsPerPage } from "../../utils/helpers";
43-
import { useAccountsGet } from "../../api/hooks/useAccounts";
44-
import {
45-
Account,
46-
FinalizeResult,
47-
substateIdToString,
48-
Transaction,
49-
TransactionStatus,
50-
} from "@tari-project/typescript-bindings";
43+
import { Account, substateIdToString, WalletTransaction } from "@tari-project/typescript-bindings";
5144

5245
export default function Transactions({ account }: { account: Account }) {
5346
const [page, setPage] = useState(0);
@@ -77,12 +70,12 @@ export default function Transactions({ account }: { account: Account }) {
7770
<TableBody>
7871
{data?.transactions
7972
?.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
80-
.map(([t, result, status, _s]: [Transaction, FinalizeResult | null, TransactionStatus, string]) => {
81-
const tx = t.V1;
82-
if (!tx?.id) {
83-
return <></>;
84-
}
85-
73+
.map((transaction: WalletTransaction) => {
74+
const {
75+
transaction: { V1: tx },
76+
finalize: result,
77+
status,
78+
} = transaction;
8679
const hash = tx.id;
8780
return (
8881
<TableRow key={hash}>

applications/tari_indexer/src/dry_run/processor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ where TSubstateCache: SubstateCache + 'static
113113

114114
// execute the payload in the WASM engine and return the result
115115
let exec_output = task::block_in_place(|| {
116-
payload_processor.execute(transaction, state_store.into_read_only(), virtual_substates)
116+
payload_processor.execute(&transaction, state_store.into_read_only(), virtual_substates)
117117
})?;
118118

119119
Ok(exec_output.result)

applications/tari_indexer/src/json_rpc/handlers.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ use tari_dan_app_utilities::{keypair::RistrettoKeypair, substate_file_cache::Sub
3737
use tari_dan_common_types::{optional::Optional, public_key_to_peer_id, Epoch, PeerAddress, SubstateRequirement};
3838
use tari_dan_engine::{template::TemplateModuleLoader, wasm::WasmModule};
3939
use tari_dan_p2p::TariMessagingSpec;
40-
use tari_dan_storage::{consensus_models::Decision, global::GlobalDb};
40+
use tari_dan_storage::{
41+
consensus_models::Decision,
42+
global::GlobalDb,
43+
time::{PrimitiveDateTime, UtcDateTime},
44+
};
4145
use tari_dan_storage_sqlite::{error::SqliteStorageError, global::SqliteGlobalDbAdapter};
4246
use tari_engine_types::{FromByteType, ToByteType};
4347
use tari_epoch_manager::{service::EpochManagerHandle, EpochManagerReader};
@@ -450,7 +454,7 @@ impl JsonRpcHandlers {
450454
execution_result: Some(Box::new(exec_result)),
451455
final_decision: Decision::Commit,
452456
abort_details: None,
453-
finalized_time: Default::default(),
457+
finalized_time: now(),
454458
execution_time: Default::default(),
455459
},
456460
transaction_id,
@@ -675,3 +679,8 @@ impl JsonRpcHandlers {
675679
Self::error_response(answer_id, JsonRpcErrorReason::InternalError, error)
676680
}
677681
}
682+
683+
fn now() -> PrimitiveDateTime {
684+
let now = UtcDateTime::now();
685+
PrimitiveDateTime::new(now.date(), now.time())
686+
}

applications/tari_validator_node/src/bootstrap.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,6 @@ pub fn create_mempool_transaction_validator(
506506
.and_then(HasInputs::new())
507507
.and_then(FeeTransactionValidator)
508508
.and_then(TransactionSignatureValidator)
509-
.and_then(HasInputs::new())
510509
.and_then(TemplateExistsValidator::new(template_manager))
511510
}
512511

applications/tari_validator_node/src/consensus/block_transaction_executor.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ use std::{collections::HashMap, sync::Arc};
66
use log::info;
77
use tari_consensus::traits::{BlockTransactionExecutor, BlockTransactionExecutorError};
88
use tari_dan_app_utilities::transaction_executor::TransactionExecutor;
9-
use tari_dan_common_types::{Epoch, SubstateRequirement};
9+
use tari_dan_common_types::{Epoch, SubstateRequirement, VersionedSubstateId};
1010
use tari_dan_engine::state_store::{memory::MemoryStateStore, new_memory_store, StateWriter};
11-
use tari_dan_storage::{consensus_models::ExecutedTransaction, StateStore};
11+
use tari_dan_storage::{
12+
consensus_models::{TransactionExecution, VersionedSubstateIdLockIntent},
13+
StateStore,
14+
};
1215
use tari_engine_types::{
1316
substate::Substate,
1417
virtual_substate::{VirtualSubstate, VirtualSubstateId, VirtualSubstates},
@@ -70,10 +73,10 @@ where
7073

7174
fn execute(
7275
&self,
73-
transaction: Transaction,
76+
transaction: &Transaction,
7477
current_epoch: Epoch,
7578
resolved_inputs: &HashMap<SubstateRequirement, Substate>,
76-
) -> Result<ExecutedTransaction, BlockTransactionExecutorError> {
79+
) -> Result<TransactionExecution, BlockTransactionExecutorError> {
7780
let id = *transaction.id();
7881

7982
info!(target: LOG_TARGET, "Transaction {} executing. {} input(s)", id, resolved_inputs.len());
@@ -98,9 +101,27 @@ where
98101
// execution
99102
let resolved_inputs = exec_output.resolve_input_locks(resolved_inputs);
100103

101-
let executed = ExecutedTransaction::new(exec_output.transaction, exec_output.result, resolved_inputs);
102-
info!(target: LOG_TARGET, "Transaction {} executed. {}", id,executed.result().finalize.result);
103-
Ok(executed)
104+
let resulting_outputs = exec_output
105+
.result
106+
.finalize
107+
.result
108+
.accept()
109+
.map(|diff| {
110+
diff.up_iter()
111+
.map(|(addr, substate)| {
112+
VersionedSubstateIdLockIntent::output(VersionedSubstateId::new(
113+
addr.clone(),
114+
substate.version(),
115+
))
116+
})
117+
.collect::<Vec<_>>()
118+
})
119+
.unwrap_or_default();
120+
121+
let exec = TransactionExecution::new(exec_output.result, resolved_inputs, resulting_outputs);
122+
123+
info!(target: LOG_TARGET, "Transaction {} executed. {}", id, exec.result().finalize.result);
124+
Ok(exec)
104125
}
105126
}
106127

applications/tari_validator_node/src/dry_run_transaction_processor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl<TStateStore: StateStore<Addr = PeerAddress> + Send + Sync> DryRunTransactio
126126
// execute the payload in the WASM engine and return the result
127127
let processor = self.payload_processor.clone();
128128
let exec_output = task::spawn_blocking(move || {
129-
processor.execute(transaction, temp_state_store.into_read_only(), virtual_substates)
129+
processor.execute(&transaction, temp_state_store.into_read_only(), virtual_substates)
130130
})
131131
.await??;
132132
let result = exec_output.result;

0 commit comments

Comments
 (0)