Protect the relay fee field with a mutex.

This prevents races when setting a new relay fee through the legacy
RPC server (settxfee).

Fixes #379.
This commit is contained in:
Josh Rickmar 2016-03-09 09:56:32 -05:00
parent 397beadfd5
commit d09c2a84c1
3 changed files with 25 additions and 8 deletions

View file

@ -512,7 +512,7 @@ func GetInfo(icmd interface{}, w *wallet.Wallet, chainClient *chain.RPCClient) (
// to using the manager version.
info.WalletVersion = int32(waddrmgr.LatestMgrVersion)
info.Balance = bal.ToBTC()
info.PaytxFee = w.RelayFee.ToBTC()
info.PaytxFee = w.RelayFee().ToBTC()
// We don't set the following since they don't make much sense in the
// wallet architecture:
// - unlocked_until
@ -1572,11 +1572,11 @@ func SetTxFee(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
return nil, ErrNeedPositiveAmount
}
incr, err := btcutil.NewAmount(cmd.Amount)
relayFee, err := btcutil.NewAmount(cmd.Amount)
if err != nil {
return nil, err
}
w.RelayFee = incr
w.SetRelayFee(relayFee)
// A boolean true result is returned upon success.
return true, nil

View file

@ -134,7 +134,7 @@ func (w *Wallet) txToOutputs(outputs []*wire.TxOut, account uint32, minconf int3
}
return txscript.PayToAddrScript(changeAddr)
}
tx, err := txauthor.NewUnsignedTransaction(outputs, w.RelayFee,
tx, err := txauthor.NewUnsignedTransaction(outputs, w.RelayFee(),
inputSource, changeSource)
if err != nil {
return nil, err

View file

@ -75,8 +75,8 @@ type Wallet struct {
chainClientSyncMtx sync.Mutex
lockedOutpoints map[wire.OutPoint]struct{}
RelayFee btcutil.Amount
DisallowFree bool
relayFee btcutil.Amount
relayFeeMu sync.Mutex
// Channels for rescan processing. Requests are added and merged with
// any waiting requests, before being sent to another goroutine to
@ -357,6 +357,23 @@ func (w *Wallet) ChainClient() *chain.RPCClient {
return chainClient
}
// RelayFee returns the current minimum relay fee (per kB of serialized
// transaction) used when constructing transactions.
func (w *Wallet) RelayFee() btcutil.Amount {
w.relayFeeMu.Lock()
relayFee := w.relayFee
w.relayFeeMu.Unlock()
return relayFee
}
// SetRelayFee sets a new minimum relay fee (per kB of serialized
// transaction) used when constructing transactions.
func (w *Wallet) SetRelayFee(relayFee btcutil.Amount) {
w.relayFeeMu.Lock()
w.relayFee = relayFee
w.relayFeeMu.Unlock()
}
// quitChan atomically reads the quit channel.
func (w *Wallet) quitChan() <-chan struct{} {
w.quitMu.Lock()
@ -2009,7 +2026,7 @@ func (w *Wallet) SendOutputs(outputs []*wire.TxOut, account uint32,
}
for _, output := range outputs {
err = txrules.CheckOutput(output, w.RelayFee)
err = txrules.CheckOutput(output, w.RelayFee())
if err != nil {
return nil, err
}
@ -2230,7 +2247,7 @@ func Open(pubPass []byte, params *chaincfg.Params, db walletdb.DB, waddrmgrNS, w
Manager: addrMgr,
TxStore: txMgr,
lockedOutpoints: map[wire.OutPoint]struct{}{},
RelayFee: txrules.DefaultRelayFeePerKb,
relayFee: txrules.DefaultRelayFeePerKb,
rescanAddJob: make(chan *RescanJob),
rescanBatch: make(chan *rescanBatch),
rescanNotifications: make(chan interface{}),