Skip to content

Commit

Permalink
fix cache for authenticated method calls (#1808)
Browse files Browse the repository at this point in the history
* fix cache for authenticated method calls

* fix mutex error

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

---------

Co-authored-by: Matt <[email protected]>
  • Loading branch information
zkokelj and BedrockSquirrel authored Feb 21, 2024
1 parent 82d4d3a commit 5772cbf
Show file tree
Hide file tree
Showing 25 changed files with 644 additions and 361 deletions.
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

0 comments on commit 5772cbf

Please sign in to comment.