@@ -10,10 +10,7 @@ import (
1010 "strconv"
1111 "sync"
1212
13- "github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
14- "github.com/attestantio/go-eth2-client/spec/phase0"
1513 ssz "github.com/ferranbt/fastssz"
16- "github.com/herumi/bls-eth-go-binary/bls"
1714 "github.com/jshufro/remote-signer-dirk-interop/generated/api"
1815 "github.com/jshufro/remote-signer-dirk-interop/pkg/dirksigner/dirk"
1916 "github.com/jshufro/remote-signer-dirk-interop/pkg/domains"
@@ -23,6 +20,8 @@ import (
2320 tlsprovider "github.com/jshufro/remote-signer-dirk-interop/pkg/tls"
2421 "github.com/jshufro/remote-signer-dirk-interop/pkg/typeconv"
2522
23+ "github.com/attestantio/go-eth2-client/spec/phase0"
24+ "github.com/herumi/bls-eth-go-binary/bls"
2625 e2t "github.com/wealdtech/go-eth2-types/v2"
2726 e2wd "github.com/wealdtech/go-eth2-wallet-dirk"
2827 e2wt "github.com/wealdtech/go-eth2-wallet-types/v2"
@@ -81,6 +80,7 @@ func (d *DirkSigner) Open(ctx context.Context, logLevel slog.Level) error {
8180
8281 // Prime the account pubkey map
8382 _ = d .getPublicKeys (ctx )
83+
8484 return nil
8585}
8686
@@ -93,6 +93,7 @@ func (d *DirkSigner) getPublicKeys(ctx context.Context) [][48]byte {
9393 out = append (out , pubkeyBytes )
9494 d .accounts .Store (pubkeyBytes , account )
9595 }
96+
9697 return out
9798}
9899
@@ -107,52 +108,53 @@ func (d *DirkSigner) GetAccountForPubkey(ctx context.Context, pubkey [48]byte) (
107108 aps , ok := account .(e2wt.AccountProtectingSigner )
108109 if ! ok {
109110 d .log .Error ("account is not a protecting signer" , "pubkey" , hex .EncodeToString (pubkey [:]))
110- return nil , errors .BadRequest ( "account is not a protecting signer" )
111+ return nil , errors .InternalServerError ( )
111112 }
112113 return aps , nil
113114 }
114115
115116 return nil , errors .PublicKeyNotFound ("account not found for pubkey: %s" , hex .EncodeToString (pubkey [:]))
116117}
117118
118- func (d * DirkSigner ) calculateDomain (
119- domainType domains.DomainType ,
120- forkInfo * fork.ForkInfo ,
121- epoch uint64 ,
122- ) ([]byte , error ) {
123- out , err := forkInfo .ComputeDomain (domainType , epoch )
119+ func (d * DirkSigner ) signature (signature e2t.Signature ) ([96 ]byte , error ) {
120+ b , err := typeconv .SignatureToBytes (signature )
124121 if err != nil {
125- d .log .Error ("failed to compute domain" , "error" , err )
126- return nil , errors .InternalServerError ()
122+ return d .returnUnexpectedFailure ("produced invalid signature" , err )
127123 }
128- d .log .Debug ("computed domain" , "domain" , fmt .Sprintf ("%#x" , out ))
129- return out , nil
130- }
131124
132- func (d * DirkSigner ) returnSignature (signature e2t.Signature ) ([96 ]byte , error ) {
133- b := signature .Marshal ()
134- if len (b ) != 96 {
135- return d .returnUnexpectedFailure ("produced signature is not 96 bytes" , fmt .Errorf ("signature is %d bytes" , len (b )))
136- }
137- return [96 ]byte (b ), nil
125+ return b , nil
138126}
139127
140- func (d * DirkSigner ) returnSignGeneric (ctx context.Context , account e2wt.AccountProtectingSigner , htr [32 ]byte , domain []byte ) ([96 ]byte , error ) {
128+ func (d * DirkSigner ) sign (
129+ ctx context.Context ,
130+ account e2wt.AccountProtectingSigner ,
131+ htr [32 ]byte ,
132+ domainProvider domains.DomainProvider ,
133+ ) ([96 ]byte , error ) {
134+ domain , err := domainProvider .ComputeDomain ()
135+ if err != nil {
136+ return d .returnUnexpectedFailure ("failed to compute domain" , err )
137+ }
141138 signature , err := account .SignGeneric (ctx , htr [:], domain )
142139 if err != nil {
143- d .log .Warn ("failed to sign generic" , "error" , err )
144- return [96 ]byte {}, errors .InternalServerError ()
140+ return d .returnUnexpectedFailure ("failed to sign generic" , err )
145141 }
146- return d .returnSignature (signature )
142+
143+ return d .signature (signature )
147144}
148145
149- func (d * DirkSigner ) sign (ctx context.Context , account e2wt.AccountProtectingSigner , htr [32 ]byte , domainType domains.DomainType , forkInfo * fork.ForkInfo , epoch uint64 ) ([96 ]byte , error ) {
150- domain , err := d .calculateDomain (domainType , forkInfo , epoch )
146+ func (d * DirkSigner ) signHashRoot (
147+ ctx context.Context ,
148+ account e2wt.AccountProtectingSigner ,
149+ htr ssz.HashRoot ,
150+ domainProvider domains.DomainProvider ,
151+ ) ([96 ]byte , error ) {
152+ htrResult , err := htr .HashTreeRoot ()
151153 if err != nil {
152- d .log .Warn ("failed to compute domain" , "error" , err )
153- return [96 ]byte {}, errors .InternalServerError ()
154+ return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
154155 }
155- return d .returnSignGeneric (ctx , account , htr , domain )
156+
157+ return d .sign (ctx , account , htrResult , domainProvider )
156158}
157159
158160func (d * DirkSigner ) returnUnexpectedFailure (msg string , err error ) ([96 ]byte , error ) {
@@ -172,17 +174,14 @@ func (d *DirkSigner) AggregationSlotSigning(
172174 if err != nil {
173175 return [96 ]byte {}, errors .BadRequest ("failed to parse slot: %w" , err )
174176 }
175- hasher := ssz .NewHasher ()
176- hasher .AppendUint64 (slot )
177- hasher .FillUpTo32 ()
178- hashTreeRoot , err := hasher .HashRoot ()
179- if err != nil {
180- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
181- }
177+ // Simply right-pad the slot to 32 bytes
178+ hashTreeRoot := typeconv .Uint64ToHashTreeRoot (slot )
182179
183180 epoch := slot / 32
184181
185- return d .sign (ctx , account , hashTreeRoot , domains .DomainSelectionProof , forkInfo , epoch )
182+ domainProvider := forkInfo .WithDomainType (domains .DomainSelectionProof ).DomainProvider (epoch )
183+
184+ return d .sign (ctx , account , hashTreeRoot , domainProvider )
186185}
187186
188187func (d * DirkSigner ) AggregateAndProofSigningV2 (
@@ -198,7 +197,7 @@ func (d *DirkSigner) AggregateAndProofSigningV2(
198197 return [96 ]byte {}, errors .BadRequest ("failed to get discriminator: %w" , err )
199198 }
200199
201- var htr func () ([ 32 ] byte , error )
200+ var htr ssz. HashRoot
202201 var epoch uint64
203202 switch discriminator {
204203 case "PHASE0" , "ALTAIR" , "BELLATRIX" , "CAPELLA" , "DENEB" :
@@ -207,25 +206,22 @@ func (d *DirkSigner) AggregateAndProofSigningV2(
207206 return [96 ]byte {}, errors .BadRequest ("failed to get phase0 aggregate and proof: %w" , err )
208207 }
209208 epoch = uint64 (phase0AggregateAndProof .Data .Aggregate .Data .Slot / 32 )
210- htr = phase0AggregateAndProof .Data . HashTreeRoot
209+ htr = & phase0AggregateAndProof .Data
211210 case "ELECTRA" , "FULU" :
212211 electraAggregateAndProof , err := aggregateAndProof .AsAggregateAndProofRequestElectra ()
213212 if err != nil {
214213 return [96 ]byte {}, errors .BadRequest ("failed to get electra aggregate and proof: %w" , err )
215214 }
216215 epoch = uint64 (electraAggregateAndProof .Data .Aggregate .Data .Slot / 32 )
217- htr = electraAggregateAndProof .Data . HashTreeRoot
216+ htr = & electraAggregateAndProof .Data
218217 default :
219218 d .log .Warn ("unknown aggregate and proof type" , "discriminator" , discriminator )
220219 return [96 ]byte {}, errors .BadRequest ("unknown aggregate and proof type: %s" , discriminator )
221220 }
222221
223- hashTreeRoot , err := htr ()
224- if err != nil {
225- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
226- }
222+ domainProvider := forkInfo .WithDomainType (domains .DomainAggregateAndProof ).DomainProvider (epoch )
227223
228- return d .sign (ctx , account , hashTreeRoot , domains . DomainAggregateAndProof , forkInfo , epoch )
224+ return d .signHashRoot (ctx , account , htr , domainProvider )
229225}
230226
231227func (d * DirkSigner ) AttestationSigning (
@@ -236,11 +232,8 @@ func (d *DirkSigner) AttestationSigning(
236232) ([96 ]byte , error ) {
237233 attestation := obj .Attestation
238234 epoch := uint64 (attestation .Slot / 32 )
239- domain , err := d .calculateDomain (
240- domains .DomainBeaconAttester ,
241- forkInfo ,
242- epoch ,
243- )
235+ domainProvider := forkInfo .WithDomainType (domains .DomainBeaconAttester ).DomainProvider (epoch )
236+ domain , err := domainProvider .ComputeDomain ()
244237 if err != nil {
245238 return d .returnUnexpectedFailure ("failed to compute domain" , err )
246239 }
@@ -259,7 +252,8 @@ func (d *DirkSigner) AttestationSigning(
259252 if err != nil {
260253 return d .returnUnexpectedFailure ("failed to sign beacon attestation" , err )
261254 }
262- return d .returnSignature (signature )
255+
256+ return d .signature (signature )
263257}
264258
265259func (d * DirkSigner ) BeaconBlockSigning (
@@ -348,11 +342,8 @@ func (d *DirkSigner) BeaconBlockSigning(
348342 }
349343
350344 epoch := uint64 (header .Slot / 32 )
351- domain , err := d .calculateDomain (
352- domains .DomainBeaconProposer ,
353- forkInfo ,
354- epoch ,
355- )
345+ domainProvider := forkInfo .WithDomainType (domains .DomainBeaconProposer ).DomainProvider (epoch )
346+ domain , err := domainProvider .ComputeDomain ()
356347 if err != nil {
357348 return d .returnUnexpectedFailure ("failed to compute domain" , err )
358349 }
@@ -368,7 +359,8 @@ func (d *DirkSigner) BeaconBlockSigning(
368359 if err != nil {
369360 return d .returnUnexpectedFailure ("failed to sign beacon proposal" , err )
370361 }
371- return d .returnSignature (signature )
362+
363+ return d .signature (signature )
372364}
373365
374366func (d * DirkSigner ) DepositSigning (
@@ -385,7 +377,7 @@ func (d *DirkSigner) DepositSigning(
385377 return [96 ]byte {}, errors .BadRequest ("genesis fork version is not 4 bytes" )
386378 }
387379 // Round-trip the obj.Deposit to a phase0.DepositMessage via json
388- // The payload to this api has an extra field and this is removes it plus gives us
380+ // The payload to this api has an extra field and this removes it plus gives us
389381 // a type that implements ssz.HashRoot
390382 depositMessageJson , err := json .Marshal (obj .Deposit )
391383 if err != nil {
@@ -397,23 +389,9 @@ func (d *DirkSigner) DepositSigning(
397389 return [96 ]byte {}, errors .BadRequest ("failed to unmarshal deposit: %w" , err )
398390 }
399391
400- hashTreeRoot , err := deposit .HashTreeRoot ()
401- if err != nil {
402- return [96 ]byte {}, errors .InternalServerError ()
403- }
404-
405- // For deposits, only genesis fork version is needed
406- // genesis validators root must be nil
407- domain , err := signing .ComputeDomain (
408- domains .DomainDeposit ,
409- genesisForkVersion ,
410- nil , /* genesis validators root */
411- )
412- if err != nil {
413- return d .returnUnexpectedFailure ("failed to compute domain" , err )
414- }
392+ domainProvider := domains .DepositDomainProvider (genesisForkVersion )
415393
416- return d .returnSignGeneric (ctx , account , hashTreeRoot , domain )
394+ return d .signHashRoot (ctx , account , deposit , domainProvider )
417395}
418396
419397func (d * DirkSigner ) RandaoRevealSigning (
@@ -428,15 +406,11 @@ func (d *DirkSigner) RandaoRevealSigning(
428406 if err != nil {
429407 return [96 ]byte {}, errors .BadRequest ("failed to parse epoch: %w" , err )
430408 }
431- hasher := ssz .NewHasher ()
432- hasher .AppendUint64 (epoch )
433- hasher .FillUpTo32 ()
434- hashTreeRoot , err := hasher .HashRoot ()
435- if err != nil {
436- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
437- }
438409
439- return d .sign (ctx , account , hashTreeRoot , domains .DomainRandao , forkInfo , epoch )
410+ hashTreeRoot := typeconv .Uint64ToHashTreeRoot (epoch )
411+ domainProvider := forkInfo .WithDomainType (domains .DomainRandao ).DomainProvider (epoch )
412+
413+ return d .sign (ctx , account , hashTreeRoot , domainProvider )
440414}
441415
442416func (d * DirkSigner ) VoluntaryExitSigning (
@@ -445,14 +419,10 @@ func (d *DirkSigner) VoluntaryExitSigning(
445419 obj * api.VoluntaryExitSigning ,
446420 forkInfo * fork.ForkInfo ,
447421) ([96 ]byte , error ) {
448- hashTreeRoot , err := obj .VoluntaryExit .HashTreeRoot ()
449- if err != nil {
450- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
451- }
452-
453422 epoch := uint64 (obj .VoluntaryExit .Epoch )
423+ domainProvider := forkInfo .WithDomainType (domains .DomainVoluntaryExit ).DomainProvider (epoch )
454424
455- return d .sign (ctx , account , hashTreeRoot , domains . DomainVoluntaryExit , forkInfo , epoch )
425+ return d .signHashRoot (ctx , account , & obj . VoluntaryExit , domainProvider )
456426}
457427
458428func (d * DirkSigner ) SyncCommitteeMessageSigning (
@@ -479,7 +449,9 @@ func (d *DirkSigner) SyncCommitteeMessageSigning(
479449
480450 epoch := slot / 32
481451
482- return d .sign (ctx , account , htr , domains .DomainSyncCommittee , forkInfo , epoch )
452+ domainProvider := forkInfo .WithDomainType (domains .DomainSyncCommittee ).DomainProvider (epoch )
453+
454+ return d .sign (ctx , account , htr , domainProvider )
483455}
484456
485457func (d * DirkSigner ) SyncCommitteeSelectionProofSigning (
@@ -488,14 +460,10 @@ func (d *DirkSigner) SyncCommitteeSelectionProofSigning(
488460 obj * api.SyncCommitteeSelectionProofSigning ,
489461 forkInfo * fork.ForkInfo ,
490462) ([96 ]byte , error ) {
491- hashTreeRoot , err := obj .SyncAggregatorSelectionData .HashTreeRoot ()
492- if err != nil {
493- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
494- }
495-
496463 epoch := uint64 (obj .SyncAggregatorSelectionData .Slot / 32 )
464+ domainProvider := forkInfo .WithDomainType (domains .DomainSyncCommiteeSelectionProof ).DomainProvider (epoch )
497465
498- return d .sign (ctx , account , hashTreeRoot , domains . DomainSyncCommiteeSelectionProof , forkInfo , epoch )
466+ return d .signHashRoot (ctx , account , & obj . SyncAggregatorSelectionData , domainProvider )
499467}
500468
501469func (d * DirkSigner ) SyncCommitteeContributionAndProofSigning (
@@ -504,38 +472,18 @@ func (d *DirkSigner) SyncCommitteeContributionAndProofSigning(
504472 obj * api.SyncCommitteeContributionAndProofSigning ,
505473 forkInfo * fork.ForkInfo ,
506474) ([96 ]byte , error ) {
507- hashTreeRoot , err := obj .ContributionAndProof .HashTreeRoot ()
508- if err != nil {
509- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
510- }
511-
512475 epoch := uint64 (obj .ContributionAndProof .Contribution .Slot / 32 )
476+ domainProvider := forkInfo .WithDomainType (domains .DomainSyncContributionAndProof ).DomainProvider (epoch )
513477
514- return d .sign (ctx , account , hashTreeRoot , domains . DomainSyncContributionAndProof , forkInfo , epoch )
478+ return d .signHashRoot (ctx , account , & obj . ContributionAndProof , domainProvider )
515479}
516480
517481func (d * DirkSigner ) ValidatorRegistrationSigning (
518482 ctx context.Context ,
519483 account e2wt.AccountProtectingSigner ,
520484 obj * api.ValidatorRegistrationSigning ,
521485) ([96 ]byte , error ) {
486+ domainProvider := domains .ValidatorRegistrationDomainProvider (d .genesisForkVersion )
522487
523- hashTreeRoot , err := obj .ValidatorRegistration .HashTreeRoot ()
524- if err != nil {
525- return d .returnUnexpectedFailure ("failed to compute hash tree root" , err )
526- }
527-
528- // Compute the domain
529- // For validator registrations, only genesis fork version is needed
530- // genesis validators root must be nil
531- domain , err := signing .ComputeDomain (
532- domains .DomainApplicationBuilder ,
533- d .genesisForkVersion ,
534- nil , /* genesis validators root */
535- )
536- if err != nil {
537- return d .returnUnexpectedFailure ("failed to compute domain" , err )
538- }
539-
540- return d .returnSignGeneric (ctx , account , hashTreeRoot , domain )
488+ return d .signHashRoot (ctx , account , & obj .ValidatorRegistration , domainProvider )
541489}
0 commit comments