Skip to content

Commit dec8c32

Browse files
committed
fix(ledger): use raw bytes for metadata
Signed-off-by: Chris Gianelloni <[email protected]>
1 parent ac6eddd commit dec8c32

File tree

10 files changed

+584
-177
lines changed

10 files changed

+584
-177
lines changed

ledger/allegra/allegra.go

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ func (b *AllegraBlock) UnmarshalCBOR(cborData []byte) error {
6161
}
6262
*b = AllegraBlock(tmp)
6363
b.SetCbor(cborData)
64+
65+
// Extract and store CBOR for each component
66+
if err := common.ExtractTransactionCbor(cborData, &b.TransactionBodies, &b.TransactionWitnessSets); err != nil {
67+
return err
68+
}
6469
return nil
6570
}
6671

@@ -104,13 +109,14 @@ func (b *AllegraBlock) Transactions() []common.Transaction {
104109
ret := make([]common.Transaction, len(b.TransactionBodies))
105110
// #nosec G115
106111
for idx := range b.TransactionBodies {
107-
// Note: Ignoring the presence flag; if distinguishing "missing" vs "present but empty/failed decode" is needed, plumb the second return value through
108-
txMetadata, _ := b.TransactionMetadataSet.GetMetadata(uint(idx))
109-
ret[idx] = &AllegraTransaction{
112+
tx := &AllegraTransaction{
110113
Body: b.TransactionBodies[idx],
111114
WitnessSet: b.TransactionWitnessSets[idx],
112-
TxMetadata: txMetadata,
113115
}
116+
if metadata, ok := b.TransactionMetadataSet.GetMetadata(uint(idx)); ok {
117+
tx.TxMetadata = metadata
118+
}
119+
ret[idx] = tx
114120
}
115121
return ret
116122
}
@@ -250,12 +256,32 @@ type AllegraTransaction struct {
250256
}
251257

252258
func (t *AllegraTransaction) UnmarshalCBOR(cborData []byte) error {
253-
type tAllegraTransaction AllegraTransaction
254-
var tmp tAllegraTransaction
255-
if _, err := cbor.Decode(cborData, &tmp); err != nil {
259+
// Decode as raw array to capture metadata bytes
260+
var txArray []cbor.RawMessage
261+
if _, err := cbor.Decode(cborData, &txArray); err != nil {
256262
return err
257263
}
258-
*t = AllegraTransaction(tmp)
264+
if len(txArray) < 2 {
265+
return fmt.Errorf(
266+
"invalid transaction: expected at least 2 components, got %d",
267+
len(txArray),
268+
)
269+
}
270+
// Decode body and witness set
271+
if _, err := cbor.Decode(txArray[0], &t.Body); err != nil {
272+
return fmt.Errorf("failed to decode transaction body: %w", err)
273+
}
274+
if _, err := cbor.Decode(txArray[1], &t.WitnessSet); err != nil {
275+
return fmt.Errorf("failed to decode transaction witness set: %w", err)
276+
}
277+
// Handle metadata (component 3)
278+
// DecodeAuxiliaryDataToMetadata already preserves raw bytes via DecodeMetadatumRaw
279+
if len(txArray) > 2 && len(txArray[2]) > 0 {
280+
metadata, err := common.DecodeAuxiliaryDataToMetadata(txArray[2])
281+
if err == nil && metadata != nil {
282+
t.TxMetadata = metadata
283+
}
284+
}
259285
t.SetCbor(cborData)
260286
return nil
261287
}
@@ -356,7 +382,7 @@ func (t AllegraTransaction) Donation() uint64 {
356382
return t.Body.Donation()
357383
}
358384

359-
func (t AllegraTransaction) Metadata() common.TransactionMetadatum {
385+
func (t *AllegraTransaction) Metadata() common.TransactionMetadatum {
360386
return t.TxMetadata
361387
}
362388

@@ -401,6 +427,25 @@ func (t AllegraTransaction) Utxorpc() (*utxorpc.Tx, error) {
401427
return tx, nil
402428
}
403429

430+
func (t *AllegraTransaction) MarshalCBOR() ([]byte, error) {
431+
// If we have stored CBOR (from decode), return it to preserve metadata bytes
432+
cborData := t.DecodeStoreCbor.Cbor()
433+
if cborData != nil {
434+
return cborData, nil
435+
}
436+
// Otherwise, construct and encode
437+
tmpObj := []any{
438+
t.Body,
439+
t.WitnessSet,
440+
}
441+
if t.TxMetadata != nil {
442+
tmpObj = append(tmpObj, cbor.RawMessage(t.TxMetadata.Cbor()))
443+
} else {
444+
tmpObj = append(tmpObj, nil)
445+
}
446+
return cbor.Encode(tmpObj)
447+
}
448+
404449
func (t *AllegraTransaction) Cbor() []byte {
405450
// Return stored CBOR if we have any
406451
cborData := t.DecodeStoreCbor.Cbor()
@@ -411,19 +456,8 @@ func (t *AllegraTransaction) Cbor() []byte {
411456
if t.Body.Cbor() == nil {
412457
return nil
413458
}
414-
// Generate our own CBOR
415-
// This is necessary when a transaction is put together from pieces stored separately in a block
416-
tmpObj := []any{
417-
cbor.RawMessage(t.Body.Cbor()),
418-
cbor.RawMessage(t.WitnessSet.Cbor()),
419-
}
420-
if t.TxMetadata != nil {
421-
tmpObj = append(tmpObj, t.TxMetadata)
422-
} else {
423-
tmpObj = append(tmpObj, nil)
424-
}
425-
// This should never fail, since we're only encoding a list and a bool value
426-
cborData, err := cbor.Encode(&tmpObj)
459+
// Delegate to MarshalCBOR which handles encoding
460+
cborData, err := cbor.Encode(t)
427461
if err != nil {
428462
panic("CBOR encoding that should never fail has failed: " + err.Error())
429463
}

ledger/alonzo/alonzo.go

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ func (b *AlonzoBlock) UnmarshalCBOR(cborData []byte) error {
6868
}
6969
*b = AlonzoBlock(tmp)
7070
b.SetCbor(cborData)
71+
72+
// Extract and store CBOR for each component
73+
if err := common.ExtractTransactionCbor(cborData, &b.TransactionBodies, &b.TransactionWitnessSets); err != nil {
74+
return err
75+
}
7176
return nil
7277
}
7378

@@ -156,14 +161,15 @@ func (b *AlonzoBlock) Transactions() []common.Transaction {
156161
ret := make([]common.Transaction, len(b.TransactionBodies))
157162
// #nosec G115
158163
for idx := range b.TransactionBodies {
159-
// Note: Ignoring the presence flag; if distinguishing "missing" vs "present but empty/failed decode" is needed, plumb the second return value through
160-
txMetadata, _ := b.TransactionMetadataSet.GetMetadata(uint(idx))
161-
ret[idx] = &AlonzoTransaction{
164+
tx := &AlonzoTransaction{
162165
Body: b.TransactionBodies[idx],
163166
WitnessSet: b.TransactionWitnessSets[idx],
164-
TxMetadata: txMetadata,
165167
TxIsValid: !invalidTxMap[uint(idx)],
166168
}
169+
if metadata, ok := b.TransactionMetadataSet.GetMetadata(uint(idx)); ok {
170+
tx.TxMetadata = metadata
171+
}
172+
ret[idx] = tx
167173
}
168174
return ret
169175
}
@@ -646,16 +652,52 @@ type AlonzoTransaction struct {
646652
}
647653

648654
func (t *AlonzoTransaction) UnmarshalCBOR(cborData []byte) error {
649-
type tAlonzoTransaction AlonzoTransaction
650-
var tmp tAlonzoTransaction
651-
if _, err := cbor.Decode(cborData, &tmp); err != nil {
655+
// Decode as raw array to preserve metadata bytes
656+
var txArray []cbor.RawMessage
657+
if _, err := cbor.Decode(cborData, &txArray); err != nil {
652658
return err
653659
}
654-
*t = AlonzoTransaction(tmp)
660+
661+
// Ensure we have at least 3 components
662+
if len(txArray) < 3 {
663+
return fmt.Errorf(
664+
"invalid transaction: expected at least 3 components, got %d",
665+
len(txArray),
666+
)
667+
}
668+
669+
// Decode body
670+
if _, err := cbor.Decode([]byte(txArray[0]), &t.Body); err != nil {
671+
return fmt.Errorf("failed to decode transaction body: %w", err)
672+
}
673+
674+
// Decode witness set
675+
if _, err := cbor.Decode([]byte(txArray[1]), &t.WitnessSet); err != nil {
676+
return fmt.Errorf("failed to decode transaction witness set: %w", err)
677+
}
678+
679+
// Decode TxIsValid flag
680+
if _, err := cbor.Decode([]byte(txArray[2]), &t.TxIsValid); err != nil {
681+
return fmt.Errorf("failed to decode TxIsValid: %w", err)
682+
}
683+
684+
// Handle metadata (component 4)
685+
// DecodeAuxiliaryDataToMetadata already preserves raw bytes via DecodeMetadatumRaw
686+
if len(txArray) > 3 && len(txArray[3]) > 0 {
687+
metadata, err := common.DecodeAuxiliaryDataToMetadata(txArray[3])
688+
if err == nil && metadata != nil {
689+
t.TxMetadata = metadata
690+
}
691+
}
692+
655693
t.SetCbor(cborData)
656694
return nil
657695
}
658696

697+
func (t *AlonzoTransaction) Metadata() common.TransactionMetadatum {
698+
return t.TxMetadata
699+
}
700+
659701
func (AlonzoTransaction) Type() int {
660702
return TxTypeAlonzo
661703
}
@@ -756,10 +798,6 @@ func (t AlonzoTransaction) Donation() uint64 {
756798
return t.Body.Donation()
757799
}
758800

759-
func (t AlonzoTransaction) Metadata() common.TransactionMetadatum {
760-
return t.TxMetadata
761-
}
762-
763801
func (t AlonzoTransaction) IsValid() bool {
764802
return t.TxIsValid
765803
}
@@ -798,30 +836,38 @@ func (t AlonzoTransaction) Witnesses() common.TransactionWitnessSet {
798836
return t.WitnessSet
799837
}
800838

801-
func (t *AlonzoTransaction) Cbor() []byte {
802-
// Return stored CBOR if we have any
839+
func (t *AlonzoTransaction) MarshalCBOR() ([]byte, error) {
840+
// If we have stored CBOR (from decode), return it to preserve metadata bytes
803841
cborData := t.DecodeStoreCbor.Cbor()
804842
if len(cborData) > 0 {
805-
return cborData[:]
843+
return cborData, nil
806844
}
807-
// Return immediately if the body CBOR is also empty, which implies an empty TX object
808-
if t.Body.Cbor() == nil {
809-
return nil
810-
}
811-
// Generate our own CBOR
812-
// This is necessary when a transaction is put together from pieces stored separately in a block
845+
// Otherwise, construct and encode
813846
tmpObj := []any{
814-
cbor.RawMessage(t.Body.Cbor()),
815-
cbor.RawMessage(t.WitnessSet.Cbor()),
847+
t.Body,
848+
t.WitnessSet,
816849
t.TxIsValid,
817850
}
818851
if t.TxMetadata != nil {
819-
tmpObj = append(tmpObj, t.TxMetadata)
852+
tmpObj = append(tmpObj, cbor.RawMessage(t.TxMetadata.Cbor()))
820853
} else {
821854
tmpObj = append(tmpObj, nil)
822855
}
823-
// This should never fail, since we're only encoding a list and a bool value
824-
cborData, err := cbor.Encode(&tmpObj)
856+
return cbor.Encode(tmpObj)
857+
}
858+
859+
func (t *AlonzoTransaction) Cbor() []byte {
860+
// Return stored CBOR if we have any
861+
cborData := t.DecodeStoreCbor.Cbor()
862+
if len(cborData) > 0 {
863+
return cborData[:]
864+
}
865+
// Return immediately if the body CBOR is also empty, which implies an empty TX object
866+
if t.Body.Cbor() == nil {
867+
return nil
868+
}
869+
// Delegate to MarshalCBOR which handles encoding
870+
cborData, err := cbor.Encode(t)
825871
if err != nil {
826872
panic("CBOR encoding that should never fail has failed: " + err.Error())
827873
}

0 commit comments

Comments
 (0)