lnwallet/btcwallet: return concrete error type from PublishTransaction

This commit is contained in:
Johan T. Halseth 2018-01-15 23:27:27 +01:00
parent a1a9834a53
commit 1dcc89cca9
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
1 changed files with 83 additions and 2 deletions

View File

@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"math"
"strings"
"sync"
"time"
@ -399,9 +400,89 @@ func (b *BtcWallet) ListUnspentWitness(minConfs int32) ([]*lnwallet.Utxo, error)
}
// PublishTransaction performs cursory validation (dust checks, etc), then
// finally broadcasts the passed transaction to the Bitcoin network.
// finally broadcasts the passed transaction to the Bitcoin network. If
// publishing the transaction fails, an error describing the reason is
// returned (currently ErrDoubleSpend). If the transaction is already
// published to the network (either in the mempool or chain) no error
// will be returned.
func (b *BtcWallet) PublishTransaction(tx *wire.MsgTx) error {
return b.wallet.PublishTransaction(tx)
if err := b.wallet.PublishTransaction(tx); err != nil {
switch b.chain.(type) {
case *chain.RPCClient:
if strings.Contains(err.Error(), "already have") {
// Transaction was already in the mempool, do
// not treat as an error. We do this to mimic
// the behaviour of bitcoind, which will not
// return an error if a transaction in the
// mempool is sent again using the
// sendrawtransaction RPC call.
return nil
}
if strings.Contains(err.Error(), "already exists") {
// Transaction was already mined, we don't
// consider this an error.
return nil
}
if strings.Contains(err.Error(), "already spent") {
// Output was already spent.
return lnwallet.ErrDoubleSpend
}
if strings.Contains(err.Error(), "orphan transaction") {
// Transaction is spending either output that
// is missing or already spent.
return lnwallet.ErrDoubleSpend
}
case *chain.BitcoindClient:
if strings.Contains(err.Error(), "txn-already-in-mempool") {
// Transaction in mempool, treat as non-error.
return nil
}
if strings.Contains(err.Error(), "txn-already-known") {
// Transaction in mempool, treat as non-error.
return nil
}
if strings.Contains(err.Error(), "already in block") {
// Transaction was already mined, we don't
// consider this an error.
return nil
}
if strings.Contains(err.Error(), "txn-mempool-conflict") {
// Output was spent by other transaction
// already in the mempool.
return lnwallet.ErrDoubleSpend
}
if strings.Contains(err.Error(), "insufficient fee") {
// RBF enabled transaction did not have enough fee.
return lnwallet.ErrDoubleSpend
}
if strings.Contains(err.Error(), "Missing inputs") {
// Transaction is spending either output that
// is missing or already spent.
return lnwallet.ErrDoubleSpend
}
case *chain.NeutrinoClient:
if strings.Contains(err.Error(), "already have") {
// Transaction was already in the mempool, do
// not treat as an error.
return nil
}
if strings.Contains(err.Error(), "already exists") {
// Transaction was already mined, we don't
// consider this an error.
return nil
}
if strings.Contains(err.Error(), "already spent") {
// Output was already spent.
return lnwallet.ErrDoubleSpend
}
default:
}
return err
}
return nil
}
// extractBalanceDelta extracts the net balance delta from the PoV of the