The fee split braided two independent concerns into one line: how much of a
fee is kept (a protocol constant, floor(fee/2)) and where the kept part goes
(compiled-in extras.FeeRewardVault = 0x0100..02). The second half made the
destination ungovernable and silently bypassed the RewardManager precompile
the moment FeeSplit activated, so turning the burn on would have DISABLED the
one on-chain knob the chain already has.
Split the concerns:
ratio -> stays a right shift. Fixed, auditable, not settable by any
transaction. Changing it remains a release plus a coordinated
fork, deliberately: monetary policy should not move at the
speed of a multisig.
destination -> the configured coinbase, i.e. BlockChain.GetCoinbaseAt, i.e.
the RewardManager precompile's stored address. Already part of
header validity (dummy.verifyCoinbase), so it is verifiable
from the header and movable by one admin transaction.
creditTxFee collapses to one credit site; extras.FeeRewardVault is deleted.
Also adds the ordering gate this created a need for: ChainConfig.Verify now
refuses a config that schedules feeSplitTimestamp while rewardManagerConfig is
not enabled at that time (and allowFeeRecipients is off). Without RewardManager
GetCoinbaseAt falls back to the keyless blackhole, so such a config would burn
half of every fee and strand the other half forever -- the C-Chain already has
~3867 LUX stuck at that address. mainnet/cchain.json currently ships exactly
that shape (feeSplitTimestamp 1785715200, no rewardManagerConfig in any of the
49 precompileUpgrades); the node will now refuse to start on it instead.
This is a no-op on every live chain: mainnet 96369's running config has no
feeSplitTimestamp at all (eth_getChainConfig), the vault balance is 0, and the
branch has never executed. The correction is free today and costs a fork later.
Tests:
core: destination follows the configured coinbase; a redirect mid-chain moves
the whole reward stream while the burn is unchanged; supply conservation
on executed blocks; genesis refuses the ungoverned shape.
dummy: a proposer naming any other coinbase is rejected with ErrInvalidCoinbase,
so crediting the header coinbase is not a validator-capture hole.
extras: the verbatim upgrade.json fragment activating rewardManagerConfig and
feeManagerConfig with the DAO Safe as adminAddresses parses through the
registry, and feeManager's governable surface contains no ratio.
Co-authored-by: Hanzo Dev <[email protected]>
Consensus
Disclaimer: the consensus package in evm is a complete misnomer.
The consensus package in go-ethereum handles block validation and specifically handles validating the PoW portion of consensus - thus the name.
Since Luxd handles consensus for EVM, EVM is just the VM, but we keep the consensus package in place to handle part of the block verification process.
Block Verification
The dummy consensus engine is responsible for performing verification on the header of a block. The engine verifies that all of the fields of the header are correct.
Dynamic Fees
EVM includes a dynamic fee algorithm based off of (EIP-1559)[https://eips.ethereum.org/EIPS/eip-1559]. This introduces a field to the block type called BaseFee. The Base Fee sets a minimum gas price for any transaction to be included in the block. For example, a transaction with a gas price of 49 gwei, will be invalid to include in a block with a base fee of 50 gwei.
The dynamic fee algorithm aims to adjust the base fee to handle network congestion. EVM sets a target utilization on the network, and the dynamic fee algorithm adjusts the base fee accordingly. If the network operates above the target utilization, the dynamic fee algorithm will increase the base fee to make utilizing the network more expensive and bring overall utilization down. If the network operates below the target utilization, the dynamic fee algorithm will decrease the base fee to make it cheaper to use the network.
- EIP-1559 is intended for Ethereum where a block is produced roughly every 10s
- The dynamic fee algorithm needs to handle the case that the network quiesces and there are no blocks for a long period of time
- Since EVM produces blocks at a different cadence, it adapts EIP-1559 to sum the amount of gas consumed within a 10-second interval instead of using only the amount of gas consumed in the parent block
Consensus Engine Callbacks
The consensus engine is called while blocks are being both built and processed and EVM adds callback functions into the dummy consensus engine to insert its own logic into these stages.
FinalizeAndAssemble
The FinalizeAndAssemble callback is used as the final step in building a block within the miner package.
Finalize
Finalize is called as the final step in processing a block here. Since either Finalize or FinalizeAndAssemble are called, but not both, when building or verifying/processing a block they need to perform the exact same processing/verification step to ensure that a block produced by the miner where FinalizeAndAssemble is called will be processed and verified in the same way when Finalize gets called.