Skip to content

Commit

Permalink
RMN Integration Test (#14932)
Browse files Browse the repository at this point in the history
* MessageHasher logging and bugfixing

* EVMRmnCrypto logging

* Bootstraper oracle updates

* RMNPeerClient logging improvement

* add RMNIntegrationTest

* upgrade cl-ccip

* skip the test

* remove exec part

* fix linter errs and add comments on addrs

* fix typo

* include exec report and fix exec plugin codec

* fix exec codec unit test

* upgrade cl-ccip

* use latest working cl-ccip version

* disable activeCandidate test

* fix gosum
  • Loading branch information
dimkouv authored Oct 25, 2024
1 parent 5eb6b74 commit 7c7222b
Show file tree
Hide file tree
Showing 25 changed files with 648 additions and 73 deletions.
3 changes: 1 addition & 2 deletions core/capabilities/ccip/ccipevm/executecodec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/ethereum/go-ethereum/common"

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

"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers"
)
Expand Down Expand Up @@ -86,7 +85,7 @@ func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.Exec
SequenceNumber: uint64(message.Header.SequenceNumber),
Nonce: message.Header.Nonce,
},
Sender: message.Sender,
Sender: common.LeftPadBytes(message.Sender, 32), // todo: make it chain-agnostic
Data: message.Data,
Receiver: receiver,
GasLimit: gasLimit,
Expand Down
3 changes: 2 additions & 1 deletion core/capabilities/ccip/ccipevm/executecodec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"

cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
Expand Down Expand Up @@ -61,7 +62,7 @@ var randomExecuteReport = func(t *testing.T, d *testSetupData) cciptypes.Execute
MsgHash: utils.RandomBytes32(),
OnRamp: utils.RandomAddress().Bytes(),
},
Sender: utils.RandomAddress().Bytes(),
Sender: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32),
Data: data,
Receiver: utils.RandomAddress().Bytes(),
ExtraArgs: extraArgs,
Expand Down
31 changes: 24 additions & 7 deletions core/capabilities/ccip/ccipevm/msghasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"fmt"

"github.com/smartcontractkit/chainlink-common/pkg/logger"

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

"github.com/ethereum/go-ethereum/accounts/abi"
Expand Down Expand Up @@ -34,10 +36,14 @@ var (
// MessageHasherV1 implements the MessageHasher interface.
// Compatible with:
// - "OnRamp 1.6.0-dev"
type MessageHasherV1 struct{}
type MessageHasherV1 struct {
lggr logger.Logger
}

func NewMessageHasherV1() *MessageHasherV1 {
return &MessageHasherV1{}
func NewMessageHasherV1(lggr logger.Logger) *MessageHasherV1 {
return &MessageHasherV1{
lggr: lggr,
}
}

// Hash implements the MessageHasher interface.
Expand Down Expand Up @@ -66,6 +72,8 @@ func NewMessageHasherV1() *MessageHasherV1 {
);
*/
func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (cciptypes.Bytes32, error) {
h.lggr.Debugw("hashing message", "msg", msg)

var rampTokenAmounts []message_hasher.InternalAny2EVMTokenTransfer
for _, rta := range msg.TokenAmounts {
destGasAmount, err := abiDecodeUint32(rta.DestExecData)
Expand All @@ -87,7 +95,8 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (ccipty
return [32]byte{}, fmt.Errorf("abi encode token amounts: %w", err)
}

fmt.Printf("encodedRampTokenAmounts: %x\n", encodedRampTokenAmounts)
h.lggr.Debugw("abi encoded ramp token amounts",
"encodedRampTokenAmounts", hexutil.Encode(encodedRampTokenAmounts))

metaDataHashInput, err := h.abiEncode(
"encodeMetadataHashPreimage",
Expand All @@ -102,6 +111,9 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (ccipty
return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err)
}

h.lggr.Debugw("abi encoded metadata hash input",
"metaDataHashInput", cciptypes.Bytes32(utils.Keccak256Fixed(metaDataHashInput)).String())

// Need to decode the extra args to get the gas limit.
// TODO: we assume that extra args is always abi-encoded for now, but we need
// to decode according to source chain selector family. We should add a family
Expand All @@ -128,17 +140,22 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (ccipty
leafDomainSeparator,
utils.Keccak256Fixed(metaDataHashInput), // metaDataHash
utils.Keccak256Fixed(fixedSizeFieldsEncoded),
utils.Keccak256Fixed(msg.Sender),
utils.Keccak256Fixed(common.LeftPadBytes(msg.Sender, 32)), // todo: this is not chain-agnostic
utils.Keccak256Fixed(msg.Data),
utils.Keccak256Fixed(encodedRampTokenAmounts),
)
if err != nil {
return [32]byte{}, fmt.Errorf("abi encode packed values: %w", err)
}

fmt.Printf("packedValues: %x\n", packedValues)
res := utils.Keccak256Fixed(packedValues)

h.lggr.Debugw("abi encoded msg hash",
"abiEncodedMsg", hexutil.Encode(packedValues),
"result", hexutil.Encode(res[:]),
)

return utils.Keccak256Fixed(packedValues), nil
return res, nil
}

func (h *MessageHasherV1) abiEncode(method string, values ...interface{}) ([]byte, error) {
Expand Down
43 changes: 41 additions & 2 deletions core/capabilities/ccip/ccipevm/msghasher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/stretchr/testify/require"

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

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"

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

// NOTE: these test cases are only EVM <-> EVM.
Expand Down Expand Up @@ -74,7 +77,7 @@ func testHasherEVM2EVM(ctx context.Context, t *testing.T, d *testSetupData, evmE
expectedHash, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, ccipMsg.Header.OnRamp)
require.NoError(t, err)

evmMsgHasher := NewMessageHasherV1()
evmMsgHasher := NewMessageHasherV1(logger.Test(t))
actualHash, err := evmMsgHasher.Hash(ctx, ccipMsg)
require.NoError(t, err)

Expand Down Expand Up @@ -194,3 +197,39 @@ func testSetup(t *testing.T) *testSetupData {
auth: transactor,
}
}

func TestMessagerHasher_againstRmnSharedVector(t *testing.T) {
const (
messageID = "c6f553ab71282f01324bbdbcc82e22a7e66efbcd108881ecc4cdbd728aed9b1e"
onRampAddress = "0000000000000000000000007a2088a1bfc9d81c55368ae168c2c02570cb814f"
dataField = "68656c6c6f"
receiverAddress = "677df0cb865368207999f2862ece576dc56d8df6"
extraArgs = "181dcf100000000000000000000000000000000000000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000000000"
senderAddress = "f39fd6e51aad88f6f4ce6ab8827279cfffb92266"
feeToken = "9fe46736679d2d9a65f0992f2272de9f3c7fa6e0"
sourceChainSelector = 3379446385462418246
destChainSelector = 12922642891491394802
expectedMsgHash = "0x1c61fef7a3dd153943419c1101031316ed7b7a3d75913c34cbe8628033f5924f"
)

h := NewMessageHasherV1(logger.Test(t))
msgH, err := h.Hash(context.Background(), cciptypes.Message{
Header: cciptypes.RampMessageHeader{
MessageID: cciptypes.Bytes32(common.Hex2Bytes(messageID)),
SourceChainSelector: sourceChainSelector,
DestChainSelector: destChainSelector,
SequenceNumber: 1,
Nonce: 1,
MsgHash: cciptypes.Bytes32{},
OnRamp: common.HexToAddress(onRampAddress).Bytes(),
},
Sender: common.HexToAddress(senderAddress).Bytes(),
Data: common.Hex2Bytes(dataField),
Receiver: common.Hex2Bytes(receiverAddress),
ExtraArgs: common.Hex2Bytes(extraArgs),
FeeToken: common.HexToAddress(feeToken).Bytes(),
TokenAmounts: []cciptypes.RampTokenAmount{},
})
require.NoError(t, err)
require.Equal(t, expectedMsgHash, msgH.String())
}
21 changes: 18 additions & 3 deletions core/capabilities/ccip/ccipevm/rmncrypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"

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

// encodingUtilsAbi is the ABI for the EncodingUtils contract.
Expand Down Expand Up @@ -46,13 +47,17 @@ const (
)

// EVMRMNCrypto is the RMNCrypto implementation for EVM chains.
type EVMRMNCrypto struct{}
type EVMRMNCrypto struct {
lggr logger.Logger
}

// Interface compliance check
var _ cciptypes.RMNCrypto = (*EVMRMNCrypto)(nil)

func NewEVMRMNCrypto() *EVMRMNCrypto {
return &EVMRMNCrypto{}
func NewEVMRMNCrypto(lggr logger.Logger) *EVMRMNCrypto {
return &EVMRMNCrypto{
lggr: lggr,
}
}

// Should be replaced by gethwrapper types when they're available
Expand Down Expand Up @@ -86,6 +91,12 @@ func (r *EVMRMNCrypto) VerifyReportSignatures(
return fmt.Errorf("no lane updates provided")
}

r.lggr.Debugw("Verifying RMN report signatures",
"sigs", sigs,
"report", report,
"signerAddresses", signerAddresses,
)

evmLaneUpdates := make([]evmInternalMerkleRoot, len(report.LaneUpdates))
for i, lu := range report.LaneUpdates {
onRampAddress := common.BytesToAddress(lu.OnRampAddress)
Expand Down Expand Up @@ -117,6 +128,7 @@ func (r *EVMRMNCrypto) VerifyReportSignatures(
}

signedHash := crypto.Keccak256Hash(abiEnc)
r.lggr.Debugw("Generated hash of ABI encoded report", "abiEnc", abiEnc, "hash", signedHash)

// keep track of the previous signer for validating signers ordering
prevSignerAddr := common.Address{}
Expand All @@ -138,6 +150,9 @@ func (r *EVMRMNCrypto) VerifyReportSignatures(
}
prevSignerAddr = recoveredAddress

r.lggr.Debugw("Recovered public key from signature",
"recoveredAddress", recoveredAddress.String())

// Check if the public key is in the list of the provided RMN nodes
found := false
for _, signerAddr := range signerAddresses {
Expand Down
3 changes: 2 additions & 1 deletion core/capabilities/ccip/ccipevm/rmncrypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"

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

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -54,7 +55,7 @@ func Test_VerifyRmnReportSignatures(t *testing.T) {

ctx := tests.Context(t)

rmnCrypto := NewEVMRMNCrypto()
rmnCrypto := NewEVMRMNCrypto(logger.Test(t))

r, _ := cciptypes.NewBytes32FromString("0x89546b4652d0377062a398e413344e4da6034ae877c437d0efe0e5246b70a9a1")
s, _ := cciptypes.NewBytes32FromString("0x95eef2d24d856ccac3886db8f4aebea60684ed73942392692908fed79a679b4e")
Expand Down
1 change: 1 addition & 0 deletions core/capabilities/ccip/delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services
ocrDB,
d.monitoringEndpointGen,
d.lggr,
homeChainContractReader,
)
}

Expand Down
Loading

0 comments on commit 7c7222b

Please sign in to comment.