Skip to content

Mercury ver upgrade #1669

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

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
24 changes: 20 additions & 4 deletions consensus/cuckoo/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package cuckoo
import (
"encoding/binary"
// "encoding/hex"
// "bytes"
"bytes"
"errors"
"fmt"
"math/big"
Expand Down Expand Up @@ -278,7 +278,8 @@ func (cuckoo *Cuckoo) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}

validate := checkGasLimit(parent.GasUsed, parent.GasLimit, header.GasLimit)
//validate := checkGasLimit(parent.GasUsed, parent.GasLimit, header.GasLimit, chain.Config(), header.Number)
validate := gasCheck(chain, parent, header)
if !validate {
return fmt.Errorf("invalid gas limit trend: have %d, want %d used %d", header.GasLimit, parent.GasLimit, parent.GasUsed)
}
Expand Down Expand Up @@ -369,7 +370,10 @@ func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Heade
}

// important add gas limit to consensus
func checkGasLimit(gasUsed, gasLimit, currentGasLimit uint64) bool {
func gasCheck(chain consensus.ChainHeaderReader, parent, header *types.Header) bool {
return checkGasLimit(parent.GasUsed, parent.GasLimit, header.GasLimit, chain.Config(), header.Number)
}
func checkGasLimit(gasUsed, gasLimit, currentGasLimit uint64, config *params.ChainConfig, num *big.Int) bool {
contrib := (gasUsed + gasUsed/2) / params.GasLimitBoundDivisor

decay := gasLimit/params.GasLimitBoundDivisor - 1
Expand All @@ -391,7 +395,10 @@ func checkGasLimit(gasUsed, gasLimit, currentGasLimit uint64) bool {
}
}

// TODO
if config != nil && config.IsMercury(num) {
return limit <= currentGasLimit
}

return limit == currentGasLimit
}

Expand Down Expand Up @@ -677,6 +684,15 @@ func (cuckoo *Cuckoo) VerifySeal(chain consensus.ChainHeaderReader, header *type
return errInvalidDifficulty
}

// Verify the calculated values against the ones provided in the header
if chain.Config().IsMercury(header.Number) {
log.Trace("Mix digest verify", "number", header.Number, "mix", header.Solution.Hash(), "header", header.MixDigest)
digest := header.Solution.Hash().Bytes()
if !bytes.Equal(header.MixDigest[:], digest) {
return errInvalidMixDigest
}
}

var (
result = header.Solution
nonce uint64 = uint64(header.Nonce.Uint64())
Expand Down
21 changes: 16 additions & 5 deletions consensus/cuckoo/consensus_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cuckoo

import (
"bytes"
"encoding/binary"
"math/big"
"math/rand"
Expand Down Expand Up @@ -71,23 +72,33 @@ func randSlice(min, max uint32) []byte {
}

func TestGasLimitCheck(t *testing.T) {
if validate := checkGasLimit(0, 7992189, 8000000); !validate {
if validate := checkGasLimit(0, 7992189, 8000000, nil, nil); !validate {
t.Fatalf("failed")
}

if validate := checkGasLimit(7992189, 7992189, 8000000); !validate {
if validate := checkGasLimit(7992189, 7992189, 8000000, nil, nil); !validate {
t.Fatalf("failed")
}

if validate := checkGasLimit(0, 8000000, 7992189); validate {
if validate := checkGasLimit(0, 8000000, 7992189, nil, nil); validate {
t.Fatalf("failed")
}

if validate := checkGasLimit(7980000, 8000000, 8003878); !validate {
if validate := checkGasLimit(7980000, 8000000, 8003878, nil, nil); !validate {
t.Fatalf("failed")
}

if validate := checkGasLimit(7980000, 8000000, 8003879); validate {
if validate := checkGasLimit(7980000, 8000000, 8003879, nil, nil); validate {
t.Fatalf("failed")
}
}

func TestMixDigest(t *testing.T) {
sol := &types.BlockSolution{36552774, 57703112, 69439022, 71282429, 117293109, 186862362, 271815245, 283711993, 301666096, 321610391, 345111432, 376920806, 469608283, 480776867, 488279241, 490162501, 496690146, 516943318, 548320772, 575755973, 584516346, 590932588, 594672482, 596315856, 611820183, 626014278, 668956240, 724642732, 737723908, 761956873, 772529653, 781328833, 782613854, 804339063, 838293864, 852149620, 875286932, 888462575, 905024013, 993378264, 1039286741, 1068794681}
mix := sol.Hash()

t.Log("sol:", sol, "mix:", mix)
if !bytes.Equal(mix[:], sol.Hash().Bytes()) {
t.Fatalf("failed")
}
}
2 changes: 1 addition & 1 deletion consensus/cuckoo/sealer.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func (cuckoo *Cuckoo) remote() {
// Verify the correctness of submitted result.
header := block.Header()
header.Nonce = nonce
//header.MixDigest = mixDigest
header.MixDigest = sol.Hash()
header.Solution = sol
if err := cuckoo.VerifySeal(nil, header); err != nil {
log.Warn("Invalid proof-of-work submitted", "hash", hash, "err", err)
Expand Down
11 changes: 11 additions & 0 deletions core/cvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/CortexFoundation/CortexTheseus/core/types"
"github.com/CortexFoundation/CortexTheseus/core/vm"
"github.com/CortexFoundation/CortexTheseus/log"
"github.com/CortexFoundation/CortexTheseus/params"
)

// ChainContext supports retrieving headers and consensus parameters from the
Expand All @@ -48,9 +49,19 @@ func NewCVMBlockContext(header *types.Header, chain ChainContext, author *common
} else {
beneficiary = *author
}

log.Trace("Random", "number", header.Number, "mix", header.MixDigest, "parent", header.ParentHash, "mercury", params.MERCURY_MAINNET)

// TODO auto invoked by PoS (IsMerge Version) op random, set when mining work commit, it will not happen by PoW
if header.Difficulty.Cmp(common.Big0) == 0 {
random = &header.MixDigest
} else {
// TODO fake random only for random op pass, used carefully, check block number
if params.MERCURY_MAINNET != nil && header.Number.Cmp(params.MERCURY_MAINNET) >= 0 {
random = &header.ParentHash
}
}

return vm.BlockContext{
CanTransfer: CanTransfer,
Transfer: Transfer,
Expand Down
8 changes: 8 additions & 0 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ func (n *BlockNonce) UnmarshalText(input []byte) error {
return hexutil.UnmarshalFixedText("BlockNonce", input, n[:])
}

func (s *BlockSolution) Hash() common.Hash {
b, e := s.MarshalText()
if e != nil {
return common.EmptyHash
}
return common.BytesToHash(b)
}

func (s *BlockSolution) Uint32() []uint32 { return s[:] }

func (s *BlockSolution) MarshalText() ([]byte, error) {
Expand Down
2 changes: 2 additions & 0 deletions core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ func NewCVMInterpreter(cvm *CVM) *CVMInterpreter {
// If jump table was not initialised we set the default one.
var table *JumpTable
switch {
case cvm.chainRules.IsMercury:
table = &mercuryInstructionSet
case cvm.chainRules.IsMerge:
table = &mergeInstructionSet
case cvm.chainRules.IsNeo:
Expand Down
10 changes: 9 additions & 1 deletion core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ var (
neoInstructionSet = newNeoInstructionSet()

mergeInstructionSet = newMergeInstructionSet()

mercuryInstructionSet = newMercuryInstructionSet()
)

// JumpTable contains the CVM opcodes supported at a given fork.
Expand All @@ -67,14 +69,20 @@ func validate(jt JumpTable) JumpTable {
return jt
}

func newMercuryInstructionSet() JumpTable {
instructionSet := newMergeInstructionSet()
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)

return validate(instructionSet)
}

func newMergeInstructionSet() JumpTable {
instructionSet := newNeoInstructionSet()
instructionSet[RANDOM] = &operation{
execute: opRandom,
gasCost: constGasFunc(GasQuickStep),
validateStack: makeStackFunc(0, 1),
}
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)
return validate(instructionSet)
}

Expand Down
32 changes: 24 additions & 8 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ var (
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(3_230_000),
NeoBlock: big.NewInt(4_650_000),
MercuryBlock: MERCURY_MAINNET,
TerminalTotalDifficulty: nil,
TerminalTotalDifficultyPassed: false,
Cuckoo: new(CuckooConfig),
Expand All @@ -151,6 +152,7 @@ var (
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
NeoBlock: big.NewInt(5_000_000),
MercuryBlock: nil,
TerminalTotalDifficulty: nil,
TerminalTotalDifficultyPassed: false,
Clique: &CliqueConfig{
Expand All @@ -174,6 +176,7 @@ var (
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
NeoBlock: big.NewInt(0),
MercuryBlock: nil,
TerminalTotalDifficulty: nil,
TerminalTotalDifficultyPassed: false,
Cuckoo: new(CuckooConfig),
Expand All @@ -194,6 +197,7 @@ var (
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
NeoBlock: big.NewInt(0),
MercuryBlock: nil,
TerminalTotalDifficulty: nil,
TerminalTotalDifficultyPassed: false,
Clique: &CliqueConfig{
Expand Down Expand Up @@ -221,6 +225,7 @@ var (
PetersburgBlock: big.NewInt(0),
IstanbulBlock: nil,
NeoBlock: nil,
MercuryBlock: nil,
TerminalTotalDifficulty: nil,
TerminalTotalDifficultyPassed: false,
Cuckoo: new(CuckooConfig),
Expand All @@ -231,9 +236,9 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, false, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, false, nil, &CliqueConfig{Period: 0, Epoch: 30000}}

TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, false, new(CuckooConfig), nil}
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, false, new(CuckooConfig), nil}
TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
)

Expand Down Expand Up @@ -269,6 +274,7 @@ type ChainConfig struct {
PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople)
IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul)
NeoBlock *big.Int `json:"neoBlock,omitempty"`
MercuryBlock *big.Int `json:"mercuryBlock,omitempty"`
// TerminalTotalDifficulty is the amount of total difficulty reached by
// the network that triggers the consensus upgrade.
TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"`
Expand Down Expand Up @@ -311,7 +317,7 @@ func (c *ChainConfig) String() string {
default:
engine = "unknown"
}
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v TangerineWhistle(EIP150): %v SpuriousDragon(EIP155): %v SpuriousDragon(EIP158): %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v Neo:%v Engine: %v}",
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v TangerineWhistle(EIP150): %v SpuriousDragon(EIP155): %v SpuriousDragon(EIP158): %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v Neo:%v Mercury:%v Engine: %v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
Expand All @@ -324,6 +330,7 @@ func (c *ChainConfig) String() string {
c.PetersburgBlock,
c.IstanbulBlock,
c.NeoBlock,
c.MercuryBlock,
engine,
)
}
Expand Down Expand Up @@ -378,6 +385,10 @@ func (c *ChainConfig) IsNeo(num *big.Int) bool {
return isForked(c.NeoBlock, num)
}

func (c *ChainConfig) IsMercury(num *big.Int) bool {
return isForked(c.MercuryBlock, num)
}

// IsTerminalPoWBlock returns whether the given block is the last block of PoW stage.
func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool {
if c.TerminalTotalDifficulty == nil {
Expand Down Expand Up @@ -442,6 +453,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "petersburgBlock", block: c.PetersburgBlock},
{name: "istanbulBlock", block: c.IstanbulBlock},
{name: "neoBlock", block: c.NeoBlock},
{name: "mercuryBlock", block: c.MercuryBlock},
} {
if lastFork.name != "" {
// Next one must be higher number
Expand Down Expand Up @@ -505,6 +517,10 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
if isForkIncompatible(c.NeoBlock, newcfg.NeoBlock, head) {
return newCompatError("Neo fork block", c.NeoBlock, newcfg.NeoBlock)
}

if isForkIncompatible(c.MercuryBlock, newcfg.MercuryBlock, head) {
return newCompatError("Mercury fork block", c.MercuryBlock, newcfg.MercuryBlock)
}
return nil
}

Expand Down Expand Up @@ -622,10 +638,10 @@ func (err *ConfigCompatError) Error() string {
// Rules is a one time interface meaning that it shouldn't be used in between transition
// phases.
type Rules struct {
ChainID *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul, IsNeo bool
IsMerge bool
ChainID *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul, IsNeo, IsMercury bool
IsMerge bool
}

// Rules ensures c's ChainID is not nil.
Expand All @@ -634,7 +650,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
if chainID == nil {
chainID = new(big.Int)
}
return Rules{ChainID: new(big.Int).Set(chainID), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsByzantium: c.IsByzantium(num), IsPetersburg: c.IsPetersburg(num), IsIstanbul: c.IsIstanbul(num), IsNeo: c.IsNeo(num), IsMerge: isMerge}
return Rules{ChainID: new(big.Int).Set(chainID), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsByzantium: c.IsByzantium(num), IsPetersburg: c.IsPetersburg(num), IsIstanbul: c.IsIstanbul(num), IsNeo: c.IsNeo(num), IsMercury: c.IsMercury(num), IsMerge: isMerge}
}

// Get Mature Block
Expand Down
2 changes: 2 additions & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ var (

CTXC_F1 = big.NewInt(0).Mul(big.NewInt(20_486_540), big.NewInt(1000000000000000000))
CTXC_F2 = big.NewInt(0).Mul(big.NewInt(21_285_544), big.NewInt(1000000000000000000))

MERCURY_MAINNET *big.Int = nil //big.NewInt(0)
)

const (
Expand Down