Closed koxu1996 closed 1 month ago
i had experimented with this and had not had much luck. If you can get it to pass the contract tests I'm all for it.
Risc0 verifier (+ bincode2 deserialization for receipt)
Make sure you use the code when judging the size, only code paths you use and ones that could be called by dyn trait make it into the optimized binary. Our contract also has std from risc0 transitive dependencies linked in.
Looks good, any idea why we are running out of gas in the tests?
@Avi-D-coder @marijanp Contract calls in test engine are using the default payment, which is 2500 CSPR.
Since we optimized code for size, it might be more expensive to execute. I just measured it and previously the cost was 1043 CSPR, and after full size optimization it is 2756 CSPR :fearful:. For example just by setting Rust o='s'
we get 1004KiB (still fits in production chainspec) and execution takes 1588 CSPR.
We should find a good balance between WASM size and cost of execution, but I think compatibility with the production chainspec is a priority here.
Code used for testing:
let cost = self
.builder
.get_last_exec_results()
.unwrap()
.get(0)
.unwrap()
.cost();
panic!("Cost of execution: {:?}", cost);
@koxu1996 try build-std https://doc.rust-lang.org/cargo/reference/unstable.html
Risc0 verifier (+ bincode2 deserialization for receipt)
Make sure you use the code when judging the size, only code paths you use and ones that could be called by dyn trait make it into the optimized binary. Our contract also has std from risc0 transitive dependencies linked in.
Yup, I made unsuccessful verification trigger panic, so Risc0 code was definitely used there.
@koxu1996 try build-std https://doc.rust-lang.org/cargo/reference/unstable.html
On the one hand Risc0 has a bug, where std
is introduced in one of old dependencies (downcast-rs
in rrs-lib
). However, it gets optimized out, since it's not used in our code. Overall, std
library is not present in Kairos contracts, so there is no need for build-std
.
Hmm, that seems odd. What is the main contributor to our binary size then?
I don't like serde_json
... but this needs more investigation, as we pull quite a lot of dependencies.
Try borsh we could not get bincode working in the wasm contract, float related issue.
Context
In Casper v1.5.6 maximum contract size is 1 MiB (1,048,576 bytes), which we fairly exceed with demo contract (1.4 MiB), therefore making Kairos incompatible with production network.
Can we reduce it?
I was suspecting that Risc0 verifier might be the biggest part of final WASM, so I did some tests on bare minimum contract. However, bare Risc0 verifier (+ bincode2 deserialization for receipt) is less than 20 KB :space_invader:. Casper API calls are also quite small (few kilobytes), so it means we should be able to get way less than 1 MiB.
First easy optimization
Simple idea: we can enable more aggressive optimization in Rust complier and WASM optimizer.
I run benchmark for WASM produced by
nix build -L --no-link --show-trace .#packages.x86_64-linux.kairos-contracts
:o='s'
: 1004KiB (1,025,823 bytes)o='z'
: 904KiB (921,813 bytes)o='s'
: 1.3MiB (1,322,590 bytes)o='z'
: 1.3MiB (1,320,589 bytes)o='s'
and WASMo='s'
: 964KiB (985,116 bytes)o='s'
and WASMo='z'
: 964KiB (983,713 bytes)o='z'
and WASMo='s'
: 868KiB (886,560 bytes)o='z'
and WASMo='z'
: 868KiB (884,798 bytes) :arrow_left: This PR.After those optimizations we are using 84.77% of production WASM limit :relieved:. Still much, but it was low hanging fruit.