package attack import ( "math/rand" "os" "sync" "time" "github.com/simple-rules/harmony-benchmark/log" ) const ( DroppingTickDuration = 2 * time.Second HitRate = 10 DelayResponseDuration = 10 * time.Second ConsensusIdThresholdMin = 10 ConsensusIdThresholdMax = 100 ) type AttackType byte const ( KilledItself AttackType = iota DelayResponse IncorrectResponse ) // AttackModel contains different models of attacking. type Attack struct { AttackEnabled bool attackType AttackType ConsensusIdThreshold uint32 readyByConsensusThreshold bool log log.Logger // Log utility } var attack *Attack var once sync.Once // GetInstance returns attack model by using singleton pattern. func GetInstance() *Attack { once.Do(func() { attack = &Attack{} attack.Init() }) return attack } func (attack *Attack) Init() { attack.AttackEnabled = false attack.readyByConsensusThreshold = false } func (attack *Attack) SetAttackEnabled(AttackEnabled bool) { attack.AttackEnabled = AttackEnabled if AttackEnabled { attack.attackType = AttackType(rand.Intn(3)) attack.ConsensusIdThreshold = uint32(ConsensusIdThresholdMin + rand.Intn(ConsensusIdThresholdMax-ConsensusIdThresholdMin)) } } func (attack *Attack) SetLogger(log log.Logger) { attack.log = log } func (attack *Attack) Run() { attack.NodeKilledByItSelf() attack.DelayResponse() } // NodeKilledByItSelf runs killing itself attack func (attack *Attack) NodeKilledByItSelf() { if !attack.AttackEnabled || attack.attackType != KilledItself || !attack.readyByConsensusThreshold { return } if rand.Intn(HitRate) == 0 { attack.log.Debug("******************Killing myself******************", "PID: ", os.Getpid()) os.Exit(1) } } func (attack *Attack) DelayResponse() { if !attack.AttackEnabled || attack.attackType != DelayResponse || !attack.readyByConsensusThreshold { return } if rand.Intn(HitRate) == 0 { attack.log.Debug("******************Attack: DelayResponse******************", "PID: ", os.Getpid()) time.Sleep(DelayResponseDuration) } } func (attack *Attack) IncorrectResponse() bool { if !attack.AttackEnabled || attack.attackType != IncorrectResponse || !attack.readyByConsensusThreshold { return false } if rand.Intn(HitRate) == 0 { attack.log.Debug("******************Attack: IncorrectResponse******************", "PID: ", os.Getpid()) return true } return false } func (attack *Attack) UpdateConsensusReady(consensusId uint32) { if consensusId > attack.ConsensusIdThreshold { attack.readyByConsensusThreshold = true } }