mirror of https://github.com/certusone/vouch.git
Update dependencies
This commit is contained in:
parent
e66a4a3613
commit
925e69fb9a
2
go.mod
2
go.mod
|
@ -6,7 +6,7 @@ require (
|
|||
cloud.google.com/go v0.72.0 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
||||
github.com/attestantio/dirk v0.9.6
|
||||
github.com/attestantio/go-eth2-client v0.6.14
|
||||
github.com/attestantio/go-eth2-client v0.6.15
|
||||
github.com/aws/aws-sdk-go v1.35.35
|
||||
github.com/ferranbt/fastssz v0.0.0-20201030134205-9b9624098321
|
||||
github.com/goccy/go-yaml v1.8.4 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -83,6 +83,8 @@ github.com/attestantio/go-eth2-client v0.6.13 h1:n2mN6ZUJcKbNKh/rhE8la7IB5Z8V2Tg
|
|||
github.com/attestantio/go-eth2-client v0.6.13/go.mod h1:Hya4fp1ZLWAFI64qMhNbQgfY4StWiHulW4CFwu+vP3s=
|
||||
github.com/attestantio/go-eth2-client v0.6.14 h1:zP/zP8CKygHVfbxV1ppwWBqbI8yfs3paBsv7Nccx34Q=
|
||||
github.com/attestantio/go-eth2-client v0.6.14/go.mod h1:Hya4fp1ZLWAFI64qMhNbQgfY4StWiHulW4CFwu+vP3s=
|
||||
github.com/attestantio/go-eth2-client v0.6.15 h1:GNkiSF2Dqp6qahMXMW8r8Wy61WEvytnAM+rEyutdfv8=
|
||||
github.com/attestantio/go-eth2-client v0.6.15/go.mod h1:Hya4fp1ZLWAFI64qMhNbQgfY4StWiHulW4CFwu+vP3s=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.33.5/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
|
|
12
main.go
12
main.go
|
@ -328,7 +328,7 @@ func startServices(ctx context.Context, majordomo majordomo.Service) error {
|
|||
standardattester.WithProcessConcurrency(viper.GetInt64("process-concurrency")),
|
||||
standardattester.WithSlotsPerEpochProvider(eth2Client.(eth2client.SlotsPerEpochProvider)),
|
||||
standardattester.WithAttestationDataProvider(attestationDataProvider),
|
||||
standardattester.WithAttestationSubmitter(submitterStrategy.(submitter.AttestationSubmitter)),
|
||||
standardattester.WithAttestationsSubmitter(submitterStrategy.(submitter.AttestationsSubmitter)),
|
||||
standardattester.WithMonitor(monitor.(metrics.AttestationMonitor)),
|
||||
standardattester.WithValidatingAccountsProvider(accountManager.(accountmanager.ValidatingAccountsProvider)),
|
||||
standardattester.WithBeaconAttestationsSigner(signerSvc.(signer.BeaconAttestationsSigner)),
|
||||
|
@ -751,10 +751,10 @@ func selectSubmitterStrategy(ctx context.Context, monitor metrics.Service, eth2C
|
|||
var submitter submitter.Service
|
||||
var err error
|
||||
switch viper.GetString("submitter.style") {
|
||||
case "all":
|
||||
case "all", "multinode":
|
||||
log.Info().Msg("Starting multinode submitter strategy")
|
||||
beaconBlockSubmitters := make(map[string]eth2client.BeaconBlockSubmitter)
|
||||
attestationSubmitters := make(map[string]eth2client.AttestationSubmitter)
|
||||
attestationsSubmitters := make(map[string]eth2client.AttestationsSubmitter)
|
||||
aggregateAttestationSubmitters := make(map[string]eth2client.AggregateAttestationsSubmitter)
|
||||
beaconCommitteeSubscriptionsSubmitters := make(map[string]eth2client.BeaconCommitteeSubscriptionsSubmitter)
|
||||
for _, address := range viper.GetStringSlice("submitter.beacon-node-addresses") {
|
||||
|
@ -763,7 +763,7 @@ func selectSubmitterStrategy(ctx context.Context, monitor metrics.Service, eth2C
|
|||
return nil, errors.Wrap(err, fmt.Sprintf("failed to fetch client %s for submitter strategy", address))
|
||||
}
|
||||
beaconBlockSubmitters[address] = client.(eth2client.BeaconBlockSubmitter)
|
||||
attestationSubmitters[address] = client.(eth2client.AttestationSubmitter)
|
||||
attestationsSubmitters[address] = client.(eth2client.AttestationsSubmitter)
|
||||
aggregateAttestationSubmitters[address] = client.(eth2client.AggregateAttestationsSubmitter)
|
||||
beaconCommitteeSubscriptionsSubmitters[address] = client.(eth2client.BeaconCommitteeSubscriptionsSubmitter)
|
||||
}
|
||||
|
@ -772,7 +772,7 @@ func selectSubmitterStrategy(ctx context.Context, monitor metrics.Service, eth2C
|
|||
multinodesubmitter.WithProcessConcurrency(viper.GetInt64("process-concurrency")),
|
||||
multinodesubmitter.WithLogLevel(logLevel(viper.GetString("submitter.log-level"))),
|
||||
multinodesubmitter.WithBeaconBlockSubmitters(beaconBlockSubmitters),
|
||||
multinodesubmitter.WithAttestationSubmitters(attestationSubmitters),
|
||||
multinodesubmitter.WithAttestationsSubmitters(attestationsSubmitters),
|
||||
multinodesubmitter.WithAggregateAttestationsSubmitters(aggregateAttestationSubmitters),
|
||||
multinodesubmitter.WithBeaconCommitteeSubscriptionsSubmitters(beaconCommitteeSubscriptionsSubmitters),
|
||||
)
|
||||
|
@ -782,7 +782,7 @@ func selectSubmitterStrategy(ctx context.Context, monitor metrics.Service, eth2C
|
|||
immediatesubmitter.WithLogLevel(logLevel(viper.GetString("submitter.log-level"))),
|
||||
immediatesubmitter.WithClientMonitor(monitor.(metrics.ClientMonitor)),
|
||||
immediatesubmitter.WithBeaconBlockSubmitter(eth2Client.(eth2client.BeaconBlockSubmitter)),
|
||||
immediatesubmitter.WithAttestationSubmitter(eth2Client.(eth2client.AttestationSubmitter)),
|
||||
immediatesubmitter.WithAttestationsSubmitter(eth2Client.(eth2client.AttestationsSubmitter)),
|
||||
immediatesubmitter.WithBeaconCommitteeSubscriptionsSubmitter(eth2Client.(eth2client.BeaconCommitteeSubscriptionsSubmitter)),
|
||||
immediatesubmitter.WithAggregateAttestationsSubmitter(eth2Client.(eth2client.AggregateAttestationsSubmitter)),
|
||||
)
|
||||
|
|
|
@ -107,29 +107,29 @@ func (m *ErroringSlotsPerEpochProvider) SlotsPerEpoch(ctx context.Context) (uint
|
|||
return 0, errors.New("error")
|
||||
}
|
||||
|
||||
// AttestationSubmitter is a mock for eth2client.AttestationSubmitter.
|
||||
type AttestationSubmitter struct{}
|
||||
// AttestationsSubmitter is a mock for eth2client.AttestationsSubmitter.
|
||||
type AttestationsSubmitter struct{}
|
||||
|
||||
// NewAttestationSubmitter returns a mock attestation submitter.
|
||||
func NewAttestationSubmitter() eth2client.AttestationSubmitter {
|
||||
return &AttestationSubmitter{}
|
||||
// NewAttestationsSubmitter returns a mock attestations submitter.
|
||||
func NewAttestationsSubmitter() eth2client.AttestationsSubmitter {
|
||||
return &AttestationsSubmitter{}
|
||||
}
|
||||
|
||||
// SubmitAttestation is a mock.
|
||||
func (m *AttestationSubmitter) SubmitAttestation(ctx context.Context, attestation *spec.Attestation) error {
|
||||
// SubmitAttestations is a mock.
|
||||
func (m *AttestationsSubmitter) SubmitAttestations(ctx context.Context, attestation []*spec.Attestation) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ErroringAttestationSubmitter is a mock for eth2client.AttestationSubmitter that returns errors.
|
||||
type ErroringAttestationSubmitter struct{}
|
||||
// ErroringAttestationsSubmitter is a mock for eth2client.AttestationsSubmitter that returns errors.
|
||||
type ErroringAttestationsSubmitter struct{}
|
||||
|
||||
// NewErroringAttestationSubmitter returns a mock attestation submitter.
|
||||
func NewErroringAttestationSubmitter() eth2client.AttestationSubmitter {
|
||||
return &ErroringAttestationSubmitter{}
|
||||
// NewErroringAttestationsSubmitter returns a mock attestation submitter.
|
||||
func NewErroringAttestationsSubmitter() eth2client.AttestationsSubmitter {
|
||||
return &ErroringAttestationsSubmitter{}
|
||||
}
|
||||
|
||||
// SubmitAttestation is a mock.
|
||||
func (m *ErroringAttestationSubmitter) SubmitAttestation(ctx context.Context, attestation *spec.Attestation) error {
|
||||
// SubmitAttestations is a mock.
|
||||
func (m *ErroringAttestationsSubmitter) SubmitAttestations(ctx context.Context, attestations []*spec.Attestation) error {
|
||||
return errors.New("error")
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ type parameters struct {
|
|||
monitor metrics.AttestationMonitor
|
||||
slotsPerEpochProvider eth2client.SlotsPerEpochProvider
|
||||
attestationDataProvider eth2client.AttestationDataProvider
|
||||
attestationSubmitter submitter.AttestationSubmitter
|
||||
attestationsSubmitter submitter.AttestationsSubmitter
|
||||
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
|
||||
beaconAttestationsSigner signer.BeaconAttestationsSigner
|
||||
}
|
||||
|
@ -73,10 +73,10 @@ func WithAttestationDataProvider(provider eth2client.AttestationDataProvider) Pa
|
|||
})
|
||||
}
|
||||
|
||||
// WithAttestationSubmitter sets the attestation submitter.
|
||||
func WithAttestationSubmitter(submitter submitter.AttestationSubmitter) Parameter {
|
||||
// WithAttestationsSubmitter sets the attestations submitter.
|
||||
func WithAttestationsSubmitter(submitter submitter.AttestationsSubmitter) Parameter {
|
||||
return parameterFunc(func(p *parameters) {
|
||||
p.attestationSubmitter = submitter
|
||||
p.attestationsSubmitter = submitter
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -121,8 +121,8 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
|
|||
if parameters.attestationDataProvider == nil {
|
||||
return nil, errors.New("no attestation data provider specified")
|
||||
}
|
||||
if parameters.attestationSubmitter == nil {
|
||||
return nil, errors.New("no attestation submitter specified")
|
||||
if parameters.attestationsSubmitter == nil {
|
||||
return nil, errors.New("no attestations submitter specified")
|
||||
}
|
||||
if parameters.monitor == nil {
|
||||
return nil, errors.New("no monitor specified")
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
eth2client "github.com/attestantio/go-eth2-client"
|
||||
|
@ -27,7 +26,6 @@ import (
|
|||
"github.com/attestantio/vouch/services/metrics"
|
||||
"github.com/attestantio/vouch/services/signer"
|
||||
"github.com/attestantio/vouch/services/submitter"
|
||||
"github.com/attestantio/vouch/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/rs/zerolog"
|
||||
|
@ -42,7 +40,7 @@ type Service struct {
|
|||
slotsPerEpoch uint64
|
||||
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
|
||||
attestationDataProvider eth2client.AttestationDataProvider
|
||||
attestationSubmitter submitter.AttestationSubmitter
|
||||
attestationsSubmitter submitter.AttestationsSubmitter
|
||||
beaconAttestationsSigner signer.BeaconAttestationsSigner
|
||||
}
|
||||
|
||||
|
@ -73,7 +71,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
|||
slotsPerEpoch: slotsPerEpoch,
|
||||
validatingAccountsProvider: parameters.validatingAccountsProvider,
|
||||
attestationDataProvider: parameters.attestationDataProvider,
|
||||
attestationSubmitter: parameters.attestationSubmitter,
|
||||
attestationsSubmitter: parameters.attestationsSubmitter,
|
||||
beaconAttestationsSigner: parameters.beaconAttestationsSigner,
|
||||
}
|
||||
|
||||
|
@ -201,49 +199,41 @@ func (s *Service) attest(
|
|||
}
|
||||
log.Trace().Dur("elapsed", time.Since(started)).Msg("Signed")
|
||||
|
||||
// Submit the attestations.
|
||||
// Create the attestations.
|
||||
zeroSig := spec.BLSSignature{}
|
||||
attestations := make([]*spec.Attestation, len(sigs))
|
||||
_, err = util.Scatter(len(sigs), func(offset int, entries int, _ *sync.RWMutex) (interface{}, error) {
|
||||
for i := offset; i < offset+entries; i++ {
|
||||
log := log.With().Uint64("slot", uint64(duty.Slot())).Uint64("validator_index", uint64(validatorIndices[i])).Logger()
|
||||
if bytes.Equal(sigs[i][:], zeroSig[:]) {
|
||||
log.Warn().Msg("No signature for validator; not creating attestation")
|
||||
continue
|
||||
}
|
||||
|
||||
aggregationBits := bitfield.NewBitlist(committeeSizes[i])
|
||||
aggregationBits.SetBitAt(uint64(validatorCommitteeIndices[i]), true)
|
||||
attestation := &spec.Attestation{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: &spec.AttestationData{
|
||||
Slot: duty.Slot(),
|
||||
Index: committeeIndices[i],
|
||||
BeaconBlockRoot: data.BeaconBlockRoot,
|
||||
Source: &spec.Checkpoint{
|
||||
Epoch: data.Source.Epoch,
|
||||
Root: data.Source.Root,
|
||||
},
|
||||
Target: &spec.Checkpoint{
|
||||
Epoch: data.Target.Epoch,
|
||||
Root: data.Target.Root,
|
||||
},
|
||||
},
|
||||
}
|
||||
copy(attestation.Signature[:], sigs[i][:])
|
||||
if err := s.attestationSubmitter.SubmitAttestation(ctx, attestation); err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to submit attestation")
|
||||
continue
|
||||
}
|
||||
attestations[i] = attestation
|
||||
s.monitor.AttestationCompleted(started, "succeeded")
|
||||
attestations := make([]*spec.Attestation, 0, len(sigs))
|
||||
for i := range sigs {
|
||||
if bytes.Equal(sigs[i][:], zeroSig[:]) {
|
||||
log.Warn().Msg("No signature for validator; not creating attestation")
|
||||
continue
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to scatter submit")
|
||||
aggregationBits := bitfield.NewBitlist(committeeSizes[i])
|
||||
aggregationBits.SetBitAt(uint64(validatorCommitteeIndices[i]), true)
|
||||
attestation := &spec.Attestation{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: &spec.AttestationData{
|
||||
Slot: duty.Slot(),
|
||||
Index: committeeIndices[i],
|
||||
BeaconBlockRoot: data.BeaconBlockRoot,
|
||||
Source: &spec.Checkpoint{
|
||||
Epoch: data.Source.Epoch,
|
||||
Root: data.Source.Root,
|
||||
},
|
||||
Target: &spec.Checkpoint{
|
||||
Epoch: data.Target.Epoch,
|
||||
Root: data.Target.Root,
|
||||
},
|
||||
},
|
||||
}
|
||||
copy(attestation.Signature[:], sigs[i][:])
|
||||
attestations = append(attestations, attestation)
|
||||
}
|
||||
log.Trace().Dur("elapsed", time.Since(started)).Msg("Submitted")
|
||||
|
||||
// Submit the attestations.
|
||||
if err := s.attestationsSubmitter.SubmitAttestations(ctx, attestations); err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to submit attestations")
|
||||
}
|
||||
log.Trace().Dur("elapsed", time.Since(started)).Msg("Submitted attestations")
|
||||
|
||||
return attestations, nil
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
|||
return nil, errors.Wrap(err, "failed to obtain active validator indices for the current epoch")
|
||||
}
|
||||
if len(validatorIndices) != s.activeValidators {
|
||||
log.Info().Int("old_valdiators", s.activeValidators).Int("new_validators", len(validatorIndices)).Msg("Change in number of active validators")
|
||||
log.Info().Int("old_validators", s.activeValidators).Int("new_validators", len(validatorIndices)).Msg("Change in number of active validators")
|
||||
s.activeValidators = len(validatorIndices)
|
||||
}
|
||||
nextEpochAccounts, nextEpochValidatorIndices, err := s.accountsAndIndicesForEpoch(ctx, epoch+1)
|
||||
|
@ -162,8 +162,6 @@ func (s *Service) startTickers(ctx context.Context) error {
|
|||
// Wait for genesis.
|
||||
log.Info().Str("genesis", fmt.Sprintf("%v", genesisTime)).Msg("Waiting for genesis")
|
||||
time.Sleep(time.Until(genesisTime))
|
||||
// Give it another half second to let the beacon node be ready.
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
// Start epoch tickers.
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright © 2020 Attestant Limited.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package standard
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
spec "github.com/attestantio/go-eth2-client/spec/phase0"
|
||||
"github.com/pkg/errors"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
// sign signs a root, using protected methods if possible.
|
||||
func (s *Service) sign(ctx context.Context,
|
||||
account e2wtypes.Account,
|
||||
root spec.Root,
|
||||
domain spec.Domain,
|
||||
) (
|
||||
spec.BLSSignature,
|
||||
error,
|
||||
) {
|
||||
var sig e2types.Signature
|
||||
if protectingSigner, isProtectingSigner := account.(e2wtypes.AccountProtectingSigner); isProtectingSigner {
|
||||
var err error
|
||||
sig, err = protectingSigner.SignGeneric(ctx, root[:], domain[:])
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, err
|
||||
}
|
||||
} else {
|
||||
container := spec.SigningData{
|
||||
ObjectRoot: root,
|
||||
Domain: domain,
|
||||
}
|
||||
root, err := container.HashTreeRoot()
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to generate hash tree root")
|
||||
}
|
||||
sig, err = account.(e2wtypes.AccountSigner).Sign(ctx, root[:])
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, err
|
||||
}
|
||||
}
|
||||
|
||||
var signature spec.BLSSignature
|
||||
copy(signature[:], sig.Marshal())
|
||||
return signature, nil
|
||||
}
|
|
@ -38,12 +38,10 @@ func (s *Service) SignAggregateAndProof(ctx context.Context,
|
|||
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon aggregate and proof")
|
||||
}
|
||||
|
||||
sig, err := account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, aggregateAndProofRoot[:], domain[:])
|
||||
sig, err := s.sign(ctx, account, aggregateAndProofRoot, domain)
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to aggregate and proof")
|
||||
}
|
||||
|
||||
var signature spec.BLSSignature
|
||||
copy(signature[:], sig.Marshal())
|
||||
return signature, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ func (s *Service) SignBeaconAttestation(ctx context.Context,
|
|||
spec.BLSSignature,
|
||||
error,
|
||||
) {
|
||||
|
||||
domain, err := s.domainProvider.Domain(ctx,
|
||||
s.beaconAttesterDomainType,
|
||||
spec.Epoch(slot/s.slotsPerEpoch))
|
||||
|
@ -43,20 +42,44 @@ func (s *Service) SignBeaconAttestation(ctx context.Context,
|
|||
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon attestation")
|
||||
}
|
||||
|
||||
sig, err := account.(e2wtypes.AccountProtectingSigner).SignBeaconAttestation(ctx,
|
||||
uint64(slot),
|
||||
uint64(committeeIndex),
|
||||
blockRoot[:],
|
||||
uint64(sourceEpoch),
|
||||
sourceRoot[:],
|
||||
uint64(targetEpoch),
|
||||
targetRoot[:],
|
||||
domain[:])
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign beacon attestation")
|
||||
var sig spec.BLSSignature
|
||||
if protectingSigner, isProtectingSigner := account.(e2wtypes.AccountProtectingSigner); isProtectingSigner {
|
||||
signature, err := protectingSigner.SignBeaconAttestation(ctx,
|
||||
uint64(slot),
|
||||
uint64(committeeIndex),
|
||||
blockRoot[:],
|
||||
uint64(sourceEpoch),
|
||||
sourceRoot[:],
|
||||
uint64(targetEpoch),
|
||||
targetRoot[:],
|
||||
domain[:])
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign beacon attestation")
|
||||
}
|
||||
copy(sig[:], signature.Marshal())
|
||||
} else {
|
||||
attestation := &spec.AttestationData{
|
||||
Slot: slot,
|
||||
Index: committeeIndex,
|
||||
BeaconBlockRoot: blockRoot,
|
||||
Source: &spec.Checkpoint{
|
||||
Epoch: sourceEpoch,
|
||||
Root: sourceRoot,
|
||||
},
|
||||
Target: &spec.Checkpoint{
|
||||
Epoch: targetEpoch,
|
||||
Root: targetRoot,
|
||||
},
|
||||
}
|
||||
root, err := attestation.HashTreeRoot()
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to generate hash tree root")
|
||||
}
|
||||
sig, err = s.sign(ctx, account, root, domain)
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, err
|
||||
}
|
||||
}
|
||||
|
||||
var signature spec.BLSSignature
|
||||
copy(signature[:], sig.Marshal())
|
||||
return signature, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func (s *Service) SignBeaconAttestations(ctx context.Context,
|
|||
[]spec.BLSSignature,
|
||||
error,
|
||||
) {
|
||||
span, ctx := opentracing.StartSpanFromContext(ctx, "dirk.SignBeaconAttestations")
|
||||
span, ctx := opentracing.StartSpanFromContext(ctx, "signer.SignBeaconAttestations")
|
||||
defer span.Finish()
|
||||
|
||||
if len(accounts) == 0 {
|
||||
|
@ -50,30 +50,51 @@ func (s *Service) SignBeaconAttestations(ctx context.Context,
|
|||
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon attestation")
|
||||
}
|
||||
|
||||
uintCommitteeIndices := make([]uint64, len(committeeIndices))
|
||||
for i := range committeeIndices {
|
||||
uintCommitteeIndices[i] = uint64(committeeIndices[i])
|
||||
sigs := make([]spec.BLSSignature, len(accounts))
|
||||
if multiSigner, isMultiSigner := accounts[0].(e2wtypes.AccountProtectingMultiSigner); isMultiSigner {
|
||||
uintCommitteeIndices := make([]uint64, len(committeeIndices))
|
||||
for i := range committeeIndices {
|
||||
uintCommitteeIndices[i] = uint64(committeeIndices[i])
|
||||
}
|
||||
signatures, err := multiSigner.SignBeaconAttestations(ctx,
|
||||
uint64(slot),
|
||||
accounts,
|
||||
uintCommitteeIndices,
|
||||
blockRoot[:],
|
||||
uint64(sourceEpoch),
|
||||
sourceRoot[:],
|
||||
uint64(targetEpoch),
|
||||
targetRoot[:],
|
||||
signatureDomain[:],
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to multisign beacon attestation")
|
||||
}
|
||||
for i := range signatures {
|
||||
if signatures[i] != nil {
|
||||
copy(sigs[i][:], signatures[i].Marshal())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := range accounts {
|
||||
sigs[i], err = s.SignBeaconAttestation(ctx,
|
||||
accounts[i],
|
||||
slot,
|
||||
committeeIndices[i],
|
||||
blockRoot,
|
||||
sourceEpoch,
|
||||
sourceRoot,
|
||||
targetEpoch,
|
||||
targetRoot,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to sign beacon attestation")
|
||||
}
|
||||
}
|
||||
}
|
||||
sigs, err := accounts[0].(e2wtypes.AccountProtectingMultiSigner).SignBeaconAttestations(ctx,
|
||||
uint64(slot),
|
||||
accounts,
|
||||
uintCommitteeIndices,
|
||||
blockRoot[:],
|
||||
uint64(sourceEpoch),
|
||||
sourceRoot[:],
|
||||
uint64(targetEpoch),
|
||||
targetRoot[:],
|
||||
signatureDomain[:],
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to sign beacon attestation")
|
||||
}
|
||||
|
||||
res := make([]spec.BLSSignature, len(sigs))
|
||||
for i := range sigs {
|
||||
if sigs[i] != nil {
|
||||
copy(res[i][:], sigs[i].Marshal())
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
return sigs, nil
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
// SignBeaconBlockProposal signs a beacon block proposal item.
|
||||
// SignBeaconBlockProposal signs a beacon block proposal.
|
||||
func (s *Service) SignBeaconBlockProposal(ctx context.Context,
|
||||
account e2wtypes.Account,
|
||||
slot spec.Slot,
|
||||
|
@ -42,18 +42,36 @@ func (s *Service) SignBeaconBlockProposal(ctx context.Context,
|
|||
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon proposal")
|
||||
}
|
||||
|
||||
sig, err := account.(e2wtypes.AccountProtectingSigner).SignBeaconProposal(ctx,
|
||||
uint64(slot),
|
||||
uint64(proposerIndex),
|
||||
parentRoot[:],
|
||||
stateRoot[:],
|
||||
bodyRoot[:],
|
||||
domain[:])
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign beacon block proposal")
|
||||
var sig spec.BLSSignature
|
||||
if protectingSigner, isProtectingSigner := account.(e2wtypes.AccountProtectingSigner); isProtectingSigner {
|
||||
signature, err := protectingSigner.SignBeaconProposal(ctx,
|
||||
uint64(slot),
|
||||
uint64(proposerIndex),
|
||||
parentRoot[:],
|
||||
stateRoot[:],
|
||||
bodyRoot[:],
|
||||
domain[:])
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign beacon block proposal")
|
||||
}
|
||||
copy(sig[:], signature.Marshal())
|
||||
} else {
|
||||
header := &spec.BeaconBlockHeader{
|
||||
Slot: slot,
|
||||
ProposerIndex: proposerIndex,
|
||||
ParentRoot: parentRoot,
|
||||
StateRoot: stateRoot,
|
||||
BodyRoot: bodyRoot,
|
||||
}
|
||||
root, err := header.HashTreeRoot()
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to generate hash tree root")
|
||||
}
|
||||
sig, err = s.sign(ctx, account, root, domain)
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, err
|
||||
}
|
||||
}
|
||||
|
||||
var signature spec.BLSSignature
|
||||
copy(signature[:], sig.Marshal())
|
||||
return signature, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
|
|
@ -43,15 +43,13 @@ func (s *Service) SignRANDAOReveal(ctx context.Context,
|
|||
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for RANDAO reveal")
|
||||
}
|
||||
|
||||
epochBytes := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(epochBytes, uint64(epoch))
|
||||
var epochBytes spec.Root
|
||||
binary.LittleEndian.PutUint64(epochBytes[:], uint64(epoch))
|
||||
|
||||
sig, err := account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, epochBytes, domain[:])
|
||||
sig, err := s.sign(ctx, account, epochBytes, domain)
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign RANDO reveal")
|
||||
}
|
||||
|
||||
var signature spec.BLSSignature
|
||||
copy(signature[:], sig.Marshal())
|
||||
return signature, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
|
|
@ -42,15 +42,13 @@ func (s *Service) SignSlotSelection(ctx context.Context,
|
|||
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for selection proof")
|
||||
}
|
||||
|
||||
slotBytes := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(slotBytes, uint64(slot))
|
||||
var slotBytes spec.Root
|
||||
binary.LittleEndian.PutUint64(slotBytes[:], uint64(slot))
|
||||
|
||||
sig, err := account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, slotBytes, domain[:])
|
||||
sig, err := s.sign(ctx, account, slotBytes, domain)
|
||||
if err != nil {
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign slot")
|
||||
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign RANDO reveal")
|
||||
}
|
||||
|
||||
var signature spec.BLSSignature
|
||||
copy(signature[:], sig.Marshal())
|
||||
return signature, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ type parameters struct {
|
|||
logLevel zerolog.Level
|
||||
clientMonitor metrics.ClientMonitor
|
||||
beaconBlockSubmitter eth2client.BeaconBlockSubmitter
|
||||
attestationSubmitter eth2client.AttestationSubmitter
|
||||
attestationsSubmitter eth2client.AttestationsSubmitter
|
||||
beaconCommitteeSubscriptionsSubmitter eth2client.BeaconCommitteeSubscriptionsSubmitter
|
||||
aggregateAttestationsSubmitter eth2client.AggregateAttestationsSubmitter
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ func WithBeaconBlockSubmitter(submitter eth2client.BeaconBlockSubmitter) Paramet
|
|||
})
|
||||
}
|
||||
|
||||
// WithAttestationSubmitter sets the attestation submitter.
|
||||
func WithAttestationSubmitter(submitter eth2client.AttestationSubmitter) Parameter {
|
||||
// WithAttestationsSubmitter sets the attestation submitter.
|
||||
func WithAttestationsSubmitter(submitter eth2client.AttestationsSubmitter) Parameter {
|
||||
return parameterFunc(func(p *parameters) {
|
||||
p.attestationSubmitter = submitter
|
||||
p.attestationsSubmitter = submitter
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -104,8 +104,8 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
|
|||
if parameters.beaconBlockSubmitter == nil {
|
||||
return nil, errors.New("no beacon block submitter specified")
|
||||
}
|
||||
if parameters.attestationSubmitter == nil {
|
||||
return nil, errors.New("no attestation submitter specified")
|
||||
if parameters.attestationsSubmitter == nil {
|
||||
return nil, errors.New("no attestations submitter specified")
|
||||
}
|
||||
if parameters.beaconCommitteeSubscriptionsSubmitter == nil {
|
||||
return nil, errors.New("no beacon committee subscriptions submitter specified")
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
// Service is the submitter for signed items.
|
||||
type Service struct {
|
||||
clientMonitor metrics.ClientMonitor
|
||||
attestationSubmitter eth2client.AttestationSubmitter
|
||||
attestationsSubmitter eth2client.AttestationsSubmitter
|
||||
beaconBlockSubmitter eth2client.BeaconBlockSubmitter
|
||||
beaconCommitteeSubscriptionsSubmitter eth2client.BeaconCommitteeSubscriptionsSubmitter
|
||||
aggregateAttestationsSubmitter eth2client.AggregateAttestationsSubmitter
|
||||
|
@ -54,7 +54,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
|||
|
||||
s := &Service{
|
||||
clientMonitor: parameters.clientMonitor,
|
||||
attestationSubmitter: parameters.attestationSubmitter,
|
||||
attestationsSubmitter: parameters.attestationsSubmitter,
|
||||
beaconBlockSubmitter: parameters.beaconBlockSubmitter,
|
||||
beaconCommitteeSubscriptionsSubmitter: parameters.beaconCommitteeSubscriptionsSubmitter,
|
||||
aggregateAttestationsSubmitter: parameters.aggregateAttestationsSubmitter,
|
||||
|
@ -90,27 +90,27 @@ func (s *Service) SubmitBeaconBlock(ctx context.Context, block *spec.SignedBeaco
|
|||
return nil
|
||||
}
|
||||
|
||||
// SubmitAttestation submits an attestation.
|
||||
func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attestation) error {
|
||||
if attestation == nil {
|
||||
return errors.New("no attestation supplied")
|
||||
// SubmitAttestations submits multiple attestations.
|
||||
func (s *Service) SubmitAttestations(ctx context.Context, attestations []*spec.Attestation) error {
|
||||
if len(attestations) == 0 {
|
||||
return errors.New("no attestations supplied")
|
||||
}
|
||||
|
||||
started := time.Now()
|
||||
err := s.attestationSubmitter.SubmitAttestation(ctx, attestation)
|
||||
if service, isService := s.attestationSubmitter.(eth2client.Service); isService {
|
||||
s.clientMonitor.ClientOperation(service.Address(), "submit attestation", err == nil, time.Since(started))
|
||||
err := s.attestationsSubmitter.SubmitAttestations(ctx, attestations)
|
||||
if service, isService := s.attestationsSubmitter.(eth2client.Service); isService {
|
||||
s.clientMonitor.ClientOperation(service.Address(), "submit attestations", err == nil, time.Since(started))
|
||||
} else {
|
||||
s.clientMonitor.ClientOperation("<unknown>", "submit attestation", err == nil, time.Since(started))
|
||||
s.clientMonitor.ClientOperation("<unknown>", "submit attestations", err == nil, time.Since(started))
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to submit attestation")
|
||||
return errors.Wrap(err, "failed to submit attestations")
|
||||
}
|
||||
|
||||
if e := log.Trace(); e.Enabled() {
|
||||
data, err := json.Marshal(attestation)
|
||||
data, err := json.Marshal(attestations)
|
||||
if err == nil {
|
||||
e.Str("attestation", string(data)).Msg("Submitted attestation")
|
||||
e.Str("attestations", string(data)).Msg("Submitted attestations")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
)
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
attestationSubmitter := mock.NewAttestationSubmitter()
|
||||
attestationsSubmitter := mock.NewAttestationsSubmitter()
|
||||
beaconBlockSubmitter := mock.NewBeaconBlockSubmitter()
|
||||
beaconCommitteeSubscriptionSubmitter := mock.NewBeaconCommitteeSubscriptionsSubmitter()
|
||||
aggregateAttestationSubmitter := mock.NewAggregateAttestationsSubmitter()
|
||||
|
@ -38,20 +38,20 @@ func TestService(t *testing.T) {
|
|||
err string
|
||||
}{
|
||||
{
|
||||
name: "AttestationSubmitterMissing",
|
||||
name: "AttestationsSubmitterMissing",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithBeaconBlockSubmitter(beaconBlockSubmitter),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(beaconCommitteeSubscriptionSubmitter),
|
||||
immediate.WithAggregateAttestationsSubmitter(aggregateAttestationSubmitter),
|
||||
},
|
||||
err: "problem with parameters: no attestation submitter specified",
|
||||
err: "problem with parameters: no attestations submitter specified",
|
||||
},
|
||||
{
|
||||
name: "BeaconBlockSubmitterMissing",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(attestationSubmitter),
|
||||
immediate.WithAttestationsSubmitter(attestationsSubmitter),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(beaconCommitteeSubscriptionSubmitter),
|
||||
immediate.WithAggregateAttestationsSubmitter(aggregateAttestationSubmitter),
|
||||
},
|
||||
|
@ -61,7 +61,7 @@ func TestService(t *testing.T) {
|
|||
name: "AttestationSubnetSubscriptionsSubmitterMissing",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(attestationSubmitter),
|
||||
immediate.WithAttestationsSubmitter(attestationsSubmitter),
|
||||
immediate.WithBeaconBlockSubmitter(beaconBlockSubmitter),
|
||||
immediate.WithAggregateAttestationsSubmitter(aggregateAttestationSubmitter),
|
||||
},
|
||||
|
@ -71,7 +71,7 @@ func TestService(t *testing.T) {
|
|||
name: "AggregateAttestationSubmitterMissing",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(attestationSubmitter),
|
||||
immediate.WithAttestationsSubmitter(attestationsSubmitter),
|
||||
immediate.WithBeaconBlockSubmitter(beaconBlockSubmitter),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(beaconCommitteeSubscriptionSubmitter),
|
||||
},
|
||||
|
@ -81,7 +81,7 @@ func TestService(t *testing.T) {
|
|||
name: "Good",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.TraceLevel),
|
||||
immediate.WithAttestationSubmitter(attestationSubmitter),
|
||||
immediate.WithAttestationsSubmitter(attestationsSubmitter),
|
||||
immediate.WithBeaconBlockSubmitter(beaconBlockSubmitter),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(beaconCommitteeSubscriptionSubmitter),
|
||||
immediate.WithAggregateAttestationsSubmitter(aggregateAttestationSubmitter),
|
||||
|
@ -103,14 +103,14 @@ func TestService(t *testing.T) {
|
|||
func TestInterfaces(t *testing.T) {
|
||||
s, err := immediate.New(context.Background(),
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Implements(t, (*submitter.BeaconBlockSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.AttestationSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.AttestationsSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.BeaconCommitteeSubscriptionsSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.AggregateAttestationsSubmitter)(nil), s)
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func TestSubmitBeaconBlock(t *testing.T) {
|
|||
name: "Nil",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -137,7 +137,7 @@ func TestSubmitBeaconBlock(t *testing.T) {
|
|||
name: "Empty",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -148,7 +148,7 @@ func TestSubmitBeaconBlock(t *testing.T) {
|
|||
name: "Erroring",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewErroringBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -160,7 +160,7 @@ func TestSubmitBeaconBlock(t *testing.T) {
|
|||
name: "Good",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.TraceLevel),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -184,57 +184,58 @@ func TestSubmitBeaconBlock(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSubmitAttestation(t *testing.T) {
|
||||
func TestSubmitAttestations(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
params []immediate.Parameter
|
||||
attestation *spec.Attestation
|
||||
err string
|
||||
name string
|
||||
params []immediate.Parameter
|
||||
attestations []*spec.Attestation
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "Nil",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
},
|
||||
err: "no attestation supplied",
|
||||
err: "no attestations supplied",
|
||||
},
|
||||
{
|
||||
name: "Empty",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
},
|
||||
attestation: &spec.Attestation{},
|
||||
attestations: []*spec.Attestation{},
|
||||
err: "no attestations supplied",
|
||||
},
|
||||
{
|
||||
name: "Erroring",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewErroringAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewErroringAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
},
|
||||
attestation: &spec.Attestation{},
|
||||
err: "failed to submit attestation: error",
|
||||
attestations: []*spec.Attestation{{}},
|
||||
err: "failed to submit attestations: error",
|
||||
},
|
||||
{
|
||||
name: "Good",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.TraceLevel),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
},
|
||||
attestation: &spec.Attestation{},
|
||||
attestations: []*spec.Attestation{{}},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -243,7 +244,7 @@ func TestSubmitAttestation(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
err := s.SubmitAttestation(context.Background(), test.attestation)
|
||||
err := s.SubmitAttestations(context.Background(), test.attestations)
|
||||
if test.err != "" {
|
||||
require.EqualError(t, err, test.err)
|
||||
} else {
|
||||
|
@ -264,7 +265,7 @@ func TestSubmitAggregateAttestations(t *testing.T) {
|
|||
name: "Nil",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -275,7 +276,7 @@ func TestSubmitAggregateAttestations(t *testing.T) {
|
|||
name: "Empty",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -287,7 +288,7 @@ func TestSubmitAggregateAttestations(t *testing.T) {
|
|||
name: "Erroring",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewErroringAggregateAttestationsSubmitter()),
|
||||
|
@ -301,7 +302,7 @@ func TestSubmitAggregateAttestations(t *testing.T) {
|
|||
name: "Good",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.TraceLevel),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -338,7 +339,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
|
|||
name: "Nil",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -349,7 +350,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
|
|||
name: "Empty",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -361,7 +362,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
|
|||
name: "Erroring",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.Disabled),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewErroringBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
@ -375,7 +376,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
|
|||
name: "Good",
|
||||
params: []immediate.Parameter{
|
||||
immediate.WithLogLevel(zerolog.TraceLevel),
|
||||
immediate.WithAttestationSubmitter(mock.NewAttestationSubmitter()),
|
||||
immediate.WithAttestationsSubmitter(mock.NewAttestationsSubmitter()),
|
||||
immediate.WithBeaconBlockSubmitter(mock.NewBeaconBlockSubmitter()),
|
||||
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
|
||||
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright © 2020 Attestant Limited.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package multinode
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
eth2client "github.com/attestantio/go-eth2-client"
|
||||
)
|
||||
|
||||
// serviceInfo returns the service name and provider information.
|
||||
func (s *Service) serviceInfo(ctx context.Context, submitter interface{}) (string, string) {
|
||||
serviceName := "<unknown>"
|
||||
provider := "<unknown>"
|
||||
if service, isService := submitter.(eth2client.Service); isService {
|
||||
provider = service.Address()
|
||||
}
|
||||
if service, isService := submitter.(eth2client.NodeVersionProvider); isService {
|
||||
nodeVersion, err := service.NodeVersion(ctx)
|
||||
if err == nil {
|
||||
switch {
|
||||
case strings.Contains(strings.ToLower(nodeVersion), "lighthouse"):
|
||||
serviceName = "lighthouse"
|
||||
case strings.Contains(strings.ToLower(nodeVersion), "prysm"):
|
||||
serviceName = "prysm"
|
||||
case strings.Contains(strings.ToLower(nodeVersion), "teku"):
|
||||
serviceName = "teku"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serviceName, provider
|
||||
}
|
|
@ -30,7 +30,7 @@ type parameters struct {
|
|||
clientMonitor metrics.ClientMonitor
|
||||
processConcurrency int64
|
||||
beaconBlockSubmitters map[string]eth2client.BeaconBlockSubmitter
|
||||
attestationSubmitters map[string]eth2client.AttestationSubmitter
|
||||
attestationsSubmitters map[string]eth2client.AttestationsSubmitter
|
||||
aggregateAttestationsSubmitters map[string]eth2client.AggregateAttestationsSubmitter
|
||||
beaconCommitteeSubscriptionsSubmitters map[string]eth2client.BeaconCommitteeSubscriptionsSubmitter
|
||||
}
|
||||
|
@ -74,10 +74,10 @@ func WithBeaconBlockSubmitters(submitters map[string]eth2client.BeaconBlockSubmi
|
|||
})
|
||||
}
|
||||
|
||||
// WithAttestationSubmitters sets the attestation submitters.
|
||||
func WithAttestationSubmitters(submitters map[string]eth2client.AttestationSubmitter) Parameter {
|
||||
// WithAttestationsSubmitters sets the attestation submitters.
|
||||
func WithAttestationsSubmitters(submitters map[string]eth2client.AttestationsSubmitter) Parameter {
|
||||
return parameterFunc(func(p *parameters) {
|
||||
p.attestationSubmitters = submitters
|
||||
p.attestationsSubmitters = submitters
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -116,8 +116,8 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
|
|||
if len(parameters.beaconBlockSubmitters) == 0 {
|
||||
return nil, errors.New("no beacon block submitters specified")
|
||||
}
|
||||
if len(parameters.attestationSubmitters) == 0 {
|
||||
return nil, errors.New("no attestation submitters specified")
|
||||
if len(parameters.attestationsSubmitters) == 0 {
|
||||
return nil, errors.New("no attestations submitters specified")
|
||||
}
|
||||
if len(parameters.aggregateAttestationsSubmitters) == 0 {
|
||||
return nil, errors.New("no aggregate attestations submitters specified")
|
||||
|
|
|
@ -28,7 +28,7 @@ type Service struct {
|
|||
clientMonitor metrics.ClientMonitor
|
||||
processConcurrency int64
|
||||
beaconBlockSubmitters map[string]eth2client.BeaconBlockSubmitter
|
||||
attestationSubmitters map[string]eth2client.AttestationSubmitter
|
||||
attestationsSubmitters map[string]eth2client.AttestationsSubmitter
|
||||
aggregateAttestationsSubmitters map[string]eth2client.AggregateAttestationsSubmitter
|
||||
beaconCommitteeSubscriptionSubmitters map[string]eth2client.BeaconCommitteeSubscriptionsSubmitter
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
|||
clientMonitor: parameters.clientMonitor,
|
||||
processConcurrency: parameters.processConcurrency,
|
||||
beaconBlockSubmitters: parameters.beaconBlockSubmitters,
|
||||
attestationSubmitters: parameters.attestationSubmitters,
|
||||
attestationsSubmitters: parameters.attestationsSubmitters,
|
||||
aggregateAttestationsSubmitters: parameters.aggregateAttestationsSubmitters,
|
||||
beaconCommitteeSubscriptionSubmitters: parameters.beaconCommitteeSubscriptionsSubmitters,
|
||||
}
|
||||
|
|
|
@ -26,24 +26,24 @@ import (
|
|||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
// SubmitAttestation submits an attestation.
|
||||
func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attestation) error {
|
||||
if attestation == nil {
|
||||
return errors.New("no attestation supplied")
|
||||
// SubmitAttestations submits a batch of attestations.
|
||||
func (s *Service) SubmitAttestations(ctx context.Context, attestations []*spec.Attestation) error {
|
||||
if len(attestations) == 0 {
|
||||
return errors.New("no attestations supplied")
|
||||
}
|
||||
|
||||
sem := semaphore.NewWeighted(s.processConcurrency)
|
||||
var wg sync.WaitGroup
|
||||
for name, submitter := range s.attestationSubmitters {
|
||||
for name, submitter := range s.attestationsSubmitters {
|
||||
wg.Add(1)
|
||||
go func(ctx context.Context,
|
||||
sem *semaphore.Weighted,
|
||||
wg *sync.WaitGroup,
|
||||
name string,
|
||||
submitter eth2client.AttestationSubmitter,
|
||||
submitter eth2client.AttestationsSubmitter,
|
||||
) {
|
||||
defer wg.Done()
|
||||
log := log.With().Str("beacon_node_address", name).Uint64("slot", uint64(attestation.Data.Slot)).Logger()
|
||||
log := log.With().Str("beacon_node_address", name).Uint64("slot", uint64(attestations[0].Data.Slot)).Logger()
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to acquire semaphore")
|
||||
return
|
||||
|
@ -52,8 +52,8 @@ func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attes
|
|||
|
||||
serverType, address := s.serviceInfo(ctx, submitter)
|
||||
started := time.Now()
|
||||
err := submitter.SubmitAttestation(ctx, attestation)
|
||||
s.clientMonitor.ClientOperation(address, "submit attestation", err == nil, time.Since(started))
|
||||
err := submitter.SubmitAttestations(ctx, attestations)
|
||||
s.clientMonitor.ClientOperation(address, "submit attestations", err == nil, time.Since(started))
|
||||
if err != nil {
|
||||
switch {
|
||||
case serverType == "lighthouse" && strings.Contains(err.Error(), "PriorAttestationKnown"):
|
||||
|
@ -64,47 +64,22 @@ func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attes
|
|||
// Lighthouse rejects an attestation for a block that is not its current head. It is possible
|
||||
// that the node is just behind, and we can't do anything about it anyway at this point having
|
||||
// already signed an attestation for this slot, so ignore the error.
|
||||
log.Trace().Msg("Node does not know head slot; ignored")
|
||||
log.Debug().Err(err).Msg("Node does not know head block; rejected")
|
||||
case serverType == "lighthouse" && strings.Contains(err.Error(), "InvalidSignature"):
|
||||
data, err2 := json.Marshal(attestations)
|
||||
if err2 != nil {
|
||||
log.Error().Err(err).Msg("Failed to marshal JSON")
|
||||
}
|
||||
log.Warn().Err(err).Str("data", string(data)).Msg("Invalid signature!")
|
||||
default:
|
||||
log.Warn().Err(err).Msg("Failed to submit attestation")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
log.Trace().Msg("Submitted attestations")
|
||||
}
|
||||
log.Trace().Msg("Submitted attestation")
|
||||
}(ctx, sem, &wg, name, submitter)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
if e := log.Trace(); e.Enabled() {
|
||||
data, err := json.Marshal(attestation)
|
||||
if err == nil {
|
||||
e.Str("attestation", string(data)).Msg("Submitted attestation")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serviceInfo returns the service name and provider information.
|
||||
func (s *Service) serviceInfo(ctx context.Context, submitter interface{}) (string, string) {
|
||||
serviceName := "<unknown>"
|
||||
provider := "<unknown>"
|
||||
if service, isService := submitter.(eth2client.Service); isService {
|
||||
provider = service.Address()
|
||||
}
|
||||
if service, isService := submitter.(eth2client.NodeVersionProvider); isService {
|
||||
nodeVersion, err := service.NodeVersion(ctx)
|
||||
if err == nil {
|
||||
switch {
|
||||
case strings.Contains(strings.ToLower(nodeVersion), "lighthouse"):
|
||||
serviceName = "lighthouse"
|
||||
case strings.Contains(strings.ToLower(nodeVersion), "prysm"):
|
||||
serviceName = "prysm"
|
||||
case strings.Contains(strings.ToLower(nodeVersion), "teku"):
|
||||
serviceName = "teku"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serviceName, provider
|
||||
}
|
|
@ -64,16 +64,16 @@ func (s *Service) SubmitBeaconBlock(ctx context.Context, block *spec.SignedBeaco
|
|||
return nil
|
||||
}
|
||||
|
||||
// SubmitAttestation submits a beacon block attestation.
|
||||
func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attestation) error {
|
||||
if attestation == nil {
|
||||
return errors.New("no attestation supplied")
|
||||
// SubmitAttestations submits multiple attestations.
|
||||
func (s *Service) SubmitAttestations(ctx context.Context, attestations []*spec.Attestation) error {
|
||||
if len(attestations) == 0 {
|
||||
return errors.New("no attestations supplied")
|
||||
}
|
||||
|
||||
if e := log.Trace(); e.Enabled() {
|
||||
data, err := json.Marshal(attestation)
|
||||
data, err := json.Marshal(attestations)
|
||||
if err == nil {
|
||||
e.Str("attestation", string(data)).Msg("Not submitting attestation")
|
||||
e.Str("attestations", string(data)).Msg("Not submitting attestations")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ func TestSubmit(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
require.EqualError(t, s.SubmitBeaconBlock(context.Background(), nil), "no beacon block supplied")
|
||||
require.EqualError(t, s.SubmitAttestation(context.Background(), nil), "no attestation supplied")
|
||||
require.EqualError(t, s.SubmitAttestations(context.Background(), nil), "no attestations supplied")
|
||||
require.EqualError(t, s.SubmitBeaconCommitteeSubscriptions(context.Background(), nil), "no subscriptions supplied")
|
||||
require.EqualError(t, s.SubmitAggregateAttestations(context.Background(), nil), "no aggregate attestations supplied")
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func TestInterfaces(t *testing.T) {
|
|||
)
|
||||
require.NoError(t, err)
|
||||
require.Implements(t, (*submitter.BeaconBlockSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.AttestationSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.AttestationsSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.BeaconCommitteeSubscriptionsSubmitter)(nil), s)
|
||||
require.Implements(t, (*submitter.AggregateAttestationsSubmitter)(nil), s)
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ import (
|
|||
// Service is the submitter service.
|
||||
type Service interface{}
|
||||
|
||||
// AttestationSubmitter is the interface for a submitter of attestations.
|
||||
type AttestationSubmitter interface {
|
||||
// SubmitAttestation submits an attestation.
|
||||
SubmitAttestation(ctx context.Context, block *spec.Attestation) error
|
||||
// AttestationsSubmitter is the interface for a submitter of attestations.
|
||||
type AttestationsSubmitter interface {
|
||||
// SubmitAttestations submits multiple attestations.
|
||||
SubmitAttestations(ctx context.Context, attestations []*spec.Attestation) error
|
||||
}
|
||||
|
||||
// BeaconBlockSubmitter is the interface for a submitter of beacon blocks.
|
||||
|
|
Loading…
Reference in New Issue