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 }