@@ -399,6 +399,64 @@ type (
399399 VrfKeyHash = Blake2b256
400400)
401401
402+ const (
403+ LeiosBlsPublicKeySize = 96
404+ LeiosBlsPossessionProofSize = 48
405+ )
406+
407+ // LeiosKey is the BLS12-381 verification key and proof of possession
408+ // optionally registered with a Dijkstra-era stake pool. The prototype accepts
409+ // this data but does not use it for committee voting yet.
410+ type LeiosKey struct {
411+ cbor.StructAsArray
412+ PublicKey []byte `json:"publicKey"`
413+ PossessionProof []byte `json:"possessionProof"`
414+ }
415+
416+ func (k LeiosKey ) validate () error {
417+ if len (k .PublicKey ) != LeiosBlsPublicKeySize {
418+ return fmt .Errorf (
419+ "invalid Leios BLS public key length: expected %d, got %d" ,
420+ LeiosBlsPublicKeySize ,
421+ len (k .PublicKey ),
422+ )
423+ }
424+ if len (k .PossessionProof ) != LeiosBlsPossessionProofSize {
425+ return fmt .Errorf (
426+ "invalid Leios BLS possession proof length: expected %d, got %d" ,
427+ LeiosBlsPossessionProofSize ,
428+ len (k .PossessionProof ),
429+ )
430+ }
431+ return nil
432+ }
433+
434+ func (k * LeiosKey ) UnmarshalCBOR (data []byte ) error {
435+ type tmpLeiosKey LeiosKey
436+ var tmp tmpLeiosKey
437+ if _ , err := cbor .Decode (data , & tmp ); err != nil {
438+ return err
439+ }
440+ if err := LeiosKey (tmp ).validate (); err != nil {
441+ return err
442+ }
443+ * k = LeiosKey (tmp )
444+ return nil
445+ }
446+
447+ func (k * LeiosKey ) UnmarshalJSON (data []byte ) error {
448+ type tmpLeiosKey LeiosKey
449+ var tmp tmpLeiosKey
450+ if err := json .Unmarshal (data , & tmp ); err != nil {
451+ return err
452+ }
453+ if err := LeiosKey (tmp ).validate (); err != nil {
454+ return err
455+ }
456+ * k = LeiosKey (tmp )
457+ return nil
458+ }
459+
402460type PoolMetadata struct {
403461 cbor.StructAsArray
404462 Url string
@@ -499,6 +557,7 @@ type PoolRegistrationCertificate struct {
499557 CertType uint `json:"certType,omitempty"`
500558 Operator PoolKeyHash `json:"operator"`
501559 VrfKeyHash VrfKeyHash `json:"vrfKeyHash"`
560+ LeiosKey * LeiosKey `json:"leiosKey,omitempty"`
502561 Pledge uint64 `json:"pledge"`
503562 Cost uint64 `json:"cost"`
504563 Margin GenesisRat `json:"margin"`
@@ -512,6 +571,7 @@ func (p *PoolRegistrationCertificate) UnmarshalJSON(data []byte) error {
512571 type tempPool struct {
513572 Operator string `json:"operator"`
514573 VrfKeyHash string `json:"vrfKeyHash"`
574+ LeiosKey * LeiosKey `json:"leiosKey,omitempty"`
515575 Pledge uint64 `json:"pledge"`
516576 Cost uint64 `json:"cost"`
517577 Margin json.RawMessage `json:"margin"`
@@ -564,6 +624,7 @@ func (p *PoolRegistrationCertificate) UnmarshalJSON(data []byte) error {
564624
565625 p .Pledge = tmp .Pledge
566626 p .Cost = tmp .Cost
627+ p .LeiosKey = tmp .LeiosKey
567628 p .Relays = make ([]PoolRelay , len (tmp .Relays ))
568629 for i , relay := range tmp .Relays {
569630 p .Relays [i ] = PoolRelay {
@@ -650,16 +711,117 @@ func (p *PoolRegistrationCertificate) UnmarshalJSON(data []byte) error {
650711func (c PoolRegistrationCertificate ) isCertificate () {}
651712
652713func (c * PoolRegistrationCertificate ) UnmarshalCBOR (cborData []byte ) error {
653- type tPoolRegistrationCertificate PoolRegistrationCertificate
654- var tmp tPoolRegistrationCertificate
655- if _ , err := cbor .Decode (cborData , & tmp ); err != nil {
714+ type legacyPoolRegistrationCertificate struct {
715+ cbor.StructAsArray
716+ CertType uint
717+ Operator PoolKeyHash
718+ VrfKeyHash VrfKeyHash
719+ Pledge uint64
720+ Cost uint64
721+ Margin GenesisRat
722+ RewardAccount AddrKeyHash
723+ PoolOwners []AddrKeyHash
724+ Relays []PoolRelay
725+ PoolMetadata * PoolMetadata
726+ }
727+ type leiosPoolRegistrationCertificate struct {
728+ cbor.StructAsArray
729+ CertType uint
730+ Operator PoolKeyHash
731+ VrfKeyHash VrfKeyHash
732+ LeiosKey * LeiosKey
733+ Pledge uint64
734+ Cost uint64
735+ Margin GenesisRat
736+ RewardAccount AddrKeyHash
737+ PoolOwners []AddrKeyHash
738+ Relays []PoolRelay
739+ PoolMetadata * PoolMetadata
740+ }
741+
742+ var fields []cbor.RawMessage
743+ if _ , err := cbor .Decode (cborData , & fields ); err != nil {
656744 return err
657745 }
658- * c = PoolRegistrationCertificate (tmp )
746+ switch len (fields ) {
747+ case 10 :
748+ var tmp legacyPoolRegistrationCertificate
749+ if _ , err := cbor .Decode (cborData , & tmp ); err != nil {
750+ return err
751+ }
752+ c .CertType = tmp .CertType
753+ c .Operator = tmp .Operator
754+ c .VrfKeyHash = tmp .VrfKeyHash
755+ c .LeiosKey = nil
756+ c .Pledge = tmp .Pledge
757+ c .Cost = tmp .Cost
758+ c .Margin = tmp .Margin
759+ c .RewardAccount = tmp .RewardAccount
760+ c .PoolOwners = tmp .PoolOwners
761+ c .Relays = tmp .Relays
762+ c .PoolMetadata = tmp .PoolMetadata
763+ case 11 :
764+ var tmp leiosPoolRegistrationCertificate
765+ if _ , err := cbor .Decode (cborData , & tmp ); err != nil {
766+ return err
767+ }
768+ c .CertType = tmp .CertType
769+ c .Operator = tmp .Operator
770+ c .VrfKeyHash = tmp .VrfKeyHash
771+ c .LeiosKey = tmp .LeiosKey
772+ c .Pledge = tmp .Pledge
773+ c .Cost = tmp .Cost
774+ c .Margin = tmp .Margin
775+ c .RewardAccount = tmp .RewardAccount
776+ c .PoolOwners = tmp .PoolOwners
777+ c .Relays = tmp .Relays
778+ c .PoolMetadata = tmp .PoolMetadata
779+ default :
780+ return fmt .Errorf (
781+ "invalid pool registration certificate: expected 10 or 11 fields, got %d" ,
782+ len (fields ),
783+ )
784+ }
659785 c .SetCbor (cborData )
660786 return nil
661787}
662788
789+ // NOTE: UnmarshalCBOR caches the original CBOR bytes, and MarshalCBOR returns
790+ // those bytes for both 10- and 11-field variants. Call SetCbor(nil) before
791+ // marshaling mutated fields.
792+ func (c PoolRegistrationCertificate ) MarshalCBOR () ([]byte , error ) {
793+ if cborData := c .Cbor (); cborData != nil {
794+ return cborData , nil
795+ }
796+ if c .LeiosKey == nil {
797+ return cbor .Encode ([]any {
798+ c .CertType ,
799+ c .Operator ,
800+ c .VrfKeyHash ,
801+ c .Pledge ,
802+ c .Cost ,
803+ c .Margin ,
804+ c .RewardAccount ,
805+ c .PoolOwners ,
806+ c .Relays ,
807+ c .PoolMetadata ,
808+ })
809+ }
810+ return cbor .Encode ([]any {
811+ c .CertType ,
812+ c .Operator ,
813+ c .VrfKeyHash ,
814+ c .LeiosKey ,
815+ c .Pledge ,
816+ c .Cost ,
817+ c .Margin ,
818+ c .RewardAccount ,
819+ c .PoolOwners ,
820+ c .Relays ,
821+ c .PoolMetadata ,
822+ })
823+ }
824+
663825func (c * PoolRegistrationCertificate ) Utxorpc () (* utxorpc.Certificate , error ) {
664826 tmpPoolOwners := make ([][]byte , len (c .PoolOwners ))
665827 for i , owner := range c .PoolOwners {
0 commit comments