Skip to content

Commit d9a0607

Browse files
authored
Merge pull request ethereum#24 from binance-chain/develop
[R4R] prepare for release 1.0.1-beta
2 parents 5cc893a + f2e4ef2 commit d9a0607

File tree

20 files changed

+494
-90
lines changed

20 files changed

+494
-90
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## v1.0.1-beta
4+
5+
IMPROVEMENT
6+
* [\#22](https://github.com/binance-chain/bsc/pull/22) resolve best practice advice
7+
8+
FEATURES
9+
* [\#23](https://github.com/binance-chain/bsc/pull/23) enforce backoff time for out-turn validator
10+
11+
BUGFIX
12+
* [\#25](https://github.com/binance-chain/bsc/pull/25) minor fix for ramanujan upgrade
13+
14+
UPGRADE
15+
* [\#26](https://github.com/binance-chain/bsc/pull/26) update chapel network config for ramanujan fork
16+
317
## v1.0.0-beta.0
418

519
FEATURES

cmd/geth/retesteth.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/ethereum/go-ethereum/core"
3737
"github.com/ethereum/go-ethereum/core/rawdb"
3838
"github.com/ethereum/go-ethereum/core/state"
39+
"github.com/ethereum/go-ethereum/core/systemcontracts"
3940
"github.com/ethereum/go-ethereum/core/types"
4041
"github.com/ethereum/go-ethereum/core/vm"
4142
"github.com/ethereum/go-ethereum/crypto"
@@ -133,6 +134,7 @@ type CParamsParams struct {
133134
ConstantinopleForkBlock *math.HexOrDecimal64 `json:"constantinopleForkBlock"`
134135
ConstantinopleFixForkBlock *math.HexOrDecimal64 `json:"constantinopleFixForkBlock"`
135136
IstanbulBlock *math.HexOrDecimal64 `json:"istanbulForkBlock"`
137+
RamanujanForkBlock *math.HexOrDecimal64 `json:"ramanujanForkBlock"`
136138
ChainID *math.HexOrDecimal256 `json:"chainID"`
137139
MaximumExtraDataSize math.HexOrDecimal64 `json:"maximumExtraDataSize"`
138140
TieBreakingGas bool `json:"tieBreakingGas"`
@@ -322,6 +324,7 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa
322324
constantinopleBlock *big.Int
323325
petersburgBlock *big.Int
324326
istanbulBlock *big.Int
327+
ramanujanBlock *big.Int
325328
)
326329
if chainParams.Params.HomesteadForkBlock != nil {
327330
homesteadBlock = big.NewInt(int64(*chainParams.Params.HomesteadForkBlock))
@@ -351,6 +354,9 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa
351354
if chainParams.Params.IstanbulBlock != nil {
352355
istanbulBlock = big.NewInt(int64(*chainParams.Params.IstanbulBlock))
353356
}
357+
if chainParams.Params.RamanujanForkBlock != nil {
358+
ramanujanBlock = big.NewInt(int64(*chainParams.Params.RamanujanForkBlock))
359+
}
354360

355361
genesis := &core.Genesis{
356362
Config: &params.ChainConfig{
@@ -365,6 +371,7 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa
365371
ConstantinopleBlock: constantinopleBlock,
366372
PetersburgBlock: petersburgBlock,
367373
IstanbulBlock: istanbulBlock,
374+
RamanujanBlock: ramanujanBlock,
368375
},
369376
Nonce: uint64(chainParams.Genesis.Nonce),
370377
Timestamp: uint64(chainParams.Genesis.Timestamp),
@@ -501,6 +508,7 @@ func (api *RetestethAPI) mineBlock() error {
501508
if api.chainConfig.DAOForkSupport && api.chainConfig.DAOForkBlock != nil && api.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 {
502509
misc.ApplyDAOHardFork(statedb)
503510
}
511+
systemcontracts.UpgradeBuildInSystemContract(api.chainConfig, header.Number, statedb)
504512
gasPool := new(core.GasPool).AddGas(header.GasLimit)
505513
txCount := 0
506514
var txs []*types.Transaction

consensus/parlia/parlia.go

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/ethereum/go-ethereum/consensus/misc"
2727
"github.com/ethereum/go-ethereum/core"
2828
"github.com/ethereum/go-ethereum/core/state"
29+
"github.com/ethereum/go-ethereum/core/systemcontracts"
2930
"github.com/ethereum/go-ethereum/core/types"
3031
"github.com/ethereum/go-ethereum/core/vm"
3132
"github.com/ethereum/go-ethereum/crypto"
@@ -48,21 +49,11 @@ const (
4849
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
4950

5051
validatorBytesLength = common.AddressLength
51-
wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
52-
fixedBackOffTime = 200 * time.Millisecond
52+
wiggleTime = uint64(1) // second, Random delay (per signer) to allow concurrent signers
53+
initialBackOffTime = uint64(1) // second
5354

5455
systemRewardPercent = 4 // it means 1/2^4 = 1/16 percentage of gas fee incoming will be distributed to system
5556

56-
// genesis contracts
57-
ValidatorContract = "0x0000000000000000000000000000000000001000"
58-
SlashContract = "0x0000000000000000000000000000000000001001"
59-
SystemRewardContract = "0x0000000000000000000000000000000000001002"
60-
LightClientContract = "0x0000000000000000000000000000000000001003"
61-
TokenHubContract = "0x0000000000000000000000000000000000001004"
62-
RelayerIncentivizeContract = "0x0000000000000000000000000000000000001005"
63-
RelayerHubContract = "0x0000000000000000000000000000000000001006"
64-
GovHubContract = "0x0000000000000000000000000000000000001007"
65-
CrossChainContract = "0x0000000000000000000000000000000000002000"
6657
)
6758

6859
var (
@@ -73,15 +64,15 @@ var (
7364
maxSystemBalance = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether))
7465

7566
systemContracts = map[common.Address]bool{
76-
common.HexToAddress(ValidatorContract): true,
77-
common.HexToAddress(SlashContract): true,
78-
common.HexToAddress(SystemRewardContract): true,
79-
common.HexToAddress(LightClientContract): true,
80-
common.HexToAddress(RelayerHubContract): true,
81-
common.HexToAddress(GovHubContract): true,
82-
common.HexToAddress(TokenHubContract): true,
83-
common.HexToAddress(RelayerIncentivizeContract): true,
84-
common.HexToAddress(CrossChainContract): true,
67+
common.HexToAddress(systemcontracts.ValidatorContract): true,
68+
common.HexToAddress(systemcontracts.SlashContract): true,
69+
common.HexToAddress(systemcontracts.SystemRewardContract): true,
70+
common.HexToAddress(systemcontracts.LightClientContract): true,
71+
common.HexToAddress(systemcontracts.RelayerHubContract): true,
72+
common.HexToAddress(systemcontracts.GovHubContract): true,
73+
common.HexToAddress(systemcontracts.TokenHubContract): true,
74+
common.HexToAddress(systemcontracts.RelayerIncentivizeContract): true,
75+
common.HexToAddress(systemcontracts.CrossChainContract): true,
8576
}
8677
)
8778

@@ -395,10 +386,20 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainReader, header *type
395386
return consensus.ErrUnknownAncestor
396387
}
397388

389+
snap, err := p.snapshot(chain, number-1, header.ParentHash, parents)
390+
if err != nil {
391+
return err
392+
}
393+
394+
err = p.blockTimeVerifyForRamanujanFork(snap, header, parent)
395+
if err != nil {
396+
return err
397+
}
398+
398399
// Verify that the gas limit is <= 2^63-1
399-
cap := uint64(0x7fffffffffffffff)
400-
if header.GasLimit > cap {
401-
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
400+
capacity := uint64(0x7fffffffffffffff)
401+
if header.GasLimit > capacity {
402+
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, capacity)
402403
}
403404
// Verify that the gasUsed is <= gasLimit
404405
if header.GasUsed > header.GasLimit {
@@ -570,7 +571,7 @@ func (p *Parlia) verifySeal(chain consensus.ChainReader, header *types.Header, p
570571

571572
// Ensure that the difficulty corresponds to the turn-ness of the signer
572573
if !p.fakeDiff {
573-
inturn := snap.inturn(header.Number.Uint64(), signer)
574+
inturn := snap.inturn(signer)
574575
if inturn && header.Difficulty.Cmp(diffInTurn) != 0 {
575576
return errWrongDifficulty
576577
}
@@ -626,8 +627,7 @@ func (p *Parlia) Prepare(chain consensus.ChainReader, header *types.Header) erro
626627
if parent == nil {
627628
return consensus.ErrUnknownAncestor
628629
}
629-
630-
header.Time = parent.Time + p.config.Period
630+
header.Time = p.blockTimeForRamanujanFork(snap, header, parent)
631631
if header.Time < uint64(time.Now().Unix()) {
632632
header.Time = uint64(time.Now().Unix())
633633
}
@@ -809,14 +809,7 @@ func (p *Parlia) Seal(chain consensus.ChainReader, block *types.Block, results c
809809
}
810810

811811
// Sweet, the protocol permits us to sign the block, wait for our time
812-
delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
813-
if header.Difficulty.Cmp(diffNoTurn) == 0 {
814-
// It's not our turn explicitly to sign, delay it a bit
815-
wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTime
816-
delay += time.Duration(fixedBackOffTime) + time.Duration(rand.Int63n(int64(wiggle)))
817-
818-
log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
819-
}
812+
delay := p.delayForRamanujanFork(snap, header)
820813

821814
log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex())
822815

@@ -861,7 +854,7 @@ func (p *Parlia) CalcDifficulty(chain consensus.ChainReader, time uint64, parent
861854
// that a new block should have based on the previous blocks in the chain and the
862855
// current signer.
863856
func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
864-
if snap.inturn(snap.Number+1, signer) {
857+
if snap.inturn(signer) {
865858
return new(big.Int).Set(diffInTurn)
866859
}
867860
return new(big.Int).Set(diffNoTurn)
@@ -907,7 +900,7 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash) ([]common.Address,
907900
}
908901
// call
909902
msgData := (hexutil.Bytes)(data)
910-
toAddress := common.HexToAddress(ValidatorContract)
903+
toAddress := common.HexToAddress(systemcontracts.ValidatorContract)
911904
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
912905
result, err := p.ethAPI.Call(ctx, ethapi.CallArgs{
913906
Gas: &gas,
@@ -945,7 +938,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
945938
state.SetBalance(consensus.SystemAddress, big.NewInt(0))
946939
state.AddBalance(coinbase, balance)
947940

948-
doDistributeSysReward := state.GetBalance(common.HexToAddress(SystemRewardContract)).Cmp(maxSystemBalance) < 0
941+
doDistributeSysReward := state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
949942
if doDistributeSysReward {
950943
var rewards = new(big.Int)
951944
rewards = rewards.Rsh(balance, systemRewardPercent)
@@ -977,7 +970,7 @@ func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header *
977970
return err
978971
}
979972
// get system message
980-
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(SlashContract), data, common.Big0)
973+
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SlashContract), data, common.Big0)
981974
// apply message
982975
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
983976
}
@@ -988,7 +981,15 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain
988981
// method
989982
method := "init"
990983
// contracts
991-
contracts := []string{ValidatorContract, SlashContract, LightClientContract, RelayerHubContract, TokenHubContract, RelayerIncentivizeContract, CrossChainContract}
984+
contracts := []string{
985+
systemcontracts.ValidatorContract,
986+
systemcontracts.SlashContract,
987+
systemcontracts.LightClientContract,
988+
systemcontracts.RelayerHubContract,
989+
systemcontracts.TokenHubContract,
990+
systemcontracts.RelayerIncentivizeContract,
991+
systemcontracts.CrossChainContract,
992+
}
992993
// get packed data
993994
data, err := p.validatorSetABI.Pack(method)
994995
if err != nil {
@@ -1010,7 +1011,7 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain
10101011
func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, header *types.Header, chain core.ChainContext,
10111012
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
10121013
// get system message
1013-
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(SystemRewardContract), nil, amount)
1014+
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SystemRewardContract), nil, amount)
10141015
// apply message
10151016
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
10161017
}
@@ -1031,7 +1032,7 @@ func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address
10311032
return err
10321033
}
10331034
// get system message
1034-
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(ValidatorContract), data, amount)
1035+
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, amount)
10351036
// apply message
10361037
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
10371038
}
@@ -1072,8 +1073,8 @@ func (p *Parlia) applyTransaction(
10721073
return errors.New("supposed to get a actual transaction, but get none")
10731074
}
10741075
actualTx := (*receivedTxs)[0]
1075-
if bytes.Compare(p.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) != 0 {
1076-
return errors.New(fmt.Sprintf("expected tx hash %v, get %v", expectedHash.String(), actualTx.Hash().String()))
1076+
if !bytes.Equal(p.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) {
1077+
return fmt.Errorf("expected tx hash %v, get %v", expectedHash.String(), actualTx.Hash().String())
10771078
}
10781079
expectedTx = actualTx
10791080
// move to next
@@ -1140,6 +1141,30 @@ func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
11401141
}
11411142
}
11421143

1144+
func backOffTime(snap *Snapshot, val common.Address) uint64 {
1145+
if snap.inturn(val) {
1146+
return 0
1147+
} else {
1148+
idx := snap.indexOfVal(val)
1149+
if idx < 0 {
1150+
// The backOffTime does not matter when a validator is not authorized.
1151+
return 0
1152+
}
1153+
s := rand.NewSource(int64(snap.Number))
1154+
r := rand.New(s)
1155+
n := len(snap.Validators)
1156+
backOffSteps := make([]uint64, 0, n)
1157+
for idx := uint64(0); idx < uint64(n); idx++ {
1158+
backOffSteps = append(backOffSteps, idx)
1159+
}
1160+
r.Shuffle(n, func(i, j int) {
1161+
backOffSteps[i], backOffSteps[j] = backOffSteps[j], backOffSteps[i]
1162+
})
1163+
delay := initialBackOffTime + backOffSteps[idx]*wiggleTime
1164+
return delay
1165+
}
1166+
}
1167+
11431168
// chain context
11441169
type chainContext struct {
11451170
Chain consensus.ChainReader
@@ -1194,4 +1219,3 @@ func applyMessage(
11941219
}
11951220
return msg.Gas() - returnGas, err
11961221
}
1197-

consensus/parlia/parlia_test.go

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"math/rand"
66
"testing"
7-
"time"
87

98
"github.com/ethereum/go-ethereum/common"
109
)
@@ -57,7 +56,7 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int) {
5756
return validators[idx]
5857
}
5958

60-
downDelay := time.Duration(0)
59+
downDelay := uint64(0)
6160
for h := 1; h <= downBlocks; h++ {
6261
if limit := uint64(totalValidators/2 + 1); uint64(h) >= limit {
6362
delete(recents, uint64(h)-limit)
@@ -73,21 +72,21 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int) {
7372
if len(candidates) == 0 {
7473
panic("can not test such case")
7574
}
76-
idx, delay := producerBlockDelay(candidates, totalValidators)
75+
idx, delay := producerBlockDelay(candidates, h, totalValidators)
7776
downDelay = downDelay + delay
7877
recents[uint64(h)] = idx
7978
} else {
8079
recents[uint64(h)] = proposer
8180
}
8281
}
8382
fmt.Printf("average delay is %v when there is %d validators and %d is down \n",
84-
downDelay/time.Duration(downBlocks), totalValidators, downValidators)
83+
downDelay/uint64(downBlocks), totalValidators, downValidators)
8584

8685
for i := 0; i < downValidators; i++ {
8786
validators[down[i]] = true
8887
}
8988

90-
recoverDelay := time.Duration(0)
89+
recoverDelay := uint64(0)
9190
lastseen := downBlocks
9291
for h := downBlocks + 1; h <= downBlocks+recoverBlocks; h++ {
9392
if limit := uint64(totalValidators/2 + 1); uint64(h) >= limit {
@@ -105,7 +104,7 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int) {
105104
if len(candidates) == 0 {
106105
panic("can not test such case")
107106
}
108-
idx, delay := producerBlockDelay(candidates, totalValidators)
107+
idx, delay := producerBlockDelay(candidates, h, totalValidators)
109108
recoverDelay = recoverDelay + delay
110109
recents[uint64(h)] = idx
111110
} else {
@@ -116,18 +115,28 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int) {
116115
recoverDelay, downValidators, lastseen)
117116
}
118117

119-
func producerBlockDelay(candidates map[int]bool, numOfValidators int) (int, time.Duration) {
120-
minDur := time.Duration(0)
121-
minIdx := 0
122-
wiggle := time.Duration(numOfValidators/2+1) * wiggleTime
123-
for idx := range candidates {
124-
sleepTime := rand.Int63n(int64(wiggle))
125-
if int64(minDur) < sleepTime {
126-
minDur = time.Duration(rand.Int63n(int64(wiggle)))
127-
minIdx = idx
118+
func producerBlockDelay(candidates map[int]bool, height, numOfValidators int) (int, uint64) {
119+
120+
s := rand.NewSource(int64(height))
121+
r := rand.New(s)
122+
n := numOfValidators
123+
backOffSteps := make([]int, 0, n)
124+
for idx := 0; idx < n; idx++ {
125+
backOffSteps = append(backOffSteps, idx)
126+
}
127+
r.Shuffle(n, func(i, j int) {
128+
backOffSteps[i], backOffSteps[j] = backOffSteps[j], backOffSteps[i]
129+
})
130+
minDelay := numOfValidators
131+
minCandidate := 0
132+
for c := range candidates {
133+
if minDelay > backOffSteps[c] {
134+
minDelay = backOffSteps[c]
135+
minCandidate = c
128136
}
129137
}
130-
return minIdx, minDur
138+
delay := initialBackOffTime + uint64(minDelay)*wiggleTime
139+
return minCandidate, delay
131140
}
132141

133142
func randomAddress() common.Address {

0 commit comments

Comments
 (0)