Skip to content

Commit fa00cd1

Browse files
authored
Keep rotation meta in memory. (#4459)
* Keep rotation meta in memory. * Proper name for struct. * Clean up.
1 parent b093fea commit fa00cd1

File tree

8 files changed

+183
-48
lines changed

8 files changed

+183
-48
lines changed

consensus/consensus_v2.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,11 @@ func (consensus *Consensus) finalCommit() {
157157
Msg("[finalCommit] Unable to construct Committed message")
158158
return
159159
}
160-
msgToSend, FBFTMsg :=
161-
network.Bytes,
162-
network.FBFTMsg
163-
commitSigAndBitmap := FBFTMsg.Payload
160+
var (
161+
msgToSend = network.Bytes
162+
FBFTMsg = network.FBFTMsg
163+
commitSigAndBitmap = FBFTMsg.Payload
164+
)
164165
consensus.fBFTLog.AddVerifiedMessage(FBFTMsg)
165166
// find correct block content
166167
curBlockHash := consensus.blockHash

core/blockchain_impl.go

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ type BlockChainImpl struct {
221221
badBlocks *lru.Cache // Bad block cache
222222
pendingSlashes slash.Records
223223
maxGarbCollectedBlkNum int64
224+
leaderRotationMeta leaderRotationMeta
224225

225226
options Options
226227
}
@@ -359,6 +360,12 @@ func newBlockChainWithOptions(
359360
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Hash())
360361
}
361362

363+
curHeader := bc.CurrentBlock().Header()
364+
err = bc.buildLeaderRotationMeta(curHeader)
365+
if err != nil {
366+
return nil, errors.WithMessage(err, "failed to build leader rotation meta")
367+
}
368+
362369
// Take ownership of this particular state
363370
go bc.update()
364371
return bc, nil
@@ -1479,8 +1486,11 @@ func (bc *BlockChainImpl) WriteBlockWithState(
14791486
defer bc.mu.Unlock()
14801487

14811488
currentBlock := bc.CurrentBlock()
1482-
if currentBlock == nil || block.ParentHash() != currentBlock.Hash() {
1483-
return NonStatTy, errors.New("Hash of parent block doesn't match the current block hash")
1489+
if currentBlock == nil {
1490+
return NonStatTy, errors.New("Current block is nil")
1491+
}
1492+
if block.ParentHash() != currentBlock.Hash() {
1493+
return NonStatTy, errors.Errorf("Hash of parent block %s doesn't match the current block hash %s", currentBlock.Hash().Hex(), block.ParentHash().Hex())
14841494
}
14851495

14861496
// Commit state object changes to in-memory trie
@@ -1650,20 +1660,52 @@ func (bc *BlockChainImpl) InsertChain(chain types.Blocks, verifyHeaders bool) (i
16501660
return n, err
16511661
}
16521662

1663+
// buildLeaderRotationMeta builds leader rotation meta if feature is activated.
1664+
func (bc *BlockChainImpl) buildLeaderRotationMeta(curHeader *block.Header) error {
1665+
if !bc.chainConfig.IsLeaderRotation(curHeader.Epoch()) {
1666+
return nil
1667+
}
1668+
if curHeader.NumberU64() == 0 {
1669+
return errors.New("current header is genesis")
1670+
}
1671+
curPubKey, err := bc.getLeaderPubKeyFromCoinbase(curHeader)
1672+
if err != nil {
1673+
return err
1674+
}
1675+
for i := curHeader.NumberU64() - 1; i >= 0; i-- {
1676+
header := bc.GetHeaderByNumber(i)
1677+
if header == nil {
1678+
return errors.New("header is nil")
1679+
}
1680+
blockPubKey, err := bc.getLeaderPubKeyFromCoinbase(header)
1681+
if err != nil {
1682+
return err
1683+
}
1684+
if curPubKey.Bytes != blockPubKey.Bytes || curHeader.Epoch().Uint64() != header.Epoch().Uint64() {
1685+
for j := i; i <= curHeader.NumberU64(); j++ {
1686+
header := bc.GetHeaderByNumber(i)
1687+
if header == nil {
1688+
return errors.New("header is nil")
1689+
}
1690+
err := bc.saveLeaderRotationMeta(header)
1691+
if err != nil {
1692+
utils.Logger().Error().Err(err).Msg("save leader continuous blocks count error")
1693+
return err
1694+
}
1695+
}
1696+
return nil
1697+
}
1698+
}
1699+
return errors.New("no leader rotation meta to save")
1700+
}
1701+
16531702
func (bc *BlockChainImpl) saveLeaderRotationMeta(h *block.Header) error {
16541703
blockPubKey, err := bc.getLeaderPubKeyFromCoinbase(h)
16551704
if err != nil {
16561705
return err
16571706
}
1658-
type stored struct {
1659-
pub []byte
1660-
epoch uint64
1661-
count uint64
1662-
shifts uint64
1663-
}
1664-
var s stored
1665-
// error is possible here only on the first iteration, so we can ignore it
1666-
s.pub, s.epoch, s.count, s.shifts, _ = rawdb.ReadLeaderRotationMeta(bc.db)
1707+
1708+
var s = bc.leaderRotationMeta
16671709

16681710
// increase counter only if the same leader and epoch
16691711
if bytes.Equal(s.pub, blockPubKey.Bytes[:]) && s.epoch == h.Epoch().Uint64() {
@@ -1679,11 +1721,9 @@ func (bc *BlockChainImpl) saveLeaderRotationMeta(h *block.Header) error {
16791721
if s.epoch != h.Epoch().Uint64() {
16801722
s.shifts = 0
16811723
}
1724+
s.epoch = h.Epoch().Uint64()
1725+
bc.leaderRotationMeta = s
16821726

1683-
err = rawdb.WriteLeaderRotationMeta(bc.db, blockPubKey.Bytes[:], h.Epoch().Uint64(), s.count, s.shifts)
1684-
if err != nil {
1685-
return err
1686-
}
16871727
return nil
16881728
}
16891729

core/blockchain_leader_rotation.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package core
2+
3+
type leaderRotationMeta struct {
4+
pub []byte
5+
epoch uint64
6+
count uint64
7+
shifts uint64
8+
}

core/state_processor.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ func (p *StateProcessor) Process(
119119
usedGas = new(uint64)
120120
header = block.Header()
121121
allLogs []*types.Log
122-
gp = new(GasPool).AddGas(block.GasLimit())
123-
blockStakeMsgs []staking.StakeMsg = make([]staking.StakeMsg, 0)
122+
gp = new(GasPool).AddGas(block.GasLimit())
123+
blockStakeMsgs = make([]staking.StakeMsg, 0)
124124
)
125125

126126
beneficiary, err := p.bc.GetECDSAFromCoinbase(header)
@@ -202,7 +202,7 @@ func (p *StateProcessor) Process(
202202
receipts, outcxs, incxs, block.StakingTransactions(), slashes, sigsReady, func() uint64 { return header.ViewID().Uint64() },
203203
)
204204
if err != nil {
205-
return nil, nil, nil, nil, 0, nil, statedb, errors.New("[Process] Cannot finalize block")
205+
return nil, nil, nil, nil, 0, nil, statedb, errors.WithMessage(err, "[Process] Cannot finalize block")
206206
}
207207

208208
result := &ProcessorResult{

core_test/shardchain_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package core_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/ethereum/go-ethereum/common"
8+
"github.com/harmony-one/harmony/consensus"
9+
"github.com/harmony-one/harmony/consensus/quorum"
10+
"github.com/harmony-one/harmony/core"
11+
"github.com/harmony-one/harmony/core/types"
12+
"github.com/harmony-one/harmony/crypto/bls"
13+
"github.com/harmony-one/harmony/internal/chain"
14+
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
15+
"github.com/harmony-one/harmony/internal/registry"
16+
"github.com/harmony-one/harmony/internal/shardchain"
17+
"github.com/harmony-one/harmony/internal/utils"
18+
"github.com/harmony-one/harmony/multibls"
19+
"github.com/harmony-one/harmony/node"
20+
"github.com/harmony-one/harmony/p2p"
21+
"github.com/harmony-one/harmony/shard"
22+
"github.com/stretchr/testify/require"
23+
)
24+
25+
var testDBFactory = &shardchain.MemDBFactory{}
26+
27+
func TestAddNewBlock(t *testing.T) {
28+
blsKey := bls.RandPrivateKey()
29+
pubKey := blsKey.GetPublicKey()
30+
leader := p2p.Peer{IP: "127.0.0.1", Port: "9882", ConsensusPubKey: pubKey}
31+
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
32+
host, err := p2p.NewHost(p2p.HostConfig{
33+
Self: &leader,
34+
BLSKey: priKey,
35+
})
36+
if err != nil {
37+
t.Fatalf("newhost failure: %v", err)
38+
}
39+
engine := chain.NewEngine()
40+
chainconfig := nodeconfig.GetShardConfig(shard.BeaconChainShardID).GetNetworkType().ChainConfig()
41+
collection := shardchain.NewCollection(
42+
nil, testDBFactory, &core.GenesisInitializer{NetworkType: nodeconfig.GetShardConfig(shard.BeaconChainShardID).GetNetworkType()}, engine, &chainconfig,
43+
)
44+
decider := quorum.NewDecider(
45+
quorum.SuperMajorityVote, shard.BeaconChainShardID,
46+
)
47+
blockchain, err := collection.ShardChain(shard.BeaconChainShardID)
48+
if err != nil {
49+
t.Fatal("cannot get blockchain")
50+
}
51+
reg := registry.New().SetBlockchain(blockchain)
52+
consensus, err := consensus.New(
53+
host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsKey), reg, decider, 3, false,
54+
)
55+
if err != nil {
56+
t.Fatalf("Cannot craeate consensus: %v", err)
57+
}
58+
nodeconfig.SetNetworkType(nodeconfig.Testnet)
59+
var block *types.Block
60+
node := node.New(host, consensus, engine, collection, nil, nil, nil, nil, nil, reg)
61+
commitSigs := make(chan []byte, 1)
62+
commitSigs <- []byte{}
63+
block, err = node.Worker.FinalizeNewBlock(
64+
commitSigs, func() uint64 { return uint64(0) }, common.Address{}, nil, nil,
65+
)
66+
if err != nil {
67+
t.Fatal("cannot finalize new block")
68+
}
69+
70+
nn := node.Blockchain().CurrentBlock()
71+
t.Log("[*]", nn.NumberU64(), nn.Hash().Hex(), nn.ParentHash())
72+
73+
_, err = blockchain.InsertChain([]*types.Block{block}, false)
74+
require.NoError(t, err, "error when adding new block")
75+
76+
pk, epoch, count, shifts, err := blockchain.LeaderRotationMeta()
77+
fmt.Println("pk", pk, "epoch", epoch, "count", count, "shifts", shifts, "err", err)
78+
79+
t.Log("#", block.Header().NumberU64(), node.Blockchain().CurrentBlock().NumberU64(), block.Hash().Hex(), block.ParentHash())
80+
81+
err = blockchain.Rollback([]common.Hash{block.Hash()})
82+
require.NoError(t, err, "error when rolling back")
83+
}

internal/configs/node/config.go

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,31 @@ const (
5858
Localnet = "localnet"
5959
)
6060

61+
// ChainConfig returns the chain configuration for the network type.
62+
func (t NetworkType) ChainConfig() params.ChainConfig {
63+
switch t {
64+
case Mainnet:
65+
return *params.MainnetChainConfig
66+
case Pangaea:
67+
return *params.PangaeaChainConfig
68+
case Partner:
69+
return *params.PartnerChainConfig
70+
case Stressnet:
71+
return *params.StressnetChainConfig
72+
case Localnet:
73+
return *params.LocalnetChainConfig
74+
default:
75+
return *params.TestnetChainConfig
76+
}
77+
}
78+
79+
func (n NetworkType) String() string {
80+
if n == "" {
81+
return Testnet // default to testnet
82+
}
83+
return string(n)
84+
}
85+
6186
// Global is the index of the global node configuration
6287
const (
6388
Global = 0
@@ -352,21 +377,3 @@ func (conf *ConfigType) ValidateConsensusKeysForSameShard(pubkeys multibls.Publi
352377
}
353378
return nil
354379
}
355-
356-
// ChainConfig returns the chain configuration for the network type.
357-
func (t NetworkType) ChainConfig() params.ChainConfig {
358-
switch t {
359-
case Mainnet:
360-
return *params.MainnetChainConfig
361-
case Pangaea:
362-
return *params.PangaeaChainConfig
363-
case Partner:
364-
return *params.PartnerChainConfig
365-
case Stressnet:
366-
return *params.StressnetChainConfig
367-
case Localnet:
368-
return *params.LocalnetChainConfig
369-
default:
370-
return *params.TestnetChainConfig
371-
}
372-
}

node/node_handler_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,11 @@ func TestAddNewBlock(t *testing.T) {
4646
t.Fatal("cannot get blockchain")
4747
}
4848
reg := registry.New().SetBlockchain(blockchain)
49-
consensus, err := consensus.New(
50-
host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsKey), reg, decider, 3, false,
51-
)
49+
consensus, err := consensus.New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsKey), reg, decider, 3, false)
5250
if err != nil {
5351
t.Fatalf("Cannot craeate consensus: %v", err)
5452
}
55-
nodeconfig.SetNetworkType(nodeconfig.Devnet)
53+
nodeconfig.SetNetworkType(nodeconfig.Testnet)
5654
node := New(host, consensus, engine, collection, nil, nil, nil, nil, nil, reg)
5755

5856
txs := make(map[common.Address]types.Transactions)

node/node_newblock_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,8 @@ func TestFinalizeNewBlockAsync(t *testing.T) {
6363
node.Worker.CommitTransactions(
6464
txs, stks, common.Address{},
6565
)
66-
commitSigs := make(chan []byte)
67-
go func() {
68-
commitSigs <- []byte{}
69-
}()
66+
commitSigs := make(chan []byte, 1)
67+
commitSigs <- []byte{}
7068

7169
block, _ := node.Worker.FinalizeNewBlock(
7270
commitSigs, func() uint64 { return 0 }, common.Address{}, nil, nil,

0 commit comments

Comments
 (0)