diff --git a/Makefile b/Makefile index 3db2c17af7..7c30d22d05 100644 --- a/Makefile +++ b/Makefile @@ -377,6 +377,15 @@ devdoc-update: .PHONY: devdoc devdoc-clean devdoc-init devdoc-save devdoc-update +############################################################################### +### easyjson ### +############################################################################### +# easyjson must be used for types that are not registered in amino by RegisterConcrete. +easyjson-gen: + @echo "Generating easyjson files" + go get github.com/mailru/easyjson@v0.7.7 + easyjson ./types/result.go + ############################################################################### ### Protobuf ### ############################################################################### diff --git a/codecov.yml b/codecov.yml index 5968480701..b3b729a97d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -57,6 +57,7 @@ ignore: - "*.sh" - "*.png" - "*_test.go" + - "**/*_easyjson.go" - "x/**/*.pb.go" - "x/**/*.pb.gw.go" - "scripts/" diff --git a/go.mod b/go.mod index 466d8be9f3..06d088d2ef 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( github.com/line/tm-db/v2 v2.0.0-init.1.0.20210413083915-5bb60e117524 github.com/line/wasmvm v0.14.0-0.5.0 github.com/magiconair/properties v1.8.4 + github.com/mailru/easyjson v0.7.7 github.com/mattn/go-isatty v0.0.12 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/nxadm/tail v1.4.8 // indirect diff --git a/go.sum b/go.sum index 37366211ed..6c30e58154 100644 --- a/go.sum +++ b/go.sum @@ -298,6 +298,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -347,6 +349,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= diff --git a/types/decimal_internal_test.go b/types/decimal_internal_test.go index 6127267853..9fc9f7c345 100644 --- a/types/decimal_internal_test.go +++ b/types/decimal_internal_test.go @@ -4,6 +4,7 @@ import ( "math/big" "testing" + "github.com/line/lbm-sdk/v2/codec" "github.com/stretchr/testify/suite" ) @@ -22,6 +23,7 @@ func (s *decimalInternalTestSuite) TestPrecisionMultiplier() { } func (s *decimalInternalTestSuite) TestZeroDeserializationJSON() { + var cdc = codec.NewLegacyAmino() d := Dec{new(big.Int)} err := cdc.UnmarshalJSON([]byte(`"0"`), &d) s.Require().Nil(err) @@ -30,6 +32,7 @@ func (s *decimalInternalTestSuite) TestZeroDeserializationJSON() { } func (s *decimalInternalTestSuite) TestSerializationGocodecJSON() { + var cdc = codec.NewLegacyAmino() d := MustNewDecFromStr("0.333") bz, err := cdc.MarshalJSON(d) diff --git a/types/result.go b/types/result.go index f861308ec8..216fe56c5a 100644 --- a/types/result.go +++ b/types/result.go @@ -9,17 +9,14 @@ import ( "github.com/gogo/protobuf/proto" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" abci "github.com/line/ostracon/abci/types" ctypes "github.com/line/ostracon/rpc/core/types" - "github.com/line/lbm-sdk/v2/codec" codectypes "github.com/line/lbm-sdk/v2/codec/types" ) -var cdc = codec.NewLegacyAmino() - func (gi GasInfo) String() string { bz, _ := yaml.Marshal(gi) return string(bz) @@ -40,6 +37,7 @@ func (r Result) GetEvents() Events { } // ABCIMessageLogs represents a slice of ABCIMessageLog. +//easyjson:json type ABCIMessageLogs []ABCIMessageLog func NewABCIMessageLog(i uint32, log string, events Events) ABCIMessageLog { @@ -51,15 +49,15 @@ func NewABCIMessageLog(i uint32, log string, events Events) ABCIMessageLog { } // String implements the fmt.Stringer interface for the ABCIMessageLogs type. -func (logs ABCIMessageLogs) String() (str string) { +func (logs ABCIMessageLogs) String() string { if logs != nil { - raw, err := cdc.MarshalJSON(logs) - if err == nil { - str = string(raw) + res, err := logs.MarshalJSON() + if err != nil { + panic(err) } + return string(res) } - - return str + return "" } // NewResponseResultTx returns a TxResponse given a ResultTx from ostracon diff --git a/types/result_easyjson.go b/types/result_easyjson.go new file mode 100644 index 0000000000..506e3e33f7 --- /dev/null +++ b/types/result_easyjson.go @@ -0,0 +1,326 @@ +// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. + +package types + +import ( + json "encoding/json" + easyjson "github.com/mailru/easyjson" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" +) + +// suppress unused package warning +var ( + _ *json.RawMessage + _ *jlexer.Lexer + _ *jwriter.Writer + _ easyjson.Marshaler +) + +func easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types(in *jlexer.Lexer, out *ABCIMessageLogs) { + isTopLevel := in.IsStart() + if in.IsNull() { + in.Skip() + *out = nil + } else { + in.Delim('[') + if *out == nil { + if !in.IsDelim(']') { + *out = make(ABCIMessageLogs, 0, 1) + } else { + *out = ABCIMessageLogs{} + } + } else { + *out = (*out)[:0] + } + for !in.IsDelim(']') { + var v1 ABCIMessageLog + easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types1(in, &v1) + *out = append(*out, v1) + in.WantComma() + } + in.Delim(']') + } + if isTopLevel { + in.Consumed() + } +} +func easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types(out *jwriter.Writer, in ABCIMessageLogs) { + if in == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v2, v3 := range in { + if v2 > 0 { + out.RawByte(',') + } + easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types1(out, v3) + } + out.RawByte(']') + } +} + +// MarshalJSON supports json.Marshaler interface +func (v ABCIMessageLogs) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v ABCIMessageLogs) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *ABCIMessageLogs) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *ABCIMessageLogs) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types(l, v) +} +func easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types1(in *jlexer.Lexer, out *ABCIMessageLog) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "msg_index": + out.MsgIndex = uint32(in.Uint32()) + case "log": + out.Log = string(in.String()) + case "events": + if in.IsNull() { + in.Skip() + out.Events = nil + } else { + in.Delim('[') + if out.Events == nil { + if !in.IsDelim(']') { + out.Events = make(StringEvents, 0, 1) + } else { + out.Events = StringEvents{} + } + } else { + out.Events = (out.Events)[:0] + } + for !in.IsDelim(']') { + var v4 StringEvent + easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types2(in, &v4) + out.Events = append(out.Events, v4) + in.WantComma() + } + in.Delim(']') + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types1(out *jwriter.Writer, in ABCIMessageLog) { + out.RawByte('{') + first := true + _ = first + if in.MsgIndex != 0 { + const prefix string = ",\"msg_index\":" + first = false + out.RawString(prefix[1:]) + out.Uint32(uint32(in.MsgIndex)) + } + if in.Log != "" { + const prefix string = ",\"log\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Log)) + } + { + const prefix string = ",\"events\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Events == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v5, v6 := range in.Events { + if v5 > 0 { + out.RawByte(',') + } + easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types2(out, v6) + } + out.RawByte(']') + } + } + out.RawByte('}') +} +func easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types2(in *jlexer.Lexer, out *StringEvent) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "type": + out.Type = string(in.String()) + case "attributes": + if in.IsNull() { + in.Skip() + out.Attributes = nil + } else { + in.Delim('[') + if out.Attributes == nil { + if !in.IsDelim(']') { + out.Attributes = make([]Attribute, 0, 2) + } else { + out.Attributes = []Attribute{} + } + } else { + out.Attributes = (out.Attributes)[:0] + } + for !in.IsDelim(']') { + var v7 Attribute + easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types3(in, &v7) + out.Attributes = append(out.Attributes, v7) + in.WantComma() + } + in.Delim(']') + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types2(out *jwriter.Writer, in StringEvent) { + out.RawByte('{') + first := true + _ = first + if in.Type != "" { + const prefix string = ",\"type\":" + first = false + out.RawString(prefix[1:]) + out.String(string(in.Type)) + } + { + const prefix string = ",\"attributes\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Attributes == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v8, v9 := range in.Attributes { + if v8 > 0 { + out.RawByte(',') + } + easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types3(out, v9) + } + out.RawByte(']') + } + } + out.RawByte('}') +} +func easyjsonD3b49167DecodeGithubComLineLbmSdkV2Types3(in *jlexer.Lexer, out *Attribute) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + out.Key = string(in.String()) + case "value": + out.Value = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonD3b49167EncodeGithubComLineLbmSdkV2Types3(out *jwriter.Writer, in Attribute) { + out.RawByte('{') + first := true + _ = first + if in.Key != "" { + const prefix string = ",\"key\":" + first = false + out.RawString(prefix[1:]) + out.String(string(in.Key)) + } + if in.Value != "" { + const prefix string = ",\"value\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Value)) + } + out.RawByte('}') +} diff --git a/types/result_test.go b/types/result_test.go index faeb353799..dc09d6af9b 100644 --- a/types/result_test.go +++ b/types/result_test.go @@ -44,13 +44,77 @@ func (s *resultTestSuite) TestParseABCILog() { func (s *resultTestSuite) TestABCIMessageLog() { cdc := codec.NewLegacyAmino() - events := sdk.Events{sdk.NewEvent("transfer", sdk.NewAttribute("sender", "foo"))} - msgLog := sdk.NewABCIMessageLog(0, "", events) - msgLogs := sdk.ABCIMessageLogs{msgLog} - bz, err := cdc.MarshalJSON(msgLogs) - s.Require().NoError(err) - s.Require().Equal(string(bz), msgLogs.String()) + const maxIter = 5 + + tests := []struct { + emptyLog bool + emptyType bool + emptyKey bool + emptyValue bool + }{ + {false, false, false, false}, + {true, false, false, false}, + {false, true, false, false}, + {false, false, true, false}, + {false, false, false, true}, + {false, false, true, true}, + {false, true, false, true}, + {false, true, true, false}, + {true, false, false, true}, + {true, false, true, false}, + {true, true, false, false}, + {false, true, true, true}, + {true, false, true, true}, + {true, true, false, true}, + {true, true, true, false}, + {true, true, true, true}, + } + + for _, tt := range tests { + msgLogs := sdk.ABCIMessageLogs{} + for numMsgs := 0; numMsgs < maxIter; numMsgs++ { + for i := 0; i < numMsgs; i++ { + events := sdk.Events{} + for numEvents := 0; numEvents < maxIter; numEvents++ { + for j := 0; j < numEvents; j++ { + var attributes []sdk.Attribute + for numAttributes := 0; numAttributes < maxIter; numAttributes++ { + for i := 0; i < numAttributes; i++ { + key := "" + value := "" + if !tt.emptyKey { + key = fmt.Sprintf("key%d", i) + } + if !tt.emptyValue { + value = fmt.Sprintf("value%d", i) + } + attributes = append(attributes, sdk.NewAttribute(key, value)) + } + } + typeStr := "" + if !tt.emptyType { + typeStr = fmt.Sprintf("type%d", i) + } + events = append(events, sdk.NewEvent(typeStr, attributes...)) + } + } + + log := "" + if !tt.emptyLog { + log = fmt.Sprintf("log%d", i) + } + msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint32(i), log, events)) + } + } + bz, err := cdc.MarshalJSON(msgLogs) + + s.Require().NoError(err) + s.Require().Equal(string(bz), msgLogs.String()) + } + + var msgLogs sdk.ABCIMessageLogs + s.Require().Equal("", msgLogs.String()) } func (s *resultTestSuite) TestNewSearchTxsResult() {