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

Commit

Permalink
refactor validation schemes
Browse files Browse the repository at this point in the history
  • Loading branch information
winsvega committed Jun 13, 2018
1 parent 41dc392 commit f412526
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 131 deletions.
44 changes: 21 additions & 23 deletions libdevcore/JsonUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/

#include <libdevcore/JsonUtils.h>
#include <json_spirit/JsonSpiritHeaders.h>
#include <libdevcore/JsonUtils.h>
#include <boost/algorithm/string/join.hpp>
#include <ostream>
#include <set>
#include <string>
#include <ostream>

void dev::validateFieldNames(json_spirit::mObject const& _obj, std::set<std::string> const& _allowedFields)
{
Expand Down Expand Up @@ -56,7 +57,7 @@ std::string dev::jsonTypeAsString(json_spirit::Value_type _type)
}

void dev::requireJsonFields(json_spirit::mObject const& _o, std::string const& _config,
std::map<std::string, jsonType> const& _validationMap)
std::map<std::string, JsonFieldOptions> const& _validationMap)
{
// check for unexpected fiedls
for (auto const& field : _o)
Expand All @@ -74,40 +75,37 @@ void dev::requireJsonFields(json_spirit::mObject const& _o, std::string const& _
// check field types with validation map
for (auto const vmap : _validationMap)
{
auto const& expectedFieldName = vmap.first;
auto const& expectedFieldPresence = vmap.second.second;
// check that all required fields are in the object
if (!_o.count(vmap.first))
if (!_o.count(expectedFieldName))
{
if (vmap.second.second == jsonField::Required)
if (expectedFieldPresence == JsonFieldPresence::Required)
{
std::string const comment =
"Expected field '" + vmap.first + "' not found in config: " + _config;
"Expected field '" + expectedFieldName + "' not found in config: " + _config;
std::cerr << comment << "\n"
<< json_spirit::write_string((json_spirit::mValue)_o, true) << "\n";
BOOST_THROW_EXCEPTION(MissingField() << errinfo_comment(comment));
}
else if (vmap.second.second == jsonField::Optional)
else if (expectedFieldPresence == JsonFieldPresence::Optional)
continue;
}

// check that field type is one of allowed field types
bool matched = false;
for (auto const& type : vmap.second.first)
{
if (_o.at(vmap.first).type() == type)
matched = true;
}
auto const& expectedFieldTypes = vmap.second.first;
bool matched = expectedFieldTypes.count(_o.at(expectedFieldName).type());
if (matched == false)
{
std::string sTypes;
for (auto const& type : vmap.second.first)
{
if (sTypes.size())
sTypes += ", or ";
sTypes += jsonTypeAsString(type);
}
std::string const comment =
"Field '" + vmap.first + "' expected to be " + sTypes + ", but set to " +
jsonTypeAsString(_o.at(vmap.first).type()) + " in " + _config;
std::vector<std::string> types;
for (auto const& type : expectedFieldTypes)
types.push_back(jsonTypeAsString(type));
std::string sTypes = boost::algorithm::join(types, " or ");

std::string const comment = "Field '" + expectedFieldName + "' is expected to be " +
sTypes + ", but is set to " +
jsonTypeAsString(_o.at(expectedFieldName).type()) + " in " +
_config;
std::cerr << comment << "\n"
<< json_spirit::write_string((json_spirit::mValue)_o, true) << "\n";
BOOST_THROW_EXCEPTION(WrongFieldType() << errinfo_comment(comment));
Expand Down
20 changes: 10 additions & 10 deletions libdevcore/JsonUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ void validateFieldNames(json_spirit::mObject const& _obj, std::set<std::string>
// Converts json value type to string
std::string jsonTypeAsString(json_spirit::Value_type _type);

enum jsonField
enum class JsonFieldPresence
{
Required,
Optional
};
using jsonTypeSet = std::set<json_spirit::Value_type>;
using jsonType = std::pair<jsonTypeSet, jsonField>;
//! Check the json object with validation map that reuires certain field of certain type to be
//! present in json
/*!
\param _o a json object to check
\param _configName a string with json object name. Will apper in error message.
\param _validationMap a map with json objects that would be checked. "objName" -> {js::str_type,
using JsonTypeSet = std::set<json_spirit::Value_type>;
using JsonFieldOptions = std::pair<JsonTypeSet, JsonFieldPresence>;
/// Check the json object with validation map that reuires certain field of certain type to be
/// present in json
/**
@param _o a json object to check
@param _configName a string with json object name. Will apper in error message.
@param _validationMap a map with json objects that would be checked. "objName" -> {js::str_type,
jsonField::Required}
*/
void requireJsonFields(json_spirit::mObject const& _o, std::string const& _configName,
std::map<std::string, jsonType> const& _validationMap);
std::map<std::string, JsonFieldOptions> const& _validationMap);
}
75 changes: 38 additions & 37 deletions libethereum/Account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,22 @@ uint64_t toUnsigned(js::mValue const& _v)
}
}

PrecompiledContract createPrecompiledContract(js::mObject& _precompiled)
PrecompiledContract createPrecompiledContract(js::mObject const& _precompiled)
{
auto n = _precompiled["name"].get_str();
try
auto n = _precompiled.at("name").get_str();
try
{
u256 startingBlock = 0;
if (_precompiled.count("startingBlock"))
startingBlock = u256(_precompiled["startingBlock"].get_str());
startingBlock = u256(_precompiled.at("startingBlock").get_str());

if (!_precompiled.count("linear"))
if (!_precompiled.count("linear"))
return PrecompiledContract(PrecompiledRegistrar::pricer(n), PrecompiledRegistrar::executor(n), startingBlock);

auto l = _precompiled["linear"].get_obj();
unsigned base = toUnsigned(l["base"]);
unsigned word = toUnsigned(l["word"]);
return PrecompiledContract(base, word, PrecompiledRegistrar::executor(n), startingBlock);
auto const& l = _precompiled.at("linear").get_obj();
unsigned base = toUnsigned(l.at("base"));
unsigned word = toUnsigned(l.at("word"));
return PrecompiledContract(base, word, PrecompiledRegistrar::executor(n), startingBlock);
}
catch (PricerNotFound const&)
{
Expand Down Expand Up @@ -99,35 +99,36 @@ AccountMap dev::eth::jsonToAccountMap(std::string const& _json, u256 const& _def

js::mValue val;
json_spirit::read_string_or_throw(_json, val);
js::mObject o = val.get_obj();
for (auto const& account: o)
{

for (auto const& account : val.get_obj())
{
Address a(fromHex(account.first));
// FIXME: Do not copy every account object.
auto o = account.second.get_obj();
validateAccountMapObj(o);
auto const& accountMapJson = account.second.get_obj();
validateAccountMapObj(accountMapJson);

bool haveBalance = (o.count(c_wei) || o.count(c_finney) || o.count(c_balance));
bool haveNonce = o.count(c_nonce);
bool haveCode = o.count(c_code) || o.count(c_codeFromFile);
bool haveStorage = o.count(c_storage);
bool shouldNotExists = o.count(c_shouldnotexist);
bool haveBalance = (accountMapJson.count(c_wei) || accountMapJson.count(c_finney) ||
accountMapJson.count(c_balance));
bool haveNonce = accountMapJson.count(c_nonce);
bool haveCode = accountMapJson.count(c_code) || accountMapJson.count(c_codeFromFile);
bool haveStorage = accountMapJson.count(c_storage);
bool shouldNotExists = accountMapJson.count(c_shouldnotexist);

if (haveStorage || haveCode || haveNonce || haveBalance)
if (haveStorage || haveCode || haveNonce || haveBalance)
{
u256 balance = 0;
if (o.count(c_wei))
balance = u256Safe(o[c_wei].get_str());
else if (o.count(c_finney))
balance = u256Safe(o[c_finney].get_str()) * finney;
else if (o.count(c_balance))
balance = u256Safe(o[c_balance].get_str());
if (accountMapJson.count(c_wei))
balance = u256Safe(accountMapJson.at(c_wei).get_str());
else if (accountMapJson.count(c_finney))
balance = u256Safe(accountMapJson.at(c_finney).get_str()) * finney;
else if (accountMapJson.count(c_balance))
balance = u256Safe(accountMapJson.at(c_balance).get_str());

u256 nonce = haveNonce ? u256Safe(o[c_nonce].get_str()) : _defaultNonce;
u256 nonce = haveNonce ? u256Safe(accountMapJson.at(c_nonce).get_str()) : _defaultNonce;

ret[a] = Account(nonce, balance);
auto codeIt = o.find(c_code);
if (codeIt != o.end())
auto codeIt = accountMapJson.find(c_code);
if (codeIt != accountMapJson.end())
{
auto& codeObj = codeIt->second;
if (codeObj.type() == json_spirit::str_type)
Expand All @@ -144,8 +145,8 @@ AccountMap dev::eth::jsonToAccountMap(std::string const& _json, u256 const& _def
<< "! Code field needs to be a string";
}

auto codePathIt = o.find(c_codeFromFile);
if (codePathIt != o.end())
auto codePathIt = accountMapJson.find(c_codeFromFile);
if (codePathIt != accountMapJson.end())
{
auto& codePathObj = codePathIt->second;
if (codePathObj.type() == json_spirit::str_type)
Expand All @@ -166,8 +167,8 @@ AccountMap dev::eth::jsonToAccountMap(std::string const& _json, u256 const& _def


if (haveStorage)
for (pair<string, js::mValue> const& j: o[c_storage].get_obj())
ret[a].setStorage(u256(j.first), u256(j.second.get_str()));
for (pair<string, js::mValue> const& j : accountMapJson.at(c_storage).get_obj())
ret[a].setStorage(u256(j.first), u256(j.second.get_str()));
}

if (o_mask)
Expand All @@ -177,10 +178,10 @@ AccountMap dev::eth::jsonToAccountMap(std::string const& _json, u256 const& _def
ret[a] = Account(0, 0);
}

if (o_precompiled && o.count(c_precompiled))
{
js::mObject p = o[c_precompiled].get_obj();
o_precompiled->insert(make_pair(a, createPrecompiledContract(p)));
if (o_precompiled && accountMapJson.count(c_precompiled))
{
js::mObject p = accountMapJson.at(c_precompiled).get_obj();
o_precompiled->insert(make_pair(a, createPrecompiledContract(p)));
}
}

Expand Down
29 changes: 15 additions & 14 deletions libethereum/ChainParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@
*/

#include "ChainParams.h"
#include "Account.h"
#include "GenesisInfo.h"
#include "State.h"
#include "ValidationSchemes.h"
#include <json_spirit/JsonSpiritHeaders.h>
#include <libdevcore/JsonUtils.h>
#include <libdevcore/Log.h>
#include <libdevcore/TrieDB.h>
#include <libdevcore/JsonUtils.h>
#include <libethcore/SealEngine.h>
#include <libethcore/BlockHeader.h>
#include <libethcore/Precompiled.h>
#include "ValidationSchemes.h"
#include "GenesisInfo.h"
#include "State.h"
#include "Account.h"
#include <libethcore/SealEngine.h>

using namespace std;
using namespace dev;
using namespace eth;
Expand Down Expand Up @@ -58,8 +59,8 @@ ChainParams ChainParams::loadConfig(
{
ChainParams cp(*this);
js::mValue val;
json_spirit::read_string_or_throw(_json, val);
js::mObject obj = val.get_obj();
js::read_string_or_throw(_json, val);
js::mObject obj = val.get_obj();

validateConfigJson(obj);
cp.sealEngineName = obj[c_sealEngine].get_str();
Expand Down Expand Up @@ -96,16 +97,16 @@ ChainParams ChainParams::loadConfig(
cp.allowFutureBlocks = params.count(c_allowFutureBlocks);

// genesis
string genesisStr = json_spirit::write_string(obj[c_genesis], false);
cp = cp.loadGenesis(genesisStr, _stateRoot);
string genesisStr = js::write_string(obj[c_genesis], false);
cp = cp.loadGenesis(genesisStr, _stateRoot);
// genesis state
string genesisStateStr = json_spirit::write_string(obj[c_accounts], false);
string genesisStateStr = js::write_string(obj[c_accounts], false);

cp.genesisState = jsonToAccountMap(
genesisStateStr, cp.accountStartNonce, nullptr, &cp.precompiled, _configPath);

// Strict account check
json_spirit::read_string_or_throw(genesisStateStr, val);
js::read_string_or_throw(genesisStateStr, val);
for (auto const& account: val.get_obj())
validateAccountObj(account.second.get_obj());

Expand All @@ -119,8 +120,8 @@ ChainParams ChainParams::loadGenesis(string const& _json, h256 const& _stateRoot
ChainParams cp(*this);

js::mValue val;
json_spirit::read_string(_json, val);
js::mObject genesis = val.get_obj();
js::read_string(_json, val);
js::mObject genesis = val.get_obj();

cp.parentHash = h256(0); // required by the YP
cp.author = genesis.count(c_coinbase) ? h160(genesis[c_coinbase].get_str()) : h160(genesis[c_author].get_str());
Expand Down
Loading

0 comments on commit f412526

Please sign in to comment.