From a2e92cdb03c02b251c78abcf432bf98873acd9d1 Mon Sep 17 00:00:00 2001 From: Ryan Tinianov Date: Thu, 14 Dec 2023 13:06:51 -0500 Subject: [PATCH] Simplify chain reader's bindings. --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/relay/evm/binding.go | 156 +++++++++++++ core/services/relay/evm/bindings.go | 75 +++--- core/services/relay/evm/chain_reader.go | 229 ++++++++----------- core/services/relay/evm/chain_reader_test.go | 24 +- core/services/relay/evm/evm.go | 11 +- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- 11 files changed, 310 insertions(+), 203 deletions(-) create mode 100644 core/services/relay/evm/binding.go diff --git a/core/scripts/go.mod b/core/scripts/go.mod index f334d94ba34..148ba233dff 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -237,7 +237,7 @@ require ( github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231214180711-f4668ff89fe9 // indirect + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20231213175155-181d4a261f5d // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index df6461ff55b..868c91838bd 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1148,8 +1148,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.20231214180711-f4668ff89fe9 h1:dca0f2dpHOPPu6raYK5nJU0A5P7JkXM5PbMGNezg2NI= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231214180711-f4668ff89fe9/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e h1:t9yp8N8WgbCspo0JOIJaxyYNeMEzpNhQXEyr708bFT4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679 h1:iu1pNbUoSDTrp+7BUtfTygZ2C0f5C2ZOBQhIoJjp+S0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679/go.mod h1:2Jx7bTEk4ujFQdsZpZq3A0BydvaVPs6mX8clUfxHOEM= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= diff --git a/core/services/relay/evm/binding.go b/core/services/relay/evm/binding.go new file mode 100644 index 00000000000..465a10b368d --- /dev/null +++ b/core/services/relay/evm/binding.go @@ -0,0 +1,156 @@ +package evm + +import ( + "context" + "fmt" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type readBinding interface { + GetLatestValue(ctx context.Context, params any) ([]byte, error) + Bind(binding commontypes.BoundContract) error + SetCodec(codec commontypes.Codec) + Register() error + Unregister() error +} + +type methodBinding struct { + address common.Address + contractName string + method string + client evmclient.Client + codec commontypes.Codec + bound bool +} + +var _ readBinding = &methodBinding{} + +func (m *methodBinding) SetCodec(codec commontypes.Codec) { + m.codec = codec +} + +func (m *methodBinding) Register() error { + return nil +} + +func (m *methodBinding) Unregister() error { + return nil +} + +func (m *methodBinding) GetLatestValue(ctx context.Context, params any) ([]byte, error) { + if !m.bound { + return nil, fmt.Errorf("%w: method not bound", commontypes.ErrInvalidType) + } + + data, err := m.codec.Encode(ctx, params, wrapItemType(m.contractName, m.method, true)) + if err != nil { + return nil, err + } + + callMsg := ethereum.CallMsg{ + To: &m.address, + From: m.address, + Data: data, + } + + return m.client.CallContract(ctx, callMsg, nil) +} + +func (m *methodBinding) Bind(binding commontypes.BoundContract) error { + m.address = common.HexToAddress(binding.Address) + m.bound = true + return nil +} + +type eventBinding struct { + address common.Address + contractName string + eventName string + lp logpoller.LogPoller + hash common.Hash + codec commontypes.Codec + pending bool + subscribed bool + bound bool +} + +func (e *eventBinding) SetCodec(codec commontypes.Codec) { + e.codec = codec +} + +func (e *eventBinding) Register() error { + e.subscribed = true + if !e.bound { + return nil + } + + if err := e.lp.RegisterFilter(logpoller.Filter{ + Name: wrapItemType(e.contractName, e.eventName, false), + EventSigs: evmtypes.HashArray{e.hash}, + Addresses: evmtypes.AddressArray{e.address}, + }); err != nil { + return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) + } + return nil +} + +func (e *eventBinding) Unregister() error { + e.subscribed = false + if !e.bound { + return nil + } + + if err := e.lp.UnregisterFilter(wrapItemType(e.contractName, e.eventName, false)); err != nil { + return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) + } + return nil +} + +var _ readBinding = &eventBinding{} + +func (e *eventBinding) GetLatestValue(_ context.Context, _ any) ([]byte, error) { + if !e.bound { + return nil, fmt.Errorf("%w: event not bound", commontypes.ErrInvalidType) + } + + confs := logpoller.Finalized + if e.pending { + confs = logpoller.Unconfirmed + } + log, err := e.lp.LatestLogByEventSigWithConfs(e.hash, e.address, confs) + if err != nil { + errStr := err.Error() + if strings.Contains(errStr, "not found") || strings.Contains(errStr, "no rows") { + return nil, nil + } + return nil, err + } + + return log.Data, nil +} + +func (e *eventBinding) Bind(binding commontypes.BoundContract) error { + wasSubscribed := e.subscribed + if wasSubscribed { + if err := e.Unregister(); err != nil { + return err + } + } + e.address = common.HexToAddress(binding.Address) + e.pending = binding.Pending + e.bound = true + + if wasSubscribed { + return e.Register() + } + return nil +} diff --git a/core/services/relay/evm/bindings.go b/core/services/relay/evm/bindings.go index b1f705e2ce9..1a23128d19f 100644 --- a/core/services/relay/evm/bindings.go +++ b/core/services/relay/evm/bindings.go @@ -3,48 +3,59 @@ package evm import ( "fmt" - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-common/pkg/types" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" ) -type Bindings map[string]methodBindings +// key is contract name +type contractBindings map[string]readBindings -func (b Bindings) addEvent(contractName, typeName string, evt common.Hash) error { - ae, err := b.getBinding(contractName, typeName, true) - if err != nil { - return err - } +// key is read name +type readBindings map[string]readBinding - ae.evt = &evt - return nil -} - -func (b Bindings) getBinding(contractName, methodName string, isConfig bool) (*addrEvtBinding, error) { - errType := types.ErrInvalidType - if isConfig { - errType = types.ErrInvalidConfig - } - methodNames, ok := b[contractName] - if !ok { - return nil, fmt.Errorf("%w: contract %s not found", errType, contractName) +func (b contractBindings) GetReadBinding(contractName, readName string) (readBinding, error) { + rb, rbExists := b[contractName] + if !rbExists { + return nil, fmt.Errorf("%w: no contract named %s", commontypes.ErrInvalidType, contractName) } - ae, ok := methodNames[methodName] - if !ok { - return nil, fmt.Errorf("%w: method %s not found in contract %s", errType, methodName, contractName) + reader, readerExists := rb[readName] + if !readerExists { + return nil, fmt.Errorf("%w: no readName named %s in contract %s", commontypes.ErrInvalidType, readName, contractName) } - - return ae, nil + return reader, nil } -type methodBindings map[string]*addrEvtBinding +func (b contractBindings) AddReadBinding(contractName, readName string, reader readBinding) { + rbs, rbsExists := b[contractName] + if !rbsExists { + rbs = readBindings{} + b[contractName] = rbs + } + rbs[readName] = reader +} -func NewAddrEvtFromAddress(address common.Address) *addrEvtBinding { - return &addrEvtBinding{addr: address} +func (b contractBindings) Bind(boundContracts []commontypes.BoundContract) error { + for _, bc := range boundContracts { + rbs, rbsExist := b[bc.Name] + if !rbsExist { + return fmt.Errorf("%w: no contract named %s", commontypes.ErrInvalidConfig, bc.Name) + } + for _, r := range rbs { + if err := r.Bind(bc); err != nil { + return err + } + } + } + return nil } -type addrEvtBinding struct { - addr common.Address - evt *common.Hash +func (b contractBindings) ForEach(fn func(readBinding) error) error { + for _, rbs := range b { + for _, rb := range rbs { + if err := fn(rb); err != nil { + return err + } + } + } + return nil } diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index 387d411d1af..589c8e8b4e8 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -5,15 +5,12 @@ import ( "fmt" "strings" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -28,34 +25,40 @@ type ChainReaderService interface { } type chainReader struct { - lggr logger.Logger - lp logpoller.LogPoller - codec commontypes.RemoteCodec - client evmclient.Client - bindings Bindings + lggr logger.Logger + lp logpoller.LogPoller + client evmclient.Client + contractBindings contractBindings + parsed *parsedTypes + codec commontypes.RemoteCodec commonservices.StateMachine } // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error -func NewChainReaderService(lggr logger.Logger, lp logpoller.LogPoller, b Bindings, chain legacyevm.Chain, config types.ChainReaderConfig) (ChainReaderService, error) { - parsed := &parsedTypes{ - encoderDefs: map[string]*codecEntry{}, - decoderDefs: map[string]*codecEntry{}, +func NewChainReaderService(lggr logger.Logger, lp logpoller.LogPoller, chain legacyevm.Chain, config types.ChainReaderConfig) (ChainReaderService, error) { + cr := &chainReader{ + lggr: lggr.Named("ChainReader"), + lp: lp, + client: chain.Client(), + contractBindings: contractBindings{}, + parsed: &parsedTypes{encoderDefs: map[string]*codecEntry{}, decoderDefs: map[string]*codecEntry{}}, } - if err := addTypes(config.ChainContractReaders, b, parsed); err != nil { + var err error + if err = cr.init(config.ChainContractReaders); err != nil { return nil, err } - c, err := parsed.toCodec() + if cr.codec, err = cr.parsed.toCodec(); err != nil { + return nil, err + } - return &chainReader{ - lggr: lggr.Named("ChainReader"), - lp: lp, - codec: c, - client: chain.Client(), - bindings: b, - }, err + err = cr.contractBindings.ForEach(func(b readBinding) error { + b.SetCodec(cr.codec) + return nil + }) + + return cr, err } func (cr *chainReader) Name() string { return cr.lggr.Name() } @@ -63,90 +66,59 @@ func (cr *chainReader) Name() string { return cr.lggr.Name() } var _ commontypes.ContractTypeProvider = &chainReader{} func (cr *chainReader) GetLatestValue(ctx context.Context, contractName, method string, params any, returnVal any) error { - ae, err := cr.bindings.getBinding(contractName, method, false) + b, err := cr.contractBindings.GetReadBinding(contractName, method) if err != nil { return err } - if ae.evt == nil { - return cr.getLatestValueFromContract(ctx, contractName, method, params, returnVal) - } - - return cr.getLatestValueFromLogPoller(ctx, contractName, method, *ae.evt, returnVal) -} - -func (cr *chainReader) getLatestValueFromLogPoller(ctx context.Context, contractName, method string, hash common.Hash, returnVal any) error { - ae, err := cr.bindings.getBinding(contractName, method, false) + bytes, err := b.GetLatestValue(ctx, params) if err != nil { return err } - - log, err := cr.lp.LatestLogByEventSigWithConfs(hash, ae.addr, logpoller.Finalized) - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, "not found") || strings.Contains(errStr, "noRows") { - return fmt.Errorf("%w: %w", commontypes.ErrNotFound, err) - } - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - return cr.codec.Decode(ctx, log.Data, returnVal, wrapItemType(contractName, method, false)) + return cr.codec.Decode(ctx, bytes, returnVal, wrapItemType(contractName, method, false)) } -func (cr *chainReader) getLatestValueFromContract(ctx context.Context, contractName, method string, params any, returnVal any) error { - data, err := cr.codec.Encode(ctx, params, wrapItemType(contractName, method, true)) - if err != nil { - return err - } +func (cr *chainReader) Bind(_ context.Context, bindings []commontypes.BoundContract) error { + return cr.contractBindings.Bind(bindings) +} - ae, err := cr.bindings.getBinding(contractName, method, true) - if err != nil { - return err - } - callMsg := ethereum.CallMsg{ - To: &ae.addr, - From: ae.addr, - Data: data, - } +func (cr *chainReader) init(chainContractReaders map[string]types.ChainContractReader) error { + for contractName, chainContractReader := range chainContractReaders { + contractAbi, err := abi.JSON(strings.NewReader(chainContractReader.ContractABI)) + if err != nil { + return err + } - output, err := cr.client.CallContract(ctx, callMsg, nil) + for typeName, chainReaderDefinition := range chainContractReader.ChainReaderDefinitions { + switch chainReaderDefinition.ReadType { + case types.Method: + err = cr.addMethod(contractName, typeName, contractAbi, chainReaderDefinition) + case types.Event: + err = cr.addEvent(contractName, typeName, contractAbi, chainReaderDefinition) + default: + return fmt.Errorf( + "%w: invalid chain reader definition read type: %d", + commontypes.ErrInvalidConfig, + chainReaderDefinition.ReadType) + } - if err != nil { - return err + if err != nil { + return err + } + } } - - return cr.codec.Decode(ctx, output, returnVal, wrapItemType(contractName, method, false)) + return nil } func (cr *chainReader) Start(_ context.Context) error { return cr.StartOnce("ChainReader", func() error { - for contractName, contractEvents := range cr.bindings { - for eventName, b := range contractEvents { - if b.evt == nil { - continue - } - - if err := cr.lp.RegisterFilter(logpoller.Filter{ - Name: wrapItemType(contractName, eventName, false), - EventSigs: evmtypes.HashArray{*b.evt}, - Addresses: evmtypes.AddressArray{b.addr}, - }); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - } - } - return nil + return cr.contractBindings.ForEach(readBinding.Register) }) } + func (cr *chainReader) Close() error { return cr.StopOnce("ChainReader", func() error { - for contractName, contractEvents := range cr.bindings { - for eventName := range contractEvents { - if err := cr.lp.UnregisterFilter(wrapItemType(contractName, eventName, false)); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - } - } - return nil + return cr.contractBindings.ForEach(readBinding.Unregister) }) } @@ -159,34 +131,49 @@ func (cr *chainReader) CreateContractType(contractName, methodName string, forEn return cr.codec.CreateType(wrapItemType(contractName, methodName, forEncoding), forEncoding) } -func addEventTypes(contractName, methodName string, b Bindings, contractABI abi.ABI, chainReaderDefinition types.ChainReaderDefinition, parsed *parsedTypes) error { - event, methodExists := contractABI.Events[chainReaderDefinition.ChainSpecificName] - if !methodExists { - return fmt.Errorf("%w: method %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) - } - - if err := b.addEvent(contractName, methodName, event.ID); err != nil { - return err +func wrapItemType(contractName, methodName string, isParams bool) string { + if isParams { + return fmt.Sprintf("params.%s.%s", contractName, methodName) } - - return addDecoderDef(contractName, methodName, event.Inputs, parsed, chainReaderDefinition) + return fmt.Sprintf("return.%s.%s", contractName, methodName) } -func addMethods( - contractName, methodName string, abi abi.ABI, chainReaderDefinition types.ChainReaderDefinition, parsed *parsedTypes) error { +func (cr *chainReader) addMethod( + contractName, + methodName string, + abi abi.ABI, + chainReaderDefinition types.ChainReaderDefinition) error { method, methodExists := abi.Methods[chainReaderDefinition.ChainSpecificName] if !methodExists { - return fmt.Errorf("method: %q doesn't exist", chainReaderDefinition.ChainSpecificName) + return fmt.Errorf("%w: method %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) } - if err := addEncoderDef(contractName, methodName, method, parsed, chainReaderDefinition); err != nil { + cr.contractBindings.AddReadBinding(contractName, methodName, &methodBinding{ + contractName: contractName, + method: methodName, + client: cr.client, + }) + + if err := cr.addEncoderDef(contractName, methodName, method, chainReaderDefinition); err != nil { return err } - return addDecoderDef(contractName, methodName, method.Outputs, parsed, chainReaderDefinition) + return cr.addDecoderDef(contractName, methodName, method.Outputs, chainReaderDefinition) } -func addEncoderDef(contractName, methodName string, method abi.Method, parsed *parsedTypes, chainReaderDefinition types.ChainReaderDefinition) error { +func (cr *chainReader) addEvent(contractName, eventName string, abi abi.ABI, chainReaderDefinition types.ChainReaderDefinition) error { + event, eventExists := abi.Events[chainReaderDefinition.ChainSpecificName] + if !eventExists { + return fmt.Errorf("%w: method %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) + } + cr.contractBindings.AddReadBinding(contractName, eventName, &eventBinding{ + lp: cr.lp, + hash: event.ID, + }) + return cr.addDecoderDef(contractName, eventName, event.Inputs, chainReaderDefinition) +} + +func (cr *chainReader) addEncoderDef(contractName, methodName string, method abi.Method, 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: method.Inputs, encodingPrefix: method.ID} @@ -199,53 +186,17 @@ func addEncoderDef(contractName, methodName string, method abi.Method, parsed *p return err } input.mod = inputMod - parsed.encoderDefs[wrapItemType(contractName, methodName, true)] = input + cr.parsed.encoderDefs[wrapItemType(contractName, methodName, true)] = input return nil } -func addDecoderDef(contractName, methodName string, outputs abi.Arguments, parsed *parsedTypes, def types.ChainReaderDefinition) error { +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 - parsed.decoderDefs[wrapItemType(contractName, methodName, false)] = output + cr.parsed.decoderDefs[wrapItemType(contractName, methodName, false)] = output return output.Init() } - -func addTypes(chainContractReaders map[string]types.ChainContractReader, b Bindings, parsed *parsedTypes) error { - for contractName, chainContractReader := range chainContractReaders { - contractAbi, err := abi.JSON(strings.NewReader(chainContractReader.ContractABI)) - if err != nil { - return err - } - - for typeName, chainReaderDefinition := range chainContractReader.ChainReaderDefinitions { - switch chainReaderDefinition.ReadType { - case types.Method: - err = addMethods(contractName, typeName, contractAbi, chainReaderDefinition, parsed) - case types.Event: - err = addEventTypes(contractName, typeName, b, contractAbi, chainReaderDefinition, parsed) - default: - return fmt.Errorf( - "%w: invalid chain reader definition read type: %d", - commontypes.ErrInvalidConfig, - chainReaderDefinition.ReadType) - } - - if err != nil { - return err - } - } - } - - return nil -} - -func wrapItemType(contractName, methodName string, isParams bool) string { - if isParams { - return fmt.Sprintf("params.%s.%s", contractName, methodName) - } - return fmt.Sprintf("return.%s.%s", contractName, methodName) -} diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go index 689c2941e88..360524bd9e1 100644 --- a/core/services/relay/evm/chain_reader_test.go +++ b/core/services/relay/evm/chain_reader_test.go @@ -141,27 +141,12 @@ func (it *chainReaderInterfaceTester) GetChainReader(t *testing.T) clcommontypes return it.cr } - addr := common.HexToAddress(it.address) - addr2 := common.HexToAddress(it.address2) lggr := logger.NullLogger db := pgtest.NewSqlxDB(t) lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr, pgtest.NewQConfig(true)), it.chain.Client(), lggr, time.Millisecond, false, 0, 1, 1, 10000) require.NoError(t, lp.Start(ctx)) it.chain.On("LogPoller").Return(lp) - b := evm.Bindings{ - AnyContractName: { - MethodTakingLatestParamsReturningTestStruct: evm.NewAddrEvtFromAddress(addr), - MethodReturningUint64: evm.NewAddrEvtFromAddress(addr), - DifferentMethodReturningUint64: evm.NewAddrEvtFromAddress(addr2), - MethodReturningUint64Slice: evm.NewAddrEvtFromAddress(addr), - EventName: evm.NewAddrEvtFromAddress(addr), - MethodReturningSeenStruct: evm.NewAddrEvtFromAddress(addr), - }, - AnySecondContractName: { - MethodReturningUint64: evm.NewAddrEvtFromAddress(addr2), - }, - } - cr, err := evm.NewChainReaderService(lggr, lp, b, it.chain, it.chainConfig) + cr, err := evm.NewChainReaderService(lggr, lp, it.chain, it.chainConfig) require.NoError(t, err) require.NoError(t, cr.Start(ctx)) it.cr = cr @@ -176,6 +161,13 @@ func (it *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *Tes it.sendTxWithTestStruct(t, testStruct, (*testfiles.TestfilesTransactor).TriggerEvent) } +func (it *chainReaderInterfaceTester) GetBindings(t *testing.T) []clcommontypes.BoundContract { + return []clcommontypes.BoundContract{ + {Name: AnyContractName, Address: it.address, Pending: true}, + {Name: AnySecondContractName, Address: it.address2, Pending: true}, + } +} + type testStructFn = func(*testfiles.TestfilesTransactor, *bind.TransactOpts, int32, string, uint8, [32]uint8, common.Address, []common.Address, *big.Int, testfiles.MidLevelTestStruct) (*evmtypes.Transaction, error) func (it *chainReaderInterfaceTester) sendTxWithTestStruct(t *testing.T, testStruct *TestStruct, fn testStructFn) { diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 71845512767..e4901117820 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -493,15 +493,12 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp // allow fallback until chain reader is default and median contract is removed, but still log just in case var chainReaderService ChainReaderService if relayConfig.ChainReader != nil { - b := Bindings{ - // TODO BCF-2837: clean up the hard-coded values. - "median": { - "LatestTransmissionDetails": &addrEvtBinding{addr: contractID}, - "LatestRoundRequested": &addrEvtBinding{addr: contractID}, - }, + if chainReaderService, err = NewChainReaderService(lggr, r.chain.LogPoller(), r.chain, *relayConfig.ChainReader); err != nil { + return nil, err } - if chainReaderService, err = NewChainReaderService(lggr, r.chain.LogPoller(), b, r.chain, *relayConfig.ChainReader); err != nil { + boundContracts := []commontypes.BoundContract{{Name: "median", Pending: true, Address: contractID.String()}} + if err = chainReaderService.Bind(context.Background(), boundContracts); err != nil { return nil, err } } else { diff --git a/go.mod b/go.mod index 6b509a1a6ad..5b4fd8fbb80 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.20231214180711-f4668ff89fe9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 github.com/smartcontractkit/chainlink-feeds v0.0.0-20231213175155-181d4a261f5d diff --git a/go.sum b/go.sum index fbdaa58c58e..a8769c28452 100644 --- a/go.sum +++ b/go.sum @@ -1134,8 +1134,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.20231214180711-f4668ff89fe9 h1:dca0f2dpHOPPu6raYK5nJU0A5P7JkXM5PbMGNezg2NI= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231214180711-f4668ff89fe9/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e h1:t9yp8N8WgbCspo0JOIJaxyYNeMEzpNhQXEyr708bFT4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679 h1:iu1pNbUoSDTrp+7BUtfTygZ2C0f5C2ZOBQhIoJjp+S0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679/go.mod h1:2Jx7bTEk4ujFQdsZpZq3A0BydvaVPs6mX8clUfxHOEM= 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 5b0e0c34648..54612b74d61 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -24,7 +24,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.20231214180711-f4668ff89fe9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e github.com/smartcontractkit/chainlink-testing-framework v1.22.0 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 4d8a285a00a..faac9b5958d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1432,8 +1432,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.20231214180711-f4668ff89fe9 h1:dca0f2dpHOPPu6raYK5nJU0A5P7JkXM5PbMGNezg2NI= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231214180711-f4668ff89fe9/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e h1:t9yp8N8WgbCspo0JOIJaxyYNeMEzpNhQXEyr708bFT4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231220205429-813aebce838e/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679 h1:iu1pNbUoSDTrp+7BUtfTygZ2C0f5C2ZOBQhIoJjp+S0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231128204301-ee4297eff679/go.mod h1:2Jx7bTEk4ujFQdsZpZq3A0BydvaVPs6mX8clUfxHOEM= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ=