Skip to content

Commit f04da14

Browse files
authored
fix(ledger): verify kes for all shelley+ eras (#1309)
Signed-off-by: Chris Gianelloni <[email protected]>
1 parent 7173b7b commit f04da14

File tree

1 file changed

+116
-13
lines changed

1 file changed

+116
-13
lines changed

ledger/verify_kes.go

Lines changed: 116 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ import (
2626
"math"
2727

2828
"github.com/blinklabs-io/gouroboros/cbor"
29+
"github.com/blinklabs-io/gouroboros/ledger/allegra"
30+
"github.com/blinklabs-io/gouroboros/ledger/alonzo"
31+
"github.com/blinklabs-io/gouroboros/ledger/babbage"
32+
"github.com/blinklabs-io/gouroboros/ledger/common"
33+
"github.com/blinklabs-io/gouroboros/ledger/conway"
34+
"github.com/blinklabs-io/gouroboros/ledger/leios"
35+
"github.com/blinklabs-io/gouroboros/ledger/mary"
36+
"github.com/blinklabs-io/gouroboros/ledger/shelley"
2937
"golang.org/x/crypto/blake2b"
3038
)
3139

@@ -131,27 +139,100 @@ func (s Sum0KesSig) Verify(
131139
return ed25519.Verify(pubKey, msg, s)
132140
}
133141

134-
// TODO: make this work on anything from Shelley onward (#845)
142+
func extractKesFieldsShelleyAlonzo(
143+
header interface{},
144+
) (bodyCbor []byte, sig []byte, hotVkey []byte, kesPeriod uint64, slot uint64, err error) {
145+
switch h := header.(type) {
146+
case *shelley.ShelleyBlockHeader:
147+
bodyCbor, err = cbor.Encode(h.Body)
148+
if err != nil {
149+
return nil, nil, nil, 0, 0, err
150+
}
151+
return bodyCbor, h.Signature, h.Body.OpCertHotVkey, uint64(h.Body.OpCertKesPeriod), h.Body.Slot, nil
152+
case *allegra.AllegraBlockHeader:
153+
bodyCbor, err = cbor.Encode(h.Body)
154+
if err != nil {
155+
return nil, nil, nil, 0, 0, err
156+
}
157+
return bodyCbor, h.Signature, h.Body.OpCertHotVkey, uint64(h.Body.OpCertKesPeriod), h.Body.Slot, nil
158+
case *mary.MaryBlockHeader:
159+
bodyCbor, err = cbor.Encode(h.Body)
160+
if err != nil {
161+
return nil, nil, nil, 0, 0, err
162+
}
163+
return bodyCbor, h.Signature, h.Body.OpCertHotVkey, uint64(h.Body.OpCertKesPeriod), h.Body.Slot, nil
164+
case *alonzo.AlonzoBlockHeader:
165+
bodyCbor, err = cbor.Encode(h.Body)
166+
if err != nil {
167+
return nil, nil, nil, 0, 0, err
168+
}
169+
return bodyCbor, h.Signature, h.Body.OpCertHotVkey, uint64(h.Body.OpCertKesPeriod), h.Body.Slot, nil
170+
default:
171+
return nil, nil, nil, 0, 0, fmt.Errorf("unsupported header type: %T", header)
172+
}
173+
}
174+
175+
func extractKesFieldsBabbagePlus(
176+
header interface{},
177+
) (bodyCbor []byte, sig []byte, hotVkey []byte, kesPeriod uint64, slot uint64, err error) {
178+
switch h := header.(type) {
179+
case *babbage.BabbageBlockHeader:
180+
bodyCbor, err = cbor.Encode(h.Body)
181+
if err != nil {
182+
return nil, nil, nil, 0, 0, err
183+
}
184+
return bodyCbor, h.Signature, h.Body.OpCert.HotVkey, uint64(h.Body.OpCert.KesPeriod), h.Body.Slot, nil
185+
case *conway.ConwayBlockHeader:
186+
bodyCbor, err = cbor.Encode(h.Body)
187+
if err != nil {
188+
return nil, nil, nil, 0, 0, err
189+
}
190+
return bodyCbor, h.Signature, h.Body.OpCert.HotVkey, uint64(h.Body.OpCert.KesPeriod), h.Body.Slot, nil
191+
case *leios.LeiosBlockHeader:
192+
bodyCbor, err = cbor.Encode(h.Body)
193+
if err != nil {
194+
return nil, nil, nil, 0, 0, err
195+
}
196+
return bodyCbor, h.Signature, h.Body.OpCert.HotVkey, uint64(h.Body.OpCert.KesPeriod), h.Body.Slot, nil
197+
default:
198+
return nil, nil, nil, 0, 0, fmt.Errorf("unsupported header type: %T", header)
199+
}
200+
}
201+
135202
func VerifyKes(
136-
header *BabbageBlockHeader,
203+
header common.BlockHeader,
137204
slotsPerKesPeriod uint64,
138205
) (bool, error) {
139206
// Ref: https://github.com/IntersectMBO/ouroboros-consensus/blob/de74882102236fdc4dd25aaa2552e8b3e208448c/ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Protocol/Praos.hs#L125
140207
// Ref: https://github.com/IntersectMBO/cardano-ledger/blob/master/libs/cardano-protocol-tpraos/src/Cardano/Protocol/TPraos/BHeader.hs#L189
141-
msgBytes, err := cbor.Encode(header.Body)
142-
if err != nil {
143-
return false, err
208+
var msgBytes []byte
209+
var signature []byte
210+
var hotVkey []byte
211+
var kesPeriod uint64
212+
var slot uint64
213+
var err error
214+
215+
switch h := header.(type) {
216+
case *shelley.ShelleyBlockHeader, *allegra.AllegraBlockHeader, *mary.MaryBlockHeader, *alonzo.AlonzoBlockHeader:
217+
msgBytes, signature, hotVkey, kesPeriod, slot, err = extractKesFieldsShelleyAlonzo(h)
218+
if err != nil {
219+
return false, fmt.Errorf("VerifyKes: %w", err)
220+
}
221+
case *babbage.BabbageBlockHeader, *conway.ConwayBlockHeader, *leios.LeiosBlockHeader:
222+
msgBytes, signature, hotVkey, kesPeriod, slot, err = extractKesFieldsBabbagePlus(h)
223+
if err != nil {
224+
return false, fmt.Errorf("VerifyKes: %w", err)
225+
}
226+
default:
227+
return false, fmt.Errorf("VerifyKes: unsupported block header type %T", header)
144228
}
145-
opCert := header.Body.OpCert
146-
opCertVkHotBytes := header.Body.OpCert.HotVkey
147-
startOfKesPeriod := uint64(opCert.KesPeriod)
148-
currentSlot := header.Body.Slot
229+
149230
return VerifyKesComponents(
150231
msgBytes,
151-
header.Signature,
152-
opCertVkHotBytes,
153-
startOfKesPeriod,
154-
currentSlot,
232+
signature,
233+
hotVkey,
234+
kesPeriod,
235+
slot,
155236
slotsPerKesPeriod,
156237
)
157238
}
@@ -189,3 +270,25 @@ func verifySignedKES(vkey []byte, period uint64, msg []byte, sig []byte) bool {
189270
isValid := proof.Verify(period, vkey, msg)
190271
return isValid
191272
}
273+
274+
// GetHeaderBodyCbor returns the CBOR-encoded bytes of the block header body
275+
func GetHeaderBodyCbor(header common.BlockHeader) ([]byte, error) {
276+
switch h := header.(type) {
277+
case *shelley.ShelleyBlockHeader:
278+
return cbor.Encode(h.Body)
279+
case *allegra.AllegraBlockHeader:
280+
return cbor.Encode(h.Body)
281+
case *mary.MaryBlockHeader:
282+
return cbor.Encode(h.Body)
283+
case *alonzo.AlonzoBlockHeader:
284+
return cbor.Encode(h.Body)
285+
case *babbage.BabbageBlockHeader:
286+
return cbor.Encode(h.Body)
287+
case *conway.ConwayBlockHeader:
288+
return cbor.Encode(h.Body)
289+
case *leios.LeiosBlockHeader:
290+
return cbor.Encode(h.Body)
291+
default:
292+
return nil, fmt.Errorf("GetHeaderBodyCbor: unsupported block header type %T", header)
293+
}
294+
}

0 commit comments

Comments
 (0)