Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: EIP-4844 part 4 #1536

Merged
merged 10 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cmd/dev/snapshots.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ static void print_header(const BlockHeader& header, const std::string& snapshot_
<< "difficulty=" << intx::to_string(header.difficulty) << "\n"
<< "gas_limit=" << header.gas_limit << "\n"
<< "gas_used=" << header.gas_used << "\n"
<< "data_gas_used=" << (header.data_gas_used ? *header.data_gas_used : 0) << "\n"
<< "excess_data_gas=" << (header.excess_data_gas ? *header.excess_data_gas : 0) << "\n"
<< "blob_gas_used=" << header.blob_gas_used.value_or(0) << "\n"
<< "excess_blob_gas=" << header.excess_blob_gas.value_or(0) << "\n"
<< "logs_bloom=" << to_hex(header.logs_bloom) << "\n"
<< "extra_data=" << to_hex(header.extra_data) << "\n"
<< "rlp=" << to_hex([&]() { Bytes b; rlp::encode(b, header); return b; }()) << "\n";
Expand Down Expand Up @@ -496,7 +496,7 @@ static void print_txn(const Transaction& txn, const std::string& snapshot_filena
<< "value=" << intx::to_string(txn.value) << "\n"
<< "gas_limit=" << txn.gas_limit << "\n"
<< "max_fee_per_gas=" << intx::to_string(txn.max_fee_per_gas) << "\n"
<< "max_fee_per_data_gas=" << intx::to_string(txn.max_fee_per_data_gas) << "\n"
<< "max_fee_per_blob_gas=" << intx::to_string(txn.max_fee_per_blob_gas) << "\n"
<< "max_priority_fee_per_gas=" << intx::to_string(txn.max_priority_fee_per_gas) << "\n"
<< "odd_y_parity=" << txn.odd_y_parity << "\n"
<< "v=" << intx::to_string(txn.v()) << "\n"
Expand Down
4 changes: 2 additions & 2 deletions cmd/dev/toolbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ static void print_header(const BlockHeader& header) {
<< "difficulty=" << intx::to_string(header.difficulty) << "\n"
<< "gas_limit=" << header.gas_limit << "\n"
<< "gas_used=" << header.gas_used << "\n"
<< "data_gas_used=" << (header.data_gas_used ? *header.data_gas_used : 0) << "\n"
<< "excess_data_gas=" << (header.excess_data_gas ? *header.excess_data_gas : 0) << "\n"
<< "blob_gas_used=" << header.blob_gas_used.value_or(0) << "\n"
<< "excess_blob_gas=" << header.excess_blob_gas.value_or(0) << "\n"
<< "logs_bloom=" << to_hex(header.logs_bloom) << "\n"
<< "extra_data=" << to_hex(header.extra_data) << "\n"
<< "rlp=" << to_hex([&]() { Bytes b; rlp::encode(b, header); return b; }()) << "\n";
Expand Down
2 changes: 1 addition & 1 deletion cmd/state-transition/state_transition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ void StateTransition::run() {

auto pre_block_validation = ruleSet->pre_validate_block_body(block, *state);
auto block_validation = ruleSet->validate_block_header(block.header, *state, true);
auto pre_txn_validation = protocol::pre_validate_transaction(txn, rev, config.chain_id, block.header.base_fee_per_gas, block.header.data_gas_price());
auto pre_txn_validation = protocol::pre_validate_transaction(txn, rev, config.chain_id, block.header.base_fee_per_gas, block.header.blob_gas_price());
auto txn_validation = protocol::validate_transaction(txn, processor.evm().state(), processor.available_gas());

// std::cout << "pre: " << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion cmd/test/ethereum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ RunResults transaction_test(const nlohmann::json& j, bool) {

if (ValidationResult err{
pre_validate_transaction(txn, rev, config.chain_id, /*base_fee_per_gas=*/std::nullopt,
/*data_gas_price=*/std::nullopt)};
/*blob_gas_price=*/std::nullopt)};
err != ValidationResult::kOk) {
if (should_be_valid) {
std::cout << "Validation error " << magic_enum::enum_name<ValidationResult>(err) << std::endl;
Expand Down
12 changes: 1 addition & 11 deletions silkworm/core/execution/precompile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,7 @@ inline constexpr std::optional<SupportedContract> kContracts[]{
SupportedContract{{bn_mul_gas, bn_mul_run}, EVMC_BYZANTIUM}, // 0x07
SupportedContract{{snarkv_gas, snarkv_run}, EVMC_BYZANTIUM}, // 0x08
SupportedContract{{blake2_f_gas, blake2_f_run}, EVMC_ISTANBUL}, // 0x09
std::nullopt, // 0x0a
std::nullopt, // 0x0b
std::nullopt, // 0x0c
std::nullopt, // 0x0d
std::nullopt, // 0x0e
std::nullopt, // 0x0f
std::nullopt, // 0x10
std::nullopt, // 0x11
std::nullopt, // 0x12
std::nullopt, // 0x13
SupportedContract{{point_evaluation_gas, point_evaluation_run}, EVMC_CANCUN}, // 0x14
SupportedContract{{point_evaluation_gas, point_evaluation_run}, EVMC_CANCUN}, // 0x0a
};

[[nodiscard]] bool is_precompile(const evmc::address&, evmc_revision) noexcept;
Expand Down
8 changes: 4 additions & 4 deletions silkworm/core/execution/precompile_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ TEST_CASE("is_precompile") {
CHECK(is_precompile(0x0000000000000000000000000000000000000007_address, EVMC_CANCUN) == true);
CHECK(is_precompile(0x0000000000000000000000000000000000000008_address, EVMC_CANCUN) == true);
CHECK(is_precompile(0x0000000000000000000000000000000000000009_address, EVMC_CANCUN) == true);
CHECK(is_precompile(0x000000000000000000000000000000000000000a_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x000000000000000000000000000000000000000a_address, EVMC_CANCUN) == true);
CHECK(is_precompile(0x000000000000000000000000000000000000000b_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x000000000000000000000000000000000000000c_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x000000000000000000000000000000000000000d_address, EVMC_CANCUN) == false);
Expand All @@ -591,7 +591,7 @@ TEST_CASE("is_precompile") {
CHECK(is_precompile(0x0000000000000000000000000000000000000011_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000012_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000013_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000014_address, EVMC_CANCUN) == true);
CHECK(is_precompile(0x0000000000000000000000000000000000000014_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000015_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000016_address, EVMC_CANCUN) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000017_address, EVMC_CANCUN) == false);
Expand All @@ -611,7 +611,7 @@ TEST_CASE("is_precompile") {
CHECK(is_precompile(0x0000000000000000000000000000000000000007_address, EVMC_PRAGUE) == true);
CHECK(is_precompile(0x0000000000000000000000000000000000000008_address, EVMC_PRAGUE) == true);
CHECK(is_precompile(0x0000000000000000000000000000000000000009_address, EVMC_PRAGUE) == true);
CHECK(is_precompile(0x000000000000000000000000000000000000000a_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x000000000000000000000000000000000000000a_address, EVMC_PRAGUE) == true);
CHECK(is_precompile(0x000000000000000000000000000000000000000b_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x000000000000000000000000000000000000000c_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x000000000000000000000000000000000000000d_address, EVMC_PRAGUE) == false);
Expand All @@ -621,7 +621,7 @@ TEST_CASE("is_precompile") {
CHECK(is_precompile(0x0000000000000000000000000000000000000011_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000012_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000013_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000014_address, EVMC_PRAGUE) == true);
CHECK(is_precompile(0x0000000000000000000000000000000000000014_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000015_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000016_address, EVMC_PRAGUE) == false);
CHECK(is_precompile(0x0000000000000000000000000000000000000017_address, EVMC_PRAGUE) == false);
Expand Down
6 changes: 3 additions & 3 deletions silkworm/core/execution/processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ void ExecutionProcessor::execute_transaction(const Transaction& txn, Receipt& re
const intx::uint256 effective_gas_price{txn.effective_gas_price(base_fee_per_gas)};
state_.subtract_from_balance(*txn.from, txn.gas_limit * effective_gas_price);

// EIP-4844 data gas cost (calc_data_fee)
const intx::uint256 data_gas_price{evm_.block().header.data_gas_price().value_or(0)};
state_.subtract_from_balance(*txn.from, txn.total_data_gas() * data_gas_price);
// EIP-4844 blob gas cost (calc_data_fee)
const intx::uint256 blob_gas_price{evm_.block().header.blob_gas_price().value_or(0)};
state_.subtract_from_balance(*txn.from, txn.total_blob_gas() * blob_gas_price);

const intx::uint128 g0{protocol::intrinsic_gas(txn, rev)};
assert(g0 <= UINT64_MAX); // true due to the precondition (transaction must be valid)
Expand Down
20 changes: 10 additions & 10 deletions silkworm/core/protocol/base_rule_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ ValidationResult BaseRuleSet::pre_validate_block_body(const Block& block, const
return ValidationResult::kWrongWithdrawalsRoot;
}

std::optional<uint64_t> data_gas_used{std::nullopt};
std::optional<uint64_t> blob_gas_used{std::nullopt};
if (rev >= EVMC_CANCUN) {
data_gas_used = 0;
blob_gas_used = 0;
for (const Transaction& tx : block.transactions) {
*data_gas_used += tx.total_data_gas();
*blob_gas_used += tx.total_blob_gas();
}
if (data_gas_used > kMaxDataGasPerBlock) {
if (blob_gas_used > kMaxBlobGasPerBlock) {
return ValidationResult::kTooManyBlobs;
}
}
if (header.data_gas_used != data_gas_used) {
return ValidationResult::kWrongDataGasUsed;
if (header.blob_gas_used != blob_gas_used) {
return ValidationResult::kWrongBlobGasUsed;
}

if (block.ommers.empty()) {
Expand Down Expand Up @@ -201,15 +201,15 @@ ValidationResult BaseRuleSet::validate_block_header(const BlockHeader& header, c
}

if (rev < EVMC_CANCUN) {
if (header.data_gas_used || header.excess_data_gas || header.parent_beacon_block_root) {
if (header.blob_gas_used || header.excess_blob_gas || header.parent_beacon_block_root) {
return ValidationResult::kFieldBeforeFork;
}
} else {
if (!header.data_gas_used || !header.excess_data_gas || !header.parent_beacon_block_root) {
if (!header.blob_gas_used || !header.excess_blob_gas || !header.parent_beacon_block_root) {
return ValidationResult::kMissingField;
}
if (header.excess_data_gas != calc_excess_data_gas(*parent)) {
return ValidationResult::kWrongExcessDataGas;
if (header.excess_blob_gas != calc_excess_blob_gas(*parent)) {
return ValidationResult::kWrongExcessBlobGas;
}
}

Expand Down
10 changes: 5 additions & 5 deletions silkworm/core/protocol/param.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ inline constexpr uint64_t kElasticityMultiplier{2};

// EIP-4844: Shard Blob Transactions
inline constexpr uint8_t kBlobCommitmentVersionKzg{1};
inline constexpr uint64_t kMaxDataGasPerBlock{1u << 19};
inline constexpr uint64_t kTargetDataGasPerBlock{1u << 18};
inline constexpr uint64_t kDataGasPerBlob{1u << 17};
inline constexpr uint64_t kMinDataGasPrice{1};
inline constexpr uint64_t kDataGasPriceUpdateFraction{2225652};
inline constexpr uint64_t kBlobGasPerBlob{1u << 17};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just kGasPerBlob can be better?

inline constexpr uint64_t kTargetBlobGasPerBlock{3 * kBlobGasPerBlob};
inline constexpr uint64_t kMaxBlobGasPerBlock{6 * kBlobGasPerBlob};
inline constexpr uint64_t kMinBlobGasPrice{1};
inline constexpr uint64_t kBlobGasPriceUpdateFraction{3338477};

// EIP-4788: Beacon block root in the EVM
inline constexpr uint64_t kSystemCallGasLimit{30'000'000};
Expand Down
28 changes: 14 additions & 14 deletions silkworm/core/protocol/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ bool transaction_type_is_supported(TransactionType type, evmc_revision rev) {

ValidationResult pre_validate_transaction(const Transaction& txn, const evmc_revision rev, const uint64_t chain_id,
const std::optional<intx::uint256>& base_fee_per_gas,
const std::optional<intx::uint256>& data_gas_price) {
const std::optional<intx::uint256>& blob_gas_price) {
if (txn.chain_id.has_value()) {
if (rev < EVMC_SPURIOUS_DRAGON) {
// EIP-155 transaction before EIP-155 was activated
Expand Down Expand Up @@ -101,13 +101,13 @@ ValidationResult pre_validate_transaction(const Transaction& txn, const evmc_rev
return ValidationResult::kWrongBlobCommitmentVersion;
}
}
SILKWORM_ASSERT(data_gas_price);
if (txn.max_fee_per_data_gas < data_gas_price) {
return ValidationResult::kMaxFeePerDataGasTooLow;
SILKWORM_ASSERT(blob_gas_price);
if (txn.max_fee_per_blob_gas < blob_gas_price) {
return ValidationResult::kMaxFeePerBlobGasTooLow;
}
if (!txn.to) {
return ValidationResult::kBlobCreateTransaction;
}
// TODO(yperbasis): There is an equal amount of versioned hashes, kzg commitments and blobs.
// The KZG commitments hash to the versioned hashes, i.e. kzg_to_versioned_hash(kzg[i]) == versioned_hash[i]
// The KZG commitments match the blob contents.
}

return ValidationResult::kOk;
Expand Down Expand Up @@ -147,11 +147,11 @@ ValidationResult validate_transaction(const Transaction& txn, const IntraBlockSt
ValidationResult pre_validate_transactions(const Block& block, const ChainConfig& config) {
const BlockHeader& header{block.header};
const evmc_revision rev{config.revision(header.number, header.timestamp)};
const std::optional<intx::uint256> data_gas_price{header.data_gas_price()};
const std::optional<intx::uint256> blob_gas_price{header.blob_gas_price()};

for (const Transaction& txn : block.transactions) {
ValidationResult err{pre_validate_transaction(txn, rev, config.chain_id,
header.base_fee_per_gas, data_gas_price)};
header.base_fee_per_gas, blob_gas_price)};
if (err != ValidationResult::kOk) {
return err;
}
Expand Down Expand Up @@ -192,14 +192,14 @@ intx::uint256 expected_base_fee_per_gas(const BlockHeader& parent) {
}
}

uint64_t calc_excess_data_gas(const BlockHeader& parent) {
const uint64_t parent_excess_data_gas{parent.excess_data_gas.value_or(0)};
const uint64_t consumed_data_gas{parent.data_gas_used.value_or(0)};
uint64_t calc_excess_blob_gas(const BlockHeader& parent) {
const uint64_t parent_excess_blob_gas{parent.excess_blob_gas.value_or(0)};
const uint64_t consumed_blob_gas{parent.blob_gas_used.value_or(0)};

if (parent_excess_data_gas + consumed_data_gas < kTargetDataGasPerBlock) {
if (parent_excess_blob_gas + consumed_blob_gas < kTargetBlobGasPerBlock) {
return 0;
} else {
return parent_excess_data_gas + consumed_data_gas - kTargetDataGasPerBlock;
return parent_excess_blob_gas + consumed_blob_gas - kTargetBlobGasPerBlock;
}
}

Expand Down
11 changes: 6 additions & 5 deletions silkworm/core/protocol/validation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,13 @@ enum class [[nodiscard]] ValidationResult{
kWrongWithdrawalsRoot,

// EIP-4844: Shard Blob Transactions
kWrongDataGasUsed,
kWrongExcessDataGas,
kWrongBlobGasUsed,
kWrongExcessBlobGas,
kNoBlobs,
kTooManyBlobs,
kWrongBlobCommitmentVersion,
kMaxFeePerDataGasTooLow, // max_fee_per_data_gas < data_gas_price
kMaxFeePerBlobGasTooLow, // max_fee_per_blob_gas < blob_gas_price
kBlobCreateTransaction, // Blob transactions cannot have the form of a create transaction
};

namespace protocol {
Expand All @@ -112,7 +113,7 @@ namespace protocol {
//! \remarks These function is agnostic to whole block validity
ValidationResult pre_validate_transaction(const Transaction& txn, evmc_revision revision, uint64_t chain_id,
const std::optional<intx::uint256>& base_fee_per_gas,
const std::optional<intx::uint256>& data_gas_price);
const std::optional<intx::uint256>& blob_gas_price);

ValidationResult pre_validate_transactions(const Block& block, const ChainConfig& config);

Expand All @@ -128,7 +129,7 @@ namespace protocol {
intx::uint256 expected_base_fee_per_gas(const BlockHeader& parent);

//! \see EIP-4844: Shard Blob Transactions
uint64_t calc_excess_data_gas(const BlockHeader& parent);
uint64_t calc_excess_blob_gas(const BlockHeader& parent);

//! \brief Calculate the transaction root of a block body
evmc::bytes32 compute_transaction_root(const BlockBody& body);
Expand Down
Loading