When loading the wallet, display the entire path in error messages, instead of the name (which, for the default wallet, is the empty string.)
When an exception occurs during wallet loading, display e.what() if possible, instead of nothing.
When loading the wallet, display the entire path in error messages, instead of the name (which, for the default wallet, is the empty string.)
When an exception occurs during wallet loading, display e.what() if possible, instead of nothing.
4096 | @@ -4097,7 +4097,7 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b 4097 | 4098 | std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags) 4099 | { 4100 | - const std::string& walletFile = location.GetName(); 4101 | + const std::string& walletFile = (location.GetName() == "" ? "[default wallet]" : location.GetName());
const std::string& log_wallet_name = (location.GetName() == "" ? "[default wallet]" : location.GetName());
nit: I'd feel more safe if this was renamed to log_wallet_name
alternatively, why not just have [default wallet] be the thing set in the constructor for WalletLocation and just remove the need for this special casing?
const std::string& walletFile = location.GetName().empty() ? "[default wallet]" : location.GetName();
that makes sense, I will do that.
I was uncomfortable with modifying it in WalletLocation because I don't fully understand all the uses that the 'wallet name' is put to, and it seems like sometimes it's used as a path/filename.
Done.
428 | + strErr = e.what(); 429 | + } 430 | + return false; 431 | } catch (...) 432 | { 433 | + if (strErr == "") {
if (strErr.empty()) {
Done.
421 | @@ -422,8 +422,17 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, 422 | strType != "minversion" && strType != "acentry") { 423 | wss.m_unknown_records++; 424 | } 425 | + } catch (const std::exception& e) 426 | + { 427 | + if (strErr == "") {
if (strErr.empty()) {
Done.
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
No conflicts as of last run.
tACK e5637b1
I now get a flood of this with one my broken wallets:
2019-02-27T08:32:30Z [default wallet] CDataStream::read(): end of data: unspecified iostream_category error
2019-02-27T08:32:30Z [default wallet] CDataStream::read(): end of data: unspecified iostream_category error
2019-02-27T08:32:30Z [default wallet] CDataStream::read(): end of data: unspecified iostream_category error
@Sjors Yep, that's the same thing I get -- at least in my case, each of those is a 'keymeta' entry, whose value is missing the final has_key_origin field of CKeyMetaData.
I think the flood of log entries is definitely better than the lack of any, although the volume is a little annoying (but I think it makes sense when encountering a broken wallet file to be verbose about it.)
It's fine. This is the type of error that should really never happen in the real world, so indeed when it does, the more information the better.
@Sjors frankly these type of changes are mostly for developer's sanity. I've run into similar issues with wallet entries and felt compelled to upstream changes.
421 | @@ -422,8 +422,17 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, 422 | strType != "minversion" && strType != "acentry") { 423 | wss.m_unknown_records++; 424 | } 425 | + } catch (const std::exception& e)
nit, { here.
Fixed. It's annoying that the linter doesn't catch stuff like this. Then the wrong version can crop up in the code, and people like me can copy it. :-)
Does it make sense to commit some broken wallets to the repo?
The idea of committing a broken wallet as a test case makes sense to me, but (1) I seem to recall I've heard people say in past cases that committing a binary wallet file to the repo is not reasonable even as test data, and (2) I definitely don't know how to go about minimizing such a test case, which seems both necessary and painful.
Rebased.
Restarted travis job 6 - failed on commit 4e7fea2 with:
47/118 - rpc_psbt.py failed, Duration: 4 s
stdout:
2019-03-06T05:02:08.027000Z TestFramework (INFO): Initializing test directory /tmp/test_runner_₿_🏃_20190306_045534/rpc_psbt_69
2019-03-06T05:02:11.006000Z TestFramework (ERROR): Assertion failed
Traceback (most recent call last):
File "/home/travis/build/bitcoin/bitcoin/build/bitcoin-x86_64-unknown-linux-gnu/test/functional/test_framework/test_framework.py", line 175, in main
self.run_test()
File "/home/travis/build/bitcoin/bitcoin/build/bitcoin-x86_64-unknown-linux-gnu/test/functional/rpc_psbt.py", line 149, in run_test
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'])
File "/home/travis/build/bitcoin/bitcoin/build/bitcoin-x86_64-unknown-linux-gnu/test/functional/test_framework/util.py", line 105, in assert_raises_rpc_error
assert try_rpc(code, message, fun, *args, **kwds), "No exception raised"
AssertionError: No exception raised
Yeah, I think switching to absolute path would make sense. I assume I just need to switch from GetName to GetPath. Will try it out.
Switched to GetPath().string() instead of GetName(). Removed the rename to log_wallet_name, in the interest of minimizing the size of the diff, since it is once again a wallet file name. (I can reinstate the rename if preferred.)
Oh, no, this didn't do what I wanted at all. On further inspection of #15334, it doesn't actually log the absolute path, it just logs the filename, but more importantly it doesn't use WalletLocation::GetPath, but it has some other place it's getting this info. GetPath is giving me the wallet directory, excluding the filename, it seems.
Can someone clue me in to the exact semantics / interpretation of the name and path in WalletLocation? Can I just slap "wallet.dat" on the end of the output of GetPath and be good, or are there other cases?
I'd suggest adding a new method to the BerkeleyDatabase class:
+ fs::path DataFilePath() const { return env->Directory() / strFile; }
and printing the path with GetDBHandle().DataFilePath().string()
@ryanofsky I ended up taking a slightly different approach, because at this point we do not have a CWallet yet to get a db handle from (we are in the flow to open one.) Instead, I added a free function for normalizing paths.
(I could have accomplished the same thing without adding a function, by calling SplitWalletPath (but it's static, and a slightly weird interface for this) or GetWalletEnv (but it's a very weird interface for this, and also it manipulates g_dbenvs, which I don't know the consequences of and seems a little heavy-handed for just figuring out a path.)
Looks good if you s/wallet database file/data file path/ and s/FullWalletFilePath/WalletDataFilePath/.
I'd suggest:
/** Given a wallet directory path or legacy file path, return path to main data file in the wallet database. */
fs::path WalletDataFilePath(const fs::path& wallet_path);
Wallet databases are really directories, not files. At a low level, wallet databases include not just wallet.dat files but also write-ahead database/log.?????????? files. At the user level, the -wallet option and createwallet rpc create new wallets as directories, and the -rpcwallet option and getwalletinfo rpc use directory paths.
The only reason it makes sense to reference files instead of directories in log messages is to disambiguate in the legacy case where there can be multiple data files for different wallets stored in the same directory and sharing mixed log files. (This was a misfeature which is mostly removed, except we still support loading these wallets in the top level walletdir.)
Got it, thanks @ryanofsky , makes sense. Changed as suggested!
83 | @@ -84,6 +84,13 @@ bool IsWalletLoaded(const fs::path& wallet_path) 84 | return database && database->IsDatabaseLoaded(database_filename); 85 | } 86 | 87 | +fs::path WalletDataFilePath(const fs::path& wallet_path) {
nit, { should be in new line.
Curses, done.
I'm afraid my brain is stuck in the wrong style for life, sorry.
utACK 17d0114.
When loading the wallet, display the entire path in error messages, instead of
the name (which, for the default wallet, is the empty string.)
When an exception occurs during wallet loading, display e.what() if possible,
instead of nothing.