OSDN Git Service

Hulk did something
[bytom/vapor.git] / protocol / state / utxo_view_test.go
diff --git a/protocol/state/utxo_view_test.go b/protocol/state/utxo_view_test.go
new file mode 100644 (file)
index 0000000..8668a1c
--- /dev/null
@@ -0,0 +1,487 @@
+package state
+
+import (
+       "testing"
+
+       "github.com/vapor/consensus"
+       "github.com/vapor/database/storage"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/testutil"
+)
+
+var defaultEntry = map[bc.Hash]bc.Entry{
+       bc.Hash{V0: 0}: &bc.Output{
+               Source: &bc.ValueSource{
+                       Value: &bc.AssetAmount{
+                               AssetId: &bc.AssetID{V0: 0},
+                       },
+               },
+       },
+}
+
+var gasOnlyTxEntry = map[bc.Hash]bc.Entry{
+       bc.Hash{V1: 0}: &bc.Output{
+               Source: &bc.ValueSource{
+                       Value: &bc.AssetAmount{
+                               AssetId: consensus.BTMAssetID,
+                       },
+               },
+       },
+       bc.Hash{V1: 1}: &bc.Output{
+               Source: &bc.ValueSource{
+                       Value: &bc.AssetAmount{
+                               AssetId: &bc.AssetID{V0: 999},
+                       },
+               },
+       },
+}
+
+func TestApplyBlock(t *testing.T) {
+       cases := []struct {
+               block     *bc.Block
+               inputView *UtxoViewpoint
+               fetchView *UtxoViewpoint
+               gasOnlyTx bool
+               err       bool
+       }{
+               {
+                       // can't find prevout in tx entries
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 1},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       fetchView: NewUtxoViewpoint(),
+                       err:       true,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: NewUtxoViewpoint(),
+                       fetchView: NewUtxoViewpoint(),
+                       err:       true,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       err: true,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       err: false,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       Height:            101,
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, false),
+                               },
+                       },
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, true),
+                               },
+                       },
+                       err: false,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       Height:            0,
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, false),
+                               },
+                       },
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, true),
+                               },
+                       },
+                       err: true,
+               },
+               {
+                       // output will be store
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{
+                                                               &bc.Hash{V0: 0},
+                                                       },
+                                               },
+                                               SpentOutputIDs: []bc.Hash{},
+                                               Entries:        defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: NewUtxoViewpoint(),
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, false),
+                               },
+                       },
+                       err: false,
+               },
+               {
+                       // apply gas only tx, non-btm asset spent input will not be spent
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V1: 0},
+                                                       bc.Hash{V1: 1},
+                                               },
+                                               Entries: gasOnlyTxEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, false),
+                                       bc.Hash{V1: 1}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, true),
+                                       bc.Hash{V1: 1}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       gasOnlyTx: true,
+                       err:       false,
+               },
+               {
+                       // apply gas only tx, non-btm asset spent output will not be store
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{
+                                                               &bc.Hash{V1: 0},
+                                                               &bc.Hash{V1: 1},
+                                                       },
+                                               },
+                                               SpentOutputIDs: []bc.Hash{},
+                                               Entries:        gasOnlyTxEntry,
+                                       },
+                               },
+                       },
+                       inputView: NewUtxoViewpoint(),
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V1: 0}: storage.NewUtxoEntry(true, 0, false),
+                               },
+                       },
+                       gasOnlyTx: true,
+                       err:       false,
+               },
+       }
+
+       for i, c := range cases {
+               c.block.TransactionStatus.SetStatus(0, c.gasOnlyTx)
+               if err := c.inputView.ApplyBlock(c.block, c.block.TransactionStatus); c.err != (err != nil) {
+                       t.Errorf("case #%d want err = %v, get err = %v", i, c.err, err)
+               }
+               if c.err {
+                       continue
+               }
+               if !testutil.DeepEqual(c.inputView, c.fetchView) {
+                       t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
+               }
+       }
+}
+
+func TestDetachBlock(t *testing.T) {
+       cases := []struct {
+               block     *bc.Block
+               inputView *UtxoViewpoint
+               fetchView *UtxoViewpoint
+               gasOnlyTx bool
+               err       bool
+       }{
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: NewUtxoViewpoint(),
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       err: false,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{
+                                                               &bc.Hash{V0: 0},
+                                                       },
+                                               },
+                                               SpentOutputIDs: []bc.Hash{},
+                                               Entries:        defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: NewUtxoViewpoint(),
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       err: false,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       err: true,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V0: 0},
+                                               },
+                                               Entries: defaultEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
+                               },
+                       },
+                       err: false,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{},
+                                               },
+                                               SpentOutputIDs: []bc.Hash{
+                                                       bc.Hash{V1: 0},
+                                                       bc.Hash{V1: 1},
+                                               },
+                                               Entries: gasOnlyTxEntry,
+                                       },
+                               },
+                       },
+                       inputView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, true),
+                                       bc.Hash{V1: 1}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, false),
+                                       bc.Hash{V1: 1}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       gasOnlyTx: true,
+                       err:       false,
+               },
+               {
+                       block: &bc.Block{
+                               BlockHeader: &bc.BlockHeader{
+                                       TransactionStatus: bc.NewTransactionStatus(),
+                               },
+                               Transactions: []*bc.Tx{
+                                       &bc.Tx{
+                                               TxHeader: &bc.TxHeader{
+                                                       ResultIds: []*bc.Hash{
+                                                               &bc.Hash{V1: 0},
+                                                               &bc.Hash{V1: 1},
+                                                       },
+                                               },
+                                               SpentOutputIDs: []bc.Hash{},
+                                               Entries:        gasOnlyTxEntry,
+                                       },
+                               },
+                       },
+                       inputView: NewUtxoViewpoint(),
+                       fetchView: &UtxoViewpoint{
+                               Entries: map[bc.Hash]*storage.UtxoEntry{
+                                       bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, true),
+                               },
+                       },
+                       gasOnlyTx: true,
+                       err:       false,
+               },
+       }
+
+       for i, c := range cases {
+               c.block.TransactionStatus.SetStatus(0, c.gasOnlyTx)
+               if err := c.inputView.DetachBlock(c.block, c.block.TransactionStatus); c.err != (err != nil) {
+                       t.Errorf("case %d want err = %v, get err = %v", i, c.err, err)
+               }
+               if c.err {
+                       continue
+               }
+               if !testutil.DeepEqual(c.inputView, c.fetchView) {
+                       t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
+               }
+       }
+}