mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-07 22:54:17 -05:00
WIP
This commit is contained in:
@@ -5,6 +5,8 @@ go_library(
|
||||
srcs = [
|
||||
"activation.go",
|
||||
"attestation_data.go",
|
||||
"attester_slashings.go",
|
||||
"attester_slashings_helpers.go",
|
||||
"beacon_api_beacon_chain_client.go",
|
||||
"beacon_api_helpers.go",
|
||||
"beacon_api_node_client.go",
|
||||
@@ -65,6 +67,8 @@ go_test(
|
||||
srcs = [
|
||||
"activation_test.go",
|
||||
"attestation_data_test.go",
|
||||
"attester_slashings_helpers_test.go",
|
||||
"attester_slashings_test.go",
|
||||
"beacon_api_helpers_test.go",
|
||||
"beacon_api_validator_client_test.go",
|
||||
"beacon_block_converter_test.go",
|
||||
|
||||
73
validator/client/beacon-api/attester_slashings.go
Normal file
73
validator/client/beacon-api/attester_slashings.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (c beaconApiSlasherClient) getSlashableAttestations(ctx context.Context, in *ethpb.IndexedAttestation) (*ethpb.AttesterSlashingResponse, error) {
|
||||
attesterSlashingsPoolResponse := apimiddleware.AttesterSlashingsPoolResponseJson{}
|
||||
if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, "/eth/v1/beacon/pool/attester_slashings", &attesterSlashingsPoolResponse); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attester slashings")
|
||||
}
|
||||
|
||||
attesterSlashings, err := convertAttesterSlashingsToProto(attesterSlashingsPoolResponse.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to convert attester slashings")
|
||||
}
|
||||
|
||||
type mapKey struct {
|
||||
targetEpoch primitives.Epoch
|
||||
attestingIndex uint64
|
||||
}
|
||||
|
||||
// Make a map of the requested attesting indices to easily filter them
|
||||
attestingIndicesMap := make(map[mapKey]bool, len(in.AttestingIndices))
|
||||
for _, attestingIndex := range in.AttestingIndices {
|
||||
attestingIndicesMap[mapKey{
|
||||
targetEpoch: in.Data.Target.Epoch,
|
||||
attestingIndex: attestingIndex,
|
||||
}] = true
|
||||
}
|
||||
|
||||
filteredAttesterSlashings := make([]*ethpb.AttesterSlashing, 0)
|
||||
for _, attesterSlashing := range attesterSlashings {
|
||||
// Keep the intersection of the Attestation_1 and Attestion_2 attesting indices
|
||||
attestingIndices1Map := make(map[uint64]bool, len(attesterSlashing.Attestation_1.AttestingIndices))
|
||||
for _, attestingIndex := range attesterSlashing.Attestation_1.AttestingIndices {
|
||||
attestingIndices1Map[attestingIndex] = true
|
||||
}
|
||||
|
||||
attestingIndicesIntersection := make([]uint64, 0, len(attesterSlashing.Attestation_1.AttestingIndices))
|
||||
for _, attestingIndex := range attesterSlashing.Attestation_2.AttestingIndices {
|
||||
if _, ok := attestingIndices1Map[attestingIndex]; ok {
|
||||
attestingIndicesIntersection = append(attestingIndicesIntersection, attestingIndex)
|
||||
}
|
||||
}
|
||||
|
||||
for _, attestingIndex := range attestingIndicesIntersection {
|
||||
_, foundAttestation1Match := attestingIndicesMap[mapKey{
|
||||
targetEpoch: attesterSlashing.Attestation_1.Data.Target.Epoch,
|
||||
attestingIndex: attestingIndex,
|
||||
}]
|
||||
|
||||
_, foundAttestation2Match := attestingIndicesMap[mapKey{
|
||||
targetEpoch: attesterSlashing.Attestation_2.Data.Target.Epoch,
|
||||
attestingIndex: attestingIndex,
|
||||
}]
|
||||
|
||||
if foundAttestation1Match || foundAttestation2Match {
|
||||
filteredAttesterSlashings = append(filteredAttesterSlashings, attesterSlashing)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ðpb.AttesterSlashingResponse{
|
||||
AttesterSlashings: filteredAttesterSlashings,
|
||||
}, nil
|
||||
}
|
||||
70
validator/client/beacon-api/attester_slashings_helpers.go
Normal file
70
validator/client/beacon-api/attester_slashings_helpers.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func convertAttesterSlashingsToProto(jsonAttesterSlashings []*apimiddleware.AttesterSlashingJson) ([]*ethpb.AttesterSlashing, error) {
|
||||
attesterSlashings := make([]*ethpb.AttesterSlashing, len(jsonAttesterSlashings))
|
||||
|
||||
for index, jsonAttesterSlashing := range jsonAttesterSlashings {
|
||||
if jsonAttesterSlashing == nil {
|
||||
return nil, errors.Errorf("attester slashing at index `%d` is nil", index)
|
||||
}
|
||||
|
||||
attestation1, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation 1")
|
||||
}
|
||||
|
||||
attestation2, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_2)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation 2")
|
||||
}
|
||||
|
||||
attesterSlashings[index] = ðpb.AttesterSlashing{
|
||||
Attestation_1: attestation1,
|
||||
Attestation_2: attestation2,
|
||||
}
|
||||
}
|
||||
|
||||
return attesterSlashings, nil
|
||||
}
|
||||
|
||||
func convertIndexedAttestationToProto(jsonAttestation *apimiddleware.IndexedAttestationJson) (*ethpb.IndexedAttestation, error) {
|
||||
if jsonAttestation == nil {
|
||||
return nil, errors.New("indexed attestation is nil")
|
||||
}
|
||||
|
||||
attestingIndices := make([]uint64, len(jsonAttestation.AttestingIndices))
|
||||
|
||||
for index, jsonAttestingIndex := range jsonAttestation.AttestingIndices {
|
||||
attestingIndex, err := strconv.ParseUint(jsonAttestingIndex, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse attesting index `%s`", jsonAttestingIndex)
|
||||
}
|
||||
|
||||
attestingIndices[index] = attestingIndex
|
||||
}
|
||||
|
||||
signature, err := hexutil.Decode(jsonAttestation.Signature)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode attestation signature `%s`", jsonAttestation.Signature)
|
||||
}
|
||||
|
||||
attestationData, err := convertAttestationDataToProto(jsonAttestation.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation data")
|
||||
}
|
||||
|
||||
return ðpb.IndexedAttestation{
|
||||
AttestingIndices: attestingIndices,
|
||||
Data: attestationData,
|
||||
Signature: signature,
|
||||
}, nil
|
||||
}
|
||||
223
validator/client/beacon-api/attester_slashings_helpers_test.go
Normal file
223
validator/client/beacon-api/attester_slashings_helpers_test.go
Normal file
@@ -0,0 +1,223 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
)
|
||||
|
||||
func TestBeaconBlockProtoHelpers_ConvertAttesterSlashingsToProto(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
generateInput func() []*apimiddleware.AttesterSlashingJson
|
||||
expectedResult []*ethpb.AttesterSlashing
|
||||
expectedErrorMessage string
|
||||
}{
|
||||
{
|
||||
name: "nil attester slashing",
|
||||
expectedErrorMessage: "attester slashing at index `0` is nil",
|
||||
generateInput: func() []*apimiddleware.AttesterSlashingJson {
|
||||
return []*apimiddleware.AttesterSlashingJson{
|
||||
nil,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad attestation 1",
|
||||
expectedErrorMessage: "failed to get attestation 1",
|
||||
generateInput: func() []*apimiddleware.AttesterSlashingJson {
|
||||
return []*apimiddleware.AttesterSlashingJson{
|
||||
{
|
||||
Attestation_1: nil,
|
||||
Attestation_2: nil,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad attestation 2",
|
||||
expectedErrorMessage: "failed to get attestation 2",
|
||||
generateInput: func() []*apimiddleware.AttesterSlashingJson {
|
||||
input := generateAttesterSlashingsJson()
|
||||
input[0].Attestation_2 = nil
|
||||
return input
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
generateInput: generateAttesterSlashingsJson,
|
||||
expectedResult: generateAttesterSlashingsProto(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
result, err := convertAttesterSlashingsToProto(testCase.generateInput())
|
||||
|
||||
if testCase.expectedResult != nil {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, testCase.expectedResult, result)
|
||||
} else if testCase.expectedErrorMessage != "" {
|
||||
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func generateAttesterSlashingsJson() []*apimiddleware.AttesterSlashingJson {
|
||||
return []*apimiddleware.AttesterSlashingJson{
|
||||
{
|
||||
Attestation_1: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"1", "2"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "3",
|
||||
CommitteeIndex: "4",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{5}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "6",
|
||||
Root: hexutil.Encode([]byte{7}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "8",
|
||||
Root: hexutil.Encode([]byte{9}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{10}),
|
||||
},
|
||||
Attestation_2: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"11", "12"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "13",
|
||||
CommitteeIndex: "14",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{15}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "16",
|
||||
Root: hexutil.Encode([]byte{17}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "18",
|
||||
Root: hexutil.Encode([]byte{19}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{20}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Attestation_1: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"21", "22"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "23",
|
||||
CommitteeIndex: "24",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{25}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "26",
|
||||
Root: hexutil.Encode([]byte{27}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "28",
|
||||
Root: hexutil.Encode([]byte{29}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{30}),
|
||||
},
|
||||
Attestation_2: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"31", "32"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "33",
|
||||
CommitteeIndex: "34",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{35}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "36",
|
||||
Root: hexutil.Encode([]byte{37}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "38",
|
||||
Root: hexutil.Encode([]byte{39}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{40}),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func generateAttesterSlashingsProto() []*ethpb.AttesterSlashing {
|
||||
return []*ethpb.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{1, 2},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 3,
|
||||
CommitteeIndex: 4,
|
||||
BeaconBlockRoot: []byte{5},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 6,
|
||||
Root: []byte{7},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 8,
|
||||
Root: []byte{9},
|
||||
},
|
||||
},
|
||||
Signature: []byte{10},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{11, 12},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 13,
|
||||
CommitteeIndex: 14,
|
||||
BeaconBlockRoot: []byte{15},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 16,
|
||||
Root: []byte{17},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 18,
|
||||
Root: []byte{19},
|
||||
},
|
||||
},
|
||||
Signature: []byte{20},
|
||||
},
|
||||
},
|
||||
{
|
||||
Attestation_1: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{21, 22},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 23,
|
||||
CommitteeIndex: 24,
|
||||
BeaconBlockRoot: []byte{25},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 26,
|
||||
Root: []byte{27},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 28,
|
||||
Root: []byte{29},
|
||||
},
|
||||
},
|
||||
Signature: []byte{30},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{31, 32},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 33,
|
||||
CommitteeIndex: 34,
|
||||
BeaconBlockRoot: []byte{35},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 36,
|
||||
Root: []byte{37},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 38,
|
||||
Root: []byte{39},
|
||||
},
|
||||
},
|
||||
Signature: []byte{40},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
167
validator/client/beacon-api/attester_slashings_test.go
Normal file
167
validator/client/beacon-api/attester_slashings_test.go
Normal file
@@ -0,0 +1,167 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v3/validator/client/beacon-api/mock"
|
||||
)
|
||||
|
||||
const getSlashableAttestationsTestEndpoint = "/eth/v1/beacon/pool/attester_slashings"
|
||||
|
||||
func TestGetSlashableAttestations_Valid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
ctx := context.Background()
|
||||
|
||||
jsonAttesterSlashings := &apimiddleware.AttesterSlashingsPoolResponseJson{}
|
||||
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
getSlashableAttestationsTestEndpoint,
|
||||
jsonAttesterSlashings,
|
||||
).Return(
|
||||
nil,
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
apimiddleware.AttesterSlashingsPoolResponseJson{
|
||||
Data: []*apimiddleware.AttesterSlashingJson{
|
||||
{
|
||||
Attestation_1: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"1", "2", "3", "4"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "5",
|
||||
CommitteeIndex: "6",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{7}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "8",
|
||||
Root: hexutil.Encode([]byte{9}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "10",
|
||||
Root: hexutil.Encode([]byte{11}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{12}),
|
||||
},
|
||||
Attestation_2: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"3", "4", "13", "14"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "15",
|
||||
CommitteeIndex: "16",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{17}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "18",
|
||||
Root: hexutil.Encode([]byte{19}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "10",
|
||||
Root: hexutil.Encode([]byte{21}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{22}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Attestation_1: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"23", "24"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "25",
|
||||
CommitteeIndex: "26",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{27}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "28",
|
||||
Root: hexutil.Encode([]byte{29}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "30",
|
||||
Root: hexutil.Encode([]byte{31}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{32}),
|
||||
},
|
||||
Attestation_2: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"33", "34"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "35",
|
||||
CommitteeIndex: "36",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{37}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "38",
|
||||
Root: hexutil.Encode([]byte{39}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "40",
|
||||
Root: hexutil.Encode([]byte{41}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{42}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
slasherClient := beaconApiSlasherClient{jsonRestHandler: jsonRestHandler}
|
||||
|
||||
expectedAttesterSlashingResponse := ðpb.AttesterSlashingResponse{
|
||||
AttesterSlashings: []*ethpb.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{1, 2, 3, 4},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 5,
|
||||
CommitteeIndex: 6,
|
||||
BeaconBlockRoot: []byte{7},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 8,
|
||||
Root: []byte{9},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 10,
|
||||
Root: []byte{11},
|
||||
},
|
||||
},
|
||||
Signature: []byte{12},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{3, 4, 13, 14},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 15,
|
||||
CommitteeIndex: 16,
|
||||
BeaconBlockRoot: []byte{17},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 18,
|
||||
Root: []byte{19},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 10,
|
||||
Root: []byte{21},
|
||||
},
|
||||
},
|
||||
Signature: []byte{22},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
attesterSlashingResponse, err := slasherClient.getSlashableAttestations(ctx, ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{13, 2, 14, 4, 3, 1, 23, 24, 33, 34},
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 10,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedAttesterSlashingResponse, attesterSlashingResponse)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -15,12 +16,30 @@ type beaconApiSlasherClient struct {
|
||||
}
|
||||
|
||||
func (c beaconApiSlasherClient) IsSlashableAttestation(ctx context.Context, in *ethpb.IndexedAttestation) (*ethpb.AttesterSlashingResponse, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.IsSlashableAttestation(ctx, in)
|
||||
grpcResult, err := c.fallbackClient.IsSlashableAttestation(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiSlasherClient.IsSlashableAttestation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiSlasherClientWithFallback.")
|
||||
restResult, err := c.getSlashableAttestations(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
marshalledGrpcResult, err := json.Marshal(grpcResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
marshalledRestResult, err := json.Marshal(restResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Errorf("***************GRPC RESULT: %s", string(marshalledGrpcResult))
|
||||
log.Errorf("***************REST RESULT: %s", string(marshalledRestResult))
|
||||
|
||||
return c.getSlashableAttestations(ctx, in)
|
||||
}
|
||||
|
||||
func (c beaconApiSlasherClient) IsSlashableBlock(ctx context.Context, in *ethpb.SignedBeaconBlockHeader) (*ethpb.ProposerSlashingResponse, error) {
|
||||
|
||||
@@ -89,66 +89,6 @@ func convertProposerSlashingSignedHeaderToProto(signedHeader *apimiddleware.Sign
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertAttesterSlashingsToProto(jsonAttesterSlashings []*apimiddleware.AttesterSlashingJson) ([]*ethpb.AttesterSlashing, error) {
|
||||
attesterSlashings := make([]*ethpb.AttesterSlashing, len(jsonAttesterSlashings))
|
||||
|
||||
for index, jsonAttesterSlashing := range jsonAttesterSlashings {
|
||||
if jsonAttesterSlashing == nil {
|
||||
return nil, errors.Errorf("attester slashing at index `%d` is nil", index)
|
||||
}
|
||||
|
||||
attestation1, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation 1")
|
||||
}
|
||||
|
||||
attestation2, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_2)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation 2")
|
||||
}
|
||||
|
||||
attesterSlashings[index] = ðpb.AttesterSlashing{
|
||||
Attestation_1: attestation1,
|
||||
Attestation_2: attestation2,
|
||||
}
|
||||
}
|
||||
|
||||
return attesterSlashings, nil
|
||||
}
|
||||
|
||||
func convertIndexedAttestationToProto(jsonAttestation *apimiddleware.IndexedAttestationJson) (*ethpb.IndexedAttestation, error) {
|
||||
if jsonAttestation == nil {
|
||||
return nil, errors.New("indexed attestation is nil")
|
||||
}
|
||||
|
||||
attestingIndices := make([]uint64, len(jsonAttestation.AttestingIndices))
|
||||
|
||||
for index, jsonAttestingIndex := range jsonAttestation.AttestingIndices {
|
||||
attestingIndex, err := strconv.ParseUint(jsonAttestingIndex, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse attesting index `%s`", jsonAttestingIndex)
|
||||
}
|
||||
|
||||
attestingIndices[index] = attestingIndex
|
||||
}
|
||||
|
||||
signature, err := hexutil.Decode(jsonAttestation.Signature)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode attestation signature `%s`", jsonAttestation.Signature)
|
||||
}
|
||||
|
||||
attestationData, err := convertAttestationDataToProto(jsonAttestation.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation data")
|
||||
}
|
||||
|
||||
return ðpb.IndexedAttestation{
|
||||
AttestingIndices: attestingIndices,
|
||||
Data: attestationData,
|
||||
Signature: signature,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertCheckpointToProto(jsonCheckpoint *apimiddleware.CheckpointJson) (*ethpb.Checkpoint, error) {
|
||||
if jsonCheckpoint == nil {
|
||||
return nil, errors.New("checkpoint is nil")
|
||||
|
||||
@@ -219,137 +219,6 @@ func TestBeaconBlockProtoHelpers_ConvertProposerSlashingSignedHeaderToProto(t *t
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeaconBlockProtoHelpers_ConvertAttesterSlashingsToProto(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
generateInput func() []*apimiddleware.AttesterSlashingJson
|
||||
expectedResult []*ethpb.AttesterSlashing
|
||||
expectedErrorMessage string
|
||||
}{
|
||||
{
|
||||
name: "nil attester slashing",
|
||||
expectedErrorMessage: "attester slashing at index `0` is nil",
|
||||
generateInput: func() []*apimiddleware.AttesterSlashingJson {
|
||||
return []*apimiddleware.AttesterSlashingJson{
|
||||
nil,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad attestation 1",
|
||||
expectedErrorMessage: "failed to get attestation 1",
|
||||
generateInput: func() []*apimiddleware.AttesterSlashingJson {
|
||||
return []*apimiddleware.AttesterSlashingJson{
|
||||
{
|
||||
Attestation_1: nil,
|
||||
Attestation_2: nil,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad attestation 2",
|
||||
expectedErrorMessage: "failed to get attestation 2",
|
||||
generateInput: func() []*apimiddleware.AttesterSlashingJson {
|
||||
input := generateAttesterSlashings()
|
||||
input[0].Attestation_2 = nil
|
||||
return input
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
generateInput: generateAttesterSlashings,
|
||||
expectedResult: []*ethpb.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{1, 2},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 3,
|
||||
CommitteeIndex: 4,
|
||||
BeaconBlockRoot: []byte{5},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 6,
|
||||
Root: []byte{7},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 8,
|
||||
Root: []byte{9},
|
||||
},
|
||||
},
|
||||
Signature: []byte{10},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{11, 12},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 13,
|
||||
CommitteeIndex: 14,
|
||||
BeaconBlockRoot: []byte{15},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 16,
|
||||
Root: []byte{17},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 18,
|
||||
Root: []byte{19},
|
||||
},
|
||||
},
|
||||
Signature: []byte{20},
|
||||
},
|
||||
},
|
||||
{
|
||||
Attestation_1: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{21, 22},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 23,
|
||||
CommitteeIndex: 24,
|
||||
BeaconBlockRoot: []byte{25},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 26,
|
||||
Root: []byte{27},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 28,
|
||||
Root: []byte{29},
|
||||
},
|
||||
},
|
||||
Signature: []byte{30},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{31, 32},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 33,
|
||||
CommitteeIndex: 34,
|
||||
BeaconBlockRoot: []byte{35},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 36,
|
||||
Root: []byte{37},
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 38,
|
||||
Root: []byte{39},
|
||||
},
|
||||
},
|
||||
Signature: []byte{40},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
result, err := convertAttesterSlashingsToProto(testCase.generateInput())
|
||||
|
||||
if testCase.expectedResult != nil {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, testCase.expectedResult, result)
|
||||
} else if testCase.expectedErrorMessage != "" {
|
||||
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeaconBlockProtoHelpers_ConvertAttestationToProto(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -1143,83 +1012,6 @@ func generateSignedBeaconBlockHeader() *apimiddleware.SignedBeaconBlockHeaderJso
|
||||
}
|
||||
}
|
||||
|
||||
func generateAttesterSlashings() []*apimiddleware.AttesterSlashingJson {
|
||||
return []*apimiddleware.AttesterSlashingJson{
|
||||
{
|
||||
Attestation_1: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"1", "2"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "3",
|
||||
CommitteeIndex: "4",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{5}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "6",
|
||||
Root: hexutil.Encode([]byte{7}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "8",
|
||||
Root: hexutil.Encode([]byte{9}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{10}),
|
||||
},
|
||||
Attestation_2: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"11", "12"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "13",
|
||||
CommitteeIndex: "14",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{15}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "16",
|
||||
Root: hexutil.Encode([]byte{17}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "18",
|
||||
Root: hexutil.Encode([]byte{19}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{20}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Attestation_1: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"21", "22"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "23",
|
||||
CommitteeIndex: "24",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{25}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "26",
|
||||
Root: hexutil.Encode([]byte{27}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "28",
|
||||
Root: hexutil.Encode([]byte{29}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{30}),
|
||||
},
|
||||
Attestation_2: &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"31", "32"},
|
||||
Data: &apimiddleware.AttestationDataJson{
|
||||
Slot: "33",
|
||||
CommitteeIndex: "34",
|
||||
BeaconBlockRoot: hexutil.Encode([]byte{35}),
|
||||
Source: &apimiddleware.CheckpointJson{
|
||||
Epoch: "36",
|
||||
Root: hexutil.Encode([]byte{37}),
|
||||
},
|
||||
Target: &apimiddleware.CheckpointJson{
|
||||
Epoch: "38",
|
||||
Root: hexutil.Encode([]byte{39}),
|
||||
},
|
||||
},
|
||||
Signature: hexutil.Encode([]byte{40}),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func generateIndexedAttestation() *apimiddleware.IndexedAttestationJson {
|
||||
return &apimiddleware.IndexedAttestationJson{
|
||||
AttestingIndices: []string{"1", "2"},
|
||||
|
||||
Reference in New Issue
Block a user