From 3c2d0182ed4a5a87e4dfb3c7f565a984c1a3f0ef Mon Sep 17 00:00:00 2001 From: Awbrey Hughlett Date: Thu, 14 Mar 2024 17:21:40 -0500 Subject: [PATCH 01/14] Implement Basic GetLatestValue for Solana (#612) * Implement Basic GetLatestValue for Solana This commit fills in the functionality for `GetLatestValue` such that one or more accounts with an associated Anchor IDl can be read and mapped to native Go structs. Methods and prodecures can be defined in a config where an IDL and codec modifiers can be provided. Current limitations include completing enums and defining max length of strings. * add interface tests that ensure service functions in loop mode * updates to package information * add epoch to time hook * add check for circular dependencies in IDL * go mod tidy * move test types, rename file, and add detail to comments * combine bindings into single struct * ensure no struct fields overlap * tests to boost coverage * add todo and update max wait time * upgrade deps in integration tests * moved files to new directory and removed unused file * mod tidy --- go.mod | 23 +- go.sum | 33 +- integration-tests/go.mod | 6 +- integration-tests/go.sum | 10 +- pkg/solana/chain_reader.go | 74 -- pkg/solana/chain_reader_test.go | 37 - .../chainreader/account_read_binding.go | 51 ++ pkg/solana/chainreader/bindings.go | 142 ++++ pkg/solana/chainreader/bindings_test.go | 120 ++++ pkg/solana/chainreader/chain_reader.go | 168 +++++ pkg/solana/chainreader/chain_reader_test.go | 662 ++++++++++++++++++ pkg/solana/codec/anchoridl.go | 403 +++++++++++ pkg/solana/codec/duration.go | 54 ++ pkg/solana/codec/solana.go | 326 +++++++++ pkg/solana/codec/solana_test.go | 139 ++++ .../codec/testutils/circularDepIDL.json | 42 ++ pkg/solana/codec/testutils/testIDL.json | 159 +++++ pkg/solana/codec/testutils/types.go | 87 +++ pkg/solana/config/chain_reader.go | 39 ++ sonar-project.properties | 2 +- 20 files changed, 2445 insertions(+), 132 deletions(-) delete mode 100644 pkg/solana/chain_reader.go delete mode 100644 pkg/solana/chain_reader_test.go create mode 100644 pkg/solana/chainreader/account_read_binding.go create mode 100644 pkg/solana/chainreader/bindings.go create mode 100644 pkg/solana/chainreader/bindings_test.go create mode 100644 pkg/solana/chainreader/chain_reader.go create mode 100644 pkg/solana/chainreader/chain_reader_test.go create mode 100644 pkg/solana/codec/anchoridl.go create mode 100644 pkg/solana/codec/duration.go create mode 100644 pkg/solana/codec/solana.go create mode 100644 pkg/solana/codec/solana_test.go create mode 100644 pkg/solana/codec/testutils/circularDepIDL.json create mode 100644 pkg/solana/codec/testutils/testIDL.json create mode 100644 pkg/solana/codec/testutils/types.go create mode 100644 pkg/solana/config/chain_reader.go diff --git a/go.mod b/go.mod index 92e546feb..0d485b698 100644 --- a/go.mod +++ b/go.mod @@ -8,19 +8,21 @@ require ( github.com/gagliardetto/gofuzz v1.2.2 github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 github.com/gagliardetto/treeout v0.1.4 + github.com/gagliardetto/utilz v0.1.1 github.com/google/uuid v1.3.1 - github.com/hashicorp/go-plugin v1.5.2 + github.com/hashicorp/go-plugin v1.6.0 + github.com/mitchellh/mapstructure v1.5.0 github.com/pelletier/go-toml/v2 v2.1.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240213113935-001c2f4befd4 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 github.com/smartcontractkit/libocr v0.0.0-20240112202000-6359502d2ff1 - github.com/stretchr/testify v1.8.4 - github.com/test-go/testify v1.1.4 + github.com/stretchr/testify v1.9.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.6.0 + golang.org/x/text v0.14.0 gopkg.in/guregu/null.v4 v4.0.0 ) @@ -32,6 +34,7 @@ require ( github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blendle/zapdriver v1.3.1 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/confluentinc/confluent-kafka-go/v2 v2.3.0 // indirect @@ -47,16 +50,20 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect - github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.15 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/linkedin/goavro/v2 v2.12.0 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/miekg/dns v1.1.35 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -70,9 +77,11 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/riferrei/srclient v0.5.4 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -93,11 +102,11 @@ require ( golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ff155ba26..d3874d791 100644 --- a/go.sum +++ b/go.sum @@ -78,6 +78,8 @@ github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHf github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= @@ -105,6 +107,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -142,10 +145,13 @@ github.com/gagliardetto/binary v0.7.1 h1:6ggDQ26vR+4xEvl/S13NcdLK3MUCi4oSy73pS9a github.com/gagliardetto/binary v0.7.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 h1:q2IztKyRQUxJ6abXRsawaBtvDFvM+szj4jDqV4od1gs= github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27/go.mod h1:NFuoDwHPvw858ZMHUJr6bkhN8qHt4x6e+U3EYHxAwNY= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -244,6 +250,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -267,8 +275,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -328,6 +336,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -380,6 +390,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -410,10 +421,13 @@ github.com/riferrei/srclient v0.5.4 h1:dfwyR5u23QF7beuVl2WemUY2KXh5+Sc4DHKyPXBNY github.com/riferrei/srclient v0.5.4/go.mod h1:vbkLmWcgYa7JgfPvuy/+K8fTS0p1bApqadxrxi/S1MI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= @@ -424,8 +438,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240213113935-001c2f4befd4 h1:Yk0RK9WV59ISOZZMsdtxZBAKaBfdgb05oXyca/qSqcw= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240213113935-001c2f4befd4/go.mod h1:pRlQrvcizMmuHAUV4N96oO2e3XbA99JCQELLc6ES160= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 h1:WeLb67RVd0lqdbm8qJ/LqrcfoLr7PoMjzi9wGy7ocqc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498/go.mod h1:8sn4HEfG8lR/D1Ov0yPHsY4kOleDKZKh2r8Op4oaAFE= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= @@ -447,8 +461,9 @@ github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -459,8 +474,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= @@ -540,6 +556,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= @@ -637,6 +654,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= @@ -658,6 +676,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -692,6 +711,7 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= @@ -879,6 +899,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index b9cdee810..9a57ee8f4 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -12,13 +12,13 @@ require ( github.com/lib/pq v1.10.9 github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240219152510-85226a0fbdc1 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e github.com/smartcontractkit/chainlink-testing-framework v1.23.6 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2 github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2 github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.23.0 go.uber.org/zap v1.26.0 golang.org/x/crypto v0.19.0 @@ -372,7 +372,7 @@ require ( github.com/spf13/viper v1.16.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e81748fbb..0208dcba4 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1399,8 +1399,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429 h1:xkejUBZhcBpBrTSfxc91Iwzadrb6SXw8ks69bHIQ9Ww= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429/go.mod h1:wJmVvDf4XSjsahWtfUq3wvIAYEAuhr7oxmxYnEL/LGQ= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240219152510-85226a0fbdc1 h1:MNYkjakmoKxg7L1nmfAVeFOdONaLT7E62URBpmcTh84= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240219152510-85226a0fbdc1/go.mod h1:6aXWSEQawX2oZXcPPOdxnEGufAhj7PqPKolXf6ijRGA= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 h1:WeLb67RVd0lqdbm8qJ/LqrcfoLr7PoMjzi9wGy7ocqc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498/go.mod h1:8sn4HEfG8lR/D1Ov0yPHsY4kOleDKZKh2r8Op4oaAFE= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336 h1:j00D0/EqE9HRu+63v7KwUOe4ZxLc4AN5SOJFiinkkH0= @@ -1473,8 +1473,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1486,8 +1487,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= diff --git a/pkg/solana/chain_reader.go b/pkg/solana/chain_reader.go deleted file mode 100644 index 6642cf62a..000000000 --- a/pkg/solana/chain_reader.go +++ /dev/null @@ -1,74 +0,0 @@ -package solana - -import ( - "context" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -const ServiceName = "SolanaChainReader" - -type SolanaChainReaderService struct { - lggr logger.Logger - services.StateMachine -} - -var ( - _ services.Service = &SolanaChainReaderService{} - _ types.ChainReader = &SolanaChainReaderService{} -) - -// NewChainReaderService is a constructor for a new ChainReaderService for Solana. Returns a nil service on error. -func NewChainReaderService(lggr logger.Logger) (*SolanaChainReaderService, error) { - return &SolanaChainReaderService{ - lggr: logger.Named(lggr, ServiceName), - }, nil -} - -// Name implements the services.ServiceCtx interface and returns the logger service name. -func (s *SolanaChainReaderService) Name() string { - return s.lggr.Name() -} - -// Start implements the services.ServiceCtx interface and starts necessary background services. -// An error is returned if starting any internal services fails. Subsequent calls to Start return -// and error. -func (s *SolanaChainReaderService) Start(_ context.Context) error { - return s.StartOnce(ServiceName, func() error { - return nil - }) -} - -// Close implements the services.ServiceCtx interface and stops all background services and cleans -// up used resources. Subsequent calls to Close return an error. -func (s *SolanaChainReaderService) Close() error { - return s.StopOnce(ServiceName, func() error { - return nil - }) -} - -// Ready implements the services.ServiceCtx interface and returns an error if starting the service -// encountered any errors or if the service is not ready to serve requests. -func (s *SolanaChainReaderService) Ready() error { - return s.StateMachine.Ready() -} - -// HealthReport implements the services.ServiceCtx interface and returns errors for any internal -// function or service that may have failed. -func (s *SolanaChainReaderService) HealthReport() map[string]error { - return map[string]error{s.Name(): s.Healthy()} -} - -// GetLatestValue implements the types.ChainReader interface and requests and parses on-chain -// data named by the provided contract, method, and params. -func (s *SolanaChainReaderService) GetLatestValue(_ context.Context, contractName, method string, params any, returnVal any) error { - return types.UnimplementedError("GetLatestValue not available") -} - -// Bind implements the types.ChainReader interface and allows new contract bindings to be added -// to the service. -func (s *SolanaChainReaderService) Bind(_ context.Context, bindings []types.BoundContract) error { - return types.UnimplementedError("Bind not available") -} diff --git a/pkg/solana/chain_reader_test.go b/pkg/solana/chain_reader_test.go deleted file mode 100644 index 9db536a6c..000000000 --- a/pkg/solana/chain_reader_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package solana_test - -import ( - "testing" - - "github.com/test-go/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink-solana/pkg/solana" -) - -func TestSolanaChainReaderService_ServiceCtx(t *testing.T) { - t.Parallel() - - ctx := tests.Context(t) - svc, err := solana.NewChainReaderService(logger.Test(t)) - - require.NoError(t, err) - require.NotNil(t, svc) - - require.Error(t, svc.Ready()) - require.Len(t, svc.HealthReport(), 1) - require.Contains(t, svc.HealthReport(), solana.ServiceName) - require.Error(t, svc.HealthReport()[solana.ServiceName]) - - require.NoError(t, svc.Start(ctx)) - require.NoError(t, svc.Ready()) - require.Equal(t, map[string]error{solana.ServiceName: nil}, svc.HealthReport()) - - require.Error(t, svc.Start(ctx)) - - require.NoError(t, svc.Close()) - require.Error(t, svc.Ready()) - require.Error(t, svc.Close()) -} diff --git a/pkg/solana/chainreader/account_read_binding.go b/pkg/solana/chainreader/account_read_binding.go new file mode 100644 index 000000000..6d44d1c6f --- /dev/null +++ b/pkg/solana/chainreader/account_read_binding.go @@ -0,0 +1,51 @@ +package chainreader + +import ( + "context" + "fmt" + + "github.com/gagliardetto/solana-go" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// BinaryDataReader provides an interface for reading bytes from a source. This is likely a wrapper +// for a solana client. +type BinaryDataReader interface { + ReadAll(context.Context, solana.PublicKey) ([]byte, error) +} + +// accountReadBinding provides decoding and reading Solana Account data using a defined codec. The +// `idlAccount` refers to the account name in the IDL for which the codec has a type mapping. +type accountReadBinding struct { + idlAccount string + account solana.PublicKey + codec types.RemoteCodec + reader BinaryDataReader +} + +var _ readBinding = &accountReadBinding{} + +func (b *accountReadBinding) GetLatestValue(ctx context.Context, _ any, outVal any) error { + bts, err := b.reader.ReadAll(ctx, b.account) + if err != nil { + return fmt.Errorf("%w: failed to get binary data", err) + } + + return b.codec.Decode(ctx, bts, outVal, b.idlAccount) +} + +func (b *accountReadBinding) Bind(contract types.BoundContract) error { + account, err := solana.PublicKeyFromBase58(contract.Address) + if err != nil { + return err + } + + b.account = account + + return nil +} + +func (b *accountReadBinding) CreateType(_ bool) (any, error) { + return b.codec.CreateType(b.idlAccount, false) +} diff --git a/pkg/solana/chainreader/bindings.go b/pkg/solana/chainreader/bindings.go new file mode 100644 index 000000000..2125684b2 --- /dev/null +++ b/pkg/solana/chainreader/bindings.go @@ -0,0 +1,142 @@ +package chainreader + +import ( + "context" + "fmt" + "reflect" + "strconv" + "strings" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +type readBinding interface { + GetLatestValue(ctx context.Context, params, returnVal any) error + Bind(types.BoundContract) error + CreateType(bool) (any, error) +} + +// key is namespace +type namespaceBindings map[string]methodBindings + +// key is method name +type methodBindings map[string]readBindings + +// read bindings is a list of bindings by index +type readBindings []readBinding + +func (b namespaceBindings) AddReadBinding(namespace, methodName string, reader readBinding) { + nbs, nbsExists := b[namespace] + if !nbsExists { + nbs = methodBindings{} + b[namespace] = nbs + } + + rbs, rbsExists := nbs[methodName] + if !rbsExists { + rbs = []readBinding{} + } + + b[namespace][methodName] = append(rbs, reader) +} + +func (b namespaceBindings) GetReadBindings(namespace, methodName string) ([]readBinding, error) { + nbs, nbsExists := b[namespace] + if !nbsExists { + return nil, fmt.Errorf("%w: no read binding exists for %s", types.ErrInvalidConfig, namespace) + } + + rbs, rbsExists := nbs[methodName] + if !rbsExists { + return nil, fmt.Errorf("%w: no read binding exists for %s and %s", types.ErrInvalidConfig, namespace, methodName) + } + + return rbs, nil +} + +func (b namespaceBindings) CreateType(namespace, methodName string, forEncoding bool) (any, error) { + bindings, err := b.GetReadBindings(namespace, methodName) + if err != nil { + return nil, err + } + + if len(bindings) == 1 { + // get the item type from the binding codec + return bindings[0].CreateType(forEncoding) + } + + // build a merged struct from all bindings + fields := make([]reflect.StructField, 0) + var fieldIdx int + fieldNames := make(map[string]struct{}) + + for _, binding := range bindings { + bindingType, err := binding.CreateType(forEncoding) + if err != nil { + return nil, err + } + + tBinding := reflect.TypeOf(bindingType) + + // all bindings must be structs to allow multiple bindings + if tBinding.Kind() != reflect.Struct { + return nil, fmt.Errorf("%w: support for multiple bindings only applies to all bindings having the type struct", types.ErrInvalidType) + } + + for idx := 0; idx < tBinding.NumField(); idx++ { + value := tBinding.FieldByIndex([]int{idx}) + + _, exists := fieldNames[value.Name] + if exists { + return nil, fmt.Errorf("%w: field name overlap on %s", types.ErrInvalidConfig, value.Name) + } + + field := reflect.StructField{ + Name: value.Name, + Type: value.Type, + Index: []int{fieldIdx}, + } + + fields = append(fields, field) + + fieldIdx++ + fieldNames[value.Name] = struct{}{} + } + } + + return reflect.New(reflect.StructOf(fields)).Interface(), nil +} + +func (b namespaceBindings) Bind(boundContracts []types.BoundContract) error { + for _, bc := range boundContracts { + parts := strings.Split(bc.Name, ".") + if len(parts) != 3 { + return fmt.Errorf("%w: BoundContract.Name must follow pattern of [namespace.method.procedure_idx]", types.ErrInvalidConfig) + } + + nbs, nbsExist := b[parts[0]] + if !nbsExist { + return fmt.Errorf("%w: no namespace named %s for %s", types.ErrInvalidConfig, parts[0], bc.Name) + } + + mbs, mbsExists := nbs[parts[1]] + if !mbsExists { + return fmt.Errorf("%w: no method named %s for %s", types.ErrInvalidConfig, parts[1], bc.Name) + } + + val, err := strconv.Atoi(parts[2]) + if err != nil { + return fmt.Errorf("%w: procedure index not parsable for %s", types.ErrInvalidConfig, bc.Name) + } + + if len(mbs) <= val { + return fmt.Errorf("%w: no procedure for index %d for %s", types.ErrInvalidConfig, val, bc.Name) + } + + if err := mbs[val].Bind(bc); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/solana/chainreader/bindings_test.go b/pkg/solana/chainreader/bindings_test.go new file mode 100644 index 000000000..77befa06b --- /dev/null +++ b/pkg/solana/chainreader/bindings_test.go @@ -0,0 +1,120 @@ +package chainreader + +import ( + "context" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func TestBindings_CreateType(t *testing.T) { + t.Parallel() + + t.Run("single binding returns type", func(t *testing.T) { + t.Parallel() + + expected := 8 + binding := new(mockBinding) + bindings := namespaceBindings{} + bindings.AddReadBinding("A", "B", binding) + + binding.On("CreateType", mock.Anything).Return(expected, nil) + + returned, err := bindings.CreateType("A", "B", true) + + require.NoError(t, err) + assert.Equal(t, expected, returned) + }) + + t.Run("multiple bindings return merged struct", func(t *testing.T) { + t.Parallel() + + bindingA := new(mockBinding) + bindingB := new(mockBinding) + bindings := namespaceBindings{} + + bindings.AddReadBinding("A", "B", bindingA) + bindings.AddReadBinding("A", "B", bindingB) + + bindingA.On("CreateType", mock.Anything).Return(struct{ A string }{A: "test"}, nil) + bindingB.On("CreateType", mock.Anything).Return(struct{ B int }{B: 8}, nil) + + result, err := bindings.CreateType("A", "B", true) + + expected := reflect.New(reflect.StructOf([]reflect.StructField{ + {Name: "A", Type: reflect.TypeOf("")}, + {Name: "B", Type: reflect.TypeOf(0)}, + })) + + require.NoError(t, err) + assert.Equal(t, expected.Type(), reflect.TypeOf(result)) + }) + + t.Run("multiple bindings fails when not a struct", func(t *testing.T) { + t.Parallel() + + bindingA := new(mockBinding) + bindingB := new(mockBinding) + bindings := namespaceBindings{} + + bindings.AddReadBinding("A", "B", bindingA) + bindings.AddReadBinding("A", "B", bindingB) + + bindingA.On("CreateType", mock.Anything).Return(8, nil) + bindingB.On("CreateType", mock.Anything).Return(struct{ A string }{A: "test"}, nil) + + _, err := bindings.CreateType("A", "B", true) + + require.ErrorIs(t, err, types.ErrInvalidType) + }) + + t.Run("multiple bindings errors when fields overlap", func(t *testing.T) { + t.Parallel() + + bindingA := new(mockBinding) + bindingB := new(mockBinding) + bindings := namespaceBindings{} + + bindings.AddReadBinding("A", "B", bindingA) + bindings.AddReadBinding("A", "B", bindingB) + + type A struct { + A string + B int + } + + type B struct { + A int + } + + bindingA.On("CreateType", mock.Anything).Return(A{A: ""}, nil) + bindingB.On("CreateType", mock.Anything).Return(B{A: 8}, nil) + + _, err := bindings.CreateType("A", "B", true) + + require.ErrorIs(t, err, types.ErrInvalidConfig) + }) +} + +type mockBinding struct { + mock.Mock +} + +func (_m *mockBinding) GetLatestValue(ctx context.Context, params, returnVal any) error { + return nil +} + +func (_m *mockBinding) Bind(types.BoundContract) error { + return nil +} + +func (_m *mockBinding) CreateType(b bool) (any, error) { + ret := _m.Called(b) + + return ret.Get(0), ret.Error(1) +} diff --git a/pkg/solana/chainreader/chain_reader.go b/pkg/solana/chainreader/chain_reader.go new file mode 100644 index 000000000..3418b59ff --- /dev/null +++ b/pkg/solana/chainreader/chain_reader.go @@ -0,0 +1,168 @@ +package chainreader + +import ( + "context" + "encoding/json" + + ag_solana "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +const ServiceName = "SolanaChainReader" + +type SolanaChainReaderService struct { + // provided values + lggr logger.Logger + client BinaryDataReader + + // internal values + bindings namespaceBindings + + // service state management + services.StateMachine +} + +var ( + _ services.Service = &SolanaChainReaderService{} + _ types.ChainReader = &SolanaChainReaderService{} +) + +// NewChainReaderService is a constructor for a new ChainReaderService for Solana. Returns a nil service on error. +func NewChainReaderService(lggr logger.Logger, dataReader BinaryDataReader, cfg config.ChainReader) (*SolanaChainReaderService, error) { + svc := &SolanaChainReaderService{ + lggr: logger.Named(lggr, ServiceName), + client: dataReader, + bindings: namespaceBindings{}, + } + + if err := svc.init(cfg.Namespaces); err != nil { + return nil, err + } + + return svc, nil +} + +// Name implements the services.ServiceCtx interface and returns the logger service name. +func (s *SolanaChainReaderService) Name() string { + return s.lggr.Name() +} + +// Start implements the services.ServiceCtx interface and starts necessary background services. +// An error is returned if starting any internal services fails. Subsequent calls to Start return +// and error. +func (s *SolanaChainReaderService) Start(_ context.Context) error { + return s.StartOnce(ServiceName, func() error { + return nil + }) +} + +// Close implements the services.ServiceCtx interface and stops all background services and cleans +// up used resources. Subsequent calls to Close return an error. +func (s *SolanaChainReaderService) Close() error { + return s.StopOnce(ServiceName, func() error { + return nil + }) +} + +// Ready implements the services.ServiceCtx interface and returns an error if starting the service +// encountered any errors or if the service is not ready to serve requests. +func (s *SolanaChainReaderService) Ready() error { + return s.StateMachine.Ready() +} + +// HealthReport implements the services.ServiceCtx interface and returns errors for any internal +// function or service that may have failed. +func (s *SolanaChainReaderService) HealthReport() map[string]error { + return map[string]error{s.Name(): s.Healthy()} +} + +// GetLatestValue implements the types.ChainReader interface and requests and parses on-chain +// data named by the provided contract, method, and params. +func (s *SolanaChainReaderService) GetLatestValue(ctx context.Context, contractName, method string, params any, returnVal any) error { + bindings, err := s.bindings.GetReadBindings(contractName, method) + if err != nil { + return err + } + + for _, binding := range bindings { + if err := binding.GetLatestValue(ctx, params, returnVal); err != nil { + return err + } + } + + return nil +} + +// Bind implements the types.ChainReader interface and allows new contract bindings to be added +// to the service. +func (s *SolanaChainReaderService) Bind(_ context.Context, bindings []types.BoundContract) error { + return s.bindings.Bind(bindings) +} + +// CreateContractType implements the ContractTypeProvider interface and allows the chain reader +// service to explicitly define the expected type for a grpc server to provide. +func (s *SolanaChainReaderService) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { + return s.bindings.CreateType(contractName, itemType, forEncoding) +} + +func (s *SolanaChainReaderService) init(namespaces map[string]config.ChainReaderMethods) error { + for namespace, methods := range namespaces { + for methodName, method := range methods.Methods { + var idl codec.IDL + if err := json.Unmarshal([]byte(method.AnchorIDL), &idl); err != nil { + return err + } + + idlCodec, err := codec.NewIDLCodec(idl) + if err != nil { + return err + } + + for _, procedure := range method.Procedures { + mod, err := procedure.OutputModifications.ToModifier(codec.DecoderHooks...) + if err != nil { + return err + } + + codecWithModifiers, err := codec.NewNamedModifierCodec(idlCodec, procedure.IDLAccount, mod) + if err != nil { + return err + } + + s.bindings.AddReadBinding(namespace, methodName, &accountReadBinding{ + idlAccount: procedure.IDLAccount, + codec: codecWithModifiers, + reader: s.client, + }) + } + } + } + + return nil +} + +type accountDataReader struct { + client *rpc.Client +} + +func NewAccountDataReader(client *rpc.Client) *accountDataReader { + return &accountDataReader{client: client} +} + +func (r *accountDataReader) ReadAll(ctx context.Context, pk ag_solana.PublicKey) ([]byte, error) { + result, err := r.client.GetAccountInfo(ctx, pk) + if err != nil { + return nil, err + } + + bts := result.Value.Data.GetBinary() + + return bts, nil +} diff --git a/pkg/solana/chainreader/chain_reader_test.go b/pkg/solana/chainreader/chain_reader_test.go new file mode 100644 index 000000000..2daa5fc12 --- /dev/null +++ b/pkg/solana/chainreader/chain_reader_test.go @@ -0,0 +1,662 @@ +package chainreader_test + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strconv" + "strings" + "testing" + "time" + + ag_solana "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" + "github.com/smartcontractkit/chainlink-common/pkg/types" + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/chainreader" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec/testutils" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +const ( + Namespace = "NameSpace" + NamedMethod = "NamedMethod1" +) + +func TestSolanaChainReaderService_ReaderInterface(t *testing.T) { + t.Parallel() + + it := &chainReaderInterfaceTester{} + RunChainReaderInterfaceTests(t, it) + RunChainReaderInterfaceTests(t, commontestutils.WrapChainReaderTesterForLoop(it)) +} + +func TestSolanaChainReaderService_ServiceCtx(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + svc, err := chainreader.NewChainReaderService(logger.Test(t), new(mockedRPCClient), config.ChainReader{}) + + require.NoError(t, err) + require.NotNil(t, svc) + + require.Error(t, svc.Ready()) + require.Len(t, svc.HealthReport(), 1) + require.Contains(t, svc.HealthReport(), chainreader.ServiceName) + require.Error(t, svc.HealthReport()[chainreader.ServiceName]) + + require.NoError(t, svc.Start(ctx)) + require.NoError(t, svc.Ready()) + require.Equal(t, map[string]error{chainreader.ServiceName: nil}, svc.HealthReport()) + + require.Error(t, svc.Start(ctx)) + + require.NoError(t, svc.Close()) + require.Error(t, svc.Ready()) + require.Error(t, svc.Close()) +} + +func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + + // encode values from unmodified test struct to be read and decoded + expected := testutils.DefaultTestStruct + + t.Run("Success", func(t *testing.T) { + t.Parallel() + + testCodec, conf := newTestConfAndCodec(t) + encoded, err := testCodec.Encode(ctx, expected, testutils.TestStructWithNestedStruct) + + require.NoError(t, err) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + + client.On("ReadAll", mock.Anything, mock.Anything).Return(encoded, nil) + + var result modifiedStructWithNestedStruct + + require.NoError(t, svc.GetLatestValue(ctx, Namespace, NamedMethod, nil, &result)) + assert.Equal(t, expected.InnerStruct, result.InnerStruct) + assert.Equal(t, expected.Value, result.V) + assert.Equal(t, expected.TimeVal, result.TimeVal) + assert.Equal(t, expected.DurationVal, result.DurationVal) + }) + + t.Run("Error Returned From Account Reader", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + expectedErr := fmt.Errorf("expected error") + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + + client.On("ReadAll", mock.Anything, mock.Anything).Return(nil, expectedErr) + + var result modifiedStructWithNestedStruct + + assert.ErrorIs(t, svc.GetLatestValue(ctx, Namespace, NamedMethod, nil, &result), expectedErr) + }) + + t.Run("Method Not Found", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + + var result modifiedStructWithNestedStruct + + assert.NotNil(t, svc.GetLatestValue(ctx, Namespace, "Unknown", nil, &result)) + }) + + t.Run("Namespace Not Found", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + + var result modifiedStructWithNestedStruct + + assert.NotNil(t, svc.GetLatestValue(ctx, "Unknown", "Unknown", nil, &result)) + }) + + t.Run("Bind Success", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + + pk := ag_solana.NewWallet().PublicKey() + err = svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", Namespace, NamedMethod, 0), + }, + }) + + assert.NoError(t, err) + }) + + t.Run("Bind Errors", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + + pk := ag_solana.NewWallet().PublicKey() + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: "incorrect format", + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", "Unknown", "Unknown", 0), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", Namespace, "Unknown", 0), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", Namespace, NamedMethod, 1), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.o", Namespace, NamedMethod), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: "invalid", + Name: fmt.Sprintf("%s.%s.%d", Namespace, NamedMethod, 0), + }, + })) + }) +} + +func newTestIDLAndCodec(t *testing.T) (string, codec.IDL, encodings.CodecFromTypeCodec) { + t.Helper() + + var idl codec.IDL + if err := json.Unmarshal([]byte(testutils.JSONIDLWithAllTypes), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + entry, err := codec.NewIDLCodec(idl) + if err != nil { + t.Logf("failed to create new codec from test IDL: %s", err.Error()) + t.FailNow() + } + + require.NotNil(t, entry) + + return testutils.JSONIDLWithAllTypes, idl, entry +} + +func newTestConfAndCodec(t *testing.T) (encodings.CodecFromTypeCodec, config.ChainReader) { + t.Helper() + + rawIDL, _, testCodec := newTestIDLAndCodec(t) + conf := config.ChainReader{ + Namespaces: map[string]config.ChainReaderMethods{ + Namespace: { + Methods: map[string]config.ChainDataReader{ + NamedMethod: { + AnchorIDL: rawIDL, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + Type: config.ProcedureTypeAnchor, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.RenameModifierConfig{Fields: map[string]string{"Value": "V"}}, + }, + }, + }, + }, + }, + }, + }, + } + + return testCodec, conf +} + +type modifiedStructWithNestedStruct struct { + V uint8 + InnerStruct testutils.ObjectRef1 + BasicNestedArray [][]uint32 + Option *string + DefinedArray []testutils.ObjectRef2 + BasicVector []string + TimeVal int64 + DurationVal time.Duration + PublicKey ag_solana.PublicKey + EnumVal uint8 +} + +// TODO: BCF-3060 convert mock client to be instance of solana chain. +type mockedRPCClient struct { + mock.Mock +} + +func (_m *mockedRPCClient) ReadAll(ctx context.Context, pk ag_solana.PublicKey) ([]byte, error) { + ret := _m.Called(ctx, pk) + + var r0 []byte + + if val, ok := ret.Get(0).([]byte); ok { + r0 = val + } + + return r0, ret.Error(1) +} + +type chainReaderInterfaceTester struct { + conf config.ChainReader + address []string + reader *wrappedTestChainReader +} + +func (r *chainReaderInterfaceTester) GetAccountBytes(i int) []byte { + account := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + account[i%20] += byte(i) + account[(i+3)%20] += byte(i + 3) + return account[:] +} + +func (r *chainReaderInterfaceTester) Name() string { + return "Solana" +} + +func (r *chainReaderInterfaceTester) Setup(t *testing.T) { + r.address = make([]string, 6) + for idx := range r.address { + r.address[idx] = ag_solana.NewWallet().PublicKey().String() + } + + r.conf = config.ChainReader{ + Namespaces: map[string]config.ChainReaderMethods{ + AnyContractName: { + Methods: map[string]config.ChainDataReader{ + MethodTakingLatestParamsReturningTestStruct: { + AnchorIDL: fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "TestStruct", + Type: config.ProcedureTypeAnchor, + }, + }, + }, + MethodReturningUint64: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "SimpleUint64Value", + Type: config.ProcedureTypeAnchor, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "I"}, + }, + }, + }, + }, + DifferentMethodReturningUint64: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "SimpleUint64Value", + Type: config.ProcedureTypeAnchor, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "I"}, + }, + }, + }, + }, + MethodReturningUint64Slice: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, ""), + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "Uint64Slice", + Type: config.ProcedureTypeAnchor, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "Vals"}, + }, + }, + }, + }, + MethodReturningSeenStruct: { + AnchorIDL: fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "TestStruct", + Type: config.ProcedureTypeAnchor, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, + // &codeccommon.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + }, + }, + }, + }, + }, + }, + AnySecondContractName: { + Methods: map[string]config.ChainDataReader{ + MethodReturningUint64: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "SimpleUint64Value", + Type: config.ProcedureTypeAnchor, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "I"}, + }, + }, + }, + }, + }, + }, + }, + } +} + +func (r *chainReaderInterfaceTester) GetChainReader(t *testing.T) types.ChainReader { + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, r.conf) + if err != nil { + t.Logf("chain reader service was not able to start: %s", err.Error()) + t.FailNow() + } + + if r.reader == nil { + r.reader = &wrappedTestChainReader{ + test: t, + tester: r, + } + } + + r.reader.service = svc + r.reader.client = client + + return r.reader +} + +type wrappedTestChainReader struct { + test *testing.T + service *chainreader.SolanaChainReaderService + client *mockedRPCClient + tester ChainReaderInterfaceTester + testStructQueue []*TestStruct +} + +func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractName string, method string, params, returnVal any) error { + switch contractName + method { + case AnyContractName + EventName: + // t.Skip won't skip the test here + // returning the expected error to satisfy the test + return types.ErrNotFound + case AnyContractName + MethodReturningUint64: + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, "")) + onChainStruct := struct { + I uint64 + }{ + I: AnyValueToReadWithoutAnArgument, + } + + bts, err := cdc.Encode(ctx, onChainStruct, "SimpleUint64Value") + if err != nil { + r.test.Log(err.Error()) + r.test.FailNow() + } + + r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + case AnyContractName + MethodReturningUint64Slice: + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, "")) + onChainStruct := struct { + Vals []uint64 + }{ + Vals: AnySliceToReadWithoutAnArgument, + } + + bts, err := cdc.Encode(ctx, onChainStruct, "Uint64Slice") + if err != nil { + r.test.FailNow() + } + + r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + case AnySecondContractName + MethodReturningUint64, AnyContractName + DifferentMethodReturningUint64: + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, "")) + onChainStruct := struct { + I uint64 + }{ + I: AnyDifferentValueToReadWithoutAnArgument, + } + + bts, err := cdc.Encode(ctx, onChainStruct, "SimpleUint64Value") + if err != nil { + r.test.FailNow() + } + + r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + case AnyContractName + MethodReturningSeenStruct: + nextStruct := CreateTestStruct(0, r.tester) + r.testStructQueue = append(r.testStructQueue, &nextStruct) + + fallthrough + default: + if r.testStructQueue == nil || len(r.testStructQueue) == 0 { + r.test.FailNow() + } + + nextTestStruct := r.testStructQueue[0] + r.testStructQueue = r.testStructQueue[1:len(r.testStructQueue)] + + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ","))) + bts, err := cdc.Encode(ctx, nextTestStruct, "TestStruct") + if err != nil { + r.test.FailNow() + } + + r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + } + + return r.service.GetLatestValue(ctx, contractName, method, params, returnVal) +} + +func (r *wrappedTestChainReader) Bind(ctx context.Context, bindings []types.BoundContract) error { + return r.service.Bind(ctx, bindings) +} + +func (r *wrappedTestChainReader) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { + if AnyContractName+EventName == contractName+itemType { + // events are not supported, so just make the tests pass + return nil, types.ErrNotFound + } + + return r.service.CreateContractType(contractName, itemType, forEncoding) +} + +// SetLatestValue is expected to return the same bound contract and method in the same test +// Any setup required for this should be done in Setup. +// The contract should take a LatestParams as the params and return the nth TestStruct set +func (r *chainReaderInterfaceTester) SetLatestValue(t *testing.T, testStruct *TestStruct) { + if r.reader == nil { + r.reader = &wrappedTestChainReader{ + test: t, + tester: r, + } + } + + r.reader.testStructQueue = append(r.reader.testStructQueue, testStruct) +} + +func (r *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *TestStruct) { + t.Skip("Events are not yet supported in Solana") +} + +func (r *chainReaderInterfaceTester) GetBindings(t *testing.T) []types.BoundContract { + return []types.BoundContract{ + {Name: strings.Join([]string{AnyContractName, MethodTakingLatestParamsReturningTestStruct, "0"}, "."), Address: r.address[0], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningUint64, "0"}, "."), Address: r.address[1], Pending: true}, + {Name: strings.Join([]string{AnyContractName, DifferentMethodReturningUint64, "0"}, "."), Address: r.address[2], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningUint64Slice, "0"}, "."), Address: r.address[3], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningSeenStruct, "0"}, "."), Address: r.address[4], Pending: true}, + {Name: strings.Join([]string{AnySecondContractName, MethodReturningUint64, "0"}, "."), Address: r.address[5], Pending: true}, + } +} + +func (r *chainReaderInterfaceTester) MaxWaitTimeForEvents() time.Duration { + // From trial and error, when running on CI, sometimes the boxes get slow + maxWaitTime := time.Second + maxWaitTimeStr, ok := os.LookupEnv("MAX_WAIT_TIME_FOR_EVENTS_S") + if ok { + wiatS, err := strconv.ParseInt(maxWaitTimeStr, 10, 64) + if err != nil { + fmt.Printf("Error parsing MAX_WAIT_TIME_FOR_EVENTS_S: %v, defaulting to %v\n", err, maxWaitTime) + } + maxWaitTime = time.Second * time.Duration(wiatS) + } + + return maxWaitTime +} + +func makeTestCodec(t *testing.T, rawIDL string) encodings.CodecFromTypeCodec { + t.Helper() + + var idl codec.IDL + if err := json.Unmarshal([]byte(rawIDL), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + testCodec, err := codec.NewIDLCodec(idl) + if err != nil { + t.Logf("failed to create new codec from test IDL: %s", err.Error()) + t.FailNow() + } + + return testCodec +} + +const ( + baseIDL = `{ + "version": "0.1.0", + "name": "some_test_idl", + "accounts": [%s], + "types": [%s] + }` + + testStructIDL = `{ + "name": "TestStruct", + "type": { + "kind": "struct", + "fields": [ + {"name": "field","type": {"option": "i32"}}, + {"name": "differentField","type": "string"}, + {"name": "oracleID","type": "u8"}, + {"name": "oracleIDs","type": {"array": ["u8",32]}}, + {"name": "account","type": "bytes"}, + {"name": "accounts","type": {"vec": "bytes"}}, + {"name": "bigField","type": "i128"}, + {"name": "nestedStruct","type": {"defined": "MidLevelStruct"}} + ] + } + }` + + midLevelStructIDL = `{ + "name": "MidLevelStruct", + "type": { + "kind": "struct", + "fields": [ + {"name": "fixedBytes", "type": {"array": ["u8",2]}}, + {"name": "inner", "type": {"defined": "InnerTestStruct"}} + ] + } + }` + + innerStructIDL = `{ + "name": "InnerTestStruct", + "type": { + "kind": "struct", + "fields": [ + {"name": "i", "type": "i32"}, + {"name": "s", "type": "string"} + ] + } + }` + + uint64BaseTypeIDL = `{ + "name": "SimpleUint64Value", + "type": { + "kind": "struct", + "fields": [ + {"name": "i", "type": "u64"} + ] + } + }` + + uint64SliceBaseTypeIDL = `{ + "name": "Uint64Slice", + "type": { + "kind": "struct", + "fields": [ + {"name": "vals", "type": {"vec": "u64"}} + ] + } + }` +) diff --git a/pkg/solana/codec/anchoridl.go b/pkg/solana/codec/anchoridl.go new file mode 100644 index 000000000..359409d5c --- /dev/null +++ b/pkg/solana/codec/anchoridl.go @@ -0,0 +1,403 @@ +package codec + +/* +copied from https://github.com/gagliardetto/anchor-go where the IDL definition is not importable due to being defined +in the `main` package. +*/ + +import ( + "encoding/json" + "fmt" + + "github.com/davecgh/go-spew/spew" + "github.com/gagliardetto/utilz" +) + +// https://github.com/project-serum/anchor/blob/97e9e03fb041b8b888a9876a7c0676d9bb4736f3/ts/src/idl.ts +type IDL struct { + Version string `json:"version"` + Name string `json:"name"` + Instructions []IdlInstruction `json:"instructions"` + Accounts IdlTypeDefSlice `json:"accounts,omitempty"` + Types IdlTypeDefSlice `json:"types,omitempty"` + Events []IdlEvent `json:"events,omitempty"` + Errors []IdlErrorCode `json:"errors,omitempty"` + Constants []IdlConstant `json:"constants,omitempty"` +} + +type IdlConstant struct { + Name string + Type IdlType + Value string +} + +type IdlTypeDefSlice []IdlTypeDef + +func (named IdlTypeDefSlice) GetByName(name string) *IdlTypeDef { + for i := range named { + v := named[i] + if v.Name == name { + return &v + } + } + return nil +} + +type IdlEvent struct { + Name string `json:"name"` + Fields []IdlEventField `json:"fields"` +} + +type IdlEventField struct { + Name string `json:"name"` + Type IdlType `json:"type"` + Index bool `json:"index"` +} + +type IdlInstruction struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Accounts IdlAccountItemSlice `json:"accounts"` + Args []IdlField `json:"args"` +} + +type IdlAccountItemSlice []IdlAccountItem + +func (slice IdlAccountItemSlice) NumAccounts() (count int) { + + for _, item := range slice { + if item.IdlAccount != nil { + count++ + } + + if item.IdlAccounts != nil { + count += item.IdlAccounts.Accounts.NumAccounts() + } + } + + return count +} + +// type IdlAccountItem = IdlAccount | IdlAccounts; +type IdlAccountItem struct { + IdlAccount *IdlAccount + IdlAccounts *IdlAccounts +} + +func (env *IdlAccountItem) UnmarshalJSON(data []byte) error { + var temp interface{} + if err := json.Unmarshal(data, &temp); err != nil { + return err + } + + if temp == nil { + return fmt.Errorf("envelope is nil: %v", env) + } + + switch v := temp.(type) { + case map[string]interface{}: + if len(v) == 0 { + return nil + } + + // Multiple accounts: + if _, ok := v["accounts"]; ok { + if err := utilz.TranscodeJSON(temp, &env.IdlAccounts); err != nil { + return err + } + } + // Single account: + // TODO: check both isMut and isSigner + if _, ok := v["isMut"]; ok { + if err := utilz.TranscodeJSON(temp, &env.IdlAccount); err != nil { + return err + } + } + default: + return fmt.Errorf("Unknown kind: %s", spew.Sdump(temp)) + } + + return nil +} + +type IdlAccount struct { + Docs []string `json:"docs"` // @custom + Name string `json:"name"` + IsMut bool `json:"isMut"` + IsSigner bool `json:"isSigner"` + Optional bool `json:"optional"` // @custom +} + +// A nested/recursive version of IdlAccount. +type IdlAccounts struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Accounts IdlAccountItemSlice `json:"accounts"` +} + +type IdlField struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Type IdlType `json:"type"` +} + +type IdlTypeAsString string + +const ( + IdlTypeBool IdlTypeAsString = "bool" + IdlTypeU8 IdlTypeAsString = "u8" + IdlTypeI8 IdlTypeAsString = "i8" + IdlTypeU16 IdlTypeAsString = "u16" + IdlTypeI16 IdlTypeAsString = "i16" + IdlTypeU32 IdlTypeAsString = "u32" + IdlTypeI32 IdlTypeAsString = "i32" + IdlTypeU64 IdlTypeAsString = "u64" + IdlTypeI64 IdlTypeAsString = "i64" + IdlTypeU128 IdlTypeAsString = "u128" + IdlTypeI128 IdlTypeAsString = "i128" + IdlTypeBytes IdlTypeAsString = "bytes" + IdlTypeString IdlTypeAsString = "string" + IdlTypePublicKey IdlTypeAsString = "publicKey" + + // Custom additions: + IdlTypeUnixTimestamp IdlTypeAsString = "unixTimestamp" + IdlTypeHash IdlTypeAsString = "hash" + IdlTypeDuration IdlTypeAsString = "duration" +) + +type IdlTypeVec struct { + Vec IdlType `json:"vec"` +} + +type IdlTypeOption struct { + Option IdlType `json:"option"` +} + +// User defined type. +type IdlTypeDefined struct { + Defined string `json:"defined"` +} + +// Wrapper type: +type IdlTypeArray struct { + Thing IdlType + Num int +} + +func (env *IdlType) UnmarshalJSON(data []byte) error { + var temp interface{} + if err := json.Unmarshal(data, &temp); err != nil { + return err + } + + if temp == nil { + return fmt.Errorf("envelope is nil: %v", env) + } + + switch v := temp.(type) { + case string: + env.asString = IdlTypeAsString(v) + case map[string]interface{}: + if len(v) == 0 { + return nil + } + + if _, ok := v["vec"]; ok { + var target IdlTypeVec + if err := utilz.TranscodeJSON(temp, &target); err != nil { + return err + } + env.asIdlTypeVec = &target + } + if _, ok := v["option"]; ok { + var target IdlTypeOption + if err := utilz.TranscodeJSON(temp, &target); err != nil { + return err + } + env.asIdlTypeOption = &target + } + if _, ok := v["defined"]; ok { + var target IdlTypeDefined + if err := utilz.TranscodeJSON(temp, &target); err != nil { + return err + } + env.asIdlTypeDefined = &target + } + if got, ok := v["array"]; ok { + + if _, ok := got.([]interface{}); !ok { + panic(utilz.Sf("array is not in expected format:\n%s", spew.Sdump(got))) + } + arrVal := got.([]interface{}) + if len(arrVal) != 2 { + panic(utilz.Sf("array is not of expected length:\n%s", spew.Sdump(got))) + } + var target IdlTypeArray + if err := utilz.TranscodeJSON(arrVal[0], &target.Thing); err != nil { + return err + } + + target.Num = int(arrVal[1].(float64)) + + env.asIdlTypeArray = &target + } + default: + return fmt.Errorf("Unknown kind: %s", spew.Sdump(temp)) + } + + return nil +} + +// Wrapper type: +type IdlType struct { + asString IdlTypeAsString + asIdlTypeVec *IdlTypeVec + asIdlTypeOption *IdlTypeOption + asIdlTypeDefined *IdlTypeDefined + asIdlTypeArray *IdlTypeArray +} + +func (env *IdlType) IsString() bool { + return env.asString != "" +} +func (env *IdlType) IsIdlTypeVec() bool { + return env.asIdlTypeVec != nil +} +func (env *IdlType) IsIdlTypeOption() bool { + return env.asIdlTypeOption != nil +} +func (env *IdlType) IsIdlTypeDefined() bool { + return env.asIdlTypeDefined != nil +} +func (env *IdlType) IsArray() bool { + return env.asIdlTypeArray != nil +} + +// Getters: +func (env *IdlType) GetString() IdlTypeAsString { + return env.asString +} +func (env *IdlType) GetIdlTypeVec() *IdlTypeVec { + return env.asIdlTypeVec +} +func (env *IdlType) GetIdlTypeOption() *IdlTypeOption { + return env.asIdlTypeOption +} +func (env *IdlType) GetIdlTypeDefined() *IdlTypeDefined { + return env.asIdlTypeDefined +} +func (env *IdlType) GetArray() *IdlTypeArray { + return env.asIdlTypeArray +} + +type IdlTypeDef struct { + Name string `json:"name"` + Type IdlTypeDefTy `json:"type"` +} + +type IdlTypeDefTyKind string + +const ( + IdlTypeDefTyKindStruct IdlTypeDefTyKind = "struct" + IdlTypeDefTyKindEnum IdlTypeDefTyKind = "enum" +) + +type IdlTypeDefTyStruct struct { + Kind IdlTypeDefTyKind `json:"kind"` // == "struct" + + Fields *IdlTypeDefStruct `json:"fields,omitempty"` +} + +type IdlTypeDefTyEnum struct { + Kind IdlTypeDefTyKind `json:"kind"` // == "enum" + + Variants IdlEnumVariantSlice `json:"variants,omitempty"` +} + +type IdlTypeDefTy struct { + Kind IdlTypeDefTyKind `json:"kind"` + + Fields *IdlTypeDefStruct `json:"fields,omitempty"` + Variants IdlEnumVariantSlice `json:"variants,omitempty"` +} + +type IdlEnumVariantSlice []IdlEnumVariant + +func (slice IdlEnumVariantSlice) IsAllUint8() bool { + for _, elem := range slice { + if !elem.IsUint8() { + return false + } + } + return true +} + +func (slice IdlEnumVariantSlice) IsSimpleEnum() bool { + return slice.IsAllUint8() +} + +type IdlTypeDefStruct = []IdlField + +type IdlEnumVariant struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Fields *IdlEnumFields `json:"fields,omitempty"` +} + +func (variant *IdlEnumVariant) IsUint8() bool { + // it's a simple uint8 if there is no fields data + return variant.Fields == nil +} + +// type IdlEnumFields = IdlEnumFieldsNamed | IdlEnumFieldsTuple; +type IdlEnumFields struct { + IdlEnumFieldsNamed *IdlEnumFieldsNamed + IdlEnumFieldsTuple *IdlEnumFieldsTuple +} + +type IdlEnumFieldsNamed []IdlField + +type IdlEnumFieldsTuple []IdlType + +// TODO: verify with examples +func (env *IdlEnumFields) UnmarshalJSON(data []byte) error { + var temp interface{} + if err := json.Unmarshal(data, &temp); err != nil { + return err + } + + if temp == nil { + return fmt.Errorf("envelope is nil: %v", env) + } + + switch v := temp.(type) { + case []interface{}: + if len(v) == 0 { + return nil + } + + firstItem := v[0] + + if _, ok := firstItem.(map[string]interface{})["name"]; ok { + // TODO: + // If has `name` field, then it's most likely a IdlEnumFieldsNamed. + if err := utilz.TranscodeJSON(temp, &env.IdlEnumFieldsNamed); err != nil { + return err + } + } else { + if err := utilz.TranscodeJSON(temp, &env.IdlEnumFieldsTuple); err != nil { + return err + } + } + default: + return fmt.Errorf("Unknown kind: %s", spew.Sdump(temp)) + } + + return nil +} + +type IdlErrorCode struct { + Code int `json:"code"` + Name string `json:"name"` + Msg string `json:"msg,omitempty"` +} diff --git a/pkg/solana/codec/duration.go b/pkg/solana/codec/duration.go new file mode 100644 index 000000000..e6e540778 --- /dev/null +++ b/pkg/solana/codec/duration.go @@ -0,0 +1,54 @@ +package codec + +import ( + "fmt" + "reflect" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func NewDuration(builder encodings.Builder) encodings.TypeCodec { + return &duration{ + intEncoder: builder.Int64(), + } +} + +type duration struct { + intEncoder encodings.TypeCodec +} + +var _ encodings.TypeCodec = &duration{} + +func (d *duration) Encode(value any, into []byte) ([]byte, error) { + bi, ok := value.(time.Duration) + if !ok { + return nil, fmt.Errorf("%w: expected time.Duration, got %T", types.ErrInvalidType, value) + } + + return d.intEncoder.Encode(int64(bi), into) +} + +func (d *duration) Decode(encoded []byte) (any, []byte, error) { + value, bytes, err := d.intEncoder.Decode(encoded) + + bi, ok := value.(int64) + if !ok { + return value, bytes, err + } + + return time.Duration(bi), bytes, nil +} + +func (d *duration) GetType() reflect.Type { + return reflect.TypeOf(time.Duration(0)) +} + +func (d *duration) Size(val int) (int, error) { + return d.intEncoder.Size(val) +} + +func (d *duration) FixedSize() (int, error) { + return d.intEncoder.FixedSize() +} diff --git a/pkg/solana/codec/solana.go b/pkg/solana/codec/solana.go new file mode 100644 index 000000000..2df40529d --- /dev/null +++ b/pkg/solana/codec/solana.go @@ -0,0 +1,326 @@ +/* +Package codec provides functions to create a codec from an Anchor IDL. All Anchor primitives map to the following native +Go values: + +bool -> bool +string -> string +bytes -> []byte +[u|i][8-64] -> [u]int[8-64] +[u|i]128 -> *big.Int +duration -> time.Duration +unixTimestamp -> int64 +publicKey -> [32]byte +hash -> [32]byte + +Enums as an Anchor data structure are only supported in their basic form of uint8 values. Enums with variants are not +supported at this time. + +Modifiers can be provided to assist in modifying property names, adding properties, etc. +*/ +package codec + +import ( + "fmt" + "math" + + "github.com/mitchellh/mapstructure" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +const ( + DefaultHashBitLength = 32 + unknownIDLFormat = "%w: unknown IDL type def %s" +) + +// BigIntHook allows *big.Int to be represented as any integer type or a string and to go back to them. +// Useful for config, or if when a model may use a go type that isn't a *big.Int when Pack expects one. +// Eg: int32 in a go struct from a plugin could require a *big.Int in Pack for int24, if it fits, we shouldn't care. +// SliceToArrayVerifySizeHook verifies that slices have the correct size when converting to an array +// EpochToTimeHook allows multiple conversions: time.Time -> int64; int64 -> time.Time; *big.Int -> time.Time; and more +var DecoderHooks = []mapstructure.DecodeHookFunc{codec.EpochToTimeHook, codec.BigIntHook, codec.SliceToArrayVerifySizeHook} + +func NewNamedModifierCodec(original types.RemoteCodec, itemType string, modifier codec.Modifier) (types.RemoteCodec, error) { + mod, err := codec.NewByItemTypeModifier(map[string]codec.Modifier{itemType: modifier}) + if err != nil { + return nil, err + } + + modCodec, err := codec.NewModifierCodec(original, mod, DecoderHooks...) + if err != nil { + return nil, err + } + + _, err = modCodec.CreateType(itemType, true) + + return modCodec, err +} + +// NewIDLCodec is for Anchor custom types +func NewIDLCodec(idl IDL) (encodings.CodecFromTypeCodec, error) { + accounts := make(map[string]encodings.TypeCodec) + + refs := &codecRefs{ + builder: binary.LittleEndian(), + codecs: make(map[string]encodings.TypeCodec), + typeDefs: idl.Types, + dependencies: make(map[string][]string), + } + + for _, account := range idl.Accounts { + var ( + name string + accCodec encodings.TypeCodec + err error + ) + + name, accCodec, err = createNamedCodec(account, refs) + if err != nil { + return nil, err + } + + accounts[name] = accCodec + } + + return encodings.CodecFromTypeCodec(accounts), nil +} + +type codecRefs struct { + builder encodings.Builder + codecs map[string]encodings.TypeCodec + typeDefs IdlTypeDefSlice + dependencies map[string][]string +} + +func createNamedCodec( + def IdlTypeDef, + refs *codecRefs, +) (string, encodings.TypeCodec, error) { + caser := cases.Title(language.English) + name := def.Name + + switch def.Type.Kind { + case IdlTypeDefTyKindStruct: + return asStruct(def, refs, name, caser) + case IdlTypeDefTyKindEnum: + variants := def.Type.Variants + if !variants.IsAllUint8() { + return name, nil, fmt.Errorf("%w: variants are not supported", types.ErrInvalidConfig) + } + + return name, refs.builder.Uint8(), nil + default: + return name, nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, def.Type.Kind) + } +} + +func asStruct( + def IdlTypeDef, + refs *codecRefs, + name string, // name is the struct name and can be used in dependency checks + caser cases.Caser, +) (string, encodings.TypeCodec, error) { + named := make([]encodings.NamedTypeCodec, len(*def.Type.Fields)) + + for idx, field := range *def.Type.Fields { + fieldName := field.Name + + typedCodec, err := processFieldType(name, field.Type, refs) + if err != nil { + return name, nil, err + } + + named[idx] = encodings.NamedTypeCodec{Name: caser.String(fieldName), Codec: typedCodec} + } + + structCodec, err := encodings.NewStructCodec(named) + if err != nil { + return name, nil, err + } + + return name, structCodec, nil +} + +func processFieldType(parentTypeName string, idlType IdlType, refs *codecRefs) (encodings.TypeCodec, error) { + switch true { + case idlType.IsString(): + return getCodecByStringType(idlType.GetString(), refs.builder) + case idlType.IsIdlTypeOption(): + // Go doesn't have an `Option` type; use pointer to type instead + // this should be automatic in the codec + return processFieldType(parentTypeName, idlType.GetIdlTypeOption().Option, refs) + case idlType.IsIdlTypeDefined(): + return asDefined(parentTypeName, idlType.GetIdlTypeDefined(), refs) + case idlType.IsArray(): + return asArray(parentTypeName, idlType.GetArray(), refs) + case idlType.IsIdlTypeVec(): + return asVec(parentTypeName, idlType.GetIdlTypeVec(), refs) + default: + return nil, fmt.Errorf("%w: unknown IDL type def", types.ErrInvalidConfig) + } +} + +func asDefined(parentTypeName string, definedName *IdlTypeDefined, refs *codecRefs) (encodings.TypeCodec, error) { + if definedName == nil { + return nil, fmt.Errorf("%w: defined type name should not be nil", types.ErrInvalidConfig) + } + + // already exists as a type in the typed codecs + if savedCodec, ok := refs.codecs[definedName.Defined]; ok { + return savedCodec, nil + } + + // nextDef should not have a dependency on definedName + if !validDependency(refs, parentTypeName, definedName.Defined) { + return nil, fmt.Errorf("%w: circular dependency detected on %s -> %s relation", types.ErrInvalidConfig, parentTypeName, definedName.Defined) + } + + // codec by defined type doesn't exist + // process it using the provided typeDefs + nextDef := refs.typeDefs.GetByName(definedName.Defined) + if nextDef == nil { + return nil, fmt.Errorf("%w: IDL type does not exist for name %s", types.ErrInvalidConfig, definedName.Defined) + } + + saveDependency(refs, parentTypeName, definedName.Defined) + + newTypeName, newTypeCodec, err := createNamedCodec(*nextDef, refs) + if err != nil { + return nil, err + } + + // we know that recursive found codecs are types so add them to the type lookup + refs.codecs[newTypeName] = newTypeCodec + + return newTypeCodec, nil +} + +func asArray(parentTypeName string, idlArray *IdlTypeArray, refs *codecRefs) (encodings.TypeCodec, error) { + codec, err := processFieldType(parentTypeName, idlArray.Thing, refs) + if err != nil { + return nil, err + } + + return encodings.NewArray(idlArray.Num, codec) +} + +func asVec(parentTypeName string, idlVec *IdlTypeVec, refs *codecRefs) (encodings.TypeCodec, error) { + codec, err := processFieldType(parentTypeName, idlVec.Vec, refs) + if err != nil { + return nil, err + } + + b, err := refs.builder.Int(4) + if err != nil { + return nil, err + } + + return encodings.NewSlice(codec, b) +} + +func getCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeBool: + return builder.Bool(), nil + case IdlTypeString: + return builder.String(math.MaxUint32) + case IdlTypeI8, IdlTypeI16, IdlTypeI32, IdlTypeI64, IdlTypeI128: + return getIntCodecByStringType(curType, builder) + case IdlTypeU8, IdlTypeU16, IdlTypeU32, IdlTypeU64, IdlTypeU128: + return getUIntCodecByStringType(curType, builder) + case IdlTypeUnixTimestamp, IdlTypeDuration: + return getTimeCodecByStringType(curType, builder) + case IdlTypeBytes, IdlTypePublicKey, IdlTypeHash: + return getByteCodecByStringType(curType, builder) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getIntCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeI8: + return builder.Int8(), nil + case IdlTypeI16: + return builder.Int16(), nil + case IdlTypeI32: + return builder.Int32(), nil + case IdlTypeI64: + return builder.Int64(), nil + case IdlTypeI128: + return builder.BigInt(16, true) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getUIntCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeU8: + return builder.Uint8(), nil + case IdlTypeU16: + return builder.Uint16(), nil + case IdlTypeU32: + return builder.Uint32(), nil + case IdlTypeU64: + return builder.Uint64(), nil + case IdlTypeU128: + return builder.BigInt(16, true) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getTimeCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeUnixTimestamp: + return builder.Int64(), nil + case IdlTypeDuration: + return NewDuration(builder), nil + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getByteCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeBytes: + b, err := builder.Int(4) + if err != nil { + return nil, err + } + + return encodings.NewSlice(builder.Uint8(), b) + case IdlTypePublicKey, IdlTypeHash: + return encodings.NewArray(DefaultHashBitLength, builder.Uint8()) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func validDependency(refs *codecRefs, parent, child string) bool { + deps, ok := refs.dependencies[child] + if ok { + for _, dep := range deps { + if dep == parent { + return false + } + } + } + + return true +} + +func saveDependency(refs *codecRefs, parent, child string) { + deps, ok := refs.dependencies[parent] + if !ok { + deps = make([]string, 0) + } + + refs.dependencies[parent] = append(deps, child) +} diff --git a/pkg/solana/codec/solana_test.go b/pkg/solana/codec/solana_test.go new file mode 100644 index 000000000..48415dd07 --- /dev/null +++ b/pkg/solana/codec/solana_test.go @@ -0,0 +1,139 @@ +package codec_test + +import ( + "encoding/json" + "testing" + "time" + + ag_solana "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec/testutils" +) + +func TestNewIDLCodec(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + _, _, entry := newTestIDLAndCodec(t) + + expected := testutils.DefaultTestStruct + bts, err := entry.Encode(ctx, expected, testutils.TestStructWithNestedStruct) + + require.NoError(t, err) + + var decoded testutils.StructWithNestedStruct + + require.NoError(t, entry.Decode(ctx, bts, &decoded, testutils.TestStructWithNestedStruct)) + require.Equal(t, expected, decoded) +} + +func TestNewIDLCodec_WithModifiers(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + _, _, idlCodec := newTestIDLAndCodec(t) + modConfig := codeccommon.ModifiersConfig{ + &codeccommon.RenameModifierConfig{Fields: map[string]string{"Value": "V"}}, + } + + renameMod, err := modConfig.ToModifier(codec.DecoderHooks...) + require.NoError(t, err) + + idlCodecWithMods, err := codec.NewNamedModifierCodec(idlCodec, testutils.TestStructWithNestedStruct, renameMod) + require.NoError(t, err) + + type modifiedTestStruct struct { + V uint8 + InnerStruct testutils.ObjectRef1 + BasicNestedArray [][]uint32 + Option *string + DefinedArray []testutils.ObjectRef2 + BasicVector []string + TimeVal int64 + DurationVal time.Duration + PublicKey ag_solana.PublicKey + EnumVal uint8 + } + + expected := modifiedTestStruct{ + V: testutils.DefaultTestStruct.Value, + InnerStruct: testutils.DefaultTestStruct.InnerStruct, + BasicNestedArray: testutils.DefaultTestStruct.BasicNestedArray, + Option: testutils.DefaultTestStruct.Option, + DefinedArray: testutils.DefaultTestStruct.DefinedArray, + BasicVector: testutils.DefaultTestStruct.BasicVector, + TimeVal: testutils.DefaultTestStruct.TimeVal, + DurationVal: testutils.DefaultTestStruct.DurationVal, + PublicKey: testutils.DefaultTestStruct.PublicKey, + EnumVal: testutils.DefaultTestStruct.EnumVal, + } + + withModsBts, err := idlCodecWithMods.Encode(ctx, expected, testutils.TestStructWithNestedStruct) + require.NoError(t, err) + + noModsBts, err := idlCodec.Encode(ctx, testutils.DefaultTestStruct, testutils.TestStructWithNestedStruct) + + // the codec without modifiers should encode an unmodified struct to the same bytes + // as the codec with modifiers encodes a modified struct + require.NoError(t, err) + require.Equal(t, withModsBts, noModsBts) + + var decoded modifiedTestStruct + + // the codec with modifiers should decode from unmodified bytes into a modified struct + require.NoError(t, idlCodecWithMods.Decode(ctx, noModsBts, &decoded, testutils.TestStructWithNestedStruct)) + require.Equal(t, expected, decoded) + + var unmodifiedDecoded testutils.StructWithNestedStruct + + // the codec without modifiers should decode from unmodified bytes to the same values as + // modified struct + require.NoError(t, idlCodec.Decode(ctx, noModsBts, &unmodifiedDecoded, testutils.TestStructWithNestedStruct)) + require.Equal(t, expected.V, unmodifiedDecoded.Value) + require.Equal(t, expected.TimeVal, unmodifiedDecoded.TimeVal) + require.Equal(t, expected.DurationVal, unmodifiedDecoded.DurationVal) + require.Equal(t, expected.PublicKey, unmodifiedDecoded.PublicKey) + require.Equal(t, expected.EnumVal, unmodifiedDecoded.EnumVal) +} + +func TestNewIDLCodec_CircularDependency(t *testing.T) { + t.Parallel() + + var idl codec.IDL + if err := json.Unmarshal([]byte(testutils.CircularDepIDL), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + _, err := codec.NewIDLCodec(idl) + + assert.ErrorIs(t, err, types.ErrInvalidConfig) +} + +func newTestIDLAndCodec(t *testing.T) (string, codec.IDL, encodings.CodecFromTypeCodec) { + t.Helper() + + var idl codec.IDL + if err := json.Unmarshal([]byte(testutils.JSONIDLWithAllTypes), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + entry, err := codec.NewIDLCodec(idl) + if err != nil { + t.Logf("failed to create new codec from test IDL: %s", err.Error()) + t.FailNow() + } + + require.NotNil(t, entry) + + return testutils.JSONIDLWithAllTypes, idl, entry +} diff --git a/pkg/solana/codec/testutils/circularDepIDL.json b/pkg/solana/codec/testutils/circularDepIDL.json new file mode 100644 index 000000000..fb896f088 --- /dev/null +++ b/pkg/solana/codec/testutils/circularDepIDL.json @@ -0,0 +1,42 @@ +{ + "accounts": [{ + "name": "TopLevelStruct", + "type": { + "kind": "struct", + "fields": [{ + "name": "circularOne", + "type": { + "defined": "TypeOne" + } + }, { + "name": "circularTwo", + "type": { + "defined": "TypeTwo" + } + }] + } + }], + "types": [{ + "name": "TypeOne", + "type": { + "kind": "struct", + "fields": [{ + "name": "circular", + "type": { + "defined": "TypeTwo" + } + }] + } + }, { + "name": "TypeTwo", + "type": { + "kind": "struct", + "fields": [{ + "name": "circular", + "type": { + "defined": "TypeOne" + } + }] + } + }] +} \ No newline at end of file diff --git a/pkg/solana/codec/testutils/testIDL.json b/pkg/solana/codec/testutils/testIDL.json new file mode 100644 index 000000000..d05496ee5 --- /dev/null +++ b/pkg/solana/codec/testutils/testIDL.json @@ -0,0 +1,159 @@ +{ + "version": "0.1.0", + "name": "some_test_idl", + "accounts": [ + { + "name": "StructWithNestedStruct", + "type": { + "kind": "struct", + "fields": [ + { + "name": "value", + "type": "u8" + }, + { + "name": "innerStruct", + "type": { + "defined": "ObjectRef1" + } + }, + { + "name": "basicNestedArray", + "type": { + "array": [ + { + "array": [ + "u32", + 3 + ] + }, + 3 + ] + } + }, + { + "name": "option", + "type": { + "option": "string" + } + }, + { + "name": "definedArray", + "type": { + "array": [ + { + "defined": "ObjectRef2" + }, + 2 + ] + } + }, + { + "name": "basicVector", + "type": { + "vec": "string" + } + }, + { + "name": "timeVal", + "type": "unixTimestamp" + }, + { + "name": "durationVal", + "type": "duration" + }, + { + "name": "publicKey", + "type": "publicKey" + }, + { + "name": "enumVal", + "type": { + "defined": "SimpleEnum" + } + } + ] + } + } + ], + "types": [ + { + "name": "ObjectRef1", + "type": { + "kind": "struct", + "fields": [ + { + "name": "prop1", + "type": "i8" + }, + { + "name": "prop2", + "type": "string" + }, + { + "name": "prop3", + "type": "u128" + }, + { + "name": "prop4", + "type": "u16" + }, + { + "name": "prop5", + "type": "u64" + }, + { + "name": "prop6", + "type": "bool" + } + ] + } + }, + { + "name": "ObjectRef2", + "type": { + "kind": "struct", + "fields": [ + { + "name": "prop1", + "type": "u32" + }, + { + "name": "prop2", + "type": "i128" + }, + { + "name": "prop3", + "type": "i16" + }, + { + "name": "prop4", + "type": "i32" + }, + { + "name": "prop5", + "type": "i64" + }, + { + "name": "prop6", + "type": "bytes" + } + ] + } + }, + { + "name": "SimpleEnum", + "type": { + "kind": "enum", + "variants": [ + { + "name": "A" + }, + { + "name": "B" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/solana/codec/testutils/types.go b/pkg/solana/codec/testutils/types.go new file mode 100644 index 000000000..7c20762f7 --- /dev/null +++ b/pkg/solana/codec/testutils/types.go @@ -0,0 +1,87 @@ +package testutils + +import ( + _ "embed" + "math/big" + "time" + + ag_solana "github.com/gagliardetto/solana-go" +) + +var ( + TestStructWithNestedStruct = "StructWithNestedStruct" + DefaultStringRef = "test string" + DefaultTestStruct = StructWithNestedStruct{ + Value: 80, + InnerStruct: ObjectRef1{ + Prop1: 10, + Prop2: "some_val", + Prop3: new(big.Int).SetUint64(42), + Prop4: 42, + Prop5: 42, + Prop6: true, + }, + BasicNestedArray: [][]uint32{{5, 6, 7}, {0, 0, 0}, {0, 0, 0}}, + Option: &DefaultStringRef, + DefinedArray: []ObjectRef2{ + { + Prop1: 42, + Prop2: new(big.Int).SetInt64(42), + Prop3: 43, + Prop4: 44, + Prop5: 45, + Prop6: []byte{}, + }, + { + Prop1: 46, + Prop2: new(big.Int).SetInt64(46), + Prop3: 47, + Prop4: 48, + Prop5: 49, + Prop6: []byte{}, + }, + }, + BasicVector: []string{"some string", "another string"}, + TimeVal: 683_100_000, + DurationVal: 42 * time.Second, + PublicKey: ag_solana.NewWallet().PublicKey(), + EnumVal: 0, + } +) + +type StructWithNestedStruct struct { + Value uint8 + InnerStruct ObjectRef1 + BasicNestedArray [][]uint32 + Option *string + DefinedArray []ObjectRef2 + BasicVector []string + TimeVal int64 + DurationVal time.Duration + PublicKey ag_solana.PublicKey + EnumVal uint8 +} + +type ObjectRef1 struct { + Prop1 int8 + Prop2 string + Prop3 *big.Int + Prop4 uint16 + Prop5 uint64 + Prop6 bool +} + +type ObjectRef2 struct { + Prop1 uint32 + Prop2 *big.Int + Prop3 int16 + Prop4 int32 + Prop5 int64 + Prop6 []byte +} + +//go:embed testIDL.json +var JSONIDLWithAllTypes string + +//go:embed circularDepIDL.json +var CircularDepIDL string diff --git a/pkg/solana/config/chain_reader.go b/pkg/solana/config/chain_reader.go new file mode 100644 index 000000000..980f6c535 --- /dev/null +++ b/pkg/solana/config/chain_reader.go @@ -0,0 +1,39 @@ +package config + +import "github.com/smartcontractkit/chainlink-common/pkg/codec" + +type ChainReader struct { + Namespaces map[string]ChainReaderMethods `json:"namespaces" toml:"namespaces"` +} + +type ChainReaderMethods struct { + Methods map[string]ChainDataReader `json:"methods" toml:"methods"` +} + +type ChainDataReader struct { + AnchorIDL string `json:"anchorIDL" toml:"anchorIDL"` + Procedures []ChainReaderProcedure `json:"procedures" toml:"procedures"` +} + +type ProcedureType int + +const ( + ProcedureTypeInternal ProcedureType = iota + ProcedureTypeAnchor +) + +type ChainReaderProcedure chainDataProcedureFields + +type chainDataProcedureFields struct { + // IDLAccount refers to the account defined in the IDL. + IDLAccount string `json:"idlAccount"` + // Type describes the procedure type to use such as internal for static values, + // anchor-read for using an anchor generated IDL to read values from an account, + // or custom structure for reading from a native account. Currently, only anchor + // reads are supported, but the type is a placeholder to allow internal functions + // to be run apart from anchor reads. + Type ProcedureType `json:"type"` + // OutputModifications provides modifiers to convert chain data format to custom + // output formats. + OutputModifications codec.ModifiersConfig `json:"outputModifications,omitempty"` +} diff --git a/sonar-project.properties b/sonar-project.properties index 7f64da7db..0434465b5 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.projectKey=smartcontractkit_chainlink-solana sonar.sources=. # Full exclusions from the static analysis -sonar.exclusions=**/node_modules/**/*, **/contracts/artifacts/**/*, **/generated/**/*, **/docs/**/*, **/*.config.ts, **/*.config.js, **/*.txt +sonar.exclusions=**/node_modules/**/*, **/contracts/artifacts/**/*, **/generated/**/*, **/docs/**/*, **/*.config.ts, **/*.config.js, **/*.txt, pkg/solana/codec/anchoridl.go # Coverage exclusions sonar.coverage.exclusions=**/*.test.ts, **/*_test.go, **/contracts/tests/**/*, **/integration-tests/**/* From fc4541c16dcef7988e18c7d9b73983e1ae67c268 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:06:08 +0000 Subject: [PATCH 02/14] [automated] bump solana image to v1.17.26 (#626) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- integration-tests/docker/test_env/sol.go | 2 +- scripts/install-solana-ci.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/docker/test_env/sol.go b/integration-tests/docker/test_env/sol.go index d7edb2805..3b05658c3 100644 --- a/integration-tests/docker/test_env/sol.go +++ b/integration-tests/docker/test_env/sol.go @@ -157,7 +157,7 @@ func (ms *Solana) getContainerRequest(inactiveFeatures InactiveFeatures) (*tc.Co return &tc.ContainerRequest{ Name: ms.ContainerName, - Image: "solanalabs/solana:v1.17.25", + Image: "solanalabs/solana:v1.17.26", ExposedPorts: []string{test_env.NatPortFormat(SOL_HTTP_PORT), test_env.NatPortFormat(SOL_WS_PORT)}, Env: map[string]string{ "SERVER_PORT": "1080", diff --git a/scripts/install-solana-ci.sh b/scripts/install-solana-ci.sh index 117639c3a..e71eeda72 100755 --- a/scripts/install-solana-ci.sh +++ b/scripts/install-solana-ci.sh @@ -2,5 +2,5 @@ set -euxo pipefail -sh -c "$(curl -sSfL https://release.solana.com/v1.17.25/install)" +sh -c "$(curl -sSfL https://release.solana.com/v1.17.26/install)" echo "PATH=$HOME/.local/share/solana/install/active_release/bin:$PATH" >> $GITHUB_ENV From 786829f2fff78400faddd388dac1abc12588b060 Mon Sep 17 00:00:00 2001 From: Awbrey Hughlett Date: Fri, 15 Mar 2024 13:36:49 -0500 Subject: [PATCH 03/14] BCF-3015 Add Configuration for Encoding (#616) Solana allows multiple encoding types for account data. This commit adds support for two encoding types `borsh` and `bincode`. --- pkg/solana/chainreader/chain_reader.go | 2 +- pkg/solana/chainreader/chain_reader_test.go | 28 ++--- pkg/solana/codec/solana.go | 5 +- pkg/solana/codec/solana_test.go | 5 +- pkg/solana/config/chain_reader.go | 74 +++++++++-- pkg/solana/config/chain_reader_test.go | 118 ++++++++++++++++++ .../config/testChainReader_invalid.json | 15 +++ pkg/solana/config/testChainReader_valid.json | 37 ++++++ 8 files changed, 252 insertions(+), 32 deletions(-) create mode 100644 pkg/solana/config/chain_reader_test.go create mode 100644 pkg/solana/config/testChainReader_invalid.json create mode 100644 pkg/solana/config/testChainReader_valid.json diff --git a/pkg/solana/chainreader/chain_reader.go b/pkg/solana/chainreader/chain_reader.go index 3418b59ff..97be00f50 100644 --- a/pkg/solana/chainreader/chain_reader.go +++ b/pkg/solana/chainreader/chain_reader.go @@ -120,7 +120,7 @@ func (s *SolanaChainReaderService) init(namespaces map[string]config.ChainReader return err } - idlCodec, err := codec.NewIDLCodec(idl) + idlCodec, err := codec.NewIDLCodec(idl, config.BuilderForEncoding(method.Encoding)) if err != nil { return err } diff --git a/pkg/solana/chainreader/chain_reader_test.go b/pkg/solana/chainreader/chain_reader_test.go index 2daa5fc12..11caaaa0e 100644 --- a/pkg/solana/chainreader/chain_reader_test.go +++ b/pkg/solana/chainreader/chain_reader_test.go @@ -17,6 +17,7 @@ import ( codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" "github.com/smartcontractkit/chainlink-common/pkg/logger" commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -239,7 +240,7 @@ func newTestIDLAndCodec(t *testing.T) (string, codec.IDL, encodings.CodecFromTyp t.FailNow() } - entry, err := codec.NewIDLCodec(idl) + entry, err := codec.NewIDLCodec(idl, binary.LittleEndian()) if err != nil { t.Logf("failed to create new codec from test IDL: %s", err.Error()) t.FailNow() @@ -263,7 +264,6 @@ func newTestConfAndCodec(t *testing.T) (encodings.CodecFromTypeCodec, config.Cha Procedures: []config.ChainReaderProcedure{ { IDLAccount: testutils.TestStructWithNestedStruct, - Type: config.ProcedureTypeAnchor, OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.RenameModifierConfig{Fields: map[string]string{"Value": "V"}}, }, @@ -337,19 +337,19 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { Methods: map[string]config.ChainDataReader{ MethodTakingLatestParamsReturningTestStruct: { AnchorIDL: fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), + Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { IDLAccount: "TestStruct", - Type: config.ProcedureTypeAnchor, }, }, }, MethodReturningUint64: { AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { IDLAccount: "SimpleUint64Value", - Type: config.ProcedureTypeAnchor, OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.PropertyExtractorConfig{FieldName: "I"}, }, @@ -358,10 +358,10 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { }, DifferentMethodReturningUint64: { AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { IDLAccount: "SimpleUint64Value", - Type: config.ProcedureTypeAnchor, OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.PropertyExtractorConfig{FieldName: "I"}, }, @@ -370,10 +370,10 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { }, MethodReturningUint64Slice: { AnchorIDL: fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, ""), + Encoding: config.EncodingTypeBincode, Procedures: []config.ChainReaderProcedure{ { IDLAccount: "Uint64Slice", - Type: config.ProcedureTypeAnchor, OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.PropertyExtractorConfig{FieldName: "Vals"}, }, @@ -382,10 +382,10 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { }, MethodReturningSeenStruct: { AnchorIDL: fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), + Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { IDLAccount: "TestStruct", - Type: config.ProcedureTypeAnchor, OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, // &codeccommon.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, @@ -399,10 +399,10 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { Methods: map[string]config.ChainDataReader{ MethodReturningUint64: { AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { IDLAccount: "SimpleUint64Value", - Type: config.ProcedureTypeAnchor, OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.PropertyExtractorConfig{FieldName: "I"}, }, @@ -451,7 +451,7 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam // returning the expected error to satisfy the test return types.ErrNotFound case AnyContractName + MethodReturningUint64: - cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, "")) + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), config.EncodingTypeBorsh) onChainStruct := struct { I uint64 }{ @@ -466,7 +466,7 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() case AnyContractName + MethodReturningUint64Slice: - cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, "")) + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, ""), config.EncodingTypeBincode) onChainStruct := struct { Vals []uint64 }{ @@ -480,7 +480,7 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() case AnySecondContractName + MethodReturningUint64, AnyContractName + DifferentMethodReturningUint64: - cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, "")) + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), config.EncodingTypeBorsh) onChainStruct := struct { I uint64 }{ @@ -506,7 +506,7 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam nextTestStruct := r.testStructQueue[0] r.testStructQueue = r.testStructQueue[1:len(r.testStructQueue)] - cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ","))) + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), config.EncodingTypeBorsh) bts, err := cdc.Encode(ctx, nextTestStruct, "TestStruct") if err != nil { r.test.FailNow() @@ -575,7 +575,7 @@ func (r *chainReaderInterfaceTester) MaxWaitTimeForEvents() time.Duration { return maxWaitTime } -func makeTestCodec(t *testing.T, rawIDL string) encodings.CodecFromTypeCodec { +func makeTestCodec(t *testing.T, rawIDL string, encoding config.EncodingType) encodings.CodecFromTypeCodec { t.Helper() var idl codec.IDL @@ -584,7 +584,7 @@ func makeTestCodec(t *testing.T, rawIDL string) encodings.CodecFromTypeCodec { t.FailNow() } - testCodec, err := codec.NewIDLCodec(idl) + testCodec, err := codec.NewIDLCodec(idl, config.BuilderForEncoding(encoding)) if err != nil { t.Logf("failed to create new codec from test IDL: %s", err.Error()) t.FailNow() diff --git a/pkg/solana/codec/solana.go b/pkg/solana/codec/solana.go index 2df40529d..aecdbf612 100644 --- a/pkg/solana/codec/solana.go +++ b/pkg/solana/codec/solana.go @@ -29,7 +29,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" - "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -62,11 +61,11 @@ func NewNamedModifierCodec(original types.RemoteCodec, itemType string, modifier } // NewIDLCodec is for Anchor custom types -func NewIDLCodec(idl IDL) (encodings.CodecFromTypeCodec, error) { +func NewIDLCodec(idl IDL, builder encodings.Builder) (encodings.CodecFromTypeCodec, error) { accounts := make(map[string]encodings.TypeCodec) refs := &codecRefs{ - builder: binary.LittleEndian(), + builder: builder, codecs: make(map[string]encodings.TypeCodec), typeDefs: idl.Types, dependencies: make(map[string][]string), diff --git a/pkg/solana/codec/solana_test.go b/pkg/solana/codec/solana_test.go index 48415dd07..73bcf28d8 100644 --- a/pkg/solana/codec/solana_test.go +++ b/pkg/solana/codec/solana_test.go @@ -11,6 +11,7 @@ import ( codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -113,7 +114,7 @@ func TestNewIDLCodec_CircularDependency(t *testing.T) { t.FailNow() } - _, err := codec.NewIDLCodec(idl) + _, err := codec.NewIDLCodec(idl, binary.LittleEndian()) assert.ErrorIs(t, err, types.ErrInvalidConfig) } @@ -127,7 +128,7 @@ func newTestIDLAndCodec(t *testing.T) (string, codec.IDL, encodings.CodecFromTyp t.FailNow() } - entry, err := codec.NewIDLCodec(idl) + entry, err := codec.NewIDLCodec(idl, binary.LittleEndian()) if err != nil { t.Logf("failed to create new codec from test IDL: %s", err.Error()) t.FailNow() diff --git a/pkg/solana/config/chain_reader.go b/pkg/solana/config/chain_reader.go index 980f6c535..f770c0939 100644 --- a/pkg/solana/config/chain_reader.go +++ b/pkg/solana/config/chain_reader.go @@ -1,6 +1,14 @@ package config -import "github.com/smartcontractkit/chainlink-common/pkg/codec" +import ( + "encoding/json" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) type ChainReader struct { Namespaces map[string]ChainReaderMethods `json:"namespaces" toml:"namespaces"` @@ -11,29 +19,71 @@ type ChainReaderMethods struct { } type ChainDataReader struct { - AnchorIDL string `json:"anchorIDL" toml:"anchorIDL"` + AnchorIDL string `json:"anchorIDL" toml:"anchorIDL"` + // Encoding defines the type of encoding used for on-chain data. Currently supported + // are 'borsh' and 'bincode'. + Encoding EncodingType `json:"encoding" toml:"encoding"` Procedures []ChainReaderProcedure `json:"procedures" toml:"procedures"` } -type ProcedureType int +type EncodingType int const ( - ProcedureTypeInternal ProcedureType = iota - ProcedureTypeAnchor + EncodingTypeBorsh EncodingType = iota + EncodingTypeBincode + + encodingTypeBorshStr = "borsh" + encodingTypeBincodeStr = "bincode" ) +func (t EncodingType) MarshalJSON() ([]byte, error) { + switch t { + case EncodingTypeBorsh: + return json.Marshal(encodingTypeBorshStr) + case EncodingTypeBincode: + return json.Marshal(encodingTypeBincodeStr) + default: + return nil, fmt.Errorf("%w: unrecognized encoding type: %d", types.ErrInvalidConfig, t) + } +} + +func (t *EncodingType) UnmarshalJSON(data []byte) error { + var str string + + if err := json.Unmarshal(data, &str); err != nil { + return fmt.Errorf("%w: %s", types.ErrInvalidConfig, err.Error()) + } + + switch str { + case encodingTypeBorshStr: + *t = EncodingTypeBorsh + case encodingTypeBincodeStr: + *t = EncodingTypeBincode + default: + return fmt.Errorf("%w: unrecognized encoding type: %s", types.ErrInvalidConfig, str) + } + + return nil +} + type ChainReaderProcedure chainDataProcedureFields type chainDataProcedureFields struct { // IDLAccount refers to the account defined in the IDL. - IDLAccount string `json:"idlAccount"` - // Type describes the procedure type to use such as internal for static values, - // anchor-read for using an anchor generated IDL to read values from an account, - // or custom structure for reading from a native account. Currently, only anchor - // reads are supported, but the type is a placeholder to allow internal functions - // to be run apart from anchor reads. - Type ProcedureType `json:"type"` + IDLAccount string `json:"idlAccount,omitempty"` // OutputModifications provides modifiers to convert chain data format to custom // output formats. OutputModifications codec.ModifiersConfig `json:"outputModifications,omitempty"` } + +// BuilderForEncoding returns a builder for the encoding configuration. Defaults to little endian. +func BuilderForEncoding(eType EncodingType) encodings.Builder { + switch eType { + case EncodingTypeBorsh: + return binary.LittleEndian() + case EncodingTypeBincode: + return binary.BigEndian() + default: + return binary.LittleEndian() + } +} diff --git a/pkg/solana/config/chain_reader_test.go b/pkg/solana/config/chain_reader_test.go new file mode 100644 index 000000000..26ac5ef91 --- /dev/null +++ b/pkg/solana/config/chain_reader_test.go @@ -0,0 +1,118 @@ +package config_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec/testutils" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +//go:embed testChainReader_valid.json +var validJSON string + +//go:embed testChainReader_invalid.json +var invalidJSON string + +func TestChainReaderConfig(t *testing.T) { + t.Parallel() + + t.Run("valid unmarshal", func(t *testing.T) { + t.Parallel() + + var result config.ChainReader + require.NoError(t, json.Unmarshal([]byte(validJSON), &result)) + assert.Equal(t, validChainReaderConfig, result) + }) + + t.Run("invalid unmarshal", func(t *testing.T) { + t.Parallel() + + var result config.ChainReader + require.ErrorIs(t, json.Unmarshal([]byte(invalidJSON), &result), types.ErrInvalidConfig) + }) + + t.Run("marshal", func(t *testing.T) { + t.Parallel() + + result, err := json.Marshal(validChainReaderConfig) + + require.NoError(t, err) + + var conf config.ChainReader + + require.NoError(t, json.Unmarshal(result, &conf)) + assert.Equal(t, validChainReaderConfig, conf) + }) +} + +func TestEncodingType_Fail(t *testing.T) { + t.Parallel() + + _, err := json.Marshal(config.EncodingType(100)) + + require.NotNil(t, err) + + var tp config.EncodingType + + require.ErrorIs(t, json.Unmarshal([]byte(`42`), &tp), types.ErrInvalidConfig) + require.ErrorIs(t, json.Unmarshal([]byte(`"invalid"`), &tp), types.ErrInvalidConfig) +} + +func TestBuilderForEncoding_Default(t *testing.T) { + t.Parallel() + + builder := config.BuilderForEncoding(config.EncodingType(100)) + require.Equal(t, binary.LittleEndian(), builder) +} + +var validChainReaderConfig = config.ChainReader{ + Namespaces: map[string]config.ChainReaderMethods{ + "Contract": { + Methods: map[string]config.ChainDataReader{ + "Method": { + AnchorIDL: "test idl 1", + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + }, + }, + }, + "MethodWithOpts": { + AnchorIDL: "test idl 2", + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "DurationVal"}, + }, + }, + }, + }, + }, + }, + "OtherContract": { + Methods: map[string]config.ChainDataReader{ + "Method": { + AnchorIDL: "test idl 3", + Encoding: config.EncodingTypeBincode, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + }, + }, + }, + }, + }, + }, +} diff --git a/pkg/solana/config/testChainReader_invalid.json b/pkg/solana/config/testChainReader_invalid.json new file mode 100644 index 000000000..b428b6115 --- /dev/null +++ b/pkg/solana/config/testChainReader_invalid.json @@ -0,0 +1,15 @@ +{ + "namespaces": { + "Contract": { + "methods": { + "Method": { + "anchorIDL": "test idl 1", + "encoding": "invalid", + "procedures": [{ + "idlAccount": "StructWithNestedStruct" + }] + } + } + } + } +} \ No newline at end of file diff --git a/pkg/solana/config/testChainReader_valid.json b/pkg/solana/config/testChainReader_valid.json new file mode 100644 index 000000000..d2649739d --- /dev/null +++ b/pkg/solana/config/testChainReader_valid.json @@ -0,0 +1,37 @@ +{ + "namespaces": { + "Contract": { + "methods": { + "Method": { + "anchorIDL": "test idl 1", + "encoding": "borsh", + "procedures": [{ + "idlAccount": "StructWithNestedStruct" + }] + }, + "MethodWithOpts": { + "anchorIDL": "test idl 2", + "encoding": "borsh", + "procedures": [{ + "idlAccount": "StructWithNestedStruct", + "outputModifications": [{ + "Type": "extract property", + "FieldName": "DurationVal" + }] + }] + } + } + }, + "OtherContract": { + "methods": { + "Method": { + "anchorIDL": "test idl 3", + "encoding": "bincode", + "procedures": [{ + "idlAccount": "StructWithNestedStruct" + }] + } + } + } + } +} \ No newline at end of file From 5b3b9fb73825cd2c8b2a69a9274d30fe053fd57e Mon Sep 17 00:00:00 2001 From: Awbrey Hughlett Date: Fri, 15 Mar 2024 17:57:17 -0500 Subject: [PATCH 04/14] BCF-3016 Convert Multiple Binding Calls to Parallel (#617) * Convert Multiple Binding Calls to Parallel The binding calls are expected to be run in sequence as they map over the returnVal, but the associated RPC calls can be run in parallel. This commit preloads all data over RPC in parallel before mapping over the returnVal in sequence. * remove unnecessary constant --- .../chainreader/account_read_binding.go | 53 ++++- .../chainreader/account_read_binding_test.go | 159 +++++++++++++ pkg/solana/chainreader/bindings.go | 11 +- pkg/solana/chainreader/bindings_test.go | 4 +- pkg/solana/chainreader/chain_reader.go | 81 ++++++- pkg/solana/chainreader/chain_reader_test.go | 209 +++++++++++++++--- 6 files changed, 473 insertions(+), 44 deletions(-) create mode 100644 pkg/solana/chainreader/account_read_binding_test.go diff --git a/pkg/solana/chainreader/account_read_binding.go b/pkg/solana/chainreader/account_read_binding.go index 6d44d1c6f..107dc851b 100644 --- a/pkg/solana/chainreader/account_read_binding.go +++ b/pkg/solana/chainreader/account_read_binding.go @@ -24,12 +24,61 @@ type accountReadBinding struct { reader BinaryDataReader } +func newAccountReadBinding(acct string, codec types.RemoteCodec, reader BinaryDataReader) *accountReadBinding { + return &accountReadBinding{ + idlAccount: acct, + codec: codec, + reader: reader, + } +} + var _ readBinding = &accountReadBinding{} -func (b *accountReadBinding) GetLatestValue(ctx context.Context, _ any, outVal any) error { +func (b *accountReadBinding) PreLoad(ctx context.Context, result *loadedResult) { + if result == nil { + return + } + bts, err := b.reader.ReadAll(ctx, b.account) if err != nil { - return fmt.Errorf("%w: failed to get binary data", err) + result.err <- fmt.Errorf("%w: failed to get binary data", err) + + return + } + + select { + case <-ctx.Done(): + result.err <- ctx.Err() + default: + result.value <- bts + } +} + +func (b *accountReadBinding) GetLatestValue(ctx context.Context, _ any, outVal any, result *loadedResult) error { + var ( + bts []byte + err error + ) + + if result != nil { + // when preloading, the process will wait for one of three conditions: + // 1. the context ends and returns an error + // 2. bytes were loaded in the bytes channel + // 3. an error was loaded in the err channel + select { + case <-ctx.Done(): + err = ctx.Err() + case bts = <-result.value: + case err = <-result.err: + } + + if err != nil { + return err + } + } else { + if bts, err = b.reader.ReadAll(ctx, b.account); err != nil { + return fmt.Errorf("%w: failed to get binary data", err) + } } return b.codec.Decode(ctx, bts, outVal, b.idlAccount) diff --git a/pkg/solana/chainreader/account_read_binding_test.go b/pkg/solana/chainreader/account_read_binding_test.go new file mode 100644 index 000000000..a5d344f8f --- /dev/null +++ b/pkg/solana/chainreader/account_read_binding_test.go @@ -0,0 +1,159 @@ +package chainreader + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func TestPreload(t *testing.T) { + t.Parallel() + + testCodec := makeTestCodec(t) + + t.Run("get latest value waits for preload", func(t *testing.T) { + t.Parallel() + + reader := new(mockReader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader) + + expected := testStruct{A: true, B: 42} + bts, err := testCodec.Encode(context.Background(), expected, testCodecKey) + + require.NoError(t, err) + + reader.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).After(time.Second) + + ctx := context.Background() + start := time.Now() + loaded := &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + + binding.PreLoad(ctx, loaded) + + var result testStruct + + err = binding.GetLatestValue(ctx, nil, &result, loaded) + elapsed := time.Since(start) + + require.NoError(t, err) + assert.GreaterOrEqual(t, elapsed, time.Second) + assert.Less(t, elapsed, 1100*time.Millisecond) + assert.Equal(t, expected, result) + }) + + t.Run("cancelled context exits preload and returns error on get latest value", func(t *testing.T) { + t.Parallel() + + reader := new(mockReader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader) + + ctx, cancel := context.WithCancelCause(context.Background()) + + // make the readall pause until after the context is cancelled + reader.On("ReadAll", mock.Anything, mock.Anything). + Return([]byte{}, nil). + After(600 * time.Millisecond) + + expectedErr := errors.New("test error") + go func() { + time.Sleep(500 * time.Millisecond) + cancel(expectedErr) + }() + + loaded := &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + start := time.Now() + binding.PreLoad(ctx, loaded) + + var result testStruct + err := binding.GetLatestValue(ctx, nil, &result, loaded) + elapsed := time.Since(start) + + assert.ErrorIs(t, err, ctx.Err()) + assert.ErrorIs(t, context.Cause(ctx), expectedErr) + assert.GreaterOrEqual(t, elapsed, 600*time.Millisecond) + assert.Less(t, elapsed, 700*time.Millisecond) + }) + + t.Run("error from preload is returned in get latest value", func(t *testing.T) { + t.Parallel() + + reader := new(mockReader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader) + ctx := context.Background() + expectedErr := errors.New("test error") + + reader.On("ReadAll", mock.Anything, mock.Anything). + Return([]byte{}, expectedErr) + + loaded := &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + binding.PreLoad(ctx, loaded) + + var result testStruct + err := binding.GetLatestValue(ctx, nil, &result, loaded) + + assert.ErrorIs(t, err, expectedErr) + }) +} + +type mockReader struct { + mock.Mock +} + +func (_m *mockReader) ReadAll(ctx context.Context, pk solana.PublicKey) ([]byte, error) { + ret := _m.Called(ctx, pk) + + var r0 []byte + if val, ok := ret.Get(0).([]byte); ok { + r0 = val + } + + var r1 error + if fn, ok := ret.Get(1).(func() error); ok { + r1 = fn() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type testStruct struct { + A bool + B int64 +} + +const testCodecKey = "TEST" + +func makeTestCodec(t *testing.T) types.RemoteCodec { + t.Helper() + + builder := binary.LittleEndian() + + structCodec, err := encodings.NewStructCodec([]encodings.NamedTypeCodec{ + {Name: "A", Codec: builder.Bool()}, + {Name: "B", Codec: builder.Int64()}, + }) + + require.NoError(t, err) + + return encodings.CodecFromTypeCodec(map[string]encodings.TypeCodec{testCodecKey: structCodec}) +} diff --git a/pkg/solana/chainreader/bindings.go b/pkg/solana/chainreader/bindings.go index 2125684b2..3e96f3be9 100644 --- a/pkg/solana/chainreader/bindings.go +++ b/pkg/solana/chainreader/bindings.go @@ -11,7 +11,8 @@ import ( ) type readBinding interface { - GetLatestValue(ctx context.Context, params, returnVal any) error + PreLoad(context.Context, *loadedResult) + GetLatestValue(ctx context.Context, params, returnVal any, preload *loadedResult) error Bind(types.BoundContract) error CreateType(bool) (any, error) } @@ -77,6 +78,9 @@ func (b namespaceBindings) CreateType(namespace, methodName string, forEncoding } tBinding := reflect.TypeOf(bindingType) + if tBinding.Kind() == reflect.Pointer { + tBinding = tBinding.Elem() + } // all bindings must be structs to allow multiple bindings if tBinding.Kind() != reflect.Struct { @@ -140,3 +144,8 @@ func (b namespaceBindings) Bind(boundContracts []types.BoundContract) error { return nil } + +type loadedResult struct { + value chan []byte + err chan error +} diff --git a/pkg/solana/chainreader/bindings_test.go b/pkg/solana/chainreader/bindings_test.go index 77befa06b..94b3632a5 100644 --- a/pkg/solana/chainreader/bindings_test.go +++ b/pkg/solana/chainreader/bindings_test.go @@ -105,7 +105,9 @@ type mockBinding struct { mock.Mock } -func (_m *mockBinding) GetLatestValue(ctx context.Context, params, returnVal any) error { +func (_m *mockBinding) PreLoad(context.Context, *loadedResult) {} + +func (_m *mockBinding) GetLatestValue(ctx context.Context, params, returnVal any, _ *loadedResult) error { return nil } diff --git a/pkg/solana/chainreader/chain_reader.go b/pkg/solana/chainreader/chain_reader.go index 97be00f50..3ba33508a 100644 --- a/pkg/solana/chainreader/chain_reader.go +++ b/pkg/solana/chainreader/chain_reader.go @@ -3,6 +3,9 @@ package chainreader import ( "context" "encoding/json" + "fmt" + "reflect" + "sync" ag_solana "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" @@ -26,6 +29,7 @@ type SolanaChainReaderService struct { bindings namespaceBindings // service state management + wg sync.WaitGroup services.StateMachine } @@ -67,6 +71,8 @@ func (s *SolanaChainReaderService) Start(_ context.Context) error { // up used resources. Subsequent calls to Close return an error. func (s *SolanaChainReaderService) Close() error { return s.StopOnce(ServiceName, func() error { + s.wg.Wait() + return nil }) } @@ -86,17 +92,78 @@ func (s *SolanaChainReaderService) HealthReport() map[string]error { // GetLatestValue implements the types.ChainReader interface and requests and parses on-chain // data named by the provided contract, method, and params. func (s *SolanaChainReaderService) GetLatestValue(ctx context.Context, contractName, method string, params any, returnVal any) error { + if err := s.Ready(); err != nil { + return err + } + + s.wg.Add(1) + defer s.wg.Done() + bindings, err := s.bindings.GetReadBindings(contractName, method) if err != nil { return err } - for _, binding := range bindings { - if err := binding.GetLatestValue(ctx, params, returnVal); err != nil { + localCtx, localCancel := context.WithCancel(ctx) + + // the wait group ensures GetLatestValue returns only after all go-routines have completed + var wg sync.WaitGroup + + results := make(map[int]*loadedResult) + + if len(bindings) > 1 { + // might go for some guardrails when dealing with multiple bindings + // the returnVal should be compatible with multiple passes by the codec decoder + // this should only apply to types struct{} and map[any]any + tReturnVal := reflect.TypeOf(returnVal) + if tReturnVal.Kind() == reflect.Pointer { + tReturnVal = reflect.Indirect(reflect.ValueOf(returnVal)).Type() + } + + switch tReturnVal.Kind() { + case reflect.Struct, reflect.Map: + default: + localCancel() + + wg.Wait() + + return fmt.Errorf("%w: multiple bindings is only supported for struct and map", types.ErrInvalidType) + } + + // for multiple bindings, preload the remote data in parallel + for idx, binding := range bindings { + results[idx] = &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + + wg.Add(1) + go func(ctx context.Context, rb readBinding, res *loadedResult) { + defer wg.Done() + + rb.PreLoad(ctx, res) + }(localCtx, binding, results[idx]) + } + } + + // in the case of parallel preloading, GetLatestValue will still run in + // sequence because the function will block until the data is loaded. + // in the case of no preloading, GetLatestValue will load and decode in + // sequence. + for idx, binding := range bindings { + if err := binding.GetLatestValue(ctx, params, returnVal, results[idx]); err != nil { + localCancel() + + wg.Wait() + return err } } + localCancel() + + wg.Wait() + return nil } @@ -136,11 +203,11 @@ func (s *SolanaChainReaderService) init(namespaces map[string]config.ChainReader return err } - s.bindings.AddReadBinding(namespace, methodName, &accountReadBinding{ - idlAccount: procedure.IDLAccount, - codec: codecWithModifiers, - reader: s.client, - }) + s.bindings.AddReadBinding(namespace, methodName, newAccountReadBinding( + procedure.IDLAccount, + codecWithModifiers, + s.client, + )) } } } diff --git a/pkg/solana/chainreader/chain_reader_test.go b/pkg/solana/chainreader/chain_reader_test.go index 11caaaa0e..0787734c2 100644 --- a/pkg/solana/chainreader/chain_reader_test.go +++ b/pkg/solana/chainreader/chain_reader_test.go @@ -7,12 +7,12 @@ import ( "os" "strconv" "strings" + "sync" "testing" "time" ag_solana "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" @@ -89,8 +89,13 @@ func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { require.NoError(t, err) require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) - client.On("ReadAll", mock.Anything, mock.Anything).Return(encoded, nil) + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + client.SetNext(encoded, nil, 0) var result modifiedStructWithNestedStruct @@ -112,8 +117,13 @@ func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { require.NoError(t, err) require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) - client.On("ReadAll", mock.Anything, mock.Anything).Return(nil, expectedErr) + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + client.SetNext(nil, expectedErr, 0) var result modifiedStructWithNestedStruct @@ -130,6 +140,11 @@ func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { require.NoError(t, err) require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) var result modifiedStructWithNestedStruct @@ -146,6 +161,11 @@ func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { require.NoError(t, err) require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) var result modifiedStructWithNestedStruct @@ -162,6 +182,11 @@ func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { require.NoError(t, err) require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) pk := ag_solana.NewWallet().PublicKey() err = svc.Bind(ctx, []types.BoundContract{ @@ -184,6 +209,11 @@ func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { require.NoError(t, err) require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) pk := ag_solana.NewWallet().PublicKey() @@ -291,21 +321,74 @@ type modifiedStructWithNestedStruct struct { EnumVal uint8 } -// TODO: BCF-3060 convert mock client to be instance of solana chain. +type mockedRPCCall struct { + bts []byte + err error + delay time.Duration +} + type mockedRPCClient struct { - mock.Mock + mu sync.Mutex + responseByAddress map[string]mockedRPCCall + sequence []mockedRPCCall +} + +func (_m *mockedRPCClient) ReadAll(_ context.Context, pk ag_solana.PublicKey) ([]byte, error) { + _m.mu.Lock() + defer _m.mu.Unlock() + + if _m.responseByAddress == nil { + _m.responseByAddress = make(map[string]mockedRPCCall) + } + + if resp, ok := _m.responseByAddress[pk.String()]; ok { + if resp.delay > 0 { + time.Sleep(resp.delay) + } + + delete(_m.responseByAddress, pk.String()) + + return resp.bts, resp.err + } + + if len(_m.sequence) == 0 { + panic("no values to return") + } + + next := _m.sequence[0] + _m.sequence = _m.sequence[1:len(_m.sequence)] + + if next.delay > 0 { + time.Sleep(next.delay) + } + + return next.bts, next.err } -func (_m *mockedRPCClient) ReadAll(ctx context.Context, pk ag_solana.PublicKey) ([]byte, error) { - ret := _m.Called(ctx, pk) +func (_m *mockedRPCClient) SetNext(bts []byte, err error, delay time.Duration) { + _m.mu.Lock() + defer _m.mu.Unlock() + + _m.sequence = append(_m.sequence, mockedRPCCall{ + bts: bts, + err: err, + delay: delay, + }) +} - var r0 []byte +func (_m *mockedRPCClient) SetForAddress(pk ag_solana.PublicKey, bts []byte, err error, delay time.Duration) { + _m.mu.Lock() + defer _m.mu.Unlock() - if val, ok := ret.Get(0).([]byte); ok { - r0 = val + if _m.responseByAddress == nil { + _m.responseByAddress = make(map[string]mockedRPCCall) } - return r0, ret.Error(1) + _m.responseByAddress[pk.String()] = mockedRPCCall{ + bts: bts, + err: err, + delay: delay, + } } type chainReaderInterfaceTester struct { @@ -326,7 +409,7 @@ func (r *chainReaderInterfaceTester) Name() string { } func (r *chainReaderInterfaceTester) Setup(t *testing.T) { - r.address = make([]string, 6) + r.address = make([]string, 8) for idx := range r.address { r.address[idx] = ag_solana.NewWallet().PublicKey().String() } @@ -336,11 +419,14 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { AnyContractName: { Methods: map[string]config.ChainDataReader{ MethodTakingLatestParamsReturningTestStruct: { - AnchorIDL: fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), + AnchorIDL: fullStructIDL(t), Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { - IDLAccount: "TestStruct", + IDLAccount: "TestStructB", + }, + { + IDLAccount: "TestStructA", }, }, }, @@ -381,14 +467,16 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { }, }, MethodReturningSeenStruct: { - AnchorIDL: fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), + AnchorIDL: fullStructIDL(t), Encoding: config.EncodingTypeBorsh, Procedures: []config.ChainReaderProcedure{ { - IDLAccount: "TestStruct", + IDLAccount: "TestStructB", + }, + { + IDLAccount: "TestStructA", OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, - // &codeccommon.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, }, }, }, @@ -423,6 +511,11 @@ func (r *chainReaderInterfaceTester) GetChainReader(t *testing.T) types.ChainRea t.FailNow() } + require.NoError(t, svc.Start(context.Background())) + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + if r.reader == nil { r.reader = &wrappedTestChainReader{ test: t, @@ -445,6 +538,10 @@ type wrappedTestChainReader struct { } func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractName string, method string, params, returnVal any) error { + var ( + a ag_solana.PublicKey + b ag_solana.PublicKey + ) switch contractName + method { case AnyContractName + EventName: // t.Skip won't skip the test here @@ -464,7 +561,7 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam r.test.FailNow() } - r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + r.client.SetNext(bts, nil, 0) case AnyContractName + MethodReturningUint64Slice: cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, ""), config.EncodingTypeBincode) onChainStruct := struct { @@ -478,7 +575,7 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam r.test.FailNow() } - r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + r.client.SetNext(bts, nil, 0) case AnySecondContractName + MethodReturningUint64, AnyContractName + DifferentMethodReturningUint64: cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), config.EncodingTypeBorsh) onChainStruct := struct { @@ -492,32 +589,57 @@ func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractNam r.test.FailNow() } - r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + r.client.SetNext(bts, nil, 0) case AnyContractName + MethodReturningSeenStruct: nextStruct := CreateTestStruct(0, r.tester) r.testStructQueue = append(r.testStructQueue, &nextStruct) + a, b = getAddresses(r.test, r.tester, 5, 6) + fallthrough default: if r.testStructQueue == nil || len(r.testStructQueue) == 0 { r.test.FailNow() } + if contractName+method != AnyContractName+MethodReturningSeenStruct { + a, b = getAddresses(r.test, r.tester, 0, 1) + } + nextTestStruct := r.testStructQueue[0] r.testStructQueue = r.testStructQueue[1:len(r.testStructQueue)] - cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, testStructIDL, strings.Join([]string{midLevelStructIDL, innerStructIDL}, ",")), config.EncodingTypeBorsh) - bts, err := cdc.Encode(ctx, nextTestStruct, "TestStruct") + // split into two encoded parts to test the preloading function + cdc := makeTestCodec(r.test, fullStructIDL(r.test), config.EncodingTypeBorsh) + + bts, err := cdc.Encode(ctx, nextTestStruct, "TestStructB") if err != nil { r.test.FailNow() } - r.client.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).Once() + // make part A return slower than part B + r.client.SetForAddress(a, bts, nil, 300*time.Millisecond) + + bts, err = cdc.Encode(ctx, nextTestStruct, "TestStructA") + if err != nil { + r.test.FailNow() + } + + r.client.SetForAddress(b, bts, nil, 50*time.Millisecond) } return r.service.GetLatestValue(ctx, contractName, method, params, returnVal) } +func getAddresses(t *testing.T, tester ChainReaderInterfaceTester, a, b int) (ag_solana.PublicKey, ag_solana.PublicKey) { + t.Helper() + + bindings := tester.GetBindings(t) + fn := ag_solana.MustPublicKeyFromBase58 + + return fn(bindings[a].Address), fn(bindings[b].Address) +} + func (r *wrappedTestChainReader) Bind(ctx context.Context, bindings []types.BoundContract) error { return r.service.Bind(ctx, bindings) } @@ -552,11 +674,13 @@ func (r *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *Test func (r *chainReaderInterfaceTester) GetBindings(t *testing.T) []types.BoundContract { return []types.BoundContract{ {Name: strings.Join([]string{AnyContractName, MethodTakingLatestParamsReturningTestStruct, "0"}, "."), Address: r.address[0], Pending: true}, - {Name: strings.Join([]string{AnyContractName, MethodReturningUint64, "0"}, "."), Address: r.address[1], Pending: true}, - {Name: strings.Join([]string{AnyContractName, DifferentMethodReturningUint64, "0"}, "."), Address: r.address[2], Pending: true}, - {Name: strings.Join([]string{AnyContractName, MethodReturningUint64Slice, "0"}, "."), Address: r.address[3], Pending: true}, - {Name: strings.Join([]string{AnyContractName, MethodReturningSeenStruct, "0"}, "."), Address: r.address[4], Pending: true}, - {Name: strings.Join([]string{AnySecondContractName, MethodReturningUint64, "0"}, "."), Address: r.address[5], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodTakingLatestParamsReturningTestStruct, "1"}, "."), Address: r.address[1], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningUint64, "0"}, "."), Address: r.address[2], Pending: true}, + {Name: strings.Join([]string{AnyContractName, DifferentMethodReturningUint64, "0"}, "."), Address: r.address[3], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningUint64Slice, "0"}, "."), Address: r.address[4], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningSeenStruct, "0"}, "."), Address: r.address[5], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningSeenStruct, "1"}, "."), Address: r.address[6], Pending: true}, + {Name: strings.Join([]string{AnySecondContractName, MethodReturningUint64, "0"}, "."), Address: r.address[7], Pending: true}, } } @@ -593,6 +717,16 @@ func makeTestCodec(t *testing.T, rawIDL string, encoding config.EncodingType) en return testCodec } +func fullStructIDL(t *testing.T) string { + t.Helper() + + return fmt.Sprintf( + baseIDL, + strings.Join([]string{testStructAIDL, testStructBIDL}, ","), + strings.Join([]string{midLevelStructIDL, innerStructIDL}, ","), + ) +} + const ( baseIDL = `{ "version": "0.1.0", @@ -601,19 +735,28 @@ const ( "types": [%s] }` - testStructIDL = `{ - "name": "TestStruct", + testStructAIDL = `{ + "name": "TestStructA", "type": { "kind": "struct", "fields": [ {"name": "field","type": {"option": "i32"}}, {"name": "differentField","type": "string"}, + {"name": "bigField","type": "i128"}, + {"name": "nestedStruct","type": {"defined": "MidLevelStruct"}} + ] + } + }` + + testStructBIDL = `{ + "name": "TestStructB", + "type": { + "kind": "struct", + "fields": [ {"name": "oracleID","type": "u8"}, {"name": "oracleIDs","type": {"array": ["u8",32]}}, {"name": "account","type": "bytes"}, - {"name": "accounts","type": {"vec": "bytes"}}, - {"name": "bigField","type": "i128"}, - {"name": "nestedStruct","type": {"defined": "MidLevelStruct"}} + {"name": "accounts","type": {"vec": "bytes"}} ] } }` From e583587d2fb149fcf0c4824a1ac778061ecb11d8 Mon Sep 17 00:00:00 2001 From: Awbrey Hughlett Date: Mon, 18 Mar 2024 15:41:19 -0500 Subject: [PATCH 05/14] BCF-3055 Add RPC Opts to Config and Pass to Binding (#627) Solana RPC options include commitment level, data encoding type, and data slice opts. Providing these options in the ChainReader config will allow more control over RPC behavior. --- .../chainreader/account_read_binding.go | 11 +++++--- .../chainreader/account_read_binding_test.go | 15 +++++------ pkg/solana/chainreader/chain_reader.go | 25 +++++++++++++++++-- pkg/solana/chainreader/chain_reader_test.go | 17 ++++++++++++- pkg/solana/config/chain_reader.go | 12 +++++++++ pkg/solana/config/chain_reader_test.go | 17 +++++++++++++ pkg/solana/config/testChainReader_valid.json | 10 +++++++- 7 files changed, 92 insertions(+), 15 deletions(-) diff --git a/pkg/solana/chainreader/account_read_binding.go b/pkg/solana/chainreader/account_read_binding.go index 107dc851b..c1635e3a9 100644 --- a/pkg/solana/chainreader/account_read_binding.go +++ b/pkg/solana/chainreader/account_read_binding.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -12,7 +13,7 @@ import ( // BinaryDataReader provides an interface for reading bytes from a source. This is likely a wrapper // for a solana client. type BinaryDataReader interface { - ReadAll(context.Context, solana.PublicKey) ([]byte, error) + ReadAll(context.Context, solana.PublicKey, *rpc.GetAccountInfoOpts) ([]byte, error) } // accountReadBinding provides decoding and reading Solana Account data using a defined codec. The @@ -22,13 +23,15 @@ type accountReadBinding struct { account solana.PublicKey codec types.RemoteCodec reader BinaryDataReader + opts *rpc.GetAccountInfoOpts } -func newAccountReadBinding(acct string, codec types.RemoteCodec, reader BinaryDataReader) *accountReadBinding { +func newAccountReadBinding(acct string, codec types.RemoteCodec, reader BinaryDataReader, opts *rpc.GetAccountInfoOpts) *accountReadBinding { return &accountReadBinding{ idlAccount: acct, codec: codec, reader: reader, + opts: opts, } } @@ -39,7 +42,7 @@ func (b *accountReadBinding) PreLoad(ctx context.Context, result *loadedResult) return } - bts, err := b.reader.ReadAll(ctx, b.account) + bts, err := b.reader.ReadAll(ctx, b.account, b.opts) if err != nil { result.err <- fmt.Errorf("%w: failed to get binary data", err) @@ -76,7 +79,7 @@ func (b *accountReadBinding) GetLatestValue(ctx context.Context, _ any, outVal a return err } } else { - if bts, err = b.reader.ReadAll(ctx, b.account); err != nil { + if bts, err = b.reader.ReadAll(ctx, b.account, b.opts); err != nil { return fmt.Errorf("%w: failed to get binary data", err) } } diff --git a/pkg/solana/chainreader/account_read_binding_test.go b/pkg/solana/chainreader/account_read_binding_test.go index a5d344f8f..3b391e104 100644 --- a/pkg/solana/chainreader/account_read_binding_test.go +++ b/pkg/solana/chainreader/account_read_binding_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -25,14 +26,14 @@ func TestPreload(t *testing.T) { t.Parallel() reader := new(mockReader) - binding := newAccountReadBinding(testCodecKey, testCodec, reader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader, nil) expected := testStruct{A: true, B: 42} bts, err := testCodec.Encode(context.Background(), expected, testCodecKey) require.NoError(t, err) - reader.On("ReadAll", mock.Anything, mock.Anything).Return(bts, nil).After(time.Second) + reader.On("ReadAll", mock.Anything, mock.Anything, mock.Anything).Return(bts, nil).After(time.Second) ctx := context.Background() start := time.Now() @@ -58,12 +59,12 @@ func TestPreload(t *testing.T) { t.Parallel() reader := new(mockReader) - binding := newAccountReadBinding(testCodecKey, testCodec, reader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader, nil) ctx, cancel := context.WithCancelCause(context.Background()) // make the readall pause until after the context is cancelled - reader.On("ReadAll", mock.Anything, mock.Anything). + reader.On("ReadAll", mock.Anything, mock.Anything, mock.Anything). Return([]byte{}, nil). After(600 * time.Millisecond) @@ -94,11 +95,11 @@ func TestPreload(t *testing.T) { t.Parallel() reader := new(mockReader) - binding := newAccountReadBinding(testCodecKey, testCodec, reader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader, nil) ctx := context.Background() expectedErr := errors.New("test error") - reader.On("ReadAll", mock.Anything, mock.Anything). + reader.On("ReadAll", mock.Anything, mock.Anything, mock.Anything). Return([]byte{}, expectedErr) loaded := &loadedResult{ @@ -118,7 +119,7 @@ type mockReader struct { mock.Mock } -func (_m *mockReader) ReadAll(ctx context.Context, pk solana.PublicKey) ([]byte, error) { +func (_m *mockReader) ReadAll(ctx context.Context, pk solana.PublicKey, opts *rpc.GetAccountInfoOpts) ([]byte, error) { ret := _m.Called(ctx, pk) var r0 []byte diff --git a/pkg/solana/chainreader/chain_reader.go b/pkg/solana/chainreader/chain_reader.go index 3ba33508a..b52c72bb5 100644 --- a/pkg/solana/chainreader/chain_reader.go +++ b/pkg/solana/chainreader/chain_reader.go @@ -207,6 +207,7 @@ func (s *SolanaChainReaderService) init(namespaces map[string]config.ChainReader procedure.IDLAccount, codecWithModifiers, s.client, + createRPCOpts(procedure.RPCOpts), )) } } @@ -215,6 +216,26 @@ func (s *SolanaChainReaderService) init(namespaces map[string]config.ChainReader return nil } +func createRPCOpts(opts *config.RPCOpts) *rpc.GetAccountInfoOpts { + if opts == nil { + return nil + } + + result := &rpc.GetAccountInfoOpts{ + DataSlice: opts.DataSlice, + } + + if opts.Encoding != nil { + result.Encoding = *opts.Encoding + } + + if opts.Commitment != nil { + result.Commitment = *opts.Commitment + } + + return result +} + type accountDataReader struct { client *rpc.Client } @@ -223,8 +244,8 @@ func NewAccountDataReader(client *rpc.Client) *accountDataReader { return &accountDataReader{client: client} } -func (r *accountDataReader) ReadAll(ctx context.Context, pk ag_solana.PublicKey) ([]byte, error) { - result, err := r.client.GetAccountInfo(ctx, pk) +func (r *accountDataReader) ReadAll(ctx context.Context, pk ag_solana.PublicKey, opts *rpc.GetAccountInfoOpts) ([]byte, error) { + result, err := r.client.GetAccountInfoWithOpts(ctx, pk, opts) if err != nil { return nil, err } diff --git a/pkg/solana/chainreader/chain_reader_test.go b/pkg/solana/chainreader/chain_reader_test.go index 0787734c2..dd4b4ebc7 100644 --- a/pkg/solana/chainreader/chain_reader_test.go +++ b/pkg/solana/chainreader/chain_reader_test.go @@ -11,7 +11,9 @@ import ( "testing" "time" + "github.com/gagliardetto/solana-go" ag_solana "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -333,7 +335,7 @@ type mockedRPCClient struct { sequence []mockedRPCCall } -func (_m *mockedRPCClient) ReadAll(_ context.Context, pk ag_solana.PublicKey) ([]byte, error) { +func (_m *mockedRPCClient) ReadAll(_ context.Context, pk ag_solana.PublicKey, _ *rpc.GetAccountInfoOpts) ([]byte, error) { _m.mu.Lock() defer _m.mu.Unlock() @@ -414,6 +416,11 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { r.address[idx] = ag_solana.NewWallet().PublicKey().String() } + encodingBase64 := solana.EncodingBase64 + commitment := rpc.CommitmentConfirmed + offset := uint64(1) + length := uint64(1) + r.conf = config.ChainReader{ Namespaces: map[string]config.ChainReaderMethods{ AnyContractName: { @@ -424,6 +431,14 @@ func (r *chainReaderInterfaceTester) Setup(t *testing.T) { Procedures: []config.ChainReaderProcedure{ { IDLAccount: "TestStructB", + RPCOpts: &config.RPCOpts{ + Encoding: &encodingBase64, + Commitment: &commitment, + DataSlice: &rpc.DataSlice{ + Offset: &offset, + Length: &length, + }, + }, }, { IDLAccount: "TestStructA", diff --git a/pkg/solana/config/chain_reader.go b/pkg/solana/config/chain_reader.go index f770c0939..a1fed147d 100644 --- a/pkg/solana/config/chain_reader.go +++ b/pkg/solana/config/chain_reader.go @@ -4,6 +4,9 @@ import ( "encoding/json" "fmt" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" @@ -66,6 +69,12 @@ func (t *EncodingType) UnmarshalJSON(data []byte) error { return nil } +type RPCOpts struct { + Encoding *solana.EncodingType `json:"encoding,omitempty"` + Commitment *rpc.CommitmentType `json:"commitment,omitempty"` + DataSlice *rpc.DataSlice `json:"dataSlice,omitempty"` +} + type ChainReaderProcedure chainDataProcedureFields type chainDataProcedureFields struct { @@ -74,6 +83,9 @@ type chainDataProcedureFields struct { // OutputModifications provides modifiers to convert chain data format to custom // output formats. OutputModifications codec.ModifiersConfig `json:"outputModifications,omitempty"` + // RPCOpts provides optional configurations for commitment, encoding, and data + // slice offsets. + RPCOpts *RPCOpts `json:"rpcOpts,omitempty"` } // BuilderForEncoding returns a builder for the encoding configuration. Defaults to little endian. diff --git a/pkg/solana/config/chain_reader_test.go b/pkg/solana/config/chain_reader_test.go index 26ac5ef91..b0ad49181 100644 --- a/pkg/solana/config/chain_reader_test.go +++ b/pkg/solana/config/chain_reader_test.go @@ -5,6 +5,8 @@ import ( "encoding/json" "testing" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -74,6 +76,13 @@ func TestBuilderForEncoding_Default(t *testing.T) { require.Equal(t, binary.LittleEndian(), builder) } +var ( + encodingBase64 = solana.EncodingBase64 + commitment = rpc.CommitmentFinalized + offset = uint64(10) + length = uint64(10) +) + var validChainReaderConfig = config.ChainReader{ Namespaces: map[string]config.ChainReaderMethods{ "Contract": { @@ -96,6 +105,14 @@ var validChainReaderConfig = config.ChainReader{ OutputModifications: codeccommon.ModifiersConfig{ &codeccommon.PropertyExtractorConfig{FieldName: "DurationVal"}, }, + RPCOpts: &config.RPCOpts{ + Encoding: &encodingBase64, + Commitment: &commitment, + DataSlice: &rpc.DataSlice{ + Offset: &offset, + Length: &length, + }, + }, }, }, }, diff --git a/pkg/solana/config/testChainReader_valid.json b/pkg/solana/config/testChainReader_valid.json index d2649739d..6dfbe0626 100644 --- a/pkg/solana/config/testChainReader_valid.json +++ b/pkg/solana/config/testChainReader_valid.json @@ -17,7 +17,15 @@ "outputModifications": [{ "Type": "extract property", "FieldName": "DurationVal" - }] + }], + "rpcOpts": { + "encoding": "base64", + "commitment": "finalized", + "dataSlice": { + "offset": 10, + "length": 10 + } + } }] } } From 32234257d78229cddae874b7fd4b36fe048d6f34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 07:58:16 -0600 Subject: [PATCH 06/14] [automated] bump solana image to v1.17.27 (#628) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- integration-tests/docker/test_env/sol.go | 2 +- scripts/install-solana-ci.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/docker/test_env/sol.go b/integration-tests/docker/test_env/sol.go index 3b05658c3..4ecc7e520 100644 --- a/integration-tests/docker/test_env/sol.go +++ b/integration-tests/docker/test_env/sol.go @@ -157,7 +157,7 @@ func (ms *Solana) getContainerRequest(inactiveFeatures InactiveFeatures) (*tc.Co return &tc.ContainerRequest{ Name: ms.ContainerName, - Image: "solanalabs/solana:v1.17.26", + Image: "solanalabs/solana:v1.17.27", ExposedPorts: []string{test_env.NatPortFormat(SOL_HTTP_PORT), test_env.NatPortFormat(SOL_WS_PORT)}, Env: map[string]string{ "SERVER_PORT": "1080", diff --git a/scripts/install-solana-ci.sh b/scripts/install-solana-ci.sh index e71eeda72..c983f7a73 100755 --- a/scripts/install-solana-ci.sh +++ b/scripts/install-solana-ci.sh @@ -2,5 +2,5 @@ set -euxo pipefail -sh -c "$(curl -sSfL https://release.solana.com/v1.17.26/install)" +sh -c "$(curl -sSfL https://release.solana.com/v1.17.27/install)" echo "PATH=$HOME/.local/share/solana/install/active_release/bin:$PATH" >> $GITHUB_ENV From a697cf5f01ecfee0d8fa08f9193e6b878dd0915e Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Thu, 21 Mar 2024 08:49:49 -0600 Subject: [PATCH 07/14] feat: autorun CI on dependency update PR (#631) * feat: autorun CI on dependency update PR * use composite action * fix: test dep updater - do not fail on first tidy attempt --- .github/workflows/open-pr.yml | 12 ++++++++++-- scripts/update-e2e.sh | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/open-pr.yml b/.github/workflows/open-pr.yml index f9f1fc20a..8aa6291a1 100644 --- a/.github/workflows/open-pr.yml +++ b/.github/workflows/open-pr.yml @@ -14,6 +14,13 @@ jobs: create-commits-and-pr: runs-on: ubuntu-latest steps: + - name: Setup GitHub Token + id: token + uses: smartcontractkit/.github/actions/setup-github-token@9e7cc0779934cae4a9028b8588c9adb64d8ce68c # setup-github-token@0.1.0 + with: + aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_SOLANA_CICD_TOKEN_ISSUER_ROLE_ARN }} + aws-lambda-url: ${{ secrets.AWS_RELENG_TEAM_GATI_LAMBDA_URL }} + aws-region: ${{ secrets.AWS_REGION }} - uses: actions/checkout@v3 # checkout branch that it is called from - uses: actions/setup-go@v3 with: @@ -30,7 +37,7 @@ jobs: - name: Check if changes + PR exists id: check env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ steps.token.outputs.access-token }} run: | prs=$(gh pr list \ --repo "$GITHUB_REPOSITORY" \ @@ -56,7 +63,7 @@ jobs: repo: ${{ github.repository }} branch: "${{ steps.run.outputs.name }}" env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ steps.token.outputs.access-token }} - name: "Cleanup branch" if: '!steps.check.outputs.skip' run: | @@ -72,3 +79,4 @@ jobs: branch: ${{ steps.run.outputs.name }} reviewers: ${{ inputs.reviewers }} body: ${{ steps.run.outputs.prBody }} + token: ${{ steps.token.outputs.access-token }} diff --git a/scripts/update-e2e.sh b/scripts/update-e2e.sh index 35c28d0af..33198d5df 100755 --- a/scripts/update-e2e.sh +++ b/scripts/update-e2e.sh @@ -7,6 +7,6 @@ echo "Chainlink Develop Commit: $SHA" # update dependencies go get github.com/smartcontractkit/chainlink/integration-tests@$SHA -go mod tidy +go mod tidy || echo -e "------\nInitial go mod tidy failed - will update chainlink dep and try tidy again\n------" go get github.com/smartcontractkit/chainlink/v2@$SHA go mod tidy From 1b6cdf4c80d2d442f952a6eee1374d2b3c085043 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:08:13 -0600 Subject: [PATCH 08/14] CI: add AWS OIDC permissions (#632) --- .github/workflows/open-pr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/open-pr.yml b/.github/workflows/open-pr.yml index 8aa6291a1..91b136ce0 100644 --- a/.github/workflows/open-pr.yml +++ b/.github/workflows/open-pr.yml @@ -12,6 +12,9 @@ on: jobs: create-commits-and-pr: + permissions: + id-token: write + contents: read runs-on: ubuntu-latest steps: - name: Setup GitHub Token From 3b534980490b163ed2ec480a74f6d73a478b9e49 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:33:03 -0600 Subject: [PATCH 09/14] fix: configure git creds (#633) * fix permissions + add author * remove: testing on push * move GATI token to end --- .github/workflows/open-pr.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/open-pr.yml b/.github/workflows/open-pr.yml index 91b136ce0..1da1285af 100644 --- a/.github/workflows/open-pr.yml +++ b/.github/workflows/open-pr.yml @@ -14,16 +14,9 @@ jobs: create-commits-and-pr: permissions: id-token: write - contents: read + contents: write runs-on: ubuntu-latest steps: - - name: Setup GitHub Token - id: token - uses: smartcontractkit/.github/actions/setup-github-token@9e7cc0779934cae4a9028b8588c9adb64d8ce68c # setup-github-token@0.1.0 - with: - aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_SOLANA_CICD_TOKEN_ISSUER_ROLE_ARN }} - aws-lambda-url: ${{ secrets.AWS_RELENG_TEAM_GATI_LAMBDA_URL }} - aws-region: ${{ secrets.AWS_REGION }} - uses: actions/checkout@v3 # checkout branch that it is called from - uses: actions/setup-go@v3 with: @@ -40,7 +33,7 @@ jobs: - name: Check if changes + PR exists id: check env: - GITHUB_TOKEN: ${{ steps.token.outputs.access-token }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | prs=$(gh pr list \ --repo "$GITHUB_REPOSITORY" \ @@ -66,13 +59,21 @@ jobs: repo: ${{ github.repository }} branch: "${{ steps.run.outputs.name }}" env: - GITHUB_TOKEN: ${{ steps.token.outputs.access-token }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: "Cleanup branch" if: '!steps.check.outputs.skip' run: | git reset --hard git branch --set-upstream-to=origin/${{ steps.run.outputs.name }} git pull + - name: Setup GitHub Token + if: '!steps.check.outputs.skip' + id: token + uses: smartcontractkit/.github/actions/setup-github-token@9e7cc0779934cae4a9028b8588c9adb64d8ce68c # setup-github-token@0.1.0 + with: + aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_SOLANA_CICD_TOKEN_ISSUER_ROLE_ARN }} + aws-lambda-url: ${{ secrets.AWS_RELENG_TEAM_GATI_LAMBDA_URL }} + aws-region: ${{ secrets.AWS_REGION }} - name: Create pull request if: '!steps.check.outputs.skip' uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 # v6.0.0 From 0c6eee5da1456ad70c282e440ab98df68b430599 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-infra-releng[bot]" <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:23:45 -0600 Subject: [PATCH 10/14] [automated] bump e2e test deps to match chainlink/integration-tests (#638) * [automated] bump e2e <> core/integration-tests dependencies * remove replace override + fix naming --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: aalu1418 <50029043+aalu1418@users.noreply.github.com> --- integration-tests/common/test_common.go | 2 +- integration-tests/go.mod | 59 ++++++------ integration-tests/go.sum | 120 ++++++++++++++---------- 3 files changed, 101 insertions(+), 80 deletions(-) diff --git a/integration-tests/common/test_common.go b/integration-tests/common/test_common.go index 16c129345..59db94fc4 100644 --- a/integration-tests/common/test_common.go +++ b/integration-tests/common/test_common.go @@ -190,7 +190,7 @@ func (m *OCRv2TestState) DeployCluster(contractsDir string) { } else { env, err := test_env.NewTestEnv() require.NoError(m.T, err) - sol := test_env_sol.NewSolana([]string{env.Network.Name}) + sol := test_env_sol.NewSolana([]string{env.DockerNetwork.Name}) err = sol.StartContainer() require.NoError(m.T, err) m.Common.SolanaUrl = sol.InternalHttpUrl diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 9a57ee8f4..bcfbc9ad0 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -8,18 +8,18 @@ require ( github.com/ethereum/go-ethereum v1.13.8 github.com/gagliardetto/binary v0.7.7 github.com/gagliardetto/solana-go v1.8.3 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.6.0 github.com/lib/pq v1.10.9 github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e - github.com/smartcontractkit/chainlink-testing-framework v1.23.6 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2 - github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2 - github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a + github.com/smartcontractkit/chainlink-testing-framework v1.27.0 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240321154927-31350477ae51 + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240321154927-31350477ae51 + github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.23.0 + github.com/testcontainers/testcontainers-go v0.28.0 go.uber.org/zap v1.26.0 golang.org/x/crypto v0.19.0 golang.org/x/exp v0.0.0-20240213143201-ec583247a57a @@ -55,11 +55,10 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.1 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect @@ -68,6 +67,7 @@ require ( github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect @@ -96,7 +96,7 @@ require ( github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/containerd/containerd v1.7.7 // indirect + github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/continuity v0.4.3 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect @@ -123,9 +123,10 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.7+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/docker v25.0.2+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect @@ -158,7 +159,7 @@ require ( github.com/go-kit/log v0.2.1 // indirect github.com/go-ldap/ldap/v3 v3.4.6 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/analysis v0.21.4 // indirect @@ -210,8 +211,8 @@ require ( github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 // indirect github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect - github.com/grafana/pyroscope-go v1.0.4 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect + github.com/grafana/pyroscope-go v1.1.1 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -223,7 +224,7 @@ require ( github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/consul/api v1.25.1 // indirect - github.com/hashicorp/consul/sdk v0.14.1 // indirect + github.com/hashicorp/consul/sdk v0.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect @@ -232,6 +233,7 @@ require ( github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect @@ -265,7 +267,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/compress v1.17.3 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -295,10 +297,12 @@ require ( github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect @@ -306,6 +310,8 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect + github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -345,19 +351,20 @@ require ( github.com/segmentio/ksuid v1.0.4 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/shirou/gopsutil/v3 v3.23.11 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/slack-go/slack v0.12.2 // indirect github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429 // indirect + github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect + github.com/smartcontractkit/seth v0.1.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wasp v0.4.5 // indirect @@ -378,6 +385,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect + github.com/test-go/testify v1.1.4 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -410,18 +418,18 @@ require ( go.opentelemetry.io/collector/semconv v0.87.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/ratelimit v0.3.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.7.0 // indirect golang.org/x/mod v0.15.0 // indirect @@ -440,7 +448,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.32.0 // indirect - gopkg.in/guregu/null.v2 v2.1.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect @@ -483,8 +490,6 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - github.com/testcontainers/testcontainers-go => github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56 - // K8s imports are weird k8s.io/api => k8s.io/api v0.25.11 k8s.io/client-go => k8s.io/client-go v0.25.11 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 0208dcba4..aeafaf7db 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -130,8 +130,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= -github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -139,8 +139,6 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56 h1:HItfr1XKD/4xnsJE56m3uxnkMQ9lbg8xDnkf9qoZCH0= -github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56/go.mod h1:ICriE9bLX5CLxL9OFQ2N+2N+f+803LNJ1utJb1+Inx0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= @@ -167,7 +165,6 @@ github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -198,6 +195,8 @@ github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYS github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -299,8 +298,8 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= -github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= +github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= +github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -392,14 +391,16 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.104.1 h1:SZNxjAsskM/su0YW9P8Wx3gU0W1Z13b6tZlYNpl5BnA= github.com/digitalocean/godo v1.104.1/go.mod h1:VAI/L5YDzMuPRU01lEEUSQ/sp5Z//1HnnFv/RBTEdbg= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= +github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= @@ -522,8 +523,8 @@ github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/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-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= @@ -755,8 +756,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -795,10 +796,10 @@ github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qv github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= -github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMHC7Bm0= -github.com/grafana/pyroscope-go v1.0.4/go.mod h1:0d7ftwSMBV/Awm7CCiYmHQEG8Y44Ma3YSjt+nWcWztY= -github.com/grafana/pyroscope-go/godeltaprof v0.1.4 h1:mDsJ3ngul7UfrHibGQpV66PbZ3q1T8glz/tK3bQKKEk= -github.com/grafana/pyroscope-go/godeltaprof v0.1.4/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko= +github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= +github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= +github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= +github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= @@ -832,8 +833,8 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= -github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= +github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8= +github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -849,6 +850,7 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -862,8 +864,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= @@ -1027,8 +1029,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -1163,6 +1165,8 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8 github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1175,6 +1179,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= @@ -1188,6 +1194,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= @@ -1373,8 +1383,8 @@ github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08O github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= -github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -1397,32 +1407,34 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429 h1:xkejUBZhcBpBrTSfxc91Iwzadrb6SXw8ks69bHIQ9Ww= -github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429/go.mod h1:wJmVvDf4XSjsahWtfUq3wvIAYEAuhr7oxmxYnEL/LGQ= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 h1:WeLb67RVd0lqdbm8qJ/LqrcfoLr7PoMjzi9wGy7ocqc= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498/go.mod h1:8sn4HEfG8lR/D1Ov0yPHsY4kOleDKZKh2r8Op4oaAFE= +github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= +github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35/go.mod h1:2I0dWdYdK6jHPnSYYy7Y7Xp7L0YTnJ3KZtkhLQflsTU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c h1:EKWa6Il+8Z36Mcs4eQJJP8aUyZX0nCDfdzhzZkC4W8o= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c/go.mod h1://xWphjmC6GWJtT8l86J2VpnG21xNwFCb0thzz4ItEk= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336 h1:j00D0/EqE9HRu+63v7KwUOe4ZxLc4AN5SOJFiinkkH0= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336/go.mod h1:umLyYLRGqyIuFfGpEREZP3So6+O8iL35cCCqW+OxX5w= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= -github.com/smartcontractkit/chainlink-testing-framework v1.23.6 h1:krjJswtgQ/J4kBgFpC7Tyh8wSFfWiGGUsADg6BG/EGw= -github.com/smartcontractkit/chainlink-testing-framework v1.23.6/go.mod h1:lGaqSnCB36n49fZNdTGXMrxhPu9w5+2n3c9V1Fqz1hM= +github.com/smartcontractkit/chainlink-testing-framework v1.27.0 h1:fs60anZu4VMPv0E9TtGo9uQ4kJcqChClxgjC9ArvqN4= +github.com/smartcontractkit/chainlink-testing-framework v1.27.0/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2 h1:5Snvs4I/TlfEku8cjv7FlaDQxOzgb/xhlScewi1ZyD0= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2/go.mod h1:A6vR7K9Ps9CAQlt+2J1tAoudv+0apEdCmXmM8l6tfKg= -github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2 h1:oRhIbbpv6lYVgaRNoLbYYPVvVG78OAdPal1FusyjGsU= -github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2/go.mod h1:gNYKSdUUe0b6EjrnMmomnrcwHcBmwUjjKIfz0TdUjQQ= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240321154927-31350477ae51 h1:GpnHh/3Pn7dioR9P8jpPv6NKUAaXg+7FQLQluZ2lyn8= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240321154927-31350477ae51/go.mod h1:Wx8qoqkK1akgHnyeGwVlTWd0EKpKYy7HmsM2Rj1HOgw= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240321154927-31350477ae51 h1:cuRZhnBrGfyrD2tc1Fp0s1fdGeBUBSZLyDkdo5lEw3M= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240321154927-31350477ae51/go.mod h1:bsdQB5So2RZ+gneOPexVpfD1M65h9itn4rd6iFwbQH8= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a h1:nGkZ9uXS8lPIJOi68rdftEo2c9Q8qbRAi5+XMnKobVc= -github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a/go.mod h1:kC0qmVPUaVkFqGiZMNhmRmjdphuUmeyLEdlWFOQzFWI= +github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 h1:xsU00JB9GJxEiN6tDbqgN+fT98ySdxkUwTw6CfBXscw= +github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +github.com/smartcontractkit/seth v0.1.2 h1:ImXJmniuq6yWB6b3eezjV+lkYb1GfQuaJkwRvrCfTKQ= +github.com/smartcontractkit/seth v0.1.2/go.mod h1:aOaGwrIVFG/MYaLSj9UUMyE5QJnYQoAgnxm5cKfT9Ng= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= @@ -1504,6 +1516,8 @@ github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= +github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= @@ -1628,26 +1642,29 @@ go.opentelemetry.io/collector/pdata v1.0.0-rcv0016/go.mod h1:OdN0alYOlYhHXu6BDlG go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXnizczQpEs/gg8= go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1 h1:mMv2jG58h6ZI5t5S9QCVGdzCmAsTakMa3oxVgpSD44g= -go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1/go.mod h1:oqRuNKG0upTaDPbLVCG8AD0G2ETrfDtmh7jViy7ox6M= +go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= +go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= @@ -1669,8 +1686,9 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= +go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -2196,8 +2214,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/guregu/null.v2 v2.1.2 h1:YOuepWdYqGnrenzPyMi+ybCjeDzjdazynbwsXXOk4i8= -gopkg.in/guregu/null.v2 v2.1.2/go.mod h1:XORrx8tyS5ZDcyUboCIxQtta/Aujk/6pfWrn9Xe33mU= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= From 74795f62c558a07bd4723aebef67c4d9e4e84a11 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-infra-releng[bot]" <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 07:20:18 -0600 Subject: [PATCH 11/14] [automated] bump e2e test deps to match chainlink/integration-tests (#644) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- integration-tests/go.mod | 7 ++++--- integration-tests/go.sum | 14 ++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bcfbc9ad0..bcc7f22ec 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -14,9 +14,9 @@ require ( github.com/rs/zerolog v1.30.0 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e - github.com/smartcontractkit/chainlink-testing-framework v1.27.0 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240321154927-31350477ae51 - github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240321154927-31350477ae51 + github.com/smartcontractkit/chainlink-testing-framework v1.27.3 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240322204500-8162f7b1012d + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240322204500-8162f7b1012d github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.28.0 @@ -128,6 +128,7 @@ require ( github.com/docker/docker v25.0.2+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/dominikbraun/graph v0.23.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index aeafaf7db..e56df575a 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -404,6 +404,8 @@ github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= +github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -1419,14 +1421,14 @@ github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= -github.com/smartcontractkit/chainlink-testing-framework v1.27.0 h1:fs60anZu4VMPv0E9TtGo9uQ4kJcqChClxgjC9ArvqN4= -github.com/smartcontractkit/chainlink-testing-framework v1.27.0/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= +github.com/smartcontractkit/chainlink-testing-framework v1.27.3 h1:rUvTtLXPcxI5s3AttdpWeWTNXAprrjyyBvBEvYZp994= +github.com/smartcontractkit/chainlink-testing-framework v1.27.3/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240321154927-31350477ae51 h1:GpnHh/3Pn7dioR9P8jpPv6NKUAaXg+7FQLQluZ2lyn8= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240321154927-31350477ae51/go.mod h1:Wx8qoqkK1akgHnyeGwVlTWd0EKpKYy7HmsM2Rj1HOgw= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240321154927-31350477ae51 h1:cuRZhnBrGfyrD2tc1Fp0s1fdGeBUBSZLyDkdo5lEw3M= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240321154927-31350477ae51/go.mod h1:bsdQB5So2RZ+gneOPexVpfD1M65h9itn4rd6iFwbQH8= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240322204500-8162f7b1012d h1:aLt03YSJQcOfBHuFb5N/aJLGvT7c+OXFVhKx1MNEJMA= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240322204500-8162f7b1012d/go.mod h1:j2WmzOnhq/qGbgcNDtE+Etwt+ZesDy6mWb0gf3Zt714= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240322204500-8162f7b1012d h1:X8S3alXl/Q3koShShet48xkhp7D2VNHtPW7GZBG5AFc= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240322204500-8162f7b1012d/go.mod h1:U/4dT+sjottvAg5cdJ2XOu+HKkIKmAy+zOB4whiHHag= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= From 8d077323a3160d857a9e4b17eac247501a4d47c3 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Mon, 25 Mar 2024 07:32:10 -0600 Subject: [PATCH 12/14] SIMD Tracking (#641) * testing SIMD tracking * test: skipping issue creation * split into separate workflow + run once a week --- .github/workflows/dependency-updates.yml | 4 +-- .github/workflows/upstream-tracker.yml | 33 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/upstream-tracker.yml diff --git a/.github/workflows/dependency-updates.yml b/.github/workflows/dependency-updates.yml index 52ac166c6..e7219013d 100644 --- a/.github/workflows/dependency-updates.yml +++ b/.github/workflows/dependency-updates.yml @@ -16,7 +16,7 @@ jobs: # outputs echo "name=bump/solana-$image" >> "$GITHUB_OUTPUT" echo "prTitle=[automated] bump solana image to $image" >> "$GITHUB_OUTPUT" - echo "prBody=(run CI by closing + reopening PR) Latest Solana mainnet release is [$image](https://github.com/solana-labs/solana/releases/latest)" >> "$GITHUB_OUTPUT" + echo "prBody=Latest Solana mainnet release is [$image](https://github.com/solana-labs/solana/releases/latest)" >> "$GITHUB_OUTPUT" echo "commitString=[automated] bump solana dependencies" >> "$GITHUB_OUTPUT" secrets: inherit E2E-Testing-Dependencies: @@ -48,6 +48,6 @@ jobs: # outputs echo "name=bump/e2e-deps-$coreVersion" >> "$GITHUB_OUTPUT" echo "prTitle=[automated] bump e2e test deps to match chainlink/integration-tests" >> "$GITHUB_OUTPUT" - echo "prBody=(run CI by closing + reopening PR) chainlink/integration-tests uses chainlink-testing-framework@$coreVersion" >> "$GITHUB_OUTPUT" + echo "prBody=chainlink/integration-tests uses chainlink-testing-framework@$coreVersion" >> "$GITHUB_OUTPUT" echo "commitString=[automated] bump e2e <> core/integration-tests dependencies" >> "$GITHUB_OUTPUT" secrets: inherit diff --git a/.github/workflows/upstream-tracker.yml b/.github/workflows/upstream-tracker.yml new file mode 100644 index 000000000..4c068f603 --- /dev/null +++ b/.github/workflows/upstream-tracker.yml @@ -0,0 +1,33 @@ +name: UpstreamTracker +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 1' # check monday at midnight UTC + +jobs: + SIMD-Update-Checker: + runs-on: ubuntu-latest + steps: + - name: Check For Updates In Past Week + id: updates + run: | + # new PRs + OPEN=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state=open\&per_page=100 | jq --arg t "$(date -d '7 days ago' +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + # macos + # OPEN=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state\=open\&per_page\=100 | jq --arg t "$(date -v-7d +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + + # closed PRs + CLOSED=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state=closed\&per_page=100 | jq --arg t "$(date -d '7 days ago' +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + # macos + # CLOSED=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state\=closed\&per_page\=100 | jq --arg t "$(date -v-7d +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + + echo "open=$OPEN" >> "$GITHUB_OUTPUT" + echo "closed=$CLOSED" >> "$GITHUB_OUTPUT" + - uses: actions/checkout@v3 + if: steps.updates.outputs.open || steps.updates.outputs.closed + - name: Open Issue + if: steps.updates.outputs.open || steps.updates.outputs.closed + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # TODO: update tagged to team + run: gh issue create -a aalu1418 -t "SIMD Updates - $(date)" -l "[auto] SIMD Updates" -b $'## Opened\n${{ steps.updates.outputs.open}}\n\n## Closed\n${{ steps.updates.outputs.closed}}' From 33b485eeeb36550b0404874d8832789d85bc65d4 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-infra-releng[bot]" <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 07:33:36 -0600 Subject: [PATCH 13/14] [automated] bump solana image to v1.17.28 (#645) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- integration-tests/docker/test_env/sol.go | 2 +- scripts/install-solana-ci.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/docker/test_env/sol.go b/integration-tests/docker/test_env/sol.go index 4ecc7e520..d2f83818b 100644 --- a/integration-tests/docker/test_env/sol.go +++ b/integration-tests/docker/test_env/sol.go @@ -157,7 +157,7 @@ func (ms *Solana) getContainerRequest(inactiveFeatures InactiveFeatures) (*tc.Co return &tc.ContainerRequest{ Name: ms.ContainerName, - Image: "solanalabs/solana:v1.17.27", + Image: "solanalabs/solana:v1.17.28", ExposedPorts: []string{test_env.NatPortFormat(SOL_HTTP_PORT), test_env.NatPortFormat(SOL_WS_PORT)}, Env: map[string]string{ "SERVER_PORT": "1080", diff --git a/scripts/install-solana-ci.sh b/scripts/install-solana-ci.sh index c983f7a73..633287384 100755 --- a/scripts/install-solana-ci.sh +++ b/scripts/install-solana-ci.sh @@ -2,5 +2,5 @@ set -euxo pipefail -sh -c "$(curl -sSfL https://release.solana.com/v1.17.27/install)" +sh -c "$(curl -sSfL https://release.solana.com/v1.17.28/install)" echo "PATH=$HOME/.local/share/solana/install/active_release/bin:$PATH" >> $GITHUB_ENV From f7f633e33665c63f5a72c6a2249e8476d87ba0df Mon Sep 17 00:00:00 2001 From: "app-token-issuer-infra-releng[bot]" <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 07:35:33 -0600 Subject: [PATCH 14/14] [automated] bump e2e test deps to match chainlink/integration-tests (#647) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- integration-tests/go.mod | 36 ++++++++++--------- integration-tests/go.sum | 77 ++++++++++++++++++++++------------------ 2 files changed, 62 insertions(+), 51 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bcc7f22ec..fec496004 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -12,16 +12,16 @@ require ( github.com/lib/pq v1.10.9 github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240327133125-eed636b9a6df github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e - github.com/smartcontractkit/chainlink-testing-framework v1.27.3 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240322204500-8162f7b1012d - github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240322204500-8162f7b1012d - github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 + github.com/smartcontractkit/chainlink-testing-framework v1.27.8 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240327222022-90568911d216 + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240327222022-90568911d216 + github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.28.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.19.0 + golang.org/x/crypto v0.21.0 golang.org/x/exp v0.0.0-20240213143201-ec583247a57a golang.org/x/sync v0.6.0 gopkg.in/guregu/null.v4 v4.0.0 @@ -56,6 +56,8 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/NethermindEth/juno v0.3.1 // indirect + github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect @@ -66,6 +68,7 @@ require ( github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -189,7 +192,7 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.0 // indirect github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gnostic v0.6.9 // indirect @@ -250,14 +253,15 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.1 // indirect + github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.1 // indirect + github.com/jackc/pgx/v4 v4.18.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -357,13 +361,12 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/slack-go/slack v0.12.2 // indirect - github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect github.com/smartcontractkit/seth v0.1.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect @@ -402,6 +405,7 @@ require ( github.com/umbracle/ethgo v0.1.3 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.1.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -436,8 +440,8 @@ require ( golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.18.0 // indirect @@ -448,7 +452,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect @@ -472,7 +476,7 @@ require ( sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e56df575a..0fcb95925 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -132,6 +132,10 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= +github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 h1:9SBvy3eZut1X+wEyAFqfb7ADGj8IQw7ZnlkMwz0YOTY= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1/go.mod h1:V6qrbi1+fTDCftETIT1grBXIf+TvWP/4Aois1a9EF1E= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -192,6 +196,8 @@ github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3s github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -689,8 +695,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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 v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -934,6 +940,8 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/ionos-cloud/sdk-go/v6 v6.1.9 h1:Iq3VIXzeEbc8EbButuACgfLMiY5TPVWUPNrF+Vsddo4= github.com/ionos-cloud/sdk-go/v6 v6.1.9/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -946,9 +954,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= -github.com/jackc/pgconn v1.14.1 h1:smbxIaZA08n6YuxEX1sDyjV/qkbtUtkH20qLkR9MUR4= -github.com/jackc/pgconn v1.14.1/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= +github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -964,8 +971,8 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= -github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +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= @@ -979,12 +986,11 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08 github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= -github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= +github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= 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/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -1366,6 +1372,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1405,36 +1413,34 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35/go.mod h1:2I0dWdYdK6jHPnSYYy7Y7Xp7L0YTnJ3KZtkhLQflsTU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c h1:EKWa6Il+8Z36Mcs4eQJJP8aUyZX0nCDfdzhzZkC4W8o= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240320150640-2ab7f210b05c/go.mod h1://xWphjmC6GWJtT8l86J2VpnG21xNwFCb0thzz4ItEk= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240327133125-eed636b9a6df h1:AKjckaIV8R53dLJwoQ3VlUI56L34Ca+nkkzjR1784zY= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240327133125-eed636b9a6df/go.mod h1:u2XnvJHl7sQ9HMlRnVLsOKgV9ihk0RGIYywB12p9gQQ= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= -github.com/smartcontractkit/chainlink-testing-framework v1.27.3 h1:rUvTtLXPcxI5s3AttdpWeWTNXAprrjyyBvBEvYZp994= -github.com/smartcontractkit/chainlink-testing-framework v1.27.3/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8 h1:V1G4hVjztvFuY6dPfBdv53OzQ99lwLUraXH0Wapyh3Q= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240322204500-8162f7b1012d h1:aLt03YSJQcOfBHuFb5N/aJLGvT7c+OXFVhKx1MNEJMA= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240322204500-8162f7b1012d/go.mod h1:j2WmzOnhq/qGbgcNDtE+Etwt+ZesDy6mWb0gf3Zt714= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240322204500-8162f7b1012d h1:X8S3alXl/Q3koShShet48xkhp7D2VNHtPW7GZBG5AFc= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240322204500-8162f7b1012d/go.mod h1:U/4dT+sjottvAg5cdJ2XOu+HKkIKmAy+zOB4whiHHag= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240327222022-90568911d216 h1:tJLpFGp0LhlUN6G30FwbLDYjvJkQGPB2Ca5Ij5fpS9A= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240327222022-90568911d216/go.mod h1:cD8iUq244aN237wHe0KwJYOjsCJ6TUGUJ6ukpp1Fr/w= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240327222022-90568911d216 h1:9698nTCBXxy/jPn4B10eXLRfrBveRnQFK6gv2AJcOwQ= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240327222022-90568911d216/go.mod h1:KagwtDKSGK5L45xmFKKxlYMMSlZJVOAfM+B2CJwIqLo= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 h1:xsU00JB9GJxEiN6tDbqgN+fT98ySdxkUwTw6CfBXscw= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 h1:1WFjrrVrWoQ9UpVMh7Mx4jDpzhmo1h8hFUKd9awIhIU= +github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= github.com/smartcontractkit/seth v0.1.2 h1:ImXJmniuq6yWB6b3eezjV+lkYb1GfQuaJkwRvrCfTKQ= github.com/smartcontractkit/seth v0.1.2/go.mod h1:aOaGwrIVFG/MYaLSj9UUMyE5QJnYQoAgnxm5cKfT9Ng= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= @@ -1571,6 +1577,8 @@ github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7E github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -1733,10 +1741,9 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1965,8 +1972,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1976,8 +1983,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2204,8 +2211,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba 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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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= @@ -2297,5 +2304,5 @@ sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2 sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=