diff --git a/cbor/cbor.go b/cbor/cbor.go index c341b587..5ffb92d5 100644 --- a/cbor/cbor.go +++ b/cbor/cbor.go @@ -69,18 +69,3 @@ func (d *DecodeStoreCbor) SetCbor(cborData []byte) { func (d DecodeStoreCbor) Cbor() []byte { return d.cborData } - -// UnmarshalCbor decodes the specified CBOR into the destination object and saves the original CBOR -func (d *DecodeStoreCbor) UnmarshalCbor( - cborData []byte, - dest DecodeStoreCborInterface, -) error { - if err := DecodeGeneric(cborData, dest); err != nil { - return err - } - // Store a copy of the original CBOR data - // This must be done after we copy from the temp object above, or it gets wiped out - // when using struct embedding and the DecodeStoreCbor struct is embedded at a deeper level - d.SetCbor(cborData) - return nil -} diff --git a/ledger/allegra/pparams.go b/ledger/allegra/pparams.go index 317da9a2..e9afaabb 100644 --- a/ledger/allegra/pparams.go +++ b/ledger/allegra/pparams.go @@ -16,37 +16,14 @@ package allegra import ( "github.com/blinklabs-io/gouroboros/ledger/shelley" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) -type AllegraProtocolParameters struct { - shelley.ShelleyProtocolParameters -} - -func (p *AllegraProtocolParameters) Update( - paramUpdate *AllegraProtocolParameterUpdate, -) { - p.ShelleyProtocolParameters.Update( - ¶mUpdate.ShelleyProtocolParameterUpdate, - ) -} - -type AllegraProtocolParameterUpdate struct { - shelley.ShelleyProtocolParameterUpdate -} - -func (u *AllegraProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { - return u.UnmarshalCbor(data, u) -} +type AllegraProtocolParameters = shelley.ShelleyProtocolParameters -func (p *AllegraProtocolParameters) Utxorpc() *cardano.PParams { - return p.ShelleyProtocolParameters.Utxorpc() -} +type AllegraProtocolParameterUpdate = shelley.ShelleyProtocolParameterUpdate func UpgradePParams( prevPParams shelley.ShelleyProtocolParameters, ) AllegraProtocolParameters { - return AllegraProtocolParameters{ - ShelleyProtocolParameters: prevPParams, - } + return AllegraProtocolParameters(prevPParams) } diff --git a/ledger/allegra/pparams_test.go b/ledger/allegra/pparams_test.go index b23c7fa2..6e9290b2 100644 --- a/ledger/allegra/pparams_test.go +++ b/ledger/allegra/pparams_test.go @@ -22,7 +22,6 @@ import ( "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/allegra" - "github.com/blinklabs-io/gouroboros/ledger/shelley" "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) @@ -34,28 +33,20 @@ func TestAllegraProtocolParamsUpdate(t *testing.T) { }{ { startParams: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{Rat: new(big.Rat).SetInt64(1)}, - }, + Decentralization: &cbor.Rat{Rat: new(big.Rat).SetInt64(1)}, }, updateCbor: "a10cd81e82090a", expectedParams: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, - }, + Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, }, }, { startParams: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - ProtocolMajor: 3, - }, + ProtocolMajor: 3, }, updateCbor: "a10e820400", expectedParams: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - ProtocolMajor: 4, - }, + ProtocolMajor: 4, }, }, } @@ -82,23 +73,21 @@ func TestAllegraProtocolParamsUpdate(t *testing.T) { func TestAllegraUtxorpc(t *testing.T) { inputParams := allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinFeeA: 500, - MinFeeB: 2, - MaxBlockBodySize: 65536, - MaxTxSize: 16384, - MaxBlockHeaderSize: 1024, - KeyDeposit: 2000, - PoolDeposit: 500000, - MaxEpoch: 2160, - NOpt: 100, - A0: &cbor.Rat{Rat: big.NewRat(1, 2)}, - Rho: &cbor.Rat{Rat: big.NewRat(3, 4)}, - Tau: &cbor.Rat{Rat: big.NewRat(5, 6)}, - ProtocolMajor: 8, - ProtocolMinor: 0, - MinUtxoValue: 1000000, - }, + MinFeeA: 500, + MinFeeB: 2, + MaxBlockBodySize: 65536, + MaxTxSize: 16384, + MaxBlockHeaderSize: 1024, + KeyDeposit: 2000, + PoolDeposit: 500000, + MaxEpoch: 2160, + NOpt: 100, + A0: &cbor.Rat{Rat: big.NewRat(1, 2)}, + Rho: &cbor.Rat{Rat: big.NewRat(3, 4)}, + Tau: &cbor.Rat{Rat: big.NewRat(5, 6)}, + ProtocolMajor: 8, + ProtocolMinor: 0, + MinUtxoValue: 1000000, } expectedUtxorpc := &cardano.PParams{ diff --git a/ledger/allegra/rules.go b/ledger/allegra/rules.go index a53000d2..b1ea57b6 100644 --- a/ledger/allegra/rules.go +++ b/ledger/allegra/rules.go @@ -74,7 +74,7 @@ func UtxoValidateFeeTooSmallUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } @@ -119,7 +119,7 @@ func UtxoValidateValueNotConservedUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } @@ -137,7 +137,7 @@ func UtxoValidateOutputTooSmallUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } @@ -164,6 +164,6 @@ func UtxoValidateMaxTxSizeUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } diff --git a/ledger/allegra/rules_test.go b/ledger/allegra/rules_test.go index 972ad499..10c3abe0 100644 --- a/ledger/allegra/rules_test.go +++ b/ledger/allegra/rules_test.go @@ -203,10 +203,8 @@ func TestUtxoValidateFeeTooSmallUtxo(t *testing.T) { } testTx.SetCbor(testTxCbor) testProtocolParams := &allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinFeeA: 7, - MinFeeB: 53, - }, + MinFeeA: 7, + MinFeeB: 53, } testLedgerState := test.MockLedgerState{} testSlot := uint64(0) @@ -526,9 +524,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { } testSlot := uint64(0) testProtocolParams := &allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - KeyDeposit: uint(testStakeDeposit), - }, + KeyDeposit: uint(testStakeDeposit), } // Exact amount t.Run( @@ -675,9 +671,7 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) { testLedgerState := test.MockLedgerState{} testSlot := uint64(0) testProtocolParams := &allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinUtxoValue: 100000, - }, + MinUtxoValue: 100000, } // Good t.Run( diff --git a/ledger/alonzo/pparams.go b/ledger/alonzo/pparams.go index 6e1d438c..c5164404 100644 --- a/ledger/alonzo/pparams.go +++ b/ledger/alonzo/pparams.go @@ -24,7 +24,24 @@ import ( ) type AlonzoProtocolParameters struct { - mary.MaryProtocolParameters + cbor.StructAsArray + MinFeeA uint + MinFeeB uint + MaxBlockBodySize uint + MaxTxSize uint + MaxBlockHeaderSize uint + KeyDeposit uint + PoolDeposit uint + MaxEpoch uint + NOpt uint + A0 *cbor.Rat + Rho *cbor.Rat + Tau *cbor.Rat + Decentralization *cbor.Rat + ExtraEntropy common.Nonce + ProtocolMajor uint + ProtocolMinor uint + MinUtxoValue uint MinPoolCost uint64 AdaPerUtxoByte uint64 CostModels map[uint][]int64 @@ -39,9 +56,55 @@ type AlonzoProtocolParameters struct { func (p *AlonzoProtocolParameters) Update( paramUpdate *AlonzoProtocolParameterUpdate, ) { - p.MaryProtocolParameters.Update( - ¶mUpdate.MaryProtocolParameterUpdate, - ) + if paramUpdate.MinFeeA != nil { + p.MinFeeA = *paramUpdate.MinFeeA + } + if paramUpdate.MinFeeB != nil { + p.MinFeeB = *paramUpdate.MinFeeB + } + if paramUpdate.MaxBlockBodySize != nil { + p.MaxBlockBodySize = *paramUpdate.MaxBlockBodySize + } + if paramUpdate.MaxTxSize != nil { + p.MaxTxSize = *paramUpdate.MaxTxSize + } + if paramUpdate.MaxBlockHeaderSize != nil { + p.MaxBlockHeaderSize = *paramUpdate.MaxBlockHeaderSize + } + if paramUpdate.KeyDeposit != nil { + p.KeyDeposit = *paramUpdate.KeyDeposit + } + if paramUpdate.PoolDeposit != nil { + p.PoolDeposit = *paramUpdate.PoolDeposit + } + if paramUpdate.MaxEpoch != nil { + p.MaxEpoch = *paramUpdate.MaxEpoch + } + if paramUpdate.NOpt != nil { + p.NOpt = *paramUpdate.NOpt + } + if paramUpdate.A0 != nil { + p.A0 = paramUpdate.A0 + } + if paramUpdate.Rho != nil { + p.Rho = paramUpdate.Rho + } + if paramUpdate.Tau != nil { + p.Tau = paramUpdate.Tau + } + if paramUpdate.Decentralization != nil { + p.Decentralization = paramUpdate.Decentralization + } + if paramUpdate.ProtocolVersion != nil { + p.ProtocolMajor = paramUpdate.ProtocolVersion.Major + p.ProtocolMinor = paramUpdate.ProtocolVersion.Minor + } + if paramUpdate.ExtraEntropy != nil { + p.ExtraEntropy = *paramUpdate.ExtraEntropy + } + if paramUpdate.MinUtxoValue != nil { + p.MinUtxoValue = *paramUpdate.MinUtxoValue + } if paramUpdate.MinPoolCost != nil { p.MinPoolCost = *paramUpdate.MinPoolCost } @@ -100,20 +163,45 @@ func (p *AlonzoProtocolParameters) UpdateFromGenesis(genesis *AlonzoGenesis) { } type AlonzoProtocolParameterUpdate struct { - mary.MaryProtocolParameterUpdate - MinPoolCost *uint64 `cbor:"16,keyasint"` - AdaPerUtxoByte *uint64 `cbor:"17,keyasint"` - CostModels map[uint][]int64 `cbor:"18,keyasint"` - ExecutionCosts *common.ExUnitPrice `cbor:"19,keyasint"` - MaxTxExUnits *common.ExUnits `cbor:"20,keyasint"` - MaxBlockExUnits *common.ExUnits `cbor:"21,keyasint"` - MaxValueSize *uint `cbor:"22,keyasint"` - CollateralPercentage *uint `cbor:"23,keyasint"` - MaxCollateralInputs *uint `cbor:"24,keyasint"` + cbor.DecodeStoreCbor + MinFeeA *uint `cbor:"0,keyasint"` + MinFeeB *uint `cbor:"1,keyasint"` + MaxBlockBodySize *uint `cbor:"2,keyasint"` + MaxTxSize *uint `cbor:"3,keyasint"` + MaxBlockHeaderSize *uint `cbor:"4,keyasint"` + KeyDeposit *uint `cbor:"5,keyasint"` + PoolDeposit *uint `cbor:"6,keyasint"` + MaxEpoch *uint `cbor:"7,keyasint"` + NOpt *uint `cbor:"8,keyasint"` + A0 *cbor.Rat `cbor:"9,keyasint"` + Rho *cbor.Rat `cbor:"10,keyasint"` + Tau *cbor.Rat `cbor:"11,keyasint"` + Decentralization *cbor.Rat `cbor:"12,keyasint"` + ExtraEntropy *common.Nonce `cbor:"13,keyasint"` + ProtocolVersion *common.ProtocolParametersProtocolVersion `cbor:"14,keyasint"` + MinUtxoValue *uint `cbor:"15,keyasint"` + MinPoolCost *uint64 `cbor:"16,keyasint"` + AdaPerUtxoByte *uint64 `cbor:"17,keyasint"` + CostModels map[uint][]int64 `cbor:"18,keyasint"` + ExecutionCosts *common.ExUnitPrice `cbor:"19,keyasint"` + MaxTxExUnits *common.ExUnits `cbor:"20,keyasint"` + MaxBlockExUnits *common.ExUnits `cbor:"21,keyasint"` + MaxValueSize *uint `cbor:"22,keyasint"` + CollateralPercentage *uint `cbor:"23,keyasint"` + MaxCollateralInputs *uint `cbor:"24,keyasint"` } -func (u *AlonzoProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { - return u.UnmarshalCbor(data, u) +func (AlonzoProtocolParameterUpdate) IsProtocolParameterUpdate() {} + +func (u *AlonzoProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { + type tAlonzoProtocolParameterUpdate AlonzoProtocolParameterUpdate + var tmp tAlonzoProtocolParameterUpdate + if _, err := cbor.Decode(cborData, &tmp); err != nil { + return err + } + *u = AlonzoProtocolParameterUpdate(tmp) + u.SetCbor(cborData) + return nil } func (p *AlonzoProtocolParameters) Utxorpc() *cardano.PParams { @@ -203,6 +291,22 @@ func UpgradePParams( prevPParams mary.MaryProtocolParameters, ) AlonzoProtocolParameters { return AlonzoProtocolParameters{ - MaryProtocolParameters: prevPParams, + MinFeeA: prevPParams.MinFeeA, + MinFeeB: prevPParams.MinFeeB, + MaxBlockBodySize: prevPParams.MaxBlockBodySize, + MaxTxSize: prevPParams.MaxTxSize, + MaxBlockHeaderSize: prevPParams.MaxBlockHeaderSize, + KeyDeposit: prevPParams.KeyDeposit, + PoolDeposit: prevPParams.PoolDeposit, + MaxEpoch: prevPParams.MaxEpoch, + NOpt: prevPParams.NOpt, + A0: prevPParams.A0, + Rho: prevPParams.Rho, + Tau: prevPParams.Tau, + Decentralization: prevPParams.Decentralization, + ExtraEntropy: prevPParams.ExtraEntropy, + ProtocolMajor: prevPParams.ProtocolMajor, + ProtocolMinor: prevPParams.ProtocolMinor, + MinUtxoValue: prevPParams.MinUtxoValue, } } diff --git a/ledger/alonzo/pparams_test.go b/ledger/alonzo/pparams_test.go index 2a4117ca..699a1887 100644 --- a/ledger/alonzo/pparams_test.go +++ b/ledger/alonzo/pparams_test.go @@ -22,11 +22,8 @@ import ( "testing" "github.com/blinklabs-io/gouroboros/cbor" - "github.com/blinklabs-io/gouroboros/ledger/allegra" "github.com/blinklabs-io/gouroboros/ledger/alonzo" "github.com/blinklabs-io/gouroboros/ledger/common" - "github.com/blinklabs-io/gouroboros/ledger/mary" - "github.com/blinklabs-io/gouroboros/ledger/shelley" "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) @@ -38,57 +35,27 @@ func TestAlonzoProtocolParamsUpdate(t *testing.T) { }{ { startParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{ - Rat: new(big.Rat).SetInt64(1), - }, - }, - }, + Decentralization: &cbor.Rat{ + Rat: new(big.Rat).SetInt64(1), }, }, updateCbor: "a10cd81e82090a", expectedParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, - }, - }, - }, + Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, }, }, { startParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - ProtocolMajor: 5, - }, - }, - }, + ProtocolMajor: 5, }, updateCbor: "a10e820600", expectedParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - ProtocolMajor: 6, - }, - }, - }, + ProtocolMajor: 6, }, }, { startParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MaxBlockBodySize: 1, - }, - }, - }, + MaxBlockBodySize: 1, MaxTxExUnits: common.ExUnits{ Memory: 1, Steps: 1, @@ -96,13 +63,7 @@ func TestAlonzoProtocolParamsUpdate(t *testing.T) { }, updateCbor: "a2021a0001200014821a00aba9501b00000002540be400", expectedParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MaxBlockBodySize: 73728, - }, - }, - }, + MaxBlockBodySize: 73728, MaxTxExUnits: common.ExUnits{ Memory: 11250000, Steps: 10000000000, @@ -139,26 +100,14 @@ func TestAlonzoProtocolParamsUpdateFromGenesis(t *testing.T) { }{ { startParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{ - Rat: new(big.Rat).SetInt64(1), - }, - }, - }, + Decentralization: &cbor.Rat{ + Rat: new(big.Rat).SetInt64(1), }, }, genesisJson: `{"lovelacePerUTxOWord": 34482}`, expectedParams: alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{ - Rat: new(big.Rat).SetInt64(1), - }, - }, - }, + Decentralization: &cbor.Rat{ + Rat: new(big.Rat).SetInt64(1), }, AdaPerUtxoByte: 34482 / 8, }, @@ -185,26 +134,20 @@ func TestAlonzoProtocolParamsUpdateFromGenesis(t *testing.T) { func TestAlonzoUtxorpc(t *testing.T) { inputParams := alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MaxTxSize: 16384, - MinFeeA: 500, - MinFeeB: 2, - MaxBlockBodySize: 65536, - MaxBlockHeaderSize: 1024, - KeyDeposit: 2000, - PoolDeposit: 500000, - MaxEpoch: 2160, - NOpt: 100, - A0: &cbor.Rat{Rat: big.NewRat(1, 2)}, - Rho: &cbor.Rat{Rat: big.NewRat(3, 4)}, - Tau: &cbor.Rat{Rat: big.NewRat(5, 6)}, - ProtocolMajor: 8, - ProtocolMinor: 0, - }, - }, - }, + MaxTxSize: 16384, + MinFeeA: 500, + MinFeeB: 2, + MaxBlockBodySize: 65536, + MaxBlockHeaderSize: 1024, + KeyDeposit: 2000, + PoolDeposit: 500000, + MaxEpoch: 2160, + NOpt: 100, + A0: &cbor.Rat{Rat: big.NewRat(1, 2)}, + Rho: &cbor.Rat{Rat: big.NewRat(3, 4)}, + Tau: &cbor.Rat{Rat: big.NewRat(5, 6)}, + ProtocolMajor: 8, + ProtocolMinor: 0, AdaPerUtxoByte: 44 / 8, MinPoolCost: 340000000, MaxValueSize: 1024, diff --git a/ledger/alonzo/rules.go b/ledger/alonzo/rules.go index 88ed0d25..5b0ddcd1 100644 --- a/ledger/alonzo/rules.go +++ b/ledger/alonzo/rules.go @@ -259,12 +259,54 @@ func UtxoValidateValueNotConservedUtxo( if !ok { return errors.New("pparams are not expected type") } - return shelley.UtxoValidateValueNotConservedUtxo( - tx, - slot, - ls, - &tmpPparams.ShelleyProtocolParameters, - ) + // Calculate consumed value + // consumed = value from input(s) + withdrawals + refunds + var consumedValue uint64 + for _, tmpInput := range tx.Inputs() { + tmpUtxo, err := ls.UtxoById(tmpInput) + // Ignore errors fetching the UTxO and exclude it from calculations + if err != nil { + continue + } + consumedValue += tmpUtxo.Output.Amount() + } + for _, tmpWithdrawalAmount := range tx.Withdrawals() { + consumedValue += tmpWithdrawalAmount + } + for _, cert := range tx.Certificates() { + switch cert.(type) { + case *common.StakeDeregistrationCertificate: + consumedValue += uint64(tmpPparams.KeyDeposit) + } + } + // Calculate produced value + // produced = value from output(s) + fee + deposits + var producedValue uint64 + for _, tmpOutput := range tx.Outputs() { + producedValue += tmpOutput.Amount() + } + producedValue += tx.Fee() + for _, cert := range tx.Certificates() { + switch tmpCert := cert.(type) { + case *common.PoolRegistrationCertificate: + certs, err := ls.PoolRegistration(common.Blake2b224(tmpCert.Operator).Bytes()) + if err != nil { + return err + } + if len(certs) == 0 { + producedValue += uint64(tmpPparams.PoolDeposit) + } + case *common.StakeRegistrationCertificate: + producedValue += uint64(tmpPparams.KeyDeposit) + } + } + if consumedValue == producedValue { + return nil + } + return shelley.ValueNotConservedUtxoError{ + Consumed: consumedValue, + Produced: producedValue, + } } func UtxoValidateOutputTooSmallUtxo( @@ -273,16 +315,22 @@ func UtxoValidateOutputTooSmallUtxo( ls common.LedgerState, pp common.ProtocolParameters, ) error { - tmpPparams, ok := pp.(*AlonzoProtocolParameters) - if !ok { - return errors.New("pparams are not expected type") + minCoin, err := MinCoinTxOut(tx, pp) + if err != nil { + return err + } + var badOutputs []common.TransactionOutput + for _, tmpOutput := range tx.Outputs() { + if tmpOutput.Amount() < minCoin { + badOutputs = append(badOutputs, tmpOutput) + } + } + if len(badOutputs) == 0 { + return nil + } + return shelley.OutputTooSmallUtxoError{ + Outputs: badOutputs, } - return shelley.UtxoValidateOutputTooSmallUtxo( - tx, - slot, - ls, - &tmpPparams.ShelleyProtocolParameters, - ) } func UtxoValidateOutputBootAddrAttrsTooBig( @@ -322,12 +370,21 @@ func UtxoValidateMaxTxSizeUtxo( if !ok { return errors.New("pparams are not expected type") } - return shelley.UtxoValidateMaxTxSizeUtxo( - tx, - slot, - ls, - &tmpPparams.ShelleyProtocolParameters, - ) + txBytes := tx.Cbor() + if len(txBytes) == 0 { + var err error + txBytes, err = cbor.Encode(tx) + if err != nil { + return err + } + } + if uint(len(txBytes)) <= tmpPparams.MaxTxSize { + return nil + } + return shelley.MaxTxSizeUtxoError{ + TxSize: uint(len(txBytes)), + MaxTxSize: tmpPparams.MaxTxSize, + } } // MinFeeTx calculates the minimum required fee for a transaction based on protocol parameters @@ -358,3 +415,16 @@ func MinFeeTx( ) return minFee, nil } + +// MinCoinTxOut calculates the minimum coin for a transaction output based on protocol parameters +func MinCoinTxOut( + _ common.Transaction, + pparams common.ProtocolParameters, +) (uint64, error) { + tmpPparams, ok := pparams.(*AlonzoProtocolParameters) + if !ok { + return 0, errors.New("pparams are not expected type") + } + minCoinTxOut := uint64(tmpPparams.MinUtxoValue) + return minCoinTxOut, nil +} diff --git a/ledger/alonzo/rules_test.go b/ledger/alonzo/rules_test.go index 2c40af4b..a4d33310 100644 --- a/ledger/alonzo/rules_test.go +++ b/ledger/alonzo/rules_test.go @@ -207,14 +207,8 @@ func TestUtxoValidateFeeTooSmallUtxo(t *testing.T) { } testTx.SetCbor(testTxCbor) testProtocolParams := &alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinFeeA: 7, - MinFeeB: 53, - }, - }, - }, + MinFeeA: 7, + MinFeeB: 53, } testLedgerState := test.MockLedgerState{} testSlot := uint64(0) @@ -539,13 +533,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { } testSlot := uint64(0) testProtocolParams := &alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - KeyDeposit: uint(testStakeDeposit), - }, - }, - }, + KeyDeposit: uint(testStakeDeposit), } // Exact amount t.Run( @@ -692,13 +680,7 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) { testLedgerState := test.MockLedgerState{} testSlot := uint64(0) testProtocolParams := &alonzo.AlonzoProtocolParameters{ - MaryProtocolParameters: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinUtxoValue: 100000, - }, - }, - }, + MinUtxoValue: 100000, } // Good t.Run( diff --git a/ledger/babbage/pparams.go b/ledger/babbage/pparams.go index a49f6d1f..336d55a6 100644 --- a/ledger/babbage/pparams.go +++ b/ledger/babbage/pparams.go @@ -151,8 +151,15 @@ type BabbageProtocolParameterUpdate struct { func (BabbageProtocolParameterUpdate) IsProtocolParameterUpdate() {} -func (u *BabbageProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { - return u.UnmarshalCbor(data, u) +func (u *BabbageProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { + type tBabbageProtocolParameterUpdate BabbageProtocolParameterUpdate + var tmp tBabbageProtocolParameterUpdate + if _, err := cbor.Decode(cborData, &tmp); err != nil { + return err + } + *u = BabbageProtocolParameterUpdate(tmp) + u.SetCbor(cborData) + return nil } func (p *BabbageProtocolParameters) Utxorpc() *cardano.PParams { diff --git a/ledger/conway/pparams.go b/ledger/conway/pparams.go index ba5a4db1..3296c337 100644 --- a/ledger/conway/pparams.go +++ b/ledger/conway/pparams.go @@ -350,8 +350,15 @@ type ConwayProtocolParameterUpdate struct { MinFeeRefScriptCostPerByte *cbor.Rat `cbor:"33,keyasint"` } -func (u *ConwayProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { - return u.UnmarshalCbor(data, u) +func (u *ConwayProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { + type tConwayProtocolParameterUpdate ConwayProtocolParameterUpdate + var tmp tConwayProtocolParameterUpdate + if _, err := cbor.Decode(cborData, &tmp); err != nil { + return err + } + *u = ConwayProtocolParameterUpdate(tmp) + u.SetCbor(cborData) + return nil } type PoolVotingThresholds struct { diff --git a/ledger/mary/pparams.go b/ledger/mary/pparams.go index 187adc66..163cdf6c 100644 --- a/ledger/mary/pparams.go +++ b/ledger/mary/pparams.go @@ -14,39 +14,14 @@ package mary -import ( - "github.com/blinklabs-io/gouroboros/ledger/allegra" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" -) +import "github.com/blinklabs-io/gouroboros/ledger/shelley" -type MaryProtocolParameters struct { - allegra.AllegraProtocolParameters -} - -func (p *MaryProtocolParameters) Update( - paramUpdate *MaryProtocolParameterUpdate, -) { - p.AllegraProtocolParameters.Update( - ¶mUpdate.AllegraProtocolParameterUpdate, - ) -} - -type MaryProtocolParameterUpdate struct { - allegra.AllegraProtocolParameterUpdate -} - -func (u *MaryProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { - return u.UnmarshalCbor(data, u) -} +type MaryProtocolParameters = shelley.ShelleyProtocolParameters -func (p *MaryProtocolParameters) Utxorpc() *cardano.PParams { - return p.AllegraProtocolParameters.Utxorpc() -} +type MaryProtocolParameterUpdate = shelley.ShelleyProtocolParameterUpdate func UpgradePParams( - prevPParams allegra.AllegraProtocolParameters, + prevPParams shelley.ShelleyProtocolParameters, ) MaryProtocolParameters { - return MaryProtocolParameters{ - AllegraProtocolParameters: prevPParams, - } + return MaryProtocolParameters(prevPParams) } diff --git a/ledger/mary/pparams_test.go b/ledger/mary/pparams_test.go index d4577432..17299d65 100644 --- a/ledger/mary/pparams_test.go +++ b/ledger/mary/pparams_test.go @@ -21,9 +21,7 @@ import ( "testing" "github.com/blinklabs-io/gouroboros/cbor" - "github.com/blinklabs-io/gouroboros/ledger/allegra" "github.com/blinklabs-io/gouroboros/ledger/mary" - "github.com/blinklabs-io/gouroboros/ledger/shelley" "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) @@ -35,38 +33,22 @@ func TestMaryProtocolParamsUpdate(t *testing.T) { }{ { startParams: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{ - Rat: new(big.Rat).SetInt64(1), - }, - }, + Decentralization: &cbor.Rat{ + Rat: new(big.Rat).SetInt64(1), }, }, updateCbor: "a10cd81e82090a", expectedParams: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, - }, - }, + Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, }, }, { startParams: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - ProtocolMajor: 4, - }, - }, + ProtocolMajor: 4, }, updateCbor: "a10e820500", expectedParams: mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - ProtocolMajor: 5, - }, - }, + ProtocolMajor: 5, }, }, } @@ -93,25 +75,21 @@ func TestMaryProtocolParamsUpdate(t *testing.T) { func TestMaryUtxorpc(t *testing.T) { inputParams := mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinFeeA: 500, - MinFeeB: 2, - MaxBlockBodySize: 65536, - MaxTxSize: 16384, - MaxBlockHeaderSize: 1024, - KeyDeposit: 2000, - PoolDeposit: 500000, - MaxEpoch: 2160, - NOpt: 100, - A0: &cbor.Rat{Rat: big.NewRat(1, 2)}, - Rho: &cbor.Rat{Rat: big.NewRat(3, 4)}, - Tau: &cbor.Rat{Rat: big.NewRat(5, 6)}, - ProtocolMajor: 8, - ProtocolMinor: 0, - MinUtxoValue: 1000000, - }, - }, + MinFeeA: 500, + MinFeeB: 2, + MaxBlockBodySize: 65536, + MaxTxSize: 16384, + MaxBlockHeaderSize: 1024, + KeyDeposit: 2000, + PoolDeposit: 500000, + MaxEpoch: 2160, + NOpt: 100, + A0: &cbor.Rat{Rat: big.NewRat(1, 2)}, + Rho: &cbor.Rat{Rat: big.NewRat(3, 4)}, + Tau: &cbor.Rat{Rat: big.NewRat(5, 6)}, + ProtocolMajor: 8, + ProtocolMinor: 0, + MinUtxoValue: 1000000, } expectedUtxorpc := &cardano.PParams{ diff --git a/ledger/mary/rules.go b/ledger/mary/rules.go index 7a79800e..3ba938fd 100644 --- a/ledger/mary/rules.go +++ b/ledger/mary/rules.go @@ -103,7 +103,7 @@ func UtxoValidateFeeTooSmallUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } @@ -148,7 +148,7 @@ func UtxoValidateValueNotConservedUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } @@ -166,7 +166,7 @@ func UtxoValidateOutputTooSmallUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } @@ -193,6 +193,6 @@ func UtxoValidateMaxTxSizeUtxo( tx, slot, ls, - &tmpPparams.ShelleyProtocolParameters, + tmpPparams, ) } diff --git a/ledger/mary/rules_test.go b/ledger/mary/rules_test.go index c0271a03..8e6754c4 100644 --- a/ledger/mary/rules_test.go +++ b/ledger/mary/rules_test.go @@ -205,12 +205,8 @@ func TestUtxoValidateFeeTooSmallUtxo(t *testing.T) { } testTx.SetCbor(testTxCbor) testProtocolParams := &mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinFeeA: 7, - MinFeeB: 53, - }, - }, + MinFeeA: 7, + MinFeeB: 53, } testLedgerState := test.MockLedgerState{} testSlot := uint64(0) @@ -535,11 +531,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { } testSlot := uint64(0) testProtocolParams := &mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - KeyDeposit: uint(testStakeDeposit), - }, - }, + KeyDeposit: uint(testStakeDeposit), } // Exact amount t.Run( @@ -686,11 +678,7 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) { testLedgerState := test.MockLedgerState{} testSlot := uint64(0) testProtocolParams := &mary.MaryProtocolParameters{ - AllegraProtocolParameters: allegra.AllegraProtocolParameters{ - ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ - MinUtxoValue: 100000, - }, - }, + MinUtxoValue: 100000, } // Good t.Run( diff --git a/ledger/shelley/pparams.go b/ledger/shelley/pparams.go index e2af007f..ce54ace2 100644 --- a/ledger/shelley/pparams.go +++ b/ledger/shelley/pparams.go @@ -154,8 +154,15 @@ type ShelleyProtocolParameterUpdate struct { func (ShelleyProtocolParameterUpdate) IsProtocolParameterUpdate() {} -func (u *ShelleyProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { - return u.UnmarshalCbor(data, u) +func (u *ShelleyProtocolParameterUpdate) UnmarshalCBOR(cborData []byte) error { + type tShelleyProtocolParameterUpdate ShelleyProtocolParameterUpdate + var tmp tShelleyProtocolParameterUpdate + if _, err := cbor.Decode(cborData, &tmp); err != nil { + return err + } + *u = ShelleyProtocolParameterUpdate(tmp) + u.SetCbor(cborData) + return nil } func (p *ShelleyProtocolParameters) Utxorpc() *cardano.PParams { diff --git a/protocol/localstatequery/queries.go b/protocol/localstatequery/queries.go index 59711737..0b085a33 100644 --- a/protocol/localstatequery/queries.go +++ b/protocol/localstatequery/queries.go @@ -476,11 +476,9 @@ non_myopic_rewards { *poolid => int } int is the amount of lovelaces each pool w type NonMyopicMemberRewardsResult interface{} type CurrentProtocolParamsResult interface { - ledger.AllegraProtocolParameters | - ledger.AlonzoProtocolParameters | + ledger.AlonzoProtocolParameters | ledger.BabbageProtocolParameters | ledger.ConwayProtocolParameters | - ledger.MaryProtocolParameters | ledger.ShelleyProtocolParameters | any }