2018-08-02 07:07:55 +00:00
|
|
|
package rpc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-09-22 17:49:20 +00:00
|
|
|
"database/sql"
|
2024-07-31 06:21:11 +00:00
|
|
|
"encoding/base64"
|
2018-08-02 07:07:55 +00:00
|
|
|
"fmt"
|
2024-07-31 06:21:11 +00:00
|
|
|
"math/big"
|
2018-08-02 07:07:55 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2024-07-31 06:21:11 +00:00
|
|
|
"sync"
|
2018-08-02 07:07:55 +00:00
|
|
|
"testing"
|
|
|
|
|
2024-07-31 06:21:11 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2018-08-02 07:07:55 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2021-09-22 17:49:20 +00:00
|
|
|
"github.com/status-im/status-go/appdatabase"
|
2018-08-02 07:07:55 +00:00
|
|
|
"github.com/status-im/status-go/params"
|
2023-08-11 11:28:45 +00:00
|
|
|
"github.com/status-im/status-go/t/helpers"
|
2018-08-02 07:07:55 +00:00
|
|
|
|
2024-07-31 06:21:11 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2018-08-02 07:07:55 +00:00
|
|
|
gethrpc "github.com/ethereum/go-ethereum/rpc"
|
|
|
|
)
|
|
|
|
|
2021-09-22 17:49:20 +00:00
|
|
|
func setupTestNetworkDB(t *testing.T) (*sql.DB, func()) {
|
2023-08-11 11:28:45 +00:00
|
|
|
db, cleanup, err := helpers.SetupTestSQLDB(appdatabase.DbInitializer{}, "rpc-network-tests")
|
2021-09-22 17:49:20 +00:00
|
|
|
require.NoError(t, err)
|
2023-08-11 11:28:45 +00:00
|
|
|
return db, func() { require.NoError(t, cleanup()) }
|
2021-09-22 17:49:20 +00:00
|
|
|
}
|
|
|
|
|
2018-08-02 07:07:55 +00:00
|
|
|
func TestBlockedRoutesCall(t *testing.T) {
|
2021-09-22 17:49:20 +00:00
|
|
|
db, close := setupTestNetworkDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2018-08-02 07:07:55 +00:00
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprintln(w, `{
|
|
|
|
"id": 1,
|
|
|
|
"jsonrpc": "2.0",
|
|
|
|
"result": "0x234234e22b9ffc2387e18636e0534534a3d0c56b0243567432453264c16e78a2adc"
|
|
|
|
}`)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
gethRPCClient, err := gethrpc.Dial(ts.URL)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-07-31 06:21:11 +00:00
|
|
|
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
|
2018-08-02 07:07:55 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
for _, m := range blockedMethods {
|
|
|
|
var (
|
|
|
|
result interface{}
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
2021-09-22 17:49:20 +00:00
|
|
|
err = c.Call(&result, 1, m)
|
2018-08-02 07:07:55 +00:00
|
|
|
require.EqualError(t, err, ErrMethodNotFound.Error())
|
|
|
|
require.Nil(t, result)
|
|
|
|
|
2021-09-22 17:49:20 +00:00
|
|
|
err = c.CallContext(context.Background(), &result, 1, m)
|
2018-08-02 07:07:55 +00:00
|
|
|
require.EqualError(t, err, ErrMethodNotFound.Error())
|
|
|
|
require.Nil(t, result)
|
|
|
|
|
2021-09-22 17:49:20 +00:00
|
|
|
err = c.CallContextIgnoringLocalHandlers(context.Background(), &result, 1, m)
|
2018-08-02 07:07:55 +00:00
|
|
|
require.EqualError(t, err, ErrMethodNotFound.Error())
|
|
|
|
require.Nil(t, result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBlockedRoutesRawCall(t *testing.T) {
|
2021-09-22 17:49:20 +00:00
|
|
|
db, close := setupTestNetworkDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2018-08-02 07:07:55 +00:00
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprintln(w, `{
|
|
|
|
"id": 1,
|
|
|
|
"jsonrpc": "2.0",
|
|
|
|
"result": "0x234234e22b9ffc2387e18636e0534534a3d0c56b0243567432453264c16e78a2adc"
|
|
|
|
}`)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
gethRPCClient, err := gethrpc.Dial(ts.URL)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-07-31 06:21:11 +00:00
|
|
|
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
|
2018-08-02 07:07:55 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
for _, m := range blockedMethods {
|
|
|
|
rawResult := c.CallRaw(fmt.Sprintf(`{
|
|
|
|
"jsonrpc": "2.0",
|
|
|
|
"id": 1,
|
|
|
|
"method": "%s",
|
|
|
|
"params": ["0xc862bf3cf4565d46abcbadaf4712a8940bfea729a91b9b0e338eab5166341ab5"]
|
|
|
|
}`, m))
|
|
|
|
require.Contains(t, rawResult, fmt.Sprintf(`{"code":-32700,"message":"%s"}`, ErrMethodNotFound))
|
|
|
|
}
|
|
|
|
}
|
2019-03-21 12:02:16 +00:00
|
|
|
|
|
|
|
func TestUpdateUpstreamURL(t *testing.T) {
|
2021-09-22 17:49:20 +00:00
|
|
|
db, close := setupTestNetworkDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2019-03-21 12:02:16 +00:00
|
|
|
ts := createTestServer("")
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
updatedUpstreamTs := createTestServer("")
|
|
|
|
defer updatedUpstreamTs.Close()
|
|
|
|
|
|
|
|
gethRPCClient, err := gethrpc.Dial(ts.URL)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-07-31 06:21:11 +00:00
|
|
|
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: true, URL: ts.URL}, []params.Network{}, db, nil)
|
2019-03-21 12:02:16 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, ts.URL, c.upstreamURL)
|
|
|
|
|
|
|
|
// cache the original upstream client
|
|
|
|
originalUpstreamClient := c.upstream
|
|
|
|
|
|
|
|
err = c.UpdateUpstreamURL(updatedUpstreamTs.URL)
|
|
|
|
require.NoError(t, err)
|
|
|
|
// the upstream cleint instance should change
|
|
|
|
require.NotEqual(t, originalUpstreamClient, c.upstream)
|
|
|
|
require.Equal(t, updatedUpstreamTs.URL, c.upstreamURL)
|
|
|
|
}
|
|
|
|
|
|
|
|
func createTestServer(resp string) *httptest.Server {
|
|
|
|
if resp == "" {
|
|
|
|
resp = `{
|
|
|
|
"id": 1,
|
|
|
|
"jsonrpc": "2.0",
|
|
|
|
"result": "0x234234e22b9ffc2387e18636e0534534a3d0c56b0243567432453264c16e78a2adc"
|
|
|
|
}`
|
|
|
|
}
|
|
|
|
|
|
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprintln(w, resp)
|
|
|
|
}))
|
|
|
|
}
|
2024-07-31 06:21:11 +00:00
|
|
|
|
|
|
|
func TestGetClientsUsingCache(t *testing.T) {
|
|
|
|
db, close := setupTestNetworkDB(t)
|
|
|
|
defer close()
|
|
|
|
|
|
|
|
providerConfig := params.ProviderConfig{
|
|
|
|
Enabled: true,
|
|
|
|
Name: ProviderStatusProxy,
|
|
|
|
User: "user1",
|
|
|
|
Password: "pass1",
|
|
|
|
}
|
|
|
|
providerConfigs := []params.ProviderConfig{providerConfig}
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(2) // 2 providers
|
|
|
|
|
|
|
|
// Create a new ServeMux
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
|
|
|
|
path1 := "/foo"
|
|
|
|
path2 := "/bar"
|
|
|
|
// Register handlers for different URL paths
|
|
|
|
mux.HandleFunc(path1, func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
authToken := base64.StdEncoding.EncodeToString([]byte(providerConfig.User + ":" + providerConfig.Password))
|
|
|
|
require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
|
|
|
|
wg.Done()
|
|
|
|
})
|
|
|
|
|
|
|
|
mux.HandleFunc(path2, func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
authToken := base64.StdEncoding.EncodeToString([]byte(providerConfig.User + ":" + providerConfig.Password))
|
|
|
|
require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
|
|
|
|
wg.Done()
|
|
|
|
})
|
|
|
|
|
|
|
|
// Create a new server with the mux as the handler
|
|
|
|
server := httptest.NewServer(mux)
|
|
|
|
defer server.Close()
|
|
|
|
|
|
|
|
networks := []params.Network{
|
|
|
|
{
|
|
|
|
ChainID: 1,
|
|
|
|
DefaultRPCURL: server.URL + path1,
|
|
|
|
DefaultFallbackURL: server.URL + path2,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
c, err := NewClient(nil, 1, params.UpstreamRPCConfig{}, networks, db, providerConfigs)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Networks from DB must pick up DefaultRPCURL and DefaultFallbackURL
|
|
|
|
chainClient, err := c.getClientUsingCache(networks[0].ChainID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, chainClient)
|
|
|
|
|
|
|
|
// Make any call to provider. If test finishes, then all handlers were called and asserts inside them passed
|
|
|
|
balance, err := chainClient.BalanceAt(context.TODO(), common.Address{0x1}, big.NewInt(1))
|
|
|
|
assert.Error(t, err) // EOF, we dont return anything from the server, because of error iterate over all providers
|
|
|
|
assert.Nil(t, balance)
|
|
|
|
wg.Wait()
|
|
|
|
}
|
2024-08-13 10:25:19 +00:00
|
|
|
|
|
|
|
func TestUserAgent(t *testing.T) {
|
2024-08-15 09:31:47 +00:00
|
|
|
require.Equal(t, "procuratee-desktop/", rpcUserAgentName)
|
|
|
|
require.Equal(t, "procuratee-desktop-upstream/", rpcUserAgentUpstreamName)
|
2024-08-13 10:25:19 +00:00
|
|
|
}
|