OSDN Git Service

update TestRescanWallet
[bytom/vapor.git] / test / wallet_test.go
1 package test
2
3 import (
4         "io/ioutil"
5         "os"
6         "reflect"
7         "testing"
8         "time"
9
10         "github.com/vapor/account"
11         "github.com/vapor/asset"
12         "github.com/vapor/blockchain/pseudohsm"
13         "github.com/vapor/blockchain/signers"
14         "github.com/vapor/blockchain/txbuilder"
15         "github.com/vapor/config"
16         "github.com/vapor/consensus"
17         "github.com/vapor/crypto/ed25519/chainkd"
18         "github.com/vapor/database"
19         dbm "github.com/vapor/database/leveldb"
20         "github.com/vapor/event"
21         "github.com/vapor/protocol"
22         "github.com/vapor/protocol/bc"
23         "github.com/vapor/protocol/bc/types"
24         wt "github.com/vapor/wallet"
25 )
26
27 func TestWalletUpdate(t *testing.T) {
28         dirPath, err := ioutil.TempDir(".", "")
29         if err != nil {
30                 t.Fatal(err)
31         }
32         defer os.RemoveAll(dirPath)
33
34         config.CommonConfig = config.DefaultConfig()
35         testDB := dbm.NewDB("testdb", "leveldb", "temp")
36         defer func() {
37                 testDB.Close()
38                 os.RemoveAll("temp")
39         }()
40
41         store := database.NewStore(testDB)
42         walletStore := database.NewWalletStore(testDB)
43         dispatcher := event.NewDispatcher()
44         txPool := protocol.NewTxPool(store, dispatcher)
45
46         chain, err := protocol.NewChain(store, txPool, dispatcher)
47         if err != nil {
48                 t.Fatal(err)
49         }
50
51         accountStore := database.NewAccountStore(testDB)
52         accountManager := account.NewManager(accountStore, chain)
53         hsm, err := pseudohsm.New(dirPath)
54         if err != nil {
55                 t.Fatal(err)
56         }
57
58         xpub1, _, err := hsm.XCreate("test_pub1", "password", "en")
59         if err != nil {
60                 t.Fatal(err)
61         }
62
63         testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub}, 1, "testAccount", signers.BIP0044)
64         if err != nil {
65                 t.Fatal(err)
66         }
67
68         controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
69         if err != nil {
70                 t.Fatal(err)
71         }
72
73         controlProg.KeyIndex = 1
74
75         reg := asset.NewRegistry(testDB, chain)
76         // reg := asset.NewRegistry(testDB, nil)
77         asset := bc.AssetID{V0: 5}
78
79         utxos := []*account.UTXO{}
80         btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
81         utxos = append(utxos, btmUtxo)
82         OtherUtxo := mockUTXO(controlProg, &asset)
83         utxos = append(utxos, OtherUtxo)
84
85         _, txData, err := mockTxData(utxos, testAccount)
86         if err != nil {
87                 t.Fatal(err)
88         }
89
90         tx := types.NewTx(*txData)
91         block := mockSingleBlock(tx)
92         txStatus := bc.NewTransactionStatus()
93         txStatus.SetStatus(0, false)
94         txStatus.SetStatus(1, false)
95         store.SaveBlock(block, txStatus)
96
97         w := newMockWallet(walletStore, accountManager, reg, chain, dispatcher, true)
98         err = w.Wallet.AttachBlock(block)
99         if err != nil {
100                 t.Fatal(err)
101         }
102
103         if _, err := w.Wallet.GetTransactionByTxID(tx.ID.String()); err != nil {
104                 t.Fatal(err)
105         }
106
107         wants, err := w.Wallet.GetTransactions(testAccount.ID, "", 1, false)
108         if len(wants) != 1 {
109                 t.Fatal(err)
110         }
111
112         if wants[0].ID != tx.ID {
113                 t.Fatal("account txID mismatch")
114         }
115
116         for position, tx := range block.Transactions {
117                 get := testDB.Get(database.CalcGlobalTxIndexKey(tx.ID.String()))
118                 bh := block.BlockHeader.Hash()
119                 expect := database.CalcGlobalTxIndex(&bh, uint64(position))
120                 if !reflect.DeepEqual(get, expect) {
121                         t.Fatalf("position#%d: compare retrieved globalTxIdx err", position)
122                 }
123         }
124 }
125
126 func TestRescanWallet(t *testing.T) {
127         // prepare wallet & db
128         dirPath, err := ioutil.TempDir(".", "")
129         if err != nil {
130                 t.Fatal(err)
131         }
132         defer os.RemoveAll(dirPath)
133
134         config.CommonConfig = config.DefaultConfig()
135         testDB := dbm.NewDB("testdb", "leveldb", "temp")
136         walletStore := database.NewWalletStore(testDB)
137         defer func() {
138                 testDB.Close()
139                 os.RemoveAll("temp")
140         }()
141
142         store := database.NewStore(testDB)
143         dispatcher := event.NewDispatcher()
144         txPool := protocol.NewTxPool(store, dispatcher)
145         chain, err := protocol.NewChain(store, txPool, dispatcher)
146         if err != nil {
147                 t.Fatal(err)
148         }
149
150         statusInfo := wt.StatusInfo{
151                 Version:  uint(1),
152                 WorkHash: bc.Hash{V0: 0xff},
153         }
154         if err := walletStore.SetWalletInfo(&statusInfo); err != nil {
155                 t.Fatal(err)
156         }
157         walletInfo, err := walletStore.GetWalletInfo()
158         if err != nil {
159                 t.Fatal(err)
160         }
161
162         // rawWallet, err := json.Marshal(statusInfo)
163         // if err != nil {
164         //      t.Fatal("save wallet info")
165         // }
166
167         w := newMockWallet(walletStore, nil, nil, chain, dispatcher, false)
168         w.Wallet.Status = *walletInfo
169         // w.store.SetWalletInfo(rawWallet)
170         // rawWallet = w.store.GetWalletInfo()
171         // if rawWallet == nil {
172         //      t.Fatal("fail to load wallet StatusInfo")
173         // }
174
175         // if err := json.Unmarshal(rawWallet, &w.Wallet.Status); err != nil {
176         //      t.Fatal(err)
177         // }
178
179         // rescan wallet
180         if err := w.Wallet.LoadWalletInfo(); err != nil {
181                 t.Fatal(err)
182         }
183
184         block := config.GenesisBlock()
185         if w.Wallet.Status.WorkHash != block.Hash() {
186                 t.Fatal("reattach from genesis block")
187         }
188 }
189
190 func mockUTXO(controlProg *account.CtrlProgram, assetID *bc.AssetID) *account.UTXO {
191         utxo := &account.UTXO{}
192         utxo.OutputID = bc.Hash{V0: 1}
193         utxo.SourceID = bc.Hash{V0: 2}
194         utxo.AssetID = *assetID
195         utxo.Amount = 1000000000
196         utxo.SourcePos = 0
197         utxo.ControlProgram = controlProg.ControlProgram
198         utxo.AccountID = controlProg.AccountID
199         utxo.Address = controlProg.Address
200         utxo.ControlProgramIndex = controlProg.KeyIndex
201         return utxo
202 }
203
204 func mockTxData(utxos []*account.UTXO, testAccount *account.Account) (*txbuilder.Template, *types.TxData, error) {
205         tplBuilder := txbuilder.NewBuilder(time.Now())
206
207         for _, utxo := range utxos {
208                 txInput, sigInst, err := account.UtxoToInputs(testAccount.Signer, utxo)
209                 if err != nil {
210                         return nil, nil, err
211                 }
212                 tplBuilder.AddInput(txInput, sigInst)
213
214                 out := &types.TxOutput{}
215                 if utxo.AssetID == *consensus.BTMAssetID {
216                         out = types.NewIntraChainOutput(utxo.AssetID, 100, utxo.ControlProgram)
217                 } else {
218                         out = types.NewIntraChainOutput(utxo.AssetID, utxo.Amount, utxo.ControlProgram)
219                 }
220                 tplBuilder.AddOutput(out)
221         }
222
223         return tplBuilder.Build()
224 }
225
226 type mockWallet struct {
227         Wallet *wt.Wallet
228 }
229
230 func newMockWallet(store wt.WalletStore, account *account.Manager, asset *asset.Registry, chain *protocol.Chain, dispatcher *event.Dispatcher, txIndexFlag bool) *mockWallet {
231         w, err := wt.NewWallet(store, account, asset, nil, chain, dispatcher, txIndexFlag)
232         if err != nil {
233                 panic(err)
234         }
235         return &mockWallet{w}
236 }
237
238 func mockSingleBlock(tx *types.Tx) *types.Block {
239         return &types.Block{
240                 BlockHeader: types.BlockHeader{
241                         Version: 1,
242                         Height:  1,
243                         PreviousBlockHash: bc.Hash{
244                                 V0: uint64(14952355164967094643),
245                                 V1: uint64(2960316323621296529),
246                                 V2: uint64(4202730371317372163),
247                                 V3: uint64(7569611631634777133),
248                         },
249                 },
250                 Transactions: []*types.Tx{config.GenesisTx(), tx},
251         }
252 }