mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
11 Commits
epbs-propo
...
revert-148
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72305974ef | ||
|
|
91cdd318a8 | ||
|
|
3dc00816fb | ||
|
|
e331d5b371 | ||
|
|
8d5090ce54 | ||
|
|
25244d906d | ||
|
|
aa445713ac | ||
|
|
177769a1ce | ||
|
|
967e9255a2 | ||
|
|
910609a75f | ||
|
|
f9c202190a |
@@ -52,6 +52,9 @@ func HistoricalSummaryFromConsensus(s *eth.HistoricalSummary) *HistoricalSummary
|
||||
}
|
||||
|
||||
func (s *SignedBLSToExecutionChange) ToConsensus() (*eth.SignedBLSToExecutionChange, error) {
|
||||
if s.Message == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Message")
|
||||
}
|
||||
change, err := s.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
@@ -103,14 +106,17 @@ func SignedBLSChangeFromConsensus(ch *eth.SignedBLSToExecutionChange) *SignedBLS
|
||||
|
||||
func SignedBLSChangesToConsensus(src []*SignedBLSToExecutionChange) ([]*eth.SignedBLSToExecutionChange, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "SignedBLSToExecutionChanges")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "SignedBLSToExecutionChanges")
|
||||
}
|
||||
changes := make([]*eth.SignedBLSToExecutionChange, len(src))
|
||||
for i, ch := range src {
|
||||
if ch == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
changes[i], err = ch.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i))
|
||||
@@ -156,6 +162,9 @@ func ForkFromConsensus(f *eth.Fork) *Fork {
|
||||
}
|
||||
|
||||
func (s *SignedValidatorRegistration) ToConsensus() (*eth.SignedValidatorRegistrationV1, error) {
|
||||
if s.Message == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Message")
|
||||
}
|
||||
msg, err := s.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
@@ -212,6 +221,9 @@ func SignedValidatorRegistrationFromConsensus(vr *eth.SignedValidatorRegistratio
|
||||
}
|
||||
|
||||
func (s *SignedContributionAndProof) ToConsensus() (*eth.SignedContributionAndProof, error) {
|
||||
if s.Message == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Message")
|
||||
}
|
||||
msg, err := s.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
@@ -236,6 +248,9 @@ func SignedContributionAndProofFromConsensus(c *eth.SignedContributionAndProof)
|
||||
}
|
||||
|
||||
func (c *ContributionAndProof) ToConsensus() (*eth.ContributionAndProof, error) {
|
||||
if c.Contribution == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Contribution")
|
||||
}
|
||||
contribution, err := c.Contribution.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Contribution")
|
||||
@@ -307,6 +322,9 @@ func SyncCommitteeContributionFromConsensus(c *eth.SyncCommitteeContribution) *S
|
||||
}
|
||||
|
||||
func (s *SignedAggregateAttestationAndProof) ToConsensus() (*eth.SignedAggregateAttestationAndProof, error) {
|
||||
if s.Message == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Message")
|
||||
}
|
||||
msg, err := s.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
@@ -327,6 +345,9 @@ func (a *AggregateAttestationAndProof) ToConsensus() (*eth.AggregateAttestationA
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "AggregatorIndex")
|
||||
}
|
||||
if a.Aggregate == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Aggregate")
|
||||
}
|
||||
agg, err := a.Aggregate.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Aggregate")
|
||||
@@ -343,6 +364,9 @@ func (a *AggregateAttestationAndProof) ToConsensus() (*eth.AggregateAttestationA
|
||||
}
|
||||
|
||||
func (s *SignedAggregateAttestationAndProofElectra) ToConsensus() (*eth.SignedAggregateAttestationAndProofElectra, error) {
|
||||
if s.Message == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Message")
|
||||
}
|
||||
msg, err := s.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
@@ -363,6 +387,9 @@ func (a *AggregateAttestationAndProofElectra) ToConsensus() (*eth.AggregateAttes
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "AggregatorIndex")
|
||||
}
|
||||
if a.Aggregate == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Aggregate")
|
||||
}
|
||||
agg, err := a.Aggregate.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Aggregate")
|
||||
@@ -383,6 +410,9 @@ func (a *Attestation) ToConsensus() (*eth.Attestation, error) {
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "AggregationBits")
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Data")
|
||||
}
|
||||
data, err := a.Data.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Data")
|
||||
@@ -412,6 +442,9 @@ func (a *AttestationElectra) ToConsensus() (*eth.AttestationElectra, error) {
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "AggregationBits")
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Data")
|
||||
}
|
||||
data, err := a.Data.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Data")
|
||||
@@ -433,6 +466,15 @@ func (a *AttestationElectra) ToConsensus() (*eth.AttestationElectra, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SingleAttFromConsensus(a *eth.SingleAttestation) *SingleAttestation {
|
||||
return &SingleAttestation{
|
||||
CommitteeIndex: fmt.Sprintf("%d", a.CommitteeId),
|
||||
AttesterIndex: fmt.Sprintf("%d", a.AttesterIndex),
|
||||
Data: AttDataFromConsensus(a.Data),
|
||||
Signature: hexutil.Encode(a.Signature),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *SingleAttestation) ToConsensus() (*eth.SingleAttestation, error) {
|
||||
ci, err := strconv.ParseUint(a.CommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
@@ -442,6 +484,9 @@ func (a *SingleAttestation) ToConsensus() (*eth.SingleAttestation, error) {
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "AttesterIndex")
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Data")
|
||||
}
|
||||
data, err := a.Data.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Data")
|
||||
@@ -481,10 +526,16 @@ func (a *AttestationData) ToConsensus() (*eth.AttestationData, error) {
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "BeaconBlockRoot")
|
||||
}
|
||||
if a.Source == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Source")
|
||||
}
|
||||
source, err := a.Source.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Source")
|
||||
}
|
||||
if a.Target == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Target")
|
||||
}
|
||||
target, err := a.Target.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Target")
|
||||
@@ -584,15 +635,17 @@ func (b *BeaconCommitteeSubscription) ToConsensus() (*validator.BeaconCommitteeS
|
||||
}
|
||||
|
||||
func (e *SignedVoluntaryExit) ToConsensus() (*eth.SignedVoluntaryExit, error) {
|
||||
sig, err := bytesutil.DecodeHexWithLength(e.Signature, fieldparams.BLSSignatureLength)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Signature")
|
||||
if e.Message == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Message")
|
||||
}
|
||||
exit, err := e.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
}
|
||||
|
||||
sig, err := bytesutil.DecodeHexWithLength(e.Signature, fieldparams.BLSSignatureLength)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Signature")
|
||||
}
|
||||
return ð.SignedVoluntaryExit{
|
||||
Exit: exit,
|
||||
Signature: sig,
|
||||
@@ -695,10 +748,16 @@ func Eth1DataFromConsensus(e1d *eth.Eth1Data) *Eth1Data {
|
||||
}
|
||||
|
||||
func (s *ProposerSlashing) ToConsensus() (*eth.ProposerSlashing, error) {
|
||||
if s.SignedHeader1 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "SignedHeader1")
|
||||
}
|
||||
h1, err := s.SignedHeader1.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "SignedHeader1")
|
||||
}
|
||||
if s.SignedHeader2 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "SignedHeader2")
|
||||
}
|
||||
h2, err := s.SignedHeader2.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "SignedHeader2")
|
||||
@@ -711,10 +770,16 @@ func (s *ProposerSlashing) ToConsensus() (*eth.ProposerSlashing, error) {
|
||||
}
|
||||
|
||||
func (s *AttesterSlashing) ToConsensus() (*eth.AttesterSlashing, error) {
|
||||
if s.Attestation1 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Attestation1")
|
||||
}
|
||||
att1, err := s.Attestation1.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Attestation1")
|
||||
}
|
||||
if s.Attestation2 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Attestation2")
|
||||
}
|
||||
att2, err := s.Attestation2.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Attestation2")
|
||||
@@ -723,10 +788,16 @@ func (s *AttesterSlashing) ToConsensus() (*eth.AttesterSlashing, error) {
|
||||
}
|
||||
|
||||
func (s *AttesterSlashingElectra) ToConsensus() (*eth.AttesterSlashingElectra, error) {
|
||||
if s.Attestation1 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Attestation1")
|
||||
}
|
||||
att1, err := s.Attestation1.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Attestation1")
|
||||
}
|
||||
if s.Attestation2 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Attestation2")
|
||||
}
|
||||
att2, err := s.Attestation2.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Attestation2")
|
||||
@@ -747,6 +818,9 @@ func (a *IndexedAttestation) ToConsensus() (*eth.IndexedAttestation, error) {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("AttestingIndices[%d]", i))
|
||||
}
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Data")
|
||||
}
|
||||
data, err := a.Data.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Data")
|
||||
@@ -779,6 +853,9 @@ func (a *IndexedAttestationElectra) ToConsensus() (*eth.IndexedAttestationElectr
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("AttestingIndices[%d]", i))
|
||||
}
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, "Data")
|
||||
}
|
||||
data, err := a.Data.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Data")
|
||||
@@ -934,11 +1011,11 @@ func (d *DepositRequest) ToConsensus() (*enginev1.DepositRequest, error) {
|
||||
|
||||
func ProposerSlashingsToConsensus(src []*ProposerSlashing) ([]*eth.ProposerSlashing, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "ProposerSlashings")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "ProposerSlashings")
|
||||
}
|
||||
proposerSlashings := make([]*eth.ProposerSlashing, len(src))
|
||||
for i, s := range src {
|
||||
@@ -1067,11 +1144,11 @@ func ProposerSlashingFromConsensus(src *eth.ProposerSlashing) *ProposerSlashing
|
||||
|
||||
func AttesterSlashingsToConsensus(src []*AttesterSlashing) ([]*eth.AttesterSlashing, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "AttesterSlashings")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "AttesterSlashings")
|
||||
}
|
||||
|
||||
attesterSlashings := make([]*eth.AttesterSlashing, len(src))
|
||||
@@ -1082,10 +1159,19 @@ func AttesterSlashingsToConsensus(src []*AttesterSlashing) ([]*eth.AttesterSlash
|
||||
if s.Attestation1 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1", i))
|
||||
}
|
||||
|
||||
if s.Attestation1.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1.Data", i))
|
||||
}
|
||||
|
||||
if s.Attestation2 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2", i))
|
||||
}
|
||||
|
||||
if s.Attestation2.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2.Data", i))
|
||||
}
|
||||
|
||||
a1Sig, err := bytesutil.DecodeHexWithLength(s.Attestation1.Signature, fieldparams.BLSSignatureLength)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Signature", i))
|
||||
@@ -1102,6 +1188,7 @@ func AttesterSlashingsToConsensus(src []*AttesterSlashing) ([]*eth.AttesterSlash
|
||||
}
|
||||
a1AttestingIndices[j] = attestingIndex
|
||||
}
|
||||
|
||||
a1Data, err := s.Attestation1.Data.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Data", i))
|
||||
@@ -1199,11 +1286,11 @@ func AttesterSlashingFromConsensus(src *eth.AttesterSlashing) *AttesterSlashing
|
||||
|
||||
func AttesterSlashingsElectraToConsensus(src []*AttesterSlashingElectra) ([]*eth.AttesterSlashingElectra, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "AttesterSlashingsElectra")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, fieldparams.MaxAttesterSlashingsElectra)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "AttesterSlashingsElectra")
|
||||
}
|
||||
|
||||
attesterSlashings := make([]*eth.AttesterSlashingElectra, len(src))
|
||||
@@ -1211,13 +1298,23 @@ func AttesterSlashingsElectraToConsensus(src []*AttesterSlashingElectra) ([]*eth
|
||||
if s == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
|
||||
if s.Attestation1 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1", i))
|
||||
}
|
||||
|
||||
if s.Attestation1.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1.Data", i))
|
||||
}
|
||||
|
||||
if s.Attestation2 == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2", i))
|
||||
}
|
||||
|
||||
if s.Attestation2.Data == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2.Data", i))
|
||||
}
|
||||
|
||||
a1Sig, err := bytesutil.DecodeHexWithLength(s.Attestation1.Signature, fieldparams.BLSSignatureLength)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Signature", i))
|
||||
@@ -1331,15 +1428,18 @@ func AttesterSlashingElectraFromConsensus(src *eth.AttesterSlashingElectra) *Att
|
||||
|
||||
func AttsToConsensus(src []*Attestation) ([]*eth.Attestation, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "Attestations")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "Attestations")
|
||||
}
|
||||
|
||||
atts := make([]*eth.Attestation, len(src))
|
||||
for i, a := range src {
|
||||
if a == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
atts[i], err = a.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i))
|
||||
@@ -1358,15 +1458,18 @@ func AttsFromConsensus(src []*eth.Attestation) []*Attestation {
|
||||
|
||||
func AttsElectraToConsensus(src []*AttestationElectra) ([]*eth.AttestationElectra, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "AttestationsElectra")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "AttestationsElectra")
|
||||
}
|
||||
|
||||
atts := make([]*eth.AttestationElectra, len(src))
|
||||
for i, a := range src {
|
||||
if a == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
atts[i], err = a.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i))
|
||||
@@ -1385,11 +1488,11 @@ func AttsElectraFromConsensus(src []*eth.AttestationElectra) []*AttestationElect
|
||||
|
||||
func DepositsToConsensus(src []*Deposit) ([]*eth.Deposit, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "Deposits")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "Deposits")
|
||||
}
|
||||
|
||||
deposits := make([]*eth.Deposit, len(src))
|
||||
@@ -1461,15 +1564,18 @@ func DepositsFromConsensus(src []*eth.Deposit) []*Deposit {
|
||||
|
||||
func SignedExitsToConsensus(src []*SignedVoluntaryExit) ([]*eth.SignedVoluntaryExit, error) {
|
||||
if src == nil {
|
||||
return nil, errNilValue
|
||||
return nil, server.NewDecodeError(errNilValue, "SignedVoluntaryExits")
|
||||
}
|
||||
err := slice.VerifyMaxLength(src, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, server.NewDecodeError(err, "SignedVoluntaryExits")
|
||||
}
|
||||
|
||||
exits := make([]*eth.SignedVoluntaryExit, len(src))
|
||||
for i, e := range src {
|
||||
if e == nil {
|
||||
return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
exits[i], err = e.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i))
|
||||
|
||||
@@ -24,3 +24,96 @@ func TestDepositSnapshotFromConsensus(t *testing.T) {
|
||||
require.Equal(t, "0x1234", res.ExecutionBlockHash)
|
||||
require.Equal(t, "67890", res.ExecutionBlockHeight)
|
||||
}
|
||||
|
||||
func TestSignedBLSToExecutionChange_ToConsensus(t *testing.T) {
|
||||
s := &SignedBLSToExecutionChange{Message: nil, Signature: ""}
|
||||
_, err := s.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestSignedValidatorRegistration_ToConsensus(t *testing.T) {
|
||||
s := &SignedValidatorRegistration{Message: nil, Signature: ""}
|
||||
_, err := s.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestSignedContributionAndProof_ToConsensus(t *testing.T) {
|
||||
s := &SignedContributionAndProof{Message: nil, Signature: ""}
|
||||
_, err := s.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestContributionAndProof_ToConsensus(t *testing.T) {
|
||||
c := &ContributionAndProof{
|
||||
Contribution: nil,
|
||||
AggregatorIndex: "invalid",
|
||||
SelectionProof: "",
|
||||
}
|
||||
_, err := c.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestSignedAggregateAttestationAndProof_ToConsensus(t *testing.T) {
|
||||
s := &SignedAggregateAttestationAndProof{Message: nil, Signature: ""}
|
||||
_, err := s.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestAggregateAttestationAndProof_ToConsensus(t *testing.T) {
|
||||
a := &AggregateAttestationAndProof{
|
||||
AggregatorIndex: "1",
|
||||
Aggregate: nil,
|
||||
SelectionProof: "",
|
||||
}
|
||||
_, err := a.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestAttestation_ToConsensus(t *testing.T) {
|
||||
a := &Attestation{
|
||||
AggregationBits: "0x10",
|
||||
Data: nil,
|
||||
Signature: "",
|
||||
}
|
||||
_, err := a.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestSingleAttestation_ToConsensus(t *testing.T) {
|
||||
s := &SingleAttestation{
|
||||
CommitteeIndex: "1",
|
||||
AttesterIndex: "1",
|
||||
Data: nil,
|
||||
Signature: "",
|
||||
}
|
||||
_, err := s.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestSignedVoluntaryExit_ToConsensus(t *testing.T) {
|
||||
s := &SignedVoluntaryExit{Message: nil, Signature: ""}
|
||||
_, err := s.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestProposerSlashing_ToConsensus(t *testing.T) {
|
||||
p := &ProposerSlashing{SignedHeader1: nil, SignedHeader2: nil}
|
||||
_, err := p.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestAttesterSlashing_ToConsensus(t *testing.T) {
|
||||
a := &AttesterSlashing{Attestation1: nil, Attestation2: nil}
|
||||
_, err := a.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
func TestIndexedAttestation_ToConsensus(t *testing.T) {
|
||||
a := &IndexedAttestation{
|
||||
AttestingIndices: []string{"1"},
|
||||
Data: nil,
|
||||
Signature: "invalid",
|
||||
}
|
||||
_, err := a.ToConsensus()
|
||||
require.ErrorContains(t, errNilValue.Error(), err)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ go_library(
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/electra:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/feed:go_default_library",
|
||||
"//beacon-chain/core/feed/state:go_default_library",
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
@@ -468,7 +469,7 @@ func (s *Service) validateStateTransition(ctx context.Context, preState state.Be
|
||||
stateTransitionStartTime := time.Now()
|
||||
postState, err := transition.ExecuteStateTransition(ctx, preState, signed)
|
||||
if err != nil {
|
||||
if ctx.Err() != nil {
|
||||
if ctx.Err() != nil || electra.IsExecutionRequestError(err) {
|
||||
return nil, err
|
||||
}
|
||||
return nil, invalidBlock{error: err}
|
||||
|
||||
@@ -8,6 +8,7 @@ go_library(
|
||||
"consolidations.go",
|
||||
"deposits.go",
|
||||
"effective_balance_updates.go",
|
||||
"error.go",
|
||||
"registry_updates.go",
|
||||
"transition.go",
|
||||
"transition_no_verify_sig.go",
|
||||
@@ -55,13 +56,16 @@ go_test(
|
||||
"deposit_fuzz_test.go",
|
||||
"deposits_test.go",
|
||||
"effective_balance_updates_test.go",
|
||||
"error_test.go",
|
||||
"export_test.go",
|
||||
"registry_updates_test.go",
|
||||
"transition_no_verify_sig_test.go",
|
||||
"transition_test.go",
|
||||
"upgrade_test.go",
|
||||
"validator_test.go",
|
||||
"withdrawals_test.go",
|
||||
],
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
@@ -86,6 +90,7 @@ go_test(
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
|
||||
16
beacon-chain/core/electra/error.go
Normal file
16
beacon-chain/core/electra/error.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package electra
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
type execReqErr struct {
|
||||
error
|
||||
}
|
||||
|
||||
// IsExecutionRequestError returns true if the error has `execReqErr`.
|
||||
func IsExecutionRequestError(e error) bool {
|
||||
if e == nil {
|
||||
return false
|
||||
}
|
||||
var d execReqErr
|
||||
return errors.As(e, &d)
|
||||
}
|
||||
45
beacon-chain/core/electra/error_test.go
Normal file
45
beacon-chain/core/electra/error_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package electra
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestIsExecutionRequestError(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "nil error",
|
||||
err: nil,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "random error",
|
||||
err: errors.New("some error"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "execution request error",
|
||||
err: execReqErr{errors.New("execution request failed")},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "wrapped execution request error",
|
||||
err: errors.Wrap(execReqErr{errors.New("execution request failed")}, "wrapped"),
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := IsExecutionRequestError(tt.err)
|
||||
if got != tt.want {
|
||||
t.Errorf("IsExecutionRequestError(%v) = %v, want %v", tt.err, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package electra
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks"
|
||||
@@ -82,16 +81,31 @@ func ProcessOperations(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution requests")
|
||||
}
|
||||
for _, d := range requests.Deposits {
|
||||
if d == nil {
|
||||
return nil, errors.New("nil deposit request")
|
||||
}
|
||||
}
|
||||
st, err = ProcessDepositRequests(ctx, st, requests.Deposits)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process deposit requests")
|
||||
return nil, execReqErr{errors.Wrap(err, "could not process deposit requests")}
|
||||
}
|
||||
for _, w := range requests.Withdrawals {
|
||||
if w == nil {
|
||||
return nil, errors.New("nil withdrawal request")
|
||||
}
|
||||
}
|
||||
st, err = ProcessWithdrawalRequests(ctx, st, requests.Withdrawals)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process withdrawal requests")
|
||||
return nil, execReqErr{errors.Wrap(err, "could not process withdrawal requests")}
|
||||
}
|
||||
for _, c := range requests.Consolidations {
|
||||
if c == nil {
|
||||
return nil, errors.New("nil consolidation request")
|
||||
}
|
||||
}
|
||||
if err := ProcessConsolidationRequests(ctx, st, requests.Consolidations); err != nil {
|
||||
return nil, fmt.Errorf("could not process consolidation requests: %w", err)
|
||||
return nil, execReqErr{errors.Wrap(err, "could not process consolidation requests")}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
61
beacon-chain/core/electra/transition_no_verify_sig_test.go
Normal file
61
beacon-chain/core/electra/transition_no_verify_sig_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package electra_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestProcessOperationsWithNilRequests(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
modifyBlk func(blockElectra *ethpb.SignedBeaconBlockElectra)
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
name: "Nil deposit request",
|
||||
modifyBlk: func(blk *ethpb.SignedBeaconBlockElectra) {
|
||||
blk.Block.Body.ExecutionRequests.Deposits = []*enginev1.DepositRequest{nil}
|
||||
},
|
||||
errMsg: "nil deposit request",
|
||||
},
|
||||
{
|
||||
name: "Nil withdrawal request",
|
||||
modifyBlk: func(blk *ethpb.SignedBeaconBlockElectra) {
|
||||
blk.Block.Body.ExecutionRequests.Withdrawals = []*enginev1.WithdrawalRequest{nil}
|
||||
},
|
||||
errMsg: "nil withdrawal request",
|
||||
},
|
||||
{
|
||||
name: "Nil consolidation request",
|
||||
modifyBlk: func(blk *ethpb.SignedBeaconBlockElectra) {
|
||||
blk.Block.Body.ExecutionRequests.Consolidations = []*enginev1.ConsolidationRequest{nil}
|
||||
},
|
||||
errMsg: "nil consolidation request",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
st, ks := util.DeterministicGenesisStateElectra(t, 128)
|
||||
blk, err := util.GenerateFullBlockElectra(st, ks, util.DefaultBlockGenConfig(), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
tc.modifyBlk(blk)
|
||||
|
||||
b, err := blocks.NewSignedBeaconBlock(blk)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, st.SetSlot(1))
|
||||
|
||||
_, err = electra.ProcessOperations(context.Background(), st, b.Block())
|
||||
require.ErrorContains(t, tc.errMsg, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,9 @@ const (
|
||||
|
||||
// AttesterSlashingReceived is sent after an attester slashing is received from gossip or rpc
|
||||
AttesterSlashingReceived = 8
|
||||
|
||||
// SingleAttReceived is sent after a single attestation object is received from gossip or rpc
|
||||
SingleAttReceived = 9
|
||||
)
|
||||
|
||||
// UnAggregatedAttReceivedData is the data sent with UnaggregatedAttReceived events.
|
||||
@@ -43,7 +46,7 @@ type UnAggregatedAttReceivedData struct {
|
||||
// AggregatedAttReceivedData is the data sent with AggregatedAttReceived events.
|
||||
type AggregatedAttReceivedData struct {
|
||||
// Attestation is the aggregated attestation object.
|
||||
Attestation *ethpb.AggregateAttestationAndProof
|
||||
Attestation ethpb.AggregateAttAndProof
|
||||
}
|
||||
|
||||
// ExitReceivedData is the data sent with ExitReceived events.
|
||||
@@ -77,3 +80,8 @@ type ProposerSlashingReceivedData struct {
|
||||
type AttesterSlashingReceivedData struct {
|
||||
AttesterSlashing ethpb.AttSlashing
|
||||
}
|
||||
|
||||
// SingleAttReceivedData is the data sent with SingleAttReceived events.
|
||||
type SingleAttReceivedData struct {
|
||||
Attestation ethpb.Att
|
||||
}
|
||||
|
||||
@@ -34,11 +34,17 @@ func (s *Service) canUpdateAttestedValidator(idx primitives.ValidatorIndex, slot
|
||||
|
||||
// attestingIndices returns the indices of validators that participated in the given aggregated attestation.
|
||||
func attestingIndices(ctx context.Context, state state.BeaconState, att ethpb.Att) ([]uint64, error) {
|
||||
committee, err := helpers.BeaconCommitteeFromState(ctx, state, att.GetData().Slot, att.GetData().CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
committeeBits := att.CommitteeBitsVal().BitIndices()
|
||||
committees := make([][]primitives.ValidatorIndex, len(committeeBits))
|
||||
var err error
|
||||
for i, ci := range committeeBits {
|
||||
committees[i], err = helpers.BeaconCommitteeFromState(ctx, state, att.GetData().Slot, primitives.CommitteeIndex(ci))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return attestation.AttestingIndices(att, committee)
|
||||
|
||||
return attestation.AttestingIndices(att, committees...)
|
||||
}
|
||||
|
||||
// logMessageTimelyFlagsForIndex returns the log message with performance info for the attestation (head, source, target)
|
||||
|
||||
@@ -236,6 +236,13 @@ func (s *Service) monitorRoutine(stateChannel chan *feed.Event, stateSub event.S
|
||||
} else {
|
||||
s.processAggregatedAttestation(s.ctx, data.Attestation)
|
||||
}
|
||||
case operation.SingleAttReceived:
|
||||
data, ok := e.Data.(*operation.SingleAttReceivedData)
|
||||
if !ok {
|
||||
log.Error("Event feed data is not of type *operation.SingleAttReceivedData")
|
||||
} else {
|
||||
s.processUnaggregatedAttestation(s.ctx, data.Attestation)
|
||||
}
|
||||
case operation.ExitReceived:
|
||||
data, ok := e.Data.(*operation.ExitReceivedData)
|
||||
if !ok {
|
||||
|
||||
@@ -320,6 +320,13 @@ func (s *Server) handleAttestationsElectra(
|
||||
}
|
||||
|
||||
for i, singleAtt := range validAttestations {
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.SingleAttReceived,
|
||||
Data: &operation.SingleAttReceivedData{
|
||||
Attestation: singleAtt,
|
||||
},
|
||||
})
|
||||
|
||||
targetState, err := s.AttestationStateFetcher.AttestationTargetState(ctx, singleAtt.Data.Target)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not get target state for attestation")
|
||||
@@ -330,13 +337,6 @@ func (s *Server) handleAttestationsElectra(
|
||||
}
|
||||
att := singleAtt.ToAttestationElectra(committee)
|
||||
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
|
||||
wantedEpoch := slots.ToEpoch(att.Data.Slot)
|
||||
vals, err := s.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
if err != nil {
|
||||
|
||||
@@ -45,6 +45,8 @@ const (
|
||||
BlockTopic = "block"
|
||||
// AttestationTopic represents a new submitted attestation event topic.
|
||||
AttestationTopic = "attestation"
|
||||
// SingleAttestationTopic represents a new submitted single attestation event topic.
|
||||
SingleAttestationTopic = "single_attestation"
|
||||
// VoluntaryExitTopic represents a new performed voluntary exit event topic.
|
||||
VoluntaryExitTopic = "voluntary_exit"
|
||||
// FinalizedCheckpointTopic represents a new finalized checkpoint event topic.
|
||||
@@ -92,6 +94,7 @@ type lazyReader func() io.Reader
|
||||
var opsFeedEventTopics = map[feed.EventType]string{
|
||||
operation.AggregatedAttReceived: AttestationTopic,
|
||||
operation.UnaggregatedAttReceived: AttestationTopic,
|
||||
operation.SingleAttReceived: SingleAttestationTopic,
|
||||
operation.ExitReceived: VoluntaryExitTopic,
|
||||
operation.SyncCommitteeContributionReceived: SyncCommitteeContributionTopic,
|
||||
operation.BLSToExecutionChangeReceived: BLSToExecutionChangeTopic,
|
||||
@@ -403,7 +406,7 @@ func (es *eventStreamer) writeOutbox(ctx context.Context, w *streamingResponseWr
|
||||
func jsonMarshalReader(name string, v any) io.Reader {
|
||||
d, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("type_name", fmt.Sprintf("%T", v)).Error("Could not marshal event data.")
|
||||
log.WithError(err).WithField("type_name", fmt.Sprintf("%T", v)).Error("Could not marshal event data")
|
||||
return nil
|
||||
}
|
||||
return bytes.NewBufferString("event: " + name + "\ndata: " + string(d) + "\n\n")
|
||||
@@ -415,6 +418,8 @@ func topicForEvent(event *feed.Event) string {
|
||||
return AttestationTopic
|
||||
case *operation.UnAggregatedAttReceivedData:
|
||||
return AttestationTopic
|
||||
case *operation.SingleAttReceivedData:
|
||||
return SingleAttestationTopic
|
||||
case *operation.ExitReceivedData:
|
||||
return VoluntaryExitTopic
|
||||
case *operation.SyncCommitteeContributionReceivedData:
|
||||
@@ -464,10 +469,20 @@ func (s *Server) lazyReaderForEvent(ctx context.Context, event *feed.Event, topi
|
||||
return jsonMarshalReader(eventName, structs.HeadEventFromV1(v))
|
||||
}, nil
|
||||
case *operation.AggregatedAttReceivedData:
|
||||
return func() io.Reader {
|
||||
att := structs.AttFromConsensus(v.Attestation.Aggregate)
|
||||
return jsonMarshalReader(eventName, att)
|
||||
}, nil
|
||||
switch att := v.Attestation.AggregateVal().(type) {
|
||||
case *eth.Attestation:
|
||||
return func() io.Reader {
|
||||
att := structs.AttFromConsensus(att)
|
||||
return jsonMarshalReader(eventName, att)
|
||||
}, nil
|
||||
case *eth.AttestationElectra:
|
||||
return func() io.Reader {
|
||||
att := structs.AttElectraFromConsensus(att)
|
||||
return jsonMarshalReader(eventName, att)
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of AggregatedAttReceivedData", v.Attestation)
|
||||
}
|
||||
case *operation.UnAggregatedAttReceivedData:
|
||||
switch att := v.Attestation.(type) {
|
||||
case *eth.Attestation:
|
||||
@@ -483,6 +498,16 @@ func (s *Server) lazyReaderForEvent(ctx context.Context, event *feed.Event, topi
|
||||
default:
|
||||
return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of UnAggregatedAttReceivedData", v.Attestation)
|
||||
}
|
||||
case *operation.SingleAttReceivedData:
|
||||
switch att := v.Attestation.(type) {
|
||||
case *eth.SingleAttestation:
|
||||
return func() io.Reader {
|
||||
att := structs.SingleAttFromConsensus(att)
|
||||
return jsonMarshalReader(eventName, att)
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of SingleAttReceivedData", v.Attestation)
|
||||
}
|
||||
case *operation.ExitReceivedData:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.SignedExitFromConsensus(v.Exit))
|
||||
|
||||
@@ -110,6 +110,7 @@ func (tr *topicRequest) testHttpRequest(ctx context.Context, _ *testing.T) *http
|
||||
func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
topics, err := newTopicRequest([]string{
|
||||
AttestationTopic,
|
||||
SingleAttestationTopic,
|
||||
VoluntaryExitTopic,
|
||||
SyncCommitteeContributionTopic,
|
||||
BLSToExecutionChangeTopic,
|
||||
@@ -123,13 +124,13 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
vblob := blocks.NewVerifiedROBlob(ro)
|
||||
|
||||
return topics, []*feed.Event{
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: util.HydrateAttestation(ð.Attestation{}),
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.AggregatedAttReceived,
|
||||
Data: &operation.AggregatedAttReceivedData{
|
||||
Attestation: ð.AggregateAttestationAndProof{
|
||||
@@ -139,7 +140,13 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.SingleAttReceived,
|
||||
Data: &operation.SingleAttReceivedData{
|
||||
Attestation: util.HydrateSingleAttestation(ð.SingleAttestation{}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: operation.ExitReceived,
|
||||
Data: &operation.ExitReceivedData{
|
||||
Exit: ð.SignedVoluntaryExit{
|
||||
@@ -151,7 +158,7 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.SyncCommitteeContributionReceived,
|
||||
Data: &operation.SyncCommitteeContributionReceivedData{
|
||||
Contribution: ð.SignedContributionAndProof{
|
||||
@@ -170,7 +177,7 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.BLSToExecutionChangeReceived,
|
||||
Data: &operation.BLSToExecutionChangeReceivedData{
|
||||
Change: ð.SignedBLSToExecutionChange{
|
||||
@@ -183,13 +190,13 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.BlobSidecarReceived,
|
||||
Data: &operation.BlobSidecarReceivedData{
|
||||
Blob: &vblob,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.AttesterSlashingReceived,
|
||||
Data: &operation.AttesterSlashingReceivedData{
|
||||
AttesterSlashing: ð.AttesterSlashing{
|
||||
@@ -222,7 +229,7 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.AttesterSlashingReceived,
|
||||
Data: &operation.AttesterSlashingReceivedData{
|
||||
AttesterSlashing: ð.AttesterSlashingElectra{
|
||||
@@ -255,7 +262,7 @@ func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: operation.ProposerSlashingReceived,
|
||||
Data: &operation.ProposerSlashingReceivedData{
|
||||
ProposerSlashing: ð.ProposerSlashing{
|
||||
@@ -367,7 +374,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
b, err := blocks.NewSignedBeaconBlock(util.HydrateSignedBeaconBlock(ð.SignedBeaconBlock{}))
|
||||
require.NoError(t, err)
|
||||
events := []*feed.Event{
|
||||
&feed.Event{
|
||||
{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: 0,
|
||||
@@ -377,7 +384,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
Optimistic: false,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: statefeed.NewHead,
|
||||
Data: ðpb.EventHead{
|
||||
Slot: 0,
|
||||
@@ -389,7 +396,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: statefeed.Reorg,
|
||||
Data: ðpb.EventChainReorg{
|
||||
Slot: 0,
|
||||
@@ -402,7 +409,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
{
|
||||
Type: statefeed.FinalizedCheckpoint,
|
||||
Data: ðpb.EventFinalizedCheckpoint{
|
||||
Block: make([]byte, 32),
|
||||
@@ -525,7 +532,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
request := topics.testHttpRequest(testSync.ctx, t)
|
||||
w := NewStreamingResponseWriterRecorder(testSync.ctx)
|
||||
events := []*feed.Event{
|
||||
&feed.Event{
|
||||
{
|
||||
Type: statefeed.PayloadAttributes,
|
||||
Data: payloadattribute.EventData{
|
||||
ProposerIndex: 0,
|
||||
@@ -577,7 +584,7 @@ func TestStuckReaderScenarios(t *testing.T) {
|
||||
|
||||
func wedgedWriterTestCase(t *testing.T, queueDepth func([]*feed.Event) int) {
|
||||
topics, events := operationEventsFixtures(t)
|
||||
require.Equal(t, 9, len(events))
|
||||
require.Equal(t, 10, len(events))
|
||||
|
||||
// set eventFeedDepth to a number lower than the events we intend to send to force the server to drop the reader.
|
||||
stn := mockChain.NewEventFeedWrapper()
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -46,7 +45,7 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation")
|
||||
defer span.End()
|
||||
|
||||
resp, err := vs.proposeAtt(ctx, att, nil, att.GetData().CommitteeIndex)
|
||||
resp, err := vs.proposeAtt(ctx, att, att.GetData().CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -74,21 +73,20 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, singleAtt *ethp
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestationElectra")
|
||||
defer span.End()
|
||||
|
||||
resp, err := vs.proposeAtt(ctx, singleAtt, singleAtt.GetCommitteeIndex())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
targetState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, singleAtt.Data.Target)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not get target state")
|
||||
}
|
||||
committeeIndex := singleAtt.GetCommitteeIndex()
|
||||
committee, err := helpers.BeaconCommitteeFromState(ctx, targetState, singleAtt.Data.Slot, committeeIndex)
|
||||
committee, err := helpers.BeaconCommitteeFromState(ctx, targetState, singleAtt.Data.Slot, singleAtt.GetCommitteeIndex())
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not get committee")
|
||||
}
|
||||
|
||||
resp, err := vs.proposeAtt(ctx, singleAtt, committee, committeeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
singleAttCopy := singleAtt.Copy()
|
||||
att := singleAttCopy.ToAttestationElectra(committee)
|
||||
if features.Get().EnableExperimentalAttestationPool {
|
||||
@@ -158,7 +156,6 @@ func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.Comm
|
||||
func (vs *Server) proposeAtt(
|
||||
ctx context.Context,
|
||||
att ethpb.Att,
|
||||
committee []primitives.ValidatorIndex, // required post-Electra
|
||||
committeeIndex primitives.CommitteeIndex,
|
||||
) (*ethpb.AttestResponse, error) {
|
||||
if _, err := bls.SignatureFromBytes(att.GetSignature()); err != nil {
|
||||
@@ -170,24 +167,23 @@ func (vs *Server) proposeAtt(
|
||||
return nil, status.Errorf(codes.Internal, "Could not get attestation root: %v", err)
|
||||
}
|
||||
|
||||
var singleAtt *ethpb.SingleAttestation
|
||||
if att.Version() >= version.Electra {
|
||||
var ok bool
|
||||
singleAtt, ok = att.(*ethpb.SingleAttestation)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Internal, "Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, att)
|
||||
}
|
||||
att = singleAtt.ToAttestationElectra(committee)
|
||||
}
|
||||
|
||||
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received unaggregated attestation.
|
||||
vs.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
if att.IsSingle() {
|
||||
vs.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.SingleAttReceived,
|
||||
Data: &operation.SingleAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
vs.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Determine subnet to broadcast attestation to
|
||||
wantedEpoch := slots.ToEpoch(att.GetData().Slot)
|
||||
@@ -198,13 +194,7 @@ func (vs *Server) proposeAtt(
|
||||
subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committeeIndex, att.GetData().Slot)
|
||||
|
||||
// Broadcast the new attestation to the network.
|
||||
var attToBroadcast ethpb.Att
|
||||
if singleAtt != nil {
|
||||
attToBroadcast = singleAtt
|
||||
} else {
|
||||
attToBroadcast = att
|
||||
}
|
||||
if err := vs.P2P.BroadcastAttestation(ctx, subnet, attToBroadcast); err != nil {
|
||||
if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1487,8 +1487,7 @@ func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interf
|
||||
if fTrie.FieldReference().Refs() > 1 {
|
||||
var newTrie *fieldtrie.FieldTrie
|
||||
// We choose to only copy the validator
|
||||
// trie as it is pretty expensive to regenerate
|
||||
// in the event of late blocks.
|
||||
// trie as it is pretty expensive to regenerate.
|
||||
if index == types.Validators {
|
||||
newTrie = fTrie.CopyTrie()
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
prysmTime "github.com/prysmaticlabs/prysm/v5/time"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
@@ -69,18 +68,12 @@ func (s *Service) validateAggregateAndProof(ctx context.Context, pid peer.ID, ms
|
||||
|
||||
// Broadcast the aggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received aggregated attestation.
|
||||
// TODO: this will be extended to Electra in a later PR
|
||||
if m.Version() == version.Phase0 {
|
||||
phase0Att, ok := m.(*ethpb.SignedAggregateAttestationAndProof)
|
||||
if ok {
|
||||
s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.AggregatedAttReceived,
|
||||
Data: &operation.AggregatedAttReceivedData{
|
||||
Attestation: phase0Att.Message,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.AggregatedAttReceived,
|
||||
Data: &operation.AggregatedAttReceivedData{
|
||||
Attestation: m.AggregateAttestationAndProof(),
|
||||
},
|
||||
})
|
||||
|
||||
if err := helpers.ValidateSlotTargetEpoch(data); err != nil {
|
||||
return pubsub.ValidationReject, err
|
||||
|
||||
@@ -139,8 +139,9 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
||||
return validationRes, err
|
||||
}
|
||||
|
||||
var singleAtt *eth.SingleAttestation
|
||||
if att.Version() >= version.Electra {
|
||||
singleAtt, ok := att.(*eth.SingleAttestation)
|
||||
singleAtt, ok = att.(*eth.SingleAttestation)
|
||||
if !ok {
|
||||
return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, att)
|
||||
}
|
||||
@@ -183,12 +184,21 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
|
||||
|
||||
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received unaggregated attestation.
|
||||
s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
if singleAtt != nil {
|
||||
s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.SingleAttReceived,
|
||||
Data: &operation.SingleAttReceivedData{
|
||||
Attestation: singleAtt,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
s.setSeenCommitteeIndicesSlot(data.Slot, committeeIndex, att.GetAggregationBits())
|
||||
|
||||
|
||||
3
changelog/james-prysm_nil-check-to-consensus.md
Normal file
3
changelog/james-prysm_nil-check-to-consensus.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- add more nil checks on ToConsensus functions for added safety
|
||||
3
changelog/james-prysm_proposer-settings-readability.md
Normal file
3
changelog/james-prysm_proposer-settings-readability.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- improving readability on proposer settings loader
|
||||
2
changelog/kasey_warn-hist-state-rep.md
Normal file
2
changelog/kasey_warn-hist-state-rep.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Added
|
||||
- WARN log message on node startup advising of the upcoming deprecation of the --enable-historical-state-representation feature flag.
|
||||
3
changelog/pvl_trace_validator_sign_requests.md
Normal file
3
changelog/pvl_trace_validator_sign_requests.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Removed
|
||||
|
||||
- Removed a tracing span on signature requests. These requests usually took less than 5 nanoseconds and are generally not worth tracing.
|
||||
3
changelog/radek_electra-events-api.md
Normal file
3
changelog/radek_electra-events-api.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Beacon API event support for `SingleAttestation` and `SignedAggregateAttestationAndProofElectra`.
|
||||
3
changelog/radek_electra-monitor.md
Normal file
3
changelog/radek_electra-monitor.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- Fix monitor service for Electra.
|
||||
3
changelog/taran_geth_v1.14.13_update.md
Normal file
3
changelog/taran_geth_v1.14.13_update.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Dependency: Updated go-ethereum to v1.14.13
|
||||
3
changelog/tt_fix_electra_core_processing.md
Normal file
3
changelog/tt_fix_electra_core_processing.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Update electra core processing to not mark block bad if execution request error.
|
||||
@@ -166,6 +166,7 @@ func applyHoleskyFeatureFlags(ctx *cli.Context) {
|
||||
// ConfigureBeaconChain sets the global config based
|
||||
// on what flags are enabled for the beacon-chain client.
|
||||
func ConfigureBeaconChain(ctx *cli.Context) error {
|
||||
warnDeprecationUpcoming(ctx)
|
||||
complainOnDeprecatedFlags(ctx)
|
||||
cfg := &Flags{}
|
||||
if ctx.Bool(devModeFlag.Name) {
|
||||
@@ -336,6 +337,22 @@ func complainOnDeprecatedFlags(ctx *cli.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
var upcomingDeprecationExtra = map[string]string{
|
||||
enableHistoricalSpaceRepresentation.Name: "The node needs to be resynced after flag removal.",
|
||||
}
|
||||
|
||||
func warnDeprecationUpcoming(ctx *cli.Context) {
|
||||
for _, f := range upcomingDeprecation {
|
||||
if ctx.IsSet(f.Names()[0]) {
|
||||
extra := "Please remove this flag from your configuration."
|
||||
if special, ok := upcomingDeprecationExtra[f.Names()[0]]; ok {
|
||||
extra += " " + special
|
||||
}
|
||||
log.Warnf("--%s is pending deprecation and will be removed in the next release. %s", f.Names()[0], extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func logEnabled(flag cli.DocGenerationFlag) {
|
||||
var name string
|
||||
if names := flag.Names(); len(names) > 0 {
|
||||
|
||||
@@ -120,6 +120,10 @@ var deprecatedFlags = []cli.Flag{
|
||||
deprecatedEnableQuic,
|
||||
}
|
||||
|
||||
var upcomingDeprecation = []cli.Flag{
|
||||
enableHistoricalSpaceRepresentation,
|
||||
}
|
||||
|
||||
// deprecatedBeaconFlags contains flags that are still used by other components
|
||||
// and therefore cannot be added to deprecatedFlags
|
||||
var deprecatedBeaconFlags = []cli.Flag{
|
||||
|
||||
@@ -205,7 +205,7 @@ var E2EValidatorFlags = []string{
|
||||
}
|
||||
|
||||
// BeaconChainFlags contains a list of all the feature flags that apply to the beacon-chain client.
|
||||
var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []cli.Flag{
|
||||
var BeaconChainFlags = combinedFlags([]cli.Flag{
|
||||
devModeFlag,
|
||||
disableExperimentalState,
|
||||
writeSSZStateTransitionsFlag,
|
||||
@@ -218,7 +218,6 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
|
||||
disablePeerScorer,
|
||||
disableBroadcastSlashingFlag,
|
||||
enableSlasherFlag,
|
||||
enableHistoricalSpaceRepresentation,
|
||||
disableStakinContractCheck,
|
||||
SaveFullExecutionPayloads,
|
||||
enableStartupOptimistic,
|
||||
@@ -236,7 +235,18 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
|
||||
DisableCommitteeAwarePacking,
|
||||
EnableDiscoveryReboot,
|
||||
enableExperimentalAttestationPool,
|
||||
}...)...)
|
||||
}, deprecatedBeaconFlags, deprecatedFlags, upcomingDeprecation)
|
||||
|
||||
func combinedFlags(flags ...[]cli.Flag) []cli.Flag {
|
||||
if len(flags) == 0 {
|
||||
return []cli.Flag{}
|
||||
}
|
||||
collected := flags[0]
|
||||
for _, f := range flags[1:] {
|
||||
collected = append(collected, f...)
|
||||
}
|
||||
return collected
|
||||
}
|
||||
|
||||
// E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E.
|
||||
var E2EBeaconChainFlags = []string{
|
||||
|
||||
@@ -28,7 +28,7 @@ const (
|
||||
onlyDB
|
||||
)
|
||||
|
||||
type settingsLoader struct {
|
||||
type SettingsLoader struct {
|
||||
loadMethods []settingsType
|
||||
existsInDB bool
|
||||
db iface.ValidatorDB
|
||||
@@ -41,11 +41,11 @@ type flagOptions struct {
|
||||
}
|
||||
|
||||
// SettingsLoaderOption sets additional options that affect the proposer settings
|
||||
type SettingsLoaderOption func(cliCtx *cli.Context, psl *settingsLoader) error
|
||||
type SettingsLoaderOption func(cliCtx *cli.Context, psl *SettingsLoader) error
|
||||
|
||||
// WithBuilderConfig applies the --enable-builder flag to proposer settings
|
||||
func WithBuilderConfig() SettingsLoaderOption {
|
||||
return func(cliCtx *cli.Context, psl *settingsLoader) error {
|
||||
return func(cliCtx *cli.Context, psl *SettingsLoader) error {
|
||||
if cliCtx.Bool(flags.EnableBuilderFlag.Name) {
|
||||
psl.options.builderConfig = &proposer.BuilderConfig{
|
||||
Enabled: true,
|
||||
@@ -58,7 +58,7 @@ func WithBuilderConfig() SettingsLoaderOption {
|
||||
|
||||
// WithGasLimit applies the --suggested-gas-limit flag to proposer settings
|
||||
func WithGasLimit() SettingsLoaderOption {
|
||||
return func(cliCtx *cli.Context, psl *settingsLoader) error {
|
||||
return func(cliCtx *cli.Context, psl *SettingsLoader) error {
|
||||
sgl := cliCtx.String(flags.BuilderGasLimitFlag.Name)
|
||||
if sgl != "" {
|
||||
gl, err := strconv.ParseUint(sgl, 10, 64)
|
||||
@@ -76,7 +76,7 @@ func WithGasLimit() SettingsLoaderOption {
|
||||
}
|
||||
|
||||
// NewProposerSettingsLoader returns a new proposer settings loader that can process the proposer settings based on flag options
|
||||
func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts ...SettingsLoaderOption) (*settingsLoader, error) {
|
||||
func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts ...SettingsLoaderOption) (*SettingsLoader, error) {
|
||||
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) && cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
return nil, fmt.Errorf("cannot specify both --%s and --%s flags; choose one method for specifying proposer settings", flags.ProposerSettingsFlag.Name, flags.ProposerSettingsURLFlag.Name)
|
||||
}
|
||||
@@ -84,25 +84,9 @@ func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts .
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
psl := &settingsLoader{db: db, existsInDB: psExists, options: &flagOptions{}}
|
||||
psl := &SettingsLoader{db: db, existsInDB: psExists, options: &flagOptions{}}
|
||||
|
||||
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) {
|
||||
psl.loadMethods = append(psl.loadMethods, defaultFlag)
|
||||
}
|
||||
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) {
|
||||
psl.loadMethods = append(psl.loadMethods, fileFlag)
|
||||
}
|
||||
if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
psl.loadMethods = append(psl.loadMethods, urlFlag)
|
||||
}
|
||||
if len(psl.loadMethods) == 0 {
|
||||
method := none
|
||||
if psExists {
|
||||
// override with db
|
||||
method = onlyDB
|
||||
}
|
||||
psl.loadMethods = append(psl.loadMethods, method)
|
||||
}
|
||||
psl.loadMethods = determineLoadMethods(cliCtx, psl.existsInDB)
|
||||
|
||||
for _, o := range opts {
|
||||
if err := o(cliCtx, psl); err != nil {
|
||||
@@ -113,14 +97,34 @@ func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts .
|
||||
return psl, nil
|
||||
}
|
||||
|
||||
func determineLoadMethods(cliCtx *cli.Context, loadedFromDB bool) []settingsType {
|
||||
var methods []settingsType
|
||||
|
||||
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) {
|
||||
methods = append(methods, defaultFlag)
|
||||
}
|
||||
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) {
|
||||
methods = append(methods, fileFlag)
|
||||
}
|
||||
if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
methods = append(methods, urlFlag)
|
||||
}
|
||||
if len(methods) == 0 && loadedFromDB {
|
||||
methods = append(methods, onlyDB)
|
||||
}
|
||||
if len(methods) == 0 {
|
||||
methods = append(methods, none)
|
||||
}
|
||||
|
||||
return methods
|
||||
}
|
||||
|
||||
// Load saves the proposer settings to the database
|
||||
func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) {
|
||||
loadConfig := &validatorpb.ProposerSettingsPayload{}
|
||||
func (psl *SettingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) {
|
||||
var loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload
|
||||
|
||||
// override settings based on other options
|
||||
if psl.options.builderConfig != nil && psl.options.gasLimit != nil {
|
||||
psl.options.builderConfig.GasLimit = *psl.options.gasLimit
|
||||
}
|
||||
psl.applyOverrides()
|
||||
|
||||
// check if database has settings already
|
||||
if psl.existsInDB {
|
||||
@@ -128,9 +132,9 @@ func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loadConfig = dbps.ToConsensus()
|
||||
dbSettings = dbps.ToConsensus()
|
||||
log.Debugf("DB loaded proposer settings: %s", func() string {
|
||||
b, err := json.Marshal(loadConfig)
|
||||
b, err := json.Marshal(dbSettings)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
@@ -140,72 +144,39 @@ func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error)
|
||||
|
||||
// start to process based on load method
|
||||
for _, method := range psl.loadMethods {
|
||||
var err error
|
||||
switch method {
|
||||
case defaultFlag:
|
||||
suggestedFeeRecipient := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
|
||||
if !common.IsHexAddress(suggestedFeeRecipient) {
|
||||
return nil, errors.Errorf("--%s is not a valid Ethereum address", flags.SuggestedFeeRecipientFlag.Name)
|
||||
}
|
||||
if err := config.WarnNonChecksummedAddress(suggestedFeeRecipient); err != nil {
|
||||
loadedSettings, err = psl.loadFromDefault(cliCtx, dbSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defaultConfig := &validatorpb.ProposerOptionPayload{
|
||||
FeeRecipient: suggestedFeeRecipient,
|
||||
}
|
||||
if psl.options.builderConfig != nil {
|
||||
defaultConfig.Builder = psl.options.builderConfig.ToConsensus()
|
||||
}
|
||||
if psl.existsInDB && len(psl.loadMethods) == 1 {
|
||||
// only log the below if default flag is the only load method
|
||||
log.Debug("Overriding previously saved proposer default settings.")
|
||||
}
|
||||
loadConfig.DefaultConfig = defaultConfig
|
||||
case fileFlag:
|
||||
var settingFromFile *validatorpb.ProposerSettingsPayload
|
||||
if err := config.UnmarshalFromFile(cliCtx.String(flags.ProposerSettingsFlag.Name), &settingFromFile); err != nil {
|
||||
loadedSettings, err = psl.loadFromFile(cliCtx, dbSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if settingFromFile == nil {
|
||||
return nil, errors.Errorf("proposer settings is empty after unmarshalling from file specified by %s flag", flags.ProposerSettingsFlag.Name)
|
||||
}
|
||||
loadConfig = psl.processProposerSettings(settingFromFile, loadConfig)
|
||||
log.WithField(flags.ProposerSettingsFlag.Name, cliCtx.String(flags.ProposerSettingsFlag.Name)).Info("Proposer settings loaded from file")
|
||||
case urlFlag:
|
||||
var settingFromURL *validatorpb.ProposerSettingsPayload
|
||||
if err := config.UnmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &settingFromURL); err != nil {
|
||||
loadedSettings, err = psl.loadFromURL(cliCtx, dbSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if settingFromURL == nil {
|
||||
return nil, errors.New("proposer settings is empty after unmarshalling from url")
|
||||
}
|
||||
loadConfig = psl.processProposerSettings(settingFromURL, loadConfig)
|
||||
log.WithField(flags.ProposerSettingsURLFlag.Name, cliCtx.String(flags.ProposerSettingsURLFlag.Name)).Infof("Proposer settings loaded from URL")
|
||||
case onlyDB:
|
||||
loadConfig = psl.processProposerSettings(nil, loadConfig)
|
||||
log.Info("Proposer settings loaded from the DB")
|
||||
case none:
|
||||
case onlyDB, none:
|
||||
loadedSettings = psl.processProposerSettings(&validatorpb.ProposerSettingsPayload{}, dbSettings)
|
||||
if psl.existsInDB {
|
||||
log.Info("Proposer settings loaded from the DB")
|
||||
}
|
||||
if psl.options.builderConfig != nil {
|
||||
// if there are no proposer settings provided, create a default where fee recipient is not populated, this will be skipped for validator registration on validators that don't have a fee recipient set.
|
||||
// skip saving to DB if only builder settings are provided until a trigger like keymanager API updates with fee recipient values
|
||||
option := &proposer.Option{
|
||||
BuilderConfig: psl.options.builderConfig.Clone(),
|
||||
}
|
||||
loadConfig.DefaultConfig = option.ToConsensus()
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("load method for proposer settings does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
// exit early if nothing is provided
|
||||
if loadConfig == nil || (loadConfig.ProposerConfig == nil && loadConfig.DefaultConfig == nil) {
|
||||
if loadedSettings == nil || (loadedSettings.ProposerConfig == nil && loadedSettings.DefaultConfig == nil) {
|
||||
log.Warn("No proposer settings were provided")
|
||||
return nil, nil
|
||||
}
|
||||
ps, err := proposer.SettingFromConsensus(loadConfig)
|
||||
ps, err := proposer.SettingFromConsensus(loadedSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -215,66 +186,128 @@ func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error)
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload) *validatorpb.ProposerSettingsPayload {
|
||||
func (psl *SettingsLoader) applyOverrides() {
|
||||
if psl.options.builderConfig != nil && psl.options.gasLimit != nil {
|
||||
psl.options.builderConfig.GasLimit = *psl.options.gasLimit
|
||||
}
|
||||
}
|
||||
|
||||
func (psl *SettingsLoader) loadFromDefault(cliCtx *cli.Context, dbSettings *validatorpb.ProposerSettingsPayload) (*validatorpb.ProposerSettingsPayload, error) {
|
||||
suggestedFeeRecipient := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
|
||||
if !common.IsHexAddress(suggestedFeeRecipient) {
|
||||
return nil, errors.Errorf("--%s is not a valid Ethereum address", flags.SuggestedFeeRecipientFlag.Name)
|
||||
}
|
||||
if err := config.WarnNonChecksummedAddress(suggestedFeeRecipient); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if psl.existsInDB && len(psl.loadMethods) == 1 {
|
||||
// only log the below if default flag is the only load method
|
||||
log.Debug("Overriding previously saved proposer default settings.")
|
||||
}
|
||||
log.WithField(flags.SuggestedFeeRecipientFlag.Name, cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)).Info("Proposer settings loaded from default")
|
||||
return psl.processProposerSettings(&validatorpb.ProposerSettingsPayload{DefaultConfig: &validatorpb.ProposerOptionPayload{
|
||||
FeeRecipient: suggestedFeeRecipient,
|
||||
}}, dbSettings), nil
|
||||
}
|
||||
|
||||
func (psl *SettingsLoader) loadFromFile(cliCtx *cli.Context, dbSettings *validatorpb.ProposerSettingsPayload) (*validatorpb.ProposerSettingsPayload, error) {
|
||||
var settingFromFile *validatorpb.ProposerSettingsPayload
|
||||
if err := config.UnmarshalFromFile(cliCtx.String(flags.ProposerSettingsFlag.Name), &settingFromFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if settingFromFile == nil {
|
||||
return nil, errors.Errorf("proposer settings is empty after unmarshalling from file specified by %s flag", flags.ProposerSettingsFlag.Name)
|
||||
}
|
||||
log.WithField(flags.ProposerSettingsFlag.Name, cliCtx.String(flags.ProposerSettingsFlag.Name)).Info("Proposer settings loaded from file")
|
||||
return psl.processProposerSettings(settingFromFile, dbSettings), nil
|
||||
}
|
||||
|
||||
func (psl *SettingsLoader) loadFromURL(cliCtx *cli.Context, dbSettings *validatorpb.ProposerSettingsPayload) (*validatorpb.ProposerSettingsPayload, error) {
|
||||
var settingFromURL *validatorpb.ProposerSettingsPayload
|
||||
if err := config.UnmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &settingFromURL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if settingFromURL == nil {
|
||||
return nil, errors.Errorf("proposer settings is empty after unmarshalling from url specified by %s flag", flags.ProposerSettingsURLFlag.Name)
|
||||
}
|
||||
log.WithField(flags.ProposerSettingsURLFlag.Name, cliCtx.String(flags.ProposerSettingsURLFlag.Name)).Infof("Proposer settings loaded from URL")
|
||||
return psl.processProposerSettings(settingFromURL, dbSettings), nil
|
||||
}
|
||||
|
||||
func (psl *SettingsLoader) processProposerSettings(loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload) *validatorpb.ProposerSettingsPayload {
|
||||
if loadedSettings == nil && dbSettings == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// loaded settings have higher priority than db settings
|
||||
newSettings := &validatorpb.ProposerSettingsPayload{}
|
||||
// Merge settings with priority: loadedSettings > dbSettings
|
||||
newSettings := mergeProposerSettings(loadedSettings, dbSettings, psl.options)
|
||||
|
||||
// Return nil if settings remain empty
|
||||
if newSettings.DefaultConfig == nil && len(newSettings.ProposerConfig) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return newSettings
|
||||
}
|
||||
|
||||
// mergeProposerSettings merges database settings with loaded settings, giving precedence to loadedSettings
|
||||
func mergeProposerSettings(loaded, db *validatorpb.ProposerSettingsPayload, options *flagOptions) *validatorpb.ProposerSettingsPayload {
|
||||
merged := &validatorpb.ProposerSettingsPayload{}
|
||||
|
||||
// Apply builder config overrides
|
||||
var builderConfig *validatorpb.BuilderConfig
|
||||
var gasLimitOnly *validator.Uint64
|
||||
|
||||
if psl.options != nil {
|
||||
if psl.options.builderConfig != nil {
|
||||
builderConfig = psl.options.builderConfig.ToConsensus()
|
||||
if options != nil {
|
||||
if options.builderConfig != nil {
|
||||
builderConfig = options.builderConfig.ToConsensus()
|
||||
}
|
||||
if psl.options.gasLimit != nil {
|
||||
gasLimitOnly = psl.options.gasLimit
|
||||
if options.gasLimit != nil {
|
||||
gasLimitOnly = options.gasLimit
|
||||
}
|
||||
}
|
||||
|
||||
if dbSettings != nil && dbSettings.DefaultConfig != nil {
|
||||
// Merge DefaultConfig
|
||||
if db != nil && db.DefaultConfig != nil {
|
||||
merged.DefaultConfig = db.DefaultConfig
|
||||
// db always falls back to local building if no builder settings are provided
|
||||
if builderConfig == nil {
|
||||
dbSettings.DefaultConfig.Builder = nil
|
||||
db.DefaultConfig.Builder = nil
|
||||
}
|
||||
newSettings.DefaultConfig = dbSettings.DefaultConfig
|
||||
}
|
||||
if loadedSettings != nil && loadedSettings.DefaultConfig != nil {
|
||||
newSettings.DefaultConfig = loadedSettings.DefaultConfig
|
||||
if loaded != nil && loaded.DefaultConfig != nil {
|
||||
merged.DefaultConfig = loaded.DefaultConfig
|
||||
}
|
||||
|
||||
// process any builder overrides on defaults
|
||||
if newSettings.DefaultConfig != nil {
|
||||
newSettings.DefaultConfig.Builder = processBuilderConfig(newSettings.DefaultConfig.Builder, builderConfig, gasLimitOnly)
|
||||
}
|
||||
|
||||
if dbSettings != nil && len(dbSettings.ProposerConfig) != 0 {
|
||||
for _, option := range dbSettings.ProposerConfig {
|
||||
// Merge ProposerConfig
|
||||
if db != nil && len(db.ProposerConfig) > 0 {
|
||||
merged.ProposerConfig = db.ProposerConfig
|
||||
for _, option := range db.ProposerConfig {
|
||||
// db always falls back to local building if no builder settings are provided
|
||||
if builderConfig == nil {
|
||||
option.Builder = nil
|
||||
}
|
||||
}
|
||||
newSettings.ProposerConfig = dbSettings.ProposerConfig
|
||||
}
|
||||
if loadedSettings != nil && len(loadedSettings.ProposerConfig) != 0 {
|
||||
newSettings.ProposerConfig = loadedSettings.ProposerConfig
|
||||
if loaded != nil && len(loaded.ProposerConfig) > 0 {
|
||||
merged.ProposerConfig = loaded.ProposerConfig
|
||||
}
|
||||
|
||||
// process any overrides for proposer config
|
||||
for _, option := range newSettings.ProposerConfig {
|
||||
if merged.DefaultConfig != nil {
|
||||
merged.DefaultConfig.Builder = processBuilderConfig(merged.DefaultConfig.Builder, builderConfig, gasLimitOnly)
|
||||
}
|
||||
for _, option := range merged.ProposerConfig {
|
||||
if option != nil {
|
||||
option.Builder = processBuilderConfig(option.Builder, builderConfig, gasLimitOnly)
|
||||
}
|
||||
}
|
||||
|
||||
// if default and proposer configs are both missing even after db setting
|
||||
if newSettings.DefaultConfig == nil && newSettings.ProposerConfig == nil {
|
||||
return nil
|
||||
if merged.DefaultConfig == nil && builderConfig != nil {
|
||||
merged.DefaultConfig = &validatorpb.ProposerOptionPayload{Builder: builderConfig}
|
||||
}
|
||||
|
||||
return newSettings
|
||||
return merged
|
||||
}
|
||||
|
||||
func processBuilderConfig(current *validatorpb.BuilderConfig, override *validatorpb.BuilderConfig, gasLimitOnly *validator.Uint64) *validatorpb.BuilderConfig {
|
||||
|
||||
4
deps.bzl
4
deps.bzl
@@ -760,8 +760,8 @@ def prysm_deps():
|
||||
patches = [
|
||||
"//third_party:com_github_ethereum_go_ethereum_secp256k1.patch",
|
||||
],
|
||||
sum = "h1:8hl57x77HSUo+cXExrURjU/w1VhL+ShCTJrTwcCQSe4=",
|
||||
version = "v1.14.12",
|
||||
sum = "h1:L81Wmv0OUP6cf4CW6wtXsr23RUrDhKs2+Y9Qto+OgHU=",
|
||||
version = "v1.14.13",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_ethereum_go_verkle",
|
||||
|
||||
2
go.mod
2
go.mod
@@ -14,7 +14,7 @@ require (
|
||||
github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/emicklei/dot v0.11.0
|
||||
github.com/ethereum/go-ethereum v1.14.12
|
||||
github.com/ethereum/go-ethereum v1.14.13
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
|
||||
4
go.sum
4
go.sum
@@ -235,8 +235,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=
|
||||
github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
|
||||
github.com/ethereum/go-ethereum v1.14.12 h1:8hl57x77HSUo+cXExrURjU/w1VhL+ShCTJrTwcCQSe4=
|
||||
github.com/ethereum/go-ethereum v1.14.12/go.mod h1:RAC2gVMWJ6FkxSPESfbshrcKpIokgQKsVKmAuqdekDY=
|
||||
github.com/ethereum/go-ethereum v1.14.13 h1:L81Wmv0OUP6cf4CW6wtXsr23RUrDhKs2+Y9Qto+OgHU=
|
||||
github.com/ethereum/go-ethereum v1.14.13/go.mod h1:RAC2gVMWJ6FkxSPESfbshrcKpIokgQKsVKmAuqdekDY=
|
||||
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
|
||||
github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
|
||||
@@ -321,6 +321,17 @@ func HydrateAttestationElectra(a *ethpb.AttestationElectra) *ethpb.AttestationEl
|
||||
return a
|
||||
}
|
||||
|
||||
func HydrateSingleAttestation(a *ethpb.SingleAttestation) *ethpb.SingleAttestation {
|
||||
if a.Signature == nil {
|
||||
a.Signature = make([]byte, 96)
|
||||
}
|
||||
if a.Data == nil {
|
||||
a.Data = ðpb.AttestationData{}
|
||||
}
|
||||
a.Data = HydrateAttestationData(a.Data)
|
||||
return a
|
||||
}
|
||||
|
||||
// HydrateV1Attestation hydrates a v1 attestation object with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateV1Attestation(a *attv1.Attestation) *attv1.Attestation {
|
||||
|
||||
@@ -94,9 +94,6 @@ func signValidatorRegistration(ctx context.Context, signer iface.SigningFunc, re
|
||||
|
||||
// SignValidatorRegistrationRequest compares and returns either the cached validator registration request or signs a new one.
|
||||
func (v *validator) SignValidatorRegistrationRequest(ctx context.Context, signer iface.SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool /* isCached */, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "validator.SignValidatorRegistrationRequest")
|
||||
defer span.End()
|
||||
|
||||
signedReg, ok := v.signedValidatorRegistrations[bytesutil.ToBytes48(newValidatorRegistration.Pubkey)]
|
||||
if ok && isValidatorRegistrationSame(signedReg.Message, newValidatorRegistration) {
|
||||
return signedReg, true, nil
|
||||
|
||||
Reference in New Issue
Block a user