-
Notifications
You must be signed in to change notification settings - Fork 2.2k
explicit chainParams check #5030
Conversation
98a1af7
to
9b9d269
Compare
Codecov Report
@@ Coverage Diff @@
## develop #5030 +/- ##
===========================================
- Coverage 58.71% 58.37% -0.34%
===========================================
Files 334 346 +12
Lines 26424 26888 +464
Branches 3133 3228 +95
===========================================
+ Hits 15514 15696 +182
- Misses 9909 10180 +271
- Partials 1001 1012 +11 |
libdevcore/JsonUtils.h
Outdated
|
||
// 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me jsonTypeSet
sounds better.
First I thought "possibly it is a json type, but possibly it is not a json type".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, JsonTypeSet
would be better.
Also better use using
instead of typedef
.
And better place type definitions at the top, before function definitions.
libdevcore/JsonUtils.cpp
Outdated
{ | ||
if (sTypes.size()) | ||
sTypes += ", or "; | ||
sTypes += jsonTypeAsString(type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need this concatenation only when there is an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so you think two loops on for (auto const& type : vmap.second)
is better ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
@gumb0 @pirapira My question is do we really need it? Precompiled contracts are hardcoded anyway. non other clients support this specific account desctiption anyway. retesteth and hive has to prepare a specific genesis for cpp in this case. could we move those params to hardcode of the client?
|
I think we should be able to get rid of them. On the other hand I think ewasm team requested or even implemented the feature with config file to refer to external files with precompiled code when they want to create wasm-precompiles. Not sure what to do with that. cc @chfast |
libethereum/ChainParams.cpp
Outdated
@@ -98,7 +133,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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to leave both of these validations here?
So now we have two separate list of allowed fields to maintain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the other one could be removed from this place. once we come to a standart in genesis config.
the question remains is wether we should use constants instead of strings in scheme validation functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should validate it two times. So let's not merge it then until we have final version
optional fields are ok. |
libethereum/ChainParams.cpp
Outdated
@@ -98,7 +133,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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should validate it two times. So let's not merge it then until we have final version
libethereum/ChainParams.cpp
Outdated
void validateConfigJson(js::mObject const& _obj) | ||
{ | ||
requireJsonFields(_obj, "ChainParams::loadConfig", | ||
{{"sealEngine", {json_spirit::str_type}}, {"params", {json_spirit::obj_type}}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So why did you choose not to use the constants for the field names here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this check is like a constant itself. if it does not match, then it throws an error.
so if you have a typo, it will break the test run.
although it is said that it is not good to use char in the code this way. maybe we need a dictionary class that would return a string by id for all text checks and messages in the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't have duplicate string literals in the code here, it's maintenance pain and might waste resources. So use here c_sealEngine
, c_params
etc.
} | ||
} | ||
|
||
void dev::requireJsonFields(json_spirit::mObject const& _o, std::string const& _config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about having it in libdevcore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the previous checks were put into this file. @pirapira ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is a better place, feel free to move.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we could remove jsonUtils from libdevcore. and keep it in libethereum. but I dont think its a better choise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If libdevcore
or libethereum
, I'd vote for libdevcore
. This is not so particularly about Ethereum.
looks like client devs wont come up with the common scheme any time soon. |
libethereum/ValidationSchemes.cpp
Outdated
// A precompiled contract | ||
requireJsonFields(_obj, "validateAccountObj", | ||
{{c_precompiled, {json_spirit::obj_type}}}, | ||
{c_wei}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you want wei
as str_type
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it's not required?
libdevcore/JsonUtils.h
Outdated
// Check json _o with validation map that reuires certain field of certain type to be present in | ||
// json | ||
using jsonTypeSet = std::set<json_spirit::Value_type>; | ||
void requireJsonFields(json_spirit::mObject const& _o, std::string const& _config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document this function.
Have you considered using JSON Schema to specify and validate JSON configs? I've found validator for JSON Schema: https://github.com/tristanpenman/valijson. |
Hmm. That repo looks like a lot of code to add for dependencies. |
libdevcore/JsonUtils.h
Outdated
}; | ||
using jsonTypeSet = std::set<json_spirit::Value_type>; | ||
using jsonType = std::pair<jsonTypeSet, jsonField>; | ||
void requireJsonFields(json_spirit::mObject const& _o, std::string const& _config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function does a little bit different job from what "require Json Fields" suggests.
Please document the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you clarify what "document the function" should look like ?
libdevcore/JsonUtils.h
Outdated
// Converts json value type to string | ||
std::string jsonTypeAsString(json_spirit::Value_type _type); | ||
|
||
enum jsonField |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enum class
is preferable to enum
. Also start type names with capital letter. Also this should be better named something like JsonFieldPresence
maybe
libdevcore/JsonUtils.h
Outdated
Required, | ||
Optional | ||
}; | ||
using jsonTypeSet = std::set<json_spirit::Value_type>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start type name with capital letter
libdevcore/JsonUtils.h
Outdated
Optional | ||
}; | ||
using jsonTypeSet = std::set<json_spirit::Value_type>; | ||
using jsonType = std::pair<jsonTypeSet, jsonField>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start type name with capital letter, also this is something like JsonTypesAndPresence
I'd say
libdevcore/JsonUtils.cpp
Outdated
if (matched == false) | ||
{ | ||
std::string sTypes; | ||
for (auto const& type : vmap.second.first) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use boost::algorithm::join
here instead of reinventing joining the strings, but it's up to you
libdevcore/JsonUtils.cpp
Outdated
sTypes += jsonTypeAsString(type); | ||
} | ||
std::string const comment = | ||
"Field '" + vmap.first + "' expected to be " + sTypes + ", but set to " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is (or was) expected to be, but is (or was) set
libethereum/ValidationSchemes.h
Outdated
You should have received a copy of the GNU General Public License | ||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
/** @file ValidationSchemes.h |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove these @file
and @date
Use @file
only if you provide some meaningful description of the file
libethereum/Account.cpp
Outdated
// FIXME: Do not copy every account object. | ||
auto o = account.second.get_obj(); | ||
validateAccountMapObj(o); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you do this now inside the loop? Validating the whole map object in each iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checking one account instead of a list of accounts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah wow, don't use o
for both the whole map and one account object.
Use more meaningful names than o
anyway
libethereum/ValidationSchemes.h
Outdated
namespace eth { | ||
namespace validation { | ||
|
||
extern std::string const c_sealEngine; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked these constants more in ChainParams.cpp
/ Account.cpp
... where they are closer to the actual useful work being done with them.
Are you sure with moving all of this into separate file? I'd leave the three validation functions closer to the other work with the json configs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this constants could grow over time into a big amount of variables
libethereum/ValidationSchemes.h
Outdated
void validateAccountMapObj(json_spirit::mObject const& _o); | ||
|
||
|
||
}}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like it was clang-formatted
libethereum/ValidationSchemes.cpp
Outdated
{c_precompiled, {{json_spirit::obj_type}, JsonFieldPresence::Optional}}, | ||
{c_shouldnotexist, {{json_spirit::str_type}, JsonFieldPresence::Optional}}, | ||
{c_wei, {{json_spirit::str_type}, JsonFieldPresence::Optional}}}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation is off here. Use clang-format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used clang-format
libethereum/ValidationSchemes.cpp
Outdated
#include <string> | ||
|
||
using namespace std; | ||
using namespace dev; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this, everything is defined inside dev
anyway.
You probably don't need using namespace std;
either
libethereum/ValidationSchemes.cpp
Outdated
|
||
using namespace std; | ||
using namespace dev; | ||
namespace js = json_spirit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't use this below, it's json_spirit
everywhere. So maybe just delete it.
libethereum/ValidationSchemes.cpp
Outdated
} | ||
else | ||
{ | ||
// A standart account with all fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between standard account and genesis account? Do these standard accounts really always have code and storage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. standart account required to have all 4 fields.
in genesis it is not required.
and account map could be empty
libethereum/ChainParams.cpp
Outdated
@@ -27,15 +27,16 @@ | |||
#include <libethcore/SealEngine.h> | |||
#include <libethcore/BlockHeader.h> | |||
#include <libethcore/Precompiled.h> | |||
#include "ValidationSchemes.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use clang-format here, it should reorder includes
} | ||
else | ||
{ | ||
// A standart account with all fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which configs are they used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah it's allowed to have in genesis accounts either balance only or all 4 fields? ok then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In tests also
libethereum/ValidationSchemes.h
Outdated
// Validate account json object | ||
void validateAccountObj(json_spirit::mObject const& _o); | ||
|
||
// Validate account Map json object. Map indicates which fields are set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second part of comment is not needed I guess?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the confusion is because it should be account mask here
libethereum/Account.cpp
Outdated
// FIXME: Do not copy every account object. | ||
auto o = account.second.get_obj(); | ||
auto const& accountMapJson = account.second.get_obj(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just accountJson
or accountObject
, because acountMap
sounds like a map of accounts, but as I understand it refers to single account
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Map is because it indicates which fields are set and which are not. there is a class for that: AccountMask. should be renamed to accountMask to avoid confusion
libethereum/ValidationSchemes.h
Outdated
void validateAccountObj(json_spirit::mObject const& _o); | ||
|
||
// Validate account Map json object. Map indicates which fields are set | ||
void validateAccountMapObj(json_spirit::mObject const& _o); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also this name, if it validates just one account object I would name it differently
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accountMaskObj
libethereum/ChainParams.cpp
Outdated
// Strict account check | ||
js::read_string_or_throw(genesisStateStr, val); | ||
for (auto const& account: val.get_obj()) | ||
validateAccountObj(account.second.get_obj()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need this here at all? You call validateConfigJson(obj);
above and inside it it already goes over all accounts, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you right
void validateConfigJson(json_spirit::mObject const& _obj); | ||
|
||
// Validate account json object | ||
void validateAccountObj(json_spirit::mObject const& _o); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now used only by validateConfigJson
so make it internal to ValidationSchemes.cpp
, remove from header
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it shoud be removed. it should be used in testeth.
I'm confused now about these account masks.
Now you want to validate input json to this function. Input json has account description, not "account masks". So the validation of json of each account it seems should be called something like Also: I'm looking at
So do you even need both of |
Could we have a call? |
your confusion might be because
double check in jsonToAccountMap is because we don't store data in objects. instead we pass arguments from function to function and this function here jsonToAccountMap could not rely on the correctness of the input data. what would be better is an abstraction layer between json data and logical objects. so once you read json data into those objects you wont need to verify every input argument of the function. |
Sure, ping me in discord for a call, you're offline now |
Dismissing Yoichi's review as he says he is not available for doing reviews at the moment
Instead of validating fields names with c_fieldname constant
I moved requireJson function to libdevcode
so you could specify how json object should look like, and what fields it must have and of what time those fields could be.
example code in validating the chainParams. requires review.
this is a step toward understanding what chain params are required and what could be set optional.