Return size of block (in bytes) from web3.eth.getBlock RPC function#5829
Return size of block (in bytes) from web3.eth.getBlock RPC function#5829halfalicious merged 9 commits intomasterfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## master #5829 +/- ##
==========================================
- Coverage 64.05% 64.02% -0.04%
==========================================
Files 362 364 +2
Lines 30903 30970 +67
Branches 3431 3434 +3
==========================================
+ Hits 19796 19828 +32
- Misses 9878 9918 +40
+ Partials 1229 1224 -5 |
|
Size returned for genesis block is still 0 bytes, need to investigate. |
33b6590 to
956528b
Compare
libethereum/BlockChain.cpp
Outdated
| fs::remove_all(chainSubPathBlocks); | ||
| fs::remove_all(extrasSubPathExtras); | ||
| LOG(m_loggerInfo) << "Deleting all databases. This will require a resync from genesis."; | ||
| fs::remove_all(chainPath); |
There was a problem hiding this comment.
I think here it was removing only blocks and extras because BlockChain class is responsible on only for these DB, and State is responsible for state.
I'd leave it without change for better separation of concertns.
(with this change there's at least a problem when it gets to State::openDB and logs Killing state database - that's not true anymore)
There was a problem hiding this comment.
Ah I see below that you did it to remove also extras.old, if it's there... Maybe better to remove existing extras.old in that case?
There was a problem hiding this comment.
@gumb0 I think we should leave extras.old (unless one explicitly specifies --kill) since there's the possibility of using it to restore your extras DB (if you know what you're doing), keeping it around gives the user the chance to do that.
libethereum/BlockChain.cpp
Outdated
| fs::create_directories(extrasPath); | ||
| DEV_IGNORE_EXCEPTIONS(fs::permissions(extrasPath, fs::owner_all)); | ||
|
|
||
| auto const extrasSubPathMinor = extrasPath / fs::path("minor"); |
There was a problem hiding this comment.
Perhaps make a constant out of "minor" as it's used in more that one place now
There was a problem hiding this comment.
@gumb0 I don't see where it's being used multiple times in a function?
There was a problem hiding this comment.
Ah, yes, most of the paths are used in both places...thought you were referring to within the same function. I can move them to anonymous namespace vars.
|
Need to also handle case of the minor version file not existing and the DB format changing |
|
Will squash some changes to clean up the commit history before merging |
1d5742b to
57a4c7d
Compare
|
Rebased to fix changelog merge conflict |
92f33b9 to
193c839
Compare
|
Also did a successful rebuild of ~2M blocks. |
libethereum/DatabasePaths.h
Outdated
| { | ||
| bool databasePathsSet(); | ||
| void setDatabasePaths(boost::filesystem::path const& _rootPath, h256 const& _genesisHash); | ||
| boost::filesystem::path rootPath(); |
There was a problem hiding this comment.
I think I would return const references from these, to avoid copying
There was a problem hiding this comment.
Somewhat confusing that we have db::databasePath() and now these. Should all these maybe better put into DBFactory.h?
There was a problem hiding this comment.
@gumb0 I considered that but DBFactory strikes me as more general purpose..it doesn’t include anything related to chains and such. Should I maybe rename the new namespace and files to something like BlockchainDatabasePaths to make the differences more clear?
There was a problem hiding this comment.
The namespace and files are fine, but then maybe it makes sense to move db::setDatabasePath to this file and/or merge with setDatabasePaths?
Isn't rootPath here basically the same as db::databasePath ?
There was a problem hiding this comment.
@gumb0 Yes, rootPath is the same as db::databasePath. After looking at this a little more I like your original suggestion of merging these together...I'll move the DatabasePaths functions out of that namespace and into the dev::db namespace.
|
Still need to merge DatabasePaths with dev::db |
gumb0
left a comment
There was a problem hiding this comment.
BlockChain and State shouldn't set the global data
libethereum/State.cpp
Outdated
|
|
||
| if (db::isDiskDatabase()) | ||
| { | ||
| db_paths::setDatabasePaths(_basePath, _genesisHash); |
There was a problem hiding this comment.
You call this from here and in BlockChain class, so it will be called at least twice, won't it?
Also it makes it impossible to have two instantces of State pointing to different databases.
It should rather be called once somewhere at the higher level (like main function or Client initialization).
There was a problem hiding this comment.
@gumb0 Yes, it will be called twice, thought that it was simpler this way rather than checking if it was already set and then only setting it in that case. I agree that setting the paths at a higher level makes sense.
For context, when would we ever have two State instances pointing to different databases?
There was a problem hiding this comment.
Maybe in tests, maybe nowhere, but it's one thing to set the global data once and then only read it in various places, but writing global data from various places just doesn't seem good practice - both from thread-safety perspective and from general complexity management perspective
99a1213 to
5d76fe6
Compare
|
Rebased to address CHANGELOG merge conflict |
|
Need to fix OpenDB test error |
libethereum/DatabasePaths.h
Outdated
| public: | ||
| DatabasePaths(boost::filesystem::path const& _rootPath, h256 const& _genesisHash) noexcept; | ||
| DatabasePaths() = default; | ||
| void setPaths(boost::filesystem::path const& _rootPath, h256 const& _genesisHash) noexcept; |
There was a problem hiding this comment.
I would make it immutable class, i.e. have only constructor without setter, and create another instance each time you need to reset the paths.
There was a problem hiding this comment.
@gumb0 I like the immutable idea, I went with the current approach since I was hesitant to use dynamic allocation for something trivial like paths. I can use unique_ptr and remove the default ctor + setter method which will effectively make the class immutable.
libethereum/DatabasePaths.h
Outdated
| DatabasePaths() = default; | ||
| void setPaths(boost::filesystem::path const& _rootPath, h256 const& _genesisHash) noexcept; | ||
| bool pathsSet() const noexcept; | ||
| boost::filesystem::path const& rootPath() noexcept; |
There was a problem hiding this comment.
these getters should be const methods
libethereum/State.cpp
Outdated
| fs::path(toString(c_databaseVersion)); | ||
| auto const statePath = chainPath / fs::path("state"); | ||
|
|
||
| DatabasePaths dbPaths{_basePath, _genesisHash}; |
libethereum/BlockChain.cpp
Outdated
|
|
||
| if (db::isDiskDatabase()) | ||
| { | ||
| if (!_path.empty()) |
There was a problem hiding this comment.
Ah I see, when we reopen?
Why is it needed, why can't you just use the path provided to reopen and just reset m_dbPaths in that case?
There was a problem hiding this comment.
@gumb0: We can, but that seems unnecessary if m_dbPaths is already set?
There was a problem hiding this comment.
You could then just
if (!m_dbPaths.pathsSet())
m_dbPaths.setPaths(_path, m_genesisHash);
But I would probably make it unique_ptr and
if (!m_dbPaths)
m_dbPaths = std::make_unique<DatabasePaths>(_path, m_genesisHash);
There was a problem hiding this comment.
@gumb0 unique_ptr makes sense, but I like the current behavior of only setting the path if the supplied path arg is empty since I think that's more intuitive, i.e. if I call a function and pass it an arg I expect that arg to be used and not silently dropped. What do you think?
There was a problem hiding this comment.
Makes sense, but I don't like the hidden features of the function interface, like magic value "empty path" meaning "use previous path".
How about instead of empty path calling it with the current path (as before) and then here:
if (!m_dbPaths || m_dbPaths.rootPath() != _path)
m_dbPaths = std::make_unique<DatabasePaths>(_path, m_genesisHash);
then it's kind of an optimization to not reset the paths when not needed. And in practice re-creation will never happen, because it's called with the same path only.
14e669d to
b23f049
Compare
| throw; | ||
| } | ||
|
|
||
| if (_we != WithExisting::Verify && !rebuildNeeded && !details(m_genesisHash)) |
There was a problem hiding this comment.
I can slightly streamline things by initializing rebuildNeeded to (_we == WithExisting::Verify) and then checking !rebuildNeeded here rather than also checking _we. This would also enable me to skip the minor version checks if rebuildNeeded == true. However, this file already has a ton of churn and this streamlining is pretty minor so I can take care of it in a future change.
gumb0
left a comment
There was a problem hiding this comment.
Please squash some commits before merging
Also expose this to RPC callers
Throw exception on rebuild failure, detect existence of temporary extras database and throw exception, only update database minor version file on successful rebuild
Remove individual directories in BlockChain::open on WithExisting::Kill and save genesis block details RLP in local variable before inserting into extras db. Untabify BlockDetails and pass ctor args by const& Cleanup web3.eth.getBlock* calls Make BlockDetails::blockSizeBytes a size_t instead of unsigned Minor formatting/logging changes (e.g. untabify BlockDetails files)
Case = minor version file not present but extras database exists. This should only happen if someone is upgrading to a release of Aleth which writes the minor version file, and this release will also have an extras database upgrade so require a rebuild.
New namespace is called dev::eth::database_paths. Also tweak BlockChain::open and BlockChain::rebuild so that BlockChain::m_dbPath is no longer needed, and set BlockDetails::size in BlockDetails::rlp(). Finally, remove unnecessary boost::filesystem::create_directories calls in BlockChain::open / State::openDB.
Remove misleading log messages when memoryDB is used Only set database paths if disk db is being used Remove unused exceptions
Required by one of the tests (BlockChainFrontierSuite/opendb)
Remove unnecessary static_cast when creating BlockDetails and change return values of DatabasePaths getters to const& Use const and noexcept where possible and move DatabasePaths from namespace to immutable class
97be029 to
cfe3ce7
Compare
|
Squashed a bunch of commits and rebased |
Fix #5797, #5814
Return the size of a block in bytes to calls to
web3.eth.getBlock. This requires extending theBlockDetailsstructure (by adding a newblockSizeBytesfield) which in turn requires incrementing the db minor version number (sinceBlockDetailsare stored in the Extras database) which triggers an automatic database rebuild (which can take a while depending on how many blocks are in your local chain).I've also made some minor changes to the database rebuild code to handle edge cases:
Tested changes by calling web3.eth.getBlock with the following block numbers and comparing the results against Etherscan: 0, 1, 65001 (3 txs), 101146 (2 txs), 109424 (1 tx), 115367 (7 txs)