mirror of
https://github.com/status-im/status-go.git
synced 2025-02-15 00:08:46 +00:00
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
269 lines
9.3 KiB
Go
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{}))
|
|
}
|