Skip to content

Commit 489e47f

Browse files
authored
refactor(ledger): Decode block header as proper era type (#951)
Signed-off-by: Akhil Repala <[email protected]>
1 parent daaabff commit 489e47f

File tree

10 files changed

+231
-47
lines changed

10 files changed

+231
-47
lines changed

ledger/allegra.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const (
3939
// Allegra functions
4040
var (
4141
NewAllegraBlockFromCbor = allegra.NewAllegraBlockFromCbor
42+
NewAllegraBlockHeaderFromCbor = allegra.NewAllegraBlockHeaderFromCbor
4243
NewAllegraTransactionFromCbor = allegra.NewAllegraTransactionFromCbor
4344
NewAllegraTransactionBodyFromCbor = allegra.NewAllegraTransactionBodyFromCbor
4445
)

ledger/allegra/allegra.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,14 @@ func NewAllegraBlockFromCbor(data []byte) (*AllegraBlock, error) {
326326
return &allegraBlock, nil
327327
}
328328

329+
func NewAllegraBlockHeaderFromCbor(data []byte) (*AllegraBlockHeader, error) {
330+
var allegraBlockHeader AllegraBlockHeader
331+
if _, err := cbor.Decode(data, &allegraBlockHeader); err != nil {
332+
return nil, fmt.Errorf("Allegra block header decode error: %w", err)
333+
}
334+
return &allegraBlockHeader, nil
335+
}
336+
329337
func NewAllegraTransactionBodyFromCbor(
330338
data []byte,
331339
) (*AllegraTransactionBody, error) {

ledger/alonzo.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242
// Alonzo functions
4343
var (
4444
NewAlonzoBlockFromCbor = alonzo.NewAlonzoBlockFromCbor
45+
NewAlonzoBlockHeaderFromCbor = alonzo.NewAlonzoBlockHeaderFromCbor
4546
NewAlonzoTransactionFromCbor = alonzo.NewAlonzoTransactionFromCbor
4647
NewAlonzoTransactionBodyFromCbor = alonzo.NewAlonzoTransactionBodyFromCbor
4748
NewAlonzoTransactionOutputFromCbor = alonzo.NewAlonzoTransactionOutputFromCbor

ledger/alonzo/alonzo.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,14 @@ func NewAlonzoBlockFromCbor(data []byte) (*AlonzoBlock, error) {
528528
return &alonzoBlock, nil
529529
}
530530

531+
func NewAlonzoBlockHeaderFromCbor(data []byte) (*AlonzoBlockHeader, error) {
532+
var alonzoBlockHeader AlonzoBlockHeader
533+
if _, err := cbor.Decode(data, &alonzoBlockHeader); err != nil {
534+
return nil, fmt.Errorf("Alonzo block header decode error: %w", err)
535+
}
536+
return &alonzoBlockHeader, nil
537+
}
538+
531539
func NewAlonzoTransactionBodyFromCbor(
532540
data []byte,
533541
) (*AlonzoTransactionBody, error) {

ledger/babbage/babbage.go

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -142,33 +142,39 @@ func (b *BabbageBlock) Utxorpc() *utxorpc.Block {
142142
type BabbageBlockHeader struct {
143143
cbor.StructAsArray
144144
cbor.DecodeStoreCbor
145-
hash string
146-
Body struct {
147-
cbor.StructAsArray
148-
BlockNumber uint64
149-
Slot uint64
150-
PrevHash common.Blake2b256
151-
IssuerVkey common.IssuerVkey
152-
VrfKey []byte
153-
VrfResult common.VrfResult
154-
BlockBodySize uint64
155-
BlockBodyHash common.Blake2b256
156-
OpCert struct {
157-
cbor.StructAsArray
158-
HotVkey []byte
159-
SequenceNumber uint32
160-
KesPeriod uint32
161-
Signature []byte
162-
}
163-
ProtoVersion struct {
164-
cbor.StructAsArray
165-
Major uint64
166-
Minor uint64
167-
}
168-
}
145+
hash string
146+
Body BabbageBlockHeaderBody
169147
Signature []byte
170148
}
171149

150+
type BabbageBlockHeaderBody struct {
151+
cbor.StructAsArray
152+
BlockNumber uint64
153+
Slot uint64
154+
PrevHash common.Blake2b256
155+
IssuerVkey common.IssuerVkey
156+
VrfKey []byte
157+
VrfResult common.VrfResult
158+
BlockBodySize uint64
159+
BlockBodyHash common.Blake2b256
160+
OpCert BabbageOpCert
161+
ProtoVersion BabbageProtoVersion
162+
}
163+
164+
type BabbageOpCert struct {
165+
cbor.StructAsArray
166+
HotVkey []byte
167+
SequenceNumber uint32
168+
KesPeriod uint32
169+
Signature []byte
170+
}
171+
172+
type BabbageProtoVersion struct {
173+
cbor.StructAsArray
174+
Major uint64
175+
Minor uint64
176+
}
177+
172178
func (h *BabbageBlockHeader) UnmarshalCBOR(cborData []byte) error {
173179
return h.UnmarshalCbor(cborData, h)
174180
}

ledger/block.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,21 @@ func NewBlockHeaderFromCbor(blockType uint, data []byte) (BlockHeader, error) {
5555
return NewByronEpochBoundaryBlockHeaderFromCbor(data)
5656
case BlockTypeByronMain:
5757
return NewByronMainBlockHeaderFromCbor(data)
58-
// TODO: break into separate cases and parse as specific block header types (#844)
59-
case BlockTypeShelley, BlockTypeAllegra, BlockTypeMary, BlockTypeAlonzo:
58+
case BlockTypeShelley:
6059
return NewShelleyBlockHeaderFromCbor(data)
61-
case BlockTypeBabbage, BlockTypeConway:
60+
case BlockTypeAllegra:
61+
return NewAllegraBlockHeaderFromCbor(data)
62+
case BlockTypeMary:
63+
return NewMaryBlockHeaderFromCbor(data)
64+
case BlockTypeAlonzo:
65+
return NewAlonzoBlockHeaderFromCbor(data)
66+
case BlockTypeBabbage:
6267
return NewBabbageBlockHeaderFromCbor(data)
68+
case BlockTypeConway:
69+
return NewConwayBlockHeaderFromCbor(data)
70+
default:
71+
return nil, fmt.Errorf("unknown node-to-node block type: %d", blockType)
6372
}
64-
return nil, fmt.Errorf("unknown node-to-node block type: %d", blockType)
6573
}
6674

6775
func DetermineBlockType(data []byte) (uint, error) {

ledger/block_test.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package ledger
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/blinklabs-io/gouroboros/ledger/allegra"
8+
"github.com/blinklabs-io/gouroboros/ledger/babbage"
9+
"github.com/blinklabs-io/gouroboros/ledger/common"
10+
"github.com/blinklabs-io/gouroboros/ledger/mary"
11+
"github.com/blinklabs-io/gouroboros/ledger/shelley"
12+
"github.com/fxamacker/cbor/v2"
13+
)
14+
15+
func mockShelleyCBOR() []byte {
16+
shelleyHeader := shelley.ShelleyBlockHeader{
17+
Body: shelley.ShelleyBlockHeaderBody{
18+
BlockNumber: 12345,
19+
Slot: 67890,
20+
PrevHash: common.Blake2b256{},
21+
IssuerVkey: common.IssuerVkey{},
22+
VrfKey: []byte{0x01, 0x02},
23+
NonceVrf: common.VrfResult{},
24+
LeaderVrf: common.VrfResult{},
25+
BlockBodySize: 512,
26+
BlockBodyHash: common.Blake2b256{},
27+
OpCertHotVkey: []byte{0x03, 0x04},
28+
OpCertSequenceNumber: 10,
29+
OpCertKesPeriod: 20,
30+
OpCertSignature: []byte{0x05, 0x06},
31+
ProtoMajorVersion: 1,
32+
ProtoMinorVersion: 0,
33+
},
34+
Signature: []byte{0x07, 0x08},
35+
}
36+
37+
// Convert to CBOR
38+
data, err := cbor.Marshal(shelleyHeader)
39+
if err != nil {
40+
fmt.Printf("CBOR Encoding Error: %v\n", err)
41+
}
42+
return data
43+
}
44+
45+
func mockAllegraCBOR() []byte {
46+
allegraHeader := allegra.AllegraBlockHeader{ShelleyBlockHeader: ShelleyBlockHeader{}}
47+
data, _ := cbor.Marshal(allegraHeader)
48+
return data
49+
}
50+
51+
func mockMaryCBOR() []byte {
52+
maryHeader := mary.MaryBlockHeader{ShelleyBlockHeader: ShelleyBlockHeader{}}
53+
data, _ := cbor.Marshal(maryHeader)
54+
return data
55+
}
56+
57+
func mockAlonzoCBOR() []byte {
58+
alonzoHeader := AlonzoBlockHeader{ShelleyBlockHeader: ShelleyBlockHeader{}}
59+
data, _ := cbor.Marshal(alonzoHeader)
60+
return data
61+
}
62+
63+
func mockBabbageCBOR() []byte {
64+
babbageHeader := babbage.BabbageBlockHeader{
65+
Body: babbage.BabbageBlockHeaderBody{
66+
BlockNumber: 54321,
67+
Slot: 98765,
68+
PrevHash: common.Blake2b256{},
69+
IssuerVkey: common.IssuerVkey{},
70+
VrfKey: []byte{0x09, 0x10},
71+
VrfResult: common.VrfResult{},
72+
BlockBodySize: 1024,
73+
BlockBodyHash: common.Blake2b256{},
74+
OpCert: babbage.BabbageOpCert{
75+
HotVkey: []byte{0x11, 0x12},
76+
SequenceNumber: 30,
77+
KesPeriod: 40,
78+
Signature: []byte{0x13, 0x14},
79+
},
80+
ProtoVersion: babbage.BabbageProtoVersion{
81+
Major: 2,
82+
Minor: 0,
83+
},
84+
},
85+
Signature: []byte{0x15, 0x16},
86+
}
87+
88+
// Convert to CBOR
89+
data, err := cbor.Marshal(babbageHeader)
90+
if err != nil {
91+
fmt.Printf("CBOR Encoding Error for Babbage: %v\n", err)
92+
}
93+
return data
94+
}
95+
96+
func mockConwayCBOR() []byte {
97+
conwayHeader := ConwayBlockHeader{BabbageBlockHeader: BabbageBlockHeader{}}
98+
data, _ := cbor.Marshal(conwayHeader)
99+
return data
100+
}
101+
102+
func TestNewBlockHeaderFromCbor(t *testing.T) {
103+
tests := []struct {
104+
name string
105+
blockType uint
106+
data []byte
107+
expectErr bool
108+
expectedFn string
109+
}{
110+
{"Shelley Block", BlockTypeShelley, mockShelleyCBOR(), false, "NewShelleyBlockHeaderFromCbor"},
111+
{"Allegra Block", BlockTypeAllegra, mockAllegraCBOR(), false, "NewAllegraBlockHeaderFromCbor"},
112+
{"Mary Block", BlockTypeMary, mockMaryCBOR(), false, "NewMaryBlockHeaderFromCbor"},
113+
{"Alonzo Block", BlockTypeAlonzo, mockAlonzoCBOR(), false, "NewAlonzoBlockHeaderFromCbor"},
114+
{"Babbage Block", BlockTypeBabbage, mockBabbageCBOR(), false, "NewBabbageBlockHeaderFromCbor"},
115+
{"Conway Block", BlockTypeConway, mockConwayCBOR(), false, "NewConwayBlockHeaderFromCbor"},
116+
{"Invalid Block Type", 9999, []byte{0xFF, 0x00, 0x00}, true, "UnknownFunction"},
117+
}
118+
119+
for _, test := range tests {
120+
t.Run(test.name, func(t *testing.T) {
121+
fmt.Printf("\n Running Test: %s\n", test.name)
122+
123+
header, err := NewBlockHeaderFromCbor(test.blockType, test.data)
124+
125+
if test.expectErr {
126+
if err == nil {
127+
t.Errorf("Expected error for %s, but got none!", test.name)
128+
} else {
129+
fmt.Printf("Expected failure for %s: %v\n", test.name, err)
130+
}
131+
} else {
132+
if err != nil {
133+
t.Errorf("Unexpected error for %s: %v", test.name, err)
134+
} else if header == nil {
135+
t.Errorf("Expected non-nil block header for %s, but got nil", test.name)
136+
} else {
137+
fmt.Printf("Test Passed: %s → %s executed successfully!\n", test.name, test.expectedFn)
138+
}
139+
}
140+
})
141+
}
142+
}

ledger/mary.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242
// Mary functions
4343
var (
4444
NewMaryBlockFromCbor = mary.NewMaryBlockFromCbor
45+
NewMaryBlockHeaderFromCbor = mary.NewMaryBlockHeaderFromCbor
4546
NewMaryTransactionFromCbor = mary.NewMaryTransactionFromCbor
4647
NewMaryTransactionBodyFromCbor = mary.NewMaryTransactionBodyFromCbor
4748
NewMaryTransactionOutputFromCbor = mary.NewMaryTransactionOutputFromCbor

ledger/mary/mary.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,14 @@ func NewMaryBlockFromCbor(data []byte) (*MaryBlock, error) {
410410
return &maryBlock, nil
411411
}
412412

413+
func NewMaryBlockHeaderFromCbor(data []byte) (*MaryBlockHeader, error) {
414+
var maryBlockHeader MaryBlockHeader
415+
if _, err := cbor.Decode(data, &maryBlockHeader); err != nil {
416+
return nil, fmt.Errorf("Mary block header decode error: %w", err)
417+
}
418+
return &maryBlockHeader, nil
419+
}
420+
413421
func NewMaryTransactionBodyFromCbor(data []byte) (*MaryTransactionBody, error) {
414422
var maryTx MaryTransactionBody
415423
if _, err := cbor.Decode(data, &maryTx); err != nil {

ledger/shelley/shelley.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -132,27 +132,28 @@ func (b *ShelleyBlock) Utxorpc() *utxorpc.Block {
132132
type ShelleyBlockHeader struct {
133133
cbor.StructAsArray
134134
cbor.DecodeStoreCbor
135-
hash string
136-
Body struct {
137-
cbor.StructAsArray
138-
BlockNumber uint64
139-
Slot uint64
140-
PrevHash common.Blake2b256
141-
IssuerVkey common.IssuerVkey
142-
VrfKey []byte
143-
NonceVrf common.VrfResult
144-
LeaderVrf common.VrfResult
145-
BlockBodySize uint64
146-
BlockBodyHash common.Blake2b256
147-
OpCertHotVkey []byte
148-
OpCertSequenceNumber uint32
149-
OpCertKesPeriod uint32
150-
OpCertSignature []byte
151-
ProtoMajorVersion uint64
152-
ProtoMinorVersion uint64
153-
}
135+
hash string
136+
Body ShelleyBlockHeaderBody
154137
Signature []byte
155138
}
139+
type ShelleyBlockHeaderBody struct {
140+
cbor.StructAsArray
141+
BlockNumber uint64
142+
Slot uint64
143+
PrevHash common.Blake2b256
144+
IssuerVkey common.IssuerVkey
145+
VrfKey []byte
146+
NonceVrf common.VrfResult
147+
LeaderVrf common.VrfResult
148+
BlockBodySize uint64
149+
BlockBodyHash common.Blake2b256
150+
OpCertHotVkey []byte
151+
OpCertSequenceNumber uint32
152+
OpCertKesPeriod uint32
153+
OpCertSignature []byte
154+
ProtoMajorVersion uint64
155+
ProtoMinorVersion uint64
156+
}
156157

157158
func (h *ShelleyBlockHeader) UnmarshalCBOR(cborData []byte) error {
158159
return h.UnmarshalCbor(cborData, h)

0 commit comments

Comments
 (0)