algorand / go-algorand

Algorand's official implementation in Go.
https://developer.algorand.org/
Other
1.35k stars 471 forks source link

Increase max application program size beyond 8kb #6155

Open SilentRhetoric opened 6 hours ago

SilentRhetoric commented 6 hours ago

Status

The maximum program size for an application is currently 8kb. Once a contract is deployed, the program size is immutable.

This limit is currently constraining multiple builders in the ecosystem who have hit the limit and are using creative approaches to optimize program size. The limit could also constrain future upgradability of contracts that are deployed today with max program pages but may need to add additional logic in the future.

Expected

Raising the maximum program size would enable developers to create more capable applications on Algorand without resorting to contortive optimizations.

Solution

Increase the maximum program size substantively.

One approach that could be elegant is to align the max program size to the max box size, which is currently 32KB. This way, an app factory pattern could store program bytes in one box and use that to create new applications. If this approach was followed, any future expansions of the box storage limit would also apply to the maximum program size.

Dependencies

Unknown

Urgency

Relatively urgent. Three different ecosystem projects have recently escalated to DevRel that they have hit the program size limit, so the current limit is actively constraining builders in the ecosystem.

joe-p commented 6 hours ago

I just want to point out that right now the max amount of data the AVM loads for a single app eval is 16KB (8KB for program, 8KB for boxes). I imagine increasing that amount would have performance implications.

We could do something simmilar to #6057 for called programs in a group, but I think that would really hurt composability because it's not immediately obvious to developers which apps can be called together.

jannotti commented 5 hours ago

I just want to point out that right now the max amount of data the AVM loads for a single app eval is 16KB (8KB for program, 8KB for boxes). I imagine increasing that amount would have performance implications.

This is the problem. We don't put in arbitrary limits for the fun of it. When boxes were introduced, we created a system to ensure that, even if the boxes were big, the I/O caused by evaluating a transaction was not greater than it used to be.

Unfortunately, we have no such quota system on programs. So, very large programs would, potentially, cause a great deal of I/O. Consider, for example, that one transaction can call 8 different foreign apps. If each of those apps was 32kb, we need to read 9*32kb for a single transaction.

I do not have a great idea for fixing this. Using such large programs is pretty intensive for a chain that intends to run txns at 10,000 TPS. I have the unfounded belief that programs bigger than 8kb probably have a lot of room for optimization, so I would like someone to spend some time trying to understand if there are improvements to puya's compilation (presumably we're not talking pyteal anymore) that could save space. That could include adding opcodes for very frequent sequences that could be shortened.

My not so great idea for fixing this more directly would be try and come up with a way to bring large programs into the box quota system. If you invoke a large program, that would count against your I/O quota somehow. I suspect people would quickly run into other limits because of that choice. A completely unfleshed out thought is to somehow make it possible to invoke a program in a box. Then we let the quota system work as is.

joe-p commented 5 hours ago

The solution using what we currently have availible to us is just breaking down your logic into multiple on-chain apps with different apps implenenting different methods. The main problem with this approach is that application can't share state access, so you need a lot of inter-app communication (ie. scratch, global/local, itxns, etc.) which can get rather complex.

Rather than allowing one program to be larger than 8kb, what if we allowed apps to share state access (both read + write, including boxes)? Presumably this would be an optional field in appl that can be used when the programs are first deployed on-chain.

Edit: So I suppose I'm asking if developers really want programs larger than 8kb or if they just want > 8kb of logic to be able to interact with the same state. I would suspect it's the latter. I am aware though that this would also introduce a lot of challenges with regards to compilation, deployment, composability, etc.

pbennett commented 3 hours ago

Correct - because box storage is opaque, to have independent 'helper' contracts expected to act as app a + (helpers b, c, d) doesn't work. You can't call A which calls B which then has to call back to A to read box state - no re-entrancy allowed. Alternative then becomes passing everything B might need as part of its call. There's also the issue of B knowing its being called from a 'true' A and the various machinations that might involve (and extra calls). So even ignoring the extra work for contracts (if even possible tbh), the extra work for the AVM with all these workarounds would I think be far greater than just allowing larger contracts. Having to burn up extra transactions to cover the size would probably be ok - we often have to burn transactions already to cover the various references.