-
Notifications
You must be signed in to change notification settings - Fork 124
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
chore(lib/runtime): CheckRuntimeVersion
independent from existing runtime instance
#2687
Conversation
649b9ad
to
8375fdf
Compare
8375fdf
to
2ee6693
Compare
0ab702b
to
8d5d087
Compare
Codecov Report
@@ Coverage Diff @@
## development #2687 +/- ##
===============================================
- Coverage 62.81% 62.79% -0.03%
===============================================
Files 213 213
Lines 27069 27057 -12
===============================================
- Hits 17003 16990 -13
- Misses 8514 8519 +5
+ Partials 1552 1548 -4 |
8d5d087
to
327170d
Compare
@@ -16,7 +16,6 @@ import ( | |||
// Instance is the interface a v0.8 runtime instance must implement | |||
type Instance interface { | |||
UpdateRuntimeCode([]byte) error | |||
CheckRuntimeVersion([]byte) (Version, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why you removed this function from the interface since it creates a new instance to do the version check, but how will we mock this out now? We'd have to change the function signatures of all callers of this function to include a func([]byte) (Version, error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say it's better to not mock it, since:
- it's fast
- it's all CPU/in-memory and no IO
- it's predictable
- it adds testing depth which we should crave for when those 3 above are true
If you still want to mock it somewhere though, then you can set it as a functional field on the receiving struct like
type Service struct {
checkRuntimeVersion(code []byte) (version Version, err error)
}
func New() *Service {
return &Service{
checkRuntimeVersion: wasmer.CheckRuntimeVersion,
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's fast at all. It's instantiating a wasmer instance, loading the code in, binding the imports, etc. Now all of the unit tests are runtime specific if we remove it from the Instance
interface.
Why aren't we just implementing a RuntimeVersion() (Version, error)
(no blob) on Instance
. Then anyone who needs to version check needs to instantiate an instance via NewInstance
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It takes 500ms to load the version, so not that fast indeed.
But if you have a look, there was no configuration of the CheckRuntimeVersion
mock method expectation, so it won't change a thing with our code as it is.
And as I mentioned above, if in the future we want to mock the runtime check (for test coverage or testing speed), we can just set it as a field on the receiving struct (like we would with timeNow func() time.Time
to mock time).
Also (in my opinionated opinion), having a function as a method just for the sake of it being part of an interface for testing is a bit weird, especially if it doesn't depend on the struct/implementation at all (wasn't the case before though, but it is now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at the interface again. The Instance
interface includes a Version() (Version, error)
method. I think we should remove CheckRuntimeVersion
from the runtime package and make this a private method in dot/state
and a helper function for the tests. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, although that would require to export a bunch of things such as setupVM
, the wasmer Instance
struct fields vm
and ctx
, and I think ultimately we should keep this in the wasmer package since it's quite tightly coupled with wasmer thingies? I would rather export CheckRuntimeVersion
than these other function/fields, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need to export those private functions? To check a version of a given wasm blob, you instantiate an instance by calling NewInstance(code []byte, cfg runtime.InstanceConfig)
and call Version()
on that instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, sorry I misunderstood.
I changed CheckRuntimeVersion
to use NewInstance
, simplifying it a bit / reducing code duplication (although it sets up extra stuff it doesn't need, but that's a dep injection problem for another day).
On the other hand, ext_misc_runtime_version_version_1
in wasmer/imports.go
uses CheckRuntimeVersion
so I think we should still keep it in the wasmer package? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have dissonance with having a function on the public package API that achieves the same functionality that can be achieved by instantiating an instance and calling a receiver method on that instance. But that would lead to code duplication cause we use it in various places. I gave it a shot in this commit, and I'm not really happy with it. So I'm ok with leaving with leaving it in the wasmer
package.
327170d
to
7b15e83
Compare
@@ -16,7 +16,6 @@ import ( | |||
// Instance is the interface a v0.8 runtime instance must implement | |||
type Instance interface { | |||
UpdateRuntimeCode([]byte) error | |||
CheckRuntimeVersion([]byte) (Version, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have dissonance with having a function on the public package API that achieves the same functionality that can be achieved by instantiating an instance and calling a receiver method on that instance. But that would lead to code duplication cause we use it in various places. I gave it a shot in this commit, and I'm not really happy with it. So I'm ok with leaving with leaving it in the wasmer
package.
lib/runtime/wasmer/instance.go
Outdated
// CheckRuntimeVersion finds the runtime version by initiating a temporary | ||
// runtime instance using the WASM code provided, and querying it. | ||
func CheckRuntimeVersion(code []byte) (version runtime.Version, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like @timwu20 mentioned there isn't really a need for this function to remain in the runtime/wasmer package anymore, might make more sense for it to be in dot/state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kept it there to avoid replicating 3 times (lib/runtime/wasmer, dot/state, and somewhere else too) as per what Tim described.
Also it might get a bit more complex due to Core_version
being deprecated, and we won't need to create an instance anymore for newer runtimes, so we should definitely have it in one place. (see paritytech/substrate#8688)
If it's stateless, I would say it's fine to have as a 'pure' function (without interfacing etc.). The caller can always have it as a function struct field (or other).
Yeah I would rather have it in the wasmer package as a helper function than duplicated in 3 places. |
- No dependency on existing instance - Closes temporary instance on exit - Remove `CheckRuntimeVersion` from Instance interface
f3a8cbf
to
6bce0f6
Compare
I am Quentin Mc Gaw, a software engineer working the Go Polkadot host **Gossamer**. I have been working full time on Gossamer since October 2021, mostly on the state trie and storage. I have also made a [few minor pull requests](https://github.com/w3f/polkadot-spec/pulls?q=is%3Apr+is%3Aclosed+author%3Aqdm12) to the Polkadot specification repository. I am requesting to join the Fellowship at rank 1. ## Main contributions ### Gossamer - Fix memory leaks - Trie encoding buffer pools usage fixed [#2009](ChainSafe/gossamer#2009) - Fix state map of tries memory leak [#2286](ChainSafe/gossamer#2286) - Fix sync benchmark [#2234](ChainSafe/gossamer#2234) - Trie proof fixes ([#2604](ChainSafe/gossamer#2604), [#2661](ChainSafe/gossamer#2661)) - Fix end to end tests orchestration ([#2470](ChainSafe/gossamer#2470), [#2452](ChainSafe/gossamer#2452), [#2385](ChainSafe/gossamer#2385), [#2370](ChainSafe/gossamer#2370)) - State trie statistics ([#2378](ChainSafe/gossamer#2378), [#2310](ChainSafe/gossamer#2310), [#2272](ChainSafe/gossamer#2272)) - State trie fixes and improvements - Only deep copy nodes when mutation is certain [#2352](ChainSafe/gossamer#2352) and [#2223](ChainSafe/gossamer#2223) - Only deep copy necessary fields of a node [#2384](ChainSafe/gossamer#2384) - Use Merkle values for database keys instead of always hash [#2725](ChainSafe/gossamer#2725) - Opportunistic parallel Merkle value commputing [#2081](ChainSafe/gossamer#2081) - Grandpa capped number of tracked messages ([#2490](ChainSafe/gossamer#2490), [#2485](ChainSafe/gossamer#2485)) - Add pprof HTTP service for profiling [#1991](ChainSafe/gossamer#1991) Ongoing work: - State trie lazy loading and caching - State trie v1 support ([#2736](ChainSafe/gossamer#2736), [#2747](ChainSafe/gossamer#2747), [#2687](ChainSafe/gossamer#2687), [#2686](ChainSafe/gossamer#2686), [#2685](ChainSafe/gossamer#2685), [#2673](ChainSafe/gossamer#2673), [#2611](ChainSafe/gossamer#2611), [#2530](ChainSafe/gossamer#2530)) ### Polkadot specification ➡️ [Pull requests from qdm12](https://github.com/w3f/polkadot-spec/pulls?q=is%3Apr+is%3Aclosed+author%3Aqdm12)
🎉 This PR is included in version 0.7.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Changes
Blocked by #2686 and #2685
CheckRuntimeVersion
as function instead of instance methodCheckRuntimeVersion
from Instance interfaceext_misc_runtime_version_version_1
usesCheckRuntimeVersion
Tests
Issues
#2418
Primary Reviewer
@timwu20