diff --git a/go.mod b/go.mod index a06a6557..7c3f293b 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,10 @@ require ( github.com/fxamacker/cbor/v2 v2.9.0 github.com/jinzhu/copier v0.4.0 github.com/stretchr/testify v1.11.1 - github.com/utxorpc/go-codegen v0.17.0 + github.com/utxorpc/go-codegen v0.18.1 go.uber.org/goleak v1.3.0 golang.org/x/crypto v0.43.0 + google.golang.org/protobuf v1.36.10 ) require ( @@ -25,12 +26,10 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/sys v0.37.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 441952d5..53707390 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -103,8 +103,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/utxorpc/go-codegen v0.17.0 h1:cJ7Df9r8Az39lveIcmzcRciIDc3UJFdMSmXg8IAtBPM= -github.com/utxorpc/go-codegen v0.17.0/go.mod h1:LBVGFns4YAHMhy+Pc8tF5ExkU+N8Wm3srst4omKZy4g= +github.com/utxorpc/go-codegen v0.18.1 h1:2eenzXCkqvB2+g8MCq70MBR6koWs9CeTihZ0AqUvLDY= +github.com/utxorpc/go-codegen v0.18.1/go.mod h1:DFij3zIGDM39BYCuzrz1rSuO3kTIIiHglWV0043wQxo= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -143,8 +143,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/ledger/allegra/block_test.go b/ledger/allegra/block_test.go index f6762c77..afe341c0 100644 --- a/ledger/allegra/block_test.go +++ b/ledger/allegra/block_test.go @@ -17,6 +17,7 @@ package allegra_test import ( "bytes" "encoding/hex" + "math/big" "strings" "testing" @@ -150,12 +151,23 @@ func TestAllegraUtxorpcBlock(t *testing.T) { 0, "Transaction should have outputs", ) - assert.Greater( - t, - firstRpcTx.Fee, - uint64(0), - "Transaction fee should be positive", - ) + fee := firstRpcTx.Fee + if fee.GetInt() != 0 { + assert.Greater( + t, + fee.GetInt(), + int64(0), + "Transaction fee should be positive", + ) + } else { + feeBigInt := new(big.Int).SetBytes(fee.GetBigUInt()) + assert.Greater( + t, + feeBigInt.Sign(), + 0, + "Transaction fee should be positive", + ) + } } }) } diff --git a/ledger/allegra/pparams_test.go b/ledger/allegra/pparams_test.go index cc007ed3..1fb1f183 100644 --- a/ledger/allegra/pparams_test.go +++ b/ledger/allegra/pparams_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 Blink Labs Software +// Copyright 2025 Blink Labs Software // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/allegra" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/gouroboros/ledger/shelley" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) func TestAllegraProtocolParamsUpdate(t *testing.T) { @@ -92,29 +92,29 @@ func TestAllegraUtxorpc(t *testing.T) { MinUtxoValue: 1000000, } - expectedUtxorpc := &cardano.PParams{ - MinFeeCoefficient: 500, - MinFeeConstant: 2, - MaxBlockBodySize: 65536, - MaxTxSize: 16384, - MaxBlockHeaderSize: 1024, - StakeKeyDeposit: 2000, - PoolDeposit: 500000, + expectedUtxorpc := &utxorpc.PParams{ + MinFeeCoefficient: common.ToUtxorpcBigInt(500), + MinFeeConstant: common.ToUtxorpcBigInt(2), + MaxBlockBodySize: 65536, + MaxTxSize: 16384, + MaxBlockHeaderSize: 1024, + StakeKeyDeposit: common.ToUtxorpcBigInt(2000), + PoolDeposit: common.ToUtxorpcBigInt(500000), PoolRetirementEpochBound: 2160, DesiredNumberOfPools: 100, - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(3), Denominator: uint32(4), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(5), Denominator: uint32(6), }, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: 8, Minor: 0, }, @@ -171,10 +171,10 @@ func TestAllegraTransactionBody_Utxorpc(t *testing.T) { } // Check that the fee matches - if actual.Fee != txBody.Fee() { + if actual.Fee.GetInt() != int64(txBody.Fee()) { t.Errorf( "AllegraTransactionBody.Utxorpc() fee mismatch\nGot: %d\nWant: %d", - actual.Fee, + actual.Fee.GetInt(), txBody.Fee(), ) } @@ -233,10 +233,10 @@ func TestAllegraTransaction_Utxorpc(t *testing.T) { t.Fatalf("Could not convert transaction to utxorpc format: %v", err) } // Assertion checks - if actual.Fee != tx.Fee() { + if actual.Fee.GetInt() != int64(tx.Fee()) { t.Errorf( "AllegraTransaction.Utxorpc() fee mismatch\nGot: %d\nWant: %d", - actual.Fee, + actual.Fee.GetInt(), tx.Fee(), ) } diff --git a/ledger/alonzo/alonzo.go b/ledger/alonzo/alonzo.go index a352bc39..4e032fc6 100644 --- a/ledger/alonzo/alonzo.go +++ b/ledger/alonzo/alonzo.go @@ -454,8 +454,10 @@ func (o AlonzoTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { for _, assetName := range tmpAssets.Assets(policyId) { amount := tmpAssets.Asset(policyId, assetName) asset := &utxorpc.Asset{ - Name: assetName, - OutputCoin: amount, + Name: assetName, + Quantity: &utxorpc.Asset_OutputCoin{ + OutputCoin: common.ToUtxorpcBigInt(amount), + }, } ma.Assets = append(ma.Assets, asset) } @@ -476,7 +478,7 @@ func (o AlonzoTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { return &utxorpc.TxOutput{ Address: addressBytes, - Coin: o.Amount(), + Coin: common.ToUtxorpcBigInt(o.Amount()), Assets: assets, Datum: &utxorpc.Datum{ Hash: datumHash, diff --git a/ledger/alonzo/pparams.go b/ledger/alonzo/pparams.go index 1aeed050..82b22d4b 100644 --- a/ledger/alonzo/pparams.go +++ b/ledger/alonzo/pparams.go @@ -24,7 +24,7 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/gouroboros/ledger/mary" - cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) // Constants for Plutus version mapping @@ -274,59 +274,73 @@ func (u *AlonzoProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { return nil } -func (p *AlonzoProtocolParameters) Utxorpc() (*cardano.PParams, error) { +func (p *AlonzoProtocolParameters) Utxorpc() (*utxorpc.PParams, error) { // sanity check - if p.A0.Num().Int64() > math.MaxInt32 || + if p.A0 == nil || + p.A0.Num().Int64() < math.MinInt32 || + p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid A0 rational number values") } - if p.Rho.Num().Int64() > math.MaxInt32 || + if p.Rho == nil || + p.Rho.Num().Int64() < math.MinInt32 || + p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid Rho rational number values") } - if p.Tau.Num().Int64() > math.MaxInt32 || + if p.Tau == nil || + p.Tau.Num().Int64() < math.MinInt32 || + p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid Tau rational number values") } - if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || + if p.ExecutionCosts.MemPrice == nil || + p.ExecutionCosts.MemPrice.Num().Int64() < math.MinInt32 || + p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid memory price rational number values") } - if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || + if p.ExecutionCosts.StepPrice == nil || + p.ExecutionCosts.StepPrice.Num().Int64() < math.MinInt32 || + p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid step price rational number values") } + if p.MaxTxExUnits.Memory < 0 || p.MaxTxExUnits.Steps < 0 || + p.MaxBlockExUnits.Memory < 0 || p.MaxBlockExUnits.Steps < 0 { + return nil, errors.New("invalid execution unit values") + } // #nosec G115 - return &cardano.PParams{ - CoinsPerUtxoByte: p.AdaPerUtxoByte, + return &utxorpc.PParams{ + CoinsPerUtxoByte: common.ToUtxorpcBigInt(p.AdaPerUtxoByte), MaxTxSize: uint64(p.MaxTxSize), - MinFeeCoefficient: uint64(p.MinFeeA), - MinFeeConstant: uint64(p.MinFeeB), + MinFeeCoefficient: common.ToUtxorpcBigInt(uint64(p.MinFeeA)), + MinFeeConstant: common.ToUtxorpcBigInt(uint64(p.MinFeeB)), MaxBlockBodySize: uint64(p.MaxBlockBodySize), MaxBlockHeaderSize: uint64(p.MaxBlockHeaderSize), - StakeKeyDeposit: uint64(p.KeyDeposit), - PoolDeposit: uint64(p.PoolDeposit), + StakeKeyDeposit: common.ToUtxorpcBigInt(uint64(p.KeyDeposit)), + PoolDeposit: common.ToUtxorpcBigInt(uint64(p.PoolDeposit)), + MinPoolCost: common.ToUtxorpcBigInt(p.MinPoolCost), PoolRetirementEpochBound: uint64(p.MaxEpoch), DesiredNumberOfPools: uint64(p.NOpt), - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(p.A0.Num().Int64()), Denominator: uint32(p.A0.Denom().Int64()), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Rho.Num().Int64()), Denominator: uint32(p.Rho.Denom().Int64()), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Tau.Num().Int64()), Denominator: uint32(p.Tau.Denom().Int64()), }, - MinPoolCost: p.MinPoolCost, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: uint32(p.ProtocolMajor), Minor: uint32(p.ProtocolMinor), }, @@ -336,21 +350,21 @@ func (p *AlonzoProtocolParameters) Utxorpc() (*cardano.PParams, error) { CostModels: common.ConvertToUtxorpcCardanoCostModels( p.CostModels, ), - Prices: &cardano.ExPrices{ - Memory: &cardano.RationalNumber{ + Prices: &utxorpc.ExPrices{ + Memory: &utxorpc.RationalNumber{ Numerator: int32(p.ExecutionCosts.MemPrice.Num().Int64()), Denominator: uint32(p.ExecutionCosts.MemPrice.Denom().Int64()), }, - Steps: &cardano.RationalNumber{ + Steps: &utxorpc.RationalNumber{ Numerator: int32(p.ExecutionCosts.StepPrice.Num().Int64()), Denominator: uint32(p.ExecutionCosts.StepPrice.Denom().Int64()), }, }, - MaxExecutionUnitsPerTransaction: &cardano.ExUnits{ + MaxExecutionUnitsPerTransaction: &utxorpc.ExUnits{ Memory: uint64(p.MaxTxExUnits.Memory), Steps: uint64(p.MaxTxExUnits.Steps), }, - MaxExecutionUnitsPerBlock: &cardano.ExUnits{ + MaxExecutionUnitsPerBlock: &utxorpc.ExUnits{ Memory: uint64(p.MaxBlockExUnits.Memory), Steps: uint64(p.MaxBlockExUnits.Steps), }, diff --git a/ledger/alonzo/pparams_test.go b/ledger/alonzo/pparams_test.go index 58bfa90d..debf7514 100644 --- a/ledger/alonzo/pparams_test.go +++ b/ledger/alonzo/pparams_test.go @@ -30,7 +30,7 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/mary" "github.com/blinklabs-io/gouroboros/ledger/shelley" "github.com/stretchr/testify/assert" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) func newBaseProtocolParams() alonzo.AlonzoProtocolParameters { @@ -373,63 +373,63 @@ func TestAlonzoUtxorpc(t *testing.T) { }, } - expectedUtxorpc := &cardano.PParams{ - CoinsPerUtxoByte: 44 / 8, - MaxTxSize: 16384, - MinFeeCoefficient: 500, - MinFeeConstant: 2, - MaxBlockBodySize: 65536, - MaxBlockHeaderSize: 1024, - StakeKeyDeposit: 2000, - PoolDeposit: 500000, + expectedUtxorpc := &utxorpc.PParams{ + CoinsPerUtxoByte: common.ToUtxorpcBigInt(44 / 8), + MaxTxSize: 16384, + MinFeeCoefficient: common.ToUtxorpcBigInt(500), + MinFeeConstant: common.ToUtxorpcBigInt(2), + MaxBlockBodySize: 65536, + MaxBlockHeaderSize: 1024, + StakeKeyDeposit: common.ToUtxorpcBigInt(2000), + PoolDeposit: common.ToUtxorpcBigInt(500000), PoolRetirementEpochBound: 2160, DesiredNumberOfPools: 100, - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(3), Denominator: uint32(4), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(5), Denominator: uint32(6), }, - MinPoolCost: 340000000, - ProtocolVersion: &cardano.ProtocolVersion{ + MinPoolCost: common.ToUtxorpcBigInt(340000000), + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: 8, Minor: 0, }, MaxValueSize: 1024, CollateralPercentage: 150, MaxCollateralInputs: 5, - CostModels: &cardano.CostModels{ - PlutusV1: &cardano.CostModel{ + CostModels: &utxorpc.CostModels{ + PlutusV1: &utxorpc.CostModel{ Values: []int64{100, 200, 300}, }, - PlutusV2: &cardano.CostModel{ + PlutusV2: &utxorpc.CostModel{ Values: []int64{400, 500, 600}, }, - PlutusV3: &cardano.CostModel{ + PlutusV3: &utxorpc.CostModel{ Values: []int64{700, 800, 900}, }, }, - Prices: &cardano.ExPrices{ - Memory: &cardano.RationalNumber{ + Prices: &utxorpc.ExPrices{ + Memory: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - Steps: &cardano.RationalNumber{ + Steps: &utxorpc.RationalNumber{ Numerator: int32(2), Denominator: uint32(3), }, }, - MaxExecutionUnitsPerTransaction: &cardano.ExUnits{ + MaxExecutionUnitsPerTransaction: &utxorpc.ExUnits{ Memory: 1000000, Steps: 200000, }, - MaxExecutionUnitsPerBlock: &cardano.ExUnits{ + MaxExecutionUnitsPerBlock: &utxorpc.ExUnits{ Memory: 5000000, Steps: 1000000, }, @@ -474,11 +474,11 @@ func TestAlonzoTransactionOutput_Utxorpc(t *testing.T) { assert.NoError(t, err) addr, err := address.Bytes() assert.NoError(t, err) - want := &cardano.TxOutput{ + want := &utxorpc.TxOutput{ Address: addr, - Coin: amount, + Coin: common.ToUtxorpcBigInt(amount), Assets: nil, - Datum: &cardano.Datum{ + Datum: &utxorpc.Datum{ Hash: datumHash.Bytes(), }, } @@ -528,8 +528,8 @@ func TestAlonzoTransactionBody_Utxorpc(t *testing.T) { } // Assertion checks - if got.Fee != 50 { - t.Errorf("Fee mismatch: got %d, want 50", got.Fee) + if got.Fee.GetInt() != 50 { + t.Errorf("Fee mismatch: got %d, want 50", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) @@ -542,10 +542,20 @@ func TestAlonzoTransactionBody_Utxorpc(t *testing.T) { ) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) + } + var coinValue uint64 + coin := got.Outputs[0].Coin + if bigUInt := coin.GetBigUInt(); bigUInt != nil { + coinValue = new(big.Int).SetBytes(bigUInt).Uint64() + } else { + coinValue = uint64(coin.GetInt()) } - if got.Outputs[0].Coin != 1000 { - t.Errorf("Output coin mismatch: got %d, want 1000", got.Outputs[0].Coin) + if coinValue != uint64(1000) { + t.Errorf( + "Output coin mismatch: got %d, want 1000", + coinValue, + ) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") @@ -591,18 +601,29 @@ func TestAlonzoTransaction_Utxorpc(t *testing.T) { } // Assertion checks - if got.Fee != 75 { - t.Errorf("Transaction fee mismatch: got %d, want 75", got.Fee) + if got.Fee.GetInt() != 75 { + t.Errorf("Transaction fee mismatch: got %d, want 75", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) } - if got.Outputs[0].Coin != 2000 { - t.Errorf("Output coin mismatch: got %d, want 2000", got.Outputs[0].Coin) + var coinValue uint64 + coin := got.Outputs[0].Coin + if bigUInt := coin.GetBigUInt(); bigUInt != nil { + coinValue = new(big.Int).SetBytes(bigUInt).Uint64() + } else { + coinValue = uint64(coin.GetInt()) } + if coinValue != uint64(2000) { + t.Errorf( + "Output coin mismatch: got %d, want 2000", + coinValue, + ) + } + expectedDatum := datumHash.Bytes() if !reflect.DeepEqual(got.Outputs[0].Datum.Hash, expectedDatum) { t.Errorf( diff --git a/ledger/babbage/babbage.go b/ledger/babbage/babbage.go index 2aa7408d..719837be 100644 --- a/ledger/babbage/babbage.go +++ b/ledger/babbage/babbage.go @@ -637,8 +637,10 @@ func (o BabbageTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { for _, assetName := range tmpAssets.Assets(policyId) { amount := tmpAssets.Asset(policyId, assetName) asset := &utxorpc.Asset{ - Name: assetName, - OutputCoin: amount, + Name: assetName, + Quantity: &utxorpc.Asset_OutputCoin{ + OutputCoin: common.ToUtxorpcBigInt(amount), + }, } ma.Assets = append(ma.Assets, asset) } @@ -655,7 +657,7 @@ func (o BabbageTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { return &utxorpc.TxOutput{ Address: address, - Coin: o.Amount(), + Coin: common.ToUtxorpcBigInt(o.Amount()), Assets: assets, Datum: &utxorpc.Datum{ Hash: datumHash, diff --git a/ledger/babbage/babbage_test.go b/ledger/babbage/babbage_test.go index 3523eb7c..bae8b797 100644 --- a/ledger/babbage/babbage_test.go +++ b/ledger/babbage/babbage_test.go @@ -2791,7 +2791,13 @@ func TestBabbageTransactionOutput_Utxorpc_DatumOptionNil(t *testing.T) { assert.NotNil(t, txOutput) assert.Equal(t, []byte{}, txOutput.Datum.Hash) assert.Equal(t, []byte{0x0}, txOutput.Address) - assert.Equal(t, uint64(1000), txOutput.Coin) + coin := txOutput.Coin + if bigUInt := coin.GetBigUInt(); bigUInt != nil { + coinValue := new(big.Int).SetBytes(bigUInt).Uint64() + assert.Equal(t, uint64(1000), coinValue) + } else { + assert.Equal(t, int64(1000), coin.GetInt()) + } } func TestBabbageTransactionOutput_DatumHashReturnsNil(t *testing.T) { diff --git a/ledger/babbage/pparams.go b/ledger/babbage/pparams.go index d2f20a31..f9cdc6d9 100644 --- a/ledger/babbage/pparams.go +++ b/ledger/babbage/pparams.go @@ -21,7 +21,7 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/alonzo" "github.com/blinklabs-io/gouroboros/ledger/common" - cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) // BabbageProtocolParameters represents the current Babbage protocol parameters as seen in local-state-query @@ -163,59 +163,73 @@ func (u *BabbageProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { return nil } -func (p *BabbageProtocolParameters) Utxorpc() (*cardano.PParams, error) { +func (p *BabbageProtocolParameters) Utxorpc() (*utxorpc.PParams, error) { // sanity check - if p.A0.Num().Int64() > math.MaxInt32 || + if p.A0 == nil || + p.A0.Num().Int64() < math.MinInt32 || + p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid A0 rational number values") } - if p.Rho.Num().Int64() > math.MaxInt32 || + if p.Rho == nil || + p.Rho.Num().Int64() < math.MinInt32 || + p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid Rho rational number values") } - if p.Tau.Num().Int64() > math.MaxInt32 || + if p.Tau == nil || + p.Tau.Num().Int64() < math.MinInt32 || + p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid Tau rational number values") } - if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || + if p.ExecutionCosts.MemPrice == nil || + p.ExecutionCosts.MemPrice.Num().Int64() < math.MinInt32 || + p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid memory price rational number values") } - if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || + if p.ExecutionCosts.StepPrice == nil || + p.ExecutionCosts.StepPrice.Num().Int64() < math.MinInt32 || + p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid step price rational number values") } + if p.MaxTxExUnits.Memory < 0 || p.MaxTxExUnits.Steps < 0 || + p.MaxBlockExUnits.Memory < 0 || p.MaxBlockExUnits.Steps < 0 { + return nil, errors.New("invalid execution unit values") + } // #nosec G115 - return &cardano.PParams{ - CoinsPerUtxoByte: p.AdaPerUtxoByte, + return &utxorpc.PParams{ + CoinsPerUtxoByte: common.ToUtxorpcBigInt(p.AdaPerUtxoByte), MaxTxSize: uint64(p.MaxTxSize), - MinFeeCoefficient: uint64(p.MinFeeA), - MinFeeConstant: uint64(p.MinFeeB), + MinFeeCoefficient: common.ToUtxorpcBigInt(uint64(p.MinFeeA)), + MinFeeConstant: common.ToUtxorpcBigInt(uint64(p.MinFeeB)), MaxBlockBodySize: uint64(p.MaxBlockBodySize), MaxBlockHeaderSize: uint64(p.MaxBlockHeaderSize), - StakeKeyDeposit: uint64(p.KeyDeposit), - PoolDeposit: uint64(p.PoolDeposit), + StakeKeyDeposit: common.ToUtxorpcBigInt(uint64(p.KeyDeposit)), + PoolDeposit: common.ToUtxorpcBigInt(uint64(p.PoolDeposit)), + MinPoolCost: common.ToUtxorpcBigInt(p.MinPoolCost), PoolRetirementEpochBound: uint64(p.MaxEpoch), DesiredNumberOfPools: uint64(p.NOpt), - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(p.A0.Num().Int64()), Denominator: uint32(p.A0.Denom().Int64()), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Rho.Num().Int64()), Denominator: uint32(p.Rho.Denom().Int64()), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Tau.Num().Int64()), Denominator: uint32(p.Tau.Denom().Int64()), }, - MinPoolCost: p.MinPoolCost, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: uint32(p.ProtocolMajor), Minor: uint32(p.ProtocolMinor), }, @@ -225,21 +239,21 @@ func (p *BabbageProtocolParameters) Utxorpc() (*cardano.PParams, error) { CostModels: common.ConvertToUtxorpcCardanoCostModels( p.CostModels, ), - Prices: &cardano.ExPrices{ - Memory: &cardano.RationalNumber{ + Prices: &utxorpc.ExPrices{ + Memory: &utxorpc.RationalNumber{ Numerator: int32(p.ExecutionCosts.MemPrice.Num().Int64()), Denominator: uint32(p.ExecutionCosts.MemPrice.Denom().Int64()), }, - Steps: &cardano.RationalNumber{ + Steps: &utxorpc.RationalNumber{ Numerator: int32(p.ExecutionCosts.StepPrice.Num().Int64()), Denominator: uint32(p.ExecutionCosts.StepPrice.Denom().Int64()), }, }, - MaxExecutionUnitsPerTransaction: &cardano.ExUnits{ + MaxExecutionUnitsPerTransaction: &utxorpc.ExUnits{ Memory: uint64(p.MaxTxExUnits.Memory), Steps: uint64(p.MaxTxExUnits.Steps), }, - MaxExecutionUnitsPerBlock: &cardano.ExUnits{ + MaxExecutionUnitsPerBlock: &utxorpc.ExUnits{ Memory: uint64(p.MaxBlockExUnits.Memory), Steps: uint64(p.MaxBlockExUnits.Steps), }, diff --git a/ledger/babbage/pparams_test.go b/ledger/babbage/pparams_test.go index 97b5f235..0f28db66 100644 --- a/ledger/babbage/pparams_test.go +++ b/ledger/babbage/pparams_test.go @@ -26,7 +26,8 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/mary" "github.com/blinklabs-io/gouroboros/ledger/shelley" "github.com/stretchr/testify/assert" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + "google.golang.org/protobuf/proto" ) func TestBabbageProtocolParamsUpdate(t *testing.T) { @@ -439,7 +440,7 @@ func TestBabbageProtocolParamsUpdate(t *testing.T) { func TestBabbageUtxorpc(t *testing.T) { testDefs := []struct { startParams babbage.BabbageProtocolParameters - expectedUtxorpc *cardano.PParams + expectedUtxorpc *utxorpc.PParams }{ { startParams: babbage.BabbageProtocolParameters{ @@ -480,63 +481,75 @@ func TestBabbageUtxorpc(t *testing.T) { 3: {700, 800, 900}, }, }, - expectedUtxorpc: &cardano.PParams{ - CoinsPerUtxoByte: 44, - MaxTxSize: 16384, - MinFeeCoefficient: 500, - MinFeeConstant: 2, - MaxBlockBodySize: 65536, - MaxBlockHeaderSize: 1024, - StakeKeyDeposit: 2000, - PoolDeposit: 500000, + expectedUtxorpc: &utxorpc.PParams{ + CoinsPerUtxoByte: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 44}, + }, + MaxTxSize: 16384, + MinFeeCoefficient: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 500}, + }, + MinFeeConstant: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 2}, + }, + MaxBlockBodySize: 65536, + MaxBlockHeaderSize: 1024, + StakeKeyDeposit: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 2000}, + }, + PoolDeposit: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 500000}, + }, PoolRetirementEpochBound: 2160, DesiredNumberOfPools: 100, - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(3), Denominator: uint32(4), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(5), Denominator: uint32(6), }, - MinPoolCost: 340000000, - ProtocolVersion: &cardano.ProtocolVersion{ + MinPoolCost: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 340000000}, + }, + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: 8, Minor: 0, }, MaxValueSize: 1024, CollateralPercentage: 150, MaxCollateralInputs: 5, - CostModels: &cardano.CostModels{ - PlutusV1: &cardano.CostModel{ + CostModels: &utxorpc.CostModels{ + PlutusV1: &utxorpc.CostModel{ Values: []int64{100, 200, 300}, }, - PlutusV2: &cardano.CostModel{ + PlutusV2: &utxorpc.CostModel{ Values: []int64{400, 500, 600}, }, - PlutusV3: &cardano.CostModel{ + PlutusV3: &utxorpc.CostModel{ Values: []int64{700, 800, 900}, }, }, - Prices: &cardano.ExPrices{ - Memory: &cardano.RationalNumber{ + Prices: &utxorpc.ExPrices{ + Memory: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - Steps: &cardano.RationalNumber{ + Steps: &utxorpc.RationalNumber{ Numerator: int32(2), Denominator: uint32(3), }, }, - MaxExecutionUnitsPerTransaction: &cardano.ExUnits{ + MaxExecutionUnitsPerTransaction: &utxorpc.ExUnits{ Memory: 1000000, Steps: 200000, }, - MaxExecutionUnitsPerBlock: &cardano.ExUnits{ + MaxExecutionUnitsPerBlock: &utxorpc.ExUnits{ Memory: 5000000, Steps: 1000000, }, @@ -549,7 +562,7 @@ func TestBabbageUtxorpc(t *testing.T) { if err != nil { t.Fatalf("Utxorpc() failed: %v", err) } - if !reflect.DeepEqual(result, testDef.expectedUtxorpc) { + if !proto.Equal(result, testDef.expectedUtxorpc) { t.Fatalf( "Utxorpc() test failed:\nExpected: %#v\nGot: %#v", testDef.expectedUtxorpc, @@ -570,12 +583,12 @@ func TestBabbageTransactionInput_Utxorpc(t *testing.T) { if err != nil { t.Fatalf("Utxorpc() failed: %v", err) } - want := &cardano.TxInput{ + want := &utxorpc.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), } - if !reflect.DeepEqual(got, want) { + if !proto.Equal(got, want) { t.Errorf( "BabbageTransactionInput.Utxorpc() mismatch\\nGot: %+v\\nWant: %+v", got, @@ -598,15 +611,15 @@ func TestBabbageTransactionOutput_Utxorpc(t *testing.T) { assert.NoError(t, err) addr, err := address.Bytes() assert.NoError(t, err) - want := &cardano.TxOutput{ + want := &utxorpc.TxOutput{ Address: addr, - Coin: amount, - Datum: &cardano.Datum{ + Coin: common.ToUtxorpcBigInt(amount), + Datum: &utxorpc.Datum{ Hash: make([]byte, 32), }, } - if !reflect.DeepEqual(got, want) { + if !proto.Equal(got, want) { t.Errorf( "BabbageTransactionOutput.Utxorpc() mismatch\nGot: %+v\nWant: %+v", got, @@ -642,17 +655,26 @@ func TestBabbageTransactionBody_Utxorpc(t *testing.T) { err, ) } - if got.Fee != 100 { - t.Errorf("Fee mismatch: got %d, want 100", got.Fee) + if got.Fee.GetInt() != 100 { + t.Errorf("Fee mismatch: got %d, want 100", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) } - if got.Outputs[0].Coin != 5000 { - t.Errorf("Output coin mismatch: got %d, want 5000", got.Outputs[0].Coin) + coin := got.Outputs[0].Coin + if bigInt := coin.GetBigUInt(); bigInt != nil { + coinValue := new(big.Int).SetBytes(bigInt).Uint64() + if coinValue != uint64(5000) { + t.Errorf( + "Output coin mismatch: got %d, want 5000", + coinValue, + ) + } + } else if coin.GetInt() != 5000 { + t.Errorf("Output coin mismatch: got %d, want 5000", coin.GetInt()) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") @@ -687,17 +709,26 @@ func TestBabbageTransaction_Utxorpc(t *testing.T) { if err != nil { t.Fatalf("Could not convert transaction to utxorpc format: %v", err) } - if got.Fee != 150 { - t.Errorf("Fee mismatch: got %d, want 150", got.Fee) + if got.Fee.GetInt() != 150 { + t.Errorf("Fee mismatch: got %d, want 150", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) } - if got.Outputs[0].Coin != 9000 { - t.Errorf("Output coin mismatch: got %d, want 9000", got.Outputs[0].Coin) + coin := got.Outputs[0].Coin + if bigInt := coin.GetBigUInt(); bigInt != nil { + coinValue := new(big.Int).SetBytes(bigInt).Uint64() + if coinValue != uint64(9000) { + t.Errorf( + "Output coin mismatch: got %d, want 9000", + coinValue, + ) + } + } else if coin.GetInt() != 9000 { + t.Errorf("Output coin mismatch: got %d, want 9000", coin.GetInt()) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") diff --git a/ledger/byron/block_test.go b/ledger/byron/block_test.go index c652f0e4..3044939d 100644 --- a/ledger/byron/block_test.go +++ b/ledger/byron/block_test.go @@ -17,6 +17,7 @@ package byron_test import ( "bytes" "encoding/hex" + "math/big" "strings" "testing" @@ -143,12 +144,23 @@ func TestByronTransaction_Utxorpc(t *testing.T) { rpcOut, err := utxo.Output.Utxorpc() assert.NoError(t, err) assert.NotNil(t, rpcOut, "Utxorpc output should not be nil") - assert.Greater( - t, - rpcOut.Coin, - uint64(0), - "Coin amount should be greater than 0", - ) + coin := rpcOut.Coin + assert.NotNil(t, coin, "Coin should not be nil") + if coin.GetInt() != 0 { + assert.Greater( + t, + coin.GetInt(), + int64(0), + "Coin amount should be greater than 0", + ) + } else { + assert.Greater( + t, + new(big.Int).SetBytes(coin.GetBigUInt()).Cmp(big.NewInt(0)), + 0, + "Coin amount should be greater than 0", + ) + } assert.NotEmpty( t, rpcOut.Address, diff --git a/ledger/byron/byron.go b/ledger/byron/byron.go index 785a96d0..c07a558b 100644 --- a/ledger/byron/byron.go +++ b/ledger/byron/byron.go @@ -496,7 +496,7 @@ func (o ByronTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { } return &utxorpc.TxOutput{ Address: addressBytes, - Coin: o.Amount(), + Coin: common.ToUtxorpcBigInt(o.Amount()), }, nil } diff --git a/ledger/byron/byron_test.go b/ledger/byron/byron_test.go index e577f308..40e6f1fc 100644 --- a/ledger/byron/byron_test.go +++ b/ledger/byron/byron_test.go @@ -21,7 +21,7 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/byron" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/stretchr/testify/assert" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) // Unit test for ByronTransactionInput.Utxorpc() @@ -35,7 +35,7 @@ func TestByronTransactionInput_Utxorpc(t *testing.T) { if err != nil { t.Fatal("Could not get transaction input") } - want := &cardano.TxInput{ + want := &utxorpc.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), } @@ -61,9 +61,9 @@ func TestByronTransactionOutput_Utxorpc(t *testing.T) { assert.NoError(t, err) addr, err := address.Bytes() assert.NoError(t, err) - want := &cardano.TxOutput{ + want := &utxorpc.TxOutput{ Address: addr, - Coin: output.OutputAmount, + Coin: common.ToUtxorpcBigInt(output.OutputAmount), } if !reflect.DeepEqual(got, want) { @@ -89,7 +89,7 @@ func TestByronTransaction_Utxorpc_Empty(t *testing.T) { // Validate it's not nil if result == nil { t.Fatal( - "ByronTransaction.Utxorpc() returned nil; expected empty cardano.Tx object", + "ByronTransaction.Utxorpc() returned nil; expected empty utxorpc.Tx object", ) } @@ -100,8 +100,8 @@ func TestByronTransaction_Utxorpc_Empty(t *testing.T) { if len(result.Outputs) != 0 { t.Errorf("Expected zero outputs, got %d", len(result.Outputs)) } - if result.Fee != 0 { - t.Errorf("Expected fee = 0, got %d", result.Fee) + if result.Fee.GetInt() != 0 { + t.Errorf("Expected fee = 0, got %d", result.Fee.GetInt()) } } diff --git a/ledger/common/certs.go b/ledger/common/certs.go index c390369a..c8e0fb69 100644 --- a/ledger/common/certs.go +++ b/ledger/common/certs.go @@ -586,12 +586,12 @@ func (c *PoolRegistrationCertificate) Utxorpc() (*utxorpc.Certificate, error) { } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_PoolRegistration{ + // #nosec G115 PoolRegistration: &utxorpc.PoolRegistrationCert{ Operator: c.Operator[:], VrfKeyhash: c.VrfKeyHash[:], - Pledge: c.Pledge, - Cost: c.Cost, - // #nosec G115 + Pledge: ToUtxorpcBigInt(c.Pledge), + Cost: ToUtxorpcBigInt(c.Cost), Margin: &utxorpc.RationalNumber{ Numerator: int32(c.Margin.Num().Int64()), Denominator: uint32(c.Margin.Denom().Uint64()), @@ -758,9 +758,7 @@ func (c *MoveInstantaneousRewardsCertificate) Utxorpc() (*utxorpc.Certificate, e tmpMirTargets, &utxorpc.MirTarget{ StakeCredential: stakeCr, - // potential integer overflow - // #nosec G115 - DeltaCoin: int64(deltaCoin), + DeltaCoin: ToUtxorpcBigInt(deltaCoin), }, ) } diff --git a/ledger/common/common.go b/ledger/common/common.go index 4975c4d6..9f19eaaa 100644 --- a/ledger/common/common.go +++ b/ledger/common/common.go @@ -1,4 +1,4 @@ -// Copyright 2024 Blink Labs Software +// Copyright 2025 Blink Labs Software // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "maps" + "math" "math/big" "slices" "strings" @@ -27,6 +28,7 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/plutigo/data" "github.com/btcsuite/btcd/btcutil/bech32" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" "golang.org/x/crypto/blake2b" ) @@ -490,3 +492,17 @@ type ExUnits struct { // GenesisRat is a convenience type for cbor.Rat type GenesisRat = cbor.Rat + +// ToUtxorpcBigInt converts a uint64 into a *utxorpc.BigInt pointer +func ToUtxorpcBigInt(v uint64) *utxorpc.BigInt { + if v <= math.MaxInt64 { + return &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: int64(v)}, + } + } + return &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_BigUInt{ + BigUInt: new(big.Int).SetUint64(v).Bytes(), + }, + } +} diff --git a/ledger/common/tx.go b/ledger/common/tx.go index f53bd504..abd9c6ba 100644 --- a/ledger/common/tx.go +++ b/ledger/common/tx.go @@ -236,7 +236,7 @@ func TransactionBodyToUtxorpc(tx TransactionBody) (*utxorpc.Tx, error) { // ReferenceInputs: tx.ReferenceInputs(), // Witnesses: tx.Witnesses(), // Collateral: tx.Collateral(), - Fee: tx.Fee(), + Fee: ToUtxorpcBigInt(tx.Fee()), // Validity: tx.Validity(), // Successful: tx.Successful(), // Auxiliary: tx.AuxData(), diff --git a/ledger/conway/pparams.go b/ledger/conway/pparams.go index 2699f790..c1a74d08 100644 --- a/ledger/conway/pparams.go +++ b/ledger/conway/pparams.go @@ -23,7 +23,7 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/babbage" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/plutigo/data" - cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) type ConwayProtocolParameters struct { @@ -61,59 +61,73 @@ type ConwayProtocolParameters struct { MinFeeRefScriptCostPerByte *cbor.Rat } -func (p *ConwayProtocolParameters) Utxorpc() (*cardano.PParams, error) { +func (p *ConwayProtocolParameters) Utxorpc() (*utxorpc.PParams, error) { // sanity check - if p.A0.Num().Int64() > math.MaxInt32 || + if p.A0 == nil || + p.A0.Num().Int64() < math.MinInt32 || + p.A0.Num().Int64() > math.MaxInt32 || p.A0.Denom().Int64() < 0 || p.A0.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid A0 rational number values") } - if p.Rho.Num().Int64() > math.MaxInt32 || + if p.Rho == nil || + p.Rho.Num().Int64() < math.MinInt32 || + p.Rho.Num().Int64() > math.MaxInt32 || p.Rho.Denom().Int64() < 0 || p.Rho.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid Rho rational number values") } - if p.Tau.Num().Int64() > math.MaxInt32 || + if p.Tau == nil || + p.Tau.Num().Int64() < math.MinInt32 || + p.Tau.Num().Int64() > math.MaxInt32 || p.Tau.Denom().Int64() < 0 || p.Tau.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid Tau rational number values") } - if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || + if p.ExecutionCosts.MemPrice == nil || + p.ExecutionCosts.MemPrice.Num().Int64() < math.MinInt32 || + p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid memory price rational number values") } - if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || + if p.ExecutionCosts.StepPrice == nil || + p.ExecutionCosts.StepPrice.Num().Int64() < math.MinInt32 || + p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { return nil, errors.New("invalid step price rational number values") } + if p.MaxTxExUnits.Memory < 0 || p.MaxTxExUnits.Steps < 0 || + p.MaxBlockExUnits.Memory < 0 || p.MaxBlockExUnits.Steps < 0 { + return nil, errors.New("invalid execution unit values") + } // #nosec G115 - return &cardano.PParams{ - CoinsPerUtxoByte: p.AdaPerUtxoByte, + return &utxorpc.PParams{ + CoinsPerUtxoByte: common.ToUtxorpcBigInt(p.AdaPerUtxoByte), MaxTxSize: uint64(p.MaxTxSize), - MinFeeCoefficient: uint64(p.MinFeeA), - MinFeeConstant: uint64(p.MinFeeB), + MinFeeCoefficient: common.ToUtxorpcBigInt(uint64(p.MinFeeA)), + MinFeeConstant: common.ToUtxorpcBigInt(uint64(p.MinFeeB)), MaxBlockBodySize: uint64(p.MaxBlockBodySize), MaxBlockHeaderSize: uint64(p.MaxBlockHeaderSize), - StakeKeyDeposit: uint64(p.KeyDeposit), - PoolDeposit: uint64(p.PoolDeposit), + StakeKeyDeposit: common.ToUtxorpcBigInt(uint64(p.KeyDeposit)), + PoolDeposit: common.ToUtxorpcBigInt(uint64(p.PoolDeposit)), + MinPoolCost: common.ToUtxorpcBigInt(p.MinPoolCost), PoolRetirementEpochBound: uint64(p.MaxEpoch), DesiredNumberOfPools: uint64(p.NOpt), - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(p.A0.Num().Int64()), Denominator: uint32(p.A0.Denom().Int64()), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Rho.Num().Int64()), Denominator: uint32(p.Rho.Denom().Int64()), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Tau.Num().Int64()), Denominator: uint32(p.Tau.Denom().Int64()), }, - MinPoolCost: p.MinPoolCost, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: uint32(p.ProtocolVersion.Major), Minor: uint32(p.ProtocolVersion.Minor), }, @@ -123,21 +137,21 @@ func (p *ConwayProtocolParameters) Utxorpc() (*cardano.PParams, error) { CostModels: common.ConvertToUtxorpcCardanoCostModels( p.CostModels, ), - Prices: &cardano.ExPrices{ - Memory: &cardano.RationalNumber{ + Prices: &utxorpc.ExPrices{ + Memory: &utxorpc.RationalNumber{ Numerator: int32(p.ExecutionCosts.MemPrice.Num().Int64()), Denominator: uint32(p.ExecutionCosts.MemPrice.Denom().Int64()), }, - Steps: &cardano.RationalNumber{ + Steps: &utxorpc.RationalNumber{ Numerator: int32(p.ExecutionCosts.StepPrice.Num().Int64()), Denominator: uint32(p.ExecutionCosts.StepPrice.Denom().Int64()), }, }, - MaxExecutionUnitsPerTransaction: &cardano.ExUnits{ + MaxExecutionUnitsPerTransaction: &utxorpc.ExUnits{ Memory: uint64(p.MaxTxExUnits.Memory), Steps: uint64(p.MaxTxExUnits.Steps), }, - MaxExecutionUnitsPerBlock: &cardano.ExUnits{ + MaxExecutionUnitsPerBlock: &utxorpc.ExUnits{ Memory: uint64(p.MaxBlockExUnits.Memory), Steps: uint64(p.MaxBlockExUnits.Steps), }, diff --git a/ledger/conway/pparams_test.go b/ledger/conway/pparams_test.go index 5012f30f..62b57b1c 100644 --- a/ledger/conway/pparams_test.go +++ b/ledger/conway/pparams_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 Blink Labs Software +// Copyright 2025 Blink Labs Software // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/conway" "github.com/blinklabs-io/gouroboros/ledger/mary" "github.com/blinklabs-io/gouroboros/ledger/shelley" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) func TestConwayProtocolParamsUpdate(t *testing.T) { @@ -482,7 +482,7 @@ func TestUtxorpc(t *testing.T) { // Define test cases testDefs := []struct { startParams conway.ConwayProtocolParameters - expectedUtxorpc *cardano.PParams + expectedUtxorpc *utxorpc.PParams }{ { startParams: conway.ConwayProtocolParameters{ @@ -525,63 +525,75 @@ func TestUtxorpc(t *testing.T) { 3: {700, 800, 900}, }, }, - expectedUtxorpc: &cardano.PParams{ - CoinsPerUtxoByte: 44, - MaxTxSize: 16384, - MinFeeCoefficient: 500, - MinFeeConstant: 2, - MaxBlockBodySize: 65536, - MaxBlockHeaderSize: 1024, - StakeKeyDeposit: 2000, - PoolDeposit: 500000, + expectedUtxorpc: &utxorpc.PParams{ + CoinsPerUtxoByte: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 44}, + }, + MaxTxSize: 16384, + MinFeeCoefficient: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 500}, + }, + MinFeeConstant: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 2}, + }, + MaxBlockBodySize: 65536, + MaxBlockHeaderSize: 1024, + StakeKeyDeposit: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 2000}, + }, + PoolDeposit: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 500000}, + }, PoolRetirementEpochBound: 2160, DesiredNumberOfPools: 100, - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(3), Denominator: uint32(4), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(5), Denominator: uint32(6), }, - MinPoolCost: 340000000, - ProtocolVersion: &cardano.ProtocolVersion{ + MinPoolCost: &utxorpc.BigInt{ + BigInt: &utxorpc.BigInt_Int{Int: 340000000}, + }, + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: 8, Minor: 0, }, MaxValueSize: 1024, CollateralPercentage: 150, MaxCollateralInputs: 5, - CostModels: &cardano.CostModels{ - PlutusV1: &cardano.CostModel{ + CostModels: &utxorpc.CostModels{ + PlutusV1: &utxorpc.CostModel{ Values: []int64{100, 200, 300}, }, - PlutusV2: &cardano.CostModel{ + PlutusV2: &utxorpc.CostModel{ Values: []int64{400, 500, 600}, }, - PlutusV3: &cardano.CostModel{ + PlutusV3: &utxorpc.CostModel{ Values: []int64{700, 800, 900}, }, }, - Prices: &cardano.ExPrices{ - Memory: &cardano.RationalNumber{ + Prices: &utxorpc.ExPrices{ + Memory: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - Steps: &cardano.RationalNumber{ + Steps: &utxorpc.RationalNumber{ Numerator: int32(2), Denominator: uint32(3), }, }, - MaxExecutionUnitsPerTransaction: &cardano.ExUnits{ + MaxExecutionUnitsPerTransaction: &utxorpc.ExUnits{ Memory: 1000000, Steps: 200000, }, - MaxExecutionUnitsPerBlock: &cardano.ExUnits{ + MaxExecutionUnitsPerBlock: &utxorpc.ExUnits{ Memory: 5000000, Steps: 1000000, }, @@ -662,17 +674,26 @@ func TestConwayTransactionBody_Utxorpc(t *testing.T) { ) } - if got.Fee != 1000 { - t.Errorf("Fee mismatch: got %d, want 100", got.Fee) + if got.Fee.GetInt() != 1000 { + t.Errorf("Fee mismatch: got %d, want 1000", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) } - if got.Outputs[0].Coin != 5000 { - t.Errorf("Output coin mismatch: got %d, want 5000", got.Outputs[0].Coin) + coin := got.Outputs[0].Coin + if bigInt := coin.GetBigUInt(); bigInt != nil { + coinValue := new(big.Int).SetBytes(bigInt).Uint64() + if coinValue != uint64(5000) { + t.Errorf( + "Output coin mismatch: got %d, want 5000", + coinValue, + ) + } + } else if coin.GetInt() != 5000 { + t.Errorf("Output coin mismatch: got %d, want 5000", coin.GetInt()) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") @@ -739,17 +760,29 @@ func TestConwayTransaction_Utxorpc(t *testing.T) { t.Fatalf("Could not convert transaction to utxorpc format: %v", err) } - if got.Fee != 1000 { - t.Errorf("Transaction fee mismatch: got %d, want 25", got.Fee) + if got.Fee.GetInt() != 1000 { + t.Errorf( + "Transaction fee mismatch: got %d, want 1000", + got.Fee.GetInt(), + ) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) } - if got.Outputs[0].Coin != 5000 { - t.Errorf("Output coin mismatch: got %d, want 8000", got.Outputs[0].Coin) + coin := got.Outputs[0].Coin + if bigInt := coin.GetBigUInt(); bigInt != nil { + coinValue := new(big.Int).SetBytes(bigInt).Uint64() + if coinValue != uint64(5000) { + t.Errorf( + "Output coin mismatch: got %d, want 5000", + coinValue, + ) + } + } else if coin.GetInt() != 5000 { + t.Errorf("Output coin mismatch: got %d, want 5000", coin.GetInt()) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") diff --git a/ledger/mary/mary.go b/ledger/mary/mary.go index 8cbb141a..e36a582d 100644 --- a/ledger/mary/mary.go +++ b/ledger/mary/mary.go @@ -557,7 +557,7 @@ func (o MaryTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { } return &utxorpc.TxOutput{ Address: addressBytes, - Coin: o.Amount(), + Coin: common.ToUtxorpcBigInt(o.Amount()), // Assets: o.Assets, }, err diff --git a/ledger/mary/pparams.go b/ledger/mary/pparams.go index b8352400..1d40221d 100644 --- a/ledger/mary/pparams.go +++ b/ledger/mary/pparams.go @@ -22,7 +22,7 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/gouroboros/ledger/shelley" - cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) type MaryProtocolParameters struct { @@ -149,7 +149,7 @@ func (p *MaryProtocolParameterUpdate) MarshalCBOR() ([]byte, error) { return cbor.EncodeGeneric(p) } -func (p *MaryProtocolParameters) Utxorpc() (*cardano.PParams, error) { +func (p *MaryProtocolParameters) Utxorpc() (*utxorpc.PParams, error) { // sanity check if p.A0 == nil || p.A0.Num().Int64() < math.MinInt32 || @@ -173,30 +173,30 @@ func (p *MaryProtocolParameters) Utxorpc() (*cardano.PParams, error) { return nil, errors.New("invalid Tau rational number values") } // #nosec G115 - return &cardano.PParams{ + return &utxorpc.PParams{ MaxTxSize: uint64(p.MaxTxSize), - MinFeeCoefficient: uint64(p.MinFeeA), - MinFeeConstant: uint64(p.MinFeeB), + MinFeeCoefficient: common.ToUtxorpcBigInt(uint64(p.MinFeeA)), + MinFeeConstant: common.ToUtxorpcBigInt(uint64(p.MinFeeB)), MaxBlockBodySize: uint64(p.MaxBlockBodySize), MaxBlockHeaderSize: uint64(p.MaxBlockHeaderSize), - StakeKeyDeposit: uint64(p.KeyDeposit), - PoolDeposit: uint64(p.PoolDeposit), + StakeKeyDeposit: common.ToUtxorpcBigInt(uint64(p.KeyDeposit)), + PoolDeposit: common.ToUtxorpcBigInt(uint64(p.PoolDeposit)), + MinPoolCost: common.ToUtxorpcBigInt(p.MinPoolCost), PoolRetirementEpochBound: uint64(p.MaxEpoch), DesiredNumberOfPools: uint64(p.NOpt), - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(p.A0.Num().Int64()), Denominator: uint32(p.A0.Denom().Int64()), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Rho.Num().Int64()), Denominator: uint32(p.Rho.Denom().Int64()), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Tau.Num().Int64()), Denominator: uint32(p.Tau.Denom().Int64()), }, - MinPoolCost: p.MinPoolCost, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: uint32(p.ProtocolMajor), Minor: uint32(p.ProtocolMinor), }, diff --git a/ledger/mary/pparams_test.go b/ledger/mary/pparams_test.go index d4b48b8d..54bafd58 100644 --- a/ledger/mary/pparams_test.go +++ b/ledger/mary/pparams_test.go @@ -25,7 +25,7 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/mary" "github.com/blinklabs-io/gouroboros/ledger/shelley" "github.com/stretchr/testify/assert" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) func TestMaryProtocolParamsUpdate(t *testing.T) { @@ -93,34 +93,36 @@ func TestMaryUtxorpc(t *testing.T) { ProtocolMajor: 8, ProtocolMinor: 0, MinUtxoValue: 1000000, + MinPoolCost: 340000000, } - expectedUtxorpc := &cardano.PParams{ - MinFeeCoefficient: 500, - MinFeeConstant: 2, - MaxBlockBodySize: 65536, - MaxTxSize: 16384, - MaxBlockHeaderSize: 1024, - StakeKeyDeposit: 2000, - PoolDeposit: 500000, + expectedUtxorpc := &utxorpc.PParams{ + MinFeeCoefficient: common.ToUtxorpcBigInt(500), + MinFeeConstant: common.ToUtxorpcBigInt(2), + MaxBlockBodySize: 65536, + MaxTxSize: 16384, + MaxBlockHeaderSize: 1024, + StakeKeyDeposit: common.ToUtxorpcBigInt(2000), + PoolDeposit: common.ToUtxorpcBigInt(500000), PoolRetirementEpochBound: 2160, DesiredNumberOfPools: 100, - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(3), Denominator: uint32(4), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(5), Denominator: uint32(6), }, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: 8, Minor: 0, }, + MinPoolCost: common.ToUtxorpcBigInt(340000000), } result, err := inputParams.Utxorpc() @@ -148,7 +150,7 @@ func TestMaryTransactionInput_Utxorpc(t *testing.T) { if err != nil { t.Errorf("Could not get correct UTxorpc input") } - want := &cardano.TxInput{ + want := &utxorpc.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), } @@ -176,9 +178,9 @@ func TestMaryTransactionOutput_Utxorpc(t *testing.T) { assert.NoError(t, err) addr, err := address.Bytes() assert.NoError(t, err) - want := &cardano.TxOutput{ + want := &utxorpc.TxOutput{ Address: addr, - Coin: amount, + Coin: common.ToUtxorpcBigInt(amount), } if !reflect.DeepEqual(got, want) { @@ -220,17 +222,26 @@ func TestMaryTransactionBody_Utxorpc(t *testing.T) { ) } - if got.Fee != 100 { - t.Errorf("Fee mismatch: got %d, want 100", got.Fee) + if got.Fee.GetInt() != 100 { + t.Errorf("Fee mismatch: got %d, want 100", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) - } - if got.Outputs[0].Coin != 5000 { - t.Errorf("Output coin mismatch: got %d, want 5000", got.Outputs[0].Coin) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) + } + coin := got.Outputs[0].Coin + if bigInt := coin.GetBigUInt(); bigInt != nil { + coinValue := new(big.Int).SetBytes(bigInt).Uint64() + if coinValue != uint64(5000) { + t.Errorf( + "Output coin mismatch: got %d, want 5000", + coinValue, + ) + } + } else if coin.GetInt() != 5000 { + t.Errorf("Output coin mismatch: got %d, want 5000", coin.GetInt()) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") @@ -268,17 +279,26 @@ func TestMaryTransaction_Utxorpc(t *testing.T) { t.Fatalf("Could not convert transaction to utxorpc format: %v", err) } - if got.Fee != 25 { - t.Errorf("Transaction fee mismatch: got %d, want 25", got.Fee) + if got.Fee.GetInt() != 25 { + t.Errorf("Transaction fee mismatch: got %d, want 25", got.Fee.GetInt()) } if len(got.Inputs) != 1 { t.Errorf("Expected 1 input, got %d", len(got.Inputs)) } if len(got.Outputs) != 1 { - t.Errorf("Expected 1 output, got %d", len(got.Outputs)) - } - if got.Outputs[0].Coin != 8000 { - t.Errorf("Output coin mismatch: got %d, want 8000", got.Outputs[0].Coin) + t.Fatalf("Expected 1 output, got %d", len(got.Outputs)) + } + coin := got.Outputs[0].Coin + if bigInt := coin.GetBigUInt(); bigInt != nil { + coinValue := new(big.Int).SetBytes(bigInt).Uint64() + if coinValue != uint64(8000) { + t.Errorf( + "Output coin mismatch: got %d, want 8000", + coinValue, + ) + } + } else if coin.GetInt() != 8000 { + t.Errorf("Output coin mismatch: got %d, want 8000", coin.GetInt()) } if len(got.Hash) == 0 { t.Error("Expected non-empty transaction hash") @@ -477,10 +497,19 @@ func TestMaryUtxorpc_WithMinPoolCost(t *testing.T) { t.Fatalf("Utxorpc() conversion failed: %v", err) } - if result.MinPoolCost != tc.expectedMinPoolCost { + if bigUInt := result.MinPoolCost.GetBigUInt(); bigUInt != nil { + got := new(big.Int).SetBytes(bigUInt).Uint64() + if got != tc.expectedMinPoolCost { + t.Errorf( + "MinPoolCost mismatch: got %d, want %d", + got, + tc.expectedMinPoolCost, + ) + } + } else if intVal := result.MinPoolCost.GetInt(); uint64(intVal) != tc.expectedMinPoolCost { t.Errorf( "MinPoolCost mismatch: got %d, want %d", - result.MinPoolCost, + intVal, tc.expectedMinPoolCost, ) } diff --git a/ledger/shelley/pparams.go b/ledger/shelley/pparams.go index d919512a..1a5dfb27 100644 --- a/ledger/shelley/pparams.go +++ b/ledger/shelley/pparams.go @@ -21,7 +21,7 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" - cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) type ShelleyProtocolParameters struct { @@ -169,7 +169,7 @@ func (u *ShelleyProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { return nil } -func (p *ShelleyProtocolParameters) Utxorpc() (*cardano.PParams, error) { +func (p *ShelleyProtocolParameters) Utxorpc() (*utxorpc.PParams, error) { // sanity check if p.A0 == nil || p.A0.Num().Int64() < math.MinInt32 || @@ -193,29 +193,29 @@ func (p *ShelleyProtocolParameters) Utxorpc() (*cardano.PParams, error) { return nil, errors.New("invalid Tau rational number values") } // #nosec G115 - return &cardano.PParams{ + return &utxorpc.PParams{ MaxTxSize: uint64(p.MaxTxSize), - MinFeeCoefficient: uint64(p.MinFeeA), - MinFeeConstant: uint64(p.MinFeeB), + MinFeeCoefficient: common.ToUtxorpcBigInt(uint64(p.MinFeeA)), + MinFeeConstant: common.ToUtxorpcBigInt(uint64(p.MinFeeB)), MaxBlockBodySize: uint64(p.MaxBlockBodySize), MaxBlockHeaderSize: uint64(p.MaxBlockHeaderSize), - StakeKeyDeposit: uint64(p.KeyDeposit), - PoolDeposit: uint64(p.PoolDeposit), + StakeKeyDeposit: common.ToUtxorpcBigInt(uint64(p.KeyDeposit)), + PoolDeposit: common.ToUtxorpcBigInt(uint64(p.PoolDeposit)), PoolRetirementEpochBound: uint64(p.MaxEpoch), DesiredNumberOfPools: uint64(p.NOpt), - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(p.A0.Num().Int64()), Denominator: uint32(p.A0.Denom().Int64()), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Rho.Num().Int64()), Denominator: uint32(p.Rho.Denom().Int64()), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(p.Tau.Num().Int64()), Denominator: uint32(p.Tau.Denom().Int64()), }, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: uint32(p.ProtocolMajor), Minor: uint32(p.ProtocolMinor), }, diff --git a/ledger/shelley/pparams_test.go b/ledger/shelley/pparams_test.go index dba149e1..7e312a4d 100644 --- a/ledger/shelley/pparams_test.go +++ b/ledger/shelley/pparams_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 Blink Labs Software +// Copyright 2025 Blink Labs Software // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/gouroboros/ledger/shelley" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) func TestShelleyProtocolParamsUpdate(t *testing.T) { @@ -126,29 +126,29 @@ func TestShelleyUtxorpc(t *testing.T) { ProtocolMinor: 0, } - expectedUtxorpc := &cardano.PParams{ - MaxTxSize: 16384, - MinFeeCoefficient: 500, - MinFeeConstant: 2, - MaxBlockBodySize: 65536, - MaxBlockHeaderSize: 1024, - StakeKeyDeposit: 2000, - PoolDeposit: 500000, + expectedUtxorpc := &utxorpc.PParams{ + MaxTxSize: 16384, + MinFeeCoefficient: common.ToUtxorpcBigInt(500), + MinFeeConstant: common.ToUtxorpcBigInt(2), + MaxBlockBodySize: 65536, + MaxBlockHeaderSize: 1024, + StakeKeyDeposit: common.ToUtxorpcBigInt(2000), + PoolDeposit: common.ToUtxorpcBigInt(500000), PoolRetirementEpochBound: 2160, DesiredNumberOfPools: 100, - PoolInfluence: &cardano.RationalNumber{ + PoolInfluence: &utxorpc.RationalNumber{ Numerator: int32(1), Denominator: uint32(2), }, - MonetaryExpansion: &cardano.RationalNumber{ + MonetaryExpansion: &utxorpc.RationalNumber{ Numerator: int32(3), Denominator: uint32(4), }, - TreasuryExpansion: &cardano.RationalNumber{ + TreasuryExpansion: &utxorpc.RationalNumber{ Numerator: int32(5), Denominator: uint32(6), }, - ProtocolVersion: &cardano.ProtocolVersion{ + ProtocolVersion: &utxorpc.ProtocolVersion{ Major: 8, Minor: 0, }, @@ -183,7 +183,7 @@ func TestShelleyTransactionInput_Utxorpc(t *testing.T) { } // Expected value with same hash and index - want := &cardano.TxInput{ + want := &utxorpc.TxInput{ TxHash: input.Id().Bytes(), OutputIndex: input.Index(), } @@ -218,9 +218,9 @@ func TestShelleyTransactionOutput_Utxorpc(t *testing.T) { } // expected output in utxorpc format - expected := &cardano.TxOutput{ + expected := &utxorpc.TxOutput{ Address: expectedAddressBytes, - Coin: 1000, + Coin: common.ToUtxorpcBigInt(1000), } // Debug prints @@ -278,10 +278,10 @@ func TestShelleyTransactionBody_Utxorpc(t *testing.T) { } // Check that the fee matches - if actual.Fee != txBody.Fee() { + if actual.Fee.GetInt() != int64(txBody.Fee()) { t.Errorf( "TxBody.Utxorpc() fee mismatch\nGot: %d\nWant: %d", - actual.Fee, + actual.Fee.GetInt(), txBody.Fee(), ) } @@ -346,10 +346,10 @@ func TestShelleyTransaction_Utxorpc(t *testing.T) { } // Verify the fee - if got.Fee != tx.Body.Fee() { + if got.Fee.GetInt() != int64(tx.Body.Fee()) { t.Errorf( "ShelleyTransaction.Utxorpc() fee mismatch\nGot: %d\nWant: %d", - got.Fee, + got.Fee.GetInt(), tx.Body.Fee(), ) } diff --git a/ledger/shelley/shelley.go b/ledger/shelley/shelley.go index 929df113..ecc44e20 100644 --- a/ledger/shelley/shelley.go +++ b/ledger/shelley/shelley.go @@ -467,7 +467,7 @@ func (o ShelleyTransactionOutput) Utxorpc() (*utxorpc.TxOutput, error) { return &utxorpc.TxOutput{ Address: addressBytes, - Coin: o.Amount(), + Coin: common.ToUtxorpcBigInt(o.Amount()), }, nil }