@@ -28,7 +28,7 @@ import (
2828)
2929
3030//nolint:staticcheck
31- func VerifyBlock (block BlockHexCbor ) (error , bool , string , uint64 , uint64 ) {
31+ func VerifyBlock (block BlockHexCbor ) (bool , string , uint64 , uint64 , error ) {
3232 headerCborHex := block .HeaderCbor
3333 epochNonceHex := block .Eta0
3434 bodyHex := block .BlockBodyCbor
@@ -37,70 +37,109 @@ func VerifyBlock(block BlockHexCbor) (error, bool, string, uint64, uint64) {
3737 isValid := false
3838 vrfHex := ""
3939
40- // check is KES valid
40+ // Check if this is a Leios block, which is not supported for verification
41+ if block .Flag < 0 {
42+ return false , "" , 0 , 0 , fmt .Errorf (
43+ "VerifyBlock: invalid block flag %d, must be non-negative" ,
44+ block .Flag ,
45+ )
46+ }
47+ blockType := uint (block .Flag ) // #nosec G115
48+ if blockType == BlockTypeLeiosRanking ||
49+ blockType == BlockTypeLeiosEndorser {
50+ return false , "" , 0 , 0 , errors .New (
51+ "VerifyBlock: Leios blocks are not supported for verification" ,
52+ )
53+ }
54+
55+ // For backward compatibility, try to decode as Babbage header first
56+ // This allows the function to work with different eras that have compatible structures
4157 headerCborByte , headerDecodeError := hex .DecodeString (headerCborHex )
4258 if headerDecodeError != nil {
43- return fmt .Errorf (
59+ return false , "" , 0 , 0 , fmt .Errorf (
4460 "VerifyBlock: headerCborByte decode error, %v" ,
4561 headerDecodeError .Error (),
46- ), false , "" , 0 , 0
62+ )
4763 }
48- header , headerUnmarshalError := NewBabbageBlockHeaderFromCbor (
49- headerCborByte ,
50- )
64+ var header BlockHeader
65+ var headerUnmarshalError error
66+ header , headerUnmarshalError = NewBabbageBlockHeaderFromCbor ( headerCborByte )
5167 if headerUnmarshalError != nil {
52- return fmt .Errorf (
53- "VerifyBlock: header unmarshal error, %v" ,
54- headerUnmarshalError .Error (),
55- ), false , "" , 0 , 0
68+ // If Babbage decoding fails, try the era-specific decoder
69+ header , headerUnmarshalError = NewBlockHeaderFromCbor (
70+ blockType ,
71+ headerCborByte ,
72+ )
73+ if headerUnmarshalError != nil {
74+ return false , "" , 0 , 0 , fmt .Errorf (
75+ "VerifyBlock: header unmarshal error, %v" ,
76+ headerUnmarshalError .Error (),
77+ )
78+ }
5679 }
5780 if header == nil {
58- return errors .New ("VerifyBlock: header returned empty" ), false , "" , 0 , 0
81+ return false , "" , 0 , 0 , errors .New ("VerifyBlock: header returned empty" )
5982 }
60- isKesValid , errKes := VerifyKes (header , slotPerKesPeriod )
83+
84+ // For verification, we need to work with Babbage-compatible headers
85+ // Try to cast to BabbageBlockHeader
86+ babbageHeader , ok := header .(* BabbageBlockHeader )
87+ if ! ok {
88+ // If it's not a Babbage header, check if it's Conway (which embeds Babbage)
89+ if conwayHeader , ok := header .(* ConwayBlockHeader ); ok {
90+ babbageHeader = & conwayHeader .BabbageBlockHeader
91+ } else {
92+ return false , "" , 0 , 0 , fmt .Errorf ("VerifyBlock: block verification only supported for Babbage-compatible headers, got type: %T" , header )
93+ }
94+ }
95+
96+ isKesValid , errKes := VerifyKes (babbageHeader , slotPerKesPeriod )
6197 if errKes != nil {
62- return fmt .Errorf (
98+ return false , "" , 0 , 0 , fmt .Errorf (
6399 "VerifyBlock: KES invalid, %v" ,
64100 errKes .Error (),
65- ), false , "" , 0 , 0
101+ )
66102 }
67103
68104 // check is VRF valid
69105 // Ref: https://github.com/IntersectMBO/ouroboros-consensus/blob/de74882102236fdc4dd25aaa2552e8b3e208448c/ouroboros-consensus-protocol/src/ouroboros-consensus-protocol/Ouroboros/Consensus/Protocol/Praos.hs#L541
70106 epochNonceByte , epochNonceDecodeError := hex .DecodeString (epochNonceHex )
71107 if epochNonceDecodeError != nil {
72- return fmt .Errorf (
108+ return false , "" , 0 , 0 , fmt .Errorf (
73109 "VerifyBlock: epochNonceByte decode error, %v" ,
74110 epochNonceDecodeError .Error (),
75- ), false , "" , 0 , 0
111+ )
76112 }
77- vrfBytes := header .Body .VrfKey [:]
78- vrfResult := header .Body .VrfResult
79- seed := MkInputVrf (int64 (header .Body .Slot ), epochNonceByte ) // #nosec G115
113+ vrfBytes := babbageHeader .Body .VrfKey [:]
114+ vrfResult := babbageHeader .Body .VrfResult
115+ seed := MkInputVrf (
116+ int64 (babbageHeader .Body .Slot ),
117+ epochNonceByte ,
118+ ) // #nosec G115
80119 output , errVrf := VrfVerifyAndHash (vrfBytes , vrfResult .Proof , seed )
81120 if errVrf != nil {
82- return fmt .Errorf (
121+ return false , "" , 0 , 0 , fmt .Errorf (
83122 "VerifyBlock: vrf invalid, %v" ,
84123 errVrf .Error (),
85- ), false , "" , 0 , 0
124+ )
86125 }
87126 isVrfValid := bytes .Equal (output , vrfResult .Output )
88127
89128 // check if block data valid
90- blockBodyHash := header .Body .BlockBodyHash
129+ blockBodyHash := babbageHeader .Body .BlockBodyHash
91130 blockBodyHashHex := hex .EncodeToString (blockBodyHash [:])
92131 isBodyValid , isBodyValidError := VerifyBlockBody (bodyHex , blockBodyHashHex )
93132 if isBodyValidError != nil {
94- return fmt .Errorf (
133+ return false , "" , 0 , 0 , fmt .Errorf (
95134 "VerifyBlock: VerifyBlockBody error, %v" ,
96135 isBodyValidError .Error (),
97- ), false , "" , 0 , 0
136+ )
98137 }
99138 isValid = isKesValid && isVrfValid && isBodyValid
100139 vrfHex = hex .EncodeToString (vrfBytes )
101- blockNo := header .Body .BlockNumber
102- slotNo := header .Body .Slot
103- return nil , isValid , vrfHex , blockNo , slotNo
140+ blockNo := babbageHeader .Body .BlockNumber
141+ slotNo := babbageHeader .Body .Slot
142+ return isValid , vrfHex , blockNo , slotNo , nil
104143}
105144
106145func ExtractBlockData (
0 commit comments