OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / test / utxo_view / utxo_view_test.go
diff --git a/test/utxo_view/utxo_view_test.go b/test/utxo_view/utxo_view_test.go
new file mode 100644 (file)
index 0000000..bddeb54
--- /dev/null
@@ -0,0 +1,468 @@
+package utxo_view
+
+import (
+       "os"
+       "testing"
+
+       "github.com/vapor/testutil"
+
+       "github.com/golang/protobuf/proto"
+
+       "github.com/vapor/database"
+       dbm "github.com/vapor/database/leveldb"
+       "github.com/vapor/database/storage"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/protocol/state"
+)
+
+func TestAttachOrDetachBlocks(t *testing.T) {
+       cases := []struct {
+               desc           string
+               before         map[bc.Hash]*storage.UtxoEntry
+               want           map[bc.Hash]*storage.UtxoEntry
+               attachBlock    []*bc.Block
+               detachBlock    []*bc.Block
+               attachTxStatus []*bc.TransactionStatus
+               detachTxStatus []*bc.TransactionStatus
+       }{
+               {
+                       desc:   "coinbase tx",
+                       before: make(map[bc.Hash]*storage.UtxoEntry),
+                       want:   map[bc.Hash]*storage.UtxoEntry{*newTx(mockBlocks[0].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[0].Block.Height, false)},
+                       attachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[0].Block),
+                       },
+                       attachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+               },
+               {
+                       desc: "Chain trading 3",
+                       before: map[bc.Hash]*storage.UtxoEntry{
+                               newTx(mockBlocks[1].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height-1, false),
+                       },
+                       want: map[bc.Hash]*storage.UtxoEntry{
+                               *newTx(mockBlocks[1].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[1].Height, false),
+                               *newTx(mockBlocks[1].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
+                               *newTx(mockBlocks[1].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
+                               *newTx(mockBlocks[1].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
+                               *newTx(mockBlocks[1].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
+                       },
+                       attachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[1].Block),
+                       },
+                       attachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+               },
+               {
+                       desc: "detach 1 block, attach 2 block",
+                       before: map[bc.Hash]*storage.UtxoEntry{
+                               *newTx(mockBlocks[2].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[2].Height, false),
+                               *newTx(mockBlocks[2].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[2].Height, false),
+                               *newTx(mockBlocks[2].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[2].Height, false),
+                       },
+                       want: map[bc.Hash]*storage.UtxoEntry{
+                               *newTx(mockBlocks[3].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[3].Height, false),
+                               *newTx(mockBlocks[3].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[3].Height, false),
+
+                               *newTx(mockBlocks[4].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[4].Height, false),
+                               *newTx(mockBlocks[4].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[4].Height, false),
+                               *newTx(mockBlocks[4].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[4].Height, false),
+                       },
+                       attachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[3].Block),
+                               types.MapBlock(&mockBlocks[4].Block),
+                       },
+                       detachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[2].Block),
+                       },
+                       attachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+                       detachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+               },
+               {
+                       desc: "detach block 5, attach block 2",
+                       before: map[bc.Hash]*storage.UtxoEntry{
+                               *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[5].Height, false),
+                               *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
+                               *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
+
+                               *newTx(mockBlocks[6].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+
+                               *newTx(mockBlocks[7].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[7].Height, false),
+                               *newTx(mockBlocks[7].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
+                               *newTx(mockBlocks[7].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
+                               *newTx(mockBlocks[7].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
+                               *newTx(mockBlocks[7].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
+
+                               *newTx(mockBlocks[8].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+
+                               *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[9].Height, false),
+                               *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
+                               *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
+                       },
+                       want: map[bc.Hash]*storage.UtxoEntry{
+                               *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+
+                               *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                       },
+                       attachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[10].Block),
+                               types.MapBlock(&mockBlocks[11].Block),
+                       },
+                       detachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[9].Block),
+                               types.MapBlock(&mockBlocks[8].Block),
+                               types.MapBlock(&mockBlocks[7].Block),
+                               types.MapBlock(&mockBlocks[6].Block),
+                               types.MapBlock(&mockBlocks[5].Block),
+                       },
+                       attachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+                       detachTxStatus: []*bc.TransactionStatus{
+
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+               },
+               {
+                       desc: "detach block 5, attach block 2. Other asset deals failed.",
+                       before: map[bc.Hash]*storage.UtxoEntry{
+                               *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[5].Height, false),
+                               *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
+                               *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
+
+                               *newTx(mockBlocks[6].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[1]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[1]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               newTx(mockBlocks[6].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height-1, false),
+
+                               *newTx(mockBlocks[6].Transactions[2]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               *newTx(mockBlocks[6].Transactions[2]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
+                               newTx(mockBlocks[6].Transactions[2]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height-1, false),
+
+                               *newTx(mockBlocks[7].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[7].Height, false),
+                               *newTx(mockBlocks[7].Transactions[1]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
+                               *newTx(mockBlocks[7].Transactions[1]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
+                               newTx(mockBlocks[7].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height-1, false),
+
+                               *newTx(mockBlocks[8].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[1]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[1]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               newTx(mockBlocks[8].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height-1, false),
+
+                               *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+                               *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
+
+                               *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[9].Height, false),
+                               *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
+                               *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
+                       },
+                       want: map[bc.Hash]*storage.UtxoEntry{
+
+                               *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+                               *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
+
+                               *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                               *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
+                       },
+                       attachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[10].Block),
+                               types.MapBlock(&mockBlocks[11].Block),
+                       },
+                       detachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[9].Block),
+                               types.MapBlock(&mockBlocks[8].Block),
+                               types.MapBlock(&mockBlocks[7].Block),
+                               types.MapBlock(&mockBlocks[6].Block),
+                               types.MapBlock(&mockBlocks[5].Block),
+                       },
+                       attachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+                       detachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: true},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: true},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: true},
+                                       &bc.TxVerifyResult{StatusFail: true},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+               },
+               {
+                       desc: "detach block 2, attach block 1. Chain trading",
+                       before: map[bc.Hash]*storage.UtxoEntry{
+                               // coinbase tx
+                               *newTx(mockBlocks[12].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[12].Height, false),
+                               *newTx(mockBlocks[12].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
+                               *newTx(mockBlocks[12].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
+                               *newTx(mockBlocks[12].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
+                               *newTx(mockBlocks[12].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
+
+                               *newTx(mockBlocks[13].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[13].Height, false),
+                               *newTx(mockBlocks[13].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[13].Height, false),
+                               *newTx(mockBlocks[13].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[13].Height, false),
+                               *newTx(mockBlocks[13].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[13].Height, false),
+                       },
+                       want: map[bc.Hash]*storage.UtxoEntry{
+                               newTx(mockBlocks[12].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
+                               *newTx(mockBlocks[14].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[14].Height, false),
+                       },
+                       attachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[14].Block),
+                       },
+                       detachBlock: []*bc.Block{
+                               types.MapBlock(&mockBlocks[13].Block),
+                               types.MapBlock(&mockBlocks[12].Block),
+                       },
+                       attachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+                       detachTxStatus: []*bc.TransactionStatus{
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                               &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                                       &bc.TxVerifyResult{StatusFail: false},
+                               }},
+                       },
+               },
+       }
+       node := blockNode(types.MapBlock(&mockBlocks[0].Block).BlockHeader)
+       defer os.RemoveAll("temp")
+       for index, c := range cases {
+               testDB := dbm.NewDB("testdb", "leveldb", "temp")
+               store := database.NewStore(testDB)
+
+               utxoViewpoint := state.NewUtxoViewpoint()
+               for k, v := range c.before {
+                       utxoViewpoint.Entries[k] = v
+               }
+               if err := store.SaveChainStatus(node, node, utxoViewpoint, []*state.VoteResult{}); err != nil {
+                       t.Error(err)
+               }
+
+               utxoViewpoint = state.NewUtxoViewpoint()
+               for index, block := range c.detachBlock {
+                       if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
+                               t.Error(err)
+                       }
+                       if err := utxoViewpoint.DetachBlock(block, c.detachTxStatus[index]); err != nil {
+                               t.Error(err)
+                       }
+               }
+
+               for index, block := range c.attachBlock {
+                       if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
+                               t.Error(err)
+                       }
+                       if err := utxoViewpoint.ApplyBlock(block, c.attachTxStatus[index]); err != nil {
+                               t.Error(err)
+                       }
+               }
+               if err := store.SaveChainStatus(node, node, utxoViewpoint, []*state.VoteResult{}); err != nil {
+                       t.Error(err)
+               }
+
+               want := map[string]*storage.UtxoEntry{}
+               result := make(map[string]*storage.UtxoEntry)
+
+               for k, v := range c.want {
+                       want[string(calcUtxoKey(&k))] = v
+               }
+
+               iter := testDB.IteratorPrefix([]byte(utxoPreFix))
+               defer iter.Release()
+
+               for iter.Next() {
+                       utxoEntry := &storage.UtxoEntry{}
+                       if err := proto.Unmarshal(iter.Value(), utxoEntry); err != nil {
+                               t.Error(err)
+                       }
+                       key := string(iter.Key())
+                       result[key] = utxoEntry
+               }
+
+               if !testutil.DeepEqual(want, result) {
+                       t.Errorf("case [%d] fail. want: %v, result: %v", index, want, result)
+               }
+               testDB.Close()
+               os.RemoveAll("temp")
+       }
+}