fix(watch-only): make AddressCache::new fallible and replace panics with typed errors #931
Conversation
1938768 to
d3b758a
Compare
ac22dcc to
ad12323
Compare
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 |
|
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? |
i missed this acknowledging my mistake. |
Yes, Im not certain what will be discarded but for sure the error handling for the AddressCache is desirable.
Yes, but only if you think its proper. |
i willl expand this with the full lib.rs error handling changes. |
Notable changes on 2e98ef2
Removed all poisoned lock panics in public methods errors are now propagated instead.
Removed remaining unwraps in also the pr desc is changed accordingly. |
2e98ef2 to
0eca4c5
Compare
0eca4c5 to
7b63b7a
Compare
| let inner = self | ||
| .inner | ||
| .read() | ||
| .map_err(|_| WatchOnlyError::PoisonedLock)?; |
There was a problem hiding this comment.
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()?
There was a problem hiding this comment.
yeah addedread_inner / write_innerhelpers, same pattern as memory_database already had.
| let mut inner = self | ||
| .inner | ||
| .write() | ||
| .map_err(|_| WatchOnlyError::PoisonedLock)?; |
There was a problem hiding this comment.
|_| 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?
There was a problem hiding this comment.
i think poisonError doesnt carry call site info, just the guard backtrace gives the location. same pattern in memory_database.rs
7b63b7a to
680d48c
Compare
|
It appears that the second commit is overwriting the first one. |
squashing into one commit! |
680d48c to
f804844
Compare
2cc4af9 to
3c15243
Compare
3c15243 to
c606086
Compare
|
Needs rebase |
c606086 to
8e0547d
Compare
rebased! |
…ith typed errors Add proper error handling for save, update, and lock operations in AddressCache.
8e0547d to
8c4581a
Compare
| let balance = self | ||
| .address_cache | ||
| .get_address_balance(&script_hash) | ||
| .map_err(|e| super::error::Error::Blockchain(Box::new(e)))?; |
There was a problem hiding this comment.
You could just import Error::Blockchain, and if possible, it would be better to add automatic handling using the impl_error_from trait here.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
I think passing FromSliceError as an InvalidTxid error may be wrong, because FromSliceError is not exclusive to txid.
There was a problem hiding this comment.
will remove the variant and used expect instead.
Description and Notes
Closes part of #463
AddressCache::newandAddressCacheInner::newpreviously panicked on database load failures. This PR makes both fallible.While at it the
AddressCacheDatabasetrait’ssave()andupdate()methods were made fallible too they were silently panicking inside implementations.What changed
AddressCacheDatabase::save()andupdate()now returnResult<(), Self::Error>WatchOnlyErrorvariants:PoisonedLock,CachedAddressNotFound,IndexOutOfBoundsexpect("poisoned lock")on theRwLocknow propagate viamap_err(|_| WatchOnlyError::PoisonedLock)?maybe_derive_addressesmade fallible and now propagates errors instead of swallowing themkv_database.rs: fixed three bare unwraps (item.value(),serde_json::to_vec,Txid::from_slice), addedInvalidTxidvariantmemory_database.rs:get_transactionwas returningPoisonedLockwhen tx wasn’t found — fixed toTransactionNotFoundflorestad.rs,json_rpc/server.rs,json_rpc/blockchain.rs,electrum_protocol.rsVerification
new_returns_err_when_database_load_failstriggers a real failure by writing invalid bytes directly into the KV bucket (no stub).