Skip to content

fix(watch-only): make AddressCache::new fallible and replace panics with typed errors #931

Open
Sandipmandal25 wants to merge 1 commit into
getfloresta:masterfrom
Sandipmandal25:fix/watch-only-new-fallible
Open

fix(watch-only): make AddressCache::new fallible and replace panics with typed errors #931
Sandipmandal25 wants to merge 1 commit into
getfloresta:masterfrom
Sandipmandal25:fix/watch-only-new-fallible

Conversation

@Sandipmandal25
Copy link
Copy Markdown
Contributor

@Sandipmandal25 Sandipmandal25 commented Apr 3, 2026

Description and Notes

Closes part of #463

AddressCache::new and AddressCacheInner::new previously panicked on database load failures. This PR makes both fallible.

While at it the AddressCacheDatabase trait’s save() and update() methods were made fallible too they were silently panicking inside implementations.

What changed

  • AddressCacheDatabase::save() and update() now return Result<(), Self::Error>
  • Added three new WatchOnlyError variants: PoisonedLock, CachedAddressNotFound, IndexOutOfBounds
  • All public methods that had expect("poisoned lock") on the RwLock now propagate via map_err(|_| WatchOnlyError::PoisonedLock)?
  • maybe_derive_addresses made fallible and now propagates errors instead of swallowing them
  • kv_database.rs: fixed three bare unwraps (item.value(), serde_json::to_vec, Txid::from_slice), added InvalidTxid variant
  • memory_database.rs: get_transaction was returning PoisonedLock when tx wasn’t found — fixed to TransactionNotFound
  • Updated call sites in florestad.rs, json_rpc/server.rs, json_rpc/blockchain.rs, electrum_protocol.rs

Verification

cargo test -p floresta-watch-only

new_returns_err_when_database_load_fails triggers a real failure by writing invalid bytes directly into the KV bucket (no stub).

Comment thread crates/floresta-watch-only/src/lib.rs Outdated
Comment thread crates/floresta-watch-only/src/lib.rs
@Davidson-Souza Davidson-Souza added the reliability Related to runtime reliability, stability and production readiness label Apr 7, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in Floresta Apr 7, 2026
@Davidson-Souza Davidson-Souza moved this from Backlog to Needs review in Floresta Apr 7, 2026
@Davidson-Souza Davidson-Souza added this to the Q2/2026 milestone Apr 7, 2026
@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch 3 times, most recently from 1938768 to d3b758a Compare April 7, 2026 21:37
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
Comment thread crates/floresta-electrum/src/electrum_protocol.rs Outdated
@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch 2 times, most recently from ac22dcc to ad12323 Compare April 8, 2026 20:33
@jaoleal
Copy link
Copy Markdown
Member

jaoleal commented Apr 13, 2026

Closes part of #463 and Competency Test for sob 2026 to be submitted along with proposal

Just to be clear that was my mistake, a competency test ideally should not be a PR. Thats what i wrote on our discord channel: https://discord.com/channels/1185232004506198056/1488947854612365353/1489335077769838685

@jaoleal
Copy link
Copy Markdown
Member

jaoleal commented Apr 13, 2026

When i started reading the code here i noticed that this is partially addressed on #804 but i have the intuition that it will be discarded, AFAIK the approach there was already reviewed and validated, maybe you could steal the code there and implement it here ? (That is, the error handling for the watch only interface)

@Sandipmandal25
Copy link
Copy Markdown
Contributor Author

When i started reading the code here i noticed that this is partially addressed on #804 but i have the intuition that it will be discarded, AFAIK the approach there was already reviewed and validated, maybe you could steal the code there and implement it here ? (That is, the error handling for the watch only interface)

hey @jaoleal when you say "it will be discarded" do you mean pr #804 ? also by "steal the code from #804" and should i just take the full lib.rs error handling changes from there?

@Sandipmandal25
Copy link
Copy Markdown
Contributor Author

Closes part of #463 and Competency Test for sob 2026 to be submitted along with proposal

Just to be clear that was my mistake, a competency test ideally should not be a PR. Thats what i wrote on our discord channel: https://discord.com/channels/1185232004506198056/1488947854612365353/1489335077769838685

i missed this acknowledging my mistake.

@jaoleal
Copy link
Copy Markdown
Member

jaoleal commented Apr 13, 2026

hey @jaoleal when you say "it will be discarded" do you mean pr #804 ?

Yes, Im not certain what will be discarded but for sure the error handling for the AddressCache is desirable.

also by "steal the code from #804" and should i just take the full lib.rs error handling changes from there?

Yes, but only if you think its proper.

@Sandipmandal25
Copy link
Copy Markdown
Contributor Author

hey @jaoleal when you say "it will be discarded" do you mean pr #804 ?

Yes, Im not certain what will be discarded but for sure the error handling for the AddressCache is desirable.

also by "steal the code from #804" and should i just take the full lib.rs error handling changes from there?

Yes, but only if you think its proper.

i willl expand this with the full lib.rs error handling changes.

@Sandipmandal25
Copy link
Copy Markdown
Contributor Author

Sandipmandal25 commented Apr 16, 2026

hey @jaoleal when you say "it will be discarded" do you mean pr #804 ?

Yes, Im not certain what will be discarded but for sure the error handling for the AddressCache is desirable.

also by "steal the code from #804" and should i just take the full lib.rs error handling changes from there?

Yes, but only if you think its proper.

Notable changes on 2e98ef2

save and update on AddressCacheDatabase now return Result.

Removed all poisoned lock panics in public methods errors are now propagated instead.

memory_database was returning the wrong error when a transaction was not found fixed.

Removed remaining unwraps in kv_database, better error handling overall.

also the pr desc is changed accordingly.

@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch from 2e98ef2 to 0eca4c5 Compare April 16, 2026 13:54
Comment thread crates/floresta-electrum/src/electrum_protocol.rs Outdated
@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch from 0eca4c5 to 7b63b7a Compare April 16, 2026 16:11
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
Comment on lines +759 to +762
let inner = self
.inner
.read()
.map_err(|_| WatchOnlyError::PoisonedLock)?;
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.

noticed this pattern repeat itself multiple times across your change..how about wrapping it for read and write ...so we can easily do a let inner = self.read()? or let inner = self.write()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah addedread_inner / write_innerhelpers, same pattern as memory_database already had.

Comment thread crates/floresta-watch-only/src/lib.rs Outdated
let mut inner = self
.inner
.write()
.map_err(|_| WatchOnlyError::PoisonedLock)?;
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.

|_| matches the PoisonError and throws it away...when this gets propagated upwards, what the user will see is Error: Poison Lock error...we cant't tell from which of the numerous call sites this was triggered from...WYT?

Copy link
Copy Markdown
Contributor Author

@Sandipmandal25 Sandipmandal25 Apr 18, 2026

Choose a reason for hiding this comment

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

i think poisonError doesnt carry call site info, just the guard backtrace gives the location. same pattern in memory_database.rs

@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch from 7b63b7a to 680d48c Compare April 18, 2026 09:32
@jaoleal
Copy link
Copy Markdown
Member

jaoleal commented Apr 20, 2026

It appears that the second commit is overwriting the first one.

@Sandipmandal25
Copy link
Copy Markdown
Contributor Author

It appears that the second commit is overwriting the first one.

squashing into one commit!

@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch from 680d48c to f804844 Compare April 20, 2026 20:56
@Sandipmandal25 Sandipmandal25 changed the title fix(watch-only): make AddressCache::new fallible fix(watch-only): make AddressCache::new fallible and replace panics with typed errors Apr 20, 2026
@Davidson-Souza Davidson-Souza mentioned this pull request Apr 21, 2026
Comment thread crates/floresta-watch-only/src/lib.rs
Comment thread crates/floresta-watch-only/src/lib.rs
Comment thread crates/floresta-watch-only/src/lib.rs
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch 2 times, most recently from 2cc4af9 to 3c15243 Compare April 29, 2026 14:24
Comment thread crates/floresta-watch-only/src/lib.rs Outdated
@luisschwab
Copy link
Copy Markdown
Member

Needs rebase

@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch from c606086 to 8e0547d Compare May 12, 2026 10:31
@Sandipmandal25
Copy link
Copy Markdown
Contributor Author

Needs rebase

rebased!

Comment thread crates/floresta-electrum/src/electrum_protocol.rs Outdated
Comment thread crates/floresta-electrum/src/electrum_protocol.rs Outdated
Comment thread crates/floresta-electrum/src/electrum_protocol.rs Outdated
…ith typed errors

Add proper error handling for save, update, and lock operations in AddressCache.
@Sandipmandal25 Sandipmandal25 force-pushed the fix/watch-only-new-fallible branch from 8e0547d to 8c4581a Compare May 13, 2026 17:10
let balance = self
.address_cache
.get_address_balance(&script_hash)
.map_err(|e| super::error::Error::Blockchain(Box::new(e)))?;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You could just import Error::Blockchain, and if possible, it would be better to add automatic handling using the impl_error_from trait here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Error::Blockchain takes a boxed trait object so impl_error_from wont work directly since it doesnt box. also the error type here is generic. do you have anything specific in mind or is just the import fine?

impl_error_from!(KvDatabaseError, serde_json::Error, SerdeJsonError);
impl_error_from!(KvDatabaseError, kv::Error, KvError);
impl_error_from!(KvDatabaseError, EncodingError, DeserializeError);
impl_error_from!(KvDatabaseError, FromSliceError, InvalidTxid);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think passing FromSliceError as an InvalidTxid error may be wrong, because FromSliceError is not exclusive to txid.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will remove the variant and used expect instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reliability Related to runtime reliability, stability and production readiness

Projects

Status: Needs review

Development

Successfully merging this pull request may close these issues.

6 participants