In the original contract lifecycle proposal, we introduced a network limit of 16384 bytes for WASM contract code. I believe this limit might be too low, and wanted to get opinions on what the limit should be. The other question is should we have a single limit for contract code and contract data size, or should the limits be separate? @nimble blade @toxic swan @prime sky
#Maximum WASM contract size
32 messages · Page 1 of 1 (latest)
I think we discussed either 32k or 64k bytes as a reasonable limit in the past, but can't find any threads related to this.
I thought we were at 256k currently, but I could be wrong
Yeah that's the current SCVAL_LIMIT. The lifecycle proposal introduced an upgradeable network setting that would be a lower limit that validators could vote to change. This setting has not been implemented and hooked up to soroban yet.
Here's the section in the CAP - https://github.com/stellar/stellar-protocol/blob/master/core/cap-0046-02.md#max-contract-size-setting.
that's what i thought too
I think they should be kept separate.
- Contract data (consisting of a pair of ScVals) should not contain the executable's bytes directly, but rather the hash of the executable, as far as I understand? If so it makes the two conceptually separate.
- They may have different mechanisms of size-limiting, the contract code is a hard cap (64kb or whatever we decide) and is easily enforceable. ScVal is much harder to put a single hard cap on, and we will probably go with a more indirect approach of "number of objects" * "size of a single object" which implicitly caps the size of the ScVal without restricting its structure and nestedness (see https://github.com/stellar/stellar-protocol/issues/1298). This means we may have to introduce more limits such as
SCVEC_MAX_ELEMENTS_LIMIT,SCMAP_MAX_ELEMENTS_LIMIT,SCBYTES_LIMITetc.
In terms of the actual limit, I don't have a strong opinion. From metering perspective they won't make too much difference between 32kB and 64kB contracts (in terms of setting up the runtime environment). Running the wasm instructions will of course will cost differently.
the larger the contract, the more functions writers can expose, which is good (every one of them might be cheap)
just keep in mind that we won't be able to ever reduce this limit
What's the WASM size of our examples?
Yeah good point
we also produce a lot of meta now and this depends on the interface size as well
We need some headroom to allow developers bring in some dependencies. 16k sounds awfully small.
We also risk developers introducing dependencies as separate contracts and use cross contract calls
definitely. I'm ok with 64k, just saying that we might want to consider a bit more conservative approach with 32k or 48k given that we won't be able to reduce this without breaking lots of contracts
Am I correct about ScVal never having to storing contract code as bytes object, only as ScVal::ScContractExecutable? If not, then this will affect the ScVal limit as well.
I'd say ledger entry limit should probably be at least as large as the wasm size limit anyway (otherwise we create an incentive to store data as wasm)
(but yeah, you're right that we don't store wasm per conract instance)
Right I was thinking if we approach the ScVal limit as "number of objects" * "size of a single object", then having the byte object size no less than contract code size means we will have a multiple times larger size limit for ScCal . But it seems like the bytes object size limit can be independently chosen from the contract size limit, which makes it good.
not sure I fully understand... we should probably introduce some top-level limits, like tx size limit or ledger entry size limit. I'm not sure if implementing per-scval limits is productive
" we should probably introduce some top-level limits, like tx size limit or ledger entry size limit"
We can still have that. The ScVal limit is just to make the limit more concrete. E.g. If we can't have more than 10 objects each within 1kB each, then the user can have a clearer guideline to follow such limits when constructing an arbitrary object.
but why would we want to have such limits?
e.g. user A might want to store a vector of 5000 i1128 and user B might want to store a tree structure with 1000 nodes and i32 value for each leaf
also not clear when such limit would be enforced
most of the time users won't hit the limits and if they do, it's not that hard to figure out why and how to optimize that. I don't like artificial limitations on the data structures
is it not possible to charge 'rent' for contract storage, i know that might not be ideal
also why impose a small limit, if it were me needing to get around the limit, i'd just deploy multiple contracts, and make them interoperable somehow, it would cause inefficiencies and bloat that wouldn't be necessary with a larger limit. people would do that to get around a size limit though; and i agree that 16kb seems really small 64kb seems reasonable, and i love 256kb because i haven't ever hit the limit yet
rent is a thing, but we also need to take the IO into consideration. basically, the justification for any per-transaction limit is to allow executing at least N transactions per ledger (where N is, say, at least 10). so we have a per-ledger limit on every resource (e.g. we can't read more than K mb from the ledger if we want to close withing 1-2s), which imposes an upper bound limit on every transaction
(now I'm not sure if that applies here or not, but that's definitely a consideration for e.g. per-tx cpu limit)