Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions protocol/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package config

import (
"encoding/json"
"os"
"path/filepath"
)

// ConfigurableConsensusProtocolsFilename defines a set of consensus protocols that
// are to be loaded from the data directory ( if present ), to override the
// built-in supported consensus protocols.
const ConfigurableConsensusProtocolsFilename = "consensus.json"

// SaveConfigurableConsensus saves the configurable protocols file to the provided data directory.
// if the params contains zero protocols, the existing consensus.json file will be removed if exists.
func SaveConfigurableConsensus(dataDirectory string, params ConsensusProtocols) error {
consensusProtocolPath := filepath.Join(dataDirectory, ConfigurableConsensusProtocolsFilename)

if len(params) == 0 {
// we have no consensus params to write. In this case, just delete the existing file
// ( if any )
err := os.Remove(consensusProtocolPath)
if os.IsNotExist(err) {
return nil
}
return err
}
encodedConsensusParams, err := json.Marshal(params)
if err != nil {
return err
}
err = os.WriteFile(consensusProtocolPath, encodedConsensusParams, 0644)
return err
}

// PreloadConfigurableConsensusProtocols loads the configurable protocols from the data directory
// and merge it with a copy of the Consensus map. Then, it returns it to the caller.
func PreloadConfigurableConsensusProtocols(dataDirectory string) (ConsensusProtocols, error) {
consensusProtocolPath := filepath.Join(dataDirectory, ConfigurableConsensusProtocolsFilename)
file, err := os.Open(consensusProtocolPath)

if err != nil {
if os.IsNotExist(err) {
// this file is not required, only optional. if it's missing, no harm is done.
return Consensus, nil
}
return nil, err
}
defer file.Close()

configurableConsensus := make(ConsensusProtocols)

decoder := json.NewDecoder(file)
err = decoder.Decode(&configurableConsensus)
if err != nil {
return nil, err
}
return Consensus.Merge(configurableConsensus), nil
}

// SetConfigurableConsensusProtocols sets the configurable protocols.
func SetConfigurableConsensusProtocols(newConsensus ConsensusProtocols) ConsensusProtocols {
oldConsensus := Consensus
Consensus = newConsensus
// Set allocation limits
// checkSetAllocBounds not ported to sdk https://github.com/algorand/go-algorand/blob/e68b54e90cd9dc1b52c3a9df85e0aeb56e8206d5/config/consensus.go#L723
// for _, p := range Consensus {
// checkSetAllocBounds(p)
// }
return oldConsensus
}

// LoadConfigurableConsensusProtocols loads the configurable protocols from the data directory
func LoadConfigurableConsensusProtocols(dataDirectory string) error {
newConsensus, err := PreloadConfigurableConsensusProtocols(dataDirectory)
if err != nil {
return err
}
if newConsensus != nil {
SetConfigurableConsensusProtocols(newConsensus)
}
return nil
}
45 changes: 45 additions & 0 deletions protocol/config/consensus.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"maps"
"time"

"github.com/algorand/go-algorand-sdk/v2/protocol"
Expand Down Expand Up @@ -558,6 +559,12 @@ type ConsensusParams struct {
// available. This parameters can be removed and assumed true after the
// first consensus release in which it is set true.
EnableInnerClawbackWithoutSenderHolding bool

// AppSizeUpdates allows application update transactions to change
// the extra-program-pages and global schema sizes. Since it enables newly
// legal transactions, this parameter can be removed and assumed true after
// the first consensus release in which it is set true.
AppSizeUpdates bool
}

// ProposerPayoutRules puts several related consensus parameters in one place. The same
Expand Down Expand Up @@ -669,6 +676,42 @@ type ConsensusProtocols map[protocol.ConsensusVersion]ConsensusParams
// consensus protocol.
var Consensus ConsensusProtocols

// DeepCopy creates a deep copy of a consensus protocols map.
func (cp ConsensusProtocols) DeepCopy() ConsensusProtocols {
staticConsensus := make(ConsensusProtocols)
for consensusVersion, consensusParams := range cp {
// recreate the ApprovedUpgrades map since we don't want to modify the original one.
consensusParams.ApprovedUpgrades = maps.Clone(consensusParams.ApprovedUpgrades)
staticConsensus[consensusVersion] = consensusParams
}
return staticConsensus
}

// Merge merges a configurable consensus on top of the existing consensus protocol and return
// a new consensus protocol without modify any of the incoming structures.
func (cp ConsensusProtocols) Merge(configurableConsensus ConsensusProtocols) ConsensusProtocols {
staticConsensus := cp.DeepCopy()

for consensusVersion, consensusParams := range configurableConsensus {
if consensusParams.ApprovedUpgrades == nil {
// if we were provided with an empty ConsensusParams, delete the existing reference to this consensus version
for cVer, cParam := range staticConsensus {
if cVer == consensusVersion {
delete(staticConsensus, cVer)
} else {
// delete upgrade to deleted version
delete(cParam.ApprovedUpgrades, consensusVersion)
}
}
} else {
// need to add/update entry
staticConsensus[consensusVersion] = consensusParams
}
}

return staticConsensus
}

// initConsensusProtocols defines the consensus protocol values and how values change across different versions of the protocol.
//
// These are the only valid and tested consensus values and transitions. Other settings are not tested and may lead to unexpected behavior.
Expand Down Expand Up @@ -1331,6 +1374,8 @@ func initConsensusProtocols() {

vFuture.LogicSigVersion = 13 // When moving this to a release, put a new higher LogicSigVersion here

vFuture.AppSizeUpdates = true

Consensus[protocol.ConsensusFuture] = vFuture

// vAlphaX versions are an separate series of consensus parameters and versions for alphanet
Expand Down
4 changes: 2 additions & 2 deletions types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ type BlockHeader struct {
// Each block is associated with at most one active upgrade proposal
// (a new version of the protocol). An upgrade proposal can be made
// by a block proposer, as long as no other upgrade proposal is active.
// The upgrade proposal lasts for many rounds (UpgradeVoteRounds), and
// The upgrade proposal lasts for consensus.UpgradeVoteRounds, and
// in each round, that round's block proposer votes to support (or not)
// the proposed upgrade.
//
Expand Down Expand Up @@ -202,7 +202,7 @@ type UpgradeState struct {
NextProtocol string `codec:"nextproto"`
// NextProtocolApprovals is the number of approvals for the next protocol proposal. It is expressed in Round because it is a count of rounds.
NextProtocolApprovals Round `codec:"nextyes"`
// NextProtocolVoteBefore specify the last voting round for the next protocol proposal. If there is no voting for
// NextProtocolVoteBefore specifies the last voting round for the next protocol proposal. If there is no voting for
// an upgrade taking place, this would be zero.
NextProtocolVoteBefore Round `codec:"nextbefore"`
// NextProtocolSwitchOn specify the round number at which the next protocol would be adopted. If there is no upgrade taking place,
Expand Down
4 changes: 4 additions & 0 deletions types/statedelta.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ type AppParams struct {
StateSchemas
ExtraProgramPages uint32 `codec:"epp"`
Version uint64 `codec:"v"`

// SizeSponsor, if non-zero, is the account that must hold MBR for
// extra program pages, and the global schema.
SizeSponsor Address `codec:"ss"`
}

// AppLocalState stores the LocalState associated with an application. It also
Expand Down
Loading