Skip to content

Commit c017220

Browse files
bitwiseguygeokneerefcell
authored
Use toml instead of yaml for chain config files (#386)
* add-chain: create toml chain config file * add-chain: import toml package * add-chain: main writes toml chain config * add-chain: add expected_*.toml test files * add-chain: e2e_test uses toml chain config files * add-chain: add convert-to-toml subcommand * superchain: init reads from toml files instead of yaml * circleci: set 'Install just' step name * superchain: replace all chain config .yaml file with .toml * superchain: test uses toml.Unmarshal * add-chain: remove unused checkConfigYaml test function * codegen: fix formatting for toml * superchain: add toml tags for addresses, genesis.system_config * add-chain: convert-to-toml writes addresses, genesis.system_config * superchain: use superchain.toml instead of superchain.yaml * superchain: fix unMarshalSuperchainConfig so it works with toml * superchain: rename EnhanceTOML to GenerateTOMLComments * add-chain: remove WriteChainConfig, last yaml dependency * superchain: remove yaml config files * superchain: fix types in genesis SystemConfig * justfile: clean .toml instead of .yaml * add-chain: write addresses to toml instead of json * superchain: fix order of fields in ChainConfig * superchain: move ChainConfig.Addresses field before plasma * add-chain: remove all yaml and json testdata files * validation: fix devnet config superchain_level and standard_candidate * superchain: add addresses and genesis.system_config to all toml files * add-chain: remove convert-to-toml subcommand * justfile: remove unnecessary clean-add-chain commands * superchain: use rawTOML instead of rawYAML in tests * superchain: remove all yaml tags and references * superchain: reorder ChainConfig.Plasma in toml file * add-chain: tidy comments and function description * superchain: standardize timestamp comment in superchain.toml files * simplify AddressList.MarshalTOML (#392) * simplify mapToAddressList (#393) * superchain: convert superlumio mainnet, metal sepolia to toml * justfile: update remove-chain to point at correct files * superchain: use go codegen to create addresses.json * run go linter * remove javascript codegen * superchain: remove all extra/addresses,genesis-system-config files * superchain: remove embedded extra/addresses * superchain: return error if ChainConfig fields are improperly ordered * superchain: add explanatory comment for custom ChainConfig.MarshalTOML * fix(bindings): Parse TOML Chain Configs (#394) * fix(bindings): use toml configs * fix(bindings): no need to read extra dir * add-chain: cleanup unused code * add-chain: remove 0x0 addresses via post-process instead of custom MarshalTOML --------- Co-authored-by: George Knee <georgeknee@googlemail.com> Co-authored-by: refcell <abigger87@gmail.com>
1 parent a06cb07 commit c017220

File tree

122 files changed

+1736
-1914
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+1736
-1914
lines changed

.circleci/config.yml

+7-8
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ commands:
2121
install-just:
2222
description: "Install just"
2323
steps:
24-
- run: |
25-
wget -qO - 'https://proget.makedeb.org/debian-feeds/prebuilt-mpr.pub' | gpg --dearmor | sudo tee /usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg 1> /dev/null
26-
echo "deb [arch=all,$(dpkg --print-architecture) signed-by=/usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg] https://proget.makedeb.org prebuilt-mpr $(lsb_release -cs)" | sudo tee /etc/apt/sources.list.d/prebuilt-mpr.list
27-
sudo apt update
28-
sudo apt install just
24+
- run:
25+
name: "Install just"
26+
command: |
27+
wget -qO - 'https://proget.makedeb.org/debian-feeds/prebuilt-mpr.pub' | gpg --dearmor | sudo tee /usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg 1> /dev/null
28+
echo "deb [arch=all,$(dpkg --print-architecture) signed-by=/usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg] https://proget.makedeb.org prebuilt-mpr $(lsb_release -cs)" | sudo tee /etc/apt/sources.list.d/prebuilt-mpr.list
29+
sudo apt update
30+
sudo apt install just
2931
3032
jobs:
3133
golang-lint:
@@ -106,9 +108,6 @@ jobs:
106108
steps:
107109
- checkout
108110
- install-just
109-
- node/install:
110-
install-yarn: false
111-
node-version: '14.16.1'
112111
- run:
113112
name: Run codegen
114113
command: just codegen

add-chain/addresses.go

+5-28
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"path/filepath"
99

10+
"github.com/BurntSushi/toml"
1011
"github.com/ethereum-optimism/superchain-registry/superchain"
1112
)
1213

@@ -206,35 +207,11 @@ func readAddressesFromJSON(contractAddresses map[string]string, deploymentsDir s
206207
return nil
207208
}
208209

209-
func writeAddressesToJSON(contractsAddresses map[string]string, superchainRepoPath, target, chainName string) error {
210-
checkSummedContractAddresses := make(map[string]string)
211-
for k, v := range contractsAddresses {
212-
checkSummedContractAddresses[k] = superchain.MustHexToAddress(v).String()
213-
}
214-
215-
dirPath := filepath.Join(superchainRepoPath, "superchain", "extra", "addresses", target)
216-
if err := os.MkdirAll(dirPath, 0o755); err != nil {
217-
return fmt.Errorf("failed to create directory: %w", err)
218-
}
219-
220-
filePath := filepath.Join(dirPath, chainName+".json")
221-
file, err := os.Create(filePath)
222-
if err != nil {
223-
return fmt.Errorf("failed to create file: %w", err)
224-
}
225-
defer file.Close()
226-
227-
// Marshal the map to JSON
228-
jsonData, err := json.MarshalIndent(checkSummedContractAddresses, "", " ")
210+
func mapToAddressList(m map[string]string, result *superchain.AddressList) error {
211+
out, err := toml.Marshal(m)
229212
if err != nil {
230-
return fmt.Errorf("failed to marshal json: %w", err)
213+
return err
231214
}
232215

233-
// Write the JSON data to the file
234-
if _, err := file.Write(jsonData); err != nil {
235-
return fmt.Errorf("failed to write json to file: %w", err)
236-
}
237-
fmt.Printf("Contract addresses written to: %s\n", filePath)
238-
239-
return nil
216+
return toml.Unmarshal(out, result)
240217
}

add-chain/cmd/promote-to-standard.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ var PromoteToStandardCmd = cli.Command{
3737

3838
superchainRepoPath := filepath.Dir(filepath.Dir(filepath.Dir(thisFile)))
3939
targetDir := filepath.Join(superchainRepoPath, "superchain", "configs", chain.Superchain)
40-
targetFilePath := filepath.Join(targetDir, chain.Chain+".yaml")
41-
err := config.WriteChainConfig(*chain, targetFilePath)
40+
targetFilePath := filepath.Join(targetDir, chain.Chain+".toml")
41+
err := config.WriteChainConfigTOML(*chain, targetFilePath)
4242
if err != nil {
4343
panic(err)
4444
}

add-chain/config/config.go

+39-30
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package config
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/json"
67
"fmt"
78
"os"
89
"path/filepath"
10+
"strings"
911
"time"
1012

13+
"github.com/BurntSushi/toml"
1114
"github.com/ethereum-optimism/superchain-registry/superchain"
12-
"gopkg.in/yaml.v3"
1315
)
1416

1517
type JSONChainConfig struct {
@@ -90,43 +92,50 @@ func ConstructChainConfig(
9092
return chainConfig, nil
9193
}
9294

93-
// WriteChainConfig accepts a rollupConfig, formats it, and writes some output files based on the given
94-
// target directories
95-
func WriteChainConfig(
96-
rollupConfig superchain.ChainConfig,
97-
targetDirectory string,
98-
) error {
99-
yamlData, err := yaml.Marshal(rollupConfig)
95+
// WriteChainConfigTPOML accepts a rollupConfig, formats it, and writes a single output toml
96+
// file which includes the following:
97+
// - general chain info/config
98+
// - contract and role addresses
99+
// - genesis system config
100+
// - optional feature config info, if activated (e.g. plasma)
101+
func WriteChainConfigTOML(rollupConfig superchain.ChainConfig, targetDirectory string) error {
102+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
103+
defer cancel()
104+
105+
comments, err := rollupConfig.GenerateTOMLComments(ctx)
100106
if err != nil {
101-
return fmt.Errorf("failed to marshal yaml: %w", err)
107+
return fmt.Errorf("failed to generate toml comments: %w", err)
102108
}
103109

104-
// Unmarshal bytes into a yaml.Node for custom manipulation
105-
var rootNode yaml.Node
106-
if err = yaml.Unmarshal(yamlData, &rootNode); err != nil {
107-
return err
110+
// Marshal the struct to TOML
111+
var buf bytes.Buffer
112+
if err := toml.NewEncoder(&buf).Encode(rollupConfig); err != nil {
113+
return fmt.Errorf("failed to marshal toml: %w", err)
108114
}
109115

110-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
111-
defer cancel()
112-
if err = rollupConfig.EnhanceYAML(ctx, &rootNode); err != nil {
113-
return err
114-
}
116+
// Create final content with comments
117+
var finalContent strings.Builder
118+
lines := strings.Split(buf.String(), "\n")
115119

116-
// Write the rollup config to a yaml file
117-
filename := filepath.Join(targetDirectory)
118-
file, err := os.Create(filename)
119-
if err != nil {
120-
return err
120+
for i, line := range lines {
121+
splits := strings.Split(line, "=")
122+
lineKey := strings.TrimSpace(splits[0])
123+
if len(splits) > 1 && strings.TrimSpace(splits[1]) == "\"0x0000000000000000000000000000000000000000\"" {
124+
// Skip this line to exclude zero addresses from the output file. Makes the config .toml cleaner
125+
continue
126+
}
127+
if comment, exists := comments[lineKey]; exists {
128+
finalContent.WriteString(line + " " + comment + "\n")
129+
} else if i != len(lines)-1 || line != "" {
130+
// Prevent double empty line at the end of the file
131+
finalContent.WriteString(line + "\n")
132+
}
121133
}
122-
defer file.Close()
123-
124-
encoder := yaml.NewEncoder(file)
125-
defer encoder.Close()
126134

127-
encoder.SetIndent(2)
128-
if err := encoder.Encode(&rootNode); err != nil {
129-
return fmt.Errorf("failed to write yaml file: %w", err)
135+
// Write the enhanced TOML data to a file
136+
filename := filepath.Join(targetDirectory)
137+
if err := os.WriteFile(filename, []byte(finalContent.String()), 0o644); err != nil {
138+
return fmt.Errorf("failed to write toml file: %w", err)
130139
}
131140

132141
fmt.Printf("Rollup config written to: %s\n", filename)

add-chain/e2e_test.go

+13-36
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
package main
22

33
import (
4-
"encoding/json"
54
"os"
65
"strconv"
76
"testing"
87

9-
"github.com/google/go-cmp/cmp"
8+
"github.com/BurntSushi/toml"
109
"github.com/stretchr/testify/require"
11-
"gopkg.in/yaml.v3"
1210
)
1311

1412
const (
1513
addressDir = "../superchain/extra/addresses/sepolia/"
16-
ymlConfigDir = "../superchain/configs/sepolia/"
14+
configDir = "../superchain/configs/sepolia/"
1715
genesisSystemConfigDir = "../superchain/extra/genesis-system-configs/sepolia/"
1816
)
1917

@@ -90,9 +88,7 @@ func TestAddChain_Main(t *testing.T) {
9088
err = runApp(args)
9189
require.NoError(t, err, "add-chain app failed")
9290

93-
checkConfigYaml(t, tt.name, tt.chainShortName)
94-
compareJsonFiles(t, "superchain/extra/addresses/sepolia/", tt.name, tt.chainShortName)
95-
compareJsonFiles(t, "superchain/extra/genesis-system-configs/sepolia/", tt.name, tt.chainShortName)
91+
checkConfigTOML(t, tt.name, tt.chainShortName)
9692
})
9793
}
9894

@@ -151,44 +147,25 @@ func TestAddChain_CheckGenesis(t *testing.T) {
151147
})
152148
}
153149

154-
func compareJsonFiles(t *testing.T, dirPath, testName, chainShortName string) {
155-
expectedBytes, err := os.ReadFile("./testdata/" + dirPath + "expected_" + testName + ".json")
156-
require.NoError(t, err, "failed to read expected.json file from "+dirPath)
150+
func checkConfigTOML(t *testing.T, testName, chainShortName string) {
151+
expectedBytes, err := os.ReadFile("./testdata/superchain/configs/sepolia/expected_" + testName + ".toml")
152+
require.NoError(t, err, "failed to read expected.toml config file: %w", err)
157153

158-
var expectJSON map[string]interface{}
159-
err = json.Unmarshal(expectedBytes, &expectJSON)
160-
require.NoError(t, err, "failed to unmarshal expected.json file from "+dirPath)
154+
var expectedTOML map[string]interface{}
155+
err = toml.Unmarshal(expectedBytes, &expectedTOML)
156+
require.NoError(t, err, "failed to unmarshal expected.toml config file: %w", err)
161157

162-
testBytes, err := os.ReadFile("../" + dirPath + chainShortName + ".json")
163-
require.NoError(t, err, "failed to read test generated json file from "+dirPath)
158+
testBytes, err := os.ReadFile(configDir + chainShortName + ".toml")
159+
require.NoError(t, err, "failed to read testchain.toml config file: %w", err)
164160

165-
var testJSON map[string]interface{}
166-
err = json.Unmarshal(testBytes, &testJSON)
167-
require.NoError(t, err, "failed to read test generated json file from "+dirPath)
168-
169-
diff := cmp.Diff(expectJSON, testJSON)
170-
require.Equal(t, diff, "", "expected json (-) does not match test json (+): %s", diff)
171-
}
172-
173-
func checkConfigYaml(t *testing.T, testName, chainShortName string) {
174-
expectedBytes, err := os.ReadFile("./testdata/superchain/configs/sepolia/expected_" + testName + ".yaml")
175-
require.NoError(t, err, "failed to read expected.yaml config file: %w", err)
176-
177-
var expectedYaml map[string]interface{}
178-
err = yaml.Unmarshal(expectedBytes, &expectedYaml)
179-
require.NoError(t, err, "failed to unmarshal expected.yaml config file: %w", err)
180-
181-
testBytes, err := os.ReadFile(ymlConfigDir + chainShortName + ".yaml")
182-
require.NoError(t, err, "failed to read testchain.yaml config file: %w", err)
183-
184-
require.Equal(t, string(expectedBytes), string(testBytes), "test .yaml contents do not meet expectation")
161+
require.Equal(t, string(expectedBytes), string(testBytes), "test .toml contents do not meet expectation")
185162
}
186163

187164
func cleanupTestFiles(t *testing.T, chainShortName string) {
188165
paths := []string{
189166
addressDir + chainShortName + ".json",
190167
genesisSystemConfigDir + chainShortName + ".json",
191-
ymlConfigDir + chainShortName + ".yaml",
168+
configDir + chainShortName + ".toml",
192169
}
193170

194171
for _, path := range paths {

add-chain/go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ go 1.21
55
replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain
66

77
require (
8+
github.com/BurntSushi/toml v1.4.0
89
github.com/ethereum-optimism/optimism v1.7.7
910
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240614103325-d8902381f5d8
1011
github.com/ethereum/go-ethereum v1.13.15
1112
github.com/google/go-cmp v0.6.0
1213
github.com/joho/godotenv v1.5.1
1314
github.com/stretchr/testify v1.9.0
1415
github.com/urfave/cli/v2 v2.27.1
15-
gopkg.in/yaml.v3 v3.0.1
1616
)
1717

1818
require (
@@ -91,5 +91,6 @@ require (
9191
golang.org/x/tools v0.21.0 // indirect
9292
google.golang.org/protobuf v1.34.1 // indirect
9393
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
94+
gopkg.in/yaml.v3 v3.0.1 // indirect
9495
rsc.io/tmplfunc v0.0.3 // indirect
9596
)

add-chain/main.go

+11-31
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package main
22

33
import (
4-
"encoding/json"
54
"fmt"
65
"os"
76
"path/filepath"
@@ -135,34 +134,6 @@ func entrypoint(ctx *cli.Context) error {
135134
return fmt.Errorf("failed to construct rollup config: %w", err)
136135
}
137136

138-
targetFilePath := filepath.Join(targetDir, chainShortName+".yaml")
139-
err = config.WriteChainConfig(rollupConfig, targetFilePath)
140-
if err != nil {
141-
return fmt.Errorf("error generating chain config .yaml file: %w", err)
142-
}
143-
144-
fmt.Printf("Wrote config for new chain with identifier %s", rollupConfig.Identifier())
145-
146-
// Create genesis-system-config data
147-
// (this is deprecated, users should load this from L1, when available via SystemConfig)
148-
dirPath := filepath.Join(superchainRepoRoot, "superchain", "extra", "genesis-system-configs", superchainTarget)
149-
150-
if err := os.MkdirAll(dirPath, 0o755); err != nil {
151-
return fmt.Errorf("failed to create directory: %w", err)
152-
}
153-
154-
// Write the genesis system config JSON to a new file
155-
systemConfigJSON, err := json.MarshalIndent(rollupConfig.Genesis.SystemConfig, "", " ")
156-
if err != nil {
157-
return fmt.Errorf("failed to marshal genesis system config json: %w", err)
158-
}
159-
160-
filePath := filepath.Join(dirPath, chainShortName+".json")
161-
if err := os.WriteFile(filePath, systemConfigJSON, 0o644); err != nil {
162-
return fmt.Errorf("failed to write genesis system config json: %w", err)
163-
}
164-
fmt.Printf("Genesis system config written to: %s\n", filePath)
165-
166137
err = readAddressesFromChain(addresses, l1RpcUrl, isFaultProofs)
167138
if err != nil {
168139
return fmt.Errorf("failed to read addresses from chain: %w", err)
@@ -172,11 +143,20 @@ func entrypoint(ctx *cli.Context) error {
172143
addresses["DAChallengeAddress"] = rollupConfig.Plasma.DAChallengeAddress.String()
173144
}
174145

175-
err = writeAddressesToJSON(addresses, superchainRepoRoot, superchainTarget, chainShortName)
146+
addressList := superchain.AddressList{}
147+
err = mapToAddressList(addresses, &addressList)
176148
if err != nil {
177-
return fmt.Errorf("failed to write contract addresses to JSON file: %w", err)
149+
return fmt.Errorf("error converting map to AddressList: %w", err)
178150
}
151+
rollupConfig.Addresses = addressList
179152

153+
targetFilePath := filepath.Join(targetDir, chainShortName+".toml")
154+
err = config.WriteChainConfigTOML(rollupConfig, targetFilePath)
155+
if err != nil {
156+
return fmt.Errorf("error generating chain config .yaml file: %w", err)
157+
}
158+
159+
fmt.Printf("Wrote config for new chain with identifier %s", rollupConfig.Identifier())
180160
return nil
181161
}
182162

0 commit comments

Comments
 (0)