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

View file

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

View file

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