From b77192e2f0349a5eac6fe66cc262250cc21e283e Mon Sep 17 00:00:00 2001 From: Gary <982483+gmalouf@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:11:20 -0500 Subject: [PATCH] Consensus: Update consensus files for v39 along with types sync. (#621) * Update consensus files for v39 along with types sync. * Remove unused / linter violating msgp annotation in consensus.go. --- protocol/config/consensus.go | 86 +++++++++++++++++++++++++++++++----- protocol/consensus.go | 8 +++- types/applications.go | 2 +- types/asset.go | 6 +-- types/block.go | 15 +++---- types/genesis.go | 3 +- types/statedelta.go | 5 ++- 7 files changed, 96 insertions(+), 29 deletions(-) diff --git a/protocol/config/consensus.go b/protocol/config/consensus.go index 408dc9b8..94ce41be 100644 --- a/protocol/config/consensus.go +++ b/protocol/config/consensus.go @@ -588,6 +588,42 @@ var MaxAvailableAppProgramLen int // to be taken offline, that would be proposed to be taken offline. var MaxProposedExpiredOnlineAccounts int +// MaxAppTotalArgLen is the maximum number of bytes across all arguments of an application +// max sum([len(arg) for arg in txn.ApplicationArgs]) +var MaxAppTotalArgLen int + +// MaxAssetNameBytes is the maximum asset name length in bytes +var MaxAssetNameBytes int + +// MaxAssetUnitNameBytes is the maximum asset unit name length in bytes +var MaxAssetUnitNameBytes int + +// MaxAssetURLBytes is the maximum asset URL length in bytes +var MaxAssetURLBytes int + +// MaxAppBytesValueLen is the maximum length of a bytes value used in an application's global or +// local key/value store +var MaxAppBytesValueLen int + +// MaxAppBytesKeyLen is the maximum length of a key used in an application's global or local +// key/value store +var MaxAppBytesKeyLen int + +// StateProofTopVoters is a bound on how many online accounts get to +// participate in forming the state proof, by including the +// top StateProofTopVoters accounts (by normalized balance) into the +// vector commitment. +var StateProofTopVoters int + +// MaxTxnBytesPerBlock determines the maximum number of bytes +// that transactions can take up in a block. Specifically, +// the sum of the lengths of encodings of each transaction +// in a block must not exceed MaxTxnBytesPerBlock. +var MaxTxnBytesPerBlock int + +// MaxAppTxnForeignApps is the max number of foreign apps per txn across all consensus versions +var MaxAppTxnForeignApps int + func checkSetMax(value int, curMax *int) { if value > *curMax { *curMax = value @@ -625,6 +661,19 @@ func checkSetAllocBounds(p ConsensusParams) { checkSetMax(p.MaxAppProgramLen, &MaxLogCalls) checkSetMax(p.MaxInnerTransactions*p.MaxTxGroupSize, &MaxInnerTransactionsPerDelta) checkSetMax(p.MaxProposedExpiredOnlineAccounts, &MaxProposedExpiredOnlineAccounts) + + // These bounds are exported to make them available to the msgp generator for calculating + // maximum valid message size for each message going across the wire. + checkSetMax(p.MaxAppTotalArgLen, &MaxAppTotalArgLen) + checkSetMax(p.MaxAssetNameBytes, &MaxAssetNameBytes) + checkSetMax(p.MaxAssetUnitNameBytes, &MaxAssetUnitNameBytes) + checkSetMax(p.MaxAssetURLBytes, &MaxAssetURLBytes) + checkSetMax(p.MaxAppBytesValueLen, &MaxAppBytesValueLen) + checkSetMax(p.MaxAppKeyLen, &MaxAppBytesKeyLen) + checkSetMax(int(p.StateProofTopVoters), &StateProofTopVoters) + checkSetMax(p.MaxTxnBytesPerBlock, &MaxTxnBytesPerBlock) + + checkSetMax(p.MaxAppTxnForeignApps, &MaxAppTxnForeignApps) } // DeepCopy creates a deep copy of a consensus protocols map. @@ -669,6 +718,9 @@ func (cp ConsensusProtocols) Merge(configurableConsensus ConsensusProtocols) Con 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. func initConsensusProtocols() { // WARNING: copying a ConsensusParams by value into a new variable // does not copy the ApprovedUpgrades map. Make sure that each new @@ -1242,22 +1294,34 @@ func initConsensusProtocols() { // for the sake of future manual calculations, we'll round that down a bit : v37.ApprovedUpgrades[protocol.ConsensusV38] = 10000 - // ConsensusFuture is used to test features that are implemented - // but not yet released in a production protocol version. - vFuture := v38 + v39 := v38 + v39.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{} - vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{} + v39.LogicSigVersion = 10 + v39.EnableLogicSigCostPooling = true + + v39.AgreementDeadlineTimeoutPeriod0 = 4 * time.Second + + v39.DynamicFilterTimeout = true - vFuture.LogicSigVersion = 10 // When moving this to a release, put a new higher LogicSigVersion here - vFuture.EnableLogicSigCostPooling = true + v39.StateProofBlockHashInLightHeader = true - vFuture.AgreementDeadlineTimeoutPeriod0 = 4 * time.Second + // For future upgrades, round times will likely be shorter so giving ourselves some buffer room + v39.MaxUpgradeWaitRounds = 250000 - vFuture.StateProofBlockHashInLightHeader = true + Consensus[protocol.ConsensusV39] = v39 + + // v38 can be upgraded to v39, with an update delay of 7d: + // 157000 = (7 * 24 * 60 * 60 / 3.3 round times currently) + // but our current max is 150000 so using that : + v38.ApprovedUpgrades[protocol.ConsensusV39] = 150000 + + // ConsensusFuture is used to test features that are implemented + // but not yet released in a production protocol version. + vFuture := v39 + vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{} - // Setting DynamicFilterTimeout in vFuture will impact e2e test performance - // by reducing round time. Hence, it is commented out for now. - // vFuture.DynamicFilterTimeout = true + vFuture.LogicSigVersion = 11 // When moving this to a release, put a new higher LogicSigVersion here Consensus[protocol.ConsensusFuture] = vFuture diff --git a/protocol/consensus.go b/protocol/consensus.go index 3a9e525d..aad06796 100644 --- a/protocol/consensus.go +++ b/protocol/consensus.go @@ -195,6 +195,12 @@ const ConsensusV38 = ConsensusVersion( "https://github.com/algorandfoundation/specs/tree/abd3d4823c6f77349fc04c3af7b1e99fe4df699f", ) +// ConsensusV39 enables dynamic filter timeouts, a deadline timeout of 4 seconds, +// TEAL v10 logicSig opcode budget pooling along with elliptic curve ops on some pairing friendly curves. +const ConsensusV39 = ConsensusVersion( + "https://github.com/algorandfoundation/specs/tree/925a46433742afb0b51bb939354bd907fa88bf95", +) + // ConsensusFuture is a protocol that should not appear in any production // network, but is used to test features before they are released. const ConsensusFuture = ConsensusVersion( @@ -224,7 +230,7 @@ const ConsensusVAlpha5 = ConsensusVersion("alpha5") // ConsensusCurrentVersion is the latest version and should be used // when a specific version is not provided. -const ConsensusCurrentVersion = ConsensusV38 +const ConsensusCurrentVersion = ConsensusV39 // Error is used to indicate that an unsupported protocol has been detected. type Error ConsensusVersion diff --git a/types/applications.go b/types/applications.go index fb9a5a94..b398f7cf 100644 --- a/types/applications.go +++ b/types/applications.go @@ -105,7 +105,7 @@ type ApplicationCallTxnFields struct { ApplicationID AppIndex `codec:"apid"` OnCompletion OnCompletion `codec:"apan"` - ApplicationArgs [][]byte `codec:"apaa,allocbound=encodedMaxApplicationArgs"` + ApplicationArgs [][]byte `codec:"apaa,allocbound=encodedMaxApplicationArgs,maxtotalbytes=config.MaxAppTotalArgLen"` Accounts []Address `codec:"apat,allocbound=encodedMaxAccounts"` ForeignApps []AppIndex `codec:"apfa,allocbound=encodedMaxForeignApps"` ForeignAssets []AssetIndex `codec:"apas,allocbound=encodedMaxForeignAssets"` diff --git a/types/asset.go b/types/asset.go index 3fa226ca..89e28426 100644 --- a/types/asset.go +++ b/types/asset.go @@ -40,14 +40,14 @@ type AssetParams struct { // UnitName specifies a hint for the name of a unit of // this asset. - UnitName string `codec:"un"` + UnitName string `codec:"un,allocbound=config.MaxAssetUnitNameBytes"` // AssetName specifies a hint for the name of the asset. - AssetName string `codec:"an"` + AssetName string `codec:"an,allocbound=config.MaxAssetNameBytes"` // URL specifies a URL where more information about the asset can be // retrieved - URL string `codec:"au"` + URL string `codec:"au,allocbound=config.MaxAssetURLBytes"` // MetadataHash specifies a commitment to some unspecified asset // metadata. The format of this metadata is up to the application. diff --git a/types/block.go b/types/block.go index 2e2a1f6c..213fa86c 100644 --- a/types/block.go +++ b/types/block.go @@ -23,7 +23,7 @@ type ( TimeStamp int64 `codec:"ts"` // Genesis ID to which this block belongs. - GenesisID string `codec:"gen"` + GenesisID string `codec:"gen,allocbound=config.MaxGenesisIDLen"` // Genesis hash to which this block belongs. GenesisHash Digest `codec:"gh"` @@ -79,14 +79,9 @@ type ( UpgradeState UpgradeVote - // TxnCounter counts the number of transactions committed in the - // ledger, from the time at which support for this feature was - // introduced. - // - // Specifically, TxnCounter is the number of the next transaction - // that will be committed after this block. It is 0 when no - // transactions have ever been committed (since TxnCounter - // started being supported). + // TxnCounter is the number of the next transaction that will be + // committed after this block. Genesis blocks can start at either + // 0 or 1000, depending on a consensus parameter (AppForbidLowResources). TxnCounter uint64 `codec:"tc"` // StateProofTracking tracks the status of the state proofs, potentially @@ -205,7 +200,7 @@ type ( // A Block contains the Payset and metadata corresponding to a given Round. Block struct { BlockHeader - Payset Payset `codec:"txns"` + Payset Payset `codec:"txns,maxtotalbytes=config.MaxTxnBytesPerBlock"` } // A Payset represents a common, unforgeable, consistent, ordered set of SignedTxn objects. diff --git a/types/genesis.go b/types/genesis.go index 7939b644..4e6ab066 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -70,8 +70,9 @@ type Account struct { Status byte `codec:"onl"` MicroAlgos uint64 `codec:"algo"` VoteID [32]byte `codec:"vote"` - SelectionID [32]byte `codec:"sel"` StateProofID [64]byte `codec:"stprf"` + SelectionID [32]byte `codec:"sel"` + VoteFirstValid uint64 `codec:"voteFst"` VoteLastValid uint64 `codec:"voteLst"` VoteKeyDilution uint64 `codec:"voteKD"` } diff --git a/types/statedelta.go b/types/statedelta.go index 54c71fb5..84c3a00c 100644 --- a/types/statedelta.go +++ b/types/statedelta.go @@ -313,8 +313,9 @@ type LedgerStateDelta struct { // new block header; read-only Hdr *BlockHeader - // next round for which we expect a state proof. - // zero if no state proof is expected. + // StateProofNext represents modification on StateProofNextRound field in the block header. If the block contains + // a valid state proof transaction, this field will contain the next round for state proof. + // otherwise it will be set to 0. StateProofNext Round // previous block timestamp