diff --git a/ledger/allegra/allegra.go b/ledger/allegra/allegra.go index 11224085..ec6a7a2d 100644 --- a/ledger/allegra/allegra.go +++ b/ledger/allegra/allegra.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. @@ -98,6 +98,7 @@ func (b *AllegraBlock) Era() common.Era { func (b *AllegraBlock) Transactions() []common.Transaction { ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 for idx := range b.TransactionBodies { ret[idx] = &AllegraTransaction{ Body: b.TransactionBodies[idx], diff --git a/ledger/alonzo/alonzo.go b/ledger/alonzo/alonzo.go index 0354b1a5..8038b2d5 100644 --- a/ledger/alonzo/alonzo.go +++ b/ledger/alonzo/alonzo.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. @@ -106,6 +106,7 @@ func (b *AlonzoBlock) Transactions() []common.Transaction { } ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 for idx := range b.TransactionBodies { ret[idx] = &AlonzoTransaction{ Body: b.TransactionBodies[idx], diff --git a/ledger/alonzo/pparams.go b/ledger/alonzo/pparams.go index 38bdfdf8..44e19a6c 100644 --- a/ledger/alonzo/pparams.go +++ b/ledger/alonzo/pparams.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. @@ -15,10 +15,13 @@ package alonzo import ( + "math" + + cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/gouroboros/ledger/mary" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) type AlonzoProtocolParameters struct { @@ -115,6 +118,33 @@ func (u *AlonzoProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { } func (p *AlonzoProtocolParameters) Utxorpc() *cardano.PParams { + // sanity check + if p.A0.Num().Int64() > math.MaxInt32 || + p.A0.Denom().Int64() < 0 || + p.A0.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Rho.Num().Int64() > math.MaxInt32 || + p.Rho.Denom().Int64() < 0 || + p.Rho.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Tau.Num().Int64() > math.MaxInt32 || + p.Tau.Denom().Int64() < 0 || + p.Tau.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || + p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || + p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || + p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || + p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { + return nil + } + // #nosec G115 return &cardano.PParams{ CoinsPerUtxoByte: p.AdaPerUtxoByte, MaxTxSize: uint64(p.MaxTxSize), diff --git a/ledger/babbage/babbage.go b/ledger/babbage/babbage.go index 76a4c464..78463bcf 100644 --- a/ledger/babbage/babbage.go +++ b/ledger/babbage/babbage.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. @@ -107,6 +107,7 @@ func (b *BabbageBlock) Transactions() []common.Transaction { } ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 for idx := range b.TransactionBodies { ret[idx] = &BabbageTransaction{ Body: b.TransactionBodies[idx], diff --git a/ledger/babbage/pparams.go b/ledger/babbage/pparams.go index 992210fc..3bb27669 100644 --- a/ledger/babbage/pparams.go +++ b/ledger/babbage/pparams.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. @@ -15,10 +15,13 @@ package babbage import ( + "math" + + cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/alonzo" "github.com/blinklabs-io/gouroboros/ledger/common" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) // BabbageProtocolParameters represents the current Babbage protocol parameters as seen in local-state-query @@ -154,6 +157,33 @@ func (u *BabbageProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { } func (p *BabbageProtocolParameters) Utxorpc() *cardano.PParams { + // sanity check + if p.A0.Num().Int64() > math.MaxInt32 || + p.A0.Denom().Int64() < 0 || + p.A0.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Rho.Num().Int64() > math.MaxInt32 || + p.Rho.Denom().Int64() < 0 || + p.Rho.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Tau.Num().Int64() > math.MaxInt32 || + p.Tau.Denom().Int64() < 0 || + p.Tau.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || + p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || + p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || + p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || + p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { + return nil + } + // #nosec G115 return &cardano.PParams{ CoinsPerUtxoByte: p.AdaPerUtxoByte, MaxTxSize: uint64(p.MaxTxSize), diff --git a/ledger/byron/byron.go b/ledger/byron/byron.go index be60a9d1..a15e2459 100644 --- a/ledger/byron/byron.go +++ b/ledger/byron/byron.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. @@ -17,6 +17,7 @@ package byron import ( "encoding/hex" "fmt" + "math" "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" @@ -309,6 +310,9 @@ func NewByronTransactionInput(hash string, idx int) ByronTransactionInput { if err != nil { panic(fmt.Sprintf("failed to decode transaction hash: %s", err)) } + if idx < 0 || idx > math.MaxUint32 { + panic("index out of range") + } return ByronTransactionInput{ TxId: common.Blake2b256(tmpHash), OutputIndex: uint32(idx), diff --git a/ledger/common/certs.go b/ledger/common/certs.go index b11a152a..3707e3a8 100644 --- a/ledger/common/certs.go +++ b/ledger/common/certs.go @@ -102,7 +102,8 @@ func (c *CertificateWrapper) UnmarshalCBOR(data []byte) error { if _, err := cbor.Decode(data, tmpCert); err != nil { return err } - c.Type = uint(certType) + // certType is known within uint range + c.Type = uint(certType) // #nosec G115 c.Certificate = tmpCert return nil } @@ -355,6 +356,7 @@ func (c *PoolRegistrationCertificate) Utxorpc() *utxorpc.Certificate { VrfKeyhash: c.VrfKeyHash[:], Pledge: c.Pledge, Cost: c.Cost, + // #nosec G115 Margin: &utxorpc.RationalNumber{ Numerator: int32(c.Margin.Num().Int64()), Denominator: uint32(c.Margin.Denom().Uint64()), @@ -484,13 +486,17 @@ func (c *MoveInstantaneousRewardsCertificate) Utxorpc() *utxorpc.Certificate { tmpMirTargets, &utxorpc.MirTarget{ StakeCredential: stakeCred.Utxorpc(), - DeltaCoin: int64(deltaCoin), + // potential integer overflow + // #nosec G115 + DeltaCoin: int64(deltaCoin), }, ) } return &utxorpc.Certificate{ Certificate: &utxorpc.Certificate_MirCert{ MirCert: &utxorpc.MirCert{ + // potential integer overflow + // #nosec G115 From: utxorpc.MirSource(c.Reward.Source), To: tmpMirTargets, OtherPot: c.Reward.OtherPot, diff --git a/ledger/common/gov.go b/ledger/common/gov.go index fb75eeda..63c7e200 100644 --- a/ledger/common/gov.go +++ b/ledger/common/gov.go @@ -113,7 +113,8 @@ func (g *GovActionWrapper) UnmarshalCBOR(data []byte) error { if _, err := cbor.Decode(data, tmpAction); err != nil { return err } - g.Type = uint(actionType) + // action type is known within uint range + g.Type = uint(actionType) // #nosec G115 g.Action = tmpAction return nil } diff --git a/ledger/common/nonce.go b/ledger/common/nonce.go index c8e6ed59..481c65e8 100644 --- a/ledger/common/nonce.go +++ b/ledger/common/nonce.go @@ -38,9 +38,8 @@ func (n *Nonce) UnmarshalCBOR(data []byte) error { if err != nil { return err } - - n.Type = uint(nonceType) - + // nonce type is known within uint range + n.Type = uint(nonceType) // #nosec G115 switch nonceType { case NonceTypeNeutral: // Value uses default value diff --git a/ledger/conway/conway.go b/ledger/conway/conway.go index ce6eb233..28c3ba47 100644 --- a/ledger/conway/conway.go +++ b/ledger/conway/conway.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. @@ -106,6 +106,7 @@ func (b *ConwayBlock) Transactions() []common.Transaction { } ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 for idx := range b.TransactionBodies { ret[idx] = &ConwayTransaction{ Body: b.TransactionBodies[idx], diff --git a/ledger/conway/pparams.go b/ledger/conway/pparams.go index 532776b9..6e03d842 100644 --- a/ledger/conway/pparams.go +++ b/ledger/conway/pparams.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. @@ -15,10 +15,13 @@ package conway import ( + "math" + + cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/babbage" "github.com/blinklabs-io/gouroboros/ledger/common" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) type ConwayProtocolParameters struct { @@ -57,6 +60,33 @@ type ConwayProtocolParameters struct { } func (p *ConwayProtocolParameters) Utxorpc() *cardano.PParams { + // sanity check + if p.A0.Num().Int64() > math.MaxInt32 || + p.A0.Denom().Int64() < 0 || + p.A0.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Rho.Num().Int64() > math.MaxInt32 || + p.Rho.Denom().Int64() < 0 || + p.Rho.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Tau.Num().Int64() > math.MaxInt32 || + p.Tau.Denom().Int64() < 0 || + p.Tau.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.ExecutionCosts.MemPrice.Num().Int64() > math.MaxInt32 || + p.ExecutionCosts.MemPrice.Denom().Int64() < 0 || + p.ExecutionCosts.MemPrice.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.ExecutionCosts.StepPrice.Num().Int64() > math.MaxInt32 || + p.ExecutionCosts.StepPrice.Denom().Int64() < 0 || + p.ExecutionCosts.StepPrice.Denom().Int64() > math.MaxUint32 { + return nil + } + // #nosec G115 return &cardano.PParams{ CoinsPerUtxoByte: p.AdaPerUtxoByte, MaxTxSize: uint64(p.MaxTxSize), diff --git a/ledger/mary/mary.go b/ledger/mary/mary.go index fa0153af..7c2b3656 100644 --- a/ledger/mary/mary.go +++ b/ledger/mary/mary.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. @@ -100,6 +100,7 @@ func (b *MaryBlock) Era() common.Era { func (b *MaryBlock) Transactions() []common.Transaction { ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 for idx := range b.TransactionBodies { ret[idx] = &MaryTransaction{ Body: b.TransactionBodies[idx], diff --git a/ledger/shelley/pparams.go b/ledger/shelley/pparams.go index 5ab2e03e..adb308a5 100644 --- a/ledger/shelley/pparams.go +++ b/ledger/shelley/pparams.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. @@ -15,11 +15,13 @@ package shelley import ( + "math" "math/big" + cardano "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" + "github.com/blinklabs-io/gouroboros/cbor" "github.com/blinklabs-io/gouroboros/ledger/common" - "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" ) type ShelleyProtocolParameters struct { @@ -158,6 +160,23 @@ func (u *ShelleyProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { } func (p *ShelleyProtocolParameters) Utxorpc() *cardano.PParams { + // sanity check + if p.A0.Num().Int64() > math.MaxInt32 || + p.A0.Denom().Int64() < 0 || + p.A0.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Rho.Num().Int64() > math.MaxInt32 || + p.Rho.Denom().Int64() < 0 || + p.Rho.Denom().Int64() > math.MaxUint32 { + return nil + } + if p.Tau.Num().Int64() > math.MaxInt32 || + p.Tau.Denom().Int64() < 0 || + p.Tau.Denom().Int64() > math.MaxUint32 { + return nil + } + // #nosec G115 return &cardano.PParams{ MaxTxSize: uint64(p.MaxTxSize), MinFeeCoefficient: uint64(p.MinFeeA), diff --git a/ledger/shelley/shelley.go b/ledger/shelley/shelley.go index a469d07a..92ebe7e7 100644 --- a/ledger/shelley/shelley.go +++ b/ledger/shelley/shelley.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. @@ -17,6 +17,7 @@ package shelley import ( "encoding/hex" "fmt" + "math" utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" @@ -97,6 +98,7 @@ func (b *ShelleyBlock) Era() common.Era { func (b *ShelleyBlock) Transactions() []common.Transaction { ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 for idx := range b.TransactionBodies { ret[idx] = &ShelleyTransaction{ Body: b.TransactionBodies[idx], @@ -403,6 +405,9 @@ func NewShelleyTransactionInput(hash string, idx int) ShelleyTransactionInput { if err != nil { panic(fmt.Sprintf("failed to decode transaction hash: %s", err)) } + if idx < 0 || idx > math.MaxUint32 { + panic("index out of range") + } return ShelleyTransactionInput{ TxId: common.Blake2b256(tmpHash), OutputIndex: uint32(idx), diff --git a/ledger/verify_block.go b/ledger/verify_block.go index f9009725..25d9978d 100644 --- a/ledger/verify_block.go +++ b/ledger/verify_block.go @@ -1,5 +1,5 @@ // Copyright 2024 Cardano Foundation -// 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. @@ -30,7 +30,7 @@ func VerifyBlock(block BlockHexCbor) (error, bool, string, uint64, uint64) { headerCborHex := block.HeaderCbor epochNonceHex := block.Eta0 bodyHex := block.BlockBodyCbor - slotPerKesPeriod := uint64(block.Spk) + slotPerKesPeriod := uint64(block.Spk) // #nosec G115 isValid := false vrfHex := "" @@ -76,7 +76,7 @@ func VerifyBlock(block BlockHexCbor) (error, bool, string, uint64, uint64) { } vrfBytes := header.Body.VrfKey[:] vrfResult := header.Body.VrfResult - seed := MkInputVrf(int64(header.Body.Slot), epochNonceByte) + seed := MkInputVrf(int64(header.Body.Slot), epochNonceByte) // #nosec G115 output, errVrf := VrfVerifyAndHash(vrfBytes, vrfResult.Proof, seed) if errVrf != nil { return fmt.Errorf( diff --git a/ledger/verify_block_body.go b/ledger/verify_block_body.go index 839d45ad..f8eeea80 100644 --- a/ledger/verify_block_body.go +++ b/ledger/verify_block_body.go @@ -1,5 +1,5 @@ // Copyright 2024 Cardano Foundation -// 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. @@ -328,6 +328,7 @@ func CalculateBlockBodyHash(txsRaw [][]string) ([]byte, error) { auxBytesError.Error(), ) } + // #nosec G115 auxRawData = append(auxRawData, AuxData{ index: uint64(index), data: auxBytes, diff --git a/ledger/verify_kes.go b/ledger/verify_kes.go index a13c0be1..b90abf90 100644 --- a/ledger/verify_kes.go +++ b/ledger/verify_kes.go @@ -1,5 +1,5 @@ // Copyright 2024 Cardano Foundation -// 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. @@ -47,6 +47,9 @@ type SumXKesSig struct { func NewSumKesFromByte(depth uint64, fromByte []byte) SumXKesSig { kesSize := SIGMA_SIZE + depth*(PUBLIC_KEY_SIZE*2) + if kesSize > math.MaxInt { + panic("kes size too large") + } if len(fromByte) != int(kesSize) { panic("length not match") } diff --git a/ledger/verify_vrf.go b/ledger/verify_vrf.go index 09d671d8..2a77748a 100644 --- a/ledger/verify_vrf.go +++ b/ledger/verify_vrf.go @@ -1,5 +1,5 @@ // Copyright 2024 Cardano Foundation -// 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. @@ -38,7 +38,7 @@ const ( func MkInputVrf(slot int64, eta0 []byte) []byte { // Ref: https://github.com/IntersectMBO/ouroboros-consensus/blob/de74882102236fdc4dd25aaa2552e8b3e208448c/ouroboros-consensus-protocol/src/ouroboros-consensus-protocol/Ouroboros/Consensus/Protocol/Praos/VRF.hs#L60 concat := make([]byte, 8+32) - binary.BigEndian.PutUint64(concat[:8], uint64(slot)) + binary.BigEndian.PutUint64(concat[:8], uint64(slot)) // #nosec G115 copy(concat[8:], eta0) h, err := blake2b.New(32, nil) if err != nil {