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,
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 (
continue
}
+ //hand update the transaction input utxos
inputUtxos := txInToUtxos(tx, statusFail)
for _, inputUtxo := range inputUtxos {
if segwit.IsP2WScript(inputUtxo.ControlProgram) {
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 {
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
+ }
}
}