Skip to content

Commit ce38bdd

Browse files
authored
Merge pull request #1042 from CortexFoundation/neo
Neo version 4 cortex full node
2 parents cb78eb6 + d831341 commit ce38bdd

File tree

10 files changed

+119
-26
lines changed

10 files changed

+119
-26
lines changed

consensus/cuckoo/consensus.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,14 @@ func (cuckoo *Cuckoo) CalcDifficulty(chain consensus.ChainHeaderReader, time uin
353353
func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
354354
next := new(big.Int).Add(parent.Number, big1)
355355
switch {
356+
case config.IsNeo(next):
357+
return calcDifficultyNeo(time, parent, true)
356358
case config.IsIstanbul(next):
357-
return calcDifficultyIstanbul(time, parent)
359+
return calcDifficultyIstanbul(time, parent, false)
358360
case config.IsConstantinople(next):
359-
return calcDifficultyConstantinople(time, parent)
361+
return calcDifficultyConstantinople(time, parent, false)
360362
case config.IsByzantium(next):
361-
return calcDifficultyByzantium(time, parent)
363+
return calcDifficultyByzantium(time, parent, false)
362364
case config.IsHomestead(next):
363365
return calcDifficultyHomestead(time, parent)
364366
default:
@@ -406,18 +408,22 @@ var (
406408
bigMinus99 = big.NewInt(-99)
407409
)
408410

409-
func calcDifficultyIstanbul(time uint64, parent *types.Header) *big.Int {
410-
return calcDifficultyConstantinople(time, parent)
411+
func calcDifficultyIstanbul(time uint64, parent *types.Header, neo bool) *big.Int {
412+
return calcDifficultyConstantinople(time, parent, neo)
411413
}
412414

413-
func calcDifficultyConstantinople(time uint64, parent *types.Header) *big.Int {
414-
return calcDifficultyByzantium(time, parent)
415+
func calcDifficultyConstantinople(time uint64, parent *types.Header, neo bool) *big.Int {
416+
return calcDifficultyByzantium(time, parent, neo)
417+
}
418+
419+
func calcDifficultyNeo(time uint64, parent *types.Header, neo bool) *big.Int {
420+
return calcDifficultyIstanbul(time, parent, neo)
415421
}
416422

417423
// calcDifficultyByzantium is the difficulty adjustment algorithm. It returns
418424
// the difficulty that a new block should have when created at time given the
419425
// parent block's time and difficulty. The calculation uses the Byzantium rules.
420-
func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
426+
func calcDifficultyByzantium(time uint64, parent *types.Header, neo bool) *big.Int {
421427
// https://github.com/cortex/EIPs/issues/100.
422428
// algorithm:
423429
// diff = (parent_diff +
@@ -448,13 +454,16 @@ func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
448454
x.Set(big0)
449455
}
450456

451-
// TODO
452457
if parent.Difficulty.Cmp(params.MeanDifficultyBoundDivisor) >= 0 && parent.Difficulty.Cmp(params.HighDifficultyBoundDivisor) < 0 {
453458
y.Div(parent.Difficulty, params.MeanDifficultyBoundDivisor)
454459
} else if parent.Difficulty.Cmp(params.HighDifficultyBoundDivisor) >= 0 {
455460
y.Div(parent.Difficulty, params.HighDifficultyBoundDivisor)
456461
} else {
457-
y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
462+
if neo {
463+
y = params.MinimumDifficulty // delta 2
464+
} else {
465+
y.Div(parent.Difficulty, params.DifficultyBoundDivisor_2)
466+
}
458467

459468
if x.Cmp(big0) > 0 {
460469
x.Set(big1)
@@ -533,7 +542,7 @@ func makeDifficultyCalculator(bombDelay *big.Int) func(time uint64, parent *type
533542
x.Set(bigMinus99)
534543
}
535544
// parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99))
536-
y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
545+
y.Div(parent.Difficulty, params.DifficultyBoundDivisor_2)
537546
x.Mul(y, x)
538547
x.Add(parent.Difficulty, x)
539548

@@ -594,7 +603,7 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
594603
} else if parent.Difficulty.Cmp(params.HighDifficultyBoundDivisor) >= 0 {
595604
y.Div(parent.Difficulty, params.HighDifficultyBoundDivisor)
596605
} else {
597-
y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
606+
y.Div(parent.Difficulty, params.DifficultyBoundDivisor_2)
598607
}
599608
x.Mul(y, x)
600609
x.Add(parent.Difficulty, x)
@@ -622,7 +631,7 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
622631
// block's time and difficulty. The calculation uses the Frontier rules.
623632
func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
624633
diff := new(big.Int)
625-
adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
634+
adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor_2)
626635
bigTime := new(big.Int)
627636
bigParentTime := new(big.Int)
628637

consensus/cuckoo/consensus_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package cuckoo
22

33
import (
4+
"encoding/binary"
5+
"github.com/CortexFoundation/CortexTheseus/core/types"
46
"math/big"
7+
"math/rand"
58
"testing"
69
)
710

@@ -17,3 +20,36 @@ func TestReward(t *testing.T) {
1720
reward = calculateRewardByNumber(big.NewInt(8409600*4), uint64(21))
1821
t.Log(reward)
1922
}
23+
24+
func TestDifficultyCalculators(t *testing.T) {
25+
rand.Seed(2)
26+
diff := big.NewInt(10)
27+
for i := 0; i < 30; i++ {
28+
29+
// 1 to 300 seconds diff
30+
var timeDelta = uint64(18)
31+
//rand.Read(difficulty)
32+
header := &types.Header{
33+
Difficulty: diff,
34+
Number: new(big.Int).SetUint64(rand.Uint64() % 50_000_000),
35+
Time: rand.Uint64(),
36+
}
37+
//if rand.Uint32()&1 == 0 {
38+
header.UncleHash = types.EmptyUncleHash
39+
//}
40+
41+
diff = calcDifficultyNeo(header.Time+timeDelta, header, true)
42+
//t.Log(header.Difficulty)
43+
t.Log(diff)
44+
}
45+
}
46+
47+
func randSlice(min, max uint32) []byte {
48+
var b = make([]byte, 4)
49+
rand.Read(b)
50+
a := binary.LittleEndian.Uint32(b)
51+
size := min + a%(max-min)
52+
out := make([]byte, size)
53+
rand.Read(out)
54+
return out
55+
}

core/vm/contracts.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
7676
common.BytesToAddress([]byte{9}): &blake2F{},
7777
}
7878

79+
var PrecompiledContractsNeo = PrecompiledContractsIstanbul
80+
7981
// PrecompiledContractsBerlin contains the default set of pre-compiled Cortex
8082
// contracts used in the Berlin release.
8183
var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{

core/vm/cvm.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ func (cvm *CVM) IsInput(code []byte) bool {
6868
func (cvm *CVM) precompile(addr common.Address) (PrecompiledContract, bool) {
6969
var precompiles map[common.Address]PrecompiledContract
7070
switch {
71+
case cvm.chainRules.IsNeo:
72+
precompiles = PrecompiledContractsNeo
7173
case cvm.chainRules.IsIstanbul:
7274
precompiles = PrecompiledContractsIstanbul
7375
case cvm.chainRules.IsByzantium:

core/vm/instructions.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,9 @@ func opCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]by
871871
}
872872
stack.push(&temp)
873873
if err == nil || err == ErrExecutionReverted {
874+
if interpreter.cvm.chainRules.IsNeo {
875+
ret = common.CopyBytes(ret)
876+
}
874877
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
875878
}
876879
callContext.contract.Gas += returnGas
@@ -906,6 +909,9 @@ func opCallCode(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) (
906909
}
907910
stack.push(&temp)
908911
if err == nil || err == ErrExecutionReverted {
912+
if interpreter.cvm.chainRules.IsNeo {
913+
ret = common.CopyBytes(ret)
914+
}
909915
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
910916
}
911917
callContext.contract.Gas += returnGas
@@ -935,6 +941,9 @@ func opDelegateCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCt
935941
}
936942
stack.push(&temp)
937943
if err == nil || err == ErrExecutionReverted {
944+
if interpreter.cvm.chainRules.IsNeo {
945+
ret = common.CopyBytes(ret)
946+
}
938947
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
939948
}
940949
callContext.contract.Gas += returnGas
@@ -964,6 +973,9 @@ func opStaticCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx)
964973
}
965974
stack.push(&temp)
966975
if err == nil || err == ErrExecutionReverted {
976+
if interpreter.cvm.chainRules.IsNeo {
977+
ret = common.CopyBytes(ret)
978+
}
967979
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
968980
}
969981
callContext.contract.Gas += returnGas

core/vm/interpreter.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ func NewCVMInterpreter(cvm *CVM, cfg Config) *CVMInterpreter {
109109
if cfg.JumpTable[STOP] == nil {
110110
var jt JumpTable
111111
switch {
112+
case cvm.chainRules.IsNeo:
113+
jt = neoInstructionSet
112114
case cvm.chainRules.IsIstanbul:
113115
jt = istanbulInstructionSet
114116
case cvm.chainRules.IsConstantinople:
@@ -339,6 +341,7 @@ func (in *CVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
339341
pcCopy uint64 // needed for the deferred Tracer
340342
gasCopy uint64 // for Tracer to log gas remaining before execution
341343
logged bool // deferred Tracer should ignore already logged steps
344+
res []byte
342345
)
343346
// Don't move this deferrred function, it's placed before the capturestate-deferred method,
344347
// so that it get's executed _after_: the capturestate needs the stacks before
@@ -369,7 +372,6 @@ func (in *CVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
369372
contract.Code = contract.Code[2:]
370373
}
371374
cgas := uint64(0)
372-
res := make([]byte, 10)
373375
for atomic.LoadInt32(&in.cvm.abort) == 0 {
374376
if in.cfg.Debug {
375377
// Capture pre-execution values for tracing.
@@ -462,7 +464,11 @@ func (in *CVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
462464
// if the operation clears the return data (e.g. it has returning data)
463465
// set the last return to the result of the operation.
464466
if operation.returns {
465-
in.returnData = common.CopyBytes(res)
467+
if in.cvm.chainRules.IsNeo {
468+
in.returnData = res
469+
} else {
470+
in.returnData = common.CopyBytes(res)
471+
}
466472
}
467473
switch {
468474
case err != nil:

core/vm/jump_table.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,18 @@ var (
5454
byzantiumInstructionSet = newByzantiumInstructionSet()
5555
constantinopleInstructionSet = newConstantinopleInstructionSet()
5656
istanbulInstructionSet = newIstanbulInstructionSet()
57+
neoInstructionSet = newNeoInstructionSet()
5758
)
5859

5960
// JumpTable contains the CVM opcodes supported at a given fork.
6061
type JumpTable [256]*operation
6162

63+
func newNeoInstructionSet() JumpTable {
64+
instructionSet := newIstanbulInstructionSet()
65+
66+
return instructionSet
67+
}
68+
6269
// newIstanbulInstructionSet returns the frontier, homestead
6370
// byzantium, contantinople and petersburg instructions.
6471
func newIstanbulInstructionSet() JumpTable {

miner/worker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
10081008
log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
10091009
"uncles", len(uncles), "txs", w.current.tcount,
10101010
"gas", block.GasUsed(), "fees", totalFees(block, receipts),
1011-
"elapsed", common.PrettyDuration(time.Since(start)))
1011+
"elapsed", common.PrettyDuration(time.Since(start)), "diff", block.Difficulty())
10121012

10131013
case <-w.exitCh:
10141014
log.Info("Worker has exited")

params/config.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ var (
130130
ConstantinopleBlock: big.NewInt(0),
131131
PetersburgBlock: big.NewInt(0),
132132
IstanbulBlock: big.NewInt(3_230_000),
133+
NeoBlock: big.NewInt(4_650_000),
133134
Cuckoo: new(CuckooConfig),
134135
}
135136

@@ -147,6 +148,7 @@ var (
147148
ConstantinopleBlock: big.NewInt(0),
148149
PetersburgBlock: big.NewInt(0),
149150
IstanbulBlock: big.NewInt(0),
151+
NeoBlock: nil,
150152
Clique: &CliqueConfig{
151153
Period: 3,
152154
Epoch: 30000,
@@ -167,6 +169,7 @@ var (
167169
ConstantinopleBlock: big.NewInt(0),
168170
PetersburgBlock: big.NewInt(0),
169171
IstanbulBlock: big.NewInt(0),
172+
NeoBlock: nil,
170173
Cuckoo: new(CuckooConfig),
171174
}
172175

@@ -184,6 +187,7 @@ var (
184187
ConstantinopleBlock: big.NewInt(0),
185188
PetersburgBlock: big.NewInt(0),
186189
IstanbulBlock: big.NewInt(0),
190+
NeoBlock: nil,
187191
Clique: &CliqueConfig{
188192
Period: 15,
189193
Epoch: 30000,
@@ -208,6 +212,7 @@ var (
208212
ConstantinopleBlock: big.NewInt(0),
209213
PetersburgBlock: big.NewInt(0),
210214
IstanbulBlock: nil,
215+
NeoBlock: nil,
211216
Cuckoo: new(CuckooConfig),
212217
Clique: nil}
213218

@@ -216,9 +221,9 @@ var (
216221
//
217222
// This configuration is intentionally not using keyed fields to force anyone
218223
// adding flags to the config to also have to set these fields.
219-
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, &CliqueConfig{Period: 0, Epoch: 30000}}
224+
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, &CliqueConfig{Period: 0, Epoch: 30000}}
220225

221-
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, new(CuckooConfig), nil}
226+
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, new(CuckooConfig), nil}
222227
TestRules = TestChainConfig.Rules(new(big.Int))
223228
)
224229

@@ -246,6 +251,7 @@ type ChainConfig struct {
246251
ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
247252
PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople)
248253
IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul)
254+
NeoBlock *big.Int `json:"neoBlock,omitempty"`
249255
// Various consensus engines
250256
Cuckoo *CuckooConfig `json:"cuckoo,omitempty"`
251257
Clique *CliqueConfig `json:"clique,omitempty"`
@@ -280,7 +286,7 @@ func (c *ChainConfig) String() string {
280286
default:
281287
engine = "unknown"
282288
}
283-
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 Engine: %v}",
289+
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}",
284290
c.ChainID,
285291
c.HomesteadBlock,
286292
c.DAOForkBlock,
@@ -292,6 +298,7 @@ func (c *ChainConfig) String() string {
292298
c.ConstantinopleBlock,
293299
c.PetersburgBlock,
294300
c.IstanbulBlock,
301+
c.NeoBlock,
295302
engine,
296303
)
297304
}
@@ -342,6 +349,10 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool {
342349
return isForked(c.IstanbulBlock, num)
343350
}
344351

352+
func (c *ChainConfig) IsNeo(num *big.Int) bool {
353+
return isForked(c.NeoBlock, num)
354+
}
355+
345356
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
346357
//
347358
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
@@ -397,6 +408,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
397408
{name: "constantinopleBlock", block: c.ConstantinopleBlock},
398409
{name: "petersburgBlock", block: c.PetersburgBlock},
399410
{name: "istanbulBlock", block: c.IstanbulBlock},
411+
{name: "neoBlock", block: c.NeoBlock},
400412
} {
401413
if lastFork.name != "" {
402414
// Next one must be higher number
@@ -456,6 +468,10 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
456468
if isForkIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, head) {
457469
return newCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock)
458470
}
471+
472+
if isForkIncompatible(c.NeoBlock, newcfg.NeoBlock, head) {
473+
return newCompatError("Neo fork block", c.NeoBlock, newcfg.NeoBlock)
474+
}
459475
return nil
460476
}
461477

@@ -521,9 +537,9 @@ func (err *ConfigCompatError) Error() string {
521537
// Rules is a one time interface meaning that it shouldn't be used in between transition
522538
// phases.
523539
type Rules struct {
524-
ChainID *big.Int
525-
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
526-
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
540+
ChainID *big.Int
541+
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
542+
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul, IsNeo bool
527543
}
528544

529545
// Rules ensures c's ChainID is not nil.
@@ -532,7 +548,7 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
532548
if chainID == nil {
533549
chainID = new(big.Int)
534550
}
535-
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)}
551+
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)}
536552
}
537553

538554
// Get Mature Block

0 commit comments

Comments
 (0)