aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2018-11-13 09:43:28 +0800
committerGitHub <noreply@github.com>2018-11-13 09:43:28 +0800
commit206cdb5b68d3226eb4a771b374093a51999b3b17 (patch)
tree88c4f8af7e15e23010676d9988fa3442167d3c17
parentf2e1d268fff6815240d70f77e9b4fad6f96bd008 (diff)
downloaddexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.tar
dexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.tar.gz
dexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.tar.bz2
dexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.tar.lz
dexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.tar.xz
dexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.tar.zst
dexon-consensus-206cdb5b68d3226eb4a771b374093a51999b3b17.zip
core: Reduce call to Application.VerifyBlock (#317)
-rw-r--r--core/consensus.go3
-rw-r--r--core/leader-selector.go24
-rw-r--r--core/leader-selector_test.go28
-rw-r--r--core/types/block.go18
4 files changed, 61 insertions, 12 deletions
diff --git a/core/consensus.go b/core/consensus.go
index 89f2242..d12d30a 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -1002,9 +1002,8 @@ func (con *Consensus) preProcessBlock(b *types.Block) (err error) {
// deliverBlock deliver a block to application layer.
func (con *Consensus) deliverBlock(b *types.Block) {
- // TODO(mission): clone types.FinalizationResult
con.logger.Debug("Calling Application.BlockDelivered", "block", b)
- con.app.BlockDelivered(b.Hash, b.Position, b.Finalization)
+ con.app.BlockDelivered(b.Hash, b.Position, b.Finalization.Clone())
if b.Position.Round+roundShift == con.roundToNotify {
// Only the first block delivered of that round would
// trigger this noitification.
diff --git a/core/leader-selector.go b/core/leader-selector.go
index 247ce89..a68f8ab 100644
--- a/core/leader-selector.go
+++ b/core/leader-selector.go
@@ -101,13 +101,17 @@ func (l *leaderSelector) leaderBlockHash() common.Hash {
defer l.lock.Unlock()
newPendingBlocks := []*types.Block{}
for _, b := range l.pendingBlocks {
+ ok, dist := l.potentialLeader(b)
+ if !ok {
+ continue
+ }
ok, err := l.validLeader(b)
if err != nil {
l.logger.Error("Error checking validLeader", "error", err, "block", b)
continue
}
if ok {
- l.updateLeader(b)
+ l.updateLeader(b, dist)
} else {
newPendingBlocks = append(newPendingBlocks, b)
}
@@ -126,6 +130,10 @@ func (l *leaderSelector) processBlock(block *types.Block) error {
}
l.lock.Lock()
defer l.lock.Unlock()
+ ok, dist := l.potentialLeader(block)
+ if !ok {
+ return nil
+ }
ok, err = l.validLeader(block)
if err != nil {
return err
@@ -134,14 +142,20 @@ func (l *leaderSelector) processBlock(block *types.Block) error {
l.pendingBlocks = append(l.pendingBlocks, block)
return nil
}
- l.updateLeader(block)
+ l.updateLeader(block, dist)
return nil
}
-func (l *leaderSelector) updateLeader(block *types.Block) {
+
+func (l *leaderSelector) potentialLeader(block *types.Block) (bool, *big.Int) {
dist := l.distance(block.CRSSignature)
cmp := l.minCRSBlock.Cmp(dist)
if cmp > 0 || (cmp == 0 && block.Hash.Less(l.minBlockHash)) {
- l.minCRSBlock = dist
- l.minBlockHash = block.Hash
+ return true, dist
}
+ return false, dist
+}
+
+func (l *leaderSelector) updateLeader(block *types.Block, dist *big.Int) {
+ l.minCRSBlock = dist
+ l.minBlockHash = block.Hash
}
diff --git a/core/leader-selector_test.go b/core/leader-selector_test.go
index f2c88f1..2edad60 100644
--- a/core/leader-selector_test.go
+++ b/core/leader-selector_test.go
@@ -150,6 +150,34 @@ func (s *LeaderSelectorTestSuite) TestValidLeaderFn() {
s.Len(leader.pendingBlocks, 0)
}
+func (s *LeaderSelectorTestSuite) TestPotentialLeader() {
+ leader := s.newLeader()
+ blocks := make(map[common.Hash]*types.Block)
+ for i := 0; i < 10; i++ {
+ if i > 0 {
+ s.mockValidLeaderDefault = false
+ }
+ prv, err := ecdsa.NewPrivateKey()
+ s.Require().NoError(err)
+ block := &types.Block{
+ ProposerID: types.NewNodeID(prv.PublicKey()),
+ Hash: common.NewRandomHash(),
+ }
+ s.Require().NoError(
+ NewAuthenticator(prv).SignCRS(block, leader.hashCRS))
+ ok, _ := leader.potentialLeader(block)
+ s.Require().NoError(leader.processBlock(block))
+ if i > 0 {
+ if ok {
+ s.Contains(leader.pendingBlocks, block)
+ } else {
+ s.NotContains(leader.pendingBlocks, block)
+ }
+ blocks[block.Hash] = block
+ }
+ }
+}
+
func TestLeaderSelector(t *testing.T) {
suite.Run(t, new(LeaderSelectorTestSuite))
}
diff --git a/core/types/block.go b/core/types/block.go
index 27416d8..b24e1f7 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -83,6 +83,18 @@ type FinalizationResult struct {
Height uint64 `json:"height"`
}
+// Clone returns a deep copy of FinalizationResult
+func (f FinalizationResult) Clone() FinalizationResult {
+ frcopy := FinalizationResult{
+ ParentHash: f.ParentHash,
+ Timestamp: f.Timestamp,
+ Height: f.Height,
+ }
+ frcopy.Randomness = make([]byte, len(f.Randomness))
+ copy(frcopy.Randomness, f.Randomness)
+ return frcopy
+}
+
type rlpFinalizationResult struct {
ParentHash common.Hash
Randomness []byte
@@ -223,9 +235,7 @@ func (b *Block) Clone() (bcopy *Block) {
bcopy.Position.Height = b.Position.Height
bcopy.Signature = b.Signature.Clone()
bcopy.CRSSignature = b.CRSSignature.Clone()
- bcopy.Finalization.ParentHash = b.Finalization.ParentHash
- bcopy.Finalization.Timestamp = b.Finalization.Timestamp
- bcopy.Finalization.Height = b.Finalization.Height
+ bcopy.Finalization = b.Finalization.Clone()
bcopy.Witness.Height = b.Witness.Height
bcopy.Witness.Data = make([]byte, len(b.Witness.Data))
copy(bcopy.Witness.Data, b.Witness.Data)
@@ -235,8 +245,6 @@ func (b *Block) Clone() (bcopy *Block) {
bcopy.Payload = make([]byte, len(b.Payload))
copy(bcopy.Payload, b.Payload)
bcopy.PayloadHash = b.PayloadHash
- bcopy.Finalization.Randomness = make([]byte, len(b.Finalization.Randomness))
- copy(bcopy.Finalization.Randomness, b.Finalization.Randomness)
return
}