diff --git a/ledger/alonzo/alonzo.go b/ledger/alonzo/alonzo.go index 0cc54feb..66219ab6 100644 --- a/ledger/alonzo/alonzo.go +++ b/ledger/alonzo/alonzo.go @@ -337,7 +337,7 @@ func (o AlonzoTransactionOutput) Datum() *cbor.LazyValue { return nil } -func (o AlonzoTransactionOutput) Utxorpc() *utxorpc.TxOutput { +func (o AlonzoTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { var assets []*utxorpc.Multiasset if o.Assets() != nil { tmpAssets := o.Assets() @@ -357,14 +357,20 @@ func (o AlonzoTransactionOutput) Utxorpc() *utxorpc.TxOutput { } } + addressBytes, err := o.OutputAddress.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to get address bytes: %w", err) + } + return &utxorpc.TxOutput{ - Address: o.OutputAddress.Bytes(), - Coin: o.Amount(), - Assets: assets, - Datum: &utxorpc.Datum{ - Hash: o.TxOutputDatumHash.Bytes(), + Address: addressBytes, + Coin: o.Amount(), + Assets: assets, + Datum: &utxorpc.Datum{ + Hash: o.TxOutputDatumHash.Bytes(), + }, }, - } + nil } type AlonzoRedeemer struct { diff --git a/ledger/babbage/babbage.go b/ledger/babbage/babbage.go index c1386b25..b9988006 100644 --- a/ledger/babbage/babbage.go +++ b/ledger/babbage/babbage.go @@ -505,12 +505,17 @@ func (o BabbageTransactionOutput) Datum() *cbor.LazyValue { return nil } -func (o BabbageTransactionOutput) Utxorpc() *utxorpc.TxOutput { +func (o BabbageTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { + // Handle address bytes + addressBytes, err := o.OutputAddress.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to get output address bytes: %w", err) + } var address []byte - if o.OutputAddress.Bytes() == nil { + if addressBytes == nil { address = []byte{} } else { - address = o.OutputAddress.Bytes() + address = addressBytes } var assets []*utxorpc.Multiasset @@ -540,15 +545,16 @@ func (o BabbageTransactionOutput) Utxorpc() *utxorpc.TxOutput { } return &utxorpc.TxOutput{ - Address: address, - Coin: o.Amount(), - Assets: assets, - Datum: &utxorpc.Datum{ - Hash: datumHash, - // OriginalCbor: o.Datum().Cbor(), + Address: address, + Coin: o.Amount(), + Assets: assets, + Datum: &utxorpc.Datum{ + Hash: datumHash, + // OriginalCbor: o.Datum().Cbor(), + }, + // Script: o.ScriptRef, }, - // Script: o.ScriptRef, - } + nil } type BabbageTransactionWitnessSet struct { diff --git a/ledger/babbage/babbage_test.go b/ledger/babbage/babbage_test.go index abb9b5de..bd2a162d 100644 --- a/ledger/babbage/babbage_test.go +++ b/ledger/babbage/babbage_test.go @@ -2775,7 +2775,10 @@ func TestBabbageTransactionOutput_Utxorpc_DatumOptionNil(t *testing.T) { DatumOption: &BabbageTransactionOutputDatumOption{}, } - txOutput := output.Utxorpc() + txOutput, err := output.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() failed: %v", err) // Fail and stop the test + } assert.NotNil(t, txOutput) assert.Equal(t, []byte{}, txOutput.Datum.Hash) diff --git a/ledger/byron/byron.go b/ledger/byron/byron.go index c40247fe..5f83800e 100644 --- a/ledger/byron/byron.go +++ b/ledger/byron/byron.go @@ -430,11 +430,16 @@ func (o ByronTransactionOutput) Datum() *cbor.LazyValue { return nil } -func (o ByronTransactionOutput) Utxorpc() *utxorpc.TxOutput { - return &utxorpc.TxOutput{ - Address: o.OutputAddress.Bytes(), - Coin: o.Amount(), +func (o ByronTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { + addressBytes, err := o.OutputAddress.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to get address bytes: %w", err) } + return &utxorpc.TxOutput{ + Address: addressBytes, + Coin: o.Amount(), + }, + nil } type ByronBlockVersion struct { diff --git a/ledger/common/address.go b/ledger/common/address.go index 29a79bd9..1e5fd8c1 100644 --- a/ledger/common/address.go +++ b/ledger/common/address.go @@ -269,7 +269,11 @@ func (a *Address) UnmarshalCBOR(data []byte) error { } func (a *Address) MarshalCBOR() ([]byte, error) { - addrBytes := a.Bytes() + addrBytes, err := a.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to get address bytes: %w", err) + } + if a.addressType == AddressTypeByron { return addrBytes, nil } @@ -376,7 +380,7 @@ func (a Address) generateHRP() string { } // Bytes returns the underlying bytes for the address -func (a Address) Bytes() []byte { +func (a Address) Bytes() ([]byte, error) { if a.addressType == AddressTypeByron { tmpPayload := []any{ a.paymentAddress, @@ -385,8 +389,7 @@ func (a Address) Bytes() []byte { } rawPayload, err := cbor.Encode(tmpPayload) if err != nil { - // TODO: handle error (#851) - return nil + return nil, fmt.Errorf("failed to encode Byron address payload: %w", err) } tmpData := []any{ cbor.Tag{ @@ -397,10 +400,9 @@ func (a Address) Bytes() []byte { } ret, err := cbor.Encode(tmpData) if err != nil { - // TODO: handle error (#851) - return nil + return nil, fmt.Errorf("failed to encode Byron address data: %w", err) } - return ret + return ret, nil } ret := []byte{} ret = append( @@ -410,12 +412,15 @@ func (a Address) Bytes() []byte { ret = append(ret, a.paymentAddress...) ret = append(ret, a.stakingAddress...) ret = append(ret, a.extraData...) - return ret + return ret, nil } // String returns the bech32-encoded version of the address func (a Address) String() string { - data := a.Bytes() + data, err := a.Bytes() + if err != nil { + panic(fmt.Sprintf("failed to get address bytes: %v", err)) + } if a.addressType == AddressTypeByron { // Encode data to base58 encoded := base58.Encode(data) diff --git a/ledger/common/tx.go b/ledger/common/tx.go index 96a7fbae..5a2ff6c8 100644 --- a/ledger/common/tx.go +++ b/ledger/common/tx.go @@ -70,7 +70,7 @@ type TransactionOutput interface { Datum() *cbor.LazyValue DatumHash() *Blake2b256 Cbor() []byte - Utxorpc() *utxorpc.TxOutput + Utxorpc() (*utxorpc.TxOutput, error) } type TransactionWitnessSet interface { @@ -200,7 +200,10 @@ func TransactionBodyToUtxorpc(tx TransactionBody) *utxorpc.Tx { txi = append(txi, input) } for _, o := range tx.Outputs() { - output := o.Utxorpc() + output, err := o.Utxorpc() + if err != nil { + return nil + } txo = append(txo, output) } for _, ri := range tx.ReferenceInputs() { diff --git a/ledger/mary/mary.go b/ledger/mary/mary.go index 612c2b8c..9e6acedf 100644 --- a/ledger/mary/mary.go +++ b/ledger/mary/mary.go @@ -455,12 +455,17 @@ func (o MaryTransactionOutput) Datum() *cbor.LazyValue { return nil } -func (o MaryTransactionOutput) Utxorpc() *utxorpc.TxOutput { - return &utxorpc.TxOutput{ - Address: o.OutputAddress.Bytes(), - Coin: o.Amount(), - // Assets: o.Assets, +func (o MaryTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { + addressBytes, err := o.OutputAddress.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to get address bytes: %w", err) } + return &utxorpc.TxOutput{ + Address: addressBytes, + Coin: o.Amount(), + // Assets: o.Assets, + }, + err } type MaryTransactionOutputValue struct { diff --git a/ledger/shelley/pparams_test.go b/ledger/shelley/pparams_test.go index 2bba89f0..95808d6c 100644 --- a/ledger/shelley/pparams_test.go +++ b/ledger/shelley/pparams_test.go @@ -195,11 +195,20 @@ func TestShelleyTransactionOutput_Utxorpc(t *testing.T) { } // Convert it to utxorpc format - actual := output.Utxorpc() + actual, err := output.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() failed: %v", err) // Fail immediately on error + } + + // Get expected address bytes (with error handling) + expectedAddressBytes, err := address.Bytes() + if err != nil { + t.Fatalf("address.Bytes() failed: %v", err) + } // expected output in utxorpc format expected := &cardano.TxOutput{ - Address: address.Bytes(), + Address: expectedAddressBytes, Coin: 1000, } diff --git a/ledger/shelley/shelley.go b/ledger/shelley/shelley.go index 9508673d..1070fc53 100644 --- a/ledger/shelley/shelley.go +++ b/ledger/shelley/shelley.go @@ -401,11 +401,16 @@ func (o ShelleyTransactionOutput) Datum() *cbor.LazyValue { return nil } -func (o ShelleyTransactionOutput) Utxorpc() *utxorpc.TxOutput { +func (o ShelleyTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { + addressBytes, err := o.OutputAddress.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to get address bytes: %w", err) + } + return &utxorpc.TxOutput{ - Address: o.OutputAddress.Bytes(), + Address: addressBytes, Coin: o.Amount(), - } + }, nil } type ShelleyTransactionWitnessSet struct {