X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=account%2Futxo_keeper.go;h=d00d0f39e28a2ed5aa060313455369371cc010b9;hp=e9e486f2255fdf59b03ad3e6d952cdb5a2816eb9;hb=7a6ac7a3ec28e9238fe2e4726913ca0f165338be;hpb=08281341c2cb02ba11d4218576256688854790fc diff --git a/account/utxo_keeper.go b/account/utxo_keeper.go index e9e486f2..d00d0f39 100644 --- a/account/utxo_keeper.go +++ b/account/utxo_keeper.go @@ -143,6 +143,39 @@ func (uk *utxoKeeper) Reserve(accountID string, assetID *bc.AssetID, amount uint return result, nil } +func (uk *utxoKeeper) ReserveByAddress(address string, assetID *bc.AssetID, amount uint64, useUnconfirmed bool, isReserved bool) (*reservation, error) { + uk.mtx.Lock() + defer uk.mtx.Unlock() + + utxos, immatureAmount := uk.findUtxosByAddress(address, assetID, useUnconfirmed) + optUtxos, optAmount, reservedAmount := uk.optUTXOs(utxos, amount) + if optAmount+reservedAmount+immatureAmount < amount { + return nil, ErrInsufficient + } + if optAmount+reservedAmount < amount { + return nil, ErrImmature + } + + if optAmount < amount { + return nil, ErrReserved + } + + result := &reservation{ + id: atomic.AddUint64(&uk.nextIndex, 1), + utxos: optUtxos, + change: optAmount - amount, + } + + uk.reservations[result.id] = result + if isReserved { + for _, u := range optUtxos { + uk.reserved[u.OutputID] = result.id + } + } + + return result, nil +} + func (uk *utxoKeeper) ReserveParticular(outHash bc.Hash, useUnconfirmed bool, exp time.Time) (*reservation, error) { uk.mtx.Lock() defer uk.mtx.Unlock() @@ -234,6 +267,41 @@ func (uk *utxoKeeper) findUtxos(accountID string, assetID *bc.AssetID, useUnconf return utxos, immatureAmount } +func (uk *utxoKeeper) findUtxosByAddress(address string, assetID *bc.AssetID, useUnconfirmed bool) ([]*UTXO, uint64) { + immatureAmount := uint64(0) + currentHeight := uk.currentHeight() + utxos := []*UTXO{} + appendUtxo := func(u *UTXO) { + if u.Address != address || u.AssetID != *assetID { + return + } + if u.ValidHeight > currentHeight { + immatureAmount += u.Amount + } else { + utxos = append(utxos, u) + } + } + + utxoIter := uk.db.IteratorPrefix([]byte(UTXOPreFix)) + defer utxoIter.Release() + for utxoIter.Next() { + u := &UTXO{} + if err := json.Unmarshal(utxoIter.Value(), u); err != nil { + log.WithField("err", err).Error("utxoKeeper findUtxos fail on unmarshal utxo") + continue + } + appendUtxo(u) + } + if !useUnconfirmed { + return utxos, immatureAmount + } + + for _, u := range uk.unconfirmed { + appendUtxo(u) + } + return utxos, immatureAmount +} + func (uk *utxoKeeper) findUtxo(outHash bc.Hash, useUnconfirmed bool) (*UTXO, error) { if u, ok := uk.unconfirmed[outHash]; useUnconfirmed && ok { return u, nil