github.com/cranelv/ethereum_mpc@v0.0.0-20191031014521-23aeb1415092/consensus_pbft/pbft/mock_network_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package pbft 18 19 import ( 20 "fmt" 21 "sync" 22 "time" 23 24 "github.com/ethereum/go-ethereum/consensus_pbft/consensusInterface" 25 "github.com/ethereum/go-ethereum/consensus_pbft/pbftTypes" 26 "github.com/ethereum/go-ethereum/p2p/discover" 27 "github.com/ethereum/go-ethereum/consensus_pbft/message" 28 "github.com/ethereum/go-ethereum/consensus_pbft/singletons" 29 ) 30 func stringToPeerId(value string)pbftTypes.PeerID{ 31 var id pbftTypes.PeerID 32 copy(id[:],[]byte(value)) 33 return id 34 } 35 36 type endpoint interface { 37 stop() 38 deliver([]byte, *pbftTypes.PeerID) 39 getHandle() *pbftTypes.PeerID 40 getID() pbftTypes.ReplicaID 41 isBusy() bool 42 } 43 44 type taggedMsg struct { 45 src int 46 dst int 47 msg []byte 48 } 49 50 type testnet struct { 51 debug bool 52 N int 53 closed chan struct{} 54 endpoints []endpoint 55 msgs chan taggedMsg 56 filterFn func(int, int, []byte) []byte 57 identify consensusInterface.ValidatorIdentifyInterface 58 } 59 60 type testEndpoint struct { 61 NetValidator 62 id pbftTypes.ReplicaID 63 net *testnet 64 } 65 66 func makeTestEndpoint(id pbftTypes.ReplicaID, net *testnet) *testEndpoint { 67 ep := &testEndpoint{} 68 ep.id = id 69 ep.net = net 70 ep.NetValidator.net = ep 71 ep.NetValidator.indexer = ep 72 return ep 73 } 74 75 func (ep *testEndpoint) getID() pbftTypes.ReplicaID { 76 return ep.id 77 } 78 79 func (ep *testEndpoint) getHandle() *pbftTypes.PeerID { 80 peerId := stringToPeerId(fmt.Sprintf("vp%d", ep.id)) 81 return &peerId 82 } 83 84 func (ep *testEndpoint) GetNetworkNodes() (self pbftTypes.Peer, network []pbftTypes.Peer, err error) { 85 oSelf, oNetwork, _ := ep.GetNetworkNodeIDs() 86 self = &PbftPeer{ 87 Node: &discover.Node{ID:discover.NodeID(*oSelf)}, 88 Type: pbftTypes.Peer_VALIDATOR, 89 } 90 91 network = make([]pbftTypes.Peer, len(oNetwork)) 92 for i, id := range oNetwork { 93 network[i] = &PbftPeer{ 94 Node: &discover.Node{ID:discover.NodeID(*id)}, 95 Type: pbftTypes.Peer_VALIDATOR, 96 } 97 } 98 return 99 } 100 101 func (ep *testEndpoint) GetNetworkNodeIDs() (self *pbftTypes.PeerID, network []*pbftTypes.PeerID, err error) { 102 if nil == ep.net { 103 err = fmt.Errorf("Network not initialized") 104 return 105 } 106 self = ep.getHandle() 107 network = make([]*pbftTypes.PeerID, len(ep.net.endpoints)) 108 for i, oep := range ep.net.endpoints { 109 if nil != oep { 110 // In case this is invoked before all endpoints are initialized, this emulates a real network as well 111 network[i] = oep.getHandle() 112 } 113 } 114 return 115 } 116 func (ep *testEndpoint)ChangeToReplicaID(index int) pbftTypes.ReplicaID { 117 return pbftTypes.ReplicaID(index) 118 } 119 func (ep *testEndpoint)ChangeToIndex(id pbftTypes.ReplicaID) int { 120 return int(id) 121 } 122 // Broadcast delivers to all endpoints. In contrast to the stack 123 // Broadcast, this will also deliver back to the replica. We keep 124 // this behavior, because it exposes subtle bugs in the 125 // implementation. 126 func (ep *testEndpoint) Broadcast(msg *message.Message, peerType pbftTypes.Peer_Type) error { 127 ep.net.broadcastFilter(ep, msg.Payload) 128 return nil 129 } 130 131 func (ep *testEndpoint) Unicast(msg *message.Message, receiverHandle *pbftTypes.PeerID) error { 132 receiverID, err := ep.GetValidatorID(receiverHandle) 133 if err != nil { 134 return fmt.Errorf("Couldn't unicast message to %s: %v", receiverHandle, err) 135 } 136 singletons.Log.Info("testEndpoint Unicast:","from",ep.id,"dest",receiverID) 137 internalQueueMessage(ep.net.msgs, taggedMsg{int(ep.id), int(receiverID), msg.Payload}) 138 return nil 139 } 140 141 func internalQueueMessage(queue chan<- taggedMsg, tm taggedMsg) { 142 select { 143 case queue <- tm: 144 default: 145 fmt.Println("TEST NET: Message cannot be queued without blocking, consider increasing the queue size") 146 queue <- tm 147 } 148 } 149 150 func (net *testnet) debugMsg(msg string, args ...interface{}) { 151 if net.debug { 152 fmt.Printf(msg, args...) 153 } 154 } 155 156 func (net *testnet) broadcastFilter(ep *testEndpoint, payload []byte) { 157 select { 158 case <-net.closed: 159 fmt.Println("WARNING! Attempted to send a request to a closed network, ignoring") 160 return 161 default: 162 } 163 if net.filterFn != nil { 164 payload = net.filterFn(int(ep.id), -1, payload) 165 net.debugMsg("TEST: filtered message\n") 166 } 167 if payload != nil { 168 net.debugMsg("TEST: attempting to queue message %p\n", payload) 169 internalQueueMessage(net.msgs, taggedMsg{int(ep.id), -1, payload}) 170 net.debugMsg("TEST: message queued successfully %p\n", payload) 171 } else { 172 net.debugMsg("TEST: suppressing message with payload %p\n", payload) 173 } 174 } 175 176 func (net *testnet) deliverFilter(msg taggedMsg) { 177 net.debugMsg("TEST: deliver\n") 178 senderHandle := net.endpoints[msg.src].getHandle() 179 if msg.dst == -1 { 180 net.debugMsg("TEST: Sending broadcast %v\n", net.endpoints) 181 wg := &sync.WaitGroup{} 182 wg.Add(len(net.endpoints)) 183 for id, ep := range net.endpoints { 184 net.debugMsg("TEST: Looping broadcast %d\n", ep.getID()) 185 lid := id 186 lep := ep 187 go func() { 188 defer wg.Done() 189 if msg.src == lid { 190 if net.debug { 191 net.debugMsg("TEST: Skipping local delivery %d %d\n", lid, msg.src) 192 } 193 // do not deliver to local replica 194 return 195 } 196 payload := msg.msg 197 net.debugMsg("TEST: Filtering %d\n", lid) 198 if net.filterFn != nil { 199 payload = net.filterFn(msg.src, lid, payload) 200 } 201 net.debugMsg("TEST: Delivering %d\n", lid) 202 if payload != nil { 203 net.debugMsg("TEST: Sending message %d\n", lid) 204 lep.deliver(payload, senderHandle) 205 net.debugMsg("TEST: Sent message %d\n", lid) 206 } else { 207 net.debugMsg("TEST: Message to %d was skipped\n", lid) 208 } 209 }() 210 } 211 wg.Wait() 212 } else { 213 payload := msg.msg 214 net.debugMsg("TEST: Filtering %d\n", msg.dst) 215 if net.filterFn != nil { 216 payload = net.filterFn(msg.src, msg.dst, payload) 217 } 218 if payload != nil { 219 net.debugMsg("TEST: Sending unicast\n") 220 net.endpoints[msg.dst].deliver(msg.msg, senderHandle) 221 } 222 } 223 } 224 225 func (net *testnet) processMessageFromChannel(msg taggedMsg, ok bool) bool { 226 if !ok { 227 net.debugMsg("TEST: message channel closed, exiting\n") 228 return false 229 } 230 net.debugMsg("TEST: new message, delivering\n") 231 net.deliverFilter(msg) 232 return true 233 } 234 235 func (net *testnet) process() error { 236 retry := true 237 countdown := time.After(120 * time.Second) 238 for { 239 net.debugMsg("TEST: process looping\n") 240 select { 241 case msg, ok := <-net.msgs: 242 retry = true 243 net.debugMsg("TEST: processing message without testing for idle\n") 244 if !net.processMessageFromChannel(msg, ok) { 245 return nil 246 } 247 case <-net.closed: 248 return nil 249 case <-countdown: 250 panic("Test network took more than 60 seconds to resolve requests, this usually indicates a hang") 251 default: 252 if !retry { 253 return nil 254 } 255 256 var busy []int 257 for i, ep := range net.endpoints { 258 if ep.isBusy() { 259 busy = append(busy, i) 260 } 261 } 262 if len(busy) == 0 { 263 retry = false 264 continue 265 } 266 267 net.debugMsg("TEST: some replicas are busy, waiting: %v\n", busy) 268 select { 269 case msg, ok := <-net.msgs: 270 retry = true 271 if !net.processMessageFromChannel(msg, ok) { 272 return nil 273 } 274 continue 275 case <-time.After(100 * time.Millisecond): 276 continue 277 } 278 } 279 } 280 } 281 282 func (net *testnet) processContinually() { 283 for { 284 select { 285 case msg, ok := <-net.msgs: 286 if !net.processMessageFromChannel(msg, ok) { 287 return 288 } 289 case <-net.closed: 290 return 291 } 292 } 293 } 294 295 func makeTestnet(N uint32, initFn func(id pbftTypes.ReplicaID, network *testnet) endpoint) *testnet { 296 net := &testnet{} 297 net.msgs = make(chan taggedMsg, 100) 298 net.closed = make(chan struct{}) 299 net.endpoints = make([]endpoint, N) 300 301 for i := range net.endpoints { 302 net.endpoints[i] = initFn(pbftTypes.ReplicaID(i), net) 303 } 304 305 return net 306 } 307 308 func (net *testnet) clearMessages() { 309 for { 310 select { 311 case <-net.msgs: 312 default: 313 return 314 } 315 } 316 } 317 318 func (net *testnet) stop() { 319 close(net.closed) 320 for _, ep := range net.endpoints { 321 ep.stop() 322 } 323 }