diff --git a/kurtosis-devnet/isthmus.yaml b/kurtosis-devnet/isthmus.yaml index cf1869fa0b05e..8c689bca593ce 100644 --- a/kurtosis-devnet/isthmus.yaml +++ b/kurtosis-devnet/isthmus.yaml @@ -90,7 +90,7 @@ optimism_package: image: {{ localDockerImage "op-deployer" }} l1_artifacts_locator: {{ localContractArtifacts "l1" }} l2_artifacts_locator: {{ localContractArtifacts "l2" }} - global_deploy_overrides: + overrides: faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }} global_log_level: "info" global_node_selectors: {} diff --git a/kurtosis-devnet/pectra.yaml b/kurtosis-devnet/pectra.yaml index 8d0098d895612..a1424ad31036e 100644 --- a/kurtosis-devnet/pectra.yaml +++ b/kurtosis-devnet/pectra.yaml @@ -61,7 +61,7 @@ optimism_package: image: {{ localDockerImage "op-deployer" }} l1_artifacts_locator: {{ localContractArtifacts "l1" }} l2_artifacts_locator: {{ localContractArtifacts "l2" }} - global_deploy_overrides: + overrides: faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }} global_log_level: "info" global_node_selectors: {} diff --git a/kurtosis-devnet/pkg/kurtosis/endpoints.go b/kurtosis-devnet/pkg/kurtosis/endpoints.go index 7a7b7ab152928..803f1df9bb13d 100644 --- a/kurtosis-devnet/pkg/kurtosis/endpoints.go +++ b/kurtosis-devnet/pkg/kurtosis/endpoints.go @@ -8,52 +8,39 @@ import ( "github.com/ethereum-optimism/optimism/devnet-sdk/descriptors" "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/inspect" "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec" - "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/depset" ) -type ChainSpec struct { - spec.ChainSpec - DepSets map[string]descriptors.DepSet -} +const ( + l1Placeholder = "" +) // ServiceFinder is the main entry point for finding services and their endpoints type ServiceFinder struct { services inspect.ServiceMap nodeServices []string l2ServicePrefix string - l2Networks []ChainSpec - globalServices []string -} -// ServiceFinderOption configures a ServiceFinder -type ServiceFinderOption func(*ServiceFinder) + l2Chains []*spec.ChainSpec + depsets map[string]descriptors.DepSet -// WithNodeServices sets the node service identifiers -func WithNodeServices(services []string) ServiceFinderOption { - return func(f *ServiceFinder) { - f.nodeServices = services - } + triagedServices []*triagedService } -// WithL2ServicePrefix sets the prefix used to identify L2 services -func WithL2ServicePrefix(prefix string) ServiceFinderOption { - return func(f *ServiceFinder) { - f.l2ServicePrefix = prefix - } -} +// ServiceFinderOption configures a ServiceFinder +type ServiceFinderOption func(*ServiceFinder) -// WithL2Networks sets the L2 networks -func WithL2Networks(networks []ChainSpec) ServiceFinderOption { +// WithL2Chains sets the L2 networks +func WithL2Chains(networks []*spec.ChainSpec) ServiceFinderOption { return func(f *ServiceFinder) { - f.l2Networks = networks + f.l2Chains = networks } } -// WithGlobalServices sets the global services -func WithGlobalServices(services []string) ServiceFinderOption { +// WithDepSets sets the dependency sets +func WithDepSets(depsets map[string]descriptors.DepSet) ServiceFinderOption { return func(f *ServiceFinder) { - f.globalServices = services + f.depsets = depsets } } @@ -63,187 +50,233 @@ func NewServiceFinder(services inspect.ServiceMap, opts ...ServiceFinderOption) services: services, nodeServices: []string{"cl", "el"}, l2ServicePrefix: "op-", - globalServices: []string{"op-faucet"}, } for _, opt := range opts { opt(f) } + + f.triage() return f } -// FindL1Services finds L1 nodes. -func (f *ServiceFinder) FindL1Services() ([]descriptors.Node, descriptors.RedundantServiceMap) { - return f.findRPCEndpoints(func(serviceName string) (string, int, bool) { - // Find node services and global services - allServices := append(f.nodeServices, f.globalServices...) - for _, service := range allServices { - if strings.HasPrefix(serviceName, service) { - // strip the L2 prefix if it's there. - name := strings.TrimPrefix(serviceName, f.l2ServicePrefix) - tag, idx := f.serviceTag(name) - return tag, idx, true +type chainAcceptor func(*spec.ChainSpec) bool + +type serviceParser func(string) (int, chainAcceptor, bool) + +type triagedService struct { + tag string // service tag + idx int // service index (for nodes) + svc *descriptors.Service + accept chainAcceptor +} + +func acceptAll(c *spec.ChainSpec) bool { + return true +} + +func acceptNameOrID(s string) chainAcceptor { + return func(c *spec.ChainSpec) bool { + return c.Name == s || c.NetworkID == s + } +} + +func acceptNamesOrIDs(names ...string) chainAcceptor { + acceptors := make([]chainAcceptor, 0) + for _, name := range names { + acceptors = append(acceptors, acceptNameOrID(name)) + } + return combineAcceptors(acceptors...) +} + +func acceptL1() chainAcceptor { + return acceptNameOrID(l1Placeholder) +} + +func combineAcceptors(acceptors ...chainAcceptor) chainAcceptor { + return func(c *spec.ChainSpec) bool { + for _, acceptor := range acceptors { + if acceptor(c) { + return true } } - return "", 0, false - }) + return false + } } -// FindL2Services finds L2 nodes and services for a specific network -func (f *ServiceFinder) FindL2Services(s ChainSpec) ([]descriptors.Node, descriptors.RedundantServiceMap) { - network := s.Name - networkID := s.NetworkID - return f.findRPCEndpoints(func(serviceName string) (string, int, bool) { - possibleSuffixes := []string{"-" + network, "-" + networkID} - for _, suffix := range possibleSuffixes { - if strings.HasSuffix(serviceName, suffix) { - name := strings.TrimSuffix(serviceName, suffix) - tag, idx := f.serviceTag(strings.TrimPrefix(name, f.l2ServicePrefix)) - return tag, idx, true +func (f *ServiceFinder) triageNode(prefix string) serviceParser { + return func(serviceName string) (int, chainAcceptor, bool) { + extractIndex := func(s string) int { + // Extract numeric index from service name + parts := strings.Split(s, "-") + if idx, err := strconv.ParseUint(parts[0], 10, 32); err == nil { + return int(idx) - 1 } + return 0 } - // skip over the other L2 services - for _, l2Network := range f.l2Networks { - if strings.HasSuffix(serviceName, "-"+l2Network.Name) || strings.HasSuffix(serviceName, "-"+l2Network.NetworkID) { - return "", 0, false - } + if strings.HasPrefix(serviceName, prefix) { // L1 + idx := extractIndex(strings.TrimPrefix(serviceName, prefix)) + return idx, acceptL1(), true } - // supervisor is special: itcovers multiple networks, so we need to - // identify the depset this chain belongs to - if strings.HasPrefix(serviceName, "op-supervisor") { - // temporary backward-compatible hack for single op-supervisor instance - if serviceName == "op-supervisor" { - return "supervisor", 0, true - } + l2Prefix := f.l2ServicePrefix + prefix + if strings.HasPrefix(serviceName, l2Prefix) { + serviceName = strings.TrimPrefix(serviceName, l2Prefix) + // first we have the chain ID + parts := strings.Split(serviceName, "-") + chainID := parts[0] + idx := extractIndex(parts[1]) + return idx, acceptNameOrID(chainID), true + } - for dsName, ds := range s.DepSets { - suffix := "-" + dsName - if !strings.HasSuffix(serviceName, suffix) { - // not the right depset for this supervisor, skip it - continue - } - var depSet depset.StaticConfigDependencySet - if err := json.Unmarshal(ds, &depSet); err != nil { - return "", 0, false - } - var chainID eth.ChainID - if err := chainID.UnmarshalText([]byte(s.NetworkID)); err != nil { - return "", 0, false - } - if depSet.HasChain(chainID) { - name := strings.TrimSuffix(serviceName, suffix) - tag, idx := f.serviceTag(strings.TrimPrefix(name, f.l2ServicePrefix)) - return tag, idx, true - } - } - // this supervisor is irrelevant to this chain, skip it - return "", 0, false + return 0, nil, false + } +} + +func (f *ServiceFinder) triageExclusiveL2Service(prefix string) serviceParser { + idx := -1 + return func(serviceName string) (int, chainAcceptor, bool) { + if strings.HasPrefix(serviceName, prefix) { + suffix := strings.TrimPrefix(serviceName, prefix) + return idx, acceptNameOrID(suffix), true } + return idx, nil, false + } +} - // challenger is special too, and right now there's no way to identify which L2s it covers - // TODO: fix this horror, right now we're forced to assume there's only one. - if strings.HasPrefix(serviceName, "op-challenger") { - return "challenger", 0, true +func (f *ServiceFinder) triageMultiL2Service(prefix string) serviceParser { + idx := -1 + return func(serviceName string) (int, chainAcceptor, bool) { + if strings.HasPrefix(serviceName, prefix) { + suffix := strings.TrimPrefix(serviceName, prefix) + parts := strings.Split(suffix, "-") + // parts[0] is the service ID + return idx, acceptNamesOrIDs(parts[1:]...), true } + return idx, nil, false + } +} - // Some services don't have a network suffix, as they span multiple chains - if strings.HasPrefix(serviceName, f.l2ServicePrefix) { - tag, idx := f.serviceTag(strings.TrimPrefix(serviceName, f.l2ServicePrefix)) - return tag, idx, true +func (f *ServiceFinder) triageSuperchainService(prefix string) serviceParser { + idx := -1 + return func(serviceName string) (int, chainAcceptor, bool) { + if strings.HasPrefix(serviceName, prefix) { + suffix := strings.TrimPrefix(serviceName, prefix) + parts := strings.Split(suffix, "-") + // parts[0] is the service ID + ds, ok := f.depsets[parts[1]] + if !ok { + return idx, nil, false + } + var depSet depset.StaticConfigDependencySet + if err := json.Unmarshal(ds, &depSet); err != nil { + return idx, nil, false + } + + chains := make([]string, 0) + for _, chain := range depSet.Chains() { + chains = append(chains, chain.String()) + } + return idx, acceptNamesOrIDs(chains...), true } - return "", 0, false - }) + return idx, nil, false + } } -// findRPCEndpoints looks for services matching the given predicate that have an RPC port -func (f *ServiceFinder) findRPCEndpoints(matchService func(string) (string, int, bool)) ([]descriptors.Node, descriptors.RedundantServiceMap) { - serviceMap := make(descriptors.RedundantServiceMap) - var nodes []descriptors.Node +func (f *ServiceFinder) triageUniversalL2Service(name string) serviceParser { + idx := -1 + return func(serviceName string) (int, chainAcceptor, bool) { + if serviceName == name { + return idx, acceptAll, true + } + return idx, nil, false + } +} +func (f *ServiceFinder) triage() { + rules := map[string]serviceParser{ + "el": f.triageNode("el-"), + "cl": f.triageNode("cl-"), + "batcher": f.triageExclusiveL2Service("op-batcher-"), + "proposer": f.triageExclusiveL2Service("op-proposer-"), + "proxyd": f.triageExclusiveL2Service("proxyd-"), + "supervisor": f.triageSuperchainService("op-supervisor-"), + "challenger": f.triageMultiL2Service("op-challenger-"), + "faucet": f.triageUniversalL2Service("op-faucet"), + } + + triagedServices := []*triagedService{} for serviceName, ports := range f.services { - if serviceIdentifier, num, ok := matchService(serviceName); ok { - var allocated bool - for _, service := range f.nodeServices { - if serviceIdentifier == service { - if num > len(nodes) { - // Extend the slice to accommodate the required index - for i := len(nodes); i < num; i++ { - nodes = append(nodes, descriptors.Node{ - Services: make(descriptors.ServiceMap), - }) - } - } - endpoints := make(descriptors.EndpointMap) - for portName, portInfo := range ports { - endpoints[portName] = portInfo - } - nodes[num-1].Services[serviceIdentifier] = &descriptors.Service{ - Name: serviceName, - Endpoints: endpoints, - } - allocated = true - } - } - if !allocated { - endpoints := make(descriptors.EndpointMap) - for portName, portInfo := range ports { - endpoints[portName] = portInfo - } - serviceMap[serviceIdentifier] = []*descriptors.Service{ - &descriptors.Service{ - Name: serviceName, - Endpoints: endpoints, - }, - } + endpoints := make(descriptors.EndpointMap) + for portName, portInfo := range ports { + endpoints[portName] = portInfo + } + svc := &descriptors.Service{ + Name: serviceName, + Endpoints: endpoints, + } + for tag, rule := range rules { + if idx, accept, ok := rule(serviceName); ok { + triagedServices = append(triagedServices, &triagedService{ + tag: tag, + idx: idx, + accept: accept, + svc: svc, + }) } } } - return nodes, serviceMap + + f.triagedServices = triagedServices } -// serviceTag returns the shorthand service tag and index if it's a service with multiple instances -func (f *ServiceFinder) serviceTag(serviceName string) (string, int) { - // Find last occurrence of a number sequence - lastStart := -1 - lastEnd := -1 +func (f *ServiceFinder) findChainServices(chain *spec.ChainSpec) ([]descriptors.Node, descriptors.RedundantServiceMap) { + var nodes []descriptors.Node + services := make(descriptors.RedundantServiceMap) - // Scan through the string to find number sequences - for i := 0; i < len(serviceName); i++ { - if serviceName[i] >= '0' && serviceName[i] <= '9' { - start := i - // Find end of this number sequence - for i < len(serviceName) && serviceName[i] >= '0' && serviceName[i] <= '9' { - i++ + var selected []*triagedService + for _, svc := range f.triagedServices { + if svc.accept(chain) { + if svc.idx >= len(nodes) { + // just resize the slice, that'll create "0" items for the new indices. + // We don't expect more than a few nodes per chain, so this is fine. + nodes = make([]descriptors.Node, svc.idx+1) + } + if svc.idx < 0 { // not a node service + // create a dummy entry for the service + services[svc.tag] = nil } - lastStart = start - lastEnd = i + selected = append(selected, svc) } } - if lastStart == -1 { - return serviceName, 0 + // Now our slice is the right size, and our map has the right keys, we can just fill in the data + for _, svc := range selected { + if svc.idx >= 0 { + node := nodes[svc.idx] + if node.Services == nil { + node.Services = make(descriptors.ServiceMap) + } + node.Services[svc.tag] = svc.svc + nodes[svc.idx] = node + } else { + services[svc.tag] = append(services[svc.tag], svc.svc) + } } - idx, err := strconv.Atoi(serviceName[lastStart:lastEnd]) - if err != nil { - return serviceName, 0 - } + return nodes, services +} - // If there are multiple numbers, return just the base name - // Find the first number sequence - firstStart := strings.IndexFunc(serviceName, func(r rune) bool { - return r >= '0' && r <= '9' - }) - if firstStart != lastStart { - // Multiple numbers found, return just the base name - tag := serviceName[:firstStart] - tag = strings.TrimRight(tag, "-") - return tag, idx +// FindL1Services finds L1 nodes. +func (f *ServiceFinder) FindL1Services() ([]descriptors.Node, descriptors.RedundantServiceMap) { + chain := &spec.ChainSpec{ + Name: l1Placeholder, + NetworkID: l1Placeholder, } + return f.findChainServices(chain) +} - // Single number case - tag := serviceName[:lastStart] - tag = strings.TrimRight(tag, "-") - return tag, idx +// FindL2Services finds L2 nodes and services for a specific network +func (f *ServiceFinder) FindL2Services(s *spec.ChainSpec) ([]descriptors.Node, descriptors.RedundantServiceMap) { + return f.findChainServices(s) } diff --git a/kurtosis-devnet/pkg/kurtosis/endpoints_test.go b/kurtosis-devnet/pkg/kurtosis/endpoints_test.go index a577d3bd72824..2fbd095709e4b 100644 --- a/kurtosis-devnet/pkg/kurtosis/endpoints_test.go +++ b/kurtosis-devnet/pkg/kurtosis/endpoints_test.go @@ -1,447 +1,380 @@ package kurtosis import ( + "encoding/json" "testing" "github.com/ethereum-optimism/optimism/devnet-sdk/descriptors" "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/inspect" "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/depset" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestFindRPCEndpoints(t *testing.T) { - testServices := make(inspect.ServiceMap) - - testServices["el-1-geth-lighthouse"] = inspect.PortMap{ - "metrics": {Port: 52643}, - "tcp-discovery": {Port: 52644}, - "udp-discovery": {Port: 51936}, - "engine-rpc": {Port: 52642}, - "rpc": {Port: 52645}, - "ws": {Port: 52646}, +func TestFindChainServices(t *testing.T) { + // Create test chains based on the scenario + chain1 := &spec.ChainSpec{ + Name: "op-kurtosis-1", + NetworkID: "2151908", } - - testServices["op-batcher-op-kurtosis"] = inspect.PortMap{ - "http": {Port: 53572}, + chain2 := &spec.ChainSpec{ + Name: "op-kurtosis-2", + NetworkID: "2151909", } + chains := []*spec.ChainSpec{chain1, chain2} - testServices["op-cl-1-op-node-op-geth-op-kurtosis"] = inspect.PortMap{ - "udp-discovery": {Port: 50990}, - "http": {Port: 53503}, - "tcp-discovery": {Port: 53504}, - } + // Create mock dependency set + depSets := createTestDepSets(t) - testServices["op-el-1-op-geth-op-node-1234"] = inspect.PortMap{ - "udp-discovery": {Port: 53233}, - "engine-rpc": {Port: 53399}, - "metrics": {Port: 53400}, - "rpc": {Port: 53402}, - "ws": {Port: 53403}, - "tcp-discovery": {Port: 53401}, - } + // Create mock service map based on inspect data from the scenario + services := createTestServiceMap() - testServices["vc-1-geth-lighthouse"] = inspect.PortMap{ - "metrics": {Port: 53149}, - } + // Create service finder with the test data + finder := NewServiceFinder( + services, + WithL2Chains(chains), + WithDepSets(depSets), + ) - testServices["cl-1-lighthouse-geth"] = inspect.PortMap{ - "metrics": {Port: 52691}, - "tcp-discovery": {Port: 52692}, - "udp-discovery": {Port: 58275}, - "http": {Port: 52693}, - } + // Test triage directly to ensure services are correctly triaged + t.Run("triage services", func(t *testing.T) { + assert.NotNil(t, finder.triagedServices, "Triaged services should not be nil") + assert.NotEmpty(t, finder.triagedServices, "Triaged services should not be empty") - tests := []struct { - name string - services inspect.ServiceMap - findFn func(*ServiceFinder) ([]descriptors.Node, descriptors.RedundantServiceMap) - wantNodes []descriptors.Node - wantServices descriptors.RedundantServiceMap - }{ - { - name: "find L1 endpoints", - services: testServices, - findFn: func(f *ServiceFinder) ([]descriptors.Node, descriptors.RedundantServiceMap) { - return f.FindL1Services() - }, - wantNodes: []descriptors.Node{ - { - Services: descriptors.ServiceMap{ - "cl": &descriptors.Service{ - Name: "cl-1-lighthouse-geth", - Endpoints: descriptors.EndpointMap{ - "metrics": {Port: 52691}, - "tcp-discovery": {Port: 52692}, - "udp-discovery": {Port: 58275}, - "http": {Port: 52693}, - }, - }, - "el": &descriptors.Service{ - Name: "el-1-geth-lighthouse", - Endpoints: descriptors.EndpointMap{ - "metrics": {Port: 52643}, - "tcp-discovery": {Port: 52644}, - "udp-discovery": {Port: 51936}, - "engine-rpc": {Port: 52642}, - "rpc": {Port: 52645}, - "ws": {Port: 52646}, - }, - }, - }, - }, - }, - wantServices: descriptors.RedundantServiceMap{}, - }, - { - name: "find op-kurtosis L2 endpoints", - services: testServices, - findFn: func(f *ServiceFinder) ([]descriptors.Node, descriptors.RedundantServiceMap) { - return f.FindL2Services(ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "op-kurtosis", - NetworkID: "1234", - }, - DepSets: map[string]descriptors.DepSet{}, - }) - }, - wantNodes: []descriptors.Node{ - { - Services: descriptors.ServiceMap{ - "cl": &descriptors.Service{ - Name: "op-cl-1-op-node-op-geth-op-kurtosis", - Endpoints: descriptors.EndpointMap{ - "udp-discovery": {Port: 50990}, - "http": {Port: 53503}, - "tcp-discovery": {Port: 53504}, - }, - }, - "el": &descriptors.Service{ - Name: "op-el-1-op-geth-op-node-1234", - Endpoints: descriptors.EndpointMap{ - "udp-discovery": {Port: 53233}, - "engine-rpc": {Port: 53399}, - "metrics": {Port: 53400}, - "tcp-discovery": {Port: 53401}, - "rpc": {Port: 53402}, - "ws": {Port: 53403}, - }, - }, - }, - }, - }, - wantServices: descriptors.RedundantServiceMap{ - "batcher": []*descriptors.Service{ - &descriptors.Service{ - Name: "op-batcher-op-kurtosis", - Endpoints: descriptors.EndpointMap{ - "http": {Port: 53572}, - }, - }, - }, - }, - }, - { - name: "custom host in endpoint", - services: inspect.ServiceMap{ - "op-batcher-custom-host": inspect.PortMap{ - "http": {Host: "custom.host", Port: 8080}, - }, - }, - findFn: func(f *ServiceFinder) ([]descriptors.Node, descriptors.RedundantServiceMap) { - return f.FindL2Services(ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "custom-host", - NetworkID: "0000", - }, - DepSets: map[string]descriptors.DepSet{}, - }) - }, - wantNodes: nil, - wantServices: descriptors.RedundantServiceMap{ - "batcher": []*descriptors.Service{ - &descriptors.Service{ - Name: "op-batcher-custom-host", - Endpoints: descriptors.EndpointMap{ - "http": {Host: "custom.host", Port: 8080}, - }, - }, - }, - }, - }, - } + // Count service types + tagCount := make(map[string]int) + for _, svc := range finder.triagedServices { + tagCount[svc.tag]++ + } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - finder := NewServiceFinder(tt.services, WithL2Networks([]ChainSpec{ - {ChainSpec: spec.ChainSpec{Name: "op-kurtosis", NetworkID: "1234"}}, - {ChainSpec: spec.ChainSpec{Name: "network1", NetworkID: "1111"}}, - {ChainSpec: spec.ChainSpec{Name: "network2", NetworkID: "2222"}}, - {ChainSpec: spec.ChainSpec{Name: "custom-host", NetworkID: "0000"}}, - })) - gotNodes, gotServices := tt.findFn(finder) - assert.Equal(t, tt.wantNodes, gotNodes) - assert.Equal(t, tt.wantServices, gotServices) - }) - } + // Verify expected service counts + assert.Equal(t, 3, tagCount["cl"], "Should have 3 CL services") + assert.Equal(t, 3, tagCount["el"], "Should have 3 EL service") + assert.Equal(t, 2, tagCount["batcher"], "Should have 2 batcher services") + assert.Equal(t, 2, tagCount["proposer"], "Should have 2 proposer services") + assert.Equal(t, 2, tagCount["proxyd"], "Should have 2 proxyd services") + assert.Equal(t, 1, tagCount["challenger"], "Should have 1 challenger service") + assert.Equal(t, 1, tagCount["supervisor"], "Should have 1 supervisor service") + assert.Equal(t, 1, tagCount["faucet"], "Should have 1 faucet service") + }) + + // Test L1 service discovery + t.Run("L1 services", func(t *testing.T) { + nodes, services := finder.FindL1Services() + + // Verify L1 nodes + assert.Equal(t, 1, len(nodes), "Should have exactly 1 node") + + // Verify L1 services + assert.Equal(t, 1, len(services), "Should have exactly 1 service") + assert.Contains(t, services, "faucet", "Should have faucet service") + }) + + // Test L2 services for both chains + t.Run("L2 chain1 services", func(t *testing.T) { + nodes, services := finder.FindL2Services(chain1) + + assert.Equal(t, 1, len(nodes), "Should have exactly 1 node") + assert.Equal(t, 6, len(services), "Should have exactly 6 services") + + assert.Contains(t, services, "batcher", "Should have batcher service") + assert.Contains(t, services, "proposer", "Should have proposer service") + assert.Contains(t, services, "proxyd", "Should have proxyd service") + assert.Contains(t, services, "challenger", "Should have challenger service") + assert.Contains(t, services, "supervisor", "Should have supervisor service") + assert.Contains(t, services, "faucet", "Should have faucet service") + }) } -func TestFindL2ServicesSkipsOtherNetworks(t *testing.T) { - n1 := ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "network1", - NetworkID: "1111", - }, - DepSets: map[string]descriptors.DepSet{}, +// createTestServiceMap creates a service map based on the provided scenario output +func createTestServiceMap() inspect.ServiceMap { + services := inspect.ServiceMap{ + // L1 Services - must match pattern expected by triageNode function + "cl-1-teku-geth": { + "http": &descriptors.PortInfo{Port: 32777}, + "metrics": &descriptors.PortInfo{Port: 32778}, + "tcp-discovery": &descriptors.PortInfo{Port: 32779}, + "udp-discovery": &descriptors.PortInfo{Port: 32769}, + }, + "el-1-geth-teku": { + "engine-rpc": &descriptors.PortInfo{Port: 32774}, + "metrics": &descriptors.PortInfo{Port: 32775}, + "rpc": &descriptors.PortInfo{Port: 32772}, + "tcp-discovery": &descriptors.PortInfo{Port: 32776}, + "udp-discovery": &descriptors.PortInfo{Port: 32768}, + "ws": &descriptors.PortInfo{Port: 32773}, + }, + "fileserver": { + "http": &descriptors.PortInfo{Port: 32771}, + }, + "grafana": { + "http": &descriptors.PortInfo{Port: 32815}, + }, + "prometheus": { + "http": &descriptors.PortInfo{Port: 32814}, + }, + + // L2 Chain1 Services + "op-batcher-op-kurtosis-1": { + "http": &descriptors.PortInfo{Port: 32791}, + "metrics": &descriptors.PortInfo{Port: 32792}, + }, + "op-proposer-op-kurtosis-1": { + "http": &descriptors.PortInfo{Port: 32793}, + "metrics": &descriptors.PortInfo{Port: 32794}, + }, + "op-cl-2151908-1-op-node-op-geth-op-kurtosis-1": { + "http": &descriptors.PortInfo{Port: 32785}, + "metrics": &descriptors.PortInfo{Port: 32786}, + "rpc-interop": &descriptors.PortInfo{Port: 32788}, + "tcp-discovery": &descriptors.PortInfo{Port: 32787}, + "udp-discovery": &descriptors.PortInfo{Port: 32771}, + }, + "op-el-2151908-1-op-geth-op-node-op-kurtosis-1": { + "engine-rpc": &descriptors.PortInfo{Port: 32782}, + "metrics": &descriptors.PortInfo{Port: 32783}, + "rpc": &descriptors.PortInfo{Port: 32780}, + "tcp-discovery": &descriptors.PortInfo{Port: 32784}, + "udp-discovery": &descriptors.PortInfo{Port: 32770}, + "ws": &descriptors.PortInfo{Port: 32781}, + }, + "proxyd-2151908": { + "http": &descriptors.PortInfo{Port: 32790}, + "metrics": &descriptors.PortInfo{Port: 32789}, + }, + + // L2 Chain2 Services + "op-batcher-op-kurtosis-2": { + "http": &descriptors.PortInfo{Port: 32806}, + "metrics": &descriptors.PortInfo{Port: 32807}, + }, + "op-proposer-op-kurtosis-2": { + "http": &descriptors.PortInfo{Port: 32808}, + "metrics": &descriptors.PortInfo{Port: 32809}, + }, + "op-cl-2151909-1-op-node-op-geth-op-kurtosis-2": { + "http": &descriptors.PortInfo{Port: 32800}, + "metrics": &descriptors.PortInfo{Port: 32801}, + "rpc-interop": &descriptors.PortInfo{Port: 32803}, + "tcp-discovery": &descriptors.PortInfo{Port: 32802}, + "udp-discovery": &descriptors.PortInfo{Port: 32773}, + }, + "op-el-2151909-1-op-geth-op-node-op-kurtosis-2": { + "engine-rpc": &descriptors.PortInfo{Port: 32797}, + "metrics": &descriptors.PortInfo{Port: 32798}, + "rpc": &descriptors.PortInfo{Port: 32795}, + "tcp-discovery": &descriptors.PortInfo{Port: 32799}, + "udp-discovery": &descriptors.PortInfo{Port: 32772}, + "ws": &descriptors.PortInfo{Port: 32796}, + }, + "proxyd-2151909": { + "http": &descriptors.PortInfo{Port: 32805}, + "metrics": &descriptors.PortInfo{Port: 32804}, + }, + + // Shared L2 Services + "op-faucet": { + "rpc": &descriptors.PortInfo{Port: 32813}, + }, + "op-challenger-service-2151908-2151909": { + "metrics": &descriptors.PortInfo{Port: 32812}, + }, + "op-supervisor-service-superchain": { + "metrics": &descriptors.PortInfo{Port: 32811}, + "rpc": &descriptors.PortInfo{Port: 32810}, + }, + "validator-key-generation-cl-validator-keystore": {}, } - n2 := ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "network2", - NetworkID: "2222", + + return services +} + +// createTestDepSets creates test dependency sets for the test +func createTestDepSets(t *testing.T) map[string]descriptors.DepSet { + // Create the dependency set for the superchain + depSetData := map[eth.ChainID]*depset.StaticConfigDependency{ + eth.ChainIDFromUInt64(2151908): { + ChainIndex: 2151908, + ActivationTime: 0, + HistoryMinTime: 0, }, - DepSets: map[string]descriptors.DepSet{}, - } - n3 := ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "network3", - NetworkID: "3333", + eth.ChainIDFromUInt64(2151909): { + ChainIndex: 2151909, + ActivationTime: 0, + HistoryMinTime: 0, }, - DepSets: map[string]descriptors.DepSet{}, } - // Create a service map with services from multiple L2 networks - services := inspect.ServiceMap{ - // network1 services - "op-batcher-network1": inspect.PortMap{ - "http": {Port: 8080}, - }, - "op-proposer-network1": inspect.PortMap{ - "http": {Port: 8082}, - }, - "op-cl-1-op-node-op-geth-network1": inspect.PortMap{ - "http": {Port: 8084}, - }, + depSet, err := depset.NewStaticConfigDependencySet(depSetData) + require.NoError(t, err) - // network2 services - "op-batcher-network2": inspect.PortMap{ - "http": {Port: 8081}, - }, - "op-proposer-2222": inspect.PortMap{ - "http": {Port: 8083}, - }, - "op-cl-1-op-node-op-geth-network2": inspect.PortMap{ - "http": {Port: 8085}, - }, + jsonData, err := json.Marshal(depSet) + require.NoError(t, err) - // network3 services - "op-batcher-network3": inspect.PortMap{ - "http": {Port: 8086}, - }, - "op-proposer-network3": inspect.PortMap{ - "http": {Port: 8087}, - }, - "op-cl-1-op-node-op-geth-network3": inspect.PortMap{ - "http": {Port: 8088}, - }, + return map[string]descriptors.DepSet{ + "superchain": descriptors.DepSet(jsonData), + } +} - // Common service without network suffix - "op-common-service": inspect.PortMap{ - "http": {Port: 8089}, - }, +// TestTriageFunctions tests the actual implementation of triage functions +func TestTriageFunctions(t *testing.T) { + // Create a minimal finder with default values + finder := &ServiceFinder{ + services: make(inspect.ServiceMap), + nodeServices: []string{"cl", "el"}, + l2ServicePrefix: "op-", } - finder := NewServiceFinder( - services, - WithL2Networks([]ChainSpec{n1, n2, n3}), - ) + // Test the triageNode function for recognizing services + t.Run("triageNode", func(t *testing.T) { + // Test CL node parser + parser := finder.triageNode("cl-") + + // Test L1 node format + idx, accept, ok := parser("cl-1-teku-geth") + assert.True(t, ok, "Should recognize L1 CL node") + assert.Equal(t, 0, idx, "Should extract index 0 from L1 CL node") + assert.True(t, accept(&spec.ChainSpec{Name: l1Placeholder}), "Should accept L1") + + // Test L2 node format + idx, accept, ok = parser("op-cl-2151908-1-op-node-op-geth-op-kurtosis-1") + assert.True(t, ok, "Should recognize L2 CL node") + assert.Equal(t, 0, idx, "Should extract index 0 from L2 CL node") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "2151908"}), "Should accept matching chain ID") + assert.False(t, accept(&spec.ChainSpec{NetworkID: "2151909"}), "Should not accept different chain ID") + + // Test with various suffixes to see what is recognized + _, _, ok = parser("cl-1-teku-geth-with-extra-parts") + assert.True(t, ok, "Should recognize L1 CL node regardless of suffix") + + _, _, ok = parser("op-cl-2151908-1-op-node-op-geth-op-kurtosis-1-with-extra-parts") + assert.True(t, ok, "Should recognize L2 CL node regardless of suffix") + + // This is considered invalid + _, _, ok = parser("cl") + assert.False(t, ok, "Should not recognize simple 'cl'") + + _, _, ok = parser("op-cl") + assert.False(t, ok, "Should not recognize simple 'op-cl'") + }) - // Test finding services for network2 - t.Run("find network2 services", func(t *testing.T) { - nodes, serviceMap := finder.FindL2Services(n2) + // Test the exclusive L2 service parser (batcher, proposer, proxyd) + t.Run("triageExclusiveL2Service", func(t *testing.T) { + parser := finder.triageExclusiveL2Service("op-batcher-") - // Verify nodes - assert.Len(t, nodes, 1) - if len(nodes) > 0 { - assert.Contains(t, nodes[0].Services, "cl") - assert.Equal(t, "op-cl-1-op-node-op-geth-network2", nodes[0].Services["cl"].Name) - } + // Valid format + idx, accept, ok := parser("op-batcher-123456") + assert.True(t, ok, "Should recognize batcher") + assert.Equal(t, -1, idx, "Exclusive services have -1 index") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "123456"}), "Should accept chain with matching ID") + assert.False(t, accept(&spec.ChainSpec{NetworkID: "654321"}), "Should not accept chain with different ID") - // Verify services - assert.Len(t, serviceMap, 3) // batcher, proposer, common-service - assert.Contains(t, serviceMap, "batcher") - assert.Contains(t, serviceMap, "proposer") - assert.Contains(t, serviceMap, "common-service") - assert.Equal(t, "op-batcher-network2", serviceMap["batcher"][0].Name) - assert.Equal(t, "op-proposer-2222", serviceMap["proposer"][0].Name) - assert.Equal(t, "op-common-service", serviceMap["common-service"][0].Name) - - // Verify network1 and network3 services are not included - for _, service := range serviceMap { - assert.NotContains(t, service[0].Name, "network1") - assert.NotContains(t, service[0].Name, "network3") - } + // With suffix + _, _, ok = parser("op-batcher-123456-with-suffix") + assert.True(t, ok, "Should recognize batcher regardless of suffix") + + // Invalid formats + _, _, ok = parser("batcher-123456") + assert.False(t, ok, "Should not recognize batcher without op- prefix") + + _, _, ok = parser("op-batcher") + assert.False(t, ok, "Should not recognize op-batcher without chain ID") }) - // Test with a network that doesn't exist - t.Run("find non-existent network services", func(t *testing.T) { - nodes, serviceMap := finder.FindL2Services(ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "non-existent", - NetworkID: "plop", - }, - DepSets: map[string]descriptors.DepSet{}, - }) - - // Should only find common services - assert.Len(t, nodes, 0) - assert.Len(t, serviceMap, 1) - assert.Contains(t, serviceMap, "common-service") - assert.Equal(t, "op-common-service", serviceMap["common-service"][0].Name) + // Test the multi-chain service parser (challenger) + t.Run("triageMultiL2Service", func(t *testing.T) { + parser := finder.triageMultiL2Service("op-challenger-") + + // Valid format with service identifier and two chain IDs + idx, accept, ok := parser("op-challenger-any-123456-654321") + assert.True(t, ok, "Should recognize challenger for two chains") + assert.Equal(t, -1, idx, "Multi-chain services have -1 index") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "123456"}), "Should accept first chain") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "654321"}), "Should accept second chain") + assert.False(t, accept(&spec.ChainSpec{NetworkID: "789012"}), "Should not accept unrelated chain") + + // Valid format with service identifier and one chain ID + _, accept, ok = parser("op-challenger-any-123456") + assert.True(t, ok, "Should recognize challenger for one chain") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "123456"}), "Should accept the only chain") + assert.False(t, accept(&spec.ChainSpec{NetworkID: "654321"}), "Should not accept different chain") + + // Invalid formats + _, _, ok = parser("challenger-123456") + assert.False(t, ok, "Should not recognize challenger without prefix") + + _, _, ok = parser("op-challenger") + assert.False(t, ok, "Should not recognize op-challenger without service ID") }) -} -func TestServiceTag(t *testing.T) { - finder := NewServiceFinder(inspect.ServiceMap{}) - - tests := []struct { - name string - input string - wantTag string - wantIndex int - }{ - { - name: "simple service without index", - input: "batcher", - wantTag: "batcher", - wantIndex: 0, - }, - { - name: "service with index 1", - input: "node-1", - wantTag: "node", - wantIndex: 1, - }, - { - name: "service with index 2", - input: "node-2", - wantTag: "node", - wantIndex: 2, - }, - { - name: "service with double digit index", - input: "node-10", - wantTag: "node", - wantIndex: 10, - }, - { - name: "service with index in the middle", - input: "node-1-suffix", - wantTag: "node", - wantIndex: 1, - }, - { - name: "service with multiple hyphens", - input: "multi-part-name-1", - wantTag: "multi-part-name", - wantIndex: 1, - }, - { - name: "service with multiple numbers", - input: "node-42-1", - wantTag: "node", - wantIndex: 1, - }, - } + // Test the superchain service parser (supervisor) + t.Run("triageSuperchainService", func(t *testing.T) { + // Create some chains for the dependency set + chain1 := eth.ChainIDFromUInt64(123456) + chain2 := eth.ChainIDFromUInt64(654321) - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotTag, gotIndex := finder.serviceTag(tt.input) - assert.Equal(t, tt.wantTag, gotTag) - assert.Equal(t, tt.wantIndex, gotIndex) - }) - } -} + // Create a dependency set + depSetData := map[eth.ChainID]*depset.StaticConfigDependency{ + chain1: {ChainIndex: 123456}, + chain2: {ChainIndex: 654321}, + } + depSet, err := depset.NewStaticConfigDependencySet(depSetData) + require.NoError(t, err) + + // Serialize dependency set + jsonData, err := json.Marshal(depSet) + require.NoError(t, err) + + // Create a new finder with the dependency set + finderWithDS := &ServiceFinder{ + services: make(inspect.ServiceMap), + nodeServices: []string{"cl", "el"}, + l2ServicePrefix: "op-", + depsets: map[string]descriptors.DepSet{ + "superchain": descriptors.DepSet(jsonData), + }, + } -func TestFindL2ServicesWithSupervisors(t *testing.T) { - // Create dependency sets as raw JSON - depSet1 := []byte(`{"dependencies":{"1111":{"activationTime":0,"chainIndex":"1111","historyMinTime":0}}}`) - depSet2 := []byte(`{"dependencies":{"2222":{"activationTime":0,"chainIndex":"2222","historyMinTime":0}}}`) + parser := finderWithDS.triageSuperchainService("op-supervisor-") - // Create test services with supervisors for different networks - services := inspect.ServiceMap{ - // Network1 supervisor with depSet1 - "op-supervisor-depset1": inspect.PortMap{ - "rpc": {Port: 8080}, - }, - // Network2 supervisor with depSet2 - "op-supervisor-depset2": inspect.PortMap{ - "rpc": {Port: 8081}, - }, - // extra supervisor - "op-supervisor-depset3": inspect.PortMap{ - "rpc": {Port: 8083}, - }, - } + // Valid format - "op-supervisor-{service_id}-{depset_name}" + idx, accept, ok := parser("op-supervisor-id-superchain") + assert.True(t, ok, "Should recognize supervisor") + assert.Equal(t, -1, idx, "Superchain services have -1 index") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "123456"}), "Should accept chain1") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "654321"}), "Should accept chain2") + assert.False(t, accept(&spec.ChainSpec{NetworkID: "789012"}), "Should not accept unrelated chain") - // Create chain specs for the networks - n1 := ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "network1", - NetworkID: "1111", - }, - DepSets: map[string]descriptors.DepSet{ - "depset1": depSet1, - }, - } - n2 := ChainSpec{ - ChainSpec: spec.ChainSpec{ - Name: "network2", - NetworkID: "2222", - }, - DepSets: map[string]descriptors.DepSet{ - "depset2": depSet2, - }, - } + // Invalid formats + _, _, ok = parser("supervisor-superchain") + assert.False(t, ok, "Should not recognize supervisor without prefix") - finder := NewServiceFinder( - services, - WithL2Networks([]ChainSpec{n1, n2}), - ) + _, _, ok = parser("op-supervisor") + assert.False(t, ok, "Should not recognize op-supervisor without service ID and depset name") - tests := []struct { - name string - chainSpec ChainSpec - wantName string - wantPort int - }{ - { - name: "network1 supervisor", - chainSpec: n1, - wantName: "op-supervisor-depset1", - wantPort: 8080, - }, - { - name: "network2 supervisor", - chainSpec: n2, - wantName: "op-supervisor-depset2", - wantPort: 8081, - }, - } + // Test with non-existing depset + _, _, ok = parser("op-supervisor-id-nonexistent") + assert.False(t, ok, "Should not recognize supervisor with non-existent depset") + }) - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, serviceMap := finder.FindL2Services(tt.chainSpec) - - // Debug output - t.Logf("Service map: %+v", serviceMap) - for k, v := range serviceMap { - t.Logf("Service %s: %+v", k, v) - } - - // Verify supervisor services - assert.Len(t, serviceMap, 1) // just the supervisor service - assert.Contains(t, serviceMap, "supervisor") - assert.Equal(t, tt.wantName, serviceMap["supervisor"][0].Name) - assert.Equal(t, tt.wantPort, serviceMap["supervisor"][0].Endpoints["rpc"].Port) - }) - } + // Test the universal L2 service parser (faucet) + t.Run("triageUniversalL2Service", func(t *testing.T) { + parser := finder.triageUniversalL2Service("op-faucet") + + // Valid format + idx, accept, ok := parser("op-faucet") + assert.True(t, ok, "Should recognize faucet") + assert.Equal(t, -1, idx, "Universal services have -1 index") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "123456"}), "Should accept any chain") + assert.True(t, accept(&spec.ChainSpec{NetworkID: "654321"}), "Should accept any chain") + + // Invalid formats + _, _, ok = parser("faucet") + assert.False(t, ok, "Should not recognize faucet without prefix") + + _, _, ok = parser("op-faucet-with-suffix") + assert.False(t, ok, "Should not recognize op-faucet with suffix") + }) } diff --git a/kurtosis-devnet/pkg/kurtosis/kurtosis.go b/kurtosis-devnet/pkg/kurtosis/kurtosis.go index 2e54d7282f7f9..8cffcfb77021e 100644 --- a/kurtosis-devnet/pkg/kurtosis/kurtosis.go +++ b/kurtosis-devnet/pkg/kurtosis/kurtosis.go @@ -203,12 +203,12 @@ func (d *KurtosisDeployer) GetEnvironmentInfo(ctx context.Context, s *spec.Encla }, } - l2Networks := make([]ChainSpec, 0, len(s.Chains)) - for _, chainSpec := range s.Chains { - l2Networks = append(l2Networks, ChainSpec{ChainSpec: chainSpec, DepSets: depsets}) - } // Find L1 endpoint - finder := NewServiceFinder(inspectResult.UserServices, WithL2Networks(l2Networks)) + finder := NewServiceFinder( + inspectResult.UserServices, + WithL2Chains(s.Chains), + WithDepSets(depsets), + ) if nodes, services := finder.FindL1Services(); len(nodes) > 0 { chain := &descriptors.Chain{ ID: deployerData.L1ChainID, @@ -229,7 +229,7 @@ func (d *KurtosisDeployer) GetEnvironmentInfo(ctx context.Context, s *spec.Encla // Find L2 endpoints for _, chainSpec := range s.Chains { - nodes, services := finder.FindL2Services(ChainSpec{ChainSpec: chainSpec, DepSets: depsets}) + nodes, services := finder.FindL2Services(chainSpec) chain := &descriptors.L2Chain{ Chain: &descriptors.Chain{ diff --git a/kurtosis-devnet/pkg/kurtosis/kurtosis_test.go b/kurtosis-devnet/pkg/kurtosis/kurtosis_test.go index 45b9888cf4cad..1519c93101636 100644 --- a/kurtosis-devnet/pkg/kurtosis/kurtosis_test.go +++ b/kurtosis-devnet/pkg/kurtosis/kurtosis_test.go @@ -172,7 +172,7 @@ func (m *mockKurtosisContext) DestroyEnclave(ctx context.Context, name string) e func TestDeploy(t *testing.T) { testSpec := &spec.EnclaveSpec{ - Chains: []spec.ChainSpec{ + Chains: []*spec.ChainSpec{ { Name: "op-kurtosis", NetworkID: "1234", @@ -275,7 +275,7 @@ func TestDeploy(t *testing.T) { func TestGetEnvironmentInfo(t *testing.T) { testSpec := &spec.EnclaveSpec{ - Chains: []spec.ChainSpec{ + Chains: []*spec.ChainSpec{ { Name: "op-kurtosis", NetworkID: "1234", @@ -396,7 +396,7 @@ func TestGetEnvironmentInfo(t *testing.T) { { name: "with interop feature - depset fetched", spec: &spec.EnclaveSpec{ - Chains: []spec.ChainSpec{ + Chains: []*spec.ChainSpec{ { Name: "op-kurtosis", NetworkID: "1234", @@ -457,7 +457,7 @@ func TestGetEnvironmentInfo(t *testing.T) { { name: "without interop feature - depset not fetched", spec: &spec.EnclaveSpec{ - Chains: []spec.ChainSpec{ + Chains: []*spec.ChainSpec{ { Name: "op-kurtosis", NetworkID: "1234", diff --git a/kurtosis-devnet/pkg/kurtosis/sources/spec/spec.go b/kurtosis-devnet/pkg/kurtosis/sources/spec/spec.go index 251498836d210..eaeed7a80a9f0 100644 --- a/kurtosis-devnet/pkg/kurtosis/sources/spec/spec.go +++ b/kurtosis-devnet/pkg/kurtosis/sources/spec/spec.go @@ -30,7 +30,7 @@ func (fl FeatureList) Contains(feature string) bool { // EnclaveSpec represents the parsed chain specifications from the YAML type EnclaveSpec struct { - Chains []ChainSpec + Chains []*ChainSpec Features FeatureList } @@ -104,13 +104,13 @@ func (s *Spec) ExtractData(r io.Reader) (*EnclaveSpec, error) { } result := &EnclaveSpec{ - Chains: make([]ChainSpec, 0, len(yamlSpec.OptimismPackage.Chains)), + Chains: make([]*ChainSpec, 0, len(yamlSpec.OptimismPackage.Chains)), Features: features, } // Extract chain specifications for _, chain := range yamlSpec.OptimismPackage.Chains { - result.Chains = append(result.Chains, ChainSpec{ + result.Chains = append(result.Chains, &ChainSpec{ Name: chain.NetworkParams.Name, NetworkID: chain.NetworkParams.NetworkID, }) diff --git a/kurtosis-devnet/simple.yaml b/kurtosis-devnet/simple.yaml index 6533cec4f5758..96cc32b0e0ad8 100644 --- a/kurtosis-devnet/simple.yaml +++ b/kurtosis-devnet/simple.yaml @@ -1,4 +1,7 @@ optimism_package: + faucet: + enabled: true + image: {{ localDockerImage "op-faucet" }} chains: - participants: - el_type: op-geth @@ -61,7 +64,7 @@ optimism_package: image: {{ localDockerImage "op-deployer" }} l1_artifacts_locator: {{ localContractArtifacts "l1" }} l2_artifacts_locator: {{ localContractArtifacts "l2" }} - global_deploy_overrides: + overrides: faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }} global_log_level: "info" global_node_selectors: {}