diff --git a/attack/attack.go b/attack/attack.go index 778390d2b..199289efc 100644 --- a/attack/attack.go +++ b/attack/attack.go @@ -4,6 +4,7 @@ import ( "harmony-benchmark/log" "math/rand" "os" + "sync" "time" ) @@ -16,19 +17,29 @@ const ( // AttackModel contains different models of attacking. type Attack struct { - log log.Logger // Log utility + AttackEnabled bool + log log.Logger // Log utility } -func New(log log.Logger) *Attack { - attackModel := Attack{} - // Logger - attackModel.log = log - return &attackModel +var attack *Attack +var once sync.Once + +// GetAttackModel returns attack model by using singleton pattern. +func GetAttackModel() *Attack { + once.Do(func() { + attack = &Attack{} + attack.AttackEnabled = AttackEnabled + }) + return attack +} + +func (attack *Attack) SetLogger(log log.Logger) { + attack.log = log } // Run runs all attack models in goroutine mode. func (attack *Attack) Run() { - if !AttackEnabled { + if !attack.AttackEnabled { return } // Adding attack model here. @@ -49,8 +60,8 @@ func (attack *Attack) NodeKilledByItSelf() { } } -func DelayResponse() { - if !AttackEnabled { +func (attack *Attack) DelayResponse() { + if !attack.AttackEnabled { return } if rand.Intn(HitRate) == 0 { diff --git a/benchmark.go b/benchmark.go index 4c2548b61..bd201b450 100644 --- a/benchmark.go +++ b/benchmark.go @@ -15,6 +15,10 @@ import ( "time" ) +const ( + AttackProbability = 20 +) + func getShardId(myIp, myPort string, config *[][]string) string { for _, node := range *config { ip, port, shardId := node[0], node[1], node[3] @@ -74,16 +78,32 @@ func readConfigFile(configFile string) [][]string { return result } +func attackDetermination(attackedMode int) bool { + switch attackedMode { + case 0: + return false + case 1: + return true + case 2: + return rand.Intn(100) < AttackProbability + } + return false +} + func main() { ip := flag.String("ip", "127.0.0.1", "IP of the node") port := flag.String("port", "9000", "port of the node.") configFile := flag.String("config_file", "config.txt", "file containing all ip addresses") logFolder := flag.String("log_folder", "latest", "the folder collecting the logs of this execution") + attackedMode := flag.Int("attacked_mode", 0, "0 means not attacked, 1 means attacked, 2 means being open to be selected as attacked") flag.Parse() // Set up randomization seed. rand.Seed(int64(time.Now().Nanosecond())) + // Attack determination. + attack.GetAttackModel().AttackEnabled = attackDetermination(*attackedMode) + config := readConfigFile(*configFile) shardId := getShardId(*ip, *port, &config) peers := getPeers(*ip, *port, shardId, &config) @@ -101,7 +121,8 @@ func main() { consensus := consensus.NewConsensus(*ip, *port, shardId, peers, leader) node := node.NewNode(&consensus) - attack := attack.New(consensus.Log) + // Set logger to attack model. + attack.GetAttackModel().SetLogger(consensus.Log) clientPeer := getClientPeer(&config) // If there is a client configured in the node list. @@ -129,7 +150,7 @@ func main() { // TODO(minhdoan): Enable it later after done attacking. // Run attack. - attack.Run() + attack.GetAttackModel().Run() node.StartServer(*port) } diff --git a/p2p/peer.go b/p2p/peer.go index eb0375568..3e32a11e7 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -80,7 +80,7 @@ func sendWithSocketClient(ip, port string, message []byte) (res string) { // Send a message to another node with given port. func send(ip, port string, message []byte) (returnMessage string) { // Add attack code here. - attack.DelayResponse() + attack.GetAttackModel().DelayResponse() sendWithSocketClient(ip, port, message) return