diff --git a/ledger/allegra/allegra.go b/ledger/allegra/allegra.go index 5293b0d4..efc12c44 100644 --- a/ledger/allegra/allegra.go +++ b/ledger/allegra/allegra.go @@ -112,10 +112,13 @@ func (b *AllegraBlock) Transactions() []common.Transaction { return ret } -func (b *AllegraBlock) Utxorpc() *utxorpc.Block { +func (b *AllegraBlock) Utxorpc() (*utxorpc.Block, error) { txs := []*utxorpc.Tx{} for _, t := range b.Transactions() { - tx := t.Utxorpc() + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } txs = append(txs, tx) } body := &utxorpc.BlockBody{ @@ -130,7 +133,7 @@ func (b *AllegraBlock) Utxorpc() *utxorpc.Block { Body: body, Header: header, } - return block + return block, nil } type AllegraBlockHeader struct { @@ -221,8 +224,8 @@ func (b *AllegraTransactionBody) AuxDataHash() *common.Blake2b256 { return b.TxAuxDataHash } -func (b *AllegraTransactionBody) Utxorpc() *utxorpc.Tx { - return common.TransactionBodyToUtxorpc(b) +func (b *AllegraTransactionBody) Utxorpc() (*utxorpc.Tx, error) { + return common.TransactionBodyToUtxorpc(b), nil } type AllegraTransaction struct { @@ -332,8 +335,12 @@ func (t AllegraTransaction) Metadata() *cbor.LazyValue { return t.TxMetadata } -func (t AllegraTransaction) Utxorpc() *utxorpc.Tx { - return t.Body.Utxorpc() +func (t AllegraTransaction) Utxorpc() (*utxorpc.Tx, error) { + tx, err := t.Body.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert transaction body: %w", err) + } + return tx, nil } func (t AllegraTransaction) IsValid() bool { diff --git a/ledger/allegra/pparams_test.go b/ledger/allegra/pparams_test.go index c84bb3b9..a03d1130 100644 --- a/ledger/allegra/pparams_test.go +++ b/ledger/allegra/pparams_test.go @@ -120,8 +120,10 @@ func TestAllegraUtxorpc(t *testing.T) { }, } - result := inputParams.Utxorpc() - + result, err := inputParams.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() conversion failed: %v", err) + } if !reflect.DeepEqual(result, expectedUtxorpc) { t.Fatalf( "Utxorpc() test failed for Allegra:\nExpected: %#v\nGot: %#v", @@ -160,7 +162,10 @@ func TestAllegraTransactionBody_Utxorpc(t *testing.T) { } // Run Utxorpc conversion - actual := txBody.Utxorpc() + actual, err := txBody.Utxorpc() + if err != nil { + t.Errorf("Failed to convert the transaction") + } // Check that the fee matches if actual.Fee != txBody.Fee() { @@ -220,8 +225,10 @@ func TestAllegraTransaction_Utxorpc(t *testing.T) { } // Run Utxorpc conversion - actual := tx.Utxorpc() - + actual, err := tx.Utxorpc() + if err != nil { + t.Errorf("Failed to convert the transaction") + } // Assertion checks if actual.Fee != tx.Fee() { t.Errorf( diff --git a/ledger/alonzo/alonzo.go b/ledger/alonzo/alonzo.go index 66219ab6..6a483234 100644 --- a/ledger/alonzo/alonzo.go +++ b/ledger/alonzo/alonzo.go @@ -121,10 +121,13 @@ func (b *AlonzoBlock) Transactions() []common.Transaction { return ret } -func (b *AlonzoBlock) Utxorpc() *utxorpc.Block { +func (b *AlonzoBlock) Utxorpc() (*utxorpc.Block, error) { txs := []*utxorpc.Tx{} for _, t := range b.Transactions() { - tx := t.Utxorpc() + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } txs = append(txs, tx) } body := &utxorpc.BlockBody{ @@ -139,7 +142,7 @@ func (b *AlonzoBlock) Utxorpc() *utxorpc.Block { Body: body, Header: header, } - return block + return block, nil } type AlonzoBlockHeader struct { @@ -255,8 +258,8 @@ func (b *AlonzoTransactionBody) ScriptDataHash() *common.Blake2b256 { return b.TxScriptDataHash } -func (b *AlonzoTransactionBody) Utxorpc() *utxorpc.Tx { - return common.TransactionBodyToUtxorpc(b) +func (b *AlonzoTransactionBody) Utxorpc() (*utxorpc.Tx, error) { + return common.TransactionBodyToUtxorpc(b), nil } type AlonzoTransactionOutput struct { @@ -640,8 +643,12 @@ func (t *AlonzoTransaction) Cbor() []byte { return cborData } -func (t *AlonzoTransaction) Utxorpc() *utxorpc.Tx { - return t.Body.Utxorpc() +func (t *AlonzoTransaction) Utxorpc() (*utxorpc.Tx, error) { + tx, err := t.Body.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert Alonzo transaction: %w", err) + } + return tx, nil } func NewAlonzoBlockFromCbor(data []byte) (*AlonzoBlock, error) { diff --git a/ledger/alonzo/pparams.go b/ledger/alonzo/pparams.go index d9803386..ca2f70ac 100644 --- a/ledger/alonzo/pparams.go +++ b/ledger/alonzo/pparams.go @@ -15,6 +15,7 @@ package alonzo import ( + "errors" "fmt" "maps" "math" @@ -273,32 +274,32 @@ func (u *AlonzoProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { return nil } -func (p *AlonzoProtocolParameters) Utxorpc() *cardano.PParams { +func (p *AlonzoProtocolParameters) Utxorpc() (*cardano.PParams, error) { // sanity check if p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid A0 rational number values") } if p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Rho rational number values") } if p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Tau rational number values") } if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid memory price rational number values") } if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid step price rational number values") } // #nosec G115 return &cardano.PParams{ @@ -353,7 +354,7 @@ func (p *AlonzoProtocolParameters) Utxorpc() *cardano.PParams { Memory: p.MaxBlockExUnits.Memory, Steps: p.MaxBlockExUnits.Steps, }, - } + }, nil } func UpgradePParams( diff --git a/ledger/alonzo/pparams_test.go b/ledger/alonzo/pparams_test.go index 18b3e7b2..fc206cf1 100644 --- a/ledger/alonzo/pparams_test.go +++ b/ledger/alonzo/pparams_test.go @@ -431,7 +431,10 @@ func TestAlonzoUtxorpc(t *testing.T) { }, } - result := inputParams.Utxorpc() + result, err := inputParams.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() conversion failed") + } if !reflect.DeepEqual(result, expectedUtxorpc) { t.Fatalf( @@ -512,7 +515,10 @@ func TestAlonzoTransactionBody_Utxorpc(t *testing.T) { } // Run Utxorpc conversion - got := body.Utxorpc() + got, err := body.Utxorpc() + if err != nil { + t.Errorf("Failed to convert the transaction") + } // Assertion checks if got.Fee != 50 { @@ -572,7 +578,10 @@ func TestAlonzoTransaction_Utxorpc(t *testing.T) { } // Run Utxorpc conversion - got := tx.Utxorpc() + got, err := tx.Utxorpc() + if err != nil { + t.Errorf("Failed to convert the transaction") + } // Assertion checks if got.Fee != 75 { diff --git a/ledger/babbage/babbage.go b/ledger/babbage/babbage.go index b9988006..e0e758b7 100644 --- a/ledger/babbage/babbage.go +++ b/ledger/babbage/babbage.go @@ -123,10 +123,13 @@ func (b *BabbageBlock) Transactions() []common.Transaction { return ret } -func (b *BabbageBlock) Utxorpc() *utxorpc.Block { +func (b *BabbageBlock) Utxorpc() (*utxorpc.Block, error) { txs := []*utxorpc.Tx{} for _, t := range b.Transactions() { - tx := t.Utxorpc() + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } txs = append(txs, tx) } body := &utxorpc.BlockBody{ @@ -141,7 +144,7 @@ func (b *BabbageBlock) Utxorpc() *utxorpc.Block { Body: body, Header: header, } - return block + return block, nil } type BabbageBlockHeader struct { @@ -353,8 +356,8 @@ func (b *BabbageTransactionBody) TotalCollateral() uint64 { return b.TxTotalCollateral } -func (b *BabbageTransactionBody) Utxorpc() *utxorpc.Tx { - return common.TransactionBodyToUtxorpc(b) +func (b *BabbageTransactionBody) Utxorpc() (*utxorpc.Tx, error) { + return common.TransactionBodyToUtxorpc(b), nil } const ( @@ -799,8 +802,12 @@ func (t *BabbageTransaction) Cbor() []byte { return cborData } -func (t *BabbageTransaction) Utxorpc() *utxorpc.Tx { - return t.Body.Utxorpc() +func (t *BabbageTransaction) Utxorpc() (*utxorpc.Tx, error) { + tx, err := t.Body.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert Babbage transaction: %w", err) + } + return tx, nil } func NewBabbageBlockFromCbor(data []byte) (*BabbageBlock, error) { diff --git a/ledger/babbage/babbage_test.go b/ledger/babbage/babbage_test.go index bd2a162d..cd2b3cb6 100644 --- a/ledger/babbage/babbage_test.go +++ b/ledger/babbage/babbage_test.go @@ -2731,7 +2731,10 @@ func TestBabbageBlock_Utxorpc(t *testing.T) { assert.NotNil(t, babbageBlock.TransactionBodies) assert.NotNil(t, babbageBlock.TransactionWitnessSets) - utxoBlock := babbageBlock.Utxorpc() + utxoBlock, err := babbageBlock.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() failed: %v", err) + } // Validate the resulting utxorpc.Block assert.NotNil(t, utxoBlock) diff --git a/ledger/babbage/pparams.go b/ledger/babbage/pparams.go index 336d55a6..da3a251e 100644 --- a/ledger/babbage/pparams.go +++ b/ledger/babbage/pparams.go @@ -15,6 +15,7 @@ package babbage import ( + "errors" "math" "github.com/blinklabs-io/gouroboros/cbor" @@ -162,32 +163,32 @@ func (u *BabbageProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { return nil } -func (p *BabbageProtocolParameters) Utxorpc() *cardano.PParams { +func (p *BabbageProtocolParameters) Utxorpc() (*cardano.PParams, error) { // sanity check if p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid A0 rational number values") } if p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Rho rational number values") } if p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Tau rational number values") } if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid memory price rational number values") } if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid step price rational number values") } // #nosec G115 return &cardano.PParams{ @@ -242,7 +243,7 @@ func (p *BabbageProtocolParameters) Utxorpc() *cardano.PParams { Memory: p.MaxBlockExUnits.Memory, Steps: p.MaxBlockExUnits.Steps, }, - } + }, nil } func UpgradePParams( diff --git a/ledger/babbage/pparams_test.go b/ledger/babbage/pparams_test.go index 7119c8d4..74a0c026 100644 --- a/ledger/babbage/pparams_test.go +++ b/ledger/babbage/pparams_test.go @@ -545,7 +545,10 @@ func TestBabbageUtxorpc(t *testing.T) { } for _, testDef := range testDefs { - result := testDef.startParams.Utxorpc() + result, err := testDef.startParams.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() failed: %v", err) + } if !reflect.DeepEqual(result, testDef.expectedUtxorpc) { t.Fatalf( "Utxorpc() test failed:\nExpected: %#v\nGot: %#v", @@ -563,7 +566,10 @@ func TestBabbageTransactionInput_Utxorpc(t *testing.T) { 2, ) - got := input.Utxorpc() + got, err := input.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() failed: %v", err) + } want := &cardano.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), @@ -629,8 +635,10 @@ func TestBabbageTransactionBody_Utxorpc(t *testing.T) { TxFee: 100, } - got := body.Utxorpc() - + got, err := body.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() conversion failed: %v", err) + } if got.Fee != 100 { t.Errorf("Fee mismatch: got %d, want 100", got.Fee) } @@ -672,8 +680,10 @@ func TestBabbageTransaction_Utxorpc(t *testing.T) { TxIsValid: true, } - got := tx.Utxorpc() - + got, err := tx.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() failed: %v", err) + } if got.Fee != 150 { t.Errorf("Fee mismatch: got %d, want 150", got.Fee) } diff --git a/ledger/byron/byron.go b/ledger/byron/byron.go index 5f83800e..8f2dc04f 100644 --- a/ledger/byron/byron.go +++ b/ledger/byron/byron.go @@ -300,8 +300,8 @@ func (t ByronTransaction) Witnesses() common.TransactionWitnessSet { return nil } -func (t *ByronTransaction) Utxorpc() *utxorpc.Tx { - return &utxorpc.Tx{} +func (t *ByronTransaction) Utxorpc() (*utxorpc.Tx, error) { + return &utxorpc.Tx{}, nil } func (t *ByronTransaction) ProtocolParameterUpdates() (uint64, map[common.Blake2b224]common.ProtocolParameterUpdate) { @@ -368,13 +368,13 @@ func (i ByronTransactionInput) Index() uint32 { return i.OutputIndex } -func (i ByronTransactionInput) Utxorpc() *utxorpc.TxInput { +func (i ByronTransactionInput) Utxorpc() (*utxorpc.TxInput, error) { return &utxorpc.TxInput{ TxHash: i.TxId.Bytes(), OutputIndex: i.OutputIndex, // AsOutput: i.AsOutput, // Redeemer: i.Redeemer, - } + }, nil } func (i ByronTransactionInput) String() string { @@ -662,8 +662,8 @@ func (b *ByronMainBlock) Transactions() []common.Transaction { return ret } -func (b *ByronMainBlock) Utxorpc() *utxorpc.Block { - return &utxorpc.Block{} +func (b *ByronMainBlock) Utxorpc() (*utxorpc.Block, error) { + return &utxorpc.Block{}, nil } type ByronEpochBoundaryBlock struct { @@ -727,8 +727,8 @@ func (b *ByronEpochBoundaryBlock) Transactions() []common.Transaction { return nil } -func (b *ByronEpochBoundaryBlock) Utxorpc() *utxorpc.Block { - return &utxorpc.Block{} +func (b *ByronEpochBoundaryBlock) Utxorpc() (*utxorpc.Block, error) { + return &utxorpc.Block{}, nil } func NewByronEpochBoundaryBlockFromCbor( diff --git a/ledger/byron/byron_test.go b/ledger/byron/byron_test.go index daeb724a..b2c0c4d9 100644 --- a/ledger/byron/byron_test.go +++ b/ledger/byron/byron_test.go @@ -31,7 +31,10 @@ func TestByronTransactionInput_Utxorpc(t *testing.T) { 1, ) - got := input.Utxorpc() + got, err := input.Utxorpc() + if err != nil { + t.Fatal("Could not get transaction input") + } want := &cardano.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), @@ -78,7 +81,10 @@ func TestByronTransaction_Utxorpc_Empty(t *testing.T) { tx := &byron.ByronTransaction{} // Run Utxorpc conversion - result := tx.Utxorpc() + result, err := tx.Utxorpc() + if err != nil { + t.Fatal("Could not convert Utxorpc") + } // Validate it's not nil if result == nil { diff --git a/ledger/common/block.go b/ledger/common/block.go index 2ba4d9e9..65c3c36e 100644 --- a/ledger/common/block.go +++ b/ledger/common/block.go @@ -7,7 +7,7 @@ type Block interface { Header() BlockHeader Type() int Transactions() []Transaction - Utxorpc() *utxorpc.Block + Utxorpc() (*utxorpc.Block, error) } type BlockHeader interface { diff --git a/ledger/common/certs.go b/ledger/common/certs.go index 2bf304e5..05b8a528 100644 --- a/ledger/common/certs.go +++ b/ledger/common/certs.go @@ -116,7 +116,7 @@ func (c *CertificateWrapper) MarshalCBOR() ([]byte, error) { type Certificate interface { isCertificate() Cbor() []byte - Utxorpc() *utxorpc.Certificate + Utxorpc() (*utxorpc.Certificate, error) Type() uint } @@ -177,12 +177,16 @@ func (c *StakeRegistrationCertificate) UnmarshalCBOR(cborData []byte) error { return nil } -func (c *StakeRegistrationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *StakeRegistrationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + stakeCred, err := c.StakeRegistration.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_StakeRegistration{ - StakeRegistration: c.StakeRegistration.Utxorpc(), + StakeRegistration: stakeCred, }, - } + }, nil } func (c *StakeRegistrationCertificate) Type() uint { @@ -209,12 +213,18 @@ func (c *StakeDeregistrationCertificate) UnmarshalCBOR(cborData []byte) error { return nil } -func (c *StakeDeregistrationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *StakeDeregistrationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + stakeDeReg, err := c.StakeDeregistration.Utxorpc() + if err != nil { + return nil, err + } + return &utxorpc.Certificate{ - Certificate: &utxorpc.Certificate_StakeDeregistration{ - StakeDeregistration: c.StakeDeregistration.Utxorpc(), + Certificate: &utxorpc.Certificate_StakeDeregistration{ + StakeDeregistration: stakeDeReg, + }, }, - } + nil } func (c *StakeDeregistrationCertificate) Type() uint { @@ -242,15 +252,20 @@ func (c *StakeDelegationCertificate) UnmarshalCBOR(cborData []byte) error { return nil } -func (c *StakeDelegationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *StakeDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ - Certificate: &utxorpc.Certificate_StakeDelegation{ - StakeDelegation: &utxorpc.StakeDelegationCert{ - StakeCredential: c.StakeCredential.Utxorpc(), - PoolKeyhash: c.PoolKeyHash[:], + Certificate: &utxorpc.Certificate_StakeDelegation{ + StakeDelegation: &utxorpc.StakeDelegationCert{ + StakeCredential: stakeCred, + PoolKeyhash: c.PoolKeyHash[:], + }, }, }, - } + nil } func (c *StakeDelegationCertificate) Type() uint { @@ -269,11 +284,12 @@ type PoolMetadata struct { Hash PoolMetadataHash } -func (p *PoolMetadata) Utxorpc() *utxorpc.PoolMetadata { +func (p *PoolMetadata) Utxorpc() (*utxorpc.PoolMetadata, error) { return &utxorpc.PoolMetadata{ - Url: p.Url, - Hash: p.Hash[:], - } + Url: p.Url, + Hash: p.Hash[:], + }, + nil } const ( @@ -339,7 +355,7 @@ func (p *PoolRelay) UnmarshalCBOR(data []byte) error { return nil } -func (p *PoolRelay) Utxorpc() *utxorpc.Relay { +func (p *PoolRelay) Utxorpc() (*utxorpc.Relay, error) { ret := &utxorpc.Relay{} if p.Port != nil { ret.Port = *p.Port @@ -353,7 +369,7 @@ func (p *PoolRelay) Utxorpc() *utxorpc.Relay { if p.Port != nil { ret.Port = *p.Port } - return ret + return ret, nil } type PoolRegistrationCertificate struct { @@ -384,14 +400,24 @@ func (c *PoolRegistrationCertificate) UnmarshalCBOR(cborData []byte) error { return nil } -func (c *PoolRegistrationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *PoolRegistrationCertificate) Utxorpc() (*utxorpc.Certificate, error) { tmpPoolOwners := make([][]byte, len(c.PoolOwners)) for i, owner := range c.PoolOwners { tmpPoolOwners[i] = owner[:] } tmpRelays := make([]*utxorpc.Relay, len(c.Relays)) for i, relay := range c.Relays { - tmpRelays[i] = relay.Utxorpc() + relayUtxo, err := relay.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert relay %d: %w", i, err) + } + tmpRelays[i] = relayUtxo + } + + // Handle pool metadata with error checking + poolMetadata, err := c.PoolMetadata.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert pool metadata: %w", err) } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_PoolRegistration{ @@ -408,10 +434,10 @@ func (c *PoolRegistrationCertificate) Utxorpc() *utxorpc.Certificate { RewardAccount: c.RewardAccount[:], PoolOwners: tmpPoolOwners, Relays: tmpRelays, - PoolMetadata: c.PoolMetadata.Utxorpc(), + PoolMetadata: poolMetadata, }, }, - } + }, nil } func (c *PoolRegistrationCertificate) Type() uint { @@ -439,7 +465,7 @@ func (c *PoolRetirementCertificate) UnmarshalCBOR(cborData []byte) error { return nil } -func (c *PoolRetirementCertificate) Utxorpc() *utxorpc.Certificate { +func (c *PoolRetirementCertificate) Utxorpc() (*utxorpc.Certificate, error) { return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_PoolRetirement{ PoolRetirement: &utxorpc.PoolRetirementCert{ @@ -447,7 +473,7 @@ func (c *PoolRetirementCertificate) Utxorpc() *utxorpc.Certificate { Epoch: c.Epoch, }, }, - } + }, nil } func (c *PoolRetirementCertificate) Type() uint { @@ -476,7 +502,7 @@ func (c *GenesisKeyDelegationCertificate) UnmarshalCBOR(cborData []byte) error { return nil } -func (c *GenesisKeyDelegationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *GenesisKeyDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_GenesisKeyDelegation{ GenesisKeyDelegation: &utxorpc.GenesisKeyDelegationCert{ @@ -485,7 +511,7 @@ func (c *GenesisKeyDelegationCertificate) Utxorpc() *utxorpc.Certificate { VrfKeyhash: c.VrfKeyHash[:], }, }, - } + }, nil } func (c *GenesisKeyDelegationCertificate) Type() uint { @@ -556,13 +582,17 @@ func (c *MoveInstantaneousRewardsCertificate) UnmarshalCBOR( return nil } -func (c *MoveInstantaneousRewardsCertificate) Utxorpc() *utxorpc.Certificate { +func (c *MoveInstantaneousRewardsCertificate) Utxorpc() (*utxorpc.Certificate, error) { tmpMirTargets := []*utxorpc.MirTarget{} for stakeCred, deltaCoin := range c.Reward.Rewards { + stakeCr, err := stakeCred.Utxorpc() + if err != nil { + return nil, err + } tmpMirTargets = append( tmpMirTargets, &utxorpc.MirTarget{ - StakeCredential: stakeCred.Utxorpc(), + StakeCredential: stakeCr, // potential integer overflow // #nosec G115 DeltaCoin: int64(deltaCoin), @@ -579,7 +609,7 @@ func (c *MoveInstantaneousRewardsCertificate) Utxorpc() *utxorpc.Certificate { OtherPot: c.Reward.OtherPot, }, }, - } + }, nil } func (c *MoveInstantaneousRewardsCertificate) Type() uint { @@ -609,14 +639,18 @@ func (c *RegistrationCertificate) UnmarshalCBOR( return nil } -func (c *RegistrationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *RegistrationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_RegCert{ RegCert: &utxorpc.RegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), + StakeCredential: stakeCred, }, }, - } + }, nil } func (c *RegistrationCertificate) Type() uint { @@ -646,14 +680,18 @@ func (c *DeregistrationCertificate) UnmarshalCBOR( return nil } -func (c *DeregistrationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *DeregistrationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_UnregCert{ UnregCert: &utxorpc.UnRegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), + StakeCredential: stakeCred, }, }, - } + }, nil } func (c *DeregistrationCertificate) Type() uint { @@ -683,15 +721,23 @@ func (c *VoteDelegationCertificate) UnmarshalCBOR( return nil } -func (c *VoteDelegationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *VoteDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + drep, err := c.Drep.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert DRep: %w", err) + } + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_VoteDelegCert{ VoteDelegCert: &utxorpc.VoteDelegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), - Drep: c.Drep.Utxorpc(), + StakeCredential: stakeCred, + Drep: drep, }, }, - } + }, nil } func (c *VoteDelegationCertificate) Type() uint { @@ -722,8 +768,12 @@ func (c *StakeVoteDelegationCertificate) UnmarshalCBOR( return nil } -func (c *StakeVoteDelegationCertificate) Utxorpc() *utxorpc.Certificate { - drepProto := c.Drep.Utxorpc() +func (c *StakeVoteDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + // Handle DRep conversion with error checking + drepProto, err := c.Drep.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert DRep: %w", err) + } var drepBytes []byte // Extract DRep credential if it exists (AddrKeyHash or ScriptHash) @@ -743,15 +793,19 @@ func (c *StakeVoteDelegationCertificate) Utxorpc() *utxorpc.Certificate { encodedKey = append(encodedKey, c.PoolKeyHash...) encodedKey = append(encodedKey, drepBytes...) + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_StakeVoteDelegCert{ StakeVoteDelegCert: &utxorpc.StakeVoteDelegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), + StakeCredential: stakeCred, PoolKeyhash: encodedKey, - Drep: c.Drep.Utxorpc(), + Drep: drepProto, }, }, - } + }, nil } func (c *StakeVoteDelegationCertificate) Type() uint { @@ -782,15 +836,19 @@ func (c *StakeRegistrationDelegationCertificate) UnmarshalCBOR( return nil } -func (c *StakeRegistrationDelegationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *StakeRegistrationDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_StakeVoteDelegCert{ StakeVoteDelegCert: &utxorpc.StakeVoteDelegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), + StakeCredential: stakeCred, PoolKeyhash: c.PoolKeyHash, }, }, - } + }, nil } func (c *StakeRegistrationDelegationCertificate) Type() uint { @@ -821,15 +879,24 @@ func (c *VoteRegistrationDelegationCertificate) UnmarshalCBOR( return nil } -func (c *VoteRegistrationDelegationCertificate) Utxorpc() *utxorpc.Certificate { +func (c *VoteRegistrationDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + // Handle DRep conversion with error checking + drep, err := c.Drep.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert DRep: %w", err) + } + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_VoteRegDelegCert{ VoteRegDelegCert: &utxorpc.VoteRegDelegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), - Drep: c.Drep.Utxorpc(), + StakeCredential: stakeCred, + Drep: drep, }, }, - } + }, nil } func (c *VoteRegistrationDelegationCertificate) Type() uint { @@ -861,8 +928,13 @@ func (c *StakeVoteRegistrationDelegationCertificate) UnmarshalCBOR( return nil } -func (c *StakeVoteRegistrationDelegationCertificate) Utxorpc() *utxorpc.Certificate { - drepProto := c.Drep.Utxorpc() +func (c *StakeVoteRegistrationDelegationCertificate) Utxorpc() (*utxorpc.Certificate, error) { + // Handle DRep conversion with error checking + drepProto, err := c.Drep.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert DRep: %w", err) + } + var drepBytes []byte if drepProto != nil { @@ -873,16 +945,19 @@ func (c *StakeVoteRegistrationDelegationCertificate) Utxorpc() *utxorpc.Certific drepBytes = drepProto.GetScriptHash() } } - + stakeCred, err := c.StakeCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_StakeVoteRegDelegCert{ StakeVoteRegDelegCert: &utxorpc.StakeVoteRegDelegCert{ - StakeCredential: c.StakeCredential.Utxorpc(), + StakeCredential: stakeCred, PoolKeyhash: drepBytes, - Drep: c.Drep.Utxorpc(), + Drep: drepProto, }, }, - } + }, nil } func (c *StakeVoteRegistrationDelegationCertificate) Type() uint { @@ -912,15 +987,23 @@ func (c *AuthCommitteeHotCertificate) UnmarshalCBOR( return nil } -func (c *AuthCommitteeHotCertificate) Utxorpc() *utxorpc.Certificate { +func (c *AuthCommitteeHotCertificate) Utxorpc() (*utxorpc.Certificate, error) { + coldCred, err := c.ColdCredential.Utxorpc() + if err != nil { + return nil, err + } + hostCred, err := c.HostCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_AuthCommitteeHotCert{ AuthCommitteeHotCert: &utxorpc.AuthCommitteeHotCert{ - CommitteeColdCredential: c.ColdCredential.Utxorpc(), - CommitteeHotCredential: c.HostCredential.Utxorpc(), + CommitteeColdCredential: coldCred, + CommitteeHotCredential: hostCred, }, }, - } + }, nil } func (c *AuthCommitteeHotCertificate) Type() uint { @@ -950,7 +1033,7 @@ func (c *ResignCommitteeColdCertificate) UnmarshalCBOR( return nil } -func (c *ResignCommitteeColdCertificate) Utxorpc() *utxorpc.Certificate { +func (c *ResignCommitteeColdCertificate) Utxorpc() (*utxorpc.Certificate, error) { var anchor *utxorpc.Anchor if c.Anchor != nil { anchor = &utxorpc.Anchor{ @@ -958,14 +1041,18 @@ func (c *ResignCommitteeColdCertificate) Utxorpc() *utxorpc.Certificate { ContentHash: c.Anchor.DataHash[:], } } + coldCred, err := c.ColdCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_ResignCommitteeColdCert{ ResignCommitteeColdCert: &utxorpc.ResignCommitteeColdCert{ - CommitteeColdCredential: c.ColdCredential.Utxorpc(), + CommitteeColdCredential: coldCred, Anchor: anchor, }, }, - } + }, nil } func (c *ResignCommitteeColdCertificate) Type() uint { @@ -996,7 +1083,7 @@ func (c *RegistrationDrepCertificate) UnmarshalCBOR( return nil } -func (c *RegistrationDrepCertificate) Utxorpc() *utxorpc.Certificate { +func (c *RegistrationDrepCertificate) Utxorpc() (*utxorpc.Certificate, error) { // Handle anchor data if present var anchor *utxorpc.Anchor if c.Anchor != nil { @@ -1005,14 +1092,18 @@ func (c *RegistrationDrepCertificate) Utxorpc() *utxorpc.Certificate { ContentHash: c.Anchor.DataHash[:], } } + drepCred, err := c.DrepCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_RegDrepCert{ RegDrepCert: &utxorpc.RegDRepCert{ - DrepCredential: c.DrepCredential.Utxorpc(), + DrepCredential: drepCred, Anchor: anchor, }, }, - } + }, nil } func (c *RegistrationDrepCertificate) Type() uint { @@ -1042,14 +1133,18 @@ func (c *DeregistrationDrepCertificate) UnmarshalCBOR( return nil } -func (c *DeregistrationDrepCertificate) Utxorpc() *utxorpc.Certificate { +func (c *DeregistrationDrepCertificate) Utxorpc() (*utxorpc.Certificate, error) { + drepCred, err := c.DrepCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_UnregDrepCert{ UnregDrepCert: &utxorpc.UnRegDRepCert{ - DrepCredential: c.DrepCredential.Utxorpc(), + DrepCredential: drepCred, }, }, - } + }, nil } func (c *DeregistrationDrepCertificate) Type() uint { @@ -1079,7 +1174,7 @@ func (c *UpdateDrepCertificate) UnmarshalCBOR( return nil } -func (c *UpdateDrepCertificate) Utxorpc() *utxorpc.Certificate { +func (c *UpdateDrepCertificate) Utxorpc() (*utxorpc.Certificate, error) { var anchor *utxorpc.Anchor if c.Anchor != nil { anchor = &utxorpc.Anchor{ @@ -1087,14 +1182,18 @@ func (c *UpdateDrepCertificate) Utxorpc() *utxorpc.Certificate { ContentHash: c.Anchor.DataHash[:], } } + drepCred, err := c.DrepCredential.Utxorpc() + if err != nil { + return nil, err + } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_UpdateDrepCert{ UpdateDrepCert: &utxorpc.UpdateDRepCert{ - DrepCredential: c.DrepCredential.Utxorpc(), + DrepCredential: drepCred, Anchor: anchor, }, }, - } + }, nil } func (c *UpdateDrepCertificate) Type() uint { @@ -1102,25 +1201,25 @@ func (c *UpdateDrepCertificate) Type() uint { } // DRep implementation -func (d *Drep) Utxorpc() *utxorpc.DRep { +func (d *Drep) Utxorpc() (*utxorpc.DRep, error) { switch d.Type { case DrepTypeAddrKeyHash: return &utxorpc.DRep{ Drep: &utxorpc.DRep_AddrKeyHash{AddrKeyHash: d.Credential}, - } + }, nil case DrepTypeScriptHash: return &utxorpc.DRep{ Drep: &utxorpc.DRep_ScriptHash{ScriptHash: d.Credential}, - } + }, nil case DrepTypeAbstain: return &utxorpc.DRep{ Drep: &utxorpc.DRep_Abstain{Abstain: true}, - } + }, nil case DrepTypeNoConfidence: return &utxorpc.DRep{ Drep: &utxorpc.DRep_NoConfidence{NoConfidence: true}, - } + }, nil default: - return nil + return nil, fmt.Errorf("unknown DRep type: %d", d.Type) } } diff --git a/ledger/common/credentials.go b/ledger/common/credentials.go index f690703e..d246148a 100644 --- a/ledger/common/credentials.go +++ b/ledger/common/credentials.go @@ -63,7 +63,7 @@ func (c *Credential) Hash() Blake2b224 { return Blake2b224(hash.Sum(nil)) } -func (c *Credential) Utxorpc() *utxorpc.StakeCredential { +func (c *Credential) Utxorpc() (*utxorpc.StakeCredential, error) { ret := &utxorpc.StakeCredential{} switch c.CredType { case CredentialTypeAddrKeyHash: @@ -75,5 +75,5 @@ func (c *Credential) Utxorpc() *utxorpc.StakeCredential { ScriptHash: c.Credential[:], } } - return ret + return ret, nil } diff --git a/ledger/common/pparams.go b/ledger/common/pparams.go index eaee567c..7daf2364 100644 --- a/ledger/common/pparams.go +++ b/ledger/common/pparams.go @@ -33,7 +33,7 @@ type ProtocolParametersProtocolVersion struct { } type ProtocolParameters interface { - Utxorpc() *cardano.PParams + Utxorpc() (*cardano.PParams, error) } type ExUnitPrice struct { diff --git a/ledger/common/tx.go b/ledger/common/tx.go index 9dda3dcf..78aa48df 100644 --- a/ledger/common/tx.go +++ b/ledger/common/tx.go @@ -53,14 +53,14 @@ type TransactionBody interface { ProposalProcedures() []ProposalProcedure CurrentTreasuryValue() int64 Donation() uint64 - Utxorpc() *utxorpc.Tx + Utxorpc() (*utxorpc.Tx, error) } type TransactionInput interface { Id() Blake2b256 Index() uint32 String() string - Utxorpc() *utxorpc.TxInput + Utxorpc() (*utxorpc.TxInput, error) } type TransactionOutput interface { @@ -195,7 +195,10 @@ func TransactionBodyToUtxorpc(tx TransactionBody) *utxorpc.Tx { txi := []*utxorpc.TxInput{} txo := []*utxorpc.TxOutput{} for _, i := range tx.Inputs() { - input := i.Utxorpc() + input, err := i.Utxorpc() + if err != nil { + return nil + } txi = append(txi, input) } for _, o := range tx.Outputs() { @@ -222,11 +225,17 @@ func TransactionBodyToUtxorpc(tx TransactionBody) *utxorpc.Tx { // Proposals: tx.ProposalProcedures(), } for _, ri := range tx.ReferenceInputs() { - input := ri.Utxorpc() + input, err := ri.Utxorpc() + if err != nil { + return nil + } ret.ReferenceInputs = append(ret.ReferenceInputs, input) } for _, c := range tx.Certificates() { - cert := c.Utxorpc() + cert, err := c.Utxorpc() + if err != nil { + return nil + } ret.Certificates = append(ret.Certificates, cert) } diff --git a/ledger/conway/conway.go b/ledger/conway/conway.go index ef5d779d..f41dc6c9 100644 --- a/ledger/conway/conway.go +++ b/ledger/conway/conway.go @@ -121,10 +121,13 @@ func (b *ConwayBlock) Transactions() []common.Transaction { return ret } -func (b *ConwayBlock) Utxorpc() *utxorpc.Block { +func (b *ConwayBlock) Utxorpc() (*utxorpc.Block, error) { txs := []*utxorpc.Tx{} for _, t := range b.Transactions() { - tx := t.Utxorpc() + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } txs = append(txs, tx) } body := &utxorpc.BlockBody{ @@ -139,7 +142,7 @@ func (b *ConwayBlock) Utxorpc() *utxorpc.Block { Body: body, Header: header, } - return block + return block, nil } type ConwayBlockHeader struct { @@ -455,8 +458,8 @@ func (b *ConwayTransactionBody) Donation() uint64 { return b.TxDonation } -func (b *ConwayTransactionBody) Utxorpc() *utxorpc.Tx { - return common.TransactionBodyToUtxorpc(b) +func (b *ConwayTransactionBody) Utxorpc() (*utxorpc.Tx, error) { + return common.TransactionBodyToUtxorpc(b), nil } type ConwayTransaction struct { @@ -646,8 +649,12 @@ func (t *ConwayTransaction) Cbor() []byte { return cborData } -func (t *ConwayTransaction) Utxorpc() *utxorpc.Tx { - return t.Body.Utxorpc() +func (t *ConwayTransaction) Utxorpc() (*utxorpc.Tx, error) { + tx, err := t.Body.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert Conway transaction: %w", err) + } + return tx, nil } func NewConwayBlockFromCbor(data []byte) (*ConwayBlock, error) { diff --git a/ledger/conway/pparams.go b/ledger/conway/pparams.go index e7d9068d..73098459 100644 --- a/ledger/conway/pparams.go +++ b/ledger/conway/pparams.go @@ -15,6 +15,7 @@ package conway import ( + "errors" "math" "github.com/blinklabs-io/gouroboros/cbor" @@ -58,32 +59,32 @@ type ConwayProtocolParameters struct { MinFeeRefScriptCostPerByte *cbor.Rat } -func (p *ConwayProtocolParameters) Utxorpc() *cardano.PParams { +func (p *ConwayProtocolParameters) Utxorpc() (*cardano.PParams, error) { // sanity check if p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid A0 rational number values") } if p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Rho rational number values") } if p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Tau rational number values") } if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid memory price rational number values") } if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid step price rational number values") } // #nosec G115 return &cardano.PParams{ @@ -138,7 +139,7 @@ func (p *ConwayProtocolParameters) Utxorpc() *cardano.PParams { Memory: p.MaxBlockExUnits.Memory, Steps: p.MaxBlockExUnits.Steps, }, - } + }, nil } func (p *ConwayProtocolParameters) Update( diff --git a/ledger/conway/pparams_test.go b/ledger/conway/pparams_test.go index 8ace192a..f5463b3e 100644 --- a/ledger/conway/pparams_test.go +++ b/ledger/conway/pparams_test.go @@ -590,7 +590,10 @@ func TestUtxorpc(t *testing.T) { } for _, testDef := range testDefs { - result := testDef.startParams.Utxorpc() + result, err := testDef.startParams.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() conversion failed") + } // Compare the result with the expected value if !reflect.DeepEqual(result, testDef.expectedUtxorpc) { t.Fatalf( @@ -642,7 +645,10 @@ func TestConwayTransactionBody_Utxorpc(t *testing.T) { TxMint: txMint, } - got := body.Utxorpc() + got, err := body.Utxorpc() + if err != nil { + t.Errorf("Could not get the transaction input") + } if got.Fee != 1000 { t.Errorf("Fee mismatch: got %d, want 100", got.Fee) @@ -707,7 +713,10 @@ func TestConwayTransaction_Utxorpc(t *testing.T) { TxIsValid: true, } - got := tx.Utxorpc() + got, err := tx.Utxorpc() + if err != nil { + t.Errorf("Could not get the transaction input") + } if got.Fee != 1000 { t.Errorf("Transaction fee mismatch: got %d, want 25", got.Fee) diff --git a/ledger/mary/mary.go b/ledger/mary/mary.go index 9e6acedf..729ef33b 100644 --- a/ledger/mary/mary.go +++ b/ledger/mary/mary.go @@ -113,10 +113,13 @@ func (b *MaryBlock) Transactions() []common.Transaction { return ret } -func (b *MaryBlock) Utxorpc() *utxorpc.Block { +func (b *MaryBlock) Utxorpc() (*utxorpc.Block, error) { txs := []*utxorpc.Tx{} for _, t := range b.Transactions() { - tx := t.Utxorpc() + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } txs = append(txs, tx) } body := &utxorpc.BlockBody{ @@ -131,7 +134,7 @@ func (b *MaryBlock) Utxorpc() *utxorpc.Block { Body: body, Header: header, } - return block + return block, nil } type MaryBlockHeader struct { @@ -227,8 +230,8 @@ func (b *MaryTransactionBody) AssetMint() *common.MultiAsset[common.MultiAssetTy return b.TxMint } -func (b *MaryTransactionBody) Utxorpc() *utxorpc.Tx { - return common.TransactionBodyToUtxorpc(b) +func (b *MaryTransactionBody) Utxorpc() (*utxorpc.Tx, error) { + return common.TransactionBodyToUtxorpc(b), nil } type MaryTransaction struct { @@ -400,8 +403,12 @@ func (t *MaryTransaction) Cbor() []byte { return cborData } -func (t *MaryTransaction) Utxorpc() *utxorpc.Tx { - return t.Body.Utxorpc() +func (t *MaryTransaction) Utxorpc() (*utxorpc.Tx, error) { + tx, err := t.Body.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert Mary transaction: %w", err) + } + return tx, nil } type MaryTransactionOutput struct { diff --git a/ledger/mary/pparams_test.go b/ledger/mary/pparams_test.go index 26bf125f..7090e112 100644 --- a/ledger/mary/pparams_test.go +++ b/ledger/mary/pparams_test.go @@ -123,7 +123,10 @@ func TestMaryUtxorpc(t *testing.T) { }, } - result := inputParams.Utxorpc() + result, err := inputParams.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() conversion failed") + } if !reflect.DeepEqual(result, expectedUtxorpc) { t.Fatalf( @@ -141,7 +144,10 @@ func TestMaryTransactionInput_Utxorpc(t *testing.T) { 0, ) - got := input.Utxorpc() + got, err := input.Utxorpc() + if err != nil { + t.Errorf("Could not get correct UTxorpc input") + } want := &cardano.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), @@ -206,7 +212,10 @@ func TestMaryTransactionBody_Utxorpc(t *testing.T) { TxFee: 100, } - got := body.Utxorpc() + got, err := body.Utxorpc() + if err != nil { + t.Errorf("Could not get correct UTxorpc input") + } if got.Fee != 100 { t.Errorf("Fee mismatch: got %d, want 100", got.Fee) @@ -251,7 +260,10 @@ func TestMaryTransaction_Utxorpc(t *testing.T) { Body: body, } - got := tx.Utxorpc() + got, err := tx.Utxorpc() + if err != nil { + t.Errorf("Could not get correct UTxorpc input") + } if got.Fee != 25 { t.Errorf("Transaction fee mismatch: got %d, want 25", got.Fee) diff --git a/ledger/shelley/pparams.go b/ledger/shelley/pparams.go index 7fcae5a2..51449dfd 100644 --- a/ledger/shelley/pparams.go +++ b/ledger/shelley/pparams.go @@ -15,6 +15,7 @@ package shelley import ( + "errors" "math" "math/big" @@ -168,22 +169,22 @@ func (u *ShelleyProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { return nil } -func (p *ShelleyProtocolParameters) Utxorpc() *cardano.PParams { +func (p *ShelleyProtocolParameters) Utxorpc() (*cardano.PParams, error) { // sanity check if p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid A0 rational number values") } if p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Rho rational number values") } if p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { - return nil + return nil, errors.New("invalid Tau rational number values") } // #nosec G115 return &cardano.PParams{ @@ -212,7 +213,7 @@ func (p *ShelleyProtocolParameters) Utxorpc() *cardano.PParams { Major: uint32(p.ProtocolMajor), Minor: uint32(p.ProtocolMinor), }, - } + }, nil } func UpgradePParams(prevPParams any) ShelleyProtocolParameters { diff --git a/ledger/shelley/pparams_test.go b/ledger/shelley/pparams_test.go index 9d10659f..40f23036 100644 --- a/ledger/shelley/pparams_test.go +++ b/ledger/shelley/pparams_test.go @@ -154,7 +154,10 @@ func TestShelleyUtxorpc(t *testing.T) { }, } - result := inputParams.Utxorpc() + result, err := inputParams.Utxorpc() + if err != nil { + t.Fatalf("Utxorpc() conversion failed") + } if !reflect.DeepEqual(result, expectedUtxorpc) { t.Fatalf( @@ -174,7 +177,10 @@ func TestShelleyTransactionInput_Utxorpc(t *testing.T) { ) // Convert it to utxorpc TxInput - got := input.Utxorpc() + got, err := input.Utxorpc() + if err != nil { + t.Errorf("Could not convert to utxorpc TxInput") + } // Expected value with same hash and index want := &cardano.TxInput{ @@ -263,7 +269,10 @@ func TestShelleyTransactionBody_Utxorpc(t *testing.T) { } // Convert the transaction body to utxorpc format - actual := txBody.Utxorpc() + actual, err := txBody.Utxorpc() + if err != nil { + t.Errorf("Could not convert the transaction body to utxorpc format") + } // Check that the fee matches if actual.Fee != txBody.Fee() { @@ -328,7 +337,10 @@ func TestShelleyTransaction_Utxorpc(t *testing.T) { } // Invoke Utxorpc conversion - got := tx.Utxorpc() + got, err := tx.Utxorpc() + if err != nil { + t.Errorf("Could not Invoke Utxorpc conversion") + } // Verify the fee if got.Fee != tx.Body.Fee() { diff --git a/ledger/shelley/shelley.go b/ledger/shelley/shelley.go index 1070fc53..1df99bd5 100644 --- a/ledger/shelley/shelley.go +++ b/ledger/shelley/shelley.go @@ -114,10 +114,13 @@ func (b *ShelleyBlock) Transactions() []common.Transaction { return ret } -func (b *ShelleyBlock) Utxorpc() *utxorpc.Block { +func (b *ShelleyBlock) Utxorpc() (*utxorpc.Block, error) { txs := []*utxorpc.Tx{} for _, t := range b.Transactions() { - tx := t.Utxorpc() + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } txs = append(txs, tx) } body := &utxorpc.BlockBody{ @@ -132,7 +135,7 @@ func (b *ShelleyBlock) Utxorpc() *utxorpc.Block { Body: body, Header: header, } - return block + return block, nil } type ShelleyBlockHeader struct { @@ -279,8 +282,8 @@ func (b *ShelleyTransactionBody) AuxDataHash() *common.Blake2b256 { return b.TxAuxDataHash } -func (b *ShelleyTransactionBody) Utxorpc() *utxorpc.Tx { - return common.TransactionBodyToUtxorpc(b) +func (b *ShelleyTransactionBody) Utxorpc() (*utxorpc.Tx, error) { + return common.TransactionBodyToUtxorpc(b), nil } type ShelleyTransactionInputSet struct { @@ -348,11 +351,11 @@ func (i ShelleyTransactionInput) Index() uint32 { return i.OutputIndex } -func (i ShelleyTransactionInput) Utxorpc() *utxorpc.TxInput { +func (i ShelleyTransactionInput) Utxorpc() (*utxorpc.TxInput, error) { return &utxorpc.TxInput{ TxHash: i.TxId.Bytes(), OutputIndex: i.OutputIndex, - } + }, nil } func (i ShelleyTransactionInput) String() string { @@ -601,8 +604,12 @@ func (t ShelleyTransaction) Witnesses() common.TransactionWitnessSet { return t.WitnessSet } -func (t ShelleyTransaction) Utxorpc() *utxorpc.Tx { - return t.Body.Utxorpc() +func (t ShelleyTransaction) Utxorpc() (*utxorpc.Tx, error) { + tx, err := t.Body.Utxorpc() + if err != nil { + return nil, fmt.Errorf("failed to convert Shelley transaction: %w", err) + } + return tx, nil } func (t *ShelleyTransaction) ProtocolParameterUpdates() (uint64, map[common.Blake2b224]common.ProtocolParameterUpdate) {