status-go/t/e2e/transactions/transactions_test.go
Roman Volosovskyi 4c0d8dedea
Replace address with keyUid in accounts db
Account's address was used as a primary key in accounts db and as a
deterministic id of an account in some API calls. Also it was used as a
part of the name of the account specific database. This revealed some
extra information about the account and wasn't necessary.
At first the hash of the address was planned to be used as a
deterministic id, but we already have a keyUid which is calculated as
sha256 hash of account's public key and has similar properties:
- it is deterministic
- doesn't reveal accounts public key or address in plain
2019-12-09 11:20:12 +02:00

269 lines
9.3 KiB
Go

package transactions
import (
"io/ioutil"
"math/big"
"os"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/account"
"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"
"github.com/stretchr/testify/suite"
)
type initFunc func([]byte, *transactions.SendTxArgs)
func buildLoginParams(mainAccountAddress, chatAddress, password string) account.LoginParams {
return account.LoginParams{
ChatAddress: common.HexToAddress(chatAddress),
Password: password,
MainAccount: common.HexToAddress(mainAccountAddress),
}
}
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),
) {
err := s.Backend.SelectAccount(buildLoginParams(
utils.TestConfig.Account1.WalletAddress,
utils.TestConfig.Account1.ChatAddress,
utils.TestConfig.Account1.Password,
))
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 := common.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 = (hexutil.Bytes)(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 = (hexutil.Bytes)(byteCode)
args.Data = (hexutil.Bytes)(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 = (hexutil.Bytes)(byteCode)
args.Data = (hexutil.Bytes)(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 = (hexutil.Bytes)(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 := common.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 := hexutil.Decode(`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), gethcommon.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, gethcommon.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 := common.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, gethcommon.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 := common.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, gethcommon.Hash{}))
}