mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
First draft at splitting State.
Continuation of State split. libethereum building again. Compile fixes galore. Remove a lot of code redundancy. mix using new state/block classes
This commit is contained in:
parent
fbe4ce37a0
commit
e0863fbd27
128
TestHelper.cpp
128
TestHelper.cpp
@ -64,7 +64,7 @@ void connectClients(Client& c1, Client& c2)
|
||||
void mine(State& s, BlockChain const& _bc)
|
||||
{
|
||||
std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
|
||||
s.commitToMine(_bc);
|
||||
s.commitToSeal(_bc);
|
||||
Notified<bytes> sealed;
|
||||
sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
|
||||
sealer->generateSeal(s.info());
|
||||
@ -97,7 +97,8 @@ bigint const c_max256plus1 = bigint(1) << 256;
|
||||
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
|
||||
m_statePre(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
||||
m_statePost(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
||||
m_TestObject(_o)
|
||||
m_environment(m_envInfo),
|
||||
m_testObject(_o)
|
||||
{
|
||||
importEnv(_o["env"].get_obj());
|
||||
importState(_o["pre"].get_obj(), m_statePre);
|
||||
@ -144,99 +145,28 @@ void ImportTest::importEnv(json_spirit::mObject& _o)
|
||||
assert(_o.count("currentTimestamp") > 0);
|
||||
assert(_o.count("currentCoinbase") > 0);
|
||||
assert(_o.count("currentNumber") > 0);
|
||||
|
||||
RLPStream rlpStream;
|
||||
rlpStream.appendList(BlockInfo::BasicFields);
|
||||
|
||||
rlpStream << h256(_o["previousHash"].get_str());
|
||||
rlpStream << EmptyListSHA3;
|
||||
rlpStream << Address(_o["currentCoinbase"].get_str());
|
||||
rlpStream << h256(); // stateRoot
|
||||
rlpStream << EmptyTrie; // transactionTrie
|
||||
rlpStream << EmptyTrie; // receiptTrie
|
||||
rlpStream << LogBloom(); // bloom
|
||||
rlpStream << toInt(_o["currentDifficulty"]);
|
||||
rlpStream << toInt(_o["currentNumber"]);
|
||||
rlpStream << toInt(_o["currentGasLimit"]);
|
||||
rlpStream << 0; //gasUsed
|
||||
rlpStream << toInt(_o["currentTimestamp"]);
|
||||
rlpStream << std::string(); //extra data
|
||||
|
||||
m_environment.currentBlock = BlockInfo(rlpStream.out(), CheckEverything, h256{}, HeaderData);
|
||||
m_statePre.m_previousBlock = m_environment.previousBlock;
|
||||
m_statePre.m_currentBlock = m_environment.currentBlock;
|
||||
m_envInfo.setBeneficiary(Address(_o["currentCoinbase"].get_str()));
|
||||
m_envInfo.setDifficulty(toInt(_o["currentDifficulty"]));
|
||||
m_envInfo.setNumber(toInt(_o["currentNumber"]));
|
||||
m_envInfo.setGasLimit(toInt(_o["currentGasLimit"]));
|
||||
m_envInfo.setTimestamp(toInt(_o["currentTimestamp"]));
|
||||
}
|
||||
|
||||
// import state from not fully declared json_spirit::mObject, writing to _stateOptionsMap which fields were defined in json
|
||||
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptionsMap& _stateOptionsMap)
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state, AccountMaskMap& o_mask)
|
||||
{
|
||||
for (auto& i: _o)
|
||||
{
|
||||
json_spirit::mObject o = i.second.get_obj();
|
||||
|
||||
ImportStateOptions stateOptions;
|
||||
u256 balance = 0;
|
||||
u256 nonce = 0;
|
||||
|
||||
if (o.count("balance") > 0)
|
||||
{
|
||||
stateOptions.m_bHasBalance = true;
|
||||
if (bigint(o["balance"].get_str()) >= c_max256plus1)
|
||||
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") );
|
||||
balance = toInt(o["balance"]);
|
||||
}
|
||||
|
||||
if (o.count("nonce") > 0)
|
||||
{
|
||||
stateOptions.m_bHasNonce = true;
|
||||
if (bigint(o["nonce"].get_str()) >= c_max256plus1)
|
||||
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") );
|
||||
nonce = toInt(o["nonce"]);
|
||||
}
|
||||
|
||||
Address address = Address(i.first);
|
||||
|
||||
bytes code;
|
||||
if (o.count("code") > 0)
|
||||
{
|
||||
code = importCode(o);
|
||||
stateOptions.m_bHasCode = true;
|
||||
}
|
||||
|
||||
if (!code.empty())
|
||||
{
|
||||
_state.m_cache[address] = Account(balance, Account::ContractConception);
|
||||
_state.m_cache[address].setCode(std::move(code));
|
||||
}
|
||||
else
|
||||
_state.m_cache[address] = Account(balance, Account::NormalCreation);
|
||||
|
||||
if (o.count("storage") > 0)
|
||||
{
|
||||
stateOptions.m_bHasStorage = true;
|
||||
for (auto const& j: o["storage"].get_obj())
|
||||
_state.setStorage(address, toInt(j.first), toInt(j.second));
|
||||
}
|
||||
|
||||
for (int i = 0; i < nonce; ++i)
|
||||
_state.noteSending(address);
|
||||
|
||||
_state.ensureCached(address, false, false);
|
||||
_stateOptionsMap[address] = stateOptions;
|
||||
}
|
||||
_state.populateFrom(jsonToAccountMap(json_spirit::write_string(_o, false), &o_mask));
|
||||
}
|
||||
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
||||
{
|
||||
stateOptionsMap importedMap;
|
||||
importState(_o, _state, importedMap);
|
||||
for (auto& stateOptionMap : importedMap)
|
||||
{
|
||||
AccountMaskMap mask;
|
||||
importState(_o, _state, mask);
|
||||
for (auto const& i: mask)
|
||||
//check that every parameter was declared in state object
|
||||
if (!stateOptionMap.second.isAllSet())
|
||||
if (!i.second.allSet())
|
||||
BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTest::importTransaction(json_spirit::mObject& _o)
|
||||
@ -347,41 +277,41 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
|
||||
{
|
||||
// export output
|
||||
|
||||
m_TestObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add);
|
||||
m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add);
|
||||
|
||||
// compare expected output with post output
|
||||
if (m_TestObject.count("expectOut") > 0)
|
||||
if (m_testObject.count("expectOut") > 0)
|
||||
{
|
||||
std::string warning = "Check State: Error! Unexpected output: " + m_TestObject["out"].get_str() + " Expected: " + m_TestObject["expectOut"].get_str();
|
||||
std::string warning = "Check State: Error! Unexpected output: " + m_testObject["out"].get_str() + " Expected: " + m_testObject["expectOut"].get_str();
|
||||
if (Options::get().checkState)
|
||||
{TBOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);}
|
||||
{TBOOST_CHECK_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning);}
|
||||
else
|
||||
TBOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);
|
||||
TBOOST_WARN_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning);
|
||||
|
||||
m_TestObject.erase(m_TestObject.find("expectOut"));
|
||||
m_testObject.erase(m_testObject.find("expectOut"));
|
||||
}
|
||||
|
||||
// export logs
|
||||
m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries());
|
||||
m_testObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries());
|
||||
|
||||
// compare expected state with post state
|
||||
if (m_TestObject.count("expect") > 0)
|
||||
if (m_testObject.count("expect") > 0)
|
||||
{
|
||||
stateOptionsMap stateMap;
|
||||
State expectState(OverlayDB(), eth::BaseState::Empty);
|
||||
importState(m_TestObject["expect"].get_obj(), expectState, stateMap);
|
||||
importState(m_testObject["expect"].get_obj(), expectState, stateMap);
|
||||
checkExpectedState(expectState, _statePost, stateMap, Options::get().checkState ? WhenError::Throw : WhenError::DontThrow);
|
||||
m_TestObject.erase(m_TestObject.find("expect"));
|
||||
m_testObject.erase(m_testObject.find("expect"));
|
||||
}
|
||||
|
||||
// export post state
|
||||
m_TestObject["post"] = fillJsonWithState(_statePost);
|
||||
m_TestObject["postStateRoot"] = toHex(_statePost.rootHash().asBytes());
|
||||
m_testObject["post"] = fillJsonWithState(_statePost);
|
||||
m_testObject["postStateRoot"] = toHex(_statePost.rootHash().asBytes());
|
||||
|
||||
// export pre state
|
||||
m_TestObject["pre"] = fillJsonWithState(m_statePre);
|
||||
m_TestObject["env"] = makeAllFieldsHex(m_TestObject["env"].get_obj());
|
||||
m_TestObject["transaction"] = makeAllFieldsHex(m_TestObject["transaction"].get_obj());
|
||||
m_testObject["pre"] = fillJsonWithState(m_statePre);
|
||||
m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj());
|
||||
m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj());
|
||||
}
|
||||
|
||||
json_spirit::mObject fillJsonWithTransaction(Transaction _txn)
|
||||
|
21
TestHelper.h
21
TestHelper.h
@ -122,26 +122,16 @@ namespace test
|
||||
} \
|
||||
while (0)
|
||||
|
||||
struct ImportStateOptions
|
||||
{
|
||||
ImportStateOptions(bool _bSetAll = false):m_bHasBalance(_bSetAll), m_bHasNonce(_bSetAll), m_bHasCode(_bSetAll), m_bHasStorage(_bSetAll) {}
|
||||
bool isAllSet() {return m_bHasBalance && m_bHasNonce && m_bHasCode && m_bHasStorage;}
|
||||
bool m_bHasBalance;
|
||||
bool m_bHasNonce;
|
||||
bool m_bHasCode;
|
||||
bool m_bHasStorage;
|
||||
};
|
||||
typedef std::map<Address, ImportStateOptions> stateOptionsMap;
|
||||
|
||||
class ImportTest
|
||||
{
|
||||
public:
|
||||
ImportTest(json_spirit::mObject& _o): m_TestObject(_o) {}
|
||||
ImportTest(json_spirit::mObject& _o): m_environment(m_envInfo), m_testObject(_o) {}
|
||||
ImportTest(json_spirit::mObject& _o, bool isFiller);
|
||||
|
||||
// imports
|
||||
void importEnv(json_spirit::mObject& _o);
|
||||
static void importState(json_spirit::mObject& _o, eth::State& _state);
|
||||
static void importState(json_spirit::mObject& _o, eth::State& _state, stateOptionsMap& _stateOptionsMap);
|
||||
static void importState(json_spirit::mObject& _o, eth::State& _state, eth::AccountMaskMap& o_mask);
|
||||
void importTransaction(json_spirit::mObject& _o);
|
||||
static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o);
|
||||
|
||||
@ -150,17 +140,18 @@ public:
|
||||
|
||||
eth::State m_statePre;
|
||||
eth::State m_statePost;
|
||||
eth::EnvInfo m_envInfo;
|
||||
eth::ExtVMFace m_environment;
|
||||
eth::Transaction m_transaction;
|
||||
|
||||
private:
|
||||
json_spirit::mObject& m_TestObject;
|
||||
json_spirit::mObject& m_testObject;
|
||||
};
|
||||
|
||||
class ZeroGasPricer: public eth::GasPricer
|
||||
{
|
||||
protected:
|
||||
u256 ask(eth::State const&) const override { return 0; }
|
||||
u256 ask(eth::Block const&) const override { return 0; }
|
||||
u256 bid(eth::TransactionPriority = eth::TransactionPriority::Medium) const override { return 0; }
|
||||
};
|
||||
|
||||
|
@ -185,7 +185,7 @@ protected:
|
||||
void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0)
|
||||
{
|
||||
m_state.addBalance(m_sender, _value); // just in case
|
||||
eth::Executive executive(m_state, eth::LastHashes(), 0);
|
||||
eth::Executive executive(m_state, eth::EnvInfo(), 0);
|
||||
eth::ExecutionResult res;
|
||||
executive.setResultRecipient(res);
|
||||
eth::Transaction t =
|
||||
|
Loading…
Reference in New Issue
Block a user