github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/netsync/consensusmgr/consensus_msg.go (about)

     1  package consensusmgr
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  
     9  	"github.com/tendermint/go-wire"
    10  
    11  	"github.com/bytom/bytom/netsync/peers"
    12  	"github.com/bytom/bytom/protocol/bc"
    13  	"github.com/bytom/bytom/protocol/bc/types"
    14  )
    15  
    16  const (
    17  	blockSignatureByte = byte(0x10)
    18  	blockProposeByte   = byte(0x11)
    19  )
    20  
    21  // ConsensusMessage is a generic message for consensus reactor.
    22  type ConsensusMessage interface {
    23  	String() string
    24  	BroadcastMarkSendRecord(ps *peers.PeerSet, peers []string)
    25  	BroadcastFilterTargetPeers(ps *peers.PeerSet) []string
    26  }
    27  
    28  var _ = wire.RegisterInterface(
    29  	struct{ ConsensusMessage }{},
    30  	wire.ConcreteType{O: &BlockVerificationMsg{}, Byte: blockSignatureByte},
    31  	wire.ConcreteType{O: &BlockProposeMsg{}, Byte: blockProposeByte},
    32  )
    33  
    34  // decodeMessage decode msg
    35  func decodeMessage(bz []byte) (msgType byte, msg ConsensusMessage, err error) {
    36  	msgType = bz[0]
    37  	n := int(0)
    38  	r := bytes.NewReader(bz)
    39  	msg = wire.ReadBinary(struct{ ConsensusMessage }{}, r, maxBlockchainResponseSize, &n, &err).(struct{ ConsensusMessage }).ConsensusMessage
    40  	if err != nil && n != len(bz) {
    41  		err = errors.New("DecodeMessage() had bytes left over")
    42  	}
    43  	return
    44  }
    45  
    46  // BlockVerificationMsg block verification message transferred between nodes.
    47  type BlockVerificationMsg struct {
    48  	SourceHash bc.Hash
    49  	TargetHash bc.Hash
    50  	PubKey     []byte
    51  	Signature  []byte
    52  }
    53  
    54  // NewBlockVerificationMsg create new block verification msg.
    55  func NewBlockVerificationMsg(sourceHash, targetHash bc.Hash, pubKey, signature []byte) ConsensusMessage {
    56  	return &BlockVerificationMsg{
    57  		SourceHash: sourceHash,
    58  		TargetHash: targetHash,
    59  		PubKey:     pubKey,
    60  		Signature:  signature,
    61  	}
    62  }
    63  
    64  func (b *BlockVerificationMsg) String() string {
    65  	return fmt.Sprintf("{sourceHash:%s,targetHash:%s,signature:%s,pubkey:%s}",
    66  		b.SourceHash.String(), b.TargetHash.String(), hex.EncodeToString(b.Signature), hex.EncodeToString(b.PubKey[:]))
    67  }
    68  
    69  // BroadcastMarkSendRecord mark send message record to prevent messages from being sent repeatedly.
    70  func (b *BlockVerificationMsg) BroadcastMarkSendRecord(ps *peers.PeerSet, peers []string) {
    71  	for _, peer := range peers {
    72  		ps.MarkBlockVerification(peer, b.Signature)
    73  	}
    74  }
    75  
    76  // BroadcastFilterTargetPeers filter target peers to filter the nodes that need to send messages.
    77  func (b *BlockVerificationMsg) BroadcastFilterTargetPeers(ps *peers.PeerSet) []string {
    78  	return ps.PeersWithoutSignature(b.Signature)
    79  }
    80  
    81  // BlockProposeMsg block propose message transferred between nodes.
    82  type BlockProposeMsg struct {
    83  	RawBlock []byte
    84  }
    85  
    86  // NewBlockProposeMsg create new block propose msg.
    87  func NewBlockProposeMsg(block *types.Block) (ConsensusMessage, error) {
    88  	rawBlock, err := block.MarshalText()
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	return &BlockProposeMsg{RawBlock: rawBlock}, nil
    93  }
    94  
    95  // GetProposeBlock get propose block from msg.
    96  func (bp *BlockProposeMsg) GetProposeBlock() (*types.Block, error) {
    97  	block := &types.Block{}
    98  	if err := block.UnmarshalText(bp.RawBlock); err != nil {
    99  		return nil, err
   100  	}
   101  	return block, nil
   102  }
   103  
   104  func (bp *BlockProposeMsg) String() string {
   105  	block, err := bp.GetProposeBlock()
   106  	if err != nil {
   107  		return "{err: wrong message}"
   108  	}
   109  	blockHash := block.Hash()
   110  	return fmt.Sprintf("{block_height: %d, block_hash: %s}", block.Height, blockHash.String())
   111  }
   112  
   113  // BroadcastMarkSendRecord mark send message record to prevent messages from being sent repeatedly.
   114  func (bp *BlockProposeMsg) BroadcastMarkSendRecord(ps *peers.PeerSet, peers []string) {
   115  	block, err := bp.GetProposeBlock()
   116  	if err != nil {
   117  		return
   118  	}
   119  
   120  	hash := block.Hash()
   121  	height := block.Height
   122  	for _, peer := range peers {
   123  		ps.MarkBlock(peer, &hash)
   124  		ps.MarkStatus(peer, height)
   125  	}
   126  }
   127  
   128  // BroadcastFilterTargetPeers filter target peers to filter the nodes that need to send messages.
   129  func (bp *BlockProposeMsg) BroadcastFilterTargetPeers(ps *peers.PeerSet) []string {
   130  	block, err := bp.GetProposeBlock()
   131  	if err != nil {
   132  		return nil
   133  	}
   134  
   135  	return ps.PeersWithoutBlock(block.Hash())
   136  }