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

Commit

Permalink
explicit chainParams check
Browse files Browse the repository at this point in the history
  • Loading branch information
winsvega committed May 16, 2018
1 parent 58afde7 commit 9b9d269
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 24 deletions.
2 changes: 2 additions & 0 deletions libdevcore/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ DEV_SIMPLE_EXCEPTION(Overflow);
DEV_SIMPLE_EXCEPTION(FailedInvariant);
DEV_SIMPLE_EXCEPTION(ValueTooLarge);
DEV_SIMPLE_EXCEPTION(UnknownField);
DEV_SIMPLE_EXCEPTION(MissingField);
DEV_SIMPLE_EXCEPTION(WrongFieldType);
DEV_SIMPLE_EXCEPTION(InterfaceNotSupported);
DEV_SIMPLE_EXCEPTION(ExternalFunctionFailure);

Expand Down
74 changes: 74 additions & 0 deletions libdevcore/JsonUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,77 @@ void dev::validateFieldNames(json_spirit::mObject const& _obj, std::set<std::str
BOOST_THROW_EXCEPTION(UnknownField() << errinfo_comment(comment));
}
}

std::string dev::jsonTypeAsString(json_spirit::Value_type _type)
{
switch (_type)
{
case json_spirit::obj_type:
return "json Object";
case json_spirit::array_type:
return "json Array";
case json_spirit::str_type:
return "json String";
case json_spirit::bool_type:
return "json Bool";
case json_spirit::int_type:
return "json Int";
case json_spirit::real_type:
return "json Real";
case json_spirit::null_type:
return "json Null";
default:
return "json n/a";
}
}

void dev::requireJsonFields(json_spirit::mObject const& _o, std::string const& _config,
std::map<std::string, possibleJsonType> const& _validationMap,
std::set<std::string> const& _ignoreFields)
{
// check for unexpected fiedls
for (auto const& field : _o)
{
if (!_validationMap.count(field.first) && !_ignoreFields.count(field.first))
{
std::string const comment =
"Unexpected field '" + field.first + "' in config: " + _config;
std::cerr << comment << "\n"
<< json_spirit::write_string((json_spirit::mValue)_o, true) << "\n";
BOOST_THROW_EXCEPTION(UnknownField() << errinfo_comment(comment));
}
}

// check field types with validation map
for (auto const vmap : _validationMap)
{
if (!_o.count(vmap.first))
{
std::string const comment =
"Expected field '" + vmap.first + "' 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));
}

bool matched = false;
std::string sTypes;
for (auto const& type : vmap.second)
{
if (sTypes.size())
sTypes += ", or ";
sTypes += jsonTypeAsString(type);
if (_o.at(vmap.first).type() == type)
matched = true;
}
if (matched == false)
{
std::string const comment =
"Field '" + vmap.first + "' expected to be " + sTypes + ", but set to " +
jsonTypeAsString(_o.at(vmap.first).type()) + " in " + _config;
std::cerr << comment << "\n"
<< json_spirit::write_string((json_spirit::mValue)_o, true) << "\n";
BOOST_THROW_EXCEPTION(WrongFieldType() << errinfo_comment(comment));
}
}
}
10 changes: 10 additions & 0 deletions libdevcore/JsonUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,14 @@ namespace dev
{
// Throws UnknownField() if _obj contains field names not listed in _allowedFields.
void validateFieldNames(json_spirit::mObject const& _obj, std::set<std::string> const& _allowedFields);

// Converts json value type to string
std::string jsonTypeAsString(json_spirit::Value_type _type);

// Check json _o with validation map that reuires certain field of certain type to be present in
// json
typedef std::set<json_spirit::Value_type> possibleJsonType;
void requireJsonFields(json_spirit::mObject const& _o, std::string const& _config,
std::map<std::string, possibleJsonType> const& _validationMap,
std::set<std::string> const& _ignoreFields = {});
}
33 changes: 32 additions & 1 deletion libethereum/ChainParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,36 @@ set<string> const c_knownParamNames = {c_minGasLimit, c_maxGasLimit, c_gasLimitB
c_durationLimit, c_chainID, c_networkID, c_allowFutureBlocks};
} // anonymous namespace

void validateConfigJson(js::mObject const& _obj)
{
requireJsonFields(_obj, "ChainParams::loadConfig",
{{"sealEngine", {json_spirit::str_type}}, {"params", {json_spirit::obj_type}},
{"genesis", {json_spirit::obj_type}}, {"accounts", {json_spirit::obj_type}}});

requireJsonFields(_obj.at("genesis").get_obj(), "ChainParams::loadConfig",
{{"author", {json_spirit::str_type}}, {"nonce", {json_spirit::str_type}},
{"author", {json_spirit::str_type}}, {"gasLimit", {json_spirit::str_type}},
{"timestamp", {json_spirit::str_type}}, {"difficulty", {json_spirit::str_type}},
{"extraData", {json_spirit::str_type}}},
{"mixHash", "parentHash"});

js::mObject const& accounts = _obj.at("accounts").get_obj();
for (auto const& acc : accounts)
{
js::mObject const& account = acc.second.get_obj();
if (account.count("precompiled"))
{
requireJsonFields(account, "ChainParams::loadConfig",
{{"precompiled", {json_spirit::obj_type}}}, {"wei"});
}
else
{
requireJsonFields(account, "ChainParams::loadConfig",
{{"balance", {json_spirit::str_type}}}, {"code", "nonce", "storage"});
}
}
}

ChainParams ChainParams::loadConfig(
string const& _json, h256 const& _stateRoot, const boost::filesystem::path& _configPath) const
{
Expand All @@ -98,7 +128,8 @@ ChainParams ChainParams::loadConfig(
json_spirit::read_string_or_throw(_json, val);
js::mObject obj = val.get_obj();

validateFieldNames(obj, c_knownChainConfigFields);
validateConfigJson(obj);
validateFieldNames(obj, c_knownChainConfigFields);

cp.sealEngineName = obj[c_sealEngine].get_str();
// params
Expand Down
24 changes: 1 addition & 23 deletions test/tools/libtesteth/TestHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "TestOutputHelper.h"
#include "wast2wasm.h"

#include <libdevcore/JsonUtils.h>
#include <libethashseal/EthashCPUMiner.h>
#include <libethereum/Client.h>

Expand Down Expand Up @@ -581,29 +582,6 @@ void checkCallCreates(
}
}

string jsonTypeAsString(json_spirit::Value_type _type)
{
switch (_type)
{
case json_spirit::obj_type:
return "json Object";
case json_spirit::array_type:
return "json Array";
case json_spirit::str_type:
return "json String";
case json_spirit::bool_type:
return "json Bool";
case json_spirit::int_type:
return "json Int";
case json_spirit::real_type:
return "json Real";
case json_spirit::null_type:
return "json Null";
default:
return "json n/a";
}
}

void requireJsonFields(json_spirit::mObject const& _o, string const& _section,
map<string, json_spirit::Value_type> const& _validationMap)
{
Expand Down

0 comments on commit 9b9d269

Please sign in to comment.