Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/devenv/cciptestinterfaces/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ type ChainLaneProfile struct {
DefaultExecutorQualifier string
DefaultInboundCCVs []datastore.AddressRef
DefaultOutboundCCVs []datastore.AddressRef
TokenReceiverAllowed *bool
GasForVerification *uint32
AllowedFinalityConfig *finality.Config
}
Expand Down
15 changes: 13 additions & 2 deletions build/devenv/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -1930,7 +1930,7 @@ func proposeJobsToExecutors(
return fmt.Errorf("failed to get chain config loader for family %s: %w", exec.ChainFamily, err)
}

blockchainInfos, err := loader(blockchainOutputs)
blockchainInfos, err := loader(filterOutputsByFamily(blockchainOutputs, exec.ChainFamily))
if err != nil {
return fmt.Errorf("failed to load chain config for family %s: %w", exec.ChainFamily, err)
}
Expand Down Expand Up @@ -2259,7 +2259,7 @@ func proposeJobsToStandaloneVerifiers(
return fmt.Errorf("failed to get chain config loader for family %s: %w", ver.ChainFamily, err)
}

blockchainInfos, err := loader(blockchainOutputs)
blockchainInfos, err := loader(filterOutputsByFamily(blockchainOutputs, ver.ChainFamily))
if err != nil {
return fmt.Errorf("failed to load chain config for family %s: %w", ver.ChainFamily, err)
}
Expand Down Expand Up @@ -2298,3 +2298,14 @@ func proposeJobsToStandaloneVerifiers(

return g.Wait()
}

// filterOutputsByFamily returns only the blockchain outputs matching the given chain family.
func filterOutputsByFamily(outputs []*blockchain.Output, family string) []*blockchain.Output {
var filtered []*blockchain.Output
for _, out := range outputs {
if out.Family == family {
filtered = append(filtered, out)
}
}
return filtered
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This shouldn't be necessary, you can filter in the implementation and the GenericConfig object has a helper for that:

49 changes: 49 additions & 0 deletions build/devenv/evm/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func init() {
// provides backward compatibility with the previous FamilyEVM/FamilyCanton
// combined switch case.
cciptestinterfaces.RegisterExtraArgsSerializer(chainsel.FamilyCanton, SerializeEVMExtraArgs)
cciptestinterfaces.RegisterExtraArgsSerializer(chainsel.FamilySolana, SerializeSVMExtraArgs)
}

type CCIP17EVMConfig struct {
Expand Down Expand Up @@ -790,6 +791,16 @@ func SerializeEVMExtraArgs(opts cciptestinterfaces.MessageOptions) []byte {
}
}

// SerializeSVMExtraArgs is the Solana family's ExtraArgsSerializer, handling versions 1.
func SerializeSVMExtraArgs(opts cciptestinterfaces.MessageOptions) []byte {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is 1.6 though, right? From 2.0 onwards the extra args are encoded by the destination chain format

Copy link
Copy Markdown
Contributor Author

@huangzhen1997 huangzhen1997 Apr 16, 2026

Choose a reason for hiding this comment

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

Ideally yes, but devenv uses these chain-family serializer registries, it needs to be abi encoded otherwise fq cannot decode it. I spoke to Terry, the Devenv is still evolving, and this is just for unblocking us. CC @tt-cll

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.

I think ideally the registration we're doing above happens in the integrating repo, Solana in this instance.

cciptestinterfaces.RegisterExtraArgsSerializer(chainsel.FamilySolana, SerializeSVMExtraArgs)

That repo impl would return something to the EVM (or whoever calls it) like a byte array and anything else required for serialization to occur. fyi @winder @makramkd

switch opts.Version {
case 1:
return serializeExtraArgsSVMV1(opts)
default:
panic(fmt.Sprintf("unsupported EVM message extra args version: %d", opts.Version))
Comment thread
huangzhen1997 marked this conversation as resolved.
}
}

func serializeExtraArgsV1(opts cciptestinterfaces.MessageOptions) []byte {
evmExtraArgsV1Type, err := abi.NewType("tuple", "EVMExtraArgsV1", []abi.ArgumentMarshaling{
{Name: "gasLimit", Type: "uint256"},
Expand Down Expand Up @@ -866,6 +877,44 @@ func serializeExtraArgsV3(opts cciptestinterfaces.MessageOptions) []byte {
return extraArgs
}

func serializeExtraArgsSVMV1(opts cciptestinterfaces.MessageOptions) []byte {
svmExtraArgsV1Type, err := abi.NewType("tuple", "SVMExtraArgsV1", []abi.ArgumentMarshaling{
{Name: "computeUnits", Type: "uint32"},
{Name: "accountIsWritableBitmap", Type: "uint64"},
{Name: "allowOutOfOrderExecution", Type: "bool"},
{Name: "tokenReceiver", Type: "bytes32"},
{Name: "accounts", Type: "bytes32[]"},
})
if err != nil {
panic(fmt.Sprintf("failed to create SVMExtraArgsV1 tuple type: %v", err))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we not panic here? I don't see a clear path to adding test, asserting valid/intended errors from upstream caller

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is supposed to be running in devenv test via a call with SendMessage. And that's the pattern with all other serialize functions

}

arguments := abi.Arguments{{Type: svmExtraArgsV1Type, Name: "extraArgs"}}

type SVMExtraArgsV1 struct {
ComputeUnits uint32
AccountIsWritableBitmap uint64
AllowOutOfOrderExecution bool
TokenReceiver [32]byte
Accounts [][32]byte
}

packed, err := arguments.Pack(SVMExtraArgsV1{
ComputeUnits: opts.ExecutionGasLimit,
AccountIsWritableBitmap: 0,
AllowOutOfOrderExecution: opts.OutOfOrderExecution,
TokenReceiver: [32]byte{},
Accounts: [][32]byte{},
Comment thread
huangzhen1997 marked this conversation as resolved.
})
if err != nil {
panic(fmt.Sprintf("failed to pack SVMExtraArgsV1: %v", err))
}

// bytes4 public constant SVM_EXTRA_ARGS_V1_TAG = 0x1f3b3aba;
tag, _ := hexutil.Decode("0x1f3b3aba")
return append(tag, packed...)
}
Comment thread
huangzhen1997 marked this conversation as resolved.

func (m *CCIP17EVM) ExposeMetrics(
ctx context.Context,
source, dest uint64,
Expand Down
1 change: 1 addition & 0 deletions build/devenv/implcommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ func buildPartialChainConfig(
FeeQuoterDestChainConfig: remote.FeeQuoterDestChainConfig,
ExecutorDestChainConfig: local.ExecutorDestChainConfig,
BaseExecutionGasCost: remote.BaseExecutionGasCost,
TokenReceiverAllowed: remote.TokenReceiverAllowed,
}
}

Expand Down
Loading