Skip to content
Merged
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
15 changes: 10 additions & 5 deletions devnet-sdk/descriptors/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,21 @@ type Node struct {
// AddressMap is a map of address names to their corresponding addresses
type AddressMap map[string]types.Address

// Chain represents a chain (L1 or L2) in a devnet.
type Chain struct {
Name string `json:"name"`
ID string `json:"id,omitempty"`
Services ServiceMap `json:"services,omitempty"`
Nodes []Node `json:"nodes"`
Addresses AddressMap `json:"addresses,omitempty"`
Wallets WalletMap `json:"wallets,omitempty"`
JWT string `json:"jwt,omitempty"`
Config *params.ChainConfig `json:"config,omitempty"`
Addresses AddressMap `json:"addresses,omitempty"`
}

type L2Chain struct {
Chain
L1Addresses AddressMap `json:"l1_addresses,omitempty"`
L1Wallets WalletMap `json:"l1_wallets,omitempty"`
}

// Wallet represents a wallet with an address and optional private key.
Expand All @@ -54,9 +59,9 @@ type WalletMap map[string]Wallet

// DevnetEnvironment exposes the relevant information to interact with a devnet.
type DevnetEnvironment struct {
Name string `json:"name"`
L1 *Chain `json:"l1"`
L2 []*Chain `json:"l2"`
Name string `json:"name"`
L1 *Chain `json:"l1"`
L2 []*L2Chain `json:"l2"`

Features []string `json:"features,omitempty"`
}
2 changes: 1 addition & 1 deletion devnet-sdk/shell/env/devnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (d *DevnetEnv) GetChain(chainName string) (*ChainConfig, error) {
} else {
for _, l2Chain := range d.Config.L2 {
if l2Chain.Name == chainName {
chain = l2Chain
chain = &l2Chain.Chain
break
}
}
Expand Down
42 changes: 29 additions & 13 deletions devnet-sdk/shell/env/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

"github.com/ethereum-optimism/optimism/devnet-sdk/descriptors"
"github.com/ethereum-optimism/optimism/devnet-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -109,25 +108,42 @@ func TestGetChain(t *testing.T) {
},
},
JWT: "0x1234",
Addresses: descriptors.AddressMap{
"deployer": common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
},
L2: []*descriptors.Chain{
L2: []*descriptors.L2Chain{
{
Name: "op",
Nodes: []descriptors.Node{
{
Services: descriptors.ServiceMap{
"el": {
Endpoints: descriptors.EndpointMap{
"rpc": {
Host: "localhost",
Port: 9545,
Chain: descriptors.Chain{
Name: "op",
Nodes: []descriptors.Node{
{
Services: descriptors.ServiceMap{
"el": {
Endpoints: descriptors.EndpointMap{
"rpc": {
Host: "localhost",
Port: 9545,
},
},
},
},
},
},
JWT: "0x5678",
Addresses: descriptors.AddressMap{
"deployer": common.HexToAddress("0x2345678901234567890123456789012345678901"),
},
},
L1Addresses: descriptors.AddressMap{
"deployer": common.HexToAddress("0x2345678901234567890123456789012345678901"),
},
L1Wallets: descriptors.WalletMap{
"deployer": descriptors.Wallet{
Address: common.HexToAddress("0x2345678901234567890123456789012345678901"),
PrivateKey: "0x2345678901234567890123456789012345678901",
},
},
JWT: "0x5678",
},
},
},
Expand Down Expand Up @@ -176,7 +192,7 @@ func TestChainConfig(t *testing.T) {
},
},
JWT: "0x1234",
Addresses: map[string]types.Address{
Addresses: descriptors.AddressMap{
"deployer": common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
},
Expand Down
2 changes: 1 addition & 1 deletion devnet-sdk/shell/env/kt_native_fetch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func TestFetchKurtosisNativeDataSuccess(t *testing.T) {
envSpec := &spec.EnclaveSpec{}
env := &kurtosis.KurtosisEnvironment{
DevnetEnvironment: descriptors.DevnetEnvironment{
L2: make([]*descriptors.Chain, 0, 1),
L2: make([]*descriptors.L2Chain, 0, 1),
Features: envSpec.Features,
},
}
Expand Down
96 changes: 65 additions & 31 deletions devnet-sdk/system/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ type opBlock interface {

var (
// This will make sure that we implement the Chain interface
_ Chain = (*chain)(nil)
_ Chain = (*chain)(nil)
_ L2Chain = (*l2Chain)(nil)

// Make sure we're using op-geth in place of go-ethereum.
// If you're wondering why this fails at compile time,
Expand Down Expand Up @@ -119,13 +120,13 @@ func (m *clientManager) GethClient(rpcURL string) (*ethclient.Client, error) {
type chain struct {
id string
rpcUrl string
users map[string]Wallet
wallets WalletMap
clients *clientManager
registry interfaces.ContractsRegistry
mu sync.Mutex
node Node
chainConfig *params.ChainConfig
addresses descriptors.AddressMap
addresses AddressMap
}

func (c *chain) Node() Node {
Expand All @@ -140,20 +141,6 @@ func (c *chain) GethClient() (*ethclient.Client, error) {
return c.clients.GethClient(c.rpcUrl)
}

func newChain(chainID string, rpcUrl string, users map[string]Wallet, chainConfig *params.ChainConfig, addresses descriptors.AddressMap) *chain {
clients := newClientManager()
chain := &chain{
id: chainID,
rpcUrl: rpcUrl,
users: users,
clients: clients,
node: newNode(rpcUrl, clients),
chainConfig: chainConfig,
addresses: addresses,
}
return chain
}

func (c *chain) ContractsRegistry() interfaces.ContractsRegistry {
c.mu.Lock()
defer c.mu.Unlock()
Expand All @@ -178,14 +165,8 @@ func (c *chain) RPCURL() string {
// error.
// Typically this will be one of the pre-funded wallets associated with
// the deployed system.
func (c *chain) Wallets(ctx context.Context) ([]Wallet, error) {
wallets := []Wallet{}

for _, user := range c.users {
wallets = append(wallets, user)
}

return wallets, nil
func (c *chain) Wallets() WalletMap {
return c.wallets
}

func (c *chain) ID() types.ChainID {
Expand Down Expand Up @@ -233,18 +214,48 @@ func (c *chain) Config() (*params.ChainConfig, error) {
return c.chainConfig, nil
}

func (c *chain) Addresses() descriptors.AddressMap {
func newChainFromDescriptor(d *descriptors.Chain) (Chain, error) {
// TODO: handle incorrect descriptors better. We could panic here.
firstNodeRPC := d.Nodes[0].Services["el"].Endpoints["rpc"]
rpcURL := fmt.Sprintf("http://%s:%d", firstNodeRPC.Host, firstNodeRPC.Port)

c := newChain(d.ID, rpcURL, nil, d.Config, AddressMap(d.Addresses)) // Create chain first

wallets, err := newWalletMapFromDescriptorWalletMap(d.Wallets, c)
if err != nil {
return nil, err
}
c.wallets = wallets

return c, nil
}

func newChain(chainID string, rpcUrl string, wallets WalletMap, chainConfig *params.ChainConfig, addresses AddressMap) *chain {
clients := newClientManager()
chain := &chain{
id: chainID,
rpcUrl: rpcUrl,
wallets: wallets,
clients: clients,
node: newNode(rpcUrl, clients),
chainConfig: chainConfig,
addresses: addresses,
}
return chain
}

func (c *chain) Addresses() AddressMap {
return c.addresses
}

func chainFromDescriptor(d *descriptors.Chain) (Chain, error) {
func newL2ChainFromDescriptor(d *descriptors.L2Chain) (L2Chain, error) {
// TODO: handle incorrect descriptors better. We could panic here.
firstNodeRPC := d.Nodes[0].Services["el"].Endpoints["rpc"]
rpcURL := fmt.Sprintf("http://%s:%d", firstNodeRPC.Host, firstNodeRPC.Port)

c := newChain(d.ID, rpcURL, nil, d.Config, d.Addresses) // Create chain first
c := newL2Chain(d.ID, rpcURL, nil, nil, d.Config, AddressMap(d.L1Addresses), AddressMap(d.Addresses)) // Create chain first

users := make(map[string]Wallet)
wallets := make(WalletMap)
for key, w := range d.Wallets {
// TODO: The assumption that the wallet will necessarily be used on chain `d` may
// be problematic if the L2 admin wallets are to be used to sign L1 transactions.
Expand All @@ -253,9 +264,32 @@ func chainFromDescriptor(d *descriptors.Chain) (Chain, error) {
if err != nil {
return nil, fmt.Errorf("failed to create wallet: %w", err)
}
users[key] = k
wallets[key] = k
}
c.users = users // Set users after creation
c.wallets = wallets // Set wallets after creation

return c, nil
}

func newL2Chain(chainID string, rpcUrl string, l1Wallets WalletMap, l2Wallets WalletMap, chainConfig *params.ChainConfig, l1Addresses AddressMap, l2Addresses AddressMap) *l2Chain {
chain := &l2Chain{
chain: newChain(chainID, rpcUrl, l2Wallets, chainConfig, l2Addresses),
l1Addresses: l1Addresses,
l1Wallets: l1Wallets,
}
return chain
}

type l2Chain struct {
*chain
l1Addresses AddressMap
l1Wallets WalletMap
}

func (c *l2Chain) L1Addresses() AddressMap {
return c.l1Addresses
}

func (c *l2Chain) L1Wallets() WalletMap {
return c.l1Wallets
}
67 changes: 59 additions & 8 deletions devnet-sdk/system/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/ethereum-optimism/optimism/devnet-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestClientManager(t *testing.T) {
Expand Down Expand Up @@ -68,9 +67,64 @@ func TestChainFromDescriptor(t *testing.T) {
Address: common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
},
Addresses: descriptors.AddressMap{
"user1": common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
}

chain, err := chainFromDescriptor(descriptor)
chain, err := newChainFromDescriptor(descriptor)
assert.Nil(t, err)
assert.NotNil(t, chain)
lowLevelChain, ok := chain.(LowLevelChain)
assert.True(t, ok)
assert.Equal(t, "http://localhost:8545", lowLevelChain.RPCURL())

// Compare the underlying big.Int values
chainID := chain.ID()
expectedID := big.NewInt(1)
assert.Equal(t, 0, expectedID.Cmp(chainID))
}

func TestL2ChainFromDescriptor(t *testing.T) {
descriptor := &descriptors.L2Chain{
Chain: descriptors.Chain{
ID: "1",
Nodes: []descriptors.Node{
{
Services: descriptors.ServiceMap{
"el": descriptors.Service{
Endpoints: descriptors.EndpointMap{
"rpc": descriptors.PortInfo{
Host: "localhost",
Port: 8545,
},
},
},
},
},
},
Wallets: descriptors.WalletMap{
"user1": descriptors.Wallet{
PrivateKey: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
Address: common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
},
Addresses: descriptors.AddressMap{
"user2": common.HexToAddress("0x1234567890123456789012345678901234567891"),
},
},
L1Addresses: descriptors.AddressMap{
"user1": common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
L1Wallets: descriptors.WalletMap{
"user1": descriptors.Wallet{
PrivateKey: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
Address: common.HexToAddress("0x1234567890123456789012345678901234567890"),
},
},
}

chain, err := newL2ChainFromDescriptor(descriptor)
assert.Nil(t, err)
assert.NotNil(t, chain)
lowLevelChain, ok := chain.(LowLevelChain)
Expand All @@ -84,19 +138,17 @@ func TestChainFromDescriptor(t *testing.T) {
}

func TestChainWallet(t *testing.T) {
ctx := context.Background()
testAddr := common.HexToAddress("0x1234567890123456789012345678901234567890")

wallet, err := newWallet("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", testAddr, nil)
assert.Nil(t, err)

chain := newChain("1", "http://localhost:8545", map[string]Wallet{
l1Chain := newChain("1", "http://localhost:8545", WalletMap{
"user1": wallet}, nil, map[string]common.Address{})

t.Run("finds wallet meeting constraints", func(t *testing.T) {
constraint := &addressConstraint{addr: testAddr}
wallets, err := chain.Wallets(ctx)
require.NoError(t, err)
wallets := l1Chain.Wallets()

for _, w := range wallets {
if constraint.CheckWallet(w) {
Expand All @@ -111,8 +163,7 @@ func TestChainWallet(t *testing.T) {
t.Run("returns error when no wallet meets constraints", func(t *testing.T) {
wrongAddr := common.HexToAddress("0x0987654321098765432109876543210987654321")
constraint := &addressConstraint{addr: wrongAddr}
wallets, err := chain.Wallets(ctx)
require.NoError(t, err)
wallets := l1Chain.Wallets()

for _, w := range wallets {
if constraint.CheckWallet(w) {
Expand Down
Loading