Skip to content

Commit

Permalink
Merge branch 'develop' into feature/CAPPL-22-web-api-trigger-connecto…
Browse files Browse the repository at this point in the history
…r-handler-2
  • Loading branch information
DavidOrchard committed Sep 30, 2024
2 parents d1eaa74 + 19690b0 commit 0149b98
Show file tree
Hide file tree
Showing 34 changed files with 724 additions and 190 deletions.
5 changes: 5 additions & 0 deletions .changeset/honest-cameras-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Implementing evm specific token data encoder for CCIP #internal
8 changes: 8 additions & 0 deletions .changeset/moody-rules-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"chainlink": patch
---

- register polling subscription to avoid subscription leaking when rpc client gets closed.
- add a temporary special treatment for SubscribeNewHead before we replace it with SubscribeToHeads. Add a goroutine that forwards new head from poller to caller channel.
- fix a deadlock in poller, by using a new lock for subs slice in rpc client.
#bugfix
5 changes: 5 additions & 0 deletions .changeset/nervous-books-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#internal Updated QueryKey to be able to do advanced queries on contract event data words
5 changes: 5 additions & 0 deletions .changeset/tidy-apricots-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#added Pass the home chain selector to the commit plugin factory
10 changes: 10 additions & 0 deletions contracts/.changeset/tall-donkeys-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@chainlink/contracts': minor
---

#internal Updated ChainReaderTester to include dynamic and static nested structs in TestStruct


PR issue: BCFR-44

Solidity Review issue: BCFR-957
74 changes: 61 additions & 13 deletions contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,41 @@ struct TestStruct {
address Account;
address[] Accounts;
int192 BigField;
MidLevelTestStruct NestedStruct;
MidLevelDynamicTestStruct NestedDynamicStruct;
MidLevelStaticTestStruct NestedStaticStruct;
}

struct MidLevelTestStruct {
struct MidLevelDynamicTestStruct {
bytes2 FixedBytes;
InnerTestStruct Inner;
InnerDynamicTestStruct Inner;
}

struct InnerTestStruct {
struct InnerDynamicTestStruct {
int64 IntVal;
string S;
}

struct MidLevelStaticTestStruct {
bytes2 FixedBytes;
InnerStaticTestStruct Inner;
}

struct InnerStaticTestStruct {
int64 IntVal;
address A;
}

contract ChainReaderTester {
event Triggered(
int32 indexed field,
uint8 oracleId,
MidLevelDynamicTestStruct nestedDynamicStruct,
MidLevelStaticTestStruct nestedStaticStruct,
uint8[32] oracleIds,
address Account,
address[] Accounts,
string differentField,
int192 bigField,
MidLevelTestStruct nestedStruct
int192 bigField
);

event TriggeredEventWithDynamicTopic(string indexed fieldHash, string field);
Expand Down Expand Up @@ -61,9 +73,22 @@ contract ChainReaderTester {
address account,
address[] calldata accounts,
int192 bigField,
MidLevelTestStruct calldata nestedStruct
MidLevelDynamicTestStruct calldata nestedDynamicStruct,
MidLevelStaticTestStruct calldata nestedStaticStruct
) public {
s_seen.push(TestStruct(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct));
s_seen.push(
TestStruct(
field,
differentField,
oracleId,
oracleIds,
account,
accounts,
bigField,
nestedDynamicStruct,
nestedStaticStruct
)
);
}

function setAlterablePrimitiveValue(uint64 value) public {
Expand All @@ -78,9 +103,21 @@ contract ChainReaderTester {
address account,
address[] calldata accounts,
int192 bigField,
MidLevelTestStruct calldata nestedStruct
MidLevelDynamicTestStruct calldata nestedDynamicStruct,
MidLevelStaticTestStruct calldata nestedStaticStruct
) public pure returns (TestStruct memory) {
return TestStruct(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct);
return
TestStruct(
field,
differentField,
oracleId,
oracleIds,
account,
accounts,
bigField,
nestedDynamicStruct,
nestedStaticStruct
);
}

function getElementAtIndex(uint256 i) public view returns (TestStruct memory) {
Expand Down Expand Up @@ -110,14 +147,25 @@ contract ChainReaderTester {
function triggerEvent(
int32 field,
uint8 oracleId,
MidLevelDynamicTestStruct calldata nestedDynamicStruct,
MidLevelStaticTestStruct calldata nestedStaticStruct,
uint8[32] calldata oracleIds,
address account,
address[] calldata accounts,
string calldata differentField,
int192 bigField,
MidLevelTestStruct calldata nestedStruct
int192 bigField
) public {
emit Triggered(field, oracleId, oracleIds, account, accounts, differentField, bigField, nestedStruct);
emit Triggered(
field,
oracleId,
nestedDynamicStruct,
nestedStaticStruct,
oracleIds,
account,
accounts,
differentField,
bigField
);
}

function triggerEventWithDynamicTopic(string calldata field) public {
Expand Down
38 changes: 38 additions & 0 deletions core/capabilities/ccip/ccipevm/tokendata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ccipevm

import (
"context"

cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"

"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers"
)

type usdcAttestationPayload struct {
Message []byte
Attestation []byte
}

func (m usdcAttestationPayload) AbiString() string {
return `
[{
"components": [
{"name": "message", "type": "bytes"},
{"name": "attestation", "type": "bytes"}
],
"type": "tuple"
}]`
}

type EVMTokenDataEncoder struct{}

func NewEVMTokenDataEncoder() EVMTokenDataEncoder {
return EVMTokenDataEncoder{}
}

func (e EVMTokenDataEncoder) EncodeUSDC(_ context.Context, message cciptypes.Bytes, attestation cciptypes.Bytes) (cciptypes.Bytes, error) {
return abihelpers.EncodeAbiStruct(usdcAttestationPayload{
Message: message,
Attestation: attestation,
})
}
73 changes: 73 additions & 0 deletions core/capabilities/ccip/ccipevm/tokendata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ccipevm

import (
"testing"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/stretchr/testify/require"

cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"

"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers"
)

func Test_EVMTokenDataEncoder(t *testing.T) {
var empty usdcAttestationPayload
encoder := NewEVMTokenDataEncoder()

//https://testnet.snowtrace.io/tx/0xeeb0ad6b26bacd1570a9361724a36e338f4aacf1170dec64399220b7483b7eed/eventlog?chainid=43113
//https://iris-api-sandbox.circle.com/v1/attestations/0x69fb1b419d648cf6c9512acad303746dc85af3b864af81985c76764aba60bf6b
realMessage, err := cciptypes.NewBytesFromString("0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f8000000000000000100000006000000000004ac0d000000000000000000000000eb08f243e5d3fcff26a9e38ae5520a669f4019d00000000000000000000000009f3b8679c73c2fef8b59b4f3444d4e156fb70aa5000000000000000000000000c08835adf4884e51ff076066706e407506826d9d000000000000000000000000000000005425890298aed601595a70ab815c96711a31bc650000000000000000000000004f32ae7f112c26b109357785e5c66dc5d747fbce00000000000000000000000000000000000000000000000000000000000000640000000000000000000000007a4d8f8c18762d362e64b411d7490fba112811cd0000000000000000")
require.NoError(t, err)
realAttestation, err := cciptypes.NewBytesFromString("0xee466fbd340596aa56e3e40d249869573e4008d84d795b4f2c3cba8649083d08653d38190d0df7e0ee12ae685df2f806d100a03b3716ab1ff2013c7201f1c2d01c9af959b55a4b52dbd0319eed69ce9ace25259830e0b1bff79faf0c9c5d1b5e6d6304e824d657db38f802bcff3e97d0bd30f2ffc62b62381f52c1668ceaa5a73a1b")
require.NoError(t, err)

tt := []struct {
name string
message []byte
attestation []byte
}{
{
name: "empty both fields",
message: nil,
attestation: []byte{},
},
{
name: "empty attestation",
message: []byte("message"),
attestation: nil,
},
{
name: "both attestation and message are set",
message: realMessage,
attestation: realAttestation,
},
}

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
got, err := encoder.EncodeUSDC(tests.Context(t), tc.message, tc.attestation)
require.NoError(t, err)

decoded, err := abihelpers.ABIDecode(empty.AbiString(), got)
require.NoError(t, err)

converted := abi.ConvertType(decoded[0], &empty)
casted, ok := converted.(*usdcAttestationPayload)
require.True(t, ok)

if tc.message == nil {
require.Empty(t, casted.Message)
} else {
require.Equal(t, tc.message, casted.Message)
}

if tc.attestation == nil {
require.Empty(t, casted.Attestation)
} else {
require.Equal(t, tc.attestation, casted.Attestation)
}
})
}
}
12 changes: 12 additions & 0 deletions core/capabilities/ccip/configs/evm/contract_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ var (
nonceManagerABI = evmtypes.MustGetABI(nonce_manager.NonceManagerABI)
priceFeedABI = evmtypes.MustGetABI(aggregator_v3_interface.AggregatorV3InterfaceABI)
rmnRemoteABI = evmtypes.MustGetABI(rmn_remote.RMNRemoteABI)
rmnHomeABI = evmtypes.MustGetABI(rmnHomeString)
)

// TODO: replace with generated ABI when the contract will be defined
var rmnHomeString = "[{\"inputs\":[],\"name\":\"getAllConfigs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"num\",\"type\":\"uint256\"}],\"name\":\"store\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"

// MustSourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp.
// The configuration is marshaled into JSON so that it can be passed to the relayer NewContractReader() method.
func MustSourceReaderConfig() []byte {
Expand Down Expand Up @@ -249,6 +253,14 @@ var HomeChainReaderConfigRaw = evmrelaytypes.ChainReaderConfig{
},
},
},
consts.ContractNameRMNHome: {
ContractABI: rmnHomeString,
Configs: map[string]*evmrelaytypes.ChainReaderDefinition{
consts.MethodNameGetAllConfigs: {
ChainSpecificName: mustGetMethodName("getAllConfigs", rmnHomeABI),
},
},
},
},
}

Expand Down
16 changes: 16 additions & 0 deletions core/capabilities/ccip/delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ccip
import (
"context"
"fmt"
"strconv"
"time"

"github.com/smartcontractkit/chainlink-common/pkg/loop"
Expand All @@ -23,7 +24,11 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"

chainsel "github.com/smartcontractkit/chain-selectors"

cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"

"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
"github.com/smartcontractkit/chainlink/v2/core/config"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
Expand Down Expand Up @@ -162,6 +167,16 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services
ccipConfigBinding,
)

// get the chain selector for the home chain
homeChainChainID, err := strconv.ParseUint(d.capabilityConfig.ExternalRegistry().RelayID().ChainID, 10, 64)
if err != nil {
return nil, fmt.Errorf("failed to parse chain ID %s: %w", d.capabilityConfig.ExternalRegistry().RelayID().ChainID, err)
}
homeChainChainSelector, err := chainsel.SelectorFromChainId(homeChainChainID)
if err != nil {
return nil, fmt.Errorf("failed to get chain selector from chain ID %d", homeChainChainID)
}

// if bootstrappers are provided we assume that the node is a plugin oracle.
// the reason for this is that bootstrap oracles do not need to be aware
// of other bootstrap oracles. however, plugin oracles, at least initially,
Expand All @@ -182,6 +197,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services
d.monitoringEndpointGen,
bootstrapperLocators,
hcr,
cciptypes.ChainSelector(homeChainChainSelector),
)
} else {
oracleCreator = oraclecreator.NewBootstrapOracleCreator(
Expand Down
Loading

0 comments on commit 0149b98

Please sign in to comment.