Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVM: Implement lsig size pooling #6057

Merged
merged 22 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ec90b93
Implement lsig size pooling
giuliop Jul 2, 2024
a2e7f4d
Merge remote-tracking branch 'upstream/master' into pool-max-logicSig…
giuliop Jul 10, 2024
129bcab
Merge remote-tracking branch 'upstream/master' into pool-max-logicSig…
giuliop Jul 21, 2024
bc74e17
Implement requested changes
giuliop Jul 21, 2024
72ffe79
Merge remote-tracking branch 'upstream/master' into pool-max-logicSig…
giuliop Jul 29, 2024
e6bcb26
Implement new max size for LogicSigMaxSize
giuliop Jul 29, 2024
8fa1b7f
Merge remote-tracking branch 'upstream/master' into pool-max-logicSig…
giuliop Aug 28, 2024
16793dc
Make goal more permissive when compiling logicsigs
giuliop Aug 28, 2024
16ef899
Implement max size for logicsig args of 4096 bytes
giuliop Aug 28, 2024
91d6e09
Make TxnTagMaxSize same as max block size
giuliop Aug 28, 2024
5a1eeaf
Revert "Make TxnTagMaxSize same as max block size"
giuliop Sep 9, 2024
11baff1
Merge remote-tracking branch 'upstream/master' into pool-max-logicSig…
giuliop Sep 9, 2024
39600e5
Update TestMaxSizesCorrect with logicsig pooling
giuliop Sep 9, 2024
4de5dd0
Don't test app/lsig max size in goal clerk compile
giuliop Sep 10, 2024
7953862
Add integration test for lsig size pooling
giuliop Sep 14, 2024
2265d17
Refactor
giuliop Sep 25, 2024
6206c38
Fix linter warnings
giuliop Oct 23, 2024
c3c2224
Make GenerateProgramOfSize accessible to other packages
giuliop Oct 23, 2024
1872212
Add unit test for lsig size
giuliop Oct 23, 2024
34d6079
Add unit test for lsig arg size
giuliop Oct 23, 2024
f0b4a1e
Fix typo in comments
giuliop Oct 23, 2024
0b5564e
Merge remote-tracking branch 'upstream/master' into pool-max-logicSig…
giuliop Oct 23, 2024
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
13 changes: 11 additions & 2 deletions cmd/goal/clerk.go
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ func assembleFileImpl(fname string, printWarnings bool) *logic.OpStream {
reportErrorf(tealAppSize, fname, len(ops.Program), config.MaxAvailableAppProgramLen)
}
} else {
if uint64(len(ops.Program)) > params.LogicSigMaxSize {
if len(ops.Program) > config.MaxLogicSigMaxSize {
giuliop marked this conversation as resolved.
Show resolved Hide resolved
reportErrorf(tealLogicSigSize, fname, len(ops.Program), params.LogicSigMaxSize)
}
}
Expand Down Expand Up @@ -1179,14 +1179,19 @@ var dryrunCmd = &cobra.Command{
if timeStamp <= 0 {
timeStamp = time.Now().Unix()
}

lSigPooledSize := 0
for i, txn := range stxns {
if txn.Lsig.Blank() {
continue
}
if uint64(txn.Lsig.Len()) > params.LogicSigMaxSize {
lsigLen := txn.Lsig.Len()
lSigPooledSize += lsigLen
if !params.EnableLogicSigSizePooling && uint64(lsigLen) > params.LogicSigMaxSize {
reportErrorf("program size too large: %d > %d", len(txn.Lsig.Logic), params.LogicSigMaxSize)
}
ep := logic.NewSigEvalParams(stxns, &params, logic.NoHeaderLedger{})

err := logic.CheckSignature(i, ep)
if err != nil {
reportErrorf("program failed Check: %s", err)
Expand All @@ -1204,6 +1209,10 @@ var dryrunCmd = &cobra.Command{
fmt.Fprintf(os.Stdout, "ERROR: %s\n", err.Error())
}
}
lSigMaxPooledSize := len(stxns) * int(params.LogicSigMaxSize)
if params.EnableLogicSigSizePooling && lSigPooledSize > lSigMaxPooledSize {
reportErrorf("total lsigs size too large: %d > %d", lSigPooledSize, lSigMaxPooledSize)
}
giuliop marked this conversation as resolved.
Show resolved Hide resolved

},
}
Expand Down
12 changes: 9 additions & 3 deletions config/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ type ConsensusParams struct {
EnableAppCostPooling bool

// EnableLogicSigCostPooling specifies LogicSig budgets are pooled across a
// group. The total available is len(group) * LogicSigMaxCost)
// group. The total available is len(group) * LogicSigMaxCost
EnableLogicSigCostPooling bool

// EnableLogicSigSizePooling specifies LogicSig sizes are pooled across a
// group. The total available is len(group) * LogicSigMaxSize
EnableLogicSigSizePooling bool

// RewardUnit specifies the number of MicroAlgos corresponding to one reward
// unit.
//
Expand Down Expand Up @@ -228,7 +232,7 @@ type ConsensusParams struct {
// 0 for no support, otherwise highest version supported
LogicSigVersion uint64

// len(LogicSig.Logic) + len(LogicSig.Args[*]) must be less than this
// len(LogicSig.Logic) + len(LogicSig.Args[*]) must be less than this (unless pooling is enabled)
LogicSigMaxSize uint64

// sum of estimated op cost must be less than this
Expand Down Expand Up @@ -765,7 +769,7 @@ func checkSetAllocBounds(p ConsensusParams) {
checkSetMax(p.MaxAppProgramLen, &MaxStateDeltaKeys)
checkSetMax(p.MaxAppProgramLen, &MaxEvalDeltaAccounts)
checkSetMax(p.MaxAppProgramLen, &MaxAppProgramLen)
checkSetMax(int(p.LogicSigMaxSize), &MaxLogicSigMaxSize)
checkSetMax((int(p.LogicSigMaxSize) * p.MaxTxGroupSize), &MaxLogicSigMaxSize)
checkSetMax(p.MaxTxnNoteBytes, &MaxTxnNoteBytes)
checkSetMax(p.MaxTxGroupSize, &MaxTxGroupSize)
// MaxBytesKeyValueLen is max of MaxAppKeyLen and MaxAppBytesValueLen
Expand Down Expand Up @@ -1512,6 +1516,8 @@ func initConsensusProtocols() {

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

vFuture.EnableLogicSigSizePooling = true

vFuture.Payouts.Enabled = true
vFuture.Payouts.Percent = 75
vFuture.Payouts.GoOnlineFee = 2_000_000 // 2 algos
Expand Down
2 changes: 1 addition & 1 deletion data/transactions/logicsig.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type LogicSig struct {
Msig crypto.MultisigSig `codec:"msig"`

// Args are not signed, but checked by Logic
Args [][]byte `codec:"arg,allocbound=EvalMaxArgs,allocbound=config.MaxLogicSigMaxSize"`
Args [][]byte `codec:"arg,allocbound=EvalMaxArgs,allocbound=config.MaxLogicSigMaxSize,maxtotalbytes=config.MaxLogicSigMaxSize"`
}

// Blank returns true if there is no content in this LogicSig
Expand Down
2 changes: 1 addition & 1 deletion data/transactions/msgp_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 16 additions & 3 deletions data/transactions/verify/txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ type TxGroupErrorReason int
const (
// TxGroupErrorReasonGeneric is a generic (not tracked) reason code
TxGroupErrorReasonGeneric TxGroupErrorReason = iota
// TxGroupErrorReasonNotWellFormed is txn.WellFormed failure
// TxGroupErrorReasonNotWellFormed is txn.WellFormed failure or malformed logic signature
TxGroupErrorReasonNotWellFormed
// TxGroupErrorReasonInvalidFee is invalid fee pooling in transaction group
TxGroupErrorReasonInvalidFee
Expand Down Expand Up @@ -214,6 +214,7 @@ func txnGroupBatchPrep(stxs []transactions.SignedTxn, contextHdr *bookkeeping.Bl

minFeeCount := uint64(0)
feesPaid := uint64(0)
lSigPooledSize := 0
for i, stxn := range stxs {
prepErr := txnBatchPrep(i, groupCtx, verifier)
if prepErr != nil {
Expand All @@ -225,6 +226,18 @@ func txnGroupBatchPrep(stxs []transactions.SignedTxn, contextHdr *bookkeeping.Bl
minFeeCount++
}
feesPaid = basics.AddSaturate(feesPaid, stxn.Txn.Fee.Raw)
lSigPooledSize += stxn.Lsig.Len()
}
if groupCtx.consensusParams.EnableLogicSigSizePooling {
lSigMaxPooledSize := len(stxs) * int(groupCtx.consensusParams.LogicSigMaxSize)
if lSigPooledSize > lSigMaxPooledSize {
errorMsg := fmt.Sprintf(
"txgroup had %d bytes of LogicSigs, more than the available pool of %d bytes",
lSigPooledSize, lSigMaxPooledSize,
)
err = &TxGroupError{err: errors.New(errorMsg), GroupIndex: -1, Reason: TxGroupErrorReasonNotWellFormed}
giuliop marked this conversation as resolved.
Show resolved Hide resolved
return nil, err
}
}
feeNeeded, overflow := basics.OMul(groupCtx.consensusParams.MinTxnFee, minFeeCount)
if overflow {
Expand Down Expand Up @@ -361,8 +374,8 @@ func logicSigSanityCheckBatchPrep(gi int, groupCtx *GroupContext, batchVerifier
if version > groupCtx.consensusParams.LogicSigVersion {
return errors.New("LogicSig.Logic version too new")
}
if uint64(lsig.Len()) > groupCtx.consensusParams.LogicSigMaxSize {
return errors.New("LogicSig.Logic too long")
if !groupCtx.consensusParams.EnableLogicSigSizePooling && uint64(lsig.Len()) > groupCtx.consensusParams.LogicSigMaxSize {
giuliop marked this conversation as resolved.
Show resolved Hide resolved
return errors.New("LogicSig too long")
}

err := logic.CheckSignature(gi, groupCtx.evalParams)
Expand Down
2 changes: 1 addition & 1 deletion protocol/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const TopicMsgRespTagMaxSize = 6 * 1024 * 1024
// TxnTagMaxSize is the maximum size of a TxnTag message. This is equal to SignedTxnMaxSize()
// which is size of just a single message containing maximum Stateproof. Since Stateproof
// transactions can't be batched we don't need to multiply by MaxTxnBatchSize.
const TxnTagMaxSize = 4620031
const TxnTagMaxSize = 4394756

// UniEnsBlockReqTagMaxSize is the maximum size of a UniEnsBlockReqTag message
const UniEnsBlockReqTagMaxSize = 67
Expand Down