Skip to content

ExtraProgramPages not usable after Creation #2431

@jeapostrophe

Description

@jeapostrophe

You can set ExtraProgramPages to something greater than 0 at creation time, but you can't update an application and use extra space you allocated

If you look at this code:

if tx.ExtraProgramPages != 0 {
return fmt.Errorf("tx.ExtraProgramPages is immutable")
}
}
// Limit total number of arguments
if len(tx.ApplicationArgs) > proto.MaxAppArgs {
return fmt.Errorf("too many application args, max %d", proto.MaxAppArgs)
}
// Sum up argument lengths
var argSum uint64
for _, arg := range tx.ApplicationArgs {
argSum = basics.AddSaturate(argSum, uint64(len(arg)))
}
// Limit total length of all arguments
if argSum > uint64(proto.MaxAppTotalArgLen) {
return fmt.Errorf("application args total length too long, max len %d bytes", proto.MaxAppTotalArgLen)
}
// Limit number of accounts referred to in a single ApplicationCall
if len(tx.Accounts) > proto.MaxAppTxnAccounts {
return fmt.Errorf("tx.Accounts too long, max number of accounts is %d", proto.MaxAppTxnAccounts)
}
// Limit number of other app global states referred to
if len(tx.ForeignApps) > proto.MaxAppTxnForeignApps {
return fmt.Errorf("tx.ForeignApps too long, max number of foreign apps is %d", proto.MaxAppTxnForeignApps)
}
if len(tx.ForeignAssets) > proto.MaxAppTxnForeignAssets {
return fmt.Errorf("tx.ForeignAssets too long, max number of foreign assets is %d", proto.MaxAppTxnForeignAssets)
}
// Limit the sum of all types of references that bring in account records
if len(tx.Accounts)+len(tx.ForeignApps)+len(tx.ForeignAssets) > proto.MaxAppTotalTxnReferences {
return fmt.Errorf("tx has too many references, max is %d", proto.MaxAppTotalTxnReferences)
}
if tx.ExtraProgramPages > uint32(proto.MaxExtraAppProgramPages) {
return fmt.Errorf("tx.ExtraProgramPages too large, max number of extra pages is %d", proto.MaxExtraAppProgramPages)
}
lap := len(tx.ApprovalProgram)
lcs := len(tx.ClearStateProgram)
pages := int(1 + tx.ExtraProgramPages)
if lap > pages*proto.MaxAppProgramLen {
return fmt.Errorf("approval program too long. max len %d bytes", pages*proto.MaxAppProgramLen)
}
if lcs > pages*proto.MaxAppProgramLen {
return fmt.Errorf("clear state program too long. max len %d bytes", pages*proto.MaxAppProgramLen)
}
if lap+lcs > pages*proto.MaxAppTotalProgramLen {
return fmt.Errorf("app programs too long. max total len %d bytes", pages*proto.MaxAppTotalProgramLen)
}

You can see that

  • L348 - is true when you are updating
  • L353 - guarantees that tx.ExtraProgramPages is 0
  • L399 - is 0 because of above
  • L406 - is going to be true (i.e. error) because of that

I believe that this is not a problem when you are not updating (i.e. when you are calling) because tx.ApprovalProgram and tx.ClearProgram are expected to be 0 since they aren't being updated.

I believe that the fix is to look up the actual application ExtraProgramPages when you aren't updating and use the stored value

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions