tendermint/go-amino

Marshal and UnMarshal Binary does not work if the field's name are not identical with field's type

TanNgocDo opened this issue · 4 comments

I test the marshal and unmarshalBinary function with this code stuff
`type SimpleStruct struct {
a int
}

s := SimpleStruct{a: 10}	
cdc := amino.NewCodec()
cdc.RegisterConcrete(SimpleStruct{}, "SimpleStruct", nil)
b, _ := cdc.MarshalBinary(s)	
var s2 SimpleStruct
_ = cdc.UnmarshalBinary(b, &s2)`

The result of marshal and unmarshal are not correct.
But if I change the the field 'a' to "Int" -> it works. I noticed that in the unit test of binary_test, the field's name are always indentical with the fields type: for exp: Int->int, String->string

The reason this does not work is because a is unexported and Int is (as it is capitalized). Change to A and this should work, too :-)

There are many more examples where the field names are not the same as the field types.

OOPS, is it the rule in Amino's code ? Could you please to specify the code stuff that defines it ?

It is due to golang's reflection library which is used to get the fields:

go-amino/codec.go

Lines 422 to 430 in 2106ca6

func (cdc *Codec) parseStructInfo(rt reflect.Type) (sinfo StructInfo) {
if rt.Kind() != reflect.Struct {
panic("should not happen")
}
var infos = make([]FieldInfo, 0, rt.NumField())
for i := 0; i < rt.NumField(); i++ {
var field = rt.Field(i)
var ftype = field.Type

Also, golang's reflect does not allow to write private fields.

Thank you, I'm so careless to ignore this trick in Go Reflection