From c5a7fdfb42068def4410c1a9bd7c845b8a0bfe86 Mon Sep 17 00:00:00 2001 From: Aurora Gaffney Date: Wed, 20 Mar 2024 17:59:47 -0500 Subject: [PATCH] feat: babbage protocol parameters (#552) This adds support for parsing Babbage protocol parameter updates in transactions. It also updates the Babbage protocol params data structure used for local-state-query and makes it era-aware Fixes #328 --- cmd/gouroboros/query.go | 2 +- ledger/babbage.go | 70 +++++++++++++++++++++++++++-- protocol/localstatequery/client.go | 21 ++++++--- protocol/localstatequery/queries.go | 36 ++------------- 4 files changed, 85 insertions(+), 44 deletions(-) diff --git a/cmd/gouroboros/query.go b/cmd/gouroboros/query.go index 3bb7d695..34539040 100644 --- a/cmd/gouroboros/query.go +++ b/cmd/gouroboros/query.go @@ -150,7 +150,7 @@ func testQuery(f *globalFlags) { fmt.Printf("ERROR: failure querying protocol params: %s\n", err) os.Exit(1) } - fmt.Printf("protocol-params: %#v\n", *protoParams) + fmt.Printf("protocol-params: %#v\n", protoParams) case "stake-distribution": stakeDistribution, err := o.LocalStateQuery().Client.GetStakeDistribution() if err != nil { diff --git a/ledger/babbage.go b/ledger/babbage.go index 8350d029..4eaeaac8 100644 --- a/ledger/babbage.go +++ b/ledger/babbage.go @@ -175,10 +175,15 @@ func (h *BabbageBlockHeader) Era() Era { type BabbageTransactionBody struct { AlonzoTransactionBody - TxOutputs []BabbageTransactionOutput `cbor:"1,keyasint,omitempty"` - CollateralReturn BabbageTransactionOutput `cbor:"16,keyasint,omitempty"` - TotalCollateral uint64 `cbor:"17,keyasint,omitempty"` - TxReferenceInputs []ShelleyTransactionInput `cbor:"18,keyasint,omitempty"` + TxOutputs []BabbageTransactionOutput `cbor:"1,keyasint,omitempty"` + Update struct { + cbor.StructAsArray + ProtocolParamUpdates map[Blake2b224]BabbageProtocolParameterUpdate + Epoch uint64 + } `cbor:"6,keyasint,omitempty"` + CollateralReturn BabbageTransactionOutput `cbor:"16,keyasint,omitempty"` + TotalCollateral uint64 `cbor:"17,keyasint,omitempty"` + TxReferenceInputs []ShelleyTransactionInput `cbor:"18,keyasint,omitempty"` } func (b *BabbageTransactionBody) UnmarshalCBOR(cborData []byte) error { @@ -427,6 +432,63 @@ func (t *BabbageTransaction) Utxorpc() *utxorpc.Tx { return t.Body.Utxorpc() } +// BabbageProtocolParameters represents the current Babbage protocol parameters as seen in local-state-query +type BabbageProtocolParameters struct { + 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 + ProtocolMajor uint + ProtocolMinor uint + MinPoolCost uint + AdaPerUtxoByte uint + CostModels map[uint][]int + ExecutionUnitPrices []*cbor.Rat // [priceMemory priceSteps] + MaxTxExecutionUnits []uint + MaxBlockExecutionUnits []uint + MaxValueSize uint + CollateralPercentage uint + MaxCollateralInputs uint +} + +type BabbageProtocolParameterUpdate struct { + 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"` + ProtocolVersion struct { + cbor.StructAsArray + Major uint + Minor uint + } `cbor:"14,keyasint"` + MinPoolCost uint `cbor:"16,keyasint"` + AdaPerUtxoByte uint `cbor:"17,keyasint"` + CostModels map[uint][]int `cbor:"18,keyasint"` + ExecutionUnitPrices []*cbor.Rat `cbor:"19,keyasint"` + MaxTxExecutionUnits []uint `cbor:"20,keyasint"` + MaxBlockExecutionUnits []uint `cbor:"21,keyasint"` + MaxValueSize uint `cbor:"22,keyasint"` + CollateralPercentage uint `cbor:"23,keyasint"` + MaxCollateralInputs uint `cbor:"24,keyasint"` +} + func NewBabbageBlockFromCbor(data []byte) (*BabbageBlock, error) { var babbageBlock BabbageBlock if _, err := cbor.Decode(data, &babbageBlock); err != nil { diff --git a/protocol/localstatequery/client.go b/protocol/localstatequery/client.go index 4f4f1f17..90c96670 100644 --- a/protocol/localstatequery/client.go +++ b/protocol/localstatequery/client.go @@ -19,6 +19,7 @@ import ( "sync" "github.com/blinklabs-io/gouroboros/cbor" + "github.com/blinklabs-io/gouroboros/ledger" "github.com/blinklabs-io/gouroboros/protocol" "github.com/blinklabs-io/gouroboros/protocol/common" ) @@ -327,7 +328,7 @@ func (c *Client) GetNonMyopicMemberRewards() (*NonMyopicMemberRewardsResult, err } // GetCurrentProtocolParams returns the set of protocol params that are currently in effect -func (c *Client) GetCurrentProtocolParams() (*CurrentProtocolParamsResult, error) { +func (c *Client) GetCurrentProtocolParams() (CurrentProtocolParamsResult, error) { c.busyMutex.Lock() defer c.busyMutex.Unlock() currentEra, err := c.getCurrentEra() @@ -338,12 +339,20 @@ func (c *Client) GetCurrentProtocolParams() (*CurrentProtocolParamsResult, error currentEra, QueryTypeShelleyCurrentProtocolParams, ) - result := []CurrentProtocolParamsResult{} - if err := c.runQuery(query, &result); err != nil { - return nil, err + switch currentEra { + case ledger.EraIdBabbage: + result := []ledger.BabbageProtocolParameters{} + if err := c.runQuery(query, &result); err != nil { + return nil, err + } + return result[0], nil + default: + result := []any{} + if err := c.runQuery(query, &result); err != nil { + return nil, err + } + return result[0], nil } - return &result[0], nil - } // TODO diff --git a/protocol/localstatequery/queries.go b/protocol/localstatequery/queries.go index 4510d05e..fc06b59c 100644 --- a/protocol/localstatequery/queries.go +++ b/protocol/localstatequery/queries.go @@ -16,6 +16,7 @@ package localstatequery import ( "github.com/blinklabs-io/gouroboros/cbor" + "github.com/blinklabs-io/gouroboros/ledger" ) // Query types @@ -142,39 +143,8 @@ type eraHistoryResultParams struct { // TODO type NonMyopicMemberRewardsResult interface{} -type CurrentProtocolParamsResult struct { - // Tells the CBOR decoder to convert to/from a struct and a CBOR array - _ struct{} `cbor:",toarray"` - MinFeeA int - MinFeeB int - MaxBlockBodySize int - MaxTxSize int - MaxBlockHeaderSize int - KeyDeposit int - PoolDeposit int - EMax int - NOpt int - A0 []int - Rho []int - Tau []int - // This field no longer exists in Babbage, but we're keeping this here for reference - // unless we need to support querying a node still on an older era - //DecentralizationParam []int - ProtocolVersion struct { - // Tells the CBOR decoder to convert to/from a struct and a CBOR array - _ struct{} `cbor:",toarray"` - Major int - Minor int - } - MinPoolCost int - MinUtxoValue int - CostModels interface{} - ExecutionUnitPrices interface{} // [priceMemory priceSteps] both elements are fractions - MaxTxExecutionUnits []uint - MaxBlockExecutionUnits []uint - MaxValueSize int - CollateralPercentage int - MaxCollateralInputs int +type CurrentProtocolParamsResult interface { + ledger.BabbageProtocolParameters | any // TODO: add more per-era types } // TODO