From 3a1adfb1d49f8c37a51189d6775a993eae4f01ed Mon Sep 17 00:00:00 2001 From: Andrew Gaffney Date: Tue, 7 Mar 2023 20:52:59 -0600 Subject: [PATCH] fix: Babbage block parsing * don't try to parse arbitrary plutus scripts/data * add missing transaction witness set field * better support alternate transaction output format * update Babbage intersect point for preview in test program Fixes #204 --- cmd/go-ouroboros-network/chainsync.go | 2 +- ledger/alonzo.go | 28 ++++++++++++++++--- ledger/babbage.go | 39 +++++++++++++++++++++++---- ledger/mary.go | 10 ++++--- 4 files changed, 66 insertions(+), 13 deletions(-) diff --git a/cmd/go-ouroboros-network/chainsync.go b/cmd/go-ouroboros-network/chainsync.go index e6fac532..5ce8fcbf 100644 --- a/cmd/go-ouroboros-network/chainsync.go +++ b/cmd/go-ouroboros-network/chainsync.go @@ -74,7 +74,7 @@ var eraIntersect = map[string]map[string][]interface{}{ "genesis": []interface{}{}, "alonzo": []interface{}{}, // Last block of epoch 3 (Alonzo era) - "babbage": []interface{}{345599, "6e4de9c9b2dcc2436488aa8a6ce584250a45b42583c5d3d0749597bcf59dc0b5"}, + "babbage": []interface{}{345594, "e47ac07272e95d6c3dc8279def7b88ded00e310f99ac3dfbae48ed9ff55e6001"}, }, } diff --git a/ledger/alonzo.go b/ledger/alonzo.go index f4c95a11..916435b7 100644 --- a/ledger/alonzo.go +++ b/ledger/alonzo.go @@ -64,6 +64,7 @@ func (h *AlonzoBlockHeader) Era() Era { type AlonzoTransactionBody struct { MaryTransactionBody + Outputs []AlonzoTransactionOutput `cbor:"1,keyasint,omitempty"` ScriptDataHash Blake2b256 `cbor:"11,keyasint,omitempty"` Collateral []ShelleyTransactionInput `cbor:"13,keyasint,omitempty"` RequiredSigners []Blake2b224 `cbor:"14,keyasint,omitempty"` @@ -74,11 +75,32 @@ func (b *AlonzoTransactionBody) UnmarshalCBOR(cborData []byte) error { return b.UnmarshalCborGeneric(cborData, b) } +type AlonzoTransactionOutput struct { + cbor.StructAsArray + cbor.DecodeStoreCbor + Address Blake2b256 + Amount cbor.Value + DatumHash Blake2b256 +} + +func (o *AlonzoTransactionOutput) UnmarshalCBOR(cborData []byte) error { + // Try to parse as Mary output first + var tmpOutput MaryTransactionOutput + if _, err := cbor.Decode(cborData, &tmpOutput); err == nil { + // Copy from temp Shelley output to Alonzo format + o.Address = tmpOutput.Address + o.Amount = tmpOutput.Amount + } else { + return o.UnmarshalCborGeneric(cborData, o) + } + return nil +} + type AlonzoTransactionWitnessSet struct { ShelleyTransactionWitnessSet - PlutusScripts interface{} `cbor:"3,keyasint,omitempty"` - PlutusData []cbor.Value `cbor:"4,keyasint,omitempty"` - Redeemers []cbor.Value `cbor:"5,keyasint,omitempty"` + PlutusScripts []cbor.RawMessage `cbor:"3,keyasint,omitempty"` + PlutusData []cbor.RawMessage `cbor:"4,keyasint,omitempty"` + Redeemers []cbor.Value `cbor:"5,keyasint,omitempty"` } type AlonzoTransaction struct { diff --git a/ledger/babbage.go b/ledger/babbage.go index 62a859a1..23b1ee42 100644 --- a/ledger/babbage.go +++ b/ledger/babbage.go @@ -21,7 +21,7 @@ type BabbageBlock struct { cbor.DecodeStoreCbor Header *BabbageBlockHeader TransactionBodies []BabbageTransactionBody - TransactionWitnessSets []AlonzoTransactionWitnessSet + TransactionWitnessSets []BabbageTransactionWitnessSet TransactionMetadataSet map[uint]cbor.Value InvalidTransactions []uint } @@ -109,19 +109,48 @@ func (h *BabbageBlockHeader) Era() Era { type BabbageTransactionBody struct { AlonzoTransactionBody - CollateralReturn ShelleyTransactionOutput `cbor:"16,keyasint,omitempty"` - TotalCollateral uint64 `cbor:"17,keyasint,omitempty"` - ReferenceInputs []ShelleyTransactionInput `cbor:"18,keyasint,omitempty"` + Outputs []BabbageTransactionOutput `cbor:"1,keyasint,omitempty"` + CollateralReturn BabbageTransactionOutput `cbor:"16,keyasint,omitempty"` + TotalCollateral uint64 `cbor:"17,keyasint,omitempty"` + ReferenceInputs []ShelleyTransactionInput `cbor:"18,keyasint,omitempty"` } func (b *BabbageTransactionBody) UnmarshalCBOR(cborData []byte) error { return b.UnmarshalCborGeneric(cborData, b) } +type BabbageTransactionOutput struct { + cbor.DecodeStoreCbor + Address Blake2b256 `cbor:"0,keyasint,omitempty"` + Amount cbor.Value `cbor:"1,keyasint,omitempty"` + DatumOption []cbor.RawMessage `cbor:"2,keyasint,omitempty"` + ScriptRef []cbor.RawMessage `cbor:"3,keyasint,omitempty"` + legacyOutput bool +} + +func (o *BabbageTransactionOutput) UnmarshalCBOR(cborData []byte) error { + // Try to parse as legacy output first + var tmpOutput AlonzoTransactionOutput + if _, err := cbor.Decode(cborData, &tmpOutput); err == nil { + // Copy from temp legacy object to Babbage format + o.Address = tmpOutput.Address + o.Amount = tmpOutput.Amount + o.legacyOutput = true + } else { + return o.UnmarshalCborGeneric(cborData, o) + } + return nil +} + +type BabbageTransactionWitnessSet struct { + AlonzoTransactionWitnessSet + PlutusV2Scripts []cbor.RawMessage `cbor:"6,keyasint,omitempty"` +} + type BabbageTransaction struct { cbor.StructAsArray Body BabbageTransactionBody - WitnessSet AlonzoTransactionWitnessSet + WitnessSet BabbageTransactionWitnessSet IsValid bool Metadata cbor.Value } diff --git a/ledger/mary.go b/ledger/mary.go index 24ecb24c..ec498392 100644 --- a/ledger/mary.go +++ b/ledger/mary.go @@ -63,8 +63,7 @@ func (h *MaryBlockHeader) Era() Era { type MaryTransactionBody struct { AllegraTransactionBody - //Outputs []MaryTransactionOutput `cbor:"1,keyasint,omitempty"` - Outputs []cbor.Value `cbor:"1,keyasint,omitempty"` + Outputs []MaryTransactionOutput `cbor:"1,keyasint,omitempty"` // TODO: further parsing of this field Mint cbor.Value `cbor:"9,keyasint,omitempty"` } @@ -85,9 +84,12 @@ type MaryTransaction struct { transaction_output = [address, amount : value] value = coin / [coin,multiasset] */ -//type MaryTransactionOutput interface{} -type MaryTransactionOutput cbor.Value +type MaryTransactionOutput struct { + cbor.StructAsArray + Address Blake2b256 + Amount cbor.Value +} func NewMaryBlockFromCbor(data []byte) (*MaryBlock, error) { var maryBlock MaryBlock