X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=wallet%2Futxo.go;h=1eec505fb80aac14e195f8fb7b01bfe0785e140b;hp=7316623fdc7de568580d9842ad8251d625bb55f4;hb=73164af54a2587ba479b8b133274e3ecd0559a68;hpb=a8fcbab90cbbfcc0acea0a4bd1389e39ece3da56 diff --git a/wallet/utxo.go b/wallet/utxo.go index 7316623f..1eec505f 100644 --- a/wallet/utxo.go +++ b/wallet/utxo.go @@ -16,7 +16,7 @@ import ( ) // GetAccountUtxos return all account unspent outputs -func (w *Wallet) GetAccountUtxos(accountID string, id string, unconfirmed, isSmartContract bool) []*account.UTXO { +func (w *Wallet) GetAccountUtxos(accountID string, id string, unconfirmed, isSmartContract bool, vote bool) []*account.UTXO { prefix := account.UTXOPreFix if isSmartContract { prefix = account.SUTXOPrefix @@ -37,6 +37,10 @@ func (w *Wallet) GetAccountUtxos(accountID string, id string, unconfirmed, isSma continue } + if vote && accountUtxo.Vote == nil { + continue + } + if accountID == accountUtxo.AccountID || accountID == "" { accountUtxos = append(accountUtxos, accountUtxo) } @@ -63,11 +67,7 @@ func (w *Wallet) attachUtxos(batch dbm.Batch, b *types.Block, txStatus *bc.Trans } //hand update the transaction output utxos - validHeight := uint64(0) - if txIndex == 0 { - validHeight = b.Height + consensus.CoinbasePendingBlockNumber - } - outputUtxos := txOutToUtxos(tx, statusFail, validHeight) + outputUtxos := txOutToUtxos(tx, statusFail, b.Height) utxos := w.filterAccountUtxo(outputUtxos) if err := batchSaveUtxos(utxos, batch); err != nil { log.WithFields(log.Fields{"module": logModule, "err": err}).Error("attachUtxos fail on batchSaveUtxos") @@ -79,12 +79,20 @@ func (w *Wallet) detachUtxos(batch dbm.Batch, b *types.Block, txStatus *bc.Trans for txIndex := len(b.Transactions) - 1; txIndex >= 0; txIndex-- { tx := b.Transactions[txIndex] for j := range tx.Outputs { - resOut, err := tx.IntraChainOutput(*tx.ResultIds[j]) - if err != nil { + code := []byte{} + switch resOut := tx.Entries[*tx.ResultIds[j]].(type) { + case *bc.IntraChainOutput: + if resOut.Source.Value.Amount == uint64(0) { + continue + } + code = resOut.ControlProgram.Code + case *bc.VoteOutput: + code = resOut.ControlProgram.Code + default: continue } - if segwit.IsP2WScript(resOut.ControlProgram.Code) { + if segwit.IsP2WScript(code) { batch.Delete(account.StandardUTXOKey(*tx.ResultIds[j])) } else { batch.Delete(account.ContractUTXOKey(*tx.ResultIds[j])) @@ -165,54 +173,113 @@ func batchSaveUtxos(utxos []*account.UTXO, batch dbm.Batch) error { func txInToUtxos(tx *types.Tx, statusFail bool) []*account.UTXO { utxos := []*account.UTXO{} for _, inpID := range tx.Tx.InputIDs { - sp, err := tx.Spend(inpID) - if err != nil { - continue - } - resOut, err := tx.IntraChainOutput(*sp.SpentOutputId) + e, err := tx.Entry(inpID) if err != nil { - log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get resOut") continue } - - if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID { + utxo := &account.UTXO{} + switch inp := e.(type) { + case *bc.Spend: + resOut, err := tx.IntraChainOutput(*inp.SpentOutputId) + if err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get resOut for spedn") + continue + } + if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID { + continue + } + utxo = &account.UTXO{ + OutputID: *inp.SpentOutputId, + AssetID: *resOut.Source.Value.AssetId, + Amount: resOut.Source.Value.Amount, + ControlProgram: resOut.ControlProgram.Code, + SourceID: *resOut.Source.Ref, + SourcePos: resOut.Source.Position, + } + case *bc.VetoInput: + resOut, err := tx.VoteOutput(*inp.SpentOutputId) + if err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get resOut for vetoInput") + continue + } + if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID { + continue + } + utxo = &account.UTXO{ + OutputID: *inp.SpentOutputId, + AssetID: *resOut.Source.Value.AssetId, + Amount: resOut.Source.Value.Amount, + ControlProgram: resOut.ControlProgram.Code, + SourceID: *resOut.Source.Ref, + SourcePos: resOut.Source.Position, + Vote: resOut.Vote, + } + default: continue } - - utxos = append(utxos, &account.UTXO{ - OutputID: *sp.SpentOutputId, - AssetID: *resOut.Source.Value.AssetId, - Amount: resOut.Source.Value.Amount, - ControlProgram: resOut.ControlProgram.Code, - SourceID: *resOut.Source.Ref, - SourcePos: resOut.Source.Position, - }) + utxos = append(utxos, utxo) } return utxos } -func txOutToUtxos(tx *types.Tx, statusFail bool, vaildHeight uint64) []*account.UTXO { +func txOutToUtxos(tx *types.Tx, statusFail bool, blockHeight uint64) []*account.UTXO { + validHeight := uint64(0) + if tx.Inputs[0].InputType() == types.CoinbaseInputType { + validHeight = blockHeight + consensus.ActiveNetParams.CoinbasePendingBlockNumber + } + utxos := []*account.UTXO{} for i, out := range tx.Outputs { - bcOut, err := tx.IntraChainOutput(*tx.ResultIds[i]) + entryOutput, err := tx.Entry(*tx.ResultIds[i]) if err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txOutToUtxos fail on get entryOutput") continue } - if statusFail && *out.AssetAmount().AssetId != *consensus.BTMAssetID { + utxo := &account.UTXO{} + switch bcOut := entryOutput.(type) { + case *bc.IntraChainOutput: + if (statusFail && *out.AssetAmount().AssetId != *consensus.BTMAssetID) || out.AssetAmount().Amount == uint64(0) { + continue + } + utxo = &account.UTXO{ + OutputID: *tx.OutputID(i), + AssetID: *out.AssetAmount().AssetId, + Amount: out.AssetAmount().Amount, + ControlProgram: out.ControlProgram(), + SourceID: *bcOut.Source.Ref, + SourcePos: bcOut.Source.Position, + ValidHeight: validHeight, + } + + case *bc.VoteOutput: + if statusFail && *out.AssetAmount().AssetId != *consensus.BTMAssetID { + continue + } + + voteValidHeight := blockHeight + consensus.ActiveNetParams.VotePendingBlockNumber + if validHeight < voteValidHeight { + validHeight = voteValidHeight + } + + utxo = &account.UTXO{ + OutputID: *tx.OutputID(i), + AssetID: *out.AssetAmount().AssetId, + Amount: out.AssetAmount().Amount, + ControlProgram: out.ControlProgram(), + SourceID: *bcOut.Source.Ref, + SourcePos: bcOut.Source.Position, + ValidHeight: validHeight, + Vote: bcOut.Vote, + } + + default: + log.WithFields(log.Fields{"module": logModule}).Warn("txOutToUtxos fail on get bcOut") continue } - utxos = append(utxos, &account.UTXO{ - OutputID: *tx.OutputID(i), - AssetID: *out.AssetAmount().AssetId, - Amount: out.AssetAmount().Amount, - ControlProgram: out.ControlProgram(), - SourceID: *bcOut.Source.Ref, - SourcePos: bcOut.Source.Position, - ValidHeight: vaildHeight, - }) + utxos = append(utxos, utxo) } return utxos }