Skip to content

Commit

Permalink
CCIP-1704 OnRamp reader minor refactoring (#581)
Browse files Browse the repository at this point in the history
Extracting LeafHasher to a separate files, minor reordering in OnRamps code
  • Loading branch information
mateusz-sekara authored Mar 5, 2024
1 parent f026e9d commit d8d8a63
Show file tree
Hide file tree
Showing 11 changed files with 613 additions and 558 deletions.
84 changes: 84 additions & 0 deletions core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package v1_0_0

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/hashlib"
)

const (
MetaDataHashPrefix = "EVM2EVMMessageEvent"
)

var LeafDomainSeparator = [1]byte{0x00}

type LeafHasher struct {
metaDataHash [32]byte
ctx hashlib.Ctx[[32]byte]
onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp
}

func GetMetaDataHash[H hashlib.Hash](ctx hashlib.Ctx[H], prefix [32]byte, sourceChainSelector uint64, onRampId common.Address, destChainSelector uint64) H {
paddedOnRamp := common.BytesToHash(onRampId[:])
return ctx.Hash(utils.ConcatBytes(prefix[:], math.U256Bytes(big.NewInt(0).SetUint64(sourceChainSelector)), math.U256Bytes(big.NewInt(0).SetUint64(destChainSelector)), paddedOnRamp[:]))
}

func NewLeafHasher(sourceChainSelector uint64, destChainSelector uint64, onRampId common.Address, ctx hashlib.Ctx[[32]byte], onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp) *LeafHasher {
return &LeafHasher{
metaDataHash: GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector),
ctx: ctx,
onRamp: onRamp,
}
}

func (t *LeafHasher) HashLeaf(log types.Log) ([32]byte, error) {
message, err := t.onRamp.ParseCCIPSendRequested(log)
if err != nil {
return [32]byte{}, err
}
encodedTokens, err := utils.ABIEncode(
`[
{"components": [{"name":"token","type":"address"},{"name":"amount","type":"uint256"}], "type":"tuple[]"}]`, message.Message.TokenAmounts)
if err != nil {
return [32]byte{}, err
}

packedValues, err := utils.ABIEncode(
`[
{"name": "leafDomainSeparator","type":"bytes1"},
{"name": "metadataHash", "type":"bytes32"},
{"name": "sequenceNumber", "type":"uint64"},
{"name": "nonce", "type":"uint64"},
{"name": "sender", "type":"address"},
{"name": "receiver", "type":"address"},
{"name": "dataHash", "type":"bytes32"},
{"name": "tokenAmountsHash", "type":"bytes32"},
{"name": "gasLimit", "type":"uint256"},
{"name": "strict", "type":"bool"},
{"name": "feeToken","type": "address"},
{"name": "feeTokenAmount","type": "uint256"}
]`,
LeafDomainSeparator,
t.metaDataHash,
message.Message.SequenceNumber,
message.Message.Nonce,
message.Message.Sender,
message.Message.Receiver,
t.ctx.Hash(message.Message.Data),
t.ctx.Hash(encodedTokens),
message.Message.GasLimit,
message.Message.Strict,
message.Message.FeeToken,
message.Message.FeeTokenAmount,
)
if err != nil {
return [32]byte{}, err
}
return t.ctx.Hash(packedValues), nil
}
201 changes: 65 additions & 136 deletions core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@ package v1_0_0

import (
"context"
"errors"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers"
Expand All @@ -25,76 +22,8 @@ import (

const (
CCIPSendRequestedEventName = "CCIPSendRequested"
MetaDataHashPrefix = "EVM2EVMMessageEvent"
)

var LeafDomainSeparator = [1]byte{0x00}

type LeafHasher struct {
metaDataHash [32]byte
ctx hashlib.Ctx[[32]byte]
onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp
}

func GetMetaDataHash[H hashlib.Hash](ctx hashlib.Ctx[H], prefix [32]byte, sourceChainSelector uint64, onRampId common.Address, destChainSelector uint64) H {
paddedOnRamp := common.BytesToHash(onRampId[:])
return ctx.Hash(utils.ConcatBytes(prefix[:], math.U256Bytes(big.NewInt(0).SetUint64(sourceChainSelector)), math.U256Bytes(big.NewInt(0).SetUint64(destChainSelector)), paddedOnRamp[:]))
}

func NewLeafHasher(sourceChainSelector uint64, destChainSelector uint64, onRampId common.Address, ctx hashlib.Ctx[[32]byte], onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp) *LeafHasher {
return &LeafHasher{
metaDataHash: GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector),
ctx: ctx,
onRamp: onRamp,
}
}

func (t *LeafHasher) HashLeaf(log types.Log) ([32]byte, error) {
message, err := t.onRamp.ParseCCIPSendRequested(log)
if err != nil {
return [32]byte{}, err
}
encodedTokens, err := utils.ABIEncode(
`[
{"components": [{"name":"token","type":"address"},{"name":"amount","type":"uint256"}], "type":"tuple[]"}]`, message.Message.TokenAmounts)
if err != nil {
return [32]byte{}, err
}

packedValues, err := utils.ABIEncode(
`[
{"name": "leafDomainSeparator","type":"bytes1"},
{"name": "metadataHash", "type":"bytes32"},
{"name": "sequenceNumber", "type":"uint64"},
{"name": "nonce", "type":"uint64"},
{"name": "sender", "type":"address"},
{"name": "receiver", "type":"address"},
{"name": "dataHash", "type":"bytes32"},
{"name": "tokenAmountsHash", "type":"bytes32"},
{"name": "gasLimit", "type":"uint256"},
{"name": "strict", "type":"bool"},
{"name": "feeToken","type": "address"},
{"name": "feeTokenAmount","type": "uint256"}
]`,
LeafDomainSeparator,
t.metaDataHash,
message.Message.SequenceNumber,
message.Message.Nonce,
message.Message.Sender,
message.Message.Receiver,
t.ctx.Hash(message.Message.Data),
t.ctx.Hash(encodedTokens),
message.Message.GasLimit,
message.Message.Strict,
message.Message.FeeToken,
message.Message.FeeTokenAmount,
)
if err != nil {
return [32]byte{}, err
}
return t.ctx.Hash(packedValues), nil
}

var _ ccipdata.OnRampReader = &OnRamp{}

type OnRamp struct {
Expand All @@ -109,6 +38,34 @@ type OnRamp struct {
filters []logpoller.Filter
}

func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAddress common.Address, sourceLP logpoller.LogPoller, source client.Client) (*OnRamp, error) {
onRamp, err := evm_2_evm_onramp_1_0_0.NewEVM2EVMOnRamp(onRampAddress, source)
if err != nil {
return nil, err
}
onRampABI := abihelpers.MustParseABI(evm_2_evm_onramp_1_0_0.EVM2EVMOnRampABI)
eventSig := abihelpers.MustGetEventID(CCIPSendRequestedEventName, onRampABI)
filters := []logpoller.Filter{
{
Name: logpoller.FilterName(ccipdata.COMMIT_CCIP_SENDS, onRampAddress),
EventSigs: []common.Hash{eventSig},
Addresses: []common.Address{onRampAddress},
},
}
return &OnRamp{
lggr: lggr,
address: onRampAddress,
onRamp: onRamp,
client: source,
filters: filters,
lp: sourceLP,
leafHasher: NewLeafHasher(sourceSelector, destSelector, onRampAddress, hashlib.NewKeccakCtx(), onRamp),
// offset || sourceChainID || seqNum || ...
sendRequestedSeqNumberWord: 2,
sendRequestedEventSig: eventSig,
}, nil
}

func (o *OnRamp) Address() (cciptypes.Address, error) {
return cciptypes.Address(o.onRamp.Address().String()), nil
}
Expand All @@ -135,6 +92,42 @@ func (o *OnRamp) GetDynamicConfig() (cciptypes.OnRampDynamicConfig, error) {
}, nil
}

func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) {
logs, err := o.lp.LogsDataWordRange(
o.sendRequestedEventSig,
o.address,
o.sendRequestedSeqNumberWord,
logpoller.EvmWord(seqNumMin),
logpoller.EvmWord(seqNumMax),
ccipdata.LogsConfirmations(finalized),
pg.WithParentCtx(ctx))
if err != nil {
return nil, err
}

parsedLogs, err := ccipdata.ParseLogs[cciptypes.EVM2EVMMessage](logs, o.lggr, o.logToMessage)
if err != nil {
return nil, err
}

res := make([]cciptypes.EVM2EVMMessageWithTxMeta, 0, len(parsedLogs))
for _, log := range parsedLogs {
res = append(res, cciptypes.EVM2EVMMessageWithTxMeta{
TxMeta: log.TxMeta,
EVM2EVMMessage: log.Data,
})
}
return res, nil
}

func (o *OnRamp) RouterAddress() (cciptypes.Address, error) {
config, err := o.onRamp.GetDynamicConfig(nil)
if err != nil {
return "", err
}
return cciptypes.Address(config.Router.String()), nil
}

func (o *OnRamp) GetLastUSDCMessagePriorToLogIndexInTx(ctx context.Context, logIndex int64, txHash common.Hash) ([]byte, error) {
return nil, errors.New("USDC not supported in < 1.2.0")
}
Expand All @@ -147,34 +140,6 @@ func (o *OnRamp) RegisterFilters(qopts ...pg.QOpt) error {
return logpollerutil.RegisterLpFilters(o.lp, o.filters, qopts...)
}

func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAddress common.Address, sourceLP logpoller.LogPoller, source client.Client) (*OnRamp, error) {
onRamp, err := evm_2_evm_onramp_1_0_0.NewEVM2EVMOnRamp(onRampAddress, source)
if err != nil {
return nil, err
}
onRampABI := abihelpers.MustParseABI(evm_2_evm_onramp_1_0_0.EVM2EVMOnRampABI)
eventSig := abihelpers.MustGetEventID(CCIPSendRequestedEventName, onRampABI)
filters := []logpoller.Filter{
{
Name: logpoller.FilterName(ccipdata.COMMIT_CCIP_SENDS, onRampAddress),
EventSigs: []common.Hash{eventSig},
Addresses: []common.Address{onRampAddress},
},
}
return &OnRamp{
lggr: lggr,
address: onRampAddress,
onRamp: onRamp,
client: source,
filters: filters,
lp: sourceLP,
leafHasher: NewLeafHasher(sourceSelector, destSelector, onRampAddress, hashlib.NewKeccakCtx(), onRamp),
// offset || sourceChainID || seqNum || ...
sendRequestedSeqNumberWord: 2,
sendRequestedEventSig: eventSig,
}, nil
}

func (o *OnRamp) logToMessage(log types.Log) (*cciptypes.EVM2EVMMessage, error) {
msg, err := o.onRamp.ParseCCIPSendRequested(log)
if err != nil {
Expand Down Expand Up @@ -208,39 +173,3 @@ func (o *OnRamp) logToMessage(log types.Log) (*cciptypes.EVM2EVMMessage, error)
Hash: h,
}, nil
}

func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) {
logs, err := o.lp.LogsDataWordRange(
o.sendRequestedEventSig,
o.address,
o.sendRequestedSeqNumberWord,
logpoller.EvmWord(seqNumMin),
logpoller.EvmWord(seqNumMax),
ccipdata.LogsConfirmations(finalized),
pg.WithParentCtx(ctx))
if err != nil {
return nil, err
}

parsedLogs, err := ccipdata.ParseLogs[cciptypes.EVM2EVMMessage](logs, o.lggr, o.logToMessage)
if err != nil {
return nil, err
}

res := make([]cciptypes.EVM2EVMMessageWithTxMeta, 0, len(parsedLogs))
for _, log := range parsedLogs {
res = append(res, cciptypes.EVM2EVMMessageWithTxMeta{
TxMeta: log.TxMeta,
EVM2EVMMessage: log.Data,
})
}
return res, nil
}

func (o *OnRamp) RouterAddress() (cciptypes.Address, error) {
config, err := o.onRamp.GetDynamicConfig(nil)
if err != nil {
return "", err
}
return cciptypes.Address(config.Router.String()), nil
}
Loading

0 comments on commit d8d8a63

Please sign in to comment.