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)
|
void mine(State& s, BlockChain const& _bc)
|
||||||
{
|
{
|
||||||
std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
|
std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
|
||||||
s.commitToMine(_bc);
|
s.commitToSeal(_bc);
|
||||||
Notified<bytes> sealed;
|
Notified<bytes> sealed;
|
||||||
sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
|
sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
|
||||||
sealer->generateSeal(s.info());
|
sealer->generateSeal(s.info());
|
||||||
@ -97,7 +97,8 @@ bigint const c_max256plus1 = bigint(1) << 256;
|
|||||||
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
|
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
|
||||||
m_statePre(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
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_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());
|
importEnv(_o["env"].get_obj());
|
||||||
importState(_o["pre"].get_obj(), m_statePre);
|
importState(_o["pre"].get_obj(), m_statePre);
|
||||||
@ -144,100 +145,29 @@ void ImportTest::importEnv(json_spirit::mObject& _o)
|
|||||||
assert(_o.count("currentTimestamp") > 0);
|
assert(_o.count("currentTimestamp") > 0);
|
||||||
assert(_o.count("currentCoinbase") > 0);
|
assert(_o.count("currentCoinbase") > 0);
|
||||||
assert(_o.count("currentNumber") > 0);
|
assert(_o.count("currentNumber") > 0);
|
||||||
|
m_envInfo.setBeneficiary(Address(_o["currentCoinbase"].get_str()));
|
||||||
RLPStream rlpStream;
|
m_envInfo.setDifficulty(toInt(_o["currentDifficulty"]));
|
||||||
rlpStream.appendList(BlockInfo::BasicFields);
|
m_envInfo.setNumber(toInt(_o["currentNumber"]));
|
||||||
|
m_envInfo.setGasLimit(toInt(_o["currentGasLimit"]));
|
||||||
rlpStream << h256(_o["previousHash"].get_str());
|
m_envInfo.setTimestamp(toInt(_o["currentTimestamp"]));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// import state from not fully declared json_spirit::mObject, writing to _stateOptionsMap which fields were defined in json
|
// 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)
|
_state.populateFrom(jsonToAccountMap(json_spirit::write_string(_o, false), &o_mask));
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
||||||
{
|
{
|
||||||
stateOptionsMap importedMap;
|
AccountMaskMap mask;
|
||||||
importState(_o, _state, importedMap);
|
importState(_o, _state, mask);
|
||||||
for (auto& stateOptionMap : importedMap)
|
for (auto const& i: mask)
|
||||||
{
|
|
||||||
//check that every parameter was declared in state object
|
//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!"));
|
BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ImportTest::importTransaction(json_spirit::mObject& _o)
|
void ImportTest::importTransaction(json_spirit::mObject& _o)
|
||||||
{
|
{
|
||||||
@ -347,41 +277,41 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
|
|||||||
{
|
{
|
||||||
// export output
|
// 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
|
// 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)
|
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
|
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
|
// 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
|
// compare expected state with post state
|
||||||
if (m_TestObject.count("expect") > 0)
|
if (m_testObject.count("expect") > 0)
|
||||||
{
|
{
|
||||||
stateOptionsMap stateMap;
|
stateOptionsMap stateMap;
|
||||||
State expectState(OverlayDB(), eth::BaseState::Empty);
|
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);
|
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
|
// export post state
|
||||||
m_TestObject["post"] = fillJsonWithState(_statePost);
|
m_testObject["post"] = fillJsonWithState(_statePost);
|
||||||
m_TestObject["postStateRoot"] = toHex(_statePost.rootHash().asBytes());
|
m_testObject["postStateRoot"] = toHex(_statePost.rootHash().asBytes());
|
||||||
|
|
||||||
// export pre state
|
// export pre state
|
||||||
m_TestObject["pre"] = fillJsonWithState(m_statePre);
|
m_testObject["pre"] = fillJsonWithState(m_statePre);
|
||||||
m_TestObject["env"] = makeAllFieldsHex(m_TestObject["env"].get_obj());
|
m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj());
|
||||||
m_TestObject["transaction"] = makeAllFieldsHex(m_TestObject["transaction"].get_obj());
|
m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj());
|
||||||
}
|
}
|
||||||
|
|
||||||
json_spirit::mObject fillJsonWithTransaction(Transaction _txn)
|
json_spirit::mObject fillJsonWithTransaction(Transaction _txn)
|
||||||
|
21
TestHelper.h
21
TestHelper.h
@ -122,26 +122,16 @@ namespace test
|
|||||||
} \
|
} \
|
||||||
while (0)
|
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
|
class ImportTest
|
||||||
{
|
{
|
||||||
public:
|
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);
|
ImportTest(json_spirit::mObject& _o, bool isFiller);
|
||||||
|
|
||||||
// imports
|
// imports
|
||||||
void importEnv(json_spirit::mObject& _o);
|
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);
|
||||||
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);
|
void importTransaction(json_spirit::mObject& _o);
|
||||||
static json_spirit::mObject& makeAllFieldsHex(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_statePre;
|
||||||
eth::State m_statePost;
|
eth::State m_statePost;
|
||||||
|
eth::EnvInfo m_envInfo;
|
||||||
eth::ExtVMFace m_environment;
|
eth::ExtVMFace m_environment;
|
||||||
eth::Transaction m_transaction;
|
eth::Transaction m_transaction;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
json_spirit::mObject& m_TestObject;
|
json_spirit::mObject& m_testObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ZeroGasPricer: public eth::GasPricer
|
class ZeroGasPricer: public eth::GasPricer
|
||||||
{
|
{
|
||||||
protected:
|
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; }
|
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)
|
void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0)
|
||||||
{
|
{
|
||||||
m_state.addBalance(m_sender, _value); // just in case
|
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;
|
eth::ExecutionResult res;
|
||||||
executive.setResultRecipient(res);
|
executive.setResultRecipient(res);
|
||||||
eth::Transaction t =
|
eth::Transaction t =
|
||||||
|
Loading…
Reference in New Issue
Block a user