Skip to content

Commit

Permalink
feat: track and apply on-chain pparam updates (#201)
Browse files Browse the repository at this point in the history
  • Loading branch information
agaffney authored Oct 30, 2024
1 parent 6a7701d commit 91abb82
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 31 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.22
toolchain go1.22.6

require (
github.com/blinklabs-io/gouroboros v0.103.0
github.com/blinklabs-io/gouroboros v0.103.1
github.com/blinklabs-io/ouroboros-mock v0.3.5
github.com/dgraph-io/badger/v4 v4.3.1
github.com/glebarez/sqlite v1.11.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blinklabs-io/gouroboros v0.103.0 h1:mA/RJ7CeZEE41RQNeMoip/2BbcB1WC2O8Nd+92m4vHY=
github.com/blinklabs-io/gouroboros v0.103.0/go.mod h1:wjiNCbZ2uQy9DGfLCgEgqagHxNBAv5UYsOdRBgoi3SU=
github.com/blinklabs-io/gouroboros v0.103.1 h1:D/3Hlr09kw/cYM8gt6t7jVlTfDCXjb25nHL5V2l/3kc=
github.com/blinklabs-io/gouroboros v0.103.1/go.mod h1:wjiNCbZ2uQy9DGfLCgEgqagHxNBAv5UYsOdRBgoi3SU=
github.com/blinklabs-io/ouroboros-mock v0.3.5 h1:/KWbSoH8Pjrd9uxOH7mVbI7XFsDCNW/O9FtLlvJDUpQ=
github.com/blinklabs-io/ouroboros-mock v0.3.5/go.mod h1:JtUQ3Luo22hCnGBxuxNp6JaUx63VxidxWwmcaVMremw=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
Expand Down
31 changes: 27 additions & 4 deletions state/eras/allegra.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
)

var AllegraEraDesc = EraDesc{
Id: allegra.EraIdAllegra,
Name: allegra.EraNameAllegra,
DecodePParamsFunc: DecodePParamsAllegra,
HardForkFunc: HardForkAllegra,
Id: allegra.EraIdAllegra,
Name: allegra.EraNameAllegra,
DecodePParamsFunc: DecodePParamsAllegra,
DecodePParamsUpdateFunc: DecodePParamsUpdateAllegra,
PParamsUpdateFunc: PParamsUpdateAllegra,
HardForkFunc: HardForkAllegra,
}

func DecodePParamsAllegra(data []byte) (any, error) {
Expand All @@ -38,6 +40,27 @@ func DecodePParamsAllegra(data []byte) (any, error) {
return ret, nil
}

func DecodePParamsUpdateAllegra(data []byte) (any, error) {
var ret allegra.AllegraProtocolParameterUpdate
if _, err := cbor.Decode(data, &ret); err != nil {
return nil, err
}
return ret, nil
}

func PParamsUpdateAllegra(currentPParams any, pparamsUpdate any) (any, error) {
allegraPParams, ok := currentPParams.(allegra.AllegraProtocolParameters)
if !ok {
return nil, fmt.Errorf("current PParams (%T) is not expected type", currentPParams)
}
allegraPParamsUpdate, ok := pparamsUpdate.(allegra.AllegraProtocolParameterUpdate)
if !ok {
return nil, fmt.Errorf("PParams update (%T) is not expected type", pparamsUpdate)
}
allegraPParams.Update(&allegraPParamsUpdate)
return allegraPParams, nil
}

func HardForkAllegra(nodeConfig *cardano.CardanoNodeConfig, prevPParams any) (any, error) {
shelleyPParams, ok := prevPParams.(shelley.ShelleyProtocolParameters)
if !ok {
Expand Down
31 changes: 27 additions & 4 deletions state/eras/alonzo.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
)

var AlonzoEraDesc = EraDesc{
Id: alonzo.EraIdAlonzo,
Name: alonzo.EraNameAlonzo,
DecodePParamsFunc: DecodePParamsAlonzo,
HardForkFunc: HardForkAlonzo,
Id: alonzo.EraIdAlonzo,
Name: alonzo.EraNameAlonzo,
DecodePParamsFunc: DecodePParamsAlonzo,
DecodePParamsUpdateFunc: DecodePParamsUpdateAlonzo,
PParamsUpdateFunc: PParamsUpdateAlonzo,
HardForkFunc: HardForkAlonzo,
}

func DecodePParamsAlonzo(data []byte) (any, error) {
Expand All @@ -38,6 +40,27 @@ func DecodePParamsAlonzo(data []byte) (any, error) {
return ret, nil
}

func DecodePParamsUpdateAlonzo(data []byte) (any, error) {
var ret alonzo.AlonzoProtocolParameterUpdate
if _, err := cbor.Decode(data, &ret); err != nil {
return nil, err
}
return ret, nil
}

func PParamsUpdateAlonzo(currentPParams any, pparamsUpdate any) (any, error) {
alonzoPParams, ok := currentPParams.(alonzo.AlonzoProtocolParameters)
if !ok {
return nil, fmt.Errorf("current PParams (%T) is not expected type", currentPParams)
}
alonzoPParamsUpdate, ok := pparamsUpdate.(alonzo.AlonzoProtocolParameterUpdate)
if !ok {
return nil, fmt.Errorf("PParams update (%T) is not expected type", pparamsUpdate)
}
alonzoPParams.Update(&alonzoPParamsUpdate)
return alonzoPParams, nil
}

func HardForkAlonzo(nodeConfig *cardano.CardanoNodeConfig, prevPParams any) (any, error) {
maryPParams, ok := prevPParams.(mary.MaryProtocolParameters)
if !ok {
Expand Down
31 changes: 27 additions & 4 deletions state/eras/babbage.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
)

var BabbageEraDesc = EraDesc{
Id: babbage.EraIdBabbage,
Name: babbage.EraNameBabbage,
DecodePParamsFunc: DecodePParamsBabbage,
HardForkFunc: HardForkBabbage,
Id: babbage.EraIdBabbage,
Name: babbage.EraNameBabbage,
DecodePParamsFunc: DecodePParamsBabbage,
DecodePParamsUpdateFunc: DecodePParamsUpdateBabbage,
PParamsUpdateFunc: PParamsUpdateBabbage,
HardForkFunc: HardForkBabbage,
}

func DecodePParamsBabbage(data []byte) (any, error) {
Expand All @@ -38,6 +40,27 @@ func DecodePParamsBabbage(data []byte) (any, error) {
return ret, nil
}

func DecodePParamsUpdateBabbage(data []byte) (any, error) {
var ret babbage.BabbageProtocolParameterUpdate
if _, err := cbor.Decode(data, &ret); err != nil {
return nil, err
}
return ret, nil
}

func PParamsUpdateBabbage(currentPParams any, pparamsUpdate any) (any, error) {
babbagePParams, ok := currentPParams.(babbage.BabbageProtocolParameters)
if !ok {
return nil, fmt.Errorf("current PParams (%T) is not expected type", currentPParams)
}
babbagePParamsUpdate, ok := pparamsUpdate.(babbage.BabbageProtocolParameterUpdate)
if !ok {
return nil, fmt.Errorf("PParams update (%T) is not expected type", pparamsUpdate)
}
babbagePParams.Update(&babbagePParamsUpdate)
return babbagePParams, nil
}

func HardForkBabbage(nodeConfig *cardano.CardanoNodeConfig, prevPParams any) (any, error) {
alonzoPParams, ok := prevPParams.(alonzo.AlonzoProtocolParameters)
if !ok {
Expand Down
31 changes: 27 additions & 4 deletions state/eras/conway.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
)

var ConwayEraDesc = EraDesc{
Id: conway.EraIdConway,
Name: conway.EraNameConway,
DecodePParamsFunc: DecodePParamsConway,
HardForkFunc: HardForkConway,
Id: conway.EraIdConway,
Name: conway.EraNameConway,
DecodePParamsFunc: DecodePParamsConway,
DecodePParamsUpdateFunc: DecodePParamsUpdateConway,
PParamsUpdateFunc: PParamsUpdateConway,
HardForkFunc: HardForkConway,
}

func DecodePParamsConway(data []byte) (any, error) {
Expand All @@ -38,6 +40,27 @@ func DecodePParamsConway(data []byte) (any, error) {
return ret, nil
}

func DecodePParamsUpdateConway(data []byte) (any, error) {
var ret conway.ConwayProtocolParameterUpdate
if _, err := cbor.Decode(data, &ret); err != nil {
return nil, err
}
return ret, nil
}

func PParamsUpdateConway(currentPParams any, pparamsUpdate any) (any, error) {
conwayPParams, ok := currentPParams.(conway.ConwayProtocolParameters)
if !ok {
return nil, fmt.Errorf("current PParams (%T) is not expected type", currentPParams)
}
conwayPParamsUpdate, ok := pparamsUpdate.(conway.ConwayProtocolParameterUpdate)
if !ok {
return nil, fmt.Errorf("PParams update (%T) is not expected type", pparamsUpdate)
}
conwayPParams.Update(&conwayPParamsUpdate)
return conwayPParams, nil
}

func HardForkConway(nodeConfig *cardano.CardanoNodeConfig, prevPParams any) (any, error) {
babbagePParams, ok := prevPParams.(babbage.BabbageProtocolParameters)
if !ok {
Expand Down
10 changes: 6 additions & 4 deletions state/eras/eras.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ package eras
import "github.com/blinklabs-io/node/config/cardano"

type EraDesc struct {
Id uint
Name string
DecodePParamsFunc func([]byte) (any, error)
HardForkFunc func(*cardano.CardanoNodeConfig, any) (any, error)
Id uint
Name string
DecodePParamsFunc func([]byte) (any, error)
DecodePParamsUpdateFunc func([]byte) (any, error)
PParamsUpdateFunc func(any, any) (any, error)
HardForkFunc func(*cardano.CardanoNodeConfig, any) (any, error)
}

var Eras = []EraDesc{
Expand Down
31 changes: 27 additions & 4 deletions state/eras/mary.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
)

var MaryEraDesc = EraDesc{
Id: mary.EraIdMary,
Name: mary.EraNameMary,
DecodePParamsFunc: DecodePParamsMary,
HardForkFunc: HardForkMary,
Id: mary.EraIdMary,
Name: mary.EraNameMary,
DecodePParamsFunc: DecodePParamsMary,
DecodePParamsUpdateFunc: DecodePParamsUpdateMary,
PParamsUpdateFunc: PParamsUpdateMary,
HardForkFunc: HardForkMary,
}

func DecodePParamsMary(data []byte) (any, error) {
Expand All @@ -38,6 +40,27 @@ func DecodePParamsMary(data []byte) (any, error) {
return ret, nil
}

func DecodePParamsUpdateMary(data []byte) (any, error) {
var ret mary.MaryProtocolParameterUpdate
if _, err := cbor.Decode(data, &ret); err != nil {
return nil, err
}
return ret, nil
}

func PParamsUpdateMary(currentPParams any, pparamsUpdate any) (any, error) {
maryPParams, ok := currentPParams.(mary.MaryProtocolParameters)
if !ok {
return nil, fmt.Errorf("current PParams (%T) is not expected type", currentPParams)
}
maryPParamsUpdate, ok := pparamsUpdate.(mary.MaryProtocolParameterUpdate)
if !ok {
return nil, fmt.Errorf("PParams update (%T) is not expected type", pparamsUpdate)
}
maryPParams.Update(&maryPParamsUpdate)
return maryPParams, nil
}

func HardForkMary(nodeConfig *cardano.CardanoNodeConfig, prevPParams any) (any, error) {
allegraPParams, ok := prevPParams.(allegra.AllegraProtocolParameters)
if !ok {
Expand Down
33 changes: 29 additions & 4 deletions state/eras/shelley.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
package eras

import (
"fmt"

"github.com/blinklabs-io/gouroboros/cbor"
"github.com/blinklabs-io/gouroboros/ledger/shelley"
"github.com/blinklabs-io/node/config/cardano"
)

var ShelleyEraDesc = EraDesc{
Id: shelley.EraIdShelley,
Name: shelley.EraNameShelley,
DecodePParamsFunc: DecodePParamsShelley,
HardForkFunc: HardForkShelley,
Id: shelley.EraIdShelley,
Name: shelley.EraNameShelley,
DecodePParamsFunc: DecodePParamsShelley,
DecodePParamsUpdateFunc: DecodePParamsUpdateShelley,
PParamsUpdateFunc: PParamsUpdateShelley,
HardForkFunc: HardForkShelley,
}

func DecodePParamsShelley(data []byte) (any, error) {
Expand All @@ -35,6 +39,27 @@ func DecodePParamsShelley(data []byte) (any, error) {
return ret, nil
}

func DecodePParamsUpdateShelley(data []byte) (any, error) {
var ret shelley.ShelleyProtocolParameterUpdate
if _, err := cbor.Decode(data, &ret); err != nil {
return nil, err
}
return ret, nil
}

func PParamsUpdateShelley(currentPParams any, pparamsUpdate any) (any, error) {
shelleyPParams, ok := currentPParams.(shelley.ShelleyProtocolParameters)
if !ok {
return nil, fmt.Errorf("current PParams (%T) is not expected type", currentPParams)
}
shelleyPParamsUpdate, ok := pparamsUpdate.(shelley.ShelleyProtocolParameterUpdate)
if !ok {
return nil, fmt.Errorf("PParams update (%T) is not expected type", pparamsUpdate)
}
shelleyPParams.Update(&shelleyPParamsUpdate)
return shelleyPParams, nil
}

func HardForkShelley(nodeConfig *cardano.CardanoNodeConfig, prevPParams any) (any, error) {
// There's no Byron protocol parameters to upgrade from, so this is mostly
// a dummy call for consistency
Expand Down
43 changes: 43 additions & 0 deletions state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,49 @@ func (ls *LedgerState) handleEventChainSyncBlock(e ChainsyncEvent) error {
if e.Point.Slot > ls.currentEpoch.StartSlot+uint64(
ls.currentEpoch.LengthInSlots,
) {
// Check for pparam updates that apply at the end of the epoch
var pparamUpdates []models.PParamUpdate
result := txn.Metadata().Where("epoch = ?", ls.currentEpoch.EpochId).Order("id DESC").Find(&pparamUpdates)
if result.Error != nil {
return result.Error
}
if len(pparamUpdates) > 0 {
// We only want the latest for the epoch
pparamUpdate := pparamUpdates[0]
if eras.Eras[ls.currentEraId].DecodePParamsUpdateFunc != nil {
tmpPParamUpdate, err := eras.Eras[ls.currentEraId].DecodePParamsUpdateFunc(pparamUpdate.Cbor)
if err != nil {
return err
}
if eras.Eras[ls.currentEraId].PParamsUpdateFunc != nil {
// Update current pparams
newPParams, err := eras.Eras[ls.currentEraId].PParamsUpdateFunc(ls.currentPParams, tmpPParamUpdate)
if err != nil {
return err
}
ls.currentPParams = newPParams
ls.config.Logger.Debug(
"updated protocol params",
"pparams",
fmt.Sprintf("%#v", ls.currentPParams),
)
// Write pparams update to DB
pparamsCbor, err := cbor.Encode(&ls.currentPParams)
if err != nil {
return err
}
tmpPParams := models.PParams{
AddedSlot: e.Point.Slot,
Epoch: ls.currentEpoch.EpochId + 1,
EraId: uint(ls.currentEraId),
Cbor: pparamsCbor,
}
if result := txn.Metadata().Create(&tmpPParams); result.Error != nil {
return result.Error
}
}
}
}
// Create next epoch record
newEpoch := models.Epoch{
EpochId: ls.currentEpoch.EpochId + 1,
Expand Down

0 comments on commit 91abb82

Please sign in to comment.