Skip to content

Commit

Permalink
feat: brioche hard fork; halving block reward (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
egonspace authored May 29, 2024
2 parents cadf54b + 05a8ba2 commit 4fabf50
Show file tree
Hide file tree
Showing 23 changed files with 1,003 additions and 164 deletions.
50 changes: 49 additions & 1 deletion build/checksums.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,52 @@ e9cb6f691e62a4d8b28dd52d2eab57cca72acfd5083b3c5417a72d2eb64def09 golangci-lint-
d058dfb0c7fbd73be70f285d3f8d4d424192fe9b19760ddbb0b2c4b743b8656c golangci-lint-1.49.0-windows-amd64.zip
c049d80297228db7065eabeac5114f77f04415dcd9b944e8d7c6426d9dd6e9dd golangci-lint-1.49.0-windows-arm64.zip
ec9164bab7134ddb94f51c17fd37c109b0801ecd5494b6c0e27ca7898fbd7469 golangci-lint-1.49.0-windows-armv6.zip
68fd9e880d98073f436c58b6f6d2c141881ef49b06ca31137bc19da4e4e3b996 golangci-lint-1.49.0-windows-armv7.zip
68fd9e880d98073f436c58b6f6d2c141881ef49b06ca31137bc19da4e4e3b996 golangci-lint-1.49.0-windows-armv7.zip

01301af199161c5ea33a0350581e1bed43289a56b2fbed7539f99fca2f898278 golangci-lint-1.54.2-freebsd-amd64.tar.gz
03f1962e95066105476b8eb88b5685a95aba8ee0b41f5e986f2a61a4e1834738 golangci-lint-1.54.2-linux-mips64le.tar.gz
0a57b225c621b465bd67b7cab87e9e13063704468eb382653b5c163ec23abaa4 golangci-lint-1.54.2-windows-armv6.zip
1762e02abd5d2d7997c04682d8efe9faaa23760fa73b8a50cffc57e68f1b1173 golangci-lint-1.54.2-linux-386.deb
17c9ca05253efe833d47f38caf670aad2202b5e6515879a99873fabd4c7452b3 golangci-lint-1.54.2-linux-amd64.tar.gz
18172629827a2d595fff6a9933d9d20dc8e8ec140ad00a38e4d5723dcb7ed305 golangci-lint-1.54.2-linux-armv6.deb
19b389bc965b1fc687087dc34f09e7188f582d106c88c6c506b384be1e6656f6 golangci-lint-1.54.2-linux-amd64.rpm
2268895575ac5921633c8dd94844dea5765f1011c7814bcb73429120849a8f67 golangci-lint-1.54.2-linux-mips64le.deb
2e1a11787b08137ba16c3be6ab87de3ef5de470758b7a42441497f259e8e5a1d golangci-lint-1.54.2-windows-386.zip
30e7440fa14e2a9f4a9b9b825c61c1d6858073c74ea0aba3b2d42f08a81f4c4b golangci-lint417421bc38ff51dc18a75aa132df94a67ea078b2af2d973cdf3b1badca4b58bc golangci-lint-1.54.2-linux-ppc64le.tar.gz
42eb5bf1c935eb98f6c9ee1ce282ca0abe48475ea6bc8f682967855bd0bc5bdc golangci-lint-1.54.2-linux-mips64.rpm
50aaf3eb9b51efd2cb8ebab91725fbb1fae55d3399b66b3733118facb5087828 golangci-lint-1.54.2-source.tar.gz
522d26f9f2fefa28cc229d4acdef47e436637b7c5eaec4426217afa9061825c0 golangci-lint-1.54.2-linux-ppc64le.deb
58e0cd3b77cf0d30f59be804796a7fcae96b9fbd80c0ca7c824ec4b09de804c0 golangci-lint-1.54.2-linux-386.rpm
6a324882e39b47939b8bec23f04449c730123c9d2ff771c3f40942ab37a26d8d golangci-lint-1.54.2-windows-arm64.zip
7038b5c5cd477efbb1c828fbdf075704033f96f33598d72765f23aa87c286583 golangci-lint-1.54.2-linux-arm64.rpm
78c9f1acc357b8f9ba2a57dac40d61a091299877b1eeef6d1599f8a8715c023e golangci-lint-1.54.2-linux-loong64.tar.gz
7b11ea9de9aad90e55c66434a8a4cd30da0792b45e12a4bb5fbfd684042176fe golangci-lint-1.54.2-freebsd-armv6.tar.gz
7b33fb1be2f26b7e3d1f3c10ce9b2b5ce6d13bb1d8468a4b2ba794f05b4445e1 golangci-lint-1.54.2-darwin-arm64.tar.gz
7ce3a9e62a8835907300830aa9ac3c2e8e424c2bf98a4dcfe7e5221bd0272a89 golangci-lint-1.54.2-linux-riscv64.rpm
7eda41281f5fd722f4b60c86259bd6ece5eeef08d94c73e55987b45763d5ac9f golangci-lint-1.54.2-freebsd-armv7.tar.gz
8125ce58581d795356a09c71f82ce4fb9368e06b7ce393676907661b62c1c55b golangci-lint-1.54.2-linux-riscv64.tar.gz
839b4b620f75d9d827ec4f7ed1cf592f730a3fc5c6e2bf01f64c03ddd8d4d76c golangci-lint-1.54.2-netbsd-386.tar.gz
85674f50113bb49ffae80733b4ad493c7b58a6031ee7ded3fda2a0ae1bf94c88 golangci-lint-1.54.2-linux-loong64.rpm
860e2ab2453e7fa81d28487b91b6e479d9414baa464abac8ce1bb8f203affeec golangci-lint-1.54.2-linux-s390x.deb
8b3e8c296a9714641961e87403e4865787f16bfdce6e1ea31d46978cfbdb64e7 golangci-lint-1.54.2-linux-arm64.deb
8e42c8204dc2441b5f6873032f1f674b6b6946042d759bc244194d14da8ee7c5 golangci-lint-1.54.2-linux-riscv64.deb
8e8754108de4d8accf6bf209780b8a31ffee0d04eff6393e5a3c84c84991cd39 golangci-lint-1.54.2-linux-s390x.tar.gz
8fc12d9ab18982968a568619290c02c6a9622e29eb475db8b6eac4c1ffc1121a golangci-lint-1.54.2-linux-mips64.deb
9124be2628a93e4d4a65bf48dd049f85c20d1236e66ac321169490745f5de20e golangci-lint-1.54.2-netbsd-armv6.tar.gz
925c4097eae9e035b0b052a66d0a149f861e2ab611a4e677c7ffd2d4e05b9b89 golangci-lint-1.54.2-darwin-amd64.tar.gz
9db1154c2bfdab52822afb7ea8d505ef9e3d519402258f93a9809f4b871b9446 golangci-lint-1.54.2-freebsd-386.tar.gz
9fadc9ed7fe9a2c3abcb9113a580004d3262dbdef0d44d4271d1b7ad89657e7b golangci-lint-1.54.2-linux-s390x.rpm
a0fb8740e9771ff0b96511b04017940ada4c3d1e07b2e3c246a5078514c1be9e golangci-lint-1.54.2-illumos-amd64.tar.gz
a47ed1a6473ff9ccd2cc29d85fc197b6718fad8afcec3ae804070002f5d5f8a8 golangci-lint-1.54.2-netbsd-amd64.tar.gz
a9f14b33473c65fcfbf411ec054b53a87dbb849f4e09ee438f1ee76dbf3f3d4e golangci-lint-1.54.2-linux-arm64.tar.gz
abf8e2164bca508ab68e520ca51e887ca26498ff4c57e904a27cce05b426c81d golangci-lint-1.54.2-lintae6c9e000cdac4f39b64d01b4e8091a1600d97ffccbd1883a342e4693aade68f golangci-lint-1.54.2-linux-mips64le.rpm
b6352e83cc781c5f7e7b74d1e0e6dc137a9a200c3e852bb14009c01b8b19a7b1 golangci-lint-1.54.2-linux-armv6.tar.gz
c3a693f657488a928fc0bdd76ea242b33e2b0e77748b1f31db8a85eb84cf7954 golangci-lint-1.54.2-linux-ppc64le.rpm
c5fd737f6e3c49e168ff764b48ad4c212131d933538aa5973a60d85b8d030926 golangci-lint-1.54.2-linux-armv7.tar.gz
ce17d122f3f93e0a9e52009d2c03cc1c1a1ae28338c2702a1f53eccd10a1afa3 golangci-lint-1.54.2-windows-amd64.zip
d00b58c3fea03e314b5f0f8680606781d3c3a3428e6a4c8645997d537acd1992 golangci-lint-1.54.2-linux-mips64.tar.gz
e3091e11f040a7177f6c227514b61301189fb1bf37f4fb9da2efa041456ab81d golangci-lint-1.54.2-linux-armv7.deb
e4cfe85c6e39b7dab9d8b7f668222d9066ee8f064cd3dbd4153d15b280d636f4 golangci-lint-1.54.2-netbsd-armv7.tar.gz
f0df36248c26e30f8dd516ffc0f2158d450df733f684ddd429e3aa2d5cc23bfb golangci-lint-1.54.2-linux-armv6.rpm
f2b801c93ccfbd3d17132360f632c0281f78e5780f02727115172a33afd0b08e golangci-lint-1.54.2-linux-loong64.deb
f67b8fa171605747da66f93892257337d7ae71be59ca7b07548555f025abe836 golangci-lint-1.54.2-linux-386.tar.gz
2 changes: 1 addition & 1 deletion build/ci.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func doLint(cmdline []string) {

// downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string {
const version = "1.49.0"
const version = "1.54.2"

csdb := build.MustLoadChecksums("build/checksums.txt")
arch := runtime.GOARCH
Expand Down
12 changes: 4 additions & 8 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import (
var (
FrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block
ByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
WemixBlockReward = big.NewInt(0) // Block reward in wei for Wemix
ConstantinopleBlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
maxUncles = 2 // Maximum number of uncles allowed in a single block
allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
Expand Down Expand Up @@ -609,6 +608,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
if err := accumulateRewards(chain.Config(), state, header, uncles); err != nil {
return err
}

header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
return nil
}
Expand Down Expand Up @@ -698,22 +698,18 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
}
state.AddBalance(header.Coinbase, reward)
} else {
blockReward = WemixBlockReward
coinbase, rewards, err := wemixminer.CalculateRewards(
header.Number, blockReward, header.Fees,
rewards, err := wemixminer.CalculateRewards(
config, header.Number, header.Fees,
func(addr common.Address, amt *big.Int) {
state.AddBalance(addr, amt)
})
if err == nil {
header.Rewards = rewards
if coinbase != nil {
header.Coinbase = *coinbase
}
} else {
if err == wemixminer.ErrNotInitialized {
reward := new(big.Int)
if header.Fees != nil {
reward.Add(blockReward, header.Fees)
reward.Add(reward, header.Fees)
}
state.AddBalance(header.Coinbase, reward)
return nil
Expand Down
8 changes: 3 additions & 5 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package core

import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
Expand Down Expand Up @@ -80,14 +79,11 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned.
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, fees *big.Int) error {
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
header := block.Header()
if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
}
if !wemixminer.IsPoW() && block.Fees().Cmp(fees) != 0 {
return fmt.Errorf("invalid fees collected (remote: %v local: %v)", block.Fees(), fees)
}

// Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true.
Expand All @@ -100,11 +96,13 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
if receiptSha != header.ReceiptHash {
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
}

// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
}

return nil
}

Expand Down
22 changes: 2 additions & 20 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
wemixminer "github.com/ethereum/go-ethereum/wemix/miner"
lru "github.com/hashicorp/golang-lru"
)

Expand Down Expand Up @@ -1608,11 +1607,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
}

// wemix: reward calculation uses governance contract, meaning
// the previous block is required. For fast sync, we need to wait for
// governance is initialized and try again.
retryCount := 2
retry:
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
if err != nil {
return it.index, err
Expand Down Expand Up @@ -1642,13 +1636,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)

// Process block using the parent state as reference point
substart := time.Now()
receipts, logs, usedGas, fees, err := bc.processor.Process(block, statedb, bc.vmConfig)
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
if err != nil {
bc.reportBlock(block, receipts, err)
atomic.StoreUint32(&followupInterrupt, 1)
return it.index, err
}

// Update the metrics touched during block processing
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete, we can mark them
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete, we can mark them
Expand All @@ -1664,18 +1657,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)

// Validate the state using the default validator
substart = time.Now()
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, fees); err != nil {
if retryCount--; !wemixminer.IsPoW() && retryCount > 0 {
// make sure the previous block exists in order to calculate rewards distribution
for try := 100; try > 0; try-- {
if _, _, err := wemixminer.CalculateRewards(block.Number(), big.NewInt(0), big.NewInt(100000000), nil); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
goto retry
}

if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
bc.reportBlock(block, receipts, err)
atomic.StoreUint32(&followupInterrupt, 1)
return it.index, err
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,12 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
if err != nil {
return err
}
receipts, _, usedGas, fees, err := blockchain.processor.Process(block, statedb, vm.Config{})
receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{})
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
}
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, fees)
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
Expand Down
10 changes: 9 additions & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.Prepare(tx.Hash(), len(b.txs))
fees := new(big.Int)
var fees *big.Int
if b.header.Fees != nil {
fees = b.header.Fees // wemix block has `Fees` field
} else {
fees = new(big.Int)
}
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, fees, vm.Config{})
if err != nil {
panic(err)
Expand Down Expand Up @@ -306,6 +311,9 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}
if !wemixminer.IsPoW() {
header.Fees = new(big.Int)
}
if chain.Config().IsLondon(header.Number) {
header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header())
if !chain.Config().IsLondon(parent.Number()) {
Expand Down
24 changes: 16 additions & 8 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
// Process returns the receipts and logs accumulated during the process and
// returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error.
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, *big.Int, error) {
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
var (
receipts types.Receipts
usedGas = new(uint64)
Expand All @@ -77,23 +77,31 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
for i, tx := range block.Transactions() {
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee)
if err != nil {
return nil, nil, 0, big.NewInt(0), fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
statedb.Prepare(tx.Hash(), i)
receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, fees, vmenv)
receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, fees, vmenv)
if err != nil {
return nil, nil, 0, big.NewInt(0), fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
}
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles())
err := p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles())
if err != nil {
return receipts, nil, 0, err
}

header.Fees = fees
if block.Hash() != header.Hash() {
return receipts, nil, 0, fmt.Errorf("remote block hash is different from being processed one locally (remote=%v, local=%v)", block.Header().Hash(), header.Hash())
}

return receipts, allLogs, *usedGas, fees, nil
return receipts, allLogs, *usedGas, nil
}

func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, fees *big.Int, evm *vm.EVM) (*types.Receipt, error) {
func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, fees *big.Int, evm *vm.EVM) (*types.Receipt, error) {
// Create a new context to be used in the EVM environment.
txContext := NewEVMTxContext(msg)
evm.Reset(txContext, statedb)
Expand Down Expand Up @@ -151,5 +159,5 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, fees, vmenv)
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, fees, vmenv)
}
6 changes: 2 additions & 4 deletions core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package core

import (
"math/big"

"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
Expand All @@ -33,7 +31,7 @@ type Validator interface {

// ValidateState validates the given statedb and optionally the receipts and
// gas used.
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64, fees *big.Int) error
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
}

// Prefetcher is an interface for pre-caching transaction signatures and state.
Expand All @@ -49,5 +47,5 @@ type Processor interface {
// Process processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles.
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, *big.Int, error)
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error)
}
3 changes: 3 additions & 0 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ func CopyHeader(h *Header) *Header {
cpy.Rewards = make([]byte, len(h.Rewards))
copy(cpy.Rewards, h.Rewards)
}
if h.Fees != nil {
cpy.Fees = new(big.Int).Set(h.Fees)
}
return &cpy
}

Expand Down
Loading

0 comments on commit 4fabf50

Please sign in to comment.