From 1b02f0c2c75887e587347412d1ec72ddc13b4e6e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 7 Oct 2021 13:18:53 +0200 Subject: [PATCH] wallet: return unsigned TX in watch-only SendOutputs If SendOutputs is called on a watch-only wallet then a transaction is created but without any signatures. Publishing that transaction will always fail. But the attempt to publish will already update the internal state of the wallet so we shouldn't try to publish this unsigned TX. Instead we return a new error along with the unsigned transaction to give the caller the chance to sign and publish it through other means. --- wallet/wallet.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/wallet/wallet.go b/wallet/wallet.go index beac81e..9111855 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -72,6 +72,10 @@ var ( // to true. ErrTxLabelExists = errors.New("transaction already labelled") + // ErrTxUnsigned is returned when a transaction is created in the + // watch-only mode where we can select coins but not sign any inputs. + ErrTxUnsigned = errors.New("watch-only wallet, transaction not signed") + // Namespace bucket keys. waddrmgrNamespaceKey = []byte("waddrmgr") wtxmgrNamespaceKey = []byte("wtxmgr") @@ -3209,6 +3213,13 @@ func (w *Wallet) SendOutputs(outputs []*wire.TxOut, keyScope *waddrmgr.KeyScope, return nil, err } + // If our wallet is read-only, we'll get a transaction with coins + // selected but no witness data. In such a case we need to inform our + // caller that they'll actually need to go ahead and sign the TX. + if w.Manager.WatchOnly() { + return createdTx.Tx, ErrTxUnsigned + } + txHash, err := w.reliablyPublishTransaction(createdTx.Tx, label) if err != nil { return nil, err