Skip to content

Commit 9c7e6c0

Browse files
authored
Types: Support Custom Consensus (#756)
* Support custom consensus loading in go-algorand-sdk. * Sync types from lastest export_sdk_types run.
1 parent 139091d commit 9c7e6c0

File tree

4 files changed

+134
-2
lines changed

4 files changed

+134
-2
lines changed

protocol/config/config.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package config
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
// ConfigurableConsensusProtocolsFilename defines a set of consensus protocols that
10+
// are to be loaded from the data directory ( if present ), to override the
11+
// built-in supported consensus protocols.
12+
const ConfigurableConsensusProtocolsFilename = "consensus.json"
13+
14+
// SaveConfigurableConsensus saves the configurable protocols file to the provided data directory.
15+
// if the params contains zero protocols, the existing consensus.json file will be removed if exists.
16+
func SaveConfigurableConsensus(dataDirectory string, params ConsensusProtocols) error {
17+
consensusProtocolPath := filepath.Join(dataDirectory, ConfigurableConsensusProtocolsFilename)
18+
19+
if len(params) == 0 {
20+
// we have no consensus params to write. In this case, just delete the existing file
21+
// ( if any )
22+
err := os.Remove(consensusProtocolPath)
23+
if os.IsNotExist(err) {
24+
return nil
25+
}
26+
return err
27+
}
28+
encodedConsensusParams, err := json.Marshal(params)
29+
if err != nil {
30+
return err
31+
}
32+
err = os.WriteFile(consensusProtocolPath, encodedConsensusParams, 0644)
33+
return err
34+
}
35+
36+
// PreloadConfigurableConsensusProtocols loads the configurable protocols from the data directory
37+
// and merge it with a copy of the Consensus map. Then, it returns it to the caller.
38+
func PreloadConfigurableConsensusProtocols(dataDirectory string) (ConsensusProtocols, error) {
39+
consensusProtocolPath := filepath.Join(dataDirectory, ConfigurableConsensusProtocolsFilename)
40+
file, err := os.Open(consensusProtocolPath)
41+
42+
if err != nil {
43+
if os.IsNotExist(err) {
44+
// this file is not required, only optional. if it's missing, no harm is done.
45+
return Consensus, nil
46+
}
47+
return nil, err
48+
}
49+
defer file.Close()
50+
51+
configurableConsensus := make(ConsensusProtocols)
52+
53+
decoder := json.NewDecoder(file)
54+
err = decoder.Decode(&configurableConsensus)
55+
if err != nil {
56+
return nil, err
57+
}
58+
return Consensus.Merge(configurableConsensus), nil
59+
}
60+
61+
// SetConfigurableConsensusProtocols sets the configurable protocols.
62+
func SetConfigurableConsensusProtocols(newConsensus ConsensusProtocols) ConsensusProtocols {
63+
oldConsensus := Consensus
64+
Consensus = newConsensus
65+
// Set allocation limits
66+
// checkSetAllocBounds not ported to sdk https://github.com/algorand/go-algorand/blob/e68b54e90cd9dc1b52c3a9df85e0aeb56e8206d5/config/consensus.go#L723
67+
// for _, p := range Consensus {
68+
// checkSetAllocBounds(p)
69+
// }
70+
return oldConsensus
71+
}
72+
73+
// LoadConfigurableConsensusProtocols loads the configurable protocols from the data directory
74+
func LoadConfigurableConsensusProtocols(dataDirectory string) error {
75+
newConsensus, err := PreloadConfigurableConsensusProtocols(dataDirectory)
76+
if err != nil {
77+
return err
78+
}
79+
if newConsensus != nil {
80+
SetConfigurableConsensusProtocols(newConsensus)
81+
}
82+
return nil
83+
}

protocol/config/consensus.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package config
22

33
import (
4+
"maps"
45
"time"
56

67
"github.com/algorand/go-algorand-sdk/v2/protocol"
@@ -558,6 +559,12 @@ type ConsensusParams struct {
558559
// available. This parameters can be removed and assumed true after the
559560
// first consensus release in which it is set true.
560561
EnableInnerClawbackWithoutSenderHolding bool
562+
563+
// AppSizeUpdates allows application update transactions to change
564+
// the extra-program-pages and global schema sizes. Since it enables newly
565+
// legal transactions, this parameter can be removed and assumed true after
566+
// the first consensus release in which it is set true.
567+
AppSizeUpdates bool
561568
}
562569

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

679+
// DeepCopy creates a deep copy of a consensus protocols map.
680+
func (cp ConsensusProtocols) DeepCopy() ConsensusProtocols {
681+
staticConsensus := make(ConsensusProtocols)
682+
for consensusVersion, consensusParams := range cp {
683+
// recreate the ApprovedUpgrades map since we don't want to modify the original one.
684+
consensusParams.ApprovedUpgrades = maps.Clone(consensusParams.ApprovedUpgrades)
685+
staticConsensus[consensusVersion] = consensusParams
686+
}
687+
return staticConsensus
688+
}
689+
690+
// Merge merges a configurable consensus on top of the existing consensus protocol and return
691+
// a new consensus protocol without modify any of the incoming structures.
692+
func (cp ConsensusProtocols) Merge(configurableConsensus ConsensusProtocols) ConsensusProtocols {
693+
staticConsensus := cp.DeepCopy()
694+
695+
for consensusVersion, consensusParams := range configurableConsensus {
696+
if consensusParams.ApprovedUpgrades == nil {
697+
// if we were provided with an empty ConsensusParams, delete the existing reference to this consensus version
698+
for cVer, cParam := range staticConsensus {
699+
if cVer == consensusVersion {
700+
delete(staticConsensus, cVer)
701+
} else {
702+
// delete upgrade to deleted version
703+
delete(cParam.ApprovedUpgrades, consensusVersion)
704+
}
705+
}
706+
} else {
707+
// need to add/update entry
708+
staticConsensus[consensusVersion] = consensusParams
709+
}
710+
}
711+
712+
return staticConsensus
713+
}
714+
672715
// initConsensusProtocols defines the consensus protocol values and how values change across different versions of the protocol.
673716
//
674717
// These are the only valid and tested consensus values and transitions. Other settings are not tested and may lead to unexpected behavior.
@@ -1331,6 +1374,8 @@ func initConsensusProtocols() {
13311374

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

1377+
vFuture.AppSizeUpdates = true
1378+
13341379
Consensus[protocol.ConsensusFuture] = vFuture
13351380

13361381
// vAlphaX versions are an separate series of consensus parameters and versions for alphanet

types/block.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ type BlockHeader struct {
8181
// Each block is associated with at most one active upgrade proposal
8282
// (a new version of the protocol). An upgrade proposal can be made
8383
// by a block proposer, as long as no other upgrade proposal is active.
84-
// The upgrade proposal lasts for many rounds (UpgradeVoteRounds), and
84+
// The upgrade proposal lasts for consensus.UpgradeVoteRounds, and
8585
// in each round, that round's block proposer votes to support (or not)
8686
// the proposed upgrade.
8787
//
@@ -202,7 +202,7 @@ type UpgradeState struct {
202202
NextProtocol string `codec:"nextproto"`
203203
// NextProtocolApprovals is the number of approvals for the next protocol proposal. It is expressed in Round because it is a count of rounds.
204204
NextProtocolApprovals Round `codec:"nextyes"`
205-
// NextProtocolVoteBefore specify the last voting round for the next protocol proposal. If there is no voting for
205+
// NextProtocolVoteBefore specifies the last voting round for the next protocol proposal. If there is no voting for
206206
// an upgrade taking place, this would be zero.
207207
NextProtocolVoteBefore Round `codec:"nextbefore"`
208208
// NextProtocolSwitchOn specify the round number at which the next protocol would be adopted. If there is no upgrade taking place,

types/statedelta.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ type AppParams struct {
6161
StateSchemas
6262
ExtraProgramPages uint32 `codec:"epp"`
6363
Version uint64 `codec:"v"`
64+
65+
// SizeSponsor, if non-zero, is the account that must hold MBR for
66+
// extra program pages, and the global schema.
67+
SizeSponsor Address `codec:"ss"`
6468
}
6569

6670
// AppLocalState stores the LocalState associated with an application. It also

0 commit comments

Comments
 (0)