11 "github.com/bytom/account"
12 "github.com/bytom/asset"
13 "github.com/bytom/blockchain/pseudohsm"
14 "github.com/bytom/blockchain/signers"
15 "github.com/bytom/blockchain/txbuilder"
16 "github.com/bytom/config"
17 "github.com/bytom/consensus"
18 "github.com/bytom/crypto/ed25519/chainkd"
19 "github.com/bytom/database"
20 dbm "github.com/bytom/database/leveldb"
21 "github.com/bytom/event"
22 "github.com/bytom/protocol"
23 "github.com/bytom/protocol/bc"
24 "github.com/bytom/protocol/bc/types"
27 func TestWalletVersion(t *testing.T) {
29 dirPath, err := ioutil.TempDir(".", "")
33 defer os.RemoveAll(dirPath)
35 testDB := dbm.NewDB("testdb", "leveldb", "temp")
36 defer os.RemoveAll("temp")
38 dispatcher := event.NewDispatcher()
39 w := mockWallet(testDB, nil, nil, nil, dispatcher)
41 // legacy status test case
42 type legacyStatusInfo struct {
48 rawWallet, err := json.Marshal(legacyStatusInfo{})
50 t.Fatal("Marshal legacyStatusInfo")
53 w.DB.Set(walletKey, rawWallet)
54 rawWallet = w.DB.Get(walletKey)
56 t.Fatal("fail to load wallet StatusInfo")
59 if err := json.Unmarshal(rawWallet, &w.status); err != nil {
63 if err := w.checkWalletInfo(); err != errWalletVersionMismatch {
64 t.Fatal("fail to detect legacy wallet version")
67 // lower wallet version test case
68 lowerVersion := StatusInfo{Version: currentVersion - 1}
69 rawWallet, err = json.Marshal(lowerVersion)
71 t.Fatal("save wallet info")
74 w.DB.Set(walletKey, rawWallet)
75 rawWallet = w.DB.Get(walletKey)
77 t.Fatal("fail to load wallet StatusInfo")
80 if err := json.Unmarshal(rawWallet, &w.status); err != nil {
84 if err := w.checkWalletInfo(); err != errWalletVersionMismatch {
85 t.Fatal("fail to detect expired wallet version")
89 func TestWalletUpdate(t *testing.T) {
90 dirPath, err := ioutil.TempDir(".", "")
94 defer os.RemoveAll(dirPath)
96 testDB := dbm.NewDB("testdb", "leveldb", "temp")
97 defer os.RemoveAll("temp")
99 store := database.NewStore(testDB)
100 dispatcher := event.NewDispatcher()
101 txPool := protocol.NewTxPool(store, dispatcher)
103 chain, err := protocol.NewChain(store, txPool)
108 accountManager := account.NewManager(testDB, chain)
109 hsm, err := pseudohsm.New(dirPath)
114 xpub1, _, err := hsm.XCreate("test_pub1", "password", "en")
119 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub}, 1, "testAccount", signers.BIP0044)
124 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
129 controlProg.KeyIndex = 1
131 reg := asset.NewRegistry(testDB, chain)
132 asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, 0, "TESTASSET", nil)
137 utxos := []*account.UTXO{}
138 btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
139 utxos = append(utxos, btmUtxo)
140 OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
141 utxos = append(utxos, OtherUtxo)
143 _, txData, err := mockTxData(utxos, testAccount)
148 tx := types.NewTx(*txData)
149 block := mockSingleBlock(tx)
150 txStatus := bc.NewTransactionStatus()
151 txStatus.SetStatus(0, false)
152 txStatus.SetStatus(1, false)
153 store.SaveBlock(block, txStatus)
155 w := mockWallet(testDB, accountManager, reg, chain, dispatcher)
156 err = w.AttachBlock(block)
161 if _, err := w.GetTransactionByTxID(tx.ID.String()); err != nil {
165 wants, err := w.GetTransactions("")
170 if wants[0].ID != tx.ID {
171 t.Fatal("account txID mismatch")
174 for position, tx := range block.Transactions {
175 get := w.DB.Get(calcGlobalTxIndexKey(tx.ID.String()))
176 bh := block.BlockHeader.Hash()
177 expect := calcGlobalTxIndex(&bh, position)
178 if !reflect.DeepEqual(get, expect) {
179 t.Fatalf("position#%d: compare retrieved globalTxIdx err", position)
184 func TestMemPoolTxQueryLoop(t *testing.T) {
185 dirPath, err := ioutil.TempDir(".", "")
189 defer os.RemoveAll(dirPath)
191 testDB := dbm.NewDB("testdb", "leveldb", dirPath)
193 store := database.NewStore(testDB)
194 dispatcher := event.NewDispatcher()
195 txPool := protocol.NewTxPool(store, dispatcher)
197 chain, err := protocol.NewChain(store, txPool)
202 accountManager := account.NewManager(testDB, chain)
203 hsm, err := pseudohsm.New(dirPath)
208 xpub1, _, err := hsm.XCreate("test_pub1", "password", "en")
213 testAccount, err := accountManager.Create([]chainkd.XPub{xpub1.XPub}, 1, "testAccount", signers.BIP0044)
218 controlProg, err := accountManager.CreateAddress(testAccount.ID, false)
223 controlProg.KeyIndex = 1
225 reg := asset.NewRegistry(testDB, chain)
226 asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, 0, "TESTASSET", nil)
231 utxos := []*account.UTXO{}
232 btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
233 utxos = append(utxos, btmUtxo)
234 OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
235 utxos = append(utxos, OtherUtxo)
237 _, txData, err := mockTxData(utxos, testAccount)
242 tx := types.NewTx(*txData)
243 //block := mockSingleBlock(tx)
244 txStatus := bc.NewTransactionStatus()
245 txStatus.SetStatus(0, false)
246 w, err := NewWallet(testDB, accountManager, reg, hsm, chain, dispatcher)
247 go w.memPoolTxQueryLoop()
248 w.eventDispatcher.Post(protocol.TxMsgEvent{TxMsg: &protocol.TxPoolMsg{TxDesc: &protocol.TxDesc{Tx: tx}, MsgType: protocol.MsgNewTx}})
249 time.Sleep(time.Millisecond * 10)
250 if _, err = w.GetUnconfirmedTxByTxID(tx.ID.String()); err != nil {
251 t.Fatal("disaptch new tx msg error:", err)
253 w.eventDispatcher.Post(protocol.TxMsgEvent{TxMsg: &protocol.TxPoolMsg{TxDesc: &protocol.TxDesc{Tx: tx}, MsgType: protocol.MsgRemoveTx}})
254 time.Sleep(time.Millisecond * 10)
255 txs, err := w.GetUnconfirmedTxs(testAccount.ID)
257 t.Fatal("get unconfirmed tx error:", err)
261 t.Fatal("disaptch remove tx msg error")
264 w.eventDispatcher.Post(protocol.TxMsgEvent{TxMsg: &protocol.TxPoolMsg{TxDesc: &protocol.TxDesc{Tx: tx}, MsgType: 2}})
267 func mockUTXO(controlProg *account.CtrlProgram, assetID *bc.AssetID) *account.UTXO {
268 utxo := &account.UTXO{}
269 utxo.OutputID = bc.Hash{V0: 1}
270 utxo.SourceID = bc.Hash{V0: 2}
271 utxo.AssetID = *assetID
272 utxo.Amount = 1000000000
274 utxo.ControlProgram = controlProg.ControlProgram
275 utxo.AccountID = controlProg.AccountID
276 utxo.Address = controlProg.Address
277 utxo.ControlProgramIndex = controlProg.KeyIndex
281 func mockTxData(utxos []*account.UTXO, testAccount *account.Account) (*txbuilder.Template, *types.TxData, error) {
282 tplBuilder := txbuilder.NewBuilder(time.Now())
284 for _, utxo := range utxos {
285 txInput, sigInst, err := account.UtxoToInputs(testAccount.Signer, utxo)
289 tplBuilder.AddInput(txInput, sigInst)
291 out := &types.TxOutput{}
292 if utxo.AssetID == *consensus.BTMAssetID {
293 out = types.NewTxOutput(utxo.AssetID, 100, utxo.ControlProgram)
295 out = types.NewTxOutput(utxo.AssetID, utxo.Amount, utxo.ControlProgram)
297 tplBuilder.AddOutput(out)
300 return tplBuilder.Build()
303 func mockWallet(walletDB dbm.DB, account *account.Manager, asset *asset.Registry, chain *protocol.Chain, dispatcher *event.Dispatcher) *Wallet {
309 RecoveryMgr: newRecoveryManager(walletDB, account),
310 eventDispatcher: dispatcher,
312 wallet.txMsgSub, _ = wallet.eventDispatcher.Subscribe(protocol.TxMsgEvent{})
316 func mockSingleBlock(tx *types.Tx) *types.Block {
318 BlockHeader: types.BlockHeader{
321 Bits: 2305843009230471167,
323 Transactions: []*types.Tx{config.GenesisTx(), tx},