diff --git a/cmd/flag_loader/flag_loader.go b/cmd/flag_loader/flag_loader.go index 53417c135..f8d2e8bd6 100644 --- a/cmd/flag_loader/flag_loader.go +++ b/cmd/flag_loader/flag_loader.go @@ -3,6 +3,7 @@ package flag_loader import ( "fmt" "os" + "math/big" "github.com/spf13/cobra" ) @@ -12,6 +13,27 @@ const ( privateKeyFlagName, privateKeyEnvVar = "private-key", "PRIVATE_KEY" ) +type BigIntValue struct { + Val *big.Int +} + +func (b *BigIntValue) String() string { + // Return the decimal representation + return b.Val.String() +} + +func (b *BigIntValue) Set(s string) error { + // Parse the string in base 10 + if _, ok := b.Val.SetString(s, 10); !ok { + return fmt.Errorf("invalid big integer: %q", s) + } + return nil +} + +func (b *BigIntValue) Type() string { + return "big.Int" +} + func GetRpcUrlFlagValue(cmd *cobra.Command) *string { v, _ := getFlagValue(cmd, rpcUrlFlagName, rpcUrlEnvVar, false) return v diff --git a/cmd/fund/cmd.go b/cmd/fund/cmd.go index 8d70ab980..dba30cbf6 100644 --- a/cmd/fund/cmd.go +++ b/cmd/fund/cmd.go @@ -2,6 +2,7 @@ package fund import ( "errors" + "math/big" _ "embed" @@ -27,7 +28,7 @@ type cmdFundParams struct { WalletsNumber *uint64 UseHDDerivation *bool WalletAddresses *[]string - FundingAmountInWei *uint64 + FundingAmountInWei *big.Int OutputFile *string FunderAddress *string @@ -37,6 +38,7 @@ var ( //go:embed usage.md usage string params cmdFundParams + defaultFundingInWei = big.NewInt(50000000000000000) // 0.05 ETH ) // FundCmd represents the fund command. @@ -67,7 +69,9 @@ func init() { p.WalletsNumber = flagSet.Uint64P("number", "n", 10, "The number of wallets to fund") p.UseHDDerivation = flagSet.Bool("hd-derivation", true, "Derive wallets to fund from the private key in a deterministic way") p.WalletAddresses = flagSet.StringSlice("addresses", nil, "Comma-separated list of wallet addresses to fund") - p.FundingAmountInWei = flagSet.Uint64P("eth-amount", "a", 50000000000000000, "The amount of wei to send to each wallet") + p.FundingAmountInWei = defaultFundingInWei + flagSet.Var(&flag_loader.BigIntValue{Val: p.FundingAmountInWei }, "eth-amount", "The amount of wei to send to each wallet") + p.OutputFile = flagSet.StringP("file", "f", "wallets.json", "The output JSON file path for storing the addresses and private keys of funded wallets") // Marking flags as mutually exclusive @@ -98,7 +102,8 @@ func checkFlags() error { if params.WalletsNumber != nil && *params.WalletsNumber == 0 { return errors.New("the number of wallets to fund is set to zero") } - if params.FundingAmountInWei != nil && *params.FundingAmountInWei <= 1000000000 { + minValue := big.NewInt(1000000000) + if params.FundingAmountInWei != nil && params.FundingAmountInWei.Cmp(minValue) <= 0 { return errors.New("the funding amount must be greater than 1000000000") } if params.OutputFile != nil && *params.OutputFile == "" { diff --git a/cmd/fund/fund.go b/cmd/fund/fund.go index 06b4aa43d..9e2df5cb1 100644 --- a/cmd/fund/fund.go +++ b/cmd/fund/fund.go @@ -128,7 +128,7 @@ func deployOrInstantiateFunderContract(ctx context.Context, c *ethclient.Client, if *params.FunderAddress == "" { // Deploy the Funder contract. // Note: `fundingAmountInWei` reprensents the amount the Funder contract will send to each newly generated wallets. - fundingAmountInWei := new(big.Int).SetUint64(*params.FundingAmountInWei) + fundingAmountInWei := params.FundingAmountInWei contractAddress, _, _, err = funder.DeployFunder(tops, c, fundingAmountInWei) if err != nil { log.Error().Err(err).Msg("Unable to deploy Funder contract") diff --git a/cmd/loadtest/app.go b/cmd/loadtest/app.go index 40eca9d73..fcd5c42f3 100644 --- a/cmd/loadtest/app.go +++ b/cmd/loadtest/app.go @@ -18,6 +18,7 @@ import ( "golang.org/x/time/rate" ) + type ( blockSummary struct { Block *rpctypes.RawBlockResponse @@ -83,7 +84,7 @@ type ( StartNonce *uint64 GasPriceMultiplier *float64 SendingAddressCount *uint64 - AddressFundingAmount *uint64 + AddressFundingAmount *big.Int PreFundSendingAddresses *bool KeepFundedAmount *bool SendingAddressesFile *string @@ -164,6 +165,7 @@ var ( } randSrc *rand.Rand + defaultFunding = new(big.Int).SetUint64(1000000000000000000) // 1 ETH ) // LoadtestCmd represents the loadtest command @@ -245,7 +247,8 @@ func initFlags() { ltp.SendOnly = LoadtestCmd.PersistentFlags().Bool("send-only", false, "Send transactions and load without waiting for it to be mined.") ltp.BlobFeeCap = LoadtestCmd.Flags().Uint64("blob-fee-cap", 100000, "The blob fee cap, or the maximum blob fee per chunk, in Gwei.") ltp.SendingAddressCount = LoadtestCmd.Flags().Uint64("sending-address-count", 1, "The number of sending addresses to use. This is useful for avoiding pool account queue.") - ltp.AddressFundingAmount = LoadtestCmd.Flags().Uint64("address-funding-amount", 1000000000000000000, "The amount in wei to fund the sending addresses with.") + ltp.AddressFundingAmount = defaultFunding + LoadtestCmd.Flags().Var(&flag_loader.BigIntValue{Val: ltp.AddressFundingAmount},"address-funding-amount", "The amount in wei to fund the sending addresses with.") ltp.PreFundSendingAddresses = LoadtestCmd.Flags().Bool("pre-fund-sending-addresses", false, "If set to true, the sending addresses will be funded at the start of the execution, otherwise all addresses will be funded when used for the first time.") ltp.KeepFundedAmount = LoadtestCmd.Flags().Bool("keep-funded-amount", false, "If set to true, the funded amount will be kept in the sending addresses. Otherwise, the funded amount will be refunded back to the account used to fund the account.") ltp.SendingAddressesFile = LoadtestCmd.Flags().String("sending-addresses-file", "", "The file containing the sending addresses private keys, one per line. This is useful for avoiding pool account queue but also to keep the same sending addresses for different execution cycles.") diff --git a/cmd/loadtest/loadtest.go b/cmd/loadtest/loadtest.go index 1a00a05f2..241c3ec5a 100644 --- a/cmd/loadtest/loadtest.go +++ b/cmd/loadtest/loadtest.go @@ -331,10 +331,10 @@ func initializeLoadTestParams(ctx context.Context, c *ethclient.Client) error { randSrc = rand.New(rand.NewSource(*inputLoadTestParams.Seed)) // setup account pool - fundingAmount := *inputLoadTestParams.AddressFundingAmount + fundingAmount := inputLoadTestParams.AddressFundingAmount sendingAddressCount := *inputLoadTestParams.SendingAddressCount sendingAddressesFile := *inputLoadTestParams.SendingAddressesFile - accountPool, err = NewAccountPool(ctx, c, privateKey, big.NewInt(0).SetUint64(fundingAmount)) + accountPool, err = NewAccountPool(ctx, c, privateKey, fundingAmount) if err != nil { log.Error().Err(err).Msg("Unable to create account pool") return fmt.Errorf("unable to create account pool. %w", err) @@ -386,7 +386,7 @@ func initializeLoadTestParams(ctx context.Context, c *ethclient.Client) error { } preFundSendingAddresses := *inputLoadTestParams.PreFundSendingAddresses - if preFundSendingAddresses && *inputLoadTestParams.AddressFundingAmount > 0 { + if preFundSendingAddresses && inputLoadTestParams.AddressFundingAmount.Cmp(new(big.Int)) > 0 { err := accountPool.FundAccounts(ctx) if err != nil { log.Error().Err(err).Msg("Unable to fund sending addresses") @@ -885,7 +885,9 @@ func mainLoop(ctx context.Context, c *ethclient.Client, rpc *ethrpc.Client) erro default: log.Error().Str("mode", mode.String()).Msg("We've arrived at a load test mode that we don't recognize") } - recordSample(routineID, requestID, tErr, startReq, endReq, sendingTops.Nonce.Uint64()) + if !*inputLoadTestParams.SendOnly { + recordSample(routineID, requestID, tErr, startReq, endReq, sendingTops.Nonce.Uint64()) + } if tErr != nil { log.Error(). Int64("routineID", routineID). diff --git a/doc/polycli_fund.md b/doc/polycli_fund.md index cf26f351c..3937cf3fe 100644 --- a/doc/polycli_fund.md +++ b/doc/polycli_fund.md @@ -79,7 +79,7 @@ $ cast balance 0x5D8121cf716B70d3e345adB58157752304eED5C3 ```bash --addresses strings Comma-separated list of wallet addresses to fund --contract-address string The address of a pre-deployed Funder contract - -a, --eth-amount uint The amount of wei to send to each wallet (default 50000000000000000) + --eth-amount big.Int The amount of wei to send to each wallet (default 50000000000000000) -f, --file string The output JSON file path for storing the addresses and private keys of funded wallets (default "wallets.json") --hd-derivation Derive wallets to fund from the private key in a deterministic way (default true) -h, --help help for fund diff --git a/doc/polycli_loadtest.md b/doc/polycli_loadtest.md index 50f038c08..f2da329b9 100644 --- a/doc/polycli_loadtest.md +++ b/doc/polycli_loadtest.md @@ -104,7 +104,7 @@ The codebase has a contract that used for load testing. It's written in Solidity --adaptive-cycle-duration-seconds uint When using adaptive rate limiting, this flag controls how often we check the queue size and adjust the rates (default 10) --adaptive-rate-limit Enable AIMD-style congestion control to automatically adjust request rate --adaptive-rate-limit-increment uint When using adaptive rate limiting, this flag controls the size of the additive increases. (default 50) - --address-funding-amount uint The amount in wei to fund the sending addresses with. (default 1000000000000000000) + --address-funding-amount big.Int The amount in wei to fund the sending addresses with. (default 1000000000000000000) --batch-size uint Number of batches to perform at a time for receipt fetching. Default is 999 requests at a time. (default 999) --blob-fee-cap uint The blob fee cap, or the maximum blob fee per chunk, in Gwei. (default 100000) -b, --byte-count uint If we're in store mode, this controls how many bytes we'll try to store in our contract (default 1024)