Skip to content

Commit

Permalink
Do not use json to encode for better performance.
Browse files Browse the repository at this point in the history
  • Loading branch information
yarkinwho committed Feb 26, 2024
1 parent 621ab33 commit 19a18d5
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 72 deletions.
2 changes: 2 additions & 0 deletions eosevm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ target_include_directories(eos_evm PUBLIC ${SILKWORM_MAIN_DIR})

set(EOS_EVM_PUBLIC_LIBS
intx::intx
evmc
tl::expected
nlohmann_json::nlohmann_json
)

Expand Down
69 changes: 68 additions & 1 deletion eosevm/consensus_parameters.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include "consensus_parameters.hpp"

#if not defined(ANTELOPE)
#include <silkworm/core/common/assert.hpp>
#include <silkworm/core/common/endian.hpp>
#endif

namespace eosevm {
bool operator==(const eosevm::GasFeeParameters& a, const eosevm::GasFeeParameters& b) {
return a.gas_codedeposit == b.gas_codedeposit && a.gas_newaccount == b.gas_newaccount &&
Expand All @@ -8,4 +13,66 @@ bool operator==(const eosevm::GasFeeParameters& a, const eosevm::GasFeeParameter

bool operator==(const eosevm::ConsensusParameters& a, const eosevm::ConsensusParameters& b) {
return a.min_gas_price == b.min_gas_price && a.gas_fee_parameters == b.gas_fee_parameters; }
} // namespace eosevm


#if not defined(ANTELOPE)
[[nodiscard]] silkworm::Bytes GasFeeParameters::encode() const noexcept {
silkworm::Bytes ret(40, '\0');
silkworm::endian::store_big_u64(&ret[0], gas_txnewaccount);
silkworm::endian::store_big_u64(&ret[8], gas_newaccount);
silkworm::endian::store_big_u64(&ret[16], gas_txcreate);
silkworm::endian::store_big_u64(&ret[24], gas_codedeposit);
silkworm::endian::store_big_u64(&ret[32], gas_sset);

return ret;
}

std::optional<GasFeeParameters> GasFeeParameters::decode(silkworm::ByteView encoded) noexcept {
SILKWORM_ASSERT(encoded.length() >= 40);
GasFeeParameters feeParams;
feeParams.gas_txnewaccount = silkworm::endian::load_big_u64(&encoded[0]);
feeParams.gas_newaccount = silkworm::endian::load_big_u64(&encoded[8]);
feeParams.gas_txcreate = silkworm::endian::load_big_u64(&encoded[16]);
feeParams.gas_codedeposit = silkworm::endian::load_big_u64(&encoded[24]);
feeParams.gas_sset = silkworm::endian::load_big_u64(&encoded[32]);

return feeParams;
}
#endif

#if not defined(ANTELOPE)
[[nodiscard]] silkworm::Bytes ConsensusParameters::encode() const noexcept {
SILKWORM_ASSERT(min_gas_price.has_value());
SILKWORM_ASSERT(gas_fee_parameters.has_value());
constexpr size_t size_before_fee_param = 2 * sizeof(uint64_t);
auto value = gas_fee_parameters->encode();
silkworm::Bytes ret(value.length() + size_before_fee_param, '\0');
// Always store as latest supported version: currently 0.
silkworm::endian::store_big_u64(&ret[0], 0);
silkworm::endian::store_big_u64(&ret[sizeof(uint64_t)], *min_gas_price);
std::memcpy(&ret[size_before_fee_param], &value[0], value.length());
return ret;
};

std::optional<ConsensusParameters> ConsensusParameters::decode(silkworm::ByteView encoded) noexcept {
SILKWORM_ASSERT(encoded.length() > sizeof(uint64_t));
ConsensusParameters config{};
const auto version = silkworm::endian::load_big_u64(&encoded[0]);

// Parse according to version. For now, only 0.
switch (version) {
case 0: {
constexpr size_t size_before_fee_param = 2 * sizeof(uint64_t);
SILKWORM_ASSERT(encoded.length() > size_before_fee_param);
config.min_gas_price = silkworm::endian::load_big_u64(&encoded[sizeof(uint64_t)]);
config.gas_fee_parameters = GasFeeParameters::decode(silkworm::ByteView{&encoded[size_before_fee_param], encoded.length() - size_before_fee_param});
break;
}
default: SILKWORM_ASSERT(version <= 0);
}

return config;
}
#endif

} // namespace eosevm
77 changes: 12 additions & 65 deletions eosevm/consensus_parameters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@

#include <intx/intx.hpp>


#if not defined(ANTELOPE)
#include <nlohmann/json.hpp>
#include <silkworm/core/common/base.hpp>
#endif


namespace eosevm {

// Note: GasFeeParameters struct is NOT versioned, version will be handled by ConsensusParameters.
// If we want to change this struct, create GasFeeParametersV2 and let ConsensusParameters use it.
struct GasFeeParameters {
// gas_txnewaccount = account_bytes * gas_per_byte
uint64_t gas_txnewaccount;
Expand All @@ -26,40 +29,11 @@ struct GasFeeParameters {
uint64_t gas_sset;

#if not defined(ANTELOPE)
[[nodiscard]] nlohmann::json to_json() const noexcept {
nlohmann::json ret;
ret["gasTxnewaccount"] = gas_txnewaccount;
ret["gasNewaccount"] = gas_newaccount;
ret["gasTxcreate"] = gas_txcreate;
ret["gasCodedeposit"] = gas_codedeposit;
ret["gasSset"] = gas_sset;

return ret;
}
#endif

//! \brief Try parse a JSON object into strongly typed ChainConfig
//! \remark Should this return std::nullopt the parsing has failed
#if not defined(ANTELOPE)

static std::optional<GasFeeParameters> from_json(const nlohmann::json& json) noexcept {
GasFeeParameters feeParams;

if (!json.contains("gasTxnewaccount") || !json.contains("gasNewaccount") || !json.contains("gasTxcreate") ||
!json.contains("gasCodedeposit") || !json.contains("gasSset")) {
// Faii if any of the parameters are missing.
return std::nullopt;
}

feeParams.gas_txnewaccount = json["gasTxnewaccount"].get<uint64_t>();
feeParams.gas_newaccount = json["gasNewaccount"].get<uint64_t>();
feeParams.gas_txcreate = json["gasTxcreate"].get<uint64_t>();
feeParams.gas_codedeposit = json["gasCodedeposit"].get<uint64_t>();
feeParams.gas_sset = json["gasSset"].get<uint64_t>();

return feeParams;
}
// Encode for storage in db.
[[nodiscard]] silkworm::Bytes encode() const noexcept;

// Decode from storage in db.
static std::optional<GasFeeParameters> decode(silkworm::ByteView encoded) noexcept;
#endif

friend bool operator==(const GasFeeParameters&, const GasFeeParameters&);
Expand All @@ -69,42 +43,15 @@ struct ConsensusParameters {
std::optional<uint64_t> min_gas_price;
std::optional<GasFeeParameters> gas_fee_parameters;

//! \brief Return the JSON representation of this object
#if not defined(ANTELOPE)
[[nodiscard]] nlohmann::json to_json() const noexcept {

nlohmann::json ret;
if (min_gas_price) {
ret["minGasPrice"] = min_gas_price.value();
}
if (gas_fee_parameters) {
ret["gasFeeParameters"] = gas_fee_parameters.value().to_json();
}

return ret;
};
#endif

//! \brief Try parse a JSON object into strongly typed ChainConfig
//! \remark Should this return std::nullopt the parsing has failed
#if not defined(ANTELOPE)
static std::optional<ConsensusParameters> from_json(const nlohmann::json& json) noexcept {
ConsensusParameters config{};
if (json.contains("minGasPrice")) {
config.min_gas_price = json["minGasPrice"].get<uint64_t>();
}

if (json.contains("gasFeeParameters")) {
// Can be nullopt if parsing GasFeeParameters failed.
config.gas_fee_parameters = GasFeeParameters::from_json(json["gasFeeParameters"]);
}
// Encode for storage in db.
[[nodiscard]] silkworm::Bytes encode() const noexcept;

return config;
}
// Decode from storage in db.
static std::optional<ConsensusParameters> decode(silkworm::ByteView encoded) noexcept;
#endif

friend bool operator==(const ConsensusParameters&, const ConsensusParameters&);

};

} // namespace eosevm
9 changes: 3 additions & 6 deletions silkworm/node/db/access_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1226,18 +1226,15 @@ std::optional<eosevm::ConsensusParameters> read_consensus_parameters(ROTxn& txn,
if (!data) {
return std::nullopt;
}

// https://github.com/nlohmann/json/issues/2204
const auto json = nlohmann::json::parse(data.value.as_string(), nullptr, false);
return eosevm::ConsensusParameters::from_json(json);
const auto encoded = from_slice(data.value);
return eosevm::ConsensusParameters::decode(encoded);
}

void update_consensus_parameters(RWTxn& txn, BlockNum index, const eosevm::ConsensusParameters& config) {
auto cursor = txn.rw_cursor(table::kConsensusParameters);
auto key{db::block_key(index)};

auto config_data{config.to_json().dump()};
cursor->upsert(to_slice(key), mdbx::slice(config_data.data()));
cursor->upsert(to_slice(key), mdbx::slice(config.encode()));
}

} // namespace silkworm::db

0 comments on commit 19a18d5

Please sign in to comment.