diff --git a/account.go b/account.go index 57b944e..96958d0 100644 --- a/account.go +++ b/account.go @@ -142,7 +142,7 @@ func (a *Account) CalculateAddressBalance(addr btcutil.Address, confirms int) fl return 0. } for _, credit := range unspent { - if confirmed(confirms, credit.BlockHeight, bs.Height) { + if credit.Confirmed(confirms, bs.Height) { // We only care about the case where len(addrs) == 1, and err // will never be non-nil in that case _, addrs, _, _ := credit.Addresses(cfg.Net()) @@ -188,7 +188,7 @@ func (a *Account) ListSinceBlock(since, curBlockHeight int32, // Transactions that have not met minconf confirmations are to // be ignored. - if !confirmed(minconf, txRecord.BlockHeight, curBlockHeight) { + if !txRecord.Confirmed(minconf, curBlockHeight) { continue } @@ -681,7 +681,7 @@ func (a *Account) TotalReceived(confirms int) (float64, error) { } // Tally if the appropiate number of block confirmations have passed. - if confirmed(confirms, c.BlockHeight, bs.Height) { + if c.Confirmed(confirms, bs.Height) { amount += c.Amount() } } @@ -689,21 +689,3 @@ func (a *Account) TotalReceived(confirms int) (float64, error) { return amount.ToUnit(btcutil.AmountBTC), nil } - -// confirmed checks whether a transaction at height txHeight has met -// minconf confirmations for a blockchain at height curHeight. -func confirmed(minconf int, txHeight, curHeight int32) bool { - return confirms(txHeight, curHeight) >= int32(minconf) -} - -// confirms returns the number of confirmations for a transaction in a -// block at height txHeight (or -1 for an unconfirmed tx) given the chain -// height curHeight. -func confirms(txHeight, curHeight int32) int32 { - switch { - case txHeight == -1, txHeight > curHeight: - return 0 - default: - return curHeight - txHeight + 1 - } -} diff --git a/acctmgr.go b/acctmgr.go index ea4288f..9e1d73b 100644 --- a/acctmgr.go +++ b/acctmgr.go @@ -810,9 +810,8 @@ func (am *AccountManager) ListUnspent(minconf, maxconf int, return nil, err } for _, credit := range unspent { - confs := confirms(credit.BlockHeight, bs.Height) - switch { - case int(confs) < minconf, int(confs) > maxconf: + confs := credit.Confirmations(bs.Height) + if int(confs) < minconf || int(confs) > maxconf { continue } diff --git a/createtx.go b/createtx.go index 4dc8249..f947291 100644 --- a/createtx.go +++ b/createtx.go @@ -89,7 +89,7 @@ func (u ByAmount) Swap(i, j int) { // is the total number of satoshis which would be spent by the combination // of all selected previous outputs. err will equal ErrInsufficientFunds if there // are not enough unspent outputs to spend amt. -func selectInputs(utxos []*tx.Credit, amt btcutil.Amount, +func selectInputs(credits []*tx.Credit, amt btcutil.Amount, minconf int) (selected []*tx.Credit, out btcutil.Amount, err error) { bs, err := GetCurBlock() @@ -100,18 +100,18 @@ func selectInputs(utxos []*tx.Credit, amt btcutil.Amount, // Create list of eligible unspent previous outputs to use as tx // inputs, and sort by the amount in reverse order so a minimum number // of inputs is needed. - eligible := make([]*tx.Credit, 0, len(utxos)) - for _, utxo := range utxos { - if confirmed(minconf, utxo.BlockHeight, bs.Height) { + eligible := make([]*tx.Credit, 0, len(credits)) + for _, c := range credits { + if c.Confirmed(minconf, bs.Height) { // Coinbase transactions must have have reached maturity // before their outputs may be spent. - if utxo.IsCoinbase() { - confs := confirms(utxo.BlockHeight, bs.Height) - if confs < btcchain.CoinbaseMaturity { + if c.IsCoinbase() { + target := btcchain.CoinbaseMaturity + if !c.Confirmed(target, bs.Height) { continue } } - eligible = append(eligible, utxo) + eligible = append(eligible, c) } } sort.Sort(sort.Reverse(ByAmount(eligible))) diff --git a/rpcserver.go b/rpcserver.go index 8f0b260..855ad0f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1057,7 +1057,7 @@ func GetTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) { ret.BlockIndex = int64(first.Tx.Tx().Index()) ret.BlockHash = txBlock.Hash.String() ret.BlockTime = txBlock.Time.Unix() - ret.Confirmations = int64(confirms(txr.BlockHeight, bs.Height)) + ret.Confirmations = int64(txr.Confirmations(bs.Height)) } // TODO(oga) if the tx is a coinbase we should set "generated" to true. // Since we do not mine this currently is never the case. diff --git a/tx/json.go b/tx/json.go index 90abece..93a65fd 100644 --- a/tx/json.go +++ b/tx/json.go @@ -17,6 +17,7 @@ package tx import ( + "github.com/conformal/btcchain" "github.com/conformal/btcjson" "github.com/conformal/btcscript" "github.com/conformal/btcutil" @@ -81,7 +82,7 @@ func (d *Debits) ToJSON(account string, chainHeight int32, result.BlockHash = b.Hash.String() result.BlockIndex = int64(d.Tx().Index()) result.BlockTime = b.Time.Unix() - result.Confirmations = int64(confirms(b.Height, chainHeight)) + result.Confirmations = int64(d.Confirmations(chainHeight)) } reply = append(reply, result) } @@ -103,9 +104,21 @@ func (c *Credit) ToJSON(account string, chainHeight int32, address = addrs[0].EncodeAddress() } + var category string + switch { + case c.IsCoinbase(): + if c.Confirmed(btcchain.CoinbaseMaturity, chainHeight) { + category = "generate" + } else { + category = "immature" + } + default: + category = "receive" + } + result := btcjson.ListTransactionsResult{ Account: account, - Category: "receive", + Category: category, Address: address, Amount: btcutil.Amount(txout.Value).ToUnit(btcutil.AmountBTC), TxID: c.Tx().Sha().String(), @@ -122,7 +135,7 @@ func (c *Credit) ToJSON(account string, chainHeight int32, result.BlockHash = b.Hash.String() result.BlockIndex = int64(c.Tx().Index()) result.BlockTime = b.Time.Unix() - result.Confirmations = int64(confirms(b.Height, chainHeight)) + result.Confirmations = int64(c.Confirmations(chainHeight)) } return result, nil diff --git a/tx/tx.go b/tx/tx.go index c8c33c3..84abc95 100644 --- a/tx/tx.go +++ b/tx/tx.go @@ -1297,6 +1297,18 @@ func (c *Credit) Change() bool { return c.txRecord.credits[c.OutputIndex].change } +// Confirmed returns whether a transaction has reached some target number of +// confirmations, given the current best chain height. +func (t *TxRecord) Confirmed(target int, chainHeight int32) bool { + return confirmed(target, t.BlockHeight, chainHeight) +} + +// Confirmations returns the total number of confirmations a transaction has +// reached, given the current best chain height. +func (t *TxRecord) Confirmations(chainHeight int32) int32 { + return confirms(t.BlockHeight, chainHeight) +} + // IsCoinbase returns whether the transaction is a coinbase. func (t *TxRecord) IsCoinbase() bool { return t.BlockHeight != -1 && t.BlockIndex == 0