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

Consolidate MaxWasmSize constraints into a single var #809

Closed
wants to merge 3 commits into from
Closed

Consolidate MaxWasmSize constraints into a single var #809

wants to merge 3 commits into from

Conversation

bigs
Copy link
Contributor

@bigs bigs commented Apr 19, 2022

See #813

The maxWasmCodeSize parameter is no longer used. You can set it by overriding x/wasm/types/MaxWasmSize at compile time (in app.go). The default is now set to 800kB but any chain can easily configure when doing a binary upgrade. This change eliminates a conflict wherein the parameter was only used in the WasmKeeper while a separate constant was used to validate MsgStoreCode messages.

@bigs bigs requested a review from alpe as a code owner April 19, 2022 21:40
@webmaster128 webmaster128 added this to the v0.27.0 milestone Apr 21, 2022
@ethanfrey
Copy link
Member

Good eye.

ValidateBasic does not have access to state, so we cannot check against params. If we remove this check here, I would like to ensure that it will actually be checked somewhere in CheckTx. Otherwise, you can get honest validators to fill up the chain with arbitrary large garbage data.

Removing it is not sufficient, we need an alternative. One idea is using a var rather than const and making this definable compile time (eg in app.go or using a go linker flag)

@ethanfrey ethanfrey added the optional Not absolutely required for the milestone label Apr 25, 2022
@alpe
Copy link
Contributor

alpe commented Apr 25, 2022

Otherwise, you can get honest validators to fill up the chain with arbitrary large garbage data.

Good point!
A custom ante handler that reads the params would be an option, too.

This was referenced Apr 25, 2022
@bigs
Copy link
Contributor Author

bigs commented Apr 25, 2022

The param is ultimately read in the uncompress function which is used in the Keeper's create and importCode functions. This (more configurable) redundancy was my motivation to remove it from the message itself. I noticed my transaction was failing client side and never even sending to a validator to be rejected.

EDIT: The param is maxWasmCodeSize.

@ash-burnt
Copy link

The weird thing here is that there is a hardcoded variable that exists, and also a param for the same value. The value is exposed to governance, but not actually honored by governance. It seems like this should be one or the other, not both.

@ethanfrey
Copy link
Member

The param is ultimately read in the uncompress function which is used in the Keeper's create and importCode functions. This (more configurable) redundancy was my motivation to remove it from the message itself. I noticed my transaction was failing client side and never even sending to a validator to be rejected.

Yes, and eg. create is only called in DeliverTx, not CheckTx. We want a sanity check before including 5 MB invalid wasm tx in the blockchain in the first place (which ValidateBasic will do, but nothing else, as not x/wasm handler logic is called in CheckTx)

I agree we should only have one value. I would make it a compile-time variable and remove the param completely. (And document this along with migration for chains when they upgrade)

@bigs
Copy link
Contributor Author

bigs commented Apr 25, 2022

Ah, makes sense. I think I had my wires a bit crossed, there! Compile time seems reasonable as does a configuration object passed to NewAppModule, perhaps? Happy to take this on when we come to something, sensible.

@bigs
Copy link
Contributor Author

bigs commented Apr 26, 2022

@alpe @ethanfrey @ash-burnt Digging in a bit further, it seems like there are a few options:

  1. Change the const to a var, eliminate the conflicting module param, and respect the var in ValidateBasic. It would probably also entail removing the check in the Keeper, which seems redundant, but I'm not entirely sure on that.
  2. Implement an additional AnteDecorator in x/wasm/keeper that accepts the wasmd module's param Subspace as an argument and validates messages storing contracts in a transaction accordingly. We would then update app's NewAnteHandler to optionally accept a Subspace in HandlerOptions. When present, it can add our decorator to the stack. Similarly, my gut tells me we could then do away with the Keeper validation.

I'm relatively new to the ecosystem, so I won't claim to know which is best. Option 1 is certainly simplest and requires minimal modification to anything. Option 2 allows us to modulate this parameter via governance. For example, the wasm-opt optimized byte code for cw721-metadata-onchain comes out to 253KB which is already pushing half of the statically defined maximum. I could see a chain starting with a maximum around 500KB and then revising it upwards. Doing so via governance rather than cutting a completely new version of the application could save some headaches!

@ethanfrey
Copy link
Member

I could see a chain starting with a maximum around 500KB and then revising it upwards.

I think we advise 600KB or 1200KB as default parameters (unaware the const was still there).

I would have chains just start with something like 800KB-1000KB to start, and then if this really is an issue and some contract creator convinces them this is important, they just include this in the next upgrade. A contract creator should realise this well before production (when building code, running on testnet, etc) and I don't see a quick turnaround as critical.

Most chains do upgrades every 1-3 months, so that seems reasonable.

TL;DR all for the simple solution - using var and updating default to 800 KB or so

@bigs bigs closed this Apr 26, 2022
Also removes redundant maxWasmSize param
@bigs bigs reopened this Apr 26, 2022
@bigs
Copy link
Contributor Author

bigs commented Apr 26, 2022

@ethanfrey Pushed up a change that should address it the way we discussed (force-pushed for cleaner history, which auto-closed the branch.) Let me know what you think! Also, for posterity's sake here is a diff that implements the params & AnteHandler based approach.

EDIT: Updated PR description, as well.

@bigs bigs changed the title Remove MaxWasmSize restriction in ValidateBasic Consolidate MaxWasmSize constraints into a single var Apr 26, 2022
@ethanfrey ethanfrey removed the optional Not absolutely required for the milestone label Apr 27, 2022
Copy link
Member

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff. I agree with this.

Can you add a CHANGELOG entry? And update the description to add:

"Addresses #813"

and

"The WasmCodeSize parameter is no longer used. You can set it by overriding x/wasm/types/MaxWasmSize at compile time (in app.go). The default is now set to 800kB but any chain can easily configure when doing a binary upgrade."

You can expand the text, but that is the rough idea that should be there, and linked from the CHANGELOG. I will merge once those cleanup tasks are done. Thanks for the code contribution.

// MaxLabelSize is the longest label that can be used when Instantiating a contract
MaxLabelSize = 128
)

// MaxWasmSize is the largest a compiled contract code can be when storing code on chain
var MaxWasmSize uint64 = 800 * 1024
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good.
Can also be larger if you wish (param was upped to 1200 * 1024 earlier).

But I think 800 or 900 is a good default

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But... why make uint64 and not int? Since we compare it to length which returns an int

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this call because one of its uses requires a uint64 and with split use cases, I went unsigned as a length cannot be negative. I truly don't mind changing it, though!

@bigs
Copy link
Contributor Author

bigs commented Apr 27, 2022

@ethanfrey Should be sorted!

Copy link
Contributor

@alpe alpe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Some tests are failing. Can you run make test, please?

Would be great if can add some doc to
https://github.com/CosmWasm/wasmd#runtime-flags
for this new flag

// MaxLabelSize is the longest label that can be used when Instantiating a contract
MaxLabelSize = 128
)

// MaxWasmSize is the largest a compiled contract code can be when storing code on chain
var MaxWasmSize int = 800 * 1024
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious why you increased the value to 800kb? Do you have a contract example with this size? We had some internal discussion for tgrade yesterday where I looked at some of our contracts and max was 555kb.

Suggested change
var MaxWasmSize int = 800 * 1024
var MaxWasmSize int = 777 * 1024

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, Ethan suggested 800kb. We should have coordinated better. 🤷 It would help with tgrade if you can make it 777kb

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

777kb is an odd number.
But tgrade can easily override this default, so maybe best to use 800 and verify we can change it in the imported one

@bigs
Copy link
Contributor Author

bigs commented Apr 27, 2022

Ah wow -- sorry for moving too quickly. I need to update the protobuf definitions for the params. That broke all the tests!

@ethanfrey
Copy link
Member

Hmmm... is it possible to enable CI runs on this? I didn't realise the tests hadn't all run until @alpe pointed it out.

@ethanfrey
Copy link
Member

BTW, you can look at #822 for example how to update the README and CHANGELOG. (Just add one more line to the README section I created)

@alpe
Copy link
Contributor

alpe commented Apr 29, 2022

@bigs: we have some dependencies on this feature, so I jumped in this morning to rebased your work on top of current main in a new PR (#826) and fixed tests and protobuf. I hope you don't mind.

Can you take a look at the new PR, if this still makes sense for you? Thanks a lot for your work!

@bigs
Copy link
Contributor Author

bigs commented Apr 29, 2022 via email

@bigs
Copy link
Contributor Author

bigs commented Apr 29, 2022

Closing in favor of #826

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants