Skip to content

Parse raw bytes instead of hex over capReg grpc wire for transmitter address#1983

Closed
yashnevatia wants to merge 2 commits intomainfrom
ocr3-transmitter-rawBytes
Closed

Parse raw bytes instead of hex over capReg grpc wire for transmitter address#1983
yashnevatia wants to merge 2 commits intomainfrom
ocr3-transmitter-rawBytes

Conversation

@yashnevatia
Copy link
Copy Markdown
Contributor

@yashnevatia yashnevatia commented Apr 16, 2026

  • Aptos capability loop plugin calls ConfigForCapability on capability registry server
  • When converting the ocr3 config for the capability to proto, the server cannot hexDecode the transmitter address
  • Hence we get "error":"failed to get capability config: rpc error: code = Unknown desc = failed to decode transmitter: encoding/hex: invalid byte: U+0093"

This is the flow

Pushing on chain:

  • Push ocr3 config for any capability (does not matter aptos) here
    • calls ComputeOCR3Config
    • Which ends up creating OCR2OracleConfig with Transmitters as []common.Address
    • It then calls OCR2OracleConfigToMap to push this data to chain which stores transmitter address as base64 string
    • protojson interprets base64 strings as raw bytes, on-chain proto stores the raw 20-byte EVM address

Reading on chain:

  • LocalRegistry.Unmarshal does ocrtypes.Account(t) where t is those raw 20 bytes → the Account string contains raw binary. So when the gRPC server sees the Account, it contains raw binary bytes (like \xab\xcd\x93...). It naturally cannot hexDecode that

@yashnevatia yashnevatia requested a review from a team as a code owner April 16, 2026 11:21
Copilot AI review requested due to automatic review settings April 16, 2026 11:21
@github-actions
Copy link
Copy Markdown

👋 yashnevatia, thanks for creating this pull request!

To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.

Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks!

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 16, 2026

📊 API Diff Results

No changes detected for module github.com/smartcontractkit/chainlink-common

View full report

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Capabilities Registry gRPC marshalling for OCR3 configs so transmitter addresses are passed as raw bytes (matching the protobuf repeated bytes transmitters) instead of being hex-encoded/decoded into ocrtypes.Account strings.

Changes:

  • Remove hex encoding when decoding capabilitiespb.OCR3Config.Transmitters into ocrtypes.ContractConfig.
  • Remove hex decoding when encoding ocrtypes.ContractConfig.Transmitters back into the protobuf reply.
  • Drop the unused encoding/hex import.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 512 to 515
transmitters := make([][]byte, len(cfg.Transmitters))
for i, t := range cfg.Transmitters {
transmitters[i], err = hex.DecodeString(string(t))
if err != nil {
return nil, fmt.Errorf("failed to decode transmitter: %w", err)
}
transmitters[i] = []byte(t)
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By switching from hex.DecodeString(string(t)) to []byte(t), the server now treats cfg.Transmitters as containing raw address bytes encoded directly in a string. If any current core.CapabilitiesRegistry implementations still populate cfg.Transmitters as hex strings (as implied by the prior implementation), this will put ASCII hex on the wire rather than the intended raw bytes and won’t error anymore, leading to hard-to-debug misconfiguration. Consider supporting both encodings during rollout (decode hex when applicable), or enforce/validate the expected format (e.g., reject obvious hex strings when raw bytes are required, or add an explicit migration/version check).

Copilot uses AI. Check for mistakes.
Comment on lines 245 to 248
transmitters := make([]ocrtypes.Account, len(pbCfg.Transmitters))
for i, t := range pbCfg.Transmitters {
transmitters[i] = ocrtypes.Account(hex.EncodeToString(t))
transmitters[i] = ocrtypes.Account(t)
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change switches the in-process representation of ocrtypes.ContractConfig.Transmitters from a hex string (previously produced via hex.EncodeToString) to a raw-byte string (ocrtypes.Account(t) where t is protobuf []byte). Because ocrtypes.Account is a string type, this is a behavioral/API change for any downstream code that expects human-readable/hex transmitter addresses, and mixed-version plugin/core deployments (Hashicorp go-plugin handshake here doesn’t enforce a protocol version) could silently disagree on the encoding. Consider adding a transitional decode that accepts both formats (e.g., if the string is valid hex then decode, otherwise treat as raw bytes), or document/guard the change with an explicit versioned capability/handshake so incompatible components fail fast.

Copilot uses AI. Check for mistakes.
mchain0
mchain0 previously approved these changes Apr 16, 2026
Unheilbar
Unheilbar previously approved these changes Apr 16, 2026
Copy link
Copy Markdown
Contributor

@jmank88 jmank88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that this works for all cases? IIRC protobufs only accept utf8 encoded strings - not arbitrary bytes like Go does. Can we add a test?

@yashnevatia yashnevatia dismissed stale reviews from Unheilbar and mchain0 via 243dcd5 April 17, 2026 10:42
transmitters[i], err = hex.DecodeString(string(t))
if err != nil {
return nil, fmt.Errorf("failed to decode transmitter: %w", err)
decoded, hexErr := hex.DecodeString(string(t))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the discussion that we had it sounds like hex.DecodeString never works because the transmitter string isn't in hex, so If the transmitter is base64 encoded lets just decode it here into a hex string and keep it in that format.

@yashnevatia
Copy link
Copy Markdown
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants