Skip to content

Commit

Permalink
fix(gnovm): load map from state
Browse files Browse the repository at this point in the history
Fix gnolang#817

There was actually 2 bugs in the code responsible for loading a map from
the state:
- `UnmarshalAmino` doesn't check that `ml.Tail` is nil before accessing
  it. It is correctly done for instance in `MapList.Append` for
  instance. The fix just ensures that `ml.Tail` is not nil.
- `fillTypesOfValue` which is called just after the store data is
  unmarshalSized, resets the map data by calling `MapValue.MakeMap()`.
  So at the end the map is always empty, whatever was stored before the
  transaction. The fix replaces the call of `MakeMap` to a simple map
  creation.

This has to be confirmed, but this change may also fix gnolang#311, because I'm
not convinced that the indetermenistic behavior of the golang map can be
a problem when saved to the store. Indeed, a gno map is serialized with
the help of a slice, which should remove any indetermenistic problem.
  • Loading branch information
tbruyelle committed Jun 26, 2023
1 parent dcbe130 commit 63fddfa
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 4 deletions.
2 changes: 1 addition & 1 deletion gnovm/pkg/gnolang/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ func fillTypesOfValue(store Store, val Value) Value {
fillTypesTV(store, &cv.Receiver)
return cv
case *MapValue:
cv.MakeMap(cv.List.Size) // TODO move out.
cv.vmap = make(map[MapKey]*MapListItem, cv.List.Size)
for cur := cv.List.Head; cur != nil; cur = cur.Next {
fillTypesTV(store, &cur.Key)
fillTypesTV(store, &cur.Value)
Expand Down
5 changes: 4 additions & 1 deletion gnovm/pkg/gnolang/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"unsafe"

"github.com/cockroachdb/apd"

"github.com/gnolang/gno/tm2/pkg/crypto"
)

Expand Down Expand Up @@ -661,7 +662,9 @@ func (ml *MapList) UnmarshalAmino(mlimg MapListImage) error {
ml.Head = item
}
item.Prev = ml.Tail
ml.Tail.Next = item
if ml.Tail != nil {
ml.Tail.Next = item
}
ml.Tail = item
ml.Size++
}
Expand Down
8 changes: 6 additions & 2 deletions gnovm/tests/challenges/persist_map.gno
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ func init() {

func main() {
println("premain", amap)
amap["b"] = "2"
amap["c"] = "3"
println("postmain", amap)
}

// Current behavior: panics
// Output:
// preinit map{("a" string):("1" string)}
// postinit map{("a" string):("1" string),("b" string):("2" string)}
// premain map{("a" string):("1" string),("b" string):("2" string)}
// postmain map{("a" string):("1" string),("b" string):("2" string),("c" string):("3" string)}

0 comments on commit 63fddfa

Please sign in to comment.