OSDN Git Service

add_soft_limit for max_tx per block (#555)
[bytom/vapor.git] / protocol / bbft.go
index 888ce99..e1fa489 100644 (file)
@@ -6,13 +6,13 @@ import (
 
        log "github.com/sirupsen/logrus"
 
-       "github.com/vapor/config"
-       "github.com/vapor/crypto/ed25519/chainkd"
-       "github.com/vapor/errors"
-       "github.com/vapor/event"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/protocol/state"
+       "github.com/bytom/vapor/config"
+       "github.com/bytom/vapor/crypto/ed25519/chainkd"
+       "github.com/bytom/vapor/errors"
+       "github.com/bytom/vapor/event"
+       "github.com/bytom/vapor/protocol/bc"
+       "github.com/bytom/vapor/protocol/bc/types"
+       "github.com/bytom/vapor/protocol/state"
 )
 
 const (
@@ -20,9 +20,9 @@ const (
 )
 
 var (
-       errDoubleSignBlock  = errors.New("the consensus is double sign in same height of different block")
+       // ErrDoubleSignBlock represent the consensus is double sign in same height of different block
+       ErrDoubleSignBlock  = errors.New("the consensus is double sign in same height of different block")
        errInvalidSignature = errors.New("the signature of block is invalid")
-       errSignForkChain    = errors.New("can not sign fork before the irreversible block")
 )
 
 func signCacheKey(blockHash, pubkey string) string {
@@ -53,7 +53,7 @@ func (c *Chain) checkDoubleSign(bh *types.BlockHeader, xPub string) error {
                }
 
                if blockHeader.BlockWitness.Get(consensusNode.Order) != nil {
-                       return errDoubleSignBlock
+                       return ErrDoubleSignBlock
                }
        }
        return nil
@@ -133,17 +133,24 @@ func (c *Chain) validateSign(block *types.Block) error {
                        cachekey := signCacheKey(blockHash.String(), pubKey)
                        if signature, ok := c.signatureCache.Get(cachekey); ok {
                                block.Set(node.Order, signature.([]byte))
-                               c.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: blockHash, Signature: signature.([]byte), XPub: []byte(pubKey)})
+                               c.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: blockHash, Signature: signature.([]byte), XPub: node.XPub[:]})
                                c.signatureCache.Remove(cachekey)
                        } else {
                                continue
                        }
                }
 
-               if err := c.checkNodeSign(&block.BlockHeader, node, block.Get(node.Order)); err == errDoubleSignBlock {
+               if err := c.checkNodeSign(&block.BlockHeader, node, block.Get(node.Order)); err == ErrDoubleSignBlock {
                        log.WithFields(log.Fields{"module": logModule, "blockHash": blockHash.String(), "pubKey": pubKey}).Warn("the consensus node double sign the same height of different block")
-                       block.BlockWitness.Delete(node.Order)
-                       continue
+                       // if the blocker double sign & become the mainchain, that means
+                       // all the side chain will reject the main chain make the chain
+                       // fork. All the node will ban each other & can't roll back
+                       if blocker != pubKey {
+                               block.BlockWitness.Delete(node.Order)
+                               continue
+                       }
+
+                       return err
                } else if err != nil {
                        return err
                }
@@ -168,7 +175,7 @@ func (c *Chain) ProcessBlockSignature(signature, xPub []byte, blockHash *bc.Hash
        // save the signature if the block is not exist
        if blockHeader == nil {
                var xPubKey chainkd.XPub
-               copy(xPub[:], xPub[:])
+               copy(xPubKey[:], xPub[:])
                if !xPubKey.Verify(blockHash.Bytes(), signature) {
                        return errInvalidSignature
                }
@@ -199,27 +206,56 @@ func (c *Chain) ProcessBlockSignature(signature, xPub []byte, blockHash *bc.Hash
        return c.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: *blockHash, Signature: signature, XPub: xPub})
 }
 
-// SignBlock signing the block if current node is consensus node
-func (c *Chain) SignBlock(block *types.Block) ([]byte, error) {
+// SignBlockHeader signing the block if current node is consensus node
+func (c *Chain) SignBlockHeader(blockHeader *types.BlockHeader) error {
+       c.cond.L.Lock()
+       _, err := c.signBlockHeader(blockHeader)
+       c.cond.L.Unlock()
+       return err
+}
+
+func (c *Chain) applyBlockSign(blockHeader *types.BlockHeader) error {
+       signature, err := c.signBlockHeader(blockHeader)
+       if err != nil {
+               return err
+       }
+
+       if len(signature) == 0 {
+               return nil
+       }
+
+       if err := c.store.SaveBlockHeader(blockHeader); err != nil {
+               return err
+       }
+
+       xpub := config.CommonConfig.PrivateKey().XPub()
+       return c.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: blockHeader.Hash(), Signature: signature, XPub: xpub[:]})
+}
+
+func (c *Chain) signBlockHeader(blockHeader *types.BlockHeader) ([]byte, error) {
        xprv := config.CommonConfig.PrivateKey()
-       xpubStr := xprv.XPub().String()
-       node, err := c.getConsensusNode(&block.PreviousBlockHash, xpubStr)
+       xpub := xprv.XPub()
+       node, err := c.getConsensusNode(&blockHeader.PreviousBlockHash, xpub.String())
+       blockHash := blockHeader.Hash()
        if err == errNotFoundConsensusNode {
+               log.WithFields(log.Fields{"module": logModule, "blockHash": blockHash.String()}).Debug("can't find consensus node of current node")
                return nil, nil
        } else if err != nil {
                return nil, err
        }
 
-       if err := c.checkDoubleSign(&block.BlockHeader, node.XPub.String()); err == errDoubleSignBlock {
+       if len(blockHeader.Get(node.Order)) != 0 {
+               return nil, nil
+       }
+
+       if err := c.checkDoubleSign(blockHeader, node.XPub.String()); err == ErrDoubleSignBlock {
+               log.WithFields(log.Fields{"module": logModule, "blockHash": blockHash.String()}).Warn("current node has double sign the block")
                return nil, nil
        } else if err != nil {
                return nil, err
        }
 
-       signature := block.Get(node.Order)
-       if len(signature) == 0 {
-               signature = xprv.Sign(block.Hash().Bytes())
-               block.Set(node.Order, signature)
-       }
+       signature := xprv.Sign(blockHeader.Hash().Bytes())
+       blockHeader.Set(node.Order, signature)
        return signature, nil
 }