From 9698aa6636ba77f4c5854ea6bebd7d7f84e0d683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 26 Oct 2023 15:43:49 +0200 Subject: [PATCH 01/15] Move spam logger to models --- interactive/interactive.go | 172 +++++++++---------------------------- interactive/menu.go | 8 +- models/config.go | 15 ++++ models/spamlog.go | 95 ++++++++++++++++++++ 4 files changed, 155 insertions(+), 135 deletions(-) create mode 100644 models/config.go create mode 100644 models/spamlog.go diff --git a/interactive/interactive.go b/interactive/interactive.go index eff586c..b2f2cdc 100644 --- a/interactive/interactive.go +++ b/interactive/interactive.go @@ -3,17 +3,16 @@ package interactive import ( "encoding/json" "fmt" - "io" "os" "strconv" "strings" - "text/tabwriter" "time" "github.com/AlecAivazis/survey/v2" "go.uber.org/atomic" "github.com/iotaledger/evil-tools/evilwallet" + "github.com/iotaledger/evil-tools/models" "github.com/iotaledger/evil-tools/programs" "github.com/iotaledger/evil-tools/spammer" "github.com/iotaledger/hive.go/ds/types" @@ -25,7 +24,6 @@ const ( faucetFundsCheck = time.Minute / 12 maxConcurrentSpams = 5 lastSpamsShowed = 15 - timeFormat = "2006/01/02 15:04:05" configFilename = "interactive_config.json" ) @@ -40,19 +38,7 @@ var ( minSpamOutputs int ) -type Config struct { - //nolint:tagliatelle - WebAPI []string `json:"webAPI"` - Rate int `json:"rate"` - DurationStr string `json:"duration"` - TimeUnitStr string `json:"timeUnit"` - Deep bool `json:"deepEnabled"` - Reuse bool `json:"reuseEnabled"` - Scenario string `json:"scenario"` - AutoRequesting bool `json:"autoRequestingEnabled"` - AutoRequestingAmount string `json:"autoRequestingAmount"` - UseRateSetter bool `json:"useRateSetter"` - +type config struct { duration time.Duration timeUnit time.Duration clientURLs map[string]types.Empty @@ -71,14 +57,8 @@ var configJSON = fmt.Sprintf(`{ "useRateSetter": true }`, spammer.TypeTx) -var defaultConfig = Config{ - clientURLs: map[string]types.Empty{ - "http://localhost:8080": types.Void, - "http://localhost:8090": types.Void, - }, +var defaultConfig = models.Config{ Rate: 2, - duration: 20 * time.Second, - timeUnit: time.Second, Deep: false, Reuse: true, Scenario: spammer.TypeTx, @@ -87,6 +67,15 @@ var defaultConfig = Config{ UseRateSetter: true, } +var defaultInteractiveConfig = config{ + clientURLs: map[string]types.Empty{ + "http://localhost:8080": types.Void, + "http://localhost:8090": types.Void, + }, + duration: 20 * time.Second, + timeUnit: time.Second, +} + const ( requestAmount100 = "100" requestAmount10k = "10000" @@ -202,13 +191,14 @@ type Mode struct { preparingFunds bool - Config Config + Config models.Config + innerConfig config blkSent *atomic.Uint64 txSent *atomic.Uint64 scenariosSent *atomic.Uint64 activeSpammers map[int]*spammer.Spammer - spammerLog *SpammerLog + spammerLog *models.SpammerLog spamMutex syncutils.Mutex stdOutMutex syncutils.Mutex @@ -223,11 +213,12 @@ func NewInteractiveMode() *Mode { spamFinished: make(chan int), Config: defaultConfig, + innerConfig: defaultInteractiveConfig, blkSent: atomic.NewUint64(0), txSent: atomic.NewUint64(0), scenariosSent: atomic.NewUint64(0), - spammerLog: NewSpammerLog(), + spammerLog: models.NewSpammerLog(), activeSpammers: make(map[int]*spammer.Spammer), } } @@ -324,7 +315,7 @@ func (m *Mode) prepareFunds() { printer.FundsCurrentlyPreparedWarning() return } - if len(m.Config.clientURLs) == 0 { + if len(m.innerConfig.clientURLs) == 0 { printer.NotEnoughClientsWarning(1) } numToPrepareStr := "" @@ -376,9 +367,9 @@ func (m *Mode) spamMenu() { func (m *Mode) spamSubMenu(menuType string) { switch menuType { case spamDetails: - defaultTimeUnit := timeUnitToString(m.Config.duration) + defaultTimeUnit := timeUnitToString(m.innerConfig.duration) var spamSurvey spamDetailsSurvey - err := survey.Ask(spamDetailsQuestions(strconv.Itoa(int(m.Config.duration.Seconds())), strconv.Itoa(m.Config.Rate), defaultTimeUnit), &spamSurvey) + err := survey.Ask(spamDetailsQuestions(strconv.Itoa(int(m.innerConfig.duration.Seconds())), strconv.Itoa(m.Config.Rate), defaultTimeUnit), &spamSurvey) if err != nil { fmt.Println(err.Error()) m.mainMenu <- types.Void @@ -432,9 +423,9 @@ func (m *Mode) spamSubMenu(menuType string) { } func (m *Mode) areEnoughFundsAvailable() bool { - outputsNeeded := m.Config.Rate * int(m.Config.duration.Seconds()) - if m.Config.timeUnit == time.Minute { - outputsNeeded = int(float64(m.Config.Rate) * m.Config.duration.Minutes()) + outputsNeeded := m.Config.Rate * int(m.innerConfig.duration.Seconds()) + if m.innerConfig.timeUnit == time.Minute { + outputsNeeded = int(float64(m.Config.Rate) * m.innerConfig.duration.Minutes()) } return m.evilWallet.UnspentOutputsLeft(evilwallet.Fresh) < outputsNeeded && m.Config.Scenario != spammer.TypeBlock @@ -446,10 +437,10 @@ func (m *Mode) startSpam() { var s *spammer.Spammer if m.Config.Scenario == spammer.TypeBlock { - s = programs.SpamBlocks(m.evilWallet, m.Config.Rate, time.Second, m.Config.duration, 0, m.Config.UseRateSetter, "") + s = programs.SpamBlocks(m.evilWallet, m.Config.Rate, time.Second, m.innerConfig.duration, 0, m.Config.UseRateSetter, "") } else { scenario, _ := evilwallet.GetScenario(m.Config.Scenario) - s = programs.SpamNestedConflicts(m.evilWallet, m.Config.Rate, time.Second, m.Config.duration, scenario, m.Config.Deep, m.Config.Reuse, m.Config.UseRateSetter, "") + s = programs.SpamNestedConflicts(m.evilWallet, m.Config.Rate, time.Second, m.innerConfig.duration, scenario, m.Config.Deep, m.Config.Reuse, m.Config.UseRateSetter, "") if s == nil { return } @@ -537,11 +528,11 @@ func (m *Mode) validateAndAddURL(url string) { if !ok { printer.URLWarning() } else { - if _, ok := m.Config.clientURLs[url]; ok { + if _, ok := m.innerConfig.clientURLs[url]; ok { printer.URLExists() return } - m.Config.clientURLs[url] = types.Void + m.innerConfig.clientURLs[url] = types.Void m.evilWallet.AddClient(url) } } @@ -633,12 +624,12 @@ func (m *Mode) parseSpamDetails(details spamDetailsSurvey) { } switch details.TimeUnit { case mpm: - m.Config.timeUnit = time.Minute + m.innerConfig.timeUnit = time.Minute case mps: - m.Config.timeUnit = time.Second + m.innerConfig.timeUnit = time.Second } m.Config.Rate = rate - m.Config.duration = dur + m.innerConfig.duration = dur fmt.Println(details) } @@ -655,15 +646,15 @@ func (m *Mode) parseScenario(scenario string) { func (m *Mode) removeUrls(urls []string) { for _, url := range urls { - if _, ok := m.Config.clientURLs[url]; ok { - delete(m.Config.clientURLs, url) + if _, ok := m.innerConfig.clientURLs[url]; ok { + delete(m.innerConfig.clientURLs, url) m.evilWallet.RemoveClient(url) } } } func (m *Mode) urlMapToList() (list []string) { - for url := range m.Config.clientURLs { + for url := range m.innerConfig.clientURLs { list = append(list, url) } @@ -728,13 +719,13 @@ func (m *Mode) loadConfig() { // convert urls array to map if len(m.Config.WebAPI) > 0 { // rewrite default value - for url := range m.Config.clientURLs { + for url := range m.innerConfig.clientURLs { m.evilWallet.RemoveClient(url) } - m.Config.clientURLs = make(map[string]types.Empty) + m.innerConfig.clientURLs = make(map[string]types.Empty) } for _, url := range m.Config.WebAPI { - m.Config.clientURLs[url] = types.Void + m.innerConfig.clientURLs[url] = types.Void m.evilWallet.AddClient(url) } // parse duration @@ -746,8 +737,8 @@ func (m *Mode) loadConfig() { if err != nil { u = time.Second } - m.Config.duration = d - m.Config.timeUnit = u + m.innerConfig.duration = d + m.innerConfig.timeUnit = u } func (m *Mode) saveConfigsToFile() { @@ -760,15 +751,15 @@ func (m *Mode) saveConfigsToFile() { // update client urls m.Config.WebAPI = []string{} - for url := range m.Config.clientURLs { + for url := range m.innerConfig.clientURLs { m.Config.WebAPI = append(m.Config.WebAPI, url) } // update duration - m.Config.DurationStr = m.Config.duration.String() + m.Config.DurationStr = m.innerConfig.duration.String() // update time unit - m.Config.TimeUnitStr = m.Config.timeUnit.String() + m.Config.TimeUnitStr = m.innerConfig.timeUnit.String() jsonConfigs, err := json.MarshalIndent(m.Config, "", " ") if err != nil { @@ -815,85 +806,4 @@ func timeUnitToString(d time.Duration) string { // region SpammerLog /////////////////////////////////////////////////////////////////////////////////////////////////////////// -var ( - historyHeader = "scenario\tstart\tstop\tdeep\treuse\trate\tduration" - historyLineFmt = "%s\t%s\t%s\t%v\t%v\t%d\t%d\n" -) - -type SpammerLog struct { - spamDetails []Config - spamStartTime []time.Time - spamStopTime []time.Time - mu syncutils.Mutex -} - -func NewSpammerLog() *SpammerLog { - return &SpammerLog{ - spamDetails: make([]Config, 0), - spamStartTime: make([]time.Time, 0), - spamStopTime: make([]time.Time, 0), - } -} - -func (s *SpammerLog) SpamDetails(spamID int) *Config { - return &s.spamDetails[spamID] -} - -func (s *SpammerLog) StartTime(spamID int) time.Time { - return s.spamStartTime[spamID] -} - -func (s *SpammerLog) AddSpam(config Config) (spamID int) { - s.mu.Lock() - defer s.mu.Unlock() - - s.spamDetails = append(s.spamDetails, config) - s.spamStartTime = append(s.spamStartTime, time.Now()) - s.spamStopTime = append(s.spamStopTime, time.Time{}) - - return len(s.spamDetails) - 1 -} - -func (s *SpammerLog) SetSpamEndTime(spamID int) { - s.mu.Lock() - defer s.mu.Unlock() - - s.spamStopTime[spamID] = time.Now() -} - -func newTabWriter(writer io.Writer) *tabwriter.Writer { - return tabwriter.NewWriter(writer, 0, 0, 1, ' ', tabwriter.Debug|tabwriter.TabIndent) -} - -func (s *SpammerLog) LogHistory(lastLines int, writer io.Writer) { - s.mu.Lock() - defer s.mu.Unlock() - - w := newTabWriter(writer) - _, _ = fmt.Fprintln(w, historyHeader) - idx := len(s.spamDetails) - lastLines + 1 - if idx < 0 { - idx = 0 - } - for i, spam := range s.spamDetails[idx:] { - _, _ = fmt.Fprintf(w, historyLineFmt, spam.Scenario, s.spamStartTime[i].Format(timeFormat), s.spamStopTime[i].Format(timeFormat), - spam.Deep, spam.Deep, spam.Rate, int(spam.duration.Seconds())) - } - w.Flush() -} - -func (s *SpammerLog) LogSelected(lines []int, writer io.Writer) { - s.mu.Lock() - defer s.mu.Unlock() - - w := newTabWriter(writer) - _, _ = fmt.Fprintln(w, historyHeader) - for _, idx := range lines { - spam := s.spamDetails[idx] - _, _ = fmt.Fprintf(w, historyLineFmt, spam.Scenario, s.spamStartTime[idx].Format(timeFormat), s.spamStopTime[idx].Format(timeFormat), - spam.Deep, spam.Deep, spam.Rate, int(spam.duration.Seconds())) - } - w.Flush() -} - // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/interactive/menu.go b/interactive/menu.go index 3c35b73..5ee185c 100644 --- a/interactive/menu.go +++ b/interactive/menu.go @@ -75,7 +75,7 @@ func (p *Printer) EvilWalletStatus() { func (p *Printer) SpammerSettings() { rateUnit := "[mpm]" - if p.mode.Config.timeUnit == time.Second { + if p.mode.innerConfig.timeUnit == time.Second { rateUnit = "[mps]" } p.PrintTopLine() @@ -83,7 +83,7 @@ func (p *Printer) SpammerSettings() { p.PrintlnPoint(fmt.Sprintf("Scenario: %s", p.mode.Config.Scenario), level2) p.PrintlnPoint(fmt.Sprintf("Deep: %v, Reuse: %v", p.mode.Config.Deep, p.mode.Config.Reuse), level2) p.PrintlnPoint(fmt.Sprintf("Use rate-setter: %v", p.mode.Config.UseRateSetter), level2) - p.PrintlnPoint(fmt.Sprintf("Rate: %d%s, Duration: %d[s]", p.mode.Config.Rate, rateUnit, int(p.mode.Config.duration.Seconds())), level2) + p.PrintlnPoint(fmt.Sprintf("Rate: %d%s, Duration: %d[s]", p.mode.Config.Rate, rateUnit, int(p.mode.innerConfig.duration.Seconds())), level2) p.PrintLine() fmt.Println() } @@ -128,7 +128,7 @@ func (p *Printer) NotEnoughClientsWarning(numOfClient int) { func (p *Printer) clients() { p.Println(p.colorString("Provided clients:", "cyan"), level1) - for url := range p.mode.Config.clientURLs { + for url := range p.mode.innerConfig.clientURLs { p.PrintlnPoint(url, level2) } } @@ -175,7 +175,7 @@ func (p *Printer) CurrentSpams() { for id := range p.mode.activeSpammers { details := p.mode.spammerLog.SpamDetails(id) startTime := p.mode.spammerLog.StartTime(id) - endTime := startTime.Add(details.duration) + endTime := startTime.Add(p.mode.innerConfig.duration) timeLeft := int(time.Until(endTime).Seconds()) lines = append(lines, fmt.Sprintf("ID: %d, scenario: %s, time left: %d [s]", id, details.Scenario, timeLeft)) } diff --git a/models/config.go b/models/config.go new file mode 100644 index 0000000..f013e77 --- /dev/null +++ b/models/config.go @@ -0,0 +1,15 @@ +package models + +type Config struct { + //nolint:tagliatelle + WebAPI []string `json:"webAPI"` + Rate int `json:"rate"` + DurationStr string `json:"duration"` + TimeUnitStr string `json:"timeUnit"` + Deep bool `json:"deepEnabled"` + Reuse bool `json:"reuseEnabled"` + Scenario string `json:"scenario"` + AutoRequesting bool `json:"autoRequestingEnabled"` + AutoRequestingAmount string `json:"autoRequestingAmount"` + UseRateSetter bool `json:"useRateSetter"` +} diff --git a/models/spamlog.go b/models/spamlog.go new file mode 100644 index 0000000..5372a8e --- /dev/null +++ b/models/spamlog.go @@ -0,0 +1,95 @@ +package models + +import ( + "fmt" + "io" + "text/tabwriter" + "time" + + "github.com/iotaledger/hive.go/runtime/syncutils" +) + +const ( + timeFormat = "2006/01/02 15:04:05" +) + +var ( + historyHeader = "scenario\tstart\tstop\tdeep\treuse\trate\tduration" + historyLineFmt = "%s\t%s\t%s\t%v\t%v\t%d\t%d\n" +) + +type SpammerLog struct { + spamDetails []Config + spamStartTime []time.Time + spamStopTime []time.Time + mu syncutils.Mutex +} + +func NewSpammerLog() *SpammerLog { + return &SpammerLog{ + spamDetails: make([]Config, 0), + spamStartTime: make([]time.Time, 0), + spamStopTime: make([]time.Time, 0), + } +} + +func (s *SpammerLog) SpamDetails(spamID int) *Config { + return &s.spamDetails[spamID] +} + +func (s *SpammerLog) StartTime(spamID int) time.Time { + return s.spamStartTime[spamID] +} + +func (s *SpammerLog) AddSpam(config Config) (spamID int) { + s.mu.Lock() + defer s.mu.Unlock() + + s.spamDetails = append(s.spamDetails, config) + s.spamStartTime = append(s.spamStartTime, time.Now()) + s.spamStopTime = append(s.spamStopTime, time.Time{}) + + return len(s.spamDetails) - 1 +} + +func (s *SpammerLog) SetSpamEndTime(spamID int) { + s.mu.Lock() + defer s.mu.Unlock() + + s.spamStopTime[spamID] = time.Now() +} + +func newTabWriter(writer io.Writer) *tabwriter.Writer { + return tabwriter.NewWriter(writer, 0, 0, 1, ' ', tabwriter.Debug|tabwriter.TabIndent) +} + +func (s *SpammerLog) LogHistory(lastLines int, writer io.Writer) { + s.mu.Lock() + defer s.mu.Unlock() + + w := newTabWriter(writer) + _, _ = fmt.Fprintln(w, historyHeader) + idx := len(s.spamDetails) - lastLines + 1 + if idx < 0 { + idx = 0 + } + for i, spam := range s.spamDetails[idx:] { + _, _ = fmt.Fprintf(w, historyLineFmt, spam.Scenario, s.spamStartTime[i].Format(timeFormat), s.spamStopTime[i].Format(timeFormat), + spam.Deep, spam.Deep, spam.Rate, spam.DurationStr) + } + w.Flush() +} + +func (s *SpammerLog) LogSelected(lines []int, writer io.Writer) { + s.mu.Lock() + defer s.mu.Unlock() + + w := newTabWriter(writer) + _, _ = fmt.Fprintln(w, historyHeader) + for _, idx := range lines { + spam := s.spamDetails[idx] + _, _ = fmt.Fprintf(w, historyLineFmt, spam.Scenario, s.spamStartTime[idx].Format(timeFormat), s.spamStopTime[idx].Format(timeFormat), + spam.Deep, spam.Deep, spam.Rate, spam.DurationStr) + } + w.Flush() +} From a49bb9bfc1579486b7f64c4cd01b0b2e18e7f33e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 26 Oct 2023 15:45:20 +0200 Subject: [PATCH 02/15] No spammer timeout if duration not provided --- config.go | 2 +- programs/spammers.go | 17 +++++++++++------ spammer/spammer.go | 7 ++++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/config.go b/config.go index f8d412f..ea3f988 100644 --- a/config.go +++ b/config.go @@ -22,7 +22,7 @@ var ( ClientURLs: urls, SpamTypes: []string{spammer.TypeBlock}, Rates: []int{1}, - Durations: []time.Duration{time.Second * 20}, + Durations: []time.Duration{}, BlkToBeSent: []int{0}, TimeUnit: time.Second, DelayBetweenConflicts: 0, diff --git a/programs/spammers.go b/programs/spammers.go index 0d2d6a1..a39fe19 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -20,7 +20,12 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet for i, sType := range params.SpamTypes { log.Infof("Start spamming with rate: %d, time unit: %s, and spamming type: %s.", params.Rates[i], params.TimeUnit.String(), sType) - numOfBigWallets := spammer.BigWalletsNeeded(params.Rates[i], params.TimeUnit, params.Durations[i]) + var duration time.Duration = -1 + if len(params.Durations) > i { + duration = params.Durations[i] + } + // faucet funds preparation + numOfBigWallets := spammer.BigWalletsNeeded(params.Rates[i], params.TimeUnit, duration) fmt.Println("numOfBigWallets: ", numOfBigWallets) success := w.RequestFreshBigFaucetWallets(numOfBigWallets) if !success { @@ -37,7 +42,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet wg.Add(1) go func(i int) { defer wg.Done() - s := SpamBlocks(w, params.Rates[i], params.TimeUnit, params.Durations[i], params.BlkToBeSent[i], params.EnableRateSetter, params.AccountAlias) + s := SpamBlocks(w, params.Rates[i], params.TimeUnit, duration, params.BlkToBeSent[i], params.EnableRateSetter, params.AccountAlias) if s == nil { return } @@ -47,19 +52,19 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet wg.Add(1) go func(i int) { defer wg.Done() - SpamTransaction(w, params.Rates[i], params.TimeUnit, params.Durations[i], params.DeepSpam, params.EnableRateSetter, params.AccountAlias) + SpamTransaction(w, params.Rates[i], params.TimeUnit, duration, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) }(i) case spammer.TypeDs: wg.Add(1) go func(i int) { defer wg.Done() - SpamDoubleSpends(w, params.Rates[i], params.NSpend, params.TimeUnit, params.Durations[i], params.DelayBetweenConflicts, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) + SpamDoubleSpends(w, params.Rates[i], params.NSpend, params.TimeUnit, duration, params.DelayBetweenConflicts, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) }(i) case spammer.TypeCustom: wg.Add(1) go func(i int) { defer wg.Done() - s := SpamNestedConflicts(w, params.Rates[i], params.TimeUnit, params.Durations[i], params.Scenario, params.DeepSpam, false, params.EnableRateSetter, params.AccountAlias) + s := SpamNestedConflicts(w, params.Rates[i], params.TimeUnit, duration, params.Scenario, params.DeepSpam, false, params.EnableRateSetter, params.AccountAlias) if s == nil { return } @@ -70,7 +75,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet go func(i int) { defer wg.Done() - s := SpamAccounts(w, params.Rates[i], params.TimeUnit, params.Durations[i], params.EnableRateSetter, params.AccountAlias) + s := SpamAccounts(w, params.Rates[i], params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) if s == nil { return } diff --git a/spammer/spammer.go b/spammer/spammer.go index e62f9ae..b7939c7 100644 --- a/spammer/spammer.go +++ b/spammer/spammer.go @@ -177,7 +177,12 @@ func (s *Spammer) Spam() { s.log.Infof("Start spamming transactions with %d rate", s.SpamDetails.Rate) s.State.spamStartTime = time.Now() - timeExceeded := time.After(s.SpamDetails.MaxDuration) + + var timeExceeded <-chan time.Time + // if duration less than zero then spam infinitely + if s.SpamDetails.MaxDuration >= 0 { + timeExceeded = time.After(s.SpamDetails.MaxDuration) + } go func() { goroutineCount := atomic.NewInt32(0) From a3ace8892b52339ad74287dd1f37ce0f4ccbbc11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 26 Oct 2023 16:14:16 +0200 Subject: [PATCH 03/15] Cleanup spam config and add dispatcher between main and CustomSpam --- config.go | 1 + interactive/interactive.go | 8 ++++---- main.go | 3 ++- models/config.go | 15 +++++++-------- models/spamlog.go | 4 ++-- parse.go | 1 + programs/dispatcher.go | 36 ++++++++++++++++++++++++++++++++++++ programs/params.go | 14 ++++++++++++++ 8 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 programs/dispatcher.go diff --git a/config.go b/config.go index ea3f988..090a5b2 100644 --- a/config.go +++ b/config.go @@ -28,6 +28,7 @@ var ( DelayBetweenConflicts: 0, NSpend: 2, Scenario: evilwallet.Scenario1(), + ScenarioName: "guava", DeepSpam: false, EnableRateSetter: false, AccountAlias: accountwallet.FaucetAccountAlias, diff --git a/interactive/interactive.go b/interactive/interactive.go index b2f2cdc..257bb5c 100644 --- a/interactive/interactive.go +++ b/interactive/interactive.go @@ -729,11 +729,11 @@ func (m *Mode) loadConfig() { m.evilWallet.AddClient(url) } // parse duration - d, err := time.ParseDuration(m.Config.DurationStr) + d, err := time.ParseDuration(m.Config.Duration) if err != nil { d = time.Minute } - u, err := time.ParseDuration(m.Config.TimeUnitStr) + u, err := time.ParseDuration(m.Config.TimeUnit) if err != nil { u = time.Second } @@ -756,10 +756,10 @@ func (m *Mode) saveConfigsToFile() { } // update duration - m.Config.DurationStr = m.innerConfig.duration.String() + m.Config.Duration = m.innerConfig.duration.String() // update time unit - m.Config.TimeUnitStr = m.innerConfig.timeUnit.String() + m.Config.TimeUnit = m.innerConfig.timeUnit.String() jsonConfigs, err := json.MarshalIndent(m.Config, "", " ") if err != nil { diff --git a/main.go b/main.go index a3dbf7a..ba07a0a 100644 --- a/main.go +++ b/main.go @@ -64,7 +64,8 @@ func main() { case ScriptInteractive: interactive.Run() case ScriptSpammer: - programs.CustomSpam(&customSpamParams, accWallet) + dispatcher := programs.NewDispatcher(accWallet) + dispatcher.RunSpam(&customSpamParams) case ScriptAccounts: accountsSubcommands(accWallet, accountsSubcommandsFlags) default: diff --git a/models/config.go b/models/config.go index f013e77..dd41855 100644 --- a/models/config.go +++ b/models/config.go @@ -1,15 +1,14 @@ package models type Config struct { - //nolint:tagliatelle - WebAPI []string `json:"webAPI"` + WebAPI []string `json:"webAPI"` //nolint:tagliatelle Rate int `json:"rate"` - DurationStr string `json:"duration"` - TimeUnitStr string `json:"timeUnit"` + Duration string `json:"duration"` + TimeUnit string `json:"timeUnit"` Deep bool `json:"deepEnabled"` - Reuse bool `json:"reuseEnabled"` + Reuse bool `json:"reuseEnabled,omitempty"` Scenario string `json:"scenario"` - AutoRequesting bool `json:"autoRequestingEnabled"` - AutoRequestingAmount string `json:"autoRequestingAmount"` - UseRateSetter bool `json:"useRateSetter"` + AutoRequesting bool `json:"autoRequestingEnabled,omitempty"` + AutoRequestingAmount string `json:"autoRequestingAmount,omitempty"` + UseRateSetter bool `json:"useRateSetter,omitempty"` } diff --git a/models/spamlog.go b/models/spamlog.go index 5372a8e..5d86091 100644 --- a/models/spamlog.go +++ b/models/spamlog.go @@ -75,7 +75,7 @@ func (s *SpammerLog) LogHistory(lastLines int, writer io.Writer) { } for i, spam := range s.spamDetails[idx:] { _, _ = fmt.Fprintf(w, historyLineFmt, spam.Scenario, s.spamStartTime[i].Format(timeFormat), s.spamStopTime[i].Format(timeFormat), - spam.Deep, spam.Deep, spam.Rate, spam.DurationStr) + spam.Deep, spam.Deep, spam.Rate, spam.Duration) } w.Flush() } @@ -89,7 +89,7 @@ func (s *SpammerLog) LogSelected(lines []int, writer io.Writer) { for _, idx := range lines { spam := s.spamDetails[idx] _, _ = fmt.Fprintf(w, historyLineFmt, spam.Scenario, s.spamStartTime[idx].Format(timeFormat), s.spamStopTime[idx].Format(timeFormat), - spam.Deep, spam.Deep, spam.Rate, spam.DurationStr) + spam.Deep, spam.Deep, spam.Rate, spam.Duration) } w.Flush() } diff --git a/parse.go b/parse.go index c1a5d36..506bf15 100644 --- a/parse.go +++ b/parse.go @@ -94,6 +94,7 @@ func parseBasicSpamFlags() { conflictBatch, ok := evilwallet.GetScenario(*scenario) if ok { customSpamParams.Scenario = conflictBatch + customSpamParams.ScenarioName = *scenario } } diff --git a/programs/dispatcher.go b/programs/dispatcher.go new file mode 100644 index 0000000..3789d17 --- /dev/null +++ b/programs/dispatcher.go @@ -0,0 +1,36 @@ +package programs + +import ( + "github.com/iotaledger/evil-tools/accountwallet" + "github.com/iotaledger/evil-tools/models" + "github.com/iotaledger/evil-tools/spammer" +) + +type Runner struct { + spammer *spammer.Spammer + spamDetails *models.Config + + finished chan bool +} + +type Dispatcher struct { + activeSpammers []*Runner + accWallet *accountwallet.AccountWallet +} + +func NewDispatcher(accWallet *accountwallet.AccountWallet) *Dispatcher { + return &Dispatcher{ + accWallet: accWallet, + } +} + +func (d *Dispatcher) RunSpam(params *CustomSpamParams) { + // todo custom spam should return a spammer instance, and the process should run in the background + // or we could inject channel to be able to stop the spammer + CustomSpam(params, d.accWallet) + + d.activeSpammers = append(d.activeSpammers, &Runner{ + finished: make(chan bool), + spamDetails: ConfigFromCustomSpamParams(params), + }) +} diff --git a/programs/params.go b/programs/params.go index a89a55f..53ea12e 100644 --- a/programs/params.go +++ b/programs/params.go @@ -4,6 +4,7 @@ import ( "time" "github.com/iotaledger/evil-tools/evilwallet" + "github.com/iotaledger/evil-tools/models" ) type CustomSpamParams struct { @@ -16,7 +17,20 @@ type CustomSpamParams struct { DelayBetweenConflicts time.Duration NSpend int Scenario evilwallet.EvilBatch + ScenarioName string DeepSpam bool EnableRateSetter bool AccountAlias string } + +func ConfigFromCustomSpamParams(params *CustomSpamParams) *models.Config { + return &models.Config{ + WebAPI: params.ClientURLs, + Rate: params.Rates[0], + Duration: params.Durations[0].String(), + TimeUnit: params.TimeUnit.String(), + Deep: params.DeepSpam, + Reuse: false, + Scenario: params.ScenarioName, + } +} From e72756b2e0a12e208d6923de935c5afce61b9ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Fri, 27 Oct 2023 13:53:16 +0200 Subject: [PATCH 04/15] Remove numOfBlocks, so we can only limit the spam by providing duration --- config.go | 1 - interactive/interactive.go | 2 +- parse.go | 15 +-------------- programs/params.go | 1 - programs/spammers.go | 5 ++--- spammer/options.go | 20 ++++---------------- spammer/spammer.go | 6 +----- 7 files changed, 9 insertions(+), 41 deletions(-) diff --git a/config.go b/config.go index 090a5b2..ad8dc02 100644 --- a/config.go +++ b/config.go @@ -23,7 +23,6 @@ var ( SpamTypes: []string{spammer.TypeBlock}, Rates: []int{1}, Durations: []time.Duration{}, - BlkToBeSent: []int{0}, TimeUnit: time.Second, DelayBetweenConflicts: 0, NSpend: 2, diff --git a/interactive/interactive.go b/interactive/interactive.go index 257bb5c..08a44ee 100644 --- a/interactive/interactive.go +++ b/interactive/interactive.go @@ -437,7 +437,7 @@ func (m *Mode) startSpam() { var s *spammer.Spammer if m.Config.Scenario == spammer.TypeBlock { - s = programs.SpamBlocks(m.evilWallet, m.Config.Rate, time.Second, m.innerConfig.duration, 0, m.Config.UseRateSetter, "") + s = programs.SpamBlocks(m.evilWallet, m.Config.Rate, time.Second, m.innerConfig.duration, m.Config.UseRateSetter, "") } else { scenario, _ := evilwallet.GetScenario(m.Config.Scenario) s = programs.SpamNestedConflicts(m.evilWallet, m.Config.Rate, time.Second, m.innerConfig.duration, scenario, m.Config.Deep, m.Config.Reuse, m.Config.UseRateSetter, "") diff --git a/parse.go b/parse.go index 506bf15..e40bb56 100644 --- a/parse.go +++ b/parse.go @@ -59,8 +59,7 @@ func parseBasicSpamFlags() { spamTypes := optionFlagSet.String("spammer", "", "Spammers used during test. Format: strings separated with comma, available options: 'blk' - block,"+ " 'tx' - transaction, 'ds' - double spends spammers, 'nds' - n-spends spammer, 'custom' - spams with provided scenario") rate := optionFlagSet.String("rate", "", "Spamming rate for provided 'spammer'. Format: numbers separated with comma, e.g. 10,100,1 if three spammers were provided for 'spammer' parameter.") - duration := optionFlagSet.String("duration", "", "Spam duration. Cannot be combined with flag 'blkNum'. Format: separated by commas list of decimal numbers, each with optional fraction and a unit suffix, such as '300ms', '-1.5h' or '2h45m'.\n Valid time units are 'ns', 'us', 'ms', 's', 'm', 'h'.") - blkNum := optionFlagSet.String("blkNum", "", "Spam duration in seconds. Cannot be combined with flag 'duration'. Format: numbers separated with comma, e.g. 10,100,1 if three spammers were provided for 'spammer' parameter.") + duration := optionFlagSet.String("duration", "", "Spam duration. If not provided spam will lats infinitely. Format: separated by commas list of decimal numbers, each with optional fraction and a unit suffix, such as '300ms', '-1.5h' or '2h45m'.\n Valid time units are 'ns', 'us', 'ms', 's', 'm', 'h'.") timeunit := optionFlagSet.Duration("tu", customSpamParams.TimeUnit, "Time unit for the spamming rate. Format: decimal numbers, each with optional fraction and a unit suffix, such as '300ms', '-1.5h' or '2h45m'.\n Valid time units are 'ns', 'us', 'ms', 's', 'm', 'h'.") delayBetweenConflicts := optionFlagSet.Duration("dbc", customSpamParams.DelayBetweenConflicts, "delayBetweenConflicts - Time delay between conflicts in double spend spamming") scenario := optionFlagSet.String("scenario", "", "Name of the EvilBatch that should be used for the spam. By default uses Scenario1. Possible scenarios can be found in evilwallet/customscenarion.go.") @@ -86,10 +85,6 @@ func parseBasicSpamFlags() { parsedDurations := parseDurations(*duration) customSpamParams.Durations = parsedDurations } - if *blkNum != "" { - parsedBlkNums := parseCommaSepInt(*blkNum) - customSpamParams.BlkToBeSent = parsedBlkNums - } if *scenario != "" { conflictBatch, ok := evilwallet.GetScenario(*scenario) if ok { @@ -105,14 +100,6 @@ func parseBasicSpamFlags() { if *account != "" { customSpamParams.AccountAlias = *account } - - // fill in unused parameter: blkNum or duration with zeros - if *duration == "" && *blkNum != "" { - customSpamParams.Durations = make([]time.Duration, len(customSpamParams.BlkToBeSent)) - } - if *blkNum == "" && *duration != "" { - customSpamParams.BlkToBeSent = make([]int, len(customSpamParams.Durations)) - } } // readSubcommandsAndFlagSets splits the subcommands on multiple flag sets. diff --git a/programs/params.go b/programs/params.go index 53ea12e..ff149ae 100644 --- a/programs/params.go +++ b/programs/params.go @@ -12,7 +12,6 @@ type CustomSpamParams struct { SpamTypes []string Rates []int Durations []time.Duration - BlkToBeSent []int TimeUnit time.Duration DelayBetweenConflicts time.Duration NSpend int diff --git a/programs/spammers.go b/programs/spammers.go index a39fe19..3596037 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -42,7 +42,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet wg.Add(1) go func(i int) { defer wg.Done() - s := SpamBlocks(w, params.Rates[i], params.TimeUnit, duration, params.BlkToBeSent[i], params.EnableRateSetter, params.AccountAlias) + s := SpamBlocks(w, params.Rates[i], params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) if s == nil { return } @@ -186,7 +186,7 @@ func SpamNestedConflicts(w *evilwallet.EvilWallet, rate int, timeUnit, duration return spammer.NewSpammer(options...) } -func SpamBlocks(w *evilwallet.EvilWallet, rate int, timeUnit, duration time.Duration, numBlkToSend int, enableRateSetter bool, accountAlias string) *spammer.Spammer { +func SpamBlocks(w *evilwallet.EvilWallet, rate int, timeUnit, duration time.Duration, enableRateSetter bool, accountAlias string) *spammer.Spammer { if w.NumOfClient() < 1 { log.Infof("Warning: At least one client is needed to spam.") } @@ -194,7 +194,6 @@ func SpamBlocks(w *evilwallet.EvilWallet, rate int, timeUnit, duration time.Dura options := []spammer.Options{ spammer.WithSpamRate(rate, timeUnit), spammer.WithSpamDuration(duration), - spammer.WithBatchesSent(numBlkToSend), spammer.WithRateSetter(enableRateSetter), spammer.WithEvilWallet(w), spammer.WithSpammingFunc(spammer.DataSpammingFunction), diff --git a/spammer/options.go b/spammer/options.go index 0d079f4..aa19a72 100644 --- a/spammer/options.go +++ b/spammer/options.go @@ -64,19 +64,6 @@ func WithRateSetter(enable bool) Options { } } -// WithBatchesSent provides spammer with options regarding rate, time unit, and finishing spam criteria. Provide 0 to one of max parameters to skip it. -func WithBatchesSent(maxBatchesSent int) Options { - return func(s *Spammer) { - if s.SpamDetails == nil { - s.SpamDetails = &SpamDetails{ - MaxBatchesSent: maxBatchesSent, - } - } else { - s.SpamDetails.MaxBatchesSent = maxBatchesSent - } - } -} - // WithEvilWallet provides evil wallet instance, that will handle all spam logic according to provided EvilScenario. func WithEvilWallet(initWallets *evilwallet.EvilWallet) Options { return func(s *Spammer) { @@ -100,8 +87,9 @@ func WithTimeDelayForDoubleSpend(timeDelay time.Duration) Options { // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type SpamDetails struct { - Rate int - TimeUnit time.Duration - MaxDuration time.Duration + Rate int + TimeUnit time.Duration + MaxDuration time.Duration + // calculated based on duration, 0 for infinite spamming MaxBatchesSent int } diff --git a/spammer/spammer.go b/spammer/spammer.go index b7939c7..71ab273 100644 --- a/spammer/spammer.go +++ b/spammer/spammer.go @@ -146,12 +146,8 @@ func (s *Spammer) setupSpamDetails() { if s.SpamDetails.TimeUnit == 0 { s.SpamDetails.TimeUnit = time.Second } - // provided only maxBlkSent, calculating the default max for maxDuration - if s.SpamDetails.MaxDuration == 0 && s.SpamDetails.MaxBatchesSent > 0 { - s.SpamDetails.MaxDuration = time.Hour * 100 - } // provided only maxDuration, calculating the default max for maxBlkSent - if s.SpamDetails.MaxBatchesSent == 0 && s.SpamDetails.MaxDuration > 0 { + if s.SpamDetails.MaxDuration > 0 { s.SpamDetails.MaxBatchesSent = int(s.SpamDetails.MaxDuration.Seconds()/s.SpamDetails.TimeUnit.Seconds()*float64(s.SpamDetails.Rate)) + 1 } } From 9476033aa23fa6b21439fdd9b60232dbe55214ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 08:19:03 +0100 Subject: [PATCH 05/15] Add missing mutex --- spammer/errors.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spammer/errors.go b/spammer/errors.go index 0020f08..4f24ad0 100644 --- a/spammer/errors.go +++ b/spammer/errors.go @@ -52,6 +52,9 @@ func (e *ErrorCounter) GetTotalErrorCount() int64 { } func (e *ErrorCounter) GetErrorsSummary() string { + e.mutex.RLock() + defer e.mutex.RUnlock() + if len(e.errorsMap) == 0 { return "No errors encountered" } From 357af18d8e830fa79de36b205319da29817a4196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 08:49:54 +0100 Subject: [PATCH 06/15] Spam infinitely --- config.go | 6 +- evilwallet/evilwallet.go | 5 +- evilwallet/output_manager.go | 3 +- parse.go | 42 ++----- programs/params.go | 10 +- programs/spammers.go | 211 +++++++++++++++++++++-------------- spammer/spammer.go | 2 +- 7 files changed, 149 insertions(+), 130 deletions(-) diff --git a/config.go b/config.go index 94cad0f..e7d86c7 100644 --- a/config.go +++ b/config.go @@ -20,9 +20,9 @@ var ( customSpamParams = programs.CustomSpamParams{ ClientURLs: urls, - SpamTypes: []string{spammer.TypeBlock}, - Rates: []int{1}, - Durations: []time.Duration{}, + SpamType: spammer.TypeBlock, + Rate: 1, + Duration: 0, TimeUnit: time.Second, DelayBetweenConflicts: 0, NSpend: 2, diff --git a/evilwallet/evilwallet.go b/evilwallet/evilwallet.go index 3e06003..9731b6d 100644 --- a/evilwallet/evilwallet.go +++ b/evilwallet/evilwallet.go @@ -185,7 +185,7 @@ func (e *EvilWallet) RequestFundsFromFaucet(options ...FaucetRequestOption) (ini // RequestFreshBigFaucetWallets creates n new wallets, each wallet is created from one faucet request and contains 1000 outputs. func (e *EvilWallet) RequestFreshBigFaucetWallets(numberOfWallets int) bool { - e.log.Debug("Requesting %d wallets from faucet", numberOfWallets) + e.log.Debugf("Requesting %d wallets from faucet", numberOfWallets) success := true // channel to block the number of concurrent goroutines semaphore := make(chan bool, 1) @@ -460,7 +460,7 @@ func (e *EvilWallet) CreateTransaction(options ...Option) (*models.PayloadIssuan e.addOutputsToOutputManager(signedTx, buildOptions.outputWallet, tempWallet, tempAddresses) e.registerOutputAliases(signedTx, addrAliasMap) - e.log.Debugf("\n %s", printTransaction(signedTx)) + //e.log.Debugf("\n %s", printTransaction(signedTx)) return txData, nil } @@ -758,7 +758,6 @@ func (e *EvilWallet) updateOutputBalances(buildOptions *Options) (err error) { } func (e *EvilWallet) makeTransaction(inputs []*models.Output, outputs iotago.Outputs[iotago.Output], w *Wallet, congestionResponse *apimodels.CongestionResponse, issuerAccountID iotago.AccountID) (tx *iotago.SignedTransaction, err error) { - e.log.Debugf("makeTransaction len(outputs): %d", len(outputs)) clt := e.Connector().GetClient() currentTime := time.Now() targetSlot := clt.LatestAPI().TimeProvider().SlotFromTime(currentTime) diff --git a/evilwallet/output_manager.go b/evilwallet/output_manager.go index 1fa4a1f..37d18f6 100644 --- a/evilwallet/output_manager.go +++ b/evilwallet/output_manager.go @@ -292,9 +292,8 @@ func (o *OutputManager) AwaitTransactionToBeAccepted(txID iotago.TransactionID, clt := o.connector.GetClient() var accepted bool for ; time.Since(s) < waitFor; time.Sleep(awaitAcceptationSleep) { - resp, err := clt.GetBlockState(txID) + resp, _ := clt.GetBlockState(txID) if resp == nil { - o.log.Debugf("Block state API error: %v", err) continue } diff --git a/parse.go b/parse.go index 82752c9..a4fb970 100644 --- a/parse.go +++ b/parse.go @@ -4,7 +4,6 @@ import ( "flag" "fmt" "os" - "strconv" "strings" "time" @@ -56,11 +55,11 @@ func parseOptionFlagSet(flagSet *flag.FlagSet, args ...[]string) { func parseBasicSpamFlags() { urls := optionFlagSet.String("urls", "", "API urls for clients used in test separated with commas") - spamTypes := optionFlagSet.String("spammer", "", "Spammers used during test. Format: strings separated with comma, available options: 'blk' - block,"+ + spamType := optionFlagSet.String("spammer", "", "Spammers used during test. Format: strings separated with comma, available options: 'blk' - block,"+ " 'tx' - transaction, 'ds' - double spends spammers, 'nds' - n-spends spammer, 'custom' - spams with provided scenario, 'bb' - blowball") - rate := optionFlagSet.String("rate", "", "Spamming rate for provided 'spammer'. Format: numbers separated with comma, e.g. 10,100,1 if three spammers were provided for 'spammer' parameter.") + rate := optionFlagSet.Int("rate", customSpamParams.Rate, "Spamming rate for provided 'spammer'. Format: numbers separated with comma, e.g. 10,100,1 if three spammers were provided for 'spammer' parameter.") duration := optionFlagSet.String("duration", "", "Spam duration. If not provided spam will lats infinitely. Format: separated by commas list of decimal numbers, each with optional fraction and a unit suffix, such as '300ms', '-1.5h' or '2h45m'.\n Valid time units are 'ns', 'us', 'ms', 's', 'm', 'h'.") - timeunit := optionFlagSet.Duration("tu", customSpamParams.TimeUnit, "Time unit for the spamming rate. Format: decimal numbers, each with optional fraction and a unit suffix, such as '300ms', '-1.5h' or '2h45m'.\n Valid time units are 'ns', 'us', 'ms', 's', 'm', 'h'.") + timeunit := optionFlagSet.Duration("unit", customSpamParams.TimeUnit, "Time unit for the spamming rate. Format: decimal numbers, each with optional fraction and a unit suffix, such as '300ms', '-1.5h' or '2h45m'.\n Valid time units are 'ns', 'us', 'ms', 's', 'm', 'h'.") delayBetweenConflicts := optionFlagSet.Duration("dbc", customSpamParams.DelayBetweenConflicts, "delayBetweenConflicts - Time delay between conflicts in double spend spamming") scenario := optionFlagSet.String("scenario", "", "Name of the EvilBatch that should be used for the spam. By default uses Scenario1. Possible scenarios can be found in evilwallet/customscenarion.go.") deepSpam := optionFlagSet.Bool("deep", customSpamParams.DeepSpam, "Enable the deep spam, by reusing outputs created during the spam.") @@ -73,17 +72,12 @@ func parseBasicSpamFlags() { parsedUrls := parseCommaSepString(*urls) customSpamParams.ClientURLs = parsedUrls } - if *spamTypes != "" { - parsedSpamTypes := parseCommaSepString(*spamTypes) - customSpamParams.SpamTypes = parsedSpamTypes - } - if *rate != "" { - parsedRates := parseCommaSepInt(*rate) - customSpamParams.Rates = parsedRates - } + customSpamParams.SpamType = *spamType + customSpamParams.Rate = *rate if *duration != "" { - parsedDurations := parseDurations(*duration) - customSpamParams.Durations = parsedDurations + customSpamParams.Duration, _ = time.ParseDuration(*duration) + } else { + customSpamParams.Duration = time.Duration(-1) } if *scenario != "" { conflictBatch, ok := evilwallet.GetScenario(*scenario) @@ -426,23 +420,3 @@ func parseCommaSepString(urls string) []string { return split } - -func parseCommaSepInt(nums string) []int { - split := strings.Split(nums, ",") - parsed := make([]int, len(split)) - for i, num := range split { - parsed[i], _ = strconv.Atoi(num) - } - - return parsed -} - -func parseDurations(durations string) []time.Duration { - split := strings.Split(durations, ",") - parsed := make([]time.Duration, len(split)) - for i, dur := range split { - parsed[i], _ = time.ParseDuration(dur) - } - - return parsed -} diff --git a/programs/params.go b/programs/params.go index 3524371..0238b3b 100644 --- a/programs/params.go +++ b/programs/params.go @@ -9,9 +9,9 @@ import ( type CustomSpamParams struct { ClientURLs []string - SpamTypes []string - Rates []int - Durations []time.Duration + SpamType string + Rate int + Duration time.Duration TimeUnit time.Duration DelayBetweenConflicts time.Duration NSpend int @@ -26,8 +26,8 @@ type CustomSpamParams struct { func ConfigFromCustomSpamParams(params *CustomSpamParams) *models.Config { return &models.Config{ WebAPI: params.ClientURLs, - Rate: params.Rates[0], - Duration: params.Durations[0].String(), + Rate: params.Rate, + Duration: params.Duration.String(), TimeUnit: params.TimeUnit.String(), Deep: params.DeepSpam, Reuse: false, diff --git a/programs/spammers.go b/programs/spammers.go index ef63e64..d00ba3f 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -11,99 +11,146 @@ import ( "github.com/iotaledger/evil-tools/spammer" ) +const ( + maxBigWalletsCreatedAtOnce = 10 + checkFundsLeftInterval = time.Second * 20 +) + var log = logger.New("customSpam") -func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet) { - w := evilwallet.NewEvilWallet(evilwallet.WithClients(params.ClientURLs...), evilwallet.WithAccountsWallet(accWallet)) - wg := sync.WaitGroup{} +func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-chan bool { + if params.SpamType == spammer.TypeBlock { + return nil + } + var numOfBigWallets = 2 + fmt.Println("HERE, duration: ", params.Duration, "rate: ", params.Rate, "timeUnit: ", params.TimeUnit) + if params.Duration >= 0 { + numOfBigWallets = spammer.BigWalletsNeeded(params.Rate, params.TimeUnit, params.Duration) + if numOfBigWallets > maxBigWalletsCreatedAtOnce { + numOfBigWallets = maxBigWalletsCreatedAtOnce + log.Warnf("Reached maximum number of big wallets created at once: %d, use infinite spam instead", maxBigWalletsCreatedAtOnce) + } + } + fmt.Println("HERE, numOfBigWallets: ", numOfBigWallets) + success := w.RequestFreshBigFaucetWallets(numOfBigWallets) + if !success { + log.Errorf("Failed to request faucet wallet") + return nil + } + if params.Duration >= 0 { + unspentOutputsLeft := w.UnspentOutputsLeft(evilwallet.Fresh) + log.Debugf("Prepared %d unspent outputs for spamming.", unspentOutputsLeft) - for i, sType := range params.SpamTypes { - log.Infof("Start spamming with rate: %d, time unit: %s, and spamming type: %s.", params.Rates[i], params.TimeUnit.String(), sType) + return nil + } + var requestingChan = make(<-chan bool) + log.Debugf("Start requesting faucet funds infinitely...") + go requestInfinitely(w, requestingChan) - var duration time.Duration = -1 - if len(params.Durations) > i { - duration = params.Durations[i] - } - // faucet funds preparation - numOfBigWallets := spammer.BigWalletsNeeded(params.Rates[i], params.TimeUnit, duration) - fmt.Println("numOfBigWallets: ", numOfBigWallets) - success := w.RequestFreshBigFaucetWallets(numOfBigWallets) - if !success { - log.Errorf("Failed to request faucet wallet") - } - if sType != spammer.TypeBlock && sType != spammer.TypeBlowball { - numOfBigWallets := spammer.BigWalletsNeeded(params.Rates[i], params.TimeUnit, params.Durations[i]) - fmt.Println("numOfBigWallets: ", numOfBigWallets) - success := w.RequestFreshBigFaucetWallets(numOfBigWallets) - if !success { - log.Errorf("Failed to request faucet wallet") - return - } + return requestingChan +} - unspentOutputsLeft := w.UnspentOutputsLeft(evilwallet.Fresh) - log.Debugf("Prepared %d unspent outputs for spamming.", unspentOutputsLeft) - } +func requestInfinitely(w *evilwallet.EvilWallet, done <-chan bool) { + for { + select { + case <-done: + log.Debug("Shutdown signal. Stopping requesting faucet funds for spam: %d", 0) + + return + + case <-time.After(checkFundsLeftInterval): + outputsLeft := w.UnspentOutputsLeft(evilwallet.Fresh) + // less than one big wallet left + if outputsLeft < evilwallet.FaucetRequestSplitNumber*evilwallet.FaucetRequestSplitNumber { + log.Debugf("Requesting new faucet funds, outputs left: %d", outputsLeft) + err := w.RequestFreshBigFaucetWallet() + if err != nil { + log.Errorf("Failed to request faucet wallet: %s, stopping next requests...", err) - switch sType { - case spammer.TypeBlock: - wg.Add(1) - go func(i int) { - defer wg.Done() - s := SpamBlocks(w, params.Rates[i], params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) - if s == nil { - return - } - s.Spam() - }(i) - case spammer.TypeBlowball: - wg.Add(1) - go func(i int) { - defer wg.Done() - - s := SpamBlowball(w, params.Rates[i], params.TimeUnit, params.Durations[i], params.BlowballSize, params.EnableRateSetter, params.AccountAlias) - if s == nil { - return - } - s.Spam() - }(i) - case spammer.TypeTx: - wg.Add(1) - go func(i int) { - defer wg.Done() - SpamTransaction(w, params.Rates[i], params.TimeUnit, duration, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) - }(i) - case spammer.TypeDs: - wg.Add(1) - go func(i int) { - defer wg.Done() - SpamDoubleSpends(w, params.Rates[i], params.NSpend, params.TimeUnit, duration, params.DelayBetweenConflicts, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) - }(i) - case spammer.TypeCustom: - wg.Add(1) - go func(i int) { - defer wg.Done() - s := SpamNestedConflicts(w, params.Rates[i], params.TimeUnit, duration, params.Scenario, params.DeepSpam, false, params.EnableRateSetter, params.AccountAlias) - if s == nil { - return - } - s.Spam() - }(i) - case spammer.TypeAccounts: - wg.Add(1) - go func(i int) { - defer wg.Done() - - s := SpamAccounts(w, params.Rates[i], params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) - if s == nil { return } - s.Spam() - }(i) - default: - log.Warn("Spamming type not recognized. Try one of following: tx, ds, blk, custom, commitments") + log.Debugf("Requesting finished, currently available: %d unspent outputs for spamming.", w.UnspentOutputsLeft(evilwallet.Fresh)) + } } } +} + +func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet) { + w := evilwallet.NewEvilWallet(evilwallet.WithClients(params.ClientURLs...), evilwallet.WithAccountsWallet(accWallet)) + wg := sync.WaitGroup{} + + log.Infof("Start spamming with rate: %d, time unit: %s, and spamming type: %s.", params.Rate, params.TimeUnit.String(), params.SpamType) + + var duration time.Duration = -1 + if params.Duration >= 0 { + duration = params.Duration + } + + // TODO here we can shutdown requesting when we will have evil-tools running in the background. + _ = requestFaucetFunds(params, w) + + sType := params.SpamType + + switch sType { + case spammer.TypeBlock: + wg.Add(1) + go func() { + defer wg.Done() + s := SpamBlocks(w, params.Rate, params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) + if s == nil { + return + } + s.Spam() + }() + case spammer.TypeBlowball: + wg.Add(1) + go func() { + defer wg.Done() + + s := SpamBlowball(w, params.Rate, params.TimeUnit, duration, params.BlowballSize, params.EnableRateSetter, params.AccountAlias) + if s == nil { + return + } + s.Spam() + }() + case spammer.TypeTx: + wg.Add(1) + go func() { + defer wg.Done() + SpamTransaction(w, params.Rate, params.TimeUnit, duration, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) + }() + case spammer.TypeDs: + wg.Add(1) + go func() { + defer wg.Done() + SpamDoubleSpends(w, params.Rate, params.NSpend, params.TimeUnit, duration, params.DelayBetweenConflicts, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) + }() + case spammer.TypeCustom: + wg.Add(1) + go func() { + defer wg.Done() + s := SpamNestedConflicts(w, params.Rate, params.TimeUnit, duration, params.Scenario, params.DeepSpam, false, params.EnableRateSetter, params.AccountAlias) + if s == nil { + return + } + s.Spam() + }() + case spammer.TypeAccounts: + wg.Add(1) + go func() { + defer wg.Done() + + s := SpamAccounts(w, params.Rate, params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) + if s == nil { + return + } + s.Spam() + }() + + default: + log.Warn("Spamming type not recognized. Try one of following: tx, ds, blk, custom, commitments") + } wg.Wait() log.Info("Basic spamming finished!") diff --git a/spammer/spammer.go b/spammer/spammer.go index f787b42..4cd159d 100644 --- a/spammer/spammer.go +++ b/spammer/spammer.go @@ -213,7 +213,7 @@ func (s *Spammer) Spam() { } func (s *Spammer) CheckIfAllSent() { - if s.State.batchPrepared.Load() >= int64(s.SpamDetails.MaxBatchesSent) { + if s.SpamDetails.MaxDuration >= 0 && s.State.batchPrepared.Load() >= int64(s.SpamDetails.MaxBatchesSent) { s.log.Infof("Maximum number of blocks sent, stopping spammer...") s.done <- true } From 69c8f05678e923ceb7a507527f42069056e56f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 09:00:04 +0100 Subject: [PATCH 07/15] Silent await error, rm prints --- models/config.go | 1 + programs/spammers.go | 3 --- utils/utils.go | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/models/config.go b/models/config.go index dd41855..76f1381 100644 --- a/models/config.go +++ b/models/config.go @@ -2,6 +2,7 @@ package models type Config struct { WebAPI []string `json:"webAPI"` //nolint:tagliatelle + FaucetURL string `json:"faucetUrl"` Rate int `json:"rate"` Duration string `json:"duration"` TimeUnit string `json:"timeUnit"` diff --git a/programs/spammers.go b/programs/spammers.go index d00ba3f..246126c 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -1,7 +1,6 @@ package programs import ( - "fmt" "sync" "time" @@ -23,7 +22,6 @@ func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-ch return nil } var numOfBigWallets = 2 - fmt.Println("HERE, duration: ", params.Duration, "rate: ", params.Rate, "timeUnit: ", params.TimeUnit) if params.Duration >= 0 { numOfBigWallets = spammer.BigWalletsNeeded(params.Rate, params.TimeUnit, params.Duration) if numOfBigWallets > maxBigWalletsCreatedAtOnce { @@ -31,7 +29,6 @@ func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-ch log.Warnf("Reached maximum number of big wallets created at once: %d, use infinite spam instead", maxBigWalletsCreatedAtOnce) } } - fmt.Println("HERE, numOfBigWallets: ", numOfBigWallets) success := w.RequestFreshBigFaucetWallets(numOfBigWallets) if !success { log.Errorf("Failed to request faucet wallet") diff --git a/utils/utils.go b/utils/utils.go index e50c9ea..84c5e4f 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -59,9 +59,8 @@ func AwaitBlockToBeConfirmed(clt models.Client, blkID iotago.BlockID) error { // AwaitTransactionToBeAccepted awaits for acceptance of a single transaction. func AwaitTransactionToBeAccepted(clt models.Client, txID iotago.TransactionID, txLeft *atomic.Int64) error { for i := 0; i < MaxRetries; i++ { - resp, err := clt.GetBlockStateFromTransaction(txID) + resp, _ := clt.GetBlockStateFromTransaction(txID) if resp == nil { - UtilsLogger.Debugf("Block state API error: %v", err) continue } From eabd9a87f0f43f557a053f1ea24fd2ef7f5dd2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 09:11:18 +0100 Subject: [PATCH 08/15] Increase await time --- utils/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/utils.go b/utils/utils.go index 84c5e4f..b99325f 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -17,7 +17,7 @@ import ( var UtilsLogger = evillogger.New("Utils") const ( - MaxRetries = 20 + MaxRetries = 100 AwaitInterval = 1 * time.Second ) From 17b1d91e550c0bc30b9797591664dddac8c0b38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 09:12:31 +0100 Subject: [PATCH 09/15] Limit logging --- evilwallet/evilwallet.go | 2 +- spammer/spammer.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/evilwallet/evilwallet.go b/evilwallet/evilwallet.go index 300f996..964ca75 100644 --- a/evilwallet/evilwallet.go +++ b/evilwallet/evilwallet.go @@ -214,7 +214,7 @@ func (e *EvilWallet) RequestFreshBigFaucetWallets(numberOfWallets int) bool { } wg.Wait() - e.log.Debugf("Finished requesting %d wallets from faucet", numberOfWallets) + e.log.Debugf("Finished requesting %d wallets from faucet, outputs available: %d", numberOfWallets, e.UnspentOutputsLeft(Fresh)) return success } diff --git a/spammer/spammer.go b/spammer/spammer.go index 4cd159d..46c582a 100644 --- a/spammer/spammer.go +++ b/spammer/spammer.go @@ -301,7 +301,10 @@ func (s *Spammer) PrepareAndPostBlock(txData *models.PayloadIssuanceData, issuer } } count := s.State.txSent.Add(1) - s.log.Debugf("Last block sent, ID: %s, txCount: %d", blockID.ToHex(), count) + //s.log.Debugf("Last block sent, ID: %s, txCount: %d", blockID.ToHex(), count) + if count%200 == 0 { + s.log.Infof("Blocks issued so far: %d, errors encountered: %d", count, s.ErrCounter.GetTotalErrorCount()) + } return blockID } From faf9ac0f4ce30d578570912fa79488f23978beef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 13:34:39 +0100 Subject: [PATCH 10/15] Fix: add missing time sleep on error --- utils/utils.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/utils/utils.go b/utils/utils.go index b99325f..ab73d6f 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -14,7 +14,7 @@ import ( "github.com/iotaledger/iota.go/v4/nodeclient/apimodels" ) -var UtilsLogger = evillogger.New("Utils") +var log = evillogger.New("Utils") const ( MaxRetries = 100 @@ -39,19 +39,19 @@ func SplitBalanceEqually(splitNumber int, balance iotago.BaseToken) []iotago.Bas return outputBalances } -// AwaitTransactionToBeAccepted awaits for acceptance of a single transaction. +// AwaitBlockToBeConfirmed awaits for acceptance of a single transaction. func AwaitBlockToBeConfirmed(clt models.Client, blkID iotago.BlockID) error { for i := 0; i < MaxRetries; i++ { state := clt.GetBlockConfirmationState(blkID) if state == apimodels.BlockStateConfirmed.String() || state == apimodels.BlockStateFinalized.String() { - UtilsLogger.Debugf("Block confirmed: %s", blkID.ToHex()) + log.Debugf("Block confirmed: %s", blkID.ToHex()) return nil } time.Sleep(AwaitInterval) } - UtilsLogger.Debugf("Block not confirmed: %s", blkID.ToHex()) + log.Debugf("Block not confirmed: %s", blkID.ToHex()) return ierrors.Errorf("Block not confirmed: %s", blkID.ToHex()) } @@ -61,6 +61,7 @@ func AwaitTransactionToBeAccepted(clt models.Client, txID iotago.TransactionID, for i := 0; i < MaxRetries; i++ { resp, _ := clt.GetBlockStateFromTransaction(txID) if resp == nil { + time.Sleep(AwaitInterval) continue } @@ -78,7 +79,7 @@ func AwaitTransactionToBeAccepted(clt models.Client, txID iotago.TransactionID, confirmationState := resp.TransactionState - UtilsLogger.Debugf("Tx %s confirmationState: %s, tx left: %d", txID.ToHex(), confirmationState, txLeft.Load()) + log.Debugf("Tx %s confirmationState: %s, tx left: %d", txID.ToHex(), confirmationState, txLeft.Load()) if confirmationState == apimodels.TransactionStateAccepted.String() || confirmationState == apimodels.TransactionStateConfirmed.String() || confirmationState == apimodels.TransactionStateFinalized.String() { @@ -114,7 +115,7 @@ func AwaitAddressUnspentOutputToBeAccepted(clt models.Client, addr iotago.Addres } if len(unspents) == 0 { - UtilsLogger.Debugf("no unspent outputs found in indexer for address: %s", addrBech) + log.Debugf("no unspent outputs found in indexer for address: %s", addrBech) break } From faf487225376a0e4004102c9c782901b63ec0c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 14:08:12 +0100 Subject: [PATCH 11/15] Tune the requesting --- evilwallet/evilwallet.go | 11 +++++++++-- programs/spammers.go | 30 +++++++++++++----------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/evilwallet/evilwallet.go b/evilwallet/evilwallet.go index 964ca75..5ab5802 100644 --- a/evilwallet/evilwallet.go +++ b/evilwallet/evilwallet.go @@ -23,8 +23,15 @@ import ( const ( // FaucetRequestSplitNumber defines the number of outputs to split from a faucet request. - FaucetRequestSplitNumber = 120 - faucetTokensPerRequest iotago.BaseToken = 432_000_000 + FaucetRequestSplitNumber = 120 + // MaxBigWalletsCreatedAtOnce is maximum of evil wallets that can be created at once for non-infinite spam. + MaxBigWalletsCreatedAtOnce = 10 + // BigFaucetWalletDeposit indicates the minimum outputs left number that triggers funds requesting in the background + BigFaucetWalletDeposit = 4 + // CheckFundsLeftInterval is the interval to check funds left in the background for requesting funds triggering. + CheckFundsLeftInterval = time.Second * 5 + // BigFaucetWalletsAtOnce number of faucet wallets requested at once in the background + BigFaucetWalletsAtOnce = 2 ) var ( diff --git a/programs/spammers.go b/programs/spammers.go index 246126c..00ed456 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -10,23 +10,18 @@ import ( "github.com/iotaledger/evil-tools/spammer" ) -const ( - maxBigWalletsCreatedAtOnce = 10 - checkFundsLeftInterval = time.Second * 20 -) - var log = logger.New("customSpam") func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-chan bool { if params.SpamType == spammer.TypeBlock { return nil } - var numOfBigWallets = 2 + var numOfBigWallets = evilwallet.BigFaucetWalletsAtOnce if params.Duration >= 0 { numOfBigWallets = spammer.BigWalletsNeeded(params.Rate, params.TimeUnit, params.Duration) - if numOfBigWallets > maxBigWalletsCreatedAtOnce { - numOfBigWallets = maxBigWalletsCreatedAtOnce - log.Warnf("Reached maximum number of big wallets created at once: %d, use infinite spam instead", maxBigWalletsCreatedAtOnce) + if numOfBigWallets > evilwallet.MaxBigWalletsCreatedAtOnce { + numOfBigWallets = evilwallet.MaxBigWalletsCreatedAtOnce + log.Warnf("Reached maximum number of big wallets created at once: %d, use infinite spam instead", evilwallet.MaxBigWalletsCreatedAtOnce) } } success := w.RequestFreshBigFaucetWallets(numOfBigWallets) @@ -41,13 +36,14 @@ func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-ch return nil } var requestingChan = make(<-chan bool) + var errorChan = make(chan<- error) log.Debugf("Start requesting faucet funds infinitely...") - go requestInfinitely(w, requestingChan) + go requestInfinitely(w, requestingChan, errorChan) return requestingChan } -func requestInfinitely(w *evilwallet.EvilWallet, done <-chan bool) { +func requestInfinitely(w *evilwallet.EvilWallet, done <-chan bool, errChan chan<- error) { for { select { case <-done: @@ -55,14 +51,14 @@ func requestInfinitely(w *evilwallet.EvilWallet, done <-chan bool) { return - case <-time.After(checkFundsLeftInterval): + case <-time.After(evilwallet.CheckFundsLeftInterval): outputsLeft := w.UnspentOutputsLeft(evilwallet.Fresh) - // less than one big wallet left - if outputsLeft < evilwallet.FaucetRequestSplitNumber*evilwallet.FaucetRequestSplitNumber { + // keep requesting over and over until we have at least deposit + if outputsLeft < evilwallet.BigFaucetWalletDeposit*evilwallet.FaucetRequestSplitNumber*evilwallet.FaucetRequestSplitNumber { log.Debugf("Requesting new faucet funds, outputs left: %d", outputsLeft) - err := w.RequestFreshBigFaucetWallet() - if err != nil { - log.Errorf("Failed to request faucet wallet: %s, stopping next requests...", err) + success := w.RequestFreshBigFaucetWallets(evilwallet.BigFaucetWalletsAtOnce) + if !success { + log.Errorf("Failed to request faucet wallet: %s, stopping next requests..., stopping spammer") return } From 25f970ee1a0a725dc3bd2208ade530dd628da4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 15:04:57 +0100 Subject: [PATCH 12/15] Lower the FaucetRequestSplit for now to not break the network --- evilwallet/evilwallet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evilwallet/evilwallet.go b/evilwallet/evilwallet.go index 5ab5802..6a7d021 100644 --- a/evilwallet/evilwallet.go +++ b/evilwallet/evilwallet.go @@ -23,7 +23,7 @@ import ( const ( // FaucetRequestSplitNumber defines the number of outputs to split from a faucet request. - FaucetRequestSplitNumber = 120 + FaucetRequestSplitNumber = 50 // MaxBigWalletsCreatedAtOnce is maximum of evil wallets that can be created at once for non-infinite spam. MaxBigWalletsCreatedAtOnce = 10 // BigFaucetWalletDeposit indicates the minimum outputs left number that triggers funds requesting in the background From 32462d22ac64db9e394131f770a808858048c431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 15:11:26 +0100 Subject: [PATCH 13/15] Please the doggo --- evilwallet/evilwallet.go | 22 ++-------------------- programs/dispatcher.go | 2 -- programs/params.go | 14 +++++++------- utils/utils.go | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/evilwallet/evilwallet.go b/evilwallet/evilwallet.go index 6a7d021..e88aeff 100644 --- a/evilwallet/evilwallet.go +++ b/evilwallet/evilwallet.go @@ -1,7 +1,6 @@ package evilwallet import ( - "fmt" "sync" "time" @@ -26,11 +25,11 @@ const ( FaucetRequestSplitNumber = 50 // MaxBigWalletsCreatedAtOnce is maximum of evil wallets that can be created at once for non-infinite spam. MaxBigWalletsCreatedAtOnce = 10 - // BigFaucetWalletDeposit indicates the minimum outputs left number that triggers funds requesting in the background + // BigFaucetWalletDeposit indicates the minimum outputs left number that triggers funds requesting in the background. BigFaucetWalletDeposit = 4 // CheckFundsLeftInterval is the interval to check funds left in the background for requesting funds triggering. CheckFundsLeftInterval = time.Second * 5 - // BigFaucetWalletsAtOnce number of faucet wallets requested at once in the background + // BigFaucetWalletsAtOnce number of faucet wallets requested at once in the background. BigFaucetWalletsAtOnce = 2 ) @@ -477,23 +476,6 @@ func (e *EvilWallet) CreateTransaction(options ...Option) (*models.PayloadIssuan return txData, nil } -func printTransaction(tx *iotago.SignedTransaction) string { - txDetails := "" - txDetails += fmt.Sprintf("Transaction ID; %s, slotCreation: %d\n", lo.PanicOnErr(tx.ID()).ToHex(), tx.Transaction.CreationSlot) - for index, out := range tx.Transaction.Outputs { - txDetails += fmt.Sprintf("Output index: %d, base token: %d, stored mana: %d\n", index, out.BaseTokenAmount(), out.StoredMana()) - } - txDetails += fmt.Sprintln("Allotments:") - for _, allotment := range tx.Transaction.Allotments { - txDetails += fmt.Sprintf("AllotmentID: %s, value: %d\n", allotment.AccountID, allotment.Mana) - } - for _, allotment := range tx.Transaction.TransactionEssence.Allotments { - txDetails += fmt.Sprintf("al 2 AllotmentID: %s, value: %d\n", allotment.AccountID, allotment.Mana) - } - - return txDetails -} - // addOutputsToOutputManager adds output to the OutputManager if. func (e *EvilWallet) addOutputsToOutputManager(signedTx *iotago.SignedTransaction, outWallet, tmpWallet *Wallet, tempAddresses map[string]types.Empty) { for idx, o := range signedTx.Transaction.Outputs { diff --git a/programs/dispatcher.go b/programs/dispatcher.go index 3789d17..de68a23 100644 --- a/programs/dispatcher.go +++ b/programs/dispatcher.go @@ -3,11 +3,9 @@ package programs import ( "github.com/iotaledger/evil-tools/accountwallet" "github.com/iotaledger/evil-tools/models" - "github.com/iotaledger/evil-tools/spammer" ) type Runner struct { - spammer *spammer.Spammer spamDetails *models.Config finished chan bool diff --git a/programs/params.go b/programs/params.go index 689f5d3..9d639bd 100644 --- a/programs/params.go +++ b/programs/params.go @@ -26,13 +26,13 @@ type CustomSpamParams struct { func ConfigFromCustomSpamParams(params *CustomSpamParams) *models.Config { return &models.Config{ - WebAPI: params.ClientURLs, + WebAPI: params.ClientURLs, FaucetURL: "http://localhost:8088", - Rate: params.Rate, - Duration: params.Duration.String(), - TimeUnit: params.TimeUnit.String(), - Deep: params.DeepSpam, - Reuse: false, - Scenario: params.ScenarioName, + Rate: params.Rate, + Duration: params.Duration.String(), + TimeUnit: params.TimeUnit.String(), + Deep: params.DeepSpam, + Reuse: false, + Scenario: params.ScenarioName, } } diff --git a/utils/utils.go b/utils/utils.go index ab73d6f..a82a498 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -2,6 +2,7 @@ package utils import ( "context" + "fmt" "time" "go.uber.org/atomic" @@ -142,3 +143,20 @@ func AwaitOutputToBeAccepted(clt models.Client, outputID iotago.OutputID) bool { return false } + +func PrintTransaction(tx *iotago.SignedTransaction) string { + txDetails := "" + txDetails += fmt.Sprintf("Transaction ID; %s, slotCreation: %d\n", lo.PanicOnErr(tx.ID()).ToHex(), tx.Transaction.CreationSlot) + for index, out := range tx.Transaction.Outputs { + txDetails += fmt.Sprintf("Output index: %d, base token: %d, stored mana: %d\n", index, out.BaseTokenAmount(), out.StoredMana()) + } + txDetails += fmt.Sprintln("Allotments:") + for _, allotment := range tx.Transaction.Allotments { + txDetails += fmt.Sprintf("AllotmentID: %s, value: %d\n", allotment.AccountID, allotment.Mana) + } + for _, allotment := range tx.Transaction.TransactionEssence.Allotments { + txDetails += fmt.Sprintf("al 2 AllotmentID: %s, value: %d\n", allotment.AccountID, allotment.Mana) + } + + return txDetails +} From 63595f7e2e0b50052dc231642fcd8f5219cb596e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 15:24:02 +0100 Subject: [PATCH 14/15] Cleanup duration --- config.go | 1 - parse.go | 3 ++- programs/spammers.go | 26 ++++++++++---------------- spammer/spammer.go | 4 ++++ 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/config.go b/config.go index 8a3ccfb..08ff9df 100644 --- a/config.go +++ b/config.go @@ -23,7 +23,6 @@ var ( FaucetURL: "http://localhost:8088", SpamType: spammer.TypeBlock, Rate: 1, - Duration: 0, TimeUnit: time.Second, DelayBetweenConflicts: 0, NSpend: 2, diff --git a/parse.go b/parse.go index 3a7c925..818ebe3 100644 --- a/parse.go +++ b/parse.go @@ -9,6 +9,7 @@ import ( "github.com/iotaledger/evil-tools/accountwallet" "github.com/iotaledger/evil-tools/evilwallet" + "github.com/iotaledger/evil-tools/spammer" "github.com/iotaledger/hive.go/ierrors" ) @@ -77,7 +78,7 @@ func parseBasicSpamFlags() { if *duration != "" { customSpamParams.Duration, _ = time.ParseDuration(*duration) } else { - customSpamParams.Duration = time.Duration(-1) + customSpamParams.Duration = spammer.InfiniteDuration } if *scenario != "" { conflictBatch, ok := evilwallet.GetScenario(*scenario) diff --git a/programs/spammers.go b/programs/spammers.go index 00ed456..9d0f820 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -17,7 +17,7 @@ func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-ch return nil } var numOfBigWallets = evilwallet.BigFaucetWalletsAtOnce - if params.Duration >= 0 { + if params.Duration != spammer.InfiniteDuration { numOfBigWallets = spammer.BigWalletsNeeded(params.Rate, params.TimeUnit, params.Duration) if numOfBigWallets > evilwallet.MaxBigWalletsCreatedAtOnce { numOfBigWallets = evilwallet.MaxBigWalletsCreatedAtOnce @@ -29,21 +29,20 @@ func requestFaucetFunds(params *CustomSpamParams, w *evilwallet.EvilWallet) <-ch log.Errorf("Failed to request faucet wallet") return nil } - if params.Duration >= 0 { + if params.Duration != spammer.InfiniteDuration { unspentOutputsLeft := w.UnspentOutputsLeft(evilwallet.Fresh) log.Debugf("Prepared %d unspent outputs for spamming.", unspentOutputsLeft) return nil } var requestingChan = make(<-chan bool) - var errorChan = make(chan<- error) log.Debugf("Start requesting faucet funds infinitely...") - go requestInfinitely(w, requestingChan, errorChan) + go requestInfinitely(w, requestingChan) return requestingChan } -func requestInfinitely(w *evilwallet.EvilWallet, done <-chan bool, errChan chan<- error) { +func requestInfinitely(w *evilwallet.EvilWallet, done <-chan bool) { for { select { case <-done: @@ -75,11 +74,6 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet log.Infof("Start spamming with rate: %d, time unit: %s, and spamming type: %s.", params.Rate, params.TimeUnit.String(), params.SpamType) - var duration time.Duration = -1 - if params.Duration >= 0 { - duration = params.Duration - } - // TODO here we can shutdown requesting when we will have evil-tools running in the background. _ = requestFaucetFunds(params, w) @@ -90,7 +84,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet wg.Add(1) go func() { defer wg.Done() - s := SpamBlocks(w, params.Rate, params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) + s := SpamBlocks(w, params.Rate, params.TimeUnit, params.Duration, params.EnableRateSetter, params.AccountAlias) if s == nil { return } @@ -101,7 +95,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet go func() { defer wg.Done() - s := SpamBlowball(w, params.Rate, params.TimeUnit, duration, params.BlowballSize, params.EnableRateSetter, params.AccountAlias) + s := SpamBlowball(w, params.Rate, params.TimeUnit, params.Duration, params.BlowballSize, params.EnableRateSetter, params.AccountAlias) if s == nil { return } @@ -111,19 +105,19 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet wg.Add(1) go func() { defer wg.Done() - SpamTransaction(w, params.Rate, params.TimeUnit, duration, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) + SpamTransaction(w, params.Rate, params.TimeUnit, params.Duration, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) }() case spammer.TypeDs: wg.Add(1) go func() { defer wg.Done() - SpamDoubleSpends(w, params.Rate, params.NSpend, params.TimeUnit, duration, params.DelayBetweenConflicts, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) + SpamDoubleSpends(w, params.Rate, params.NSpend, params.TimeUnit, params.Duration, params.DelayBetweenConflicts, params.DeepSpam, params.EnableRateSetter, params.AccountAlias) }() case spammer.TypeCustom: wg.Add(1) go func() { defer wg.Done() - s := SpamNestedConflicts(w, params.Rate, params.TimeUnit, duration, params.Scenario, params.DeepSpam, false, params.EnableRateSetter, params.AccountAlias) + s := SpamNestedConflicts(w, params.Rate, params.TimeUnit, params.Duration, params.Scenario, params.DeepSpam, false, params.EnableRateSetter, params.AccountAlias) if s == nil { return } @@ -134,7 +128,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet go func() { defer wg.Done() - s := SpamAccounts(w, params.Rate, params.TimeUnit, duration, params.EnableRateSetter, params.AccountAlias) + s := SpamAccounts(w, params.Rate, params.TimeUnit, params.Duration, params.EnableRateSetter, params.AccountAlias) if s == nil { return } diff --git a/spammer/spammer.go b/spammer/spammer.go index 46c582a..eb0ac67 100644 --- a/spammer/spammer.go +++ b/spammer/spammer.go @@ -26,6 +26,10 @@ const ( TypeBlowball = "bb" ) +const ( + InfiniteDuration = time.Duration(-1) +) + // region Spammer ////////////////////////////////////////////////////////////////////////////////////////////////////// type SpammingFunc func(*Spammer) From a60e7d8b0c17020d3c7f68b86017b4426f73f8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 2 Nov 2023 15:24:19 +0100 Subject: [PATCH 15/15] Update await params --- utils/utils.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/utils.go b/utils/utils.go index a82a498..1dd5db0 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -18,8 +18,8 @@ import ( var log = evillogger.New("Utils") const ( - MaxRetries = 100 - AwaitInterval = 1 * time.Second + MaxRetries = 20 + AwaitInterval = 2 * time.Second ) // SplitBalanceEqually splits the balance equally between `splitNumber` outputs.