Skip to content

Commit

Permalink
feat: print available accounts on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
jakim929 committed Jul 11, 2024
1 parent 93d8c5b commit b7ad986
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 25 deletions.
14 changes: 10 additions & 4 deletions anvil/anvil.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ import (
)

type Config struct {
ChainID uint64
SourceChainID uint64
Port uint64
Genesis []byte
ChainID uint64
SourceChainID uint64
Port uint64
Accounts uint64
Mnemonic string
DerivationPath string
Genesis []byte
}

type Anvil struct {
Expand Down Expand Up @@ -64,6 +67,9 @@ func (a *Anvil) Start(ctx context.Context) error {

args := []string{
"--host", host,
"--accounts", fmt.Sprintf("%d", a.cfg.Accounts),
"--mnemonic", a.cfg.Mnemonic,
"--derivation-path", a.cfg.DerivationPath,
"--chain-id", fmt.Sprintf("%d", a.cfg.ChainID),
"--port", fmt.Sprintf("%d", a.cfg.Port),
}
Expand Down
20 changes: 17 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,53 @@ module github.com/ethereum-optimism/supersim
go 1.22.3

require (
github.com/btcsuite/btcd v0.24.2
github.com/btcsuite/btcd/btcutil v1.1.5
github.com/ethereum-optimism/optimism v1.7.7
github.com/ethereum/go-ethereum v1.13.15
github.com/stretchr/testify v1.9.0
github.com/tyler-smith/go-bip39 v1.1.0
github.com/urfave/cli/v2 v2.27.1
)

require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240614103325-d8902381f5d8 // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect
golang.org/x/tools v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)

replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101315.3-rc.1

replace github.com/crate-crypto/go-kzg-4844 v1.0.0 => github.com/crate-crypto/go-kzg-4844 v0.7.0
184 changes: 173 additions & 11 deletions go.sum

Large diffs are not rendered by default.

105 changes: 105 additions & 0 deletions hdaccount/hd_account_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package hdaccount

import (
"crypto/ecdsa"
"errors"

"github.com/btcsuite/btcd/btcutil/hdkeychain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"

"github.com/tyler-smith/go-bip39"
)

type HdAccountStore struct {
mnemonic string
basePath accounts.DerivationPath
seed []byte
masterKey *hdkeychain.ExtendedKey
}

func NewHdAccountStore(mnemonic string, basePath accounts.DerivationPath) (*HdAccountStore, error) {
if mnemonic == "" {
return nil, errors.New("mnemonic is required")
}

if !bip39.IsMnemonicValid(mnemonic) {
return nil, errors.New("mnemonic is invalid")
}

seed, err := bip39.NewSeedWithErrorChecking(mnemonic, "")
if err != nil {
return nil, err
}

masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, err
}

return &HdAccountStore{mnemonic: mnemonic, basePath: basePath, seed: seed, masterKey: masterKey}, nil
}

func (h *HdAccountStore) derivePrivateKeyAt(index uint32) (*ecdsa.PrivateKey, error) {

var key *hdkeychain.ExtendedKey
key = h.masterKey
for _, n := range h.derivationPathForIndex(index) {
derivedKey, err := key.Derive(n)

if err != nil {
return nil, err
}

key = derivedKey
}

privateKey, err := key.ECPrivKey()
privateKeyECDSA := privateKey.ToECDSA()
if err != nil {
return nil, err
}

return privateKeyECDSA, nil
}

func (h *HdAccountStore) derivePublicKeyAt(index uint32) (*ecdsa.PublicKey, error) {
privateKeyECDSA, err := h.derivePrivateKeyAt(index)
if err != nil {
return nil, err
}

publicKey := privateKeyECDSA.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("failed to get public key")
}

return publicKeyECDSA, nil
}

func (h *HdAccountStore) PrivateKeyHexAt(index uint32) (string, error) {
privateKey, err := h.derivePrivateKeyAt(index)
if err != nil {
return "", err
}

return hexutil.Encode(crypto.FromECDSA(privateKey)), nil
}

func (h *HdAccountStore) AddressHexAt(index uint32) (string, error) {
publicKey, err := h.derivePublicKeyAt(index)
if err != nil {
return "", err
}

address := crypto.PubkeyToAddress(*publicKey)

return address.Hex(), nil
}

func (h *HdAccountStore) derivationPathForIndex(index uint32) accounts.DerivationPath {
return accounts.DerivationPath(append(h.basePath, index))
}
7 changes: 5 additions & 2 deletions orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ type ChainConfig struct {
ChainID uint64
// The base chain ID when the chain is a rollup.
// If set to 0, the chain is considered an L1 chain
SourceChainID uint64
SourceChainID uint64
Accounts uint64
Mnemonic string
DerivationPath string
}

type OrchestratorConfig struct {
Expand Down Expand Up @@ -58,7 +61,7 @@ func NewOrchestrator(log log.Logger, config *OrchestratorConfig) (*Orchestrator,
if chainConfig.SourceChainID == 0 {
genesis = genesisL1JSON
}
anvil := anvil.New(log, &anvil.Config{ChainID: chainConfig.ChainID, SourceChainID: chainConfig.SourceChainID, Genesis: genesis})
anvil := anvil.New(log, &anvil.Config{ChainID: chainConfig.ChainID, SourceChainID: chainConfig.SourceChainID, Genesis: genesis, Accounts: chainConfig.Accounts, Mnemonic: chainConfig.Mnemonic, DerivationPath: chainConfig.DerivationPath})
anvilInstances = append(anvilInstances, anvil)
// Only create Op Simulators for L2 chains.
if chainConfig.SourceChainID != 0 {
Expand Down
62 changes: 57 additions & 5 deletions supersim.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,74 @@ import (

"context"

"github.com/ethereum-optimism/supersim/hdaccount"
"github.com/ethereum-optimism/supersim/orchestrator"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/log"
)

type Config struct {
orchestratorConfig orchestrator.OrchestratorConfig
}

var (
DefaultAccounts uint64 = 10
DefaultMnemonic string = "test test test test test test test test test test test junk"
DefaultDerivationPath accounts.DerivationPath = accounts.DefaultRootDerivationPath
)

var DefaultConfig = Config{
orchestratorConfig: orchestrator.OrchestratorConfig{

ChainConfigs: []orchestrator.ChainConfig{
{ChainID: 1, Port: 0},
{ChainID: 10, SourceChainID: 1, Port: 0},
{ChainID: 30, SourceChainID: 1, Port: 0},
{
ChainID: 1,
Port: 0,
Accounts: DefaultAccounts,
Mnemonic: DefaultMnemonic,
DerivationPath: DefaultDerivationPath.String(),
},
{
ChainID: 10,
SourceChainID: 1,
Port: 0,
Accounts: DefaultAccounts,
Mnemonic: DefaultMnemonic,
DerivationPath: DefaultDerivationPath.String(),
},
{
ChainID: 30,
SourceChainID: 1,
Port: 0,
Accounts: DefaultAccounts,
Mnemonic: DefaultMnemonic,
DerivationPath: DefaultDerivationPath.String(),
},
},
},
}

type Supersim struct {
log log.Logger
log log.Logger
hdAccountStore *hdaccount.HdAccountStore

Orchestrator *orchestrator.Orchestrator
}

func NewSupersim(log log.Logger, config *Config) (*Supersim, error) {
hdAccountStore, err := hdaccount.NewHdAccountStore(DefaultMnemonic, DefaultDerivationPath)
if err != nil {
// TODO: update NewSupersim to return an error
return nil, fmt.Errorf("failed to create HD account store", "err", err)
}

o, err := orchestrator.NewOrchestrator(log, &DefaultConfig.orchestratorConfig)
if err != nil {
return nil, fmt.Errorf("failed to create orchestrator")
}

return &Supersim{log, o}, nil
return &Supersim{log, hdAccountStore, o}, nil
}

func (s *Supersim) Start(ctx context.Context) error {
Expand Down Expand Up @@ -70,6 +106,22 @@ func (s *Supersim) Stopped() bool {
func (s *Supersim) ConfigAsString() string {
var b strings.Builder

fmt.Fprintf(&b, "\n\nAvailable Accounts\n")
fmt.Fprintf(&b, "-----------------------\n")

for i := range DefaultAccounts {
addressHex, _ := s.hdAccountStore.AddressHexAt(uint32(i))
fmt.Fprintf(&b, "(%d): %s\n", i, addressHex)
}

fmt.Fprintf(&b, "\n\nPrivate Keys\n")
fmt.Fprintf(&b, "-----------------------\n")

for i := range DefaultAccounts {
privateKeyHex, _ := s.hdAccountStore.PrivateKeyHexAt(uint32(i))
fmt.Fprintf(&b, "(%d): %s\n", i, privateKeyHex)
}

fmt.Fprintf(&b, "\nSupersim Config:\n")
fmt.Fprint(&b, s.Orchestrator.ConfigAsString())

Expand Down
33 changes: 33 additions & 0 deletions supersim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/common/math"

"github.com/ethereum/go-ethereum/log"

"github.com/ethereum/go-ethereum/rpc"
)

Expand All @@ -19,8 +21,22 @@ const (
crossL2InboxAddress = "0x4200000000000000000000000000000000000022"
l2toL2CrossDomainMessengerAddress = "0x4200000000000000000000000000000000000023"
l1BlockAddress = "0x4200000000000000000000000000000000000015"
defaultTestAccountBalance = "0x21e19e0c9bab2400000"
)

var defaultTestAccounts = [...]string{
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"0x90F79bf6EB2c4f870365E785982E1f101E93b906",
"0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"0x976EA74026E726554dB657fA54763abd0C3a0aa9",
"0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
"0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
"0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
}

type TestSuite struct {
t *testing.T

Expand Down Expand Up @@ -89,3 +105,20 @@ func TestGenesisState(t *testing.T) {
require.NotEqual(t, emptyCode, code, "L1Block is not deployed")
}
}

func TestAccountBalances(t *testing.T) {
testSuite := createTestSuite(t)

// assert that the predeploys exists on the l2 anvil instances
for _, l2Chain := range testSuite.Supersim.l2OpSims {

Check failure on line 113 in supersim_test.go

View workflow job for this annotation

GitHub Actions / go-tests

testSuite.Supersim.l2OpSims undefined (type *Supersim has no field or method l2OpSims)

Check failure on line 113 in supersim_test.go

View workflow job for this annotation

GitHub Actions / go-lint

testSuite.Supersim.l2OpSims undefined (type *Supersim has no field or method l2OpSims) (typecheck)
client, err := rpc.Dial(l2Chain.Endpoint())
require.NoError(t, err)
defer client.Close()

for _, account := range defaultTestAccounts {
var balanceHex string
require.NoError(t, client.CallContext(context.Background(), &balanceHex, "eth_getBalance", account, "latest"))
require.Equal(t, balanceHex, "0x21e19e0c9bab2400000", "Test account balance is incorrect")
}
}
}

0 comments on commit b7ad986

Please sign in to comment.