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
8 changes: 4 additions & 4 deletions agreement/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ type unauthenticatedBundle struct {
Step step `codec:"step"`
Proposal proposalValue `codec:"prop"`

Votes []voteAuthenticator `codec:"vote,allocbound=config.MaxVoteThreshold"`
EquivocationVotes []equivocationVoteAuthenticator `codec:"eqv,allocbound=config.MaxVoteThreshold"`
Votes []voteAuthenticator `codec:"vote,allocbound=bounds.MaxVoteThreshold"`
EquivocationVotes []equivocationVoteAuthenticator `codec:"eqv,allocbound=bounds.MaxVoteThreshold"`
}

// bundle is a set of votes, all from the same round, period, and step, and from distinct senders, that reaches quorum.
Expand All @@ -48,8 +48,8 @@ type bundle struct {

U unauthenticatedBundle `codec:"u"`

Votes []vote `codec:"vote,allocbound=config.MaxVoteThreshold"`
EquivocationVotes []equivocationVote `codec:"eqv,allocbound=config.MaxVoteThreshold"`
Votes []vote `codec:"vote,allocbound=bounds.MaxVoteThreshold"`
EquivocationVotes []equivocationVote `codec:"eqv,allocbound=bounds.MaxVoteThreshold"`
}

// voteAuthenticators omit the Round, Period, Step, and Proposal for compression
Expand Down
158 changes: 79 additions & 79 deletions agreement/msgp_gen.go

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions config/bounds/bounds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Copyright (C) 2019-2025 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// go-algorand is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.

package bounds

/* The bounds package is intended to hold conservative bounds on the sizes of
various messages. Many cannot be static, because they depend on consensus
parameters. They are set at runtime iterating over every consensus version
and selecting the largest bound. This allows msgpack parsing to safely
reject anything that NO consensus version would allow.
*/

// MaxVoteThreshold is the largest threshold for a bundle over all supported
// consensus protocols, used for decoding purposes.
var MaxVoteThreshold int

// MaxEvalDeltaAccounts is the largest number of accounts that may appear in an
// eval delta, used for decoding purposes.
var MaxEvalDeltaAccounts int

// MaxStateDeltaKeys is the largest number of key/value pairs that may appear in
// a StateDelta, used for decoding purposes.
var MaxStateDeltaKeys int

// MaxLogCalls is the highest allowable log messages that may appear in any
// version, used only for decoding purposes. Never decrease this value.
var MaxLogCalls int

// MaxInnerTransactionsPerDelta is the maximum number of inner transactions in
// one EvalDelta
var MaxInnerTransactionsPerDelta int

// MaxLogicSigMaxSize is the largest logical signature appear in any of the
// supported protocols, used for decoding purposes.
var MaxLogicSigMaxSize int

// MaxTxnNoteBytes is the largest supported nodes field array size supported by
// any of the consensus protocols. used for decoding purposes.
var MaxTxnNoteBytes int

// MaxTxGroupSize is the largest supported number of transactions per
// transaction group supported by any of the consensus protocols. used for
// decoding purposes.
var MaxTxGroupSize int

// MaxAppProgramLen is the largest supported app program size supported by any
// of the consensus protocols. used for decoding purposes.
var MaxAppProgramLen int

// MaxBytesKeyValueLen is a maximum length of key or value across all protocols.
// used for decoding purposes.
var MaxBytesKeyValueLen int

// MaxExtraAppProgramLen is the maximum extra app program length supported by
// any of the consensus protocols. used for decoding purposes.
var MaxExtraAppProgramLen int

// MaxAvailableAppProgramLen is the largest supported app program size including
// the extra pages supported by any of the consensus protocols. used for
// decoding purposes.
var MaxAvailableAppProgramLen int

// MaxProposedExpiredOnlineAccounts is the maximum number of online accounts
// that a proposer can take offline for having expired voting keys.
var MaxProposedExpiredOnlineAccounts int

// MaxMarkAbsent is the maximum number of online accounts that a proposer can
// suspend for not proposing "lately"
var MaxMarkAbsent 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

// MaxEvalDeltaTotalLogSize is the maximum size of the sum of all log sizes in a single eval delta.
const MaxEvalDeltaTotalLogSize = 1024

// MaxGenesisIDLen is the maximum length of the genesis ID set for purpose of
// setting allocbounds on structs containing GenesisID and for purposes of
// calculating MaxSize functions on those types. Current value is larger than
// the existing network IDs and the ones used in testing
const MaxGenesisIDLen = 128

// EncodedMaxAssetsPerAccount is the decoder limit of number of assets stored
// per account. it's being verified by the unit test
// TestEncodedAccountAllocationBounds to align with
// config.Consensus[protocol.ConsensusCurrentVersion].MaxAssetsPerAccount; note
// that the decoded parameter is used only for protecting the decoder against
// malicious encoded account data stream. protocol-specific contents would be
// tested once the decoding is complete.
const EncodedMaxAssetsPerAccount = 1024

// EncodedMaxAppLocalStates is the decoder limit for number of opted-in apps in a single account.
// It is verified in TestEncodedAccountAllocationBounds to align with
// config.Consensus[protocol.ConsensusCurrentVersion].MaxAppsOptedIn
const EncodedMaxAppLocalStates = 64

// EncodedMaxAppParams is the decoder limit for number of created apps in a single account.
// It is verified in TestEncodedAccountAllocationBounds to align with
// config.Consensus[protocol.ConsensusCurrentVersion].MaxAppsCreated
const EncodedMaxAppParams = 64

// EncodedMaxKeyValueEntries is the decoder limit for the length of a key/value store.
// It is verified in TestEncodedAccountAllocationBounds to align with
// config.Consensus[protocol.ConsensusCurrentVersion].MaxLocalSchemaEntries and
// config.Consensus[protocol.ConsensusCurrentVersion].MaxGlobalSchemaEntries
const EncodedMaxKeyValueEntries = 1024

// MaxConsensusVersionLen must be larger than any URL length of any consensus
// version (which is currently URL+hash=89)
const MaxConsensusVersionLen = 128
8 changes: 0 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,6 @@ const ConfigurableConsensusProtocolsFilename = "consensus.json"
// do not expose in normal config so it is not in code generated local_defaults.go
const defaultRelayGossipFanout = 8

// MaxGenesisIDLen is the maximum length of the genesis ID set for purpose of setting
// allocbounds on structs containing GenesisID and for purposes of calculating MaxSize functions
// on those types. Current value is larger than the existing network IDs and the ones used in testing
const MaxGenesisIDLen = 128

// MaxEvalDeltaTotalLogSize is the maximum size of the sum of all log sizes in a single eval delta.
const MaxEvalDeltaTotalLogSize = 1024

// CatchpointTrackingModeUntracked defines the CatchpointTracking mode that does _not_ track catchpoints
const CatchpointTrackingModeUntracked = -1

Expand Down
26 changes: 26 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/algorand/go-algorand/config/bounds"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
"github.com/algorand/go-algorand/util/codecs"
Expand Down Expand Up @@ -1170,3 +1171,28 @@ func TestTracksCatchpointsWithoutStoring(t *testing.T) {
require.Equal(t, true, cfg.TracksCatchpoints())
require.Equal(t, false, cfg.StoresCatchpoints())
}

func TestEncodedAccountAllocationBounds(t *testing.T) {
partitiontest.PartitionTest(t)

// ensure that all the supported protocols have value limits less or
// equal to their corresponding codec allocbounds
for protoVer, proto := range Consensus {
if proto.MaxAssetsPerAccount > 0 && proto.MaxAssetsPerAccount > bounds.EncodedMaxAssetsPerAccount {
require.Failf(t, "proto.MaxAssetsPerAccount > EncodedMaxAssetsPerAccount", "protocol version = %s", protoVer)
}
if proto.MaxAppsCreated > 0 && proto.MaxAppsCreated > bounds.EncodedMaxAppParams {
require.Failf(t, "proto.MaxAppsCreated > EncodedMaxAppParams", "protocol version = %s", protoVer)
}
if proto.MaxAppsOptedIn > 0 && proto.MaxAppsOptedIn > bounds.EncodedMaxAppLocalStates {
require.Failf(t, "proto.MaxAppsOptedIn > EncodedMaxAppLocalStates", "protocol version = %s", protoVer)
}
if proto.MaxLocalSchemaEntries > bounds.EncodedMaxKeyValueEntries {
require.Failf(t, "proto.MaxLocalSchemaEntries > EncodedMaxKeyValueEntries", "protocol version = %s", protoVer)
}
if proto.MaxGlobalSchemaEntries > bounds.EncodedMaxKeyValueEntries {
require.Failf(t, "proto.MaxGlobalSchemaEntries > EncodedMaxKeyValueEntries", "protocol version = %s", protoVer)
}
// There is no protocol limit to the number of Boxes per account, so that allocbound is not checked.
}
}
Loading
Loading