Skip to content

Commit 82d0be5

Browse files
committed
Improve the way to hash genesis config (#691)
1 parent 124d71a commit 82d0be5

File tree

5 files changed

+631
-16
lines changed

5 files changed

+631
-16
lines changed

api/api_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,8 +1017,9 @@ func TestServer_GetProductivity(t *testing.T) {
10171017
bc, _, err := setupChain(cfg)
10181018
require.NoError(err)
10191019
require.NoError(bc.Start(context.Background()))
1020+
genesisDigest := cfg.Genesis.Hash()
10201021
require.NoError(addTestingDummyBlocks(bc, test.blockProducers, test.blockProducerKeys, test.numSubEpochs,
1021-
test.failedBlockProducer))
1022+
test.failedBlockProducer, genesisDigest))
10221023
svr.bc = bc
10231024

10241025
res, err := svr.GetProductivity(context.Background(), &iotexapi.GetProductivityRequest{EpochNumber: test.epochNumber})
@@ -1189,9 +1190,10 @@ func addTestingDummyBlocks(
11891190
blockProducerKeys []keypair.PrivateKey,
11901191
numSubEpochs uint64,
11911192
failedBlockProducer genesis.Delegate,
1193+
genesisDigest hash.Hash256,
11921194
) error {
11931195
failedIndex := rand.Intn(int(numSubEpochs))
1194-
prevBlkHash := hash.ZeroHash256
1196+
prevBlkHash := genesisDigest
11951197
var prevBlkHeight uint64
11961198
for i := 0; i < int(numSubEpochs); i++ {
11971199
for j, bp := range blockProducers {

blockchain/blockchain.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ func (bc *blockchain) MintNewBlock(
719719
// The first block's previous block hash is pointing to the digest of genesis config. This is to guarantee all nodes
720720
// could verify that they start from the same genesis
721721
if newblockHeight == 1 {
722-
prevBlkHash = bc.config.Genesis.Digest
722+
prevBlkHash = bc.config.Genesis.Hash()
723723
}
724724
blk, err := block.NewBuilder(ra).
725725
SetPrevBlockHash(prevBlkHash).
@@ -1009,7 +1009,7 @@ func (bc *blockchain) validateBlock(blk *block.Block) error {
10091009
validateTimer := bc.timerFactory.NewTimer("validate")
10101010
prevBlkHash := bc.tipHash
10111011
if blk.Height() == 1 {
1012-
prevBlkHash = bc.config.Genesis.Digest
1012+
prevBlkHash = bc.config.Genesis.Hash()
10131013
}
10141014
err := bc.validator.Validate(blk, bc.tipHeight, prevBlkHash)
10151015
validateTimer.End()

blockchain/genesis/genesis.go

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@ package genesis
88

99
import (
1010
"flag"
11-
"io/ioutil"
1211
"math/big"
1312
"sort"
1413
"time"
1514

16-
"github.com/iotexproject/iotex-core/pkg/hash"
17-
15+
"github.com/golang/protobuf/proto"
1816
"github.com/pkg/errors"
1917
"go.uber.org/config"
2018
"go.uber.org/zap"
2119

2220
"github.com/iotexproject/iotex-core/address"
21+
"github.com/iotexproject/iotex-core/pkg/hash"
2322
"github.com/iotexproject/iotex-core/pkg/log"
2423
"github.com/iotexproject/iotex-core/pkg/unit"
24+
"github.com/iotexproject/iotex-core/protogen/iotextypes"
2525
"github.com/iotexproject/iotex-core/test/identityset"
2626
)
2727

@@ -84,8 +84,6 @@ type (
8484
Account `ymal:"account"`
8585
Poll `yaml:"poll"`
8686
Rewarding `yaml:"rewarding"`
87-
// Digest is the digest of genesis config file
88-
Digest hash.Hash256
8987
}
9088
// Blockchain contains blockchain level configs
9189
Blockchain struct {
@@ -159,14 +157,8 @@ type (
159157
func New() (Genesis, error) {
160158
opts := make([]config.YAMLOption, 0)
161159
opts = append(opts, config.Static(Default))
162-
genesisDigest := hash.ZeroHash256
163160
if genesisPath != "" {
164161
opts = append(opts, config.File(genesisPath))
165-
genesisCfgBytes, err := ioutil.ReadFile(genesisPath)
166-
if err != nil {
167-
return Genesis{}, err
168-
}
169-
genesisDigest = hash.Hash256b(genesisCfgBytes)
170162
}
171163
yaml, err := config.NewYAML(opts...)
172164
if err != nil {
@@ -177,10 +169,77 @@ func New() (Genesis, error) {
177169
if err := yaml.Get(config.Root).Populate(&genesis); err != nil {
178170
return Genesis{}, errors.Wrap(err, "failed to unmarshal yaml genesis to struct")
179171
}
180-
genesis.Digest = genesisDigest
181172
return genesis, nil
182173
}
183174

175+
// Hash is the hash of genesis config
176+
func (g *Genesis) Hash() hash.Hash256 {
177+
gbProto := iotextypes.GenesisBlockchain{
178+
Timestamp: g.Timestamp,
179+
BlockGasLimit: g.BlockGasLimit,
180+
ActionGasLimit: g.ActionGasLimit,
181+
BlockInterval: g.BlockInterval.Nanoseconds(),
182+
NumSubEpochs: g.NumSubEpochs,
183+
NumDelegates: g.NumDelegates,
184+
NumCandidateDelegates: g.NumCandidateDelegates,
185+
TimeBasedRotation: g.TimeBasedRotation,
186+
}
187+
188+
initBalanceAddrs := make([]string, 0)
189+
for initBalanceAddr := range g.InitBalanceMap {
190+
initBalanceAddrs = append(initBalanceAddrs, initBalanceAddr)
191+
}
192+
sort.Strings(initBalanceAddrs)
193+
initBalances := make([]string, 0)
194+
for _, initBalanceAddr := range initBalanceAddrs {
195+
initBalances = append(initBalances, g.InitBalanceMap[initBalanceAddr])
196+
}
197+
aProto := iotextypes.GenesisAccount{
198+
InitBalanceAddrs: initBalanceAddrs,
199+
InitBalances: initBalances,
200+
}
201+
202+
dProtos := make([]*iotextypes.GenesisDelegate, 0)
203+
for _, d := range g.Delegates {
204+
dProto := iotextypes.GenesisDelegate{
205+
OperatorAddr: d.OperatorAddrStr,
206+
RewardAddr: d.RewardAddrStr,
207+
Votes: d.VotesStr,
208+
}
209+
dProtos = append(dProtos, &dProto)
210+
}
211+
pProto := iotextypes.GenesisPoll{
212+
EnableGravityChainVoting: g.EnableGravityChainVoting,
213+
GravityChainStartHeight: g.GravityChainStartHeight,
214+
RegisterContractAddress: g.RegisterContractAddress,
215+
StakingContractAddress: g.StakingContractAddress,
216+
VoteThreshold: g.VoteThreshold,
217+
ScoreThreshold: g.ScoreThreshold,
218+
SelfStakingThreshold: g.SelfStakingThreshold,
219+
Delegates: dProtos,
220+
}
221+
222+
rProto := iotextypes.GenesisRewarding{
223+
InitAdminAddr: g.InitAdminAddrStr,
224+
InitBalance: g.InitBalanceStr,
225+
BlockReward: g.BlockRewardStr,
226+
EpochReward: g.EpochRewardStr,
227+
NumDelegatesForEpochReward: g.NumDelegatesForEpochReward,
228+
}
229+
230+
gProto := iotextypes.Genesis{
231+
Blockchain: &gbProto,
232+
Account: &aProto,
233+
Poll: &pProto,
234+
Rewarding: &rProto,
235+
}
236+
b, err := proto.Marshal(&gProto)
237+
if err != nil {
238+
log.L().Panic("Error when marshaling genesis proto", zap.Error(err))
239+
}
240+
return hash.Hash256b(b)
241+
}
242+
184243
// InitBalances returns the address that have initial balances and the corresponding amounts. The i-th amount is the
185244
// i-th address' balance.
186245
func (a *Account) InitBalances() ([]address.Address, []*big.Int) {

proto/types/genesis.proto

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) 2019 IoTeX
2+
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
3+
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
4+
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
5+
// License 2.0 that can be found in the LICENSE file.
6+
7+
// To compile the proto, run:
8+
// protoc --go_out=plugins=grpc:$GOPATH/src *.proto
9+
syntax = "proto3";
10+
package iotextypes;
11+
option go_package = "github.com/iotexproject/iotex-core/protogen/iotextypes";
12+
13+
message Genesis {
14+
GenesisBlockchain blockchain = 1;
15+
GenesisAccount account = 2;
16+
GenesisPoll poll = 3;
17+
GenesisRewarding rewarding = 4;
18+
}
19+
20+
message GenesisBlockchain {
21+
int64 timestamp = 1;
22+
uint64 blockGasLimit = 2;
23+
uint64 actionGasLimit = 3;
24+
int64 blockInterval = 4;
25+
uint64 numSubEpochs = 5;
26+
uint64 numDelegates = 6;
27+
uint64 numCandidateDelegates = 7;
28+
bool timeBasedRotation = 8;
29+
}
30+
31+
message GenesisAccount {
32+
repeated string initBalanceAddrs = 1;
33+
repeated string initBalances = 2;
34+
}
35+
36+
message GenesisPoll {
37+
bool enableGravityChainVoting = 1;
38+
uint64 gravityChainStartHeight = 2;
39+
string registerContractAddress = 3;
40+
string stakingContractAddress = 4;
41+
string voteThreshold = 5;
42+
string scoreThreshold = 6;
43+
string selfStakingThreshold = 7;
44+
repeated GenesisDelegate delegates = 8;
45+
}
46+
47+
message GenesisDelegate {
48+
string operatorAddr = 1;
49+
string rewardAddr = 2;
50+
string votes = 3;
51+
}
52+
53+
message GenesisRewarding {
54+
string initAdminAddr = 1;
55+
string initBalance = 2;
56+
string blockReward = 3;
57+
string epochReward = 4;
58+
uint64 numDelegatesForEpochReward = 5;
59+
}

0 commit comments

Comments
 (0)