mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-07 20:43:57 -05:00
Support authorised access to web 3 providers (#8075)
* jwt access token impl
* use secret or jwt
* rename
* separate method for splitting auth
* usage update
* Update beacon-chain/flags/base.go
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
* Update beacon-chain/node/node.go
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
* make things work
* removed unused code
* better, more flexible authorization
* move types and function to proper packages
* fix checking if endpoint is not set
* fix existing tests
* rename Endpoint field to Url
* Tests for HttpEndpoint
* better bearer auth
* tests for endpoint utils
* fix endpoint registration
* fix test build
* move endpoint parsing to powchain
* Revert "fix existing tests"
This reverts commit ceab192e6a.
* fix field name in tests
* gzl
* add httputils dependency
* remove httputils dependency
* fix compilation issue in blockchain service test
* correct endpoint fallback function and tests
* gzl
* remove pointer from currHttpEndpoint
* allow whitespace in auth string
* endpoint equality
* correct one auth data Equals test case
* remove pointer receiver
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
@@ -90,7 +90,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
require.NoError(t, err)
|
||||
web3Service, err = powchain.NewService(ctx, &powchain.Web3ServiceConfig{
|
||||
BeaconDB: beaconDB,
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: common.Address{},
|
||||
})
|
||||
require.NoError(t, err, "Unable to set up web3 service")
|
||||
|
||||
@@ -436,7 +436,7 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
}
|
||||
|
||||
cfg := &powchain.Web3ServiceConfig{
|
||||
HTTPEndpoints: endpoints,
|
||||
HttpEndpoints: endpoints,
|
||||
DepositContract: common.HexToAddress(depAddress),
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
"deposit.go",
|
||||
"log.go",
|
||||
"log_processing.go",
|
||||
"provider.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/powchain",
|
||||
@@ -32,6 +33,8 @@ go_library(
|
||||
"//proto/beacon/db:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/httputils:go_default_library",
|
||||
"//shared/httputils/authorizationmethod:go_default_library",
|
||||
"//shared/logutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/timeutils:go_default_library",
|
||||
@@ -64,6 +67,7 @@ go_test(
|
||||
"init_test.go",
|
||||
"log_processing_test.go",
|
||||
"powchain_test.go",
|
||||
"provider_test.go",
|
||||
"service_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
@@ -82,6 +86,8 @@ go_test(
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/httputils:go_default_library",
|
||||
"//shared/httputils/authorizationmethod:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestLatestMainchainInfo_OK(t *testing.T) {
|
||||
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -70,7 +70,7 @@ func TestLatestMainchainInfo_OK(t *testing.T) {
|
||||
func TestBlockHashByHeight_ReturnsHash(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -97,7 +97,7 @@ func TestBlockHashByHeight_ReturnsHash(t *testing.T) {
|
||||
func TestBlockHashByHeight_ReturnsError_WhenNoEth1Client(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -113,7 +113,7 @@ func TestBlockHashByHeight_ReturnsError_WhenNoEth1Client(t *testing.T) {
|
||||
func TestBlockExists_ValidHash(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -144,7 +144,7 @@ func TestBlockExists_ValidHash(t *testing.T) {
|
||||
func TestBlockExists_InvalidHash(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -158,7 +158,7 @@ func TestBlockExists_InvalidHash(t *testing.T) {
|
||||
func TestBlockExists_UsesCachedBlockInfo(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -181,7 +181,7 @@ func TestBlockExists_UsesCachedBlockInfo(t *testing.T) {
|
||||
func TestBlockExistsWithCache_UsesCachedHeaderInfo(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -202,7 +202,7 @@ func TestBlockExistsWithCache_UsesCachedHeaderInfo(t *testing.T) {
|
||||
func TestBlockExistsWithCache_HeaderNotCached(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -218,7 +218,7 @@ func TestService_BlockNumberByTimestamp(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -245,7 +245,7 @@ func TestService_BlockNumberByTimestampLessTargetTime(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -278,7 +278,7 @@ func TestService_BlockNumberByTimestampMoreTargetTime(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -309,7 +309,7 @@ func TestService_BlockNumberByTimestampMoreTargetTime(t *testing.T) {
|
||||
func TestService_BlockTimeByHeight_ReturnsError_WhenNoEth1Client(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
|
||||
@@ -24,7 +24,7 @@ const pubKeyErr = "could not convert bytes to public key"
|
||||
func TestProcessDeposit_OK(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "Unable to setup web3 ETH1.0 chain service")
|
||||
@@ -48,7 +48,7 @@ func TestProcessDeposit_OK(t *testing.T) {
|
||||
func TestProcessDeposit_InvalidMerkleBranch(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -74,7 +74,7 @@ func TestProcessDeposit_InvalidPublicKey(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -110,7 +110,7 @@ func TestProcessDeposit_InvalidSignature(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -145,7 +145,7 @@ func TestProcessDeposit_UnableToVerify(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -178,7 +178,7 @@ func TestProcessDeposit_UnableToVerify(t *testing.T) {
|
||||
func TestProcessDeposit_IncompleteDeposit(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -239,7 +239,7 @@ func TestProcessDeposit_IncompleteDeposit(t *testing.T) {
|
||||
func TestProcessDeposit_AllDepositedSuccessfully(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
|
||||
@@ -37,7 +37,7 @@ func TestProcessDepositLog_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -101,7 +101,7 @@ func TestProcessDepositLog_InsertsPendingDeposit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -158,7 +158,7 @@ func TestUnpackDepositLogData_OK(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
})
|
||||
@@ -209,7 +209,7 @@ func TestProcessETH2GenesisLog_8DuplicatePubkeys(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -280,7 +280,7 @@ func TestProcessETH2GenesisLog(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -367,7 +367,7 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: kvStore,
|
||||
DepositCache: depositCache,
|
||||
@@ -460,7 +460,7 @@ func TestProcessETH2GenesisLog_LargePeriodOfNoLogs(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: kvStore,
|
||||
DepositCache: depositCache,
|
||||
@@ -563,7 +563,7 @@ func TestWeb3ServiceProcessDepositLog_RequestMissedDeposits(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -655,7 +655,7 @@ func newPowchainService(t *testing.T, eth1Backend *contracts.TestAccount, beacon
|
||||
require.NoError(t, err)
|
||||
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: eth1Backend.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
|
||||
49
beacon-chain/powchain/provider.go
Normal file
49
beacon-chain/powchain/provider.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package powchain
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils"
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils/authorizationmethod"
|
||||
)
|
||||
|
||||
// HttpEndpoint extracts an httputils.Endpoint from the provider parameter.
|
||||
func HttpEndpoint(eth1Provider string) httputils.Endpoint {
|
||||
endpoint := httputils.Endpoint{
|
||||
Url: "",
|
||||
Auth: httputils.AuthorizationData{
|
||||
Method: authorizationmethod.None,
|
||||
Value: "",
|
||||
}}
|
||||
|
||||
authValues := strings.Split(eth1Provider, ",")
|
||||
endpoint.Url = strings.TrimSpace(authValues[0])
|
||||
if len(authValues) > 2 {
|
||||
log.Errorf(
|
||||
"ETH1 endpoint string can contain one comma for specifying the authorization header to access the provider."+
|
||||
" String contains too many commas: %d. Skipping authorization.", len(authValues)-1)
|
||||
} else if len(authValues) == 2 {
|
||||
switch httputils.Method(strings.TrimSpace(authValues[1])) {
|
||||
case authorizationmethod.Basic:
|
||||
basicAuthValues := strings.Split(strings.TrimSpace(authValues[1]), " ")
|
||||
if len(basicAuthValues) != 2 {
|
||||
log.Errorf("Basic Authentication has incorrect format. Skipping authorization.")
|
||||
} else {
|
||||
endpoint.Auth.Method = authorizationmethod.Basic
|
||||
endpoint.Auth.Value = base64.StdEncoding.EncodeToString([]byte(basicAuthValues[1]))
|
||||
}
|
||||
case authorizationmethod.Bearer:
|
||||
bearerAuthValues := strings.Split(strings.TrimSpace(authValues[1]), " ")
|
||||
if len(bearerAuthValues) != 2 {
|
||||
log.Errorf("Bearer Authentication has incorrect format. Skipping authorization.")
|
||||
} else {
|
||||
endpoint.Auth.Method = authorizationmethod.Bearer
|
||||
endpoint.Auth.Value = bearerAuthValues[1]
|
||||
}
|
||||
case authorizationmethod.None:
|
||||
log.Errorf("Authorization has incorrect format or authorization type is not supported.")
|
||||
}
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
74
beacon-chain/powchain/provider_test.go
Normal file
74
beacon-chain/powchain/provider_test.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package powchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils/authorizationmethod"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func TestHttpEndpoint(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
url := "http://test"
|
||||
|
||||
t.Run("URL", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url)
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.None, endpoint.Auth.Method)
|
||||
})
|
||||
t.Run("URL with separator", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url + ",")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.None, endpoint.Auth.Method)
|
||||
})
|
||||
t.Run("URL with whitespace", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(" " + url + " ,")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.None, endpoint.Auth.Method)
|
||||
})
|
||||
t.Run("Basic auth", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url + ",Basic username:password")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.Basic, endpoint.Auth.Method)
|
||||
assert.Equal(t, "dXNlcm5hbWU6cGFzc3dvcmQ=", endpoint.Auth.Value)
|
||||
})
|
||||
t.Run("Basic auth with whitespace", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url + ", Basic username:password ")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.Basic, endpoint.Auth.Method)
|
||||
assert.Equal(t, "dXNlcm5hbWU6cGFzc3dvcmQ=", endpoint.Auth.Value)
|
||||
})
|
||||
t.Run("Basic auth with incorrect format", func(t *testing.T) {
|
||||
hook.Reset()
|
||||
endpoint := HttpEndpoint(url + ",Basic username:password foo")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.None, endpoint.Auth.Method)
|
||||
assert.LogsContain(t, hook, "Skipping authorization")
|
||||
})
|
||||
t.Run("Bearer auth", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url + ",Bearer token")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.Bearer, endpoint.Auth.Method)
|
||||
assert.Equal(t, "token", endpoint.Auth.Value)
|
||||
})
|
||||
t.Run("Bearer auth with whitespace", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url + ", Bearer token ")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.Bearer, endpoint.Auth.Method)
|
||||
assert.Equal(t, "token", endpoint.Auth.Value)
|
||||
})
|
||||
t.Run("Bearer auth with incorrect format", func(t *testing.T) {
|
||||
hook.Reset()
|
||||
endpoint := HttpEndpoint(url + ",Bearer token foo")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.None, endpoint.Auth.Method)
|
||||
assert.LogsContain(t, hook, "Skipping authorization")
|
||||
})
|
||||
t.Run("Too many separators", func(t *testing.T) {
|
||||
endpoint := HttpEndpoint(url + ",Bearer token,foo")
|
||||
assert.Equal(t, url, endpoint.Url)
|
||||
assert.Equal(t, authorizationmethod.None, endpoint.Auth.Method)
|
||||
assert.LogsContain(t, hook, "Skipping authorization")
|
||||
})
|
||||
}
|
||||
@@ -35,6 +35,8 @@ import (
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
|
||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils"
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils/authorizationmethod"
|
||||
"github.com/prysmaticlabs/prysm/shared/logutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
@@ -128,7 +130,8 @@ type Service struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
headTicker *time.Ticker
|
||||
currHttpEndpoint string
|
||||
httpEndpoints []httputils.Endpoint
|
||||
currHttpEndpoint httputils.Endpoint
|
||||
httpLogger bind.ContractFilterer
|
||||
eth1DataFetcher RPCDataFetcher
|
||||
rpcClient RPCClient
|
||||
@@ -144,7 +147,7 @@ type Service struct {
|
||||
|
||||
// Web3ServiceConfig defines a config struct for web3 service to use through its life cycle.
|
||||
type Web3ServiceConfig struct {
|
||||
HTTPEndpoints []string
|
||||
HttpEndpoints []string
|
||||
DepositContract common.Address
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
DepositCache *depositcache.DepositCache
|
||||
@@ -172,16 +175,22 @@ func NewService(ctx context.Context, config *Web3ServiceConfig) (*Service, error
|
||||
config.Eth1HeaderReqLimit = defaultEth1HeaderReqLimit
|
||||
}
|
||||
|
||||
config.HTTPEndpoints = dedupEndpoints(config.HTTPEndpoints)
|
||||
stringEndpoints := dedupEndpoints(config.HttpEndpoints)
|
||||
endpoints := make([]httputils.Endpoint, len(stringEndpoints))
|
||||
for i, e := range stringEndpoints {
|
||||
endpoints[i] = HttpEndpoint(e)
|
||||
}
|
||||
|
||||
// Select first http endpoint in the provided list.
|
||||
currEndpoint := ""
|
||||
if len(config.HTTPEndpoints) > 0 {
|
||||
currEndpoint = config.HTTPEndpoints[0]
|
||||
var currEndpoint httputils.Endpoint
|
||||
if len(config.HttpEndpoints) > 0 {
|
||||
currEndpoint = endpoints[0]
|
||||
}
|
||||
s := &Service{
|
||||
cfg: config,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
cfg: config,
|
||||
httpEndpoints: endpoints,
|
||||
currHttpEndpoint: currEndpoint,
|
||||
latestEth1Data: &protodb.LatestETH1Data{
|
||||
BlockHeight: 0,
|
||||
@@ -230,7 +239,7 @@ func NewService(ctx context.Context, config *Web3ServiceConfig) (*Service, error
|
||||
func (s *Service) Start() {
|
||||
// If the chain has not started already and we don't have access to eth1 nodes, we will not be
|
||||
// able to generate the genesis state.
|
||||
if !s.chainStartData.Chainstarted && s.currHttpEndpoint == "" {
|
||||
if !s.chainStartData.Chainstarted && s.currHttpEndpoint.Url == "" {
|
||||
// check for genesis state before shutting down the node,
|
||||
// if a genesis state exists, we can continue on.
|
||||
genState, err := s.cfg.BeaconDB.GenesisState(s.ctx)
|
||||
@@ -243,7 +252,7 @@ func (s *Service) Start() {
|
||||
}
|
||||
|
||||
// Exit early if eth1 endpoint is not set.
|
||||
if s.currHttpEndpoint == "" {
|
||||
if s.currHttpEndpoint.Url == "" {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
@@ -375,11 +384,18 @@ func (s *Service) connectToPowChain() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) dialETH1Nodes(endpoint string) (*ethclient.Client, *gethRPC.Client, error) {
|
||||
httpRPCClient, err := gethRPC.Dial(endpoint)
|
||||
func (s *Service) dialETH1Nodes(endpoint httputils.Endpoint) (*ethclient.Client, *gethRPC.Client, error) {
|
||||
httpRPCClient, err := gethRPC.Dial(endpoint.Url)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if endpoint.Auth.Method != authorizationmethod.None {
|
||||
header, err := endpoint.Auth.ToHeaderValue()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
httpRPCClient.SetHeader("Authorization", header)
|
||||
}
|
||||
httpClient := ethclient.NewClient(httpRPCClient)
|
||||
// Add a method to clean-up and close clients in the event
|
||||
// of any connection failure.
|
||||
@@ -451,7 +467,7 @@ func (s *Service) waitForConnection() {
|
||||
s.connectedETH1 = true
|
||||
s.runError = nil
|
||||
log.WithFields(logrus.Fields{
|
||||
"endpoint": logutil.MaskCredentialsLogging(s.currHttpEndpoint),
|
||||
"endpoint": logutil.MaskCredentialsLogging(s.currHttpEndpoint.Url),
|
||||
}).Info("Connected to eth1 proof-of-work chain")
|
||||
return
|
||||
}
|
||||
@@ -480,7 +496,7 @@ func (s *Service) waitForConnection() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
log.Debugf("Trying to dial endpoint: %s", logutil.MaskCredentialsLogging(s.currHttpEndpoint))
|
||||
log.Debugf("Trying to dial endpoint: %s", logutil.MaskCredentialsLogging(s.currHttpEndpoint.Url))
|
||||
errConnect := s.connectToPowChain()
|
||||
if errConnect != nil {
|
||||
errorLogger(errConnect, "Could not connect to powchain endpoint")
|
||||
@@ -499,7 +515,7 @@ func (s *Service) waitForConnection() {
|
||||
s.connectedETH1 = true
|
||||
s.runError = nil
|
||||
log.WithFields(logrus.Fields{
|
||||
"endpoint": logutil.MaskCredentialsLogging(s.currHttpEndpoint),
|
||||
"endpoint": logutil.MaskCredentialsLogging(s.currHttpEndpoint.Url),
|
||||
}).Info("Connected to eth1 proof-of-work chain")
|
||||
return
|
||||
}
|
||||
@@ -854,10 +870,10 @@ func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock
|
||||
// is ready to serve we connect to it again. This method is only
|
||||
// relevant if we are on our backup endpoint.
|
||||
func (s *Service) checkDefaultEndpoint() {
|
||||
primaryEndpoint := s.cfg.HTTPEndpoints[0]
|
||||
primaryEndpoint := s.httpEndpoints[0]
|
||||
// Return early if we are running on our primary
|
||||
// endpoint.
|
||||
if s.currHttpEndpoint == primaryEndpoint {
|
||||
if s.currHttpEndpoint.Equals(primaryEndpoint) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -885,10 +901,10 @@ func (s *Service) checkDefaultEndpoint() {
|
||||
func (s *Service) fallbackToNextEndpoint() {
|
||||
currEndpoint := s.currHttpEndpoint
|
||||
currIndex := 0
|
||||
totalEndpoints := len(s.cfg.HTTPEndpoints)
|
||||
totalEndpoints := len(s.httpEndpoints)
|
||||
|
||||
for i, endpoint := range s.cfg.HTTPEndpoints {
|
||||
if endpoint == currEndpoint {
|
||||
for i, endpoint := range s.httpEndpoints {
|
||||
if endpoint.Equals(currEndpoint) {
|
||||
currIndex = i
|
||||
break
|
||||
}
|
||||
@@ -901,8 +917,8 @@ func (s *Service) fallbackToNextEndpoint() {
|
||||
if nextIndex == currIndex {
|
||||
return
|
||||
}
|
||||
s.currHttpEndpoint = s.cfg.HTTPEndpoints[nextIndex]
|
||||
log.Infof("Falling back to alternative endpoint: %s", logutil.MaskCredentialsLogging(s.currHttpEndpoint))
|
||||
s.currHttpEndpoint = s.httpEndpoints[nextIndex]
|
||||
log.Infof("Falling back to alternative endpoint: %s", logutil.MaskCredentialsLogging(s.currHttpEndpoint.Url))
|
||||
}
|
||||
|
||||
// validates the current powchain data saved and makes sure that any
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
|
||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -124,7 +125,7 @@ func TestStart_OK(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -147,13 +148,13 @@ func TestStart_OK(t *testing.T) {
|
||||
web3Service.cancel()
|
||||
}
|
||||
|
||||
func TestStart_NoHTTPEndpointDefinedFails_WithoutChainStarted(t *testing.T) {
|
||||
func TestStart_NoHttpEndpointDefinedFails_WithoutChainStarted(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
testAcc, err := contracts.Setup()
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
s, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{""}, // No endpoint defined!
|
||||
HttpEndpoints: []string{""}, // No endpoint defined!
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -182,7 +183,7 @@ func TestStart_NoHTTPEndpointDefinedFails_WithoutChainStarted(t *testing.T) {
|
||||
hook.Reset()
|
||||
}
|
||||
|
||||
func TestStart_NoHTTPEndpointDefinedSucceeds_WithGenesisState(t *testing.T) {
|
||||
func TestStart_NoHttpEndpointDefinedSucceeds_WithGenesisState(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
testAcc, err := contracts.Setup()
|
||||
@@ -196,7 +197,7 @@ func TestStart_NoHTTPEndpointDefinedSucceeds_WithGenesisState(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
s, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{""}, // No endpoint defined!
|
||||
HttpEndpoints: []string{""}, // No endpoint defined!
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -216,7 +217,7 @@ func TestStart_NoHTTPEndpointDefinedSucceeds_WithGenesisState(t *testing.T) {
|
||||
hook.Reset()
|
||||
}
|
||||
|
||||
func TestStart_NoHTTPEndpointDefinedSucceeds_WithChainStarted(t *testing.T) {
|
||||
func TestStart_NoHttpEndpointDefinedSucceeds_WithChainStarted(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
testAcc, err := contracts.Setup()
|
||||
@@ -227,7 +228,7 @@ func TestStart_NoHTTPEndpointDefinedSucceeds_WithChainStarted(t *testing.T) {
|
||||
Trie: &protodb.SparseMerkleTrie{},
|
||||
}))
|
||||
s, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{""}, // No endpoint defined!
|
||||
HttpEndpoints: []string{""}, // No endpoint defined!
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -244,7 +245,7 @@ func TestStop_OK(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -269,7 +270,7 @@ func TestService_Eth1Synced(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -290,7 +291,7 @@ func TestFollowBlock_OK(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -363,7 +364,7 @@ func TestHandlePanic_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
@@ -402,7 +403,7 @@ func TestLogTillGenesis_OK(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -462,7 +463,7 @@ func TestNewService_EarliestVotingBlock(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -513,7 +514,7 @@ func TestNewService_Eth1HeaderRequLimit(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
|
||||
s1, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
@@ -521,7 +522,7 @@ func TestNewService_Eth1HeaderRequLimit(t *testing.T) {
|
||||
assert.Equal(t, defaultEth1HeaderReqLimit, s1.cfg.Eth1HeaderReqLimit, "default eth1 header request limit not set")
|
||||
|
||||
s2, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
Eth1HeaderReqLimit: uint64(150),
|
||||
@@ -539,36 +540,36 @@ func TestServiceFallbackCorrectly(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
|
||||
s1, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndpoints: []string{firstEndpoint},
|
||||
HttpEndpoints: []string{firstEndpoint},
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, firstEndpoint, s1.currHttpEndpoint, "Unexpected http endpoint")
|
||||
assert.Equal(t, firstEndpoint, s1.currHttpEndpoint.Url, "Unexpected http endpoint")
|
||||
// Stay at the first endpoint.
|
||||
s1.fallbackToNextEndpoint()
|
||||
assert.Equal(t, firstEndpoint, s1.currHttpEndpoint, "Unexpected http endpoint")
|
||||
assert.Equal(t, firstEndpoint, s1.currHttpEndpoint.Url, "Unexpected http endpoint")
|
||||
|
||||
s1.cfg.HTTPEndpoints = append(s1.cfg.HTTPEndpoints, secondEndpoint)
|
||||
s1.httpEndpoints = append(s1.httpEndpoints, httputils.Endpoint{Url: secondEndpoint})
|
||||
|
||||
s1.fallbackToNextEndpoint()
|
||||
assert.Equal(t, secondEndpoint, s1.currHttpEndpoint, "Unexpected http endpoint")
|
||||
assert.Equal(t, secondEndpoint, s1.currHttpEndpoint.Url, "Unexpected http endpoint")
|
||||
|
||||
thirdEndpoint := "C"
|
||||
fourthEndpoint := "D"
|
||||
|
||||
s1.cfg.HTTPEndpoints = append(s1.cfg.HTTPEndpoints, thirdEndpoint, fourthEndpoint)
|
||||
s1.httpEndpoints = append(s1.httpEndpoints, httputils.Endpoint{Url: thirdEndpoint}, httputils.Endpoint{Url: fourthEndpoint})
|
||||
|
||||
s1.fallbackToNextEndpoint()
|
||||
assert.Equal(t, thirdEndpoint, s1.currHttpEndpoint, "Unexpected http endpoint")
|
||||
assert.Equal(t, thirdEndpoint, s1.currHttpEndpoint.Url, "Unexpected http endpoint")
|
||||
|
||||
s1.fallbackToNextEndpoint()
|
||||
assert.Equal(t, fourthEndpoint, s1.currHttpEndpoint, "Unexpected http endpoint")
|
||||
assert.Equal(t, fourthEndpoint, s1.currHttpEndpoint.Url, "Unexpected http endpoint")
|
||||
|
||||
// Rollover correctly back to the first endpoint
|
||||
s1.fallbackToNextEndpoint()
|
||||
assert.Equal(t, firstEndpoint, s1.currHttpEndpoint, "Unexpected http endpoint")
|
||||
assert.Equal(t, firstEndpoint, s1.currHttpEndpoint.Url, "Unexpected http endpoint")
|
||||
}
|
||||
|
||||
func TestDedupEndpoints(t *testing.T) {
|
||||
|
||||
@@ -11,11 +11,12 @@ var (
|
||||
// HTTPWeb3ProviderFlag provides an HTTP access endpoint to an ETH 1.0 RPC.
|
||||
HTTPWeb3ProviderFlag = &cli.StringFlag{
|
||||
Name: "http-web3provider",
|
||||
Usage: "A mainchain web3 provider string http endpoint. This is our primary web3 provider",
|
||||
Usage: "A mainchain web3 provider string http endpoint. Can contain auth header as well in the format --http-web3provider=\"https://goerli.infura.io/v3/xxxx,Basic xxx\" for project secret (base64 encoded) and --http-web3provider=\"https://goerli.infura.io/v3/xxxx,Bearer xxx\" for jwt use",
|
||||
Value: "",
|
||||
}
|
||||
FallbackWeb3ProviderFlag = &cli.StringSliceFlag{
|
||||
Name: "fallback-web3provider",
|
||||
Usage: "A mainchain web3 provider string http endpoint. This is our fallback web3 provider, this flag maybe used multiple times.",
|
||||
Usage: "A mainchain web3 provider string http endpoint. This is our fallback web3 provider, this flag may be used multiple times.",
|
||||
}
|
||||
// DepositContractFlag defines a flag for the deposit contract address.
|
||||
DepositContractFlag = &cli.StringFlag{
|
||||
|
||||
21
shared/httputils/BUILD.bazel
Normal file
21
shared/httputils/BUILD.bazel
Normal file
@@ -0,0 +1,21 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["endpoint.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/shared/httputils",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//shared/httputils/authorizationmethod:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["endpoint_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//shared/httputils/authorizationmethod:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
],
|
||||
)
|
||||
8
shared/httputils/authorizationmethod/BUILD.bazel
Normal file
8
shared/httputils/authorizationmethod/BUILD.bazel
Normal file
@@ -0,0 +1,8 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["authorization_method.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/shared/httputils/authorizationmethod",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
13
shared/httputils/authorizationmethod/authorization_method.go
Normal file
13
shared/httputils/authorizationmethod/authorization_method.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package authorizationmethod
|
||||
|
||||
// AuthorizationMethod is an authorization method such as 'Basic' or 'Bearer'.
|
||||
type AuthorizationMethod uint8
|
||||
|
||||
const (
|
||||
// None represents no authorization method.
|
||||
None AuthorizationMethod = iota
|
||||
// Basic represents Basic Authentication.
|
||||
Basic
|
||||
// Bearer represents Bearer Authentication (token authentication).
|
||||
Bearer
|
||||
)
|
||||
53
shared/httputils/endpoint.go
Normal file
53
shared/httputils/endpoint.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package httputils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils/authorizationmethod"
|
||||
)
|
||||
|
||||
// Endpoint is an endpoint with authorization data.
|
||||
type Endpoint struct {
|
||||
Url string
|
||||
Auth AuthorizationData
|
||||
}
|
||||
|
||||
// AuthorizationData holds all information necessary to authorize with HTTP.
|
||||
type AuthorizationData struct {
|
||||
Method authorizationmethod.AuthorizationMethod
|
||||
Value string
|
||||
}
|
||||
|
||||
func (e Endpoint) Equals(other Endpoint) bool {
|
||||
return e.Url == other.Url && e.Auth.Equals(other.Auth)
|
||||
}
|
||||
|
||||
func (d AuthorizationData) Equals(other AuthorizationData) bool {
|
||||
return d.Method == other.Method && d.Value == other.Value
|
||||
}
|
||||
|
||||
// ToHeaderValue retrieves the value of the authorization header from AuthorizationData.
|
||||
func (d *AuthorizationData) ToHeaderValue() (string, error) {
|
||||
switch d.Method {
|
||||
case authorizationmethod.Basic:
|
||||
return "Basic " + d.Value, nil
|
||||
case authorizationmethod.Bearer:
|
||||
return "Bearer " + d.Value, nil
|
||||
case authorizationmethod.None:
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return "", errors.New("could not create HTTP header for unknown authorization method")
|
||||
}
|
||||
|
||||
// Method returns the authorizationmethod.AuthorizationMethod corresponding with the parameter value.
|
||||
func Method(auth string) authorizationmethod.AuthorizationMethod {
|
||||
if strings.HasPrefix(strings.ToLower(auth), "basic") {
|
||||
return authorizationmethod.Basic
|
||||
}
|
||||
if strings.HasPrefix(strings.ToLower(auth), "bearer") {
|
||||
return authorizationmethod.Bearer
|
||||
}
|
||||
return authorizationmethod.None
|
||||
}
|
||||
142
shared/httputils/endpoint_test.go
Normal file
142
shared/httputils/endpoint_test.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package httputils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/httputils/authorizationmethod"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestToHeaderValue(t *testing.T) {
|
||||
t.Run("None", func(t *testing.T) {
|
||||
data := &AuthorizationData{
|
||||
Method: authorizationmethod.None,
|
||||
Value: "foo",
|
||||
}
|
||||
header, err := data.ToHeaderValue()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "", header)
|
||||
})
|
||||
t.Run("Basic", func(t *testing.T) {
|
||||
data := &AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "foo",
|
||||
}
|
||||
header, err := data.ToHeaderValue()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Basic foo", header)
|
||||
})
|
||||
t.Run("Bearer", func(t *testing.T) {
|
||||
data := &AuthorizationData{
|
||||
Method: authorizationmethod.Bearer,
|
||||
Value: "foo",
|
||||
}
|
||||
header, err := data.ToHeaderValue()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Bearer foo", header)
|
||||
})
|
||||
t.Run("Unknown", func(t *testing.T) {
|
||||
data := &AuthorizationData{
|
||||
Method: 99,
|
||||
Value: "foo",
|
||||
}
|
||||
_, err := data.ToHeaderValue()
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMethod(t *testing.T) {
|
||||
t.Run("None", func(t *testing.T) {
|
||||
method := Method("")
|
||||
assert.Equal(t, authorizationmethod.None, method)
|
||||
method = Method("foo")
|
||||
assert.Equal(t, authorizationmethod.None, method)
|
||||
})
|
||||
t.Run("Basic", func(t *testing.T) {
|
||||
method := Method("Basic")
|
||||
assert.Equal(t, authorizationmethod.Basic, method)
|
||||
})
|
||||
t.Run("Basic different text case", func(t *testing.T) {
|
||||
method := Method("bAsIc")
|
||||
assert.Equal(t, authorizationmethod.Basic, method)
|
||||
})
|
||||
t.Run("Bearer", func(t *testing.T) {
|
||||
method := Method("Bearer")
|
||||
assert.Equal(t, authorizationmethod.Bearer, method)
|
||||
})
|
||||
t.Run("Bearer different text case", func(t *testing.T) {
|
||||
method := Method("bEaReR")
|
||||
assert.Equal(t, authorizationmethod.Bearer, method)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEndpointEquals(t *testing.T) {
|
||||
e := Endpoint{
|
||||
Url: "Url",
|
||||
Auth: AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "Basic username:password",
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("equal", func(t *testing.T) {
|
||||
other := Endpoint{
|
||||
Url: "Url",
|
||||
Auth: AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "Basic username:password",
|
||||
},
|
||||
}
|
||||
assert.Equal(t, true, e.Equals(other))
|
||||
})
|
||||
t.Run("different URL", func(t *testing.T) {
|
||||
other := Endpoint{
|
||||
Url: "Different",
|
||||
Auth: AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "Basic username:password",
|
||||
},
|
||||
}
|
||||
assert.Equal(t, false, e.Equals(other))
|
||||
})
|
||||
t.Run("different auth data", func(t *testing.T) {
|
||||
other := Endpoint{
|
||||
Url: "Url",
|
||||
Auth: AuthorizationData{
|
||||
Method: authorizationmethod.Bearer,
|
||||
Value: "Bearer token",
|
||||
},
|
||||
}
|
||||
assert.Equal(t, false, e.Equals(other))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthorizationDataEquals(t *testing.T) {
|
||||
d := AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "username:password",
|
||||
}
|
||||
|
||||
t.Run("equal", func(t *testing.T) {
|
||||
other := AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "username:password",
|
||||
}
|
||||
assert.Equal(t, true, d.Equals(other))
|
||||
})
|
||||
t.Run("different method", func(t *testing.T) {
|
||||
other := AuthorizationData{
|
||||
Method: authorizationmethod.None,
|
||||
Value: "username:password",
|
||||
}
|
||||
assert.Equal(t, false, d.Equals(other))
|
||||
})
|
||||
t.Run("different value", func(t *testing.T) {
|
||||
other := AuthorizationData{
|
||||
Method: authorizationmethod.Basic,
|
||||
Value: "different:different",
|
||||
}
|
||||
assert.Equal(t, false, d.Equals(other))
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user