From eac7f5ceaee3f8abba388f36a7f4b60650510374 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Mon, 16 Feb 2026 16:33:06 +0000 Subject: [PATCH 01/12] Adding aptos service implementation --- cmd/chainlink-aptos/main.go | 4 +- go.mod | 128 +++++----- go.sum | 265 ++++++++++---------- relayer/aptos_service.go | 281 ++++++++++++++++++++++ relayer/chain/chain.go | 32 ++- relayer/relay.go | 27 +++ relayer/testutils/keystore.go | 4 + relayer/txm/txm.go | 91 +++++++ relayer/write_target/write_target_test.go | 2 +- 9 files changed, 637 insertions(+), 197 deletions(-) create mode 100644 relayer/aptos_service.go diff --git a/cmd/chainlink-aptos/main.go b/cmd/chainlink-aptos/main.go index b6d635b41..1da52b389 100644 --- a/cmd/chainlink-aptos/main.go +++ b/cmd/chainlink-aptos/main.go @@ -56,7 +56,7 @@ type pluginRelayer struct { // [github.com/smartcontractkit/chainlink-common/pkg/loop.PluginRelayer] // loopKs must be an implementation that can construct a aptos keystore adapter // [github.com/smartcontractkit/chainlink-aptos/relayer/txm.NewKeystoreAdapter] -func (p *pluginRelayer) NewRelayer(ctx context.Context, rawConfig string, loopKs loop.Keystore, capRegistry core.CapabilitiesRegistry) (loop.Relayer, error) { +func (p *pluginRelayer) NewRelayer(ctx context.Context, rawConfig string, keystore core.Keystore, csaKeystore core.Keystore, capRegistry core.CapabilitiesRegistry) (loop.Relayer, error) { // Initialize the chain service cfg, err := config.NewDecodedTOMLConfig(rawConfig) if err != nil { @@ -64,7 +64,7 @@ func (p *pluginRelayer) NewRelayer(ctx context.Context, rawConfig string, loopKs } opts := chain.ChainOpts{ Logger: p.Logger, - KeyStore: loopKs, + KeyStore: keystore, DS: p.ds, } chain, err := chain.NewChain(cfg, opts) diff --git a/go.mod b/go.mod index 2da81b91a..5e1957fc3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink-aptos -go 1.24.1 +go 1.25.3 require ( github.com/aptos-labs/aptos-go-sdk v1.11.0 @@ -8,59 +8,60 @@ require ( github.com/ethereum/go-ethereum v1.16.8 github.com/go-viper/mapstructure/v2 v2.4.0 github.com/google/uuid v1.6.0 - github.com/hashicorp/go-plugin v1.6.3 + github.com/hashicorp/go-plugin v1.7.0 github.com/jmoiron/sqlx v1.4.0 github.com/jpillora/backoff v1.0.0 github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/pelletier/go-toml/v2 v2.2.3 + github.com/pelletier/go-toml/v2 v2.2.4 github.com/prometheus/client_golang v1.22.0 github.com/shopspring/decimal v1.4.0 github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250519161208-80bc8b13c0e7 + github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e + github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20260213154618-c188380529d4 github.com/stretchr/testify v1.11.1 github.com/valyala/fastjson v1.6.4 - go.opentelemetry.io/otel v1.35.0 - go.opentelemetry.io/otel/metric v1.35.0 - go.opentelemetry.io/otel/trace v1.35.0 - go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.45.0 - golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - golang.org/x/sync v0.18.0 - google.golang.org/protobuf v1.36.6 + go.opentelemetry.io/otel v1.39.0 + go.opentelemetry.io/otel/metric v1.39.0 + go.opentelemetry.io/otel/trace v1.39.0 + go.uber.org/zap v1.27.1 + golang.org/x/crypto v0.47.0 + golang.org/x/exp v0.0.0-20260112195511-716be5621a96 + golang.org/x/sync v0.19.0 + google.golang.org/protobuf v1.36.11 ) require ( filippo.io/edwards25519 v1.1.0 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect - github.com/XSAM/otelsql v0.29.0 // indirect - github.com/apache/arrow-go/v18 v18.0.0 // indirect + github.com/XSAM/otelsql v0.37.0 // indirect + github.com/apache/arrow-go/v18 v18.3.1 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.2 // indirect - github.com/cloudevents/sdk-go/v2 v2.16.0 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1 // indirect + github.com/cloudevents/sdk-go/v2 v2.16.1 // indirect github.com/coder/websocket v1.8.14 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/go-json-experiment/json v0.0.0-20250213060926-925ba3f173fa // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.25.0 // indirect + github.com/go-playground/validator/v10 v10.26.0 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/flatbuffers v25.2.10+incompatible // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/yamux v0.1.2 // indirect github.com/hasura/go-graphql-client v0.14.5 // indirect @@ -72,67 +73,72 @@ require ( github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.3.3 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgtype v1.14.4 // indirect github.com/jackc/pgx/v4 v4.18.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/mailru/easyjson v0.9.0 // indirect - github.com/marcboeker/go-duckdb v1.8.3 // indirect + github.com/marcboeker/go-duckdb v1.8.5 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.1.0 // indirect + github.com/oklog/run v1.2.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.16.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect - github.com/smartcontractkit/freeport v0.1.0 // indirect + github.com/smartcontractkit/chain-selectors v1.0.89 // indirect + github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 // indirect + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe // indirect + github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect + github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b // indirect + github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/libocr v0.0.0-20250220133800-f3b940c4f298 // indirect + github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect - go.opentelemetry.io/otel/log v0.10.0 // indirect - go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect - go.opentelemetry.io/proto/otlp v1.5.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.13.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 // indirect + go.opentelemetry.io/otel/log v0.15.0 // indirect + go.opentelemetry.io/otel/sdk v1.39.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.15.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.39.0 // indirect + go.opentelemetry.io/proto/otlp v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 // indirect + golang.org/x/text v0.33.0 // indirect + golang.org/x/time v0.14.0 // indirect + golang.org/x/tools v0.41.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250219182151-9fdb1cabc7b2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/grpc v1.71.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect + google.golang.org/grpc v1.78.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e7d66884c..3b766b5f3 100644 --- a/go.sum +++ b/go.sum @@ -3,16 +3,16 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU= github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= -github.com/XSAM/otelsql v0.29.0 h1:pEw9YXXs8ZrGRYfDc0cmArIz9lci5b42gmP5+tA1Huc= -github.com/XSAM/otelsql v0.29.0/go.mod h1:d3/0xGIGC5RVEE+Ld7KotwaLy6zDeaF3fLJHOPpdN2w= +github.com/XSAM/otelsql v0.37.0 h1:ya5RNw028JW0eJW8Ma4AmoKxAYsJSGuNVbC7F1J457A= +github.com/XSAM/otelsql v0.37.0/go.mod h1:LHbCu49iU8p255nCn1oi04oX2UjSoRcUMiKEHo2a5qM= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= -github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g6V7ZM= -github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= +github.com/apache/arrow-go/v18 v18.3.1 h1:oYZT8FqONiK74JhlH3WKVv+2NKYoyZ7C2ioD4Dj3ixk= +github.com/apache/arrow-go/v18 v18.3.1/go.mod h1:12QBya5JZT6PnBihi5NJTzbACrDGXYkrgjujz3MRQXU= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/aptos-labs/aptos-go-sdk v1.11.0 h1:vIL1hpjECUiu7zMl9Wz6VV8ttXsrDqKUj0HxoeaIER4= @@ -27,16 +27,16 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/ github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.2 h1:FIvfKlS2mcuP0qYY6yzdIU9xdrRd/YMP0bNwFjXd0u8= -github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.2/go.mod h1:POsdVp/08Mki0WD9QvvgRRpg9CQ6zhjfRrBoEY8JFS8= -github.com/cloudevents/sdk-go/v2 v2.16.0 h1:wnunjgiLQCfYlyo+E4+mFlZtAh7pKn7vT8MMD3lSwCg= -github.com/cloudevents/sdk-go/v2 v2.16.0/go.mod h1:5YWqklyhDSmGzBK/JENKKXdulbPq0JFf3c/KEnMLqgg= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1 h1:nLaJZcVAnaqch3K83AyzHfY2DmQM18/L7jvkmKSfkpI= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1/go.mod h1:6Q+F2puKpJ6zWv+R02BVnizJICf7++oRT5zwpZQAsbk= +github.com/cloudevents/sdk-go/v2 v2.16.1 h1:G91iUdqvl88BZ1GYYr9vScTj5zzXSyEuqbfE63gbu9Q= +github.com/cloudevents/sdk-go/v2 v2.16.1/go.mod h1:v/kVOaWjNfbvc6tkhhlkhvLapj8Aa8kvXiH5GiOHCKI= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= @@ -72,13 +72,13 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/go-json-experiment/json v0.0.0-20250213060926-925ba3f173fa h1:Rpu6sKAzIeSWBkrFHD52g8yipagcPbY2Lmm70NL1Gzc= -github.com/go-json-experiment/json v0.0.0-20250213060926-925ba3f173fa/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= +github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 h1:F8d1AJ6M9UQCavhwmO6ZsrYLfG8zVFWfEfMS2MXPkSY= +github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -87,8 +87,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= -github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -117,8 +117,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= +github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -136,18 +136,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-memdb v1.3.5 h1:b3taDMxCBCBVgyRrS1AZVHO14ubMYZB++QpNhBg+Nyo= github.com/hashicorp/go-memdb v1.3.5/go.mod h1:8IVKKBkVe+fxFgdFOYxzQQNjz+sWCyHCdIC/+5+Vy1Y= -github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= -github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA= +github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= @@ -190,8 +190,9 @@ github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwX github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= @@ -210,8 +211,8 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= -github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= @@ -223,8 +224,8 @@ github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= -github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -247,8 +248,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSlEMXiQ= -github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= +github.com/marcboeker/go-duckdb v1.8.5 h1:tkYp+TANippy0DaIOP5OEfBEwbUINqiFqgwMQ44jME0= +github.com/marcboeker/go-duckdb v1.8.5/go.mod h1:6mK7+WQE4P4u5AFLvVBmhFxY5fvhymFptghgJX6B+/8= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -268,8 +269,6 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpsp github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -279,12 +278,14 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -296,15 +297,15 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= -github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= -github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -321,14 +322,26 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 h1:6C8qej6f1bStuePVkLSFxoU22XBS165D3klxlzRg8F4= github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82/go.mod h1:xe4pgH49k4SsmkQq5OT8abwhWmnzkhpgnXeekbx2efw= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250519161208-80bc8b13c0e7 h1:yeDKMQSKJQwe5SdfPmbzjzgyZIeq1QlcR93K3e7tRCU= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250519161208-80bc8b13c0e7/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= -github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZVL+xgS1sPo= -github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= +github.com/smartcontractkit/chain-selectors v1.0.89 h1:L9oWZGqQXWyTPnC6ODXgu3b0DFyLmJ9eHv+uJrE9IZY= +github.com/smartcontractkit/chain-selectors v1.0.89/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e h1:jtHLhpl3lP5oZBB73ImW2MHGr+IbQtAW9euiidPJF+w= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e/go.mod h1:13YN2kb3Vqpw2S7d4IwhX/578WPGC0JHN5JrOnAEsOc= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= +github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20260213154618-c188380529d4 h1:PTXqPX4/i2MjN4j9m6XO1M1XVSML8ukzxkSsJNTPkrc= +github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20260213154618-c188380529d4/go.mod h1:X+515dSSjIgr2C3urPuwJAOmyPsnGsV1Smoghbs0304= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe h1:Vc4zoSc/j6/FdCQ7vcyHTTB7kzHI2f+lHCHqFuiCcJQ= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= +github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= +github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY= +github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b h1:36knUpKHHAZ86K4FGWXtx8i/EQftGdk2bqCoEu/Cha8= +github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b/go.mod h1:dkR2uYg9XYJuT1JASkPzWE51jjFkVb86P7a/yXe5/GM= +github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9Mww35LrufCdM9wtS9yVi/rEWGI1UnjHbcKKU0nVY= +github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250220133800-f3b940c4f298 h1:PKiqnVOTChlH4a4ljJKL3OKGRgYfIpJS4YD1daAIKks= -github.com/smartcontractkit/libocr v0.0.0-20250220133800-f3b940c4f298/go.mod h1:Mb7+/LC4edz7HyHxX4QkE42pSuov4AV68+AxBXAap0o= +github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d h1:LokA9PoCNb8mm8mDT52c3RECPMRsGz1eCQORq+J3n74= +github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -364,46 +377,48 @@ github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= -go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= -go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= -go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 h1:06ZeJRe5BnYXceSM9Vya83XXVaNGe3H1QqsvqRANQq8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2/go.mod h1:DvPtKE63knkDVP88qpatBj81JxN+w1bqfVbsbCbj1WY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 h1:tPLwQlXbJ8NSOfZc4OkgU5h2A38M4c9kfHSVc4PFQGs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2/go.mod h1:QTnxBwT/1rBIgAG1goq6xMydfYOBKU6KTiYF4fp5zL8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 h1:zwdo1gS2eH26Rg+CoqVQpEK1h8gvt5qyU5Kk5Bixvow= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0/go.mod h1:rUKCPscaRWWcqGT6HnEmYrK+YNe5+Sw64xgQTOJ5b30= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 h1:gAU726w9J8fwr4qRDqu1GYMNNs4gXrU+Pv20/N1UpB4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0/go.mod h1:RboSDkp7N292rgu+T0MgVt2qgFGu6qa1RpZDOtpL76w= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.13.0 h1:yEX3aC9KDgvYPhuKECHbOlr5GLwH6KTjLJ1sBSkkxkc= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.13.0/go.mod h1:/GXR0tBmmkxDaCUGahvksvp66mx4yh5+cFXgSlhg0vQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1xzhKrotaHy3/KXdPhlWARrCgK+eqUY= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 h1:G8Xec/SgZQricwWBJF/mHZc7A02YHedfFDENwJEdRA0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0/go.mod h1:PD57idA/AiFD5aqoxGxCvT/ILJPeHy3MjqU/NS7KogY= +go.opentelemetry.io/otel/log v0.15.0 h1:0VqVnc3MgyYd7QqNVIldC3dsLFKgazR6P3P3+ypkyDY= +go.opentelemetry.io/otel/log v0.15.0/go.mod h1:9c/G1zbyZfgu1HmQD7Qj84QMmwTp2QCQsZH1aeoWDE4= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/log v0.15.0 h1:WgMEHOUt5gjJE93yqfqJOkRflApNif84kxoHWS9VVHE= +go.opentelemetry.io/otel/sdk/log v0.15.0/go.mod h1:qDC/FlKQCXfH5hokGsNg9aUBGMJQsrUyeOiW5u+dKBQ= +go.opentelemetry.io/otel/sdk/log/logtest v0.13.0 h1:9yio6AFZ3QD9j9oqshV1Ibm9gPLlHNxurno5BreMtIA= +go.opentelemetry.io/otel/sdk/log/logtest v0.13.0/go.mod h1:QOGiAJHl+fob8Nu85ifXfuQYmJTFAvcrxL6w5/tu168= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= +go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -419,8 +434,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -433,11 +448,11 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= +golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= +golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -448,8 +463,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -465,8 +480,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -475,8 +490,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -505,10 +520,10 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 h1:O1cMQHRfwNpDfDJerqRoE2oD+AFlyid87D40L/OkkJo= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -525,10 +540,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -545,8 +560,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -555,25 +570,25 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= -gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto/googleapis/api v0.0.0-20250219182151-9fdb1cabc7b2 h1:35ZFtrCgaAjF7AFAK0+lRSf+4AyYnWRbH7og13p7rZ4= -google.golang.org/genproto/googleapis/api v0.0.0-20250219182151-9fdb1cabc7b2/go.mod h1:W9ynFDP/shebLB1Hl/ESTOap2jHd6pmLXPNZC7SVDbA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE= +google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda h1:i/Q+bfisr7gq6feoJnS/DlpdwEL4ihp41fvRiM3Ork0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -585,8 +600,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/relayer/aptos_service.go b/relayer/aptos_service.go new file mode 100644 index 000000000..9aa037ff2 --- /dev/null +++ b/relayer/aptos_service.go @@ -0,0 +1,281 @@ +package relayer + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "time" + + aptosgosdk "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + "github.com/smartcontractkit/chainlink-aptos/relayer/chain" + "github.com/smartcontractkit/chainlink-aptos/relayer/utils" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + commonaptos "github.com/smartcontractkit/chainlink-common/pkg/types/chains/aptos" +) + +type aptosService struct { + commontypes.UnimplementedAptosService + chain chain.Chain + logger logger.Logger +} + +func (s *aptosService) AccountAPTBalance(ctx context.Context, req commonaptos.AccountAPTBalanceRequest) (*commonaptos.AccountAPTBalanceReply, error) { + client, err := s.chain.GetClient() + if err != nil { + return nil, fmt.Errorf("failed to get client: %w", err) + } + sdkAddr := aptosgosdk.AccountAddress(req.Address[:]) + reply, err := client.AccountAPTBalance(sdkAddr) + if err != nil { + return nil, fmt.Errorf("failed to get account APT balance: %w", err) + } + return &commonaptos.AccountAPTBalanceReply{Value: reply}, nil +} + +func (s *aptosService) View(ctx context.Context, req commonaptos.ViewRequest) (*commonaptos.ViewReply, error) { + if req.Payload == nil { + return nil, fmt.Errorf("view payload is required") + } + + client, err := s.chain.GetClient() + if err != nil { + return nil, fmt.Errorf("failed to get client: %w", err) + } + + sdkPayload := &aptosgosdk.ViewPayload{ + Module: aptosgosdk.ModuleId{ + Address: aptosgosdk.AccountAddress(req.Payload.Module.Address), + Name: req.Payload.Module.Name, + }, + Function: req.Payload.Function, + ArgTypes: convertTypeTagsToSDK(req.Payload.ArgTypes), + Args: req.Payload.Args, + } + + result, err := client.View(sdkPayload) + if err != nil { + return nil, fmt.Errorf("failed to call view function: %w", err) + } + + data, err := json.Marshal(result) + if err != nil { + return nil, fmt.Errorf("failed to marshal view result: %w", err) + } + + return &commonaptos.ViewReply{Data: data}, nil +} + +func (s *aptosService) TransactionByHash(ctx context.Context, req commonaptos.TransactionByHashRequest) (*commonaptos.TransactionByHashReply, error) { + client, err := s.chain.GetClient() + if err != nil { + return nil, fmt.Errorf("failed to get client: %w", err) + } + + tx, err := client.TransactionByHash(req.Hash) + if err != nil { + return nil, fmt.Errorf("failed to get transaction by hash: %w", err) + } + + data, err := json.Marshal(tx.Inner) + if err != nil { + return nil, fmt.Errorf("failed to marshal transaction data: %w", err) + } + + return &commonaptos.TransactionByHashReply{ + Transaction: &commonaptos.Transaction{ + Type: commonaptos.TransactionVariant(tx.Type), + Hash: string(tx.Hash()), + Version: tx.Version(), + Success: tx.Success(), + Data: data, + }, + }, nil +} + +func (s *aptosService) SubmitTransaction(ctx context.Context, req commonaptos.SubmitTransactionRequest) (*commonaptos.SubmitTransactionReply, error) { + // Deserialize the BCS-encoded TransactionPayload (containing an EntryFunction) + var txPayload aptosgosdk.TransactionPayload + if err := bcs.Deserialize(&txPayload, req.EncodedPayload); err != nil { + return nil, fmt.Errorf("failed to deserialize transaction payload: %w", err) + } + + entryFn, ok := txPayload.Payload.(*aptosgosdk.EntryFunction) + if !ok { + return nil, fmt.Errorf("expected EntryFunction payload, got %T", txPayload.Payload) + } + + // Get sender info from workflow config + wfCfg := s.chain.Config().Workflow + if wfCfg == nil { + return nil, fmt.Errorf("workflow config is required for SubmitTransaction") + } + + txID := fmt.Sprintf("aptos-service-%d", time.Now().UnixNano()) + + gasLimit := big.NewInt(int64(req.GasConfig.MaxGasAmount)) + accounts, err := s.chain.KeyStore().Accounts(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get accounts: %w", err) + } + + if len(accounts) == 0 { + return nil, errors.New("no enabled accounts available") + } + + // Find account with highest balance + publicKey, err := s.getAccountWithHighestBalance(ctx, accounts) + if err != nil { + return nil, fmt.Errorf("failed to determine account for SubmitTransaction: %w", err) + } + err = s.chain.TxManager().EnqueueCRE( + "", + &commontypes.TxMeta{ + GasLimit: gasLimit, + }, + "", // fromAddress derived from publicKey + publicKey, + entryFn, + true, // simulateTx + ) + if err != nil { + return nil, fmt.Errorf("failed to enqueue transaction: %w", err) + } + + // Poll TxManager for status until terminal + var txStatus commontypes.TransactionStatus + for { + txStatus, err = s.chain.TxManager().GetStatus(txID) + if err != nil { + return nil, fmt.Errorf("failed to get transaction status: %w", err) + } + + switch txStatus { + case commontypes.Finalized: + return &commonaptos.SubmitTransactionReply{ + PendingTransaction: &commonaptos.PendingTransaction{ + Hash: txID, + }, + }, nil + case commontypes.Failed, commontypes.Fatal: + return nil, fmt.Errorf("transaction failed with status: %v", txStatus) + case commontypes.Pending, commontypes.Unknown, commontypes.Unconfirmed: + // still in progress, wait and retry + select { + case <-ctx.Done(): + return nil, fmt.Errorf("context cancelled while waiting for transaction: %w", ctx.Err()) + case <-time.After(500 * time.Millisecond): + continue + } + default: + return nil, fmt.Errorf("unexpected transaction status: %v", txStatus) + } + } +} + +// getAccountWithHighestBalance returns the public key of the account with the highest APT balance. +func (s *aptosService) getAccountWithHighestBalance(ctx context.Context, accounts []string) (string, error) { + if len(accounts) == 0 { + return "", errors.New("no accounts provided") + } + if len(accounts) == 1 { + s.logger.Debugw("only one enabled account for chain", "account", accounts[0]) + return accounts[0], nil + } + + client, err := s.chain.GetClient() + if err != nil { + return "", fmt.Errorf("failed to get client: %w", err) + } + + var highestBalance uint64 + var selectedAccount string + var foundAny bool + + for _, account := range accounts { + addr, err := utils.HexPublicKeyToAddress(account) + if err != nil { + s.logger.Warnw("failed to convert public key to address, skipping", "account", account, "error", err) + continue + } + + balance, err := client.AccountAPTBalance(addr) + if err != nil { + s.logger.Warnw("failed to get balance for account, skipping", "account", account, "address", addr.String(), "error", err) + continue + } + + if !foundAny || balance > highestBalance { + highestBalance = balance + selectedAccount = account + foundAny = true + } + } + + if !foundAny { + // Fallback to first account if all balance queries failed + return accounts[0], nil + } + + s.logger.Debugw("selected account with highest balance for chain", + "account", selectedAccount, + "balance", highestBalance, + "totalAccounts", len(accounts)) + + return selectedAccount, nil +} + +// convertTypeTagsToSDK converts common TypeTags to SDK TypeTags. +func convertTypeTagsToSDK(tags []commonaptos.TypeTag) []aptosgosdk.TypeTag { + out := make([]aptosgosdk.TypeTag, len(tags)) + for i, tag := range tags { + out[i] = aptosgosdk.TypeTag{Value: convertTypeTagImplToSDK(tag.Value)} + } + return out +} + +func convertTypeTagImplToSDK(impl commonaptos.TypeTagImpl) aptosgosdk.TypeTagImpl { + switch v := impl.(type) { + case commonaptos.BoolTag: + return &aptosgosdk.BoolTag{} + case commonaptos.U8Tag: + return &aptosgosdk.U8Tag{} + case commonaptos.U16Tag: + return &aptosgosdk.U16Tag{} + case commonaptos.U32Tag: + return &aptosgosdk.U32Tag{} + case commonaptos.U64Tag: + return &aptosgosdk.U64Tag{} + case commonaptos.U128Tag: + return &aptosgosdk.U128Tag{} + case commonaptos.U256Tag: + return &aptosgosdk.U256Tag{} + case commonaptos.AddressTag: + return &aptosgosdk.AddressTag{} + case commonaptos.SignerTag: + return &aptosgosdk.SignerTag{} + case commonaptos.VectorTag: + return &aptosgosdk.VectorTag{ + TypeParam: aptosgosdk.TypeTag{Value: convertTypeTagImplToSDK(v.ElementType.Value)}, + } + case commonaptos.StructTag: + typeParams := make([]aptosgosdk.TypeTag, len(v.TypeParams)) + for i, tp := range v.TypeParams { + typeParams[i] = aptosgosdk.TypeTag{Value: convertTypeTagImplToSDK(tp.Value)} + } + return &aptosgosdk.StructTag{ + Address: aptosgosdk.AccountAddress(v.Address), + Module: v.Module, + Name: v.Name, + TypeParams: typeParams, + } + case commonaptos.GenericTag: + return &aptosgosdk.GenericTag{Num: uint64(v.Index)} + default: + return nil + } +} diff --git a/relayer/chain/chain.go b/relayer/chain/chain.go index 816f70bb5..781e905ea 100644 --- a/relayer/chain/chain.go +++ b/relayer/chain/chain.go @@ -39,6 +39,7 @@ type Chain interface { TxManager() *txm.AptosTxm LogPoller() *logpoller.AptosLogPoller GetClient() (aptos.AptosRpcClient, error) + KeyStore() loop.Keystore } type ChainOpts struct { @@ -73,10 +74,11 @@ var _ Chain = (*chain)(nil) type chain struct { starter commonutils.StartStopOnce - id string - cfg *config.TOMLConfig - lggr logger.Logger - ds sqlutil.DataSource + id string + cfg *config.TOMLConfig + lggr logger.Logger + ds sqlutil.DataSource + keyStore loop.Keystore // Sub-services txm *txm.AptosTxm @@ -113,10 +115,11 @@ func newChain(cfg *config.TOMLConfig, loopKs loop.Keystore, lggr logger.Logger, } ch := &chain{ - id: cfg.ChainID, - cfg: cfg, - lggr: logger.Named(lggr, "Chain"), - ds: ds, + id: cfg.ChainID, + cfg: cfg, + lggr: logger.Named(lggr, "Chain"), + ds: ds, + keyStore: loopKs, } getClient := func() (aptos.AptosRpcClient, error) { @@ -173,6 +176,10 @@ func (c *chain) ChainID() string { return c.id } +func (c *chain) KeyStore() loop.Keystore { + return c.keyStore +} + // GetClient returns a client, randomly selecting one from available and valid nodes func (c *chain) GetClient() (aptos.AptosRpcClient, error) { var node *config.Node @@ -362,6 +369,15 @@ func nodeStatus(n *config.Node, id string) (types.NodeStatus, error) { return s, nil } +func (c *chain) GetChainInfo(_ context.Context) (types.ChainInfo, error) { + return types.ChainInfo{ + FamilyName: config.ChainFamilyName, + ChainID: c.id, + NetworkName: c.cfg.NetworkName, + NetworkNameFull: c.cfg.NetworkNameFull, + }, nil +} + func (c *chain) chainInfo() rtypes.ChainInfo { return rtypes.ChainInfo{ ChainFamilyName: config.ChainFamilyName, diff --git a/relayer/relay.go b/relayer/relay.go index 119b90e1c..e92adfe43 100644 --- a/relayer/relay.go +++ b/relayer/relay.go @@ -21,6 +21,7 @@ import ( ) var _ types.Relayer = (*relayer)(nil) //nolint:staticcheck +var _ types.AptosService = (*relayer)(nil) type relayer struct { chain chain.Chain @@ -28,11 +29,13 @@ type relayer struct { starter utils.StartStopOnce stopCh services.StopChan + aptosService } func NewRelayer(lggr logger.Logger, chain chain.Chain, capRegistry core.CapabilitiesRegistry) (*relayer, error) { ctx := context.TODO() + // CAN I REMOVE THIS ? if chain.Config().Workflow != nil { capability, err := write_target.NewAptosWriteTarget(ctx, chain, lggr) if err != nil { @@ -49,6 +52,10 @@ func NewRelayer(lggr logger.Logger, chain chain.Chain, capRegistry core.Capabili chain: chain, lggr: lggr, stopCh: make(chan struct{}), + aptosService: aptosService{ + chain: chain, + logger: lggr, + }, }, nil } @@ -162,10 +169,22 @@ func (r *relayer) NewCCIPExecProvider(ctx context.Context, rargs types.RelayArgs return nil, errors.New("ccip.exec is not supported for aptos") } +func (r *relayer) NewCCIPProvider(ctx context.Context, cargs types.CCIPProviderArgs) (types.CCIPProvider, error) { + return nil, errors.New("ccip provider is not supported for aptos") +} + func (r *relayer) EVM() (types.EVMService, error) { return nil, errors.New("EVMService is not supported for aptos") } +func (r *relayer) Solana() (types.SolanaService, error) { + return nil, errors.New("SolanaService is not supported for aptos") +} + +func (r *relayer) TON() (types.TONService, error) { + return nil, errors.New("TONService is not supported for aptos") +} + func (r *relayer) Replay(ctx context.Context, fromBlock string, args map[string]any) error { return errors.ErrUnsupported } @@ -186,3 +205,11 @@ func (r *relayer) ListNodeStatuses(ctx context.Context, pageSize int32, pageToke func (r *relayer) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error { return r.chain.Transact(ctx, from, to, amount, balanceCheck) } + +func (r *relayer) Aptos() (types.AptosService, error) { + return r, nil +} + +func (r *relayer) GetChainInfo(ctx context.Context) (types.ChainInfo, error) { + return r.chain.GetChainInfo(ctx) +} diff --git a/relayer/testutils/keystore.go b/relayer/testutils/keystore.go index be2489a70..56557a7e4 100644 --- a/relayer/testutils/keystore.go +++ b/relayer/testutils/keystore.go @@ -49,3 +49,7 @@ func (tk *TestKeystore) Accounts(ctx context.Context) ([]string, error) { } return accounts, nil } + +func (tk *TestKeystore) Decrypt(ctx context.Context, id string, encrypted []byte) ([]byte, error) { + return nil, nil +} diff --git a/relayer/txm/txm.go b/relayer/txm/txm.go index fe8e18aff..c94ae677c 100644 --- a/relayer/txm/txm.go +++ b/relayer/txm/txm.go @@ -226,6 +226,97 @@ func (a *AptosTxm) Enqueue(transactionID string, txMetadata *commontypes.TxMeta, return nil } +// EnqueueCRE is like Enqueue but accepts a deserialized EntryFunction directly, +// skipping the string-based function parsing and BCS serialisation of parameters. +// The EntryFunction already contains the module, function name, type tags, and +// pre-encoded BCS args. +func (a *AptosTxm) EnqueueCRE(transactionID string, txMetadata *commontypes.TxMeta, fromAddress, publicKey string, entryFunction *aptos.EntryFunction, simulateTx bool) error { + if entryFunction == nil { + return errors.New("entry function is required") + } + + if transactionID == "" { + transactionID = uuid.New().String() + } else { + a.transactionsLock.Lock() + _, transactionExists := a.transactions[transactionID] + a.transactionsLock.Unlock() + if transactionExists { + return errors.New("transaction already exists") + } + } + + ctxLogger := GetContexedTxLogger(a.baseLogger, transactionID, txMetadata) + + ed25519PublicKey, err := utils.HexPublicKeyToEd25519PublicKey(publicKey) + if err != nil { + return fmt.Errorf("failed to convert public key: %+w", err) + } + + if fromAddress == "" { + // If the address is not specified, we assume the public key is for its corresponding address + // and not for an address with a rotated authentication key. + acc := utils.Ed25519PublicKeyToAddress(ed25519PublicKey) + fromAddress = acc.String() + } + + fromAccountAddress := &aptos.AccountAddress{} + err = fromAccountAddress.ParseStringRelaxed(fromAddress) + if err != nil { + return fmt.Errorf("failed to parse from address: %+w", err) + } + + currentTimestamp := getTimestampSecs() + tx := &AptosTx{ + ID: transactionID, + Metadata: txMetadata, + Timestamp: currentTimestamp, + FromAddress: *fromAccountAddress, + PublicKey: ed25519PublicKey, + ContractAddress: entryFunction.Module.Address, + ModuleName: entryFunction.Module.Name, + FunctionName: entryFunction.Function, + TypeTags: entryFunction.ArgTypes, + BcsValues: entryFunction.Args, + Status: commontypes.Pending, + Simulate: simulateTx, + } + + a.transactionsLock.Lock() + if (currentTimestamp - a.transactionsLastPruneTime) > a.config.PruneIntervalSecs { + for txID, tx := range a.transactions { + if tx.Status != commontypes.Finalized && tx.Status != commontypes.Failed && tx.Status != commontypes.Fatal { + continue + } + if (currentTimestamp - tx.Timestamp) < a.config.PruneTxExpirationSecs { + continue + } + ctxLogger.Debugw("Pruning transaction", "status", tx.Status) + delete(a.transactions, txID) + } + a.transactionsLastPruneTime = currentTimestamp + } + a.transactions[transactionID] = tx + a.transactionsLock.Unlock() + + select { + case a.broadcastChan <- transactionID: + ctxLogger.Debugw("Tx enqueued", "fromAddr", fromAddress) + default: + // if the channel is full, we drop the transaction. + // we do this instead of setting the tx in `a.transactions` post-broadcast to avoid a race + // with the broadcastLoop, which expects to find the tx in `a.transactions` upon reception of + // the id. + a.transactionsLock.Lock() + delete(a.transactions, transactionID) + a.transactionsLock.Unlock() + + return fmt.Errorf("failed to enqueue tx: %+v", tx) + } + + return nil +} + func (a *AptosTxm) GetStatus(transactionID string) (commontypes.TransactionStatus, error) { if transactionID == "" { return commontypes.Unknown, errors.New("nil tx id") diff --git a/relayer/write_target/write_target_test.go b/relayer/write_target/write_target_test.go index 2baddd7a8..b502ac945 100644 --- a/relayer/write_target/write_target_test.go +++ b/relayer/write_target/write_target_test.go @@ -16,7 +16,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink-protos/cre/go/values" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" From 4283546b5ac52ad2828fe81ce62933173f483de7 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 12:11:40 +0000 Subject: [PATCH 02/12] Adding EnqueueCRE test, cannot run locally, trying on CI --- relayer/aptos_service.go | 7 ++-- relayer/txm/txm.go | 10 ++---- relayer/txm/txm_local_test.go | 61 +++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/relayer/aptos_service.go b/relayer/aptos_service.go index 9aa037ff2..1ca16ce89 100644 --- a/relayer/aptos_service.go +++ b/relayer/aptos_service.go @@ -10,6 +10,7 @@ import ( aptosgosdk "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs" + "github.com/google/uuid" "github.com/smartcontractkit/chainlink-aptos/relayer/chain" "github.com/smartcontractkit/chainlink-aptos/relayer/utils" @@ -115,8 +116,6 @@ func (s *aptosService) SubmitTransaction(ctx context.Context, req commonaptos.Su return nil, fmt.Errorf("workflow config is required for SubmitTransaction") } - txID := fmt.Sprintf("aptos-service-%d", time.Now().UnixNano()) - gasLimit := big.NewInt(int64(req.GasConfig.MaxGasAmount)) accounts, err := s.chain.KeyStore().Accounts(ctx) if err != nil { @@ -132,12 +131,12 @@ func (s *aptosService) SubmitTransaction(ctx context.Context, req commonaptos.Su if err != nil { return nil, fmt.Errorf("failed to determine account for SubmitTransaction: %w", err) } + txID := uuid.New().String() err = s.chain.TxManager().EnqueueCRE( - "", + txID, &commontypes.TxMeta{ GasLimit: gasLimit, }, - "", // fromAddress derived from publicKey publicKey, entryFn, true, // simulateTx diff --git a/relayer/txm/txm.go b/relayer/txm/txm.go index c94ae677c..04a6ffdd6 100644 --- a/relayer/txm/txm.go +++ b/relayer/txm/txm.go @@ -230,7 +230,7 @@ func (a *AptosTxm) Enqueue(transactionID string, txMetadata *commontypes.TxMeta, // skipping the string-based function parsing and BCS serialisation of parameters. // The EntryFunction already contains the module, function name, type tags, and // pre-encoded BCS args. -func (a *AptosTxm) EnqueueCRE(transactionID string, txMetadata *commontypes.TxMeta, fromAddress, publicKey string, entryFunction *aptos.EntryFunction, simulateTx bool) error { +func (a *AptosTxm) EnqueueCRE(transactionID string, txMetadata *commontypes.TxMeta, publicKey string, entryFunction *aptos.EntryFunction, simulateTx bool) error { if entryFunction == nil { return errors.New("entry function is required") } @@ -253,12 +253,8 @@ func (a *AptosTxm) EnqueueCRE(transactionID string, txMetadata *commontypes.TxMe return fmt.Errorf("failed to convert public key: %+w", err) } - if fromAddress == "" { - // If the address is not specified, we assume the public key is for its corresponding address - // and not for an address with a rotated authentication key. - acc := utils.Ed25519PublicKeyToAddress(ed25519PublicKey) - fromAddress = acc.String() - } + acc := utils.Ed25519PublicKeyToAddress(ed25519PublicKey) + fromAddress := acc.String() fromAccountAddress := &aptos.AccountAddress{} err = fromAccountAddress.ParseStringRelaxed(fromAddress) diff --git a/relayer/txm/txm_local_test.go b/relayer/txm/txm_local_test.go index 55b021b3b..5dab78688 100644 --- a/relayer/txm/txm_local_test.go +++ b/relayer/txm/txm_local_test.go @@ -152,6 +152,67 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string logger.Debugw("Counter value after test", "value", counterValue) require.Equal(t, expectedValue, counterValue) + + // submit all txs at once and wait for all afterwards + // helps testing reties and failure recoveries + var txIDsCRE []string + + for i := 0; i < iterations; i++ { + incrementId := uuid.New().String() + err := txm.EnqueueCRE( + incrementId, + getSampleTxMetadata(), + publicKeyHex, + &aptos.EntryFunction{ + Module: aptos.ModuleId{ + Address: accountAddress, + Name: "counter", + }, + Function: "counter::increment", + ArgTypes: []aptos.TypeTag{}, + Args: [][]byte{ + []byte(accountAddress.String()), + }, + }, + true, + ) + require.NoError(t, err) + expectedValue += 1 + txIDsCRE = append(txIDsCRE, incrementId) + + incrementMultId := uuid.New().String() + err = txm.EnqueueCRE( + incrementMultId, + getSampleTxMetadata(), + publicKeyHex, + &aptos.EntryFunction{ + Module: aptos.ModuleId{ + Address: accountAddress, + Name: "counter", + }, + Function: "counter::increment_mult", + ArgTypes: []aptos.TypeTag{}, + Args: [][]byte{ + []byte(accountAddress.String()), + []byte(big.NewInt(3).Bytes()), + []byte(big.NewInt(4).Bytes()), + }, + }, + true, + ) + require.NoError(t, err) + expectedValue += 3 * 4 + txIDsCRE = append(txIDsCRE, incrementMultId) + } + + for _, txId := range txIDs { + waitForTxmId(t, txm, txId, time.Minute*2) + } + + counterValueCRE := testutils.ReadCounterValue(t, client, accountAddress) + logger.Debugw("Counter value after test", "value", counterValueCRE) + + require.Equal(t, expectedValue, counterValueCRE) } func deployTestModule(t *testing.T, txm *AptosTxm, fromAddress aptos.AccountAddress, publicKeyHex string) { From 3ce182f4f6425b3f2f722d833158b8454208b9e9 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 12:22:16 +0000 Subject: [PATCH 03/12] tidy --- relayer/chain/chain.go | 9 --------- relayer/relay.go | 4 ++++ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/relayer/chain/chain.go b/relayer/chain/chain.go index be09ad5b4..9ae975ce6 100644 --- a/relayer/chain/chain.go +++ b/relayer/chain/chain.go @@ -375,15 +375,6 @@ func nodeStatus(n *config.Node, id string) (types.NodeStatus, error) { return s, nil } -func (c *chain) GetChainInfo(_ context.Context) (types.ChainInfo, error) { - return types.ChainInfo{ - FamilyName: config.ChainFamilyName, - ChainID: c.id, - NetworkName: c.cfg.NetworkName, - NetworkNameFull: c.cfg.NetworkNameFull, - }, nil -} - func (c *chain) chainInfo() rtypes.ChainInfo { return rtypes.ChainInfo{ ChainFamilyName: config.ChainFamilyName, diff --git a/relayer/relay.go b/relayer/relay.go index 5733371d9..875b2dd31 100644 --- a/relayer/relay.go +++ b/relayer/relay.go @@ -63,6 +63,10 @@ func (r *relayer) Name() string { return r.lggr.Name() } +func (r *relayer) Replay(ctx context.Context, fromBlock string, args map[string]any) error { + return errors.ErrUnsupported +} + // Start starts the relayer respecting the given context. func (r *relayer) Start(ctx context.Context) error { return r.starter.StartOnce("AptosRelayer", func() error { From 55d4e2cc3118f3db35f869aa7f118c772b30ffa2 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 12:31:59 +0000 Subject: [PATCH 04/12] tidy --- integration-tests/go.mod | 4 ++-- integration-tests/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bfd499a5e..01889315e 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -14,7 +14,7 @@ require ( github.com/rs/zerolog v1.34.0 github.com/smartcontractkit/chain-selectors v1.0.89 github.com/smartcontractkit/chainlink-aptos v0.0.0-20251212131933-e5e85d6fa4d3 - github.com/smartcontractkit/chainlink-common v0.9.6-0.20260209153333-67bf1aaa3e1e + github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e github.com/smartcontractkit/chainlink-deployments-framework v0.74.2 github.com/smartcontractkit/chainlink-testing-framework/framework v0.13.0 github.com/smartcontractkit/chainlink/core/scripts v0.0.0-20260114190217-6f3f008c67a6 @@ -348,7 +348,7 @@ require ( github.com/smartcontractkit/chainlink-protos/chainlink-ccv/committee-verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260206000552-087e235a7963 // indirect + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0 // indirect github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b28a2ce1e..38acadee7 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1307,8 +1307,8 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20251222203705-84e9 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20251222203705-84e93cab86b5/go.mod h1:kDMTKjZB4pnhQVAdwVMzA0THXAxjaON58JSO+CYLYBg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260106165728-3d896e87cc56 h1:M6eS2r11Vbbll/bve5Us17cNYDlgs+dvrggPFVnhrgQ= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260106165728-3d896e87cc56/go.mod h1:6N8NSPmsy+sxtRBmBUwWlDyxPyauS7HMDzUl/lyJw7Y= -github.com/smartcontractkit/chainlink-common v0.9.6-0.20260209153333-67bf1aaa3e1e h1:3zBkN2h2JzgjEntuV/YqqqCC9vNrBdwC5/FKfJi+1G8= -github.com/smartcontractkit/chainlink-common v0.9.6-0.20260209153333-67bf1aaa3e1e/go.mod h1:TDyLV7/Y+lnZegvfeZXj5myOG0cKrsmuGnJ8OQQuPWo= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e h1:jtHLhpl3lP5oZBB73ImW2MHGr+IbQtAW9euiidPJF+w= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e/go.mod h1:13YN2kb3Vqpw2S7d4IwhX/578WPGC0JHN5JrOnAEsOc= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 h1:NOUsjsMzNecbjiPWUQGlRSRAutEvCFrqqyETDJeh5q4= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4/go.mod h1:Zpvul9sTcZNAZOVzt5vBl1XZGNvQebFpnpn3/KOQvOQ= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= @@ -1341,8 +1341,8 @@ github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0. github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d/go.mod h1:ATjAPIVJibHRcIfiG47rEQkUIOoYa6KDvWj3zwCAw6g= github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d h1:AJy55QJ/pBhXkZjc7N+ATnWfxrcjq9BI9DmdtdjwDUQ= github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d/go.mod h1:5JdppgngCOUS76p61zCinSCgOhPeYQ+OcDUuome5THQ= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260206000552-087e235a7963 h1:DCLvEn4KkFzYbK/AYl4vJmf6EHaskPYvGDGdd0kOma0= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260206000552-087e235a7963/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe h1:Vc4zoSc/j6/FdCQ7vcyHTTB7kzHI2f+lHCHqFuiCcJQ= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0 h1:xHPmFDhff7QpeFxKsZfk+24j4AlnQiFjjRh5O87Peu4= github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= From c7c93d0a1dca642d9c50952b9853540573fca411 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 13:17:15 +0000 Subject: [PATCH 05/12] function name --- relayer/txm/txm_local_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relayer/txm/txm_local_test.go b/relayer/txm/txm_local_test.go index 5dab78688..abcd7c3d2 100644 --- a/relayer/txm/txm_local_test.go +++ b/relayer/txm/txm_local_test.go @@ -168,7 +168,7 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string Address: accountAddress, Name: "counter", }, - Function: "counter::increment", + Function: "increment", ArgTypes: []aptos.TypeTag{}, Args: [][]byte{ []byte(accountAddress.String()), @@ -190,7 +190,7 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string Address: accountAddress, Name: "counter", }, - Function: "counter::increment_mult", + Function: "increment_mult", ArgTypes: []aptos.TypeTag{}, Args: [][]byte{ []byte(accountAddress.String()), From 9bee276932dae5836e29e92360c7babed053fdeb Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 13:42:02 +0000 Subject: [PATCH 06/12] wait for cre txs --- relayer/txm/txm_local_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/txm/txm_local_test.go b/relayer/txm/txm_local_test.go index abcd7c3d2..d532076f0 100644 --- a/relayer/txm/txm_local_test.go +++ b/relayer/txm/txm_local_test.go @@ -205,7 +205,7 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string txIDsCRE = append(txIDsCRE, incrementMultId) } - for _, txId := range txIDs { + for _, txId := range txIDsCRE { waitForTxmId(t, txm, txId, time.Minute*2) } From aafdb92d0890e407174c89d432d641fd3e84eddc Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 14:07:51 +0000 Subject: [PATCH 07/12] adding serialised params --- relayer/txm/txm_local_test.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/relayer/txm/txm_local_test.go b/relayer/txm/txm_local_test.go index d532076f0..ff2fa3034 100644 --- a/relayer/txm/txm_local_test.go +++ b/relayer/txm/txm_local_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/google/uuid" "github.com/stretchr/testify/require" "golang.org/x/crypto/sha3" @@ -157,6 +158,14 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string // helps testing reties and failure recoveries var txIDsCRE []string + accountBytes, err := bcs.Serialize(&accountAddress) + require.NoError(t, err) + + threeBytes, err := bcs.SerializeU64(3) + require.NoError(t, err) + fourBytes, err := bcs.SerializeU64(4) + require.NoError(t, err) + for i := 0; i < iterations; i++ { incrementId := uuid.New().String() err := txm.EnqueueCRE( @@ -171,7 +180,7 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string Function: "increment", ArgTypes: []aptos.TypeTag{}, Args: [][]byte{ - []byte(accountAddress.String()), + accountBytes, }, }, true, @@ -193,9 +202,9 @@ func runTxmTest(t *testing.T, logger logger.Logger, config Config, rpcURL string Function: "increment_mult", ArgTypes: []aptos.TypeTag{}, Args: [][]byte{ - []byte(accountAddress.String()), - []byte(big.NewInt(3).Bytes()), - []byte(big.NewInt(4).Bytes()), + accountBytes, + threeBytes, + fourBytes, }, }, true, From e180775e1fb584dc5c5980b1b2c59c0c94cda0ae Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Tue, 17 Feb 2026 20:21:21 +0000 Subject: [PATCH 08/12] clean --- LOOP_ARCHITECTURE.md | 312 +++++++++++++++++++++++++++++++++++++++ relayer/aptos_service.go | 6 - 2 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 LOOP_ARCHITECTURE.md diff --git a/LOOP_ARCHITECTURE.md b/LOOP_ARCHITECTURE.md new file mode 100644 index 000000000..f9378d09c --- /dev/null +++ b/LOOP_ARCHITECTURE.md @@ -0,0 +1,312 @@ +# LOOP Architecture: Relayer vs RelayerSet + +Understanding the two different gRPC boundaries in the Chainlink LOOP architecture. + +## Overview + +There are **two separate gRPC boundaries** where chain-specific services (like Aptos) need to be implemented: + +1. **Relayer LOOP**: When an individual relayer runs as a separate process +2. **RelayerSet for Capabilities**: When capabilities run as separate processes and need to call back to relayers + +## Architecture Diagram + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Core Node Process │ +│ │ +│ ┌──────────────┐ │ +│ │ Relayer Set │ ◄─────────────────┐ │ +│ │ - EVM │ │ │ +│ │ - Solana │ │ │ +│ │ - Aptos │ │ │ +│ └──────────────┘ │ │ +│ │ │ │ +│ │ Embedded Mode │ LOOP Mode │ +│ ▼ │ │ +│ ┌──────────────┐ ┌─────┴──────┐ │ +│ │ Relayer │ │ RelayerSet │ │ +│ │ Logic │ │ Server │ │ +│ └──────────────┘ └─────┬──────┘ │ +│ │ │ +└──────────────────────────────────────┼──────────────────────┘ + │ gRPC + ┌──────────────────┼──────────────────────┐ + │ │ │ + ┌─────▼──────┐ ┌─────▼──────┐ │ + │ Capability │ │ Capability │ │ + │ Process 1 │ │ Process 2 │ │ + │ │ │ │ │ + │ ┌────────┐ │ │ ┌────────┐ │ │ + │ │Relayer │ │ │ │Relayer │ │ │ + │ │ Set │ │ │ │ Set │ │ │ + │ │ Client │ │ │ │ Client │ │ │ + │ └────────┘ │ │ └────────┘ │ │ + └────────────┘ └────────────┘ │ + │ + Capability Processes (LOOP Mode) │ + │ +└─────────────────────────────────────────────────────────────┘ +``` + +## The Two Packages + +### 1. `pkg/loop/internal/relayer/` - Standalone Relayer LOOP + +**Location**: `chainlink-common/pkg/loop/internal/relayer/aptos.go` + +**Purpose**: Allows a relayer to run as a separate LOOP process (optional feature). + +**Process Boundary**: +``` +Core Node ◄──[gRPC]──► Relayer Process (standalone) +``` + +**When Used**: +- When environment variable `CL_APTOS_PLUGIN_CMD` is set +- Relayer runs as external binary, not embedded in core node + +**Key Components**: + +```go +// AptosClient - Used by core node to call standalone relayer +type AptosClient struct { + grpcClient aptospb.AptosClient +} + +func (ac *AptosClient) AccountAPTBalance(ctx context.Context, req aptos.AccountAPTBalanceRequest) (*aptos.AccountAPTBalanceReply, error) { + // Convert Go types → Proto types + reply, err := ac.grpcClient.AccountAPTBalance(ctx, &aptospb.AccountAPTBalanceRequest{ + Address: req.Address[:], + }) + // Convert Proto types → Go types + return &aptos.AccountAPTBalanceReply{Value: reply.Value}, nil +} + +// aptosServer - Used by standalone relayer to receive calls +type aptosServer struct { + impl types.AptosService // Actual business logic +} + +func (s *aptosServer) AccountAPTBalance(ctx context.Context, req *aptospb.AccountAPTBalanceRequest) (*aptospb.AccountAPTBalanceReply, error) { + // Convert Proto types → Go types + reply, err := s.impl.AccountAPTBalance(ctx, aptos.AccountAPTBalanceRequest{ + Address: aptos.AccountAddress(req.Address), + }) + // Convert Go types → Proto types + return &aptospb.AccountAPTBalanceReply{Value: reply.Value}, nil +} +``` + +**Call Flow**: +``` +Core Node Logic + → AptosClient (proto conversion) + → [gRPC over network/pipe] + → aptosServer (proto conversion) + → Aptos Business Logic (in separate process) +``` + +--- + +### 2. `pkg/loop/internal/relayerset/` - RelayerSet for Capabilities + +**Location**: `chainlink-common/pkg/loop/internal/relayerset/aptos.go` + +**Purpose**: Allows capability processes to call back to relayers in the core node. + +**Process Boundary**: +``` +Capability Process ◄──[gRPC]──► Core Node (RelayerSet) +``` + +**When Used**: +- **Always** when capabilities run in LOOP mode +- Capability needs to call chain-specific functions +- Most common use case + +**Key Components**: + +```go +// aptosClient - Used by capability to call back to core node +// Adds RelayID to context so server knows which relayer to use +type aptosClient struct { + relayID types.RelayID // Which relayer? (e.g., "aptos.mainnet") + client aptospb.AptosClient +} + +func (ac *aptosClient) AccountAPTBalance(ctx context.Context, in *aptospb.AccountAPTBalanceRequest, opts ...grpc.CallOption) (*aptospb.AccountAPTBalanceReply, error) { + // Add RelayID to context metadata + ctx = appendRelayID(ctx, ac.relayID) + return ac.client.AccountAPTBalance(ctx, in, opts...) +} + +// aptosServer - Used by core node to receive calls from capabilities +type aptosServer struct { + parent *Server // Has access to RelayerSet +} + +func (as *aptosServer) AccountAPTBalance(ctx context.Context, req *aptospb.AccountAPTBalanceRequest) (*aptospb.AccountAPTBalanceReply, error) { + // Get the AptosService for the specific relayer + aptosService, err := as.parent.getAptosService(ctx) + + // Convert proto → Go types and call business logic + reply, err := aptosService.AccountAPTBalance(ctx, aptos.AccountAPTBalanceRequest{ + Address: aptos.AccountAddress(req.Address), + }) + + // Convert Go types → proto + return &aptospb.AccountAPTBalanceReply{Value: reply.Value}, nil +} + +// Helper to extract RelayID and get the right service +func (s *Server) getAptosService(ctx context.Context) (types.AptosService, error) { + relayID, err := readContextValue(ctx, metadataRelayID) + relayer, err := s.impl.Get(ctx, relayID) // Get specific relayer + return relayer.Aptos() // Get its Aptos service +} +``` + +**Call Flow**: +``` +Capability Logic + → aptosClient.AccountAPTBalance() [adds RelayID to context] + → [gRPC back to Core Node] + → RelayerSet Server + → Extract RelayID from context + → Get correct Aptos relayer from RelayerSet + → Call Aptos Business Logic +``` + +--- + +## Key Differences + +| Aspect | `relayer/` (Standalone Relayer) | `relayerset/` (Capability Callbacks) | +|--------|--------------------------------|-------------------------------------| +| **Process Boundary** | Core Node ↔ Relayer Process | Capability Process ↔ Core Node | +| **Direction** | Core calls relayer | Capability calls back to core | +| **RelayID Handling** | Not needed (single relayer) | Critical (multiple relayers) | +| **Client Purpose** | Proto conversion only | Add RelayID + forward call | +| **Server Purpose** | Call business logic directly | Find relayer + call its logic | +| **When Needed** | Optional (relayer LOOP mode) | Required (capability LOOP mode) | +| **Frequency of Use** | Rare (most relayers embedded) | Common (most capabilities LOOPified) | + +--- + +## Context Metadata Pattern + +The `relayerset` uses gRPC metadata to pass the `RelayID`: + +```go +// Client side: Add RelayID to context +func appendRelayID(ctx context.Context, relayID types.RelayID) context.Context { + return metadata.AppendToOutgoingContext(ctx, + metadataRelayID, relayID.String()) +} + +// Server side: Extract RelayID from context +func readContextValue(ctx context.Context, key string) (string, error) { + md, ok := metadata.FromIncomingContext(ctx) + values := md.Get(key) + return values[0], nil +} +``` + +This allows multiple relayers (EVM mainnet, Solana devnet, Aptos testnet, etc.) to share the same gRPC connection, with the server routing calls to the correct relayer based on metadata. + +--- + +## Which Package Do I Need? + +### For Most Implementations: Start with `relayerset/` + +If you're building a new chain integration (like Aptos), you'll almost certainly need `relayerset/` first because: + +1. ✅ Capabilities typically run in LOOP mode +2. ✅ Capabilities need to call chain-specific functions +3. ✅ This is the standard architecture for most chains + +### Optional: Add `relayer/` Later + +You only need `relayer/` if: + +1. You want the relayer itself to run as a separate process +2. You're isolating relayer logic for security/stability +3. You're implementing optional LOOP mode for relayers + +**Most chains only implement `relayerset/` initially.** + +--- + +## Implementation Order + +### Step 1: Proto + Types (Both packages share these) +1. Create `.proto` file: `pkg/chains/aptos/aptos.proto` +2. Create Go types: `pkg/types/chains/aptos/aptos.go` +3. Add interface: `pkg/types/relayer.go` +4. Run `make generate` to create gRPC stubs + +### Step 2: RelayerSet (Required for capabilities) +1. Create `pkg/loop/internal/relayerset/aptos.go` +2. Update `pkg/loop/internal/relayerset/server.go` +3. Update `pkg/loop/internal/relayerset/client.go` +4. Update `pkg/loop/internal/relayerset/relayer.go` +5. Register in `pkg/loop/internal/pb/relayerset/helper.go` + +### Step 3: Business Logic +1. Implement actual Aptos service in `chainlink-aptos/` +2. Connect to Aptos SDK/RPC + +### Step 4: Relayer LOOP (Optional) +1. Create `pkg/loop/internal/relayer/aptos.go` +2. Create standalone binary in `chainlink-aptos/cmd/` +3. Add environment variable support + +--- + +## Real-World Example + +### Capability Calling Aptos + +```go +// In capability process (e.g., WriteTarget capability) +func (w *WriteTarget) Execute(ctx context.Context, req capabilities.CapabilityRequest) { + // Get Aptos service from relayer set + aptosService, err := w.relayer.Aptos() + + // Call method - this goes over gRPC back to core node + balance, err := aptosService.AccountAPTBalance(ctx, + aptos.AccountAPTBalanceRequest{ + Address: accountAddr, + }) + + // Use result... +} +``` + +**What happens under the hood:** + +1. `w.relayer.Aptos()` returns an `aptosClient` wrapper +2. `AccountAPTBalance()` call: + - Adds RelayID ("aptos.mainnet") to context metadata + - Makes gRPC call back to core node +3. Core node's `aptosServer`: + - Extracts RelayID from metadata + - Finds Aptos mainnet relayer in RelayerSet + - Calls that relayer's `AccountAPTBalance()` +4. Result flows back through gRPC to capability + +--- + +## Summary + +- **`relayer/`**: For standalone relayer processes (optional, advanced) +- **`relayerset/`**: For capability-to-relayer calls (required, standard) + +**Most implementations only need `relayerset/` initially.** + +The key insight: gRPC boundaries can be in different places depending on what's LOOPified: +- If relayers are LOOPified → use `relayer/` +- If capabilities are LOOPified → use `relayerset/` ✅ (most common) + diff --git a/relayer/aptos_service.go b/relayer/aptos_service.go index 1ca16ce89..3ae06b93b 100644 --- a/relayer/aptos_service.go +++ b/relayer/aptos_service.go @@ -110,12 +110,6 @@ func (s *aptosService) SubmitTransaction(ctx context.Context, req commonaptos.Su return nil, fmt.Errorf("expected EntryFunction payload, got %T", txPayload.Payload) } - // Get sender info from workflow config - wfCfg := s.chain.Config().Workflow - if wfCfg == nil { - return nil, fmt.Errorf("workflow config is required for SubmitTransaction") - } - gasLimit := big.NewInt(int64(req.GasConfig.MaxGasAmount)) accounts, err := s.chain.KeyStore().Accounts(ctx) if err != nil { From 517566a85ace42d2860dba9a52265ffa47fb49d6 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Mon, 23 Feb 2026 10:31:45 +0000 Subject: [PATCH 09/12] wip --- go.mod | 4 +- go.sum | 8 ++-- integration-tests/go.mod | 4 +- integration-tests/go.sum | 8 ++-- relayer/aptos_service.go | 86 ++++++++++++++++++++++++++++------------ 5 files changed, 73 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index b017beb13..4a9c0e8af 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,8 @@ require ( github.com/prometheus/client_golang v1.22.0 github.com/shopspring/decimal v1.4.0 github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 - github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe + github.com/smartcontractkit/chainlink-common v0.10.1-0.20260218165451-e87d34b6ea14 + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260217103918-db5a4ede0b6f github.com/stretchr/testify v1.11.1 github.com/valyala/fastjson v1.6.4 go.opentelemetry.io/otel v1.39.0 diff --git a/go.sum b/go.sum index 729400860..19c9cd410 100644 --- a/go.sum +++ b/go.sum @@ -324,12 +324,12 @@ github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 h1:6C8qej6f github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82/go.mod h1:xe4pgH49k4SsmkQq5OT8abwhWmnzkhpgnXeekbx2efw= github.com/smartcontractkit/chain-selectors v1.0.89 h1:L9oWZGqQXWyTPnC6ODXgu3b0DFyLmJ9eHv+uJrE9IZY= github.com/smartcontractkit/chain-selectors v1.0.89/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= -github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e h1:jtHLhpl3lP5oZBB73ImW2MHGr+IbQtAW9euiidPJF+w= -github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e/go.mod h1:13YN2kb3Vqpw2S7d4IwhX/578WPGC0JHN5JrOnAEsOc= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260218165451-e87d34b6ea14 h1:k22Otc6zoXwV3C5bOU/UDXZqUUH0QTGvcjBl0xbyQ8c= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260218165451-e87d34b6ea14/go.mod h1:DOY8qT1C6yBA+lmJFijYdCSlUsrCKM00OG7Lenf92Xo= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe h1:Vc4zoSc/j6/FdCQ7vcyHTTB7kzHI2f+lHCHqFuiCcJQ= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260217103918-db5a4ede0b6f h1:wIi0g1zvEIIMe9fd6GNar0HzSGYr4bKPn4AGFhuHe3U= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260217103918-db5a4ede0b6f/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY= github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b h1:36knUpKHHAZ86K4FGWXtx8i/EQftGdk2bqCoEu/Cha8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 01889315e..cb189dee1 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -14,7 +14,7 @@ require ( github.com/rs/zerolog v1.34.0 github.com/smartcontractkit/chain-selectors v1.0.89 github.com/smartcontractkit/chainlink-aptos v0.0.0-20251212131933-e5e85d6fa4d3 - github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e + github.com/smartcontractkit/chainlink-common v0.10.1-0.20260218143149-f4e93991b518 github.com/smartcontractkit/chainlink-deployments-framework v0.74.2 github.com/smartcontractkit/chainlink-testing-framework/framework v0.13.0 github.com/smartcontractkit/chainlink/core/scripts v0.0.0-20260114190217-6f3f008c67a6 @@ -348,7 +348,7 @@ require ( github.com/smartcontractkit/chainlink-protos/chainlink-ccv/committee-verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe // indirect + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260217043601-5cc966896c4f // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0 // indirect github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 38acadee7..528a6684f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1307,8 +1307,8 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20251222203705-84e9 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20251222203705-84e93cab86b5/go.mod h1:kDMTKjZB4pnhQVAdwVMzA0THXAxjaON58JSO+CYLYBg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260106165728-3d896e87cc56 h1:M6eS2r11Vbbll/bve5Us17cNYDlgs+dvrggPFVnhrgQ= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260106165728-3d896e87cc56/go.mod h1:6N8NSPmsy+sxtRBmBUwWlDyxPyauS7HMDzUl/lyJw7Y= -github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e h1:jtHLhpl3lP5oZBB73ImW2MHGr+IbQtAW9euiidPJF+w= -github.com/smartcontractkit/chainlink-common v0.10.1-0.20260213162239-ce0002b6079e/go.mod h1:13YN2kb3Vqpw2S7d4IwhX/578WPGC0JHN5JrOnAEsOc= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260218143149-f4e93991b518 h1:wPdjEUQjw+cp/tOeJDI32u1MDkRGwK3ZLaD5a9tm0qI= +github.com/smartcontractkit/chainlink-common v0.10.1-0.20260218143149-f4e93991b518/go.mod h1:HXgSKzmZ/bhSx8nHU7hHW6dR+BHSXkdcpFv2T8qJcS8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 h1:NOUsjsMzNecbjiPWUQGlRSRAutEvCFrqqyETDJeh5q4= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4/go.mod h1:Zpvul9sTcZNAZOVzt5vBl1XZGNvQebFpnpn3/KOQvOQ= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= @@ -1341,8 +1341,8 @@ github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0. github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d/go.mod h1:ATjAPIVJibHRcIfiG47rEQkUIOoYa6KDvWj3zwCAw6g= github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d h1:AJy55QJ/pBhXkZjc7N+ATnWfxrcjq9BI9DmdtdjwDUQ= github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d/go.mod h1:5JdppgngCOUS76p61zCinSCgOhPeYQ+OcDUuome5THQ= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe h1:Vc4zoSc/j6/FdCQ7vcyHTTB7kzHI2f+lHCHqFuiCcJQ= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260210221717-2546aed27ebe/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260217043601-5cc966896c4f h1:MHlgzqiDPyDV397bZkzS9TtWXb3FR9Pb8FR9cP9h0As= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260217043601-5cc966896c4f/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0 h1:xHPmFDhff7QpeFxKsZfk+24j4AlnQiFjjRh5O87Peu4= github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= diff --git a/relayer/aptos_service.go b/relayer/aptos_service.go index 3ae06b93b..8e2000cc6 100644 --- a/relayer/aptos_service.go +++ b/relayer/aptos_service.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" commonaptos "github.com/smartcontractkit/chainlink-common/pkg/types/chains/aptos" + "github.com/smartcontractkit/chainlink-common/pkg/utils/retry" ) type aptosService struct { @@ -138,36 +139,71 @@ func (s *aptosService) SubmitTransaction(ctx context.Context, req commonaptos.Su if err != nil { return nil, fmt.Errorf("failed to enqueue transaction: %w", err) } - - // Poll TxManager for status until terminal - var txStatus commontypes.TransactionStatus - for { - txStatus, err = s.chain.TxManager().GetStatus(txID) - if err != nil { - return nil, fmt.Errorf("failed to get transaction status: %w", err) + // TODO: dont use txmgr config, create and use workflow/cre config + maximumWaitTime := time.Duration(s.chain.Config().TransactionManager.TxExpirationSecs) * time.Second + + retryCtx, cancel := context.WithTimeout(ctx, maximumWaitTime) + defer cancel() + txStatus, err := retry.Do(retryCtx, s.logger, func(ctx context.Context) (commonaptos.TransactionStatus, error) { + txStatus, txStatusErr := s.chain.TxManager().GetStatus(txID) + if txStatusErr != nil { + return commonaptos.TxFatal, txStatusErr } - switch txStatus { - case commontypes.Finalized: - return &commonaptos.SubmitTransactionReply{ - PendingTransaction: &commonaptos.PendingTransaction{ - Hash: txID, - }, - }, nil - case commontypes.Failed, commontypes.Fatal: - return nil, fmt.Errorf("transaction failed with status: %v", txStatus) - case commontypes.Pending, commontypes.Unknown, commontypes.Unconfirmed: - // still in progress, wait and retry - select { - case <-ctx.Done(): - return nil, fmt.Errorf("context cancelled while waiting for transaction: %w", ctx.Err()) - case <-time.After(500 * time.Millisecond): - continue - } + case commontypes.Fatal, commontypes.Failed: + return commonaptos.TxFatal, nil + case commontypes.Unconfirmed, commontypes.Finalized: + return commonaptos.TxSuccess, nil + case commontypes.Pending, commontypes.Unknown: + return commonaptos.TxFatal, fmt.Errorf("tx still in state pending or unknown, tx status is %d for tx with ID %s", txStatus, txID) default: - return nil, fmt.Errorf("unexpected transaction status: %v", txStatus) + return commonaptos.TxFatal, fmt.Errorf("unexpected transaction status %d for tx with ID %s", txStatus, txID) } + }) + + if err != nil { + return nil, fmt.Errorf("failed getting transaction status: %w", err) + } + + if txStatus == commonaptos.TxFatal { + return &commonaptos.SubmitTransactionReply{ + TxStatus: commonaptos.TxFatal, + TxIdempotencyKey: txID, + }, nil + } else { + return &commonaptos.SubmitTransactionReply{ + TxStatus: commonaptos.TxSuccess, + TxIdempotencyKey: txID, + }, nil } + // TODO: + // get tx hash + // make write report get tx by hash and check for success or revert reason + // but then we also need to poll for transmission info because some other node might have done a success + // so we need to go through all possible cases and then figure out how to handle retries + + /* + receipt, err := retry.Do(retryContext, e.logger, func(ctx context.Context) (*evmtxmgr.ChainReceipt, error) { + receipt, receiptErr := e.chain.TxManager().GetTransactionReceipt(ctx, txID) + if receiptErr != nil { + return nil, fmt.Errorf("failed to get TX receipt for tx with ID %s: %w", txID, receiptErr) + } + if receipt == nil { + return nil, fmt.Errorf("receipt was nil for TX with ID %s", txID) + } + return receipt, nil + }) + + if err != nil { + return nil, fmt.Errorf("failed getting transaction receipt. %w", err) + } + + return &evm.TransactionResult{ + TxStatus: evm.TxSuccess, + TxHash: (*receipt).GetTxHash(), + TxIdempotencyKey: txID, + }, nil + */ } // getAccountWithHighestBalance returns the public key of the account with the highest APT balance. From 1bbc29edc7ba74278a2b226798e157f71f5cff1e Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Mon, 23 Feb 2026 11:07:33 +0000 Subject: [PATCH 10/12] forwarder comments --- contracts/platform/sources/forwarder.move | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/contracts/platform/sources/forwarder.move b/contracts/platform/sources/forwarder.move index 7d2f54bf6..d1ce78333 100644 --- a/contracts/platform/sources/forwarder.move +++ b/contracts/platform/sources/forwarder.move @@ -53,6 +53,18 @@ module platform::forwarder { oracles: vector } + /* + struct Transmission { + address transmitter; + // with an increased gas limit. + bool success; + // The amount of gas allocated for the `IReceiver.onReport` call. uint80 allows storing gas for known EVM block + // gas limits. Ensures that the minimum gas requested by the user is available during the transmission attempt. + // If the transmission fails (indicated by a `false` success state), it can be retried with an increased gas limit. + uint80 gasLimit; + } + */ + #[event] struct ConfigSet has drop, store { don_id: u32, @@ -212,6 +224,13 @@ module platform::forwarder { ); } + // TODO: split this into report_validation() and report_delivery() + // both called with same params and payload + // report_validation() verifies config/payload/sigs and updates transmission info with transmitter address and state to InProgress + // report_delivery() will revert if transmission not in progress + // report_delivery() will revert (or return success) ? if transmission already successful + // report_delivery() updates transmisison info with transmitter address (because different nodes can be calling report_validation() and report_delivery() + entry fun report( transmitter: &signer, receiver: address, @@ -322,6 +341,34 @@ module platform::forwarder { (metadata, data) } + /* + function getTransmissionInfo( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (TransmissionInfo memory) { + bytes32 transmissionId = getTransmissionId(receiver, workflowExecutionId, reportId); + + Transmission memory transmission = s_transmissions[transmissionId]; + + TransmissionState state; + + if (transmission.transmitter == address(0)) { + state = IRouter.TransmissionState.NOT_ATTEMPTED; + } else { + state = transmission.success ? IRouter.TransmissionState.SUCCEEDED : IRouter.TransmissionState.FAILED; + } + + return TransmissionInfo({ + gasLimit: transmission.gasLimit, + state: state, + success: transmission.success, + transmissionId: transmissionId, + transmitter: transmission.transmitter + }); + } + */ + #[view] public fun get_transmission_state( receiver: address, workflow_execution_id: vector, report_id: u16 From abfd050136ac96e4bb10c1e898e2a709f2f663de Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Mon, 23 Feb 2026 11:08:12 +0000 Subject: [PATCH 11/12] wip --- LOOP_ARCHITECTURE.md | 312 ------------------------------------------- 1 file changed, 312 deletions(-) delete mode 100644 LOOP_ARCHITECTURE.md diff --git a/LOOP_ARCHITECTURE.md b/LOOP_ARCHITECTURE.md deleted file mode 100644 index f9378d09c..000000000 --- a/LOOP_ARCHITECTURE.md +++ /dev/null @@ -1,312 +0,0 @@ -# LOOP Architecture: Relayer vs RelayerSet - -Understanding the two different gRPC boundaries in the Chainlink LOOP architecture. - -## Overview - -There are **two separate gRPC boundaries** where chain-specific services (like Aptos) need to be implemented: - -1. **Relayer LOOP**: When an individual relayer runs as a separate process -2. **RelayerSet for Capabilities**: When capabilities run as separate processes and need to call back to relayers - -## Architecture Diagram - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Core Node Process │ -│ │ -│ ┌──────────────┐ │ -│ │ Relayer Set │ ◄─────────────────┐ │ -│ │ - EVM │ │ │ -│ │ - Solana │ │ │ -│ │ - Aptos │ │ │ -│ └──────────────┘ │ │ -│ │ │ │ -│ │ Embedded Mode │ LOOP Mode │ -│ ▼ │ │ -│ ┌──────────────┐ ┌─────┴──────┐ │ -│ │ Relayer │ │ RelayerSet │ │ -│ │ Logic │ │ Server │ │ -│ └──────────────┘ └─────┬──────┘ │ -│ │ │ -└──────────────────────────────────────┼──────────────────────┘ - │ gRPC - ┌──────────────────┼──────────────────────┐ - │ │ │ - ┌─────▼──────┐ ┌─────▼──────┐ │ - │ Capability │ │ Capability │ │ - │ Process 1 │ │ Process 2 │ │ - │ │ │ │ │ - │ ┌────────┐ │ │ ┌────────┐ │ │ - │ │Relayer │ │ │ │Relayer │ │ │ - │ │ Set │ │ │ │ Set │ │ │ - │ │ Client │ │ │ │ Client │ │ │ - │ └────────┘ │ │ └────────┘ │ │ - └────────────┘ └────────────┘ │ - │ - Capability Processes (LOOP Mode) │ - │ -└─────────────────────────────────────────────────────────────┘ -``` - -## The Two Packages - -### 1. `pkg/loop/internal/relayer/` - Standalone Relayer LOOP - -**Location**: `chainlink-common/pkg/loop/internal/relayer/aptos.go` - -**Purpose**: Allows a relayer to run as a separate LOOP process (optional feature). - -**Process Boundary**: -``` -Core Node ◄──[gRPC]──► Relayer Process (standalone) -``` - -**When Used**: -- When environment variable `CL_APTOS_PLUGIN_CMD` is set -- Relayer runs as external binary, not embedded in core node - -**Key Components**: - -```go -// AptosClient - Used by core node to call standalone relayer -type AptosClient struct { - grpcClient aptospb.AptosClient -} - -func (ac *AptosClient) AccountAPTBalance(ctx context.Context, req aptos.AccountAPTBalanceRequest) (*aptos.AccountAPTBalanceReply, error) { - // Convert Go types → Proto types - reply, err := ac.grpcClient.AccountAPTBalance(ctx, &aptospb.AccountAPTBalanceRequest{ - Address: req.Address[:], - }) - // Convert Proto types → Go types - return &aptos.AccountAPTBalanceReply{Value: reply.Value}, nil -} - -// aptosServer - Used by standalone relayer to receive calls -type aptosServer struct { - impl types.AptosService // Actual business logic -} - -func (s *aptosServer) AccountAPTBalance(ctx context.Context, req *aptospb.AccountAPTBalanceRequest) (*aptospb.AccountAPTBalanceReply, error) { - // Convert Proto types → Go types - reply, err := s.impl.AccountAPTBalance(ctx, aptos.AccountAPTBalanceRequest{ - Address: aptos.AccountAddress(req.Address), - }) - // Convert Go types → Proto types - return &aptospb.AccountAPTBalanceReply{Value: reply.Value}, nil -} -``` - -**Call Flow**: -``` -Core Node Logic - → AptosClient (proto conversion) - → [gRPC over network/pipe] - → aptosServer (proto conversion) - → Aptos Business Logic (in separate process) -``` - ---- - -### 2. `pkg/loop/internal/relayerset/` - RelayerSet for Capabilities - -**Location**: `chainlink-common/pkg/loop/internal/relayerset/aptos.go` - -**Purpose**: Allows capability processes to call back to relayers in the core node. - -**Process Boundary**: -``` -Capability Process ◄──[gRPC]──► Core Node (RelayerSet) -``` - -**When Used**: -- **Always** when capabilities run in LOOP mode -- Capability needs to call chain-specific functions -- Most common use case - -**Key Components**: - -```go -// aptosClient - Used by capability to call back to core node -// Adds RelayID to context so server knows which relayer to use -type aptosClient struct { - relayID types.RelayID // Which relayer? (e.g., "aptos.mainnet") - client aptospb.AptosClient -} - -func (ac *aptosClient) AccountAPTBalance(ctx context.Context, in *aptospb.AccountAPTBalanceRequest, opts ...grpc.CallOption) (*aptospb.AccountAPTBalanceReply, error) { - // Add RelayID to context metadata - ctx = appendRelayID(ctx, ac.relayID) - return ac.client.AccountAPTBalance(ctx, in, opts...) -} - -// aptosServer - Used by core node to receive calls from capabilities -type aptosServer struct { - parent *Server // Has access to RelayerSet -} - -func (as *aptosServer) AccountAPTBalance(ctx context.Context, req *aptospb.AccountAPTBalanceRequest) (*aptospb.AccountAPTBalanceReply, error) { - // Get the AptosService for the specific relayer - aptosService, err := as.parent.getAptosService(ctx) - - // Convert proto → Go types and call business logic - reply, err := aptosService.AccountAPTBalance(ctx, aptos.AccountAPTBalanceRequest{ - Address: aptos.AccountAddress(req.Address), - }) - - // Convert Go types → proto - return &aptospb.AccountAPTBalanceReply{Value: reply.Value}, nil -} - -// Helper to extract RelayID and get the right service -func (s *Server) getAptosService(ctx context.Context) (types.AptosService, error) { - relayID, err := readContextValue(ctx, metadataRelayID) - relayer, err := s.impl.Get(ctx, relayID) // Get specific relayer - return relayer.Aptos() // Get its Aptos service -} -``` - -**Call Flow**: -``` -Capability Logic - → aptosClient.AccountAPTBalance() [adds RelayID to context] - → [gRPC back to Core Node] - → RelayerSet Server - → Extract RelayID from context - → Get correct Aptos relayer from RelayerSet - → Call Aptos Business Logic -``` - ---- - -## Key Differences - -| Aspect | `relayer/` (Standalone Relayer) | `relayerset/` (Capability Callbacks) | -|--------|--------------------------------|-------------------------------------| -| **Process Boundary** | Core Node ↔ Relayer Process | Capability Process ↔ Core Node | -| **Direction** | Core calls relayer | Capability calls back to core | -| **RelayID Handling** | Not needed (single relayer) | Critical (multiple relayers) | -| **Client Purpose** | Proto conversion only | Add RelayID + forward call | -| **Server Purpose** | Call business logic directly | Find relayer + call its logic | -| **When Needed** | Optional (relayer LOOP mode) | Required (capability LOOP mode) | -| **Frequency of Use** | Rare (most relayers embedded) | Common (most capabilities LOOPified) | - ---- - -## Context Metadata Pattern - -The `relayerset` uses gRPC metadata to pass the `RelayID`: - -```go -// Client side: Add RelayID to context -func appendRelayID(ctx context.Context, relayID types.RelayID) context.Context { - return metadata.AppendToOutgoingContext(ctx, - metadataRelayID, relayID.String()) -} - -// Server side: Extract RelayID from context -func readContextValue(ctx context.Context, key string) (string, error) { - md, ok := metadata.FromIncomingContext(ctx) - values := md.Get(key) - return values[0], nil -} -``` - -This allows multiple relayers (EVM mainnet, Solana devnet, Aptos testnet, etc.) to share the same gRPC connection, with the server routing calls to the correct relayer based on metadata. - ---- - -## Which Package Do I Need? - -### For Most Implementations: Start with `relayerset/` - -If you're building a new chain integration (like Aptos), you'll almost certainly need `relayerset/` first because: - -1. ✅ Capabilities typically run in LOOP mode -2. ✅ Capabilities need to call chain-specific functions -3. ✅ This is the standard architecture for most chains - -### Optional: Add `relayer/` Later - -You only need `relayer/` if: - -1. You want the relayer itself to run as a separate process -2. You're isolating relayer logic for security/stability -3. You're implementing optional LOOP mode for relayers - -**Most chains only implement `relayerset/` initially.** - ---- - -## Implementation Order - -### Step 1: Proto + Types (Both packages share these) -1. Create `.proto` file: `pkg/chains/aptos/aptos.proto` -2. Create Go types: `pkg/types/chains/aptos/aptos.go` -3. Add interface: `pkg/types/relayer.go` -4. Run `make generate` to create gRPC stubs - -### Step 2: RelayerSet (Required for capabilities) -1. Create `pkg/loop/internal/relayerset/aptos.go` -2. Update `pkg/loop/internal/relayerset/server.go` -3. Update `pkg/loop/internal/relayerset/client.go` -4. Update `pkg/loop/internal/relayerset/relayer.go` -5. Register in `pkg/loop/internal/pb/relayerset/helper.go` - -### Step 3: Business Logic -1. Implement actual Aptos service in `chainlink-aptos/` -2. Connect to Aptos SDK/RPC - -### Step 4: Relayer LOOP (Optional) -1. Create `pkg/loop/internal/relayer/aptos.go` -2. Create standalone binary in `chainlink-aptos/cmd/` -3. Add environment variable support - ---- - -## Real-World Example - -### Capability Calling Aptos - -```go -// In capability process (e.g., WriteTarget capability) -func (w *WriteTarget) Execute(ctx context.Context, req capabilities.CapabilityRequest) { - // Get Aptos service from relayer set - aptosService, err := w.relayer.Aptos() - - // Call method - this goes over gRPC back to core node - balance, err := aptosService.AccountAPTBalance(ctx, - aptos.AccountAPTBalanceRequest{ - Address: accountAddr, - }) - - // Use result... -} -``` - -**What happens under the hood:** - -1. `w.relayer.Aptos()` returns an `aptosClient` wrapper -2. `AccountAPTBalance()` call: - - Adds RelayID ("aptos.mainnet") to context metadata - - Makes gRPC call back to core node -3. Core node's `aptosServer`: - - Extracts RelayID from metadata - - Finds Aptos mainnet relayer in RelayerSet - - Calls that relayer's `AccountAPTBalance()` -4. Result flows back through gRPC to capability - ---- - -## Summary - -- **`relayer/`**: For standalone relayer processes (optional, advanced) -- **`relayerset/`**: For capability-to-relayer calls (required, standard) - -**Most implementations only need `relayerset/` initially.** - -The key insight: gRPC boundaries can be in different places depending on what's LOOPified: -- If relayers are LOOPified → use `relayer/` -- If capabilities are LOOPified → use `relayerset/` ✅ (most common) - From 01d90e1c530bf7ad701a7c602c8fa99759292ab6 Mon Sep 17 00:00:00 2001 From: yashnevatia Date: Mon, 23 Feb 2026 11:12:17 +0000 Subject: [PATCH 12/12] comments --- contracts/platform/sources/forwarder.move | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/contracts/platform/sources/forwarder.move b/contracts/platform/sources/forwarder.move index d1ce78333..0a3a0377d 100644 --- a/contracts/platform/sources/forwarder.move +++ b/contracts/platform/sources/forwarder.move @@ -57,7 +57,8 @@ module platform::forwarder { struct Transmission { address transmitter; // with an increased gas limit. - bool success; + bool success; // this can actually hold the transmission state (notAttempted, inProgress, successful, failed) + // or we can derive it in getTransmissionState(), do check chainlink-evm/contracts/cre/src/keystone/KeystoneForwarder.sol // The amount of gas allocated for the `IReceiver.onReport` call. uint80 allows storing gas for known EVM block // gas limits. Ensures that the minimum gas requested by the user is available during the transmission attempt. // If the transmission fails (indicated by a `false` success state), it can be retried with an increased gas limit. @@ -229,8 +230,15 @@ module platform::forwarder { // report_validation() verifies config/payload/sigs and updates transmission info with transmitter address and state to InProgress // report_delivery() will revert if transmission not in progress // report_delivery() will revert (or return success) ? if transmission already successful - // report_delivery() updates transmisison info with transmitter address (because different nodes can be calling report_validation() and report_delivery() - + // report_delivery() updates transmisison info with transmitter address (because different nodes can be calling report_validation() and report_delivery()) + // so we want to look at the AccountTransactions of the correct node + // evm also does the following and it would be nice if aptos had a similar mechanism, this can help send retry attempts with increased gas limit + /* + uint256 gasLimit = gasleft() - INTERNAL_GAS_REQUIREMENTS; + if (gasLimit < MINIMUM_GAS_LIMIT) revert InsufficientGasForRouting(transmissionId); + s_transmissions[transmissionId].gasLimit = uint80(gasLimit); + */ + entry fun report( transmitter: &signer, receiver: address,