From 3d1af8f11e883d20cf5cd42ecaffb9d7e8558208 Mon Sep 17 00:00:00 2001 From: Oliver Townsend Date: Mon, 15 Sep 2025 15:51:58 -0300 Subject: [PATCH] CCIP - add ExtraDataCodecBundle protobuf and client/server support --- .../internal/pb/ccipocr3/chainaccessor.pb.go | 21 +- .../internal/pb/ccipocr3/chainaccessor.proto | 3 +- pkg/loop/internal/pb/ccipocr3/codec.pb.go | 355 ++++++++++++++---- pkg/loop/internal/pb/ccipocr3/codec.proto | 25 ++ .../internal/pb/ccipocr3/codec_grpc.pb.go | 144 +++++++ pkg/loop/internal/pb/relayer.pb.go | 23 +- pkg/loop/internal/pb/relayer.proto | 3 +- .../ext/ccipocr3/chainaccessor.go | 20 +- .../pluginprovider/ext/ccipocr3/codec.go | 77 ++++ .../pluginprovider/ext/ccipocr3/codec_test.go | 2 +- .../ext/ccipocr3/convert_test.go | 129 +++++++ .../ext/ccipocr3/test/chain_accessor.go | 13 +- .../ext/ccipocr3/test/chain_accessor_test.go | 4 +- pkg/loop/internal/relayer/relayer.go | 68 +++- pkg/loop/internal/relayer/test/relayer.go | 27 +- pkg/types/ccipocr3/chainaccessor.go | 3 +- pkg/types/ccipocr3/generic_types.go | 3 +- pkg/types/ccipocr3/plugin_commit_types.go | 2 +- .../ccipocr3/plugin_commit_types_test.go | 2 +- pkg/types/ccipocr3/plugincodec.go | 16 +- pkg/types/ccipocr3/plugincodec_test.go | 4 +- pkg/types/provider_ccip.go | 12 +- 22 files changed, 813 insertions(+), 143 deletions(-) diff --git a/pkg/loop/internal/pb/ccipocr3/chainaccessor.pb.go b/pkg/loop/internal/pb/ccipocr3/chainaccessor.pb.go index 762346e21..45a6bbb79 100644 --- a/pkg/loop/internal/pb/ccipocr3/chainaccessor.pb.go +++ b/pkg/loop/internal/pb/ccipocr3/chainaccessor.pb.go @@ -3351,8 +3351,7 @@ func (x *GetFeedPricesUSDResponse) GetPrices() map[string]*BigInt { type GetFeeQuoterTokenUpdatesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Tokens []string `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens,omitempty"` // UnknownEncodedAddress - ChainSelector uint64 `protobuf:"varint,2,opt,name=chain_selector,json=chainSelector,proto3" json:"chain_selector,omitempty"` + TokensBytes [][]byte `protobuf:"bytes,1,rep,name=tokens_bytes,json=tokensBytes,proto3" json:"tokens_bytes,omitempty"` // UnknownAddress unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3387,20 +3386,13 @@ func (*GetFeeQuoterTokenUpdatesRequest) Descriptor() ([]byte, []int) { return file_chainaccessor_proto_rawDescGZIP(), []int{62} } -func (x *GetFeeQuoterTokenUpdatesRequest) GetTokens() []string { +func (x *GetFeeQuoterTokenUpdatesRequest) GetTokensBytes() [][]byte { if x != nil { - return x.Tokens + return x.TokensBytes } return nil } -func (x *GetFeeQuoterTokenUpdatesRequest) GetChainSelector() uint64 { - if x != nil { - return x.ChainSelector - } - return 0 -} - type GetFeeQuoterTokenUpdatesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` TokenUpdates map[string]*TimestampedUnixBig `protobuf:"bytes,1,rep,name=token_updates,json=tokenUpdates,proto3" json:"token_updates,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // key is UnknownEncodedAddress @@ -3816,10 +3808,9 @@ const file_chainaccessor_proto_rawDesc = "" + "\x06prices\x18\x01 \x03(\v2?.loop.internal.pb.ccipocr3.GetFeedPricesUSDResponse.PricesEntryR\x06prices\x1a\\\n" + "\vPricesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x127\n" + - "\x05value\x18\x02 \x01(\v2!.loop.internal.pb.ccipocr3.BigIntR\x05value:\x028\x01\"`\n" + - "\x1fGetFeeQuoterTokenUpdatesRequest\x12\x16\n" + - "\x06tokens\x18\x01 \x03(\tR\x06tokens\x12%\n" + - "\x0echain_selector\x18\x02 \x01(\x04R\rchainSelector\"\x86\x02\n" + + "\x05value\x18\x02 \x01(\v2!.loop.internal.pb.ccipocr3.BigIntR\x05value:\x028\x01\"D\n" + + "\x1fGetFeeQuoterTokenUpdatesRequest\x12!\n" + + "\ftokens_bytes\x18\x01 \x03(\fR\vtokensBytes\"\x86\x02\n" + " GetFeeQuoterTokenUpdatesResponse\x12r\n" + "\rtoken_updates\x18\x01 \x03(\v2M.loop.internal.pb.ccipocr3.GetFeeQuoterTokenUpdatesResponse.TokenUpdatesEntryR\ftokenUpdates\x1an\n" + "\x11TokenUpdatesEntry\x12\x10\n" + diff --git a/pkg/loop/internal/pb/ccipocr3/chainaccessor.proto b/pkg/loop/internal/pb/ccipocr3/chainaccessor.proto index d9faef8e8..cf0608303 100644 --- a/pkg/loop/internal/pb/ccipocr3/chainaccessor.proto +++ b/pkg/loop/internal/pb/ccipocr3/chainaccessor.proto @@ -368,8 +368,7 @@ message GetFeedPricesUSDResponse { } message GetFeeQuoterTokenUpdatesRequest { - repeated string tokens = 1; // UnknownEncodedAddress - uint64 chain_selector = 2; + repeated bytes tokens_bytes = 1; // UnknownAddress } message GetFeeQuoterTokenUpdatesResponse { diff --git a/pkg/loop/internal/pb/ccipocr3/codec.pb.go b/pkg/loop/internal/pb/ccipocr3/codec.pb.go index 93e95cbe6..0b713c444 100644 --- a/pkg/loop/internal/pb/ccipocr3/codec.pb.go +++ b/pkg/loop/internal/pb/ccipocr3/codec.pb.go @@ -826,6 +826,199 @@ func (x *DecodeDestExecDataToMapResponse) GetDecodedMap() *pb.Map { return nil } +// ExtraDataCodecBundle messages +type DecodeExtraArgsWithChainSelectorRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExtraArgs []byte `protobuf:"bytes,1,opt,name=extra_args,json=extraArgs,proto3" json:"extra_args,omitempty"` + SourceChainSelector uint64 `protobuf:"varint,2,opt,name=source_chain_selector,json=sourceChainSelector,proto3" json:"source_chain_selector,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DecodeExtraArgsWithChainSelectorRequest) Reset() { + *x = DecodeExtraArgsWithChainSelectorRequest{} + mi := &file_codec_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DecodeExtraArgsWithChainSelectorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DecodeExtraArgsWithChainSelectorRequest) ProtoMessage() {} + +func (x *DecodeExtraArgsWithChainSelectorRequest) ProtoReflect() protoreflect.Message { + mi := &file_codec_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DecodeExtraArgsWithChainSelectorRequest.ProtoReflect.Descriptor instead. +func (*DecodeExtraArgsWithChainSelectorRequest) Descriptor() ([]byte, []int) { + return file_codec_proto_rawDescGZIP(), []int{18} +} + +func (x *DecodeExtraArgsWithChainSelectorRequest) GetExtraArgs() []byte { + if x != nil { + return x.ExtraArgs + } + return nil +} + +func (x *DecodeExtraArgsWithChainSelectorRequest) GetSourceChainSelector() uint64 { + if x != nil { + return x.SourceChainSelector + } + return 0 +} + +type DecodeExtraArgsWithChainSelectorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + DecodedMap *pb.Map `protobuf:"bytes,1,opt,name=decoded_map,json=decodedMap,proto3" json:"decoded_map,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DecodeExtraArgsWithChainSelectorResponse) Reset() { + *x = DecodeExtraArgsWithChainSelectorResponse{} + mi := &file_codec_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DecodeExtraArgsWithChainSelectorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DecodeExtraArgsWithChainSelectorResponse) ProtoMessage() {} + +func (x *DecodeExtraArgsWithChainSelectorResponse) ProtoReflect() protoreflect.Message { + mi := &file_codec_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DecodeExtraArgsWithChainSelectorResponse.ProtoReflect.Descriptor instead. +func (*DecodeExtraArgsWithChainSelectorResponse) Descriptor() ([]byte, []int) { + return file_codec_proto_rawDescGZIP(), []int{19} +} + +func (x *DecodeExtraArgsWithChainSelectorResponse) GetDecodedMap() *pb.Map { + if x != nil { + return x.DecodedMap + } + return nil +} + +type DecodeTokenAmountDestExecDataRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + DestExecData []byte `protobuf:"bytes,1,opt,name=dest_exec_data,json=destExecData,proto3" json:"dest_exec_data,omitempty"` + SourceChainSelector uint64 `protobuf:"varint,2,opt,name=source_chain_selector,json=sourceChainSelector,proto3" json:"source_chain_selector,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DecodeTokenAmountDestExecDataRequest) Reset() { + *x = DecodeTokenAmountDestExecDataRequest{} + mi := &file_codec_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DecodeTokenAmountDestExecDataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DecodeTokenAmountDestExecDataRequest) ProtoMessage() {} + +func (x *DecodeTokenAmountDestExecDataRequest) ProtoReflect() protoreflect.Message { + mi := &file_codec_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DecodeTokenAmountDestExecDataRequest.ProtoReflect.Descriptor instead. +func (*DecodeTokenAmountDestExecDataRequest) Descriptor() ([]byte, []int) { + return file_codec_proto_rawDescGZIP(), []int{20} +} + +func (x *DecodeTokenAmountDestExecDataRequest) GetDestExecData() []byte { + if x != nil { + return x.DestExecData + } + return nil +} + +func (x *DecodeTokenAmountDestExecDataRequest) GetSourceChainSelector() uint64 { + if x != nil { + return x.SourceChainSelector + } + return 0 +} + +type DecodeTokenAmountDestExecDataResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + DecodedMap *pb.Map `protobuf:"bytes,1,opt,name=decoded_map,json=decodedMap,proto3" json:"decoded_map,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DecodeTokenAmountDestExecDataResponse) Reset() { + *x = DecodeTokenAmountDestExecDataResponse{} + mi := &file_codec_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DecodeTokenAmountDestExecDataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DecodeTokenAmountDestExecDataResponse) ProtoMessage() {} + +func (x *DecodeTokenAmountDestExecDataResponse) ProtoReflect() protoreflect.Message { + mi := &file_codec_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DecodeTokenAmountDestExecDataResponse.ProtoReflect.Descriptor instead. +func (*DecodeTokenAmountDestExecDataResponse) Descriptor() ([]byte, []int) { + return file_codec_proto_rawDescGZIP(), []int{21} +} + +func (x *DecodeTokenAmountDestExecDataResponse) GetDecodedMap() *pb.Map { + if x != nil { + return x.DecodedMap + } + return nil +} + // Supporting types type ExecutePluginReport struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -836,7 +1029,7 @@ type ExecutePluginReport struct { func (x *ExecutePluginReport) Reset() { *x = ExecutePluginReport{} - mi := &file_codec_proto_msgTypes[18] + mi := &file_codec_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -848,7 +1041,7 @@ func (x *ExecutePluginReport) String() string { func (*ExecutePluginReport) ProtoMessage() {} func (x *ExecutePluginReport) ProtoReflect() protoreflect.Message { - mi := &file_codec_proto_msgTypes[18] + mi := &file_codec_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -861,7 +1054,7 @@ func (x *ExecutePluginReport) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecutePluginReport.ProtoReflect.Descriptor instead. func (*ExecutePluginReport) Descriptor() ([]byte, []int) { - return file_codec_proto_rawDescGZIP(), []int{18} + return file_codec_proto_rawDescGZIP(), []int{22} } func (x *ExecutePluginReport) GetChainReports() []*ChainReport { @@ -884,7 +1077,7 @@ type ChainReport struct { func (x *ChainReport) Reset() { *x = ChainReport{} - mi := &file_codec_proto_msgTypes[19] + mi := &file_codec_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -896,7 +1089,7 @@ func (x *ChainReport) String() string { func (*ChainReport) ProtoMessage() {} func (x *ChainReport) ProtoReflect() protoreflect.Message { - mi := &file_codec_proto_msgTypes[19] + mi := &file_codec_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -909,7 +1102,7 @@ func (x *ChainReport) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainReport.ProtoReflect.Descriptor instead. func (*ChainReport) Descriptor() ([]byte, []int) { - return file_codec_proto_rawDescGZIP(), []int{19} + return file_codec_proto_rawDescGZIP(), []int{23} } func (x *ChainReport) GetSourceChainSelector() uint64 { @@ -957,7 +1150,7 @@ type MessageOffchainTokenData struct { func (x *MessageOffchainTokenData) Reset() { *x = MessageOffchainTokenData{} - mi := &file_codec_proto_msgTypes[20] + mi := &file_codec_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -969,7 +1162,7 @@ func (x *MessageOffchainTokenData) String() string { func (*MessageOffchainTokenData) ProtoMessage() {} func (x *MessageOffchainTokenData) ProtoReflect() protoreflect.Message { - mi := &file_codec_proto_msgTypes[20] + mi := &file_codec_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -982,7 +1175,7 @@ func (x *MessageOffchainTokenData) ProtoReflect() protoreflect.Message { // Deprecated: Use MessageOffchainTokenData.ProtoReflect.Descriptor instead. func (*MessageOffchainTokenData) Descriptor() ([]byte, []int) { - return file_codec_proto_rawDescGZIP(), []int{20} + return file_codec_proto_rawDescGZIP(), []int{24} } func (x *MessageOffchainTokenData) GetTokenData() [][]byte { @@ -1036,6 +1229,19 @@ const file_codec_proto_rawDesc = "" + "\x0edest_exec_data\x18\x01 \x01(\fR\fdestExecData\"R\n" + "\x1fDecodeDestExecDataToMapResponse\x12/\n" + "\vdecoded_map\x18\x01 \x01(\v2\x0e.values.v1.MapR\n" + + "decodedMap\"|\n" + + "'DecodeExtraArgsWithChainSelectorRequest\x12\x1d\n" + + "\n" + + "extra_args\x18\x01 \x01(\fR\textraArgs\x122\n" + + "\x15source_chain_selector\x18\x02 \x01(\x04R\x13sourceChainSelector\"[\n" + + "(DecodeExtraArgsWithChainSelectorResponse\x12/\n" + + "\vdecoded_map\x18\x01 \x01(\v2\x0e.values.v1.MapR\n" + + "decodedMap\"\x80\x01\n" + + "$DecodeTokenAmountDestExecDataRequest\x12$\n" + + "\x0edest_exec_data\x18\x01 \x01(\fR\fdestExecData\x122\n" + + "\x15source_chain_selector\x18\x02 \x01(\x04R\x13sourceChainSelector\"X\n" + + "%DecodeTokenAmountDestExecDataResponse\x12/\n" + + "\vdecoded_map\x18\x01 \x01(\v2\x0e.values.v1.MapR\n" + "decodedMap\"b\n" + "\x13ExecutePluginReport\x12K\n" + "\rchain_reports\x18\x01 \x03(\v2&.loop.internal.pb.ccipocr3.ChainReportR\fchainReports\"\xc9\x02\n" + @@ -1061,7 +1267,10 @@ const file_codec_proto_rawDesc = "" + "EncodeUSDC\x12,.loop.internal.pb.ccipocr3.EncodeUSDCRequest\x1a-.loop.internal.pb.ccipocr3.EncodeUSDCResponse2\xb8\x02\n" + "\x19SourceChainExtraDataCodec\x12\x87\x01\n" + "\x14DecodeExtraArgsToMap\x126.loop.internal.pb.ccipocr3.DecodeExtraArgsToMapRequest\x1a7.loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse\x12\x90\x01\n" + - "\x17DecodeDestExecDataToMap\x129.loop.internal.pb.ccipocr3.DecodeDestExecDataToMapRequest\x1a:.loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponseBWZUgithub.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb/ccipocr3;ccipocr3pbb\x06proto3" + "\x17DecodeDestExecDataToMap\x129.loop.internal.pb.ccipocr3.DecodeDestExecDataToMapRequest\x1a:.loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse2\xd8\x02\n" + + "\x14ExtraDataCodecBundle\x12\x9a\x01\n" + + "\x0fDecodeExtraArgs\x12B.loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorRequest\x1aC.loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorResponse\x12\xa2\x01\n" + + "\x1dDecodeTokenAmountDestExecData\x12?.loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataRequest\x1a@.loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataResponseBWZUgithub.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb/ccipocr3;ccipocr3pbb\x06proto3" var ( file_codec_proto_rawDescOnce sync.Once @@ -1075,65 +1284,75 @@ func file_codec_proto_rawDescGZIP() []byte { return file_codec_proto_rawDescData } -var file_codec_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_codec_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_codec_proto_goTypes = []any{ - (*AddressBytesToStringRequest)(nil), // 0: loop.internal.pb.ccipocr3.AddressBytesToStringRequest - (*AddressBytesToStringResponse)(nil), // 1: loop.internal.pb.ccipocr3.AddressBytesToStringResponse - (*AddressStringToBytesRequest)(nil), // 2: loop.internal.pb.ccipocr3.AddressStringToBytesRequest - (*AddressStringToBytesResponse)(nil), // 3: loop.internal.pb.ccipocr3.AddressStringToBytesResponse - (*OracleIDAsAddressBytesRequest)(nil), // 4: loop.internal.pb.ccipocr3.OracleIDAsAddressBytesRequest - (*OracleIDAsAddressBytesResponse)(nil), // 5: loop.internal.pb.ccipocr3.OracleIDAsAddressBytesResponse - (*TransmitterBytesToStringRequest)(nil), // 6: loop.internal.pb.ccipocr3.TransmitterBytesToStringRequest - (*TransmitterBytesToStringResponse)(nil), // 7: loop.internal.pb.ccipocr3.TransmitterBytesToStringResponse - (*EncodeExecutePluginReportRequest)(nil), // 8: loop.internal.pb.ccipocr3.EncodeExecutePluginReportRequest - (*EncodeExecutePluginReportResponse)(nil), // 9: loop.internal.pb.ccipocr3.EncodeExecutePluginReportResponse - (*DecodeExecutePluginReportRequest)(nil), // 10: loop.internal.pb.ccipocr3.DecodeExecutePluginReportRequest - (*DecodeExecutePluginReportResponse)(nil), // 11: loop.internal.pb.ccipocr3.DecodeExecutePluginReportResponse - (*EncodeUSDCRequest)(nil), // 12: loop.internal.pb.ccipocr3.EncodeUSDCRequest - (*EncodeUSDCResponse)(nil), // 13: loop.internal.pb.ccipocr3.EncodeUSDCResponse - (*DecodeExtraArgsToMapRequest)(nil), // 14: loop.internal.pb.ccipocr3.DecodeExtraArgsToMapRequest - (*DecodeExtraArgsToMapResponse)(nil), // 15: loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse - (*DecodeDestExecDataToMapRequest)(nil), // 16: loop.internal.pb.ccipocr3.DecodeDestExecDataToMapRequest - (*DecodeDestExecDataToMapResponse)(nil), // 17: loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse - (*ExecutePluginReport)(nil), // 18: loop.internal.pb.ccipocr3.ExecutePluginReport - (*ChainReport)(nil), // 19: loop.internal.pb.ccipocr3.ChainReport - (*MessageOffchainTokenData)(nil), // 20: loop.internal.pb.ccipocr3.MessageOffchainTokenData - (*pb.Map)(nil), // 21: values.v1.Map - (*Message)(nil), // 22: loop.internal.pb.ccipocr3.Message - (*BigInt)(nil), // 23: loop.internal.pb.ccipocr3.BigInt + (*AddressBytesToStringRequest)(nil), // 0: loop.internal.pb.ccipocr3.AddressBytesToStringRequest + (*AddressBytesToStringResponse)(nil), // 1: loop.internal.pb.ccipocr3.AddressBytesToStringResponse + (*AddressStringToBytesRequest)(nil), // 2: loop.internal.pb.ccipocr3.AddressStringToBytesRequest + (*AddressStringToBytesResponse)(nil), // 3: loop.internal.pb.ccipocr3.AddressStringToBytesResponse + (*OracleIDAsAddressBytesRequest)(nil), // 4: loop.internal.pb.ccipocr3.OracleIDAsAddressBytesRequest + (*OracleIDAsAddressBytesResponse)(nil), // 5: loop.internal.pb.ccipocr3.OracleIDAsAddressBytesResponse + (*TransmitterBytesToStringRequest)(nil), // 6: loop.internal.pb.ccipocr3.TransmitterBytesToStringRequest + (*TransmitterBytesToStringResponse)(nil), // 7: loop.internal.pb.ccipocr3.TransmitterBytesToStringResponse + (*EncodeExecutePluginReportRequest)(nil), // 8: loop.internal.pb.ccipocr3.EncodeExecutePluginReportRequest + (*EncodeExecutePluginReportResponse)(nil), // 9: loop.internal.pb.ccipocr3.EncodeExecutePluginReportResponse + (*DecodeExecutePluginReportRequest)(nil), // 10: loop.internal.pb.ccipocr3.DecodeExecutePluginReportRequest + (*DecodeExecutePluginReportResponse)(nil), // 11: loop.internal.pb.ccipocr3.DecodeExecutePluginReportResponse + (*EncodeUSDCRequest)(nil), // 12: loop.internal.pb.ccipocr3.EncodeUSDCRequest + (*EncodeUSDCResponse)(nil), // 13: loop.internal.pb.ccipocr3.EncodeUSDCResponse + (*DecodeExtraArgsToMapRequest)(nil), // 14: loop.internal.pb.ccipocr3.DecodeExtraArgsToMapRequest + (*DecodeExtraArgsToMapResponse)(nil), // 15: loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse + (*DecodeDestExecDataToMapRequest)(nil), // 16: loop.internal.pb.ccipocr3.DecodeDestExecDataToMapRequest + (*DecodeDestExecDataToMapResponse)(nil), // 17: loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse + (*DecodeExtraArgsWithChainSelectorRequest)(nil), // 18: loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorRequest + (*DecodeExtraArgsWithChainSelectorResponse)(nil), // 19: loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorResponse + (*DecodeTokenAmountDestExecDataRequest)(nil), // 20: loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataRequest + (*DecodeTokenAmountDestExecDataResponse)(nil), // 21: loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataResponse + (*ExecutePluginReport)(nil), // 22: loop.internal.pb.ccipocr3.ExecutePluginReport + (*ChainReport)(nil), // 23: loop.internal.pb.ccipocr3.ChainReport + (*MessageOffchainTokenData)(nil), // 24: loop.internal.pb.ccipocr3.MessageOffchainTokenData + (*pb.Map)(nil), // 25: values.v1.Map + (*Message)(nil), // 26: loop.internal.pb.ccipocr3.Message + (*BigInt)(nil), // 27: loop.internal.pb.ccipocr3.BigInt } var file_codec_proto_depIdxs = []int32{ - 18, // 0: loop.internal.pb.ccipocr3.EncodeExecutePluginReportRequest.report:type_name -> loop.internal.pb.ccipocr3.ExecutePluginReport - 18, // 1: loop.internal.pb.ccipocr3.DecodeExecutePluginReportResponse.report:type_name -> loop.internal.pb.ccipocr3.ExecutePluginReport - 21, // 2: loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse.decoded_map:type_name -> values.v1.Map - 21, // 3: loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse.decoded_map:type_name -> values.v1.Map - 19, // 4: loop.internal.pb.ccipocr3.ExecutePluginReport.chain_reports:type_name -> loop.internal.pb.ccipocr3.ChainReport - 22, // 5: loop.internal.pb.ccipocr3.ChainReport.messages:type_name -> loop.internal.pb.ccipocr3.Message - 20, // 6: loop.internal.pb.ccipocr3.ChainReport.offchain_token_data:type_name -> loop.internal.pb.ccipocr3.MessageOffchainTokenData - 23, // 7: loop.internal.pb.ccipocr3.ChainReport.proof_flag_bits:type_name -> loop.internal.pb.ccipocr3.BigInt - 0, // 8: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressBytesToString:input_type -> loop.internal.pb.ccipocr3.AddressBytesToStringRequest - 2, // 9: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressStringToBytes:input_type -> loop.internal.pb.ccipocr3.AddressStringToBytesRequest - 4, // 10: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.OracleIDAsAddressBytes:input_type -> loop.internal.pb.ccipocr3.OracleIDAsAddressBytesRequest - 6, // 11: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.TransmitterBytesToString:input_type -> loop.internal.pb.ccipocr3.TransmitterBytesToStringRequest - 8, // 12: loop.internal.pb.ccipocr3.ExecutePluginCodec.Encode:input_type -> loop.internal.pb.ccipocr3.EncodeExecutePluginReportRequest - 10, // 13: loop.internal.pb.ccipocr3.ExecutePluginCodec.Decode:input_type -> loop.internal.pb.ccipocr3.DecodeExecutePluginReportRequest - 12, // 14: loop.internal.pb.ccipocr3.TokenDataEncoder.EncodeUSDC:input_type -> loop.internal.pb.ccipocr3.EncodeUSDCRequest - 14, // 15: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeExtraArgsToMap:input_type -> loop.internal.pb.ccipocr3.DecodeExtraArgsToMapRequest - 16, // 16: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeDestExecDataToMap:input_type -> loop.internal.pb.ccipocr3.DecodeDestExecDataToMapRequest - 1, // 17: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressBytesToString:output_type -> loop.internal.pb.ccipocr3.AddressBytesToStringResponse - 3, // 18: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressStringToBytes:output_type -> loop.internal.pb.ccipocr3.AddressStringToBytesResponse - 5, // 19: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.OracleIDAsAddressBytes:output_type -> loop.internal.pb.ccipocr3.OracleIDAsAddressBytesResponse - 7, // 20: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.TransmitterBytesToString:output_type -> loop.internal.pb.ccipocr3.TransmitterBytesToStringResponse - 9, // 21: loop.internal.pb.ccipocr3.ExecutePluginCodec.Encode:output_type -> loop.internal.pb.ccipocr3.EncodeExecutePluginReportResponse - 11, // 22: loop.internal.pb.ccipocr3.ExecutePluginCodec.Decode:output_type -> loop.internal.pb.ccipocr3.DecodeExecutePluginReportResponse - 13, // 23: loop.internal.pb.ccipocr3.TokenDataEncoder.EncodeUSDC:output_type -> loop.internal.pb.ccipocr3.EncodeUSDCResponse - 15, // 24: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeExtraArgsToMap:output_type -> loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse - 17, // 25: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeDestExecDataToMap:output_type -> loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse - 17, // [17:26] is the sub-list for method output_type - 8, // [8:17] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 22, // 0: loop.internal.pb.ccipocr3.EncodeExecutePluginReportRequest.report:type_name -> loop.internal.pb.ccipocr3.ExecutePluginReport + 22, // 1: loop.internal.pb.ccipocr3.DecodeExecutePluginReportResponse.report:type_name -> loop.internal.pb.ccipocr3.ExecutePluginReport + 25, // 2: loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse.decoded_map:type_name -> values.v1.Map + 25, // 3: loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse.decoded_map:type_name -> values.v1.Map + 25, // 4: loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorResponse.decoded_map:type_name -> values.v1.Map + 25, // 5: loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataResponse.decoded_map:type_name -> values.v1.Map + 23, // 6: loop.internal.pb.ccipocr3.ExecutePluginReport.chain_reports:type_name -> loop.internal.pb.ccipocr3.ChainReport + 26, // 7: loop.internal.pb.ccipocr3.ChainReport.messages:type_name -> loop.internal.pb.ccipocr3.Message + 24, // 8: loop.internal.pb.ccipocr3.ChainReport.offchain_token_data:type_name -> loop.internal.pb.ccipocr3.MessageOffchainTokenData + 27, // 9: loop.internal.pb.ccipocr3.ChainReport.proof_flag_bits:type_name -> loop.internal.pb.ccipocr3.BigInt + 0, // 10: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressBytesToString:input_type -> loop.internal.pb.ccipocr3.AddressBytesToStringRequest + 2, // 11: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressStringToBytes:input_type -> loop.internal.pb.ccipocr3.AddressStringToBytesRequest + 4, // 12: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.OracleIDAsAddressBytes:input_type -> loop.internal.pb.ccipocr3.OracleIDAsAddressBytesRequest + 6, // 13: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.TransmitterBytesToString:input_type -> loop.internal.pb.ccipocr3.TransmitterBytesToStringRequest + 8, // 14: loop.internal.pb.ccipocr3.ExecutePluginCodec.Encode:input_type -> loop.internal.pb.ccipocr3.EncodeExecutePluginReportRequest + 10, // 15: loop.internal.pb.ccipocr3.ExecutePluginCodec.Decode:input_type -> loop.internal.pb.ccipocr3.DecodeExecutePluginReportRequest + 12, // 16: loop.internal.pb.ccipocr3.TokenDataEncoder.EncodeUSDC:input_type -> loop.internal.pb.ccipocr3.EncodeUSDCRequest + 14, // 17: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeExtraArgsToMap:input_type -> loop.internal.pb.ccipocr3.DecodeExtraArgsToMapRequest + 16, // 18: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeDestExecDataToMap:input_type -> loop.internal.pb.ccipocr3.DecodeDestExecDataToMapRequest + 18, // 19: loop.internal.pb.ccipocr3.ExtraDataCodecBundle.DecodeExtraArgs:input_type -> loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorRequest + 20, // 20: loop.internal.pb.ccipocr3.ExtraDataCodecBundle.DecodeTokenAmountDestExecData:input_type -> loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataRequest + 1, // 21: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressBytesToString:output_type -> loop.internal.pb.ccipocr3.AddressBytesToStringResponse + 3, // 22: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.AddressStringToBytes:output_type -> loop.internal.pb.ccipocr3.AddressStringToBytesResponse + 5, // 23: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.OracleIDAsAddressBytes:output_type -> loop.internal.pb.ccipocr3.OracleIDAsAddressBytesResponse + 7, // 24: loop.internal.pb.ccipocr3.ChainSpecificAddressCodec.TransmitterBytesToString:output_type -> loop.internal.pb.ccipocr3.TransmitterBytesToStringResponse + 9, // 25: loop.internal.pb.ccipocr3.ExecutePluginCodec.Encode:output_type -> loop.internal.pb.ccipocr3.EncodeExecutePluginReportResponse + 11, // 26: loop.internal.pb.ccipocr3.ExecutePluginCodec.Decode:output_type -> loop.internal.pb.ccipocr3.DecodeExecutePluginReportResponse + 13, // 27: loop.internal.pb.ccipocr3.TokenDataEncoder.EncodeUSDC:output_type -> loop.internal.pb.ccipocr3.EncodeUSDCResponse + 15, // 28: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeExtraArgsToMap:output_type -> loop.internal.pb.ccipocr3.DecodeExtraArgsToMapResponse + 17, // 29: loop.internal.pb.ccipocr3.SourceChainExtraDataCodec.DecodeDestExecDataToMap:output_type -> loop.internal.pb.ccipocr3.DecodeDestExecDataToMapResponse + 19, // 30: loop.internal.pb.ccipocr3.ExtraDataCodecBundle.DecodeExtraArgs:output_type -> loop.internal.pb.ccipocr3.DecodeExtraArgsWithChainSelectorResponse + 21, // 31: loop.internal.pb.ccipocr3.ExtraDataCodecBundle.DecodeTokenAmountDestExecData:output_type -> loop.internal.pb.ccipocr3.DecodeTokenAmountDestExecDataResponse + 21, // [21:32] is the sub-list for method output_type + 10, // [10:21] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_codec_proto_init() } @@ -1148,9 +1367,9 @@ func file_codec_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_codec_proto_rawDesc), len(file_codec_proto_rawDesc)), NumEnums: 0, - NumMessages: 21, + NumMessages: 25, NumExtensions: 0, - NumServices: 4, + NumServices: 5, }, GoTypes: file_codec_proto_goTypes, DependencyIndexes: file_codec_proto_depIdxs, diff --git a/pkg/loop/internal/pb/ccipocr3/codec.proto b/pkg/loop/internal/pb/ccipocr3/codec.proto index 9844d331a..647abc740 100644 --- a/pkg/loop/internal/pb/ccipocr3/codec.proto +++ b/pkg/loop/internal/pb/ccipocr3/codec.proto @@ -32,6 +32,12 @@ service SourceChainExtraDataCodec { rpc DecodeDestExecDataToMap(DecodeDestExecDataToMapRequest) returns (DecodeDestExecDataToMapResponse); } +// ExtraDataCodecBundle service for decoding extra args and dest exec data with chain selector +service ExtraDataCodecBundle { + rpc DecodeExtraArgs(DecodeExtraArgsWithChainSelectorRequest) returns (DecodeExtraArgsWithChainSelectorResponse); + rpc DecodeTokenAmountDestExecData(DecodeTokenAmountDestExecDataRequest) returns (DecodeTokenAmountDestExecDataResponse); +} + // ChainSpecificAddressCodec messages message AddressBytesToStringRequest { bytes address = 1; @@ -109,6 +115,25 @@ message DecodeDestExecDataToMapResponse { values.v1.Map decoded_map = 1; } +// ExtraDataCodecBundle messages +message DecodeExtraArgsWithChainSelectorRequest { + bytes extra_args = 1; + uint64 source_chain_selector = 2; +} + +message DecodeExtraArgsWithChainSelectorResponse { + values.v1.Map decoded_map = 1; +} + +message DecodeTokenAmountDestExecDataRequest { + bytes dest_exec_data = 1; + uint64 source_chain_selector = 2; +} + +message DecodeTokenAmountDestExecDataResponse { + values.v1.Map decoded_map = 1; +} + // Supporting types message ExecutePluginReport { repeated ChainReport chain_reports = 1; diff --git a/pkg/loop/internal/pb/ccipocr3/codec_grpc.pb.go b/pkg/loop/internal/pb/ccipocr3/codec_grpc.pb.go index 271ea9811..12669d704 100644 --- a/pkg/loop/internal/pb/ccipocr3/codec_grpc.pb.go +++ b/pkg/loop/internal/pb/ccipocr3/codec_grpc.pb.go @@ -633,3 +633,147 @@ var SourceChainExtraDataCodec_ServiceDesc = grpc.ServiceDesc{ Streams: []grpc.StreamDesc{}, Metadata: "codec.proto", } + +const ( + ExtraDataCodecBundle_DecodeExtraArgs_FullMethodName = "/loop.internal.pb.ccipocr3.ExtraDataCodecBundle/DecodeExtraArgs" + ExtraDataCodecBundle_DecodeTokenAmountDestExecData_FullMethodName = "/loop.internal.pb.ccipocr3.ExtraDataCodecBundle/DecodeTokenAmountDestExecData" +) + +// ExtraDataCodecBundleClient is the client API for ExtraDataCodecBundle service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// ExtraDataCodecBundle service for decoding extra args and dest exec data with chain selector +type ExtraDataCodecBundleClient interface { + DecodeExtraArgs(ctx context.Context, in *DecodeExtraArgsWithChainSelectorRequest, opts ...grpc.CallOption) (*DecodeExtraArgsWithChainSelectorResponse, error) + DecodeTokenAmountDestExecData(ctx context.Context, in *DecodeTokenAmountDestExecDataRequest, opts ...grpc.CallOption) (*DecodeTokenAmountDestExecDataResponse, error) +} + +type extraDataCodecBundleClient struct { + cc grpc.ClientConnInterface +} + +func NewExtraDataCodecBundleClient(cc grpc.ClientConnInterface) ExtraDataCodecBundleClient { + return &extraDataCodecBundleClient{cc} +} + +func (c *extraDataCodecBundleClient) DecodeExtraArgs(ctx context.Context, in *DecodeExtraArgsWithChainSelectorRequest, opts ...grpc.CallOption) (*DecodeExtraArgsWithChainSelectorResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DecodeExtraArgsWithChainSelectorResponse) + err := c.cc.Invoke(ctx, ExtraDataCodecBundle_DecodeExtraArgs_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *extraDataCodecBundleClient) DecodeTokenAmountDestExecData(ctx context.Context, in *DecodeTokenAmountDestExecDataRequest, opts ...grpc.CallOption) (*DecodeTokenAmountDestExecDataResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DecodeTokenAmountDestExecDataResponse) + err := c.cc.Invoke(ctx, ExtraDataCodecBundle_DecodeTokenAmountDestExecData_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ExtraDataCodecBundleServer is the server API for ExtraDataCodecBundle service. +// All implementations must embed UnimplementedExtraDataCodecBundleServer +// for forward compatibility. +// +// ExtraDataCodecBundle service for decoding extra args and dest exec data with chain selector +type ExtraDataCodecBundleServer interface { + DecodeExtraArgs(context.Context, *DecodeExtraArgsWithChainSelectorRequest) (*DecodeExtraArgsWithChainSelectorResponse, error) + DecodeTokenAmountDestExecData(context.Context, *DecodeTokenAmountDestExecDataRequest) (*DecodeTokenAmountDestExecDataResponse, error) + mustEmbedUnimplementedExtraDataCodecBundleServer() +} + +// UnimplementedExtraDataCodecBundleServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedExtraDataCodecBundleServer struct{} + +func (UnimplementedExtraDataCodecBundleServer) DecodeExtraArgs(context.Context, *DecodeExtraArgsWithChainSelectorRequest) (*DecodeExtraArgsWithChainSelectorResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DecodeExtraArgs not implemented") +} +func (UnimplementedExtraDataCodecBundleServer) DecodeTokenAmountDestExecData(context.Context, *DecodeTokenAmountDestExecDataRequest) (*DecodeTokenAmountDestExecDataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DecodeTokenAmountDestExecData not implemented") +} +func (UnimplementedExtraDataCodecBundleServer) mustEmbedUnimplementedExtraDataCodecBundleServer() {} +func (UnimplementedExtraDataCodecBundleServer) testEmbeddedByValue() {} + +// UnsafeExtraDataCodecBundleServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ExtraDataCodecBundleServer will +// result in compilation errors. +type UnsafeExtraDataCodecBundleServer interface { + mustEmbedUnimplementedExtraDataCodecBundleServer() +} + +func RegisterExtraDataCodecBundleServer(s grpc.ServiceRegistrar, srv ExtraDataCodecBundleServer) { + // If the following call pancis, it indicates UnimplementedExtraDataCodecBundleServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ExtraDataCodecBundle_ServiceDesc, srv) +} + +func _ExtraDataCodecBundle_DecodeExtraArgs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DecodeExtraArgsWithChainSelectorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExtraDataCodecBundleServer).DecodeExtraArgs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ExtraDataCodecBundle_DecodeExtraArgs_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExtraDataCodecBundleServer).DecodeExtraArgs(ctx, req.(*DecodeExtraArgsWithChainSelectorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExtraDataCodecBundle_DecodeTokenAmountDestExecData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DecodeTokenAmountDestExecDataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExtraDataCodecBundleServer).DecodeTokenAmountDestExecData(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ExtraDataCodecBundle_DecodeTokenAmountDestExecData_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExtraDataCodecBundleServer).DecodeTokenAmountDestExecData(ctx, req.(*DecodeTokenAmountDestExecDataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ExtraDataCodecBundle_ServiceDesc is the grpc.ServiceDesc for ExtraDataCodecBundle service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ExtraDataCodecBundle_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "loop.internal.pb.ccipocr3.ExtraDataCodecBundle", + HandlerType: (*ExtraDataCodecBundleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DecodeExtraArgs", + Handler: _ExtraDataCodecBundle_DecodeExtraArgs_Handler, + }, + { + MethodName: "DecodeTokenAmountDestExecData", + Handler: _ExtraDataCodecBundle_DecodeTokenAmountDestExecData_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "codec.proto", +} diff --git a/pkg/loop/internal/pb/relayer.pb.go b/pkg/loop/internal/pb/relayer.pb.go index 616bc5e31..c088a2cb2 100644 --- a/pkg/loop/internal/pb/relayer.pb.go +++ b/pkg/loop/internal/pb/relayer.pb.go @@ -280,11 +280,12 @@ type CCIPProviderArgs struct { ChainWriterConfig []byte `protobuf:"bytes,3,opt,name=chainWriterConfig,proto3" json:"chainWriterConfig,omitempty"` OffRampAddress []byte `protobuf:"bytes,4,opt,name=offRampAddress,proto3" json:"offRampAddress,omitempty"` // pluginType is actually a uint8 but uint32 is the smallest supported by protobuf - PluginType uint32 `protobuf:"varint,5,opt,name=pluginType,proto3" json:"pluginType,omitempty"` - SyncedAddresses map[string][]byte `protobuf:"bytes,6,rep,name=synced_addresses,json=syncedAddresses,proto3" json:"synced_addresses,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // map[contract_name]contract_address - TransmitterAddress string `protobuf:"bytes,7,opt,name=transmitterAddress,proto3" json:"transmitterAddress,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + PluginType uint32 `protobuf:"varint,5,opt,name=pluginType,proto3" json:"pluginType,omitempty"` + SyncedAddresses map[string][]byte `protobuf:"bytes,6,rep,name=synced_addresses,json=syncedAddresses,proto3" json:"synced_addresses,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // map[contract_name]contract_address + TransmitterAddress string `protobuf:"bytes,7,opt,name=transmitterAddress,proto3" json:"transmitterAddress,omitempty"` // UnknownEncodedAddress + ExtraDataCodecBundleID uint32 `protobuf:"varint,8,opt,name=extraDataCodecBundleID,proto3" json:"extraDataCodecBundleID,omitempty"` // LOOP service ID for ExtraDataCodecBundle served by core node + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CCIPProviderArgs) Reset() { @@ -366,6 +367,13 @@ func (x *CCIPProviderArgs) GetTransmitterAddress() string { return "" } +func (x *CCIPProviderArgs) GetExtraDataCodecBundleID() uint32 { + if x != nil { + return x.ExtraDataCodecBundleID + } + return 0 +} + // NewContractWriterRequest has request parameters for [github.com/smartcontractkit/chainlink-common/pkg/loop.Relayer.NewContractWriter]. type NewContractWriterRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2732,7 +2740,7 @@ const file_loop_internal_pb_relayer_proto_rawDesc = "" + "\n" + "PluginArgs\x12$\n" + "\rtransmitterID\x18\x01 \x01(\tR\rtransmitterID\x12\"\n" + - "\fpluginConfig\x18\x02 \x01(\fR\fpluginConfig\"\xae\x03\n" + + "\fpluginConfig\x18\x02 \x01(\fR\fpluginConfig\"\xe6\x03\n" + "\x10CCIPProviderArgs\x12$\n" + "\rexternalJobID\x18\x01 \x01(\fR\rexternalJobID\x122\n" + "\x14contractReaderConfig\x18\x02 \x01(\fR\x14contractReaderConfig\x12,\n" + @@ -2742,7 +2750,8 @@ const file_loop_internal_pb_relayer_proto_rawDesc = "" + "pluginType\x18\x05 \x01(\rR\n" + "pluginType\x12V\n" + "\x10synced_addresses\x18\x06 \x03(\v2+.loop.CCIPProviderArgs.SyncedAddressesEntryR\x0fsyncedAddresses\x12.\n" + - "\x12transmitterAddress\x18\a \x01(\tR\x12transmitterAddress\x1aB\n" + + "\x12transmitterAddress\x18\a \x01(\tR\x12transmitterAddress\x126\n" + + "\x16extraDataCodecBundleID\x18\b \x01(\rR\x16extraDataCodecBundleID\x1aB\n" + "\x14SyncedAddressesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"N\n" + diff --git a/pkg/loop/internal/pb/relayer.proto b/pkg/loop/internal/pb/relayer.proto index 26eec8a93..a405fc45b 100644 --- a/pkg/loop/internal/pb/relayer.proto +++ b/pkg/loop/internal/pb/relayer.proto @@ -64,7 +64,8 @@ message CCIPProviderArgs { // pluginType is actually a uint8 but uint32 is the smallest supported by protobuf uint32 pluginType = 5; map synced_addresses = 6; // map[contract_name]contract_address - string transmitterAddress = 7; + string transmitterAddress = 7; // UnknownEncodedAddress + uint32 extraDataCodecBundleID = 8; // LOOP service ID for ExtraDataCodecBundle served by core node } // NewContractWriterRequest has request parameters for [github.com/smartcontractkit/chainlink-common/pkg/loop.Relayer.NewContractWriter]. diff --git a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/chainaccessor.go b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/chainaccessor.go index 86bd44915..78aa37be1 100644 --- a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/chainaccessor.go +++ b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/chainaccessor.go @@ -337,15 +337,14 @@ func (c *ChainAccessorClient) GetFeedPricesUSD(ctx context.Context, tokens []cci return pbToTokenPriceMap(resp.Prices), nil } -func (c *ChainAccessorClient) GetFeeQuoterTokenUpdates(ctx context.Context, tokens []ccipocr3.UnknownEncodedAddress, chain ccipocr3.ChainSelector) (map[ccipocr3.UnknownEncodedAddress]ccipocr3.TimestampedUnixBig, error) { - var tokenStrs []string - for _, token := range tokens { - tokenStrs = append(tokenStrs, string(token)) +func (c *ChainAccessorClient) GetFeeQuoterTokenUpdates(ctx context.Context, tokensBytes []ccipocr3.UnknownAddress) (map[ccipocr3.UnknownEncodedAddress]ccipocr3.TimestampedUnixBig, error) { + var tokensBytesSlice [][]byte + for _, token := range tokensBytes { + tokensBytesSlice = append(tokensBytesSlice, token) } resp, err := c.grpc.GetFeeQuoterTokenUpdates(ctx, &ccipocr3pb.GetFeeQuoterTokenUpdatesRequest{ - Tokens: tokenStrs, - ChainSelector: uint64(chain), + TokensBytes: tokensBytesSlice, }) if err != nil { return nil, err @@ -663,15 +662,14 @@ func (s *chainAccessorServer) GetFeedPricesUSD(ctx context.Context, req *ccipocr } func (s *chainAccessorServer) GetFeeQuoterTokenUpdates(ctx context.Context, req *ccipocr3pb.GetFeeQuoterTokenUpdatesRequest) (*ccipocr3pb.GetFeeQuoterTokenUpdatesResponse, error) { - var tokens []ccipocr3.UnknownEncodedAddress - for _, tokenStr := range req.Tokens { - tokens = append(tokens, ccipocr3.UnknownEncodedAddress(tokenStr)) + var tokensBytes []ccipocr3.UnknownAddress + for _, tokenBytes := range req.TokensBytes { + tokensBytes = append(tokensBytes, ccipocr3.UnknownAddress(tokenBytes)) } updates, err := s.impl.GetFeeQuoterTokenUpdates( ctx, - tokens, - ccipocr3.ChainSelector(req.ChainSelector), + tokensBytes, ) if err != nil { return nil, err diff --git a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec.go b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec.go index ab579865a..4a4f823e8 100644 --- a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec.go +++ b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec.go @@ -589,3 +589,80 @@ func pbToExecutePluginReport(pb *ccipocr3pb.ExecutePluginReport) ccipocr3.Execut ChainReports: chainReports, } } + +// ExtraDataCodecBundle client +var _ ccipocr3.ExtraDataCodecBundle = (*extraDataCodecBundleClient)(nil) + +type extraDataCodecBundleClient struct { + *net.BrokerExt + grpc ccipocr3pb.ExtraDataCodecBundleClient +} + +func NewExtraDataCodecBundleClient(broker *net.BrokerExt, cc grpc.ClientConnInterface) ccipocr3.ExtraDataCodecBundle { + return &extraDataCodecBundleClient{ + BrokerExt: broker, + grpc: ccipocr3pb.NewExtraDataCodecBundleClient(cc), + } +} + +func (c *extraDataCodecBundleClient) DecodeExtraArgs(extraArgs ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector) (map[string]any, error) { + resp, err := c.grpc.DecodeExtraArgs(context.Background(), &ccipocr3pb.DecodeExtraArgsWithChainSelectorRequest{ + ExtraArgs: extraArgs, + SourceChainSelector: uint64(sourceChainSelector), + }) + if err != nil { + return nil, err + } + return pbMapToGoMap(resp.DecodedMap) +} + +func (c *extraDataCodecBundleClient) DecodeTokenAmountDestExecData(destExecData ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector) (map[string]any, error) { + resp, err := c.grpc.DecodeTokenAmountDestExecData(context.Background(), &ccipocr3pb.DecodeTokenAmountDestExecDataRequest{ + DestExecData: destExecData, + SourceChainSelector: uint64(sourceChainSelector), + }) + if err != nil { + return nil, err + } + return pbMapToGoMap(resp.DecodedMap) +} + +// ExtraDataCodecBundle server +var _ ccipocr3pb.ExtraDataCodecBundleServer = (*extraDataCodecBundleServer)(nil) + +type extraDataCodecBundleServer struct { + ccipocr3pb.UnimplementedExtraDataCodecBundleServer + impl ccipocr3.ExtraDataCodecBundle +} + +func NewExtraDataCodecBundleServer(impl ccipocr3.ExtraDataCodecBundle) ccipocr3pb.ExtraDataCodecBundleServer { + return &extraDataCodecBundleServer{impl: impl} +} + +func (s *extraDataCodecBundleServer) DecodeExtraArgs(ctx context.Context, req *ccipocr3pb.DecodeExtraArgsWithChainSelectorRequest) (*ccipocr3pb.DecodeExtraArgsWithChainSelectorResponse, error) { + decodedMap, err := s.impl.DecodeExtraArgs(req.ExtraArgs, ccipocr3.ChainSelector(req.SourceChainSelector)) + if err != nil { + return nil, err + } + pbMap, err := goMapToPbMap(decodedMap) + if err != nil { + return nil, fmt.Errorf("failed to convert decoded map to protobuf: %w", err) + } + return &ccipocr3pb.DecodeExtraArgsWithChainSelectorResponse{ + DecodedMap: pbMap, + }, nil +} + +func (s *extraDataCodecBundleServer) DecodeTokenAmountDestExecData(ctx context.Context, req *ccipocr3pb.DecodeTokenAmountDestExecDataRequest) (*ccipocr3pb.DecodeTokenAmountDestExecDataResponse, error) { + decodedMap, err := s.impl.DecodeTokenAmountDestExecData(req.DestExecData, ccipocr3.ChainSelector(req.SourceChainSelector)) + if err != nil { + return nil, err + } + pbMap, err := goMapToPbMap(decodedMap) + if err != nil { + return nil, fmt.Errorf("failed to convert decoded map to protobuf: %w", err) + } + return &ccipocr3pb.DecodeTokenAmountDestExecDataResponse{ + DecodedMap: pbMap, + }, nil +} diff --git a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec_test.go b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec_test.go index ab39c84c5..20d0e8027 100644 --- a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec_test.go +++ b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/codec_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - + ccipocr3pb "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) diff --git a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/convert_test.go b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/convert_test.go index 6f3645e19..bdc8349c4 100644 --- a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/convert_test.go +++ b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/convert_test.go @@ -1594,3 +1594,132 @@ func TestTokenInfoMapNilHandling(t *testing.T) { assert.Len(t, convertedMap, 0) }) } + +// TestExtraDataCodecBundleConversion tests the map conversion logic used by ExtraDataCodecBundle methods +// This test verifies that round-trip conversion preserves structure and semantic meaning +func TestExtraDataCodecBundleConversion(t *testing.T) { + t.Run("Nil map round-trip", func(t *testing.T) { + // Test that nil maps remain nil after round-trip + pbMap, err := goMapToPbMap(nil) + require.NoError(t, err) + + result, err := pbMapToGoMap(pbMap) + require.NoError(t, err) + assert.Nil(t, result, "nil input should result in nil output") + }) + + t.Run("Empty map round-trip", func(t *testing.T) { + // Test that empty maps remain empty after round-trip + emptyMap := map[string]any{} + pbMap, err := goMapToPbMap(emptyMap) + require.NoError(t, err) + + result, err := pbMapToGoMap(pbMap) + require.NoError(t, err) + assert.NotNil(t, result, "empty map should not become nil") + assert.Equal(t, 0, len(result), "empty map should remain empty") + }) + + t.Run("ExtraArgs-like data structure preservation", func(t *testing.T) { + // Test typical ExtraArgs structure with basic types + input := map[string]any{ + "gasLimit": uint64(100000), + "gasPrice": uint64(20000000000), + "enabled": true, + "data": []byte{0x01, 0x02, 0x03}, + } + + pbMap, err := goMapToPbMap(input) + require.NoError(t, err, "conversion to protobuf should succeed") + + result, err := pbMapToGoMap(pbMap) + require.NoError(t, err, "conversion from protobuf should succeed") + + // Verify structure is preserved + assert.Equal(t, len(input), len(result), "map size should be preserved") + + // Verify all keys exist + for key := range input { + assert.Contains(t, result, key, "key %s should exist after round-trip", key) + } + + // Verify specific values that should be exactly preserved + assert.Equal(t, input["enabled"], result["enabled"], "bool values should be preserved") + assert.Equal(t, input["data"], result["data"], "byte slice values should be preserved") + + // For numeric values, verify semantic equivalence (protobuf may normalize types) + assert.Equal(t, fmt.Sprintf("%v", input["gasLimit"]), fmt.Sprintf("%v", result["gasLimit"]), "gasLimit should be semantically equal") + assert.Equal(t, fmt.Sprintf("%v", input["gasPrice"]), fmt.Sprintf("%v", result["gasPrice"]), "gasPrice should be semantically equal") + }) + + t.Run("BigInt preservation", func(t *testing.T) { + // Test various BigInt values that are commonly used in ExtraArgs/DestExecData + input := map[string]any{ + "zero": big.NewInt(0), + "small": big.NewInt(42), + "large": big.NewInt(1000000000000000000), // 1 ETH in wei + "negative": big.NewInt(-123456789), + } + + pbMap, err := goMapToPbMap(input) + require.NoError(t, err) + + result, err := pbMapToGoMap(pbMap) + require.NoError(t, err) + + // Verify all BigInt values are preserved exactly + for key, originalVal := range input { + resultVal, exists := result[key] + require.True(t, exists, "key %s should exist", key) + + originalBigInt := originalVal.(*big.Int) + resultBigInt, ok := resultVal.(*big.Int) + require.True(t, ok, "result[%s] should be *big.Int", key) + assert.Equal(t, originalBigInt.String(), resultBigInt.String(), "BigInt value should be preserved for key %s", key) + } + }) + + t.Run("Nested structure preservation", func(t *testing.T) { + // Test nested maps and arrays as might appear in DestExecData + input := map[string]any{ + "version": uint32(1), + "config": map[string]any{ + "maxGas": uint64(500000), + "multiplier": float64(1.5), + }, + "amounts": []any{ + big.NewInt(1000), + big.NewInt(2000), + }, + } + + pbMap, err := goMapToPbMap(input) + require.NoError(t, err) + + result, err := pbMapToGoMap(pbMap) + require.NoError(t, err) + + // Verify top-level structure + assert.Equal(t, len(input), len(result), "top-level map size should be preserved") + + // Verify nested map structure + configResult, ok := result["config"].(map[string]any) + require.True(t, ok, "config should remain a map") + configInput := input["config"].(map[string]any) + assert.Equal(t, len(configInput), len(configResult), "nested map size should be preserved") + + // Verify array structure + amountsResult, ok := result["amounts"].([]any) + require.True(t, ok, "amounts should remain an array") + amountsInput := input["amounts"].([]any) + assert.Equal(t, len(amountsInput), len(amountsResult), "array size should be preserved") + + // Verify BigInt values in array are preserved + for i, originalAmount := range amountsInput { + originalBigInt := originalAmount.(*big.Int) + resultBigInt, ok := amountsResult[i].(*big.Int) + require.True(t, ok, "array element should remain *big.Int") + assert.Equal(t, originalBigInt.String(), resultBigInt.String(), "BigInt value should be preserved") + } + }) +} diff --git a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor.go b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor.go index 454220b7b..1b9e52227 100644 --- a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor.go +++ b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor.go @@ -404,15 +404,15 @@ func (s staticChainAccessor) GetFeedPricesUSD(ctx context.Context, tokens []ccip return result, nil } -func (s staticChainAccessor) GetFeeQuoterTokenUpdates(ctx context.Context, tokens []ccipocr3.UnknownEncodedAddress, chain ccipocr3.ChainSelector) (map[ccipocr3.UnknownEncodedAddress]ccipocr3.TimestampedUnixBig, error) { +func (s staticChainAccessor) GetFeeQuoterTokenUpdates(ctx context.Context, tokensBytes []ccipocr3.UnknownAddress) (map[ccipocr3.UnknownEncodedAddress]ccipocr3.TimestampedUnixBig, error) { // Return static test token updates result := make(map[ccipocr3.UnknownEncodedAddress]ccipocr3.TimestampedUnixBig) testTime := time.Date(2024, 1, 15, 12, 0, 0, 0, time.UTC) - for i, token := range tokens { + for i, token := range tokensBytes { // Generate different prices for different tokens price := big.NewInt(2000000 + int64(i)*50000) // Different prices from GetFeedPricesUSD - result[token] = ccipocr3.TimestampedUnixBig{ + result[ccipocr3.UnknownEncodedAddress(token)] = ccipocr3.TimestampedUnixBig{ Timestamp: uint32(testTime.Add(time.Duration(i) * time.Minute).Unix()), // Different timestamps Value: price, } @@ -1023,14 +1023,13 @@ func (s staticChainAccessor) evaluateGetFeedPricesUSD(ctx context.Context, other } func (s staticChainAccessor) evaluateGetFeeQuoterTokenUpdates(ctx context.Context, other ccipocr3.ChainAccessor) error { - tokens := []ccipocr3.UnknownEncodedAddress{"token1", "token2"} - chain := ccipocr3.ChainSelector(1) + tokensBytes := []ccipocr3.UnknownAddress{ccipocr3.UnknownAddress("token1"), ccipocr3.UnknownAddress("token2")} - otherUpdates, err := other.GetFeeQuoterTokenUpdates(ctx, tokens, chain) + otherUpdates, err := other.GetFeeQuoterTokenUpdates(ctx, tokensBytes) if err != nil { return fmt.Errorf("GetFeeQuoterTokenUpdates failed: %w", err) } - myUpdates, err := s.GetFeeQuoterTokenUpdates(ctx, tokens, chain) + myUpdates, err := s.GetFeeQuoterTokenUpdates(ctx, tokensBytes) if err != nil { return fmt.Errorf("GetFeeQuoterTokenUpdates failed: %w", err) } diff --git a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor_test.go b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor_test.go index afe704a5c..87a8c2e09 100644 --- a/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor_test.go +++ b/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3/test/chain_accessor_test.go @@ -148,8 +148,8 @@ func TestChainAccessor(t *testing.T) { }) t.Run("GetFeeQuoterTokenUpdates", func(t *testing.T) { - tokens := []ccipocr3.UnknownEncodedAddress{"token1", "token2"} - updates, err := chainAccessor.GetFeeQuoterTokenUpdates(ctx, tokens, ccipocr3.ChainSelector(1)) + tokensBytes := []ccipocr3.UnknownAddress{ccipocr3.UnknownAddress("token1"), ccipocr3.UnknownAddress("token2")} + updates, err := chainAccessor.GetFeeQuoterTokenUpdates(ctx, tokensBytes) assert.NoError(t, err) assert.NotNil(t, updates) assert.Len(t, updates, 2) diff --git a/pkg/loop/internal/relayer/relayer.go b/pkg/loop/internal/relayer/relayer.go index 27a928124..79b505f18 100644 --- a/pkg/loop/internal/relayer/relayer.go +++ b/pkg/loop/internal/relayer/relayer.go @@ -21,10 +21,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/goplugin" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/net" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb" + ccipocr3pb "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/contractreader" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/contractwriter" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ext/ccip" - "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3" + ccipocr3loop "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ext/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ext/median" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ext/mercury" "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ext/ocr3capability" @@ -290,27 +291,42 @@ func (r *relayerClient) NewLLOProvider(ctx context.Context, rargs types.RelayArg } func (r *relayerClient) NewCCIPProvider(ctx context.Context, cargs types.CCIPProviderArgs) (types.CCIPProvider, error) { - var ccipProvider *ccipocr3.CCIPProviderClient + var ccipProvider *ccipocr3loop.CCIPProviderClient cc := r.NewClientConn("CCIPProvider", func(ctx context.Context) (uint32, net.Resources, error) { + var deps net.Resources + + var extraDataCodecBundleID uint32 + if cargs.ExtraDataCodecBundle != nil { + edcID, edcRes, err := r.ServeNew("ExtraDataCodecBundle", func(s *grpc.Server) { + ccipocr3pb.RegisterExtraDataCodecBundleServer(s, ccipocr3loop.NewExtraDataCodecBundleServer(cargs.ExtraDataCodecBundle)) + }) + if err != nil { + return 0, nil, fmt.Errorf("failed to serve ExtraDataCodecBundle: %w", err) + } + deps.Add(edcRes) + extraDataCodecBundleID = edcID + } + persistedSyncs := ccipProvider.GetSyncRequests() reply, err := r.relayer.NewCCIPProvider(ctx, &pb.NewCCIPProviderRequest{ CcipProviderArgs: &pb.CCIPProviderArgs{ - ExternalJobID: cargs.ExternalJobID[:], - ContractReaderConfig: cargs.ContractReaderConfig, - ChainWriterConfig: cargs.ChainWriterConfig, - OffRampAddress: cargs.OffRampAddress, - PluginType: uint32(cargs.PluginType), - SyncedAddresses: persistedSyncs, - TransmitterAddress: string(cargs.TransmitterAddress), + ExternalJobID: cargs.ExternalJobID[:], + ContractReaderConfig: cargs.ContractReaderConfig, + ChainWriterConfig: cargs.ChainWriterConfig, + OffRampAddress: cargs.OffRampAddress, + TransmitterAddress: string(cargs.TransmitterAddress), + PluginType: uint32(cargs.PluginType), + SyncedAddresses: persistedSyncs, + ExtraDataCodecBundleID: extraDataCodecBundleID, }, }) if err != nil { return 0, nil, err } - return reply.CcipProviderID, nil, nil + return reply.CcipProviderID, deps, nil }) - ccipProvider = ccipocr3.NewCCIPProviderClient(r.WithName(cargs.ExternalJobID.String()).WithName("CCIPProviderClient"), cc) + ccipProvider = ccipocr3loop.NewCCIPProviderClient(r.WithName(cargs.ExternalJobID.String()).WithName("CCIPProviderClient"), cc) return ccipProvider, nil } @@ -728,6 +744,20 @@ func (r *relayerServer) NewCCIPProvider(ctx context.Context, request *pb.NewCCIP if err != nil { return nil, fmt.Errorf("invalid uuid bytes for ExternalJobID: %w", err) } + + var extraDataCodecBundle ccipocr3types.ExtraDataCodecBundle + var extraDataCodecRes net.Resource + + // If ExtraDataCodecBundleID is provided, dial the service + if rargs.ExtraDataCodecBundleID != 0 { + extraDataCodecConn, err := r.Dial(rargs.ExtraDataCodecBundleID) + if err != nil { + return nil, net.ErrConnDial{Name: "ExtraDataCodecBundle", ID: rargs.ExtraDataCodecBundleID, Err: err} + } + extraDataCodecRes = net.Resource{Closer: extraDataCodecConn, Name: "ExtraDataCodecBundle"} + extraDataCodecBundle = ccipocr3loop.NewExtraDataCodecBundleClient(r.BrokerExt, extraDataCodecConn) + } + ccipProviderArgs := types.CCIPProviderArgs{ ExternalJobID: exJobID, ContractReaderConfig: rargs.ContractReaderConfig, @@ -735,10 +765,14 @@ func (r *relayerServer) NewCCIPProvider(ctx context.Context, request *pb.NewCCIP OffRampAddress: rargs.OffRampAddress, PluginType: ccipocr3types.PluginType(rargs.PluginType), TransmitterAddress: ccipocr3types.UnknownEncodedAddress(rargs.TransmitterAddress), + ExtraDataCodecBundle: extraDataCodecBundle, } provider, err := r.impl.NewCCIPProvider(ctx, ccipProviderArgs) if err != nil { + if extraDataCodecRes.Closer != nil { + extraDataCodecRes.Close() + } return nil, err } @@ -746,14 +780,22 @@ func (r *relayerServer) NewCCIPProvider(ctx context.Context, request *pb.NewCCIP for contractName, addressBytes := range rargs.SyncedAddresses { err = provider.ChainAccessor().Sync(ctx, contractName, addressBytes) if err != nil { + if extraDataCodecRes.Closer != nil { + extraDataCodecRes.Close() + } return nil, err } } const name = "CCIPProvider" + resources := []net.Resource{{Closer: provider, Name: name}} + if extraDataCodecRes.Closer != nil { + resources = append(resources, extraDataCodecRes) + } + id, _, err := r.ServeNew(name, func(s *grpc.Server) { - ccipocr3.RegisterProviderServices(s, provider) - }, net.Resource{Closer: provider, Name: name}) + ccipocr3loop.RegisterProviderServices(s, provider) + }, resources...) if err != nil { return nil, err } diff --git a/pkg/loop/internal/relayer/test/relayer.go b/pkg/loop/internal/relayer/test/relayer.go index d24471f2a..f0bfb030b 100644 --- a/pkg/loop/internal/relayer/test/relayer.go +++ b/pkg/loop/internal/relayer/test/relayer.go @@ -47,6 +47,27 @@ var chainInfo = types.ChainInfo{ NetworkNameFull: "someNetwork-test", } +// testExtraDataCodecBundle is a dummy implementation of ExtraDataCodecBundle for testing +type testExtraDataCodecBundle struct{} + +func newTestExtraDataCodecBundle() ccipocr3.ExtraDataCodecBundle { + return testExtraDataCodecBundle{} +} + +func (t testExtraDataCodecBundle) DecodeExtraArgs(extraArgs ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector) (map[string]any, error) { + return map[string]any{ + "gasLimit": uint64(100000), + "test": "extraArgs", + }, nil +} + +func (t testExtraDataCodecBundle) DecodeTokenAmountDestExecData(destExecData ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector) (map[string]any, error) { + return map[string]any{ + "data": "test-dest-exec-data", + "test": "destExecData", + }, nil +} + type transactionRequest struct { from string to string @@ -78,6 +99,7 @@ type staticRelayerConfig struct { offRampAddress ccipocr3.UnknownAddress pluginType ccipocr3.PluginType transmitterAddress ccipocr3.UnknownEncodedAddress + extraDataCodecBundle ccipocr3.ExtraDataCodecBundle medianProvider testtypes.MedianProviderTester agnosticProvider testtypes.PluginProviderTester mercuryProvider mercurytest.MercuryProviderTester @@ -106,6 +128,7 @@ func newStaticRelayerConfig(lggr logger.Logger, staticChecks bool) staticRelayer offRampAddress: []byte("fakeAddress"), pluginType: 0, transmitterAddress: "fakeAddress", + extraDataCodecBundle: newTestExtraDataCodecBundle(), medianProvider: mediantest.MedianProvider(lggr), mercuryProvider: mercurytest.MercuryProvider(lggr), executionProvider: cciptest.ExecutionProvider(lggr), @@ -324,6 +347,7 @@ func (s staticRelayer) NewCCIPProvider(ctx context.Context, r types.CCIPProvider OffRampAddress: s.offRampAddress, PluginType: s.pluginType, TransmitterAddress: s.transmitterAddress, + ExtraDataCodecBundle: s.extraDataCodecBundle, } if s.StaticChecks && !equalCCIPProviderArgs(r, ccipProviderArgs) { return nil, fmt.Errorf("expected relay args:\n\t%v\nbut got:\n\t%v", s.relayArgs, r) @@ -483,7 +507,8 @@ func equalCCIPProviderArgs(a, b types.CCIPProviderArgs) bool { slices.Equal(a.ChainWriterConfig, b.ChainWriterConfig) && slices.Equal(a.OffRampAddress, b.OffRampAddress) && a.PluginType == b.PluginType && - a.TransmitterAddress == b.TransmitterAddress + a.TransmitterAddress == b.TransmitterAddress && + a.ExtraDataCodecBundle == b.ExtraDataCodecBundle } func newRelayArgsWithProviderType(_type types.OCR2PluginType) types.RelayArgs { diff --git a/pkg/types/ccipocr3/chainaccessor.go b/pkg/types/ccipocr3/chainaccessor.go index 764303929..a54dd8b79 100644 --- a/pkg/types/ccipocr3/chainaccessor.go +++ b/pkg/types/ccipocr3/chainaccessor.go @@ -219,7 +219,6 @@ type PriceReader interface { // GetFeeQuoterTokenUpdates returns the latest token prices from the FeeQuoter on the specified chain GetFeeQuoterTokenUpdates( ctx context.Context, - tokens []UnknownEncodedAddress, - chain ChainSelector, + tokensBytes []UnknownAddress, ) (map[UnknownEncodedAddress]TimestampedUnixBig, error) } diff --git a/pkg/types/ccipocr3/generic_types.go b/pkg/types/ccipocr3/generic_types.go index 48cfe51cf..40abe2929 100644 --- a/pkg/types/ccipocr3/generic_types.go +++ b/pkg/types/ccipocr3/generic_types.go @@ -340,7 +340,8 @@ type TimestampedBig struct { type TimestampedUnixBig struct { // Value in uint224, can contain several packed fields Value *big.Int `json:"value"` - // Timestamp in seconds since epoch of most recent update + // Timestamp is a typical Unix timestamp (seconds since the 1970 epoch). This specific timestamp is when Value was + // written. Timestamp uint32 `json:"timestamp"` } diff --git a/pkg/types/ccipocr3/plugin_commit_types.go b/pkg/types/ccipocr3/plugin_commit_types.go index 2f68b69ad..7f2f52289 100644 --- a/pkg/types/ccipocr3/plugin_commit_types.go +++ b/pkg/types/ccipocr3/plugin_commit_types.go @@ -103,7 +103,7 @@ func DecodeCommitReportInfo(data []byte) (CommitReportInfo, error) { err := dec.Decode(&result) return result, err default: - return CommitReportInfo{}, fmt.Errorf("unknown execute report info version (%d)", data[0]) + return CommitReportInfo{}, fmt.Errorf("unknown commit report info version (%d)", data[0]) } } diff --git a/pkg/types/ccipocr3/plugin_commit_types_test.go b/pkg/types/ccipocr3/plugin_commit_types_test.go index c9d3ea653..37d208ba5 100644 --- a/pkg/types/ccipocr3/plugin_commit_types_test.go +++ b/pkg/types/ccipocr3/plugin_commit_types_test.go @@ -168,7 +168,7 @@ func TestDecodeCommitReportInfo(t *testing.T) { { data := append([]byte{2}, []byte("{}")...) _, err := DecodeCommitReportInfo(data) - require.ErrorContains(t, err, "unknown execute report info version (2)") + require.ErrorContains(t, err, "unknown commit report info version (2)") } // Invalid field diff --git a/pkg/types/ccipocr3/plugincodec.go b/pkg/types/ccipocr3/plugincodec.go index ef2054024..ce62b8c10 100644 --- a/pkg/types/ccipocr3/plugincodec.go +++ b/pkg/types/ccipocr3/plugincodec.go @@ -36,11 +36,19 @@ type SourceChainExtraDataCodec interface { DecodeDestExecDataToMap(destExecData Bytes) (map[string]any, error) } -// ExtraDataCodec is a map of chain family to SourceChainExtraDataCodec -type ExtraDataCodec map[string]SourceChainExtraDataCodec +// ExtraDataCodecBundle is an interface that defines methods for decoding extra args and dest exec data. +type ExtraDataCodecBundle interface { + DecodeExtraArgs(extraArgs Bytes, sourceChainSelector ChainSelector) (map[string]any, error) + DecodeTokenAmountDestExecData(destExecData Bytes, sourceChainSelector ChainSelector) (map[string]any, error) +} + +// ExtraDataCodecMap is a map of chain family to SourceChainExtraDataCodec +type ExtraDataCodecMap map[string]SourceChainExtraDataCodec + +var _ ExtraDataCodecBundle = ExtraDataCodecMap{} // DecodeExtraArgs reformats bytes into a chain agnostic map[string]any representation for extra args -func (c ExtraDataCodec) DecodeExtraArgs(extraArgs Bytes, sourceChainSelector ChainSelector) (map[string]any, error) { +func (c ExtraDataCodecMap) DecodeExtraArgs(extraArgs Bytes, sourceChainSelector ChainSelector) (map[string]any, error) { if len(extraArgs) == 0 { // return empty map if extraArgs is empty return nil, nil @@ -60,7 +68,7 @@ func (c ExtraDataCodec) DecodeExtraArgs(extraArgs Bytes, sourceChainSelector Cha } // DecodeTokenAmountDestExecData reformats bytes to chain-agnostic map[string]any for tokenAmount DestExecData field -func (c ExtraDataCodec) DecodeTokenAmountDestExecData(destExecData Bytes, sourceChainSelector ChainSelector) (map[string]any, error) { +func (c ExtraDataCodecMap) DecodeTokenAmountDestExecData(destExecData Bytes, sourceChainSelector ChainSelector) (map[string]any, error) { if len(destExecData) == 0 { // return empty map if destExecData is empty return nil, nil diff --git a/pkg/types/ccipocr3/plugincodec_test.go b/pkg/types/ccipocr3/plugincodec_test.go index a98478078..b4a330540 100644 --- a/pkg/types/ccipocr3/plugincodec_test.go +++ b/pkg/types/ccipocr3/plugincodec_test.go @@ -9,7 +9,7 @@ import ( ) func TestExtraDataCodec_DecodeExtraArgs(t *testing.T) { - extraDataCodec := ExtraDataCodec{ + extraDataCodec := ExtraDataCodecMap{ chainsel.FamilySolana: nil, } @@ -41,7 +41,7 @@ func TestExtraDataCodec_DecodeExtraArgs(t *testing.T) { } func TestExtraDataCodec_DecodeTokenAmountDestExecData(t *testing.T) { - extraDataCodec := ExtraDataCodec{ + extraDataCodec := ExtraDataCodecMap{ chainsel.FamilySolana: nil, } diff --git a/pkg/types/provider_ccip.go b/pkg/types/provider_ccip.go index 4636d41f5..b20e55d2b 100644 --- a/pkg/types/provider_ccip.go +++ b/pkg/types/provider_ccip.go @@ -59,13 +59,17 @@ type CCIPProvider interface { // CCIPProviderArgs are the args required to create a CCIP Provider through a Relayer. // The are common to all relayer implementations. type CCIPProviderArgs struct { - ExternalJobID uuid.UUID - OffRampAddress ccipocr3.UnknownAddress - PluginType ccipocr3.PluginType - TransmitterAddress ccipocr3.UnknownEncodedAddress + ExternalJobID uuid.UUID + OffRampAddress ccipocr3.UnknownAddress + PluginType ccipocr3.PluginType + TransmitterAddress ccipocr3.UnknownEncodedAddress // These CR/CW configs are only used by accessors that still rely on ChainReader // and ChainWriter, like SolanaAccessor. ContractReaderConfig []byte ChainWriterConfig []byte + + // The actual bundle instance to serve over LOOP. pb.CCIPProviderArgs equivalent + // is ExtraDataCodecBundleID. + ExtraDataCodecBundle ccipocr3.ExtraDataCodecBundle }