diff --git a/validator/keymanager/remote-web3signer/internal/BUILD.bazel b/validator/keymanager/remote-web3signer/internal/BUILD.bazel index 44657d8867..29f3b7b316 100644 --- a/validator/keymanager/remote-web3signer/internal/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/internal/BUILD.bazel @@ -28,6 +28,8 @@ go_test( srcs = ["client_test.go"], deps = [ ":go_default_library", + "//testing/require:go_default_library", + "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", ], ) diff --git a/validator/keymanager/remote-web3signer/internal/client.go b/validator/keymanager/remote-web3signer/internal/client.go index 4d592b523b..26ef849dde 100644 --- a/validator/keymanager/remote-web3signer/internal/client.go +++ b/validator/keymanager/remote-web3signer/internal/client.go @@ -28,6 +28,11 @@ const ( type SignRequestJson []byte +// SignatureResponse is the struct representing the signing request response in json format +type SignatureResponse struct { + Signature hexutil.Bytes `json:"signature"` +} + // HttpSignerClient defines the interface for interacting with a remote web3signer. type HttpSignerClient interface { Sign(ctx context.Context, pubKey string, request SignRequestJson) (bls.Signature, error) @@ -68,9 +73,17 @@ func (client *ApiClient) Sign(ctx context.Context, pubKey string, request SignRe if resp.StatusCode == http.StatusPreconditionFailed { return nil, fmt.Errorf("signing operation failed due to slashing protection rules, Signing Request URL: %v, Status: %v", client.BaseURL.String()+requestPath, resp.StatusCode) } - - return unmarshalSignatureResponse(resp.Body) - + contentType := resp.Header.Get("Content-Type") + switch contentType { + case "application/json": + var sigResp SignatureResponse + if err := unmarshalResponse(resp.Body, &sigResp); err != nil { + return nil, err + } + return bls.SignatureFromBytes(sigResp.Signature) + default: + return unmarshalSignatureResponse(resp.Body) + } } // GetPublicKeys is a wrapper method around the web3signer publickeys api (this may be removed in the future or moved to another location due to its usage). diff --git a/validator/keymanager/remote-web3signer/internal/client_test.go b/validator/keymanager/remote-web3signer/internal/client_test.go index 9fc3637f00..7796090f3a 100644 --- a/validator/keymanager/remote-web3signer/internal/client_test.go +++ b/validator/keymanager/remote-web3signer/internal/client_test.go @@ -10,6 +10,8 @@ import ( "net/url" "testing" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer/internal" "github.com/stretchr/testify/assert" ) @@ -49,6 +51,35 @@ func TestClient_Sign_HappyPath(t *testing.T) { assert.EqualValues(t, "0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9", fmt.Sprintf("%#x", resp.Marshal())) } +func TestClient_Sign_HappyPath_Jsontype(t *testing.T) { + byteval, err := hexutil.Decode(`0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9`) + require.NoError(t, err) + sigResp := &internal.SignatureResponse{ + Signature: byteval, + } + jsonBytes, err := json.Marshal(sigResp) + require.NoError(t, err) + // create a new reader with that JSON + header := http.Header{ + "Content-Type": []string{"application/json"}, + } + r := io.NopCloser(bytes.NewReader(jsonBytes)) + mock := &mockTransport{mockResponse: &http.Response{ + StatusCode: 200, + Header: header, + Body: r, + }} + u, err := url.Parse("example.com") + assert.NoError(t, err) + cl := internal.ApiClient{BaseURL: u, RestClient: &http.Client{Transport: mock}} + jsonRequest, err := json.Marshal(`{message: "hello"}`) + assert.NoError(t, err) + resp, err := cl.Sign(context.Background(), "a2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", jsonRequest) + assert.NotNil(t, resp) + assert.Nil(t, err) + assert.EqualValues(t, "0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9", fmt.Sprintf("%#x", resp.Marshal())) +} + func TestClient_Sign_500(t *testing.T) { jsonSig := `0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9` // create a new reader with that JSON