github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/integration/connect_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/stretchr/testify/mock" 8 9 "github.com/koko1123/flow-go-1/consensus/hotstuff/mocks" 10 "github.com/koko1123/flow-go-1/consensus/hotstuff/model" 11 "github.com/koko1123/flow-go-1/model/flow" 12 ) 13 14 func Connect(instances []*Instance) { 15 16 // first, create a map of all instances and a queue for each 17 lookup := make(map[flow.Identifier]*Instance) 18 for _, in := range instances { 19 lookup[in.localID] = in 20 } 21 22 // then, for each instance, initialize a wired up communicator 23 for _, sender := range instances { 24 sender := sender // avoid capturing loop variable in closure 25 26 *sender.communicator = mocks.Communicator{} 27 sender.communicator.On("BroadcastProposalWithDelay", mock.Anything, mock.Anything).Return( 28 func(header *flow.Header, delay time.Duration) error { 29 30 // sender should always have the parent 31 parent, exists := sender.headers[header.ParentID] 32 if !exists { 33 return fmt.Errorf("parent for proposal not found (sender: %x, parent: %x)", sender.localID, header.ParentID) 34 } 35 36 // fill in the header chain ID and height 37 header.ChainID = parent.ChainID 38 header.Height = parent.Height + 1 39 40 // convert into proposal immediately 41 proposal := model.ProposalFromFlow(header, parent.View) 42 43 // store locally and loop back to engine for processing 44 sender.ProcessBlock(proposal) 45 46 // check if we should block the outgoing proposal 47 if sender.blockPropOut(proposal) { 48 return nil 49 } 50 51 // iterate through potential receivers 52 for _, receiver := range instances { 53 54 // we should skip ourselves always 55 if receiver.localID == sender.localID { 56 continue 57 } 58 59 // check if we should block the incoming proposal 60 if receiver.blockPropIn(proposal) { 61 return nil 62 } 63 64 receiver.ProcessBlock(proposal) 65 } 66 67 return nil 68 }, 69 ) 70 sender.communicator.On("SendVote", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( 71 func(blockID flow.Identifier, view uint64, sigData []byte, recipientID flow.Identifier) error { 72 73 // convert into vote 74 vote := model.VoteFromFlow(sender.localID, blockID, view, sigData) 75 76 // should never send to self 77 if recipientID == sender.localID { 78 return fmt.Errorf("can't send to self (sender: %x)", sender.localID) 79 } 80 81 // check if we should block the outgoing vote 82 if sender.blockVoteOut(vote) { 83 return nil 84 } 85 86 // get the receiver 87 receiver, exists := lookup[recipientID] 88 if !exists { 89 return fmt.Errorf("recipient doesn't exist (sender: %x, receiver: %x)", sender.localID, recipientID) 90 } 91 92 // check if e should block the incoming vote 93 if receiver.blockVoteIn(vote) { 94 return nil 95 } 96 97 // submit the vote to the receiving event loop (non-blocking) 98 receiver.queue <- vote 99 100 return nil 101 }, 102 ) 103 } 104 }