From c1f4b1fc02b54181167822833a4380a0c2f293da Mon Sep 17 00:00:00 2001 From: allnil Date: Wed, 13 Nov 2024 22:22:56 +0000 Subject: [PATCH] chore: try to run make e2e --- e2e/server_test.go | 57 +++++++++++++++++++-- e2e/setup.go | 22 +++++++- store/precomputed_key/wvm/cli.go | 18 ++----- store/precomputed_key/wvm/wvm.go | 7 +-- store/precomputed_key/wvm/wvm_rpc_client.go | 32 +++++++++--- 5 files changed, 102 insertions(+), 34 deletions(-) diff --git a/e2e/server_test.go b/e2e/server_test.go index 19accff1..d8642df2 100644 --- a/e2e/server_test.go +++ b/e2e/server_test.go @@ -1,6 +1,7 @@ package e2e_test import ( + "os" "testing" "time" @@ -37,7 +38,6 @@ this test asserts that the data can be posted/read to EigenDA with a concurrent S3 backend configured */ func TestOptimismClientWithGenericCommitment(t *testing.T) { - if !runIntegrationTests && !runTestnetIntegrationTests { t.Skip("Skipping test as INTEGRATION or TESTNET env var not set") } @@ -124,11 +124,10 @@ func TestProxyCachingWithRedis(t *testing.T) { } /* - Ensure that fallback location is read from when EigenDA blob is not available. - This is done by setting the memstore expiration time to 1ms and waiting for the blob to expire - before attempting to read it. +Ensure that fallback location is read from when EigenDA blob is not available. +This is done by setting the memstore expiration time to 1ms and waiting for the blob to expire +before attempting to read it. */ - func TestProxyReadFallback(t *testing.T) { // test can't be ran against holesky since read failure case can't be manually triggered if !runIntegrationTests || runTestnetIntegrationTests { @@ -166,3 +165,51 @@ func TestProxyReadFallback(t *testing.T) { requireWriteReadSecondary(t, ts.Metrics.SecondaryRequestsTotal, common.S3BackendType) requireDispersalRetrievalEigenDA(t, ts.Metrics.HTTPServerRequestsTotal, commitments.SimpleCommitmentMode) } + +/* + Tests fallback when wvm secondary backend is used. + Turned off in ci suite by default. +*/ + +func TestProxyReadFallbackOnWvm(t *testing.T) { + wvmTestPrivKey := os.Getenv("WVM_PRIV_KEY") + if wvmTestPrivKey == "" { + t.Skip("Skipping test as WVM key to sign transactions is absent") + } + + // test can't be ran against holesky since read failure case can't be manually triggered + if !runIntegrationTests || runTestnetIntegrationTests { + t.Skip("Skipping test as INTEGRATION env var not set") + } + + t.Parallel() + + // setup server with WVM as a fallback option + testCfg := e2e.TestConfig(useMemory()) + testCfg.UseWVMFallback = true + // ensure that blob memstore eviction times result in near immediate activation + testCfg.Expiration = time.Millisecond * 1 + + tsConfig := e2e.TestSuiteConfig(testCfg) + ts, kill := e2e.CreateTestSuite(tsConfig) + defer kill() + + cfg := &client.Config{ + URL: ts.Address(), + } + daClient := client.New(cfg) + expectedBlob := e2e.RandBytes(1_000) + t.Log("Setting input data on proxy server...") + blobInfo, err := daClient.SetData(ts.Ctx, expectedBlob) + require.NoError(t, err) + + time.Sleep(1 * time.Second) + t.Log("Getting input data from proxy server...") + actualBlob, err := daClient.GetData(ts.Ctx, blobInfo) + require.NoError(t, err) + require.Equal(t, expectedBlob, actualBlob) + + requireSimpleClientSetGet(t, ts, e2e.RandBytes(1_000)) + requireWriteReadSecondary(t, ts.Metrics.SecondaryRequestsTotal, common.WVMBackendType) + requireDispersalRetrievalEigenDA(t, ts.Metrics.HTTPServerRequestsTotal, commitments.SimpleCommitmentMode) +} diff --git a/e2e/setup.go b/e2e/setup.go index ecd4fb2d..a9d00ccb 100644 --- a/e2e/setup.go +++ b/e2e/setup.go @@ -15,6 +15,7 @@ import ( "github.com/Layr-Labs/eigenda-proxy/store/generated_key/memstore" "github.com/Layr-Labs/eigenda-proxy/store/precomputed_key/redis" "github.com/Layr-Labs/eigenda-proxy/store/precomputed_key/s3" + "github.com/Layr-Labs/eigenda-proxy/store/precomputed_key/wvm" "github.com/Layr-Labs/eigenda-proxy/verify" "github.com/Layr-Labs/eigenda/api/clients" "github.com/Layr-Labs/eigenda/encoding/kzg" @@ -113,6 +114,7 @@ type Cfg struct { UseS3Caching bool UseRedisCaching bool UseS3Fallback bool + UseWVMFallback bool } func TestConfig(useMemory bool) *Cfg { @@ -123,6 +125,7 @@ func TestConfig(useMemory bool) *Cfg { UseS3Caching: false, UseRedisCaching: false, UseS3Fallback: false, + UseWVMFallback: false, WriteThreadCount: 0, } } @@ -159,6 +162,18 @@ func createS3Config(eigendaCfg server.Config) server.CLIConfig { } } +func createWVMConfig(eigendaCfg server.Config) server.CLIConfig { + eigendaCfg.StorageConfig.WVMConfig = wvm.Config{ + Enabled: true, + Endpoint: "https://testnet-rpc.wvm.dev/", + ChainID: 9496, + Timeout: 5 * time.Second, + } + return server.CLIConfig{ + EigenDAConfig: eigendaCfg, + } +} + func TestSuiteConfig(testCfg *Cfg) server.CLIConfig { // load signer key from environment pk := os.Getenv(privateKey) @@ -237,6 +252,10 @@ func TestSuiteConfig(testCfg *Cfg) server.CLIConfig { eigendaCfg.StorageConfig.FallbackTargets = []string{"S3"} cfg = createS3Config(eigendaCfg) + case testCfg.UseWVMFallback: + eigendaCfg.StorageConfig.FallbackTargets = []string{"wvm"} + cfg = createWVMConfig(eigendaCfg) + case testCfg.UseRedisCaching: eigendaCfg.StorageConfig.CacheTargets = []string{"redis"} cfg = createRedisConfig(eigendaCfg) @@ -273,7 +292,6 @@ func CreateTestSuite(testSuiteCfg server.CLIConfig) (TestSuite, func()) { log, m, ) - if err != nil { panic(err) } @@ -340,7 +358,7 @@ func createS3Bucket(bucketName string) { } func RandStr(n int) string { - var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz") + letterRunes := []rune("abcdefghijklmnopqrstuvwxyz") b := make([]rune, n) for i := range b { b[i] = letterRunes[rand.Intn(len(letterRunes))] diff --git a/store/precomputed_key/wvm/cli.go b/store/precomputed_key/wvm/cli.go index 32d0e236..ca77909a 100644 --- a/store/precomputed_key/wvm/cli.go +++ b/store/precomputed_key/wvm/cli.go @@ -7,12 +7,11 @@ import ( ) var ( - EndpointFlagName = withFlagPrefix("endpoint") - ChainIDFlagName = withFlagPrefix("chain_id") - ArchiverAddressFlagName = withFlagPrefix("archiver_address") - TimeoutFlagName = withFlagPrefix("timeout") - Web3SignerEndpoint = withFlagPrefix("web3signer_endpoint") - EnabledFlagName = withFlagPrefix("enabled") + EndpointFlagName = withFlagPrefix("endpoint") + ChainIDFlagName = withFlagPrefix("chain_id") + TimeoutFlagName = withFlagPrefix("timeout") + Web3SignerEndpoint = withFlagPrefix("web3signer_endpoint") + EnabledFlagName = withFlagPrefix("enabled") ) func withFlagPrefix(s string) string { @@ -46,12 +45,6 @@ func CLIFlags(envPrefix, category string) []cli.Flag { EnvVars: withEnvPrefix(envPrefix, "CHAIN_ID"), Category: category, }, - &cli.StringFlag{ - Name: ArchiverAddressFlagName, - Usage: "user's wvm chain address used for archiving data", - EnvVars: withEnvPrefix(envPrefix, "ARCHIVER_ADDRESS"), - Category: category, - }, &cli.StringFlag{ Name: Web3SignerEndpoint, Usage: "web3signer endpoint", @@ -72,7 +65,6 @@ func ReadConfig(ctx *cli.Context) Config { return Config{ Endpoint: ctx.String(EndpointFlagName), ChainID: ctx.Int64(ChainIDFlagName), - ArchiverAddress: ctx.String(ArchiverAddressFlagName), Web3SignerEndpoint: ctx.String(Web3SignerEndpoint), Enabled: ctx.Bool(EnabledFlagName), Timeout: ctx.Duration(TimeoutFlagName), diff --git a/store/precomputed_key/wvm/wvm.go b/store/precomputed_key/wvm/wvm.go index db485dce..ab514ffb 100644 --- a/store/precomputed_key/wvm/wvm.go +++ b/store/precomputed_key/wvm/wvm.go @@ -23,11 +23,6 @@ type Config struct { Endpoint string // WVM chain id ChainID int64 - // User's archiver address - // Should be populated with tWVM tokens used in WVM testnet - // Please check out WVM Faucet to claim $tWVM. - // Please read README to gen an additional information - ArchiverAddress string // Endpoint for Web3 signer Web3SignerEndpoint string // Timeout on WVM calls in seconds @@ -75,7 +70,7 @@ func (wvm *Store) Put(ctx context.Context, key []byte, value []byte) error { ctx, cancel := context.WithTimeout(ctx, wvm.cfg.Timeout) defer cancel() - gas, err := wvm.rpcClient.EstimateGas(ctx, wvm.cfg.ArchiverAddress, ArchivePoolAddress, value) + gas, err := wvm.rpcClient.EstimateGas(ctx, ArchivePoolAddress, value) if err != nil { return fmt.Errorf("failed to store data in wvm: failed estimate gas: %w", err) } diff --git a/store/precomputed_key/wvm/wvm_rpc_client.go b/store/precomputed_key/wvm/wvm_rpc_client.go index 068bd3e7..e18a61df 100644 --- a/store/precomputed_key/wvm/wvm_rpc_client.go +++ b/store/precomputed_key/wvm/wvm_rpc_client.go @@ -55,13 +55,21 @@ func NewEthRPCClient(log log.Logger, cfg *Config) (*EthRPCClient, error) { } // estimateGas tries estimates the suggested amount of gas that required to execute a given transaction. -func (rpc *EthRPCClient) EstimateGas(ctx context.Context, from, to string, data []byte) (uint64, error) { +func (rpc *EthRPCClient) EstimateGas(ctx context.Context, to string, data []byte) (uint64, error) { var ( - fromAddr = common.HexToAddress(from) toAddr = common.HexToAddress(to) bytesData []byte err error ) + var fromAddress common.Address + privKey := os.Getenv("WVM_PRIV_KEY") + if privKey == "" { + accounts, err := rpc.web3signer.GetAccounts(ctx) + if err != nil { + return 0, fmt.Errorf("failed to estimate gas, no signer") + } + fromAddress = accounts[0] + } var encoded string if string(data) != "" { @@ -76,7 +84,7 @@ func (rpc *EthRPCClient) EstimateGas(ctx context.Context, from, to string, data } msg := ethereum.CallMsg{ - From: fromAddr, + From: fromAddress, To: &toAddr, Gas: 0x00, Data: bytesData, @@ -146,33 +154,41 @@ func (rpc *EthRPCClient) SendRawTransaction(ctx context.Context, signedTxHex str return tx.Hash().String(), nil } -func (rpc *EthRPCClient) signTxWithPrivateKey(ctx context.Context, to string, data string, gasFeeCap *big.Int, gasLimit uint64) (string, error) { +func getAddressFromPrivateKey() (common.Address, *ecdsa.PrivateKey, error) { // Getting public address from private key // Decode the provided private key. privKey := os.Getenv("WVM_PRIV_KEY") if privKey == "" { - panic("wvm archiver signer key is empty") + return common.Address{}, nil, fmt.Errorf("wvm archiver signer key is empty") } + pKeyBytes, err := hexutil.Decode("0x" + privKey) if err != nil { - return "", err + return common.Address{}, nil, err } // Convert the private key bytes to an ECDSA private key. ecdsaPrivateKey, err := crypto.ToECDSA(pKeyBytes) if err != nil { - return "", err + return common.Address{}, nil, err } // Extract the public key from the ECDSA private key. publicKey := ecdsaPrivateKey.Public() publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) if !ok { - return "", fmt.Errorf("error casting public key to ECDSA") + return common.Address{}, nil, fmt.Errorf("error casting public key to ECDSA") } // Compute the Ethereum address of the signer from the public key. fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) + return fromAddress, ecdsaPrivateKey, nil +} +func (rpc *EthRPCClient) signTxWithPrivateKey(ctx context.Context, to string, data string, gasFeeCap *big.Int, gasLimit uint64) (string, error) { + fromAddress, ecdsaPrivateKey, err := getAddressFromPrivateKey() + if err != nil { + return "", err + } // Retrieve the nonce for the signer's account, representing the transaction count. nonce, err := rpc.client.PendingNonceAt(ctx, fromAddress) if err != nil {