diff --git a/.gitignore b/.gitignore index 36b7b435..8c6d45a3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ dist GeoLite2-ASN.mmdb GeoLite2-City.mmdb __debug_bin +.vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 6b6953d6..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Debug Go", - "type": "go", - "request": "launch", - "mode": "debug", - "program": "${workspaceRoot}", - "args": [ - "cannon" - ], - } - ] -} \ No newline at end of file diff --git a/pkg/cannon/deriver/beacon/eth/v2/beacon_block.go b/pkg/cannon/deriver/beacon/eth/v2/block_identifier.go similarity index 100% rename from pkg/cannon/deriver/beacon/eth/v2/beacon_block.go rename to pkg/cannon/deriver/beacon/eth/v2/block_identifier.go diff --git a/pkg/proto/eth/block.go b/pkg/proto/eth/block.go new file mode 100644 index 00000000..7d27daf5 --- /dev/null +++ b/pkg/proto/eth/block.go @@ -0,0 +1,202 @@ +package eth + +import ( + "fmt" + + "github.com/attestantio/go-eth2-client/spec" + "github.com/attestantio/go-eth2-client/spec/bellatrix" + v1 "github.com/ethpandaops/xatu/pkg/proto/eth/v1" + v2 "github.com/ethpandaops/xatu/pkg/proto/eth/v2" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" +) + +func NewEventBlockV2FromVersionSignedBeaconBlock(block *spec.VersionedSignedBeaconBlock) (*v2.EventBlockV2, error) { + var data *v2.EventBlockV2 + + switch block.Version { + case spec.DataVersionPhase0: + data = NewEventBlockFromPhase0(block) + case spec.DataVersionAltair: + data = NewEventBlockFromAltair(block) + case spec.DataVersionBellatrix: + data = NewEventBlockFromBellatrix(block) + case spec.DataVersionCapella: + data = NewEventBlockFromCapella(block) + default: + return nil, fmt.Errorf("unsupported block version: %v", block.Version) + } + + return data, nil +} + +func getTransactions(data []bellatrix.Transaction) []string { + transactions := []string{} + + for _, tx := range data { + transactions = append(transactions, fmt.Sprintf("0x%x", tx)) + } + + return transactions +} + +func NewEventBlockFromPhase0(block *spec.VersionedSignedBeaconBlock) *v2.EventBlockV2 { + return &v2.EventBlockV2{ + Version: v2.BlockVersion_PHASE0, + Message: &v2.EventBlockV2_Phase0Block{ + Phase0Block: &v1.BeaconBlockV2{ + Slot: &wrapperspb.UInt64Value{Value: uint64(block.Phase0.Message.Slot)}, + ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(block.Phase0.Message.ProposerIndex)}, + ParentRoot: block.Phase0.Message.ParentRoot.String(), + StateRoot: block.Phase0.Message.StateRoot.String(), + Body: &v1.BeaconBlockBody{ + RandaoReveal: block.Phase0.Message.Body.RANDAOReveal.String(), + Eth1Data: &v1.Eth1Data{ + DepositRoot: block.Phase0.Message.Body.ETH1Data.DepositRoot.String(), + DepositCount: block.Phase0.Message.Body.ETH1Data.DepositCount, + BlockHash: fmt.Sprintf("0x%x", block.Phase0.Message.Body.ETH1Data.BlockHash), + }, + Graffiti: fmt.Sprintf("0x%x", block.Phase0.Message.Body.Graffiti[:]), + ProposerSlashings: v1.NewProposerSlashingsFromPhase0(block.Phase0.Message.Body.ProposerSlashings), + AttesterSlashings: v1.NewAttesterSlashingsFromPhase0(block.Phase0.Message.Body.AttesterSlashings), + Attestations: v1.NewAttestationsFromPhase0(block.Phase0.Message.Body.Attestations), + Deposits: v1.NewDepositsFromPhase0(block.Phase0.Message.Body.Deposits), + VoluntaryExits: v1.NewSignedVoluntaryExitsFromPhase0(block.Phase0.Message.Body.VoluntaryExits), + }, + }, + }, + Signature: block.Phase0.Signature.String(), + } +} + +func NewEventBlockFromAltair(block *spec.VersionedSignedBeaconBlock) *v2.EventBlockV2 { + return &v2.EventBlockV2{ + Version: v2.BlockVersion_ALTAIR, + Message: &v2.EventBlockV2_AltairBlock{ + AltairBlock: &v2.BeaconBlockAltairV2{ + Slot: &wrapperspb.UInt64Value{Value: uint64(block.Altair.Message.Slot)}, + ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(block.Altair.Message.ProposerIndex)}, + ParentRoot: block.Altair.Message.ParentRoot.String(), + StateRoot: block.Altair.Message.StateRoot.String(), + Body: &v2.BeaconBlockBodyAltairV2{ + RandaoReveal: block.Altair.Message.Body.RANDAOReveal.String(), + Eth1Data: &v1.Eth1Data{ + DepositRoot: block.Altair.Message.Body.ETH1Data.DepositRoot.String(), + DepositCount: block.Altair.Message.Body.ETH1Data.DepositCount, + BlockHash: fmt.Sprintf("0x%x", block.Altair.Message.Body.ETH1Data.BlockHash), + }, + Graffiti: fmt.Sprintf("0x%x", block.Altair.Message.Body.Graffiti[:]), + ProposerSlashings: v1.NewProposerSlashingsFromPhase0(block.Altair.Message.Body.ProposerSlashings), + AttesterSlashings: v1.NewAttesterSlashingsFromPhase0(block.Altair.Message.Body.AttesterSlashings), + Attestations: v1.NewAttestationsFromPhase0(block.Altair.Message.Body.Attestations), + Deposits: v1.NewDepositsFromPhase0(block.Altair.Message.Body.Deposits), + VoluntaryExits: v1.NewSignedVoluntaryExitsFromPhase0(block.Altair.Message.Body.VoluntaryExits), + SyncAggregate: &v1.SyncAggregate{ + SyncCommitteeBits: fmt.Sprintf("0x%x", block.Altair.Message.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: block.Altair.Message.Body.SyncAggregate.SyncCommitteeSignature.String(), + }, + }, + }, + }, + Signature: block.Altair.Signature.String(), + } +} + +func NewEventBlockFromBellatrix(block *spec.VersionedSignedBeaconBlock) *v2.EventBlockV2 { + return &v2.EventBlockV2{ + Version: v2.BlockVersion_BELLATRIX, + Message: &v2.EventBlockV2_BellatrixBlock{ + BellatrixBlock: &v2.BeaconBlockBellatrixV2{ + Slot: &wrapperspb.UInt64Value{Value: uint64(block.Bellatrix.Message.Slot)}, + ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(block.Bellatrix.Message.ProposerIndex)}, + ParentRoot: block.Bellatrix.Message.ParentRoot.String(), + StateRoot: block.Bellatrix.Message.StateRoot.String(), + Body: &v2.BeaconBlockBodyBellatrixV2{ + RandaoReveal: block.Bellatrix.Message.Body.RANDAOReveal.String(), + Eth1Data: &v1.Eth1Data{ + DepositRoot: block.Bellatrix.Message.Body.ETH1Data.DepositRoot.String(), + DepositCount: block.Bellatrix.Message.Body.ETH1Data.DepositCount, + BlockHash: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ETH1Data.BlockHash), + }, + Graffiti: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.Graffiti[:]), + ProposerSlashings: v1.NewProposerSlashingsFromPhase0(block.Bellatrix.Message.Body.ProposerSlashings), + AttesterSlashings: v1.NewAttesterSlashingsFromPhase0(block.Bellatrix.Message.Body.AttesterSlashings), + Attestations: v1.NewAttestationsFromPhase0(block.Bellatrix.Message.Body.Attestations), + Deposits: v1.NewDepositsFromPhase0(block.Bellatrix.Message.Body.Deposits), + VoluntaryExits: v1.NewSignedVoluntaryExitsFromPhase0(block.Bellatrix.Message.Body.VoluntaryExits), + SyncAggregate: &v1.SyncAggregate{ + SyncCommitteeBits: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: block.Bellatrix.Message.Body.SyncAggregate.SyncCommitteeSignature.String(), + }, + ExecutionPayload: &v1.ExecutionPayloadV2{ + ParentHash: block.Bellatrix.Message.Body.ExecutionPayload.ParentHash.String(), + FeeRecipient: block.Bellatrix.Message.Body.ExecutionPayload.FeeRecipient.String(), + StateRoot: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ExecutionPayload.StateRoot[:]), + ReceiptsRoot: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ExecutionPayload.ReceiptsRoot[:]), + LogsBloom: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ExecutionPayload.LogsBloom[:]), + PrevRandao: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ExecutionPayload.PrevRandao[:]), + BlockNumber: &wrapperspb.UInt64Value{Value: block.Bellatrix.Message.Body.ExecutionPayload.BlockNumber}, + GasLimit: &wrapperspb.UInt64Value{Value: block.Bellatrix.Message.Body.ExecutionPayload.GasLimit}, + GasUsed: &wrapperspb.UInt64Value{Value: block.Bellatrix.Message.Body.ExecutionPayload.GasUsed}, + Timestamp: &wrapperspb.UInt64Value{Value: block.Bellatrix.Message.Body.ExecutionPayload.Timestamp}, + ExtraData: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ExecutionPayload.ExtraData), + BaseFeePerGas: fmt.Sprintf("0x%x", block.Bellatrix.Message.Body.ExecutionPayload.BaseFeePerGas[:]), + BlockHash: block.Bellatrix.Message.Body.ExecutionPayload.BlockHash.String(), + Transactions: getTransactions(block.Bellatrix.Message.Body.ExecutionPayload.Transactions), + }, + }, + }, + }, + Signature: block.Bellatrix.Signature.String(), + } +} + +func NewEventBlockFromCapella(block *spec.VersionedSignedBeaconBlock) *v2.EventBlockV2 { + return &v2.EventBlockV2{ + Version: v2.BlockVersion_CAPELLA, + Message: &v2.EventBlockV2_CapellaBlock{ + CapellaBlock: &v2.BeaconBlockCapellaV2{ + Slot: &wrapperspb.UInt64Value{Value: uint64(block.Capella.Message.Slot)}, + ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(block.Capella.Message.ProposerIndex)}, + ParentRoot: block.Capella.Message.ParentRoot.String(), + StateRoot: block.Capella.Message.StateRoot.String(), + Body: &v2.BeaconBlockBodyCapellaV2{ + RandaoReveal: block.Capella.Message.Body.RANDAOReveal.String(), + Eth1Data: &v1.Eth1Data{ + DepositRoot: block.Capella.Message.Body.ETH1Data.DepositRoot.String(), + DepositCount: block.Capella.Message.Body.ETH1Data.DepositCount, + BlockHash: fmt.Sprintf("0x%x", block.Capella.Message.Body.ETH1Data.BlockHash), + }, + Graffiti: fmt.Sprintf("0x%x", block.Capella.Message.Body.Graffiti[:]), + ProposerSlashings: v1.NewProposerSlashingsFromPhase0(block.Capella.Message.Body.ProposerSlashings), + AttesterSlashings: v1.NewAttesterSlashingsFromPhase0(block.Capella.Message.Body.AttesterSlashings), + Attestations: v1.NewAttestationsFromPhase0(block.Capella.Message.Body.Attestations), + Deposits: v1.NewDepositsFromPhase0(block.Capella.Message.Body.Deposits), + VoluntaryExits: v1.NewSignedVoluntaryExitsFromPhase0(block.Capella.Message.Body.VoluntaryExits), + SyncAggregate: &v1.SyncAggregate{ + SyncCommitteeBits: fmt.Sprintf("0x%x", block.Capella.Message.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: block.Capella.Message.Body.SyncAggregate.SyncCommitteeSignature.String(), + }, + ExecutionPayload: &v1.ExecutionPayloadCapellaV2{ + ParentHash: block.Capella.Message.Body.ExecutionPayload.ParentHash.String(), + FeeRecipient: block.Capella.Message.Body.ExecutionPayload.FeeRecipient.String(), + StateRoot: fmt.Sprintf("0x%x", block.Capella.Message.Body.ExecutionPayload.StateRoot[:]), + ReceiptsRoot: fmt.Sprintf("0x%x", block.Capella.Message.Body.ExecutionPayload.ReceiptsRoot[:]), + LogsBloom: fmt.Sprintf("0x%x", block.Capella.Message.Body.ExecutionPayload.LogsBloom[:]), + PrevRandao: fmt.Sprintf("0x%x", block.Capella.Message.Body.ExecutionPayload.PrevRandao[:]), + BlockNumber: &wrapperspb.UInt64Value{Value: block.Capella.Message.Body.ExecutionPayload.BlockNumber}, + GasLimit: &wrapperspb.UInt64Value{Value: block.Capella.Message.Body.ExecutionPayload.GasLimit}, + GasUsed: &wrapperspb.UInt64Value{Value: block.Capella.Message.Body.ExecutionPayload.GasUsed}, + Timestamp: &wrapperspb.UInt64Value{Value: block.Capella.Message.Body.ExecutionPayload.Timestamp}, + ExtraData: fmt.Sprintf("0x%x", block.Capella.Message.Body.ExecutionPayload.ExtraData), + BaseFeePerGas: fmt.Sprintf("0x%x", block.Capella.Message.Body.ExecutionPayload.BaseFeePerGas[:]), + BlockHash: block.Capella.Message.Body.ExecutionPayload.BlockHash.String(), + Transactions: getTransactions(block.Capella.Message.Body.ExecutionPayload.Transactions), + Withdrawals: v1.NewWithdrawalsFromCapella(block.Capella.Message.Body.ExecutionPayload.Withdrawals), + }, + BlsToExecutionChanges: v2.NewBLSToExecutionChangesFromCapella(block.Capella.Message.Body.BLSToExecutionChanges), + }, + }, + }, + Signature: block.Capella.Signature.String(), + } +} diff --git a/pkg/proto/eth/v1/conversion.go b/pkg/proto/eth/v1/conversion.go index 19d25b16..dbbf4fb6 100644 --- a/pkg/proto/eth/v1/conversion.go +++ b/pkg/proto/eth/v1/conversion.go @@ -4,7 +4,9 @@ import ( "encoding/hex" "fmt" + "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/phase0" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" ) func RootAsString(root phase0.Root) string { @@ -52,3 +54,183 @@ func TrimmedString(s string) string { return s[:5] + "..." + s[len(s)-5:] } + +func NewProposerSlashingsFromPhase0(data []*phase0.ProposerSlashing) []*ProposerSlashing { + slashings := []*ProposerSlashing{} + + if data != nil { + return slashings + } + + for _, slashing := range data { + slashings = append(slashings, &ProposerSlashing{ + SignedHeader_1: &SignedBeaconBlockHeader{ + Message: &BeaconBlockHeader{ + Slot: uint64(slashing.SignedHeader1.Message.Slot), + ProposerIndex: uint64(slashing.SignedHeader1.Message.ProposerIndex), + ParentRoot: slashing.SignedHeader1.Message.ParentRoot.String(), + StateRoot: slashing.SignedHeader1.Message.StateRoot.String(), + BodyRoot: slashing.SignedHeader1.Message.BodyRoot.String(), + }, + Signature: slashing.SignedHeader1.Signature.String(), + }, + SignedHeader_2: &SignedBeaconBlockHeader{ + Message: &BeaconBlockHeader{ + Slot: uint64(slashing.SignedHeader2.Message.Slot), + ProposerIndex: uint64(slashing.SignedHeader2.Message.ProposerIndex), + ParentRoot: slashing.SignedHeader2.Message.ParentRoot.String(), + StateRoot: slashing.SignedHeader2.Message.StateRoot.String(), + BodyRoot: slashing.SignedHeader2.Message.BodyRoot.String(), + }, + Signature: slashing.SignedHeader2.Signature.String(), + }, + }) + } + + return slashings +} + +func NewAttesterSlashingsFromPhase0(data []*phase0.AttesterSlashing) []*AttesterSlashing { + slashings := []*AttesterSlashing{} + + if data == nil { + return slashings + } + + for _, slashing := range data { + slashings = append(slashings, &AttesterSlashing{ + Attestation_1: &IndexedAttestation{ + AttestingIndices: slashing.Attestation1.AttestingIndices, + Data: &AttestationData{ + Slot: uint64(slashing.Attestation1.Data.Slot), + Index: uint64(slashing.Attestation1.Data.Index), + BeaconBlockRoot: slashing.Attestation1.Data.BeaconBlockRoot.String(), + Source: &Checkpoint{ + Epoch: uint64(slashing.Attestation1.Data.Source.Epoch), + Root: slashing.Attestation1.Data.Source.Root.String(), + }, + Target: &Checkpoint{ + Epoch: uint64(slashing.Attestation1.Data.Target.Epoch), + Root: slashing.Attestation1.Data.Target.Root.String(), + }, + }, + Signature: slashing.Attestation1.Signature.String(), + }, + Attestation_2: &IndexedAttestation{ + AttestingIndices: slashing.Attestation2.AttestingIndices, + Data: &AttestationData{ + Slot: uint64(slashing.Attestation2.Data.Slot), + Index: uint64(slashing.Attestation2.Data.Index), + BeaconBlockRoot: slashing.Attestation2.Data.BeaconBlockRoot.String(), + Source: &Checkpoint{ + Epoch: uint64(slashing.Attestation2.Data.Source.Epoch), + Root: slashing.Attestation2.Data.Source.Root.String(), + }, + Target: &Checkpoint{ + Epoch: uint64(slashing.Attestation2.Data.Target.Epoch), + Root: slashing.Attestation2.Data.Target.Root.String(), + }, + }, + Signature: slashing.Attestation2.Signature.String(), + }, + }) + } + + return slashings +} + +func NewAttestationsFromPhase0(data []*phase0.Attestation) []*Attestation { + attestations := []*Attestation{} + + if data == nil { + return attestations + } + + for _, attestation := range data { + attestations = append(attestations, &Attestation{ + AggregationBits: fmt.Sprintf("0x%x", attestation.AggregationBits), + Data: &AttestationData{ + Slot: uint64(attestation.Data.Slot), + Index: uint64(attestation.Data.Index), + BeaconBlockRoot: attestation.Data.BeaconBlockRoot.String(), + Source: &Checkpoint{ + Epoch: uint64(attestation.Data.Source.Epoch), + Root: attestation.Data.Source.Root.String(), + }, + Target: &Checkpoint{ + Epoch: uint64(attestation.Data.Target.Epoch), + Root: attestation.Data.Target.Root.String(), + }, + }, + Signature: attestation.Signature.String(), + }) + } + + return attestations +} + +func NewDepositsFromPhase0(data []*phase0.Deposit) []*Deposit { + deposits := []*Deposit{} + + if data == nil { + return deposits + } + + for _, deposit := range data { + proof := []string{} + for _, p := range deposit.Proof { + proof = append(proof, fmt.Sprintf("0x%x", p)) + } + + deposits = append(deposits, &Deposit{ + Proof: proof, + Data: &Deposit_Data{ + Pubkey: deposit.Data.PublicKey.String(), + WithdrawalCredentials: fmt.Sprintf("0x%x", deposit.Data.WithdrawalCredentials), + Amount: uint64(deposit.Data.Amount), + Signature: deposit.Data.Signature.String(), + }, + }) + } + + return deposits +} + +func NewSignedVoluntaryExitsFromPhase0(data []*phase0.SignedVoluntaryExit) []*SignedVoluntaryExit { + exits := []*SignedVoluntaryExit{} + + if data == nil { + return exits + } + + for _, exit := range data { + exits = append(exits, &SignedVoluntaryExit{ + Message: &VoluntaryExit{ + Epoch: uint64(exit.Message.Epoch), + ValidatorIndex: uint64(exit.Message.ValidatorIndex), + }, + Signature: exit.Signature.String(), + }) + } + + return exits +} + +func NewWithdrawalsFromCapella(data []*capella.Withdrawal) []*WithdrawalV2 { + withdrawals := []*WithdrawalV2{} + + if data == nil { + return withdrawals + } + + for _, withdrawal := range data { + withdrawals = append(withdrawals, &WithdrawalV2{ + Index: &wrapperspb.UInt64Value{Value: uint64(withdrawal.Index)}, + ValidatorIndex: &wrapperspb.UInt64Value{Value: uint64(withdrawal.ValidatorIndex)}, + Address: withdrawal.Address.String(), + Amount: &wrapperspb.UInt64Value{Value: uint64(withdrawal.Amount)}, + }) + } + + return withdrawals +} diff --git a/pkg/proto/eth/v2/conversion.go b/pkg/proto/eth/v2/conversion.go new file mode 100644 index 00000000..7b7c2352 --- /dev/null +++ b/pkg/proto/eth/v2/conversion.go @@ -0,0 +1,24 @@ +package v2 + +import "github.com/attestantio/go-eth2-client/spec/capella" + +func NewBLSToExecutionChangesFromCapella(data []*capella.SignedBLSToExecutionChange) []*SignedBLSToExecutionChange { + changes := []*SignedBLSToExecutionChange{} + + if data == nil { + return changes + } + + for _, change := range data { + changes = append(changes, &SignedBLSToExecutionChange{ + Message: &BLSToExecutionChange{ + ValidatorIndex: uint64(change.Message.ValidatorIndex), + FromBlsPubkey: change.Message.FromBLSPubkey.String(), + ToExecutionAddress: change.Message.ToExecutionAddress.String(), + }, + Signature: change.Signature.String(), + }) + } + + return changes +} diff --git a/pkg/sentry/ethereum/beacon.go b/pkg/sentry/ethereum/beacon.go index 345e9734..5c5becf3 100644 --- a/pkg/sentry/ethereum/beacon.go +++ b/pkg/sentry/ethereum/beacon.go @@ -27,7 +27,8 @@ type BeaconNode struct { func NewBeaconNode(ctx context.Context, name string, config *Config, log logrus.FieldLogger) (*BeaconNode, error) { opts := *beacon. DefaultOptions(). - EnableDefaultBeaconSubscription() + EnableDefaultBeaconSubscription(). + DisablePrometheusMetrics() opts.HealthCheck.Interval.Duration = time.Second * 3 opts.HealthCheck.SuccessfulResponses = 1 diff --git a/pkg/sentry/event/beacon/eth/v2/beacon_block.go b/pkg/sentry/event/beacon/eth/v2/beacon_block.go index eb6dbd2e..c053305b 100644 --- a/pkg/sentry/event/beacon/eth/v2/beacon_block.go +++ b/pkg/sentry/event/beacon/eth/v2/beacon_block.go @@ -6,10 +6,7 @@ import ( "time" "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/phase0" - xatuethv1 "github.com/ethpandaops/xatu/pkg/proto/eth/v1" + "github.com/ethpandaops/xatu/pkg/proto/eth" xatuethv2 "github.com/ethpandaops/xatu/pkg/proto/eth/v2" "github.com/ethpandaops/xatu/pkg/proto/xatu" "github.com/ethpandaops/xatu/pkg/sentry/ethereum" @@ -50,19 +47,9 @@ func NewBeaconBlock(log logrus.FieldLogger, blockRoot string, event *spec.Versio } func (e *BeaconBlock) Decorate(ctx context.Context) (*xatu.DecoratedEvent, error) { - var data *xatuethv2.EventBlockV2 - - switch e.event.Version { - case spec.DataVersionPhase0: - data = e.getPhase0Data() - case spec.DataVersionAltair: - data = e.getAltairData() - case spec.DataVersionBellatrix: - data = e.getBellatrixData() - case spec.DataVersionCapella: - data = e.getCapellaData() - default: - return nil, fmt.Errorf("unsupported block version: %v", e.event.Version) + data, err := eth.NewEventBlockV2FromVersionSignedBeaconBlock(e.event) + if err != nil { + return nil, err } decoratedEvent := &xatu.DecoratedEvent{ @@ -136,379 +123,6 @@ func (e *BeaconBlock) ShouldIgnore(ctx context.Context) (bool, error) { return false, nil } -func getProposerSlashings(data []*phase0.ProposerSlashing) []*xatuethv1.ProposerSlashing { - slashings := []*xatuethv1.ProposerSlashing{} - - if data != nil { - return slashings - } - - for _, slashing := range data { - slashings = append(slashings, &xatuethv1.ProposerSlashing{ - SignedHeader_1: &xatuethv1.SignedBeaconBlockHeader{ - Message: &xatuethv1.BeaconBlockHeader{ - Slot: uint64(slashing.SignedHeader1.Message.Slot), - ProposerIndex: uint64(slashing.SignedHeader1.Message.ProposerIndex), - ParentRoot: slashing.SignedHeader1.Message.ParentRoot.String(), - StateRoot: slashing.SignedHeader1.Message.StateRoot.String(), - BodyRoot: slashing.SignedHeader1.Message.BodyRoot.String(), - }, - Signature: slashing.SignedHeader1.Signature.String(), - }, - SignedHeader_2: &xatuethv1.SignedBeaconBlockHeader{ - Message: &xatuethv1.BeaconBlockHeader{ - Slot: uint64(slashing.SignedHeader2.Message.Slot), - ProposerIndex: uint64(slashing.SignedHeader2.Message.ProposerIndex), - ParentRoot: slashing.SignedHeader2.Message.ParentRoot.String(), - StateRoot: slashing.SignedHeader2.Message.StateRoot.String(), - BodyRoot: slashing.SignedHeader2.Message.BodyRoot.String(), - }, - Signature: slashing.SignedHeader2.Signature.String(), - }, - }) - } - - return slashings -} - -func getAttesterSlashings(data []*phase0.AttesterSlashing) []*xatuethv1.AttesterSlashing { - slashings := []*xatuethv1.AttesterSlashing{} - - if data == nil { - return slashings - } - - for _, slashing := range data { - slashings = append(slashings, &xatuethv1.AttesterSlashing{ - Attestation_1: &xatuethv1.IndexedAttestation{ - AttestingIndices: slashing.Attestation1.AttestingIndices, - Data: &xatuethv1.AttestationData{ - Slot: uint64(slashing.Attestation1.Data.Slot), - Index: uint64(slashing.Attestation1.Data.Index), - BeaconBlockRoot: slashing.Attestation1.Data.BeaconBlockRoot.String(), - Source: &xatuethv1.Checkpoint{ - Epoch: uint64(slashing.Attestation1.Data.Source.Epoch), - Root: slashing.Attestation1.Data.Source.Root.String(), - }, - Target: &xatuethv1.Checkpoint{ - Epoch: uint64(slashing.Attestation1.Data.Target.Epoch), - Root: slashing.Attestation1.Data.Target.Root.String(), - }, - }, - Signature: slashing.Attestation1.Signature.String(), - }, - Attestation_2: &xatuethv1.IndexedAttestation{ - AttestingIndices: slashing.Attestation2.AttestingIndices, - Data: &xatuethv1.AttestationData{ - Slot: uint64(slashing.Attestation2.Data.Slot), - Index: uint64(slashing.Attestation2.Data.Index), - BeaconBlockRoot: slashing.Attestation2.Data.BeaconBlockRoot.String(), - Source: &xatuethv1.Checkpoint{ - Epoch: uint64(slashing.Attestation2.Data.Source.Epoch), - Root: slashing.Attestation2.Data.Source.Root.String(), - }, - Target: &xatuethv1.Checkpoint{ - Epoch: uint64(slashing.Attestation2.Data.Target.Epoch), - Root: slashing.Attestation2.Data.Target.Root.String(), - }, - }, - Signature: slashing.Attestation2.Signature.String(), - }, - }) - } - - return slashings -} - -func getAttestations(data []*phase0.Attestation) []*xatuethv1.Attestation { - attestations := []*xatuethv1.Attestation{} - - if data == nil { - return attestations - } - - for _, attestation := range data { - attestations = append(attestations, &xatuethv1.Attestation{ - AggregationBits: fmt.Sprintf("0x%x", attestation.AggregationBits), - Data: &xatuethv1.AttestationData{ - Slot: uint64(attestation.Data.Slot), - Index: uint64(attestation.Data.Index), - BeaconBlockRoot: attestation.Data.BeaconBlockRoot.String(), - Source: &xatuethv1.Checkpoint{ - Epoch: uint64(attestation.Data.Source.Epoch), - Root: attestation.Data.Source.Root.String(), - }, - Target: &xatuethv1.Checkpoint{ - Epoch: uint64(attestation.Data.Target.Epoch), - Root: attestation.Data.Target.Root.String(), - }, - }, - Signature: attestation.Signature.String(), - }) - } - - return attestations -} - -func getDeposits(data []*phase0.Deposit) []*xatuethv1.Deposit { - deposits := []*xatuethv1.Deposit{} - - if data == nil { - return deposits - } - - for _, deposit := range data { - proof := []string{} - for _, p := range deposit.Proof { - proof = append(proof, fmt.Sprintf("0x%x", p)) - } - - deposits = append(deposits, &xatuethv1.Deposit{ - Proof: proof, - Data: &xatuethv1.Deposit_Data{ - Pubkey: deposit.Data.PublicKey.String(), - WithdrawalCredentials: fmt.Sprintf("0x%x", deposit.Data.WithdrawalCredentials), - Amount: uint64(deposit.Data.Amount), - Signature: deposit.Data.Signature.String(), - }, - }) - } - - return deposits -} - -func getVoluntaryExits(data []*phase0.SignedVoluntaryExit) []*xatuethv1.SignedVoluntaryExit { - exits := []*xatuethv1.SignedVoluntaryExit{} - - if data == nil { - return exits - } - - for _, exit := range data { - exits = append(exits, &xatuethv1.SignedVoluntaryExit{ - Message: &xatuethv1.VoluntaryExit{ - Epoch: uint64(exit.Message.Epoch), - ValidatorIndex: uint64(exit.Message.ValidatorIndex), - }, - Signature: exit.Signature.String(), - }) - } - - return exits -} - -func getTransactions(data []bellatrix.Transaction) []string { - transactions := []string{} - - for _, tx := range data { - transactions = append(transactions, fmt.Sprintf("0x%x", tx)) - } - - return transactions -} - -func getBlsToExecutionChanges(data []*capella.SignedBLSToExecutionChange) []*xatuethv2.SignedBLSToExecutionChange { - changes := []*xatuethv2.SignedBLSToExecutionChange{} - - if data == nil { - return changes - } - - for _, change := range data { - changes = append(changes, &xatuethv2.SignedBLSToExecutionChange{ - Message: &xatuethv2.BLSToExecutionChange{ - ValidatorIndex: uint64(change.Message.ValidatorIndex), - FromBlsPubkey: change.Message.FromBLSPubkey.String(), - ToExecutionAddress: change.Message.ToExecutionAddress.String(), - }, - Signature: change.Signature.String(), - }) - } - - return changes -} - -func getWithdrawals(data []*capella.Withdrawal) []*xatuethv1.WithdrawalV2 { - withdrawals := []*xatuethv1.WithdrawalV2{} - - if data == nil { - return withdrawals - } - - for _, withdrawal := range data { - withdrawals = append(withdrawals, &xatuethv1.WithdrawalV2{ - Index: &wrapperspb.UInt64Value{Value: uint64(withdrawal.Index)}, - ValidatorIndex: &wrapperspb.UInt64Value{Value: uint64(withdrawal.ValidatorIndex)}, - Address: withdrawal.Address.String(), - Amount: &wrapperspb.UInt64Value{Value: uint64(withdrawal.Amount)}, - }) - } - - return withdrawals -} - -func (e *BeaconBlock) getPhase0Data() *xatuethv2.EventBlockV2 { - return &xatuethv2.EventBlockV2{ - Version: xatuethv2.BlockVersion_PHASE0, - Message: &xatuethv2.EventBlockV2_Phase0Block{ - Phase0Block: &xatuethv1.BeaconBlockV2{ - Slot: &wrapperspb.UInt64Value{Value: uint64(e.event.Phase0.Message.Slot)}, - ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(e.event.Phase0.Message.ProposerIndex)}, - ParentRoot: e.event.Phase0.Message.ParentRoot.String(), - StateRoot: e.event.Phase0.Message.StateRoot.String(), - Body: &xatuethv1.BeaconBlockBody{ - RandaoReveal: e.event.Phase0.Message.Body.RANDAOReveal.String(), - Eth1Data: &xatuethv1.Eth1Data{ - DepositRoot: e.event.Phase0.Message.Body.ETH1Data.DepositRoot.String(), - DepositCount: e.event.Phase0.Message.Body.ETH1Data.DepositCount, - BlockHash: fmt.Sprintf("0x%x", e.event.Phase0.Message.Body.ETH1Data.BlockHash), - }, - Graffiti: fmt.Sprintf("0x%x", e.event.Phase0.Message.Body.Graffiti[:]), - ProposerSlashings: getProposerSlashings(e.event.Phase0.Message.Body.ProposerSlashings), - AttesterSlashings: getAttesterSlashings(e.event.Phase0.Message.Body.AttesterSlashings), - Attestations: getAttestations(e.event.Phase0.Message.Body.Attestations), - Deposits: getDeposits(e.event.Phase0.Message.Body.Deposits), - VoluntaryExits: getVoluntaryExits(e.event.Phase0.Message.Body.VoluntaryExits), - }, - }, - }, - Signature: e.event.Phase0.Signature.String(), - } -} - -func (e *BeaconBlock) getAltairData() *xatuethv2.EventBlockV2 { - return &xatuethv2.EventBlockV2{ - Version: xatuethv2.BlockVersion_ALTAIR, - Message: &xatuethv2.EventBlockV2_AltairBlock{ - AltairBlock: &xatuethv2.BeaconBlockAltairV2{ - Slot: &wrapperspb.UInt64Value{Value: uint64(e.event.Altair.Message.Slot)}, - ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(e.event.Altair.Message.ProposerIndex)}, - ParentRoot: e.event.Altair.Message.ParentRoot.String(), - StateRoot: e.event.Altair.Message.StateRoot.String(), - Body: &xatuethv2.BeaconBlockBodyAltairV2{ - RandaoReveal: e.event.Altair.Message.Body.RANDAOReveal.String(), - Eth1Data: &xatuethv1.Eth1Data{ - DepositRoot: e.event.Altair.Message.Body.ETH1Data.DepositRoot.String(), - DepositCount: e.event.Altair.Message.Body.ETH1Data.DepositCount, - BlockHash: fmt.Sprintf("0x%x", e.event.Altair.Message.Body.ETH1Data.BlockHash), - }, - Graffiti: fmt.Sprintf("0x%x", e.event.Altair.Message.Body.Graffiti[:]), - ProposerSlashings: getProposerSlashings(e.event.Altair.Message.Body.ProposerSlashings), - AttesterSlashings: getAttesterSlashings(e.event.Altair.Message.Body.AttesterSlashings), - Attestations: getAttestations(e.event.Altair.Message.Body.Attestations), - Deposits: getDeposits(e.event.Altair.Message.Body.Deposits), - VoluntaryExits: getVoluntaryExits(e.event.Altair.Message.Body.VoluntaryExits), - SyncAggregate: &xatuethv1.SyncAggregate{ - SyncCommitteeBits: fmt.Sprintf("0x%x", e.event.Altair.Message.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: e.event.Altair.Message.Body.SyncAggregate.SyncCommitteeSignature.String(), - }, - }, - }, - }, - Signature: e.event.Altair.Signature.String(), - } -} - -func (e *BeaconBlock) getBellatrixData() *xatuethv2.EventBlockV2 { - return &xatuethv2.EventBlockV2{ - Version: xatuethv2.BlockVersion_BELLATRIX, - Message: &xatuethv2.EventBlockV2_BellatrixBlock{ - BellatrixBlock: &xatuethv2.BeaconBlockBellatrixV2{ - Slot: &wrapperspb.UInt64Value{Value: uint64(e.event.Bellatrix.Message.Slot)}, - ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(e.event.Bellatrix.Message.ProposerIndex)}, - ParentRoot: e.event.Bellatrix.Message.ParentRoot.String(), - StateRoot: e.event.Bellatrix.Message.StateRoot.String(), - Body: &xatuethv2.BeaconBlockBodyBellatrixV2{ - RandaoReveal: e.event.Bellatrix.Message.Body.RANDAOReveal.String(), - Eth1Data: &xatuethv1.Eth1Data{ - DepositRoot: e.event.Bellatrix.Message.Body.ETH1Data.DepositRoot.String(), - DepositCount: e.event.Bellatrix.Message.Body.ETH1Data.DepositCount, - BlockHash: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ETH1Data.BlockHash), - }, - Graffiti: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.Graffiti[:]), - ProposerSlashings: getProposerSlashings(e.event.Bellatrix.Message.Body.ProposerSlashings), - AttesterSlashings: getAttesterSlashings(e.event.Bellatrix.Message.Body.AttesterSlashings), - Attestations: getAttestations(e.event.Bellatrix.Message.Body.Attestations), - Deposits: getDeposits(e.event.Bellatrix.Message.Body.Deposits), - VoluntaryExits: getVoluntaryExits(e.event.Bellatrix.Message.Body.VoluntaryExits), - SyncAggregate: &xatuethv1.SyncAggregate{ - SyncCommitteeBits: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: e.event.Bellatrix.Message.Body.SyncAggregate.SyncCommitteeSignature.String(), - }, - ExecutionPayload: &xatuethv1.ExecutionPayloadV2{ - ParentHash: e.event.Bellatrix.Message.Body.ExecutionPayload.ParentHash.String(), - FeeRecipient: e.event.Bellatrix.Message.Body.ExecutionPayload.FeeRecipient.String(), - StateRoot: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ExecutionPayload.StateRoot[:]), - ReceiptsRoot: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ExecutionPayload.ReceiptsRoot[:]), - LogsBloom: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ExecutionPayload.LogsBloom[:]), - PrevRandao: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ExecutionPayload.PrevRandao[:]), - BlockNumber: &wrapperspb.UInt64Value{Value: e.event.Bellatrix.Message.Body.ExecutionPayload.BlockNumber}, - GasLimit: &wrapperspb.UInt64Value{Value: e.event.Bellatrix.Message.Body.ExecutionPayload.GasLimit}, - GasUsed: &wrapperspb.UInt64Value{Value: e.event.Bellatrix.Message.Body.ExecutionPayload.GasUsed}, - Timestamp: &wrapperspb.UInt64Value{Value: e.event.Bellatrix.Message.Body.ExecutionPayload.Timestamp}, - ExtraData: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ExecutionPayload.ExtraData), - BaseFeePerGas: fmt.Sprintf("0x%x", e.event.Bellatrix.Message.Body.ExecutionPayload.BaseFeePerGas[:]), - BlockHash: e.event.Bellatrix.Message.Body.ExecutionPayload.BlockHash.String(), - Transactions: getTransactions(e.event.Bellatrix.Message.Body.ExecutionPayload.Transactions), - }, - }, - }, - }, - Signature: e.event.Bellatrix.Signature.String(), - } -} - -func (e *BeaconBlock) getCapellaData() *xatuethv2.EventBlockV2 { - return &xatuethv2.EventBlockV2{ - Version: xatuethv2.BlockVersion_CAPELLA, - Message: &xatuethv2.EventBlockV2_CapellaBlock{ - CapellaBlock: &xatuethv2.BeaconBlockCapellaV2{ - Slot: &wrapperspb.UInt64Value{Value: uint64(e.event.Capella.Message.Slot)}, - ProposerIndex: &wrapperspb.UInt64Value{Value: uint64(e.event.Capella.Message.ProposerIndex)}, - ParentRoot: e.event.Capella.Message.ParentRoot.String(), - StateRoot: e.event.Capella.Message.StateRoot.String(), - Body: &xatuethv2.BeaconBlockBodyCapellaV2{ - RandaoReveal: e.event.Capella.Message.Body.RANDAOReveal.String(), - Eth1Data: &xatuethv1.Eth1Data{ - DepositRoot: e.event.Capella.Message.Body.ETH1Data.DepositRoot.String(), - DepositCount: e.event.Capella.Message.Body.ETH1Data.DepositCount, - BlockHash: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ETH1Data.BlockHash), - }, - Graffiti: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.Graffiti[:]), - ProposerSlashings: getProposerSlashings(e.event.Capella.Message.Body.ProposerSlashings), - AttesterSlashings: getAttesterSlashings(e.event.Capella.Message.Body.AttesterSlashings), - Attestations: getAttestations(e.event.Capella.Message.Body.Attestations), - Deposits: getDeposits(e.event.Capella.Message.Body.Deposits), - VoluntaryExits: getVoluntaryExits(e.event.Capella.Message.Body.VoluntaryExits), - SyncAggregate: &xatuethv1.SyncAggregate{ - SyncCommitteeBits: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: e.event.Capella.Message.Body.SyncAggregate.SyncCommitteeSignature.String(), - }, - ExecutionPayload: &xatuethv1.ExecutionPayloadCapellaV2{ - ParentHash: e.event.Capella.Message.Body.ExecutionPayload.ParentHash.String(), - FeeRecipient: e.event.Capella.Message.Body.ExecutionPayload.FeeRecipient.String(), - StateRoot: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ExecutionPayload.StateRoot[:]), - ReceiptsRoot: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ExecutionPayload.ReceiptsRoot[:]), - LogsBloom: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ExecutionPayload.LogsBloom[:]), - PrevRandao: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ExecutionPayload.PrevRandao[:]), - BlockNumber: &wrapperspb.UInt64Value{Value: e.event.Capella.Message.Body.ExecutionPayload.BlockNumber}, - GasLimit: &wrapperspb.UInt64Value{Value: e.event.Capella.Message.Body.ExecutionPayload.GasLimit}, - GasUsed: &wrapperspb.UInt64Value{Value: e.event.Capella.Message.Body.ExecutionPayload.GasUsed}, - Timestamp: &wrapperspb.UInt64Value{Value: e.event.Capella.Message.Body.ExecutionPayload.Timestamp}, - ExtraData: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ExecutionPayload.ExtraData), - BaseFeePerGas: fmt.Sprintf("0x%x", e.event.Capella.Message.Body.ExecutionPayload.BaseFeePerGas[:]), - BlockHash: e.event.Capella.Message.Body.ExecutionPayload.BlockHash.String(), - Transactions: getTransactions(e.event.Capella.Message.Body.ExecutionPayload.Transactions), - Withdrawals: getWithdrawals(e.event.Capella.Message.Body.ExecutionPayload.Withdrawals), - }, - BlsToExecutionChanges: getBlsToExecutionChanges(e.event.Capella.Message.Body.BLSToExecutionChanges), - }, - }, - }, - Signature: e.event.Capella.Signature.String(), - } -} - func (e *BeaconBlock) getAdditionalData(_ context.Context, data *xatuethv2.EventBlockV2) (*xatu.ClientMeta_AdditionalEthV2BeaconBlockV2Data, error) { extra := &xatu.ClientMeta_AdditionalEthV2BeaconBlockV2Data{}