diff --git a/account/accounts_test.go b/account/accounts_test.go index a6b2afdc7..e85f8abeb 100644 --- a/account/accounts_test.go +++ b/account/accounts_test.go @@ -269,7 +269,7 @@ func (s *ManagerTestSuite) TestSetChatAccount() { address := crypto.PubkeyToAddress(privKey.PublicKey) - s.accManager.SetChatAccount(privKey) + s.Require().NoError(s.accManager.SetChatAccount(privKey)) selectedChatAccount, err := s.accManager.SelectedChatAccount() s.Require().NoError(err) s.Require().NotNil(selectedChatAccount) diff --git a/api/geth_backend.go b/api/geth_backend.go index f4dbf3b95..a54e74fed 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -33,10 +33,6 @@ import ( "github.com/status-im/status-go/transactions" ) -const ( - contractQueryTimeout = 1000 * time.Millisecond -) - var ( // ErrWhisperClearIdentitiesFailure clearing whisper identities has failed. ErrWhisperClearIdentitiesFailure = errors.New("failed to clear whisper identities") @@ -278,7 +274,9 @@ func (b *GethStatusBackend) startNodeWithKey(acc multiaccounts.Account, password if err != nil { return err } - b.accountManager.SetChatAccount(chatKey) + if err := b.accountManager.SetChatAccount(chatKey); err != nil { + return err + } _, err = b.accountManager.SelectedChatAccount() if err != nil { return err diff --git a/cmd/populate-db/main.go b/cmd/populate-db/main.go index 45b161228..56176d634 100644 --- a/cmd/populate-db/main.go +++ b/cmd/populate-db/main.go @@ -3,7 +3,6 @@ package main import ( "context" "encoding/json" - "errors" "flag" "fmt" stdlog "log" @@ -25,6 +24,7 @@ import ( "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts/accounts" + //"github.com/status-im/status-go/appdatabase" //gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" "github.com/status-im/status-go/eth-node/crypto" @@ -54,8 +54,6 @@ var ( ipcEnabled = flag.Bool("ipc", false, "Enable IPC RPC endpoint") ipcFile = flag.String("ipcfile", "", "Set IPC file path") seedPhrase = flag.String("seed-phrase", "", "Seed phrase") - pprofEnabled = flag.Bool("pprof", false, "Enable runtime profiling via pprof") - pprofPort = flag.Int("pprof-port", 52525, "Port for runtime profiling via pprof") version = flag.Bool("version", false, "Print version and dump configuration") nAddedContacts = flag.Int("added-contacts", 100, "Number of added contacts to create") nContacts = flag.Int("contacts", 100, "Number of contacts to create") @@ -64,7 +62,6 @@ var ( nOneToOneChats = flag.Int("one-to-one-chats", 5, "Number of one to one chats") dataDir = flag.String("dir", getDefaultDataDir(), "Directory used by node to store data") - register = flag.Bool("register", false, "Register and make the node discoverable by other nodes") networkID = flag.Int( "network-id", params.RopstenNetworkID, @@ -74,8 +71,6 @@ var ( ), ) listenAddr = flag.String("addr", "", "address to bind listener to") - - syncAndExit = flag.Int("sync-and-exit", -1, "Timeout in minutes for blockchain sync and exit, zero means no timeout unless sync is finished") ) // All general log messages in this package should be routed through this logger. @@ -253,12 +248,6 @@ func main() { } } - url := "enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443" - fmt.Println("UPDATING") - wakuext.UpdateMailservers([]string{url}) - time.Sleep(10 * time.Second) - fmt.Println("UPDATED") - } func getDefaultDataDir() string { @@ -279,12 +268,6 @@ func setupLogging(config *params.NodeConfig) { } } -var ( - errStatusServiceRequiresIPC = errors.New("to enable the StatusService on IPC, -ipc flag must be set") - errStatusServiceRequiresHTTP = errors.New("to enable the StatusService on HTTP, -http flag must be set") - errStatusServiceInvalidFlag = errors.New("-status flag valid values are: ipc, http") -) - // printVersion prints verbose output about version and config. func printVersion(config *params.NodeConfig) { fmt.Println(strings.Title(config.Name)) @@ -429,7 +412,9 @@ func defaultNodeConfig(installationID string) (*params.NodeConfig, error) { func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { backend.UpdateRootDataDir("./tmp") manager := backend.AccountManager() - manager.InitKeystore("./tmp") + if err := manager.InitKeystore("./tmp"); err != nil { + return err + } err := backend.OpenAccounts() if err != nil { logger.Error("failed open accounts", err) @@ -438,19 +423,16 @@ func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { generator := manager.AccountsGenerator() generatedAccountInfo, err := generator.ImportMnemonic(seedPhrase, "") if err != nil { - logger.Error("import mnemonic", err) return err } derivedAddresses, err := generator.DeriveAddresses(generatedAccountInfo.ID, paths) if err != nil { - logger.Error("deriver addressess", err) return err } _, err = generator.StoreDerivedAccounts(generatedAccountInfo.ID, "", paths) if err != nil { - logger.Error("store addressess", err) return err } @@ -459,13 +441,11 @@ func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { } settings, err := defaultSettings(generatedAccountInfo, derivedAddresses, &seedPhrase) if err != nil { - logger.Error("default settings", err) return err } nodeConfig, err := defaultNodeConfig(settings.InstallationID) if err != nil { - logger.Error("node config", err) return err } @@ -529,14 +509,14 @@ func buildMessage(chat *protocol.Chat, count int) *common.Message { message.MessageType = protobuf.MessageType_PRIVATE_GROUP } - message.PrepareContent("") + _ = message.PrepareContent("") return message } func randomString(n int) string { b := make([]rune, n) for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] + b[i] = letterRunes[rand.Intn(len(letterRunes))] // nolint: gosec } return string(b) } diff --git a/cmd/populate-db/sync.go b/cmd/populate-db/sync.go deleted file mode 100644 index f555b7a70..000000000 --- a/cmd/populate-db/sync.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "context" - "time" -) - -func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) { - if timeout == 0 { - return context.WithCancel(context.Background()) - } - - return context.WithTimeout(context.Background(), time.Duration(timeout)*time.Minute) -} diff --git a/cmd/statusd/sync.go b/cmd/statusd/sync.go deleted file mode 100644 index f555b7a70..000000000 --- a/cmd/statusd/sync.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "context" - "time" -) - -func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) { - if timeout == 0 { - return context.WithCancel(context.Background()) - } - - return context.WithTimeout(context.Background(), time.Duration(timeout)*time.Minute) -} diff --git a/node/get_status_node.go b/node/get_status_node.go index 6e2401569..15b409bf5 100644 --- a/node/get_status_node.go +++ b/node/get_status_node.go @@ -9,7 +9,6 @@ import ( "path/filepath" "reflect" "sync" - "time" ma "github.com/multiformats/go-multiaddr" "github.com/syndtr/goleveldb/leveldb" @@ -35,7 +34,6 @@ import ( "github.com/status-im/status-go/services/browsers" localnotifications "github.com/status-im/status-go/services/local-notifications" "github.com/status-im/status-go/services/mailservers" - "github.com/status-im/status-go/services/nodebridge" "github.com/status-im/status-go/services/peer" "github.com/status-im/status-go/services/permissions" "github.com/status-im/status-go/services/personal" @@ -50,9 +48,6 @@ import ( "github.com/status-im/status-go/wakuv2" ) -// tickerResolution is the delta to check blockchain sync progress. -const tickerResolution = time.Second - // errors var ( ErrNodeRunning = errors.New("node is already running") @@ -96,7 +91,6 @@ type StatusNode struct { rpcStatsSrvc *rpcstats.Service accountsSrvc *accountssvc.Service browsersSrvc *browsers.Service - nodeBridgeSrvc *nodebridge.NodeService permissionsSrvc *permissions.Service mailserversSrvc *mailservers.Service appMetricsSrvc *appmetricsservice.Service @@ -403,7 +397,6 @@ func (n *StatusNode) stop() error { n.rpcStatsSrvc = nil n.accountsSrvc = nil n.browsersSrvc = nil - n.nodeBridgeSrvc = nil n.permissionsSrvc = nil n.mailserversSrvc = nil n.appMetricsSrvc = nil diff --git a/node/geth_node.go b/node/geth_node.go index 4ccbfae96..701b3039f 100644 --- a/node/geth_node.go +++ b/node/geth_node.go @@ -1,7 +1,6 @@ package node import ( - "encoding/json" "errors" "fmt" "os" @@ -10,7 +9,6 @@ import ( "github.com/syndtr/goleveldb/leveldb" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" @@ -20,7 +18,6 @@ import ( "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/params" - "github.com/status-im/status-go/static" ) // Errors related to node and services creation. @@ -69,7 +66,7 @@ func MakeNode(config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB) // newGethNodeConfig returns default stack configuration for mobile client node func newGethNodeConfig(config *params.NodeConfig) (*node.Config, error) { - // NOTE: I haven't changed anything related to this paramters, but + // NOTE: I haven't changed anything related to this parameters, but // it seems they were previously ignored if set to 0, but now they seem // to be used, so they need to be set to something maxPeers := 100 @@ -133,46 +130,6 @@ func newGethNodeConfig(config *params.NodeConfig) (*node.Config, error) { return nc, nil } -// calculateGenesis retrieves genesis value for given network -func calculateGenesis(networkID uint64) (*core.Genesis, error) { - var genesis *core.Genesis - - switch networkID { - case params.MainNetworkID: - genesis = core.DefaultGenesisBlock() - case params.RopstenNetworkID: - genesis = core.DefaultRopstenGenesisBlock() - case params.RinkebyNetworkID: - genesis = core.DefaultRinkebyGenesisBlock() - case params.GoerliNetworkID: - genesis = core.DefaultGoerliGenesisBlock() - case params.StatusChainNetworkID: - var err error - if genesis, err = defaultStatusChainGenesisBlock(); err != nil { - return nil, err - } - default: - return nil, nil - } - - return genesis, nil -} - -// defaultStatusChainGenesisBlock returns the StatusChain network genesis block. -func defaultStatusChainGenesisBlock() (*core.Genesis, error) { - genesisJSON, err := static.ConfigStatusChainGenesisJsonBytes() - if err != nil { - return nil, fmt.Errorf("status-chain-genesis.json could not be loaded: %s", err) - } - - var genesis *core.Genesis - err = json.Unmarshal(genesisJSON, &genesis) - if err != nil { - return nil, fmt.Errorf("cannot unmarshal status-chain-genesis.json: %s", err) - } - return genesis, nil -} - // parseNodes creates list of enode.Node out of enode strings. func parseNodes(enodes []string) []*enode.Node { var nodes []*enode.Node diff --git a/node/rpc.go b/node/rpc.go index f1b27b9f0..acdaf1a11 100644 --- a/node/rpc.go +++ b/node/rpc.go @@ -27,5 +27,4 @@ func addSuitableCallbacks(receiver reflect.Value, namespace string, methods map[ name := formatName(method.Name) methods[namespace+"_"+name] = true } - return } diff --git a/node/status_node_services.go b/node/status_node_services.go index a1bb22c18..27cca5dc6 100644 --- a/node/status_node_services.go +++ b/node/status_node_services.go @@ -27,7 +27,6 @@ import ( "github.com/status-im/status-go/services/ext" localnotifications "github.com/status-im/status-go/services/local-notifications" "github.com/status-im/status-go/services/mailservers" - "github.com/status-im/status-go/services/nodebridge" "github.com/status-im/status-go/services/peer" "github.com/status-im/status-go/services/permissions" "github.com/status-im/status-go/services/personal" @@ -142,13 +141,6 @@ func (b *StatusNode) nodeBridge() types.Node { return gethbridge.NewNodeBridge(b.gethNode, b.wakuSrvc, b.wakuV2Srvc) } -func (b *StatusNode) nodeBridgeService() *nodebridge.NodeService { - if b.nodeBridgeSrvc == nil { - b.nodeBridgeSrvc = &nodebridge.NodeService{Node: b.nodeBridge()} - } - return b.nodeBridgeSrvc -} - func (b *StatusNode) wakuExtService(config *params.NodeConfig) (*wakuext.Service, error) { if b.gethNode == nil { return nil, errors.New("geth node not initialized") diff --git a/services/nodebridge/node_service.go b/services/nodebridge/node_service.go deleted file mode 100644 index dad4849f3..000000000 --- a/services/nodebridge/node_service.go +++ /dev/null @@ -1,45 +0,0 @@ -package nodebridge - -import ( - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/status-im/status-go/eth-node/types" -) - -// Make sure that NodeService implements node.Lifecycle interface. -var _ node.Lifecycle = (*NodeService)(nil) - -type NodeService struct { - Node types.Node -} - -// Protocols returns a new protocols list. In this case, there are none. -func (w *NodeService) Protocols() []p2p.Protocol { - return []p2p.Protocol{} -} - -// APIs returns a list of new APIs. -func (w *NodeService) APIs() []rpc.API { - return []rpc.API{ - { - Namespace: "status", - Version: "1.0", - Service: w.Node, - Public: false, - }, - } -} - -// Start is run when a service is started. -// It does nothing in this case but is required by `node.Lifecycle` interface. -func (w *NodeService) Start() error { - return nil -} - -// Stop is run when a service is stopped. -// It does nothing in this case but is required by `node.Lifecycle` interface. -func (w *NodeService) Stop() error { - return nil -} diff --git a/services/nodebridge/waku_service.go b/services/nodebridge/waku_service.go deleted file mode 100644 index a1fcd979a..000000000 --- a/services/nodebridge/waku_service.go +++ /dev/null @@ -1,45 +0,0 @@ -package nodebridge - -import ( - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/status-im/status-go/eth-node/types" -) - -// Make sure that WakuService implements node.Lifecycle interface. -var _ node.Lifecycle = (*WakuService)(nil) - -type WakuService struct { - Waku types.Waku -} - -// Protocols returns a new protocols list. In this case, there are none. -func (w *WakuService) Protocols() []p2p.Protocol { - return []p2p.Protocol{} -} - -// APIs returns a list of new APIs. -func (w *WakuService) APIs() []rpc.API { - return []rpc.API{ - { - Namespace: "status", - Version: "1.0", - Service: w.Waku, - Public: false, - }, - } -} - -// Start is run when a service is started. -// It does nothing in this case but is required by `node.Lifecycle` interface. -func (w *WakuService) Start() error { - return nil -} - -// Stop is run when a service is stopped. -// It does nothing in this case but is required by `node.Service` interface. -func (w *WakuService) Stop() error { - return nil -} diff --git a/services/typeddata/sign_test.go b/services/typeddata/sign_test.go index e78ef4692..5ff49dcc6 100644 --- a/services/typeddata/sign_test.go +++ b/services/typeddata/sign_test.go @@ -8,21 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -var ( - fromWallet = ` -{ - "name": "Cow", - "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" -} -` - toWallet = ` -{ - "name": "Bob", - "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" -} -` -) - func TestChainIDValidation(t *testing.T) { chain := big.NewInt(10) type testCase struct { diff --git a/t/e2e/README.md b/t/e2e/README.md deleted file mode 100644 index 79b6f4bec..000000000 --- a/t/e2e/README.md +++ /dev/null @@ -1,81 +0,0 @@ -e2e -=== - -This package contains all e2e tests divided into subpackages which represents (or should represent) business domains like transactions, chat etc. - -These tests are run against public testnets: Ropsten and Rinkeby. - -e2e package contains a few utilities which are described in a [godoc](https://godoc.org/github.com/status-im/status-go/t/e2e). - -### Flags - -#### 1. `-network` -The `-network` flag is used to provide either a network id or network name which specifies the ethereum network to use -for running all test. It by default uses the `StatusChain` network. - -#### Usage - -First of all you need to export an ACCOUNT_PASSWORD environment variable. It should be a passphrase -that was used to generate accounts used in tests. If you don't know this variable for default accounts -you will have to create your own accounts and request some funds from rinkeby or ropsten faucet. -Please see Preparation section for details. - -To use the `ropsten` network for testing using network name: - -```bash -ACCOUNT_PASSWORD=test go test -v ./t/e2e/... -p=1 -network=ropsten -``` - -To use the `rinkeby` network with chain id `4` for testing: - -```bash -ACCOUNT_PASSWORD=test go test -v ./t/e2e/... -p=1 -network=4 -``` - -#### Preparation - -You will need `geth` in your PATH. Please visit: https://www.ethereum.org/cli. -Once installed - generate 2 accounts and remember the passphrase for them, so run this command twice: - -```bash -geth account new --keystore=static/keys/ -Your new account is locked with a password. Please give a password. Do not forget this password. -Passphrase: -Repeat passphrase: -Address: {b6120ddd881593537c2bd4280bae509ec94b1a6b} -``` - -We expect that accounts will be named in a certain way: - -```bash -pushd static/keys/ -mv UTC--2018-01-26T13-46-53.657752811Z--b6120ddd881593537c2bd4280bae509ec94b1a6b test-account1.pk -mv UTC--2018-01-26T13-47-49.289567120Z--9f04dc05c4c3ec3b8b1f36f7d7d153f3934b1f07 test-account2.pk -popd -``` - -Update config for tests with new accounts `t/config/public-chain-accounts.json`: - -```json -{ - "Account1": { - "Address": "0xb6120ddd881593537c2bd4280bae509ec94b1a6b" - }, - "Account2": { - "Address": "0x9f04dc05c4c3ec3b8b1f36f7d7d153f3934b1f07" - } -} -``` - -Embed keys as a binary data, you will need to install `npm` tool and web3.js lib: - -```bash -make generate -``` - -As a final step request funds from faucet for a chosen network: - -- [Rinkeby](https://faucet.rinkeby.io/) -- [Ropsten](http://faucet.ropsten.be:3001/) - -Finally, you are ready to run tests! diff --git a/t/e2e/accounts/accounts_rpc_test.go b/t/e2e/accounts/accounts_rpc_test.go deleted file mode 100644 index 5cc6118ea..000000000 --- a/t/e2e/accounts/accounts_rpc_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package accounts - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/t/e2e" - . "github.com/status-im/status-go/t/utils" -) - -func TestAccountsRPCTestSuite(t *testing.T) { - suite.Run(t, new(AccountsRPCTestSuite)) -} - -type AccountsRPCTestSuite struct { - e2e.BackendTestSuite -} - -func (s *AccountsTestSuite) TestRPCEthAccounts() { - s.StartTestBackend() - defer s.StopTestBackend() - - // log into test account - loginParams, err := buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password, nil) - s.Require().NoError(err) - - err = s.Backend.SelectAccount(loginParams) - s.NoError(err) - - rpcClient := s.Backend.StatusNode().RPCClient() - s.NotNil(rpcClient) - - expectedResponse := `{"jsonrpc":"2.0","id":1,"result":["` + strings.ToLower(TestConfig.Account1.WalletAddress) + `"]}` - resp := rpcClient.CallRaw(`{ - "jsonrpc": "2.0", - "id": 1, - "method": "eth_accounts", - "params": [] - }`) - - s.Equal(expectedResponse, resp) -} - -func (s *AccountsTestSuite) TestRPCEthAccountsWithUpstream() { - if GetNetworkID() == params.StatusChainNetworkID { - s.T().Skip() - } - - addr, err := GetRemoteURL() - s.NoError(err) - s.StartTestBackend(e2e.WithUpstream(addr)) - defer s.StopTestBackend() - - // log into test account - loginParams, err := buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password, nil) - s.Require().NoError(err) - - err = s.Backend.SelectAccount(loginParams) - s.NoError(err) - - rpcClient := s.Backend.StatusNode().RPCClient() - s.NotNil(rpcClient) - - expectedResponse := `{"jsonrpc":"2.0","id":1,"result":["` + strings.ToLower(TestConfig.Account1.WalletAddress) + `"]}` - resp := rpcClient.CallRaw(`{ - "jsonrpc": "2.0", - "id": 1, - "method": "eth_accounts", - "params": [] - }`) - s.Equal(expectedResponse, resp) -} diff --git a/t/e2e/accounts/accounts_test.go b/t/e2e/accounts/accounts_test.go deleted file mode 100644 index 2fe5260a9..000000000 --- a/t/e2e/accounts/accounts_test.go +++ /dev/null @@ -1,297 +0,0 @@ -package accounts - -import ( - "errors" - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/ethereum/go-ethereum/crypto" - - "github.com/status-im/status-go/account" - "github.com/status-im/status-go/account/generator" - "github.com/status-im/status-go/eth-node/types" - "github.com/status-im/status-go/extkeys" - "github.com/status-im/status-go/t/e2e" - "github.com/status-im/status-go/t/utils" -) - -func buildLoginParams(mainAccountAddress, chatAddress, password string, watchAddresses []types.Address) (account.LoginParams, error) { - privateKey, err := crypto.GenerateKey() - if err != nil { - return account.LoginParams{}, err - } - - acc := generator.NewAccount(privateKey, nil) - iai := acc.ToIdentifiedAccountInfo("") - - return account.LoginParams{ - ChatAddress: types.HexToAddress(chatAddress), - Password: password, - MainAccount: types.HexToAddress(mainAccountAddress), - WatchAddresses: watchAddresses, - MultiAccount: iai.ToMultiAccount(), - }, nil -} - -func TestAccountsTestSuite(t *testing.T) { - utils.Init() - suite.Run(t, new(AccountsTestSuite)) -} - -type AccountsTestSuite struct { - e2e.BackendTestSuite -} - -func (s *AccountsTestSuite) TestAccountsList() { - s.StartTestBackend() - defer s.StopTestBackend() - - accounts, err := s.Backend.AccountManager().Accounts() - s.NoError(err) - - // make sure that we start with empty accounts list (nobody has logged in yet) - s.Zero(len(accounts), "accounts returned, while there should be none (we haven't logged in yet)") - - // create an account - _, accountInfo, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) - s.NoError(err) - - // ensure that there is still no accounts returned - accounts, err = s.Backend.AccountManager().Accounts() - s.NoError(err) - s.Zero(len(accounts), "accounts returned, while there should be none (we haven't logged in yet)") - - loginParams, err := buildLoginParams( - accountInfo.WalletAddress, - accountInfo.ChatAddress, - utils.TestConfig.Account1.Password, - nil, - ) - - s.Require().NoError(err) - - // select account (sub-accounts will be created for this key) - err = s.Backend.SelectAccount(loginParams) - s.NoError(err, "account selection failed") - - // at this point main account should show up - accounts, err = s.Backend.AccountManager().Accounts() - s.NoError(err) - s.Equal(1, len(accounts), "exactly single account is expected (main account)") - s.Equal(accounts[0].Hex(), accountInfo.WalletAddress, - fmt.Sprintf("main account is not retured as the first key: got %s, expected %s", accounts[0].Hex(), "0x"+accountInfo.WalletAddress)) -} - -func (s *AccountsTestSuite) TestImportSingleExtendedKey() { - s.StartTestBackend() - defer s.StopTestBackend() - - keyStore := s.Backend.AccountManager().GetKeystore() - s.NotNil(keyStore) - - // create a master extended key - mn := extkeys.NewMnemonic() - mnemonic, err := mn.MnemonicPhrase(extkeys.EntropyStrength128, extkeys.EnglishLanguage) - s.NoError(err) - extKey, err := extkeys.NewMaster(mn.MnemonicSeed(mnemonic, "")) - s.NoError(err) - derivedExtendedKey, err := extKey.EthBIP44Child(0) - s.NoError(err) - - // import single extended key - password := "test-password-1" - addr, _, err := s.Backend.AccountManager().ImportSingleExtendedKey(derivedExtendedKey, password) - s.NoError(err) - - _, key, err := s.Backend.AccountManager().AddressToDecryptedAccount(addr, password) - s.NoError(err) - - s.Equal(crypto.FromECDSA(key.PrivateKey), crypto.FromECDSA(key.ExtendedKey.ToECDSA())) -} - -func (s *AccountsTestSuite) TestImportAccount() { - s.StartTestBackend() - defer s.StopTestBackend() - - keyStore := s.Backend.AccountManager().GetKeystore() - s.NotNil(keyStore) - - // create a private key - privateKey, err := crypto.GenerateKey() - s.NoError(err) - - // import as normal account - password := "test-password-2" - addr, err := s.Backend.AccountManager().ImportAccount(privateKey, password) - s.Require().NoError(err) - - _, key, err := s.Backend.AccountManager().AddressToDecryptedAccount(addr.String(), password) - s.NoError(err) - - s.Equal(crypto.FromECDSA(privateKey), crypto.FromECDSA(key.PrivateKey)) - s.True(key.ExtendedKey.IsZeroed()) -} - -func (s *AccountsTestSuite) TestRecoverAccount() { - s.StartTestBackend() - defer s.StopTestBackend() - - keyStore := s.Backend.AccountManager().GetKeystore() - s.NotNil(keyStore) - - // create an acc - _, accountInfo, mnemonic, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) - s.NoError(err) - s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s, mnemonic:%s}", - accountInfo.WalletAddress, accountInfo.WalletPubKey, accountInfo.ChatAddress, accountInfo.ChatPubKey, mnemonic) - - // try recovering using password + mnemonic - accountInfoCheck, err := s.Backend.AccountManager().RecoverAccount(utils.TestConfig.Account1.Password, mnemonic) - s.NoError(err, "recover acc failed") - - s.EqualValues(accountInfo, accountInfoCheck, "incorrect accound details recovered") - - // now test recovering, but make sure that acc/key file is removed i.e. simulate recovering on a new device - acc, err := account.ParseAccountString(accountInfo.WalletAddress) - s.NoError(err, "can not get acc from address") - - acc, key, err := keyStore.AccountDecryptedKey(acc, utils.TestConfig.Account1.Password) - s.NoError(err, "can not obtain decrypted acc key") - extChild2String := key.ExtendedKey.String() - - s.NoError(keyStore.Delete(acc, utils.TestConfig.Account1.Password), "cannot remove acc") - - accountInfoCheck, err = s.Backend.AccountManager().RecoverAccount(utils.TestConfig.Account1.Password, mnemonic) - s.NoError(err, "recover acc failed (for non-cached acc)") - s.EqualValues(accountInfo, accountInfoCheck, "incorrect acc details recovered (for non-cached acc)") - - // make sure that extended key exists and is imported ok too - _, key, err = keyStore.AccountDecryptedKey(acc, utils.TestConfig.Account1.Password) - s.NoError(err) - s.Equal(extChild2String, key.ExtendedKey.String(), "CKD#2 key mismatch") - - // make sure that calling import several times, just returns from cache (no error is expected) - accountInfoCheck, err = s.Backend.AccountManager().RecoverAccount(utils.TestConfig.Account1.Password, mnemonic) - s.NoError(err, "recover acc failed (for non-cached acc)") - s.EqualValues(accountInfo, accountInfoCheck, "incorrect acc details recovered (for non-cached acc)") -} - -func (s *AccountsTestSuite) TestSelectAccount() { - s.StartTestBackend() - defer s.StopTestBackend() - - // create an account - _, accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) - s.NoError(err) - s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}", - accountInfo1.WalletAddress, accountInfo1.WalletPubKey, accountInfo1.ChatAddress, accountInfo1.ChatPubKey) - - _, accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) - s.NoError(err) - s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}", - accountInfo2.WalletAddress, accountInfo2.WalletPubKey, accountInfo2.ChatAddress, accountInfo2.ChatPubKey) - - loginParams, err := buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongPassword", nil) - s.Require().NoError(err) - // try selecting with wrong password - err = s.Backend.SelectAccount(loginParams) - expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password") - s.EqualError(expectedErr, err.Error(), "select account is expected to throw error: wrong password used") - - loginParams, err = buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, utils.TestConfig.Account1.Password, nil) - s.Require().NoError(err) - - err = s.Backend.SelectAccount(loginParams) - s.NoError(err) - - // select another account, make sure that previous account is wiped out from Whisper cache - loginParams, err = buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, utils.TestConfig.Account1.Password, nil) - s.Require().NoError(err) - - s.NoError(s.Backend.SelectAccount(loginParams)) -} - -func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { - s.StartTestBackend() - - // create test accounts - _, accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) - s.NoError(err) - _, accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) - s.NoError(err) - - // make sure that no account is selected by default - selectedWalletAccount, err := s.Backend.AccountManager().MainAccountAddress() - s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be") - s.Equal(types.Address{}, selectedWalletAccount) - selectedChatAccount, err := s.Backend.AccountManager().SelectedChatAccount() - s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be") - s.Nil(selectedChatAccount) - - // select account - loginParams, err := buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongPassword", nil) - s.Require().NoError(err) - - err = s.Backend.SelectAccount(loginParams) - expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password") - s.EqualError(expectedErr, err.Error()) - - watchAddresses := []types.Address{ - types.HexToAddress("0x00000000000000000000000000000000000001"), - types.HexToAddress("0x00000000000000000000000000000000000002"), - } - - loginParams, err = buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, utils.TestConfig.Account1.Password, watchAddresses) - s.Require().NoError(err) - - s.NoError(s.Backend.SelectAccount(loginParams)) - - // stop node (and all of its sub-protocols) - nodeConfig := s.Backend.StatusNode().Config() - s.NotNil(nodeConfig) - preservedNodeConfig := *nodeConfig - s.NoError(s.Backend.StopNode()) - - // make sure that account is still selected - selectedWalletAccount, err = s.Backend.AccountManager().MainAccountAddress() - s.Require().NoError(err) - s.NotNil(selectedWalletAccount) - s.Equal(selectedWalletAccount.String(), accountInfo2.WalletAddress, "incorrect wallet address selected") - selectedChatAccount, err = s.Backend.AccountManager().SelectedChatAccount() - s.NoError(err) - s.NotNil(selectedChatAccount) - s.Equal(selectedChatAccount.Address.Hex(), accountInfo2.ChatAddress, "incorrect chat address selected") - s.Equal(watchAddresses, s.Backend.AccountManager().WatchAddresses()) - - // resume node - s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig)) - - // re-check selected account (account2 MUST be selected) - selectedWalletAccount, err = s.Backend.AccountManager().MainAccountAddress() - s.NoError(err) - s.NotNil(selectedWalletAccount) - s.Equal(selectedWalletAccount.String(), accountInfo2.WalletAddress, "incorrect wallet address selected") - selectedChatAccount, err = s.Backend.AccountManager().SelectedChatAccount() - s.NoError(err) - s.NotNil(selectedChatAccount) - s.Equal(selectedChatAccount.Address.Hex(), accountInfo2.WalletAddress, "incorrect chat address selected") - s.Equal(watchAddresses, s.Backend.AccountManager().WatchAddresses()) - - // now restart node using RestartNode() method, and make sure that account is still available - s.RestartTestNode() - defer s.StopTestBackend() - - // now logout, and make sure that on restart no account is selected (i.e. logout works properly) - s.NoError(s.Backend.Logout()) - s.RestartTestNode() - - selectedWalletAccount, err = s.Backend.AccountManager().MainAccountAddress() - s.EqualError(account.ErrNoAccountSelected, err.Error()) - s.Equal(types.Address{}, selectedWalletAccount) - selectedChatAccount, err = s.Backend.AccountManager().SelectedChatAccount() - s.EqualError(account.ErrNoAccountSelected, err.Error()) - s.Nil(selectedChatAccount) - s.Len(s.Backend.AccountManager().WatchAddresses(), 0) -} diff --git a/t/e2e/api/api_test.go b/t/e2e/api/api_test.go deleted file mode 100644 index 5ec971a16..000000000 --- a/t/e2e/api/api_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package api_test - -import ( - "encoding/json" - "math/rand" - "testing" - "time" - - "github.com/stretchr/testify/suite" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/storage" - - "github.com/status-im/status-go/api" - "github.com/status-im/status-go/node" - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/signal" - "github.com/status-im/status-go/t/utils" -) - -func TestAPI(t *testing.T) { - utils.Init() - suite.Run(t, new(APITestSuite)) -} - -type APITestSuite struct { - suite.Suite - backend *api.GethStatusBackend -} - -func (s *APITestSuite) ensureNodeStopped() { - if err := s.backend.StopNode(); err != node.ErrNoRunningNode && err != nil { - s.NoError(err, "unexpected error") - } -} - -func (s *APITestSuite) SetupTest() { - s.backend = api.NewGethStatusBackend() - s.NotNil(s.backend) -} - -func (s *APITestSuite) TestCHTUpdate() { - // TODO(tiabc): Test that CHT is really updated. -} - -func (s *APITestSuite) TestRaceConditions() { - cnt := 25 - progress := make(chan struct{}, cnt) - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) // nolint: gosec - - nodeConfig1, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.NoError(err) - - nodeConfig2, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.NoError(err) - - nodeConfigs := []*params.NodeConfig{nodeConfig1, nodeConfig2} - - var funcsToTest = []func(*params.NodeConfig){ - func(config *params.NodeConfig) { - s.T().Logf("async call to StartNode() for network: %d", config.NetworkID) - api.RunAsync(func() error { return s.backend.StartNode(config) }) - progress <- struct{}{} - }, - func(config *params.NodeConfig) { - s.T().Logf("async call to StopNode() for network: %d", config.NetworkID) - api.RunAsync(s.backend.StopNode) - progress <- struct{}{} - }, - func(config *params.NodeConfig) { - s.T().Logf("async call to RestartNode() for network: %d", config.NetworkID) - api.RunAsync(s.backend.RestartNode) - progress <- struct{}{} - }, - // TODO(adam): quarantined until it uses a different datadir - // as otherwise it wipes out cached blockchain data. - // func(config *params.NodeConfig) { - // s.T().Logf("async call to ResetChainData() for network: %d", config.NetworkID) - // _, err := s.api.ResetChainData() - // progress <- struct{}{} - // }, - } - - // increase StartNode()/StopNode() population - for i := 0; i < 5; i++ { - funcsToTest = append(funcsToTest, funcsToTest[0], funcsToTest[1]) - } - - for i := 0; i < cnt; i++ { - randConfig := nodeConfigs[rnd.Intn(len(nodeConfigs))] // nolint: gosec - randFunc := funcsToTest[rnd.Intn(len(funcsToTest))] // nolint: gosec - - // introduce random delays - if rnd.Intn(100) > 75 { // nolint: gosec - time.Sleep(500 * time.Millisecond) - } - s.NoError(s.backend.AccountManager().InitKeystore(randConfig.KeyStoreDir)) - go randFunc(randConfig) - } - - for range progress { - cnt-- - if cnt <= 0 { - break - } - } - - time.Sleep(2 * time.Second) // so that we see some logs - // just in case we have a node running - s.ensureNodeStopped() -} - -func (s *APITestSuite) TestEventsNodeStartStop() { - envelopes := make(chan signal.Envelope, 3) - signal.SetDefaultNodeNotificationHandler(func(jsonEvent string) { - var envelope signal.Envelope - err := json.Unmarshal([]byte(jsonEvent), &envelope) - s.NoError(err) - // whitelist types that we are interested in - switch envelope.Type { - case signal.EventNodeStarted: - case signal.EventNodeStopped: - case signal.EventNodeReady: - default: - return - } - envelopes <- envelope - }) - - nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.NoError(err) - s.NoError(s.backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) - s.Require().NoError(s.backend.StartNode(nodeConfig)) - s.NoError(s.backend.StopNode()) - s.verifyEnvelopes(envelopes, signal.EventNodeStarted, signal.EventNodeReady, signal.EventNodeStopped) - s.Require().NoError(s.backend.StartNode(nodeConfig)) - s.verifyEnvelopes(envelopes, signal.EventNodeStarted, signal.EventNodeReady) - s.Require().NoError(s.backend.RestartNode()) - s.verifyEnvelopes(envelopes, signal.EventNodeStopped, signal.EventNodeStarted, signal.EventNodeReady) - s.NoError(s.backend.StopNode()) - s.verifyEnvelopes(envelopes, signal.EventNodeStopped) -} - -func (s *APITestSuite) verifyEnvelopes(envelopes chan signal.Envelope, envelopeTypes ...string) { - for _, envelopeType := range envelopeTypes { - select { - case env := <-envelopes: - s.Equal(envelopeType, env.Type) - case <-time.After(1 * time.Second): - s.Fail("timeout waiting for envelope") - } - } -} - -func (s *APITestSuite) TestNodeStartCrash() { - // let's listen for node.crashed signal - signalReceived := make(chan struct{}) - signal.SetDefaultNodeNotificationHandler(func(jsonEvent string) { - var envelope signal.Envelope - err := json.Unmarshal([]byte(jsonEvent), &envelope) - s.NoError(err) - - if envelope.Type == signal.EventNodeCrashed { - close(signalReceived) - } - }) - defer signal.ResetDefaultNodeNotificationHandler() - - nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.NoError(err) - - db, err := leveldb.Open(storage.NewMemStorage(), nil) - s.NoError(err) - defer func() { s.NoError(db.Close()) }() - - // start node outside the manager (on the same port), so that manager node.Start() method fails - outsideNode, err := node.MakeNode(nodeConfig, nil, db) - s.NoError(err) - err = outsideNode.Start() - s.NoError(err) - - // now try starting using node manager, it should fail (error is irrelevant as it is implementation detail) - s.NoError(s.backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) - s.Error(<-api.RunAsync(func() error { return s.backend.StartNode(nodeConfig) })) - - select { - case <-time.After(500 * time.Millisecond): - s.FailNow("timed out waiting for signal") - case <-signalReceived: - } - - // stop outside node, and re-try - s.NoError(outsideNode.Stop()) - signalReceived = make(chan struct{}) - s.NoError(<-api.RunAsync(func() error { return s.backend.StartNode(nodeConfig) })) - - select { - case <-time.After(500 * time.Millisecond): - case <-signalReceived: - s.FailNow("signal should not be received") - } - - // cleanup - s.NoError(s.backend.StopNode()) -} diff --git a/t/e2e/api/backend_test.go b/t/e2e/api/backend_test.go deleted file mode 100644 index dc7f67179..000000000 --- a/t/e2e/api/backend_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package api_test - -import ( - "io/ioutil" - "os" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/t/e2e" - . "github.com/status-im/status-go/t/utils" -) - -func TestAPIBackendTestSuite(t *testing.T) { - Init() // from t/utils - suite.Run(t, new(APIBackendTestSuite)) -} - -type APIBackendTestSuite struct { - e2e.BackendTestSuite -} - -// FIXME(tiabc): There's also a test with the same name in node/manager_test.go -// so this test should only check StatusBackend logic with a mocked version of the underlying StatusNode. -func (s *APIBackendTestSuite) TestNetworkSwitching() { - // Get test node configuration. - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) - s.NoError(err) - s.NoError(s.Backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) - s.False(s.Backend.IsNodeRunning()) - s.Require().NoError(s.Backend.StartNode(nodeConfig)) - s.True(s.Backend.IsNodeRunning()) - - firstHash, err := e2e.FirstBlockHash(s.Backend.StatusNode()) - s.NoError(err) - s.Equal(GetHeadHash(), firstHash) - - // now stop node, and make sure that a new node, on different network can be started - s.NoError(s.Backend.StopNode()) - - // start new node with completely different config - nodeConfig, err = MakeTestNodeConfig(GetNetworkID()) - s.NoError(err) - - s.False(s.Backend.IsNodeRunning()) - s.Require().NoError(s.Backend.StartNode(nodeConfig)) - s.True(s.Backend.IsNodeRunning()) - - // make sure we are on another network indeed - firstHash, err = e2e.FirstBlockHash(s.Backend.StatusNode()) - s.NoError(err) - s.Equal(GetHeadHash(), firstHash) - - s.NoError(s.Backend.StopNode()) -} - -func (s *APIBackendTestSuite) TestResetChainData() { - if GetNetworkID() != params.StatusChainNetworkID { - s.T().Skip("test must be running on status network") - } - require := s.Require() - require.NotNil(s.Backend) - path, err := ioutil.TempDir("/tmp", "status-reset-chain-test") - require.NoError(err) - defer func() { s.NoError(os.RemoveAll(path)) }() - - s.StartTestBackend(e2e.WithDataDir(path)) - defer s.StopTestBackend() - - EnsureNodeSync(s.Backend.StatusNode().EnsureSync) - - require.NoError(s.Backend.ResetChainData()) - - s.True(s.Backend.IsNodeRunning()) // new node, with previous config should be running - - // make sure we can read the first byte, and it is valid (for Rinkeby) - firstHash, err := e2e.FirstBlockHash(s.Backend.StatusNode()) - s.NoError(err) - s.Equal(GetHeadHash(), firstHash) -} - -// FIXME(tiabc): There's also a test with the same name in node/manager_test.go -// so this test should only check StatusBackend logic with a mocked version of the underlying StatusNode. -func (s *APIBackendTestSuite) TestRestartNode() { - require := s.Require() - require.NotNil(s.Backend) - - // get config - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) - s.NoError(err) - s.NoError(s.Backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) - - s.False(s.Backend.IsNodeRunning()) - require.NoError(s.Backend.StartNode(nodeConfig)) - s.True(s.Backend.IsNodeRunning()) - - firstHash, err := e2e.FirstBlockHash(s.Backend.StatusNode()) - s.NoError(err) - s.Equal(GetHeadHash(), firstHash) - - s.True(s.Backend.IsNodeRunning()) - require.NoError(s.Backend.RestartNode()) - s.True(s.Backend.IsNodeRunning()) // new node, with previous config should be running - - // make sure we can read the first byte, and it is valid (for Rinkeby) - firstHash, err = e2e.FirstBlockHash(s.Backend.StatusNode()) - s.NoError(err) - s.Equal(GetHeadHash(), firstHash) -} diff --git a/t/e2e/rpc/client_test.go b/t/e2e/rpc/client_test.go deleted file mode 100644 index 5abea2057..000000000 --- a/t/e2e/rpc/client_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package rpc - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/node" - "github.com/status-im/status-go/rpc" - "github.com/status-im/status-go/t/e2e" - . "github.com/status-im/status-go/t/utils" //nolint: golint -) - -type RPCClientTestSuite struct { - e2e.StatusNodeTestSuite -} - -func TestRPCClientTestSuite(t *testing.T) { - e2e.Init() - suite.Run(t, new(RPCClientTestSuite)) -} - -func (s *RPCClientTestSuite) SetupTest() { - s.StatusNode = node.New() - s.NotNil(s.StatusNode) -} - -func (s *RPCClientTestSuite) TestNewClient() { - config, err := MakeTestNodeConfig(GetNetworkID()) - s.NoError(err) - - // upstream disabled - s.False(config.UpstreamConfig.Enabled) - _, err = rpc.NewClient(nil, config.UpstreamConfig) - s.NoError(err) - - // upstream enabled with correct URL - upstreamGood := config.UpstreamConfig - upstreamGood.Enabled = true - upstreamGood.URL = "http://example.com/rpc" - _, err = rpc.NewClient(nil, upstreamGood) - s.NoError(err) - - // upstream enabled with incorrect URL - upstreamBad := config.UpstreamConfig - upstreamBad.Enabled = true - upstreamBad.URL = "///__httphh://///incorrect_urlxxx" - _, err = rpc.NewClient(nil, upstreamBad) - s.Error(err) -} diff --git a/t/e2e/rpc/rpc_test.go b/t/e2e/rpc/rpc_test.go deleted file mode 100644 index 466424255..000000000 --- a/t/e2e/rpc/rpc_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package rpc - -import ( - "context" - "fmt" - "math/big" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/suite" - - "github.com/ethereum/go-ethereum/common/hexutil" - - "github.com/status-im/status-go/node" - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/t/e2e" - . "github.com/status-im/status-go/t/utils" -) - -func TestRPCTestSuite(t *testing.T) { - e2e.Init() - suite.Run(t, new(RPCTestSuite)) -} - -type RPCTestSuite struct { - e2e.StatusNodeTestSuite -} - -func (s *RPCTestSuite) SetupTest() { - s.StatusNode = node.New() - s.NotNil(s.StatusNode) -} - -func (s *RPCTestSuite) TestCallRPC() { - if GetNetworkID() == params.StatusChainNetworkID { - s.T().Skip() - } - - for _, upstreamEnabled := range []bool{false, true} { - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) - s.NoError(err) - - nodeConfig.IPCEnabled = false - nodeConfig.HTTPHost = "" // to make sure that no HTTP interface is started - - if upstreamEnabled { - networkURL, err := GetRemoteURL() - s.NoError(err) - - nodeConfig.UpstreamConfig.Enabled = true - nodeConfig.UpstreamConfig.URL = networkURL - } - - s.NoError(s.StatusNode.Start(nodeConfig, nil)) - - rpcClient := s.StatusNode.RPCClient() - s.NotNil(rpcClient) - - type rpcCall struct { - inputJSON string - validator func(resultJSON string) - } - var rpcCalls = []rpcCall{ - { - `{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}`, - func(resultJSON string) { - expected := `{"jsonrpc":"2.0","id":64,"result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"}` - s.Equal(expected, resultJSON) - }, - }, - { - `{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}`, - func(resultJSON string) { - expected := `{"jsonrpc":"2.0","id":67,"result":"` + fmt.Sprintf("%d", GetNetworkID()) + `"}` - s.Equal(expected, resultJSON) - }, - }, - { - `[{"jsonrpc":"2.0","method":"net_listening","params":[],"id":67}]`, - func(resultJSON string) { - expected := `[{"jsonrpc":"2.0","id":67,"result":true}]` - s.Equal(expected, resultJSON) - }, - }, - { - `[{"jsonrpc":"2.0","method":"net_version","params":[],"id":67},{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":68}]`, - func(resultJSON string) { - expected := `[{"jsonrpc":"2.0","id":67,"result":"` + fmt.Sprintf("%d", GetNetworkID()) + `"},{"jsonrpc":"2.0","id":68,"result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"}]` - s.Equal(expected, resultJSON) - }, - }, - } - - var wg sync.WaitGroup - for _, r := range rpcCalls { - wg.Add(1) - go func(r rpcCall) { - defer wg.Done() - resultJSON := rpcClient.CallRaw(r.inputJSON) - r.validator(resultJSON) - }(r) - } - - done := make(chan struct{}) - go func() { - wg.Wait() - close(done) - }() - - select { - case <-time.After(time.Second * 30): - s.Fail("test timed out") - case <-done: - } - - s.NoError(s.StatusNode.Stop()) - } -} - -// TestCallRawResultGetTransactionReceipt checks if returned response -// for a not yet mined transaction is "result": null. -// Issue: https://github.com/status-im/status-go/issues/547 -func (s *RPCTestSuite) TestCallRawResultGetTransactionReceipt() { - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) - s.NoError(err) - - s.NoError(s.StatusNode.Start(nodeConfig, nil)) - - client := s.StatusNode.RPCClient() - s.NotNil(client) - - jsonResult := client.CallRaw(`{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x0ca0d8f2422f62bea77e24ed17db5711a77fa72064cccbb8e53c53b699cd3b34"],"id":5}`) - s.Equal(`{"jsonrpc":"2.0","id":5,"result":null}`, jsonResult) - - s.NoError(s.StatusNode.Stop()) -} - -// TestCallContextResult checks if result passed to CallContext -// is set accordingly to its underlying memory layout. -func (s *RPCTestSuite) TestCallContextResult() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - s.StartTestNode() - defer s.StopTestNode() - - EnsureNodeSync(s.StatusNode.EnsureSync) - - client := s.StatusNode.RPCClient() - s.NotNil(client) - - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) - defer cancel() - - var balance hexutil.Big - err := client.CallContext(ctx, &balance, "eth_getBalance", TestConfig.Account1.WalletAddress, "latest") - s.NoError(err) - s.True(balance.ToInt().Cmp(big.NewInt(0)) > 0, "balance should be higher than 0") -} diff --git a/t/e2e/services/base_api_test.go b/t/e2e/services/base_api_test.go deleted file mode 100644 index 21490e856..000000000 --- a/t/e2e/services/base_api_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package services - -import ( - "encoding/json" - "fmt" - - "github.com/status-im/status-go/api" - "github.com/status-im/status-go/t/e2e" - - "github.com/status-im/status-go/t/utils" -) - -const ( - // see vendor/github.com/ethereum/go-ethereum/rpc/errors.go:L27 - methodNotFoundErrorCode = -32601 -) - -type rpcError struct { - Code int `json:"code"` -} - -type BaseJSONRPCSuite struct { - e2e.BackendTestSuite -} - -func (s *BaseJSONRPCSuite) AssertAPIMethodUnexported(method string) { - exported := s.isMethodExported(method, false) - s.False(exported, - "method %s should be hidden, but it isn't", - method) -} - -func (s *BaseJSONRPCSuite) AssertAPIMethodExported(method string) { - exported := s.isMethodExported(method, false) - s.True(exported, - "method %s should be exported, but it isn't", - method) -} - -func (s *BaseJSONRPCSuite) AssertAPIMethodExportedPrivately(method string) { - exported := s.isMethodExported(method, true) - s.True(exported, - "method %s should be exported, but it isn't", - method) -} - -func (s *BaseJSONRPCSuite) isMethodExported(method string, private bool) bool { - var ( - result string - err error - ) - - cmd := fmt.Sprintf(`{"jsonrpc":"2.0", "method": "%s", "params": []}`, method) - if private { - result, err = s.Backend.CallPrivateRPC(cmd) - } else { - result, err = s.Backend.CallRPC(cmd) - } - s.NoError(err) - - var response struct { - Error *rpcError `json:"error"` - } - - s.NoError(json.Unmarshal([]byte(result), &response)) - - return !(response.Error != nil && response.Error.Code == methodNotFoundErrorCode) -} - -func (s *BaseJSONRPCSuite) SetupTest(upstreamEnabled, statusServiceEnabled, debugAPIEnabled bool) error { - s.Backend = api.NewGethStatusBackend() - s.NotNil(s.Backend) - - nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.NoError(err) - s.NoError(s.Backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) - - nodeConfig.IPCEnabled = false - nodeConfig.EnableStatusService = statusServiceEnabled - if debugAPIEnabled { - nodeConfig.AddAPIModule("debug") - } - nodeConfig.HTTPHost = "" // to make sure that no HTTP interface is started - - if upstreamEnabled { - networkURL, err := utils.GetRemoteURL() - s.NoError(err) - - nodeConfig.UpstreamConfig.Enabled = true - nodeConfig.UpstreamConfig.URL = networkURL - } - - return s.Backend.StartNode(nodeConfig) -} diff --git a/t/e2e/services/filters_latest_test.go b/t/e2e/services/filters_latest_test.go deleted file mode 100644 index 917ee9e49..000000000 --- a/t/e2e/services/filters_latest_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package services - -import ( - "encoding/json" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/t/utils" -) - -func TestFiltersAPISuite(t *testing.T) { - utils.Init() - s := new(FiltersAPISuite) - s.upstream = false - suite.Run(t, s) -} - -func TestFiltersAPISuiteUpstream(t *testing.T) { - utils.Init() - s := new(FiltersAPISuite) - s.upstream = true - - if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { - t.Skip() - return - } - - suite.Run(t, s) -} - -type FiltersAPISuite struct { - BaseJSONRPCSuite - upstream bool -} - -func (s *FiltersAPISuite) TestFilters() { - err := s.SetupTest(s.upstream, false, false) - s.NoError(err) - defer func() { - err := s.Backend.StopNode() - s.NoError(err) - }() - - basicCall := `{"jsonrpc":"2.0","method":"eth_newBlockFilter","params":[],"id":67}` - - response, err := s.Backend.CallRPC(basicCall) - s.NoError(err) - filterID := s.filterIDFromRPCResponse(response) - - // we don't check new blocks on private network, because no one mines them - if utils.GetNetworkID() != params.StatusChainNetworkID { - timeout := time.After(time.Minute) - newBlocksChannel := s.getFirstFilterChange(filterID) - - select { - case hash := <-newBlocksChannel: - s.True(len(hash) > 0, "received hash isn't empty") - case <-timeout: - s.Fail("timeout while waiting for filter results") - } - } - - basicCall = fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_uninstallFilter","params":["%s"],"id":67}`, filterID) - - response, err = s.Backend.CallRPC(basicCall) - s.NoError(err) - result := s.boolFromRPCResponse(response) - - s.True(result, "filter expected to be removed successfully") -} - -func (s *FiltersAPISuite) getFirstFilterChange(filterID string) chan string { - - result := make(chan string) - - go func() { - timeout := time.Now().Add(time.Minute) - for time.Now().Before(timeout) { - basicCall := fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["%s"],"id":67}`, filterID) - response, err := s.Backend.CallRPC(basicCall) - s.NoError(err) - filterChanges := s.arrayFromRPCResponse(response) - if len(filterChanges) > 0 { - result <- filterChanges[0] - return - } - time.Sleep(10 * time.Millisecond) - } - }() - - return result -} - -func (s *FiltersAPISuite) filterIDFromRPCResponse(response string) string { - var r struct { - Result string `json:"result"` - } - s.NoError(json.Unmarshal([]byte(response), &r)) - - return r.Result -} - -func (s *FiltersAPISuite) arrayFromRPCResponse(response string) []string { - var r struct { - Result []string `json:"result"` - } - s.NoError(json.Unmarshal([]byte(response), &r)) - - return r.Result -} - -func (s *FiltersAPISuite) boolFromRPCResponse(response string) bool { - var r struct { - Result bool `json:"result"` - } - s.NoError(json.Unmarshal([]byte(response), &r)) - - return r.Result -} diff --git a/t/e2e/services/peer_api_test.go b/t/e2e/services/peer_api_test.go deleted file mode 100644 index cb6e8bc3f..000000000 --- a/t/e2e/services/peer_api_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package services - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/t/utils" -) - -func TestPeerAPISuite(t *testing.T) { - utils.Init() - s := new(PeerAPISuite) - s.upstream = false - suite.Run(t, s) -} - -func TestPeerAPISuiteUpstream(t *testing.T) { - utils.Init() - s := new(PeerAPISuite) - s.upstream = true - suite.Run(t, s) -} - -type PeerAPISuite struct { - BaseJSONRPCSuite - upstream bool -} - -func (s *PeerAPISuite) TestAccessiblePeerAPIs() { - if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { - s.T().Skip() - return - } - - err := s.SetupTest(s.upstream, true, false) - s.NoError(err) - defer func() { - err := s.Backend.StopNode() - s.NoError(err) - }() - // These peer APIs should be available - s.AssertAPIMethodExported("peer_discover") -} diff --git a/t/e2e/services/personal_api_test.go b/t/e2e/services/personal_api_test.go deleted file mode 100644 index 489dc8ee7..000000000 --- a/t/e2e/services/personal_api_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package services - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/params" - . "github.com/status-im/status-go/t/utils" -) - -const ( - signDataString = "0xBAADBEEF" -) - -type PersonalSignSuite struct { - upstream bool - BaseJSONRPCSuite -} - -func TestPersonalSignSuiteUpstream(t *testing.T) { - s := new(PersonalSignSuite) - s.upstream = true - suite.Run(t, s) -} - -func (s *PersonalSignSuite) TestRestrictedPersonalAPIs() { - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { - s.T().Skip() - return - } - - err := s.SetupTest(true, false, false) - s.NoError(err) - defer func() { - err := s.Backend.StopNode() - s.NoError(err) - }() - // These personal APIs should be available - s.AssertAPIMethodExported("personal_sign") - s.AssertAPIMethodExported("personal_ecRecover") - // These personal APIs shouldn't be exported - s.AssertAPIMethodUnexported("personal_sendTransaction") - s.AssertAPIMethodUnexported("personal_unlockAccount") - s.AssertAPIMethodUnexported("personal_newAccount") - s.AssertAPIMethodUnexported("personal_lockAccount") - s.AssertAPIMethodUnexported("personal_listAccounts") - s.AssertAPIMethodUnexported("personal_importRawKey") -} - -func (s *PersonalSignSuite) TestPersonalSignUnsupportedMethod() { - // Test upstream if that's not StatusChain - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { - s.T().Skip() - } - - err := s.SetupTest(true, false, false) - s.NoError(err) - defer func() { - err := s.Backend.StopNode() - s.NoError(err) - }() - - basicCall := fmt.Sprintf( - `{"jsonrpc":"2.0","method":"personal_sign","params":["%s", "%s"],"id":67}`, - signDataString, - TestConfig.Account1.WalletAddress) - - rawResult, err := s.Backend.CallRPC(basicCall) - s.NoError(err) - s.Contains(rawResult, `"error":{"code":-32700,"message":"method is unsupported by RPC interface"}`) -} - -func (s *PersonalSignSuite) TestPersonalRecoverUnsupportedMethod() { - - // Test upstream if that's not StatusChain - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { - s.T().Skip() - return - } - - err := s.SetupTest(true, false, false) - s.NoError(err) - defer func() { - err := s.Backend.StopNode() - s.NoError(err) - }() - - // 2. Test recover - basicCall := fmt.Sprintf( - `{"jsonrpc":"2.0","method":"personal_ecRecover","params":["%s", "%s"],"id":67}`, - signDataString, - "") - - rawResult, err := s.Backend.CallRPC(basicCall) - s.NoError(err) - s.Contains(rawResult, `"error":{"code":-32700,"message":"method is unsupported by RPC interface"}`) -} diff --git a/t/e2e/suites.go b/t/e2e/suites.go deleted file mode 100644 index 394e8a97f..000000000 --- a/t/e2e/suites.go +++ /dev/null @@ -1,193 +0,0 @@ -package e2e - -import ( - "encoding/json" - - "github.com/stretchr/testify/suite" - - "github.com/ethereum/go-ethereum/log" - - "github.com/status-im/status-go/api" - "github.com/status-im/status-go/eth-node/types" - "github.com/status-im/status-go/multiaccounts" - "github.com/status-im/status-go/multiaccounts/accounts" - "github.com/status-im/status-go/node" - "github.com/status-im/status-go/signal" - "github.com/status-im/status-go/t/utils" - "github.com/status-im/status-go/transactions" - "github.com/status-im/status-go/waku" -) - -// StatusNodeTestSuite defines a test suite with StatusNode. -type StatusNodeTestSuite struct { - suite.Suite - StatusNode *node.StatusNode -} - -var ( - // All general log messages in this package should be routed through this logger. - logger = log.New("package", "status-go/t/e2e") - - // Settings for testing - networks = json.RawMessage("{}") - settings = accounts.Settings{ - Address: types.HexToAddress("0xaC540f3745Ff2964AFC1171a5A0DD726d1F6B472"), - CurrentNetwork: "mainnet_rpc", - DappsAddress: types.HexToAddress("0xa1300f99fDF7346986CbC766903245087394ecd0"), - EIP1581Address: types.HexToAddress("0xa1DDDE9235a541d1344550d969715CF43982de9f"), - InstallationID: "d3efcff6-cffa-560e-a547-21d3858cbc51", - KeyUID: "0x4e8129f3edfc004875be17bf468a784098a9f69b53c095be1f52deff286935ab", - LatestDerivedPath: 0, - Name: "Jittery Cornflowerblue Kingbird", - Networks: &networks, - PhotoPath: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAAjklEQVR4nOzXwQmFMBAAUZXUYh32ZB32ZB02sxYQQSZGsod55/91WFgSS0RM+SyjA56ZRZhFmEWYRRT6h+M6G16zrxv6fdJpmUWYRbxsYr13dKfanpN0WmYRZhGzXz6AWYRZRIfbaX26fT9Jk07LLMIsosPt9I/dTDotswizCG+nhFmEWYRZhFnEHQAA///z1CFkYamgfQAAAABJRU5ErkJggg==", - PreviewPrivacy: false, - PublicKey: "0x04211fe0f69772ecf7eb0b5bfc7678672508a9fb01f2d699096f0d59ef7fe1a0cb1e648a80190db1c0f5f088872444d846f2956d0bd84069f3f9f69335af852ac0", - SigningPhrase: "yurt joey vibe", - WalletRootAddress: types.HexToAddress("0xaB591fd819F86D0A6a2EF2Bcb94f77807a7De1a6")} -) - -func Init() { - utils.Init() - for id := range utils.TestNetworkNames { - nodeConfig, err := utils.MakeTestNodeConfig(id) - if err != nil { - panic(err) - } - - err = importTestAccounts(nodeConfig.KeyStoreDir) - if err != nil { - panic(err) - } - } -} - -// StartTestNode initiazes a StatusNode instances with configuration retrieved -// from the test config. -func (s *StatusNodeTestSuite) StartTestNode(opts ...TestNodeOption) { - nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.NoError(err) - - // Apply any options altering node config. - for i := range opts { - opts[i](nodeConfig) - } - - // import account keys - s.NoError(importTestAccounts(nodeConfig.KeyStoreDir)) - - s.False(s.StatusNode.IsRunning()) - s.NoError(s.StatusNode.Start(nodeConfig, nil)) - s.True(s.StatusNode.IsRunning()) -} - -// StopTestNode attempts to stop initialized StatusNode. -func (s *StatusNodeTestSuite) StopTestNode() { - s.NotNil(s.StatusNode) - s.True(s.StatusNode.IsRunning()) - s.NoError(s.StatusNode.Stop()) - s.False(s.StatusNode.IsRunning()) -} - -// BackendTestSuite is a test suite with api.GethStatusBackend initialized -// and a few utility methods to start and stop node or get various services. -type BackendTestSuite struct { - suite.Suite - Backend *api.GethStatusBackend -} - -// SetupTest initializes Backend. -func (s *BackendTestSuite) SetupTest() { - s.Backend = api.NewGethStatusBackend() - s.NotNil(s.Backend) -} - -// TearDownTest cleans up the packages state. -func (s *BackendTestSuite) TearDownTest() { - signal.ResetDefaultNodeNotificationHandler() -} - -// StartTestBackend imports some keys and starts a node. -func (s *BackendTestSuite) StartTestBackend(opts ...TestNodeOption) { - nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.Require().NoError(err) - - // Apply any options altering node config. - for i := range opts { - opts[i](nodeConfig) - } - s.NoError(s.Backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) - // import account keys - s.NoError(importTestAccounts(nodeConfig.KeyStoreDir)) - - // start node - s.False(s.Backend.IsNodeRunning()) - s.Require().NoError(s.Backend.StartNode(nodeConfig)) - s.True(s.Backend.IsNodeRunning()) -} - -func (s *BackendTestSuite) StartTestBackendWithAccount(account multiaccounts.Account, password string, subaccs []accounts.Account, opts ...TestNodeOption) { - nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) - s.Require().NoError(err) - - // Apply any options altering node config. - for i := range opts { - opts[i](nodeConfig) - } - - keystoreDir := nodeConfig.KeyStoreDir - dataDir := nodeConfig.DataDir - nodeConfig.KeyStoreDir = "keystore" - nodeConfig.DataDir = "/" - // accounts must be imported before keystore is initialized - s.NoError(importTestAccounts(keystoreDir)) - s.Backend.UpdateRootDataDir(dataDir) - s.NoError(s.Backend.OpenAccounts()) - s.NoError(s.Backend.AccountManager().InitKeystore(keystoreDir)) - - s.Require().NoError(s.Backend.StartNodeWithAccountAndConfig(account, password, settings, nodeConfig, subaccs)) -} - -func (s *BackendTestSuite) LogoutAndStop() { - s.NoError(s.Backend.Logout()) - s.StopTestBackend() -} - -// StopTestBackend stops the node. -func (s *BackendTestSuite) StopTestBackend() { - s.True(s.Backend.IsNodeRunning()) - s.NoError(s.Backend.StopNode()) - s.False(s.Backend.IsNodeRunning()) -} - -// RestartTestNode restarts a currently running node. -func (s *BackendTestSuite) RestartTestNode() { - s.True(s.Backend.IsNodeRunning()) - s.Require().NoError(s.Backend.RestartNode()) - s.True(s.Backend.IsNodeRunning()) -} - -// WakuService returns a reference to the Waku service. -func (s *BackendTestSuite) WakuService() *waku.Waku { - wakuService, err := s.Backend.StatusNode().WakuService() - s.NoError(err) - s.NotNil(wakuService) - - return wakuService -} - -// Transactor returns a reference to the Transactor. -func (s *BackendTestSuite) Transactor() *transactions.Transactor { - return s.Backend.Transactor() -} - -func importTestAccounts(keyStoreDir string) (err error) { - logger.Debug("Import accounts to", "dir", keyStoreDir) - - err = utils.ImportTestAccount(keyStoreDir, utils.GetAccount1PKFile()) - if err != nil { - return - } - - return utils.ImportTestAccount(keyStoreDir, utils.GetAccount2PKFile()) -} diff --git a/t/e2e/testing.go b/t/e2e/testing.go deleted file mode 100644 index 94d05cb27..000000000 --- a/t/e2e/testing.go +++ /dev/null @@ -1,57 +0,0 @@ -package e2e - -import ( - "context" - "path" - - gethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/status-im/status-go/node" - "github.com/status-im/status-go/params" -) - -// TestNodeOption is a callback passed to StartTestNode which alters its config. -type TestNodeOption func(config *params.NodeConfig) - -// WithUpstream returns TestNodeOption which enabled UpstreamConfig. -func WithUpstream(url string) TestNodeOption { - return func(config *params.NodeConfig) { - config.UpstreamConfig.Enabled = true - config.UpstreamConfig.URL = url - } -} - -// WithDataDir returns TestNodeOption that allows to set another data dir. -func WithDataDir(dataDir string) TestNodeOption { - return func(config *params.NodeConfig) { - config.DataDir = dataDir - config.KeyStoreDir = path.Join(dataDir, "keystore") - config.WakuConfig.DataDir = path.Join(dataDir, "wnode") - } -} - -// FirstBlockHash validates Attach operation for the StatusNode. -func FirstBlockHash(statusNode *node.StatusNode) (string, error) { - // obtain RPC client for running node - runningNode := statusNode.GethNode() - if runningNode == nil { - return "", node.ErrNoGethNode - } - - rpcClient, err := runningNode.Attach() - if err != nil { - return "", err - } - - // get first block - var firstBlock struct { - Hash gethcommon.Hash `json:"hash"` - } - - err = rpcClient.CallContext(context.Background(), &firstBlock, "eth_getBlockByNumber", "0x0", true) - if err != nil { - return "", err - } - - return firstBlock.Hash.Hex(), nil -} diff --git a/t/e2e/transactions/transactions_test.go b/t/e2e/transactions/transactions_test.go deleted file mode 100644 index 576f5a991..000000000 --- a/t/e2e/transactions/transactions_test.go +++ /dev/null @@ -1,283 +0,0 @@ -package transactions - -import ( - "io/ioutil" - "math/big" - "os" - "reflect" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/ethereum/go-ethereum/common/hexutil" - - "github.com/status-im/status-go/account" - "github.com/status-im/status-go/account/generator" - "github.com/status-im/status-go/eth-node/crypto" - "github.com/status-im/status-go/eth-node/types" - "github.com/status-im/status-go/multiaccounts" - "github.com/status-im/status-go/multiaccounts/accounts" - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/t/e2e" - "github.com/status-im/status-go/t/utils" - "github.com/status-im/status-go/transactions" -) - -type initFunc func([]byte, *transactions.SendTxArgs) - -func buildLoginParams(mainAccountAddress, chatAddress, password string) (account.LoginParams, error) { - privateKey, err := crypto.GenerateKey() - if err != nil { - return account.LoginParams{}, err - } - - acc := generator.NewAccount(privateKey, nil) - iai := acc.ToIdentifiedAccountInfo("") - - return account.LoginParams{ - ChatAddress: types.HexToAddress(chatAddress), - Password: password, - MainAccount: types.HexToAddress(mainAccountAddress), - MultiAccount: iai.ToMultiAccount(), - }, nil -} - -func TestTransactionsTestSuite(t *testing.T) { - utils.Init() - suite.Run(t, new(TransactionsTestSuite)) -} - -type TransactionsTestSuite struct { - e2e.BackendTestSuite -} - -func (s *TransactionsTestSuite) TestCallRPCSendTransaction() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - s.StartTestBackend() - defer s.StopTestBackend() - utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) - - s.sendTransactionUsingRPCClient(s.Backend.CallRPC) -} - -func (s *TransactionsTestSuite) TestCallUpstreamRPCSendTransaction() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) - - addr, err := utils.GetRemoteURL() - s.NoError(err) - s.StartTestBackend(e2e.WithUpstream(addr)) - defer s.StopTestBackend() - - s.sendTransactionUsingRPCClient(s.Backend.CallRPC) -} - -func (s *TransactionsTestSuite) TestCallPrivateRPCSendTransaction() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - s.StartTestBackend() - defer s.StopTestBackend() - utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) - - s.sendTransactionUsingRPCClient(s.Backend.CallPrivateRPC) -} - -func (s *TransactionsTestSuite) TestCallUpstreamPrivateRPCSendTransaction() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) - - addr, err := utils.GetRemoteURL() - s.NoError(err) - s.StartTestBackend(e2e.WithUpstream(addr)) - defer s.StopTestBackend() - - s.sendTransactionUsingRPCClient(s.Backend.CallPrivateRPC) -} - -func (s *TransactionsTestSuite) sendTransactionUsingRPCClient( - callRPCFn func(string) (string, error), -) { - loginParams, err := buildLoginParams( - utils.TestConfig.Account1.WalletAddress, - utils.TestConfig.Account1.ChatAddress, - utils.TestConfig.Account1.Password, - ) - s.Require().NoError(err) - - err = s.Backend.SelectAccount(loginParams) - s.NoError(err) - - result, err := callRPCFn(`{ - "jsonrpc": "2.0", - "id": 1, - "method": "eth_sendTransaction", - "params": [{ - "from": "` + utils.TestConfig.Account1.WalletAddress + `", - "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - "value": "0x9184e72a" - }] - }`) - s.NoError(err) - s.Contains(result, `"error":{"code":-32700,"message":"method is unsupported by RPC interface"}`) -} - -func (s *TransactionsTestSuite) TestEmptyToFieldPreserved() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - tmpdir, err := ioutil.TempDir("", "transactions-tests-") - s.Require().NoError(err) - defer os.Remove(tmpdir) - - wallet := types.HexToAddress(utils.TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{KeyUID: utils.TestConfig.Account1.WalletAddress}, utils.TestConfig.Account1.Password, - []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, - e2e.WithDataDir(tmpdir), - ) - defer s.LogoutAndStop() - - utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) - - args := transactions.SendTxArgs{ - From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), - } - - hash, err := s.Backend.SendTransaction(args, utils.TestConfig.Account1.Password) - s.NoError(err) - s.NotNil(hash) -} - -// TestSendContractCompat tries to send transaction using the legacy "Data" -// field, which is supported for backward compatibility reasons. -func (s *TransactionsTestSuite) TestSendContractTxCompat() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - initFunc := func(byteCode []byte, args *transactions.SendTxArgs) { - args.Data = (types.HexBytes)(byteCode) - } - s.testSendContractTx(initFunc, nil, "") -} - -// TestSendContractCompat tries to send transaction using both the legacy -// "Data" and "Input" fields. Also makes sure that the error is returned if -// they have different values. -func (s *TransactionsTestSuite) TestSendContractTxCollision() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - // Scenario 1: Both fields are filled and have the same value, expect success - initFunc := func(byteCode []byte, args *transactions.SendTxArgs) { - args.Input = (types.HexBytes)(byteCode) - args.Data = (types.HexBytes)(byteCode) - } - s.testSendContractTx(initFunc, nil, "") - - // Scenario 2: Both fields are filled with different values, expect an error - inverted := func(source []byte) []byte { - inverse := make([]byte, len(source)) - copy(inverse, source) - for i, b := range inverse { - inverse[i] = b ^ 0xFF - } - return inverse - } - - initFunc2 := func(byteCode []byte, args *transactions.SendTxArgs) { - args.Input = (types.HexBytes)(byteCode) - args.Data = (types.HexBytes)(inverted(byteCode)) - } - s.testSendContractTx(initFunc2, transactions.ErrInvalidSendTxArgs, "expected error when invalid tx args are sent") -} - -func (s *TransactionsTestSuite) TestSendContractTx() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - - initFunc := func(byteCode []byte, args *transactions.SendTxArgs) { - args.Input = (types.HexBytes)(byteCode) - } - s.testSendContractTx(initFunc, nil, "") -} - -func (s *TransactionsTestSuite) testSendContractTx(setInputAndDataValue initFunc, expectedError error, expectedErrorDescription string) { - tmpdir, err := ioutil.TempDir("", "transactions-tests-") - s.Require().NoError(err) - defer os.Remove(tmpdir) - - wallet := types.HexToAddress(utils.TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{KeyUID: utils.TestConfig.Account1.WalletAddress}, utils.TestConfig.Account1.Password, - []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, - e2e.WithDataDir(tmpdir), - ) - defer s.LogoutAndStop() - - utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) - - // this call blocks, up until Complete Transaction is called - byteCode, err := types.DecodeHex(`0x6060604052341561000c57fe5b5b60a58061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636ffa1caa14603a575bfe5b3415604157fe5b60556004808035906020019091905050606b565b6040518082815260200191505060405180910390f35b60008160020290505b9190505600a165627a7a72305820ccdadd737e4ac7039963b54cee5e5afb25fa859a275252bdcf06f653155228210029`) - s.NoError(err) - - gas := uint64(params.DefaultGas) - args := transactions.SendTxArgs{ - From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), - To: nil, // marker, contract creation is expected - //Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), common.Ether)), - Gas: (*hexutil.Uint64)(&gas), - } - - setInputAndDataValue(byteCode, &args) - hash, err := s.Backend.SendTransaction(args, utils.TestConfig.Account1.Password) - if expectedError != nil { - s.Equal(expectedError, err, expectedErrorDescription) - return - } - s.NoError(err) - s.False(reflect.DeepEqual(hash, types.Hash{})) -} - -func (s *TransactionsTestSuite) TestSendEther() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) - tmpdir, err := ioutil.TempDir("", "transactions-tests-") - s.Require().NoError(err) - defer os.Remove(tmpdir) - - wallet := types.HexToAddress(utils.TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{KeyUID: utils.TestConfig.Account1.WalletAddress}, utils.TestConfig.Account1.Password, - []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, - e2e.WithDataDir(tmpdir), - ) - defer s.LogoutAndStop() - - utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) - - hash, err := s.Backend.SendTransaction(transactions.SendTxArgs{ - From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), - To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), - Value: (*hexutil.Big)(big.NewInt(1000000000000)), - }, utils.TestConfig.Account1.Password) - s.NoError(err) - s.False(reflect.DeepEqual(hash, types.Hash{})) -} - -func (s *TransactionsTestSuite) TestSendEtherTxUpstream() { - utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) - - tmpdir, err := ioutil.TempDir("", "transactions-tests-") - s.Require().NoError(err) - defer os.Remove(tmpdir) - addr, err := utils.GetRemoteURL() - s.NoError(err) - - wallet := types.HexToAddress(utils.TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{KeyUID: utils.TestConfig.Account1.WalletAddress}, utils.TestConfig.Account1.Password, - []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, - e2e.WithUpstream(addr), - e2e.WithDataDir(tmpdir), - ) - defer s.LogoutAndStop() - - hash, err := s.Backend.SendTransaction(transactions.SendTxArgs{ - From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), - To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), - GasPrice: (*hexutil.Big)(big.NewInt(28000000000)), - Value: (*hexutil.Big)(big.NewInt(1000000000000)), - }, utils.TestConfig.Account1.Password) - s.NoError(err) - s.False(reflect.DeepEqual(hash, types.Hash{})) -} diff --git a/transactions/transactor_test.go b/transactions/transactor_test.go index 2f94a4e95..830a51420 100644 --- a/transactions/transactor_test.go +++ b/transactions/transactor_test.go @@ -1,10 +1,8 @@ package transactions import ( - "context" "errors" "fmt" - "math" "math/big" "reflect" "testing" @@ -13,10 +11,8 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" gethtypes "github.com/ethereum/go-ethereum/core/types" gethcrypto "github.com/ethereum/go-ethereum/crypto" gethparams "github.com/ethereum/go-ethereum/params" diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go deleted file mode 100644 index 06cd0908e..000000000 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go +++ /dev/null @@ -1,873 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package backends - -import ( - "context" - "errors" - "fmt" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -// This nil assignment ensures at compile time that SimulatedBackend implements bind.ContractBackend. -var _ bind.ContractBackend = (*SimulatedBackend)(nil) - -var ( - errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block") - errBlockDoesNotExist = errors.New("block does not exist in blockchain") - errTransactionDoesNotExist = errors.New("transaction does not exist") -) - -// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in -// the background. Its main purpose is to allow for easy testing of contract bindings. -// Simulated backend implements the following interfaces: -// ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor, -// DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender -type SimulatedBackend struct { - database ethdb.Database // In memory database to store our testing data - blockchain *core.BlockChain // Ethereum blockchain to handle the consensus - - mu sync.Mutex - pendingBlock *types.Block // Currently pending block that will be imported on request - pendingState *state.StateDB // Currently pending state that will be the active on request - - events *filters.EventSystem // Event system for filtering log events live - - config *params.ChainConfig -} - -// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database -// and uses a simulated blockchain for testing purposes. -// A simulated backend always uses chainID 1337. -func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { - genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc} - genesis.MustCommit(database) - blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil, nil) - - backend := &SimulatedBackend{ - database: database, - blockchain: blockchain, - config: genesis.Config, - events: filters.NewEventSystem(&filterBackend{database, blockchain}, false), - } - backend.rollback(blockchain.CurrentBlock()) - return backend -} - -// NewSimulatedBackend creates a new binding backend using a simulated blockchain -// for testing purposes. -// A simulated backend always uses chainID 1337. -func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { - return NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), alloc, gasLimit) -} - -// Close terminates the underlying blockchain's update loop. -func (b *SimulatedBackend) Close() error { - b.blockchain.Stop() - return nil -} - -// Commit imports all the pending transactions as a single block and starts a -// fresh new state. -func (b *SimulatedBackend) Commit() { - b.mu.Lock() - defer b.mu.Unlock() - - if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil { - panic(err) // This cannot happen unless the simulator is wrong, fail in that case - } - // Using the last inserted block here makes it possible to build on a side - // chain after a fork. - b.rollback(b.pendingBlock) -} - -// Rollback aborts all pending transactions, reverting to the last committed state. -func (b *SimulatedBackend) Rollback() { - b.mu.Lock() - defer b.mu.Unlock() - - b.rollback(b.blockchain.CurrentBlock()) -} - -func (b *SimulatedBackend) rollback(parent *types.Block) { - blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {}) - - b.pendingBlock = blocks[0] - b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache(), nil) -} - -// Fork creates a side-chain that can be used to simulate reorgs. -// -// This function should be called with the ancestor block where the new side -// chain should be started. Transactions (old and new) can then be applied on -// top and Commit-ed. -// -// Note, the side-chain will only become canonical (and trigger the events) when -// it becomes longer. Until then CallContract will still operate on the current -// canonical chain. -// -// There is a % chance that the side chain becomes canonical at the same length -// to simulate live network behavior. -func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error { - b.mu.Lock() - defer b.mu.Unlock() - - if len(b.pendingBlock.Transactions()) != 0 { - return errors.New("pending block dirty") - } - block, err := b.blockByHash(ctx, parent) - if err != nil { - return err - } - b.rollback(block) - return nil -} - -// stateByBlockNumber retrieves a state by a given blocknumber. -func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) { - if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 { - return b.blockchain.State() - } - block, err := b.blockByNumber(ctx, blockNumber) - if err != nil { - return nil, err - } - return b.blockchain.StateAt(block.Root()) -} - -// CodeAt returns the code associated with a certain account in the blockchain. -func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { - b.mu.Lock() - defer b.mu.Unlock() - - stateDB, err := b.stateByBlockNumber(ctx, blockNumber) - if err != nil { - return nil, err - } - - return stateDB.GetCode(contract), nil -} - -// BalanceAt returns the wei balance of a certain account in the blockchain. -func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) { - b.mu.Lock() - defer b.mu.Unlock() - - stateDB, err := b.stateByBlockNumber(ctx, blockNumber) - if err != nil { - return nil, err - } - - return stateDB.GetBalance(contract), nil -} - -// NonceAt returns the nonce of a certain account in the blockchain. -func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) { - b.mu.Lock() - defer b.mu.Unlock() - - stateDB, err := b.stateByBlockNumber(ctx, blockNumber) - if err != nil { - return 0, err - } - - return stateDB.GetNonce(contract), nil -} - -// StorageAt returns the value of key in the storage of an account in the blockchain. -func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { - b.mu.Lock() - defer b.mu.Unlock() - - stateDB, err := b.stateByBlockNumber(ctx, blockNumber) - if err != nil { - return nil, err - } - - val := stateDB.GetState(contract, key) - return val[:], nil -} - -// TransactionReceipt returns the receipt of a transaction. -func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - b.mu.Lock() - defer b.mu.Unlock() - - receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config) - return receipt, nil -} - -// TransactionByHash checks the pool of pending transactions in addition to the -// blockchain. The isPending return value indicates whether the transaction has been -// mined yet. Note that the transaction may not be part of the canonical chain even if -// it's not pending. -func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { - b.mu.Lock() - defer b.mu.Unlock() - - tx := b.pendingBlock.Transaction(txHash) - if tx != nil { - return tx, true, nil - } - tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash) - if tx != nil { - return tx, false, nil - } - return nil, false, ethereum.NotFound -} - -// BlockByHash retrieves a block based on the block hash. -func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - b.mu.Lock() - defer b.mu.Unlock() - - return b.blockByHash(ctx, hash) -} - -// blockByHash retrieves a block based on the block hash without Locking. -func (b *SimulatedBackend) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - if hash == b.pendingBlock.Hash() { - return b.pendingBlock, nil - } - - block := b.blockchain.GetBlockByHash(hash) - if block != nil { - return block, nil - } - - return nil, errBlockDoesNotExist -} - -// BlockByNumber retrieves a block from the database by number, caching it -// (associated with its hash) if found. -func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - b.mu.Lock() - defer b.mu.Unlock() - - return b.blockByNumber(ctx, number) -} - -// blockByNumber retrieves a block from the database by number, caching it -// (associated with its hash) if found without Lock. -func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 { - return b.blockchain.CurrentBlock(), nil - } - - block := b.blockchain.GetBlockByNumber(uint64(number.Int64())) - if block == nil { - return nil, errBlockDoesNotExist - } - - return block, nil -} - -// HeaderByHash returns a block header from the current canonical chain. -func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - b.mu.Lock() - defer b.mu.Unlock() - - if hash == b.pendingBlock.Hash() { - return b.pendingBlock.Header(), nil - } - - header := b.blockchain.GetHeaderByHash(hash) - if header == nil { - return nil, errBlockDoesNotExist - } - - return header, nil -} - -// HeaderByNumber returns a block header from the current canonical chain. If number is -// nil, the latest known header is returned. -func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) { - b.mu.Lock() - defer b.mu.Unlock() - - if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 { - return b.blockchain.CurrentHeader(), nil - } - - return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil -} - -// TransactionCount returns the number of transactions in a given block. -func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { - b.mu.Lock() - defer b.mu.Unlock() - - if blockHash == b.pendingBlock.Hash() { - return uint(b.pendingBlock.Transactions().Len()), nil - } - - block := b.blockchain.GetBlockByHash(blockHash) - if block == nil { - return uint(0), errBlockDoesNotExist - } - - return uint(block.Transactions().Len()), nil -} - -// TransactionInBlock returns the transaction for a specific block at a specific index. -func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { - b.mu.Lock() - defer b.mu.Unlock() - - if blockHash == b.pendingBlock.Hash() { - transactions := b.pendingBlock.Transactions() - if uint(len(transactions)) < index+1 { - return nil, errTransactionDoesNotExist - } - - return transactions[index], nil - } - - block := b.blockchain.GetBlockByHash(blockHash) - if block == nil { - return nil, errBlockDoesNotExist - } - - transactions := block.Transactions() - if uint(len(transactions)) < index+1 { - return nil, errTransactionDoesNotExist - } - - return transactions[index], nil -} - -// PendingCodeAt returns the code associated with an account in the pending state. -func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { - b.mu.Lock() - defer b.mu.Unlock() - - return b.pendingState.GetCode(contract), nil -} - -func newRevertError(result *core.ExecutionResult) *revertError { - reason, errUnpack := abi.UnpackRevert(result.Revert()) - err := errors.New("execution reverted") - if errUnpack == nil { - err = fmt.Errorf("execution reverted: %v", reason) - } - return &revertError{ - error: err, - reason: hexutil.Encode(result.Revert()), - } -} - -// revertError is an API error that encompasses an EVM revert with JSON error -// code and a binary data blob. -type revertError struct { - error - reason string // revert reason hex encoded -} - -// ErrorCode returns the JSON error code for a revert. -// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal -func (e *revertError) ErrorCode() int { - return 3 -} - -// ErrorData returns the hex encoded revert reason. -func (e *revertError) ErrorData() interface{} { - return e.reason -} - -// CallContract executes a contract call. -func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - b.mu.Lock() - defer b.mu.Unlock() - - if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { - return nil, errBlockNumberUnsupported - } - stateDB, err := b.blockchain.State() - if err != nil { - return nil, err - } - res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB) - if err != nil { - return nil, err - } - // If the result contains a revert reason, try to unpack and return it. - if len(res.Revert()) > 0 { - return nil, newRevertError(res) - } - return res.Return(), res.Err -} - -// PendingCallContract executes a contract call on the pending state. -func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) { - b.mu.Lock() - defer b.mu.Unlock() - defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot()) - - res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) - if err != nil { - return nil, err - } - // If the result contains a revert reason, try to unpack and return it. - if len(res.Revert()) > 0 { - return nil, newRevertError(res) - } - return res.Return(), res.Err -} - -// PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving -// the nonce currently pending for the account. -func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - b.mu.Lock() - defer b.mu.Unlock() - - return b.pendingState.GetOrNewStateObject(account).Nonce(), nil -} - -// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated -// chain doesn't have miners, we just return a gas price of 1 for any call. -func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - return big.NewInt(1), nil -} - -// SuggestGasTipCap implements ContractTransactor.SuggestGasTipCap. Since the simulated -// chain doesn't have miners, we just return a gas tip of 1 for any call. -func (b *SimulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - return big.NewInt(1), nil -} - -// EstimateGas executes the requested code against the currently pending block/state and -// returns the used amount of gas. -func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { - b.mu.Lock() - defer b.mu.Unlock() - - // Determine the lowest and highest possible gas limits to binary search in between - var ( - lo uint64 = params.TxGas - 1 - hi uint64 - cap uint64 - ) - if call.Gas >= params.TxGas { - hi = call.Gas - } else { - hi = b.pendingBlock.GasLimit() - } - // Recap the highest gas allowance with account's balance. - if call.GasPrice != nil && call.GasPrice.BitLen() != 0 { - balance := b.pendingState.GetBalance(call.From) // from can't be nil - available := new(big.Int).Set(balance) - if call.Value != nil { - if call.Value.Cmp(available) >= 0 { - return 0, errors.New("insufficient funds for transfer") - } - available.Sub(available, call.Value) - } - allowance := new(big.Int).Div(available, call.GasPrice) - if allowance.IsUint64() && hi > allowance.Uint64() { - transfer := call.Value - if transfer == nil { - transfer = new(big.Int) - } - log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, - "sent", transfer, "gasprice", call.GasPrice, "fundable", allowance) - hi = allowance.Uint64() - } - } - cap = hi - - // Create a helper to check if a gas allowance results in an executable transaction - executable := func(gas uint64) (bool, *core.ExecutionResult, error) { - call.Gas = gas - - snapshot := b.pendingState.Snapshot() - res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) - b.pendingState.RevertToSnapshot(snapshot) - - if err != nil { - if errors.Is(err, core.ErrIntrinsicGas) { - return true, nil, nil // Special case, raise gas limit - } - return true, nil, err // Bail out - } - return res.Failed(), res, nil - } - // Execute the binary search and hone in on an executable gas limit - for lo+1 < hi { - mid := (hi + lo) / 2 - failed, _, err := executable(mid) - - // If the error is not nil(consensus error), it means the provided message - // call or transaction will never be accepted no matter how much gas it is - // assigned. Return the error directly, don't struggle any more - if err != nil { - return 0, err - } - if failed { - lo = mid - } else { - hi = mid - } - } - // Reject the transaction as invalid if it still fails at the highest allowance - if hi == cap { - failed, result, err := executable(hi) - if err != nil { - return 0, err - } - if failed { - if result != nil && result.Err != vm.ErrOutOfGas { - if len(result.Revert()) > 0 { - return 0, newRevertError(result) - } - return 0, result.Err - } - // Otherwise, the specified gas cap is too low - return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) - } - } - return hi, nil -} - -// callContract implements common code between normal and pending contract calls. -// state is modified during execution, make sure to copy it if necessary. -func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) { - // Gas prices post 1559 need to be initialized - if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { - return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") - } - head := b.blockchain.CurrentHeader() - if !b.blockchain.Config().IsLondon(head.Number) { - // If there's no basefee, then it must be a non-1559 execution - if call.GasPrice == nil { - call.GasPrice = new(big.Int) - } - call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice - } else { - // A basefee is provided, necessitating 1559-type execution - if call.GasPrice != nil { - // User specified the legacy gas field, convert to 1559 gas typing - call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice - } else { - // User specified 1559 gas feilds (or none), use those - if call.GasFeeCap == nil { - call.GasFeeCap = new(big.Int) - } - if call.GasTipCap == nil { - call.GasTipCap = new(big.Int) - } - // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes - call.GasPrice = new(big.Int) - if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 { - call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap) - } - } - } - // Ensure message is initialized properly. - if call.Gas == 0 { - call.Gas = 50000000 - } - if call.Value == nil { - call.Value = new(big.Int) - } - // Set infinite balance to the fake caller account. - from := stateDB.GetOrNewStateObject(call.From) - from.SetBalance(math.MaxBig256) - // Execute the call. - msg := callMsg{call} - - txContext := core.NewEVMTxContext(msg) - evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil) - // Create a new environment which holds all relevant information - // about the transaction and calling mechanisms. - vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) - gasPool := new(core.GasPool).AddGas(math.MaxUint64) - - return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb() -} - -// SendTransaction updates the pending block to include the given transaction. -// It panics if the transaction is invalid. -func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { - b.mu.Lock() - defer b.mu.Unlock() - - // Get the last block - block, err := b.blockByHash(ctx, b.pendingBlock.ParentHash()) - if err != nil { - panic("could not fetch parent") - } - // Check transaction validity - signer := types.MakeSigner(b.blockchain.Config(), block.Number()) - sender, err := types.Sender(signer, tx) - if err != nil { - panic(fmt.Errorf("invalid transaction: %v", err)) - } - nonce := b.pendingState.GetNonce(sender) - if tx.Nonce() != nonce { - panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)) - } - // Include tx in chain - blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { - for _, tx := range b.pendingBlock.Transactions() { - block.AddTxWithChain(b.blockchain, tx) - } - block.AddTxWithChain(b.blockchain, tx) - }) - stateDB, _ := b.blockchain.State() - - b.pendingBlock = blocks[0] - b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil) - return nil -} - -// FilterLogs executes a log filter operation, blocking during execution and -// returning all the results in one batch. -// -// TODO(karalabe): Deprecate when the subscription one can return past data too. -func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { - var filter *filters.Filter - if query.BlockHash != nil { - // Block filter requested, construct a single-shot filter - filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain}, *query.BlockHash, query.Addresses, query.Topics) - } else { - // Initialize unset filter boundaries to run from genesis to chain head - from := int64(0) - if query.FromBlock != nil { - from = query.FromBlock.Int64() - } - to := int64(-1) - if query.ToBlock != nil { - to = query.ToBlock.Int64() - } - // Construct the range filter - filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain}, from, to, query.Addresses, query.Topics) - } - // Run the filter and return all the logs - logs, err := filter.Logs(ctx) - if err != nil { - return nil, err - } - res := make([]types.Log, len(logs)) - for i, nLog := range logs { - res[i] = *nLog - } - return res, nil -} - -// SubscribeFilterLogs creates a background log filtering operation, returning a -// subscription immediately, which can be used to stream the found events. -func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { - // Subscribe to contract events - sink := make(chan []*types.Log) - - sub, err := b.events.SubscribeLogs(query, sink) - if err != nil { - return nil, err - } - // Since we're getting logs in batches, we need to flatten them into a plain stream - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case logs := <-sink: - for _, nlog := range logs { - select { - case ch <- *nlog: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// SubscribeNewHead returns an event subscription for a new header. -func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { - // subscribe to a new head - sink := make(chan *types.Header) - sub := b.events.SubscribeNewHeads(sink) - - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case head := <-sink: - select { - case ch <- head: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// AdjustTime adds a time shift to the simulated clock. -// It can only be called on empty blocks. -func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { - b.mu.Lock() - defer b.mu.Unlock() - - if len(b.pendingBlock.Transactions()) != 0 { - return errors.New("Could not adjust time on non-empty block") - } - - blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { - block.OffsetTime(int64(adjustment.Seconds())) - }) - stateDB, _ := b.blockchain.State() - - b.pendingBlock = blocks[0] - b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil) - - return nil -} - -// Blockchain returns the underlying blockchain. -func (b *SimulatedBackend) Blockchain() *core.BlockChain { - return b.blockchain -} - -// callMsg implements core.Message to allow passing it as a transaction simulator. -type callMsg struct { - ethereum.CallMsg -} - -func (m callMsg) From() common.Address { return m.CallMsg.From } -func (m callMsg) Nonce() uint64 { return 0 } -func (m callMsg) CheckNonce() bool { return false } -func (m callMsg) To() *common.Address { return m.CallMsg.To } -func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } -func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap } -func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap } -func (m callMsg) Gas() uint64 { return m.CallMsg.Gas } -func (m callMsg) Value() *big.Int { return m.CallMsg.Value } -func (m callMsg) Data() []byte { return m.CallMsg.Data } -func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList } - -// filterBackend implements filters.Backend to support filtering for logs without -// taking bloom-bits acceleration structures into account. -type filterBackend struct { - db ethdb.Database - bc *core.BlockChain -} - -func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db } -func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") } - -func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) { - if block == rpc.LatestBlockNumber { - return fb.bc.CurrentHeader(), nil - } - return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil -} - -func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return fb.bc.GetHeaderByHash(hash), nil -} - -func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - number := rawdb.ReadHeaderNumber(fb.db, hash) - if number == nil { - return nil, nil - } - return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil -} - -func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { - number := rawdb.ReadHeaderNumber(fb.db, hash) - if number == nil { - return nil, nil - } - receipts := rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()) - if receipts == nil { - return nil, nil - } - logs := make([][]*types.Log, len(receipts)) - for i, receipt := range receipts { - logs[i] = receipt.Logs - } - return logs, nil -} - -func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - return nullSubscription() -} - -func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { - return fb.bc.SubscribeChainEvent(ch) -} - -func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { - return fb.bc.SubscribeRemovedLogsEvent(ch) -} - -func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - return fb.bc.SubscribeLogsEvent(ch) -} - -func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { - return nullSubscription() -} - -func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 } - -func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) { - panic("not supported") -} - -func nullSubscription() event.Subscription { - return event.NewSubscription(func(quit <-chan struct{}) error { - <-quit - return nil - }) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index dc739f820..40510b91e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -43,7 +43,6 @@ github.com/ethereum/go-ethereum github.com/ethereum/go-ethereum/accounts github.com/ethereum/go-ethereum/accounts/abi github.com/ethereum/go-ethereum/accounts/abi/bind -github.com/ethereum/go-ethereum/accounts/abi/bind/backends github.com/ethereum/go-ethereum/accounts/external github.com/ethereum/go-ethereum/accounts/keystore github.com/ethereum/go-ethereum/accounts/scwallet