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  }