Skip to content

Commit 68e077b

Browse files
authored
feat(validation/genesis): improve error messages (#791)
* update temporary repo if it already exists in order to have latest changes * improve error for genesis_creation_command * improve error for mismatched allocs * lint * specify the repo to run the command against
1 parent 32db7f8 commit 68e077b

File tree

1 file changed

+35
-28
lines changed

1 file changed

+35
-28
lines changed

validation/genesis/genesis-allocs_test.go

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package genesis
33
import (
44
"encoding/json"
55
"fmt"
6-
"log"
76
"os"
87
"os/exec"
98
"path"
@@ -35,12 +34,15 @@ func TestMain(m *testing.M) {
3534
thisDir := filepath.Dir(filename)
3635
temporaryOptimismDir = path.Join(thisDir, "../../../optimism-temporary")
3736

38-
// Clone the repo if the folder doesn't exist
37+
// Clone the repo if the folder doesn't exist, otherwise pull the latest changes
3938
_, err := os.Stat(temporaryOptimismDir)
4039
needToClone := os.IsNotExist(err)
4140
if needToClone {
4241
mustExecuteCommandInDir(thisDir,
4342
exec.Command("git", "clone", "--recurse-submodules", "https://github.com/ethereum-optimism/optimism.git", temporaryOptimismDir))
43+
} else {
44+
mustExecuteCommandInDir(thisDir,
45+
exec.Command("git", "pull", temporaryOptimismDir))
4446
}
4547

4648
// Run tests
@@ -109,17 +111,15 @@ func testGenesisAllocs(t *testing.T, chain *ChainConfig) {
109111
mustExecuteCommandInDir(validationInputsDir,
110112
exec.Command("cp", "deploy-config.json", path.Join(contractsDir, "deploy-config", chainIdString+".json")))
111113
err := os.MkdirAll(path.Join(contractsDir, "deployments", chainIdString), os.ModePerm)
112-
if err != nil {
113-
log.Fatalf("Failed to create directory: %v", err)
114-
}
114+
require.NoError(t, err, "Failed to create directory")
115+
115116
if vis.GenesisCreationCommand == "opnode1" {
116117
err = writeDeploymentsLegacy(chainId, path.Join(contractsDir, "deployments", chainIdString))
117118
} else {
118119
err = writeDeployments(chainId, path.Join(contractsDir, "deployments", chainIdString))
119120
}
120-
if err != nil {
121-
log.Fatalf("Failed to write deployments: %v", err)
122-
}
121+
122+
require.NoError(t, err, "Failed to write deployments; check that your `genesis_creation_command` field was set correctly in `meta.toml`. Options: opnode1, opnode2, forge1")
123123

124124
var runDir string
125125
if strings.HasPrefix(vis.GenesisCreationCommand, "forge") {
@@ -130,20 +130,17 @@ func testGenesisAllocs(t *testing.T, chain *ChainConfig) {
130130

131131
mustExecuteCommandInDir(thisDir, exec.Command("cp", "./monorepo-outputs.sh", runDir))
132132
buildCommand := BuildCommand[vis.MonorepoBuildCommand]
133-
if vis.NodeVersion == "" {
134-
panic("must set node_version in meta.toml")
135-
}
133+
require.NotEmpty(t, vis.NodeVersion, "must set node_version in meta.toml")
134+
136135
creationCommand := GenesisCreationCommand[vis.GenesisCreationCommand](chainId, Superchains[chain.Superchain].Config.L1.PublicRPC)
137136
cmd := exec.Command("bash", "./monorepo-outputs.sh", vis.NodeVersion, buildCommand, creationCommand)
138137

139138
stdoutPipe, err := cmd.StdoutPipe()
140-
if err != nil {
141-
t.Fatalf("Failed to get stdout pipe: %v", err)
142-
}
139+
require.NoError(t, err, "Failed to get stdout pipe")
140+
143141
stderrPipe, err := cmd.StderrPipe()
144-
if err != nil {
145-
t.Fatalf("Failed to get stderr pipe: %v", err)
146-
}
142+
require.NoError(t, err, "Failed to get stderr pipe")
143+
147144
// Stream the command's stdout and stderr to the test logger
148145
go streamOutputToLogger(stdoutPipe, t)
149146
go streamOutputToLogger(stderrPipe, t)
@@ -158,19 +155,22 @@ func testGenesisAllocs(t *testing.T, chain *ChainConfig) {
158155
expectedData, err = os.ReadFile(path.Join(contractsDir, "statedump.json"))
159156
require.NoError(t, err)
160157
allocs := types.GenesisAlloc{}
158+
161159
err = json.Unmarshal(expectedData, &allocs)
162160
removeEmptyStorageSlots(allocs, t)
163-
164161
require.NoError(t, err)
162+
165163
expectedData, err = json.MarshalIndent(allocs, "", " ")
166164
require.NoError(t, err)
167165
} else {
168166
expectedData, err = os.ReadFile(path.Join(monorepoDir, "expected-genesis.json"))
169167
require.NoError(t, err)
168+
170169
gen := core.Genesis{}
171170
err = json.Unmarshal(expectedData, &gen)
172171
removeEmptyStorageSlots(gen.Alloc, t)
173172
require.NoError(t, err)
173+
174174
expectedData, err = json.MarshalIndent(gen.Alloc, "", " ")
175175
require.NoError(t, err)
176176
}
@@ -202,22 +202,27 @@ func testGenesisAllocs(t *testing.T, chain *ChainConfig) {
202202
gotData, err := json.MarshalIndent(g.Alloc, "", " ")
203203
require.NoError(t, err)
204204

205-
// special handling of weth9 for op-sepolia at the validated commit
206-
// We've observed that the contract [metadata hash](https://docs.soliditylang.org/en/latest/metadata.html)
207-
// does not match for the bytecode that is generated and what's in the superchain-registry.
208-
// The issue is likely a difference in compiler settings when the contract artifacts were generated and
209-
// stored in the superchain registry. To account for this, we trim the metadata hash portion of the
210-
// weth9 contract bytecode before writing to file/comparing the outputs
211-
// For extra safety, we allow this type of check only at the commit hash we know has this issue.
212-
// In other instances, the metadata may have optionally been excluded from the bytecode in the registry,
213-
// in which case we ought to check for a complete match.
205+
/*
206+
special handling of weth9 for op-sepolia at the validated commit
207+
We've observed that the contract [metadata hash](https://docs.soliditylang.org/en/latest/metadata.html)
208+
does not match for the bytecode that is generated and what's in the superchain-registry.
209+
210+
The issue is likely a difference in compiler settings when the contract artifacts were generated and
211+
stored in the superchain registry. To account for this, we trim the metadata hash portion of the
212+
weth9 contract bytecode before writing to file/comparing the outputs
213+
214+
For extra safety, we allow this type of check only at the commit hash we know has this issue.
215+
In other instances, the metadata may have optionally been excluded from the bytecode in the registry,
216+
in which case we ought to check for a complete match.
217+
*/
214218
if chainId == uint64(11155420) && monorepoCommit == "ba493e94a25df0f646a040c0899bfd0f4d237c06" {
215219
t.Log("✂️️ Trimming WETH9 bytecode CBOR hash for OP-Sepolia...")
216220
expectedData, err = trimWeth9BytecodeMetadataHash(expectedData)
217221
if err != nil {
218222
err = fmt.Errorf("Regenerated alloc: %w", err)
219223
}
220224
require.NoError(t, err)
225+
221226
gotData, err = trimWeth9BytecodeMetadataHash(gotData)
222227
if err != nil {
223228
err = fmt.Errorf("Registry alloc: %w", err)
@@ -227,10 +232,12 @@ func testGenesisAllocs(t *testing.T, chain *ChainConfig) {
227232

228233
err = os.WriteFile(path.Join(monorepoDir, "regenerated-alloc.json"), expectedData, os.ModePerm) // regenerated
229234
require.NoError(t, err)
235+
230236
err = os.WriteFile(path.Join(monorepoDir, "registry-alloc.json"), gotData, os.ModePerm) // read from registry
231237
require.NoError(t, err)
232238

233-
require.Equal(t, string(expectedData), string(gotData))
239+
l2Time := chain.Genesis.L2Time
240+
require.Equal(t, string(expectedData), string(gotData), "regenerated alloc does not match registry alloc; this may have been caused by using the wrong `genesis_creation_commit`. You must specify the commit at which you deployed your contracts; to find an appropriate commit, run this command against the `optimism` repository: `git rev-list --before=%d HEAD`", l2Time)
234241
}
235242

236243
// This function removes empty storage slots as we know declaring empty slots is functionally equivalent to not declaring them.

0 commit comments

Comments
 (0)