Skip to content

feat!: impl epoch birthday for utxo scanning - #1633

Merged
sdbondi merged 2 commits into
tari-project:developmentfrom
sdbondi:cipher-seed-birthday
Nov 6, 2025
Merged

feat!: impl epoch birthday for utxo scanning#1633
sdbondi merged 2 commits into
tari-project:developmentfrom
sdbondi:cipher-seed-birthday

Conversation

@sdbondi

@sdbondi sdbondi commented Nov 6, 2025

Copy link
Copy Markdown
Member

Description

feat!: impl epoch birthday for utxo scanning

Motivation and Context

Tracks the birthday epoch for wallet accounts and adds an epoch filter to the indexer utxo stream request.
This allows the wallet to limit UTXO scanning to epochs after the account/cipher seed's creation.

caveats: the birthday epoch is calculated based on time, it does not fetch the current epoch from the indexer at account creation time. Therefore, the calculation will be inaccurate if epoch time is not as expected e.g. due to network conditions.
If epochs occur faster than the target, the wallet will do extra scanning, if significantly slower, the wallet could miss UTXOs.

Currently, the wallet hardcodes a zero-epoch time that will always yield an epoch 0 birthday.

How Has This Been Tested?

New unit test and manually

What process can a PR reviewer use to test or verify this change?

Breaking Changes

  • None
  • Requires data directory to be deleted
  • Other - Please specify

Summary by CodeRabbit

  • New Features

    • Account birthday epoch support for wallet recovery and seed management
    • Epoch tracking in UTXO updates and streaming (new from_epoch/max_epoch fields)
  • Bug Fixes

    • Indexer returns 503 while initial sync is in progress
    • Treat empty committee as a handled network error and map to service_unavailable
    • Return bad request when submitting transactions with no inputs
  • Refactor

    • Public proto/type rename: SubstateCreatedProof → SubstateCreate (and Destroy)

@coderabbitai

coderabbitai Bot commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds epoch tracking to UTXO storage and streaming, threads epoch/birthday through wallet/account APIs, renames substate proof types, centralizes global DB path handling, and refines error handling and request guards across indexer and wallet services.

Changes

Cohort / File(s) Summary
Global DB Path
applications/tari_indexer/src/config.rs, applications/tari_indexer/src/lib.rs, applications/tari_validator_node/src/config.rs, applications/tari_validator_node/src/lib.rs, crates/storage_sqlite/src/sqlite_db_factory.rs
Added global_db_path/get_global_db_path accessors; SqliteDbFactory now accepts a DB file path (db_path) directly.
UTXO schema & models
applications/tari_indexer/src/storage_sqlite/migrations/.../up.sql, applications/tari_indexer/src/storage_sqlite/schema.rs, applications/tari_indexer/src/storage_sqlite/models/utxo.rs
Added non-null epoch column to utxos; updated index; added epoch fields to UTXO insert/update/record models.
UTXO reader/writer & store traits
applications/tari_indexer/src/storage_sqlite/reader.rs, applications/tari_indexer/src/storage_sqlite/writer.rs, applications/tari_indexer/src/store.rs, applications/tari_indexer/src/substate_manager.rs
utxos_get_updates now accepts from_epoch: Epoch and returns UtxoStateUpdateSet { updates, max_state_version, max_epoch }; batch_insert_utxo_updates now takes epoch: Epoch and persists it.
Indexer runtime & worker
applications/tari_indexer/src/network_state_sync/worker.rs, applications/tari_indexer/src/lib.rs
Callsites updated to pass epoch/global DB path: worker passes epoch into batch_insert_utxo_updates; indexer uses global_db_path() for DB factory.
Streaming & REST handlers
applications/tari_indexer/src/rest_api/streaming/utxo_stream.rs, applications/tari_indexer/src/rest_api/handlers/substates.rs, applications/tari_indexer/src/rest_api/handlers/transactions.rs
Streaming logic adapted to UtxoStateUpdateSet (destructure updates, max_state_version, max_epoch) and pass from_epoch; substates handler enforces initial-scan-complete guard; submit_transaction handles NoCommitteeMembers and NoInputsProvided.
Substate proof renames
crates/p2p/proto/rpc.proto, crates/p2p/src/block_sync.rs, crates/p2p/src/conversions/rpc.rs, crates/rpc_state_sync/src/state_sync.rs, crates/state_store_rocksdb/src/reader.rs, crates/storage/src/consensus_models/*.rs
Renamed SubstateCreatedProofSubstateCreate and SubstateDestroyedProofSubstateDestroy across proto, conversions, readers, and consensus models; updated signatures/usages.
Indexer error handling
crates/indexer_lib/src/error.rs, crates/indexer_lib/src/substate_scanner.rs
Added NoCommitteeMembers { details: String } error variant and early-return guard when committee is empty.
Wallet: epoch/birthday models & storage
crates/wallet/sdk/src/models/epoch_birthday.rs, crates/wallet/sdk/src/models/mod.rs, crates/wallet/sdk/src/models/account.rs, crates/wallet/storage_sqlite/migrations/.../up.sql, crates/wallet/storage_sqlite/src/schema.rs, crates/wallet/storage_sqlite/src/models/account.rs
Added EpochBirthday type; added birthday_epoch: Epoch to Account models; added birthday_epoch DB column and schema updates.
Wallet APIs & key manager
crates/wallet/sdk/src/apis/accounts.rs, crates/wallet/sdk/src/apis/key_manager.rs, crates/wallet/sdk/src/key_managers/backend.rs, crates/wallet/sdk/src/local_key_store.rs, crates/wallet/sdk/src/key_managers/local.rs
AccountsApi now holds epoch_birthday; add_account/create_account/accounts_insert accept/propagate birthday_epoch; key manager exposes get_cipher_seed_birthday_epoch(); key store trait gains cipher_seed_birthday().
Wallet SDK wiring
crates/wallet/sdk/src/sdk.rs, crates/wallet/sdk/src/storage/writer.rs, crates/wallet/sdk/src/network.rs, crates/wallet/sdk/src/models/utxo_update.rs
WalletSdk::initialize now requires EpochBirthday; calculate_birthday_epoch() added; stream_stealth_utxo_updates gains from_epoch: Epoch; UtxoStateUpdateSet includes max_epoch; accounts_insert takes birthday_epoch.
Wallet services & recovery
crates/wallet/sdk_services/src/indexer_rest_api.rs, crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs, crates/wallet/sdk_services/src/account_recovery/service.rs
stream_stealth_utxo_updates forwards from_epoch; AccountRecoveryService stores and uses cipher_seed_birthday_epoch when adding recovered accounts.
Bindings & client types
bindings/src/types/Account.ts, bindings/src/types/UtxoStateUpdateSet.ts, bindings/src/types/tari-indexer-client/GetUtxoUpdatesRequest.ts, clients/tari_indexer_client/src/types.rs, clients/tari_indexer_client/tests/streaming.rs
JS/TS and Rust client types updated: Account adds birthday_epoch, UtxoStateUpdateSet adds max_epoch, GetUtxoUpdatesRequest adds from_epoch (serde default); tests updated to set from_epoch.
Tests & utilities updates
crates/wallet/sdk/tests/support/harness.rs, crates/wallet/storage_sqlite/tests/accounts.rs, utilities/tariswap_test_bench/src/*
Test harnesses, storage tests, and bench utilities updated to initialize WalletSdk with EpochBirthday and pass Epoch::zero()/EpochBirthday::far_future() where required.
Misc
crates/epoch_manager/src/service/epoch_manager_service.rs
Log message updated to "🚀 Starting epoch manager".

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Indexer as Indexer API
    participant Store as UTXO Store
    participant DB as SQLite DB

    Client->>Indexer: stream_utxo_updates(from_epoch, ...)
    Indexer->>Store: utxos_get_updates(from_epoch, ...)
    Store->>DB: SELECT ... WHERE epoch >= from_epoch ...
    DB-->>Store: Utxo rows (updates) + max_state_version + max_epoch
    Store-->>Indexer: UtxoStateUpdateSet { updates, max_state_version, max_epoch }
    Indexer-->>Client: StartOfShard, [updates...], EndOfShard (includes max_epoch)
Loading
sequenceDiagram
    participant Init as App Init
    participant WalletSDK as Wallet SDK
    participant KeyMgr as Key Manager
    participant Accounts as Accounts API

    Init->>WalletSDK: initialize(store, indexer, config, EpochBirthday)
    WalletSDK->>KeyMgr: key_manager_api(..., epoch_birthday)
    WalletSDK->>Accounts: accounts_api(..., epoch_birthday)
    Accounts->>Accounts: calculate_current_epoch() -> birthday_epoch
    Accounts->>Storage: add_account(..., birthday_epoch, ...)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas to focus on:

  • epoch propagation through indexer → writer → DB and index correctness;
  • correctness of UtxoStateUpdateSet handling at all callsites (streaming, pending updates, encoding);
  • EpochBirthday arithmetic and tests (edge cases, saturating behavior);
  • DB migrations and schema+model alignment for epoch and birthday_epoch;
  • consistent renaming of substate proof types across proto/conversions/storage.

Possibly related PRs

Poem

🐰
I hop through rows and indices bright,
I tuck an epoch in each byte,
I give accounts a birthday tune,
Renamed proofs dance under moon,
Hooray — the rabbit coded night. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.58% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly describes the main change: implementing epoch birthday support for UTXO scanning. This directly summarizes the primary objective across the substantial changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
applications/tari_indexer/src/rest_api/streaming/utxo_stream.rs (1)

101-132: Don't drop max_epoch from the streaming payload

get_utxo_updates now returns { updates, max_state_version, max_epoch } so that wallets can persist both the state-version and epoch high-water marks. In this path we only log max_epoch and then discard it, so REST-streaming clients never learn the new epoch and cannot advance their stored birthday/epoch filter—they’re forced back to wall-clock heuristics and will continue to re-scan the same range. Please propagate max_epoch through PendingUpdates and encode it into the stream payload (e.g., StartOfShard/EndOfShard), mirroring whatever you did on the gRPC side, so downstream consumers can persist the server-provided epoch.

crates/state_store_rocksdb/src/reader.rs (2)

1044-1049: Bug: wrong block used for membership check (can return stale change)

You’re checking applicable_blocks.contains(block_id) where block_id is the function parameter (always present in the set). This ignores the change’s actual block and can pick a change from outside the pending chain.

Apply this fix:

-            if max_change.as_ref().is_none_or(|c| c.version < key.version) && applicable_blocks.contains(block_id) {
+            if max_change.as_ref().is_none_or(|c| c.version < key.version)
+                && applicable_blocks.contains(&key.block_id)
+            {

1080-1084: Bug: same membership check issue in versioned-substate query

Same problem here; membership must be evaluated against the key’s block, not the function parameter.

-            if versioned.version() == key.version && applicable_blocks.contains(block_id) {
+            if versioned.version() == key.version && applicable_blocks.contains(&key.block_id) {
crates/wallet/storage_sqlite/src/writer.rs (1)

656-667: Store birthday_epoch with a safe conversion

Epoch is u64; SQLite INTEGER is signed 64-bit. Casting with as i64 silently wraps on overflow. Use i64::try_from and return a clear error, or store as TEXT/unsigned.

-        diesel::insert_into(accounts::table)
+        let birthday_epoch_i64 = i64::try_from(birthday_epoch.as_u64())
+            .map_err(|_| WalletStorageError::bad_query("accounts_insert", "birthday_epoch exceeds i64::MAX"))?;
+
+        diesel::insert_into(accounts::table)
             .values((
                 ...
-                accounts::birthday_epoch.eq(birthday_epoch.as_u64() as i64),
+                accounts::birthday_epoch.eq(birthday_epoch_i64),
                 ...
             ))

If the schema permits, alternatively store birthday_epoch as a string to avoid signed-range constraints. Based on learnings.

Also applies to: 677-691

🧹 Nitpick comments (8)
applications/tari_indexer/src/lib.rs (1)

82-82: LGTM!

The refactoring to use config.global_db_path() centralizes database path configuration, improving maintainability by eliminating hardcoded path construction logic.

applications/tari_validator_node/src/config.rs (1)

135-137: LGTM!

The new get_global_db_path() method centralizes the global database path construction, improving consistency with similar changes in the indexer configuration.

applications/tari_validator_node/src/lib.rs (1)

95-95: LGTM! Good refactor for maintainability.

Encapsulating the global database path in a dedicated method improves consistency and makes it easier to modify path construction logic in the future.

crates/state_store_rocksdb/src/reader.rs (1)

218-221: Minor: duplicate logic between get_pending_chain_until and get_pending_chain_ordered

Both functions traverse the same parent chain. Consider extracting a shared iterator over parents and then collect into HashSet/Vec to DRY this up.

Also applies to: 240-254

crates/wallet/sdk_services/src/indexer_rest_api.rs (1)

181-195: Avoid magic 1000; derive has_more from the request limit

Use a single constant for per-shard page size and compare with equality (the server should not exceed the requested limit).

+const PER_SHARD_LIMIT: u32 = 1000;
...
-            .stream_utxo_updates_protobuf(GetUtxoUpdatesRequest {
-                from_epoch,
-                shard_state_versions,
-                resource_address,
-                unspent_only,
-                per_shard_limit: 1000,
-            })
+            .stream_utxo_updates_protobuf(GetUtxoUpdatesRequest {
+                from_epoch,
+                shard_state_versions,
+                resource_address,
+                unspent_only,
+                per_shard_limit: PER_SHARD_LIMIT,
+            })
...
-                let sos = res.sos.map(|sos| StartOfShard {
+                let sos = res.sos.map(|sos| StartOfShard {
                     shard: Shard::from(sos.shard),
                     max_state_version: StateVersion::from(sos.max_state_version),
-                    has_more: sos.num_updates >= 1000,
+                    has_more: sos.num_updates == PER_SHARD_LIMIT,
                 });

Also applies to: 200-205

utilities/tariswap_test_bench/src/accounts.rs (1)

65-73: Birthday epoch defaulting to Epoch::zero() in tests

Fine for synthetic runs, but note this forces scanning from genesis. If tests aim to validate birthday filtering, consider passing a non-zero epoch derived from the harness’ configured epoch timing.

Also applies to: 146-154

crates/wallet/sdk/src/apis/accounts.rs (1)

47-53: Guard against epoch drift with an overlap/clamp strategy

Computing birthday from local time risks missing UTXOs if epochs progress slower than assumed. Mitigate by:

  • subtracting a small overlap (e.g., 1–2 epochs) from the computed birthday, and
  • clamping the request’s from_epoch to the indexer’s current epoch when streaming.

Example minimal overlap in create_account:

-        let birthday_epoch = self.epoch_birthday.calculate_current_epoch();
+        const OVERLAP_EPOCHS: u64 = 2;
+        let computed = self.epoch_birthday.calculate_current_epoch();
+        let birthday_epoch = Epoch(computed.as_u64().saturating_sub(OVERLAP_EPOCHS));

Pair this with a clamp at call-sites building GetUtxoUpdatesRequest (or store a per-account overlap policy).

Please confirm the streaming path already clamps from_epoch to the indexer’s current epoch; otherwise, wallet may miss earlier updates after long pauses. Based on PR objectives.

Also applies to: 59-74, 89-99, 116-125, 147-157

crates/wallet/sdk/src/models/epoch_birthday.rs (1)

29-36: Document the magic number 1200.

The hardcoded value 1200 on Line 34 appears to represent epoch duration in seconds (20 minutes), but this isn't documented. Consider extracting this to a named constant or adding a comment explaining why this specific value is used in far_future().

 pub const fn far_future() -> Self {
     Self {
         epoch_time_secs: NonZeroU64::new(u64::MAX).unwrap(),
+        // 1200 seconds (20 minutes) is the standard epoch duration
         rel_zero_epoch_secs: 1200,
     }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ddc8057 and a474ad9.

📒 Files selected for processing (57)
  • applications/tari_indexer/src/config.rs (1 hunks)
  • applications/tari_indexer/src/lib.rs (1 hunks)
  • applications/tari_indexer/src/network_state_sync/worker.rs (1 hunks)
  • applications/tari_indexer/src/rest_api/handlers/substates.rs (1 hunks)
  • applications/tari_indexer/src/rest_api/handlers/transactions.rs (1 hunks)
  • applications/tari_indexer/src/rest_api/streaming/utxo_stream.rs (3 hunks)
  • applications/tari_indexer/src/storage_sqlite/migrations/2023-02-16-145719_initial/up.sql (1 hunks)
  • applications/tari_indexer/src/storage_sqlite/models/utxo.rs (3 hunks)
  • applications/tari_indexer/src/storage_sqlite/reader.rs (3 hunks)
  • applications/tari_indexer/src/storage_sqlite/schema.rs (1 hunks)
  • applications/tari_indexer/src/storage_sqlite/writer.rs (3 hunks)
  • applications/tari_indexer/src/store.rs (3 hunks)
  • applications/tari_indexer/src/substate_manager.rs (2 hunks)
  • applications/tari_validator_node/src/config.rs (1 hunks)
  • applications/tari_validator_node/src/lib.rs (1 hunks)
  • applications/tari_validator_node/src/p2p/rpc/block_sync_task.rs (2 hunks)
  • applications/tari_walletd/src/lib.rs (3 hunks)
  • applications/tari_walletd/src/main.rs (1 hunks)
  • bindings/src/types/Account.ts (2 hunks)
  • bindings/src/types/UtxoStateUpdateSet.ts (1 hunks)
  • bindings/src/types/tari-indexer-client/GetUtxoUpdatesRequest.ts (1 hunks)
  • clients/tari_indexer_client/src/types.rs (1 hunks)
  • clients/tari_indexer_client/tests/streaming.rs (1 hunks)
  • crates/epoch_manager/src/service/epoch_manager_service.rs (1 hunks)
  • crates/indexer_lib/src/error.rs (1 hunks)
  • crates/indexer_lib/src/substate_scanner.rs (1 hunks)
  • crates/p2p/proto/rpc.proto (2 hunks)
  • crates/p2p/src/block_sync.rs (2 hunks)
  • crates/p2p/src/conversions/rpc.rs (3 hunks)
  • crates/rpc_state_sync/src/state_sync.rs (2 hunks)
  • crates/state_store_rocksdb/src/reader.rs (3 hunks)
  • crates/storage/src/consensus_models/block.rs (5 hunks)
  • crates/storage/src/consensus_models/substate.rs (4 hunks)
  • crates/storage_sqlite/src/sqlite_db_factory.rs (2 hunks)
  • crates/wallet/sdk/src/apis/accounts.rs (8 hunks)
  • crates/wallet/sdk/src/apis/key_manager.rs (6 hunks)
  • crates/wallet/sdk/src/key_managers/backend.rs (1 hunks)
  • crates/wallet/sdk/src/key_managers/local.rs (1 hunks)
  • crates/wallet/sdk/src/local_key_store.rs (1 hunks)
  • crates/wallet/sdk/src/models/account.rs (4 hunks)
  • crates/wallet/sdk/src/models/epoch_birthday.rs (1 hunks)
  • crates/wallet/sdk/src/models/mod.rs (2 hunks)
  • crates/wallet/sdk/src/models/utxo_update.rs (2 hunks)
  • crates/wallet/sdk/src/network.rs (2 hunks)
  • crates/wallet/sdk/src/sdk.rs (8 hunks)
  • crates/wallet/sdk/src/storage/writer.rs (2 hunks)
  • crates/wallet/sdk/tests/support/harness.rs (4 hunks)
  • crates/wallet/sdk_services/src/account_recovery/service.rs (6 hunks)
  • crates/wallet/sdk_services/src/indexer_rest_api.rs (2 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs (1 hunks)
  • crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (1 hunks)
  • crates/wallet/storage_sqlite/src/models/account.rs (3 hunks)
  • crates/wallet/storage_sqlite/src/schema.rs (1 hunks)
  • crates/wallet/storage_sqlite/src/writer.rs (3 hunks)
  • crates/wallet/storage_sqlite/tests/accounts.rs (2 hunks)
  • utilities/tariswap_test_bench/src/accounts.rs (3 hunks)
  • utilities/tariswap_test_bench/src/runner.rs (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-19T10:49:02.115Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1543
File: crates/common_types/src/shard_state_versions.rs:59-74
Timestamp: 2025-08-19T10:49:02.115Z
Learning: In crates/common_types/src/shard_state_versions.rs, MAX_SHARDS represents the maximum shard number + 1 (257) used for bounds checking, not the maximum capacity. The current code correctly validates that shard group end numbers don't exceed the maximum possible shard number (256).

Applied to files:

  • applications/tari_indexer/src/rest_api/streaming/utxo_stream.rs
🧬 Code graph analysis (36)
applications/tari_indexer/src/rest_api/handlers/transactions.rs (1)
applications/tari_indexer/src/rest_api/error.rs (1)
  • service_unavailable (91-96)
bindings/src/types/Account.ts (1)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
clients/tari_indexer_client/src/types.rs (1)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/storage_sqlite/src/schema.rs (1)
crates/wallet/sdk/src/models/account.rs (2)
  • birthday_epoch (43-45)
  • birthday_epoch (81-84)
crates/wallet/sdk/src/network.rs (2)
bindings/src/types/Shard.ts (1)
  • Shard (3-3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk_services/src/account_recovery/service.rs (2)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/models/account.rs (2)
  • birthday_epoch (43-45)
  • birthday_epoch (81-84)
applications/tari_indexer/src/rest_api/handlers/substates.rs (1)
applications/tari_indexer/src/rest_api/error.rs (2)
  • anyhow (44-48)
  • service_unavailable (91-96)
crates/wallet/sdk/src/models/account.rs (1)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/local_key_store.rs (1)
crates/wallet/sdk/src/key_managers/backend.rs (1)
  • cipher_seed_birthday (29-29)
crates/wallet/sdk/src/models/utxo_update.rs (2)
bindings/src/types/Shard.ts (1)
  • Shard (3-3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
utilities/tariswap_test_bench/src/runner.rs (2)
crates/wallet/sdk/src/sdk.rs (2)
  • initialize (76-103)
  • store (145-147)
crates/wallet/sdk/src/models/epoch_birthday.rs (1)
  • far_future (31-36)
applications/tari_indexer/src/rest_api/streaming/utxo_stream.rs (2)
bindings/src/types/UtxoStateUpdateSet.ts (1)
  • UtxoStateUpdateSet (6-10)
bindings/src/types/WalletUtxoUpdate.ts (1)
  • WalletUtxoUpdate (6-6)
applications/tari_indexer/src/substate_manager.rs (2)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
bindings/src/types/UtxoStateUpdateSet.ts (1)
  • UtxoStateUpdateSet (6-10)
applications/tari_indexer/src/storage_sqlite/writer.rs (2)
crates/storage/src/consensus_models/block.rs (1)
  • epoch (347-349)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
applications/tari_indexer/src/storage_sqlite/schema.rs (1)
crates/storage/src/consensus_models/block.rs (1)
  • epoch (347-349)
applications/tari_indexer/src/storage_sqlite/reader.rs (2)
bindings/src/types/UtxoStateUpdateSet.ts (1)
  • UtxoStateUpdateSet (6-10)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/storage/src/consensus_models/substate.rs (1)
crates/p2p/src/conversions/rpc.rs (8)
  • from (41-45)
  • from (60-65)
  • from (81-88)
  • from (107-113)
  • from (119-124)
  • from (164-173)
  • from (189-194)
  • value (153-157)
applications/tari_indexer/src/store.rs (3)
bindings/src/types/UtxoStateUpdateSet.ts (1)
  • UtxoStateUpdateSet (6-10)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
bindings/src/types/Shard.ts (1)
  • Shard (3-3)
crates/wallet/sdk/src/key_managers/backend.rs (1)
crates/wallet/sdk/src/local_key_store.rs (3)
  • derive_secret (47-54)
  • get_imported_secret (56-70)
  • cipher_seed_birthday (72-75)
crates/wallet/sdk/src/models/epoch_birthday.rs (2)
crates/wallet/sdk/src/apis/accounts.rs (1)
  • new (60-74)
crates/wallet/sdk/src/apis/key_manager.rs (1)
  • new (55-69)
crates/wallet/sdk/src/storage/writer.rs (3)
bindings/src/types/Shard.ts (1)
  • Shard (3-3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/models/account.rs (2)
  • birthday_epoch (43-45)
  • birthday_epoch (81-84)
bindings/src/types/tari-indexer-client/GetUtxoUpdatesRequest.ts (1)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
applications/tari_walletd/src/main.rs (1)
crates/wallet/sdk/src/models/account.rs (4)
  • birthday_epoch (43-45)
  • birthday_epoch (81-84)
  • name (47-49)
  • name (98-100)
crates/wallet/sdk_services/src/indexer_rest_api.rs (2)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
bindings/src/types/tari-indexer-client/GetUtxoUpdatesRequest.ts (1)
  • GetUtxoUpdatesRequest (7-13)
bindings/src/types/UtxoStateUpdateSet.ts (2)
bindings/src/types/WalletUtxoUpdate.ts (1)
  • WalletUtxoUpdate (6-6)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/storage_sqlite/src/writer.rs (2)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/models/account.rs (2)
  • birthday_epoch (43-45)
  • birthday_epoch (81-84)
crates/wallet/sdk/src/apis/accounts.rs (3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/sdk.rs (3)
  • network (157-159)
  • store (145-147)
  • key_manager_api (174-183)
crates/wallet/sdk/src/models/account.rs (2)
  • birthday_epoch (43-45)
  • birthday_epoch (81-84)
crates/wallet/sdk/src/apis/key_manager.rs (1)
crates/wallet/sdk/src/cipher_seed.rs (1)
  • cipher_seed (29-34)
crates/storage/src/consensus_models/block.rs (1)
applications/tari_indexer/src/storage_sqlite/writer.rs (1)
  • updates (93-109)
applications/tari_walletd/src/lib.rs (7)
crates/wallet/sdk/src/key_managers/backend.rs (1)
  • cipher_seed_birthday (29-29)
crates/wallet/sdk/src/local_key_store.rs (1)
  • cipher_seed_birthday (72-75)
crates/wallet/sdk/src/apis/accounts.rs (1)
  • new (60-74)
crates/wallet/sdk/src/apis/key_manager.rs (1)
  • new (55-69)
crates/wallet/sdk_services/src/account_recovery/service.rs (1)
  • new (43-55)
crates/wallet/sdk/src/sdk.rs (3)
  • initialize (76-103)
  • store (145-147)
  • network (157-159)
crates/wallet/sdk/src/models/epoch_birthday.rs (1)
  • far_future (31-36)
crates/wallet/storage_sqlite/src/models/account.rs (1)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/tests/support/harness.rs (3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/sdk.rs (2)
  • initialize (76-103)
  • store (145-147)
crates/wallet/sdk/src/apis/accounts.rs (1)
  • new (60-74)
utilities/tariswap_test_bench/src/accounts.rs (3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
bindings/src/types/wallet-daemon-client/KeyId.ts (1)
  • KeyId (3-3)
crates/wallet/sdk/src/models/key.rs (1)
  • derived (322-324)
crates/wallet/sdk/src/sdk.rs (1)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
clients/tari_indexer_client/tests/streaming.rs (3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
bindings/src/types/NumPreshards.ts (1)
  • NumPreshards (3-3)
bindings/src/types/tari-indexer-client/GetUtxoUpdatesRequest.ts (1)
  • GetUtxoUpdatesRequest (7-13)
crates/p2p/src/conversions/rpc.rs (2)
crates/storage/src/consensus_models/substate.rs (6)
  • value (314-319)
  • value (363-365)
  • from (344-346)
  • from (350-352)
  • from (381-390)
  • from (450-452)
crates/common_types/src/substate_address.rs (1)
  • from_bytes (61-71)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: check stable
  • GitHub Check: test
  • GitHub Check: check nightly
  • GitHub Check: machete
  • GitHub Check: clippy
🔇 Additional comments (62)
crates/epoch_manager/src/service/epoch_manager_service.rs (1)

116-116: LGTM!

The rocket emoji addition is consistent with the existing log message style throughout the file and improves log readability.

crates/rpc_state_sync/src/state_sync.rs (2)

659-663: LGTM! Function signature correctly updated with renamed type.

The parameter type has been properly updated from SubstateCreatedProof to SubstateCreate. The function body's field accesses remain unchanged, indicating the new type maintains interface compatibility.


31-31: Type rename is correctly applied and complete.

Verification confirms that the import and function parameter have been properly updated from SubstateCreatedProof to SubstateCreate. No remaining references to the old type name exist in the codebase, and the field accesses within the function body (create.substate.substate_id, create.substate.value, create.substate.to_value_hash()) remain compatible with the new type.

crates/indexer_lib/src/error.rs (1)

29-30: LGTM! Clear error variant for empty committee scenario.

The new NoCommitteeMembers error variant appropriately captures scenarios where no committee members are available, with helpful diagnostic details.

crates/indexer_lib/src/substate_scanner.rs (1)

124-128: Good defensive check preventing operations on empty committee.

This guard prevents downstream issues including:

  • A meaningless committee.shuffle() operation on line 130
  • Potential arithmetic issues in the Byzantine fault tolerance calculation (committee.len() - 1) / 3 on line 132 when committee.len() is 0

The error message provides helpful context for debugging.

applications/tari_indexer/src/rest_api/handlers/transactions.rs (2)

71-74: LGTM! Appropriate error handling for empty committee scenario.

The NoCommitteeMembers case is correctly mapped to a 503 Service Unavailable status, consistent with the AllValidatorsFailed error handling.


79-81: LGTM! Proper validation error for missing transaction inputs.

Returns a 400 Bad Request status for transactions without inputs, which correctly categorizes this as a client error rather than a server error.

applications/tari_indexer/src/rest_api/handlers/substates.rs (1)

70-79: LGTM! Prevents queries before indexer is ready.

The initial scanning check correctly returns a 503 Service Unavailable status with a helpful message, improving the user experience by preventing incomplete or inconsistent query results during the initial sync phase.

applications/tari_validator_node/src/p2p/rpc/block_sync_task.rs (2)

15-15: Type rename: SubstateCreatedProofSubstateCreate.

This change is part of a broader type renaming effort across the codebase. The rename improves clarity by using a more concise name.


32-32: Field type updated to match renamed type.

Consistent with the import change on line 15.

applications/tari_indexer/src/config.rs (1)

84-86: LGTM! Centralized global database path configuration.

The new method follows the same pattern as state_db_path() and provides a consistent way to access the global database path. This aligns with the refactoring in SqliteDbFactory to accept complete database paths.

clients/tari_indexer_client/src/types.rs (1)

376-377: Epoch default value is appropriate for backward compatibility.

Verification confirms that Epoch is defined in crates/common_types/src/epoch.rs as a newtype struct wrapping u64 with a Default derive. This means Epoch::default() returns Epoch(0), which correctly represents the first epoch and enables backward-compatible deserialization without filtering historical UTXOs. The implementation is sound.

crates/storage_sqlite/src/sqlite_db_factory.rs (1)

47-52: All call sites properly updated; no issues found.

Verification confirms both SqliteDbFactory::new() call sites have been correctly updated to pass complete database file paths:

  • applications/tari_validator_node/src/lib.rs:95: passes config.validator_node.get_global_db_path() → returns data_dir.join("global_storage.sqlite")
  • applications/tari_indexer/src/lib.rs:82: passes config.global_db_path() → returns to_data_dir().join("global_storage.sqlite")

No other instantiation patterns exist. The breaking API change has been properly managed across the codebase.

clients/tari_indexer_client/tests/streaming.rs (2)

6-6: LGTM!

The import addition correctly brings Epoch into scope for the new from_epoch field.


13-24: LGTM!

The test correctly initializes the new from_epoch field. Using Epoch::zero() ensures the test scans from the beginning, which is appropriate for a comprehensive dev test.

applications/tari_indexer/src/storage_sqlite/migrations/2023-02-16-145719_initial/up.sql (1)

146-146: LGTM! Index optimized for epoch-based queries.

The updated index utxos_resource_state_version_shard_epoch_idx now includes the epoch column, which will optimize queries filtering by epoch—a key feature of this PR.

crates/wallet/storage_sqlite/src/schema.rs (1)

11-11: LGTM!

The Diesel schema correctly reflects the birthday_epoch column added in the migration. The BigInt type mapping is appropriate for the SQL BIGINT column type.

applications/tari_indexer/src/storage_sqlite/schema.rs (1)

111-111: LGTM!

The Diesel schema correctly reflects the epoch column added in the migration. The BigInt type mapping is appropriate for the SQL bigint column type.

crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (1)

90-90: Review comment contains inaccurate technical reasoning.

The concern about NOT NULL without a default is technically incorrect for a CREATE TABLE statement. Adding NOT NULL columns without defaults is standard and correct when creating new tables—the constraint only causes issues when altering existing tables with data.

However, this appears to be a recent change introducing epoch birthday functionality (commit a474ad9). If this modifies an already-deployed schema, the breaking change concern is valid but stems from adding a required column, not from the NOT NULL definition itself.

Clarification needed: Verify whether this migration requires users to delete existing data directories, and if so, ensure that requirement is clearly documented in upgrade guidance or release notes. The current codebase shows no explicit documentation confirming this requirement.

bindings/src/types/Account.ts (1)

1-16: LGTM! Auto-generated bindings correctly reflect the backend changes.

The addition of the birthday_epoch field aligns with the epoch birthday feature introduced in this PR.

crates/wallet/sdk/src/models/utxo_update.rs (1)

7-7: LGTM! Clean addition of epoch tracking to UTXO updates.

The max_epoch field properly extends the UtxoStateUpdateSet to include epoch information alongside state version tracking.

Also applies to: 44-44

bindings/src/types/tari-indexer-client/GetUtxoUpdatesRequest.ts (1)

1-13: LGTM! Auto-generated bindings correctly add epoch filtering capability.

The from_epoch field enables the wallet to limit UTXO scanning to epochs after account creation, as described in the PR objectives.

utilities/tariswap_test_bench/src/runner.rs (1)

10-10: LGTM! Appropriate use of EpochBirthday::far_future() in test code.

Using far_future() in the test bench ensures no historical UTXO scanning occurs during performance testing, which is appropriate for this context.

Also applies to: 122-122

crates/wallet/storage_sqlite/src/models/account.rs (1)

5-5: LGTM! Field addition aligns with birthday epoch feature.

The birthday_epoch field is properly added to the SQLite model.

Also applies to: 23-23

bindings/src/types/UtxoStateUpdateSet.ts (1)

1-10: LGTM! Auto-generated bindings correctly include epoch tracking.

The max_epoch field properly extends the UTXO update set type to include epoch information.

crates/wallet/sdk/src/models/mod.rs (1)

8-8: LGTM! Standard module organization.

The epoch_birthday module is properly integrated into the models module hierarchy.

Also applies to: 25-25

crates/wallet/sdk/src/key_managers/backend.rs (1)

22-29: Well-designed trait extension.

The new cipher_seed_birthday method is properly documented and returns Option<u16> to support implementations that may not have birthday support. The error propagation through Self::Error is consistent with other trait methods.

crates/wallet/sdk/src/key_managers/local.rs (1)

62-63: Improved error message clarity.

The updated message "Key store error" more accurately describes the wrapped TKeyStoreErr type compared to the previous "Cipher error" message, reducing confusion with the separate CipherError type.

crates/wallet/sdk/src/models/account.rs (1)

8-8: LGTM! Account struct properly extended.

The birthday_epoch field and getter are correctly added to the Account struct with proper type imports.

Also applies to: 21-21, 43-45

crates/wallet/sdk/src/local_key_store.rs (1)

72-75: Clean implementation of cipher_seed_birthday.

The implementation correctly retrieves the cipher seed and extracts its birthday value, with appropriate error propagation.

crates/wallet/sdk/src/storage/writer.rs (1)

10-10: Breaking API change - signature extended appropriately.

The accounts_insert method now requires a birthday_epoch parameter, which aligns with the Account model extension. This is a necessary breaking change for the epoch birthday feature.

Also applies to: 93-104

crates/p2p/src/block_sync.rs (1)

8-8: Type rename applied correctly.

The import and return type are updated to use the renamed SubstateCreate type. The method logic remains unchanged.

Also applies to: 63-68

crates/wallet/storage_sqlite/tests/accounts.rs (1)

6-6: Test updated for new API signature.

The test correctly passes Epoch::zero() to match the updated accounts_insert signature.

Also applies to: 22-33

applications/tari_indexer/src/storage_sqlite/models/utxo.rs (1)

20-20: UTXO models extended with epoch field.

The epoch field is correctly added to all UTXO record structs:

  • Optional in UtxoRecordUpdate for partial updates
  • Required in UtxoRecordInsert and UtxoRecord for new/stored records

The epoch field is appropriately not used in the conversion methods since it's metadata for scanning/filtering rather than part of the UTXO content.

Also applies to: 40-40, 57-57

applications/tari_indexer/src/network_state_sync/worker.rs (1)

415-415: LGTM! Epoch parameter correctly threaded through UTXO updates.

The msg_epoch is properly extracted from the message (lines 375-380) with validation, and is now correctly passed to batch_insert_utxo_updates to align with the updated API signature.

crates/wallet/sdk/src/network.rs (1)

64-70: LGTM! Trait signature properly updated for epoch filtering.

The addition of the from_epoch parameter to stream_stealth_utxo_updates is correctly placed and aligns with the epoch-based UTXO scanning feature.

applications/tari_walletd/src/main.rs (1)

95-104: Verify epoch 0 birthday limitation doesn't cause UTXO scanning issues.

Based on the relevant code snippet from account.rs, the calculate_birthday_epoch() implementation returns a hardcoded Epoch(0) with a TODO comment. This aligns with the PR description's note about hardcoding a zero-epoch time. However, this could lead to:

  • Scanning extra history if epochs have progressed beyond 0
  • Missing UTXOs if the epoch timing assumptions are incorrect

Please verify that starting from epoch 0 is acceptable for the current network state, or if this needs immediate follow-up work before release.

crates/storage/src/consensus_models/substate.rs (2)

274-289: LGTM! Type renames improve clarity.

The refactoring from SubstateCreatedProofSubstateCreate and SubstateDestroyedProofSubstateDestroy is consistent throughout the codebase (as evidenced by the conversions in crates/p2p/src/conversions/rpc.rs).


394-462: LGTM! Enum and trait implementations properly updated.

All references to the renamed types have been correctly updated, including the enum variants, the as_create method, the From implementation, and the Display trait.

applications/tari_indexer/src/storage_sqlite/writer.rs (3)

117-121: LGTM! Epoch parameter correctly added to UTXO batch updates.

The new epoch parameter extends the method signature appropriately and will be threaded through the insert/update logic below.


131-149: LGTM! Epoch persisted for unspent UTXOs.

The epoch value is correctly converted and stored in the UtxoRecordInsert struct at line 140.


151-170: LGTM! Epoch persisted for spent UTXOs.

The epoch value is correctly wrapped in Some() and stored in the UtxoRecordUpdate struct at line 155, maintaining consistency with the update pattern.

applications/tari_walletd/src/lib.rs (2)

95-102: LGTM! Birthday epoch correctly integrated into account recovery.

The cipher seed birthday is properly retrieved and passed to AccountRecoveryService, enabling epoch-aware UTXO scanning during account recovery.


199-202: LGTM! Birthday epoch correctly passed to SDK initialization.

The epoch birthday is properly obtained from the helper function and passed to WalletSdk::initialize.

applications/tari_indexer/src/storage_sqlite/reader.rs (3)

519-527: LGTM! Method signature properly updated for epoch filtering.

The addition of from_epoch parameter and the return type change to UtxoStateUpdateSet align with the epoch-aware UTXO scanning feature.


531-544: LGTM! Epoch filter correctly applied to query.

The epoch filter at line 534 using .ge() (greater than or equal) correctly implements "from epoch" semantics, allowing UTXOs from the specified epoch onwards.


551-570: LGTM! Max epoch tracking and return structure properly implemented.

The max_epoch is tracked alongside max_state_version and correctly included in the returned UtxoStateUpdateSet structure. The epoch extraction from the row at line 558 and the max calculation at line 561 follow the same pattern as the state version tracking.

applications/tari_indexer/src/substate_manager.rs (1)

108-128: LGTM! Method signature and delegation properly updated.

The get_utxo_updates method correctly threads the new from_epoch parameter through to the underlying store transaction and returns the updated UtxoStateUpdateSet type. The changes are consistent with the broader epoch filtering feature.

crates/state_store_rocksdb/src/reader.rs (1)

1622-1645: Rename to SubstateCreate/SubstateDestroy wired correctly

Construction of SubstateUpdateProof::{Create,Destroy} with the new SubstateCreate/SubstateDestroy looks consistent with value_filter and SubstateData fields. No functional concerns here.

crates/storage/src/consensus_models/block.rs (1)

56-56: Type rename propagation looks good; receipts now return SubstateCreate

  • SubstateUpdateProof::{Create,Destroy} now carry SubstateCreate/SubstateDestroy consistently.
  • get_transaction_receipts() returning Vec is coherent with downstream uses.

Please confirm p2p/rpc and SQL writer paths were updated to persist/read is_up and value_hash from the new types (e.g., applications/tari_indexer/.../writer.rs). Based on learnings.

Also applies to: 66-66, 800-815, 825-846

applications/tari_indexer/src/store.rs (1)

175-180: Epoch threading on write path

Adding epoch: Epoch to batch_insert_utxo_updates is aligned with the read API. Validate that writers persist epoch and that max_epoch is computed when building UtxoStateUpdateSet.

crates/wallet/sdk/tests/support/harness.rs (1)

52-60: Verify EpochBirthday test parameters: u64::MAX forces all epochs to zero

The parameters are semantically correct but unconventional. The rel_zero_epoch_secs: u64::MAX is safe—epoch calculations use saturating_sub to prevent underflow. However, with any realistic timestamp < u64::MAX, all subtractions saturate to 0, making every epoch calculate as Epoch(0), which appears intentional given the explicit Epoch::zero() passed to add_account.

Confirm whether forcing all epochs to zero is the intended test behavior or if rel_zero_epoch_secs should use a realistic Minotari-epoch-relative timestamp (e.g., genesis time or current time offset).

Also applies to: 71-74, 200-206

crates/wallet/sdk/src/models/epoch_birthday.rs (6)

1-10: LGTM: Imports and constants are appropriate.

The imports and constant definition are clean and well-structured.


11-19: LGTM: Well-designed struct with appropriate safeguards.

The use of NonZeroU64 for epoch_time_secs prevents division-by-zero errors in epoch calculations. The documentation appropriately warns about potential inaccuracies due to network conditions.


38-40: LGTM: Simple getter.


42-48: Verify that silently returning 0 is the desired behavior for all error cases.

This method returns 0 when:

  1. System time calculations fail (.ok() on Line 45)
  2. Subtraction underflows (.and_then(|t| t.as_secs().checked_sub(...)) on Line 46)

While returning 0 for underflow is intentional (as noted in Line 58's comment about saturating_sub), system time failures might indicate actual problems (e.g., incorrect system clock) that should not be silently ignored. Consider whether logging or different handling is appropriate for system time errors versus intentional underflow cases.


50-66: LGTM: Epoch calculation logic is sound.

The use of saturating_sub in Line 59 appropriately handles cases where rel_zero_epoch_secs is in the future (returning epoch zero), and the comment clearly explains the rationale. The division on Line 64 is protected from divide-by-zero through the NonZeroU64 type.


85-124: LGTM: Comprehensive test coverage.

The tests appropriately cover the various epoch calculation methods with clear assertions and test data.

crates/p2p/src/conversions/rpc.rs (4)

11-19: LGTM: Import statements correctly updated.

The imports now reference SubstateCreate and SubstateDestroy, properly reflecting the type rename.


26-46: LGTM: SubstateCreate conversions are correct.

The TryFrom and From implementations properly handle the type rename with appropriate error handling and field mapping.


48-66: LGTM: SubstateDestroy conversions are correct.

The bidirectional conversions properly handle substate_id byte serialization/deserialization and version field mapping.


68-89: LGTM: SubstateUpdateProof correctly uses renamed types.

The TryFrom and From implementations for SubstateUpdateProof properly delegate to the SubstateCreate and SubstateDestroy conversions, maintaining consistency with the type rename.

Comment thread applications/tari_indexer/src/store.rs
Comment thread applications/tari_walletd/src/lib.rs
Comment thread crates/storage_sqlite/src/sqlite_db_factory.rs Outdated
Comment thread crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs
Comment thread crates/wallet/sdk/src/models/account.rs
Comment thread crates/wallet/sdk/src/models/epoch_birthday.rs Outdated
Comment thread crates/wallet/storage_sqlite/src/models/account.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a474ad9 and ff36589.

📒 Files selected for processing (3)
  • crates/storage_sqlite/src/sqlite_db_factory.rs (2 hunks)
  • crates/wallet/sdk/src/models/account.rs (4 hunks)
  • crates/wallet/sdk/src/models/epoch_birthday.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/wallet/sdk/src/models/account.rs
🧰 Additional context used
🧬 Code graph analysis (2)
crates/wallet/sdk/src/models/epoch_birthday.rs (3)
bindings/src/types/Epoch.ts (1)
  • Epoch (3-3)
crates/wallet/sdk/src/apis/key_manager.rs (1)
  • new (55-69)
crates/wallet/sdk/src/local_key_store.rs (1)
  • new (27-37)
crates/storage_sqlite/src/sqlite_db_factory.rs (1)
crates/storage_sqlite/src/sqlite_transaction.rs (1)
  • connection (46-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: check nightly
  • GitHub Check: check stable
  • GitHub Check: test
  • GitHub Check: machete
  • GitHub Check: clippy
  • GitHub Check: fmt
🔇 Additional comments (4)
crates/storage_sqlite/src/sqlite_db_factory.rs (4)

23-27: LGTM!

The import changes appropriately support the refactored path handling and directory creation logic.


41-44: LGTM!

The rename from data_dir to db_path better conveys that this field stores the complete database file path rather than just a directory.


47-52: LGTM!

The generic AsRef<Path> parameter is idiomatic and provides flexibility for callers to pass various path types.


55-59: Parent directory handling improved.

The if let Some(parent) pattern correctly addresses the previous review concern about panicking when db_path has no parent. However, verify that silently skipping directory creation when there's no parent (e.g., for a bare filename like "db.sqlite") aligns with the intended behavior - SQLite will attempt to create the file in the current working directory in such cases.

details: format!("Failed to create parent directory for database file: {}", e),
})?;
}
let database_url = self.db_path.to_str().expect("database_url utf-8 error");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle non-UTF-8 paths gracefully instead of panicking.

The .expect() call on to_str() will panic if db_path contains invalid UTF-8 sequences. While uncommon, non-UTF-8 paths are possible on some systems (particularly Unix).

Consider returning a proper error instead:

-        let database_url = self.db_path.to_str().expect("database_url utf-8 error");
+        let database_url = self.db_path.to_str().ok_or_else(|| StorageError::General {
+            details: "Database path contains invalid UTF-8 characters".to_string(),
+        })?;
🤖 Prompt for AI Agents
In crates/storage_sqlite/src/sqlite_db_factory.rs around line 60, replace the
panic-causing to_str().expect(...) call with a non-panicking conversion and
return an error on failure: detect if the path cannot be represented as UTF-8
and return a Result::Err with a clear error variant (or map into the function's
existing error type) instead of panicking; alternatively use to_string_lossy()
if accepting lossy conversion is acceptable, but prefer returning a descriptive
error (e.g., InvalidDatabasePath) so callers can handle non-UTF-8 paths
gracefully.

@sdbondi
sdbondi merged commit 68461ad into tari-project:development Nov 6, 2025
11 of 12 checks passed
@sdbondi
sdbondi deleted the cipher-seed-birthday branch November 6, 2025 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants