Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetworkTests: add options for test users to use gateway #1806

Merged
merged 5 commits into from
Feb 21, 2024
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
10 changes: 5 additions & 5 deletions integration/networktest/actions/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ var KeyNumberOfTestUsers = ActionKey("numberOfTestUsers")
// ActionKey is the type for all test data stored in the context. Go documentation recommends using a typed key rather than string to avoid conflicts.
type ActionKey string

func storeTestUser(ctx context.Context, userNumber int, user *userwallet.UserWallet) context.Context {
func storeTestUser(ctx context.Context, userNumber int, user userwallet.User) context.Context {
return context.WithValue(ctx, userKey(userNumber), user)
}

func FetchTestUser(ctx context.Context, userNumber int) (*userwallet.UserWallet, error) {
func FetchTestUser(ctx context.Context, userNumber int) (userwallet.User, error) {
u := ctx.Value(userKey(userNumber))
if u == nil {
return nil, fmt.Errorf("no UserWallet found in context for userNumber=%d", userNumber)
return nil, fmt.Errorf("no userWallet found in context for userNumber=%d", userNumber)
}
user, ok := u.(*userwallet.UserWallet)
user, ok := u.(userwallet.User)
if !ok {
return nil, fmt.Errorf("user retrieved from context was not of expected type UserWallet for userNumber=%d type=%T", userNumber, u)
return nil, fmt.Errorf("user retrieved from context was not of expected type userWallet for userNumber=%d type=%T", userNumber, u)
}
return user, nil
}
Expand Down
4 changes: 2 additions & 2 deletions integration/networktest/actions/native_fund_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type SendNativeFunds struct {
GasLimit *big.Int
SkipVerify bool

user *userwallet.UserWallet
user userwallet.User
txHash *common.Hash
}

Expand All @@ -35,7 +35,7 @@ func (s *SendNativeFunds) Run(ctx context.Context, _ networktest.NetworkConnecto
if err != nil {
return ctx, err
}
txHash, err := user.SendFunds(ctx, target.Address(), s.Amount)
txHash, err := user.SendFunds(ctx, target.Wallet().Address(), s.Amount)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions integration/networktest/actions/node_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (w *waitForValidatorHealthCheckAction) Run(ctx context.Context, network net
validator := network.GetValidatorNode(w.validatorIdx)
// poll the health check until success or timeout
err := retry.Do(func() error {
return networktest.NodeHealthCheck(validator.HostRPCAddress())
return networktest.NodeHealthCheck(validator.HostRPCWSAddress())
}, retry.NewTimeoutStrategy(w.maxWait, 1*time.Second))
if err != nil {
return nil, err
Expand All @@ -158,7 +158,7 @@ func WaitForSequencerHealthCheck(maxWait time.Duration) networktest.Action {
sequencer := network.GetSequencerNode()
// poll the health check until success or timeout
err := retry.Do(func() error {
return networktest.NodeHealthCheck(sequencer.HostRPCAddress())
return networktest.NodeHealthCheck(sequencer.HostRPCWSAddress())
}, retry.NewTimeoutStrategy(maxWait, 1*time.Second))
if err != nil {
return nil, err
Expand Down
42 changes: 18 additions & 24 deletions integration/networktest/actions/setup_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
)

type CreateTestUser struct {
UserID int
UserID int
UseGateway bool
}

func (c *CreateTestUser) String() string {
Expand All @@ -21,9 +22,22 @@ func (c *CreateTestUser) String() string {

func (c *CreateTestUser) Run(ctx context.Context, network networktest.NetworkConnector) (context.Context, error) {
logger := testlog.Logger()

wal := datagenerator.RandomWallet(integration.TenChainID)
// traffic sim users are round robin-ed onto the validators for now (todo (@matt) - make that overridable)
user := userwallet.NewUserWallet(wal.PrivateKey(), network.ValidatorRPCAddress(c.UserID%network.NumValidators()), logger)
var user userwallet.User
if c.UseGateway {
gwURL, err := network.GetGatewayURL()
if err != nil {
return ctx, fmt.Errorf("failed to get required gateway URL: %w", err)
}
user, err = userwallet.NewGatewayUser(wal, gwURL, logger)
if err != nil {
return ctx, fmt.Errorf("failed to create gateway user: %w", err)
}
} else {
// traffic sim users are round robin-ed onto the validators for now (todo (@matt) - make that overridable)
user = userwallet.NewUserWallet(wal, network.ValidatorRPCAddress(c.UserID%network.NumValidators()), logger)
}
return storeTestUser(ctx, c.UserID, user), nil
}

Expand All @@ -44,7 +58,7 @@ func (a *AllocateFaucetFunds) Run(ctx context.Context, network networktest.Netwo
if err != nil {
return ctx, err
}
return ctx, network.AllocateFaucetFunds(ctx, user.Address())
return ctx, network.AllocateFaucetFunds(ctx, user.Wallet().Address())
}

func (a *AllocateFaucetFunds) Verify(_ context.Context, _ networktest.NetworkConnector) error {
Expand All @@ -65,23 +79,3 @@ func CreateAndFundTestUsers(numUsers int) *MultiAction {
newUserActions = append(newUserActions, SnapshotUserBalances(SnapAfterAllocation))
return Series(newUserActions...)
}

func AuthenticateAllUsers() networktest.Action {
return RunOnlyAction(func(ctx context.Context, network networktest.NetworkConnector) (context.Context, error) {
numUsers, err := FetchNumberOfTestUsers(ctx)
if err != nil {
return nil, fmt.Errorf("expected number of test users to be set on the context")
}
for i := 0; i < numUsers; i++ {
user, err := FetchTestUser(ctx, i)
if err != nil {
return nil, err
}
err = user.ResetClient(ctx)
if err != nil {
return nil, fmt.Errorf("unable to (re)authenticate client %d - %w", i, err)
}
}
return ctx, nil
})
}
24 changes: 20 additions & 4 deletions integration/networktest/env/dev_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ func (d *devNetworkEnv) Prepare() (networktest.NetworkConnector, func(), error)
}

func awaitNodesAvailable(nc networktest.NetworkConnector) error {
err := awaitHealthStatus(nc.GetSequencerNode().HostRPCAddress(), 60*time.Second)
err := awaitHealthStatus(nc.GetSequencerNode().HostRPCWSAddress(), 60*time.Second)
if err != nil {
return err
}
for i := 0; i < nc.NumValidators(); i++ {
err := awaitHealthStatus(nc.GetValidatorNode(i).HostRPCAddress(), 60*time.Second)
err := awaitHealthStatus(nc.GetValidatorNode(i).HostRPCWSAddress(), 60*time.Second)
if err != nil {
return err
}
Expand Down Expand Up @@ -61,12 +61,28 @@ func awaitHealthStatus(rpcAddress string, timeout time.Duration) error {
}, retry.NewTimeoutStrategy(timeout, 200*time.Millisecond))
}

func LocalDevNetwork() networktest.Environment {
return &devNetworkEnv{inMemDevNetwork: devnetwork.DefaultDevNetwork()}
func LocalDevNetwork(opts ...LocalNetworkOption) networktest.Environment {
config := &LocalNetworkConfig{}
for _, opt := range opts {
opt(config)
}
return &devNetworkEnv{inMemDevNetwork: devnetwork.DefaultDevNetwork(config.TenGatewayEnabled)}
}

// LocalNetworkLiveL1 creates a local network that points to a live running L1.
// Note: seqWallet and validatorWallets need funds. seqWallet is used to deploy the L1 contracts
func LocalNetworkLiveL1(seqWallet wallet.Wallet, validatorWallets []wallet.Wallet, l1RPCURLs []string) networktest.Environment {
return &devNetworkEnv{inMemDevNetwork: devnetwork.LiveL1DevNetwork(seqWallet, validatorWallets, l1RPCURLs)}
}

type LocalNetworkConfig struct {
TenGatewayEnabled bool
}

type LocalNetworkOption func(*LocalNetworkConfig)

func WithTenGateway() LocalNetworkOption {
return func(c *LocalNetworkConfig) {
c.TenGatewayEnabled = true
}
}
4 changes: 4 additions & 0 deletions integration/networktest/env/network_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func SepoliaTestnet() networktest.Environment {
[]string{"http://erpc.sepolia-testnet.ten.xyz:80"},
"http://sepolia-testnet-faucet.uksouth.azurecontainer.io/fund/eth",
"https://rpc.sepolia.org/",
"https://testnet.ten.xyz", // :81 for websocket
)
return &testnetEnv{connector}
}
Expand All @@ -21,6 +22,7 @@ func UATTestnet() networktest.Environment {
[]string{"http://erpc.uat-testnet.ten.xyz:80"},
"http://uat-testnet-faucet.uksouth.azurecontainer.io/fund/eth",
"ws://uat-testnet-eth2network.uksouth.cloudapp.azure.com:9000",
"https://uat-testnet.ten.xyz",
)
return &testnetEnv{connector}
}
Expand All @@ -31,6 +33,7 @@ func DevTestnet() networktest.Environment {
[]string{"http://erpc.dev-testnet.ten.xyz:80"},
"http://dev-testnet-faucet.uksouth.azurecontainer.io/fund/eth",
"ws://dev-testnet-eth2network.uksouth.cloudapp.azure.com:9000",
"https://dev-testnet.ten.xyz",
)
return &testnetEnv{connector}
}
Expand All @@ -42,6 +45,7 @@ func LongRunningLocalNetwork(l1WSURL string) networktest.Environment {
[]string{"ws://127.0.0.1:37901"},
genesis.TestnetPrefundedPK,
l1WSURL,
"",
)
return &testnetEnv{connector}
}
Expand Down
23 changes: 19 additions & 4 deletions integration/networktest/env/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,32 @@ type testnetConnector struct {
validatorRPCAddresses []string
faucetHTTPAddress string
l1RPCURL string
faucetWallet *userwallet.UserWallet
tenGatewayURL string
faucetWallet userwallet.User
}

func NewTestnetConnector(seqRPCAddr string, validatorRPCAddressses []string, faucetHTTPAddress string, l1WSURL string) networktest.NetworkConnector {
func NewTestnetConnector(seqRPCAddr string, validatorRPCAddressses []string, faucetHTTPAddress string, l1WSURL string, tenGatewayURL string) networktest.NetworkConnector {
return &testnetConnector{
seqRPCAddress: seqRPCAddr,
validatorRPCAddresses: validatorRPCAddressses,
faucetHTTPAddress: faucetHTTPAddress,
l1RPCURL: l1WSURL,
tenGatewayURL: tenGatewayURL,
}
}

func NewTestnetConnectorWithFaucetAccount(seqRPCAddr string, validatorRPCAddressses []string, faucetPK string, l1RPCAddress string) networktest.NetworkConnector {
func NewTestnetConnectorWithFaucetAccount(seqRPCAddr string, validatorRPCAddressses []string, faucetPK string, l1RPCAddress string, tenGatewayURL string) networktest.NetworkConnector {
ecdsaKey, err := crypto.HexToECDSA(faucetPK)
if err != nil {
panic(err)
}
wal := wallet.NewInMemoryWalletFromPK(big.NewInt(integration.TenChainID), ecdsaKey, testlog.Logger())
return &testnetConnector{
seqRPCAddress: seqRPCAddr,
validatorRPCAddresses: validatorRPCAddressses,
faucetWallet: userwallet.NewUserWallet(ecdsaKey, validatorRPCAddressses[0], testlog.Logger(), userwallet.WithChainID(big.NewInt(integration.TenChainID))),
faucetWallet: userwallet.NewUserWallet(wal, validatorRPCAddressses[0], testlog.Logger()),
l1RPCURL: l1RPCAddress,
tenGatewayURL: tenGatewayURL,
}
}

Expand Down Expand Up @@ -131,3 +135,14 @@ func (t *testnetConnector) AllocateFaucetFundsWithWallet(ctx context.Context, ac
func (t *testnetConnector) GetMCOwnerWallet() (wallet.Wallet, error) {
return nil, errors.New("testnet connector environments cannot access the MC owner wallet")
}

func (t *testnetConnector) GetGatewayClient() (ethadapter.EthClient, error) {
if t.tenGatewayURL == "" {
return nil, errors.New("gateway client not set for this environment")
}
return ethadapter.NewEthClientFromURL(t.tenGatewayURL, time.Minute, gethcommon.Address{}, testlog.Logger())
}

func (t *testnetConnector) GetGatewayURL() (string, error) {
return t.tenGatewayURL, nil
}
4 changes: 3 additions & 1 deletion integration/networktest/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type NetworkConnector interface {
GetValidatorNode(idx int) NodeOperator
GetL1Client() (ethadapter.EthClient, error)
GetMCOwnerWallet() (wallet.Wallet, error) // wallet that owns the management contract (network admin)
GetGatewayURL() (string, error)
}

// Action is any step in a test, they will typically be either minimally small steps in the test or they will be containers
Expand Down Expand Up @@ -62,5 +63,6 @@ type NodeOperator interface {
StartHost() error
StopHost() error

HostRPCAddress() string
HostRPCHTTPAddress() string
HostRPCWSAddress() string
}
41 changes: 41 additions & 0 deletions integration/networktest/tests/gateway/gateway_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gateway

import (
"math/big"
"testing"

"github.com/ten-protocol/go-ten/integration/networktest"
"github.com/ten-protocol/go-ten/integration/networktest/actions"
"github.com/ten-protocol/go-ten/integration/networktest/env"
)

var _transferAmount = big.NewInt(100_000_000)

// TestGatewayHappyPath tests ths same functionality as the smoke_test but with the gateway:
// 1. Create two test users
// 2. Allocate funds to the first user
// 3. Send funds from the first user to the second
// 4. Verify the second user has the funds
// 5. Verify the first user has the funds deducted
// To run this test with a local network use the flag to start it with the gateway enabled.
func TestGatewayHappyPath(t *testing.T) {
networktest.TestOnlyRunsInIDE(t)
networktest.Run(
"gateway-happy-path",
t,
env.LocalDevNetwork(env.WithTenGateway()),
actions.Series(
&actions.CreateTestUser{UserID: 0, UseGateway: true},
&actions.CreateTestUser{UserID: 1, UseGateway: true},
actions.SetContextValue(actions.KeyNumberOfTestUsers, 2),

&actions.AllocateFaucetFunds{UserID: 0},
actions.SnapshotUserBalances(actions.SnapAfterAllocation), // record user balances (we have no guarantee on how much the network faucet allocates)

&actions.SendNativeFunds{FromUser: 0, ToUser: 1, Amount: _transferAmount},

&actions.VerifyBalanceAfterTest{UserID: 1, ExpectedBalance: _transferAmount},
&actions.VerifyBalanceDiffAfterTest{UserID: 0, Snapshot: actions.SnapAfterAllocation, ExpectedDiff: big.NewInt(0).Neg(_transferAmount)},
),
)
}
4 changes: 2 additions & 2 deletions integration/networktest/tests/helpful/availability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import (
"github.com/ten-protocol/go-ten/integration/networktest/env"
)

const _testTimeSpan = 120 * time.Second
const _testTimeSpan = 30 * time.Second

// basic test that verifies it can connect the L1 client and L2 client and sees block numbers increasing (useful to sanity check testnet issues etc.)
func TestNetworkAvailability(t *testing.T) {
networktest.TestOnlyRunsInIDE(t)
networktest.Run(
"network-availability",
t,
env.DevTestnet(),
env.SepoliaTestnet(),
actions.RunOnlyAction(func(ctx context.Context, network networktest.NetworkConnector) (context.Context, error) {
client, err := network.GetL1Client()
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ func TestRestartNetwork(t *testing.T) {
// This needs investigating but it suggests to me that the health check is succeeding prematurely
actions.SleepAction(5*time.Second), // allow time for re-sync

// resubmit user viewing keys (all users will have lost their "session")
// todo: get rid of this once the enclave persists viewing keys correctly
actions.AuthenticateAllUsers(),

// another load test, check that the network is still working
actions.GenerateUsersRandomisedTransferActionsInParallel(4, 60*time.Second),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ func TestRestartValidatorEnclave(t *testing.T) {
// This needs investigating but it suggests to me that the health check is succeeding prematurely
actions.SleepAction(5*time.Second), // allow time for re-sync

// resubmit user viewing keys (any users attached to the restarted node will have lost their "session")
// todo (@matt) - get rid of this once the enclave persists viewing keys correctly
actions.AuthenticateAllUsers(),

// another load test (important that at least one of the users will be using the validator with restarted enclave)
actions.GenerateUsersRandomisedTransferActionsInParallel(4, 10*time.Second),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ func TestRestartValidatorNode(t *testing.T) {
// This needs investigating but it suggests to me that the health check is succeeding prematurely
actions.SleepAction(5*time.Second), // allow time for re-sync

// resubmit user viewing keys (any users attached to the restarted node will have lost their "session")
// todo (@matt) - get rid of this once the enclave persists viewing keys correctly
actions.AuthenticateAllUsers(),

// another load test (important that at least one of the users will be using the validator with restarted enclave)
actions.GenerateUsersRandomisedTransferActionsInParallel(4, 10*time.Second),
),
Expand Down
Loading
Loading