From 23aebae40d29a3d8d671d05a3a194febb2635186 Mon Sep 17 00:00:00 2001 From: Aurora Gaffney Date: Tue, 31 Dec 2024 15:15:20 -0600 Subject: [PATCH] fix: custom CBOR marshaling for ShelleyGenesisConfig (#818) --- ledger/shelley/genesis.go | 96 +++++++++++++++++++++++++++++++++- ledger/shelley/genesis_test.go | 10 ++-- 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/ledger/shelley/genesis.go b/ledger/shelley/genesis.go index e32b23c8..4c2a5de1 100644 --- a/ledger/shelley/genesis.go +++ b/ledger/shelley/genesis.go @@ -15,19 +15,22 @@ package shelley import ( + "encoding/hex" "encoding/json" "io" "os" "time" + "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" ) type ShelleyGenesis struct { + cbor.StructAsArray SystemStart time.Time `json:"systemStart"` NetworkMagic uint32 `json:"networkMagic"` NetworkId string `json:"networkid"` - ActiveSlotsCoeff float32 `json:"activeSlotsCoeff"` + ActiveSlotsCoeff common.GenesisRat `json:"activeSlotsCoeff"` SecurityParam int `json:"securityParam"` EpochLength int `json:"epochLength"` SlotsPerKESPeriod int `json:"slotsPerKESPeriod"` @@ -36,12 +39,67 @@ type ShelleyGenesis struct { UpdateQuorum int `json:"updateQuorum"` MaxLovelaceSupply uint64 `json:"maxLovelaceSupply"` ProtocolParameters ShelleyGenesisProtocolParams `json:"protocolParams"` - GenDelegs map[string]map[string]any `json:"genDelegs"` + GenDelegs map[string]map[string]string `json:"genDelegs"` InitialFunds map[string]any `json:"initialFunds"` Staking any `json:"staking"` } +func (g ShelleyGenesis) MarshalCBOR() ([]byte, error) { + genDelegs := map[cbor.ByteString][]cbor.ByteString{} + for k, v := range g.GenDelegs { + keyBytes, err := hex.DecodeString(k) + if err != nil { + return nil, err + } + vrfBytes, err := hex.DecodeString(v["vrf"]) + if err != nil { + return nil, err + } + delegateBytes, err := hex.DecodeString(v["delegate"]) + if err != nil { + return nil, err + } + genDelegs[cbor.NewByteString(keyBytes)] = []cbor.ByteString{ + cbor.NewByteString(delegateBytes), + cbor.NewByteString(vrfBytes), + } + } + staking := []any{} + if g.Staking == nil { + staking = []any{ + map[any]any{}, + map[any]any{}, + } + } + tmpData := []any{ + []any{ + g.SystemStart.Year(), + g.SystemStart.YearDay(), + g.SystemStart.Nanosecond() * 1000, + }, + g.NetworkMagic, + map[string]int{"Testnet": 0, "Mainnet": 1}[g.NetworkId], + []any{ + g.ActiveSlotsCoeff.Num().Int64(), + g.ActiveSlotsCoeff.Denom().Int64(), + }, + g.SecurityParam, + g.EpochLength, + g.SlotsPerKESPeriod, + g.MaxKESEvolutions, + g.SlotLength * 1_000_000, + g.UpdateQuorum, + g.MaxLovelaceSupply, + g.ProtocolParameters, + genDelegs, + g.InitialFunds, + staking, + } + return cbor.Encode(tmpData) +} + type ShelleyGenesisProtocolParams struct { + cbor.StructAsArray MinFeeA uint MinFeeB uint MaxBlockBodySize uint @@ -64,6 +122,40 @@ type ShelleyGenesisProtocolParams struct { MinPoolCost uint } +func (p ShelleyGenesisProtocolParams) MarshalCBOR() ([]byte, error) { + tmpData := []any{ + p.MinFeeA, + p.MinFeeB, + p.MaxBlockBodySize, + p.MaxTxSize, + p.MaxBlockHeaderSize, + p.KeyDeposit, + p.PoolDeposit, + p.MaxEpoch, + p.NOpt, + cbor.Rat{ + Rat: p.A0.Rat, + }, + cbor.Rat{ + Rat: p.Rho.Rat, + }, + cbor.Rat{ + Rat: p.Tau.Rat, + }, + cbor.Rat{ + Rat: p.Decentralization.Rat, + }, + []any{ + map[string]int{"NeutralNonce": 0}[p.ExtraEntropy["Tag"]], + }, + p.ProtocolVersion.Major, + p.ProtocolVersion.Minor, + p.MinUtxoValue, + p.MinPoolCost, + } + return cbor.Encode(tmpData) +} + func NewShelleyGenesisFromReader(r io.Reader) (ShelleyGenesis, error) { var ret ShelleyGenesis dec := json.NewDecoder(r) diff --git a/ledger/shelley/genesis_test.go b/ledger/shelley/genesis_test.go index a55850ac..3669323c 100644 --- a/ledger/shelley/genesis_test.go +++ b/ledger/shelley/genesis_test.go @@ -107,9 +107,11 @@ var expectedGenesisObj = shelley.ShelleyGenesis{ 0, time.UTC, ), - NetworkMagic: 764824073, - NetworkId: "Mainnet", - ActiveSlotsCoeff: 0.05, + NetworkMagic: 764824073, + NetworkId: "Mainnet", + ActiveSlotsCoeff: common.GenesisRat{ + Rat: big.NewRat(5, 100), + }, SecurityParam: 2160, EpochLength: 432000, SlotsPerKESPeriod: 129600, @@ -144,7 +146,7 @@ var expectedGenesisObj = shelley.ShelleyGenesis{ MinUtxoValue: 1000000, MinPoolCost: 340000000, }, - GenDelegs: map[string]map[string]any{ + GenDelegs: map[string]map[string]string{ "162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82": { "delegate": "4485708022839a7b9b8b639a939c85ec0ed6999b5b6dc651b03c43f6", "vrf": "aba81e764b71006c515986bf7b37a72fbb5554f78e6775f08e384dbd572a4b32",