aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2018-08-30 15:39:06 +0800
committermissionliao <38416648+missionliao@users.noreply.github.com>2018-08-30 15:39:06 +0800
commita4e0da981a3dfc8817d39be65cb5b24938b0761a (patch)
tree9c372875258bd942c30050643604d7d1448d2627 /core
parent8cb1d5c4f3f7f93d8b2c54addf5c2caced0a1eb8 (diff)
downloaddexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.tar
dexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.tar.gz
dexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.tar.bz2
dexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.tar.lz
dexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.tar.xz
dexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.tar.zst
dexon-consensus-a4e0da981a3dfc8817d39be65cb5b24938b0761a.zip
core: Change the lattice key from validatorID to chainID. (#83)
* Add chainID in simulation.Validator * Change validatorid to chainID in rbModule
Diffstat (limited to 'core')
-rw-r--r--core/consensus.go1
-rw-r--r--core/consensus_test.go26
-rw-r--r--core/reliable-broadcast.go100
-rw-r--r--core/reliable-broadcast_test.go141
-rw-r--r--core/test/blocks-generator.go5
5 files changed, 176 insertions, 97 deletions
diff --git a/core/consensus.go b/core/consensus.go
index 6c841bf..d163686 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -79,6 +79,7 @@ func NewConsensus(
// Setup acking by information returned from Governace.
rb := newReliableBroadcast()
+ rb.setChainNum(len(validatorSet))
for vID := range validatorSet {
rb.addValidator(vID)
}
diff --git a/core/consensus_test.go b/core/consensus_test.go
index cd7ff02..46df8eb 100644
--- a/core/consensus_test.go
+++ b/core/consensus_test.go
@@ -36,10 +36,12 @@ type ConsensusTestSuite struct {
func (s *ConsensusTestSuite) prepareGenesisBlock(
proposerID types.ValidatorID,
+ chainID uint64,
con *Consensus) *types.Block {
block := &types.Block{
ProposerID: proposerID,
+ ChainID: chainID,
}
err := con.PrepareGenesisBlock(block, time.Now().UTC())
s.Require().Nil(err)
@@ -102,13 +104,13 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
}
}
// Genesis blocks
- b00 := s.prepareGenesisBlock(validators[0], objs[validators[0]].con)
+ b00 := s.prepareGenesisBlock(validators[0], 0, objs[validators[0]].con)
time.Sleep(minInterval)
- b10 := s.prepareGenesisBlock(validators[1], objs[validators[1]].con)
+ b10 := s.prepareGenesisBlock(validators[1], 1, objs[validators[1]].con)
time.Sleep(minInterval)
- b20 := s.prepareGenesisBlock(validators[2], objs[validators[2]].con)
+ b20 := s.prepareGenesisBlock(validators[2], 2, objs[validators[2]].con)
time.Sleep(minInterval)
- b30 := s.prepareGenesisBlock(validators[3], objs[validators[3]].con)
+ b30 := s.prepareGenesisBlock(validators[3], 3, objs[validators[3]].con)
broadcast(b00)
broadcast(b10)
broadcast(b20)
@@ -117,6 +119,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b11 := &types.Block{
ProposerID: validators[1],
+ ChainID: 1,
}
b11.Hash, err = hashBlock(b11)
s.Require().Nil(err)
@@ -131,6 +134,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b01 := &types.Block{
ProposerID: validators[0],
+ ChainID: 0,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[0]].con.PrepareBlock(b01, time.Now().UTC()))
@@ -140,6 +144,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b21 := &types.Block{
ProposerID: validators[2],
+ ChainID: 2,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[2]].con.PrepareBlock(b21, time.Now().UTC()))
@@ -149,6 +154,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b31 := &types.Block{
ProposerID: validators[3],
+ ChainID: 3,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[3]].con.PrepareBlock(b31, time.Now().UTC()))
@@ -163,6 +169,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b02 := &types.Block{
ProposerID: validators[0],
+ ChainID: 0,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[0]].con.PrepareBlock(b02, time.Now().UTC()))
@@ -174,6 +181,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b12 := &types.Block{
ProposerID: validators[1],
+ ChainID: 1,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[1]].con.PrepareBlock(b12, time.Now().UTC()))
@@ -186,6 +194,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b22 := &types.Block{
ProposerID: validators[2],
+ ChainID: 2,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[2]].con.PrepareBlock(b22, time.Now().UTC()))
@@ -197,6 +206,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() {
time.Sleep(minInterval)
b32 := &types.Block{
ProposerID: validators[3],
+ ChainID: 3,
Hash: common.NewRandomHash(),
}
req.Nil(objs[validators[3]].con.PrepareBlock(b32, time.Now().UTC()))
@@ -286,10 +296,10 @@ func (s *ConsensusTestSuite) TestPrepareBlock() {
con *Consensus
}{app, con}
}
- b00 := s.prepareGenesisBlock(validators[0], objs[validators[0]].con)
- b10 := s.prepareGenesisBlock(validators[1], objs[validators[1]].con)
- b20 := s.prepareGenesisBlock(validators[2], objs[validators[2]].con)
- b30 := s.prepareGenesisBlock(validators[3], objs[validators[3]].con)
+ b00 := s.prepareGenesisBlock(validators[0], 0, objs[validators[0]].con)
+ b10 := s.prepareGenesisBlock(validators[1], 1, objs[validators[1]].con)
+ b20 := s.prepareGenesisBlock(validators[2], 2, objs[validators[2]].con)
+ b30 := s.prepareGenesisBlock(validators[3], 3, objs[validators[3]].con)
for _, obj := range objs {
con := obj.con
req.Nil(con.ProcessBlock(b00))
diff --git a/core/reliable-broadcast.go b/core/reliable-broadcast.go
index d9a469a..918bad9 100644
--- a/core/reliable-broadcast.go
+++ b/core/reliable-broadcast.go
@@ -39,7 +39,7 @@ const (
// reliableBroadcast is a module for reliable broadcast.
type reliableBroadcast struct {
// lattice stores validator's blocks and other info.
- lattice map[types.ValidatorID]*rbcValidatorStatus
+ lattice []*rbcValidatorStatus
// blockInfos stores block infos.
blockInfos map[common.Hash]*rbcBlockInfo
@@ -47,6 +47,9 @@ type reliableBroadcast struct {
// receivedBlocks stores blocks which is received but its acks are not all
// in lattice.
receivedBlocks map[common.Hash]*types.Block
+
+ // validators stores validator set.
+ validators map[types.ValidatorID]struct{}
}
type rbcValidatorStatus struct {
@@ -58,21 +61,22 @@ type rbcValidatorStatus struct {
// acked height + 1. Initialized to 0, when genesis blocks are still not
// being acked. For example, rb.lattice[vid1].NextAck[vid2] - 1 is the last
// acked height by vid1 acking vid2.
- nextAck map[types.ValidatorID]uint64
+ nextAck []uint64
// nextOutput is the next output height of block, default to 0.
nextOutput uint64
}
type rbcBlockInfo struct {
- block *types.Block
- receivedTime time.Time
- status blockStatus
- ackedValidators map[types.ValidatorID]struct{}
+ block *types.Block
+ receivedTime time.Time
+ status blockStatus
+ ackedChain map[uint64]struct{}
}
// Errors for sanity check error.
var (
+ ErrInvalidChainID = fmt.Errorf("invalid chain id")
ErrInvalidProposerID = fmt.Errorf("invalid proposer id")
ErrInvalidTimestamp = fmt.Errorf("invalid timestamp")
ErrForkBlock = fmt.Errorf("fork block")
@@ -85,20 +89,25 @@ var (
// newReliableBroadcast creates a new reliableBroadcast struct.
func newReliableBroadcast() *reliableBroadcast {
return &reliableBroadcast{
- lattice: make(map[types.ValidatorID]*rbcValidatorStatus),
blockInfos: make(map[common.Hash]*rbcBlockInfo),
receivedBlocks: make(map[common.Hash]*types.Block),
+ validators: make(map[types.ValidatorID]struct{}),
}
}
func (rb *reliableBroadcast) sanityCheck(b *types.Block) error {
+ // Check if the chain id is valid.
+ if b.ChainID >= uint64(len(rb.lattice)) {
+ return ErrInvalidChainID
+ }
+
// Check if its proposer is in validator set.
- if _, exist := rb.lattice[b.ProposerID]; !exist {
+ if _, exist := rb.validators[b.ProposerID]; !exist {
return ErrInvalidProposerID
}
// Check if it forks.
- if bInLattice, exist := rb.lattice[b.ProposerID].blocks[b.Height]; exist {
+ if bInLattice, exist := rb.lattice[b.ChainID].blocks[b.Height]; exist {
if b.Hash != bInLattice.Hash {
return ErrForkBlock
}
@@ -120,20 +129,24 @@ func (rb *reliableBroadcast) sanityCheck(b *types.Block) error {
for hash := range b.Acks {
if bAckStat, exist := rb.blockInfos[hash]; exist {
bAck := bAckStat.block
- if bAck.Height < rb.lattice[b.ProposerID].nextAck[bAck.ProposerID] {
+ if bAck.Height < rb.lattice[b.ChainID].nextAck[bAck.ChainID] {
return ErrDoubleAck
}
}
}
- // Check if its timestamp is valid.
- for h := range rb.lattice {
- if _, exist := b.Timestamps[h]; !exist {
- return ErrInvalidTimestamp
+ // TODO(jimmy-dexon): verify the timestamps.
+ /*
+ // Check if its timestamp is valid.
+ for h := range rb.lattice {
+ if _, exist := b.Timestamps[h]; !exist {
+ return ErrInvalidTimestamp
+ }
}
- }
- if bParent, exist := rb.lattice[b.ProposerID].blocks[b.Height-1]; exist {
- for hash := range rb.lattice {
+ */
+
+ if bParent, exist := rb.lattice[b.ChainID].blocks[b.Height-1]; exist {
+ for hash := range b.Timestamps {
if b.Timestamps[hash].Before(bParent.Timestamps[hash]) {
return ErrInvalidTimestamp
}
@@ -154,7 +167,7 @@ func (rb *reliableBroadcast) areAllAcksInLattice(b *types.Block) bool {
}
bAck := bAckStat.block
- bAckInLattice, exist := rb.lattice[bAck.ProposerID].blocks[bAck.Height]
+ bAckInLattice, exist := rb.lattice[bAck.ChainID].blocks[bAck.Height]
if !exist {
return false
}
@@ -173,9 +186,9 @@ func (rb *reliableBroadcast) processBlock(block *types.Block) (err error) {
return
}
rb.blockInfos[block.Hash] = &rbcBlockInfo{
- block: block,
- receivedTime: time.Now().UTC(),
- ackedValidators: make(map[types.ValidatorID]struct{}),
+ block: block,
+ receivedTime: time.Now().UTC(),
+ ackedChain: make(map[uint64]struct{}),
}
rb.receivedBlocks[block.Hash] = block
@@ -206,28 +219,28 @@ func (rb *reliableBroadcast) processBlock(block *types.Block) (err error) {
continue
// TODO(mission): how to return for multiple errors?
}
- rb.lattice[b.ProposerID].blocks[b.Height] = b
+ rb.lattice[b.ChainID].blocks[b.Height] = b
delete(rb.receivedBlocks, b.Hash)
for h := range b.Acks {
bAckStat := rb.blockInfos[h]
// Update nextAck only when bAckStat.block.Height + 1 is greater. A
// block might ack blocks proposed by same validator with different
// height.
- if rb.lattice[b.ProposerID].nextAck[bAckStat.block.ProposerID] < bAckStat.block.Height+1 {
- rb.lattice[b.ProposerID].nextAck[bAckStat.block.ProposerID] = bAckStat.block.Height + 1
+ if rb.lattice[b.ChainID].nextAck[bAckStat.block.ChainID] < bAckStat.block.Height+1 {
+ rb.lattice[b.ChainID].nextAck[bAckStat.block.ChainID] = bAckStat.block.Height + 1
}
- // Update ackedValidators for each ack blocks and its parents.
+ // Update ackedChain for each ack blocks and its parents.
for {
- if _, exist := bAckStat.ackedValidators[b.ProposerID]; exist {
+ if _, exist := bAckStat.ackedChain[b.ChainID]; exist {
break
}
if bAckStat.status > blockStatusInit {
break
}
- bAckStat.ackedValidators[b.ProposerID] = struct{}{}
+ bAckStat.ackedChain[b.ChainID] = struct{}{}
// A block is strongly acked if it is acked by more than
// 2 * (maximum number of byzatine validators) unique validators.
- if len(bAckStat.ackedValidators) > 2*((len(rb.lattice)-1)/3) {
+ if len(bAckStat.ackedChain) > 2*((len(rb.lattice)-1)/3) {
blocksToAcked[bAckStat.block.Hash] = bAckStat.block
}
if bAckStat.block.Height == 0 {
@@ -371,19 +384,19 @@ func (rb *reliableBroadcast) prepareBlock(block *types.Block) {
}
// Initial timestamps with current validator set.
times := make(map[types.ValidatorID]time.Time)
- for vID := range rb.lattice {
+ for vID := range rb.validators {
times[vID] = time.Time{}
}
acks := make(map[common.Hash]struct{})
- for vID := range rb.lattice {
+ for chainID := range rb.lattice {
// find height of the latest block for that validator.
var (
curBlock *types.Block
- nextHeight = rb.lattice[block.ProposerID].nextAck[vID]
+ nextHeight = rb.lattice[block.ChainID].nextAck[chainID]
)
for {
- tmpBlock, exists := rb.lattice[vID].blocks[nextHeight]
+ tmpBlock, exists := rb.lattice[chainID].blocks[nextHeight]
if !exists {
break
}
@@ -395,7 +408,7 @@ func (rb *reliableBroadcast) prepareBlock(block *types.Block) {
}
acks[curBlock.Hash] = struct{}{}
accumulateTimestamps(times, curBlock)
- if vID == block.ProposerID {
+ if uint64(chainID) == block.ChainID {
block.ParentHash = curBlock.Hash
block.Height = curBlock.Height + 1
}
@@ -407,17 +420,22 @@ func (rb *reliableBroadcast) prepareBlock(block *types.Block) {
// addValidator adds validator in the validator set.
func (rb *reliableBroadcast) addValidator(h types.ValidatorID) {
- rb.lattice[h] = &rbcValidatorStatus{
- blocks: make(map[uint64]*types.Block),
- nextAck: make(map[types.ValidatorID]uint64),
- nextOutput: 0,
- }
+ rb.validators[h] = struct{}{}
}
// deleteValidator deletes validator in validator set.
func (rb *reliableBroadcast) deleteValidator(h types.ValidatorID) {
- for h := range rb.lattice {
- delete(rb.lattice[h].nextAck, h)
+ delete(rb.validators, h)
+}
+
+// setChainNum set the number of chains.
+func (rb *reliableBroadcast) setChainNum(num int) {
+ rb.lattice = make([]*rbcValidatorStatus, num)
+ for i := range rb.lattice {
+ rb.lattice[i] = &rbcValidatorStatus{
+ blocks: make(map[uint64]*types.Block),
+ nextAck: make([]uint64, num),
+ nextOutput: 0,
+ }
}
- delete(rb.lattice, h)
}
diff --git a/core/reliable-broadcast_test.go b/core/reliable-broadcast_test.go
index 28edda7..0dcbb80 100644
--- a/core/reliable-broadcast_test.go
+++ b/core/reliable-broadcast_test.go
@@ -56,6 +56,12 @@ func (s *ReliableBroadcastTest) prepareGenesisBlock(
Acks: make(map[common.Hash]struct{}),
Timestamps: genTimestamps(validatorIDs),
}
+ for i, vID := range validatorIDs {
+ if proposerID == vID {
+ b.ChainID = uint64(i)
+ break
+ }
+ }
for _, vID := range validatorIDs {
b.Timestamps[vID] = time.Time{}
}
@@ -94,6 +100,7 @@ func genTestCase1(s *ReliableBroadcastTest, rb *reliableBroadcast) []types.Valid
rb.addValidator(vid)
vids = append(vids, vid)
}
+ rb.setChainNum(len(vids))
// Add genesis blocks.
for _, vid := range vids {
b = s.prepareGenesisBlock(vid, vids)
@@ -101,13 +108,14 @@ func genTestCase1(s *ReliableBroadcastTest, rb *reliableBroadcast) []types.Valid
}
// Add block 0-1 which acks 0-0.
- h = rb.lattice[vids[0]].blocks[0].Hash
+ h = rb.lattice[0].blocks[0].Hash
b = &types.Block{
ProposerID: vids[0],
ParentHash: h,
Hash: common.NewRandomHash(),
Timestamps: genTimestamps(vids),
Height: 1,
+ ChainID: 0,
Acks: map[common.Hash]struct{}{
h: struct{}{},
},
@@ -116,33 +124,35 @@ func genTestCase1(s *ReliableBroadcastTest, rb *reliableBroadcast) []types.Valid
b.Hash, err = hashBlock(b)
s.Require().Nil(err)
s.Require().Nil(rb.processBlock(b))
- s.Require().NotNil(rb.lattice[vids[0]].blocks[1])
+ s.Require().NotNil(rb.lattice[0].blocks[1])
// Add block 0-2 which acks 0-1 and 1-0.
- h = rb.lattice[vids[0]].blocks[1].Hash
+ h = rb.lattice[0].blocks[1].Hash
b = &types.Block{
ProposerID: vids[0],
ParentHash: h,
Height: 2,
+ ChainID: 0,
Timestamps: genTimestamps(vids),
Acks: map[common.Hash]struct{}{
h: struct{}{},
- rb.lattice[vids[1]].blocks[0].Hash: struct{}{},
+ rb.lattice[1].blocks[0].Hash: struct{}{},
},
}
b.Hash, err = hashBlock(b)
s.Require().Nil(err)
s.Require().Nil(rb.processBlock(b))
- s.Require().NotNil(rb.lattice[vids[0]].blocks[2])
+ s.Require().NotNil(rb.lattice[0].blocks[2])
// Add block 0-3 which acks 0-2.
- h = rb.lattice[vids[0]].blocks[2].Hash
+ h = rb.lattice[0].blocks[2].Hash
b = &types.Block{
ProposerID: vids[0],
ParentHash: h,
Hash: common.NewRandomHash(),
Timestamps: genTimestamps(vids),
Height: 3,
+ ChainID: 0,
Acks: map[common.Hash]struct{}{
h: struct{}{},
},
@@ -150,16 +160,17 @@ func genTestCase1(s *ReliableBroadcastTest, rb *reliableBroadcast) []types.Valid
b.Hash, err = hashBlock(b)
s.Require().Nil(err)
s.Require().Nil(rb.processBlock(b))
- s.Require().NotNil(rb.lattice[vids[0]].blocks[3])
+ s.Require().NotNil(rb.lattice[0].blocks[3])
// Add block 3-1 which acks 3-0.
- h = rb.lattice[vids[3]].blocks[0].Hash
+ h = rb.lattice[3].blocks[0].Hash
b = &types.Block{
ProposerID: vids[3],
ParentHash: h,
Hash: common.NewRandomHash(),
Timestamps: genTimestamps(vids),
Height: 1,
+ ChainID: 3,
Acks: map[common.Hash]struct{}{
h: struct{}{},
},
@@ -167,7 +178,7 @@ func genTestCase1(s *ReliableBroadcastTest, rb *reliableBroadcast) []types.Valid
b.Hash, err = hashBlock(b)
s.Require().Nil(err)
s.Require().Nil(rb.processBlock(b))
- s.Require().NotNil(rb.lattice[vids[3]].blocks[0])
+ s.Require().NotNil(rb.lattice[3].blocks[0])
return vids
}
@@ -195,6 +206,7 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
ProposerID: vids[0],
ParentHash: common.NewRandomHash(),
Height: 10,
+ ChainID: 0,
Acks: make(map[common.Hash]struct{}),
}
b.Hash, err = hashBlock(b)
@@ -208,8 +220,9 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
ProposerID: vids[1],
ParentHash: common.NewRandomHash(),
Height: 1,
+ ChainID: 1,
Acks: map[common.Hash]struct{}{
- rb.lattice[vids[2]].blocks[0].Hash: struct{}{},
+ rb.lattice[2].blocks[0].Hash: struct{}{},
},
}
b.Hash, err = hashBlock(b)
@@ -219,11 +232,12 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
s.Require().Equal(ErrNotAckParent.Error(), err.Error())
// Non-genesis block which acks its parent but the height is invalid.
- h = rb.lattice[vids[1]].blocks[0].Hash
+ h = rb.lattice[1].blocks[0].Hash
b = &types.Block{
ProposerID: vids[1],
ParentHash: h,
Height: 2,
+ ChainID: 1,
Acks: map[common.Hash]struct{}{
h: struct{}{},
},
@@ -235,7 +249,7 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
s.Require().Equal(ErrInvalidBlockHeight.Error(), err.Error())
// Invalid proposer ID.
- h = rb.lattice[vids[1]].blocks[0].Hash
+ h = rb.lattice[1].blocks[0].Hash
b = &types.Block{
ProposerID: types.ValidatorID{Hash: common.NewRandomHash()},
ParentHash: h,
@@ -250,12 +264,30 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
s.Require().NotNil(err)
s.Require().Equal(ErrInvalidProposerID.Error(), err.Error())
+ // Invalid chain ID.
+ h = rb.lattice[1].blocks[0].Hash
+ b = &types.Block{
+ ProposerID: vids[1],
+ ParentHash: h,
+ Height: 1,
+ ChainID: 100,
+ Acks: map[common.Hash]struct{}{
+ h: struct{}{},
+ },
+ }
+ b.Hash, err = hashBlock(b)
+ s.Require().Nil(err)
+ err = rb.sanityCheck(b)
+ s.Require().NotNil(err)
+ s.Require().Equal(ErrInvalidChainID.Error(), err.Error())
+
// Fork block.
- h = rb.lattice[vids[0]].blocks[0].Hash
+ h = rb.lattice[0].blocks[0].Hash
b = &types.Block{
ProposerID: vids[0],
ParentHash: h,
Height: 1,
+ ChainID: 0,
Acks: map[common.Hash]struct{}{
h: struct{}{},
},
@@ -270,14 +302,15 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
s.Require().Equal(ErrForkBlock.Error(), err.Error())
// Replicated ack.
- h = rb.lattice[vids[0]].blocks[3].Hash
+ h = rb.lattice[0].blocks[3].Hash
b = &types.Block{
ProposerID: vids[0],
ParentHash: h,
Height: 4,
+ ChainID: 0,
Acks: map[common.Hash]struct{}{
h: struct{}{},
- rb.lattice[vids[1]].blocks[0].Hash: struct{}{},
+ rb.lattice[1].blocks[0].Hash: struct{}{},
},
}
b.Hash, err = hashBlock(b)
@@ -287,11 +320,12 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
s.Require().Equal(ErrDoubleAck.Error(), err.Error())
// Normal block.
- h = rb.lattice[vids[1]].blocks[0].Hash
+ h = rb.lattice[1].blocks[0].Hash
b = &types.Block{
ProposerID: vids[1],
ParentHash: h,
Height: 1,
+ ChainID: 1,
Acks: map[common.Hash]struct{}{
h: struct{}{},
common.NewRandomHash(): struct{}{},
@@ -306,9 +340,8 @@ func (s *ReliableBroadcastTest) TestSanityCheck() {
func (s *ReliableBroadcastTest) TestAreAllAcksInLattice() {
var b *types.Block
- var vids []types.ValidatorID
rb := newReliableBroadcast()
- vids = genTestCase1(s, rb)
+ genTestCase1(s, rb)
// Empty ack should get true, although won't pass sanity check.
b = &types.Block{
@@ -319,8 +352,8 @@ func (s *ReliableBroadcastTest) TestAreAllAcksInLattice() {
// Acks blocks in lattice
b = &types.Block{
Acks: map[common.Hash]struct{}{
- rb.lattice[vids[0]].blocks[0].Hash: struct{}{},
- rb.lattice[vids[0]].blocks[1].Hash: struct{}{},
+ rb.lattice[0].blocks[0].Hash: struct{}{},
+ rb.lattice[0].blocks[1].Hash: struct{}{},
},
}
s.Require().True(rb.areAllAcksInLattice(b))
@@ -343,29 +376,30 @@ func (s *ReliableBroadcastTest) TestStrongAck() {
// Check block 0-0 to 0-3 before adding 1-1 and 2-1.
for i := uint64(0); i < 4; i++ {
- s.Require().Equal(blockStatusInit, rb.blockInfos[rb.lattice[vids[0]].blocks[i].Hash].status)
+ s.Require().Equal(blockStatusInit, rb.blockInfos[rb.lattice[0].blocks[i].Hash].status)
}
// Add block 1-1 which acks 1-0 and 0-2, and block 0-0 to 0-3 are still
// in blockStatusInit, because they are not strongly acked.
b = &types.Block{
ProposerID: vids[1],
- ParentHash: rb.lattice[vids[1]].blocks[0].Hash,
+ ParentHash: rb.lattice[1].blocks[0].Hash,
Hash: common.NewRandomHash(),
Height: 1,
+ ChainID: 1,
Timestamps: genTimestamps(vids),
Acks: map[common.Hash]struct{}{
- rb.lattice[vids[0]].blocks[2].Hash: struct{}{},
- rb.lattice[vids[1]].blocks[0].Hash: struct{}{},
+ rb.lattice[0].blocks[2].Hash: struct{}{},
+ rb.lattice[1].blocks[0].Hash: struct{}{},
},
}
var err error
b.Hash, err = hashBlock(b)
s.Require().Nil(err)
s.Require().Nil(rb.processBlock(b))
- s.Require().NotNil(rb.lattice[vids[1]].blocks[1])
+ s.Require().NotNil(rb.lattice[1].blocks[1])
for i := uint64(0); i < 4; i++ {
- h := rb.lattice[vids[0]].blocks[i].Hash
+ h := rb.lattice[0].blocks[i].Hash
s.Require().Equal(blockStatusInit, rb.blockInfos[h].status)
}
@@ -373,23 +407,24 @@ func (s *ReliableBroadcastTest) TestStrongAck() {
// 0-3 is still not.
b = &types.Block{
ProposerID: vids[2],
- ParentHash: rb.lattice[vids[2]].blocks[0].Hash,
+ ParentHash: rb.lattice[2].blocks[0].Hash,
Hash: common.NewRandomHash(),
Height: 1,
+ ChainID: 2,
Timestamps: genTimestamps(vids),
Acks: map[common.Hash]struct{}{
- rb.lattice[vids[0]].blocks[2].Hash: struct{}{},
- rb.lattice[vids[2]].blocks[0].Hash: struct{}{},
+ rb.lattice[0].blocks[2].Hash: struct{}{},
+ rb.lattice[2].blocks[0].Hash: struct{}{},
},
}
b.Hash, err = hashBlock(b)
s.Require().Nil(err)
s.Require().Nil(rb.processBlock(b))
- s.Require().Equal(blockStatusAcked, rb.blockInfos[rb.lattice[vids[0]].blocks[0].Hash].status)
- s.Require().Equal(blockStatusAcked, rb.blockInfos[rb.lattice[vids[0]].blocks[1].Hash].status)
- s.Require().Equal(blockStatusAcked, rb.blockInfos[rb.lattice[vids[0]].blocks[2].Hash].status)
- s.Require().Equal(blockStatusInit, rb.blockInfos[rb.lattice[vids[0]].blocks[3].Hash].status)
+ s.Require().Equal(blockStatusAcked, rb.blockInfos[rb.lattice[0].blocks[0].Hash].status)
+ s.Require().Equal(blockStatusAcked, rb.blockInfos[rb.lattice[0].blocks[1].Hash].status)
+ s.Require().Equal(blockStatusAcked, rb.blockInfos[rb.lattice[0].blocks[2].Hash].status)
+ s.Require().Equal(blockStatusInit, rb.blockInfos[rb.lattice[0].blocks[3].Hash].status)
}
func (s *ReliableBroadcastTest) TestExtractBlocks() {
@@ -400,14 +435,15 @@ func (s *ReliableBroadcastTest) TestExtractBlocks() {
// Add block 1-1 which acks 1-0, 0-2, 3-0.
b = &types.Block{
ProposerID: vids[1],
- ParentHash: rb.lattice[vids[1]].blocks[0].Hash,
+ ParentHash: rb.lattice[1].blocks[0].Hash,
Hash: common.NewRandomHash(),
Height: 1,
+ ChainID: 1,
Timestamps: genTimestamps(vids),
Acks: map[common.Hash]struct{}{
- rb.lattice[vids[0]].blocks[2].Hash: struct{}{},
- rb.lattice[vids[1]].blocks[0].Hash: struct{}{},
- rb.lattice[vids[3]].blocks[0].Hash: struct{}{},
+ rb.lattice[0].blocks[2].Hash: struct{}{},
+ rb.lattice[1].blocks[0].Hash: struct{}{},
+ rb.lattice[3].blocks[0].Hash: struct{}{},
},
}
var err error
@@ -418,14 +454,15 @@ func (s *ReliableBroadcastTest) TestExtractBlocks() {
// Add block 2-1 which acks 0-2, 2-0, 3-0.
b = &types.Block{
ProposerID: vids[2],
- ParentHash: rb.lattice[vids[2]].blocks[0].Hash,
+ ParentHash: rb.lattice[2].blocks[0].Hash,
Hash: common.NewRandomHash(),
Height: 1,
+ ChainID: 2,
Timestamps: genTimestamps(vids),
Acks: map[common.Hash]struct{}{
- rb.lattice[vids[0]].blocks[2].Hash: struct{}{},
- rb.lattice[vids[2]].blocks[0].Hash: struct{}{},
- rb.lattice[vids[3]].blocks[0].Hash: struct{}{},
+ rb.lattice[0].blocks[2].Hash: struct{}{},
+ rb.lattice[2].blocks[0].Hash: struct{}{},
+ rb.lattice[3].blocks[0].Hash: struct{}{},
},
}
b.Hash, err = hashBlock(b)
@@ -433,9 +470,9 @@ func (s *ReliableBroadcastTest) TestExtractBlocks() {
s.Require().Nil(rb.processBlock(b))
hashes := []common.Hash{
- rb.lattice[vids[0]].blocks[0].Hash,
- rb.lattice[vids[0]].blocks[1].Hash,
- rb.lattice[vids[3]].blocks[0].Hash,
+ rb.lattice[0].blocks[0].Hash,
+ rb.lattice[0].blocks[1].Hash,
+ rb.lattice[3].blocks[0].Hash,
}
hashExtracted := map[common.Hash]*types.Block{}
for _, b := range rb.extractBlocks() {
@@ -458,6 +495,7 @@ func (s *ReliableBroadcastTest) TestRandomIntensiveAcking() {
for _, vid := range vids {
rb.addValidator(vid)
}
+ rb.setChainNum(len(vids))
// Generate genesis blocks.
for _, vid := range vids {
b := s.prepareGenesisBlock(vid, vids)
@@ -466,13 +504,14 @@ func (s *ReliableBroadcastTest) TestRandomIntensiveAcking() {
}
for i := 0; i < 5000; i++ {
- vid := vids[rand.Int()%len(vids)]
+ id := rand.Int() % len(vids)
+ vid := vids[id]
height := heights[vid]
heights[vid]++
- parentHash := rb.lattice[vid].blocks[height-1].Hash
+ parentHash := rb.lattice[id].blocks[height-1].Hash
acks := map[common.Hash]struct{}{}
- for _, vid2 := range vids {
- if b, exist := rb.lattice[vid2].blocks[rb.lattice[vid].nextAck[vid2]]; exist {
+ for id2 := range vids {
+ if b, exist := rb.lattice[id2].blocks[rb.lattice[id].nextAck[id2]]; exist {
acks[b.Hash] = struct{}{}
}
}
@@ -480,6 +519,7 @@ func (s *ReliableBroadcastTest) TestRandomIntensiveAcking() {
ProposerID: vid,
ParentHash: parentHash,
Height: height,
+ ChainID: uint64(id),
Timestamps: genTimestamps(vids),
Acks: acks,
}
@@ -526,6 +566,7 @@ func (s *ReliableBroadcastTest) TestRandomlyGeneratedBlocks() {
for i := 0; i < repeat; i++ {
validators := map[types.ValidatorID]struct{}{}
rb := newReliableBroadcast()
+ rb.setChainNum(validatorCount)
stronglyAckedHashes := common.Hashes{}
revealer.Reset()
@@ -580,6 +621,7 @@ func (s *ReliableBroadcastTest) TestPrepareBlock() {
for _, vID := range validators {
rb.addValidator(vID)
}
+ rb.setChainNum(len(validators))
// Setup genesis blocks.
b00 := s.prepareGenesisBlock(validators[0], validators)
time.Sleep(minInterval)
@@ -597,6 +639,7 @@ func (s *ReliableBroadcastTest) TestPrepareBlock() {
// prepareBlock.
b11 := &types.Block{
ProposerID: validators[1],
+ ChainID: 1,
}
rb.prepareBlock(b11)
var err error
@@ -620,6 +663,7 @@ func (s *ReliableBroadcastTest) TestPrepareBlock() {
// Propose/Process a block based on collected info.
b12 := &types.Block{
ProposerID: validators[1],
+ ChainID: 1,
}
rb.prepareBlock(b12)
b12.Hash, err = hashBlock(b12)
@@ -633,6 +677,7 @@ func (s *ReliableBroadcastTest) TestPrepareBlock() {
// get 4 blocks to ack.
b01 := &types.Block{
ProposerID: validators[0],
+ ChainID: 0,
}
rb.prepareBlock(b01)
b01.Hash, err = hashBlock(b01)
diff --git a/core/test/blocks-generator.go b/core/test/blocks-generator.go
index b05d08f..3485b77 100644
--- a/core/test/blocks-generator.go
+++ b/core/test/blocks-generator.go
@@ -163,6 +163,11 @@ func (vs *validatorSetStatus) proposeBlock(
Timestamps: ts,
// TODO(mission.liao): Generate timestamp.
}
+ for i, vID := range vs.validatorIDs {
+ if vID == proposerID {
+ newBlock.ChainID = uint64(i)
+ }
+ }
var err error
newBlock.Hash, err = vs.hashBlock(newBlock)
if err != nil {