github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/integration/blockordelay_test.go (about) 1 package integration_test 2 3 import ( 4 "fmt" 5 "math/rand" 6 "sync" 7 "time" 8 9 "github.com/onflow/flow-go/model/flow" 10 "github.com/onflow/flow-go/model/messages" 11 "github.com/onflow/flow-go/network/channels" 12 ) 13 14 // This file includes functions to simulate network conditions. 15 // The network conditions are simulated by defining whether a message sent to a receiver should be 16 // blocked or delayed. 17 18 // blockNodesFirstMessages blocks the _first_ n incoming messages for each member in `denyList` 19 // (messages are counted individually for each Node). 20 func blockNodesFirstMessages(n uint64, denyList ...*Node) BlockOrDelayFunc { 21 blackList := make(map[flow.Identifier]uint64, len(denyList)) 22 for _, node := range denyList { 23 blackList[node.id.ID()] = n 24 } 25 lock := new(sync.Mutex) 26 return func(channel channels.Channel, event interface{}, sender, receiver *Node) (bool, time.Duration) { 27 // filter only consensus messages 28 switch event.(type) { 29 case *messages.BlockProposal: 30 case *messages.BlockVote: 31 case *messages.BlockResponse: 32 case *messages.TimeoutObject: 33 default: 34 return false, 0 35 } 36 lock.Lock() 37 defer lock.Unlock() 38 count, ok := blackList[receiver.id.ID()] 39 if ok && count > 0 { 40 blackList[receiver.id.ID()] = count - 1 41 return true, 0 42 } 43 return false, 0 44 } 45 } 46 47 // blockReceiverMessagesRandomly drops messages randomly with a probability of `dropProbability` ∈ [0,1] 48 func blockReceiverMessagesRandomly(dropProbability float32) BlockOrDelayFunc { 49 lock := new(sync.Mutex) 50 prng := rand.New(rand.NewSource(time.Now().UnixNano())) 51 return func(channel channels.Channel, event interface{}, sender, receiver *Node) (bool, time.Duration) { 52 lock.Lock() 53 block := prng.Float32() < dropProbability 54 lock.Unlock() 55 return block, 0 56 } 57 } 58 59 // delayReceiverMessagesByRange delivers all messages, but with a randomly sampled 60 // delay in the interval [low, high). Panics when `low` < 0 or `low > `high` 61 func delayReceiverMessagesByRange(low time.Duration, high time.Duration) BlockOrDelayFunc { 62 lock := new(sync.Mutex) 63 prng := rand.New(rand.NewSource(time.Now().UnixNano())) 64 delayRangeNs := int64(high - low) 65 minDelayNs := int64(low) 66 67 // fail early for non-sensical parameter settings 68 if int64(low) < 0 { 69 panic(fmt.Sprintf("minimal delay cannot be negative, but is %d ns", int64(low))) 70 } 71 if delayRangeNs < 0 { 72 panic(fmt.Sprintf("upper bound on delay (%d ns) cannot be smaller than lower bound (%d ns)", int64(high), int64(low))) 73 } 74 75 // shortcut for low = high: always return low 76 if delayRangeNs == 0 { 77 return func(channel channels.Channel, event interface{}, sender, receiver *Node) (bool, time.Duration) { 78 return false, low 79 } 80 } 81 // general version 82 return func(channel channels.Channel, event interface{}, sender, receiver *Node) (bool, time.Duration) { 83 lock.Lock() 84 d := prng.Int63n(delayRangeNs) 85 lock.Unlock() 86 return false, time.Duration(minDelayNs + d) 87 } 88 }