From 43f4b14c28e47b7b1f0f2d9866b138277769c042 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 2 Apr 2024 14:40:02 +0200 Subject: [PATCH 01/11] kvdb+sqldb: use the same tx retry helper --- go.mod | 9 +- go.sum | 2 - kvdb/go.mod | 90 +++++++++++------ kvdb/go.sum | 237 +++++++++++++++++++++++++++++++------------- kvdb/sqlbase/db.go | 155 +++++++++-------------------- sqldb/interfaces.go | 199 +++++++++++++++++++++++++++++-------- 6 files changed, 437 insertions(+), 255 deletions(-) diff --git a/go.mod b/go.mod index 09c462e0d..6995e40b1 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/lightningnetwork/lnd/healthcheck v1.2.3 github.com/lightningnetwork/lnd/kvdb v1.4.5 github.com/lightningnetwork/lnd/queue v1.1.1 - github.com/lightningnetwork/lnd/sqldb v0.0.0-00010101000000-000000000000 + github.com/lightningnetwork/lnd/sqldb v1.0.0 github.com/lightningnetwork/lnd/ticker v1.1.1 github.com/lightningnetwork/lnd/tlv v1.2.3 github.com/lightningnetwork/lnd/tor v1.1.2 @@ -203,7 +203,12 @@ replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 // allows us to specify that as an option. replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display -// Temporary replace rule until sqldb is tagged. +// Temporary replace rule until kvdb is tagged with changes from +// https://github.com/lightningnetwork/lnd/pull/8611. +replace github.com/lightningnetwork/lnd/kvdb => ./kvdb + +// Temporary replace rule until sqldb is tagged with changes from +// https://github.com/lightningnetwork/lnd/pull/8611. replace github.com/lightningnetwork/lnd/sqldb => ./sqldb // If you change this please also update .github/pull_request_template.md and diff --git a/go.sum b/go.sum index 2e4e9c957..550bbb84b 100644 --- a/go.sum +++ b/go.sum @@ -449,8 +449,6 @@ github.com/lightningnetwork/lnd/fn v1.0.5 h1:ffDgMSn83avw6rNzxhbt6w5/2oIrwQKTPGf github.com/lightningnetwork/lnd/fn v1.0.5/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U= github.com/lightningnetwork/lnd/healthcheck v1.2.3 h1:oqhOOy8WmIEa6RBkYKC0mmYZkhl8T2kGD97n9jpML8o= github.com/lightningnetwork/lnd/healthcheck v1.2.3/go.mod h1:eDxH3dEwV9DeBW/6inrmlVh1qBOFV0AI14EEPnGt9gc= -github.com/lightningnetwork/lnd/kvdb v1.4.5 h1:wwX3hbFTsnxEIL5X2Pszq1o3Fd2OZGdyWIMr9QrMxL8= -github.com/lightningnetwork/lnd/kvdb v1.4.5/go.mod h1:oaGL6R/qwazM7hPurg8jSPYsWw3cGEOt6YJDs5TUNos= github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= diff --git a/kvdb/go.mod b/kvdb/go.mod index a4bbb513e..861558c6c 100644 --- a/kvdb/go.mod +++ b/kvdb/go.mod @@ -6,63 +6,87 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/fergusstrange/embedded-postgres v1.25.0 github.com/google/btree v1.0.1 - github.com/jackc/pgconn v1.14.0 - github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa + github.com/jackc/pgconn v1.14.3 + github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 github.com/jackc/pgx/v4 v4.18.1 github.com/lightningnetwork/lnd/healthcheck v1.0.0 - github.com/stretchr/testify v1.8.2 + github.com/lightningnetwork/lnd/sqldb v0.0.0-00010101000000-000000000000 + github.com/stretchr/testify v1.9.0 go.etcd.io/bbolt v1.3.7 go.etcd.io/etcd/api/v3 v3.5.7 go.etcd.io/etcd/client/pkg/v3 v3.5.7 go.etcd.io/etcd/client/v3 v3.5.7 go.etcd.io/etcd/server/v3 v3.5.7 - golang.org/x/net v0.17.0 - modernc.org/sqlite v1.20.3 + golang.org/x/net v0.22.0 + modernc.org/sqlite v1.29.5 ) require ( + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/containerd/continuity v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect + github.com/docker/cli v20.10.17+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang-migrate/migrate/v4 v4.17.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // 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/jonboulle/clockwork v0.2.2 // indirect github.com/json-iterator/go v1.1.11 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/pretty v0.3.0 // indirect - github.com/lib/pq v1.10.4 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/lightningnetwork/lnd/ticker v1.0.0 // indirect github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.4.1 // 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.1 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/runc v1.1.5 // indirect + github.com/ory/dockertest/v3 v3.10.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/sirupsen/logrus v1.9.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/etcd/client/v2 v2.305.7 // indirect @@ -78,28 +102,28 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/mod v0.10.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect - golang.org/x/tools v0.9.1 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - google.golang.org/grpc v1.56.3 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect + golang.org/x/mod v0.16.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.19.0 // indirect + google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.40.0 // indirect - modernc.org/ccgo/v3 v3.16.13 // indirect - modernc.org/libc v1.22.2 // indirect - modernc.org/mathutil v1.5.0 // indirect - modernc.org/memory v1.4.0 // indirect - modernc.org/opt v0.1.3 // indirect - modernc.org/strutil v1.1.3 // indirect - modernc.org/token v1.0.1 // indirect + modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect + modernc.org/libc v1.41.0 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.2 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) @@ -113,4 +137,8 @@ replace github.com/ulikunitz/xz => github.com/ulikunitz/xz v0.5.11 // https://deps.dev/advisory/OSV/GO-2021-0053?from=%2Fgo%2Fgithub.com%252Fgogo%252Fprotobuf%2Fv1.3.1 replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 -go 1.19 +// Temporary replace rule until sqldb is tagged with changes from +// https://github.com/lightningnetwork/lnd/pull/8611. +replace github.com/lightningnetwork/lnd/sqldb => ../sqldb + +go 1.21.4 diff --git a/kvdb/go.sum b/kvdb/go.sum index 96bf7970d..8529056a5 100644 --- a/kvdb/go.sum +++ b/kvdb/go.sum @@ -1,12 +1,20 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +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/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= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -27,34 +35,61 @@ github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8 github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M= +github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78= +github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +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/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -63,10 +98,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fergusstrange/embedded-postgres v1.25.0 h1:sa+k2Ycrtz40eCRPOzI7Ry7TtkWXXJ+YRsxpKMDhxK0= github.com/fergusstrange/embedded-postgres v1.25.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -74,14 +112,19 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYND2gB4p7xcaU= +github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -111,12 +154,16 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -125,6 +172,15 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +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/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -135,10 +191,11 @@ 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 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= -github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw= -github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +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/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= +github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= 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= @@ -154,8 +211,9 @@ 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= @@ -184,8 +242,6 @@ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMW github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -205,8 +261,8 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightningnetwork/lnd/healthcheck v1.0.0 h1:0Cj8aiFB1OANsUuW9P0OlheSPcZEB38rUQXankr8ZpU= github.com/lightningnetwork/lnd/healthcheck v1.0.0/go.mod h1:u92p1JGFJNMSkMvztKEwmt1P3TRnLeJBXZ3M85xkU1E= github.com/lightningnetwork/lnd/ticker v1.0.0 h1:S1b60TEGoTtCe2A0yeB+ecoj/kkS4qpwh6l+AkQEZwU= @@ -218,19 +274,39 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +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= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= 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/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= +github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= 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= @@ -256,8 +332,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -266,14 +342,18 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= @@ -294,10 +374,20 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +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/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= @@ -345,6 +435,7 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -368,9 +459,11 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +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-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -380,8 +473,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -397,15 +490,17 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -414,7 +509,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ 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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -423,8 +519,10 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -439,13 +537,17 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -457,10 +559,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -476,8 +578,8 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -487,13 +589,18 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= +google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= +google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -504,8 +611,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -518,8 +625,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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= @@ -543,32 +650,26 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= +gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= -modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= -modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= -modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= -modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk= -modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs= -modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A= -modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= -modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= -modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= +modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= +modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE= +modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index f6f2c7590..16227a97f 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -8,12 +8,12 @@ import ( "errors" "fmt" "io" - "math" - "math/rand" + "strings" "sync" "time" "github.com/btcsuite/btcwallet/walletdb" + "github.com/lightningnetwork/lnd/sqldb" ) const ( @@ -24,18 +24,7 @@ const ( // DefaultNumTxRetries is the default number of times we'll retry a // transaction if it fails with an error that permits transaction // repetition. - DefaultNumTxRetries = 10 - - // DefaultInitialRetryDelay is the default initial delay between - // retries. This will be used to generate a random delay between -50% - // and +50% of this value, so 20 to 60 milliseconds. The retry will be - // doubled after each attempt until we reach DefaultMaxRetryDelay. We - // start with a random value to avoid multiple goroutines that are - // created at the same time to effectively retry at the same time. - DefaultInitialRetryDelay = time.Millisecond * 50 - - // DefaultMaxRetryDelay is the default maximum delay between retries. - DefaultMaxRetryDelay = time.Second * 5 + DefaultNumTxRetries = 50 ) // Config holds a set of configuration options of a sql database connection. @@ -227,112 +216,43 @@ func (db *db) Update(f func(tx walletdb.ReadWriteTx) error, return db.executeTransaction(f, reset, false) } -// randRetryDelay returns a random retry delay between -50% and +50% of the -// configured delay that is doubled for each attempt and capped at a max value. -func randRetryDelay(initialRetryDelay, maxRetryDelay time.Duration, - attempt int) time.Duration { - - halfDelay := initialRetryDelay / 2 - randDelay := rand.Int63n(int64(initialRetryDelay)) //nolint:gosec - - // 50% plus 0%-100% gives us the range of 50%-150%. - initialDelay := halfDelay + time.Duration(randDelay) - - // If this is the first attempt, we just return the initial delay. - if attempt == 0 { - return initialDelay - } - - // For each subsequent delay, we double the initial delay. This still - // gives us a somewhat random delay, but it still increases with each - // attempt. If we double something n times, that's the same as - // multiplying the value with 2^n. We limit the power to 32 to avoid - // overflows. - factor := time.Duration(math.Pow(2, math.Min(float64(attempt), 32))) - actualDelay := initialDelay * factor - - // Cap the delay at the maximum configured value. - if actualDelay > maxRetryDelay { - return maxRetryDelay - } - - return actualDelay -} - // executeTransaction creates a new read-only or read-write transaction and // executes the given function within it. func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, reset func(), readOnly bool) error { - // waitBeforeRetry is a helper function that will wait for a random - // interval before exiting to retry the db transaction. If false is - // returned, then this means that daemon is shutting down so we - // should abort the retries. - waitBeforeRetry := func(attemptNumber int) bool { - retryDelay := randRetryDelay( - DefaultInitialRetryDelay, DefaultMaxRetryDelay, - attemptNumber, - ) - - log.Debugf("Retrying transaction due to tx serialization "+ - "error, attempt_number=%v, delay=%v", attemptNumber, - retryDelay) - - select { - // Before we try again, we'll wait with a random backoff based - // on the retry delay. - case <-time.After(retryDelay): - return true - - // If the daemon is shutting down, then we'll exit early. - case <-db.ctx.Done(): - return false - } + makeTx := func() (sqldb.Tx, error) { + return newReadWriteTx(db, readOnly) } - for i := 0; i < DefaultNumTxRetries; i++ { + execTxBody := func(tx sqldb.Tx) error { + kvTx, ok := tx.(*readWriteTx) + if !ok { + return fmt.Errorf("expected *readWriteTx, got %T", tx) + } + reset() - - tx, err := newReadWriteTx(db, readOnly) - if err != nil { - dbErr := MapSQLError(err) - - if IsSerializationError(dbErr) { - // Nothing to roll back here, since we didn't - // even get a transaction yet. - if waitBeforeRetry(i) { - continue - } - } - - return dbErr - } - - err = catchPanic(func() error { return f(tx) }) - if err != nil { - if rollbackErr := tx.Rollback(); rollbackErr != nil { - log.Errorf("Error rolling back tx: %v", - rollbackErr) - } - - return err - } - - dbErr := tx.Commit() - if IsSerializationError(dbErr) { - _ = tx.Rollback() - - if waitBeforeRetry(i) { - continue - } - } - - return dbErr + return catchPanic(func() error { return f(kvTx) }) } - // If we get to this point, then we weren't able to successfully commit - // a tx given the max number of retries. - return ErrRetriesExceeded + onBackoff := func(retry int, delay time.Duration) { + log.Tracef("Retrying transaction due to tx serialization "+ + "error, attempt_number=%v, delay=%v", retry, delay) + } + + rollbackTx := func(tx sqldb.Tx) error { + kvTx, ok := tx.(*readWriteTx) + if !ok { + return fmt.Errorf("expected *readWriteTx, got %T", tx) + } + + return attemptRollback(kvTx) + } + + return sqldb.ExecuteSQLTransactionWithRetry( + db.ctx, makeTx, rollbackTx, execTxBody, onBackoff, + DefaultNumTxRetries, + ) } // PrintStats returns all collected stats pretty printed into a string. @@ -367,3 +287,18 @@ func (db *db) Close() error { return dbConns.Close(db.cfg.Dsn) } + +// attemptRollback attempts to roll back the transaction, and if it fails, it +// will return the error. If the transaction was already closed, it will return +// nil. +func attemptRollback(tx *readWriteTx) error { + rollbackErr := tx.Rollback() + if rollbackErr != nil && + !errors.Is(rollbackErr, walletdb.ErrTxClosed) && + !strings.Contains(rollbackErr.Error(), "conn closed") { + + return fmt.Errorf("error rolling back tx: %w", rollbackErr) + } + + return nil +} diff --git a/sqldb/interfaces.go b/sqldb/interfaces.go index 3a031df6f..53defdd3c 100644 --- a/sqldb/interfaces.go +++ b/sqldb/interfaces.go @@ -3,6 +3,9 @@ package sqldb import ( "context" "database/sql" + "fmt" + "math" + "math/rand" prand "math/rand" "time" @@ -24,6 +27,9 @@ const ( // DefaultRetryDelay is the default delay between retries. This will be // used to generate a random delay between 0 and this value. DefaultRetryDelay = time.Millisecond * 50 + + // DefaultMaxRetryDelay is the default maximum delay between retries. + DefaultMaxRetryDelay = time.Second ) // TxOptions represents a set of options one can use to control what type of @@ -156,38 +162,98 @@ func NewTransactionExecutor[Querier any](db BatchedQuerier, } } -// ExecTx is a wrapper for txBody to abstract the creation and commit of a db -// transaction. The db transaction is embedded in a `*Queries` that txBody -// needs to use when executing each one of the queries that need to be applied -// atomically. This can be used by other storage interfaces to parameterize the -// type of query and options run, in order to have access to batched operations -// related to a storage object. -func (t *TransactionExecutor[Q]) ExecTx(ctx context.Context, - txOptions TxOptions, txBody func(Q) error) error { +// randRetryDelay returns a random retry delay between -50% and +50% of the +// configured delay that is doubled for each attempt and capped at a max value. +func randRetryDelay(initialRetryDelay, maxRetryDelay time.Duration, + attempt int) time.Duration { - waitBeforeRetry := func(attemptNumber int) { - retryDelay := t.opts.randRetryDelay() + halfDelay := initialRetryDelay / 2 + randDelay := rand.Int63n(int64(initialRetryDelay)) //nolint:gosec - log.Tracef("Retrying transaction due to tx serialization "+ - "error, attempt_number=%v, delay=%v", attemptNumber, - retryDelay) + // 50% plus 0%-100% gives us the range of 50%-150%. + initialDelay := halfDelay + time.Duration(randDelay) - // Before we try again, we'll wait with a random backoff based - // on the retry delay. - time.Sleep(retryDelay) + // If this is the first attempt, we just return the initial delay. + if attempt == 0 { + return initialDelay } - for i := 0; i < t.opts.numRetries; i++ { - // Create the db transaction. - tx, err := t.BatchedQuerier.BeginTx(ctx, txOptions) + // For each subsequent delay, we double the initial delay. This still + // gives us a somewhat random delay, but it still increases with each + // attempt. If we double something n times, that's the same as + // multiplying the value with 2^n. We limit the power to 32 to avoid + // overflows. + factor := time.Duration(math.Pow(2, math.Min(float64(attempt), 32))) + actualDelay := initialDelay * factor + + // Cap the delay at the maximum configured value. + if actualDelay > maxRetryDelay { + return maxRetryDelay + } + + return actualDelay +} + +// MakeTx is a function that creates a new transaction. It returns a Tx and an +// error if the transaction cannot be created. This is used to abstract the +// creation of a transaction from the actual transaction logic in order to be +// able to reuse the transaction retry logic in other packages. +type MakeTx func() (Tx, error) + +// TxBody represents the function type for transactions. It returns an +// error to indicate success or failure. +type TxBody func(tx Tx) error + +// RollbackTx is a function that is called when a transaction needs to be rolled +// back due to a serialization error. By using this intermediate function, we +// can avoid having to return rollback errors that are not actionable by the +// caller. +type RollbackTx func(tx Tx) error + +// OnBackoff is a function that is called when a transaction is retried due to a +// serialization error. The function is called with the retry attempt number and +// the delay before the next retry. +type OnBackoff func(retry int, delay time.Duration) + +// ExecuteSQLTransactionWithRetry is a helper function that executes a +// transaction with retry logic. It will retry the transaction if it fails with +// a serialization error. The function will return an error if the transaction +// fails with a non-retryable error, the context is cancelled or the number of +// retries is exceeded. +func ExecuteSQLTransactionWithRetry(ctx context.Context, makeTx MakeTx, + rollbackTx RollbackTx, txBody TxBody, onBackoff OnBackoff, + numRetries int) error { + + waitBeforeRetry := func(attemptNumber int) bool { + retryDelay := randRetryDelay( + DefaultRetryDelay, DefaultMaxRetryDelay, attemptNumber, + ) + + onBackoff(attemptNumber, retryDelay) + + select { + // Before we try again, we'll wait with a random backoff based + // on the retry delay. + case <-time.After(retryDelay): + return true + + // If the daemon is shutting down, then we'll exit early. + case <-ctx.Done(): + return false + } + } + + for i := 0; i < numRetries; i++ { + tx, err := makeTx() if err != nil { dbErr := MapSQLError(err) if IsSerializationError(dbErr) { - // Nothing to roll back here, since we didn't - // even get a transaction yet. - waitBeforeRetry(i) - - continue + // Nothing to roll back here, since we haven't + // even get a transaction yet. We'll just wait + // and try again. + if waitBeforeRetry(i) { + continue + } } return dbErr @@ -199,32 +265,38 @@ func (t *TransactionExecutor[Q]) ExecTx(ctx context.Context, _ = tx.Rollback() }() - if err := txBody(t.createQuery(tx)); err != nil { - dbErr := MapSQLError(err) + if bodyErr := txBody(tx); bodyErr != nil { + // Roll back the transaction, then attempt a random + // backoff and try again if the error was a + // serialization error. + if err := rollbackTx(tx); err != nil { + return MapSQLError(err) + } + + dbErr := MapSQLError(bodyErr) if IsSerializationError(dbErr) { - // Roll back the transaction, then pop back up - // to try once again. - _ = tx.Rollback() - - waitBeforeRetry(i) - - continue + if waitBeforeRetry(i) { + continue + } } return dbErr } // Commit transaction. - if err = tx.Commit(); err != nil { - dbErr := MapSQLError(err) + if commitErr := tx.Commit(); commitErr != nil { + // Roll back the transaction, then attempt a random + // backoff and try again if the error was a + // serialization error. + if err := rollbackTx(tx); err != nil { + return MapSQLError(err) + } + + dbErr := MapSQLError(commitErr) if IsSerializationError(dbErr) { - // Roll back the transaction, then pop back up - // to try once again. - _ = tx.Rollback() - - waitBeforeRetry(i) - - continue + if waitBeforeRetry(i) { + continue + } } return dbErr @@ -238,6 +310,49 @@ func (t *TransactionExecutor[Q]) ExecTx(ctx context.Context, return ErrRetriesExceeded } +// ExecTx is a wrapper for txBody to abstract the creation and commit of a db +// transaction. The db transaction is embedded in a `*Queries` that txBody +// needs to use when executing each one of the queries that need to be applied +// atomically. This can be used by other storage interfaces to parameterize the +// type of query and options run, in order to have access to batched operations +// related to a storage object. +func (t *TransactionExecutor[Q]) ExecTx(ctx context.Context, + txOptions TxOptions, txBody func(Q) error) error { + + makeTx := func() (Tx, error) { + return t.BatchedQuerier.BeginTx(ctx, txOptions) + } + + execTxBody := func(tx Tx) error { + sqlTx, ok := tx.(*sql.Tx) + if !ok { + return fmt.Errorf("expected *sql.Tx, got %T", tx) + } + return txBody(t.createQuery(sqlTx)) + } + + onBackoff := func(retry int, delay time.Duration) { + log.Tracef("Retrying transaction due to tx serialization "+ + "error, attempt_number=%v, delay=%v", retry, delay) + } + + rollbackTx := func(tx Tx) error { + sqlTx, ok := tx.(*sql.Tx) + if !ok { + return fmt.Errorf("expected *sql.Tx, got %T", tx) + } + + _ = sqlTx.Rollback() + + return nil + } + + return ExecuteSQLTransactionWithRetry( + ctx, makeTx, rollbackTx, execTxBody, onBackoff, + t.opts.numRetries, + ) +} + // BaseDB is the base database struct that each implementation can embed to // gain some common functionality. type BaseDB struct { From 329fcc64982d13927a6bb04ec65b0004cba2380e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:12:50 -0700 Subject: [PATCH 02/11] kvdb+sqldb: update SQL error parsing to account for non wrapped errs Some sub-systems like btcwallet will return an error from the database, but they won't properly wrap it. As a result, we were unable to actually catch the serialization errors in the first place. To work around this, we'll now attempt to parse the error string directly. --- kvdb/sqlbase/sqlerrors_postgres.go | 14 ++++++++++++++ kvdb/sqlbase/sqlerrors_sqlite.go | 16 ++++++++++++++++ sqldb/sqlerrors.go | 25 +++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/kvdb/sqlbase/sqlerrors_postgres.go b/kvdb/sqlbase/sqlerrors_postgres.go index 3915a34f4..1b12dda66 100644 --- a/kvdb/sqlbase/sqlerrors_postgres.go +++ b/kvdb/sqlbase/sqlerrors_postgres.go @@ -5,6 +5,7 @@ package sqlbase import ( "errors" "fmt" + "strings" "github.com/jackc/pgconn" "github.com/jackc/pgerrcode" @@ -13,6 +14,19 @@ import ( // parsePostgresError attempts to parse a postgres error as a database agnostic // SQL error. func parsePostgresError(err error) error { + if err == nil { + return nil + } + + // Sometimes the error won't be properly wrapped, so we'll need to + // inspect raw error itself to detect something we can wrap properly. + const postgresErrMsg = "could not serialize access" + if strings.Contains(err.Error(), postgresErrMsg) { + return &ErrSerializationError{ + DBError: err, + } + } + var pqErr *pgconn.PgError if !errors.As(err, &pqErr) { return nil diff --git a/kvdb/sqlbase/sqlerrors_sqlite.go b/kvdb/sqlbase/sqlerrors_sqlite.go index c29146610..9df93893a 100644 --- a/kvdb/sqlbase/sqlerrors_sqlite.go +++ b/kvdb/sqlbase/sqlerrors_sqlite.go @@ -5,6 +5,7 @@ package sqlbase import ( "errors" "fmt" + "strings" "modernc.org/sqlite" sqlite3 "modernc.org/sqlite/lib" @@ -13,6 +14,21 @@ import ( // parseSqliteError attempts to parse a sqlite error as a database agnostic // SQL error. func parseSqliteError(err error) error { + if err == nil { + return nil + } + + // If the error isn't wrapped properly, the errors.As call with fail, + // so we'll also try to check the expected error message directly. + // This is taken from: + // https://gitlab.com/cznic/sqlite/-/blob/v1.25.0/sqlite.go#L75. + const sqliteErrMsg = "SQLITE_BUSY" + if strings.Contains(err.Error(), sqliteErrMsg) { + return &ErrSerializationError{ + DBError: err, + } + } + var sqliteErr *sqlite.Error if !errors.As(err, &sqliteErr) { return nil diff --git a/sqldb/sqlerrors.go b/sqldb/sqlerrors.go index a939ec499..6cc1b1cf8 100644 --- a/sqldb/sqlerrors.go +++ b/sqldb/sqlerrors.go @@ -5,6 +5,7 @@ package sqldb import ( "errors" "fmt" + "strings" "github.com/jackc/pgconn" "github.com/jackc/pgerrcode" @@ -21,6 +22,10 @@ var ( // MapSQLError attempts to interpret a given error as a database agnostic SQL // error. func MapSQLError(err error) error { + if err == nil { + return nil + } + // Attempt to interpret the error as a sqlite error. var sqliteErr *sqlite.Error if errors.As(err, &sqliteErr) { @@ -33,6 +38,26 @@ func MapSQLError(err error) error { return parsePostgresError(pqErr) } + // Sometimes the error won't be properly wrapped, so we'll need to + // inspect raw error itself to detect something we can wrap properly. + // This handles a postgres variant of the error. + const postgresErrMsg = "could not serialize access" + if strings.Contains(err.Error(), postgresErrMsg) { + return &ErrSerializationError{ + DBError: err, + } + } + + // We'll also attempt to catch this for sqlite, that uses a slightly + // different error message. This is taken from: + // https://gitlab.com/cznic/sqlite/-/blob/v1.25.0/sqlite.go#L75. + const sqliteErrMsg = "SQLITE_BUSY" + if strings.Contains(err.Error(), sqliteErrMsg) { + return &ErrSerializationError{ + DBError: err, + } + } + // Return original error if it could not be classified as a database // specific error. return err From 120d6dd297fb1f27a6ee7dd21e6f5960d4940245 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:14:12 -0700 Subject: [PATCH 03/11] channeldb: explicitly catch error in pruneGraphNodes With the new postgres concurrency control, an error may come from a bucket function that's actually a postgres error. In this case, we need to return early so we can retry the txn. Otherwise, we'll be working with an aborted tx, and never actually return the error so we don't auto retry. --- channeldb/graph.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/channeldb/graph.go b/channeldb/graph.go index 2c000f3e7..99ccdaf0b 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -1508,9 +1508,15 @@ func (c *ChannelGraph) pruneGraphNodes(nodes kvdb.RwBucket, // If we reach this point, then there are no longer any edges // that connect this node, so we can delete it. if err := c.deleteLightningNode(nodes, nodePubKey[:]); err != nil { - log.Warnf("Unable to prune node %x from the "+ - "graph: %v", nodePubKey, err) - continue + if errors.Is(err, ErrGraphNodeNotFound) || + errors.Is(err, ErrGraphNodesNotFound) { + + log.Warnf("Unable to prune node %x from the "+ + "graph: %v", nodePubKey, err) + continue + } + + return err } log.Infof("Pruned unconnected node %x from channel graph", From cd0ca43a00b22395f1b915e073639ccab249af1d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:15:38 -0700 Subject: [PATCH 04/11] kvdb: don't do a critical log for db serialization errors In this commit, we fix a bug that would cause the entire db to shutdown if hit a panic (since db operations in the main buckets exit with a panic) while executing a txn call back. This might be a postgres error we need to check, so we don't want to bail out, and instead want to pass up the error to the caller so we can retry if needed. --- kvdb/sqlbase/db.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 16227a97f..221a77bfd 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -170,8 +170,6 @@ func (db *db) getPrefixedTableName(table string) string { func catchPanic(f func() error) (err error) { defer func() { if r := recover(); r != nil { - log.Criticalf("Caught unhandled error: %v", r) - switch data := r.(type) { case error: err = data @@ -179,6 +177,18 @@ func catchPanic(f func() error) (err error) { default: err = errors.New(fmt.Sprintf("%v", data)) } + + // Before we issue a critical log which'll cause the + // daemon to shut down, we'll first check if this is a + // DB serialization error. If so, then we don't need to + // log as we can retry safely and avoid tearing + // everything down. + if sqldb.IsSerializationError(sqldb.MapSQLError(err)) { + log.Tracef("Detected db serialization error "+ + "via panic: %v", err) + } else { + log.Criticalf("Caught unhandled error: %v", r) + } } }() From 9a28a4c1056af217edbff781e77cbc4139ec7047 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 2 Apr 2024 15:16:07 +0200 Subject: [PATCH 05/11] kvdb: remove the unused SQL error mappers --- kvdb/go.mod | 4 +- kvdb/sqlbase/sqlerrors.go | 64 --------------------------- kvdb/sqlbase/sqlerrors_no_postgres.go | 9 ---- kvdb/sqlbase/sqlerrors_no_sqlite.go | 9 ---- kvdb/sqlbase/sqlerrors_postgres.go | 51 --------------------- kvdb/sqlbase/sqlerrors_sqlite.go | 53 ---------------------- 6 files changed, 2 insertions(+), 188 deletions(-) delete mode 100644 kvdb/sqlbase/sqlerrors.go delete mode 100644 kvdb/sqlbase/sqlerrors_no_postgres.go delete mode 100644 kvdb/sqlbase/sqlerrors_no_sqlite.go delete mode 100644 kvdb/sqlbase/sqlerrors_postgres.go delete mode 100644 kvdb/sqlbase/sqlerrors_sqlite.go diff --git a/kvdb/go.mod b/kvdb/go.mod index 861558c6c..721342950 100644 --- a/kvdb/go.mod +++ b/kvdb/go.mod @@ -6,8 +6,6 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/fergusstrange/embedded-postgres v1.25.0 github.com/google/btree v1.0.1 - github.com/jackc/pgconn v1.14.3 - github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 github.com/jackc/pgx/v4 v4.18.1 github.com/lightningnetwork/lnd/healthcheck v1.0.0 github.com/lightningnetwork/lnd/sqldb v0.0.0-00010101000000-000000000000 @@ -51,6 +49,8 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.3 // indirect + github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.3.3 // indirect diff --git a/kvdb/sqlbase/sqlerrors.go b/kvdb/sqlbase/sqlerrors.go deleted file mode 100644 index 5e8afdb41..000000000 --- a/kvdb/sqlbase/sqlerrors.go +++ /dev/null @@ -1,64 +0,0 @@ -package sqlbase - -import ( - "errors" - "fmt" -) - -var ( - // ErrRetriesExceeded is returned when a transaction is retried more - // than the max allowed valued without a success. - ErrRetriesExceeded = errors.New("db tx retries exceeded") -) - -// MapSQLError attempts to interpret a given error as a database agnostic SQL -// error. -func MapSQLError(err error) error { - // Attempt to interpret the error as a sqlite error. - if sqliteErr := parseSqliteError(err); sqliteErr != nil { - return sqliteErr - } - - // Attempt to interpret the error as a postgres error. - if postgresErr := parsePostgresError(err); postgresErr != nil { - return postgresErr - } - - // Return original error if it could not be classified as a database - // specific error. - return err -} - -// ErrSQLUniqueConstraintViolation is an error type which represents a database -// agnostic SQL unique constraint violation. -type ErrSQLUniqueConstraintViolation struct { - DBError error -} - -func (e ErrSQLUniqueConstraintViolation) Error() string { - return fmt.Sprintf("sql unique constraint violation: %v", e.DBError) -} - -// ErrSerializationError is an error type which represents a database agnostic -// error that a transaction couldn't be serialized with other concurrent db -// transactions. -type ErrSerializationError struct { - DBError error -} - -// Unwrap returns the wrapped error. -func (e ErrSerializationError) Unwrap() error { - return e.DBError -} - -// Error returns the error message. -func (e ErrSerializationError) Error() string { - return e.DBError.Error() -} - -// IsSerializationError returns true if the given error is a serialization -// error. -func IsSerializationError(err error) bool { - var serializationError *ErrSerializationError - return errors.As(err, &serializationError) -} diff --git a/kvdb/sqlbase/sqlerrors_no_postgres.go b/kvdb/sqlbase/sqlerrors_no_postgres.go deleted file mode 100644 index 94f08b66a..000000000 --- a/kvdb/sqlbase/sqlerrors_no_postgres.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !kvdb_postgres - -package sqlbase - -// parsePostgresError attempts to parse a postgres error as a database agnostic -// SQL error. -func parsePostgresError(err error) error { - return nil -} diff --git a/kvdb/sqlbase/sqlerrors_no_sqlite.go b/kvdb/sqlbase/sqlerrors_no_sqlite.go deleted file mode 100644 index 9f475a14c..000000000 --- a/kvdb/sqlbase/sqlerrors_no_sqlite.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !kvdb_sqlite || (windows && (arm || 386)) || (linux && (ppc64 || mips || mipsle || mips64)) - -package sqlbase - -// parseSqliteError attempts to parse a sqlite error as a database agnostic -// SQL error. -func parseSqliteError(err error) error { - return nil -} diff --git a/kvdb/sqlbase/sqlerrors_postgres.go b/kvdb/sqlbase/sqlerrors_postgres.go deleted file mode 100644 index 1b12dda66..000000000 --- a/kvdb/sqlbase/sqlerrors_postgres.go +++ /dev/null @@ -1,51 +0,0 @@ -//go:build kvdb_postgres - -package sqlbase - -import ( - "errors" - "fmt" - "strings" - - "github.com/jackc/pgconn" - "github.com/jackc/pgerrcode" -) - -// parsePostgresError attempts to parse a postgres error as a database agnostic -// SQL error. -func parsePostgresError(err error) error { - if err == nil { - return nil - } - - // Sometimes the error won't be properly wrapped, so we'll need to - // inspect raw error itself to detect something we can wrap properly. - const postgresErrMsg = "could not serialize access" - if strings.Contains(err.Error(), postgresErrMsg) { - return &ErrSerializationError{ - DBError: err, - } - } - - var pqErr *pgconn.PgError - if !errors.As(err, &pqErr) { - return nil - } - - switch pqErr.Code { - // Handle unique constraint violation error. - case pgerrcode.UniqueViolation: - return &ErrSQLUniqueConstraintViolation{ - DBError: pqErr, - } - - // Unable to serialize the transaction, so we'll need to try again. - case pgerrcode.SerializationFailure: - return &ErrSerializationError{ - DBError: pqErr, - } - - default: - return fmt.Errorf("unknown postgres error: %w", pqErr) - } -} diff --git a/kvdb/sqlbase/sqlerrors_sqlite.go b/kvdb/sqlbase/sqlerrors_sqlite.go deleted file mode 100644 index 9df93893a..000000000 --- a/kvdb/sqlbase/sqlerrors_sqlite.go +++ /dev/null @@ -1,53 +0,0 @@ -//go:build kvdb_sqlite && !(windows && (arm || 386)) && !(linux && (ppc64 || mips || mipsle || mips64)) - -package sqlbase - -import ( - "errors" - "fmt" - "strings" - - "modernc.org/sqlite" - sqlite3 "modernc.org/sqlite/lib" -) - -// parseSqliteError attempts to parse a sqlite error as a database agnostic -// SQL error. -func parseSqliteError(err error) error { - if err == nil { - return nil - } - - // If the error isn't wrapped properly, the errors.As call with fail, - // so we'll also try to check the expected error message directly. - // This is taken from: - // https://gitlab.com/cznic/sqlite/-/blob/v1.25.0/sqlite.go#L75. - const sqliteErrMsg = "SQLITE_BUSY" - if strings.Contains(err.Error(), sqliteErrMsg) { - return &ErrSerializationError{ - DBError: err, - } - } - - var sqliteErr *sqlite.Error - if !errors.As(err, &sqliteErr) { - return nil - } - - switch sqliteErr.Code() { - // Handle unique constraint violation error. - case sqlite3.SQLITE_CONSTRAINT_UNIQUE: - return &ErrSQLUniqueConstraintViolation{ - DBError: sqliteErr, - } - - // Database is currently busy, so we'll need to try again. - case sqlite3.SQLITE_BUSY: - return &ErrSerializationError{ - DBError: sqliteErr, - } - - default: - return fmt.Errorf("unknown sqlite error: %w", sqliteErr) - } -} From 648fb22f63ea9024f3219c3223ca1153ec6914cc Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 7 Mar 2024 13:19:28 +0100 Subject: [PATCH 06/11] multi: wrap all errors --- autopilot/agent.go | 2 +- autopilot/combinedattach.go | 2 +- autopilot/manager.go | 2 +- brontide/listener.go | 2 +- cert/selfsigned.go | 8 +++---- chainntnfs/bitcoindnotify/bitcoind.go | 4 ++-- chainntnfs/btcdnotify/btcd.go | 4 ++-- chainntnfs/interface.go | 23 ++++++++++--------- chainntnfs/neutrinonotify/neutrino.go | 8 +++---- chainreg/chainregistry.go | 4 ++-- channeldb/codec.go | 3 ++- channeldb/db.go | 2 +- .../migration21/current/current_codec.go | 3 ++- channeldb/migration21/legacy/legacy_codec.go | 3 ++- channeldb/migration25/migration.go | 2 +- channeldb/migration27/migration.go | 2 +- channeldb/migration30/migration.go | 2 +- channeldb/migration_01_to_11/codec.go | 2 +- channeldb/migration_01_to_11/graph.go | 2 +- channeldb/migration_01_to_11/migrations.go | 6 ++--- .../migration_01_to_11/zpay32/amountunits.go | 2 +- channeldb/payment_control.go | 2 +- channeldb/payments.go | 2 +- cmd/lncli/cmd_macaroon.go | 2 +- cmd/lncli/cmd_open_channel.go | 8 +++---- cmd/lncli/cmd_payments.go | 14 +++++------ cmd/lncli/cmd_profile.go | 4 ++-- cmd/lncli/commands.go | 2 +- cmd/lncli/macaroon_jar.go | 6 ++--- cmd/lncli/profile.go | 4 ++-- cmd/lncli/walletrpc_active.go | 4 ++-- config_builder.go | 8 +++---- contractcourt/breach_arbitrator.go | 2 +- discovery/gossiper.go | 6 ++--- discovery/message_store.go | 2 +- discovery/syncer.go | 2 +- feature/manager.go | 2 +- funding/batch.go | 4 ++-- funding/manager.go | 10 ++++---- input/musig2.go | 2 +- kvdb/bolt_compact.go | 6 ++--- lnd.go | 2 +- lnrpc/devrpc/dev_server.go | 4 ++-- lnrpc/routerrpc/router_server.go | 4 ++-- lnrpc/signrpc/signer_server.go | 12 +++++----- lnrpc/walletrpc/walletkit_server.go | 4 ++-- lnrpc/wtclientrpc/wtclient.go | 3 ++- lntest/bitcoind_common.go | 2 +- lntest/node/harness_node.go | 6 ++--- lnwallet/btcwallet/psbt.go | 6 ++--- lnwallet/chanfunding/psbt_assembler.go | 4 ++-- lnwallet/rpcwallet/rpcwallet.go | 14 +++++------ peer/brontide.go | 2 +- routing/missioncontrol_store.go | 2 +- rpcperms/middleware_handler.go | 2 +- rpcserver.go | 10 ++++---- walletunlocker/service.go | 2 +- watchtower/wtclient/session_negotiator.go | 2 +- watchtower/wtclient/session_queue.go | 8 +++---- zpay32/amountunits.go | 2 +- 60 files changed, 138 insertions(+), 133 deletions(-) diff --git a/autopilot/agent.go b/autopilot/agent.go index 9aef4f9f4..d9c35a685 100644 --- a/autopilot/agent.go +++ b/autopilot/agent.go @@ -648,7 +648,7 @@ func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32, // to open channels to. scores, err = chooseN(numChans, scores) if err != nil { - return fmt.Errorf("unable to make weighted choice: %v", + return fmt.Errorf("unable to make weighted choice: %w", err) } diff --git a/autopilot/combinedattach.go b/autopilot/combinedattach.go index 0a7e3557b..b43856d24 100644 --- a/autopilot/combinedattach.go +++ b/autopilot/combinedattach.go @@ -84,7 +84,7 @@ func (c *WeightedCombAttachment) NodeScores(g ChannelGraph, chans []LocalChannel g, chans, chanSize, nodes, ) if err != nil { - return nil, fmt.Errorf("unable to get sub score: %v", + return nil, fmt.Errorf("unable to get sub score: %w", err) } diff --git a/autopilot/manager.go b/autopilot/manager.go index cf30aca82..e5999f518 100644 --- a/autopilot/manager.go +++ b/autopilot/manager.go @@ -341,7 +341,7 @@ func (m *Manager) queryHeuristics(nodes map[NodeID]struct{}, localState bool) ( m.cfg.PilotCfg.Graph, totalChans, chanSize, nodes, ) if err != nil { - return nil, fmt.Errorf("unable to get sub score: %v", + return nil, fmt.Errorf("unable to get sub score: %w", err) } diff --git a/brontide/listener.go b/brontide/listener.go index e3f93a665..ba210853c 100644 --- a/brontide/listener.go +++ b/brontide/listener.go @@ -91,7 +91,7 @@ func (l *Listener) listen() { // rejectedConnErr is a helper function that prepends the remote address of the // failed connection attempt to the original error message. func rejectedConnErr(err error, remoteAddr string) error { - return fmt.Errorf("unable to accept connection from %v: %v", remoteAddr, + return fmt.Errorf("unable to accept connection from %v: %w", remoteAddr, err) } diff --git a/cert/selfsigned.go b/cert/selfsigned.go index 748eeba77..c956afb00 100644 --- a/cert/selfsigned.go +++ b/cert/selfsigned.go @@ -261,7 +261,7 @@ func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string, &template, &priv.PublicKey, priv, ) if err != nil { - return nil, nil, fmt.Errorf("failed to create certificate: %v", + return nil, nil, fmt.Errorf("failed to create certificate: %w", err) } @@ -270,13 +270,13 @@ func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string, certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}, ) if err != nil { - return nil, nil, fmt.Errorf("failed to encode certificate: %v", + return nil, nil, fmt.Errorf("failed to encode certificate: %w", err) } keybytes, err := x509.MarshalECPrivateKey(priv) if err != nil { - return nil, nil, fmt.Errorf("unable to encode privkey: %v", + return nil, nil, fmt.Errorf("unable to encode privkey: %w", err) } keyBuf := &bytes.Buffer{} @@ -284,7 +284,7 @@ func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string, keyBuf, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keybytes}, ) if err != nil { - return nil, nil, fmt.Errorf("failed to encode private key: %v", + return nil, nil, fmt.Errorf("failed to encode private key: %w", err) } diff --git a/chainntnfs/bitcoindnotify/bitcoind.go b/chainntnfs/bitcoindnotify/bitcoind.go index d268c8374..c4813cd2f 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -792,8 +792,8 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // proceed with fallback methods. jsonErr, ok := err.(*btcjson.RPCError) if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { - return nil, fmt.Errorf("unable to query for txid %v: %v", - outpoint.Hash, err) + return nil, fmt.Errorf("unable to query for txid "+ + "%v: %w", outpoint.Hash, err) } } diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index 430a10661..89cedffc9 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -886,8 +886,8 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // proceed with fallback methods. jsonErr, ok := err.(*btcjson.RPCError) if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { - return nil, fmt.Errorf("unable to query for txid %v: %v", - outpoint.Hash, err) + return nil, fmt.Errorf("unable to query for txid %v: "+ + "%w", outpoint.Hash, err) } } diff --git a/chainntnfs/interface.go b/chainntnfs/interface.go index 0f2fe27e4..e40c271b4 100644 --- a/chainntnfs/interface.go +++ b/chainntnfs/interface.go @@ -483,13 +483,13 @@ func GetCommonBlockAncestorHeight(chainConn ChainConn, reorgHash, for reorgHash != chainHash { reorgHeader, err := chainConn.GetBlockHeader(&reorgHash) if err != nil { - return 0, fmt.Errorf("unable to get header for hash=%v: %v", - reorgHash, err) + return 0, fmt.Errorf("unable to get header for "+ + "hash=%v: %w", reorgHash, err) } chainHeader, err := chainConn.GetBlockHeader(&chainHash) if err != nil { - return 0, fmt.Errorf("unable to get header for hash=%v: %v", - chainHash, err) + return 0, fmt.Errorf("unable to get header for "+ + "hash=%v: %w", chainHash, err) } reorgHash = reorgHeader.PrevBlock chainHash = chainHeader.PrevBlock @@ -497,8 +497,8 @@ func GetCommonBlockAncestorHeight(chainConn ChainConn, reorgHash, verboseHeader, err := chainConn.GetBlockHeaderVerbose(&chainHash) if err != nil { - return 0, fmt.Errorf("unable to get verbose header for hash=%v: %v", - chainHash, err) + return 0, fmt.Errorf("unable to get verbose header for "+ + "hash=%v: %w", chainHash, err) } return verboseHeader.Height, nil @@ -719,7 +719,7 @@ func ConfDetailsFromTxIndex(chainConn TxIndexConn, r ConfRequest, } return nil, TxNotFoundIndex, - fmt.Errorf("unable to query for txid %v: %v", + fmt.Errorf("unable to query for txid %v: %w", r.TxID, err) } @@ -728,13 +728,13 @@ func ConfDetailsFromTxIndex(chainConn TxIndexConn, r ConfRequest, rawTx, err := hex.DecodeString(rawTxRes.Hex) if err != nil { return nil, TxNotFoundIndex, - fmt.Errorf("unable to deserialize tx %v: %v", + fmt.Errorf("unable to deserialize tx %v: %w", r.TxID, err) } var tx wire.MsgTx if err := tx.Deserialize(bytes.NewReader(rawTx)); err != nil { return nil, TxNotFoundIndex, - fmt.Errorf("unable to deserialize tx %v: %v", + fmt.Errorf("unable to deserialize tx %v: %w", r.TxID, err) } @@ -759,13 +759,14 @@ func ConfDetailsFromTxIndex(chainConn TxIndexConn, r ConfRequest, if err != nil { return nil, TxNotFoundIndex, fmt.Errorf("unable to get block hash %v for "+ - "historical dispatch: %v", rawTxRes.BlockHash, err) + "historical dispatch: %w", rawTxRes.BlockHash, + err) } block, err := chainConn.GetBlock(blockHash) if err != nil { return nil, TxNotFoundIndex, fmt.Errorf("unable to get block with hash %v for "+ - "historical dispatch: %v", blockHash, err) + "historical dispatch: %w", blockHash, err) } // In the modern chain (the only one we really care about for LN), the diff --git a/chainntnfs/neutrinonotify/neutrino.go b/chainntnfs/neutrinonotify/neutrino.go index b2e00da80..80e210c2f 100644 --- a/chainntnfs/neutrinonotify/neutrino.go +++ b/chainntnfs/neutrinonotify/neutrino.go @@ -582,8 +582,8 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ // can compute the current block hash. blockHash, err := n.p2pNode.GetBlockHash(int64(scanHeight)) if err != nil { - return nil, fmt.Errorf("unable to get header for height=%v: %v", - scanHeight, err) + return nil, fmt.Errorf("unable to get header for "+ + "height=%v: %w", scanHeight, err) } // With the hash computed, we can now fetch the basic filter for this @@ -600,8 +600,8 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ neutrino.MaxBatchSize(int64(scanHeight-startHeight+1)), ) if err != nil { - return nil, fmt.Errorf("unable to retrieve regular filter for "+ - "height=%v: %v", scanHeight, err) + return nil, fmt.Errorf("unable to retrieve regular "+ + "filter for height=%v: %w", scanHeight, err) } // In the case that the filter exists, we'll attempt to see if diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index c3d428611..036da71a5 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -763,11 +763,11 @@ func NewChainControl(walletConfig lnwallet.Config, lnWallet, err := lnwallet.NewLightningWallet(walletConfig) if err != nil { - return nil, ccCleanup, fmt.Errorf("unable to create wallet: %v", + return nil, ccCleanup, fmt.Errorf("unable to create wallet: %w", err) } if err := lnWallet.Startup(); err != nil { - return nil, ccCleanup, fmt.Errorf("unable to create wallet: %v", + return nil, ccCleanup, fmt.Errorf("unable to create wallet: %w", err) } diff --git a/channeldb/codec.go b/channeldb/codec.go index a79ef8558..07f125742 100644 --- a/channeldb/codec.go +++ b/channeldb/codec.go @@ -78,7 +78,8 @@ func WriteElement(w io.Writer, element interface{}) error { if e.PubKey != nil { if err := binary.Write(w, byteOrder, true); err != nil { - return fmt.Errorf("error writing serialized element: %s", err) + return fmt.Errorf("error writing serialized "+ + "element: %w", err) } return WriteElement(w, e.PubKey) diff --git a/channeldb/db.go b/channeldb/db.go index 34d621a68..93bb239bb 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -643,7 +643,7 @@ func (c *ChannelStateDB) fetchNodeChannels(chainBucket kvdb.RBucket) ( oChannel, err := fetchOpenChannel(chanBucket, &outPoint) if err != nil { return fmt.Errorf("unable to read channel data for "+ - "chan_point=%v: %v", outPoint, err) + "chan_point=%v: %w", outPoint, err) } oChannel.Db = c diff --git a/channeldb/migration21/current/current_codec.go b/channeldb/migration21/current/current_codec.go index c78319a4f..d4a28e69b 100644 --- a/channeldb/migration21/current/current_codec.go +++ b/channeldb/migration21/current/current_codec.go @@ -83,7 +83,8 @@ func WriteElement(w io.Writer, element interface{}) error { if e.PubKey != nil { if err := binary.Write(w, byteOrder, true); err != nil { - return fmt.Errorf("error writing serialized element: %s", err) + return fmt.Errorf("error writing serialized "+ + "element: %w", err) } return WriteElement(w, e.PubKey) diff --git a/channeldb/migration21/legacy/legacy_codec.go b/channeldb/migration21/legacy/legacy_codec.go index 8416ff39b..e14a42a5c 100644 --- a/channeldb/migration21/legacy/legacy_codec.go +++ b/channeldb/migration21/legacy/legacy_codec.go @@ -81,7 +81,8 @@ func WriteElement(w io.Writer, element interface{}) error { if e.PubKey != nil { if err := binary.Write(w, byteOrder, true); err != nil { - return fmt.Errorf("error writing serialized element: %s", err) + return fmt.Errorf("error writing serialized "+ + "element: %w", err) } return WriteElement(w, e.PubKey) diff --git a/channeldb/migration25/migration.go b/channeldb/migration25/migration.go index 257d8272c..53bff3642 100644 --- a/channeldb/migration25/migration.go +++ b/channeldb/migration25/migration.go @@ -93,7 +93,7 @@ func findOpenChannels(openChanBucket kvdb.RBucket) ([]*OpenChannel, error) { // open channels as they don't have any revocation logs and // their current commitments reflect the initial balances. if err := FetchChanCommitments(chanBucket, c); err != nil { - return fmt.Errorf("unable to fetch chan commits: %v", + return fmt.Errorf("unable to fetch chan commits: %w", err) } diff --git a/channeldb/migration27/migration.go b/channeldb/migration27/migration.go index a6f7b1a96..85b1d52c9 100644 --- a/channeldb/migration27/migration.go +++ b/channeldb/migration27/migration.go @@ -79,7 +79,7 @@ func findHistoricalChannels(historicalBucket kvdb.RBucket) ([]*OpenChannel, // Try to fetch channel info in old format. err = fetchChanInfoCompatible(chanBucket, c, true) if err != nil { - return fmt.Errorf("%s: fetch chan info got: %v", + return fmt.Errorf("%s: fetch chan info got: %w", c.FundingOutpoint, err) } diff --git a/channeldb/migration30/migration.go b/channeldb/migration30/migration.go index 406cc291a..83a9cee8f 100644 --- a/channeldb/migration30/migration.go +++ b/channeldb/migration30/migration.go @@ -254,7 +254,7 @@ func writeRevocationLogs(openChanBucket kvdb.RwBucket, logEntrykey := mig24.MakeLogKey(entry.commitHeight) err = logBucket.Put(logEntrykey[:], b.Bytes()) if err != nil { - return fmt.Errorf("putRevocationLog err: %v", + return fmt.Errorf("putRevocationLog err: %w", err) } } diff --git a/channeldb/migration_01_to_11/codec.go b/channeldb/migration_01_to_11/codec.go index a87f6eda7..ca2f5cff6 100644 --- a/channeldb/migration_01_to_11/codec.go +++ b/channeldb/migration_01_to_11/codec.go @@ -70,7 +70,7 @@ func WriteElement(w io.Writer, element interface{}) error { if e.PubKey != nil { if err := binary.Write(w, byteOrder, true); err != nil { - return fmt.Errorf("error writing serialized element: %s", err) + return fmt.Errorf("error writing serialized element: %w", err) } return WriteElement(w, e.PubKey) diff --git a/channeldb/migration_01_to_11/graph.go b/channeldb/migration_01_to_11/graph.go index 0f36a78ed..9035e3e6f 100644 --- a/channeldb/migration_01_to_11/graph.go +++ b/channeldb/migration_01_to_11/graph.go @@ -1140,7 +1140,7 @@ func deserializeChanEdgePolicy(r io.Reader, node, err := fetchLightningNode(nodes, pub[:]) if err != nil { - return nil, fmt.Errorf("unable to fetch node: %x, %v", + return nil, fmt.Errorf("unable to fetch node: %x, %w", pub[:], err) } edge.Node = &node diff --git a/channeldb/migration_01_to_11/migrations.go b/channeldb/migration_01_to_11/migrations.go index 6ae25e210..5027034cb 100644 --- a/channeldb/migration_01_to_11/migrations.go +++ b/channeldb/migration_01_to_11/migrations.go @@ -516,7 +516,7 @@ func MigratePruneEdgeUpdateIndex(tx kvdb.RwTx) error { // well. edgeIndex, err := edges.CreateBucketIfNotExists(edgeIndexBucket) if err != nil { - return fmt.Errorf("error creating edge index bucket: %s", err) + return fmt.Errorf("error creating edge index bucket: %w", err) } if edgeIndex == nil { return fmt.Errorf("unable to create/fetch edge index " + @@ -546,7 +546,7 @@ func MigratePruneEdgeUpdateIndex(tx kvdb.RwTx) error { return nil }) if err != nil { - return fmt.Errorf("unable to gather existing edge policies: %v", + return fmt.Errorf("unable to gather existing edge policies: %w", err) } @@ -560,7 +560,7 @@ func MigratePruneEdgeUpdateIndex(tx kvdb.RwTx) error { return nil }) if err != nil { - return fmt.Errorf("unable to gather existing edge updates: %v", + return fmt.Errorf("unable to gather existing edge updates: %w", err) } diff --git a/channeldb/migration_01_to_11/zpay32/amountunits.go b/channeldb/migration_01_to_11/zpay32/amountunits.go index 0cc1fcdbe..938a0b0ef 100644 --- a/channeldb/migration_01_to_11/zpay32/amountunits.go +++ b/channeldb/migration_01_to_11/zpay32/amountunits.go @@ -136,7 +136,7 @@ func encodeAmount(msat lnwire.MilliSatoshi) (string, error) { // Should always be expressible in pico BTC. pico, err := fromMSat['p'](msat) if err != nil { - return "", fmt.Errorf("unable to express %d msat as pBTC: %v", + return "", fmt.Errorf("unable to express %d msat as pBTC: %w", msat, err) } shortened := strconv.FormatUint(pico, 10) + "p" diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 4ad29167e..bd83e32cc 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -229,7 +229,7 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, return bucket.Delete(paymentFailInfoKey) }) if err != nil { - return err + return fmt.Errorf("unable to init payment: %w", err) } return updateErr diff --git a/channeldb/payments.go b/channeldb/payments.go index 15bcd8342..a1baa07f7 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -615,7 +615,7 @@ func (d *DB) QueryPayments(query PaymentsQuery) (PaymentsResponse, error) { err = indexes.ForEach(countFn) } if err != nil { - return fmt.Errorf("error counting payments: %v", + return fmt.Errorf("error counting payments: %w", err) } diff --git a/cmd/lncli/cmd_macaroon.go b/cmd/lncli/cmd_macaroon.go index 92a96c43c..54e03057a 100644 --- a/cmd/lncli/cmd_macaroon.go +++ b/cmd/lncli/cmd_macaroon.go @@ -361,7 +361,7 @@ func printMacaroon(ctx *cli.Context) error { case args.Present(): macBytes, err = hex.DecodeString(args.First()) if err != nil { - return fmt.Errorf("unable to hex decode macaroon: %v", + return fmt.Errorf("unable to hex decode macaroon: %w", err) } diff --git a/cmd/lncli/cmd_open_channel.go b/cmd/lncli/cmd_open_channel.go index d7081e4e0..74cb1668a 100644 --- a/cmd/lncli/cmd_open_channel.go +++ b/cmd/lncli/cmd_open_channel.go @@ -602,7 +602,7 @@ func openChannelPsbt(rpcCtx context.Context, ctx *cli.Context, // Recv blocks until a message or error arrives. resp, err := stream.Recv() if err == io.EOF { - srvErr <- fmt.Errorf("lnd shutting down: %v", + srvErr <- fmt.Errorf("lnd shutting down: %w", err) return } else if err != nil { @@ -685,7 +685,7 @@ func openChannelPsbt(rpcCtx context.Context, ctx *cli.Context, } fundedPsbt, err := decodePsbt(inputPsbt) if err != nil { - return fmt.Errorf("psbt decode failed: %v", + return fmt.Errorf("psbt decode failed: %w", err) } verifyMsg := &lnrpc.FundingTransitionMsg{ @@ -873,14 +873,14 @@ func batchOpenChannel(ctx *cli.Context) error { for idx, jsonChannel := range jsonChannels { pubKeyBytes, err := hex.DecodeString(jsonChannel.NodePubkey) if err != nil { - return fmt.Errorf("error parsing node pubkey hex: %v", + return fmt.Errorf("error parsing node pubkey hex: %w", err) } pendingChanBytes, err := hex.DecodeString( jsonChannel.PendingChanID, ) if err != nil { - return fmt.Errorf("error parsing pending chan ID: %v", + return fmt.Errorf("error parsing pending chan ID: %w", err) } diff --git a/cmd/lncli/cmd_payments.go b/cmd/lncli/cmd_payments.go index 9ba6f296d..550bb8f3e 100644 --- a/cmd/lncli/cmd_payments.go +++ b/cmd/lncli/cmd_payments.go @@ -525,13 +525,13 @@ func sendPaymentRequest(ctx *cli.Context, recordID, err := strconv.ParseUint(kv[0], 10, 64) if err != nil { - return fmt.Errorf("invalid data format: %v", + return fmt.Errorf("invalid data format: %w", err) } hexValue, err := hex.DecodeString(kv[1]) if err != nil { - return fmt.Errorf("invalid data format: %v", + return fmt.Errorf("invalid data format: %w", err) } @@ -1514,7 +1514,7 @@ func forwardingHistory(ctx *cli.Context) error { case args.Present(): i, err := strconv.ParseInt(args.First(), 10, 64) if err != nil { - return fmt.Errorf("unable to decode index_offset: %v", + return fmt.Errorf("unable to decode index_offset: %w", err) } indexOffset = uint32(i) @@ -1527,7 +1527,7 @@ func forwardingHistory(ctx *cli.Context) error { case args.Present(): m, err := strconv.ParseInt(args.First(), 10, 64) if err != nil { - return fmt.Errorf("unable to decode max_events: %v", + return fmt.Errorf("unable to decode max_events: %w", err) } maxEvents = uint32(m) @@ -1616,7 +1616,7 @@ func buildRoute(ctx *cli.Context) error { for _, k := range hops { pubkey, err := route.NewVertexFromStr(k) if err != nil { - return fmt.Errorf("error parsing %v: %v", k, err) + return fmt.Errorf("error parsing %v: %w", k, err) } rpcHops = append(rpcHops, pubkey[:]) } @@ -1757,7 +1757,7 @@ func deletePayments(ctx *cli.Context) error { case singlePayment: paymentHash, err = hex.DecodeString(ctx.String("payment_hash")) if err != nil { - return fmt.Errorf("error decoding payment_hash: %v", + return fmt.Errorf("error decoding payment_hash: %w", err) } @@ -1766,7 +1766,7 @@ func deletePayments(ctx *cli.Context) error { FailedHtlcsOnly: failedHTLCsOnly, }) if err != nil { - return fmt.Errorf("error deleting single payment: %v", + return fmt.Errorf("error deleting single payment: %w", err) } diff --git a/cmd/lncli/cmd_profile.go b/cmd/lncli/cmd_profile.go index 0f350e5c2..21666be96 100644 --- a/cmd/lncli/cmd_profile.go +++ b/cmd/lncli/cmd_profile.go @@ -150,7 +150,7 @@ func profileAdd(ctx *cli.Context) error { // All done, store the updated profile file. f.Profiles = append(f.Profiles, profile) if err = saveProfileFile(defaultProfileFile, f); err != nil { - return fmt.Errorf("error writing profile file %s: %v", + return fmt.Errorf("error writing profile file %s: %w", defaultProfileFile, err) } @@ -443,7 +443,7 @@ func profileAddMacaroon(ctx *cli.Context) error { selectedProfile.Macaroons.Jar, macEntry, ) if err = saveProfileFile(defaultProfileFile, f); err != nil { - return fmt.Errorf("error writing profile file %s: %v", + return fmt.Errorf("error writing profile file %s: %w", defaultProfileFile, err) } diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index da03b67a3..10bb55a95 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1811,7 +1811,7 @@ func getChanInfo(ctx *cli.Context) error { case ctx.Args().Present(): chanID, err = strconv.ParseUint(ctx.Args().First(), 10, 64) if err != nil { - return fmt.Errorf("error parsing chan_id: %s", err) + return fmt.Errorf("error parsing chan_id: %w", err) } default: return fmt.Errorf("chan_id argument missing") diff --git a/cmd/lncli/macaroon_jar.go b/cmd/lncli/macaroon_jar.go index 2c140fa6d..f54f29a26 100644 --- a/cmd/lncli/macaroon_jar.go +++ b/cmd/lncli/macaroon_jar.go @@ -67,7 +67,7 @@ func (e *macaroonEntry) loadMacaroon( macBytes, err = decryptMacaroon(parts[1], parts[2], pw) if err != nil { - return nil, fmt.Errorf("unable to decrypt macaroon: %v", + return nil, fmt.Errorf("unable to decrypt macaroon: %w", err) } } else { @@ -142,7 +142,7 @@ func decryptMacaroon(keyB64, dataB64 string, pw []byte) ([]byte, error) { key := &snacl.SecretKey{} err = key.Unmarshal(keyData) if err != nil { - return nil, fmt.Errorf("could not unmarshal encryption key: %v", + return nil, fmt.Errorf("could not unmarshal encryption key: %w", err) } @@ -155,7 +155,7 @@ func decryptMacaroon(keyB64, dataB64 string, pw []byte) ([]byte, error) { } macBytes, err := key.Decrypt(encryptedMac) if err != nil { - return nil, fmt.Errorf("could not decrypt macaroon data: %v", + return nil, fmt.Errorf("could not decrypt macaroon data: %w", err) } return macBytes, nil diff --git a/cmd/lncli/profile.go b/cmd/lncli/profile.go index 9c6680542..90ac69c0e 100644 --- a/cmd/lncli/profile.go +++ b/cmd/lncli/profile.go @@ -224,7 +224,7 @@ func loadProfileFile(file string) (*profileFile, error) { content, err := ioutil.ReadFile(file) if err != nil { - return nil, fmt.Errorf("could not load profile file %s: %v", + return nil, fmt.Errorf("could not load profile file %s: %w", file, err) } f := &profileFile{} @@ -262,7 +262,7 @@ func (f *profileFile) unmarshalJSON(content []byte) error { func (f *profileFile) marshalJSON() ([]byte, error) { b, err := json.Marshal(f) if err != nil { - return nil, fmt.Errorf("error JSON marshalling profile: %v", + return nil, fmt.Errorf("error JSON marshalling profile: %w", err) } diff --git a/cmd/lncli/walletrpc_active.go b/cmd/lncli/walletrpc_active.go index 5118ddd2f..bb1fb4ecc 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -1235,8 +1235,8 @@ func fundPsbt(ctx *cli.Context) error { // entry must be present. jsonMap := []byte(ctx.String("outputs")) if err := json.Unmarshal(jsonMap, &amountToAddr); err != nil { - return fmt.Errorf("error parsing outputs JSON: %v", - err) + return fmt.Errorf("error parsing outputs "+ + "JSON: %w", err) } tpl.Outputs = amountToAddr } diff --git a/config_builder.go b/config_builder.go index 002ae288a..bbf291506 100644 --- a/config_builder.go +++ b/config_builder.go @@ -568,7 +568,7 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context, ) cleanUpTasks = append(cleanUpTasks, pccCleanup) if err != nil { - err := fmt.Errorf("unable to create partial chain control: %v", + err := fmt.Errorf("unable to create partial chain control: %w", err) d.logger.Error(err) return nil, nil, nil, err @@ -1073,7 +1073,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( if err != nil { cleanUp() - err := fmt.Errorf("unable to open %s database: %v", + err := fmt.Errorf("unable to open %s database: %w", lncfg.NSTowerClientDB, err) d.logger.Error(err) return nil, nil, err @@ -1088,7 +1088,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( if err != nil { cleanUp() - err := fmt.Errorf("unable to open %s database: %v", + err := fmt.Errorf("unable to open %s database: %w", lncfg.NSTowerServerDB, err) d.logger.Error(err) return nil, nil, err @@ -1303,7 +1303,7 @@ func importWatchOnlyAccounts(wallet *wallet.Wallet, addrSchema, ) if err != nil { - return fmt.Errorf("could not import account %v: %v", + return fmt.Errorf("could not import account %v: %w", name, err) } } diff --git a/contractcourt/breach_arbitrator.go b/contractcourt/breach_arbitrator.go index 0e33dc571..017e8bdac 100644 --- a/contractcourt/breach_arbitrator.go +++ b/contractcourt/breach_arbitrator.go @@ -931,7 +931,7 @@ func (b *BreachArbitrator) cleanupBreach(chanPoint *wire.OutPoint) error { // info from the database. err = b.cfg.Store.Remove(chanPoint) if err != nil { - return fmt.Errorf("unable to remove retribution from db: %v", + return fmt.Errorf("unable to remove retribution from db: %w", err) } diff --git a/discovery/gossiper.go b/discovery/gossiper.go index e1884445e..507035e70 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -1647,7 +1647,7 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { return nil }) if err != nil && err != channeldb.ErrGraphNoEdgesFound { - return fmt.Errorf("unable to retrieve outgoing channels: %v", + return fmt.Errorf("unable to retrieve outgoing channels: %w", err) } @@ -1873,7 +1873,7 @@ func (d *AuthenticatedGossiper) processRejectedEdge( // to the database. err = d.cfg.Router.AddProof(chanAnnMsg.ShortChannelID, proof) if err != nil { - err := fmt.Errorf("unable add proof to shortChanID=%v: %v", + err := fmt.Errorf("unable add proof to shortChanID=%v: %w", chanAnnMsg.ShortChannelID, err) log.Error(err) return nil, err @@ -1910,7 +1910,7 @@ func (d *AuthenticatedGossiper) addNode(msg *lnwire.NodeAnnouncement, op ...batch.SchedulerOption) error { if err := routing.ValidateNodeAnn(msg); err != nil { - return fmt.Errorf("unable to validate node announcement: %v", + return fmt.Errorf("unable to validate node announcement: %w", err) } diff --git a/discovery/message_store.go b/discovery/message_store.go index cf228eee7..10fa51623 100644 --- a/discovery/message_store.go +++ b/discovery/message_store.go @@ -72,7 +72,7 @@ func NewMessageStore(db kvdb.Backend) (*MessageStore, error) { return err }) if err != nil { - return nil, fmt.Errorf("unable to create required buckets: %v", + return nil, fmt.Errorf("unable to create required buckets: %w", err) } diff --git a/discovery/syncer.go b/discovery/syncer.go index b567a6940..b910151cb 100644 --- a/discovery/syncer.go +++ b/discovery/syncer.go @@ -1252,7 +1252,7 @@ func (g *GossipSyncer) replyShortChanIDs(query *lnwire.QueryShortChanIDs) error query.ChainHash, query.ShortChanIDs, ) if err != nil { - return fmt.Errorf("unable to fetch chan anns for %v..., %v", + return fmt.Errorf("unable to fetch chan anns for %v..., %w", query.ShortChanIDs[0].ToUint64(), err) } diff --git a/feature/manager.go b/feature/manager.go index 991d5c611..98317eb8f 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -211,7 +211,7 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { fv := lnwire.NewFeatureVector(raw, lnwire.Features) err := ValidateDeps(fv) if err != nil { - return nil, fmt.Errorf("invalid feature set %v: %v", + return nil, fmt.Errorf("invalid feature set %v: %w", set, err) } } diff --git a/funding/batch.go b/funding/batch.go index 30eac1478..fc050cdf5 100644 --- a/funding/batch.go +++ b/funding/batch.go @@ -226,7 +226,7 @@ func (b *Batcher) BatchFund(ctx context.Context, "chan ID") } } else if _, err := rand.Read(pendingChanID[:]); err != nil { - return nil, fmt.Errorf("error making temp chan ID: %v", + return nil, fmt.Errorf("error making temp chan ID: %w", err) } @@ -265,7 +265,7 @@ func (b *Batcher) BatchFund(ctx context.Context, }, }) if err != nil { - return nil, fmt.Errorf("error parsing channel %d: %v", + return nil, fmt.Errorf("error parsing channel %d: %w", idx, err) } diff --git a/funding/manager.go b/funding/manager.go index 86e70c17c..e110269a7 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -1123,7 +1123,7 @@ func (f *Manager) stateStep(channel *channeldb.OpenChannel, case markedOpen: err := f.sendChannelReady(channel, lnChannel) if err != nil { - return fmt.Errorf("failed sending channelReady: %v", + return fmt.Errorf("failed sending channelReady: %w", err) } @@ -1137,7 +1137,7 @@ func (f *Manager) stateStep(channel *channeldb.OpenChannel, ) if err != nil { return fmt.Errorf("error setting channel state to"+ - " channelReadySent: %v", err) + " channelReadySent: %w", err) } log.Debugf("Channel(%v) with ShortChanID %v: successfully "+ @@ -1207,7 +1207,7 @@ func (f *Manager) stateStep(channel *channeldb.OpenChannel, // shutdown. err = f.deleteChannelOpeningState(&channel.FundingOutpoint) if err != nil { - return fmt.Errorf("error deleting channel state: %v", + return fmt.Errorf("error deleting channel state: %w", err) } @@ -2757,7 +2757,7 @@ func (f *Manager) fundingTimeout(c *channeldb.OpenChannel, if err := c.CloseChannel( closeInfo, channeldb.ChanStatusLocalCloseInitiator, ); err != nil { - return fmt.Errorf("failed closing channel %v: %v", + return fmt.Errorf("failed closing channel %v: %w", c.FundingOutpoint, err) } @@ -4784,7 +4784,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { } if err := msg.Peer.SendMessage(true, &fundingOpen); err != nil { - e := fmt.Errorf("unable to send funding request message: %v", + e := fmt.Errorf("unable to send funding request message: %w", err) log.Errorf(e.Error()) diff --git a/input/musig2.go b/input/musig2.go index 28a15af73..589152282 100644 --- a/input/musig2.go +++ b/input/musig2.go @@ -587,7 +587,7 @@ func DeserializePartialSignature(scalarBytes []byte) (*musig2.PartialSignature, sig := &musig2.PartialSignature{} if err := sig.Decode(bytes.NewReader(scalarBytes)); err != nil { - return nil, fmt.Errorf("error decoding partial signature: %v", + return nil, fmt.Errorf("error decoding partial signature: %w", err) } diff --git a/kvdb/bolt_compact.go b/kvdb/bolt_compact.go index 6597eb2d5..b477e206b 100644 --- a/kvdb/bolt_compact.go +++ b/kvdb/bolt_compact.go @@ -90,7 +90,7 @@ func (cmd *compacter) execute() (int64, int64, error) { Timeout: cmd.dbTimeout, }) if err != nil { - return 0, 0, fmt.Errorf("error opening source database: %v", + return 0, 0, fmt.Errorf("error opening source database: %w", err) } defer func() { @@ -105,7 +105,7 @@ func (cmd *compacter) execute() (int64, int64, error) { }) if err != nil { return 0, 0, fmt.Errorf("error opening destination database: "+ - "%v", err) + "%w", err) } defer func() { if err := dst.Close(); err != nil { @@ -122,7 +122,7 @@ func (cmd *compacter) execute() (int64, int64, error) { fi, err = os.Stat(cmd.dstPath) if err != nil { return 0, 0, fmt.Errorf("error determining destination "+ - "database size: %v", err) + "database size: %w", err) } else if fi.Size() == 0 { return 0, 0, fmt.Errorf("zero db size") } diff --git a/lnd.go b/lnd.go index 0034f134b..f4ef03a07 100644 --- a/lnd.go +++ b/lnd.go @@ -91,7 +91,7 @@ func AdminAuthOptions(cfg *Config, skipMacaroons bool) ([]grpc.DialOption, mac := &macaroon.Macaroon{} if err = mac.UnmarshalBinary(macBytes); err != nil { - return nil, fmt.Errorf("unable to decode macaroon: %v", + return nil, fmt.Errorf("unable to decode macaroon: %w", err) } diff --git a/lnrpc/devrpc/dev_server.go b/lnrpc/devrpc/dev_server.go index e2b98efa7..662c0d08d 100644 --- a/lnrpc/devrpc/dev_server.go +++ b/lnrpc/devrpc/dev_server.go @@ -252,7 +252,7 @@ func (s *Server) ImportGraph(ctx context.Context, } if err := graphDB.AddLightningNode(node); err != nil { - return nil, fmt.Errorf("unable to add node %v: %v", + return nil, fmt.Errorf("unable to add node %v: %w", rpcNode.PubKey, err) } @@ -285,7 +285,7 @@ func (s *Server) ImportGraph(ctx context.Context, edge.ChannelPoint = *channelPoint if err := graphDB.AddChannelEdge(edge); err != nil { - return nil, fmt.Errorf("unable to add edge %v: %v", + return nil, fmt.Errorf("unable to add edge %v: %w", rpcEdge.ChanPoint, err) } diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 7ed683f24..194bdc996 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -1140,7 +1140,7 @@ func toPairSnapshot(pairResult *PairHistory) (*routing.MissionControlPairSnapsho pairResult.History.FailTime, ) if err != nil { - return nil, fmt.Errorf("%v invalid failure: %v", pairPrefix, + return nil, fmt.Errorf("%v invalid failure: %w", pairPrefix, err) } @@ -1150,7 +1150,7 @@ func toPairSnapshot(pairResult *PairHistory) (*routing.MissionControlPairSnapsho pairResult.History.SuccessTime, ) if err != nil { - return nil, fmt.Errorf("%v invalid success: %v", pairPrefix, + return nil, fmt.Errorf("%v invalid success: %w", pairPrefix, err) } diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index a84ea68ff..c29d495eb 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -710,14 +710,14 @@ func (s *Server) VerifyMessage(_ context.Context, // for Schnorr signatures. pubkey, err := schnorr.ParsePubKey(in.Pubkey) if err != nil { - return nil, fmt.Errorf("unable to parse pubkey: %v", + return nil, fmt.Errorf("unable to parse pubkey: %w", err) } sigParsed, err := schnorr.ParseSignature(in.Signature) if err != nil { return nil, fmt.Errorf("can't parse Schnorr "+ - "signature: %v", err) + "signature: %w", err) } var digest []byte @@ -746,7 +746,7 @@ func (s *Server) VerifyMessage(_ context.Context, } sig, err := wireSig.ToSignature() if err != nil { - return nil, fmt.Errorf("failed to convert from wire format: %v", + return nil, fmt.Errorf("failed to convert from wire format: %w", err) } @@ -874,7 +874,7 @@ func (s *Server) MuSig2CombineKeys(_ context.Context, // Are there any tweaks to apply to the combined public key? tweaks, err := UnmarshalTweaks(in.Tweaks, in.TaprootTweak) if err != nil { - return nil, fmt.Errorf("error unmarshaling tweak options: %v", + return nil, fmt.Errorf("error unmarshaling tweak options: %w", err) } @@ -1014,7 +1014,7 @@ func (s *Server) MuSig2CreateSession(_ context.Context, // Are there any tweaks to apply to the combined public key? tweaks, err := UnmarshalTweaks(in.Tweaks, in.TaprootTweak) if err != nil { - return nil, fmt.Errorf("error unmarshaling tweak options: %v", + return nil, fmt.Errorf("error unmarshaling tweak options: %w", err) } @@ -1139,7 +1139,7 @@ func (s *Server) MuSig2CombineSig(_ context.Context, in.OtherPartialSignatures, ) if err != nil { - return nil, fmt.Errorf("error parsing partial signatures: %v", + return nil, fmt.Errorf("error parsing partial signatures: %w", err) } diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 05b20c339..b25c187ff 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1038,7 +1038,7 @@ func (w *WalletKit) BumpFee(ctx context.Context, // with an unconfirmed transaction. _, currentHeight, err := w.cfg.Chain.GetBestBlock() if err != nil { - return nil, fmt.Errorf("unable to retrieve current height: %v", + return nil, fmt.Errorf("unable to retrieve current height: %w", err) } @@ -2607,7 +2607,7 @@ func (w *WalletKit) ImportTapscript(_ context.Context, taprootScope := waddrmgr.KeyScopeBIP0086 addr, err := w.cfg.Wallet.ImportTaprootScript(taprootScope, tapscript) if err != nil { - return nil, fmt.Errorf("error importing script into wallet: %v", + return nil, fmt.Errorf("error importing script into wallet: %w", err) } diff --git a/lnrpc/wtclientrpc/wtclient.go b/lnrpc/wtclientrpc/wtclient.go index 459ce3240..5ddb99d37 100644 --- a/lnrpc/wtclientrpc/wtclient.go +++ b/lnrpc/wtclientrpc/wtclient.go @@ -208,7 +208,8 @@ func (c *WatchtowerClient) AddTower(ctx context.Context, c.cfg.Resolver, ) if err != nil { - return nil, fmt.Errorf("invalid address %v: %v", req.Address, err) + return nil, fmt.Errorf("invalid address %v: %w", req.Address, + err) } towerAddr := &lnwire.NetAddress{ diff --git a/lntest/bitcoind_common.go b/lntest/bitcoind_common.go index b5c43c448..657da7cd3 100644 --- a/lntest/bitcoind_common.go +++ b/lntest/bitcoind_common.go @@ -192,7 +192,7 @@ func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string, client, err := rpcclient.New(&rpcCfg, nil) if err != nil { _ = cleanUp() - return nil, nil, fmt.Errorf("unable to create rpc client: %v", + return nil, nil, fmt.Errorf("unable to create rpc client: %w", err) } diff --git a/lntest/node/harness_node.go b/lntest/node/harness_node.go index fb0eea014..00424184e 100644 --- a/lntest/node/harness_node.go +++ b/lntest/node/harness_node.go @@ -294,14 +294,14 @@ func (hn *HarnessNode) ReadMacaroon(macPath string, timeout time.Duration) ( err := wait.NoError(func() error { macBytes, err := ioutil.ReadFile(macPath) if err != nil { - return fmt.Errorf("error reading macaroon file: %v", + return fmt.Errorf("error reading macaroon file: %w", err) } newMac := &macaroon.Macaroon{} if err = newMac.UnmarshalBinary(macBytes); err != nil { return fmt.Errorf("error unmarshalling macaroon "+ - "file: %v", err) + "file: %w", err) } mac = newMac @@ -619,7 +619,7 @@ func (hn *HarnessNode) cleanup() error { if hn.Cfg.backupDBDir != "" { err := os.RemoveAll(hn.Cfg.backupDBDir) if err != nil { - return fmt.Errorf("unable to remove backup dir: %v", + return fmt.Errorf("unable to remove backup dir: %w", err) } } diff --git a/lnwallet/btcwallet/psbt.go b/lnwallet/btcwallet/psbt.go index 0bea6a695..0fdf76c38 100644 --- a/lnwallet/btcwallet/psbt.go +++ b/lnwallet/btcwallet/psbt.go @@ -450,7 +450,7 @@ func signSegWitV0(in *psbt.PInput, tx *wire.MsgTx, in.SighashType, privKey, ) if err != nil { - return fmt.Errorf("error signing input %d: %v", idx, err) + return fmt.Errorf("error signing input %d: %w", idx, err) } in.PartialSigs = append(in.PartialSigs, &psbt.PartialSig{ PubKey: pubKeyBytes, @@ -472,7 +472,7 @@ func signSegWitV1KeySpend(in *psbt.PInput, tx *wire.MsgTx, privKey, ) if err != nil { - return fmt.Errorf("error signing taproot input %d: %v", idx, + return fmt.Errorf("error signing taproot input %d: %w", idx, err) } @@ -492,7 +492,7 @@ func signSegWitV1ScriptSpend(in *psbt.PInput, tx *wire.MsgTx, in.WitnessUtxo.PkScript, leaf, in.SighashType, privKey, ) if err != nil { - return fmt.Errorf("error signing taproot script input %d: %v", + return fmt.Errorf("error signing taproot script input %d: %w", idx, err) } diff --git a/lnwallet/chanfunding/psbt_assembler.go b/lnwallet/chanfunding/psbt_assembler.go index 5132f1296..885fb7b46 100644 --- a/lnwallet/chanfunding/psbt_assembler.go +++ b/lnwallet/chanfunding/psbt_assembler.go @@ -192,7 +192,7 @@ func (i *PsbtIntent) FundingParams() (btcutil.Address, int64, *psbt.Packet, // Encode the address in the human-readable bech32 format. addr, err := script.Address(i.netParams) if err != nil { - return nil, 0, nil, fmt.Errorf("unable to encode address: %v", + return nil, 0, nil, fmt.Errorf("unable to encode address: %w", err) } @@ -204,7 +204,7 @@ func (i *PsbtIntent) FundingParams() (btcutil.Address, int64, *psbt.Packet, packet, err = psbt.New(nil, nil, 2, 0, nil) if err != nil { return nil, 0, nil, fmt.Errorf("unable to create "+ - "PSBT: %v", err) + "PSBT: %w", err) } } packet.UnsignedTx.TxOut = append(packet.UnsignedTx.TxOut, out) diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index e85d87e39..5a16490e5 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -533,12 +533,12 @@ func (r *RPCKeyRing) SignMessageSchnorr(keyLoc keychain.KeyLocator, if err != nil { considerShutdown(err) return nil, fmt.Errorf("error signing message in remote "+ - "signer instance: %v", err) + "signer instance: %w", err) } sigParsed, err := schnorr.ParseSignature(resp.Signature) if err != nil { - return nil, fmt.Errorf("can't parse schnorr signature: %v", + return nil, fmt.Errorf("can't parse schnorr signature: %w", err) } return sigParsed, nil @@ -634,7 +634,7 @@ func (r *RPCKeyRing) ComputeInputScript(tx *wire.MsgTx, // input. sig, err := r.remoteSign(tx, signDesc, witnessProgram) if err != nil { - return nil, fmt.Errorf("error signing with remote instance: %v", + return nil, fmt.Errorf("error signing with remote instance: %w", err) } @@ -740,7 +740,7 @@ func (r *RPCKeyRing) MuSig2CreateSession(bipVersion input.MuSig2Version, resp.TaprootInternalKey, ) if err != nil { - return nil, fmt.Errorf("error parsing internal key: %v", + return nil, fmt.Errorf("error parsing internal key: %w", err) } } @@ -1261,7 +1261,7 @@ func connectRPC(hostPort, tlsCertPath, macaroonPath string, certBytes, err := ioutil.ReadFile(tlsCertPath) if err != nil { - return nil, fmt.Errorf("error reading TLS cert file %v: %v", + return nil, fmt.Errorf("error reading TLS cert file %v: %w", tlsCertPath, err) } @@ -1273,7 +1273,7 @@ func connectRPC(hostPort, tlsCertPath, macaroonPath string, macBytes, err := ioutil.ReadFile(macaroonPath) if err != nil { - return nil, fmt.Errorf("error reading macaroon file %v: %v", + return nil, fmt.Errorf("error reading macaroon file %v: %w", macaroonPath, err) } mac := &macaroon.Macaroon{} @@ -1297,7 +1297,7 @@ func connectRPC(hostPort, tlsCertPath, macaroonPath string, defer cancel() conn, err := grpc.DialContext(ctxt, hostPort, opts...) if err != nil { - return nil, fmt.Errorf("unable to connect to RPC server: %v", + return nil, fmt.Errorf("unable to connect to RPC server: %w", err) } diff --git a/peer/brontide.go b/peer/brontide.go index 187fbafe1..984a52809 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -3352,7 +3352,7 @@ func (p *Brontide) handleInitMsg(msg *lnwire.Init) error { // those presented in the local features fields. err := msg.Features.Merge(msg.GlobalFeatures) if err != nil { - return fmt.Errorf("unable to merge legacy global features: %v", + return fmt.Errorf("unable to merge legacy global features: %w", err) } diff --git a/routing/missioncontrol_store.go b/routing/missioncontrol_store.go index a6c98571f..dd60d9346 100644 --- a/routing/missioncontrol_store.go +++ b/routing/missioncontrol_store.go @@ -75,7 +75,7 @@ func newMissionControlStore(db kvdb.Backend, maxRecords int, err := kvdb.Update(db, func(tx kvdb.RwTx) error { resultsBucket, err := tx.CreateTopLevelBucket(resultsKey) if err != nil { - return fmt.Errorf("cannot create results bucket: %v", + return fmt.Errorf("cannot create results bucket: %w", err) } diff --git a/rpcperms/middleware_handler.go b/rpcperms/middleware_handler.go index 9b1d77a54..296203787 100644 --- a/rpcperms/middleware_handler.go +++ b/rpcperms/middleware_handler.go @@ -418,7 +418,7 @@ func NewMessageInterceptionRequest(ctx context.Context, case proto.Message: req.ProtoSerialized, err = proto.Marshal(t) if err != nil { - return nil, fmt.Errorf("cannot marshal proto msg: %v", + return nil, fmt.Errorf("cannot marshal proto msg: %w", err) } req.ProtoTypeName = string(proto.MessageName(t)) diff --git a/rpcserver.go b/rpcserver.go index f321bbdcf..517bca41e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1919,7 +1919,7 @@ func newPsbtAssembler(req *lnrpc.OpenChannelRequest, normalizedMinConfs int32, bytes.NewReader(psbtShim.BasePsbt), false, ) if err != nil { - return nil, fmt.Errorf("error parsing base PSBT: %v", + return nil, fmt.Errorf("error parsing base PSBT: %w", err) } } @@ -2144,7 +2144,7 @@ func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest, in.CloseAddress, r.cfg.ActiveNetParams.Params, ) if err != nil { - return nil, fmt.Errorf("error parsing upfront shutdown: %v", + return nil, fmt.Errorf("error parsing upfront shutdown: %w", err) } @@ -6513,7 +6513,7 @@ func (r *rpcServer) StopDaemon(_ context.Context, // otherwise some funds wouldn't be picked up. isRecoveryMode, progress, err := r.server.cc.Wallet.GetRecoveryInfo() if err != nil { - return nil, fmt.Errorf("unable to get wallet recovery info: %v", + return nil, fmt.Errorf("unable to get wallet recovery info: %w", err) } if isRecoveryMode && progress < 1 { @@ -7211,7 +7211,7 @@ func (r *rpcServer) ForwardingHistory(ctx context.Context, } timeSlice, err := r.server.miscDB.ForwardingLog().Query(eventQuery) if err != nil { - return nil, fmt.Errorf("unable to query forwarding log: %v", + return nil, fmt.Errorf("unable to query forwarding log: %w", err) } @@ -8013,7 +8013,7 @@ func (r *rpcServer) FundingStateStep(ctx context.Context, false, ) if err != nil { - return nil, fmt.Errorf("error parsing psbt: %v", + return nil, fmt.Errorf("error parsing psbt: %w", err) } diff --git a/walletunlocker/service.go b/walletunlocker/service.go index d896c2d88..bde5c7a56 100644 --- a/walletunlocker/service.go +++ b/walletunlocker/service.go @@ -882,7 +882,7 @@ func (u *UnlockerService) ChangePassword(ctx context.Context, err = macaroonService.Close() if err != nil { - return nil, fmt.Errorf("could not close macaroon service: %v", + return nil, fmt.Errorf("could not close macaroon service: %w", err) } diff --git a/watchtower/wtclient/session_negotiator.go b/watchtower/wtclient/session_negotiator.go index 1f92660db..ea17c5b47 100644 --- a/watchtower/wtclient/session_negotiator.go +++ b/watchtower/wtclient/session_negotiator.go @@ -475,7 +475,7 @@ func (n *sessionNegotiator) tryAddress(sessionKey keychain.SingleKeyECDH, err = n.cfg.DB.CreateClientSession(dbClientSession) if err != nil { - return fmt.Errorf("unable to persist ClientSession: %v", + return fmt.Errorf("unable to persist ClientSession: %w", err) } diff --git a/watchtower/wtclient/session_queue.go b/watchtower/wtclient/session_queue.go index 786410515..41ae28f2f 100644 --- a/watchtower/wtclient/session_queue.go +++ b/watchtower/wtclient/session_queue.go @@ -527,7 +527,7 @@ func (q *sessionQueue) nextStateUpdate() (*wtwire.StateUpdate, bool, hint, encBlob, err := task.craftSessionPayload(q.cfg.Signer) if err != nil { // TODO(conner): mark will not send - err := fmt.Errorf("unable to craft session payload: %v", + err := fmt.Errorf("unable to craft session payload: %w", err) return nil, false, wtdb.BackupID{}, err } @@ -665,7 +665,7 @@ func (q *sessionQueue) sendStateUpdate(conn wtserver.Peer, switch { case err == wtdb.ErrUnallocatedLastApplied: // TODO(conner): borked watchtower - err = fmt.Errorf("unable to ack seqnum=%d: %v", + err = fmt.Errorf("unable to ack seqnum=%d: %w", stateUpdate.SeqNum, err) q.log.Errorf("SessionQueue(%v) failed to ack update: %v", q.ID(), err) @@ -673,14 +673,14 @@ func (q *sessionQueue) sendStateUpdate(conn wtserver.Peer, case err == wtdb.ErrLastAppliedReversion: // TODO(conner): borked watchtower - err = fmt.Errorf("unable to ack seqnum=%d: %v", + err = fmt.Errorf("unable to ack seqnum=%d: %w", stateUpdate.SeqNum, err) q.log.Errorf("SessionQueue(%s) failed to ack update: %v", q.ID(), err) return err case err != nil: - err = fmt.Errorf("unable to ack seqnum=%d: %v", + err = fmt.Errorf("unable to ack seqnum=%d: %w", stateUpdate.SeqNum, err) q.log.Errorf("SessionQueue(%s) failed to ack update: %v", q.ID(), err) diff --git a/zpay32/amountunits.go b/zpay32/amountunits.go index f53f3ff00..8dcfb7c10 100644 --- a/zpay32/amountunits.go +++ b/zpay32/amountunits.go @@ -136,7 +136,7 @@ func encodeAmount(msat lnwire.MilliSatoshi) (string, error) { // Should always be expressible in pico BTC. pico, err := fromMSat['p'](msat) if err != nil { - return "", fmt.Errorf("unable to express %d msat as pBTC: %v", + return "", fmt.Errorf("unable to express %d msat as pBTC: %w", msat, err) } shortened := strconv.FormatUint(pico, 10) + "p" From 0609431a0c30d01899a2aaf1c1857081e9bd1a52 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 15:43:30 -0800 Subject: [PATCH 07/11] channeldb: fix payment control unit tests w/ errors.Is --- channeldb/payment_control_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 9db6fe862..5b394edae 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -181,7 +181,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { // Attempt a final payment, which should now fail since the prior // payment succeed. err = pControl.InitPayment(info.PaymentIdentifier, info) - if err != ErrAlreadyPaid { + if !errors.Is(err, ErrAlreadyPaid) { t.Fatalf("unable to send htlc message: %v", err) } } @@ -216,9 +216,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { // payment hash, should result in error indicating that payment has // already been sent. err = pControl.InitPayment(info.PaymentIdentifier, info) - require.Equal(t, ErrPaymentExists, err, "payment control wrong "+ - "behaviour: init payment again must trigger ErrPaymentExists "+ - "error") + require.ErrorIs(t, err, ErrPaymentExists) // Record an attempt. _, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt) @@ -234,7 +232,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { // Sends base htlc message which initiate StatusInFlight. err = pControl.InitPayment(info.PaymentIdentifier, info) - if err != ErrPaymentInFlight { + if !errors.Is(err, ErrPaymentInFlight) { t.Fatalf("payment control wrong behaviour: " + "double sending must trigger ErrPaymentInFlight error") } @@ -253,7 +251,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { assertPaymentInfo(t, pControl, info.PaymentIdentifier, info, nil, htlc) err = pControl.InitPayment(info.PaymentIdentifier, info) - if err != ErrAlreadyPaid { + if !errors.Is(err, ErrAlreadyPaid) { t.Fatalf("unable to send htlc message: %v", err) } } From c6073a14caf1b5697be100fd55c21152c0c879a8 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 2 Apr 2024 16:35:56 +0200 Subject: [PATCH 08/11] sqldb: ensure that we're using serializable isolation --- sqldb/interfaces.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sqldb/interfaces.go b/sqldb/interfaces.go index 53defdd3c..690414bb6 100644 --- a/sqldb/interfaces.go +++ b/sqldb/interfaces.go @@ -366,7 +366,8 @@ type BaseDB struct { // struct. func (s *BaseDB) BeginTx(ctx context.Context, opts TxOptions) (*sql.Tx, error) { sqlOptions := sql.TxOptions{ - ReadOnly: opts.ReadOnly(), + Isolation: sql.LevelSerializable, + ReadOnly: opts.ReadOnly(), } return s.DB.BeginTx(ctx, &sqlOptions) From 478ae1e9b0c7110ac9c8fcacadc3000cfefcb7f0 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 2 Apr 2024 16:46:31 +0200 Subject: [PATCH 09/11] sqldb: cleanup scope state reset by adding reset closure to ExecTx For SQL transactions, we often accumulate results in variables declared outside the closure's scope. To eliminate the need for manually clearing these containers, we introduce a reset function to ExecTx, mirroring the approach already adopted in kvdb. --- invoices/sql_store.go | 22 +++++++++++++--------- sqldb/interfaces.go | 6 ++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/invoices/sql_store.go b/invoices/sql_store.go index 94575ede0..cf829cd43 100644 --- a/invoices/sql_store.go +++ b/invoices/sql_store.go @@ -259,7 +259,7 @@ func (i *SQLStore) AddInvoice(ctx context.Context, AddedAt: newInvoice.CreationDate.UTC(), InvoiceID: invoiceID, }) - }) + }, func() {}) if err != nil { mappedSQLErr := sqldb.MapSQLError(err) var uniqueConstraintErr *sqldb.ErrSQLUniqueConstraintViolation @@ -599,7 +599,7 @@ func (i *SQLStore) LookupInvoice(ctx context.Context, invoice, err = i.fetchInvoice(ctx, db, ref) return err - }) + }, func() {}) if txErr != nil { return Invoice{}, txErr } @@ -617,7 +617,6 @@ func (i *SQLStore) FetchPendingInvoices(ctx context.Context) ( readTxOpt := NewSQLInvoiceQueryReadTx() err := i.db.ExecTx(ctx, &readTxOpt, func(db SQLInvoiceQueries) error { - invoices = make(map[lntypes.Hash]Invoice) limit := queryPaginationLimit return queryWithLimit(func(offset int) (int, error) { @@ -647,6 +646,8 @@ func (i *SQLStore) FetchPendingInvoices(ctx context.Context) ( return len(rows), nil }, limit) + }, func() { + invoices = make(map[lntypes.Hash]Invoice) }) if err != nil { return nil, fmt.Errorf("unable to fetch pending invoices: %w", @@ -674,7 +675,6 @@ func (i *SQLStore) InvoicesSettledSince(ctx context.Context, idx uint64) ( readTxOpt := NewSQLInvoiceQueryReadTx() err := i.db.ExecTx(ctx, &readTxOpt, func(db SQLInvoiceQueries) error { - invoices = nil settleIdx := idx limit := queryPaginationLimit @@ -762,6 +762,8 @@ func (i *SQLStore) InvoicesSettledSince(ctx context.Context, idx uint64) ( } return nil + }, func() { + invoices = nil }) if err != nil { return nil, fmt.Errorf("unable to get invoices settled since "+ @@ -788,7 +790,6 @@ func (i *SQLStore) InvoicesAddedSince(ctx context.Context, idx uint64) ( readTxOpt := NewSQLInvoiceQueryReadTx() err := i.db.ExecTx(ctx, &readTxOpt, func(db SQLInvoiceQueries) error { - result = nil addIdx := idx limit := queryPaginationLimit @@ -821,6 +822,8 @@ func (i *SQLStore) InvoicesAddedSince(ctx context.Context, idx uint64) ( return len(rows), nil }, limit) + }, func() { + result = nil }) if err != nil { @@ -845,7 +848,6 @@ func (i *SQLStore) QueryInvoices(ctx context.Context, readTxOpt := NewSQLInvoiceQueryReadTx() err := i.db.ExecTx(ctx, &readTxOpt, func(db SQLInvoiceQueries) error { - invoices = nil limit := queryPaginationLimit return queryWithLimit(func(offset int) (int, error) { @@ -919,6 +921,8 @@ func (i *SQLStore) QueryInvoices(ctx context.Context, return len(rows), nil }, limit) + }, func() { + invoices = nil }) if err != nil { return InvoiceSlice{}, fmt.Errorf("unable to query "+ @@ -1306,7 +1310,7 @@ func (i *SQLStore) UpdateInvoice(ctx context.Context, ref InvoiceRef, ) return err - }) + }, func() {}) if txErr != nil { // If the invoice is already settled, we'll return the // (unchanged) invoice and the ErrInvoiceAlreadySettled error. @@ -1370,7 +1374,7 @@ func (i *SQLStore) DeleteInvoice(ctx context.Context, } return nil - }) + }, func() {}) if err != nil { return fmt.Errorf("unable to delete invoices: %w", err) @@ -1390,7 +1394,7 @@ func (i *SQLStore) DeleteCanceledInvoices(ctx context.Context) error { } return nil - }) + }, func() {}) if err != nil { return fmt.Errorf("unable to delete invoices: %w", err) } diff --git a/sqldb/interfaces.go b/sqldb/interfaces.go index 690414bb6..f81799c57 100644 --- a/sqldb/interfaces.go +++ b/sqldb/interfaces.go @@ -52,7 +52,7 @@ type BatchedTx[Q any] interface { // specify if a transaction should be read-only and optionally what // type of concurrency control should be used. ExecTx(ctx context.Context, txOptions TxOptions, - txBody func(Q) error) error + txBody func(Q) error, reset func()) error } // Tx represents a database transaction that can be committed or rolled back. @@ -317,7 +317,7 @@ func ExecuteSQLTransactionWithRetry(ctx context.Context, makeTx MakeTx, // type of query and options run, in order to have access to batched operations // related to a storage object. func (t *TransactionExecutor[Q]) ExecTx(ctx context.Context, - txOptions TxOptions, txBody func(Q) error) error { + txOptions TxOptions, txBody func(Q) error, reset func()) error { makeTx := func() (Tx, error) { return t.BatchedQuerier.BeginTx(ctx, txOptions) @@ -328,6 +328,8 @@ func (t *TransactionExecutor[Q]) ExecTx(ctx context.Context, if !ok { return fmt.Errorf("expected *sql.Tx, got %T", tx) } + + reset() return txBody(t.createQuery(sqlTx)) } From 043e4aff01aa9a68de781116d51f23ec6ed8fae4 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Wed, 3 Apr 2024 16:21:12 +0200 Subject: [PATCH 10/11] sqldb+invoices: fix ordering bug in FilterInvoices Previously if the `reverse` named arg was unset (value of NULL), then SQL would order by NULL instead of ID causing undifined ordering of the returned rows. To fix that we check for NULL and also make sure to set the `reverse` arg in the code explicitly as it in the generated code it is an `interface{}` instead of `bool`. --- invoices/sql_store.go | 19 +++++++++++-------- sqldb/sqlc/invoices.sql.go | 16 ++++++++-------- sqldb/sqlc/queries/invoices.sql | 16 ++++++++-------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/invoices/sql_store.go b/invoices/sql_store.go index cf829cd43..bcf3c1f89 100644 --- a/invoices/sql_store.go +++ b/invoices/sql_store.go @@ -624,6 +624,7 @@ func (i *SQLStore) FetchPendingInvoices(ctx context.Context) ( PendingOnly: true, NumOffset: int32(offset), NumLimit: int32(limit), + Reverse: false, } rows, err := db.FilterInvoices(ctx, params) @@ -683,6 +684,7 @@ func (i *SQLStore) InvoicesSettledSince(ctx context.Context, idx uint64) ( SettleIndexGet: sqldb.SQLInt64(settleIdx + 1), NumLimit: int32(limit), NumOffset: int32(offset), + Reverse: false, } rows, err := db.FilterInvoices(ctx, params) @@ -798,6 +800,7 @@ func (i *SQLStore) InvoicesAddedSince(ctx context.Context, idx uint64) ( AddIndexGet: sqldb.SQLInt64(addIdx + 1), NumLimit: int32(limit), NumOffset: int32(offset), + Reverse: false, } rows, err := db.FilterInvoices(ctx, params) @@ -857,14 +860,6 @@ func (i *SQLStore) QueryInvoices(ctx context.Context, PendingOnly: q.PendingOnly, } - if !q.Reversed { - // The invoice with index offset id must not be - // included in the results. - params.AddIndexGet = sqldb.SQLInt64( - q.IndexOffset + uint64(offset) + 1, - ) - } - if q.Reversed { idx := int32(q.IndexOffset) @@ -883,6 +878,14 @@ func (i *SQLStore) QueryInvoices(ctx context.Context, } params.Reverse = true + } else { + // The invoice with index offset id must not be + // included in the results. + params.AddIndexGet = sqldb.SQLInt64( + q.IndexOffset + uint64(offset) + 1, + ) + + params.Reverse = false } if q.CreationDateStart != 0 { diff --git a/sqldb/sqlc/invoices.sql.go b/sqldb/sqlc/invoices.sql.go index 09ca1a1e2..fde02391c 100644 --- a/sqldb/sqlc/invoices.sql.go +++ b/sqldb/sqlc/invoices.sql.go @@ -82,19 +82,19 @@ WHERE ( $7 IS NULL ) AND ( CASE - WHEN $8=TRUE THEN (state = 0 OR state = 3) + WHEN $8 = TRUE THEN (state = 0 OR state = 3) ELSE TRUE END ) ORDER BY - CASE - WHEN $9 = FALSE THEN id - ELSE NULL +CASE + WHEN $9 = FALSE OR $9 IS NULL THEN id + ELSE NULL END ASC, - CASE - WHEN $9 = TRUE THEN id - ELSE NULL - END DESC +CASE + WHEN $9 = TRUE THEN id + ELSE NULL +END DESC LIMIT $11 OFFSET $10 ` diff --git a/sqldb/sqlc/queries/invoices.sql b/sqldb/sqlc/queries/invoices.sql index c36976a25..07c5ca418 100644 --- a/sqldb/sqlc/queries/invoices.sql +++ b/sqldb/sqlc/queries/invoices.sql @@ -73,19 +73,19 @@ WHERE ( sqlc.narg('created_before') IS NULL ) AND ( CASE - WHEN sqlc.narg('pending_only')=TRUE THEN (state = 0 OR state = 3) + WHEN sqlc.narg('pending_only') = TRUE THEN (state = 0 OR state = 3) ELSE TRUE END ) ORDER BY - CASE - WHEN sqlc.narg('reverse') = FALSE THEN id - ELSE NULL +CASE + WHEN sqlc.narg('reverse') = FALSE OR sqlc.narg('reverse') IS NULL THEN id + ELSE NULL END ASC, - CASE - WHEN sqlc.narg('reverse') = TRUE THEN id - ELSE NULL - END DESC +CASE + WHEN sqlc.narg('reverse') = TRUE THEN id + ELSE NULL +END DESC LIMIT @num_limit OFFSET @num_offset; -- name: UpdateInvoiceState :execresult From 024598266d66286fbca52c20985cb64889899277 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 2 Apr 2024 16:48:11 +0200 Subject: [PATCH 11/11] docs: update release notes for 0.18 --- docs/release-notes/release-notes-0.18.0.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index dfd7fab33..aafbc076f 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -440,6 +440,10 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * [Turn `sqldb` into a separate Go module](https://github.com/lightningnetwork/lnd/pull/8603). +* [Consolidate transaction + retry](https://github.com/lightningnetwork/lnd/pull/8611) logic and isolation + settings between `sqldb` and `kvdb` packages. + ## Code Health * [Remove database pointers](https://github.com/lightningnetwork/lnd/pull/8117)