diff --git a/core/scripts/go.mod b/core/scripts/go.mod index d5ec9beeb53..9603be6368e 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -19,7 +19,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.1 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20231130143053-c5102a9c0fb7 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 9c401125a27..d1df655c6ed 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1164,8 +1164,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f h1:7904h45vNBT+IVO7PMcucvNXSIS9ilf2cxf+RMYb7zs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5 h1:o36okzBAbWhlxKrIeb66Iw/U7Uy3j4FsPGQREb06SUo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71 h1:Ju0cxdrzGFwHGDPp16IzkOyX87LZ/kKDFG1A+VSEJHY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71/go.mod h1:Ppv5X8MTUkkpKdb270dLefjio724vMkCWmSSaWo7CzI= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index b8e7f20cc21..f9d2161460b 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -45,7 +45,7 @@ func NewChainReaderService(lggr logger.Logger, lp logpoller.LogPoller, chain leg lp: lp, client: chain.Client(), contractBindings: contractBindings{}, - parsed: &parsedTypes{encoderDefs: map[string]*codecEntry{}, decoderDefs: map[string]*codecEntry{}}, + parsed: &parsedTypes{encoderDefs: map[string]types.CodecEntry{}, decoderDefs: map[string]types.CodecEntry{}}, } var err error @@ -208,7 +208,7 @@ func (cr *chainReader) addEvent(contractName, eventName string, a abi.ABI, chain } func (cr *chainReader) getEventInput(def types.ChainReaderDefinition, contractName, eventName string) ( - *codecEntry, codec.Modifier, error) { + types.CodecEntry, codec.Modifier, error) { inputInfo := cr.parsed.encoderDefs[wrapItemType(contractName, eventName, true)] inMod, err := def.InputModifications.ToModifier(evmDecoderHooks...) if err != nil { @@ -216,7 +216,7 @@ func (cr *chainReader) getEventInput(def types.ChainReaderDefinition, contractNa } // initialize the modification - if _, err = inMod.RetypeForOffChain(reflect.PointerTo(inputInfo.checkedType), ""); err != nil { + if _, err = inMod.RetypeForOffChain(reflect.PointerTo(inputInfo.CheckedType()), ""); err != nil { return nil, nil, err } @@ -234,41 +234,39 @@ func verifyEventInputsUsed(chainReaderDefinition types.ChainReaderDefinition, in func (cr *chainReader) addEncoderDef(contractName, methodName string, args abi.Arguments, prefix []byte, chainReaderDefinition types.ChainReaderDefinition) error { // ABI.Pack prepends the method.ID to the encodings, we'll need the encoder to do the same. - input := &codecEntry{Args: args, encodingPrefix: prefix} - - if err := input.Init(); err != nil { + inputMod, err := chainReaderDefinition.InputModifications.ToModifier(evmDecoderHooks...) + if err != nil { return err } + input := types.NewCodecEntry(args, prefix, inputMod) - inputMod, err := chainReaderDefinition.InputModifications.ToModifier(evmDecoderHooks...) - if err != nil { + if err := input.Init(); err != nil { return err } - input.mod = inputMod + cr.parsed.encoderDefs[wrapItemType(contractName, methodName, true)] = input return nil } func (cr *chainReader) addDecoderDef(contractName, methodName string, outputs abi.Arguments, def types.ChainReaderDefinition) error { - output := &codecEntry{Args: outputs} mod, err := def.OutputModifications.ToModifier(evmDecoderHooks...) if err != nil { return err } - output.mod = mod + output := types.NewCodecEntry(outputs, nil, mod) cr.parsed.decoderDefs[wrapItemType(contractName, methodName, false)] = output return output.Init() } -func setupEventInput(event abi.Event, def types.ChainReaderDefinition) ([]abi.Argument, *codecEntry, map[string]bool) { +func setupEventInput(event abi.Event, def types.ChainReaderDefinition) ([]abi.Argument, types.CodecEntry, map[string]bool) { topicFieldDefs := map[string]bool{} for _, value := range def.EventInputFields { capFirstValue := abi.ToCamelCase(value) topicFieldDefs[capFirstValue] = true } - filterArgs := make([]abi.Argument, 0, maxTopicFields) - info := &codecEntry{} + filterArgs := make([]abi.Argument, 0, types.MaxTopicFields) + inputArgs := make([]abi.Argument, 0, len(event.Inputs)) indexArgNames := map[string]bool{} for _, input := range event.Inputs { @@ -286,9 +284,9 @@ func setupEventInput(event abi.Event, def types.ChainReaderDefinition) ([]abi.Ar filterArgs = append(filterArgs, inputUnindexed) } - info.Args = append(info.Args, input) + inputArgs = append(inputArgs, input) indexArgNames[abi.ToCamelCase(input.Name)] = true } - return filterArgs, info, indexArgNames + return filterArgs, types.NewCodecEntry(inputArgs, nil, nil), indexArgNames } diff --git a/core/services/relay/evm/codec.go b/core/services/relay/evm/codec.go index 8655831a588..c371897379e 100644 --- a/core/services/relay/evm/codec.go +++ b/core/services/relay/evm/codec.go @@ -36,8 +36,8 @@ var evmDecoderHooks = []mapstructure.DecodeHookFunc{decodeAccountHook, codec.Big // eg: rename FooBar -> Bar, not foo_bar_ to Bar if the name on-chain is foo_bar_ func NewCodec(conf types.CodecConfig) (commontypes.RemoteCodec, error) { parsed := &parsedTypes{ - encoderDefs: map[string]*codecEntry{}, - decoderDefs: map[string]*codecEntry{}, + encoderDefs: map[string]types.CodecEntry{}, + decoderDefs: map[string]types.CodecEntry{}, } for k, v := range conf.ChainCodecConfigs { @@ -51,7 +51,7 @@ func NewCodec(conf types.CodecConfig) (commontypes.RemoteCodec, error) { return nil, err } - item := &codecEntry{Args: args, mod: mod} + item := types.NewCodecEntry(args, nil, mod) if err = item.Init(); err != nil { return nil, err } @@ -70,7 +70,7 @@ type evmCodec struct { } func (c *evmCodec) CreateType(itemType string, forEncoding bool) (any, error) { - var itemTypes map[string]*codecEntry + var itemTypes map[string]types.CodecEntry if forEncoding { itemTypes = c.encoderDefs } else { @@ -82,7 +82,7 @@ func (c *evmCodec) CreateType(itemType string, forEncoding bool) (any, error) { return nil, fmt.Errorf("%w: cannot find type name %s", commontypes.ErrInvalidType, itemType) } - return reflect.New(def.checkedType).Interface(), nil + return reflect.New(def.CheckedType()).Interface(), nil } var bigIntType = reflect.TypeOf((*big.Int)(nil)) diff --git a/core/services/relay/evm/codec_entry_test.go b/core/services/relay/evm/codec_entry_test.go deleted file mode 100644 index 62a6bf25368..00000000000 --- a/core/services/relay/evm/codec_entry_test.go +++ /dev/null @@ -1,219 +0,0 @@ -package evm - -import ( - "math/big" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -func TestCodecEntry(t *testing.T) { - t.Run("basic types", func(t *testing.T) { - type1, err := abi.NewType("uint16", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - type2, err := abi.NewType("string", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - type3, err := abi.NewType("uint24", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - type4, err := abi.NewType("int24", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{ - Args: abi.Arguments{ - {Name: "Field1", Type: type1}, - {Name: "Field2", Type: type2}, - {Name: "Field3", Type: type3}, - {Name: "Field4", Type: type4}, - }, - } - require.NoError(t, entry.Init()) - native := reflect.New(entry.nativeType) - iNative := reflect.Indirect(native) - iNative.FieldByName("Field1").Set(reflect.ValueOf(uint16(2))) - iNative.FieldByName("Field2").Set(reflect.ValueOf("any string")) - iNative.FieldByName("Field3").Set(reflect.ValueOf(big.NewInt( /*2^24 - 1*/ 16777215))) - iNative.FieldByName("Field4").Set(reflect.ValueOf(big.NewInt( /*2^23 - 1*/ 8388607))) - // native and checked point to the same item, even though they have different "types" - // they have the same memory layout so this is safe per unsafe casting rules, see unsafe.Pointer for details - checked := reflect.NewAt(entry.checkedType, native.UnsafePointer()) - iChecked := reflect.Indirect(checked) - checkedField := iChecked.FieldByName("Field3").Interface() - - sbi, ok := checkedField.(types.SizedBigInt) - require.True(t, ok) - assert.NoError(t, sbi.Verify()) - bi, ok := iNative.FieldByName("Field3").Interface().(*big.Int) - require.True(t, ok) - bi.Add(bi, big.NewInt(1)) - assert.IsType(t, commontypes.ErrInvalidType, sbi.Verify()) - bi, ok = iNative.FieldByName("Field4").Interface().(*big.Int) - require.True(t, ok) - bi.Add(bi, big.NewInt(1)) - assert.IsType(t, commontypes.ErrInvalidType, sbi.Verify()) - }) - - t.Run("tuples", func(t *testing.T) { - type1, err := abi.NewType("uint16", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - tupleType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ - {Name: "Field3", Type: "uint24"}, - {Name: "Field4", Type: "int24"}, - }) - require.NoError(t, err) - entry := codecEntry{ - Args: abi.Arguments{ - {Name: "Field1", Type: type1}, - {Name: "Field2", Type: tupleType}, - }, - } - require.NoError(t, entry.Init()) - native := reflect.New(entry.nativeType) - iNative := reflect.Indirect(native) - iNative.FieldByName("Field1").Set(reflect.ValueOf(uint16(2))) - f2 := iNative.FieldByName("Field2") - f2.FieldByName("Field3").Set(reflect.ValueOf(big.NewInt( /*2^24 - 1*/ 16777215))) - f2.FieldByName("Field4").Set(reflect.ValueOf(big.NewInt( /*2^23 - 1*/ 8388607))) - // native and checked point to the same item, even though they have different "types" - // they have the same memory layout so this is safe per unsafe casting rules, see unsafe.Pointer for details - checked := reflect.NewAt(entry.checkedType, native.UnsafePointer()) - tuple := reflect.Indirect(checked).FieldByName("Field2") - checkedField := tuple.FieldByName("Field3").Interface() - - sbi, ok := checkedField.(types.SizedBigInt) - require.True(t, ok) - assert.NoError(t, sbi.Verify()) - bi, ok := f2.FieldByName("Field3").Interface().(*big.Int) - require.True(t, ok) - bi.Add(bi, big.NewInt(1)) - assert.IsType(t, commontypes.ErrInvalidType, sbi.Verify()) - bi, ok = f2.FieldByName("Field4").Interface().(*big.Int) - require.True(t, ok) - bi.Add(bi, big.NewInt(1)) - assert.IsType(t, commontypes.ErrInvalidType, sbi.Verify()) - }) - - t.Run("unwrapped types", func(t *testing.T) { - // This exists to allow you to decode single returned values without naming the parameter - wrappedTuple, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ - {Name: "Field1", Type: "int16"}, - }) - require.NoError(t, err) - entry := codecEntry{ - Args: abi.Arguments{{Name: "", Type: wrappedTuple}}, - } - require.NoError(t, entry.Init()) - native := reflect.New(entry.nativeType) - iNative := reflect.Indirect(native) - iNative.FieldByName("Field1").Set(reflect.ValueOf(int16(2))) - }) - - t.Run("slice types", func(t *testing.T) { - type1, err := abi.NewType("int16[]", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{ - Args: abi.Arguments{{Name: "Field1", Type: type1}}, - } - require.NoError(t, entry.Init()) - native := reflect.New(entry.nativeType) - iNative := reflect.Indirect(native) - iNative.FieldByName("Field1").Set(reflect.ValueOf([]int16{2, 3})) - }) - - t.Run("array types", func(t *testing.T) { - type1, err := abi.NewType("int16[3]", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{ - Args: abi.Arguments{{Name: "Field1", Type: type1}}, - } - require.NoError(t, entry.Init()) - native := reflect.New(entry.nativeType) - iNative := reflect.Indirect(native) - iNative.FieldByName("Field1").Set(reflect.ValueOf([3]int16{2, 3, 30})) - }) - - t.Run("Not return values makes struct{}", func(t *testing.T) { - entry := codecEntry{Args: abi.Arguments{}} - require.NoError(t, entry.Init()) - assert.Equal(t, reflect.TypeOf(struct{}{}), entry.nativeType) - assert.Equal(t, reflect.TypeOf(struct{}{}), entry.checkedType) - }) - - t.Run("Address works", func(t *testing.T) { - address, err := abi.NewType("address", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{Args: abi.Arguments{{Name: "foo", Type: address}}} - require.NoError(t, entry.Init()) - }) - - t.Run("Multiple unnamed parameters are not supported", func(t *testing.T) { - anyType, err := abi.NewType("int16[3]", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{Args: abi.Arguments{{Name: "", Type: anyType}, {Name: "", Type: anyType}}} - assert.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidType)) - }) - - t.Run("Multiple abi arguments with the same name returns an error", func(t *testing.T) { - anyType, err := abi.NewType("int16[3]", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{Args: abi.Arguments{{Name: "Name", Type: anyType}, {Name: "Name", Type: anyType}}} - assert.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidConfig)) - }) - - t.Run("Indexed basic types leave their native and checked types as-is", func(t *testing.T) { - anyType, err := abi.NewType("int16", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{Args: abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}} - require.NoError(t, entry.Init()) - nativeField, ok := entry.nativeType.FieldByName("Name") - require.True(t, ok) - assert.Equal(t, reflect.TypeOf(int16(0)), nativeField.Type) - checkedField, ok := entry.checkedType.FieldByName("Name") - require.True(t, ok) - assert.Equal(t, reflect.TypeOf(int16(0)), checkedField.Type) - }) - - t.Run("Indexed non basic types change to hash", func(t *testing.T) { - anyType, err := abi.NewType("string", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{Args: abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}} - require.NoError(t, entry.Init()) - nativeField, ok := entry.nativeType.FieldByName("Name") - require.True(t, ok) - assert.Equal(t, reflect.TypeOf(common.Hash{}), nativeField.Type) - checkedField, ok := entry.checkedType.FieldByName("Name") - require.True(t, ok) - assert.Equal(t, reflect.TypeOf(common.Hash{}), checkedField.Type) - }) - - t.Run("Too many indexed items returns an error", func(t *testing.T) { - anyType, err := abi.NewType("int16", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{ - Args: abi.Arguments{ - {Name: "Name1", Type: anyType, Indexed: true}, - {Name: "Name2", Type: anyType, Indexed: true}, - {Name: "Name3", Type: anyType, Indexed: true}, - {Name: "Name4", Type: anyType, Indexed: true}, - }, - } - require.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidConfig)) - }) - - // TODO: when the TODO on - // https://github.com/ethereum/go-ethereum/blob/release/1.12/accounts/abi/topics.go#L78 - // is removed, remove this test. - t.Run("Using unsupported types by go-ethereum returns an error", func(t *testing.T) { - anyType, err := abi.NewType("int256[2]", "", []abi.ArgumentMarshaling{}) - require.NoError(t, err) - entry := codecEntry{Args: abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}} - assert.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidConfig)) - }) -} diff --git a/core/services/relay/evm/codec_test.go b/core/services/relay/evm/codec_test.go index b281039759c..e3694dc4aed 100644 --- a/core/services/relay/evm/codec_test.go +++ b/core/services/relay/evm/codec_test.go @@ -32,7 +32,7 @@ func TestCodec(t *testing.T) { actual, err := c.GetMaxEncodingSize(testutils.Context(t), anyN, sizeItemType) assert.NoError(t, err) - expected, err := evm.GetMaxSize(anyN, parseDefs(t)[sizeItemType]) + expected, err := types.GetMaxSize(anyN, parseDefs(t)[sizeItemType]) require.NoError(t, err) assert.Equal(t, expected, actual) }) @@ -41,7 +41,7 @@ func TestCodec(t *testing.T) { actual, err := c.GetMaxDecodingSize(testutils.Context(t), anyN, sizeItemType) assert.NoError(t, err) - expected, err := evm.GetMaxSize(anyN, parseDefs(t)[sizeItemType]) + expected, err := types.GetMaxSize(anyN, parseDefs(t)[sizeItemType]) require.NoError(t, err) assert.Equal(t, expected, actual) }) diff --git a/core/services/relay/evm/decoder.go b/core/services/relay/evm/decoder.go index 1520afa0fd9..f16875d80f6 100644 --- a/core/services/relay/evm/decoder.go +++ b/core/services/relay/evm/decoder.go @@ -8,15 +8,17 @@ import ( "github.com/mitchellh/mapstructure" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) type decoder struct { - Definitions map[string]*codecEntry + Definitions map[string]types.CodecEntry } var _ commontypes.Decoder = &decoder{} -func (m *decoder) Decode(ctx context.Context, raw []byte, into any, itemType string) error { +func (m *decoder) Decode(_ context.Context, raw []byte, into any, itemType string) error { info, ok := m.Definitions[itemType] if !ok { return fmt.Errorf("%w: cannot find definition for %s", commontypes.ErrInvalidType, itemType) @@ -51,14 +53,19 @@ func (m *decoder) decodeArray(into any, rDecode reflect.Value) error { return setElements(length, rDecode, iInto) } -func (m *decoder) GetMaxDecodingSize(ctx context.Context, n int, itemType string) (int, error) { - return m.Definitions[itemType].GetMaxSize(n) +func (m *decoder) GetMaxDecodingSize(_ context.Context, n int, itemType string) (int, error) { + entry, ok := m.Definitions[itemType] + if !ok { + return 0, fmt.Errorf("%w: nil entry", commontypes.ErrInvalidType) + } + return entry.GetMaxSize(n) } -func extractDecoding(info *codecEntry, raw []byte) (any, error) { +func extractDecoding(info types.CodecEntry, raw []byte) (any, error) { unpacked := map[string]any{} - if err := info.Args.UnpackIntoMap(unpacked, raw); err != nil { - return nil, fmt.Errorf("%w: %w: for args %#v", commontypes.ErrInvalidEncoding, err, info.Args) + args := info.Args() + if err := args.UnpackIntoMap(unpacked, raw); err != nil { + return nil, fmt.Errorf("%w: %w: for args %#v", commontypes.ErrInvalidEncoding, err, args) } var decode any = unpacked diff --git a/core/services/relay/evm/encoder.go b/core/services/relay/evm/encoder.go index 7af0d7f7bce..afead53f34e 100644 --- a/core/services/relay/evm/encoder.go +++ b/core/services/relay/evm/encoder.go @@ -6,15 +6,17 @@ import ( "reflect" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) type encoder struct { - Definitions map[string]*codecEntry + Definitions map[string]types.CodecEntry } var _ commontypes.Encoder = &encoder{} -func (e *encoder) Encode(ctx context.Context, item any, itemType string) (res []byte, err error) { +func (e *encoder) Encode(_ context.Context, item any, itemType string) (res []byte, err error) { // nil values can cause abi.Arguments.Pack to panic. defer func() { if r := recover(); r != nil { @@ -28,19 +30,21 @@ func (e *encoder) Encode(ctx context.Context, item any, itemType string) (res [] } if item == nil { - cpy := make([]byte, len(info.encodingPrefix)) - copy(cpy, info.encodingPrefix) - return cpy, nil + return info.EncodingPrefix(), nil } return encode(reflect.ValueOf(item), info) } -func (e *encoder) GetMaxEncodingSize(ctx context.Context, n int, itemType string) (int, error) { - return e.Definitions[itemType].GetMaxSize(n) +func (e *encoder) GetMaxEncodingSize(_ context.Context, n int, itemType string) (int, error) { + entry, ok := e.Definitions[itemType] + if !ok { + return 0, fmt.Errorf("%w: nil entry", commontypes.ErrInvalidType) + } + return entry.GetMaxSize(n) } -func encode(item reflect.Value, info *codecEntry) ([]byte, error) { +func encode(item reflect.Value, info types.CodecEntry) ([]byte, error) { for item.Kind() == reflect.Pointer { item = reflect.Indirect(item) } @@ -62,42 +66,58 @@ func encode(item reflect.Value, info *codecEntry) ([]byte, error) { } } -func representArray(item reflect.Value, info *codecEntry) (any, error) { +func representArray(item reflect.Value, info types.CodecEntry) (any, error) { length := item.Len() - var native reflect.Value - switch info.checkedType.Kind() { + checkedType := info.CheckedType() + checked := reflect.New(checkedType) + iChecked := reflect.Indirect(checked) + switch checkedType.Kind() { case reflect.Array: - if info.checkedType.Len() != length { + if checkedType.Len() != length { return nil, commontypes.ErrSliceWrongLen } - native = reflect.New(info.nativeType).Elem() case reflect.Slice: - native = reflect.MakeSlice(info.nativeType, length, length) + iChecked.Set(reflect.MakeSlice(checkedType, length, length)) default: - return nil, fmt.Errorf("%w: cannot encode %v as array", commontypes.ErrInvalidType, info.checkedType.Kind()) + return nil, fmt.Errorf("%w: cannot encode %v as array", commontypes.ErrInvalidType, checkedType.Kind()) } - checkedElm := info.checkedType.Elem() - nativeElm := info.nativeType.Elem() + checkedElm := checkedType.Elem() for i := 0; i < length; i++ { tmp := reflect.New(checkedElm) if err := mapstructureDecode(item.Index(i).Interface(), tmp.Interface()); err != nil { return nil, err } - native.Index(i).Set(reflect.NewAt(nativeElm, tmp.UnsafePointer()).Elem()) + iChecked.Index(i).Set(tmp.Elem()) } - return native.Interface(), nil + native, err := info.ToNative(checked) + if err != nil { + return nil, err + } + + return native.Elem().Interface(), nil } -func unrollItem(item reflect.Value, info *codecEntry) ([]any, error) { - if item.Type() == reflect.PointerTo(info.checkedType) { - item = reflect.NewAt(info.nativeType, item.UnsafePointer()) - } else if item.Type() != reflect.PointerTo(info.nativeType) { - checked := reflect.New(info.checkedType) - if err := mapstructureDecode(item.Interface(), checked.Interface()); err != nil { +func unrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { + checkedType := info.CheckedType() + if item.CanAddr() { + item = item.Addr() + } + + if item.Type() == reflect.PointerTo(checkedType) { + var err error + if item, err = info.ToNative(item); err != nil { + return nil, err + } + } else if !info.IsNativePointer(item.Type()) { + var err error + checked := reflect.New(checkedType) + if err = mapstructureDecode(item.Interface(), checked.Interface()); err != nil { + return nil, err + } + if item, err = info.ToNative(checked); err != nil { return nil, err } - item = reflect.NewAt(info.nativeType, checked.UnsafePointer()) } item = reflect.Indirect(item) @@ -112,13 +132,12 @@ func unrollItem(item reflect.Value, info *codecEntry) ([]any, error) { return values, nil } -func pack(info *codecEntry, values ...any) ([]byte, error) { - bytes, err := info.Args.Pack(values...) +func pack(info types.CodecEntry, values ...any) ([]byte, error) { + bytes, err := info.Args().Pack(values...) if err != nil { return nil, fmt.Errorf("%w: %w", commontypes.ErrInvalidType, err) } - withPrefix := make([]byte, 0, len(info.encodingPrefix)+len(bytes)) - withPrefix = append(withPrefix, info.encodingPrefix...) + withPrefix := info.EncodingPrefix() return append(withPrefix, bytes...), nil } diff --git a/core/services/relay/evm/event_binding.go b/core/services/relay/evm/event_binding.go index 8ad9669c073..f520e6f0f82 100644 --- a/core/services/relay/evm/event_binding.go +++ b/core/services/relay/evm/event_binding.go @@ -15,11 +15,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -// Max four topics on EVM, the first topic is always the event signature, so 3 topics left for fields -const maxTopicFields = 3 - type eventBinding struct { address common.Address contractName string @@ -31,9 +29,9 @@ type eventBinding struct { bound bool registerCalled bool lock sync.Mutex - inputInfo *codecEntry + inputInfo types.CodecEntry inputModifier codec.Modifier - topicInfo *codecEntry + topicInfo types.CodecEntry // used to allow Register and Unregister to be unique in case two bindings have the same event. // otherwise, if one unregisters, it'll unregister both with the LogPoller. id string @@ -88,7 +86,7 @@ func (e *eventBinding) GetLatestValue(ctx context.Context, params, into any) err confs = logpoller.Unconfirmed } - if len(e.inputInfo.Args) == 0 { + if len(e.inputInfo.Args()) == 0 { return e.getLatestValueWithoutFilters(ctx, confs, into) } @@ -131,7 +129,11 @@ func (e *eventBinding) getLatestValueWithFilters( return err } - nativeParams := reflect.NewAt(e.inputInfo.nativeType, reflect.ValueOf(checkedParams).UnsafePointer()) + nativeParams, err := e.inputInfo.ToNative(reflect.ValueOf(checkedParams)) + if err != nil { + return err + } + filtersAndIndices, err := e.encodeParams(nativeParams) if err != nil { return err @@ -240,7 +242,7 @@ func (e *eventBinding) decodeLog(ctx context.Context, log *logpoller.Log, into a return err } - topics := make([]common.Hash, len(e.topicInfo.Args)) + topics := make([]common.Hash, len(e.topicInfo.Args())) if len(log.Topics) < len(topics)+1 { return fmt.Errorf("%w: not enough topics to decode", commontypes.ErrInvalidType) } @@ -250,7 +252,7 @@ func (e *eventBinding) decodeLog(ctx context.Context, log *logpoller.Log, into a } topicsInto := map[string]any{} - if err := abi.ParseTopicsIntoMap(topicsInto, e.topicInfo.Args, topics); err != nil { + if err := abi.ParseTopicsIntoMap(topicsInto, e.topicInfo.Args(), topics); err != nil { return fmt.Errorf("%w: %w", commontypes.ErrInvalidType, err) } diff --git a/core/services/relay/evm/parsed_types.go b/core/services/relay/evm/parsed_types.go index da54d5c15a3..8ffa9ae0a6a 100644 --- a/core/services/relay/evm/parsed_types.go +++ b/core/services/relay/evm/parsed_types.go @@ -6,11 +6,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) type parsedTypes struct { - encoderDefs map[string]*codecEntry - decoderDefs map[string]*codecEntry + encoderDefs map[string]types.CodecEntry + decoderDefs map[string]types.CodecEntry } func (parsed *parsedTypes) toCodec() (commontypes.RemoteCodec, error) { @@ -36,10 +38,10 @@ func (parsed *parsedTypes) toCodec() (commontypes.RemoteCodec, error) { // addEntries extracts the mods from codecEntry and adds them to modByTypeName use with codec.NewByItemTypeModifier // Since each input/output can have its own modifications, we need to keep track of them by type name -func addEntries(defs map[string]*codecEntry, modByTypeName map[string]codec.Modifier) error { +func addEntries(defs map[string]types.CodecEntry, modByTypeName map[string]codec.Modifier) error { for k, def := range defs { - modByTypeName[k] = def.mod - _, err := def.mod.RetypeForOffChain(reflect.PointerTo(def.checkedType), k) + modByTypeName[k] = def.Modifier() + _, err := def.Modifier().RetypeForOffChain(reflect.PointerTo(def.CheckedType()), k) if err != nil { return fmt.Errorf("%w: cannot retype %v: %w", commontypes.ErrInvalidConfig, k, err) } diff --git a/core/services/relay/evm/types/abi_types.go b/core/services/relay/evm/types/abi_types.go index a3a02a41bc2..34b12d885b4 100644 --- a/core/services/relay/evm/types/abi_types.go +++ b/core/services/relay/evm/types/abi_types.go @@ -10,54 +10,54 @@ import ( var typeMap = map[string]*ABIEncodingType{ "bool": { - Native: reflect.TypeOf(true), - Checked: reflect.TypeOf(true), + native: reflect.TypeOf(true), + checked: reflect.TypeOf(true), }, "int8": { - Native: reflect.TypeOf(int8(0)), - Checked: reflect.TypeOf(int8(0)), + native: reflect.TypeOf(int8(0)), + checked: reflect.TypeOf(int8(0)), }, "int16": { - Native: reflect.TypeOf(int16(0)), - Checked: reflect.TypeOf(int16(0)), + native: reflect.TypeOf(int16(0)), + checked: reflect.TypeOf(int16(0)), }, "int32": { - Native: reflect.TypeOf(int32(0)), - Checked: reflect.TypeOf(int32(0)), + native: reflect.TypeOf(int32(0)), + checked: reflect.TypeOf(int32(0)), }, "int64": { - Native: reflect.TypeOf(int64(0)), - Checked: reflect.TypeOf(int64(0)), + native: reflect.TypeOf(int64(0)), + checked: reflect.TypeOf(int64(0)), }, "uint8": { - Native: reflect.TypeOf(uint8(0)), - Checked: reflect.TypeOf(uint8(0)), + native: reflect.TypeOf(uint8(0)), + checked: reflect.TypeOf(uint8(0)), }, "uint16": { - Native: reflect.TypeOf(uint16(0)), - Checked: reflect.TypeOf(uint16(0)), + native: reflect.TypeOf(uint16(0)), + checked: reflect.TypeOf(uint16(0)), }, "uint32": { - Native: reflect.TypeOf(uint32(0)), - Checked: reflect.TypeOf(uint32(0)), + native: reflect.TypeOf(uint32(0)), + checked: reflect.TypeOf(uint32(0)), }, "uint64": { - Native: reflect.TypeOf(uint64(0)), - Checked: reflect.TypeOf(uint64(0)), + native: reflect.TypeOf(uint64(0)), + checked: reflect.TypeOf(uint64(0)), }, "string": { - Native: reflect.TypeOf(""), - Checked: reflect.TypeOf(""), + native: reflect.TypeOf(""), + checked: reflect.TypeOf(""), }, "address": { - Native: reflect.TypeOf(common.Address{}), - Checked: reflect.TypeOf(common.Address{}), + native: reflect.TypeOf(common.Address{}), + checked: reflect.TypeOf(common.Address{}), }, } type ABIEncodingType struct { - Native reflect.Type - Checked reflect.Type + native reflect.Type + checked reflect.Type } func GetAbiEncodingType(name string) (*ABIEncodingType, bool) { diff --git a/core/services/relay/evm/types/byte_types_gen.go b/core/services/relay/evm/types/byte_types_gen.go index fb9fd9bdb5c..cf8d15ccabc 100644 --- a/core/services/relay/evm/types/byte_types_gen.go +++ b/core/services/relay/evm/types/byte_types_gen.go @@ -6,8 +6,8 @@ type bytes1 [1]byte func init() { typeMap["bytes1"] = &ABIEncodingType{ - Native: reflect.TypeOf([1]byte{}), - Checked: reflect.TypeOf(bytes1{}), + native: reflect.TypeOf([1]byte{}), + checked: reflect.TypeOf(bytes1{}), } } @@ -15,8 +15,8 @@ type bytes2 [2]byte func init() { typeMap["bytes2"] = &ABIEncodingType{ - Native: reflect.TypeOf([2]byte{}), - Checked: reflect.TypeOf(bytes2{}), + native: reflect.TypeOf([2]byte{}), + checked: reflect.TypeOf(bytes2{}), } } @@ -24,8 +24,8 @@ type bytes3 [3]byte func init() { typeMap["bytes3"] = &ABIEncodingType{ - Native: reflect.TypeOf([3]byte{}), - Checked: reflect.TypeOf(bytes3{}), + native: reflect.TypeOf([3]byte{}), + checked: reflect.TypeOf(bytes3{}), } } @@ -33,8 +33,8 @@ type bytes4 [4]byte func init() { typeMap["bytes4"] = &ABIEncodingType{ - Native: reflect.TypeOf([4]byte{}), - Checked: reflect.TypeOf(bytes4{}), + native: reflect.TypeOf([4]byte{}), + checked: reflect.TypeOf(bytes4{}), } } @@ -42,8 +42,8 @@ type bytes5 [5]byte func init() { typeMap["bytes5"] = &ABIEncodingType{ - Native: reflect.TypeOf([5]byte{}), - Checked: reflect.TypeOf(bytes5{}), + native: reflect.TypeOf([5]byte{}), + checked: reflect.TypeOf(bytes5{}), } } @@ -51,8 +51,8 @@ type bytes6 [6]byte func init() { typeMap["bytes6"] = &ABIEncodingType{ - Native: reflect.TypeOf([6]byte{}), - Checked: reflect.TypeOf(bytes6{}), + native: reflect.TypeOf([6]byte{}), + checked: reflect.TypeOf(bytes6{}), } } @@ -60,8 +60,8 @@ type bytes7 [7]byte func init() { typeMap["bytes7"] = &ABIEncodingType{ - Native: reflect.TypeOf([7]byte{}), - Checked: reflect.TypeOf(bytes7{}), + native: reflect.TypeOf([7]byte{}), + checked: reflect.TypeOf(bytes7{}), } } @@ -69,8 +69,8 @@ type bytes8 [8]byte func init() { typeMap["bytes8"] = &ABIEncodingType{ - Native: reflect.TypeOf([8]byte{}), - Checked: reflect.TypeOf(bytes8{}), + native: reflect.TypeOf([8]byte{}), + checked: reflect.TypeOf(bytes8{}), } } @@ -78,8 +78,8 @@ type bytes9 [9]byte func init() { typeMap["bytes9"] = &ABIEncodingType{ - Native: reflect.TypeOf([9]byte{}), - Checked: reflect.TypeOf(bytes9{}), + native: reflect.TypeOf([9]byte{}), + checked: reflect.TypeOf(bytes9{}), } } @@ -87,8 +87,8 @@ type bytes10 [10]byte func init() { typeMap["bytes10"] = &ABIEncodingType{ - Native: reflect.TypeOf([10]byte{}), - Checked: reflect.TypeOf(bytes10{}), + native: reflect.TypeOf([10]byte{}), + checked: reflect.TypeOf(bytes10{}), } } @@ -96,8 +96,8 @@ type bytes11 [11]byte func init() { typeMap["bytes11"] = &ABIEncodingType{ - Native: reflect.TypeOf([11]byte{}), - Checked: reflect.TypeOf(bytes11{}), + native: reflect.TypeOf([11]byte{}), + checked: reflect.TypeOf(bytes11{}), } } @@ -105,8 +105,8 @@ type bytes12 [12]byte func init() { typeMap["bytes12"] = &ABIEncodingType{ - Native: reflect.TypeOf([12]byte{}), - Checked: reflect.TypeOf(bytes12{}), + native: reflect.TypeOf([12]byte{}), + checked: reflect.TypeOf(bytes12{}), } } @@ -114,8 +114,8 @@ type bytes13 [13]byte func init() { typeMap["bytes13"] = &ABIEncodingType{ - Native: reflect.TypeOf([13]byte{}), - Checked: reflect.TypeOf(bytes13{}), + native: reflect.TypeOf([13]byte{}), + checked: reflect.TypeOf(bytes13{}), } } @@ -123,8 +123,8 @@ type bytes14 [14]byte func init() { typeMap["bytes14"] = &ABIEncodingType{ - Native: reflect.TypeOf([14]byte{}), - Checked: reflect.TypeOf(bytes14{}), + native: reflect.TypeOf([14]byte{}), + checked: reflect.TypeOf(bytes14{}), } } @@ -132,8 +132,8 @@ type bytes15 [15]byte func init() { typeMap["bytes15"] = &ABIEncodingType{ - Native: reflect.TypeOf([15]byte{}), - Checked: reflect.TypeOf(bytes15{}), + native: reflect.TypeOf([15]byte{}), + checked: reflect.TypeOf(bytes15{}), } } @@ -141,8 +141,8 @@ type bytes16 [16]byte func init() { typeMap["bytes16"] = &ABIEncodingType{ - Native: reflect.TypeOf([16]byte{}), - Checked: reflect.TypeOf(bytes16{}), + native: reflect.TypeOf([16]byte{}), + checked: reflect.TypeOf(bytes16{}), } } @@ -150,8 +150,8 @@ type bytes17 [17]byte func init() { typeMap["bytes17"] = &ABIEncodingType{ - Native: reflect.TypeOf([17]byte{}), - Checked: reflect.TypeOf(bytes17{}), + native: reflect.TypeOf([17]byte{}), + checked: reflect.TypeOf(bytes17{}), } } @@ -159,8 +159,8 @@ type bytes18 [18]byte func init() { typeMap["bytes18"] = &ABIEncodingType{ - Native: reflect.TypeOf([18]byte{}), - Checked: reflect.TypeOf(bytes18{}), + native: reflect.TypeOf([18]byte{}), + checked: reflect.TypeOf(bytes18{}), } } @@ -168,8 +168,8 @@ type bytes19 [19]byte func init() { typeMap["bytes19"] = &ABIEncodingType{ - Native: reflect.TypeOf([19]byte{}), - Checked: reflect.TypeOf(bytes19{}), + native: reflect.TypeOf([19]byte{}), + checked: reflect.TypeOf(bytes19{}), } } @@ -177,8 +177,8 @@ type bytes20 [20]byte func init() { typeMap["bytes20"] = &ABIEncodingType{ - Native: reflect.TypeOf([20]byte{}), - Checked: reflect.TypeOf(bytes20{}), + native: reflect.TypeOf([20]byte{}), + checked: reflect.TypeOf(bytes20{}), } } @@ -186,8 +186,8 @@ type bytes21 [21]byte func init() { typeMap["bytes21"] = &ABIEncodingType{ - Native: reflect.TypeOf([21]byte{}), - Checked: reflect.TypeOf(bytes21{}), + native: reflect.TypeOf([21]byte{}), + checked: reflect.TypeOf(bytes21{}), } } @@ -195,8 +195,8 @@ type bytes22 [22]byte func init() { typeMap["bytes22"] = &ABIEncodingType{ - Native: reflect.TypeOf([22]byte{}), - Checked: reflect.TypeOf(bytes22{}), + native: reflect.TypeOf([22]byte{}), + checked: reflect.TypeOf(bytes22{}), } } @@ -204,8 +204,8 @@ type bytes23 [23]byte func init() { typeMap["bytes23"] = &ABIEncodingType{ - Native: reflect.TypeOf([23]byte{}), - Checked: reflect.TypeOf(bytes23{}), + native: reflect.TypeOf([23]byte{}), + checked: reflect.TypeOf(bytes23{}), } } @@ -213,8 +213,8 @@ type bytes24 [24]byte func init() { typeMap["bytes24"] = &ABIEncodingType{ - Native: reflect.TypeOf([24]byte{}), - Checked: reflect.TypeOf(bytes24{}), + native: reflect.TypeOf([24]byte{}), + checked: reflect.TypeOf(bytes24{}), } } @@ -222,8 +222,8 @@ type bytes25 [25]byte func init() { typeMap["bytes25"] = &ABIEncodingType{ - Native: reflect.TypeOf([25]byte{}), - Checked: reflect.TypeOf(bytes25{}), + native: reflect.TypeOf([25]byte{}), + checked: reflect.TypeOf(bytes25{}), } } @@ -231,8 +231,8 @@ type bytes26 [26]byte func init() { typeMap["bytes26"] = &ABIEncodingType{ - Native: reflect.TypeOf([26]byte{}), - Checked: reflect.TypeOf(bytes26{}), + native: reflect.TypeOf([26]byte{}), + checked: reflect.TypeOf(bytes26{}), } } @@ -240,8 +240,8 @@ type bytes27 [27]byte func init() { typeMap["bytes27"] = &ABIEncodingType{ - Native: reflect.TypeOf([27]byte{}), - Checked: reflect.TypeOf(bytes27{}), + native: reflect.TypeOf([27]byte{}), + checked: reflect.TypeOf(bytes27{}), } } @@ -249,8 +249,8 @@ type bytes28 [28]byte func init() { typeMap["bytes28"] = &ABIEncodingType{ - Native: reflect.TypeOf([28]byte{}), - Checked: reflect.TypeOf(bytes28{}), + native: reflect.TypeOf([28]byte{}), + checked: reflect.TypeOf(bytes28{}), } } @@ -258,8 +258,8 @@ type bytes29 [29]byte func init() { typeMap["bytes29"] = &ABIEncodingType{ - Native: reflect.TypeOf([29]byte{}), - Checked: reflect.TypeOf(bytes29{}), + native: reflect.TypeOf([29]byte{}), + checked: reflect.TypeOf(bytes29{}), } } @@ -267,8 +267,8 @@ type bytes30 [30]byte func init() { typeMap["bytes30"] = &ABIEncodingType{ - Native: reflect.TypeOf([30]byte{}), - Checked: reflect.TypeOf(bytes30{}), + native: reflect.TypeOf([30]byte{}), + checked: reflect.TypeOf(bytes30{}), } } @@ -276,8 +276,8 @@ type bytes31 [31]byte func init() { typeMap["bytes31"] = &ABIEncodingType{ - Native: reflect.TypeOf([31]byte{}), - Checked: reflect.TypeOf(bytes31{}), + native: reflect.TypeOf([31]byte{}), + checked: reflect.TypeOf(bytes31{}), } } @@ -285,8 +285,8 @@ type bytes32 [32]byte func init() { typeMap["bytes32"] = &ABIEncodingType{ - Native: reflect.TypeOf([32]byte{}), - Checked: reflect.TypeOf(bytes32{}), + native: reflect.TypeOf([32]byte{}), + checked: reflect.TypeOf(bytes32{}), } } @@ -294,7 +294,7 @@ type bytes0 [0]byte func init() { typeMap["bytes0"] = &ABIEncodingType{ - Native: reflect.TypeOf([0]byte{}), - Checked: reflect.TypeOf(bytes0{}), + native: reflect.TypeOf([0]byte{}), + checked: reflect.TypeOf(bytes0{}), } } diff --git a/core/services/relay/evm/codec_entry.go b/core/services/relay/evm/types/codec_entry.go similarity index 70% rename from core/services/relay/evm/codec_entry.go rename to core/services/relay/evm/types/codec_entry.go index 34be546692b..df51ad7b897 100644 --- a/core/services/relay/evm/codec_entry.go +++ b/core/services/relay/evm/types/codec_entry.go @@ -1,4 +1,4 @@ -package evm +package types import ( "fmt" @@ -11,24 +11,86 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) +// MaxTopicFields is three because the EVM has a m of ax four topics, but the first topic is always the event signature. +const MaxTopicFields = 3 + +type CodecEntry interface { + Init() error + Args() abi.Arguments + EncodingPrefix() []byte + GetMaxSize(n int) (int, error) + Modifier() codec.Modifier + + // CheckedType provides a type that can be used to decode into with type-safety around sizes of integers etc. + CheckedType() reflect.Type + + // ToNative converts a pointer to checked value into a pointer of a type to use with the go-ethereum ABI encoder + // Note that modification of the returned value will modify the original checked value and vice versa. + ToNative(checked reflect.Value) (reflect.Value, error) + + // IsNativePointer returns if the type is a pointer to the native type + IsNativePointer(item reflect.Type) bool +} + +func NewCodecEntry(args abi.Arguments, encodingPrefix []byte, mod codec.Modifier) CodecEntry { + if mod == nil { + mod = codec.MultiModifier{} + } + return &codecEntry{args: args, encodingPrefix: encodingPrefix, mod: mod} +} + type codecEntry struct { - Args abi.Arguments + args abi.Arguments encodingPrefix []byte checkedType reflect.Type nativeType reflect.Type mod codec.Modifier } +func (entry *codecEntry) CheckedType() reflect.Type { + return entry.checkedType +} + +func (entry *codecEntry) NativeType() reflect.Type { + return entry.nativeType +} + +func (entry *codecEntry) ToNative(checked reflect.Value) (reflect.Value, error) { + if checked.Type() != reflect.PointerTo(entry.checkedType) { + return reflect.Value{}, fmt.Errorf("%w: checked type %v does not match expected type %v", commontypes.ErrInvalidType, reflect.TypeOf(checked), entry.checkedType) + } + + return reflect.NewAt(entry.nativeType, checked.UnsafePointer()), nil +} + +func (entry *codecEntry) IsNativePointer(item reflect.Type) bool { + return item == reflect.PointerTo(entry.nativeType) +} + +func (entry *codecEntry) Modifier() codec.Modifier { + return entry.mod +} + +func (entry *codecEntry) Args() abi.Arguments { + tmp := make(abi.Arguments, len(entry.args)) + copy(tmp, entry.args) + return tmp +} + +func (entry *codecEntry) EncodingPrefix() []byte { + tmp := make([]byte, len(entry.encodingPrefix)) + copy(tmp, entry.encodingPrefix) + return tmp +} + func (entry *codecEntry) Init() error { if entry.checkedType != nil { return nil } - args := UnwrapArgs(entry.Args) + args := unwrapArgs(entry.args) argLen := len(args) native := make([]reflect.StructField, argLen) checked := make([]reflect.StructField, argLen) @@ -52,7 +114,7 @@ func (entry *codecEntry) Init() error { seenNames := map[string]bool{} for i, arg := range args { if arg.Indexed { - if numIndices == maxTopicFields { + if numIndices == MaxTopicFields { return fmt.Errorf("%w: too many indexed arguments", commontypes.ErrInvalidConfig) } numIndices++ @@ -82,13 +144,10 @@ func (entry *codecEntry) Init() error { } func (entry *codecEntry) GetMaxSize(n int) (int, error) { - if entry == nil { - return 0, fmt.Errorf("%w: nil entry", commontypes.ErrInvalidType) - } - return GetMaxSize(n, entry.Args) + return GetMaxSize(n, entry.args) } -func UnwrapArgs(args abi.Arguments) abi.Arguments { +func unwrapArgs(args abi.Arguments) abi.Arguments { // Unwrap an unnamed tuple so that callers don't need to wrap it // Eg: If you have struct Foo { ... } and return an unnamed Foo, you should be able ot decode to a go Foo{} directly if len(args) != 1 || args[0].Name != "" { @@ -116,8 +175,8 @@ func getNativeAndCheckedTypesForArg(arg *abi.Argument) (reflect.Type, reflect.Ty case abi.StringTy: return reflect.TypeOf(common.Hash{}), reflect.TypeOf(common.Hash{}), nil case abi.ArrayTy: - u8, _ := types.GetAbiEncodingType("uint8") - if arg.Type.Elem.GetType() == u8.Native { + u8, _ := GetAbiEncodingType("uint8") + if arg.Type.Elem.GetType() == u8.native { return reflect.TypeOf(common.Hash{}), reflect.TypeOf(common.Hash{}), nil } fallthrough @@ -152,9 +211,9 @@ func getNativeAndCheckedTypes(curType *abi.Type) (reflect.Type, reflect.Type, er "%w: cannot create type for kind %v", commontypes.ErrInvalidType, curType.GetType().Kind()) } } - base, ok := types.GetAbiEncodingType(curType.String()) + base, ok := GetAbiEncodingType(curType.String()) if ok { - return converter(base.Native), converter(base.Checked), nil + return converter(base.native), converter(base.checked), nil } return createTupleType(curType, converter) diff --git a/core/services/relay/evm/types/codec_entry_test.go b/core/services/relay/evm/types/codec_entry_test.go new file mode 100644 index 00000000000..861fb4b96e2 --- /dev/null +++ b/core/services/relay/evm/types/codec_entry_test.go @@ -0,0 +1,284 @@ +package types + +import ( + "math/big" + "reflect" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/codec" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func TestCodecEntry(t *testing.T) { + t.Run("basic types", func(t *testing.T) { + type1, err := abi.NewType("uint16", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + type2, err := abi.NewType("string", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + type3, err := abi.NewType("uint24", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + type4, err := abi.NewType("int24", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + args := abi.Arguments{ + {Name: "Field1", Type: type1}, + {Name: "Field2", Type: type2}, + {Name: "Field3", Type: type3}, + {Name: "Field4", Type: type4}, + } + entry := NewCodecEntry(args, nil, nil) + require.NoError(t, entry.Init()) + checked := reflect.New(entry.CheckedType()) + iChecked := reflect.Indirect(checked) + iChecked.FieldByName("Field1").Set(reflect.ValueOf(uint16(2))) + iChecked.FieldByName("Field2").Set(reflect.ValueOf("any string")) + + f3 := big.NewInt( /*2^24 - 1*/ 16777215) + setAndVerifyLimit(t, (*uint24)(f3), f3, iChecked.FieldByName("Field3")) + + f4 := big.NewInt( /*2^23 - 1*/ 8388607) + setAndVerifyLimit(t, (*int24)(f4), f4, iChecked.FieldByName("Field4")) + + rNative, err := entry.ToNative(checked) + require.NoError(t, err) + iNative := reflect.Indirect(rNative) + assert.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) + assert.Equal(t, iNative.Field(1).Interface(), iChecked.Field(1).Interface()) + assert.Equal(t, iNative.Field(2).Interface(), f3) + assert.Equal(t, iNative.Field(3).Interface(), f4) + assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + }) + + t.Run("tuples", func(t *testing.T) { + type1, err := abi.NewType("uint16", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + tupleType, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + {Name: "Field3", Type: "uint24"}, + {Name: "Field4", Type: "int24"}, + }) + require.NoError(t, err) + args := abi.Arguments{ + {Name: "Field1", Type: type1}, + {Name: "Field2", Type: tupleType}, + } + entry := NewCodecEntry(args, nil, nil) + require.NoError(t, entry.Init()) + + checked := reflect.New(entry.CheckedType()) + iChecked := reflect.Indirect(checked) + iChecked.FieldByName("Field1").Set(reflect.ValueOf(uint16(2))) + f2 := iChecked.FieldByName("Field2") + f3 := big.NewInt( /*2^24 - 1*/ 16777215) + setAndVerifyLimit(t, (*uint24)(f3), f3, f2.FieldByName("Field3")) + f4 := big.NewInt( /*2^23 - 1*/ 8388607) + setAndVerifyLimit(t, (*int24)(f4), f4, f2.FieldByName("Field4")) + + native, err := entry.ToNative(checked) + require.NoError(t, err) + iNative := reflect.Indirect(native) + require.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) + nF2 := iNative.Field(1) + assert.Equal(t, nF2.Field(0).Interface(), f3) + assert.Equal(t, nF2.Field(1).Interface(), f4) + assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + }) + + t.Run("unwrapped types", func(t *testing.T) { + // This exists to allow you to decode single returned values without naming the parameter + wrappedTuple, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + {Name: "Field1", Type: "int16"}, + }) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "", Type: wrappedTuple}}, nil, nil) + require.NoError(t, entry.Init()) + checked := reflect.New(entry.CheckedType()) + iChecked := reflect.Indirect(checked) + anyValue := int16(2) + iChecked.FieldByName("Field1").Set(reflect.ValueOf(anyValue)) + native, err := entry.ToNative(checked) + require.NoError(t, err) + iNative := reflect.Indirect(native) + assert.Equal(t, anyValue, iNative.FieldByName("Field1").Interface()) + assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + }) + + t.Run("slice types", func(t *testing.T) { + type1, err := abi.NewType("int16[]", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "Field1", Type: type1}}, nil, nil) + + require.NoError(t, entry.Init()) + checked := reflect.New(entry.CheckedType()) + iChecked := reflect.Indirect(checked) + anySliceValue := []int16{2, 3} + iChecked.FieldByName("Field1").Set(reflect.ValueOf(anySliceValue)) + native, err := entry.ToNative(checked) + require.NoError(t, err) + iNative := reflect.Indirect(native) + assert.Equal(t, anySliceValue, iNative.FieldByName("Field1").Interface()) + assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + }) + + t.Run("array types", func(t *testing.T) { + type1, err := abi.NewType("int16[3]", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "Field1", Type: type1}}, nil, nil) + require.NoError(t, entry.Init()) + checked := reflect.New(entry.CheckedType()) + iChecked := reflect.Indirect(checked) + anySliceValue := [3]int16{2, 3, 30} + iChecked.FieldByName("Field1").Set(reflect.ValueOf(anySliceValue)) + native, err := entry.ToNative(checked) + require.NoError(t, err) + iNative := reflect.Indirect(native) + assert.Equal(t, anySliceValue, iNative.FieldByName("Field1").Interface()) + }) + + t.Run("Not return values makes struct{}", func(t *testing.T) { + entry := NewCodecEntry(abi.Arguments{}, nil, nil) + require.NoError(t, entry.Init()) + assert.Equal(t, reflect.TypeOf(struct{}{}), entry.CheckedType()) + native, err := entry.ToNative(reflect.ValueOf(&struct{}{})) + require.NoError(t, err) + assert.Equal(t, &struct{}{}, native.Interface()) + }) + + t.Run("Address works", func(t *testing.T) { + address, err := abi.NewType("address", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "foo", Type: address}}, nil, nil) + require.NoError(t, entry.Init()) + + checked := reflect.New(entry.CheckedType()) + iChecked := reflect.Indirect(checked) + anyAddr := common.Address{1, 2, 3} + iChecked.FieldByName("Foo").Set(reflect.ValueOf(anyAddr)) + + native, err := entry.ToNative(checked) + require.NoError(t, err) + iNative := reflect.Indirect(native) + assert.Equal(t, anyAddr, iNative.FieldByName("Foo").Interface()) + assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + }) + + t.Run("Multiple unnamed parameters are not supported", func(t *testing.T) { + anyType, err := abi.NewType("int16[3]", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "", Type: anyType}, {Name: "", Type: anyType}}, nil, nil) + assert.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidType)) + }) + + t.Run("Multiple abi arguments with the same name returns an error", func(t *testing.T) { + anyType, err := abi.NewType("int16[3]", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "Name", Type: anyType}, {Name: "Name", Type: anyType}}, nil, nil) + assert.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidConfig)) + }) + + t.Run("Indexed basic types leave their native and checked types as-is", func(t *testing.T) { + anyType, err := abi.NewType("int16", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}, nil, nil) + require.NoError(t, entry.Init()) + checkedField, ok := entry.CheckedType().FieldByName("Name") + require.True(t, ok) + assert.Equal(t, reflect.TypeOf(int16(0)), checkedField.Type) + native, err := entry.ToNative(reflect.New(entry.CheckedType())) + require.NoError(t, err) + iNative := reflect.Indirect(native) + assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + }) + + t.Run("Indexed non basic types change to hash", func(t *testing.T) { + anyType, err := abi.NewType("string", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}, nil, nil) + require.NoError(t, entry.Init()) + nativeField, ok := entry.CheckedType().FieldByName("Name") + require.True(t, ok) + assert.Equal(t, reflect.TypeOf(common.Hash{}), nativeField.Type) + native, err := entry.ToNative(reflect.New(entry.CheckedType())) + require.NoError(t, err) + assertHaveSameStructureAndNames(t, native.Type().Elem(), entry.CheckedType()) + }) + + t.Run("Too many indexed items returns an error", func(t *testing.T) { + anyType, err := abi.NewType("int16", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry( + abi.Arguments{ + {Name: "Name1", Type: anyType, Indexed: true}, + {Name: "Name2", Type: anyType, Indexed: true}, + {Name: "Name3", Type: anyType, Indexed: true}, + {Name: "Name4", Type: anyType, Indexed: true}, + }, nil, nil) + require.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidConfig)) + }) + + // TODO: when the TODO on + // https://github.com/ethereum/go-ethereum/blob/release/1.12/accounts/abi/topics.go#L78 + // is removed, remove this test. + t.Run("Using unsupported types by go-ethereum returns an error", func(t *testing.T) { + anyType, err := abi.NewType("int256[2]", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + entry := NewCodecEntry(abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}, nil, nil) + assert.True(t, errors.Is(entry.Init(), commontypes.ErrInvalidConfig)) + }) + + t.Run("Modifier returns provided modifier", func(t *testing.T) { + anyType, err := abi.NewType("int16", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + mod := codec.NewRenamer(map[string]string{"Name": "RenamedName"}) + entry := NewCodecEntry(abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}, nil, mod) + assert.Equal(t, mod, entry.Modifier()) + }) + + t.Run("EncodingPrefix returns provided prefix", func(t *testing.T) { + anyType, err := abi.NewType("int16", "", []abi.ArgumentMarshaling{}) + require.NoError(t, err) + prefix := []byte{1, 2, 3} + entry := NewCodecEntry(abi.Arguments{{Name: "Name", Type: anyType, Indexed: true}}, prefix, nil) + assert.Equal(t, prefix, entry.EncodingPrefix()) + }) +} + +// sized and bi must be the same pointer. +func setAndVerifyLimit(t *testing.T, sbi SizedBigInt, bi *big.Int, field reflect.Value) { + require.Same(t, reflect.NewAt(reflect.TypeOf(big.Int{}), reflect.ValueOf(sbi).UnsafePointer()).Interface(), bi) + field.Set(reflect.ValueOf(sbi)) + assert.NoError(t, sbi.Verify()) + bi.Add(bi, big.NewInt(1)) + assert.IsType(t, commontypes.ErrInvalidType, sbi.Verify()) +} + +// verifying the same structure allows us to use unsafe pointers to cast between them. +// This is done for perf and simplicity in mapping the two structures. +// [reflect.NewAt]'s use is the same as (*native)(unsafe.Pointer(checked)) +// See the safe usecase 1 from [unsafe.Pointer], as this is a subset of that. +// This also verifies field names are the same. +func assertHaveSameStructureAndNames(t *testing.T, t1, t2 reflect.Type) { + require.Equal(t, t1.Kind(), t2.Kind()) + + switch t1.Kind() { + case reflect.Array: + require.Equal(t, t1.Len(), t2.Len()) + assertHaveSameStructureAndNames(t, t1.Elem(), t2.Elem()) + case reflect.Slice, reflect.Pointer: + assertHaveSameStructureAndNames(t, t1.Elem(), t2.Elem()) + case reflect.Struct: + numFields := t1.NumField() + require.Equal(t, numFields, t2.NumField()) + for i := 0; i < numFields; i++ { + require.Equal(t, t1.Field(i).Name, t2.Field(i).Name) + assertHaveSameStructureAndNames(t, t1.Field(i).Type, t2.Field(i).Type) + } + default: + require.Equal(t, t1, t2) + } +} diff --git a/core/services/relay/evm/types/gen/bytes.tmpl b/core/services/relay/evm/types/gen/bytes.tmpl index 2414c412c64..3c06529b0f3 100644 --- a/core/services/relay/evm/types/gen/bytes.tmpl +++ b/core/services/relay/evm/types/gen/bytes.tmpl @@ -6,8 +6,8 @@ import "reflect" type bytes{{.Size}} [{{.Size}}]byte func init() { typeMap["bytes{{.Size}}"] = &ABIEncodingType { - Native: reflect.TypeOf([{{.Size}}]byte{}), - Checked: reflect.TypeOf(bytes{{.Size}}{}), + native: reflect.TypeOf([{{.Size}}]byte{}), + checked: reflect.TypeOf(bytes{{.Size}}{}), } } diff --git a/core/services/relay/evm/types/gen/ints.tmpl b/core/services/relay/evm/types/gen/ints.tmpl index 38c1fae03a6..b5f0fa363ca 100644 --- a/core/services/relay/evm/types/gen/ints.tmpl +++ b/core/services/relay/evm/types/gen/ints.tmpl @@ -5,7 +5,8 @@ import ( "reflect" "github.com/fxamacker/cbor/v2" - + + "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -55,7 +56,7 @@ func (i *{{.Prefix}}int{{.Size}}) Verify() error { return types.ErrInvalidType } {{ else }} - if bi.BitLen() > {{.Size}} { + if bi.BitLen() > {{.Size}} || bi.Sign() < 0 { return types.ErrInvalidType } {{ end }} @@ -66,8 +67,8 @@ func (i *{{.Prefix}}int{{.Size}}) private() {} func init() { typeMap["{{.Prefix}}int{{.Size}}"] = &ABIEncodingType { - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*{{.Prefix}}int{{.Size}})(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*{{.Prefix}}int{{.Size}})(nil)), } } {{ end }} \ No newline at end of file diff --git a/core/services/relay/evm/types/gen/main.go b/core/services/relay/evm/types/gen/main.go index 6253c6d282d..cdc1eab77e0 100644 --- a/core/services/relay/evm/types/gen/main.go +++ b/core/services/relay/evm/types/gen/main.go @@ -31,7 +31,7 @@ func genInts() { continue } - signed := &IntType{Size: i, Signed: false} + signed := &IntType{Size: i, Signed: true} unsigned := &IntType{Prefix: "u", Size: i} intTypes = append(intTypes, signed, unsigned) } diff --git a/core/services/relay/evm/types/int_types_gen.go b/core/services/relay/evm/types/int_types_gen.go index 0cc1471b37d..1ff82d5691d 100644 --- a/core/services/relay/evm/types/int_types_gen.go +++ b/core/services/relay/evm/types/int_types_gen.go @@ -6,6 +6,7 @@ import ( "github.com/fxamacker/cbor/v2" + "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -52,7 +53,7 @@ func (i *int24) MarshalText() ([]byte, error) { func (i *int24) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 24 { + if !codec.FitsInNBitsSigned(24, bi) { return types.ErrInvalidType } @@ -63,8 +64,8 @@ func (i *int24) private() {} func init() { typeMap["int24"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int24)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int24)(nil)), } } @@ -100,7 +101,7 @@ func (i *uint24) MarshalText() ([]byte, error) { func (i *uint24) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 24 { + if bi.BitLen() > 24 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -111,8 +112,8 @@ func (i *uint24) private() {} func init() { typeMap["uint24"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint24)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint24)(nil)), } } @@ -148,7 +149,7 @@ func (i *int40) MarshalText() ([]byte, error) { func (i *int40) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 40 { + if !codec.FitsInNBitsSigned(40, bi) { return types.ErrInvalidType } @@ -159,8 +160,8 @@ func (i *int40) private() {} func init() { typeMap["int40"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int40)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int40)(nil)), } } @@ -196,7 +197,7 @@ func (i *uint40) MarshalText() ([]byte, error) { func (i *uint40) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 40 { + if bi.BitLen() > 40 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -207,8 +208,8 @@ func (i *uint40) private() {} func init() { typeMap["uint40"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint40)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint40)(nil)), } } @@ -244,7 +245,7 @@ func (i *int48) MarshalText() ([]byte, error) { func (i *int48) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 48 { + if !codec.FitsInNBitsSigned(48, bi) { return types.ErrInvalidType } @@ -255,8 +256,8 @@ func (i *int48) private() {} func init() { typeMap["int48"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int48)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int48)(nil)), } } @@ -292,7 +293,7 @@ func (i *uint48) MarshalText() ([]byte, error) { func (i *uint48) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 48 { + if bi.BitLen() > 48 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -303,8 +304,8 @@ func (i *uint48) private() {} func init() { typeMap["uint48"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint48)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint48)(nil)), } } @@ -340,7 +341,7 @@ func (i *int56) MarshalText() ([]byte, error) { func (i *int56) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 56 { + if !codec.FitsInNBitsSigned(56, bi) { return types.ErrInvalidType } @@ -351,8 +352,8 @@ func (i *int56) private() {} func init() { typeMap["int56"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int56)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int56)(nil)), } } @@ -388,7 +389,7 @@ func (i *uint56) MarshalText() ([]byte, error) { func (i *uint56) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 56 { + if bi.BitLen() > 56 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -399,8 +400,8 @@ func (i *uint56) private() {} func init() { typeMap["uint56"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint56)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint56)(nil)), } } @@ -436,7 +437,7 @@ func (i *int72) MarshalText() ([]byte, error) { func (i *int72) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 72 { + if !codec.FitsInNBitsSigned(72, bi) { return types.ErrInvalidType } @@ -447,8 +448,8 @@ func (i *int72) private() {} func init() { typeMap["int72"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int72)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int72)(nil)), } } @@ -484,7 +485,7 @@ func (i *uint72) MarshalText() ([]byte, error) { func (i *uint72) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 72 { + if bi.BitLen() > 72 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -495,8 +496,8 @@ func (i *uint72) private() {} func init() { typeMap["uint72"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint72)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint72)(nil)), } } @@ -532,7 +533,7 @@ func (i *int80) MarshalText() ([]byte, error) { func (i *int80) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 80 { + if !codec.FitsInNBitsSigned(80, bi) { return types.ErrInvalidType } @@ -543,8 +544,8 @@ func (i *int80) private() {} func init() { typeMap["int80"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int80)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int80)(nil)), } } @@ -580,7 +581,7 @@ func (i *uint80) MarshalText() ([]byte, error) { func (i *uint80) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 80 { + if bi.BitLen() > 80 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -591,8 +592,8 @@ func (i *uint80) private() {} func init() { typeMap["uint80"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint80)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint80)(nil)), } } @@ -628,7 +629,7 @@ func (i *int88) MarshalText() ([]byte, error) { func (i *int88) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 88 { + if !codec.FitsInNBitsSigned(88, bi) { return types.ErrInvalidType } @@ -639,8 +640,8 @@ func (i *int88) private() {} func init() { typeMap["int88"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int88)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int88)(nil)), } } @@ -676,7 +677,7 @@ func (i *uint88) MarshalText() ([]byte, error) { func (i *uint88) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 88 { + if bi.BitLen() > 88 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -687,8 +688,8 @@ func (i *uint88) private() {} func init() { typeMap["uint88"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint88)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint88)(nil)), } } @@ -724,7 +725,7 @@ func (i *int96) MarshalText() ([]byte, error) { func (i *int96) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 96 { + if !codec.FitsInNBitsSigned(96, bi) { return types.ErrInvalidType } @@ -735,8 +736,8 @@ func (i *int96) private() {} func init() { typeMap["int96"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int96)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int96)(nil)), } } @@ -772,7 +773,7 @@ func (i *uint96) MarshalText() ([]byte, error) { func (i *uint96) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 96 { + if bi.BitLen() > 96 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -783,8 +784,8 @@ func (i *uint96) private() {} func init() { typeMap["uint96"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint96)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint96)(nil)), } } @@ -820,7 +821,7 @@ func (i *int104) MarshalText() ([]byte, error) { func (i *int104) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 104 { + if !codec.FitsInNBitsSigned(104, bi) { return types.ErrInvalidType } @@ -831,8 +832,8 @@ func (i *int104) private() {} func init() { typeMap["int104"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int104)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int104)(nil)), } } @@ -868,7 +869,7 @@ func (i *uint104) MarshalText() ([]byte, error) { func (i *uint104) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 104 { + if bi.BitLen() > 104 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -879,8 +880,8 @@ func (i *uint104) private() {} func init() { typeMap["uint104"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint104)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint104)(nil)), } } @@ -916,7 +917,7 @@ func (i *int112) MarshalText() ([]byte, error) { func (i *int112) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 112 { + if !codec.FitsInNBitsSigned(112, bi) { return types.ErrInvalidType } @@ -927,8 +928,8 @@ func (i *int112) private() {} func init() { typeMap["int112"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int112)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int112)(nil)), } } @@ -964,7 +965,7 @@ func (i *uint112) MarshalText() ([]byte, error) { func (i *uint112) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 112 { + if bi.BitLen() > 112 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -975,8 +976,8 @@ func (i *uint112) private() {} func init() { typeMap["uint112"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint112)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint112)(nil)), } } @@ -1012,7 +1013,7 @@ func (i *int120) MarshalText() ([]byte, error) { func (i *int120) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 120 { + if !codec.FitsInNBitsSigned(120, bi) { return types.ErrInvalidType } @@ -1023,8 +1024,8 @@ func (i *int120) private() {} func init() { typeMap["int120"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int120)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int120)(nil)), } } @@ -1060,7 +1061,7 @@ func (i *uint120) MarshalText() ([]byte, error) { func (i *uint120) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 120 { + if bi.BitLen() > 120 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1071,8 +1072,8 @@ func (i *uint120) private() {} func init() { typeMap["uint120"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint120)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint120)(nil)), } } @@ -1108,7 +1109,7 @@ func (i *int128) MarshalText() ([]byte, error) { func (i *int128) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 128 { + if !codec.FitsInNBitsSigned(128, bi) { return types.ErrInvalidType } @@ -1119,8 +1120,8 @@ func (i *int128) private() {} func init() { typeMap["int128"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int128)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int128)(nil)), } } @@ -1156,7 +1157,7 @@ func (i *uint128) MarshalText() ([]byte, error) { func (i *uint128) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 128 { + if bi.BitLen() > 128 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1167,8 +1168,8 @@ func (i *uint128) private() {} func init() { typeMap["uint128"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint128)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint128)(nil)), } } @@ -1204,7 +1205,7 @@ func (i *int136) MarshalText() ([]byte, error) { func (i *int136) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 136 { + if !codec.FitsInNBitsSigned(136, bi) { return types.ErrInvalidType } @@ -1215,8 +1216,8 @@ func (i *int136) private() {} func init() { typeMap["int136"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int136)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int136)(nil)), } } @@ -1252,7 +1253,7 @@ func (i *uint136) MarshalText() ([]byte, error) { func (i *uint136) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 136 { + if bi.BitLen() > 136 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1263,8 +1264,8 @@ func (i *uint136) private() {} func init() { typeMap["uint136"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint136)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint136)(nil)), } } @@ -1300,7 +1301,7 @@ func (i *int144) MarshalText() ([]byte, error) { func (i *int144) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 144 { + if !codec.FitsInNBitsSigned(144, bi) { return types.ErrInvalidType } @@ -1311,8 +1312,8 @@ func (i *int144) private() {} func init() { typeMap["int144"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int144)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int144)(nil)), } } @@ -1348,7 +1349,7 @@ func (i *uint144) MarshalText() ([]byte, error) { func (i *uint144) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 144 { + if bi.BitLen() > 144 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1359,8 +1360,8 @@ func (i *uint144) private() {} func init() { typeMap["uint144"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint144)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint144)(nil)), } } @@ -1396,7 +1397,7 @@ func (i *int152) MarshalText() ([]byte, error) { func (i *int152) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 152 { + if !codec.FitsInNBitsSigned(152, bi) { return types.ErrInvalidType } @@ -1407,8 +1408,8 @@ func (i *int152) private() {} func init() { typeMap["int152"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int152)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int152)(nil)), } } @@ -1444,7 +1445,7 @@ func (i *uint152) MarshalText() ([]byte, error) { func (i *uint152) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 152 { + if bi.BitLen() > 152 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1455,8 +1456,8 @@ func (i *uint152) private() {} func init() { typeMap["uint152"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint152)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint152)(nil)), } } @@ -1492,7 +1493,7 @@ func (i *int160) MarshalText() ([]byte, error) { func (i *int160) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 160 { + if !codec.FitsInNBitsSigned(160, bi) { return types.ErrInvalidType } @@ -1503,8 +1504,8 @@ func (i *int160) private() {} func init() { typeMap["int160"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int160)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int160)(nil)), } } @@ -1540,7 +1541,7 @@ func (i *uint160) MarshalText() ([]byte, error) { func (i *uint160) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 160 { + if bi.BitLen() > 160 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1551,8 +1552,8 @@ func (i *uint160) private() {} func init() { typeMap["uint160"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint160)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint160)(nil)), } } @@ -1588,7 +1589,7 @@ func (i *int168) MarshalText() ([]byte, error) { func (i *int168) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 168 { + if !codec.FitsInNBitsSigned(168, bi) { return types.ErrInvalidType } @@ -1599,8 +1600,8 @@ func (i *int168) private() {} func init() { typeMap["int168"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int168)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int168)(nil)), } } @@ -1636,7 +1637,7 @@ func (i *uint168) MarshalText() ([]byte, error) { func (i *uint168) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 168 { + if bi.BitLen() > 168 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1647,8 +1648,8 @@ func (i *uint168) private() {} func init() { typeMap["uint168"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint168)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint168)(nil)), } } @@ -1684,7 +1685,7 @@ func (i *int176) MarshalText() ([]byte, error) { func (i *int176) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 176 { + if !codec.FitsInNBitsSigned(176, bi) { return types.ErrInvalidType } @@ -1695,8 +1696,8 @@ func (i *int176) private() {} func init() { typeMap["int176"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int176)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int176)(nil)), } } @@ -1732,7 +1733,7 @@ func (i *uint176) MarshalText() ([]byte, error) { func (i *uint176) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 176 { + if bi.BitLen() > 176 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1743,8 +1744,8 @@ func (i *uint176) private() {} func init() { typeMap["uint176"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint176)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint176)(nil)), } } @@ -1780,7 +1781,7 @@ func (i *int184) MarshalText() ([]byte, error) { func (i *int184) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 184 { + if !codec.FitsInNBitsSigned(184, bi) { return types.ErrInvalidType } @@ -1791,8 +1792,8 @@ func (i *int184) private() {} func init() { typeMap["int184"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int184)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int184)(nil)), } } @@ -1828,7 +1829,7 @@ func (i *uint184) MarshalText() ([]byte, error) { func (i *uint184) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 184 { + if bi.BitLen() > 184 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1839,8 +1840,8 @@ func (i *uint184) private() {} func init() { typeMap["uint184"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint184)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint184)(nil)), } } @@ -1876,7 +1877,7 @@ func (i *int192) MarshalText() ([]byte, error) { func (i *int192) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 192 { + if !codec.FitsInNBitsSigned(192, bi) { return types.ErrInvalidType } @@ -1887,8 +1888,8 @@ func (i *int192) private() {} func init() { typeMap["int192"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int192)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int192)(nil)), } } @@ -1924,7 +1925,7 @@ func (i *uint192) MarshalText() ([]byte, error) { func (i *uint192) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 192 { + if bi.BitLen() > 192 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -1935,8 +1936,8 @@ func (i *uint192) private() {} func init() { typeMap["uint192"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint192)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint192)(nil)), } } @@ -1972,7 +1973,7 @@ func (i *int200) MarshalText() ([]byte, error) { func (i *int200) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 200 { + if !codec.FitsInNBitsSigned(200, bi) { return types.ErrInvalidType } @@ -1983,8 +1984,8 @@ func (i *int200) private() {} func init() { typeMap["int200"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int200)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int200)(nil)), } } @@ -2020,7 +2021,7 @@ func (i *uint200) MarshalText() ([]byte, error) { func (i *uint200) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 200 { + if bi.BitLen() > 200 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2031,8 +2032,8 @@ func (i *uint200) private() {} func init() { typeMap["uint200"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint200)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint200)(nil)), } } @@ -2068,7 +2069,7 @@ func (i *int208) MarshalText() ([]byte, error) { func (i *int208) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 208 { + if !codec.FitsInNBitsSigned(208, bi) { return types.ErrInvalidType } @@ -2079,8 +2080,8 @@ func (i *int208) private() {} func init() { typeMap["int208"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int208)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int208)(nil)), } } @@ -2116,7 +2117,7 @@ func (i *uint208) MarshalText() ([]byte, error) { func (i *uint208) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 208 { + if bi.BitLen() > 208 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2127,8 +2128,8 @@ func (i *uint208) private() {} func init() { typeMap["uint208"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint208)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint208)(nil)), } } @@ -2164,7 +2165,7 @@ func (i *int216) MarshalText() ([]byte, error) { func (i *int216) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 216 { + if !codec.FitsInNBitsSigned(216, bi) { return types.ErrInvalidType } @@ -2175,8 +2176,8 @@ func (i *int216) private() {} func init() { typeMap["int216"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int216)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int216)(nil)), } } @@ -2212,7 +2213,7 @@ func (i *uint216) MarshalText() ([]byte, error) { func (i *uint216) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 216 { + if bi.BitLen() > 216 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2223,8 +2224,8 @@ func (i *uint216) private() {} func init() { typeMap["uint216"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint216)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint216)(nil)), } } @@ -2260,7 +2261,7 @@ func (i *int224) MarshalText() ([]byte, error) { func (i *int224) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 224 { + if !codec.FitsInNBitsSigned(224, bi) { return types.ErrInvalidType } @@ -2271,8 +2272,8 @@ func (i *int224) private() {} func init() { typeMap["int224"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int224)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int224)(nil)), } } @@ -2308,7 +2309,7 @@ func (i *uint224) MarshalText() ([]byte, error) { func (i *uint224) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 224 { + if bi.BitLen() > 224 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2319,8 +2320,8 @@ func (i *uint224) private() {} func init() { typeMap["uint224"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint224)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint224)(nil)), } } @@ -2356,7 +2357,7 @@ func (i *int232) MarshalText() ([]byte, error) { func (i *int232) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 232 { + if !codec.FitsInNBitsSigned(232, bi) { return types.ErrInvalidType } @@ -2367,8 +2368,8 @@ func (i *int232) private() {} func init() { typeMap["int232"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int232)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int232)(nil)), } } @@ -2404,7 +2405,7 @@ func (i *uint232) MarshalText() ([]byte, error) { func (i *uint232) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 232 { + if bi.BitLen() > 232 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2415,8 +2416,8 @@ func (i *uint232) private() {} func init() { typeMap["uint232"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint232)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint232)(nil)), } } @@ -2452,7 +2453,7 @@ func (i *int240) MarshalText() ([]byte, error) { func (i *int240) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 240 { + if !codec.FitsInNBitsSigned(240, bi) { return types.ErrInvalidType } @@ -2463,8 +2464,8 @@ func (i *int240) private() {} func init() { typeMap["int240"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int240)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int240)(nil)), } } @@ -2500,7 +2501,7 @@ func (i *uint240) MarshalText() ([]byte, error) { func (i *uint240) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 240 { + if bi.BitLen() > 240 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2511,8 +2512,8 @@ func (i *uint240) private() {} func init() { typeMap["uint240"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint240)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint240)(nil)), } } @@ -2548,7 +2549,7 @@ func (i *int248) MarshalText() ([]byte, error) { func (i *int248) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 248 { + if !codec.FitsInNBitsSigned(248, bi) { return types.ErrInvalidType } @@ -2559,8 +2560,8 @@ func (i *int248) private() {} func init() { typeMap["int248"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int248)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int248)(nil)), } } @@ -2596,7 +2597,7 @@ func (i *uint248) MarshalText() ([]byte, error) { func (i *uint248) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 248 { + if bi.BitLen() > 248 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2607,8 +2608,8 @@ func (i *uint248) private() {} func init() { typeMap["uint248"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint248)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint248)(nil)), } } @@ -2644,7 +2645,7 @@ func (i *int256) MarshalText() ([]byte, error) { func (i *int256) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 256 { + if !codec.FitsInNBitsSigned(256, bi) { return types.ErrInvalidType } @@ -2655,8 +2656,8 @@ func (i *int256) private() {} func init() { typeMap["int256"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*int256)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*int256)(nil)), } } @@ -2692,7 +2693,7 @@ func (i *uint256) MarshalText() ([]byte, error) { func (i *uint256) Verify() error { bi := (*big.Int)(i) - if bi.BitLen() > 256 { + if bi.BitLen() > 256 || bi.Sign() < 0 { return types.ErrInvalidType } @@ -2703,7 +2704,7 @@ func (i *uint256) private() {} func init() { typeMap["uint256"] = &ABIEncodingType{ - Native: reflect.TypeOf((*big.Int)(nil)), - Checked: reflect.TypeOf((*uint256)(nil)), + native: reflect.TypeOf((*big.Int)(nil)), + checked: reflect.TypeOf((*uint256)(nil)), } } diff --git a/core/services/relay/evm/types/int_types_test.go b/core/services/relay/evm/types/int_types_test.go new file mode 100644 index 00000000000..1227773ce90 --- /dev/null +++ b/core/services/relay/evm/types/int_types_test.go @@ -0,0 +1,54 @@ +package types + +import ( + "fmt" + "math/big" + "reflect" + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func TestIntTypes(t *testing.T) { + t.Parallel() + for i := 24; i <= 256; i += 8 { + if i == 64 || i == 32 { + continue + } + t.Run(fmt.Sprintf("int%v", i), func(t *testing.T) { + tpe, ok := GetAbiEncodingType(fmt.Sprintf("int%v", i)) + require.True(t, ok) + minVal := new(big.Int).Neg(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(i-1)), nil)) + maxVal := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(i-1)), nil), big.NewInt(1)) + assertBigIntBounds(t, tpe, minVal, maxVal) + }) + + t.Run(fmt.Sprintf("uint%v", i), func(t *testing.T) { + tep, ok := GetAbiEncodingType(fmt.Sprintf("uint%v", i)) + require.True(t, ok) + minVal := big.NewInt(0) + maxVal := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(i)), nil), big.NewInt(1)) + assertBigIntBounds(t, tep, minVal, maxVal) + }) + } +} + +func assertBigIntBounds(t *testing.T, tpe *ABIEncodingType, min, max *big.Int) { + t.Helper() + assert.Equal(t, reflect.TypeOf(min), tpe.native) + assert.True(t, tpe.checked.ConvertibleTo(reflect.TypeOf(min))) + minMinusOne := new(big.Int).Sub(min, big.NewInt(1)) + maxPlusOne := new(big.Int).Add(max, big.NewInt(1)) + sbi := reflect.ValueOf(min).Convert(tpe.checked).Interface().(SizedBigInt) + assert.NoError(t, sbi.Verify()) + sbi = reflect.ValueOf(max).Convert(tpe.checked).Interface().(SizedBigInt) + assert.NoError(t, sbi.Verify()) + sbi = reflect.ValueOf(minMinusOne).Convert(tpe.checked).Interface().(SizedBigInt) + assert.True(t, errors.Is(types.ErrInvalidType, sbi.Verify())) + sbi = reflect.ValueOf(maxPlusOne).Convert(tpe.checked).Interface().(SizedBigInt) + assert.True(t, errors.Is(types.ErrInvalidType, sbi.Verify())) +} diff --git a/core/services/relay/evm/size_helper.go b/core/services/relay/evm/types/size_helper.go similarity index 99% rename from core/services/relay/evm/size_helper.go rename to core/services/relay/evm/types/size_helper.go index c6ff3d82f38..921b8a28315 100644 --- a/core/services/relay/evm/size_helper.go +++ b/core/services/relay/evm/types/size_helper.go @@ -1,4 +1,4 @@ -package evm +package types import ( "github.com/ethereum/go-ethereum/accounts/abi" diff --git a/core/services/relay/evm/size_helper_test.go b/core/services/relay/evm/types/size_helper_test.go similarity index 97% rename from core/services/relay/evm/size_helper_test.go rename to core/services/relay/evm/types/size_helper_test.go index 0368f0f4059..202269a4536 100644 --- a/core/services/relay/evm/size_helper_test.go +++ b/core/services/relay/evm/types/size_helper_test.go @@ -1,4 +1,4 @@ -package evm_test +package types_test import ( "math/big" @@ -10,7 +10,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) const anyNumElements = 10 @@ -189,12 +189,12 @@ func TestGetMaxSize(t *testing.T) { t.Run("Nested dynamic types return errors", func(t *testing.T) { t.Run("Slice in slice", func(t *testing.T) { args := abi.Arguments{{Name: "B", Type: mustType(t, "int32[][]")}} - _, err := evm.GetMaxSize(anyNumElements, args) + _, err := types.GetMaxSize(anyNumElements, args) assert.IsType(t, commontypes.ErrInvalidType, err) }) t.Run("Slice in array", func(t *testing.T) { args := abi.Arguments{{Name: "B", Type: mustType(t, "int32[][2]")}} - _, err := evm.GetMaxSize(anyNumElements, args) + _, err := types.GetMaxSize(anyNumElements, args) assert.IsType(t, commontypes.ErrInvalidType, err) }) }) @@ -237,14 +237,14 @@ func TestGetMaxSize(t *testing.T) { require.NoError(t, err) args := abi.Arguments{{Name: "t2", Type: t2}} - _, err = evm.GetMaxSize(anyNumElements, args) + _, err = types.GetMaxSize(anyNumElements, args) assert.IsType(t, commontypes.ErrInvalidType, err) }) } func runSizeTest(t *testing.T, n int, args abi.Arguments, params ...any) { - actual, err := evm.GetMaxSize(n, args) + actual, err := types.GetMaxSize(n, args) require.NoError(t, err) expected, err := args.Pack(params...) diff --git a/go.mod b/go.mod index bb7b5147c04..b64aea78ffe 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240110170252-c27581c17dc1 diff --git a/go.sum b/go.sum index a9e955eb503..74f647919fd 100644 --- a/go.sum +++ b/go.sum @@ -1150,8 +1150,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f h1:7904h45vNBT+IVO7PMcucvNXSIS9ilf2cxf+RMYb7zs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5 h1:o36okzBAbWhlxKrIeb66Iw/U7Uy3j4FsPGQREb06SUo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71 h1:Ju0cxdrzGFwHGDPp16IzkOyX87LZ/kKDFG1A+VSEJHY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71/go.mod h1:Ppv5X8MTUkkpKdb270dLefjio724vMkCWmSSaWo7CzI= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index e85c4569e1a..506277689dd 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -25,7 +25,7 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5 github.com/smartcontractkit/chainlink-testing-framework v1.22.1 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 63a8c1de756..fab47ad1182 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1481,8 +1481,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f h1:7904h45vNBT+IVO7PMcucvNXSIS9ilf2cxf+RMYb7zs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240115191717-1e2676fced3f/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5 h1:o36okzBAbWhlxKrIeb66Iw/U7Uy3j4FsPGQREb06SUo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240116201354-23cd46ccbbe5/go.mod h1:f+0ei9N4PlTJHu7pbGzEjTnBUr45syPdGFu5+31lS5Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71 h1:Ju0cxdrzGFwHGDPp16IzkOyX87LZ/kKDFG1A+VSEJHY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231222201016-da3f0a763f71/go.mod h1:Ppv5X8MTUkkpKdb270dLefjio724vMkCWmSSaWo7CzI= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ=