зеркало из https://github.com/microsoft/eEVM.git
from_json/to_json issue#40 (#41)
* From_json/to_json: read and write nonce and code fields as hexstrings * Default initializer added for Account fields * Test added checking that from_json/to_json are mutually inverse * parseAccount() changed to be compatible with to_json/from_json logic * * to_uint64(const string&) overload added * Account::nonce is serialized from hex string * to_json/from_json tests added * added some JSON tests * address must be lower-case, 40-bytes hex string starting with 0x * accountFull.json test file added * address_to_hex_string is used to serialize address field * to_hex_string: string width should not be changed from default
This commit is contained in:
Родитель
5dc8a7ad9a
Коммит
881e198e8c
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"address": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||
"balance": "0x152d02c7e14af6800000",
|
||||
"code": "0x33ff",
|
||||
"nonce": "0x0"
|
||||
}
|
|
@ -55,17 +55,21 @@ namespace evm
|
|||
|
||||
void to_json(nlohmann::json& j, const Account& a)
|
||||
{
|
||||
j["address"] = a.address;
|
||||
j["address"] = address_to_hex_string(a.address);
|
||||
j["balance"] = a.balance;
|
||||
j["nonce"] = a.nonce;
|
||||
j["code"] = a.code;
|
||||
j["nonce"] = to_hex_string(a.nonce);
|
||||
j["code"] = to_hex_string(a.code);
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json& j, Account& a)
|
||||
{
|
||||
if (j.find("address") != j.end())
|
||||
assign_j(a.address, j["address"]);
|
||||
if (j.find("balance") != j.end())
|
||||
assign_j(a.balance, j["balance"]);
|
||||
assign_j(a.nonce, j["nonce"]);
|
||||
assign_j(a.code, j["code"]);
|
||||
if (j.find("nonce") != j.end())
|
||||
assign_j(a.nonce, to_uint64(j["nonce"]));
|
||||
if (j.find("code") != j.end())
|
||||
assign_j(a.code, to_bytes(j["code"]));
|
||||
}
|
||||
} // namespace evm
|
|
@ -16,10 +16,14 @@ namespace evm
|
|||
return (s.size() >= 2 && s[1] == 'x') ? s.substr(2) : s;
|
||||
}
|
||||
|
||||
uint64_t to_uint64(const std::string& s)
|
||||
{
|
||||
return strtoull(&s[0], nullptr, 16);
|
||||
}
|
||||
|
||||
uint64_t to_uint64(const nlohmann::json& j)
|
||||
{
|
||||
string s = j;
|
||||
return strtoull(&s[0], nullptr, 16);
|
||||
return to_uint64(string(j));
|
||||
}
|
||||
|
||||
vector<uint8_t> to_bytes(const string& _s)
|
||||
|
|
|
@ -15,10 +15,10 @@ namespace evm
|
|||
|
||||
struct Account
|
||||
{
|
||||
Address address;
|
||||
uint64_t nonce;
|
||||
uint256_t balance;
|
||||
Code code;
|
||||
Address address = {};
|
||||
uint64_t nonce = {};
|
||||
uint256_t balance = {};
|
||||
Code code = {};
|
||||
|
||||
Account() = default;
|
||||
Account(
|
||||
|
|
|
@ -111,6 +111,22 @@ namespace evm
|
|||
return to_hex_string(bytes.begin(), bytes.end());
|
||||
}
|
||||
|
||||
inline std::string to_hex_string(uint64_t v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
inline auto address_to_hex_string(const Address& v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::setw(40) << std::setfill('0') << v;
|
||||
auto s = ss.str();
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string to_checksum_address(const Address& a)
|
||||
{
|
||||
auto s = to_lower_hex_str(a);
|
||||
|
@ -142,4 +158,5 @@ namespace evm
|
|||
Address generate_address(const Address& sender, uint64_t nonce);
|
||||
|
||||
uint64_t to_uint64(const nlohmann::json& j);
|
||||
uint64_t to_uint64(const std::string& s);
|
||||
} // namespace evm
|
||||
|
|
|
@ -19,12 +19,10 @@ using namespace nlohmann;
|
|||
|
||||
pair<Account, SimpleStorage> parseAccount(json::const_iterator& it)
|
||||
{
|
||||
auto j = it.value();
|
||||
return {{from_hex_str(it.key()),
|
||||
to_uint64(j["nonce"]),
|
||||
j["balance"].get<uint256_t>(),
|
||||
to_bytes(j["code"])},
|
||||
j["storage"]};
|
||||
auto storage = it.value()["storage"];
|
||||
auto account = it.value().get<Account>();
|
||||
account.address = from_hex_str(it.key());
|
||||
return {account, storage};
|
||||
}
|
||||
|
||||
void run_test_case(
|
||||
|
|
|
@ -10,10 +10,66 @@
|
|||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include <doctest/doctest.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "../include/bigint.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace evm;
|
||||
|
||||
TEST_CASE("from_json/to_json are mutually inverse")
|
||||
{
|
||||
constexpr auto env_var = "TEST_DIR";
|
||||
auto test_dir = getenv(env_var);
|
||||
if (!test_dir) {
|
||||
throw std::logic_error(
|
||||
"Must set path to test cases in " + std::string(env_var) +
|
||||
" environment variable");
|
||||
}
|
||||
SUBCASE("Using default Account objects")
|
||||
{
|
||||
Account a1;
|
||||
nlohmann::json j = a1;
|
||||
Account a2 = j.get<Account>();
|
||||
REQUIRE(a1 == a2);
|
||||
}
|
||||
SUBCASE("Using non-default values for Account")
|
||||
{
|
||||
Account a1;
|
||||
a1.address = from_hex_str("0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
|
||||
a1.nonce = to_uint64(string("0x66"));
|
||||
nlohmann::json j = a1;
|
||||
Account a2 = j;
|
||||
REQUIRE(a1 == a2);
|
||||
}
|
||||
SUBCASE("Using partially defined JSON as a source for Account")
|
||||
{
|
||||
auto test_path = string(test_dir) + "/vmTests.json";
|
||||
const auto j = nlohmann::json::parse(std::ifstream(test_path));
|
||||
const auto rec = *j["suicide"]["pre"].begin();
|
||||
Account a1 = rec.get<Account>();
|
||||
nlohmann::json j2 = a1;
|
||||
if (rec.find("balance") != rec.end())
|
||||
CHECK(a1.balance == from_hex_str(j2["balance"]));
|
||||
if (rec.find("code") != rec.end())
|
||||
CHECK(a1.code == to_bytes(j2["code"]));
|
||||
if (rec.find("nonce") != rec.end())
|
||||
CHECK(a1.nonce == to_uint64(j2["nonce"]));
|
||||
if (rec.find("address") != rec.end())
|
||||
CHECK(a1.address == from_hex_str(j2["address"]));
|
||||
}
|
||||
SUBCASE("Using fully defined JSON as a source for Account")
|
||||
{
|
||||
auto test_path = string(test_dir) + "/accountFull.json";
|
||||
const auto j = nlohmann::json::parse(std::ifstream(test_path));
|
||||
Account a1 = j.get<Account>();
|
||||
nlohmann::json j2 = a1;
|
||||
REQUIRE(j == j2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("util" * doctest::test_suite("util"))
|
||||
{
|
||||
SUBCASE("to_bytes")
|
||||
|
|
Загрузка…
Ссылка в новой задаче