Repository: celestiaorg/celestia-app

Issue:
`make install` redownloads all embedded binaries each invocation
## Context

Currently on `main`, running `make install` multiple times will result in re downloading the v3 embedded binaries even if they haven't changed

## Proposal

Skip downloading the v3 embedded binaries if they're already up to date

Hints from issue comments:

Solution patch:
diff --git a/Makefile b/Makefile
index 80c5687c..3b795c73 100644
--- a/Makefile
+++ b/Makefile
@@ -54,14 +54,41 @@ install-standalone: check-bbr
 	@go install $(BUILD_FLAGS) ./cmd/celestia-appd
 .PHONY: install-standalone
 
+define EMBED_BIN
+	if test -f internal/embedding/$$out; then \
+	  if [ -f internal/embedding/.embed_version_$$out ]; then \
+	    existing_version=$$(cat internal/embedding/.embed_version_$$out); \
+	    if [ "$$existing_version" = "$(CELESTIA_V3_VERSION)" ]; then \
+	      echo "Skipping download, existing correct version: $$out"; \
+	    else \
+	      echo "Version mismatch, re-downloading $$out"; \
+	      wget -q https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/$$url -O internal/embedding/$$out; \
+	      echo "$(CELESTIA_V3_VERSION)" > internal/embedding/.embed_version_$$out; \
+	    fi; \
+	  else \
+	    echo "No version file for $$out, re-downloading"; \
+	    wget -q https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/$$url -O internal/embedding/$$out; \
+	    echo "$(CELESTIA_V3_VERSION)" > internal/embedding/.embed_version_$$out; \
+	  fi; \
+	else \
+	  echo "Binary $$out not found, downloading"; \
+	  wget -q https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/$$url -O internal/embedding/$$out; \
+	  echo "$(CELESTIA_V3_VERSION)" > internal/embedding/.embed_version_$$out; \
+	fi
+endef
+
 ## install: Build and install the multiplexer version of celestia-appd into the $GOPATH/bin directory.
 # TODO: Improve logic here and in goreleaser to make it future proof and less expensive.
 install: check-bbr
-	@echo "--> Download embedded binaries for v3"
-	wget https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/celestia-app_Darwin_arm64.tar.gz -O internal/embedding/celestia-app_darwin_v3_arm64.tar.gz
-	wget https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/celestia-app_Linux_arm64.tar.gz -O internal/embedding/celestia-app_linux_v3_arm64.tar.gz
-	wget https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/celestia-app_Darwin_x86_64.tar.gz -O internal/embedding/celestia-app_darwin_v3_amd64.tar.gz
-	wget https://github.com/celestiaorg/celestia-app/releases/download/$(CELESTIA_V3_VERSION)/celestia-app_Linux_x86_64.tar.gz -O internal/embedding/celestia-app_linux_v3_amd64.tar.gz
+	@echo "--> Downloading embedded binaries for v3"
+	@for pair in \
+		"celestia-app_Darwin_arm64.tar.gz:celestia-app_darwin_v3_arm64.tar.gz" \
+		"celestia-app_Linux_arm64.tar.gz:celestia-app_linux_v3_arm64.tar.gz" \
+		"celestia-app_Darwin_x86_64.tar.gz:celestia-app_darwin_v3_amd64.tar.gz" \
+		"celestia-app_Linux_x86_64.tar.gz:celestia-app_linux_v3_amd64.tar.gz"; do \
+		url=$${pair%%:*}; out=$${pair##*:}; \
+		$(EMBED_BIN); \
+	done
 	@echo "--> Installing celestia-appd with multiplexer support"
 	@go install $(BUILD_FLAGS_MULTIPLEXER) ./cmd/celestia-appd
 .PHONY: install
diff --git a/README.md b/README.md
index 6d7ebe6d..c69c1e67 100644
--- a/README.md
+++ b/README.md
@@ -94,9 +94,9 @@ make bbr-enable
 
 ### Environment variables
 
-| Variable        | Explanation                                                       | Default value                                            | Required |
-|-----------------|-------------------------------------------------------------------|----------------------------------------------------------|----------|
-| `CELESTIA_HOME` | Where the application directory (`.celestia-app`) should be saved | [User home directory](https://pkg.go.dev/os#UserHomeDir) | Optional |
+| Variable            | Explanation                                  | Default value                                               | Required |
+|---------------------|----------------------------------------------|-------------------------------------------------------------|----------|
+| `CELESTIA_APP_HOME` | Where the application files should be saved. | [`$HOME/.celestia-appd`](https://pkg.go.dev/os#UserHomeDir) | Optional |
 
 ### Using celestia-appd
 
diff --git a/app/init.go b/app/init.go
index 0669240a..5527167d 100644
--- a/app/init.go
+++ b/app/init.go
@@ -8,7 +8,7 @@ import (
 
 // EnvPrefix is the environment variable prefix for celestia-appd.
 // Environment variables that Cobra reads must be prefixed with this value.
-const EnvPrefix = "CELESTIA"
+const EnvPrefix = "CELESTIA_APP"
 
 // Name is the name of the application.
 const Name = "celestia-app"
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 0256edb6..e7aa7929 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -54,7 +54,7 @@ FROM ${RUNTIME_IMAGE} AS runtime
 # Ref: https://github.com/hexops/dockerfile/blob/main/README.md#do-not-use-a-uid-below-10000
 ARG UID=10001
 ARG USER_NAME=celestia
-ENV CELESTIA_HOME=/home/${USER_NAME}
+ENV CELESTIA_APP_HOME=/home/${USER_NAME}/.celestia-appd
 # hadolint ignore=DL3018
 RUN apk update && apk add --no-cache \
     bash \
@@ -63,7 +63,7 @@ RUN apk update && apk add --no-cache \
     && adduser ${USER_NAME} \
     -D \
     -g ${USER_NAME} \
-    -h ${CELESTIA_HOME} \
+    -h ${CELESTIA_APP_HOME} \
     -s /sbin/nologin \
     -u ${UID}
 # Copy the celestia-appd binary from the builder into the final image.
@@ -73,7 +73,7 @@ COPY --chown=${USER_NAME}:${USER_NAME} docker/entrypoint.sh /opt/entrypoint.sh
 # Set the user to celestia.
 USER ${USER_NAME}
 # Set the working directory to the home directory.
-WORKDIR ${CELESTIA_HOME}
+WORKDIR ${CELESTIA_APP_HOME}
 # Expose ports:
 # 1317 is the default API server port.
 # 9090 is the default GRPC server port.
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
index 6f19ab21..cef8dc8a 100644
--- a/docker/entrypoint.sh
+++ b/docker/entrypoint.sh
@@ -3,10 +3,10 @@
 # This script creates the necessary files before starting celestia-appd
 
 # only create the priv_validator_state.json if it doesn't exist and the command is start
-if [[ $1 == "start" && ! -f ${CELESTIA_HOME}/data/priv_validator_state.json ]]
+if [[ $1 == "start" && ! -f ${CELESTIA_APP_HOME}/data/priv_validator_state.json ]]
 then
-    mkdir -p ${CELESTIA_HOME}/data
-    cat <<EOF > ${CELESTIA_HOME}/data/priv_validator_state.json
+    mkdir -p ${CELESTIA_APP_HOME}/data
+    cat <<EOF > ${CELESTIA_APP_HOME}/data/priv_validator_state.json
 {
   "height": "0",
   "round": 0,
diff --git a/docker/multiplexer.Dockerfile b/docker/multiplexer.Dockerfile
index 1302ebbf..5e3cb1a1 100644
--- a/docker/multiplexer.Dockerfile
+++ b/docker/multiplexer.Dockerfile
@@ -77,7 +77,7 @@ FROM ${RUNTIME_IMAGE} AS runtime
 # Ref: https://github.com/hexops/dockerfile/blob/main/README.md#do-not-use-a-uid-below-10000
 ARG UID=10001
 ARG USER_NAME=celestia
-ENV CELESTIA_HOME=/home/${USER_NAME}
+ENV CELESTIA_APP_HOME=/home/${USER_NAME}/.celestia-appd
 # hadolint ignore=DL3018
 RUN apk update && apk add --no-cache \
     bash \
@@ -86,7 +86,7 @@ RUN apk update && apk add --no-cache \
     && adduser ${USER_NAME} \
     -D \
     -g ${USER_NAME} \
-    -h ${CELESTIA_HOME} \
+    -h ${CELESTIA_APP_HOME} \
     -s /sbin/nologin \
     -u ${UID}
 # Copy the celestia-appd binary from the builder into the final image.
@@ -96,7 +96,7 @@ COPY --chown=${USER_NAME}:${USER_NAME} docker/entrypoint.sh /opt/entrypoint.sh
 # Set the user to celestia.
 USER ${USER_NAME}
 # Set the working directory to the home directory.
-WORKDIR ${CELESTIA_HOME}
+WORKDIR ${CELESTIA_APP_HOME}
 # Expose ports:
 # 1317 is the default API server port.
 # 9090 is the default GRPC server port.
diff --git a/docker/txsim/Dockerfile b/docker/txsim/Dockerfile
index a4150883..f577cb30 100644
--- a/docker/txsim/Dockerfile
+++ b/docker/txsim/Dockerfile
@@ -29,7 +29,7 @@ FROM docker.io/alpine:3.20
 ARG UID=10001
 ARG USER_NAME=celestia
 
-ENV CELESTIA_HOME=/home/${USER_NAME}
+ENV CELESTIA_APP_HOME=/home/${USER_NAME}/.celestia-appd
 
 # hadolint ignore=DL3018
 RUN apk update && apk add --no-cache \
@@ -40,7 +40,7 @@ RUN apk update && apk add --no-cache \
     && adduser ${USER_NAME} \
     -D \
     -g ${USER_NAME} \
-    -h ${CELESTIA_HOME} \
+    -h ${CELESTIA_APP_HOME} \
     -s /sbin/nologin \
     -u ${UID}
 
@@ -52,6 +52,6 @@ COPY --chown=${USER_NAME}:${USER_NAME} docker/txsim/entrypoint.sh /opt/entrypoin
 USER ${USER_NAME}
 
 # Set the working directory to the home directory.
-WORKDIR ${CELESTIA_HOME}
+WORKDIR ${CELESTIA_APP_HOME}
 
 ENTRYPOINT [ "/bin/bash", "/opt/entrypoint.sh" ]
diff --git a/docs/architecture/adr-006-non-interactive-defaults.md b/docs/architecture/adr-006-non-interactive-defaults.md
index 3ce0aff8..598c796e 100644
--- a/docs/architecture/adr-006-non-interactive-defaults.md
+++ b/docs/architecture/adr-006-non-interactive-defaults.md
@@ -47,7 +47,7 @@ Below is an example block that has been filled using the non-interactive default
 - `ns = 1`: The first namespace is put at the beginning of the messages space.
 - `ns = 2`: Starting at the largest power of 2 that is not larger than the message length or `k`.
 - `ns = 3`: Message spanning multiple rows. So, it will be at the beginning of a new row.
-- `ns  = 4`: Starting at the largest power of 2 that is not larger than the message length or `k`.
+- `ns = 4`: Starting at the largest power of 2 that is not larger than the message length or `k`.
 
 Not only does doing this allow for easy trust minimized message inclusion checks for specific messages by light clients, but also allows for the creation of message inclusion fraud proofs for all messages in the block. This is important to reduce the trust assumptions made by light clients.
 
diff --git a/go.mod b/go.mod
index 22ec6fe6..1e5c6a7b 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
 	cosmossdk.io/x/tx v0.13.8
 	cosmossdk.io/x/upgrade v0.1.4
 	github.com/bcp-innovations/hyperlane-cosmos v1.0.0
-	github.com/celestiaorg/celestia-app/multiplexer v0.1.0
+	github.com/celestiaorg/celestia-app/multiplexer v0.2.0
 	github.com/celestiaorg/go-square/v2 v2.2.0
 	github.com/celestiaorg/knuu v0.16.3
 	github.com/celestiaorg/nmt v0.23.0
diff --git a/go.sum b/go.sum
index e70d9a16..1b76c88b 100644
--- a/go.sum
+++ b/go.sum
@@ -348,8 +348,8 @@ github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFos
 github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
 github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7 h1:nxplQi8wrLMjhu260RuigXylC3pWoDu4OVumPHeojnk=
 github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7/go.mod h1:1EF5MfOxVf0WC51Gb7pJ6bcZxnXKNAf9pqWtjgPBAYc=
-github.com/celestiaorg/celestia-app/multiplexer v0.1.0 h1:VVPGFcP+omG90NW7r1wi/fEbpNOXgVFtGWkuQX0CCSY=
-github.com/celestiaorg/celestia-app/multiplexer v0.1.0/go.mod h1:H0hIPPJkoWUNXHsP6g8IC0nwiD5T3kzilLrGKE9L93U=
+github.com/celestiaorg/celestia-app/multiplexer v0.2.0 h1:72jRIzqWwcNntGmrKTNHg7AzudZCanHoG2LhVErdShw=
+github.com/celestiaorg/celestia-app/multiplexer v0.2.0/go.mod h1:H0hIPPJkoWUNXHsP6g8IC0nwiD5T3kzilLrGKE9L93U=
 github.com/celestiaorg/celestia-core v1.45.0-tm-v0.34.35 h1:T21AhezjcByAlWDHmiVbpg743Uqk/dqBzJkQsAnbQf8=
 github.com/celestiaorg/celestia-core v1.45.0-tm-v0.34.35/go.mod h1:fQ46s1hYFTGFBsHsuGsbxDZ720ZPQow5Iyqw+yErZSo=
 github.com/celestiaorg/celestia-core v1.53.0-tm-v0.38.17 h1:AHjnWwPoOFH5zr+aPqdWkF1CutP1ynVEOGOuW1/8iq8=
diff --git a/local_devnet/docker-compose.yml b/local_devnet/docker-compose.yml
index 1cf768d5..40dca1e4 100644
--- a/local_devnet/docker-compose.yml
+++ b/local_devnet/docker-compose.yml
@@ -39,7 +39,7 @@ services:
       - core0
     environment:
       - MONIKER=core1
-      - CELESTIA_HOME=/opt
+      - CELESTIA_APP_HOME=/opt
       - AMOUNT=5000000000utia
     entrypoint: [
       "/bin/bash"
@@ -68,7 +68,7 @@ services:
       - core0
     environment:
       - MONIKER=core2
-      - CELESTIA_HOME=/opt
+      - CELESTIA_APP_HOME=/opt
       - AMOUNT=5000000000utia
     entrypoint: [
       "/bin/bash"
@@ -97,7 +97,7 @@ services:
       - core0
     environment:
       - MONIKER=core3
-      - CELESTIA_HOME=/opt
+      - CELESTIA_APP_HOME=/opt
       - AMOUNT=5000000000utia
     entrypoint: [
       "/bin/bash"
diff --git a/local_devnet/scripts/init.sh b/local_devnet/scripts/init.sh
index c16be125..0b9841f0 100755
--- a/local_devnet/scripts/init.sh
+++ b/local_devnet/scripts/init.sh
@@ -5,21 +5,21 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
 PWD=$(pwd)
 
 if [ -z "$CELESTIA_BIN" ]; then echo "CELESTIA_BIN is not set. Make sure to run 'make install' before"; exit 1; fi
-CELESTIA_HOME=$($CELESTIA_BIN config home)
-if [ -d "$CELESTIA_HOME" ]; then rm -r $CELESTIA_HOME; fi
+CELESTIA_APP_HOME=$($CELESTIA_BIN config home)
+if [ -d "$CELESTIA_APP_HOME" ]; then rm -r $CELESTIA_APP_HOME; fi
 $CELESTIA_BIN config set client chain-id local_devnet
 $CELESTIA_BIN config set client keyring-backend test
 $CELESTIA_BIN config set app api.enable true
 $CELESTIA_BIN keys add alice
 
 if [ "$MULTIPLEXER" = "true" ]; then
-cd $SCRIPT_DIR; cp ../celestia-app/genesis_046.json $CELESTIA_HOME/config/genesis.json; cd $PWD # use local_devnet genesis
+cd $SCRIPT_DIR; cp ../celestia-app/genesis_046.json $CELESTIA_APP_HOME/config/genesis.json; cd $PWD # use local_devnet genesis
 $CELESTIA_BIN passthrough v3 add-genesis-account alice 5000000000utia --keyring-backend test
 $CELESTIA_BIN passthrough v3 gentx alice 1000000utia --fees 1utia --chain-id local_devnet
 $CELESTIA_BIN passthrough v3 collect-gentxs
 else
-cd $SCRIPT_DIR; cp ../celestia-app/genesis.json $CELESTIA_HOME/config/genesis.json; cd $PWD # use local_devnet genesis
+cd $SCRIPT_DIR; cp ../celestia-app/genesis.json $CELESTIA_APP_HOME/config/genesis.json; cd $PWD # use local_devnet genesis
 $CELESTIA_BIN genesis add-genesis-account alice 5000000000utia --keyring-backend test
 $CELESTIA_BIN genesis gentx alice 1000000utia --fees 1utia --chain-id local_devnet
 $CELESTIA_BIN genesis collect-gentxs
-fi
\ No newline at end of file
+fi
diff --git a/local_devnet/scripts/start_node_and_create_validator.sh b/local_devnet/scripts/start_node_and_create_validator.sh
index 97808752..7c43e74e 100644
--- a/local_devnet/scripts/start_node_and_create_validator.sh
+++ b/local_devnet/scripts/start_node_and_create_validator.sh
@@ -4,17 +4,17 @@
 # keeps running it validating blocks.
 
 # check if environment variables are set
-if [[ -z "${CELESTIA_HOME}" || -z "${MONIKER}" || -z "${AMOUNT}" ]]
+if [[ -z "${CELESTIA_APP_HOME}" || -z "${MONIKER}" || -z "${AMOUNT}" ]]
 then
-  echo "Environment not setup correctly. Please set: CELESTIA_HOME, MONIKER, AMOUNT variables"
+  echo "Environment not setup correctly. Please set: CELESTIA_APP_HOME, MONIKER, AMOUNT variables"
   exit 1
 fi
 
 # create necessary structure if doesn't exist
-if [[ ! -f ${CELESTIA_HOME}/data/priv_validator_state.json ]]
+if [[ ! -f ${CELESTIA_APP_HOME}/data/priv_validator_state.json ]]
 then
-    mkdir "${CELESTIA_HOME}"/data
-    cat <<EOF > ${CELESTIA_HOME}/data/priv_validator_state.json
+    mkdir "${CELESTIA_APP_HOME}"/data
+    cat <<EOF > ${CELESTIA_APP_HOME}/data/priv_validator_state.json
 {
   "height": "0",
   "round": 0,
@@ -42,7 +42,7 @@ fi
     # create validator
     celestia-appd tx staking create-validator \
       --amount="${AMOUNT}" \
-      --pubkey="$(celestia-appd tendermint show-validator --home "${CELESTIA_HOME}")" \
+      --pubkey="$(celestia-appd tendermint show-validator --home "${CELESTIA_APP_HOME}")" \
       --moniker="${MONIKER}" \
       --chain-id="test" \
       --commission-rate=0.1 \
@@ -51,7 +51,7 @@ fi
       --min-self-delegation=1000000 \
       --from="${MONIKER}" \
       --keyring-backend=test \
-      --home="${CELESTIA_HOME}" \
+      --home="${CELESTIA_APP_HOME}" \
       --broadcast-mode=block \
       --fees="300000utia" \
       --yes
@@ -66,7 +66,7 @@ fi
 
 # start node
 celestia-appd start \
-  --home="${CELESTIA_HOME}" \
+  --home="${CELESTIA_APP_HOME}" \
   --moniker="${MONIKER}" \
   --p2p.persistent_peers=1c29bcd0d568df34f148b26205543566e4d1a177@core0:26656 \
   --rpc.laddr=tcp://0.0.0.0:26657 \



Test patch:
diff --git a/test/e2e/simple.go b/test/e2e/simple.go
index d38ad96f..09aa6c81 100644
--- a/test/e2e/simple.go
+++ b/test/e2e/simple.go
@@ -47,7 +47,7 @@ func E2ESimple(logger *log.Logger) error {
 	endpoints, err := testNet.RemoteGRPCEndpoints()
 	testnet.NoError("failed to get remote gRPC endpoints", err)
 	upgradeSchedule := map[int64]uint64{}
-	err = testNet.CreateTxClient(ctx, "txsim", testnet.TxsimVersion, 10, "100-2000", 100, testnet.DefaultResources, endpoints[0], upgradeSchedule)
+	err = testNet.CreateTxClient(ctx, "txsim", latestVersion, 10, "100-2000", 100, testnet.DefaultResources, endpoints[0], upgradeSchedule)
 	testnet.NoError("failed to create tx client", err)
 
 	logger.Println("Setting up testnets")
@@ -56,19 +56,41 @@ func E2ESimple(logger *log.Logger) error {
 	logger.Println("Starting testnets")
 	testnet.NoError("failed to start testnets", testNet.Start(ctx))
 
-	logger.Println("Waiting for 30 seconds to produce blocks")
-	time.Sleep(30 * time.Second)
+	logger.Println("Waiting for transactions to be committed")
 
-	logger.Println("Reading blockchain headers")
-	blockchain, err := testnode.ReadBlockchainHeaders(ctx, testNet.Node(0).AddressRPC())
-	testnet.NoError("failed to read blockchain headers", err)
+	pollCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
+	defer cancel()
 
-	totalTxs := 0
-	for _, blockMeta := range blockchain {
-		totalTxs += blockMeta.NumTxs
-	}
-	if totalTxs < 10 {
-		return fmt.Errorf("expected at least 10 transactions, got %d", totalTxs)
+	const requiredTxs = 10
+	const pollInterval = 5 * time.Second
+
+	// periodically check for transactions until timeout or required transactions are found
+	ticker := time.NewTicker(pollInterval)
+	defer ticker.Stop()
+
+	for {
+		select {
+		case <-ticker.C:
+			// Check for transactions
+			blockchain, err := testnode.ReadBlockchainHeaders(ctx, testNet.Node(0).AddressRPC())
+			if err != nil {
+				logger.Printf("Error reading blockchain headers: %v", err)
+				continue
+			}
+
+			totalTxs := 0
+			for _, blockMeta := range blockchain {
+				totalTxs += blockMeta.NumTxs
+			}
+
+			logger.Printf("Current transaction count: %d", totalTxs)
+
+			if totalTxs >= requiredTxs {
+				logger.Printf("Found %d transactions, continuing with test", totalTxs)
+				return nil
+			}
+		case <-pollCtx.Done():
+			return fmt.Errorf("timed out waiting for %d transactions", requiredTxs)
+		}
 	}
-	return nil
 }
diff --git a/test/e2e/testnet/defaults.go b/test/e2e/testnet/defaults.go
index e39c8a52..fa0adaa4 100644
--- a/test/e2e/testnet/defaults.go
+++ b/test/e2e/testnet/defaults.go
@@ -10,7 +10,7 @@ var DefaultResources = Resources{
 }
 
 const (
-	TxsimVersion = "b5a8e7c" // TODO: use a proper version, this is one built on the sdk 50 fork
+	TxsimVersion = "v4.0.0-rc1"
 	MB           = 1000 * 1000
 	GB           = 1000 * MB
 	MiB          = 1024 * 1024
diff --git a/test/e2e/testnet/testnet.go b/test/e2e/testnet/testnet.go
index c3298290..0985b0e6 100644
--- a/test/e2e/testnet/testnet.go
+++ b/test/e2e/testnet/testnet.go
@@ -19,6 +19,7 @@ import (
 
 	"github.com/celestiaorg/celestia-app/v4/app"
 	"github.com/celestiaorg/celestia-app/v4/app/encoding"
+	"github.com/celestiaorg/celestia-app/v4/pkg/appconsts"
 	"github.com/celestiaorg/celestia-app/v4/test/util/genesis"
 )
 
@@ -508,4 +509,7 @@ func (o *Options) setDefaults() {
 	if o.Seed == 0 {
 		o.Seed = DefaultSeed
 	}
+	if o.AppVersion == 0 {
+		o.AppVersion = appconsts.LatestVersion
+	}
 }