From 45a94de61725bad757914d4f4577d24fa450e8ad 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