Skip to content

Commit d10a42b

Browse files
committed
fix(amino/json): use AminoMarshaler reprType info
When a type is registered, if it implements AminoMarshaler, then use the type returned by `MarshalAmino` method to feed type `ConcreteInfo`. This prevents a panics that happens during the sanity check phase of `encodeReflectJSONInterface` when the type `ConcreteInfo` doesn't match the JSON structure. For instance, that used to happen with `BigintValue` which is a struct (so expected JSON is `{...}`), but is marshaled into a simple string (so expected JSON is only `"..."`).
1 parent e90bfd8 commit d10a42b

File tree

4 files changed

+34
-44
lines changed

4 files changed

+34
-44
lines changed

gnovm/pkg/gnolang/package_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package gnolang
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
"github.com/jaekwon/testify/require"
8+
9+
"github.com/gnolang/gno/tm2/pkg/amino"
10+
)
11+
12+
// Tries to reproduce the bug #1036 on all registered types
13+
func TestMarshalAminoRegisteredTypes(t *testing.T) {
14+
for _, typ := range Package.Types {
15+
// Instanciate registered type
16+
x := reflect.New(typ.Type).Interface()
17+
// Call MarshalAmino directly on 'x'
18+
_, err := amino.MarshalJSON(x)
19+
require.NoError(t, err, "marshal type %s", typ.Type.Name())
20+
// Call MarshalAmino on a struct that embeds 'x' in a field of type any
21+
xx := struct {
22+
X any
23+
}{X: x}
24+
_, err = amino.MarshalJSON(xx)
25+
require.NoError(t, err, "marshal type %s from struct", typ.Type.Name())
26+
}
27+
}

gnovm/pkg/gnolang/values_test.go

Lines changed: 0 additions & 22 deletions
This file was deleted.

tm2/pkg/amino/codec.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -634,13 +634,16 @@ func (cdc *Codec) newTypeInfoUnregisteredWLocked(rt reflect.Type) *TypeInfo {
634634
panic(err)
635635
}
636636
info.ConcreteInfo.ReprType = rinfo
637+
info.ConcreteInfo.IsJSONWellKnownType = rinfo.IsJSONWellKnownType
638+
info.ConcreteInfo.IsJSONAnyValueType = rinfo.IsJSONAnyValueType
639+
info.ConcreteInfo.IsBinaryWellKnownType = rinfo.IsBinaryWellKnownType
637640
} else {
638641
info.ConcreteInfo.IsAminoMarshaler = false
639642
info.ConcreteInfo.ReprType = info
643+
info.ConcreteInfo.IsJSONWellKnownType = isJSONWellKnownType(rt)
644+
info.ConcreteInfo.IsJSONAnyValueType = isJSONAnyValueType(rt)
645+
info.ConcreteInfo.IsBinaryWellKnownType = isBinaryWellKnownType(rt)
640646
}
641-
info.ConcreteInfo.IsBinaryWellKnownType = isBinaryWellKnownType(rt)
642-
info.ConcreteInfo.IsJSONWellKnownType = isJSONWellKnownType(rt)
643-
info.ConcreteInfo.IsJSONAnyValueType = isJSONAnyValueType(rt)
644647
if rt.Kind() == reflect.Array || rt.Kind() == reflect.Slice {
645648
einfo, err := cdc.getTypeInfoWLocked(rt.Elem())
646649
if err != nil {

tm2/pkg/amino/json_encode.go

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -397,24 +397,6 @@ func isJSONAnyValueType(rt reflect.Type) bool {
397397
// {@type,value}, the latter specifically
398398
// {@type:"/google.protobuf.Any",value:{@type,value}).
399399
return true
400-
} else {
401-
// Otherwise, it depends on the kind.
402-
switch rt.Kind() {
403-
case
404-
reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
405-
reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16,
406-
reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64,
407-
// Primitive types get special {@type,value} treatment. In
408-
// binary form, most of these types would be encoded
409-
// wrapped in an implicit struct, except for lists (both of
410-
// bytes and of anything else), and for strings...
411-
reflect.Array, reflect.Slice, reflect.String:
412-
// ...which are all non-objects that must be encoded as
413-
// {@type,value}.
414-
return true
415-
default:
416-
return false
417-
}
418-
return false
419400
}
401+
return false
420402
}

0 commit comments

Comments
 (0)