Skip to content

Commit

Permalink
V0.2.12 candidate (ethereum#261)
Browse files Browse the repository at this point in the history
* Fix ancient receipts

* bumped version to 0.2.11

* Genesis change fix (ethereum#252)

* read from genesis file

* add: set code in finalize and assemble

* new: storing data in bor config

* chg: remove unwanted code

* chg: refactor

* minor change

* add error states

* Fix small things

* Add test

* Add more coverage in genesis finalize test

* Ensure balance is not changed

* Add decode safe check

* Change bor config block alloc field name

* Remove block alloc values in blocks

* Add genesis alloc code change info logging

Co-authored-by: Ferran Borreguero <ferranbt@protonmail.com>

* add block alloc

* change block alloc

* remove byte array

* mainnet upgrade

Co-authored-by: Ferran Borreguero <ferranbt@protonmail.com>
Co-authored-by: Sandeep Sreenath <sandeep.sreenath@gmail.com>
Co-authored-by: Jaynti Kanani <jdkanani@gmail.com>
  • Loading branch information
4 people authored Dec 7, 2021
1 parent b633382 commit 39116e6
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 2 deletions.
46 changes: 46 additions & 0 deletions consensus/bor/bor.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@ func New(
WithoutHeimdall: withoutHeimdall,
}

// make sure we can decode all the GenesisAlloc in the BorConfig.
for key, genesisAlloc := range c.config.BlockAlloc {
if _, err := decodeGenesisAlloc(genesisAlloc); err != nil {
panic(fmt.Sprintf("BUG: Block alloc '%s' in genesis is not correct: %v", key, err))
}
}

return c
}

Expand Down Expand Up @@ -675,6 +682,11 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
}
}

if err = c.changeContractCodeIfNeeded(headerNumber, state); err != nil {
log.Error("Error changing contract code", "error", err)
return
}

// No block rewards in PoA, so the state remains as is and uncles are dropped
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.UncleHash = types.CalcUncleHash(nil)
Expand All @@ -684,12 +696,41 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
bc.SetStateSync(stateSyncData)
}

func decodeGenesisAlloc(i interface{}) (core.GenesisAlloc, error) {
var alloc core.GenesisAlloc
b, err := json.Marshal(i)
if err != nil {
return nil, err
}
if err := json.Unmarshal(b, &alloc); err != nil {
return nil, err
}
return alloc, nil
}

func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.StateDB) error {
for blockNumber, genesisAlloc := range c.config.BlockAlloc {
if blockNumber == strconv.FormatUint(headerNumber, 10) {
allocs, err := decodeGenesisAlloc(genesisAlloc)
if err != nil {
return fmt.Errorf("failed to decode genesis alloc: %v", err)
}
for addr, account := range allocs {
log.Info("change contract code", "address", addr)
state.SetCode(addr, account.Code)
}
}
}
return nil
}

// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
stateSyncData := []*types.StateSyncData{}

headerNumber := header.Number.Uint64()

if headerNumber%c.config.Sprint == 0 {
cx := chainContext{Chain: chain, Bor: c}

Expand All @@ -710,6 +751,11 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
}
}

if err := c.changeContractCodeIfNeeded(headerNumber, state); err != nil {
log.Error("Error changing contract code", "error", err)
return nil, err
}

// No block rewards in PoA, so the state remains as is and uncles are dropped
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.UncleHash = types.CalcUncleHash(nil)
Expand Down
101 changes: 101 additions & 0 deletions consensus/bor/bor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package bor

import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/assert"
)

func TestGenesisContractChange(t *testing.T) {
addr0 := common.Address{0x1}

b := &Bor{
config: &params.BorConfig{
Sprint: 10, // skip sprint transactions in sprint
BlockAlloc: map[string]interface{}{
// write as interface since that is how it is decoded in genesis
"2": map[string]interface{}{
addr0.Hex(): map[string]interface{}{
"code": hexutil.Bytes{0x1, 0x2},
"balance": "0",
},
},
"4": map[string]interface{}{
addr0.Hex(): map[string]interface{}{
"code": hexutil.Bytes{0x1, 0x3},
"balance": "0x1000",
},
},
},
},
}

genspec := &core.Genesis{
Alloc: map[common.Address]core.GenesisAccount{
addr0: {
Balance: big.NewInt(0),
Code: []byte{0x1, 0x1},
},
},
}

db := rawdb.NewMemoryDatabase()
genesis := genspec.MustCommit(db)

statedb, err := state.New(genesis.Root(), state.NewDatabase(db), nil)
assert.NoError(t, err)

config := params.ChainConfig{}
chain, err := core.NewBlockChain(db, nil, &config, b, vm.Config{}, nil, nil)
assert.NoError(t, err)

addBlock := func(root common.Hash, num int64) (common.Hash, *state.StateDB) {
h := &types.Header{
ParentHash: root,
Number: big.NewInt(num),
}
b.Finalize(chain, h, statedb, nil, nil)

// write state to database
root, err := statedb.Commit(false)
assert.NoError(t, err)
assert.NoError(t, statedb.Database().TrieDB().Commit(root, true, nil))

statedb, err := state.New(h.Root, state.NewDatabase(db), nil)
assert.NoError(t, err)

return root, statedb
}

assert.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x1})

root := genesis.Root()

// code does not change
root, statedb = addBlock(root, 1)
assert.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x1})

// code changes 1st time
root, statedb = addBlock(root, 2)
assert.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x2})

// code same as 1st change
root, statedb = addBlock(root, 3)
assert.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x2})

// code changes 2nd time
_, statedb = addBlock(root, 4)
assert.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x3})

// make sure balance change DOES NOT take effect
assert.Equal(t, statedb.GetBalance(addr0), big.NewInt(0))
}
3 changes: 3 additions & 0 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
if err := newcfg.CheckConfigForkOrder(); err != nil {
return newcfg, common.Hash{}, err
}

storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg == nil {
log.Warn("Found genesis block without chain config")
Expand All @@ -236,6 +237,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
if compatErr != nil && *height != 0 && compatErr.RewindTo != 0 {
return newcfg, stored, compatErr
}

rawdb.WriteChainConfig(db, stored, newcfg)
return newcfg, stored, nil
}
Expand Down Expand Up @@ -279,6 +281,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
statedb.SetState(addr, key, value)
}
}

root := statedb.IntermediateRoot(false)
head := &types.Header{
Number: new(big.Int).SetUint64(g.Number),
Expand Down
Loading

0 comments on commit 39116e6

Please sign in to comment.