-
Notifications
You must be signed in to change notification settings - Fork 379
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
fix(gnovm): correctly update refs count when self-assigning #960
Conversation
Before merging anything, we need to answer the following questions convincingly, in the following order.
I haven't been able to reproduce the bug, which limits me in making a strong case to answering the other 2 questions. I've ran the functions you listed in a regular Go test inside the VM and Gno test contract (locally), it works fine. |
@peter7891 |
That would be great. Discord? Petar#4367 |
I think, i can answer these questions now.
With the code of the original bug report,
After the assignment inside
@jaekwon What do you think? |
304dcf2
to
cb0665c
Compare
I updated the commit with the changes proposed by @peter7891 |
36bdbe7
to
2e26a35
Compare
this solution was mostly found by @peter7891 Signed-off-by: Norman Meier <norman@berty.tech>
2e26a35
to
351a0f1
Compare
Are we able to reproduce this in a unit test at all? |
Yeah I managed to have a test using manfred's pattern in #979, will push it here |
Signed-off-by: Norman Meier <norman@berty.tech>
The test I just added fails on master but passes on this PR, it reproduces the original bug description in #939 |
Signed-off-by: Norman Meier <norman@berty.tech>
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.
Thank you for adding a fix for this 🙏
Can you please update the PR description with a brief summary of the changes (from Peter's comment)?
Pinging @peter7891 and @jaekwon to give a look as well
@@ -0,0 +1,62 @@ | |||
package multitxtest |
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.
Should these tests be contained in the examples
subdirectory, instead of gnovm
, since these are .go
files after all?
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 believe we should keep them in the examples folder, alongside the contract implementation.
I started this in #979, but paused to prioritize #1016, which will also provide a go API for advanced gno tests.
In the future, we plan to remove those _test.go
files completely in favor of a gno-centric multi-step approach defined in #934.
By the way, I suggest moving the entire realm to the r/demo/x/
subfolder for experiments and things we don't want people to interact with.
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.
Given that the _test.go file is loading the local .gno file, my suggestion is to create an official folder for these flows, located at gnovm/tests/flows/
. We can place multitx.go in this folder as well as the other file, issue939/flow_test.go
. This way, the examples folder can remain dedicated to showcasing real examples.
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.
See comments, thank you.
@n0izn0iz Ping for visibility on this PR, please check out the comments so we can go ahead and merge this 🙏 |
@n0izn0iz just switched the PR to draft; please remove the draft flag when you'll apply the last changes. |
sorry for moving slowly on that, I'd like to take the time to properly implement the multi-tx test helper, currently it barely works, I barely understand it and is very hacky/brittle, maybe I should revert to include it as-is directly in the test and do the mutli-tx test helper in another PR |
@n0izn0iz Hey sounds this is related to a bug we had on gnochess, see #1170, can you confirm we're talking about the same bug ? Basically you setup your "*_test.go" file with |
So I think we can state that the bugs we have in gnolang#960, gnolang#1167 and gnolang#1170, are all related to slice storage when its capacity is different than its length. @deelawn found a great way to overcome that bug, but the bug is still there, somewhere in the VM code I think. I spent the last couple of days trying to find it, unfortunately without success. That said, I found a workaround, that could be also applied: when a slice is stored, ignore any capacity different than the slice's length. I think this is a good workaround because its one-line and because we don't really care about storing slice with capacity higher than their length (unless I'm missing something).
Addresses #1167, #960, and #1170 Consider the following situation: - A slice of structs exists with a length of zero and a capacity of one - A new struct literal is appended to the slice - The code panics because the newly allocated struct literal was never marked as "new" ``` go package append import ( "gno.land/p/demo/ufmt" ) type T struct{ i int } var a []T func init() { a = make([]T, 0, 1) } func Append(i int) { a = append(a, T{i: i}) } ``` Invoking the `Append` function will cause a panic. The solution is to traverse each of the array elements after slice append assignment to make sure any new or updated elements are marked as such. This PR also includes a change to ensure that marking an object as dirty and managing references to the object are mutually exclusive. I think this is correct but am not sure. The changes include txtar test cases that incorporate the issue described by @tbruyelle in #1170 --------- Co-authored-by: jaekwon <jae@tendermint.com>
The issue this PR was meant to address has been fixed by #1305 |
…lang#1305) Addresses gnolang#1167, gnolang#960, and gnolang#1170 Consider the following situation: - A slice of structs exists with a length of zero and a capacity of one - A new struct literal is appended to the slice - The code panics because the newly allocated struct literal was never marked as "new" ``` go package append import ( "gno.land/p/demo/ufmt" ) type T struct{ i int } var a []T func init() { a = make([]T, 0, 1) } func Append(i int) { a = append(a, T{i: i}) } ``` Invoking the `Append` function will cause a panic. The solution is to traverse each of the array elements after slice append assignment to make sure any new or updated elements are marked as such. This PR also includes a change to ensure that marking an object as dirty and managing references to the object are mutually exclusive. I think this is correct but am not sure. The changes include txtar test cases that incorporate the issue described by @tbruyelle in gnolang#1170 --------- Co-authored-by: jaekwon <jae@tendermint.com>
Fixes #939
See #960 (comment) for explanations of the fix
Thanks to @peter7891 for most of the actual fixing
Checklists...
Contributors Checklist
BREAKING CHANGE: xxx
message was included in the descriptionMaintainers Checklist
CONTRIBUTING.md
BREAKING CHANGE:
in the body)