Skip to content

Commit c5ac031

Browse files
authored
feat(evolve): wire force inclusion (#247)
* feat(evolve): wire force inclusion * cl * add DAEpochForcedInclusion to genesis * bump to latest main * updates * updates * bump to main ev-abci * add core replace
1 parent 1ace9dd commit c5ac031

File tree

11 files changed

+333
-98
lines changed

11 files changed

+333
-98
lines changed

.github/workflows/chain-liveness.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
run: |
5757
cd gm
5858
# start the local da in the background
59-
go tool github.com/evolve/ev-node/da/cmd/local-da &
59+
go tool github.com/evolve/ev-node/tools/local-da &
6060
# capture the background process PID
6161
echo "DA_PID=$!" >> $GITHUB_ENV
6262
# give it a moment to start

evolve/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- [#247](https://github.com/ignite/apps/pull/247) Bump `ev-node`, `ev-abci` and wire force inclusion changes.
6+
57
## [`v0.5.0`](https://github.com/ignite/apps/releases/tag/evolve/v0.5.0)
68

79
- [#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.

evolve/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Then start `local-da` or use Celestia mainnet as data availability layer.
2222

2323
```sh
2424
cd gm
25-
go tool github.com/evstack/ev-node/da/cmd/local-da
25+
go tool github.com/evstack/ev-node/tools/local-da
2626
```
2727

2828
Finally, run the network:

evolve/cmd/init.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"context"
56
"fmt"
67
"math"
78
"os"
89
"path/filepath"
10+
"reflect"
11+
"strings"
912

1013
sdkmath "cosmossdk.io/math"
1114
"github.com/cometbft/cometbft/crypto"
@@ -17,6 +20,7 @@ import (
1720
"github.com/spf13/viper"
1821

1922
evconfig "github.com/evstack/ev-node/pkg/config"
23+
evgenesis "github.com/evstack/ev-node/pkg/genesis"
2024

2125
configchain "github.com/ignite/cli/v29/ignite/config/chain"
2226
"github.com/ignite/cli/v29/ignite/pkg/cliui"
@@ -114,6 +118,16 @@ func initEVABCI(
114118
return err
115119
}
116120

121+
// Add DAEpochForcedInclusion field to genesis
122+
fieldTag, err := getJSONTag(evgenesis.Genesis{}, "DAEpochForcedInclusion")
123+
if err != nil {
124+
return fmt.Errorf("failed to get JSON tag for DAEpochForcedInclusion in Evolve genesis: %w", err)
125+
}
126+
127+
if err := prependFieldToGenesis(genesisPath, fieldTag, "25"); err != nil {
128+
return fmt.Errorf("failed to add %s to genesis: %w", fieldTag, err)
129+
}
130+
117131
// modify evolve config (add da namespace)
118132
evolveConfigPath := filepath.Join(home, evconfig.AppConfigDir, evconfig.ConfigName)
119133
evolveViper := viper.New()
@@ -132,6 +146,7 @@ func initEVABCI(
132146
}
133147
evolveConfig.DA.Namespace = chainID
134148
evolveConfig.DA.DataNamespace = fmt.Sprintf("%s-data", chainID)
149+
// evolveConfig.DA.ForcedInclusionNamespace = fmt.Sprintf("%s-fi-txs", chainID) // currently disable force inclusion until https://github.com/evstack/ev-node/issues/2906
135150

136151
if err := evolveConfig.SaveAsYaml(); err != nil {
137152
return err
@@ -153,3 +168,75 @@ func getPubKey(chainHome string) (crypto.PubKey, error) {
153168
}
154169
return pvKey.PubKey, nil
155170
}
171+
172+
// getJSONTag extracts the JSON tag value for a given field name using reflection.
173+
func getJSONTag(v interface{}, fieldName string) (string, error) {
174+
t := reflect.TypeOf(v)
175+
field, ok := t.FieldByName(fieldName)
176+
if !ok {
177+
return "", fmt.Errorf("field %s not found in type %s", fieldName, t.Name())
178+
}
179+
180+
jsonTag := field.Tag.Get("json")
181+
if jsonTag == "" {
182+
return "", fmt.Errorf("field %s does not have a json tag", fieldName)
183+
}
184+
185+
// Handle tags like "field_name,omitempty" by taking only the first part
186+
if idx := strings.Index(jsonTag, ","); idx != -1 {
187+
jsonTag = jsonTag[:idx]
188+
}
189+
190+
return jsonTag, nil
191+
}
192+
193+
// prependFieldToGenesis adds a field as the first field in the genesis JSON file
194+
// without loading the entire JSON structure into memory.
195+
func prependFieldToGenesis(genesisPath, fieldName, fieldValue string) error {
196+
data, err := os.ReadFile(genesisPath)
197+
if err != nil {
198+
return fmt.Errorf("failed to read genesis file: %w", err)
199+
}
200+
201+
// Find the first opening brace
202+
openBraceIdx := bytes.IndexByte(data, '{')
203+
if openBraceIdx == -1 {
204+
return fmt.Errorf("invalid genesis file: no opening brace found")
205+
}
206+
207+
// Start right after the opening brace
208+
insertPos := openBraceIdx + 1
209+
210+
// Find where the next non-whitespace content starts
211+
contentStart := insertPos
212+
for contentStart < len(data) && (data[contentStart] == ' ' || data[contentStart] == '\n' || data[contentStart] == '\r' || data[contentStart] == '\t') {
213+
contentStart++
214+
}
215+
216+
// Check if there's any content (not just closing brace)
217+
hasContent := contentStart < len(data) && data[contentStart] != '}'
218+
219+
// Build the new field with proper formatting
220+
var newField string
221+
if hasContent {
222+
// There's existing content, add comma after our field
223+
newField = fmt.Sprintf("\n \"%s\": %s,", fieldName, fieldValue)
224+
} else {
225+
// Empty object, no comma needed
226+
newField = fmt.Sprintf("\n \"%s\": %s\n", fieldName, fieldValue)
227+
}
228+
229+
// Construct the new file content
230+
var buf bytes.Buffer
231+
buf.Write(data[:insertPos])
232+
buf.WriteString(newField)
233+
// Write the original whitespace and remaining content
234+
buf.Write(data[insertPos:])
235+
236+
// Write back to file
237+
if err := os.WriteFile(genesisPath, buf.Bytes(), 0644); err != nil {
238+
return fmt.Errorf("failed to write genesis file: %w", err)
239+
}
240+
241+
return nil
242+
}

evolve/cmd/init_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"strings"
7+
"testing"
8+
9+
"gotest.tools/v3/assert"
10+
)
11+
12+
func TestPrependFieldToGenesis(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
input string
16+
fieldName string
17+
fieldValue string
18+
expectedStart string
19+
wantErr bool
20+
}{
21+
{
22+
name: "prepend to non-empty genesis",
23+
input: `{
24+
"genesis_time": "2024-01-01T00:00:00Z",
25+
"chain_id": "test-chain"
26+
}`,
27+
fieldName: "da_epoch_forced_inclusion",
28+
fieldValue: "0",
29+
expectedStart: `{
30+
"da_epoch_forced_inclusion": 0,
31+
"genesis_time": "2024-01-01T00:00:00Z",`,
32+
wantErr: false,
33+
},
34+
{
35+
name: "prepend to empty genesis",
36+
input: `{}`,
37+
fieldName: "da_epoch_forced_inclusion",
38+
fieldValue: "0",
39+
expectedStart: `{
40+
"da_epoch_forced_inclusion": 0
41+
}`,
42+
wantErr: false,
43+
},
44+
{
45+
name: "prepend to genesis with whitespace",
46+
input: `{
47+
48+
"app_state": {}
49+
}`,
50+
fieldName: "da_epoch_forced_inclusion",
51+
fieldValue: "0",
52+
expectedStart: `{
53+
"da_epoch_forced_inclusion": 0,
54+
55+
"app_state": {}`,
56+
wantErr: false,
57+
},
58+
{
59+
name: "invalid genesis - no opening brace",
60+
input: `"chain_id": "test"}`,
61+
fieldName: "da_epoch_forced_inclusion",
62+
fieldValue: "0",
63+
wantErr: true,
64+
},
65+
{
66+
name: "prepend string value",
67+
input: `{
68+
"existing": "value"
69+
}`,
70+
fieldName: "new_field",
71+
fieldValue: `"string_value"`,
72+
expectedStart: `{
73+
"new_field": "string_value",
74+
"existing": "value"`,
75+
wantErr: false,
76+
},
77+
}
78+
79+
for _, tt := range tests {
80+
t.Run(tt.name, func(t *testing.T) {
81+
tmpDir := t.TempDir()
82+
genesisPath := filepath.Join(tmpDir, "genesis.json")
83+
84+
err := os.WriteFile(genesisPath, []byte(tt.input), 0644)
85+
assert.NilError(t, err)
86+
87+
err = prependFieldToGenesis(genesisPath, tt.fieldName, tt.fieldValue)
88+
89+
if tt.wantErr {
90+
assert.ErrorContains(t, err, "")
91+
return
92+
}
93+
94+
assert.NilError(t, err)
95+
96+
result, err := os.ReadFile(genesisPath)
97+
assert.NilError(t, err)
98+
99+
resultStr := string(result)
100+
if !strings.HasPrefix(resultStr, tt.expectedStart) {
101+
t.Errorf("result does not start with expected content\nGot:\n%s\n\nExpected to start with:\n%s", resultStr, tt.expectedStart)
102+
}
103+
104+
if !strings.HasSuffix(resultStr, "}") {
105+
t.Errorf("result does not end with closing brace: %s", resultStr)
106+
}
107+
})
108+
}
109+
}

evolve/go.mod

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
module github.com/ignite/apps/evolve
22

3-
go 1.24.1
3+
go 1.24.6
44

55
require (
66
cosmossdk.io/math v1.5.3
77
github.com/cometbft/cometbft v0.38.19
88
github.com/cosmos/cosmos-sdk v0.53.4
9-
github.com/evstack/ev-node v1.0.0-beta.2.0.20250908090838-0584153217ed
9+
github.com/evstack/ev-node v1.0.0-beta.10.0.20251216132820-afcd6bd9b354
1010
github.com/gobuffalo/genny/v2 v2.1.0
1111
github.com/gobuffalo/plush/v4 v4.1.22
1212
github.com/hashicorp/go-plugin v1.6.3
1313
github.com/ignite/cli/v29 v29.6.1
14-
github.com/spf13/viper v1.20.1
15-
github.com/stretchr/testify v1.10.0
14+
github.com/spf13/viper v1.21.0
15+
github.com/stretchr/testify v1.11.1
16+
gotest.tools/v3 v3.5.2
1617
)
1718

1819
require (
@@ -43,6 +44,7 @@ require (
4344
github.com/buger/jsonparser v1.1.1 // indirect
4445
github.com/bytedance/sonic v1.14.0 // indirect
4546
github.com/bytedance/sonic/loader v0.3.0 // indirect
47+
github.com/celestiaorg/go-square/v3 v3.0.2 // indirect
4648
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
4749
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
4850
github.com/cespare/xxhash/v2 v2.3.0 // indirect
@@ -112,7 +114,7 @@ require (
112114
github.com/gobuffalo/tags/v3 v3.1.4 // indirect
113115
github.com/gobuffalo/validate/v3 v3.3.3 // indirect
114116
github.com/gobwas/glob v0.2.3 // indirect
115-
github.com/goccy/go-yaml v1.18.0 // indirect
117+
github.com/goccy/go-yaml v1.19.0 // indirect
116118
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
117119
github.com/gofrs/uuid v4.4.0+incompatible // indirect
118120
github.com/gogo/googleapis v1.4.1 // indirect
@@ -146,7 +148,7 @@ require (
146148
github.com/imdario/mergo v0.3.15 // indirect
147149
github.com/improbable-eng/grpc-web v0.15.0 // indirect
148150
github.com/inconshreveable/mousetrap v1.1.0 // indirect
149-
github.com/ipfs/go-cid v0.5.0 // indirect
151+
github.com/ipfs/go-cid v0.6.0 // indirect
150152
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
151153
github.com/jmhodges/levigo v1.0.0 // indirect
152154
github.com/josharian/intern v1.0.0 // indirect
@@ -176,7 +178,7 @@ require (
176178
github.com/multiformats/go-multiaddr v0.16.1 // indirect
177179
github.com/multiformats/go-multibase v0.2.0 // indirect
178180
github.com/multiformats/go-multihash v0.2.3 // indirect
179-
github.com/multiformats/go-varint v0.0.7 // indirect
181+
github.com/multiformats/go-varint v0.1.0 // indirect
180182
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
181183
github.com/nqd/flat v0.2.0 // indirect
182184
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
@@ -190,29 +192,29 @@ require (
190192
github.com/pjbgf/sha1cd v0.3.2 // indirect
191193
github.com/pkg/errors v0.9.1 // indirect
192194
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
193-
github.com/prometheus/client_golang v1.23.0 // indirect
195+
github.com/prometheus/client_golang v1.23.2 // indirect
194196
github.com/prometheus/client_model v0.6.2 // indirect
195-
github.com/prometheus/common v0.65.0 // indirect
197+
github.com/prometheus/common v0.66.1 // indirect
196198
github.com/prometheus/procfs v0.17.0 // indirect
197199
github.com/radovskyb/watcher v1.0.7 // indirect
198200
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
199201
github.com/rivo/uniseg v0.4.7 // indirect
200202
github.com/rogpeppe/go-internal v1.14.1 // indirect
201203
github.com/rs/cors v1.11.1 // indirect
202204
github.com/rs/zerolog v1.34.0 // indirect
203-
github.com/sagikazarmark/locafero v0.7.0 // indirect
205+
github.com/sagikazarmark/locafero v0.11.0 // indirect
204206
github.com/sasha-s/go-deadlock v0.3.5 // indirect
205207
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
206208
github.com/sirupsen/logrus v1.9.3 // indirect
207209
github.com/skeema/knownhosts v1.3.0 // indirect
208210
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect
209-
github.com/sourcegraph/conc v0.3.0 // indirect
211+
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
210212
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect
211213
github.com/spaolacci/murmur3 v1.1.0 // indirect
212-
github.com/spf13/afero v1.12.0 // indirect
213-
github.com/spf13/cast v1.9.2 // indirect
214-
github.com/spf13/cobra v1.9.1 // indirect
215-
github.com/spf13/pflag v1.0.7 // indirect
214+
github.com/spf13/afero v1.15.0 // indirect
215+
github.com/spf13/cast v1.10.0 // indirect
216+
github.com/spf13/cobra v1.10.2 // indirect
217+
github.com/spf13/pflag v1.0.10 // indirect
216218
github.com/subosito/gotenv v1.6.0 // indirect
217219
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
218220
github.com/tendermint/go-amino v0.16.0 // indirect
@@ -226,26 +228,25 @@ require (
226228
go.etcd.io/bbolt v1.4.0 // indirect
227229
go.mongodb.org/mongo-driver v1.14.0 // indirect
228230
go.opencensus.io v0.24.0 // indirect
229-
go.uber.org/multierr v1.11.0 // indirect
230-
go.yaml.in/yaml/v2 v2.4.2 // indirect
231+
go.yaml.in/yaml/v2 v2.4.3 // indirect
232+
go.yaml.in/yaml/v3 v3.0.4 // indirect
231233
golang.org/x/arch v0.17.0 // indirect
232-
golang.org/x/crypto v0.41.0 // indirect
233-
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 // indirect
234-
golang.org/x/mod v0.27.0 // indirect
235-
golang.org/x/net v0.43.0 // indirect
236-
golang.org/x/sync v0.16.0 // indirect
237-
golang.org/x/sys v0.35.0 // indirect
238-
golang.org/x/term v0.34.0 // indirect
239-
golang.org/x/text v0.28.0 // indirect
240-
golang.org/x/tools v0.36.0 // indirect
234+
golang.org/x/crypto v0.46.0 // indirect
235+
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
236+
golang.org/x/mod v0.30.0 // indirect
237+
golang.org/x/net v0.48.0 // indirect
238+
golang.org/x/sync v0.19.0 // indirect
239+
golang.org/x/sys v0.39.0 // indirect
240+
golang.org/x/term v0.38.0 // indirect
241+
golang.org/x/text v0.32.0 // indirect
242+
golang.org/x/tools v0.39.0 // indirect
241243
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
242244
google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0 // indirect
243245
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
244246
google.golang.org/grpc v1.72.2 // indirect
245-
google.golang.org/protobuf v1.36.7 // indirect
247+
google.golang.org/protobuf v1.36.10 // indirect
246248
gopkg.in/warnings.v0 v0.1.2 // indirect
247249
gopkg.in/yaml.v3 v3.0.1 // indirect
248-
gotest.tools/v3 v3.5.2 // indirect
249250
lukechampine.com/blake3 v1.4.1 // indirect
250251
nhooyr.io/websocket v1.8.6 // indirect
251252
pgregory.net/rapid v1.2.0 // indirect

0 commit comments

Comments
 (0)