wallet: check RPC error code for rejected confirmed transactions
This unifies the logic of receiving an error when broadcasting a confirmed transaction through btcd's/bitcoind's RPC interface. The btcd dependency update is required in order for it to match bitcoind's behavior. For older nodes that have yet to update, the confirmed transaction will still be caught by the "transaction already exists" case. This is not needed for bitcoind however, because its been sending the same RPC error code for several major releases now.
This commit is contained in:
parent
0efe836773
commit
bf9cc20045
3 changed files with 30 additions and 13 deletions
4
go.mod
4
go.mod
|
@ -1,9 +1,9 @@
|
||||||
module github.com/btcsuite/btcwallet
|
module github.com/btcsuite/btcwallet
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32
|
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c
|
||||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
|
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
|
||||||
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d
|
||||||
github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8
|
github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8
|
||||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792
|
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792
|
||||||
github.com/coreos/bbolt v1.3.2
|
github.com/coreos/bbolt v1.3.2
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -4,14 +4,17 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA
|
||||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||||
github.com/btcsuite/btcd v0.0.0-20180823030728-d81d8877b8f3/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
github.com/btcsuite/btcd v0.0.0-20180823030728-d81d8877b8f3/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
||||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78=
|
|
||||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||||
|
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q=
|
||||||
|
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
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/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||||
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE=
|
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE=
|
||||||
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||||
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 h1:j3AgPKKZtZStM2nyhrDSLSYgT7YHrZKdSkq1OYeLjvM=
|
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 h1:j3AgPKKZtZStM2nyhrDSLSYgT7YHrZKdSkq1OYeLjvM=
|
||||||
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||||
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
|
||||||
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||||
github.com/btcsuite/btcwallet v0.0.0-20180904010540-284e2e0e696e33d5be388f7f3d9a26db703e0c06/go.mod h1:/d7QHZsfUAruXuBhyPITqoYOmJ+nq35qPsJjz/aSpCg=
|
github.com/btcsuite/btcwallet v0.0.0-20180904010540-284e2e0e696e33d5be388f7f3d9a26db703e0c06/go.mod h1:/d7QHZsfUAruXuBhyPITqoYOmJ+nq35qPsJjz/aSpCg=
|
||||||
github.com/btcsuite/btcwallet v0.0.0-20190313032608-acf3b04b0273/go.mod h1:mkOYY8/psBiL5E+Wb0V7M0o+N7NXi2SZJz6+RKkncIc=
|
github.com/btcsuite/btcwallet v0.0.0-20190313032608-acf3b04b0273/go.mod h1:mkOYY8/psBiL5E+Wb0V7M0o+N7NXi2SZJz6+RKkncIc=
|
||||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
|
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
|
||||||
|
|
|
@ -3414,6 +3414,14 @@ func (w *Wallet) publishTransaction(tx *wire.MsgTx) (*chainhash.Hash, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
txid, err := chainClient.SendRawTransaction(tx, false)
|
txid, err := chainClient.SendRawTransaction(tx, false)
|
||||||
|
|
||||||
|
// Determine if this was an RPC error thrown due to the transaction
|
||||||
|
// already confirming.
|
||||||
|
var rpcTxConfirmed bool
|
||||||
|
if rpcErr, ok := err.(*btcjson.RPCError); ok {
|
||||||
|
rpcTxConfirmed = rpcErr.Code == btcjson.ErrRPCTxAlreadyInChain
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
return txid, nil
|
return txid, nil
|
||||||
|
@ -3425,12 +3433,16 @@ func (w *Wallet) publishTransaction(tx *wire.MsgTx) (*chainhash.Hash, error) {
|
||||||
//
|
//
|
||||||
// This error is returned when broadcasting/sending a transaction to a
|
// This error is returned when broadcasting/sending a transaction to a
|
||||||
// btcd node that already has it in their mempool.
|
// btcd node that already has it in their mempool.
|
||||||
case strings.Contains(err.Error(), "already have transaction"):
|
case strings.Contains(
|
||||||
|
strings.ToLower(err.Error()), "already have transaction",
|
||||||
|
):
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
// This error is returned when broadcasting a transaction to a bitcoind
|
// This error is returned when broadcasting a transaction to a bitcoind
|
||||||
// node that already has it in their mempool.
|
// node that already has it in their mempool.
|
||||||
case strings.Contains(err.Error(), "txn-already-in-mempool"):
|
case strings.Contains(
|
||||||
|
strings.ToLower(err.Error()), "txn-already-in-mempool",
|
||||||
|
):
|
||||||
return txid, nil
|
return txid, nil
|
||||||
|
|
||||||
// If the transaction has already confirmed, we can safely remove it
|
// If the transaction has already confirmed, we can safely remove it
|
||||||
|
@ -3438,19 +3450,21 @@ func (w *Wallet) publishTransaction(tx *wire.MsgTx) (*chainhash.Hash, error) {
|
||||||
// confirmed store. We'll avoid returning an error as the broadcast was
|
// confirmed store. We'll avoid returning an error as the broadcast was
|
||||||
// in a sense successful.
|
// in a sense successful.
|
||||||
//
|
//
|
||||||
// This error is returned when broadcasting/sending a transaction that
|
// This error is returned when sending a transaction that has already
|
||||||
// has already confirmed to a btcd node.
|
// confirmed to a btcd/bitcoind node over RPC.
|
||||||
case strings.Contains(err.Error(), "transaction already exists"):
|
case rpcTxConfirmed:
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
// This error is returned when broadcasting a transaction that has
|
// This error is returned when broadcasting a transaction that has
|
||||||
// already confirmed to a bitcoind node.
|
// already confirmed to a btcd node over the P2P network.
|
||||||
case strings.Contains(err.Error(), "txn-already-known"):
|
case strings.Contains(
|
||||||
|
strings.ToLower(err.Error()), "transaction already exists",
|
||||||
|
):
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
// This error is returned when sending a transaction that has already
|
// This error is returned when broadcasting a transaction that has
|
||||||
// confirmed to a bitcoind node over RPC.
|
// already confirmed to a bitcoind node over the P2P network.
|
||||||
case strings.Contains(err.Error(), "transaction already in block chain"):
|
case strings.Contains(strings.ToLower(err.Error()), "txn-already-known"):
|
||||||
dbErr := walletdb.Update(w.db, func(dbTx walletdb.ReadWriteTx) error {
|
dbErr := walletdb.Update(w.db, func(dbTx walletdb.ReadWriteTx) error {
|
||||||
txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey)
|
txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey)
|
||||||
txRec, err := wtxmgr.NewTxRecordFromMsgTx(tx, time.Now())
|
txRec, err := wtxmgr.NewTxRecordFromMsgTx(tx, time.Now())
|
||||||
|
|
Loading…
Reference in a new issue