Repository: celestiaorg/celestia-app

Issue:
Multiplexer v3.x embedded binary doesn't respect log level
## Problem

Multiplexer embedded v3.x binary doesn't appear to respect the log level specified via CLI or config. I ran this:

```
celestia-appd start --log-to-file celestia-app.log --log_level info
```

and my config.toml looks like this

```toml
# Output level for logging, including package level options
log_level = "info"
```

but in the log file I'm seeing debug logs. Example:

```
3:05AM DBG Read PacketMsg conn=MConn{88.198.70.23:11656} module=p2p packet={"channel_id":32,"eof":true,"data":"OgkI5vaQAxgBICs="} peer=17a1fd70609562ecb7cd10599e0a7d566d8b8699@88.198.70.23:11656
```

This is on the Mocha DevOps validator

Hints from issue comments:
@julienrbrt: ~~Flags aren't passed down to the multiplexer: https://github.com/celestiaorg/celestia-app/blob/858f9383f11156a4a254a09046668d9586723f75/cmd/celestia-appd/cmd/modify_root_command_multiplexer.go#L41-L52~~
~~This is related to https://github.com/celestiaorg/celestia-app/issues/4932 as well.
I have opened a PR to fix in on v4 however.~~

~~I am still thinking on how to properly pass down flags to the embedded binary, because you cannot actually pass down all the flags, as some may exist in the current but not on the latest embedded  (this is the reason it was hardcoded). This may require a slight redesign.~~@julienrbrt: Following up on the message above, the flags are correctly passed down via `GetStartArgs` on the multiplexer (directly using os.Args). This means when a flag is added on v4 start that do not exist on an embedded binary this may be a problem, but this isn't a problem today.

A design such as the following may be required later, but today it isn't needed.

```
$ celestia-appd start --force-no-bbr --embedded-args-file ~/downloads/embedded_args.json
```

```json
{
    "v3": [
        "--grpc.address=localhost:50051"
    ],
    "vX": [
        "--grpc.address=localhost:50051"
    ]
}
```@julienrbrt: It mainly looks like we have two sort of loggers, it is shown by running:

```sh
celestia-appd start --log-to-file celestia-app.log --log_level info --force-no-bbr --log_format json
```

The file will contain a mix of normal (debug) log lines and json log lines@julienrbrt: Ok, the other issue is simply on v3. v3 discards other log level flags https://github.com/celestiaorg/celestia-app/blob/v3.x/cmd/celestia-appd/cmd/root.go#L172 (like v4 did too before https://github.com/celestiaorg/celestia-app/pull/4970)@evan-forbes: > Ok, the other issue is simply on v3. v3 discards other log level flags

🤔 I'm missing something sorry, on v3 I can select the log level and its not ignored. that looks like it only gets hit when there is a flag to keep the logs to a file (not sure who uses this anymore and probably deprecate)@julienrbrt: > > Ok, the other issue is simply on v3. v3 discards other log level flags
> 
> 🤔 I'm missing something sorry, on v3 I can select the log level and its not ignored. that looks like it only gets hit when there is a flag to keep the logs to a file (not sure who uses this anymore and probably deprecate)

Yes that is what is happening.
When not using that flag, it uses the SDK logger, which parses the flags properly, and when it was using that flag, it wasn't (it was even using another logger). The PR fixes that for v3. The same bug was happening for v4 as well (except then it was using the same logger, but not parsing those extra flags either), hence the two PRs.

Solution patch:
diff --git a/.golangci.yml b/.golangci.yml
index 59be9b02..68389479 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,20 +1,41 @@
+version: "2"
 run:
-  timeout: 5m
   modules-download-mode: readonly
-
 linters:
   enable:
     - copyloopvar
-    - gofumpt
+    - gocritic
     - misspell
     - nakedret
-    - revive
     - prealloc
-    - stylecheck
+    - revive
+    - staticcheck
     - unconvert
     - gocritic
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
+  settings:
+    nakedret:
+      # Ban the use of naked returns as they decrease code readability
+      # Make an issue if func has more lines of code than this setting, and it has naked returns.
+      max-func-lines: 0 # Default: 30
+    staticcheck:
+      checks:
+        - all # Default configuration. See https://golangci-lint.run/usage/linters/#staticcheck
+        - -QF1008 # Disable QF1008 because it's not helpful.
 
-linters-settings:
-  nakedret:
-    # Ban the use of naked returns because they reduce code readability.
-    max-func-lines: 0 # override the default: 30
+formatters:
+  enable:
+    - gofumpt
+  exclusions:
+    # Sources are excluded if they contain lines like `autogenerated file`, `code generated`, `do not edit`. (e.g. .pb.go files)
+    generated: lax
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
diff --git a/app/export.go b/app/export.go
index a49df5b1..994bb353 100644
--- a/app/export.go
+++ b/app/export.go
@@ -67,13 +67,7 @@ func (app *App) getExportHeight(forZeroHeight bool) int64 {
 // genesis is a temporary feature which will be deprecated in favour of export
 // at a block height.
 func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) {
-	applyAllowedAddrs := false
-
-	// check if there is a allowed address list
-	if len(jailAllowedAddrs) > 0 {
-		applyAllowedAddrs = true
-	}
-
+	applyAllowedAddrs := len(jailAllowedAddrs) > 0
 	allowedAddrsMap := make(map[string]bool)
 
 	for _, addr := range jailAllowedAddrs {
diff --git a/cmd/celestia-appd/cmd/root.go b/cmd/celestia-appd/cmd/root.go
index 58300224..3c8f12eb 100644
--- a/cmd/celestia-appd/cmd/root.go
+++ b/cmd/celestia-appd/cmd/root.go
@@ -1,7 +1,10 @@
 package cmd
 
 import (
+	"fmt"
+	"io"
 	"os"
+	"strings"
 
 	"github.com/celestiaorg/celestia-app/v3/app"
 	"github.com/celestiaorg/celestia-app/v3/app/encoding"
@@ -20,10 +23,11 @@ import (
 	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
 	"github.com/cosmos/cosmos-sdk/x/crisis"
 	genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
+	"github.com/go-kit/log"
+	"github.com/rs/zerolog"
 	"github.com/spf13/cobra"
 	"github.com/tendermint/tendermint/cmd/cometbft/commands"
 	tmcli "github.com/tendermint/tendermint/libs/cli"
-	"github.com/tendermint/tendermint/libs/log"
 )
 
 const (
@@ -168,7 +172,27 @@ func replaceLogger(cmd *cobra.Command) error {
 		return err
 	}
 
-	sctx := server.GetServerContextFromCmd(cmd)
-	sctx.Logger = log.NewTMLogger(log.NewSyncWriter(file))
-	return server.SetCmdServerContext(cmd, sctx)
+	serverCtx := server.GetServerContextFromCmd(cmd)
+	logLvlStr := serverCtx.Viper.GetString(flags.FlagLogLevel)
+	logLvl, err := zerolog.ParseLevel(logLvlStr)
+	if err != nil {
+		return fmt.Errorf("failed to parse log level (%s): %w", logLvlStr, err)
+	}
+
+	var logWriter io.Writer
+	if strings.EqualFold(serverCtx.Viper.GetString(flags.FlagLogFormat), "plain") || strings.EqualFold(serverCtx.Viper.GetString(flags.FlagLogFormat), "text") {
+		logWriter = zerolog.ConsoleWriter{Out: log.NewSyncWriter(file), NoColor: true}
+	} else {
+		logWriter = log.NewSyncWriter(file)
+	}
+
+	serverCtx.Logger = &server.ZeroLogWrapper{
+		Logger: zerolog.New(logWriter).
+			Level(logLvl).
+			With().
+			Timestamp().
+			Logger(),
+	}
+
+	return server.SetCmdServerContext(cmd, serverCtx)
 }
diff --git a/pkg/da/data_availability_header.go b/pkg/da/data_availability_header.go
index 9f324815..4b14d1ad 100644
--- a/pkg/da/data_availability_header.go
+++ b/pkg/da/data_availability_header.go
@@ -203,8 +203,8 @@ func EmptySquareShares() []share.Share {
 
 // SquareSize is a copy of the function defined in the square package to avoid
 // a circular dependency. TODO deduplicate
-func SquareSize(len int) int {
-	return RoundUpPowerOfTwo(int(math.Ceil(math.Sqrt(float64(len)))))
+func SquareSize(length int) int {
+	return RoundUpPowerOfTwo(int(math.Ceil(math.Sqrt(float64(length)))))
 }
 
 // RoundUpPowerOfTwo returns the next power of two greater than or equal to input.
diff --git a/pkg/wrapper/README.md b/pkg/wrapper/README.md
index cacbd55d..db1f7b3b 100644
--- a/pkg/wrapper/README.md
+++ b/pkg/wrapper/README.md
@@ -78,7 +78,6 @@ One namespace ID is located in the first `NamespaceIDSize` bytes, while the othe
 - Namespaced Merkle tree specifications: <https://github.com/celestiaorg/nmt/blob/master/docs/spec/nmt.md>
 - Celestia original data square specification: <https://github.com/celestiaorg/celestia-app/blob/main/specs/src/data_structures.md#arranging-available-data-into-shares>
 - Celestia constants: <https://github.com/celestiaorg/celestia-app/blob/main/specs/src/consensus.md#constants>
-- Celestia reserved namespace IDs: <https://github.com/celestiaorg/celestia-app/blob/main/specs/src/consensus.md#reserved-namespace-ids>
 
 [nmtlink]: https://github.com/celestiaorg/nmt/blob/master/docs/spec/nmt.md
 [nmtwrapper-link]: https://github.com/celestiaorg/celestia-app/blob/main/pkg/wrapper/nmt_wrapper.go
diff --git a/specs/src/multisig.md b/specs/src/multisig.md
index 55ecf7f7..a8cdd47a 100644
--- a/specs/src/multisig.md
+++ b/specs/src/multisig.md
@@ -12,4 +12,4 @@ $ celestia-appd keys show multisig
   type: multi
 ```
 
-Please see the [Cosmos SDK docs](https://docs.cosmos.network/main/user/run-node/multisig-guide#step-by-step-guide-to-multisig-transactions) for more information on how to use multisig accounts.
+Please see the [Cosmos SDK docs](https://github.com/cosmos/cosmos-sdk-docs/blob/ee7ad5945788cc057b80b125b86f7ba54d194192/versioned_docs/version-0.47/user/run-node/07-multisig-guide.md#L5) for more information on how to use multisig accounts.
diff --git a/specs/src/state_machine_modules_v1.md b/specs/src/state_machine_modules_v1.md
index eef6d4df..6919ea12 100644
--- a/specs/src/state_machine_modules_v1.md
+++ b/specs/src/state_machine_modules_v1.md
@@ -5,9 +5,9 @@ The modules used in app version 1 are:
 ## `celestia-app` modules
 
 - [blob](https://github.com/celestiaorg/celestia-app/blob/main/x/blob/README.md)
-- [blobstream](https://github.com/celestiaorg/celestia-app/blob/main/x/blobstream/README.md)
+- [qgb](https://github.com/celestiaorg/celestia-app/tree/f02b041b93864c363c3c4d6fbd9c534451424e1c/x/qgb)
 - [mint](https://github.com/celestiaorg/celestia-app/blob/main/x/mint/README.md)
-- [paramfilter](https://github.com/celestiaorg/celestia-app/blob/main/x/paramfilter/README.md)
+- [paramfilter](https://github.com/celestiaorg/celestia-app/blob/f02b041b93864c363c3c4d6fbd9c534451424e1c/x/paramfilter/README.md)
 - [tokenfilter](https://github.com/celestiaorg/celestia-app/blob/main/x/tokenfilter/README.md)
 
 ## `cosmos-sdk` modules
diff --git a/specs/src/state_machine_modules_v2.md b/specs/src/state_machine_modules_v2.md
index 25fea494..2571ec92 100644
--- a/specs/src/state_machine_modules_v2.md
+++ b/specs/src/state_machine_modules_v2.md
@@ -7,7 +7,7 @@ The modules used in app version 2 are:
 - [blob](https://github.com/celestiaorg/celestia-app/blob/main/x/blob/README.md)
 - [minfee](https://github.com/celestiaorg/celestia-app/blob/main/x/minfee/README.md)
 - [mint](https://github.com/celestiaorg/celestia-app/blob/main/x/mint/README.md)
-- [paramfilter](https://github.com/celestiaorg/celestia-app/blob/main/x/paramfilter/README.md)
+- [paramfilter](https://github.com/celestiaorg/celestia-app/blob/0a7154538e6b47ca806e9f4b3fd9ff1581213099/x/paramfilter/README.md)
 - [signal](https://github.com/celestiaorg/celestia-app/blob/main/x/signal/README.md)
 - [tokenfilter](https://github.com/celestiaorg/celestia-app/blob/main/x/tokenfilter/README.md)
 
diff --git a/tools/blocktime/main.go b/tools/blocktime/main.go
index 661c4dad..579ff97a 100644
--- a/tools/blocktime/main.go
+++ b/tools/blocktime/main.go
@@ -89,7 +89,7 @@ func analyzeBlockTimes(times []time.Time) (float64, float64, float64, float64) {
 		if maxTime == 0 || diff > maxTime {
 			maxTime = diff
 		}
-		variance += math.Pow(averageTime-diff, 2)
+		variance += (averageTime - diff) * (averageTime - diff)
 	}
 	stddev := math.Sqrt(variance / float64(numberOfObservations))
 	return averageTime, minTime, maxTime, stddev
diff --git a/x/blob/ante/max_total_blob_size_ante.go b/x/blob/ante/max_total_blob_size_ante.go
index 3a9af081..5a2abb43 100644
--- a/x/blob/ante/max_total_blob_size_ante.go
+++ b/x/blob/ante/max_total_blob_size_ante.go
@@ -31,11 +31,11 @@ func (d MaxTotalBlobSizeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
 		return next(ctx, tx, simulate)
 	}
 
-	max := d.maxTotalBlobSize(ctx)
+	maximum := d.maxTotalBlobSize(ctx)
 	for _, m := range tx.GetMsgs() {
 		if pfb, ok := m.(*blobtypes.MsgPayForBlobs); ok {
-			if total := getTotal(pfb.BlobSizes); total > max {
-				return ctx, errors.Wrapf(blobtypes.ErrTotalBlobSizeTooLarge, "total blob size %d exceeds max %d", total, max)
+			if total := getTotal(pfb.BlobSizes); total > maximum {
+				return ctx, errors.Wrapf(blobtypes.ErrTotalBlobSizeTooLarge, "total blob size %d exceeds max %d", total, maximum)
 			}
 		}
 	}
diff --git a/x/blobstream/README.md b/x/blobstream/README.md
index 05627454..ab82258b 100644
--- a/x/blobstream/README.md
+++ b/x/blobstream/README.md
@@ -11,7 +11,7 @@ The Blobstream state machine is responsible for creating attestations which are
 
 ### Attestations types
 
-[Attestations](https://github.com/celestiaorg/celestia-app/blob/main/x/blobstream/types/attestation.go#L10-L18) are requests for signatures generated by the state machine during the `EndBlock` phase. They facilitate alignment between orchestrators and relayers on which data to sign, and when to relay it.
+[Attestations](https://github.com/celestiaorg/celestia-app/blob/0a7154538e6b47ca806e9f4b3fd9ff1581213099/x/blobstream/types/attestation.go#L10-L18) are requests for signatures generated by the state machine during the `EndBlock` phase. They facilitate alignment between orchestrators and relayers on which data to sign, and when to relay it.
 
 There are two types of attestations, [valsets](https://github.com/celestiaorg/celestia-app/blob/376a1d4c0f321f12ba78279d2bd34fc6cb5e6dc2/proto/celestia/qgb/v1/types.proto#L18-L33) and [data commitments](https://github.com/celestiaorg/celestia-app/blob/376a1d4c0f321f12ba78279d2bd34fc6cb5e6dc2/proto/celestia/qgb/v1/types.proto#L35-L55).
 
diff --git a/x/blobstream/overview.md b/x/blobstream/overview.md
index bfe07a59..181fa895 100644
--- a/x/blobstream/overview.md
+++ b/x/blobstream/overview.md
@@ -1,3 +1,4 @@
+<!-- markdown-link-check-disable -->
 # Overview
 
 Blobstream is a one way bridge from Celestia to EVM chains. It provides a way for rollups using Celestia for Data Availability (DA), and an EVM chain as a settlement layer, to prove on-chain that the rollup data was correctly posted to Celestia and verify fraud proofs otherwise. These types of rollups are discussed in the [Quantum Gravity Bridge: Secure Off-Chain Data Availability for Ethereum L2s with Celestia](https://blog.celestia.org/celestiums) blog post.
@@ -6,15 +7,15 @@ Blobstream implementation consists of three components: The [state machine](http
 
 ## [State machine](https://github.com/celestiaorg/celestia-app/tree/main/x/blobstream)
 
-The state machine is the `blobstream` module implementation. It is responsible for creating [attestations](https://github.com/celestiaorg/celestia-app/blob/main/x/blobstream/types/attestation.go#L10-L18) which are signed by [orchestrators](https://github.com/celestiaorg/orchestrator-relayer/blob/main/docs/orchestrator.md). Each Celestia validator is expected to also run an orchestrator. [Relayers](https://github.com/celestiaorg/orchestrator-relayer/blob/main/docs/relayer.md) periodically query the Celestia state for attestations and submit them to the Blobstream smart contract deployed on some EVM chain.
+The state machine is the `blobstream` module implementation. It is responsible for creating [attestations](https://github.com/celestiaorg/celestia-app/blob/0a7154538e6b47ca806e9f4b3fd9ff1581213099/x/blobstream/types/attestation.go#L10-L18) which are signed by [orchestrators](https://github.com/celestiaorg/orchestrator-relayer/blob/main/docs/orchestrator.md). Each Celestia validator is expected to also run an orchestrator. [Relayers](https://github.com/celestiaorg/orchestrator-relayer/blob/main/docs/relayer.md) periodically query the Celestia state for attestations and submit them to the Blobstream smart contract deployed on some EVM chain.
 
-There are two types of [attestations](https://github.com/celestiaorg/celestia-app/blob/main/x/blobstream/types/attestation.go#L10-L18): [valsets](https://github.com/celestiaorg/celestia-app/blob/376a1d4c0f321f12ba78279d2bd34fc6cb5e6dc2/proto/celestia/qgb/v1/types.proto#L18-L33) and [data commitments](https://github.com/celestiaorg/celestia-app/blob/376a1d4c0f321f12ba78279d2bd34fc6cb5e6dc2/proto/celestia/qgb/v1/types.proto#L35-L55).
+There are two types of [attestations](https://github.com/celestiaorg/celestia-app/blob/0a7154538e6b47ca806e9f4b3fd9ff1581213099/x/blobstream/types/attestation.go#L10-L18): [valsets](https://github.com/celestiaorg/celestia-app/blob/376a1d4c0f321f12ba78279d2bd34fc6cb5e6dc2/proto/celestia/qgb/v1/types.proto#L18-L33) and [data commitments](https://github.com/celestiaorg/celestia-app/blob/376a1d4c0f321f12ba78279d2bd34fc6cb5e6dc2/proto/celestia/qgb/v1/types.proto#L35-L55).
 
 All attestations have a [`nonce`](https://github.com/celestiaorg/celestia-app/blob/8ae6a84b2c99e55625bbe99f70db1e5a985c9675/x/qgb/types/attestation.go#L16) field that defines the order in which the attestations are generated. This nonce is stored in the Blobstream smart contract as per [ADR-004](https://github.com/celestiaorg/celestia-app/blob/main/docs/architecture/adr-004-qgb-relayer-security.md#decision), and is used to order attestation submissions on the EVM chain.
 
-### [Valsets](https://github.com/celestiaorg/celestia-app/tree/main/x/blobstream#valsets)
+### [Valsets](https://github.com/celestiaorg/celestia-app/blob/0a7154538e6b47ca806e9f4b3fd9ff1581213099/x/blobstream/README.md?plain=1#L18)
 
-A [valset](https://github.com/celestiaorg/celestia-app/tree/main/x/blobstream#valsets) represents a validator set snapshot. It contains a list of validators' EVM addresses along with their [Blobstream staking power](https://github.com/celestiaorg/celestia-app/tree/main/x/blobstream#validator-power-normalization). It enables the Blobstream smart contract to track the state of the Celestia validator set. This is necessary so that the Blobstream smart contract can determine when a 2/3 threshold has signed that a particular data hash has been made available on Celestia.
+A [valset](https://github.com/celestiaorg/celestia-app/blob/0a7154538e6b47ca806e9f4b3fd9ff1581213099/x/blobstream/README.md?plain=1#L18) represents a validator set snapshot. It contains a list of validators' EVM addresses along with their [Blobstream staking power](https://github.com/celestiaorg/celestia-app/tree/main/x/blobstream#validator-power-normalization). It enables the Blobstream smart contract to track the state of the Celestia validator set. This is necessary so that the Blobstream smart contract can determine when a 2/3 threshold has signed that a particular data hash has been made available on Celestia.
 
 A valset is [generated](https://github.com/celestiaorg/celestia-app/tree/main/x/blobstream#valset-handler) inside the state machine. It is then queried, signed, and submitted to the [Blobstream P2P network](https://github.com/celestiaorg/orchestrator-relayer/pull/66) by orchestrators. After more than 2/3rds of the Celestia validator set have submitted their signatures, [relayers](https://github.com/celestiaorg/orchestrator-relayer/blob/main/docs/relayer.md) relay the attestation to the Blobstream smart contract along with the signatures to be [verified](https://github.com/celestiaorg/quantum-gravity-bridge/blob/3cef3f5dfd37c3086fa40a6324f144595726dc16/src/QuantumGravityBridge.sol#L172-L211) and eventually [stored](https://github.com/celestiaorg/quantum-gravity-bridge/blob/3cef3f5dfd37c3086fa40a6324f144595726dc16/src/QuantumGravityBridge.sol#L266-L268).
 



Test patch:
diff --git a/test/txsim/blob.go b/test/txsim/blob.go
index 3fcef2fa..c5433d3d 100644
--- a/test/txsim/blob.go
+++ b/test/txsim/blob.go
@@ -123,8 +123,8 @@ type Range struct {
 	Max int
 }
 
-func NewRange(min, max int) Range {
-	return Range{Min: min, Max: max}
+func NewRange(minimum, maximum int) Range {
+	return Range{Min: minimum, Max: maximum}
 }
 
 // Rand returns a random number between min (inclusive) and max (exclusive).
diff --git a/test/util/common.go b/test/util/common.go
index 3b0cfcea..8518f254 100644
--- a/test/util/common.go
+++ b/test/util/common.go
@@ -289,12 +289,13 @@ func CreateTestEnvWithoutBlobstreamKeysInit(t *testing.T) TestInput {
 	for name, permissions := range moduleAccountPermissions {
 		moduleAccount := authtypes.NewEmptyModuleAccount(name, permissions...)
 		totalSupply := sdk.NewCoins(sdk.NewInt64Coin("stake", 100000000))
-		if name == stakingtypes.NotBondedPoolName {
+		switch name {
+		case stakingtypes.NotBondedPoolName:
 			err = bankKeeper.MintCoins(ctx, blobstreamtypes.ModuleName, totalSupply)
 			require.NoError(t, err)
 			err = bankKeeper.SendCoinsFromModuleToModule(ctx, blobstreamtypes.ModuleName, moduleAccount.Name, totalSupply)
 			require.NoError(t, err)
-		} else if name == distrtypes.ModuleName {
+		case distrtypes.ModuleName:
 			// some big pot to pay out
 			amt := sdk.NewCoins(sdk.NewInt64Coin("stake", 500000))
 			err = bankKeeper.MintCoins(ctx, blobstreamtypes.ModuleName, amt)
diff --git a/x/mint/types/minter_test.go b/x/mint/types/minter_test.go
index bafe1989..f6d989ba 100644
--- a/x/mint/types/minter_test.go
+++ b/x/mint/types/minter_test.go
@@ -156,14 +156,14 @@ func TestCalculateBlockProvisionError(t *testing.T) {
 }
 
 func randomBlockInterval() time.Duration {
-	min := (14 * time.Second).Nanoseconds()
-	max := (16 * time.Second).Nanoseconds()
-	return time.Duration(randInRange(min, max))
+	minimum := (14 * time.Second).Nanoseconds()
+	maximum := (16 * time.Second).Nanoseconds()
+	return time.Duration(randInRange(minimum, maximum))
 }
 
-// randInRange returns a random number in the range (min, max) inclusive.
-func randInRange(min int64, max int64) int64 {
-	return rand.Int63n(max-min) + min
+// randInRange returns a random number in the range (minimum, maximum) inclusive.
+func randInRange(minimum int64, maximum int64) int64 {
+	return rand.Int63n(maximum-minimum) + minimum
 }
 
 func BenchmarkCalculateBlockProvision(b *testing.B) {