Skip to content

Commit d8a3881

Browse files
committed
add address codec registry
1 parent 93bed05 commit d8a3881

File tree

25 files changed

+230
-218
lines changed

25 files changed

+230
-218
lines changed
Lines changed: 2 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,7 @@
11
package common
22

33
import (
4-
"fmt"
5-
6-
chainsel "github.com/smartcontractkit/chain-selectors"
7-
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
4+
cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
85
)
96

10-
var _ cciptypes.AddressCodec = &AddressCodec{}
11-
12-
// AddressCodec is a struct that holds the chain specific address codecs and
13-
// implements a superset of the cciptypes.AddressCodec interface.
14-
type AddressCodec struct {
15-
registeredAddressCodecMap map[string]ChainSpecificAddressCodec
16-
}
17-
18-
// NewAddressCodec is a constructor for NewAddressCodec
19-
func NewAddressCodec(registeredMap map[string]ChainSpecificAddressCodec) AddressCodec {
20-
return AddressCodec{
21-
registeredAddressCodecMap: registeredMap,
22-
}
23-
}
24-
25-
// AddressBytesToString converts an address from bytes to string
26-
func (ac AddressCodec) AddressBytesToString(addr cciptypes.UnknownAddress, chainSelector cciptypes.ChainSelector) (string, error) {
27-
family, err := chainsel.GetSelectorFamily(uint64(chainSelector))
28-
if err != nil {
29-
return "", fmt.Errorf("failed to get chain family for selector %d: %w", chainSelector, err)
30-
}
31-
32-
codec, exist := ac.registeredAddressCodecMap[family]
33-
if !exist {
34-
return "", fmt.Errorf("unsupported family for address decode type %s", family)
35-
}
36-
37-
return codec.AddressBytesToString(addr)
38-
}
39-
40-
// TransmitterBytesToString converts a transmitter account from bytes to string
41-
func (ac AddressCodec) TransmitterBytesToString(addr cciptypes.UnknownAddress, chainSelector cciptypes.ChainSelector) (string, error) {
42-
family, err := chainsel.GetSelectorFamily(uint64(chainSelector))
43-
if err != nil {
44-
return "", fmt.Errorf("failed to get chain family for selector %d: %w", chainSelector, err)
45-
}
46-
47-
codec, exist := ac.registeredAddressCodecMap[family]
48-
if !exist {
49-
return "", fmt.Errorf("unsupported family for transmitter decode type %s", family)
50-
}
51-
52-
return codec.TransmitterBytesToString(addr)
53-
}
54-
55-
// AddressStringToBytes converts an address from string to bytes
56-
func (ac AddressCodec) AddressStringToBytes(addr string, chainSelector cciptypes.ChainSelector) (cciptypes.UnknownAddress, error) {
57-
family, err := chainsel.GetSelectorFamily(uint64(chainSelector))
58-
if err != nil {
59-
return nil, fmt.Errorf("failed to get chain family for selector %d: %w", chainSelector, err)
60-
}
61-
codec, exist := ac.registeredAddressCodecMap[family]
62-
if !exist {
63-
return nil, fmt.Errorf("unsupported family for address decode type %s", family)
64-
}
65-
66-
return codec.AddressStringToBytes(addr)
67-
}
68-
69-
// OracleIDAsAddressBytes returns valid address bytes for a given chain selector and oracle ID.
70-
// Used for making nil transmitters in the OCR config valid, it just means that this oracle does not support the destination chain.
71-
func (ac AddressCodec) OracleIDAsAddressBytes(oracleID uint8, chainSelector cciptypes.ChainSelector) ([]byte, error) {
72-
family, err := chainsel.GetSelectorFamily(uint64(chainSelector))
73-
if err != nil {
74-
return nil, fmt.Errorf("failed to get chain family for selector %d: %w", chainSelector, err)
75-
}
76-
codec, exist := ac.registeredAddressCodecMap[family]
77-
if !exist {
78-
return nil, fmt.Errorf("unsupported family for address decode type %s", family)
79-
}
80-
81-
return codec.OracleIDAsAddressBytes(oracleID)
82-
}
7+
type AddressCodec = cciptypes.AddressCodecMap
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package common
2+
3+
import (
4+
"sync"
5+
6+
cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
7+
)
8+
9+
// Ensure AddressCodecRegistry implements the AddressCodecBundle interface
10+
var _ cciptypes.AddressCodecBundle = (*AddressCodecRegistry)(nil)
11+
12+
// AddressCodecRegistry is a singleton registry that manages ChainSpecificAddressCodec instances
13+
// for different chain families. It implements the AddressCodecBundle interface
14+
// by delegating to the existing AddressCodec implementation.
15+
//
16+
// Terminology:
17+
// - "AddressCodecRegistry": refers to the entire singleton registry instance. It both maintains the map of
18+
// chain family to codec and provides thread-safe access to it.
19+
// - "AddressCodecBundle": is the interface that the registry implements
20+
type AddressCodecRegistry struct {
21+
addressCodec cciptypes.AddressCodecMap
22+
mu sync.RWMutex
23+
}
24+
25+
var (
26+
addressRegistryInstance *AddressCodecRegistry
27+
addressRegistryOnce sync.Once
28+
)
29+
30+
// GetAddressCodecRegistry returns the singleton instance of AddressCodecRegistry. This is only called
31+
// in core node.
32+
func GetAddressCodecRegistry() *AddressCodecRegistry {
33+
addressRegistryOnce.Do(func() {
34+
addressRegistryInstance = &AddressCodecRegistry{
35+
addressCodec: make(cciptypes.AddressCodecMap),
36+
}
37+
})
38+
return addressRegistryInstance
39+
}
40+
41+
// RegisterFamily registers a chain family with a no-op ChainSpecificAddressCodec if not already registered.
42+
// This is used when we know which chain families we want to support but don't have a specific codec
43+
// implementation initialized for it yet.
44+
func (r *AddressCodecRegistry) RegisterFamily(chainFamily string) {
45+
r.mu.Lock()
46+
defer r.mu.Unlock()
47+
if _, exists := r.addressCodec[chainFamily]; !exists {
48+
r.addressCodec[chainFamily] = NoOpChainSpecificAddressCodec{}
49+
}
50+
}
51+
52+
// RegisterCodec registers a ChainSpecificAddressCodec for a specific chain family
53+
func (r *AddressCodecRegistry) RegisterCodec(chainFamily string, codec ChainSpecificAddressCodec) {
54+
r.mu.Lock()
55+
defer r.mu.Unlock()
56+
r.addressCodec[chainFamily] = codec
57+
}
58+
59+
// ============ Implementation of AddressCodecBundle interface ============
60+
61+
func (r *AddressCodecRegistry) AddressBytesToString(addr cciptypes.UnknownAddress, chainSelector cciptypes.ChainSelector) (string, error) {
62+
r.mu.RLock()
63+
defer r.mu.RUnlock()
64+
return r.addressCodec.AddressBytesToString(addr, chainSelector)
65+
}
66+
67+
func (r *AddressCodecRegistry) TransmitterBytesToString(addr cciptypes.UnknownAddress, chainSelector cciptypes.ChainSelector) (string, error) {
68+
r.mu.RLock()
69+
defer r.mu.RUnlock()
70+
return r.addressCodec.TransmitterBytesToString(addr, chainSelector)
71+
}
72+
73+
func (r *AddressCodecRegistry) AddressStringToBytes(addr string, chainSelector cciptypes.ChainSelector) (cciptypes.UnknownAddress, error) {
74+
r.mu.RLock()
75+
defer r.mu.RUnlock()
76+
return r.addressCodec.AddressStringToBytes(addr, chainSelector)
77+
}
78+
79+
func (r *AddressCodecRegistry) OracleIDAsAddressBytes(oracleID uint8, chainSelector cciptypes.ChainSelector) ([]byte, error) {
80+
r.mu.RLock()
81+
defer r.mu.RUnlock()
82+
return r.addressCodec.OracleIDAsAddressBytes(oracleID, chainSelector)
83+
}
84+
85+
type NoOpChainSpecificAddressCodec struct{}
86+
87+
func (n NoOpChainSpecificAddressCodec) AddressBytesToString(addr []byte) (string, error) {
88+
return string(addr), nil
89+
}
90+
91+
func (n NoOpChainSpecificAddressCodec) AddressStringToBytes(addr string) ([]byte, error) {
92+
return []byte(addr), nil
93+
}
94+
95+
func (n NoOpChainSpecificAddressCodec) OracleIDAsAddressBytes(oracleID uint8) ([]byte, error) {
96+
return []byte{oracleID}, nil
97+
}
98+
99+
func (n NoOpChainSpecificAddressCodec) TransmitterBytesToString(addr []byte) (string, error) {
100+
return string(addr), nil
101+
}

core/capabilities/ccip/common/extradatacodec.go

Lines changed: 0 additions & 9 deletions
This file was deleted.

core/capabilities/ccip/common/extradatacodecregistry.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,6 @@ var (
2828
registryOnce sync.Once
2929
)
3030

31-
type NoOpSourceChainExtraDataCodec struct{}
32-
33-
func (n NoOpSourceChainExtraDataCodec) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) {
34-
return make(map[string]any), nil
35-
}
36-
37-
func (n NoOpSourceChainExtraDataCodec) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) {
38-
return make(map[string]any), nil
39-
}
40-
4131
// GetExtraDataCodecRegistry returns the singleton instance of ExtraDataCodecRegistry. This is only called
4232
// in core node.
4333
func GetExtraDataCodecRegistry() *ExtraDataCodecRegistry {
@@ -91,3 +81,13 @@ func (r *ExtraDataCodecRegistry) DecodeTokenAmountDestExecData(
9181
defer r.mu.RUnlock()
9282
return r.extraDataCodec.DecodeTokenAmountDestExecData(destExecData, sourceChainSelector)
9383
}
84+
85+
type NoOpSourceChainExtraDataCodec struct{}
86+
87+
func (n NoOpSourceChainExtraDataCodec) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) {
88+
return make(map[string]any), nil
89+
}
90+
91+
func (n NoOpSourceChainExtraDataCodec) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) {
92+
return make(map[string]any), nil
93+
}

core/capabilities/ccip/common/pluginconfig.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ type PluginConfig struct {
2929
// PluginServices aggregates services for a specific chain family.
3030
type PluginServices struct {
3131
PluginConfig PluginConfig
32-
AddrCodec AddressCodec
3332
ChainRW MultiChainRW
3433
CCIPProviderSupported map[string]bool
3534
}
@@ -53,24 +52,25 @@ func GetPluginServices(lggr logger.Logger, chainFamily string) (PluginServices,
5352

5453
pluginServices := PluginServices{}
5554
extraDataCodecRegistry := GetExtraDataCodecRegistry()
56-
addressCodecMap := make(map[string]ChainSpecificAddressCodec)
55+
addressCodecRegistry := GetAddressCodecRegistry()
5756
chainRWProviderMap := make(map[string]ChainRWProvider)
5857
CCIPProviderSupported := make(map[string]bool)
5958

6059
for family, initFunc := range registeredFactories {
6160
config := initFunc(lggr, GetExtraDataCodecRegistry())
6261
CCIPProviderSupported[family] = config.CCIPProviderSupported
63-
if config.AddressCodec != nil {
64-
addressCodecMap[family] = config.AddressCodec
65-
}
6662

67-
// Register all known families, this includes families whose SourceChainExtraDataCodec is provided
68-
// by the CCIPProvider
63+
// Add all families to the registries. If the codecs are provided by the config, set them here, otherwise
64+
// ccipProvider will set them later in the oracle creator.
6965
extraDataCodecRegistry.RegisterFamily(family)
66+
addressCodecRegistry.RegisterFamily(family)
67+
7068
if config.ExtraDataCodec != nil {
71-
// Register the actual codec for this family if we have it defined in core already
7269
extraDataCodecRegistry.RegisterCodec(family, config.ExtraDataCodec)
7370
}
71+
if config.AddressCodec != nil {
72+
addressCodecRegistry.RegisterCodec(family, config.AddressCodec)
73+
}
7474
if config.ChainRW != nil {
7575
chainRWProviderMap[family] = config.ChainRW
7676
}
@@ -79,7 +79,6 @@ func GetPluginServices(lggr logger.Logger, chainFamily string) (PluginServices,
7979
}
8080
}
8181

82-
pluginServices.AddrCodec = NewAddressCodec(addressCodecMap)
8382
pluginServices.ChainRW = NewCRCW(chainRWProviderMap)
8483
pluginServices.CCIPProviderSupported = CCIPProviderSupported
8584
return pluginServices, nil

core/capabilities/ccip/delegate.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import (
1717
"github.com/smartcontractkit/chainlink-common/pkg/loop"
1818
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
1919
"github.com/smartcontractkit/chainlink-common/pkg/types"
20+
"github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
2021
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
2122

23+
chainsel "github.com/smartcontractkit/chain-selectors"
24+
2225
"github.com/smartcontractkit/chainlink-ccip/pkg/consts"
2326
ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader"
24-
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
25-
26-
chainsel "github.com/smartcontractkit/chain-selectors"
2727

2828
kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
2929
"github.com/smartcontractkit/chainlink-evm/pkg/config/toml"
@@ -214,11 +214,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services
214214
return nil, fmt.Errorf("failed to get chain selector from chain ID %d", homeChainChainID)
215215
}
216216

217-
pluginServices, err := common.GetPluginServices(d.lggr, d.capabilityConfig.ExternalRegistry().RelayID().Network)
218-
if err != nil {
219-
return nil, err
220-
}
221-
222217
// if bootstrappers are provided we assume that the node is a plugin oracle.
223218
// the reason for this is that bootstrap oracles do not need to be aware
224219
// of other bootstrap oracles. however, plugin oracles, at least initially,
@@ -239,8 +234,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services
239234
d.monitoringEndpointGen,
240235
bootstrapperLocators,
241236
hcr,
242-
cciptypes.ChainSelector(homeChainChainSelector),
243-
pluginServices.AddrCodec,
237+
ccipocr3.ChainSelector(homeChainChainSelector),
244238
p2pID,
245239
)
246240
} else {
@@ -251,7 +245,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services
251245
d.monitoringEndpointGen,
252246
d.lggr,
253247
homeChainContractReader,
254-
pluginServices.AddrCodec,
255248
)
256249
}
257250

core/capabilities/ccip/ocrimpls/config_tracker.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@ import (
44
"context"
55
"fmt"
66

7-
ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common"
87
cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
98

109
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
1110
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
1211

12+
ccipcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
13+
1314
"github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
1415
)
1516

1617
type configTracker struct {
1718
cfg cctypes.OCR3ConfigWithMeta
18-
addressCodec ccipcommon.AddressCodec
19+
addressCodec ccipcommontypes.AddressCodecBundle
1920
contractConfig types.ContractConfig
2021
}
2122

22-
func NewConfigTracker(cfg cctypes.OCR3ConfigWithMeta, addressCodec ccipcommon.AddressCodec) (*configTracker, error) {
23+
func NewConfigTracker(cfg cctypes.OCR3ConfigWithMeta, addressCodec ccipcommontypes.AddressCodecBundle) (*configTracker, error) {
2324
contractConfig, err := contractConfigFromOCRConfig(cfg, addressCodec)
2425
if err != nil {
2526
return nil, fmt.Errorf("failed to create contract config from ocr config: %w", err)
@@ -51,7 +52,7 @@ func (c *configTracker) Notify() <-chan struct{} {
5152
return nil
5253
}
5354

54-
func contractConfigFromOCRConfig(cfg cctypes.OCR3ConfigWithMeta, addressCodec ccipcommon.AddressCodec) (types.ContractConfig, error) {
55+
func contractConfigFromOCRConfig(cfg cctypes.OCR3ConfigWithMeta, addressCodec ccipcommontypes.AddressCodecBundle) (types.ContractConfig, error) {
5556
var signers [][]byte
5657
var transmitters [][]byte
5758
var err error
@@ -105,7 +106,7 @@ func toOnchainPublicKeys(signers [][]byte) []types.OnchainPublicKey {
105106
return keys
106107
}
107108

108-
func toOCRAccounts(transmitters [][]byte, addressCodec ccipcommon.AddressCodec, chainSelector ccipocr3.ChainSelector) ([]types.Account, error) {
109+
func toOCRAccounts(transmitters [][]byte, addressCodec ccipcommontypes.AddressCodecBundle, chainSelector ccipocr3.ChainSelector) ([]types.Account, error) {
109110
accounts := make([]types.Account, len(transmitters))
110111
for i, transmitter := range transmitters {
111112
address, err := addressCodec.TransmitterBytesToString(transmitter, chainSelector)

0 commit comments

Comments
 (0)