Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Commit

Permalink
Merge branch 'master' into legacybc
Browse files Browse the repository at this point in the history
  • Loading branch information
winsvega authored Nov 4, 2019
2 parents 78bf588 + 57b8156 commit 2608720
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 436 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Added: [#5752](https://github.com/ethereum/aleth/pull/5752) [#5753](https://github.com/ethereum/aleth/pull/5753) Implement EIP1380 (reduced gas costs for call-to-self).
- Changed: [#5801](https://github.com/ethereum/aleth/pull/5801) "testeth -t BlockchainTests" command now doesn't run the tests for the forks before Istanbul. To run those tests use a separate LegacyTests suite with command "testeth -t LegacyTests/Constantinople/BlockchainTests"
- Removed: [#5760](https://github.com/ethereum/aleth/pull/5760) Official support for Visual Studio 2015 has been dropped. Compilation with this compiler is expected to stop working after migration to C++14.
- Removed: [#5760](https://github.com/ethereum/aleth/pull/5760) Official support for Visual Studio 2015 has been dropped. Compilation with this compiler is expected to stop working after migration to C++14.
- Fixed: [#5792](https://github.com/ethereum/aleth/pull/5792) Faster and cheaper execution of RPC functions which query blockchain state (e.g. getBalance).

## [1.7.0] - Unreleased

Expand Down
523 changes: 262 additions & 261 deletions libdevcore/FixedHash.h

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions libethcore/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ DEV_SIMPLE_EXCEPTION(UnknownError);

DEV_SIMPLE_EXCEPTION(InvalidDatabaseKind);
DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen);
DEV_SIMPLE_EXCEPTION(DatabaseCorruption);

DEV_SIMPLE_EXCEPTION(DAGCreationFailure);
DEV_SIMPLE_EXCEPTION(DAGComputeFailure);

Expand Down
67 changes: 38 additions & 29 deletions libethereum/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,47 +136,56 @@ void Block::noteChain(BlockChain const& _bc)
}
}

PopulationStatistics Block::populateFromChain(BlockChain const& _bc, h256 const& _h, ImportRequirements::value _ir)
void Block::populateFromChain(BlockChain const& _bc, h256 const& _h)
{
noteChain(_bc);

PopulationStatistics ret { 0.0, 0.0 };

if (!_bc.isKnown(_h))
{
// Might be worth throwing here.
cwarn << "Invalid block given for state population: " << _h;
BOOST_THROW_EXCEPTION(BlockNotFound() << errinfo_target(_h));
}

auto b = _bc.block(_h);
BlockHeader bi(b); // No need to check - it's already in the DB.
if (bi.number())
auto const& blockBytes = _bc.block(_h);

// Set block headers
auto const blockHeader = BlockHeader{blockBytes};
m_currentBlock = blockHeader;

if (blockHeader.number())
m_previousBlock = _bc.info(blockHeader.parentHash());
else
m_previousBlock = m_currentBlock;

// Set state root and precommit state
//
// First check for database corruption by looking up the state root in the state database. Note
// that we don't technically need to do this since if the state DB is corrupt setting a new
// state root will throw anyway, but checking here enables us to log a user-friendly error
// message.
if (m_state.db().lookup(blockHeader.stateRoot()).empty())
{
// Non-genesis:

// 1. Start at parent's end state (state root).
BlockHeader bip(_bc.block(bi.parentHash()));
sync(_bc, bi.parentHash(), bip);

// 2. Enact the block's transactions onto this state.
m_author = bi.author();
Timer t;
auto vb = _bc.verifyBlock(&b, function<void(Exception&)>(), _ir | ImportRequirements::TransactionBasic);
ret.verify = t.elapsed();
t.restart();
enact(vb, _bc);
ret.enact = t.elapsed();
cerr << "Unable to populate block " << blockHeader.hash() << " - state root "
<< blockHeader.stateRoot() << " not found in database.";
cerr << "Database corrupt: contains block without state root: " << blockHeader;
cerr << "Try rescuing the database by running: eth --rescue";
BOOST_THROW_EXCEPTION(InvalidStateRoot() << errinfo_target(blockHeader.stateRoot()));
}
else

m_state.setRoot(blockHeader.stateRoot());
m_precommit = m_state;

RLP blockRLP{blockBytes};
auto const& txListRLP = blockRLP[1];
for (auto const& txRLP : txListRLP)
{
// Genesis required:
// We know there are no transactions, so just populate directly.
m_state = State(m_state.accountStartNonce(), m_state.db(), BaseState::Empty); // TODO: try with PreExisting.
sync(_bc, _h, bi);
m_transactions.push_back(Transaction{txRLP.data(), CheckTransaction::None});
m_transactionSet.insert(m_transactions.back().sha3());
}
m_receipts = _bc.receipts(_h).receipts;

return ret;
m_author = blockHeader.author();

m_committedToSeal = false;
m_sealEngine = _bc.sealEngine();
}

bool Block::sync(BlockChain const& _bc)
Expand Down
8 changes: 1 addition & 7 deletions libethereum/Block.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ class TransactionQueue;
struct VerifiedBlockRef;
class LastBlockHashesFace;

struct PopulationStatistics
{
double verify;
double enact;
};

DEV_SIMPLE_EXCEPTION(ChainOperationWithUnknownBlockChain);
DEV_SIMPLE_EXCEPTION(InvalidOperationOnSealedBlock);

Expand Down Expand Up @@ -190,7 +184,7 @@ class Block
// State-change operations

/// Construct state object from arbitrary point in blockchain.
PopulationStatistics populateFromChain(BlockChain const& _bc, h256 const& _hash, ImportRequirements::value _ir = ImportRequirements::None);
void populateFromChain(BlockChain const& _bc, h256 const& _hash);

/// Execute a given transaction.
/// This will append @a _t to the transaction list and change the state accordingly.
Expand Down
65 changes: 36 additions & 29 deletions libethereum/BlockChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,71 +194,78 @@ void BlockChain::init(ChainParams const& _p)

unsigned BlockChain::open(fs::path const& _path, WithExisting _we)
{
fs::path path = _path.empty() ? db::databasePath() : _path;
fs::path chainPath = path / fs::path(toHex(m_genesisHash.ref().cropped(0, 4)));
fs::path extrasPath = chainPath / fs::path(toString(c_databaseVersion));
auto const path = _path.empty() ? db::databasePath() : _path;
auto const chainPath = path / fs::path(toHex(m_genesisHash.ref().cropped(0, 4)));
auto const chainSubPathBlocks = chainPath / fs::path("blocks");
auto const extrasPath = chainPath / fs::path(toString(c_databaseVersion));
auto const extrasSubPathExtras = extrasPath / fs::path("extras");
unsigned lastMinor = c_minorProtocolVersion;

if (db::isDiskDatabase())
{
fs::create_directories(extrasPath);
DEV_IGNORE_EXCEPTIONS(fs::permissions(extrasPath, fs::owner_all));

bytes status = contents(extrasPath / fs::path("minor"));
auto const extrasSubPathMinor = extrasPath / fs::path("minor");
bytes const status = contents(extrasSubPathMinor);
if (!status.empty())
DEV_IGNORE_EXCEPTIONS(lastMinor = (unsigned)RLP(status));
if (c_minorProtocolVersion != lastMinor)
{
cnote << "Killing extras database (DB minor version:" << lastMinor << " != our miner version: " << c_minorProtocolVersion << ").";
cnote << "Killing extras database " << extrasPath << " (DB minor version:" << lastMinor
<< " != our minor version: " << c_minorProtocolVersion << ").";
DEV_IGNORE_EXCEPTIONS(fs::remove_all(extrasPath / fs::path("details.old")));
fs::rename(extrasPath / fs::path("extras"), extrasPath / fs::path("extras.old"));
fs::rename(extrasSubPathExtras, extrasPath / fs::path("extras.old"));
fs::remove_all(extrasPath / fs::path("state"));
writeFile(extrasPath / fs::path("minor"), rlp(c_minorProtocolVersion));
writeFile(extrasSubPathMinor, rlp(c_minorProtocolVersion));
lastMinor = (unsigned)RLP(status);
}

if (_we == WithExisting::Kill)
{
cnote << "Killing blockchain & extras database (WithExisting::Kill).";
fs::remove_all(chainPath / fs::path("blocks"));
fs::remove_all(extrasPath / fs::path("extras"));
cnote << "Killing blockchain (" << chainSubPathBlocks << ") & extras ("
<< extrasSubPathExtras << ") databases (WithExisting::Kill).";
fs::remove_all(chainSubPathBlocks);
fs::remove_all(extrasSubPathExtras);
}
}

try
{
m_blocksDB = db::DBFactory::create(chainPath / fs::path("blocks"));
m_extrasDB = db::DBFactory::create(extrasPath / fs::path("extras"));
m_blocksDB = db::DBFactory::create(chainSubPathBlocks);
m_extrasDB = db::DBFactory::create(extrasSubPathExtras);
}
catch (db::DatabaseError const& ex)
{
// Check the exact reason of errror, in case of IOError we can display user-friendly message
if (*boost::get_error_info<db::errinfo_dbStatusCode>(ex) != db::DatabaseStatus::IOError)
throw;
// Determine which database open call failed
auto const dbPath = !m_blocksDB.get() ? chainSubPathBlocks : extrasSubPathExtras;
cerror << "Error opening database: " << dbPath;

if (db::isDiskDatabase())
{
if (fs::space(chainPath / fs::path("blocks")).available < 1024)
db::DatabaseStatus const dbStatus = *boost::get_error_info<db::errinfo_dbStatusCode>(ex);
if (fs::space(path).available < 1024)
{
cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing.";
cerror << "Not enough available space found on hard drive. Please free some up and "
"re-run.";
BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace());
}
else
else if (dbStatus == db::DatabaseStatus::Corruption)
{
cerror << "Database corruption detected. Please see the exception for corruption "
"details. Exception: "
<< ex.what();
BOOST_THROW_EXCEPTION(DatabaseCorruption());
}
else if (dbStatus == db::DatabaseStatus::IOError)
{
cwarn <<
"Database " <<
(chainPath / fs::path("blocks")) <<
"or " <<
(extrasPath / fs::path("extras")) <<
"already open. You appear to have another instance of ethereum running. Bailing.";
cerror << "Database already open. You appear to have another instance of Aleth running.";
BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
}
}
else
{
cwarn << "Unknown database error occurred during in-memory database creation";
throw;
}

cerror << "Unknown error occurred. Exception details: " << ex.what();
throw;
}

if (_we != WithExisting::Verify && !details(m_genesisHash))
Expand Down
52 changes: 26 additions & 26 deletions libethereum/ChainParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,32 @@ class SealEngineFace;

struct ChainParams: public ChainOperationParams
{
ChainParams();
ChainParams(ChainParams const& /*_org*/) = default;
ChainParams(std::string const& _s, h256 const& _stateRoot = h256());
ChainParams(bytes const& _genesisRLP, AccountMap const& _state) { populateFromGenesis(_genesisRLP, _state); }
ChainParams(std::string const& _json, bytes const& _genesisRLP, AccountMap const& _state): ChainParams(_json) { populateFromGenesis(_genesisRLP, _state); }

SealEngineFace* createSealEngine();

/// Genesis params.
h256 parentHash = h256();
Address author = Address();
u256 difficulty = 1;
u256 gasLimit = 1 << 31;
u256 gasUsed = 0;
u256 timestamp = 0;
bytes extraData;
mutable h256 stateRoot; ///< Only pre-populate if known equivalent to genesisState's root. If they're different Bad Things Will Happen.
AccountMap genesisState;

unsigned sealFields = 0;
bytes sealRLP;

h256 calculateStateRoot(bool _force = false) const;

/// Genesis block info.
bytes genesisBlock() const;
ChainParams();
ChainParams(ChainParams const& /*_org*/) = default;
ChainParams(std::string const& _s, h256 const& _stateRoot = h256());
ChainParams(bytes const& _genesisRLP, AccountMap const& _state) { populateFromGenesis(_genesisRLP, _state); }
ChainParams(std::string const& _json, bytes const& _genesisRLP, AccountMap const& _state): ChainParams(_json) { populateFromGenesis(_genesisRLP, _state); }

SealEngineFace* createSealEngine();

/// Genesis params.
h256 parentHash = h256();
Address author = Address();
u256 difficulty = 1;
u256 gasLimit = 1 << 31;
u256 gasUsed = 0;
u256 timestamp = 0;
bytes extraData;
mutable h256 stateRoot; ///< Only pre-populate if known equivalent to genesisState's root. If they're different Bad Things Will Happen.
AccountMap genesisState;

unsigned sealFields = 0;
bytes sealRLP;

h256 calculateStateRoot(bool _force = false) const;

/// Genesis block info.
bytes genesisBlock() const;

/// load config
ChainParams loadConfig(std::string const& _json, h256 const& _stateRoot = {},
Expand Down
26 changes: 4 additions & 22 deletions libethereum/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,37 +759,19 @@ void Client::prepareForTransaction()
startWorking();
}

Block Client::block(h256 const& _block) const
Block Client::block(h256 const& _blockHash) const
{
try
{
Block ret(bc(), m_stateDB);
ret.populateFromChain(bc(), _block);
return ret;
}
catch (Exception& ex)
{
ex << errinfo_block(bc().block(_block));
onBadBlock(ex);
return Block(bc());
}
}

Block Client::block(h256 const& _blockHash, PopulationStatistics* o_stats) const
{
try
{
Block ret(bc(), m_stateDB);
PopulationStatistics s = ret.populateFromChain(bc(), _blockHash);
if (o_stats)
swap(s, *o_stats);
Block ret{bc(), m_stateDB};
ret.populateFromChain(bc(), _blockHash);
return ret;
}
catch (Exception& ex)
{
ex << errinfo_block(bc().block(_blockHash));
onBadBlock(ex);
return Block(bc());
return Block{bc()};
}
}

Expand Down
4 changes: 0 additions & 4 deletions libethereum/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ class Client: public ClientBase, protected Worker
/// Get the gas bid price
u256 gasBidPrice() const override { return m_gp->bid(); }

// [PRIVATE API - only relevant for base clients, not available in general]
/// Get the block.
dev::eth::Block block(h256 const& _blockHash, PopulationStatistics* o_stats) const;

/// Get the object representing the current state of Ethereum.
dev::eth::Block postState() const { ReadGuard l(x_postSeal); return m_postSeal; }
/// Get the object representing the current canonical blockchain.
Expand Down
Loading

0 comments on commit 2608720

Please sign in to comment.