From 2dfe9bfaa94291e2314d16f882fc8a334c1d64b5 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Mon, 21 Oct 2024 17:32:47 +0200 Subject: [PATCH] fix(gnovm): save object when refCount changed --- .../cmd/gnoland/testdata/issue_1543.txtar | 41 +++ .../cmd/gnoland/testdata/issue_2266.txtar | 42 +++ gnovm/pkg/gnolang/realm.go | 4 + gnovm/tests/files/heap_item_value_init.gno | 20 ++ gnovm/tests/files/zrealm13.gno | 125 +++++++++ gnovm/tests/files/zrealm14.gno | 114 +++++++++ gnovm/tests/files/zrealm15.gno | 241 ++++++++++++++++++ 7 files changed, 587 insertions(+) create mode 100644 gno.land/cmd/gnoland/testdata/issue_1543.txtar create mode 100644 gno.land/cmd/gnoland/testdata/issue_2266.txtar create mode 100644 gnovm/tests/files/zrealm13.gno create mode 100644 gnovm/tests/files/zrealm14.gno create mode 100644 gnovm/tests/files/zrealm15.gno diff --git a/gno.land/cmd/gnoland/testdata/issue_1543.txtar b/gno.land/cmd/gnoland/testdata/issue_1543.txtar new file mode 100644 index 00000000000..388f126fcda --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/issue_1543.txtar @@ -0,0 +1,41 @@ +# test issue + +loadpkg gno.land/r/demo/realm $WORK + +# start a new node +gnoland start + + +gnokey maketx call -pkgpath gno.land/r/demo/realm --func Fill --args 0 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/realm --func UnFill --args 0 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/realm --func Fill --args 0 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 + + +-- realm.gno -- +package main + +type A struct { + A string +} +type B struct { + A *A + B string +} + +var ( + a = &A{A: "here"} + b [2]*B +) + +func Fill(i int) { + c := B{ + A: a, + B: "", + } + b[i] = &c +} + +func UnFill(i int) { + b[i] = nil +} + diff --git a/gno.land/cmd/gnoland/testdata/issue_2266.txtar b/gno.land/cmd/gnoland/testdata/issue_2266.txtar new file mode 100644 index 00000000000..046f57802e3 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/issue_2266.txtar @@ -0,0 +1,42 @@ +# test issue + +loadpkg gno.land/r/demo/realm $WORK + +# start a new node +gnoland start + + +gnokey maketx call -pkgpath gno.land/r/demo/realm --func Fill --args 0 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/realm --func Fill --args 1 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/realm --func UnFill --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 + + +-- realm.gno -- +package main + +type A struct { + A string +} +type B struct { + A *A + B string +} + +var ( + a = &A{A: "here"} + b [2]*B +) + +func Fill(i int) { + c := B{ + A: a, + B: "", + } + b[i] = &c +} + +func UnFill() { + b[0] = nil + b[1] = nil +} + diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 3710524130a..0fc8d692017 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -187,6 +187,8 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { if xo.GetIsReal() { rlm.MarkNewDeleted(xo) } + } else { + rlm.MarkDirty(xo) } } } @@ -436,6 +438,7 @@ func (rlm *Realm) incRefCreatedDescendants(store Store, oo Object) { child.SetIsNewReal(true) } } else if rc > 1 { + rlm.MarkDirty(child) if child.GetIsEscaped() { // already escaped, do nothing. } else { @@ -509,6 +512,7 @@ func (rlm *Realm) decRefDeletedDescendants(store Store, oo Object) { if rc == 0 { rlm.decRefDeletedDescendants(store, child) } else if rc > 0 { + rlm.MarkDirty(child) // do nothing } else { panic("deleted descendants should not have a reference count of less than zero") diff --git a/gnovm/tests/files/heap_item_value_init.gno b/gnovm/tests/files/heap_item_value_init.gno index 72f065326f1..6230cadd58b 100644 --- a/gnovm/tests/files/heap_item_value_init.gno +++ b/gnovm/tests/files/heap_item_value_init.gno @@ -183,3 +183,23 @@ func main() { // } // ] // } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:4]={ +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4", +// "IsEscaped": true, +// "ModTime": "6", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", +// "RefCount": "2" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.S" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "a05e5e1e2d2a27d94408a9325a58068e60b504df", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:5" +// } +// } +// } diff --git a/gnovm/tests/files/zrealm13.gno b/gnovm/tests/files/zrealm13.gno new file mode 100644 index 00000000000..1b3b327d6e9 --- /dev/null +++ b/gnovm/tests/files/zrealm13.gno @@ -0,0 +1,125 @@ +// PKGPATH: gno.land/r/test +package test + +var ( + a = &A{A: "here"} + b [2]*B +) + + +type A struct { + A string +} +type B struct { + A *A + B string +} + +func init() { + c := B{ + A: a, + B: "c", + } + b[0] = &c + + d := B{ + A: a, + B: "d", + } + b[1] = &d +} + +func main() { + b[0] = nil +} + + +// Realm: +// switchrealm["gno.land/r/test"] +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:5]={ +// "Data": null, +// "List": [ +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:7" +// }, +// "Index": "1", +// "TV": null +// } +// } +// ], +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:5", +// "ModTime": "9", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", +// "RefCount": "1" +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:7]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:7", +// "IsEscaped": true, +// "ModTime": "9", +// "RefCount": "1" +// }, +// "Parent": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:6" +// }, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "18", +// "PkgPath": "gno.land/r/test" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "c22ccb7832b422c83fec9943b751cb134fcbed0b", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:8" +// } +// }, +// { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "86c916fd78da57d354cb38019923bf64c1a3471c", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:9" +// } +// } +// ] +// } diff --git a/gnovm/tests/files/zrealm14.gno b/gnovm/tests/files/zrealm14.gno new file mode 100644 index 00000000000..972c3462b25 --- /dev/null +++ b/gnovm/tests/files/zrealm14.gno @@ -0,0 +1,114 @@ +// PKGPATH: gno.land/r/test +package test + +var ( + a = &A{A: "here"} + b [2]*B +) + + +type A struct { + A string +} +type B struct { + A *A + B string +} + +func init() { + c := B{ + A: a, + B: "c", + } + b[0] = &c + + d := B{ + A: a, + B: "d", + } + b[1] = &d +} + +func main() { + b[0] = nil + b[1] = nil +} + +// Realm: +// switchrealm["gno.land/r/test"] +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:5]={ +// "Data": null, +// "List": [ +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// } +// } +// } +// ], +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:5", +// "ModTime": "9", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", +// "RefCount": "1" +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:3]={ +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:3", +// "IsEscaped": true, +// "ModTime": "9", +// "RefCount": "1" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.A" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "95dca2f5b12899b6367402ecdac04c7ca59a03d9", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4" +// } +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:6]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:6", +// "IsEscaped": true, +// "ModTime": "9", +// "RefCount": "3" +// }, +// "Parent": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2" +// }, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "2", +// "PkgPath": "gno.land/r/test" +// } +// }, +// "Values": [] +// } +// d[a8ada09dee16d791fd406d629fe29bb0ed084a30:7] +// d[a8ada09dee16d791fd406d629fe29bb0ed084a30:8] +// d[a8ada09dee16d791fd406d629fe29bb0ed084a30:9] diff --git a/gnovm/tests/files/zrealm15.gno b/gnovm/tests/files/zrealm15.gno new file mode 100644 index 00000000000..3cfc67c8078 --- /dev/null +++ b/gnovm/tests/files/zrealm15.gno @@ -0,0 +1,241 @@ +// PKGPATH: gno.land/r/test +package test + +var ( + a = &A{} + b [2]*B + s *S +) + +type S struct { + S string +} +type A struct { + A *S +} +type B struct { + A *A + B *S +} + +func init() { + s = &S{ + S: "c", + } + c := B{ + A: a, + B: s, + } + b[0] = &c + b[1] = &c + a.A = s +} + +func main() { + b[0] = nil + b[1] = nil + a.A = nil +} + + +// Realm: +// switchrealm["gno.land/r/test"] +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:5]={ +// "Data": null, +// "List": [ +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// } +// } +// } +// ], +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:5", +// "ModTime": "10", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", +// "RefCount": "1" +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:10]={ +// "Fields": [ +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.A" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:3" +// }, +// "Index": "0", +// "TV": null +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.S" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:7" +// }, +// "Index": "0", +// "TV": null +// } +// } +// ], +// "ObjectInfo": { +// "Hash": "5bf603ab337f9f40f8b22441562319d67be402b2", +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:10", +// "ModTime": "0", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:9", +// "RefCount": "0" +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:9]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:9", +// "IsEscaped": true, +// "ModTime": "10", +// "RefCount": "0" +// }, +// "Parent": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:6" +// }, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "21", +// "PkgPath": "gno.land/r/test" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.B" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "b539bd303432cae02c338b921b02725cfe3597db", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:10" +// } +// } +// ] +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:4]={ +// "Fields": [ +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.S" +// } +// } +// } +// ], +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4", +// "ModTime": "10", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:3", +// "RefCount": "1" +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:7]={ +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:7", +// "IsEscaped": true, +// "ModTime": "10", +// "RefCount": "1" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.S" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "6e4c3c716e28df1d3a25efeb654a7b7a379ce3b0", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:8" +// } +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:3]={ +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:3", +// "IsEscaped": true, +// "ModTime": "10", +// "RefCount": "1" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.A" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "e82e410f22425e48d5f6c611160084a4dd50d3d1", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4" +// } +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:6]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:6", +// "IsEscaped": true, +// "ModTime": "10", +// "RefCount": "3" +// }, +// "Parent": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2" +// }, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "2", +// "PkgPath": "gno.land/r/test" +// } +// }, +// "Values": [] +// } +// d[a8ada09dee16d791fd406d629fe29bb0ed084a30:9] +// d[a8ada09dee16d791fd406d629fe29bb0ed084a30:10]