Skip to content
Open
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
19 changes: 11 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,15 @@ func runIt(recipe playground.Recipe) error {
overrides[parts[0]] = parts[1]
}

out, err := playground.NewOutput(outputFlag)
if err != nil {
return err
}

builder := recipe.Artifacts()
builder.OutputDir(outputFlag)
builder.GenesisDelay(genesisDelayFlag)
builder.PrefundedAccounts(prefundedAccounts)
artifacts, err := builder.Build()
if err != nil {
if err := builder.Build(out); err != nil {
return err
}

Expand All @@ -244,13 +247,13 @@ func runIt(recipe playground.Recipe) error {
},
}

svcManager := playground.NewManifest(exCtx, artifacts.Out)
svcManager := playground.NewManifest(exCtx, out)

recipe.Apply(svcManager)

// generate the dot graph
dotGraph := svcManager.GenerateDotGraph()
if err := artifacts.Out.WriteFile("graph.dot", dotGraph); err != nil {
if err := out.WriteFile("graph.dot", dotGraph); err != nil {
return err
}

Expand All @@ -264,7 +267,7 @@ func runIt(recipe playground.Recipe) error {
}

if withPrometheus {
if err := playground.CreatePrometheusServices(svcManager, artifacts.Out); err != nil {
if err := playground.CreatePrometheusServices(svcManager, out); err != nil {
return fmt.Errorf("failed to create prometheus services: %w", err)
}
}
Expand All @@ -278,7 +281,7 @@ func runIt(recipe playground.Recipe) error {
}

cfg := &playground.RunnerConfig{
Out: artifacts.Out,
Out: out,
Manifest: svcManager,
BindHostPortsLocally: !bindExternal,
NetworkName: networkName,
Expand Down Expand Up @@ -362,7 +365,7 @@ func runIt(recipe playground.Recipe) error {
watchdogErr := make(chan error, 1)
if watchdog {
go func() {
if err := playground.RunWatchdog(artifacts.Out, svcManager.Services); err != nil {
if err := playground.RunWatchdog(out, svcManager.Services); err != nil {
watchdogErr <- fmt.Errorf("watchdog failed: %w", err)
}
}()
Expand Down
198 changes: 100 additions & 98 deletions playground/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
var queryReadyCheck []byte

type ArtifactsBuilder struct {
outputDir string
applyLatestL1Fork bool
genesisDelay uint64
applyLatestL2Fork *uint64
Expand All @@ -74,19 +73,13 @@

func NewArtifactsBuilder() *ArtifactsBuilder {
return &ArtifactsBuilder{
outputDir: "",
applyLatestL1Fork: false,
genesisDelay: MinimumGenesisDelay,
l1BlockTimeInSeconds: defaultL1BlockTimeSeconds,
opBlockTimeInSeconds: defaultOpBlockTimeSeconds,
}
}

func (b *ArtifactsBuilder) OutputDir(outputDir string) *ArtifactsBuilder {
b.outputDir = outputDir
return b
}

func (b *ArtifactsBuilder) ApplyLatestL1Fork(applyLatestL1Fork bool) *ArtifactsBuilder {
b.applyLatestL1Fork = applyLatestL1Fork
return b
Expand Down Expand Up @@ -138,32 +131,9 @@
return staticPrefundedAccounts
}

type Artifacts struct {
Out *output
}

func (b *ArtifactsBuilder) Build() (*Artifacts, error) {
func (b *ArtifactsBuilder) Build(out *output) error {
defer utils.StartTimer("artifacts.builder")()

homeDir, err := GetHomeDir()
if err != nil {
return nil, err
}
if b.outputDir == "" {
// Use the $HOMEDIR/devnet as the default output
b.outputDir = filepath.Join(homeDir, "devnet")
}

out := &output{dst: b.outputDir, homeDir: homeDir}

// check if the output directory exists
if out.Exists("") {
log.Printf("deleting existing output directory %s", b.outputDir)
if err := out.Remove(""); err != nil {
return nil, err
}
}

if b.genesisDelay < MinimumGenesisDelay {
log.Printf("genesis delay must be at least %d seconds, using %d", MinimumGenesisDelay, MinimumGenesisDelay)
b.genesisDelay = MinimumGenesisDelay
Expand All @@ -182,10 +152,10 @@
// load the config.yaml file
clConfig, err := params.UnmarshalConfig([]byte(clConfigContentStr), nil)
if err != nil {
return nil, err
return err
}
if err := params.SetActive(clConfig); err != nil {
return nil, err
return err
}

genesisTime := uint64(time.Now().Add(time.Duration(b.genesisDelay) * time.Second).Unix())
Expand All @@ -196,52 +166,17 @@
gen.Config.DepositContractAddress = gethcommon.HexToAddress(config.DepositContractAddress)

// add pre-funded accounts
prefundedBalance, _ := new(big.Int).SetString("10000000000000000000000", 16)

for _, privStr := range b.getPrefundedAccounts() {
priv, err := getPrivKey(privStr)
if err != nil {
return nil, err
}
addr := ecrypto.PubkeyToAddress(priv.PublicKey)
gen.Alloc[addr] = types.Account{
Balance: prefundedBalance,
Nonce: 1,
}
if err := appendPrefundedAccountsToAlloc(&gen.Alloc, b.getPrefundedAccounts()); err != nil {
return err
}

// Apply Optimism pre-state
{
var state struct {
L1StateDump string `json:"l1StateDump"`
}
if err := json.Unmarshal(opState, &state); err != nil {
return nil, fmt.Errorf("failed to unmarshal opState: %w", err)
}

decoded, err := base64.StdEncoding.DecodeString(state.L1StateDump)
opAllocs, err := readOptimismL1Allocs()
if err != nil {
return nil, fmt.Errorf("failed to decode opState: %w", err)
}

// Create gzip reader from the base64 decoded data
gr, err := gzip.NewReader(bytes.NewReader(decoded))
if err != nil {
return nil, fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gr.Close()

// Read and decode the contents
contents, err := io.ReadAll(gr)
if err != nil {
return nil, fmt.Errorf("failed to read opState: %w", err)
}

var alloc types.GenesisAlloc
if err := json.Unmarshal(contents, &alloc); err != nil {
return nil, fmt.Errorf("failed to unmarshal opState: %w", err)
return err
}
maps.Copy(gen.Alloc, alloc)
maps.Copy(gen.Alloc, opAllocs)
}

block := gen.ToBlock()
Expand All @@ -256,20 +191,20 @@

priv, pub, err := interop.DeterministicallyGenerateKeys(0, 100)
if err != nil {
return nil, err
return err
}

depositData, roots, err := interop.DepositDataFromKeysWithExecCreds(priv, pub, 100)
if err != nil {
return nil, err
return err
}

opts := make([]interop.PremineGenesisOpt, 0)
opts = append(opts, interop.WithDepositData(depositData, roots))

state, err := interop.NewPreminedGenesis(context.Background(), genesisTime, 0, 100, v, block, opts...)
if err != nil {
return nil, err
return err
}

err = out.WriteBatch(map[string]interface{}{
Expand All @@ -285,7 +220,7 @@
"scripts/query.sh": queryReadyCheck,
})
if err != nil {
return nil, err
return err
}

{
Expand All @@ -306,9 +241,16 @@
}
}

// Update the allocs to include the same prefunded accounts as the L1 genesis.
allocs := types.GenesisAlloc{}
if err := appendPrefundedAccountsToAlloc(&allocs, b.getPrefundedAccounts()); err != nil {
return err
}

// override l2 genesis, make the timestamp start 2 seconds after the L1 genesis
input := map[string]interface{}{
"timestamp": hexutil.Uint64(opTimestamp).String(),
"allocs": allocs,
}
if forkTime != nil {
// We need to enable prague on the EL to enable the engine v4 calls
Expand All @@ -318,30 +260,15 @@
}
}

// Update the allocs to include the same prefunded accounts as the L1 genesis.
allocs := make(map[string]interface{})
input["alloc"] = allocs
for _, privStr := range b.getPrefundedAccounts() {
priv, err := getPrivKey(privStr)
if err != nil {
return nil, err
}
addr := ecrypto.PubkeyToAddress(priv.PublicKey)
allocs[addr.String()] = map[string]interface{}{
"balance": "0x10000000000000000000000",
"nonce": "0x1",
}
}

newOpGenesis, err := overrideJSON(opGenesis, input)
if err != nil {
return nil, err
return err
}

// the hash of the genesis has changed beause of the timestamp so we need to account for that
opGenesisBlock, err := toOpBlock(newOpGenesis)
if err != nil {
return nil, fmt.Errorf("failed to convert opGenesis to block: %w", err)
return fmt.Errorf("failed to convert opGenesis to block: %w", err)
}

opGenesisHash := opGenesisBlock.Hash()
Expand Down Expand Up @@ -372,18 +299,18 @@

newOpRollup, err := overrideJSON(opRollupConfig, rollupInput)
if err != nil {
return nil, err
return err
}

if err := out.WriteFile("l2-genesis.json", newOpGenesis); err != nil {
return nil, err
return err
}
if err := out.WriteFile("rollup.json", newOpRollup); err != nil {
return nil, err
return err
}
}

return &Artifacts{Out: out}, nil
return nil
}

type OpGenesisTmplInput struct {
Expand Down Expand Up @@ -466,6 +393,28 @@
enodeAddrSeq *big.Int
}

func NewOutput(dst string) (*output, error) {
homeDir, err := GetHomeDir()
if err != nil {
return nil, err
}
if dst == "" {
// Use the $HOMEDIR/devnet as the default output
dst = filepath.Join(homeDir, "devnet")
}

out := &output{dst: dst, homeDir: homeDir}

// check if the output directory exists
if out.Exists("") {
if err := out.Remove(""); err != nil {
return nil, err
}
}

return out, nil
}

func (o *output) AbsoluteDstPath() (string, error) {
return filepath.Abs(o.dst)
}
Expand Down Expand Up @@ -716,7 +665,7 @@
return t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8
}

func applyTemplate2(templateStr []byte, input interface{}) ([]byte, error) {

Check failure on line 668 in playground/artifacts.go

View workflow job for this annotation

GitHub Actions / Lint

func applyTemplate2 is unused (U1000)
tpl, err := template.New("").Parse(string(templateStr))
if err != nil {
return nil, fmt.Errorf("failed to parse template: %w", err)
Expand Down Expand Up @@ -769,3 +718,56 @@

return &EnodeAddr{PrivKey: privKey, Artifact: fileName}
}

func readOptimismL1Allocs() (types.GenesisAlloc, error) {
var state struct {
L1StateDump string `json:"l1StateDump"`
}
if err := json.Unmarshal(opState, &state); err != nil {
return nil, fmt.Errorf("failed to unmarshal opState: %w", err)
}

decoded, err := base64.StdEncoding.DecodeString(state.L1StateDump)
if err != nil {
return nil, fmt.Errorf("failed to decode opState: %w", err)
}

// Create gzip reader from the base64 decoded data
gr, err := gzip.NewReader(bytes.NewReader(decoded))
if err != nil {
return nil, fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gr.Close()

// Read and decode the contents
contents, err := io.ReadAll(gr)
if err != nil {
return nil, fmt.Errorf("failed to read opState: %w", err)
}

var alloc types.GenesisAlloc
if err := json.Unmarshal(contents, &alloc); err != nil {
return nil, fmt.Errorf("failed to unmarshal opState: %w", err)
}

return alloc, nil
}

var (
prefundedBalance, _ = new(big.Int).SetString("10000000000000000000000", 16)
)

func appendPrefundedAccountsToAlloc(allocs *types.GenesisAlloc, privKeys []string) error {
for _, privStr := range privKeys {
priv, err := getPrivKey(privStr)
if err != nil {
return err
}
addr := ecrypto.PubkeyToAddress(priv.PublicKey)
(*allocs)[addr] = types.Account{
Balance: prefundedBalance,
Nonce: 1,
}
}
return nil
}
2 changes: 1 addition & 1 deletion playground/components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (tt *testFramework) test(s ServiceGen, args []string) *Manifest {
err := recipe.Flags().Parse(args)
require.NoError(t, err)

_, err = recipe.Artifacts().OutputDir(e2eTestDir).Build()
err = recipe.Artifacts().Build(o)
require.NoError(t, err)
}

Expand Down
Loading
Loading