Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/chain-liveness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
run: |
cd gm
# start the local da in the background
go tool github.com/evolve/ev-node/da/cmd/local-da &
go tool github.com/evolve/ev-node/tools/local-da &
# capture the background process PID
echo "DA_PID=$!" >> $GITHUB_ENV
# give it a moment to start
Expand Down
2 changes: 2 additions & 0 deletions evolve/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- [#247](https://github.com/ignite/apps/pull/247) Bump `ev-node`, `ev-abci` and wire force inclusion changes.

## [`v0.5.0`](https://github.com/ignite/apps/releases/tag/evolve/v0.5.0)

- [#237](https://github.com/ignite/apps/pull/237) Remove `--start` and `--migrate` flags from `evolve add` command. Split into `evolve add` and `evolve add-migrate` commands.
Expand Down
2 changes: 1 addition & 1 deletion evolve/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Then start `local-da` or use Celestia mainnet as data availability layer.

```sh
cd gm
go tool github.com/evstack/ev-node/da/cmd/local-da
go tool github.com/evstack/ev-node/tools/local-da
```

Finally, run the network:
Expand Down
87 changes: 87 additions & 0 deletions evolve/cmd/init.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package cmd

import (
"bytes"
"context"
"fmt"
"math"
"os"
"path/filepath"
"reflect"
"strings"

sdkmath "cosmossdk.io/math"
"github.com/cometbft/cometbft/crypto"
Expand All @@ -17,6 +20,7 @@ import (
"github.com/spf13/viper"

evconfig "github.com/evstack/ev-node/pkg/config"
evgenesis "github.com/evstack/ev-node/pkg/genesis"

configchain "github.com/ignite/cli/v29/ignite/config/chain"
"github.com/ignite/cli/v29/ignite/pkg/cliui"
Expand Down Expand Up @@ -114,6 +118,16 @@ func initEVABCI(
return err
}

// Add DAEpochForcedInclusion field to genesis
fieldTag, err := getJSONTag(evgenesis.Genesis{}, "DAEpochForcedInclusion")
if err != nil {
return fmt.Errorf("failed to get JSON tag for DAEpochForcedInclusion in Evolve genesis: %w", err)
}

if err := prependFieldToGenesis(genesisPath, fieldTag, "25"); err != nil {
return fmt.Errorf("failed to add %s to genesis: %w", fieldTag, err)
}

// modify evolve config (add da namespace)
evolveConfigPath := filepath.Join(home, evconfig.AppConfigDir, evconfig.ConfigName)
evolveViper := viper.New()
Expand All @@ -132,6 +146,7 @@ func initEVABCI(
}
evolveConfig.DA.Namespace = chainID
evolveConfig.DA.DataNamespace = fmt.Sprintf("%s-data", chainID)
// evolveConfig.DA.ForcedInclusionNamespace = fmt.Sprintf("%s-fi-txs", chainID) // currently disable force inclusion until https://github.com/evstack/ev-node/issues/2906

if err := evolveConfig.SaveAsYaml(); err != nil {
return err
Expand All @@ -153,3 +168,75 @@ func getPubKey(chainHome string) (crypto.PubKey, error) {
}
return pvKey.PubKey, nil
}

// getJSONTag extracts the JSON tag value for a given field name using reflection.
func getJSONTag(v interface{}, fieldName string) (string, error) {
t := reflect.TypeOf(v)
field, ok := t.FieldByName(fieldName)
if !ok {
return "", fmt.Errorf("field %s not found in type %s", fieldName, t.Name())
}

jsonTag := field.Tag.Get("json")
if jsonTag == "" {
return "", fmt.Errorf("field %s does not have a json tag", fieldName)
}

// Handle tags like "field_name,omitempty" by taking only the first part
if idx := strings.Index(jsonTag, ","); idx != -1 {
jsonTag = jsonTag[:idx]
}

return jsonTag, nil
}

// prependFieldToGenesis adds a field as the first field in the genesis JSON file
// without loading the entire JSON structure into memory.
func prependFieldToGenesis(genesisPath, fieldName, fieldValue string) error {
data, err := os.ReadFile(genesisPath)
if err != nil {
return fmt.Errorf("failed to read genesis file: %w", err)
}

// Find the first opening brace
openBraceIdx := bytes.IndexByte(data, '{')
if openBraceIdx == -1 {
return fmt.Errorf("invalid genesis file: no opening brace found")
}

// Start right after the opening brace
insertPos := openBraceIdx + 1

// Find where the next non-whitespace content starts
contentStart := insertPos
for contentStart < len(data) && (data[contentStart] == ' ' || data[contentStart] == '\n' || data[contentStart] == '\r' || data[contentStart] == '\t') {
contentStart++
}

// Check if there's any content (not just closing brace)
hasContent := contentStart < len(data) && data[contentStart] != '}'

// Build the new field with proper formatting
var newField string
if hasContent {
// There's existing content, add comma after our field
newField = fmt.Sprintf("\n \"%s\": %s,", fieldName, fieldValue)
} else {
// Empty object, no comma needed
newField = fmt.Sprintf("\n \"%s\": %s\n", fieldName, fieldValue)
}

// Construct the new file content
var buf bytes.Buffer
buf.Write(data[:insertPos])
buf.WriteString(newField)
// Write the original whitespace and remaining content
buf.Write(data[insertPos:])

// Write back to file
if err := os.WriteFile(genesisPath, buf.Bytes(), 0644); err != nil {
return fmt.Errorf("failed to write genesis file: %w", err)
}

return nil
}
109 changes: 109 additions & 0 deletions evolve/cmd/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cmd

import (
"os"
"path/filepath"
"strings"
"testing"

"gotest.tools/v3/assert"
)

func TestPrependFieldToGenesis(t *testing.T) {
tests := []struct {
name string
input string
fieldName string
fieldValue string
expectedStart string
wantErr bool
}{
{
name: "prepend to non-empty genesis",
input: `{
"genesis_time": "2024-01-01T00:00:00Z",
"chain_id": "test-chain"
}`,
fieldName: "da_epoch_forced_inclusion",
fieldValue: "0",
expectedStart: `{
"da_epoch_forced_inclusion": 0,
"genesis_time": "2024-01-01T00:00:00Z",`,
wantErr: false,
},
{
name: "prepend to empty genesis",
input: `{}`,
fieldName: "da_epoch_forced_inclusion",
fieldValue: "0",
expectedStart: `{
"da_epoch_forced_inclusion": 0
}`,
wantErr: false,
},
{
name: "prepend to genesis with whitespace",
input: `{

"app_state": {}
}`,
fieldName: "da_epoch_forced_inclusion",
fieldValue: "0",
expectedStart: `{
"da_epoch_forced_inclusion": 0,

"app_state": {}`,
wantErr: false,
},
{
name: "invalid genesis - no opening brace",
input: `"chain_id": "test"}`,
fieldName: "da_epoch_forced_inclusion",
fieldValue: "0",
wantErr: true,
},
{
name: "prepend string value",
input: `{
"existing": "value"
}`,
fieldName: "new_field",
fieldValue: `"string_value"`,
expectedStart: `{
"new_field": "string_value",
"existing": "value"`,
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tmpDir := t.TempDir()
genesisPath := filepath.Join(tmpDir, "genesis.json")

err := os.WriteFile(genesisPath, []byte(tt.input), 0644)
assert.NilError(t, err)

err = prependFieldToGenesis(genesisPath, tt.fieldName, tt.fieldValue)

if tt.wantErr {
assert.ErrorContains(t, err, "")
return
}

assert.NilError(t, err)

result, err := os.ReadFile(genesisPath)
assert.NilError(t, err)

resultStr := string(result)
if !strings.HasPrefix(resultStr, tt.expectedStart) {
t.Errorf("result does not start with expected content\nGot:\n%s\n\nExpected to start with:\n%s", resultStr, tt.expectedStart)
}

if !strings.HasSuffix(resultStr, "}") {
t.Errorf("result does not end with closing brace: %s", resultStr)
}
})
}
}
57 changes: 29 additions & 28 deletions evolve/go.mod
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
module github.com/ignite/apps/evolve

go 1.24.1
go 1.24.6

require (
cosmossdk.io/math v1.5.3
github.com/cometbft/cometbft v0.38.19
github.com/cosmos/cosmos-sdk v0.53.4
github.com/evstack/ev-node v1.0.0-beta.2.0.20250908090838-0584153217ed
github.com/evstack/ev-node v1.0.0-beta.10.0.20251216132820-afcd6bd9b354
github.com/gobuffalo/genny/v2 v2.1.0
github.com/gobuffalo/plush/v4 v4.1.22
github.com/hashicorp/go-plugin v1.6.3
github.com/ignite/cli/v29 v29.6.1
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.10.0
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
gotest.tools/v3 v3.5.2
)

require (
Expand Down Expand Up @@ -43,6 +44,7 @@ require (
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bytedance/sonic v1.14.0 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/celestiaorg/go-square/v3 v3.0.2 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
Expand Down Expand Up @@ -112,7 +114,7 @@ require (
github.com/gobuffalo/tags/v3 v3.1.4 // indirect
github.com/gobuffalo/validate/v3 v3.3.3 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/goccy/go-yaml v1.19.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/googleapis v1.4.1 // indirect
Expand Down Expand Up @@ -146,7 +148,7 @@ require (
github.com/imdario/mergo v0.3.15 // indirect
github.com/improbable-eng/grpc-web v0.15.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/go-cid v0.5.0 // indirect
github.com/ipfs/go-cid v0.6.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand Down Expand Up @@ -176,7 +178,7 @@ require (
github.com/multiformats/go-multiaddr v0.16.1 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/multiformats/go-varint v0.1.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nqd/flat v0.2.0 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
Expand All @@ -190,29 +192,29 @@ require (
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.23.0 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/radovskyb/watcher v1.0.7 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/rs/zerolog v1.34.0 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sasha-s/go-deadlock v0.3.5 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.7 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/cobra v1.10.2 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
Expand All @@ -226,26 +228,25 @@ require (
go.etcd.io/bbolt v1.4.0 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/arch v0.17.0 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/term v0.34.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/term v0.38.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/tools v0.39.0 // indirect
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
google.golang.org/grpc v1.72.2 // indirect
google.golang.org/protobuf v1.36.7 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.2 // indirect
lukechampine.com/blake3 v1.4.1 // indirect
nhooyr.io/websocket v1.8.6 // indirect
pgregory.net/rapid v1.2.0 // indirect
Expand Down
Loading
Loading