X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;ds=inline;f=protocol%2Fstate%2Futxo_view.go;h=c8071444f9e1afaba545a63c226c9a3564cbd7a0;hb=6f7fe6fd7442ddcec8ee959c09b6d45639ef045f;hp=d10517835f4abdd2f3e9f7214ca3ec4e70f7b1c5;hpb=5d1c9664ba4d870ccabfd995766487e99d1cf1b5;p=bytom%2Fvapor.git diff --git a/protocol/state/utxo_view.go b/protocol/state/utxo_view.go index d1051783..c8071444 100644 --- a/protocol/state/utxo_view.go +++ b/protocol/state/utxo_view.go @@ -20,6 +20,24 @@ func NewUtxoViewpoint() *UtxoViewpoint { } func (view *UtxoViewpoint) ApplyTransaction(block *bc.Block, tx *bc.Tx, statusFail bool) error { + for _, prevout := range tx.MainchainOutputIDs { + entry, ok := view.Entries[prevout] + if !ok { + return errors.New("fail to find mainchain output entry") + } + + if entry.Type != storage.CrosschainUTXOType { + return errors.New("look up mainchainOutputID but find utxo not from mainchain") + } + + if entry.Spent { + return errors.New("mainchain output has been spent") + } + + entry.BlockHeight = block.Height + entry.SpendOutput() + } + for _, prevout := range tx.SpentOutputIDs { assetID := bc.AssetID{} entryOutput, err := tx.Entry(prevout) @@ -44,10 +62,13 @@ func (view *UtxoViewpoint) ApplyTransaction(block *bc.Block, tx *bc.Tx, statusFa if !ok { return errors.New("fail to find utxo entry") } + if entry.Type == storage.CrosschainUTXOType { + return errors.New("look up spentOutputID but find utxo from mainchain") + } if entry.Spent { return errors.New("utxo has been spent") } - if entry.IsCoinBase && entry.BlockHeight+consensus.CoinbasePendingBlockNumber > block.Height { + if (entry.Type == storage.CoinbaseUTXOType) && ((entry.BlockHeight + consensus.CoinbasePendingBlockNumber) > block.Height) { return errors.New("coinbase utxo is not ready for use") } entry.SpendOutput() @@ -74,11 +95,11 @@ func (view *UtxoViewpoint) ApplyTransaction(block *bc.Block, tx *bc.Tx, statusFa continue } - isCoinbase := false + utxoType := storage.NormalUTXOType if block != nil && len(block.Transactions) > 0 && block.Transactions[0].ID == tx.ID { - isCoinbase = true + utxoType = storage.CoinbaseUTXOType } - view.Entries[*id] = storage.NewUtxoEntry(isCoinbase, block.Height, false) + view.Entries[*id] = storage.NewUtxoEntry(utxoType, block.Height, false) } return nil } @@ -102,6 +123,24 @@ func (view *UtxoViewpoint) CanSpend(hash *bc.Hash) bool { } func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error { + for _, prevout := range tx.MainchainOutputIDs { + // don't simply delete(view.Entries, prevout), because we need to delete from db in saveUtxoView() + entry, ok := view.Entries[prevout] + if ok && (entry.Type != storage.CrosschainUTXOType) { + return errors.New("look up mainchainOutputID but find utxo not from mainchain") + } + + if ok && !entry.Spent { + return errors.New("try to revert an unspent utxo") + } + + if !ok { + view.Entries[prevout] = storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, false) + continue + } + entry.UnspendOutput() + } + for _, prevout := range tx.SpentOutputIDs { assetID := bc.AssetID{} entryOutput, err := tx.Entry(prevout) @@ -123,11 +162,16 @@ func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error { } entry, ok := view.Entries[prevout] + if ok && (entry.Type == storage.CrosschainUTXOType) { + return errors.New("look up SpentOutputIDs but find mainchain utxo") + } + if ok && !entry.Spent { return errors.New("try to revert an unspent utxo") } + if !ok { - view.Entries[prevout] = storage.NewUtxoEntry(false, 0, false) + view.Entries[prevout] = storage.NewUtxoEntry(storage.NormalUTXOType, 0, false) continue } entry.UnspendOutput() @@ -154,7 +198,7 @@ func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error { continue } - view.Entries[*id] = storage.NewUtxoEntry(false, 0, true) + view.Entries[*id] = storage.NewUtxoEntry(storage.NormalUTXOType, 0, true) } return nil }