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

consensus, core, tests: implement Metropolis EIP 649 #15028

Merged
merged 1 commit into from Aug 25, 2017
Jump to file or symbol
Failed to load files and symbols.
+50 −129
Diff settings

Always

Just for now

consensus, core, tests: implement Metropolis EIP 649

  • Loading branch information...
karalabe committed Aug 24, 2017
commit b872961ec82ec88a7ac6ef331cfb3eb685ce2c00
Copy path View file
@@ -36,8 +36,9 @@ import (
// Ethash proof-of-work protocol constants.
var (
blockReward *big.Int = big.NewInt(5e+18) // Block reward in wei for successfully mining a block
maxUncles = 2 // Maximum number of uncles allowed in a single block
frontierBlockReward *big.Int = big.NewInt(5e+18) // Block reward in wei for successfully mining a block
metropolisBlockReward *big.Int = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Metropolis
maxUncles = 2 // Maximum number of uncles allowed in a single block
)
// Various error messages to mark blocks invalid. These should be private to
@@ -306,6 +307,7 @@ var (
big9 = big.NewInt(9)
big10 = big.NewInt(10)
bigMinus99 = big.NewInt(-99)
big2999999 = big.NewInt(2999999)
)
// calcDifficultyMetropolis is the difficulty adjustment algorithm. It returns
@@ -346,8 +348,15 @@ func calcDifficultyMetropolis(time uint64, parent *types.Header) *big.Int {
if x.Cmp(params.MinimumDifficulty) < 0 {
x.Set(params.MinimumDifficulty)
}
// calculate a fake block numer for the ice-age delay:
// https://github.com/ethereum/EIPs/pull/669
// fake_block_number = min(0, block.number - 3_000_000
fakeBlockNumber := new(big.Int)
if parent.Number.Cmp(big2999999) >= 0 {
fakeBlockNumber = fakeBlockNumber.Sub(parent.Number, big2999999) // Note, parent is 1 less than the actual block number
}
// for the exponential factor
periodCount := new(big.Int).Add(parent.Number, big1)
periodCount := fakeBlockNumber
periodCount.Div(periodCount, expDiffPeriod)
// the exponential factor, commonly referred to as "the bomb"
@@ -501,7 +510,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header)
// setting the final state and assembling the block.
func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
// Accumulate any block and uncle rewards and commit the final state root
AccumulateRewards(state, header, uncles)
AccumulateRewards(chain.Config(), state, header, uncles)
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
// Header seems complete, assemble into a block and return
@@ -518,7 +527,13 @@ var (
// reward. The total reward consists of the static block reward and rewards for
// included uncles. The coinbase of each uncle block is also rewarded.
// TODO (karalabe): Move the chain maker into this package and make this private!
func AccumulateRewards(state *state.StateDB, header *types.Header, uncles []*types.Header) {
func AccumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
// Select the correct block reward based on chain progression
blockReward := frontierBlockReward
if config.IsMetropolis(header.Number) {
blockReward = metropolisBlockReward
}
// Accumulate the rewards for the miner and any included uncles
reward := new(big.Int).Set(blockReward)
r := new(big.Int)
for _, uncle := range uncles {
Copy path View file
@@ -179,7 +179,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, db ethdb.Dat
if gen != nil {
gen(i, b)
}
ethash.AccumulateRewards(statedb, h, b.uncles)
ethash.AccumulateRewards(config, statedb, h, b.uncles)
root, err := statedb.CommitTo(db, config.IsEIP158(h.Number))
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
Copy path View file
@@ -128,18 +128,14 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
}
// capture SSTORE opcodes and determine the changed value and store
// it in the local storage container. NOTE: we do not need to do any
// range checks here because that's already handler prior to calling
// this function.
switch op {
case SSTORE:
// it in the local storage container.
if op == SSTORE && stack.len() >= 2 {
var (
value = common.BigToHash(stack.data[stack.len()-2])
address = common.BigToHash(stack.data[stack.len()-1])
)
l.changedValues[contract.Address()][address] = value
}
// copy a snapstot of the current memory state to a new buffer
var mem []byte
if !l.cfg.DisableMemory {
Copy path View file

This file was deleted.

Oops, something went wrong.
Copy path View file
@@ -17,12 +17,10 @@
package tests
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"reflect"
"strings"
"github.com/ethereum/go-ethereum/common"
@@ -33,8 +31,10 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
// StateTest checks transaction processing without block context.
@@ -63,7 +63,7 @@ type stJSON struct {
type stPostState struct {
Root common.UnprefixedHash `json:"hash"`
Logs *[]stLog `json:"logs"`
Logs common.UnprefixedHash `json:"logs"`
Indexes struct {
Data int `json:"data"`
Gas int `json:"gas"`
@@ -108,21 +108,6 @@ type stTransactionMarshaling struct {
PrivateKey hexutil.Bytes
}
//go:generate gencodec -type stLog -field-override stLogMarshaling -out gen_stlog.go
type stLog struct {
Address common.Address `json:"address"`
Data []byte `json:"data"`
Topics []common.Hash `json:"topics"`
Bloom string `json:"bloom"`
}
type stLogMarshaling struct {
Address common.UnprefixedAddress
Data hexutil.Bytes
Topics []common.UnprefixedHash
}
// Subtests returns all valid subtests of the test.
func (t *StateTest) Subtests() []StateSubtest {
var sub []StateSubtest
@@ -159,10 +144,8 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) error {
if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
statedb.RevertToSnapshot(snapshot)
}
if post.Logs != nil {
if err := checkLogs(statedb.Logs(), *post.Logs); err != nil {
return err
}
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
}
root, _ := statedb.CommitTo(db, config.IsEIP158(block.Number()))
if root != common.Hash(post.Root) {
@@ -254,28 +237,9 @@ func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) {
return msg, nil
}
func checkLogs(have []*types.Log, want []stLog) error {
if len(have) != len(want) {
return fmt.Errorf("logs length mismatch: got %d, want %d", len(have), len(want))
}
for i := range have {
if have[i].Address != want[i].Address {
return fmt.Errorf("log address %d: got %x, want %x", i, have[i].Address, want[i].Address)
}
if !bytes.Equal(have[i].Data, want[i].Data) {
return fmt.Errorf("log data %d: got %x, want %x", i, have[i].Data, want[i].Data)
}
if !reflect.DeepEqual(have[i].Topics, want[i].Topics) {
return fmt.Errorf("log topics %d:\ngot %x\nwant %x", i, have[i].Topics, want[i].Topics)
}
genBloom := math.PaddedBigBytes(types.LogsBloom([]*types.Log{have[i]}), 256)
var wantBloom types.Bloom
if err := hexutil.UnmarshalFixedUnprefixedText("Bloom", []byte(want[i].Bloom), wantBloom[:]); err != nil {
return fmt.Errorf("test log %d has invalid bloom: %v", i, err)
}
if !bytes.Equal(genBloom, wantBloom[:]) {
return fmt.Errorf("bloom mismatch")
}
}
return nil
func rlpHash(x interface{}) (h common.Hash) {
hw := sha3.NewKeccak256()
rlp.Encode(hw, x)
hw.Sum(h[:0])
return h
}
Submodule testdata updated 3016 files
Copy path View file
@@ -26,6 +26,10 @@ func TestVM(t *testing.T) {
t.Parallel()
vmt := new(testMatcher)
vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution")
vmt.skipLoad(`^vmPerformanceTest.json`) // log format broken
vmt.skipLoad(`^vmInputLimits(Light)?.json`) // log format broken
vmt.skipShortMode("^vmPerformanceTest.json")
vmt.skipShortMode("^vmInputLimits(Light)?.json")
Copy path View file
@@ -44,14 +44,14 @@ func (t *VMTest) UnmarshalJSON(data []byte) error {
}
type vmJSON struct {
Env stEnv `json:"env"`
Exec vmExec `json:"exec"`
Logs []stLog `json:"logs"`
GasRemaining *math.HexOrDecimal64 `json:"gas"`
Out hexutil.Bytes `json:"out"`
Pre core.GenesisAlloc `json:"pre"`
Post core.GenesisAlloc `json:"post"`
PostStateRoot common.Hash `json:"postStateRoot"`
Env stEnv `json:"env"`
Exec vmExec `json:"exec"`
Logs common.UnprefixedHash `json:"logs"`

This comment has been minimized.

@fjl

fjl Aug 24, 2017

Contributor

Please remove the logs check so we can merge.

This comment has been minimized.

@karalabe

karalabe Aug 24, 2017

Member

I'll wait to see how many fail (just updates the test suite), and will disable only the failing tests (so we're not overly zealous and accidentally miss consensus issues).

GasRemaining *math.HexOrDecimal64 `json:"gas"`
Out hexutil.Bytes `json:"out"`
Pre core.GenesisAlloc `json:"pre"`
Post core.GenesisAlloc `json:"post"`
PostStateRoot common.Hash `json:"postStateRoot"`
}
//go:generate gencodec -type vmExec -field-override vmExecMarshaling -out gen_vmexec.go
@@ -109,7 +109,10 @@ func (t *VMTest) Run(vmconfig vm.Config) error {
// if root := statedb.IntermediateRoot(false); root != t.json.PostStateRoot {
// return fmt.Errorf("post state root mismatch, got %x, want %x", root, t.json.PostStateRoot)
// }
return checkLogs(statedb.Logs(), t.json.Logs)
if logs := rlpHash(statedb.Logs()); logs != common.Hash(t.json.Logs) {
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, t.json.Logs)
}
return nil
}
func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) {
ProTip! Use n and p to navigate between commits in a pull request.