diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0db6a76..d73830d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ on: jobs: build: name: Build evil-tools - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Set up Go uses: actions/setup-go@v4 diff --git a/.github/workflows/codeql_analysis.yml b/.github/workflows/codeql_analysis.yml index e184698..6dee232 100644 --- a/.github/workflows/codeql_analysis.yml +++ b/.github/workflows/codeql_analysis.yml @@ -9,7 +9,7 @@ on: jobs: analyze: name: Analyze - runs-on: self-hosted + runs-on: ubuntu-latest permissions: actions: read contents: read diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 1836018..0d90d41 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -8,7 +8,7 @@ on: jobs: golangci-lint: name: GolangCI-Lint - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory uses: actions/checkout@v3 diff --git a/accountwallet/commands.go b/accountwallet/commands.go index 0a09965..62129d2 100644 --- a/accountwallet/commands.go +++ b/accountwallet/commands.go @@ -12,7 +12,7 @@ import ( "github.com/iotaledger/iota.go/v4/builder" ) -// CreateAccount creates an implicit account and immediatelly transition it to a regular account. +// CreateAccount creates an implicit account and immediately transition it to a regular account. func (a *AccountWallet) CreateAccount(params *CreateAccountParams) (iotago.AccountID, error) { if params.Implicit { return a.createAccountImplicitly(params) @@ -23,7 +23,7 @@ func (a *AccountWallet) CreateAccount(params *CreateAccountParams) (iotago.Accou func (a *AccountWallet) createAccountImplicitly(params *CreateAccountParams) (iotago.AccountID, error) { // An implicit account has an implicitly defined Block Issuer Key, corresponding to the address itself. - // Thus implicit accounts can issue blocks by signing them with the private key corresponding to the public key + // Thus, implicit accounts can issue blocks by signing them with the private key corresponding to the public key // from which the Implicit Account Creation Address was derived. implicitAccountOutput, privateKey, err := a.getFunds(params.Amount, iotago.AddressImplicitAccountCreation) if err != nil { @@ -39,7 +39,12 @@ func (a *AccountWallet) createAccountImplicitly(params *CreateAccountParams) (io log.Debugf("Transitioning implicit account with implicitAccountID %s for alias %s to regular account", params.Alias, iotago.AccountIDFromOutputID(implicitAccountOutput.OutputID).ToHex()) - implicitAccAddr := iotago.ImplicitAccountCreationAddressFromPubKey(privateKey.Public().(ed25519.PublicKey)) + pubKey, isEd25519 := privateKey.Public().(ed25519.PublicKey) + if !isEd25519 { + return iotago.EmptyAccountID, ierrors.New("Failed to create account: only Ed25519 keys are supported") + } + + implicitAccAddr := iotago.ImplicitAccountCreationAddressFromPubKey(pubKey) addrKeys := iotago.NewAddressKeysForImplicitAccountCreationAddress(implicitAccAddr, privateKey) implicitBlockIssuerKey := iotago.Ed25519PublicKeyHashBlockIssuerKeyFromImplicitAccountCreationAddress(implicitAccAddr) blockIssuerKeys := iotago.NewBlockIssuerKeys(implicitBlockIssuerKey) @@ -52,7 +57,7 @@ func (a *AccountWallet) transitionImplicitAccount( implicitAccAddr *iotago.ImplicitAccountCreationAddress, accAddr iotago.Address, blockIssuerKeys iotago.BlockIssuerKeys, - privateKey ed25519.PrivateKey, + _ ed25519.PrivateKey, params *CreateAccountParams, ) (iotago.AccountID, error) { // transition from implicit to regular account @@ -62,12 +67,10 @@ func (a *AccountWallet) transitionImplicitAccount( BlockIssuer(blockIssuerKeys, iotago.MaxSlotIndex).MustBuild() log.Infof("Created account %s with %d tokens\n", accountOutput.AccountID.ToHex(), params.Amount) - txBuilder, err := a.createTransactionBuilder(implicitAccountOutput, implicitAccAddr, accountOutput) - if err != nil { - return iotago.EmptyAccountID, ierrors.Wrap(err, "Failed to create account") - } + txBuilder := a.createTransactionBuilder(implicitAccountOutput, implicitAccAddr, accountOutput) + // TODO get congestionResponse from API - var rmc iotago.Mana = 0 + var rmc iotago.Mana var implicitAccountID iotago.AccountID txBuilder.AllotRequiredManaAndStoreRemainingManaInOutput(txBuilder.CreationSlot(), rmc, implicitAccountID, 0) @@ -79,7 +82,7 @@ func (a *AccountWallet) transitionImplicitAccount( return iotago.EmptyAccountID, nil } -func (a *AccountWallet) createAccountWithFaucet(params *CreateAccountParams) (iotago.AccountID, error) { +func (a *AccountWallet) createAccountWithFaucet(_ *CreateAccountParams) (iotago.AccountID, error) { log.Debug("Not implemented yet") //faucetOutput := a.getFaucetOutput() // @@ -94,7 +97,7 @@ func (a *AccountWallet) createAccountWithFaucet(params *CreateAccountParams) (io return iotago.EmptyAccountID, nil } -func (a *AccountWallet) createTransactionBuilder(input *models.Output, address iotago.Address, accountOutput *iotago.AccountOutput) (*builder.TransactionBuilder, error) { +func (a *AccountWallet) createTransactionBuilder(input *models.Output, address iotago.Address, accountOutput *iotago.AccountOutput) *builder.TransactionBuilder { currentTime := time.Now() currentSlot := a.client.LatestAPI().TimeProvider().SlotFromTime(currentTime) @@ -109,7 +112,7 @@ func (a *AccountWallet) createTransactionBuilder(input *models.Output, address i txBuilder.AddOutput(accountOutput) txBuilder.SetCreationSlot(currentSlot) - return txBuilder, nil + return txBuilder } func (a *AccountWallet) getAddress(addressType iotago.AddressType) (iotago.DirectUnlockableAddress, ed25519.PrivateKey, uint64) { @@ -139,6 +142,6 @@ func (a *AccountWallet) ListAccount() error { return nil } -func (a *AccountWallet) AllotToAccount(params *AllotAccountParams) error { +func (a *AccountWallet) AllotToAccount(_ *AllotAccountParams) error { return nil } diff --git a/accountwallet/config.go b/accountwallet/config.go index 2ec4017..5792039 100644 --- a/accountwallet/config.go +++ b/accountwallet/config.go @@ -15,7 +15,7 @@ type AccountOperation int const ( OperationCreateAccount AccountOperation = iota OperationConvertAccount - OperationDestroyAccound + OperationDestroyAccount OperationAllotAccount OperationDelegateAccount OperationStakeAccount @@ -58,6 +58,7 @@ func AvailableCommands(cmd string) bool { } _, ok := availableCommands[cmd] + return ok } @@ -66,7 +67,7 @@ type Configuration struct { AccountStatesFile string `json:"accountStatesFile,omitempty"` GenesisSeed string `json:"genesisSeed,omitempty"` BlockIssuerPrivateKey string `json:"blockIssuerPrivateKey,omitempty"` - AccountID string `json:"accountID,omitempty"` + AccountID string `json:"accountId,omitempty"` } var accountConfigFile = "config.json" @@ -150,7 +151,7 @@ type DestroyAccountParams struct { } func (d *DestroyAccountParams) Type() AccountOperation { - return OperationDestroyAccound + return OperationDestroyAccount } type AllotAccountParams struct { diff --git a/accountwallet/faucet.go b/accountwallet/faucet.go index 38a6904..6b64e8e 100644 --- a/accountwallet/faucet.go +++ b/accountwallet/faucet.go @@ -152,6 +152,7 @@ func newFaucet(clt models.Client, faucetParams *faucetParams) (*faucet, error) { return nil, ierrors.Wrap(err, "failed to get faucet output from indexer") } + //nolint:all,forcetypassert f.unspentOutput = &models.Output{ Address: faucetAddr.(*iotago.Ed25519Address), AddressIndex: 0, @@ -203,12 +204,12 @@ func (f *faucet) prepareFaucetRequest(receiveAddr iotago.Address, amount iotago. return nil, err } - rmcAllotedTxBuilder := txBuilder.Clone() + rmcAllottedTxBuilder := txBuilder.Clone() // faucet will allot exact mana to be burnt, rest of the mana is alloted to faucet output remainder - rmcAllotedTxBuilder.AllotRequiredManaAndStoreRemainingManaInOutput(txBuilder.CreationSlot(), rmc, f.account.ID(), remainderIndex) + rmcAllottedTxBuilder.AllotRequiredManaAndStoreRemainingManaInOutput(txBuilder.CreationSlot(), rmc, f.account.ID(), remainderIndex) var signedTx *iotago.SignedTransaction - signedTx, err = rmcAllotedTxBuilder.Build(f.genesisHdWallet.AddressSigner()) + signedTx, err = rmcAllottedTxBuilder.Build(f.genesisHdWallet.AddressSigner()) if err != nil { log.Infof("WARN: failed to build tx with min required mana allotted, genesis potential mana was not enough, fallback to faucet account") txBuilder.AllotAllMana(txBuilder.CreationSlot(), f.account.ID()) @@ -218,6 +219,7 @@ func (f *faucet) prepareFaucetRequest(receiveAddr iotago.Address, amount iotago. } // set remainder output to be reused by the Faucet wallet + //nolint:all,forcetypassert f.unspentOutput = &models.Output{ OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.Transaction.ID()), uint16(remainderIndex)), Address: f.genesisHdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address), @@ -236,6 +238,7 @@ func (f *faucet) createFaucetTransactionNoManaHandling(receiveAddr iotago.Addres apiForSlot := f.clt.APIForSlot(currentSlot) txBuilder := builder.NewTransactionBuilder(apiForSlot) + //nolint:all,forcetypassert txBuilder.AddInput(&builder.TxInput{ UnlockTarget: f.genesisHdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address), InputID: f.unspentOutput.OutputID, @@ -244,7 +247,7 @@ func (f *faucet) createFaucetTransactionNoManaHandling(receiveAddr iotago.Addres remainderAmount, err := safemath.SafeSub(f.unspentOutput.Balance, amount) if err != nil { - panic(err) + return nil, 0, ierrors.Errorf("safeSub failed %d - %d: %s", f.unspentOutput.Balance, amount, err) } txBuilder.AddOutput(&iotago.BasicOutput{ @@ -257,6 +260,7 @@ func (f *faucet) createFaucetTransactionNoManaHandling(receiveAddr iotago.Addres // remainder output remainderIndex := 1 + //nolint:all,forcetypassert txBuilder.AddOutput(&iotago.BasicOutput{ Amount: remainderAmount, Conditions: iotago.BasicOutputUnlockConditions{ diff --git a/accountwallet/wallet.go b/accountwallet/wallet.go index 5040073..63824fd 100644 --- a/accountwallet/wallet.go +++ b/accountwallet/wallet.go @@ -144,6 +144,7 @@ func (a *AccountWallet) fromAccountStateFile() error { if !os.IsNotExist(err) { return ierrors.Wrap(err, "failed to read file") } + return nil } @@ -174,6 +175,7 @@ func (a *AccountWallet) fromAccountStateFile() error { return nil } +//nolint:all,unused func (a *AccountWallet) registerAccount(alias string, outputID iotago.OutputID, index uint64, privKey ed25519.PrivateKey) iotago.AccountID { a.accountAliasesMutex.Lock() defer a.accountAliasesMutex.Unlock() @@ -259,7 +261,7 @@ func (a *AccountWallet) isAccountReady(accData *models.AccountData) bool { } if resp.Commitment.Slot >= creationSlot { - log.Infof("Slot %d commited, account %s is ready to use", creationSlot, accData.Alias) + log.Infof("Slot %d committed, account %s is ready to use", creationSlot, accData.Alias) return true, nil } @@ -311,6 +313,7 @@ func (a *AccountWallet) destroyAccount(alias string) error { }) // send all tokens to faucet + //nolint:all,forcetypassert txBuilder.AddOutput(&iotago.BasicOutput{ Amount: accountOutput.BaseTokenAmount(), Conditions: iotago.BasicOutputUnlockConditions{ @@ -337,6 +340,7 @@ func (a *AccountWallet) destroyAccount(alias string) error { delete(a.accountsAliases, alias) log.Infof("Account %s has been destroyed", alias) + return nil } diff --git a/config.go b/config.go index 0bdcd27..f8d412f 100644 --- a/config.go +++ b/config.go @@ -9,16 +9,14 @@ import ( "github.com/iotaledger/evil-tools/spammer" ) -// Nodes used during the test, use at least two nodes to be able to doublespend. +// Nodes used during the test, use at least two nodes to be able to double spend. var ( // urls = []string{"http://bootstrap-01.feature.shimmer.iota.cafe:8080", "http://vanilla-01.feature.shimmer.iota.cafe:8080", "http://drng-01.feature.shimmer.iota.cafe:8080"} urls = []string{"http://localhost:8080", "http://localhost:8090"} //, "http://localhost:8070", "http://localhost:8040"} - //urls = []string{} ) var ( - Script = "basic" - Subcommand = "" + Script = ScriptSpammer customSpamParams = programs.CustomSpamParams{ ClientURLs: urls, @@ -35,26 +33,5 @@ var ( AccountAlias: accountwallet.FaucetAccountAlias, } - quickTestParams = programs.QuickTestParams{ - ClientURLs: urls, - Rate: 100, - Duration: time.Second * 30, - TimeUnit: time.Second, - DelayBetweenConflicts: 0, - EnableRateSetter: false, - } - accountsSubcommandsFlags []accountwallet.AccountSubcommands - - //nolint:godot - // commitmentsSpamParams = CommitmentsSpamParams{ - // Rate: 1, - // Duration: time.Second * 20, - // TimeUnit: time.Second, - // NetworkAlias: "docker", - // SpammerAlias: "validator-1", - // ValidAlias: accountwallet.FaucetAccountAlias, - // CommitmentType: "latest", - // ForkAfter: 10, - // } ) diff --git a/evilwallet/evilscenario.go b/evilwallet/evilscenario.go index 00f15d9..0cd0c55 100644 --- a/evilwallet/evilscenario.go +++ b/evilwallet/evilscenario.go @@ -69,12 +69,12 @@ func NewEvilScenario(options ...ScenarioOption) *EvilScenario { option(scenario) } scenario.ID = base58.Encode([]byte(fmt.Sprintf("%v%v%v", scenario.ConflictBatch, scenario.Reuse, scenario.OutputWallet.ID)))[:11] - scenario.NumOfClientsNeeded = calculateNumofClientsNeeded(scenario) + scenario.NumOfClientsNeeded = calculateNumOfClientsNeeded(scenario) return scenario } -func calculateNumofClientsNeeded(scenario *EvilScenario) (counter int) { +func calculateNumOfClientsNeeded(scenario *EvilScenario) (counter int) { for _, conflictMap := range scenario.ConflictBatch { if len(conflictMap) > counter { counter = len(conflictMap) diff --git a/evilwallet/evilwallet.go b/evilwallet/evilwallet.go index 5e1d36a..5935b8e 100644 --- a/evilwallet/evilwallet.go +++ b/evilwallet/evilwallet.go @@ -26,10 +26,7 @@ const ( faucetTokensPerRequest iotago.BaseToken = 432_000_000 waitForAcceptance = 20 * time.Second - waitForSolidification = 10 * time.Second - - awaitAcceptationSleep = 1 * time.Second - awaitSolidificationSleep = time.Millisecond * 500 + awaitAcceptationSleep = 1 * time.Second ) var ( @@ -99,8 +96,8 @@ func (e *EvilWallet) UnspentOutputsLeft(walletType WalletType) int { } func (e *EvilWallet) NumOfClient() int { - clts := e.connector.Clients() - return len(clts) + clients := e.connector.Clients() + return len(clients) } func (e *EvilWallet) AddClient(clientURL string) { @@ -121,10 +118,12 @@ func (e *EvilWallet) GetAccount(alias string) (blockhandler.Account, error) { } func (e *EvilWallet) PrepareAndPostBlock(clt models.Client, payload iotago.Payload, congestionResp *apimodels.CongestionResponse, issuer blockhandler.Account) (iotago.BlockID, error) { - congestionResp, issuerResp, version, err := e.accWallet.RequestBlockBuiltData(clt.Client(), issuer.ID()) + issuerResp, err := clt.GetBlockIssuance(congestionResp.Slot) if err != nil { - return iotago.EmptyBlockID, ierrors.Wrapf(err, "failed to get block built data for issuer %s", issuer.ID().ToHex()) + return iotago.EmptyBlockID, ierrors.Wrap(err, "failed to get block issuance data") } + + version := clt.APIForSlot(congestionResp.Slot).Version() blockID, err := e.accWallet.PostWithBlock(clt, payload, issuer, congestionResp, issuerResp, version) if err != nil { return iotago.EmptyBlockID, err @@ -152,7 +151,7 @@ func (e *EvilWallet) RequestFundsFromFaucet(options ...FaucetRequestOption) (ini e.aliasManager.AddInputAlias(output, buildOptions.outputAliasName) } - e.log.Debug("Funds requested succesfully") + e.log.Debug("Funds requested successfully") return } @@ -167,6 +166,7 @@ func (e *EvilWallet) RequestFreshBigFaucetWallets(numberOfWallets int) bool { for reqNum := 0; reqNum < numberOfWallets; reqNum++ { wg.Add(1) + // block if full semaphore <- true go func() { @@ -188,6 +188,7 @@ func (e *EvilWallet) RequestFreshBigFaucetWallets(numberOfWallets int) bool { wg.Wait() e.log.Debugf("Finished requesting %d wallets from faucet", numberOfWallets) + return success } @@ -200,11 +201,12 @@ func (e *EvilWallet) RequestFreshBigFaucetWallet() error { if err != nil { return ierrors.Wrap(err, "failed to request big funds from faucet") } - e.log.Debug("First level of splitting finished, now split each outut once again") + + e.log.Debug("First level of splitting finished, now split each output once again") bigOutputWallet := e.NewWallet(Fresh) _, err = e.splitOutputs(receiveWallet, bigOutputWallet) if err != nil { - return ierrors.Wrap(err, "failed to split splitted outputs for the big wallet") + return ierrors.Wrap(err, "failed to again split outputs for the big wallet") } e.wallets.SetWalletReady(bigOutputWallet) @@ -285,13 +287,18 @@ func (e *EvilWallet) splitOutput(splitOutput *models.Output, inputWallet, output if txData.Payload.PayloadType() != iotago.PayloadSignedTransaction { return iotago.EmptyTransactionID, ierrors.New("payload type is not signed transaction") } - txID := lo.PanicOnErr(txData.Payload.(*iotago.SignedTransaction).Transaction.ID()) + + signedTx, ok := txData.Payload.(*iotago.SignedTransaction) + if !ok { + return iotago.EmptyTransactionID, ierrors.New("type assertion error: payload is not a signed transaction") + } + txID := lo.PanicOnErr(signedTx.Transaction.ID()) e.log.Debugf("Splitting output %s finished with tx: %s", splitOutput.OutputID.ToHex(), txID.ToHex()) return txID, nil } -// splitOutputs splits all outputs from the provided imput wallet, outputs are saved to the outputWallet. +// splitOutputs splits all outputs from the provided input wallet, outputs are saved to the outputWallet. func (e *EvilWallet) splitOutputs(inputWallet, outputWallet *Wallet) ([]iotago.TransactionID, error) { if inputWallet.IsEmpty() { return nil, ierrors.New("failed to split outputs, inputWallet is empty") @@ -371,8 +378,8 @@ func (e *EvilWallet) PrepareCustomConflicts(conflictsMaps []ConflictSlice) (conf // CreateTransaction creates a transaction based on provided options. If no input wallet is provided, the next non-empty faucet wallet is used. // Inputs of the transaction are determined in three ways: -// 1 - inputs are provided directly without associated alias, 2- alias is provided, and input is already stored in an alias manager, -// 3 - alias is provided, and there are no inputs assigned in Alias manager, so aliases are assigned to next ready inputs from input wallet. +// 1 - inputs are provided directly without associated alias, 2- provided only an alias, but inputs are stored in an alias manager, +// 3 - provided alias, but there are no inputs assigned in Alias manager, so aliases will be assigned to next ready inputs from input wallet. func (e *EvilWallet) CreateTransaction(options ...Option) (*models.PayloadIssuanceData, error) { buildOptions, err := NewOptions(options...) if err != nil { @@ -413,10 +420,11 @@ func (e *EvilWallet) CreateTransaction(options ...Option) (*models.PayloadIssuan } } - signedTx, err := e.makeTransaction(inputs, outputs, buildOptions.inputWallet, congestionResp, buildOptions.allotmentStrategy, buildOptions.issuerAccountID) + signedTx, err := e.makeTransaction(inputs, outputs, buildOptions.inputWallet, congestionResp, buildOptions.issuerAccountID) if err != nil { return nil, err } + txData := &models.PayloadIssuanceData{ Payload: signedTx, CongestionResponse: congestionResp, @@ -426,6 +434,7 @@ func (e *EvilWallet) CreateTransaction(options ...Option) (*models.PayloadIssuan e.registerOutputAliases(signedTx, addrAliasMap) e.log.Debugf("\n %s", printTransaction(signedTx)) + return txData, nil } @@ -479,6 +488,7 @@ func (e *EvilWallet) updateInputWallet(buildOptions *Options) error { if ok { // leave nil, wallet will be selected based on OutputIDWalletMap buildOptions.inputWallet = nil + return nil } @@ -489,6 +499,7 @@ func (e *EvilWallet) updateInputWallet(buildOptions *Options) error { if err != nil { return err } + buildOptions.inputWallet = wallet return nil @@ -525,6 +536,7 @@ func (e *EvilWallet) prepareInputs(buildOptions *Options) (inputs []*models.Outp if err != nil { return nil, err } + inputs = append(inputs, aliasInputs...) return inputs, nil @@ -556,11 +568,13 @@ func (e *EvilWallet) matchInputsWithAliases(buildOptions *Options) (inputs []*mo err = err2 return } + // No output found for given alias, use internal Fresh output if wallets are non-empty. in = e.wallets.GetUnspentOutput(wallet) if in == nil { return nil, ierrors.New("could not get unspent output") } + e.aliasManager.AddInputAlias(in, inputAlias) } inputs = append(inputs, in) @@ -594,7 +608,7 @@ func (e *EvilWallet) useFreshIfInputWalletNotProvided(buildOptions *Options) (*W // matchOutputsWithAliases creates outputs based on balances provided via options. // Outputs are not yet added to the Alias Manager, as they have no ID before the transaction is created. // Thus, they are tracker in address to alias map. If the scenario is used, the outputBatchAliases map is provided -// that indicates which outputs should be saved to the outputWallet.All other outputs are created with temporary wallet, +// that indicates which outputs should be saved to the outputWallet. All other outputs are created with temporary wallet, // and their addresses are stored in tempAddresses. func (e *EvilWallet) matchOutputsWithAliases(buildOptions *Options, tempWallet *Wallet) (outputs []iotago.Output, addrAliasMap map[string]string, tempAddresses map[string]types.Empty, err error, @@ -716,7 +730,7 @@ func (e *EvilWallet) updateOutputBalances(buildOptions *Options) (err error) { return } -func (e *EvilWallet) makeTransaction(inputs []*models.Output, outputs iotago.Outputs[iotago.Output], w *Wallet, congestionResponse *apimodels.CongestionResponse, allotmentStrategy models.AllotmentStrategy, issuerAccountID iotago.AccountID) (tx *iotago.SignedTransaction, 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() @@ -784,8 +798,10 @@ func (e *EvilWallet) evaluateIssuanceStrategy(strategy *models.IssuancePaymentSt if err != nil { panic("could not get issuer accountID while preparing conflicts") } + issuerAccountID = accData.Account.ID() } + return strategy.AllotmentStrategy, issuerAccountID } @@ -857,16 +873,6 @@ func (e *EvilWallet) prepareFlatOptionsForAccountScenario(scenario *EvilScenario }, allAliases } -// AwaitInputsSolidity waits for all inputs to be solid for client clt. -// func (e *EvilWallet) AwaitInputsSolidity(inputs devnetvm.Inputs, clt Client) (allSolid bool) { -// awaitSolid := make([]string, 0) -// for _, in := range inputs { -// awaitSolid = append(awaitSolid, in.Base58()) -// } -// allSolid = e.outputManager.AwaitOutputsToBeSolid(awaitSolid, clt, maxGoroutines) -// return -// } - // SetTxOutputsSolid marks all outputs as solid in OutputManager for clientID. func (e *EvilWallet) SetTxOutputsSolid(outputs iotago.OutputIDs, clientID string) { for _, out := range outputs { @@ -874,17 +880,6 @@ func (e *EvilWallet) SetTxOutputsSolid(outputs iotago.OutputIDs, clientID string } } -// AddReuseOutputsToThePool adds all addresses corresponding to provided outputs to the reuse pool. -// func (e *EvilWallet) AddReuseOutputsToThePool(outputs devnetvm.Outputs) { -// for _, out := range outputs { -// evilOutput := e.outputManager.GetOutput(out.ID()) -// if evilOutput != nil { -// wallet := e.outputManager.OutputIDWalletMap(out.ID().Base58()) -// wallet.AddReuseAddress(evilOutput.Address.Base58()) -// } -// } -// } - // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// func WithClients(urls ...string) options.Option[EvilWallet] { diff --git a/evilwallet/options.go b/evilwallet/options.go index f0a0ad5..0138cd6 100644 --- a/evilwallet/options.go +++ b/evilwallet/options.go @@ -1,8 +1,6 @@ package evilwallet import ( - "time" - "github.com/iotaledger/evil-tools/models" "github.com/iotaledger/hive.go/ds/types" "github.com/iotaledger/hive.go/ierrors" @@ -22,7 +20,6 @@ type Options struct { outputWallet *Wallet outputBatchAliases map[string]types.Empty reuse bool - issuingTime time.Time allotmentStrategy models.AllotmentStrategy issuerAccountID iotago.AccountID // maps input alias to desired output type, used to create account output types @@ -200,13 +197,6 @@ func WithReuseOutputs() Option { } } -// WithIssuingTime returns a BlockOption that is used to set issuing time of the Block. -func WithIssuingTime(issuingTime time.Time) Option { - return func(options *Options) { - options.issuingTime = issuingTime - } -} - // ConflictSlice represents a set of conflict transactions. type ConflictSlice [][]Option diff --git a/evilwallet/output_manager.go b/evilwallet/output_manager.go index 0478245..1fa4a1f 100644 --- a/evilwallet/output_manager.go +++ b/evilwallet/output_manager.go @@ -205,20 +205,6 @@ func (o *OutputManager) getOutputFromWallet(outputID iotago.OutputID) (output *m return } -// RequestOutputsByAddress finds the unspent outputs of a given address and updates the provided output status map. -// func (o *OutputManager) RequestOutputsByAddress(address string) (outputIDs []iotago.OutputID) { -// s := time.Now() -// clt := o.connector.GetClient() -// for ; time.Since(s) < awaitOutputsByAddress; time.Sleep(1 * time.Second) { -// outputIDs, err := clt.GetAddressUnspentOutputs(address) -// if err == nil && len(outputIDs) > 0 { -// return outputIDs -// } -// } - -// return -// } - // RequestOutputsByTxID adds the outputs of a given transaction to the output status map. func (o *OutputManager) RequestOutputsByTxID(txID iotago.TransactionID) (outputIDs iotago.OutputIDs) { clt := o.connector.GetClient() @@ -340,53 +326,3 @@ func (o *OutputManager) AwaitTransactionToBeAccepted(txID iotago.TransactionID, return nil } - -// AwaitOutputToBeSolid awaits for solidification of a single output by provided clt. -func (o *OutputManager) AwaitOutputToBeSolid(outID iotago.OutputID, clt models.Client, waitFor time.Duration) error { - s := time.Now() - var solid bool - - for ; time.Since(s) < waitFor; time.Sleep(awaitSolidificationSleep) { - solid = o.IssuerSolidOutIDMap(clt.URL(), outID) - if solid { - break - } - if output := clt.GetOutput(outID); output != nil { - o.SetOutputIDSolidForIssuer(outID, clt.URL()) - solid = true - - break - } - } - if !solid { - return ierrors.Errorf("output %s not solidified in time", outID) - } - - return nil -} - -// AwaitOutputsToBeSolid awaits for all provided outputs are solid for a provided client. -func (o *OutputManager) AwaitOutputsToBeSolid(outputs iotago.OutputIDs, clt models.Client, maxGoroutines int) (allSolid bool) { - wg := sync.WaitGroup{} - semaphore := make(chan bool, maxGoroutines) - allSolid = true - - for _, outID := range outputs { - wg.Add(1) - go func(outID iotago.OutputID) { - defer wg.Done() - semaphore <- true - defer func() { - <-semaphore - }() - err := o.AwaitOutputToBeSolid(outID, clt, waitForSolidification) - if err != nil { - allSolid = false - return - } - }(outID) - } - wg.Wait() - - return -} diff --git a/evilwallet/utils.go b/evilwallet/utils.go index 733d869..fe601eb 100644 --- a/evilwallet/utils.go +++ b/evilwallet/utils.go @@ -2,8 +2,6 @@ package evilwallet import iotago "github.com/iotaledger/iota.go/v4" -// region utxo/tx realted functions //////////////////////////////////////////////////////////////////////////////////////////// - // SplitBalanceEqually splits the balance equally between `splitNumber` outputs. func SplitBalanceEqually(splitNumber int, balance iotago.BaseToken) []iotago.BaseToken { outputBalances := make([]iotago.BaseToken, 0) diff --git a/evilwallet/wallets.go b/evilwallet/wallets.go index 2ec32a9..df99d7c 100644 --- a/evilwallet/wallets.go +++ b/evilwallet/wallets.go @@ -12,9 +12,8 @@ type walletID int type ( // WalletType is the type of the wallet. - //nolint:revive WalletType int8 - //nolint:revive + WalletStatus int8 ) diff --git a/identity/config.go b/identity/config.go deleted file mode 100644 index 4529b50..0000000 --- a/identity/config.go +++ /dev/null @@ -1,72 +0,0 @@ -package identity - -import ( - "encoding/json" - "fmt" - "os" -) - -type Params map[string]Identities -type Identities map[string]privKeyURLPair -type privKeyURLPair [2]string - -var Config = Params{} - -var identityConfigJSON = `{ - "docker": { - "validator-1": [ - "8q491c3YWjbPwLmF2WD95YmCgh61j2kenCKHfGfByoWi", - "http://localhost:8080" - ], - "validator-2": [ - "4ata8GcTRMJ5sSv2jQJWmSYYTHct748p3tXmCFYm7wjA", - "http://localhost:8070" - ], - "validator-3": [ - "3YX6e7AL28hHihZewKdq6CMkEYVsTJBLgRiprUNiNq5E", - "http://localhost:8090" - ] - } -}` - -func LoadIdentity(networkName, alias string) (privKey, url string) { - fmt.Println("Loading identity", alias, "for network", networkName) - if networkIdentities, exists := Config[networkName]; exists { - if keyURLPair, ok := networkIdentities[alias]; ok { - privateKey := keyURLPair[0] - urlAPI := keyURLPair[1] - fmt.Println("Loaded identity", alias, "API url:", url, "for network", networkName, "...DONE") - - return privateKey, urlAPI - } - - return "", "" - } - - return "", "" -} - -func LoadConfig() Params { - // open config file - fname := "keys-config.json" - file, err := os.Open(fname) - if err != nil { - if !os.IsNotExist(err) { - panic(err) - } - if err = os.WriteFile(fname, []byte(identityConfigJSON), 0o600); err != nil { - panic(err) - } - } - defer file.Close() - // decode config file - fbytes, err := os.ReadFile(fname) - if err != nil { - panic(err) - } - if err = json.Unmarshal(fbytes, &Config); err != nil { - panic(err) - } - - return Config -} diff --git a/interactive/interactive.go b/interactive/interactive.go index b2166f3..eff586c 100644 --- a/interactive/interactive.go +++ b/interactive/interactive.go @@ -40,7 +40,7 @@ var ( minSpamOutputs int ) -type InteractiveConfig struct { +type Config struct { //nolint:tagliatelle WebAPI []string `json:"webAPI"` Rate int `json:"rate"` @@ -71,7 +71,7 @@ var configJSON = fmt.Sprintf(`{ "useRateSetter": true }`, spammer.TypeTx) -var defaultConfig = InteractiveConfig{ +var defaultConfig = Config{ clientURLs: map[string]types.Empty{ "http://localhost:8080": types.Void, "http://localhost:8090": types.Void, @@ -202,7 +202,7 @@ type Mode struct { preparingFunds bool - Config InteractiveConfig + Config Config blkSent *atomic.Uint64 txSent *atomic.Uint64 scenariosSent *atomic.Uint64 @@ -821,7 +821,7 @@ var ( ) type SpammerLog struct { - spamDetails []InteractiveConfig + spamDetails []Config spamStartTime []time.Time spamStopTime []time.Time mu syncutils.Mutex @@ -829,13 +829,13 @@ type SpammerLog struct { func NewSpammerLog() *SpammerLog { return &SpammerLog{ - spamDetails: make([]InteractiveConfig, 0), + spamDetails: make([]Config, 0), spamStartTime: make([]time.Time, 0), spamStopTime: make([]time.Time, 0), } } -func (s *SpammerLog) SpamDetails(spamID int) *InteractiveConfig { +func (s *SpammerLog) SpamDetails(spamID int) *Config { return &s.spamDetails[spamID] } @@ -843,7 +843,7 @@ func (s *SpammerLog) StartTime(spamID int) time.Time { return s.spamStartTime[spamID] } -func (s *SpammerLog) AddSpam(config InteractiveConfig) (spamID int) { +func (s *SpammerLog) AddSpam(config Config) (spamID int) { s.mu.Lock() defer s.mu.Unlock() @@ -870,13 +870,13 @@ func (s *SpammerLog) LogHistory(lastLines int, writer io.Writer) { defer s.mu.Unlock() w := newTabWriter(writer) - fmt.Fprintln(w, historyHeader) + _, _ = 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), + _, _ = 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() @@ -887,10 +887,10 @@ func (s *SpammerLog) LogSelected(lines []int, writer io.Writer) { defer s.mu.Unlock() w := newTabWriter(writer) - fmt.Fprintln(w, historyHeader) + _, _ = 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), + _, _ = 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() diff --git a/main.go b/main.go index c4a3187..a3dbf7a 100644 --- a/main.go +++ b/main.go @@ -15,22 +15,29 @@ var ( optionFlagSet = flag.NewFlagSet("script flag set", flag.ExitOnError) ) +const ( + ScriptInteractive = "interactive" + ScriptSpammer = "spammer" + ScriptAccounts = "accounts" +) + func main() { help := parseFlags() if help { - fmt.Println("Usage of the Evil Spammer tool, provide the first argument for the selected mode:\n" + - "'interactive' - enters the interactive mode.\n" + - "'basic' - can be parametrized with additional flags to run one time spammer. Run 'evil-wallet basic -h' for the list of possible flags.\n" + - "'accounts' - tool for account creation and transition. Run 'evil-wallet accounts -h' for the list of possible flags.\n" + - "'quick' - runs simple stress test: tx spam -> blk spam -> ds spam. Run 'evil-wallet quick -h' for the list of possible flags.") + fmt.Printf("Usage of the Evil Spammer tool, provide the first argument for the selected mode:\n"+ + "'%s' - enters the interactive mode.\n"+ + "'%s' - can be parametrized with additional flags to run one time spammer. Run 'evil-wallet basic -h' for the list of possible flags.\n"+ + "'%s' - tool for account creation and transition. Run 'evil-wallet accounts -h' for the list of possible flags.\n", + ScriptInteractive, ScriptSpammer, ScriptAccounts) return } // init account wallet var accWallet *accountwallet.AccountWallet var err error - if Script == "basic" || Script == "accounts" { + //nolint:all,goconst + if Script == ScriptSpammer || Script == ScriptAccounts { // read config here config := accountwallet.LoadConfiguration() // load wallet @@ -54,16 +61,12 @@ func main() { } // run selected test scenario switch Script { - case "interactive": + case ScriptInteractive: interactive.Run() - case "basic": + case ScriptSpammer: programs.CustomSpam(&customSpamParams, accWallet) - case "accounts": + case ScriptAccounts: accountsSubcommands(accWallet, accountsSubcommandsFlags) - case "quick": - programs.QuickTest(&quickTestParams) - // case SpammerTypeCommitments: - // CommitmentsSpam(&commitmentsSpamParams) default: log.Warnf("Unknown parameter for script, possible values: interactive, basic, accounts, quick") } @@ -75,27 +78,43 @@ func accountsSubcommands(wallet *accountwallet.AccountWallet, subcommands []acco } } +//nolint:all,forcetypassert func accountsSubcommand(wallet *accountwallet.AccountWallet, sub accountwallet.AccountSubcommands) { switch sub.Type() { case accountwallet.OperationCreateAccount: log.Infof("Run subcommand: %s, with parametetr set: %v", accountwallet.OperationCreateAccount.String(), sub) - params := sub.(*accountwallet.CreateAccountParams) + params, ok := sub.(*accountwallet.CreateAccountParams) + if !ok { + log.Errorf("Type assertion error: casting subcommand: %v", sub) + + return + } + accountID, err := wallet.CreateAccount(params) if err != nil { - log.Errorf("Error creating account: %v", err) + log.Errorf("Type assertion error: creating account: %v", err) return } + log.Infof("Created account %s with %d tokens", accountID, params.Amount) - case accountwallet.OperationDestroyAccound: - log.Infof("Run subcommand: %s, with parametetr set: %v", accountwallet.OperationDestroyAccound, sub) - params := sub.(*accountwallet.DestroyAccountParams) + + case accountwallet.OperationDestroyAccount: + log.Infof("Run subcommand: %s, with parametetr set: %v", accountwallet.OperationDestroyAccount, sub) + params, ok := sub.(*accountwallet.DestroyAccountParams) + if !ok { + log.Errorf("Type assertion error: casting subcommand: %v", sub) + + return + } + err := wallet.DestroyAccount(params) if err != nil { log.Errorf("Error destroying account: %v", err) return } + case accountwallet.OperationListAccounts: err := wallet.ListAccount() if err != nil { @@ -103,9 +122,16 @@ func accountsSubcommand(wallet *accountwallet.AccountWallet, sub accountwallet.A return } + case accountwallet.OperationAllotAccount: log.Infof("Run subcommand: %s, with parametetr set: %v", accountwallet.OperationAllotAccount, sub) - params := sub.(*accountwallet.AllotAccountParams) + params, ok := sub.(*accountwallet.AllotAccountParams) + if !ok { + log.Errorf("Type assertion error: casting subcommand: %v", sub) + + return + } + err := wallet.AllotToAccount(params) if err != nil { log.Errorf("Error allotting account: %v", err) diff --git a/models/connector.go b/models/connector.go index eb3a6cc..913e24a 100644 --- a/models/connector.go +++ b/models/connector.go @@ -180,7 +180,7 @@ type Client interface { PostBlock(block *iotago.ProtocolBlock) (iotago.BlockID, error) // PostData sends the given data (payload) by creating a block in the backend. PostData(data []byte) (blkID string, err error) - // GetTransactionState returns the AcceptanceState of a given transaction ID. + // GetBlockState returns the AcceptanceState of a given transaction ID. GetBlockState(txID iotago.TransactionID) (resp *apimodels.BlockMetadataResponse, err error) // GetOutput gets the output of a given outputID. GetOutput(outputID iotago.OutputID) iotago.Output diff --git a/parse.go b/parse.go index a8f3897..8887829 100644 --- a/parse.go +++ b/parse.go @@ -34,10 +34,6 @@ func parseFlags() (help bool) { splitedCmds := readSubcommandsAndFlagSets(subcommands) accountsSubcommandsFlags = parseAccountTestFlags(splitedCmds) - case "quick": - parseQuickTestFlags() - // case SpammerTypeCommitments: - // parseCommitmentsSpamFlags() } if Script == "help" || Script == "-h" || Script == "--help" { return true @@ -76,7 +72,6 @@ func parseBasicSpamFlags() { if *urls != "" { parsedUrls := parseCommaSepString(*urls) - quickTestParams.ClientURLs = parsedUrls customSpamParams.ClientURLs = parsedUrls } if *spamTypes != "" { @@ -119,27 +114,6 @@ func parseBasicSpamFlags() { } } -func parseQuickTestFlags() { - urls := optionFlagSet.String("urls", "", "API urls for clients used in test separated with commas") - rate := optionFlagSet.Int("rate", quickTestParams.Rate, "The spamming rate") - duration := optionFlagSet.Duration("duration", quickTestParams.Duration, "Duration of the spam. 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("tu", quickTestParams.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", quickTestParams.DelayBetweenConflicts, "delayBetweenConflicts - Time delay between conflicts in double spend spamming") - verifyLedger := optionFlagSet.Bool("verify", quickTestParams.VerifyLedger, "Set to true if verify ledger script should be run at the end of the test") - - parseOptionFlagSet(optionFlagSet) - - if *urls != "" { - parsedUrls := parseCommaSepString(*urls) - quickTestParams.ClientURLs = parsedUrls - } - quickTestParams.Rate = *rate - quickTestParams.Duration = *duration - quickTestParams.TimeUnit = *timeunit - quickTestParams.DelayBetweenConflicts = *delayBetweenConflicts - quickTestParams.VerifyLedger = *verifyLedger -} - // readSubcommandsAndFlagSets splits the subcommands on multiple flag sets. func readSubcommandsAndFlagSets(subcommands []string) [][]string { prevSplitIndex := 0 @@ -234,31 +208,31 @@ func parseAccountTestFlags(splitedCmds [][]string) []accountwallet.AccountSubcom func accountUsage() { fmt.Println("Usage for accounts [COMMAND] [FLAGS], multiple commands can be chained together.") fmt.Printf("COMMAND: %s\n", accountwallet.CmdNameCreateAccount) - parseCreateAccountFlags(nil) + _, _ = parseCreateAccountFlags(nil) fmt.Printf("COMMAND: %s\n", accountwallet.CmdNameConvertAccount) - parseConvertAccountFlags(nil) + _, _ = parseConvertAccountFlags(nil) fmt.Printf("COMMAND: %s\n", accountwallet.CmdNameDestroyAccount) - parseDestroyAccountFlags(nil) + _, _ = parseDestroyAccountFlags(nil) fmt.Printf("COMMAND: %s\n", accountwallet.CmdNameAllotAccount) - parseAllotAccountFlags(nil) + _, _ = parseAllotAccountFlags(nil) fmt.Printf("COMMAND: %s\n", accountwallet.CmdNameDelegateAccount) - parseDelegateAccountFlags(nil) + _, _ = parseDelegateAccountFlags(nil) fmt.Printf("COMMAND: %s\n", accountwallet.CmdNameStakeAccount) - parseStakeAccountFlags(nil) + _, _ = parseStakeAccountFlags(nil) } func parseCreateAccountFlags(subcommands []string) (*accountwallet.CreateAccountParams, error) { flagSet := flag.NewFlagSet("create", flag.ExitOnError) alias := flagSet.String("alias", "", "The alias name of new created account") - amount := flagSet.Int64("amount", 1000, "The amount to be transfered to the new account") + amount := flagSet.Int64("amount", 1000, "The amount to be transferred to the new account") noBif := flagSet.Bool("noBIF", false, "Create account without Block Issuer Feature, can only be set false no if implicit is false, as each account created implicitly needs to have BIF.") implicit := flagSet.Bool("implicit", false, "Create an implicit account") - transition := flagSet.Bool("transition", true, "Indicates if account should be transitioned to full acount if created with implicit address.") + transition := flagSet.Bool("transition", true, "Indicates if account should be transitioned to full account if created with implicit address.") if subcommands == nil { flagSet.Usage() @@ -282,7 +256,7 @@ func parseCreateAccountFlags(subcommands []string) (*accountwallet.CreateAccount log.Infof("Parsed flags: alias: %s, amount: %d, BIF: %t, implicit: %t, transition: %t", *alias, *amount, *noBif, *implicit, *transition) if !*implicit == *transition { - log.Info("WARN: Implict flag set to false, account will be created non-implicitly by Faucet, no need for transition, flag will be ignored") + log.Info("WARN: Implicit flag set to false, account will be created non-implicitly by Faucet, no need for transition, flag will be ignored") *transition = false } @@ -459,28 +433,6 @@ func parseUpdateAccountFlags(subcommands []string) (*accountwallet.UpdateAccount }, nil } -// func parseCommitmentsSpamFlags() { -// commitmentType := optionFlagSet.String("type", commitmentsSpamParams.CommitmentType, "Type of commitment spam. Possible values: 'latest' - valid commitment spam, 'random' - completely new, invalid cahin, 'fork' - forked chain, combine with 'forkAfter' parameter.") -// rate := optionFlagSet.Int("rate", commitmentsSpamParams.Rate, "Commitment spam rate") -// duration := optionFlagSet.Duration("duration", commitmentsSpamParams.Duration, "Duration of the spam. 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("tu", commitmentsSpamParams.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'.") -// networkAlias := optionFlagSet.String("network", commitmentsSpamParams.NetworkAlias, "Network alias for the test. Check your keys-config.json file for possible values.") -// identityAlias := optionFlagSet.String("spammerAlias", commitmentsSpamParams.SpammerAlias, "Identity alias for the node identity and its private keys that will be used to spam. Check your keys-config.json file for possible values.") -// validAlias := optionFlagSet.String("validAlias", commitmentsSpamParams.ValidAlias, "Identity alias for the honest node and its private keys, will be used to request valid commitment and block data. Check your keys-config.json file for possible values.") -// forkAfter := optionFlagSet.Int("forkAfter", commitmentsSpamParams.Rate, "Indicates how many slots after spammer startup should fork be placed in the created commitment chain. Works only for 'fork' commitment spam type.") - -// parseOptionFlagSet(optionFlagSet) - -// commitmentsSpamParams.CommitmentType = *commitmentType -// commitmentsSpamParams.Rate = *rate -// commitmentsSpamParams.Duration = *duration -// commitmentsSpamParams.TimeUnit = *timeUnit -// commitmentsSpamParams.NetworkAlias = *networkAlias -// commitmentsSpamParams.SpammerAlias = *identityAlias -// commitmentsSpamParams.ValidAlias = *validAlias -// commitmentsSpamParams.ForkAfter = *forkAfter -// } - func parseCommaSepString(urls string) []string { split := strings.Split(urls, ",") diff --git a/programs/commitments.go b/programs/commitments.go deleted file mode 100644 index 5083b85..0000000 --- a/programs/commitments.go +++ /dev/null @@ -1,41 +0,0 @@ -package programs - -// import ( -// "time" - -// "github.com/iotaledger/goshimmer/client/evilspammer" -// "github.com/iotaledger/goshimmer/tools/evil-spammer/identity" -// ) - -// type CommitmentsSpamParams struct { -// CommitmentType string -// Rate int -// Duration time.Duration -// TimeUnit time.Duration -// NetworkAlias string -// SpammerAlias string -// ValidAlias string -// ForkAfter int // optional, will be used only with CommitmentType = "fork" -// } - -// func CommitmentsSpam(params *CommitmentsSpamParams) { -// identity.LoadConfig() -// SpamCommitments(*params) -// } - -// func SpamCommitments(params CommitmentsSpamParams) { -// privateKey, urlAPI := identity.LoadIdentity(params.NetworkAlias, params.SpammerAlias) -// _, validAPI := identity.LoadIdentity(params.NetworkAlias, params.ValidAlias) -// options := []evilspammer.Options{ -// evilspammer.WithClientURL(urlAPI), -// evilspammer.WithValidClientURL(validAPI), -// evilspammer.WithSpamRate(params.Rate, params.TimeUnit), -// evilspammer.WithSpamDuration(params.Duration), -// evilspammer.WithSpammingFunc(evilspammer.CommitmentsSpammingFunction), -// evilspammer.WithIdentity(params.SpammerAlias, privateKey), -// evilspammer.WithCommitmentType(params.CommitmentType), -// evilspammer.WithForkAfter(params.ForkAfter), -// } -// spammer := evilspammer.NewSpammer(options...) -// spammer.Spam() -// } diff --git a/programs/quick-test.go b/programs/quick-test.go deleted file mode 100644 index bbd962f..0000000 --- a/programs/quick-test.go +++ /dev/null @@ -1,68 +0,0 @@ -package programs - -import ( - "time" - - "github.com/iotaledger/evil-tools/evilwallet" - "github.com/iotaledger/evil-tools/spammer" -) - -type QuickTestParams struct { - ClientURLs []string - Rate int - Duration time.Duration - TimeUnit time.Duration - DelayBetweenConflicts time.Duration - VerifyLedger bool - EnableRateSetter bool -} - -// QuickTest runs short spamming periods with stable mps. -func QuickTest(params *QuickTestParams) { - evilWallet := evilwallet.NewEvilWallet(evilwallet.WithClients(params.ClientURLs...)) - counter := spammer.NewErrorCount() - log.Info("Starting quick test") - - nWallets := 2 * spammer.BigWalletsNeeded(params.Rate, params.TimeUnit, params.Duration) - - log.Info("Start preparing funds") - evilWallet.RequestFreshBigFaucetWallets(nWallets) - - // define spammers - baseOptions := []spammer.Options{ - spammer.WithSpamRate(params.Rate, params.TimeUnit), - spammer.WithSpamDuration(params.Duration), - spammer.WithErrorCounter(counter), - spammer.WithEvilWallet(evilWallet), - } - - //nolint:gocritic // we want a copy here - blkOptions := append(baseOptions, - spammer.WithSpammingFunc(spammer.DataSpammingFunction), - ) - - dsScenario := evilwallet.NewEvilScenario( - evilwallet.WithScenarioCustomConflicts(evilwallet.NSpendBatch(2)), - ) - - //nolint:gocritic // we want a copy here - dsOptions := append(baseOptions, - spammer.WithEvilScenario(dsScenario), - ) - - blkSpammer := spammer.NewSpammer(blkOptions...) - txSpammer := spammer.NewSpammer(baseOptions...) - dsSpammer := spammer.NewSpammer(dsOptions...) - - // start test - txSpammer.Spam() - time.Sleep(5 * time.Second) - - blkSpammer.Spam() - time.Sleep(5 * time.Second) - - dsSpammer.Spam() - - log.Info(counter.GetErrorsSummary()) - log.Info("Quick Test finished") -} diff --git a/programs/spammers.go b/programs/spammers.go index 9a69702..0d2d6a1 100644 --- a/programs/spammers.go +++ b/programs/spammers.go @@ -65,14 +65,9 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet } s.Spam() }(i) - case spammer.TypeCommitments: - wg.Add(1) - go func() { - defer wg.Done() - }() case spammer.TypeAccounts: wg.Add(1) - go func() { + go func(i int) { defer wg.Done() s := SpamAccounts(w, params.Rates[i], params.TimeUnit, params.Durations[i], params.EnableRateSetter, params.AccountAlias) @@ -80,7 +75,7 @@ func CustomSpam(params *CustomSpamParams, accWallet *accountwallet.AccountWallet return } s.Spam() - }() + }(i) default: log.Warn("Spamming type not recognized. Try one of following: tx, ds, blk, custom, commitments") diff --git a/spammer/clock.go b/spammer/clock.go deleted file mode 100644 index 4c3a4f0..0000000 --- a/spammer/clock.go +++ /dev/null @@ -1,76 +0,0 @@ -package spammer - -// import ( -// "time" - -// iotago "github.com/iotaledger/iota.go/v4" -// "github.com/iotaledger/evil-tools/wallet" -// ) - -// // region ClockSync //////////////evilspammerpkg///////////////////////////////////////////////////////////////////////////////// - -// // ClockSync is used to synchronize with connected nodes. -// type ClockSync struct { -// LatestCommittedSlotClock *SlotClock - -// syncTicker *time.Ticker -// clt wallet.Client -// } - -// func NewClockSync(slotDuration time.Duration, syncInterval time.Duration, clientList wallet.Client) *ClockSync { -// updateTicker := time.NewTicker(syncInterval) -// return &ClockSync{ -// LatestCommittedSlotClock: &SlotClock{slotDuration: slotDuration}, - -// syncTicker: updateTicker, -// clt: clientList, -// } -// } - -// // Start starts the clock synchronization in the background after the first sync is done.. -// func (c *ClockSync) Start() { -// c.Synchronize() -// go func() { -// for range c.syncTicker.C { -// c.Synchronize() -// } -// }() -// } - -// func (c *ClockSync) Shutdown() { -// c.syncTicker.Stop() -// } - -// func (c *ClockSync) Synchronize() { -// si, err := c.clt.GetLatestCommittedSlot() -// if err != nil { -// return -// } -// c.LatestCommittedSlotClock.Update(si) -// } - -// // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////// - -// // region SlotClock /////////////////////////////////////////////////////////////////////////////////////////////// - -// type SlotClock struct { -// lastUpdated time.Time -// updatedSlot slot.Index - -// slotDuration time.Duration -// } - -// func (c *SlotClock) Update(value slot.Index) { -// c.lastUpdated = time.Now() -// c.updatedSlot = value -// } - -// func (c *SlotClock) Get() slot.Index { -// return c.updatedSlot -// } - -// func (c *SlotClock) GetRelative() slot.Index { -// return c.updatedSlot + slot.Index(time.Since(c.lastUpdated)/c.slotDuration) -// } - -// // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/spammer/commitmentmanager.go b/spammer/commitmentmanager.go deleted file mode 100644 index 3d99755..0000000 --- a/spammer/commitmentmanager.go +++ /dev/null @@ -1,245 +0,0 @@ -package spammer - -// import ( -// "crypto/sha256" -// "math/rand" -// "time" - -// "github.com/iotaledger/hive.go/core/slot" -// "github.com/iotaledger/evil-tools/wallet" -// iotago "github.com/iotaledger/iota.go/v4" - -// "github.com/pkg/errors" -// ) - -// type CommitmentManagerParams struct { -// CommitmentType string -// ValidClientURL string -// ParentRefsCount int -// ClockResyncTime time.Duration -// GenesisTime time.Time -// SlotDuration time.Duration - -// OptionalForkAfter int -// } -// type CommitmentManager struct { -// Params *CommitmentManagerParams -// // we store here only the valid commitments to not request them again through API -// validChain map[slot.Index]*iotago.Commitment -// // commitments used to spam -// commitmentChain map[slot.Index]*iotago.Commitment - -// initiationSlot slot.Index -// forkIndex slot.Index -// latestCommitted slot.Index - -// clockSync *ClockSync -// validClient wallet.Client - -// log Logger -// } - -// func NewCommitmentManager() *CommitmentManager { -// return &CommitmentManager{ -// Params: &CommitmentManagerParams{ -// ParentRefsCount: 2, -// ClockResyncTime: 30 * time.Second, -// GenesisTime: time.Now(), -// SlotDuration: 5 * time.Second, -// }, -// validChain: make(map[slot.Index]*iotago.Commitment), -// commitmentChain: make(map[slot.Index]*iotago.Commitment), -// } -// } - -// func (c *CommitmentManager) Setup(l Logger) { -// c.log = l - -// c.log.Infof("Commitment Manager will be based on the valid client: %s", c.Params.ValidClientURL) -// c.validClient = wallet.NewWebClient(c.Params.ValidClientURL) -// c.setupTimeParams(c.validClient) - -// c.clockSync = NewClockSync(c.Params.SlotDuration, c.Params.ClockResyncTime, c.validClient) -// c.clockSync.Start() - -// c.setupForkingPoint() -// c.setupInitCommitment() -// } - -// // SetupInitCommitment sets the initiation commitment which is the current valid commitment requested from validClient. -// func (c *CommitmentManager) setupInitCommitment() { -// c.initiationSlot = c.clockSync.LatestCommittedSlotClock.Get() -// comm, err := c.getValidCommitment(c.initiationSlot) -// if err != nil { -// panic(errors.Wrapf(err, "failed to get initiation commitment")) -// } -// c.commitmentChain[comm.Slot()] = comm -// c.latestCommitted = comm.Slot() -// } - -// // SetupTimeParams requests through API and sets the genesis time and slot duration for the commitment manager. -// func (c *CommitmentManager) setupTimeParams(clt wallet.Client) { -// genesisTime, slotDuration, err := clt.GetTimeProvider() -// if err != nil { -// panic(errors.Wrapf(err, "failed to get time provider for the commitment manager setup")) -// } -// c.Params.GenesisTime = genesisTime -// c.Params.SlotDuration = slotDuration -// } - -// func (c *CommitmentManager) SetCommitmentType(commitmentType string) { -// c.Params.CommitmentType = commitmentType -// } - -// func (c *CommitmentManager) SetForkAfter(forkAfter int) { -// c.Params.OptionalForkAfter = forkAfter -// } - -// // SetupForkingPoint sets the forking point for the commitment manager. It uses ForkAfter parameter so need to be called after params are read. -// func (c *CommitmentManager) setupForkingPoint() { -// c.forkIndex = c.clockSync.LatestCommittedSlotClock.Get() + slot.Index(c.Params.OptionalForkAfter) -// } - -// func (c *CommitmentManager) Shutdown() { -// c.clockSync.Shutdown() -// } - -// func (c *CommitmentManager) commit(comm *iotago.Commitment) { -// c.commitmentChain[comm.Slot()] = comm -// if comm.Slot() > c.latestCommitted { -// if comm.Slot()-c.latestCommitted != 1 { -// panic("next committed slot is not sequential, lastCommitted: " + c.latestCommitted.String() + " nextCommitted: " + comm.Slot().String()) -// } -// c.latestCommitted = comm.Slot() -// } -// } - -// func (c *CommitmentManager) getLatestCommitment() *iotago.Commitment { -// return c.commitmentChain[c.latestCommitted] -// } - -// // GenerateCommitment generates a commitment based on the commitment type provided in spam details. -// func (c *CommitmentManager) GenerateCommitment(clt wallet.Client) (*iotago.Commitment, slot.Index, error) { -// switch c.Params.CommitmentType { -// // todo refactor this to work with chainsA -// case "latest": -// comm, err := clt.GetLatestCommitment() -// if err != nil { -// return nil, 0, errors.Wrap(err, "failed to get latest commitment") -// } -// index, err := clt.GetLatestConfirmedIndex() -// if err != nil { -// return nil, 0, errors.Wrap(err, "failed to get latest confirmed index") -// } -// return comm, index, err -// case "random": -// slot := c.clockSync.LatestCommittedSlotClock.Get() -// newCommitment := randomCommitmentChain(slot) - -// return newCommitment, slot - 10, nil - -// case "fork": -// // it should request time periodically, and be relative -// slot := c.clockSync.LatestCommittedSlotClock.Get() -// // make sure chain is upto date to the forking point -// uptoSlot := c.forkIndex -// // get minimum -// if slot < c.forkIndex { -// uptoSlot = slot -// } -// err := c.updateChainWithValidCommitment(uptoSlot) -// if err != nil { -// return nil, 0, errors.Wrap(err, "failed to update chain with valid commitment") -// } -// if c.isAfterForkPoint(slot) { -// c.updateForkedChain(slot) -// } -// comm := c.getLatestCommitment() -// index, err := clt.GetLatestConfirmedIndex() -// if err != nil { -// return nil, 0, errors.Wrap(err, "failed to get latest confirmed index") -// } -// return comm, index - 1, nil -// } -// return nil, 0, nil -// } - -// func (c *CommitmentManager) isAfterForkPoint(slot slot.Index) bool { -// return c.forkIndex != 0 && slot > c.forkIndex -// } - -// // updateChainWithValidCommitment commits the chain up to the given slot with the valid commitments. -// func (c *CommitmentManager) updateChainWithValidCommitment(s slot.Index) error { -// for i := c.latestCommitted + 1; i <= s; i++ { -// comm, err := c.getValidCommitment(i) -// if err != nil { -// return errors.Wrapf(err, "failed to get valid commitment for slot %d", i) -// } -// c.commit(comm) -// } -// return nil -// } - -// func (c *CommitmentManager) updateForkedChain(slot slot.Index) { -// for i := c.latestCommitted + 1; i <= slot; i++ { -// comm, err := c.getForkedCommitment(i) -// if err != nil { -// panic(errors.Wrapf(err, "failed to get forked commitment for slot %d", i)) -// } -// c.commit(comm) -// } -// } - -// // getValidCommitment returns the valid commitment for the given slot if not exists it requests it from the node and update the validChain. -// func (c *CommitmentManager) getValidCommitment(slot slot.Index) (*commitment.Commitment, error) { -// if comm, ok := c.validChain[slot]; ok { -// return comm, nil -// } -// // if not requested before then get it from the node -// comm, err := c.validClient.GetCommitment(int(slot)) -// if err != nil { -// return nil, errors.Wrapf(err, "failed to get commitment for slot %d", slot) -// } -// c.validChain[slot] = comm - -// return comm, nil -// } - -// func (c *CommitmentManager) getForkedCommitment(slot slot.Index) (*commitment.Commitment, error) { -// validComm, err := c.getValidCommitment(slot) -// if err != nil { -// return nil, errors.Wrapf(err, "failed to get valid commitment for slot %d", slot) -// } -// prevComm := c.commitmentChain[slot-1] -// forkedComm := commitment.New( -// validComm.Slot(), -// prevComm.ID(), -// randomRoot(), -// validComm.CumulativeWeight(), -// ) -// return forkedComm, nil -// } - -// func randomCommitmentChain(currSlot slot.Index) *commitment.Commitment { -// chain := make([]*commitment.Commitment, currSlot+1) -// chain[0] = commitment.NewEmptyCommitment() -// for i := slot.Index(0); i < currSlot-1; i++ { -// prevComm := chain[i] -// newCommitment := commitment.New( -// i, -// prevComm.ID(), -// randomRoot(), -// 100, -// ) -// chain[i+1] = newCommitment -// } -// return chain[currSlot-1] -// } - -// func randomRoot() [32]byte { -// data := make([]byte, 10) -// for i := range data { -// data[i] = byte(rand.Intn(256)) -// } -// return sha256.Sum256(data) -// } diff --git a/spammer/errors.go b/spammer/errors.go index 4c056ff..0020f08 100644 --- a/spammer/errors.go +++ b/spammer/errors.go @@ -11,15 +11,10 @@ import ( var ( ErrFailPostBlock = ierrors.New("failed to post block") - ErrFailSendDataBlock = ierrors.New("failed to send a data block") - ErrFailGetReferences = ierrors.New("failed to get references") - ErrTransactionIsNil = ierrors.New("provided transaction is nil") ErrTransactionInvalid = ierrors.New("provided transaction is invalid") ErrPayloadIsNil = ierrors.New("provided payload is nil") ErrFailToPrepareBatch = ierrors.New("custom conflict batch could not be prepared") ErrInsufficientClients = ierrors.New("insufficient clients to send conflicts") - ErrInputsNotSolid = ierrors.New("not all inputs are solid") - ErrFailPrepareBlock = ierrors.New("failed to prepare block") ErrFailGetAccount = ierrors.New("failed to get account from the account wallet") ) diff --git a/spammer/options.go b/spammer/options.go index 66b115b..0d079f4 100644 --- a/spammer/options.go +++ b/spammer/options.go @@ -4,7 +4,6 @@ import ( "time" "github.com/iotaledger/evil-tools/evilwallet" - "github.com/iotaledger/evil-tools/models" ) type Options func(*Spammer) @@ -39,25 +38,11 @@ func WithSpamDuration(maxDuration time.Duration) Options { } } -// WithErrorCounter allows for setting an error counter object, if not provided a new instance will be created. -func WithErrorCounter(errCounter *ErrorCounter) Options { - return func(s *Spammer) { - s.ErrCounter = errCounter - } -} - -// WithLogTickerInterval allows for changing interval between progress spamming logs, default is 30s. -func WithLogTickerInterval(interval time.Duration) Options { - return func(s *Spammer) { - s.State.logTickTime = interval - } -} - // WithSpammingFunc sets core function of the spammer with spamming logic, needs to use done spammer's channel to communicate. // end of spamming and errors. Default one is the CustomConflictSpammingFunc. func WithSpammingFunc(spammerFunc func(s *Spammer)) Options { return func(s *Spammer) { - s.spamFunc = spammerFunc + s.spammingFunc = spammerFunc } } @@ -112,45 +97,6 @@ func WithTimeDelayForDoubleSpend(timeDelay time.Duration) Options { } } -// WithNumberOfSpends sets how many transactions should be created with the same input, e.g 3 for triple spend, -// 2 for double spend. For this to work user needs to make sure that there is enough number of clients. -func WithNumberOfSpends(n int) Options { - return func(s *Spammer) { - s.NumberOfSpends = n - } -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// region Spammer Commitment options /////////////////////////////////////////////////////////////////////////////////////////////////// - -func WithClientURL(clientURL string) Options { - return func(s *Spammer) { - s.Clients = models.NewWebClients([]string{clientURL}) - } -} - -// func WithValidClientURL(validClient string) Options { -// return func(s *Spammer) { -// s.CommitmentManager.Params.ValidClientURL = validClient -// } -// } - -// WithCommitmentType provides commitment type for the spammer, allowed types: fork, valid, random. Enables commitment spam and disables the wallet functionality. -// func WithCommitmentType(commitmentType string) Options { -// return func(s *Spammer) { -// s.SpamType = SpamCommitments -// s.CommitmentManager.SetCommitmentType(commitmentType) -// } -// } - -// WithForkAfter provides after how many slots from the spammer setup should fork bee created, this option can be used with CommitmentType: fork. -// func WithForkAfter(forkingAfter int) Options { -// return func(s *Spammer) { -// s.CommitmentManager.SetForkAfter(forkingAfter) -// } -// } - // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type SpamDetails struct { @@ -159,7 +105,3 @@ type SpamDetails struct { MaxDuration time.Duration MaxBatchesSent int } - -type CommitmentSpamDetails struct { - CommitmentType string -} diff --git a/spammer/spammer.go b/spammer/spammer.go index fea5eae..e62f9ae 100644 --- a/spammer/spammer.go +++ b/spammer/spammer.go @@ -18,18 +18,16 @@ import ( ) const ( - TypeBlock = "blk" - TypeTx = "tx" - TypeDs = "ds" - TypeCustom = "custom" - TypeCommitments = "commitments" - TypeAccounts = "accounts" + TypeBlock = "blk" + TypeTx = "tx" + TypeDs = "ds" + TypeCustom = "custom" + TypeAccounts = "accounts" ) // region Spammer ////////////////////////////////////////////////////////////////////////////////////////////////////// -//nolint:revive -type SpammerFunc func(*Spammer) +type SpammingFunc func(*Spammer) type State struct { spamTicker *time.Ticker @@ -46,7 +44,6 @@ type SpamType int const ( SpamEvilWallet SpamType = iota - SpamCommitments ) // Spammer is a utility object for new spammer creations, can be modified by passing options. @@ -69,9 +66,9 @@ type Spammer struct { api iotago.API // accessed from spamming functions - done chan bool - shutdown chan types.Empty - spamFunc SpammerFunc + done chan bool + shutdown chan types.Empty + spammingFunc SpammingFunc TimeDelayBetweenConflicts time.Duration NumberOfSpends int @@ -89,7 +86,7 @@ func NewSpammer(options ...Options) *Spammer { } s := &Spammer{ SpamDetails: &SpamDetails{}, - spamFunc: CustomConflictSpammingFunc, + spammingFunc: CustomConflictSpammingFunc, State: state, SpamType: SpamEvilWallet, EvilScenario: evilwallet.NewEvilScenario(), @@ -203,7 +200,7 @@ func (s *Spammer) Spam() { go func() { goroutineCount.Inc() defer goroutineCount.Dec() - s.spamFunc(s) + s.spammingFunc(s) }() } } @@ -255,6 +252,7 @@ func (s *Spammer) PrepareAndPostBlock(txData *models.PayloadIssuanceData, issuer return } + //nolint:all,forcetypassert signedTx := txData.Payload.(*iotago.SignedTransaction) txID, err := signedTx.Transaction.ID() diff --git a/spammer/spamming_functions.go b/spammer/spamming_functions.go index 9b9d61d..4062c7e 100644 --- a/spammer/spamming_functions.go +++ b/spammer/spamming_functions.go @@ -82,57 +82,3 @@ func AccountSpammingFunction(s *Spammer) { s.EvilWallet.ClearAliases(aliases) s.CheckIfAllSent() } - -// func CommitmentsSpammingFunction(s *Spammer) { -// clt := s.Clients.GetClient() -// p := payload.NewGenericDataPayload([]byte("SPAM")) -// payloadBytes, err := p.Bytes() -// if err != nil { -// s.ErrCounter.CountError(ErrFailToPrepareBatch) -// } -// parents, err := clt.GetReferences(payloadBytes, s.CommitmentManager.Params.ParentRefsCount) -// if err != nil { -// s.ErrCounter.CountError(ErrFailGetReferences) -// } -// localID := s.IdentityManager.GetIdentity() -// commitment, latestConfIndex, err := s.CommitmentManager.GenerateCommitment(clt) -// if err != nil { -// s.log.Debugf(errors.WithMessage(ErrFailToPrepareBatch, err.Error()).Error()) -// s.ErrCounter.CountError(errors.WithMessage(ErrFailToPrepareBatch, err.Error())) -// } -// block := models.NewBlock( -// models.WithParents(parents), -// models.WithIssuer(localID.PublicKey()), -// models.WithIssuingTime(time.Now()), -// models.WithPayload(p), -// models.WithLatestConfirmedSlot(latestConfIndex), -// models.WithCommitment(commitment), -// models.WithSignature(ed25519.EmptySignature), -// ) -// signature, err := wallet.SignBlock(block, localID) -// if err != nil { -// return -// } -// block.SetSignature(signature) -// timeProvider := slot.NewTimeProvider(s.CommitmentManager.Params.GenesisTime.Unix(), int64(s.CommitmentManager.Params.SlotDuration.Seconds())) -// if err = block.DetermineID(timeProvider); err != nil { -// s.ErrCounter.CountError(ErrFailPrepareBlock) -// } -// blockBytes, err := block.Bytes() -// if err != nil { -// s.ErrCounter.CountError(ErrFailPrepareBlock) -// } - -// blkID, err := clt.PostBlock(blockBytes) -// if err != nil { -// fmt.Println(err) -// s.ErrCounter.CountError(ErrFailSendDataBlock) -// } - -// count := s.State.txSent.Add(1) -// if count%int64(s.SpamDetails.Rate*4) == 0 { -// s.log.Debugf("Last sent block, ID: %s; %s blkCount: %d", blkID, commitment.ID().String(), count) -// } -// s.State.batchPrepared.Add(1) -// s.CheckIfAllSent() -// }