From d3e9b80094d6fa521dc986604d8290e7c71cc723 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 15 Sep 2023 16:08:17 -0700 Subject: [PATCH 01/18] kvdb/postgres: remove global application level lock In this commit, we remove the global application level lock from the postgres backend. This lock prevents multiple write transactions from happening at the same time, and will also block a writer if a read is on going. Since this lock was added, we know always open DB connections with the strongest level of concurrency control available: `LevelSerializable`. In concert with the new auto retry logic, we ensure that if db transactions conflict (writing the same key/row in this case), then the tx is retried automatically. Removing this lock should increase perf for the postgres backend, as now concurrent write transactions can proceed, being serialized as needed. Rather then trying to handle concurrency at the application level, we'll set postgres do its job, with the application only needing to retry as necessary. --- kvdb/postgres/db.go | 1 - kvdb/sqlbase/db.go | 8 ------- kvdb/sqlbase/readwrite_tx.go | 44 ------------------------------------ 3 files changed, 53 deletions(-) diff --git a/kvdb/postgres/db.go b/kvdb/postgres/db.go index 90ca8324a8d..425ba162257 100644 --- a/kvdb/postgres/db.go +++ b/kvdb/postgres/db.go @@ -28,7 +28,6 @@ func newPostgresBackend(ctx context.Context, config *Config, prefix string) ( Schema: "public", TableNamePrefix: prefix, SQLiteCmdReplacements: sqliteCmdReplacements, - WithTxLevelLock: true, } return sqlbase.NewSqlBackend(ctx, cfg) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index f6f2c759017..4d2d7686a2d 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -66,10 +66,6 @@ type Config struct { // commands. Note that the sqlite keywords to be replaced are // case-sensitive. SQLiteCmdReplacements SQLiteCmdReplacements - - // WithTxLevelLock when set will ensure that there is a transaction - // level lock. - WithTxLevelLock bool } // db holds a reference to the sql db connection. @@ -90,10 +86,6 @@ type db struct { // db is the underlying database connection instance. db *sql.DB - // lock is the global write lock that ensures single writer. This is - // only used if cfg.WithTxLevelLock is set. - lock sync.RWMutex - // table is the name of the table that contains the data for all // top-level buckets that have keys that cannot be mapped to a distinct // sql table. diff --git a/kvdb/sqlbase/readwrite_tx.go b/kvdb/sqlbase/readwrite_tx.go index ec761931adc..18a6a682c90 100644 --- a/kvdb/sqlbase/readwrite_tx.go +++ b/kvdb/sqlbase/readwrite_tx.go @@ -5,7 +5,6 @@ package sqlbase import ( "context" "database/sql" - "sync" "github.com/btcsuite/btcwallet/walletdb" ) @@ -20,28 +19,11 @@ type readWriteTx struct { // active is true if the transaction hasn't been committed yet. active bool - - // locker is a pointer to the global db lock. - locker sync.Locker } // newReadWriteTx creates an rw transaction using a connection from the // specified pool. func newReadWriteTx(db *db, readOnly bool) (*readWriteTx, error) { - locker := newNoopLocker() - if db.cfg.WithTxLevelLock { - // Obtain the global lock instance. An alternative here is to - // obtain a database lock from Postgres. Unfortunately there is - // no database-level lock in Postgres, meaning that each table - // would need to be locked individually. Perhaps an advisory - // lock could perform this function too. - locker = &db.lock - if readOnly { - locker = db.lock.RLocker() - } - } - locker.Lock() - // Start the transaction. Don't use the timeout context because it would // be applied to the transaction as a whole. If possible, mark the // transaction as read-only to make sure that potential programming @@ -54,7 +36,6 @@ func newReadWriteTx(db *db, readOnly bool) (*readWriteTx, error) { }, ) if err != nil { - locker.Unlock() return nil, err } @@ -62,7 +43,6 @@ func newReadWriteTx(db *db, readOnly bool) (*readWriteTx, error) { db: db, tx: tx, active: true, - locker: locker, }, nil } @@ -94,7 +74,6 @@ func (tx *readWriteTx) Rollback() error { // Unlock the transaction regardless of the error result. tx.active = false - tx.locker.Unlock() return err } @@ -162,7 +141,6 @@ func (tx *readWriteTx) Commit() error { // Unlock the transaction regardless of the error result. tx.active = false - tx.locker.Unlock() return err } @@ -204,25 +182,3 @@ func (tx *readWriteTx) Exec(query string, args ...interface{}) (sql.Result, return tx.tx.ExecContext(ctx, query, args...) } - -// noopLocker is an implementation of a no-op sync.Locker. -type noopLocker struct{} - -// newNoopLocker creates a new noopLocker. -func newNoopLocker() sync.Locker { - return &noopLocker{} -} - -// Lock is a noop. -// -// NOTE: this is part of the sync.Locker interface. -func (n *noopLocker) Lock() { -} - -// Unlock is a noop. -// -// NOTE: this is part of the sync.Locker interface. -func (n *noopLocker) Unlock() { -} - -var _ sync.Locker = (*noopLocker)(nil) From 9ee3aeecc522d1499d7a592e5293d7f72fc436a1 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 18 Sep 2023 11:58:58 -0700 Subject: [PATCH 02/18] temp: add replace so new code is used --- go.mod | 2 ++ go.sum | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 6a33f3221b2..827955b1b22 100644 --- a/go.mod +++ b/go.mod @@ -206,4 +206,6 @@ replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-d // docs/INSTALL.md. go 1.19 +replace github.com/lightningnetwork/lnd/kvdb => ./kvdb + retract v0.0.2 diff --git a/go.sum b/go.sum index ccfd7277230..5224f04a5a1 100644 --- a/go.sum +++ b/go.sum @@ -432,8 +432,6 @@ github.com/lightningnetwork/lnd/fn v1.0.4 h1:n4iGRRoS+XHqNbOrsXIvweps/QfWk+moO7F github.com/lightningnetwork/lnd/fn v1.0.4/go.mod h1:K9gbvdl5z4XmRcqWUVqvvVcuRKtmq9BNQ+cWYlk+vjw= 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= From 352fe645852902cc1303b67600203d3b82075763 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:12:50 -0700 Subject: [PATCH 03/18] 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 3915a34f410..1b12dda66ff 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 c291466104d..9df93893a43 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 a939ec499f5..6cc1b1cf87f 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 d1fa789d9a9096594cf6ed190faf628fc3bc8a2b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:14:12 -0700 Subject: [PATCH 04/18] 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 8ad90f80837..b90ea9a0501 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -1497,9 +1497,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 3404a1f91b48873b90a76b42a4c035c4fb4dc71e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:15:38 -0700 Subject: [PATCH 05/18] 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 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 4d2d7686a2d..9df7f9775a7 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -173,7 +173,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: @@ -182,6 +181,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 IsSerializationError(MapSQLError(err)) { + log.Tracef("Detected db serialization error "+ + "via panic: %v", err) + } else { + log.Criticalf("Caught unhandled error: %v", r) + } } }() From 53a5155c4c596b1bd957e8e1afce95935a305fd2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:16:28 -0700 Subject: [PATCH 06/18] kvdb: implement txn retry when executing txn call back At times we'll get an error from the transaction call back itself, since we may be using postgres over streaming RPC. In this case, we still need to roll back then attempt to retry. --- kvdb/sqlbase/db.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 9df7f9775a7..04e8a31b439 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -311,14 +311,23 @@ func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, return dbErr } - err = catchPanic(func() error { return f(tx) }) - if err != nil { + fnErr := catchPanic(func() error { return f(tx) }) + if fnErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Errorf("Error rolling back tx: %v", rollbackErr) } - return err + dbErr := MapSQLError(fnErr) + if IsSerializationError(dbErr) { + // Nothing to roll back here, since we didn't + // even get a transaction yet. + if waitBeforeRetry(i) { + continue + } + } + + return fnErr } dbErr := tx.Commit() From f9565454a7aa290e534789813a908e3effc7a46f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Sep 2023 18:18:51 -0700 Subject: [PATCH 07/18] kvdb: fix bug in commit retry loop In this commit, we fix a bug in the commit retry loop, we'll now make sure that if we get an error on commit, we'll map it to the SQL error then attempt to decide if we need to retry or not. --- kvdb/sqlbase/db.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 04e8a31b439..4414257dcb4 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -330,16 +330,21 @@ func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, return fnErr } - dbErr := tx.Commit() - if IsSerializationError(dbErr) { + commitErr := tx.Commit() + if commitErr != nil { _ = tx.Rollback() - if waitBeforeRetry(i) { - continue + dbErr := MapSQLError(fnErr) + if IsSerializationError(dbErr) { + // The transaction failed due to a serialization + // problem, so we can retry. + if waitBeforeRetry(i) { + continue + } } } - return dbErr + return commitErr } // If we get to this point, then we weren't able to successfully commit From fb06c6d18f802e128bd14df94544ea4005da4a4f Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 7 Mar 2024 09:59:51 +0100 Subject: [PATCH 08/18] kvdb: return error if rollback fails Because rolling back any changes that haven't been committed yet is essential when re-trying, if rolling back we should fail hard. --- kvdb/sqlbase/db.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 4414257dcb4..6c3ac3068b7 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -313,9 +313,8 @@ func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, fnErr := catchPanic(func() error { return f(tx) }) if fnErr != nil { - if rollbackErr := tx.Rollback(); rollbackErr != nil { - log.Errorf("Error rolling back tx: %v", - rollbackErr) + if err := attemptRollback(tx); err != nil { + return err } dbErr := MapSQLError(fnErr) @@ -332,7 +331,9 @@ func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, commitErr := tx.Commit() if commitErr != nil { - _ = tx.Rollback() + if err := attemptRollback(tx); err != nil { + return err + } dbErr := MapSQLError(fnErr) if IsSerializationError(dbErr) { @@ -384,3 +385,15 @@ 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) { + return fmt.Errorf("error rolling back tx: %w", rollbackErr) + } + + return nil +} From d26774771a42fad65caabc41948bf56766eaf98d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 7 Mar 2024 13:17:15 +0100 Subject: [PATCH 09/18] mod: bump to btcwallet that wraps errors --- go.mod | 6 ++++++ go.sum | 12 ++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 827955b1b22..4935484cffe 100644 --- a/go.mod +++ b/go.mod @@ -208,4 +208,10 @@ go 1.19 replace github.com/lightningnetwork/lnd/kvdb => ./kvdb +replace github.com/btcsuite/btcwallet => github.com/guggero/btcwallet v0.13.1-0.20240307121533-003d89274212 + +replace github.com/btcsuite/btcwallet/walletdb => github.com/guggero/btcwallet/walletdb v1.4.1-0.20240307121533-003d89274212 + +replace github.com/btcsuite/btcwallet/wtxmgr => github.com/guggero/btcwallet/wtxmgr v1.3.1-0.20240307121533-003d89274212 + retract v0.0.2 diff --git a/go.sum b/go.sum index 5224f04a5a1..5b0dcbf42ec 100644 --- a/go.sum +++ b/go.sum @@ -90,18 +90,12 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.16.10-0.20240305014015-f7c216e78ee8 h1:fkPZ7LfOCm3Nn0Y/56LOqwooYaw9cV/4jZkdHw7XGik= -github.com/btcsuite/btcwallet v0.16.10-0.20240305014015-f7c216e78ee8/go.mod h1:q+J5AzV+ymzUaBXkP099uuVh18yzCyHHXPc4rxi55mk= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0= github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk= github.com/btcsuite/btcwallet/wallet/txrules v1.2.1/go.mod h1:MVSqRkju/IGxImXYPfBkG65FgEZYA4fXchheILMVl8g= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 h1:nmcKAVTv/cmYrs0A4hbiC6Qw+WTLYy/14SmTt3mLnCo= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4/go.mod h1:YqJR8WAAHiKIPesZTr9Cx9Az4fRhRLcJ6GcxzRUZCAc= -github.com/btcsuite/btcwallet/walletdb v1.4.1 h1:NGIGoxx3trpaWqmdOeuhju7KJKp5UM96mQL21idF6RY= -github.com/btcsuite/btcwallet/walletdb v1.4.1/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ= -github.com/btcsuite/btcwallet/wtxmgr v1.5.1 h1:2yXhMGa4DNz16Mi0e8dVoiFXKOznXlxiGLhB3hKj2uA= -github.com/btcsuite/btcwallet/wtxmgr v1.5.1/go.mod h1:tO4FBSdann0xg/Jtm0grV7t1DzpQMK8nThYVtvSJo/8= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= @@ -294,6 +288,12 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= +github.com/guggero/btcwallet v0.13.1-0.20240307121533-003d89274212 h1:8Nu3n5g4FM8fX5rkdyp1lLBgmp843usprdRy7+rdWHs= +github.com/guggero/btcwallet v0.13.1-0.20240307121533-003d89274212/go.mod h1:q+J5AzV+ymzUaBXkP099uuVh18yzCyHHXPc4rxi55mk= +github.com/guggero/btcwallet/walletdb v1.4.1-0.20240307121533-003d89274212 h1:LWObxWqOl8ow49C/ms2TTx/p2ykIxLOoz9yielafCd8= +github.com/guggero/btcwallet/walletdb v1.4.1-0.20240307121533-003d89274212/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ= +github.com/guggero/btcwallet/wtxmgr v1.3.1-0.20240307121533-003d89274212 h1:c16XaJHBFc4skEu42fYTs5lqrvBGCoO45kQ6jTjR7ek= +github.com/guggero/btcwallet/wtxmgr v1.3.1-0.20240307121533-003d89274212/go.mod h1:tO4FBSdann0xg/Jtm0grV7t1DzpQMK8nThYVtvSJo/8= 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= From 0cd601765a97f839c5db4440160e57bd2e05110c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 7 Mar 2024 13:19:28 +0100 Subject: [PATCH 10/18] 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 | 2 +- chainntnfs/btcdnotify/btcd.go | 2 +- chainntnfs/interface.go | 16 ++++++++-------- chainntnfs/neutrinonotify/neutrino.go | 4 ++-- chainreg/chainregistry.go | 4 ++-- channeldb/codec.go | 2 +- channeldb/db.go | 2 +- channeldb/migration21/current/current_codec.go | 2 +- channeldb/migration21/legacy/legacy_codec.go | 2 +- 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/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 | 2 +- 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 | 12 ++++++------ 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 | 2 +- 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 +- 59 files changed, 125 insertions(+), 125 deletions(-) diff --git a/autopilot/agent.go b/autopilot/agent.go index 9aef4f9f4b9..d9c35a685fa 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 0a7e3557b68..b43856d2420 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 cf30aca82c5..e5999f51826 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 e3f93a665d1..ba210853c40 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 748eeba779a..c956afb0046 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 d268c8374a6..e7fa4f52436 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -792,7 +792,7 @@ 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", + 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 430a1066140..6615be984f1 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -886,7 +886,7 @@ 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", + 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 0f2fe27e459..906bfbfbe13 100644 --- a/chainntnfs/interface.go +++ b/chainntnfs/interface.go @@ -483,12 +483,12 @@ 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", + 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", + return 0, fmt.Errorf("unable to get header for hash=%v: %w", chainHash, err) } reorgHash = reorgHeader.PrevBlock @@ -497,7 +497,7 @@ 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", + return 0, fmt.Errorf("unable to get verbose header for hash=%v: %w", chainHash, err) } @@ -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,13 @@ 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 b2e00da80e0..9a9e8a7052f 100644 --- a/chainntnfs/neutrinonotify/neutrino.go +++ b/chainntnfs/neutrinonotify/neutrino.go @@ -582,7 +582,7 @@ 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", + return nil, fmt.Errorf("unable to get header for height=%v: %w", scanHeight, err) } @@ -601,7 +601,7 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ ) if err != nil { return nil, fmt.Errorf("unable to retrieve regular filter for "+ - "height=%v: %v", scanHeight, err) + "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 02da263912c..1aa5538f3b8 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -730,11 +730,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 a79ef8558f2..7ee7a5fabf9 100644 --- a/channeldb/codec.go +++ b/channeldb/codec.go @@ -78,7 +78,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/db.go b/channeldb/db.go index aff70d46269..d2759dafe91 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 c78319a4f75..15b939dba09 100644 --- a/channeldb/migration21/current/current_codec.go +++ b/channeldb/migration21/current/current_codec.go @@ -83,7 +83,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/migration21/legacy/legacy_codec.go b/channeldb/migration21/legacy/legacy_codec.go index 8416ff39b6e..ee5414525b1 100644 --- a/channeldb/migration21/legacy/legacy_codec.go +++ b/channeldb/migration21/legacy/legacy_codec.go @@ -81,7 +81,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/migration25/migration.go b/channeldb/migration25/migration.go index 257d8272c5d..53bff36420f 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 a6f7b1a96be..85b1d52c995 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 406cc291a48..83a9cee8fb9 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 a87f6eda723..ca2f5cff6d4 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 0f36a78edf8..9035e3e6f95 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 6ae25e21012..5027034cb02 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 0cc1fcdbe41..938a0b0ef11 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/payments.go b/channeldb/payments.go index 15bcd834249..a1baa07f7a2 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 92a96c43c39..54e03057ab9 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 45f032f53c7..fd21b88d48c 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{ @@ -866,14 +866,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 1ba3b42c88e..e5e153f45e2 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 0f350e5c2c3..21666be9645 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 5190cd69f73..561208f365c 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1743,7 +1743,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 2c140fa6d9e..f54f29a26c1 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 9c668054277..90ac69c0ee6 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 f095601699d..0d72e537da8 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -1220,7 +1220,7 @@ 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", + return fmt.Errorf("error parsing outputs JSON: %w", err) } tpl.Outputs = amountToAddr diff --git a/config_builder.go b/config_builder.go index 5195777e117..c222dcc944c 100644 --- a/config_builder.go +++ b/config_builder.go @@ -567,7 +567,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 @@ -1044,7 +1044,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 @@ -1059,7 +1059,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 @@ -1274,7 +1274,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 0e33dc57160..017e8bdac2f 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 2c353bf6a5e..c34314d9e7b 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) } @@ -1872,7 +1872,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 @@ -1909,7 +1909,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 cf228eee712..10fa51623a1 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 b567a69403f..b910151cb19 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 991d5c6119f..98317eb8f15 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 163c33b7e30..51d982ebe4a 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 5196090b77c..8c1f86be595 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()) @@ -4825,7 +4825,7 @@ func (f *Manager) handleErrorMsg(peer lnpeer.Peer, msg *lnwire.Error) { // If we did indeed find the funding workflow, then we'll return the // error back to the caller (if any), and cancel the workflow itself. - fundingErr := fmt.Errorf("received funding error from %x: %v", + fundingErr := fmt.Errorf("received funding error from %x: %w", peerKey.SerializeCompressed(), msg.Error(), ) log.Errorf(fundingErr.Error()) diff --git a/input/musig2.go b/input/musig2.go index 28a15af7387..5891522829a 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 6597eb2d593..b477e206b33 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 0034f134b37..f4ef03a078b 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 e2b98efa763..662c0d08d9f 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 7ed683f24ef..194bdc996f1 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 a84ea68ffdc..c29d495eb0c 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 3e71070aae8..253d5850942 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1043,7 +1043,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) } @@ -2604,7 +2604,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 459ce3240c2..79e4287a6e0 100644 --- a/lnrpc/wtclientrpc/wtclient.go +++ b/lnrpc/wtclientrpc/wtclient.go @@ -208,7 +208,7 @@ 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 9ce962dc260..e10bfed54dd 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 71d55d9eac8..fd873c2a23d 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 e655300c1f6..1bed4b42c3b 100644 --- a/lnwallet/btcwallet/psbt.go +++ b/lnwallet/btcwallet/psbt.go @@ -449,7 +449,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, @@ -471,7 +471,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) } @@ -491,7 +491,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 5132f129664..885fb7b4657 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 50a38cd9461..62c9d52d0b7 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 189fb16605b..6ac438284d1 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -3318,7 +3318,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 a6c98571fd6..dd60d9346b1 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 9b1d77a5414..29620378745 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 d55c97257a1..7376399d399 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1889,7 +1889,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) } } @@ -2114,7 +2114,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) } @@ -6460,7 +6460,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 { @@ -7142,7 +7142,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) } @@ -7944,7 +7944,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 d896c2d88a2..bde5c7a560c 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 65d5060aec9..aed91c603b9 100644 --- a/watchtower/wtclient/session_negotiator.go +++ b/watchtower/wtclient/session_negotiator.go @@ -480,7 +480,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 78641051598..41ae28f2fac 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 f53f3ff00e0..8dcfb7c1015 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 43e6d9f70c089a95689163560e6e4d952979ae0b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 7 Mar 2024 17:23:08 +0100 Subject: [PATCH 11/18] wip: debug itest failures --- channeldb/payment_control.go | 33 ++++++++++++++++++++------------ kvdb/sqlbase/db.go | 4 ++-- lnrpc/routerrpc/router_server.go | 2 +- routing/router.go | 3 ++- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 4ad29167e89..3c0ed5dd8c3 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -159,7 +159,7 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, prefetchPayment(tx, paymentHash) bucket, err := createPaymentBucket(tx, paymentHash) if err != nil { - return err + return fmt.Errorf("couldn't create bucket: %w", err) } // Get the existing status of this payment, if any. @@ -171,14 +171,15 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, // retrying the payment or return a specific error. case err == nil: if err := paymentStatus.initializable(); err != nil { - updateErr = err + updateErr = fmt.Errorf("initialize: %w", err) return nil } // Otherwise, if the error is not `ErrPaymentNotInitiated`, // we'll return the error. case !errors.Is(err, ErrPaymentNotInitiated): - return err + return fmt.Errorf("couldn't fetch payment status: %w", + err) } // Before we set our new sequence number, we check whether this @@ -190,7 +191,8 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, if seqBytes != nil { indexBucket := tx.ReadWriteBucket(paymentsIndexBucket) if err := indexBucket.Delete(seqBytes); err != nil { - return err + return fmt.Errorf("couldn't delete index "+ + "bucket: %w", err) } } @@ -201,27 +203,30 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, tx, sequenceNum, info.PaymentIdentifier, ) if err != nil { - return err + return fmt.Errorf("couldn't create payment index "+ + "entry: %w", err) } err = bucket.Put(paymentSequenceKey, sequenceNum) if err != nil { - return err + return fmt.Errorf("couldn't put sequence key: %w", err) } // Add the payment info to the bucket, which contains the // static information for this payment err = bucket.Put(paymentCreationInfoKey, infoBytes) if err != nil { - return err + return fmt.Errorf("couldn't put creation key info: %w", + err) } // We'll delete any lingering HTLCs to start with, in case we // are initializing a payment that was attempted earlier, but // left in a state where we could retry. err = bucket.DeleteNestedBucket(paymentHtlcsBucket) - if err != nil && err != kvdb.ErrBucketNotFound { - return err + if err != nil && !errors.Is(err, kvdb.ErrBucketNotFound) { + return fmt.Errorf("couldn't delete nested bucket: %w", + err) } // Also delete any lingering failure info now that we are @@ -229,10 +234,14 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, return bucket.Delete(paymentFailInfoKey) }) if err != nil { - return err + return fmt.Errorf("error in batch: %w", err) + } + + if updateErr != nil { + return fmt.Errorf("update err: %w", updateErr) } - return updateErr + return nil } // DeleteFailedAttempts deletes all failed htlcs for a payment if configured @@ -521,7 +530,7 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash, prefetchPayment(tx, paymentHash) bucket, err := fetchPaymentBucketUpdate(tx, paymentHash) - if err == ErrPaymentNotInitiated { + if errors.Is(err, ErrPaymentNotInitiated) { updateErr = ErrPaymentNotInitiated return nil } else if err != nil { diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 6c3ac3068b7..8e27e1f84ed 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -35,7 +35,7 @@ const ( DefaultInitialRetryDelay = time.Millisecond * 50 // DefaultMaxRetryDelay is the default maximum delay between retries. - DefaultMaxRetryDelay = time.Second * 5 + DefaultMaxRetryDelay = time.Second ) // Config holds a set of configuration options of a sql database connection. @@ -345,7 +345,7 @@ func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, } } - return commitErr + return nil } // If we get to this point, then we weren't able to successfully commit diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 194bdc996f1..b5e24287307 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -1265,7 +1265,7 @@ func (s *Server) subscribePayment(identifier lntypes.Hash) ( sub, err := router.Tower.SubscribePayment(identifier) switch { - case err == channeldb.ErrPaymentNotInitiated: + case errors.Is(err, channeldb.ErrPaymentNotInitiated): return nil, status.Error(codes.NotFound, err.Error()) case err != nil: return nil, err diff --git a/routing/router.go b/routing/router.go index 4abfe54b4a7..50dcc63f79c 100644 --- a/routing/router.go +++ b/routing/router.go @@ -2442,7 +2442,8 @@ func (r *ChannelRouter) PreparePayment(payment *LightningPayment) ( // control. paySession, err := r.cfg.SessionSource.NewPaymentSession(payment) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("error creating payment session: "+ + "%w", err) } // Record this payment hash with the ControlTower, ensuring it is not From 5e5be372f99a5474713cede9c04ae0d4ebe9961f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 15:05:12 -0800 Subject: [PATCH 12/18] build: temp point to roasbeef's fork Includes a fix for a wrap, and module replace. --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 4935484cffe..42506e6909d 100644 --- a/go.mod +++ b/go.mod @@ -208,10 +208,10 @@ go 1.19 replace github.com/lightningnetwork/lnd/kvdb => ./kvdb -replace github.com/btcsuite/btcwallet => github.com/guggero/btcwallet v0.13.1-0.20240307121533-003d89274212 +replace github.com/btcsuite/btcwallet => github.com/roasbeef/btcwallet v0.11.1-0.20240307225634-ff180237e5ad -replace github.com/btcsuite/btcwallet/walletdb => github.com/guggero/btcwallet/walletdb v1.4.1-0.20240307121533-003d89274212 +replace github.com/btcsuite/btcwallet/walletdb => github.com/roasbeef/btcwallet/walletdb v1.1.1-0.20240307225634-ff180237e5ad -replace github.com/btcsuite/btcwallet/wtxmgr => github.com/guggero/btcwallet/wtxmgr v1.3.1-0.20240307121533-003d89274212 +replace github.com/btcsuite/btcwallet/wtxmgr => github.com/roasbeef/btcwallet/wtxmgr v1.0.1-0.20240307225634-ff180237e5ad retract v0.0.2 diff --git a/go.sum b/go.sum index 5b0dcbf42ec..715840cbd53 100644 --- a/go.sum +++ b/go.sum @@ -288,12 +288,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= -github.com/guggero/btcwallet v0.13.1-0.20240307121533-003d89274212 h1:8Nu3n5g4FM8fX5rkdyp1lLBgmp843usprdRy7+rdWHs= -github.com/guggero/btcwallet v0.13.1-0.20240307121533-003d89274212/go.mod h1:q+J5AzV+ymzUaBXkP099uuVh18yzCyHHXPc4rxi55mk= -github.com/guggero/btcwallet/walletdb v1.4.1-0.20240307121533-003d89274212 h1:LWObxWqOl8ow49C/ms2TTx/p2ykIxLOoz9yielafCd8= -github.com/guggero/btcwallet/walletdb v1.4.1-0.20240307121533-003d89274212/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ= -github.com/guggero/btcwallet/wtxmgr v1.3.1-0.20240307121533-003d89274212 h1:c16XaJHBFc4skEu42fYTs5lqrvBGCoO45kQ6jTjR7ek= -github.com/guggero/btcwallet/wtxmgr v1.3.1-0.20240307121533-003d89274212/go.mod h1:tO4FBSdann0xg/Jtm0grV7t1DzpQMK8nThYVtvSJo/8= 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= @@ -530,6 +524,12 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/roasbeef/btcwallet v0.11.1-0.20240307225634-ff180237e5ad h1:wvsow2VwKa/efv0ObcsMpQnw4lypkj21vNkG0cQcCjg= +github.com/roasbeef/btcwallet v0.11.1-0.20240307225634-ff180237e5ad/go.mod h1:rROXjC/DZcEkGQBaUUBnL6q02lhR7sTgZt7LM9Kiv/4= +github.com/roasbeef/btcwallet/walletdb v1.1.1-0.20240307225634-ff180237e5ad h1:ZH/8I/jIG84zkHMwOJXsOpCtm748ITS77B4DAKAjSCI= +github.com/roasbeef/btcwallet/walletdb v1.1.1-0.20240307225634-ff180237e5ad/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ= +github.com/roasbeef/btcwallet/wtxmgr v1.0.1-0.20240307225634-ff180237e5ad h1:1eXppv9SmNBe2MbP9DzocbNAcxxA0mHs8hUnL+Tjnpc= +github.com/roasbeef/btcwallet/wtxmgr v1.0.1-0.20240307225634-ff180237e5ad/go.mod h1:tO4FBSdann0xg/Jtm0grV7t1DzpQMK8nThYVtvSJo/8= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= 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= From 2c12a92f201c4683dea64856ff8c627bd78a2f23 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 15:43:08 -0800 Subject: [PATCH 13/18] funding: fix test warning due to error wrapping a logged err --- funding/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funding/manager.go b/funding/manager.go index 8c1f86be595..81f32a3a487 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -4825,7 +4825,7 @@ func (f *Manager) handleErrorMsg(peer lnpeer.Peer, msg *lnwire.Error) { // If we did indeed find the funding workflow, then we'll return the // error back to the caller (if any), and cancel the workflow itself. - fundingErr := fmt.Errorf("received funding error from %x: %w", + fundingErr := fmt.Errorf("received funding error from %x: %v", peerKey.SerializeCompressed(), msg.Error(), ) log.Errorf(fundingErr.Error()) From 31d19e1dae9c3774fb37e26c461e5b7e2ceb6b1b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 15:43:30 -0800 Subject: [PATCH 14/18] 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 9db6fe862ed..5b394edae8f 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 40b5b60115cd19a09b2ac9b7068bc4427ce8b58f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 16:14:18 -0800 Subject: [PATCH 15/18] channeldb: don't wrap the error fail from initializable This causes itests to fail, still need to investigate why the other errors.Is check isn't catching this. --- channeldb/payment_control.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 3c0ed5dd8c3..69325c4257b 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -171,7 +171,7 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, // retrying the payment or return a specific error. case err == nil: if err := paymentStatus.initializable(); err != nil { - updateErr = fmt.Errorf("initialize: %w", err) + updateErr = err return nil } @@ -234,14 +234,10 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, return bucket.Delete(paymentFailInfoKey) }) if err != nil { - return fmt.Errorf("error in batch: %w", err) + return fmt.Errorf("unable to init payment: %w", err) } - if updateErr != nil { - return fmt.Errorf("update err: %w", updateErr) - } - - return nil + return updateErr } // DeleteFailedAttempts deletes all failed htlcs for a payment if configured From 04dcb65cccd1f18470a63b175a58d60ecc29aedb Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 16:16:17 -0800 Subject: [PATCH 16/18] kvdb/sqlbase: properly map commitErr on failed commit This fixes a bug as we were mapping the `fnErr`, which was already nil if we got to this point. We'll also return the `commitErr` as is, if we were unable to match it. This ensures we don't mask an error. --- kvdb/sqlbase/db.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index 8e27e1f84ed..beb509bb2a0 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -335,14 +335,16 @@ func (db *db) executeTransaction(f func(tx walletdb.ReadWriteTx) error, return err } - dbErr := MapSQLError(fnErr) + dbErr := MapSQLError(commitErr) if IsSerializationError(dbErr) { - // The transaction failed due to a serialization - // problem, so we can retry. + // The transaction failed due to a + // serialization problem, so we can retry. if waitBeforeRetry(i) { continue } } + + return commitErr } return nil From 99506d9499b85afda8844de6fb308c9682af2acc Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 16:46:23 -0800 Subject: [PATCH 17/18] kvdb/postgres: update TestPanic w/ rollback error We'll now actually catch the error for a failed rollback, so the error we return in the case of a severed connection differs from before, requiring an update to the tests. --- kvdb/postgres/db_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kvdb/postgres/db_test.go b/kvdb/postgres/db_test.go index 0378b4dbb85..3ad1a32d9b6 100644 --- a/kvdb/postgres/db_test.go +++ b/kvdb/postgres/db_test.go @@ -58,5 +58,5 @@ func TestPanic(t *testing.T) { return nil }, func() {}) - require.Contains(t, err.Error(), "terminating connection") + require.Contains(t, err.Error(), "conn closed") } From 8dd4dc2cd09b3cf6a5cd4e6ae85a0b9f65f994a2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 7 Mar 2024 17:19:48 -0800 Subject: [PATCH 18/18] kvdb: increase max number of retries to 50 This is an attempt to get the async payment test passing. This test creates 488 concurrent payments at once. --- kvdb/sqlbase/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kvdb/sqlbase/db.go b/kvdb/sqlbase/db.go index beb509bb2a0..6251250cc2a 100644 --- a/kvdb/sqlbase/db.go +++ b/kvdb/sqlbase/db.go @@ -24,7 +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 + DefaultNumTxRetries = 50 // DefaultInitialRetryDelay is the default initial delay between // retries. This will be used to generate a random delay between -50%