OSDN Git Service

fix bug for wrong utxo balance on wallet model (#1285)
authorPaladz <yzhu101@uottawa.ca>
Tue, 28 Aug 2018 02:24:25 +0000 (10:24 +0800)
committerGitHub <noreply@github.com>
Tue, 28 Aug 2018 02:24:25 +0000 (10:24 +0800)
* fix bug for wrong utxo balance on wallet model

* clean the code

* detach utxo should in the reverse order

* fix the code format

* clear teh error message

blockchain/txbuilder/finalize.go
wallet/utxo.go

index 83ce4c7..96eb896 100644 (file)
@@ -17,6 +17,8 @@ var (
        ErrMissingRawTx = errors.New("missing raw tx")
        // ErrBadInstructionCount means too many signing instructions compare with inputs
        ErrBadInstructionCount = errors.New("too many signing instructions in template")
+       // ErrOrphanTx means submit transaction is orphan
+       ErrOrphanTx = errors.New("finalize can't find transaction input utxo")
 )
 
 // FinalizeTx validates a transaction signature template,
@@ -35,15 +37,17 @@ func FinalizeTx(ctx context.Context, c *protocol.Chain, tx *types.Tx) error {
        tx.TxData.SerializedSize = uint64(len(data))
        tx.Tx.SerializedSize = uint64(len(data))
 
-       _, err = c.ValidateTx(tx)
+       isOrphan, err := c.ValidateTx(tx)
        if errors.Root(err) == protocol.ErrBadTx {
                return errors.Sub(ErrRejected, err)
        }
        if err != nil {
                return errors.WithDetail(err, "tx rejected: "+err.Error())
        }
-
-       return errors.Wrap(err)
+       if isOrphan {
+               return ErrOrphanTx
+       }
+       return nil
 }
 
 var (
index a07808e..42acd90 100644 (file)
@@ -50,6 +50,7 @@ func (w *Wallet) attachUtxos(batch db.Batch, b *types.Block, txStatus *bc.Transa
                        continue
                }
 
+               //hand update the transaction input utxos
                inputUtxos := txInToUtxos(tx, statusFail)
                for _, inputUtxo := range inputUtxos {
                        if segwit.IsP2WScript(inputUtxo.ControlProgram) {
@@ -58,50 +59,23 @@ func (w *Wallet) attachUtxos(batch db.Batch, b *types.Block, txStatus *bc.Transa
                                batch.Delete(account.ContractUTXOKey(inputUtxo.OutputID))
                        }
                }
-       }
-
-       utxos := []*account.UTXO{}
-       for txIndex, tx := range b.Transactions {
-               statusFail, err := txStatus.GetStatus(txIndex)
-               if err != nil {
-                       log.WithField("err", err).Error("attachUtxos fail on get txStatus")
-                       continue
-               }
 
+               //hand update the transaction output utxos
                validHeight := uint64(0)
                if txIndex == 0 {
                        validHeight = b.Height + consensus.CoinbasePendingBlockNumber
                }
                outputUtxos := txOutToUtxos(tx, statusFail, validHeight)
-               utxos = append(utxos, outputUtxos...)
-       }
-
-       utxos = w.filterAccountUtxo(utxos)
-       if err := batchSaveUtxos(utxos, batch); err != nil {
-               log.WithField("err", err).Error("attachUtxos fail on batchSaveUtxos")
+               utxos := w.filterAccountUtxo(outputUtxos)
+               if err := batchSaveUtxos(utxos, batch); err != nil {
+                       log.WithField("err", err).Error("attachUtxos fail on batchSaveUtxos")
+               }
        }
 }
 
 func (w *Wallet) detachUtxos(batch db.Batch, b *types.Block, txStatus *bc.TransactionStatus) {
-       utxos := []*account.UTXO{}
-       for txIndex, tx := range b.Transactions {
-               statusFail, err := txStatus.GetStatus(txIndex)
-               if err != nil {
-                       log.WithField("err", err).Error("detachUtxos fail on get tx status")
-                       continue
-               }
-
-               inputUtxos := txInToUtxos(tx, statusFail)
-               utxos = append(utxos, inputUtxos...)
-       }
-
-       utxos = w.filterAccountUtxo(utxos)
-       if err := batchSaveUtxos(utxos, batch); err != nil {
-               log.WithField("err", err).Error("detachUtxos fail on batchSaveUtxos")
-               return
-       }
-
-       for _, tx := range b.Transactions {
+       for txIndex := len(b.Transactions) - 1; txIndex >= 0; txIndex-- {
+               tx := b.Transactions[txIndex]
                for j := range tx.Outputs {
                        resOut, err := tx.Output(*tx.ResultIds[j])
                        if err != nil {
@@ -114,6 +88,19 @@ func (w *Wallet) detachUtxos(batch db.Batch, b *types.Block, txStatus *bc.Transa
                                batch.Delete(account.ContractUTXOKey(*tx.ResultIds[j]))
                        }
                }
+
+               statusFail, err := txStatus.GetStatus(txIndex)
+               if err != nil {
+                       log.WithField("err", err).Error("detachUtxos fail on get tx status")
+                       continue
+               }
+
+               inputUtxos := txInToUtxos(tx, statusFail)
+               utxos := w.filterAccountUtxo(inputUtxos)
+               if err := batchSaveUtxos(utxos, batch); err != nil {
+                       log.WithField("err", err).Error("detachUtxos fail on batchSaveUtxos")
+                       return
+               }
        }
 }