OSDN Git Service

Support chain tx (#1365)
[bytom/bytom.git] / account / builder_test.go
1 package account
2
3 import (
4         "encoding/json"
5         "testing"
6         "time"
7
8         "github.com/bytom/blockchain/txbuilder"
9         "github.com/bytom/consensus"
10         "github.com/bytom/crypto/ed25519/chainkd"
11         "github.com/bytom/protocol/bc"
12         "github.com/bytom/testutil"
13 )
14
15 func TestReserveBtmUtxoChain(t *testing.T) {
16         chainTxUtxoNum = 3
17         utxos := []*UTXO{}
18         m := mockAccountManager(t)
19         for i := uint64(1); i <= 20; i++ {
20                 utxo := &UTXO{
21                         OutputID:  bc.Hash{V0: i},
22                         AccountID: "TestAccountID",
23                         AssetID:   *consensus.BTMAssetID,
24                         Amount:    i * chainTxMergeGas,
25                 }
26                 utxos = append(utxos, utxo)
27
28                 data, err := json.Marshal(utxo)
29                 if err != nil {
30                         t.Fatal(err)
31                 }
32
33                 m.db.Set(StandardUTXOKey(utxo.OutputID), data)
34         }
35
36         cases := []struct {
37                 amount uint64
38                 want   []uint64
39                 err    bool
40         }{
41                 {
42                         amount: 1 * chainTxMergeGas,
43                         want:   []uint64{1},
44                 },
45                 {
46                         amount: 888888 * chainTxMergeGas,
47                         want:   []uint64{},
48                         err:    true,
49                 },
50                 {
51                         amount: 7 * chainTxMergeGas,
52                         want:   []uint64{4, 3, 1},
53                 },
54                 {
55                         amount: 15 * chainTxMergeGas,
56                         want:   []uint64{5, 4, 3, 2, 1, 6},
57                 },
58                 {
59                         amount: 163 * chainTxMergeGas,
60                         want:   []uint64{20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 2, 1, 3},
61                 },
62         }
63
64         for i, c := range cases {
65                 m.utxoKeeper.expireReservation(time.Unix(999999999, 0))
66                 utxos, err := m.reserveBtmUtxoChain(&txbuilder.TemplateBuilder{}, "TestAccountID", c.amount, false)
67
68                 if err != nil != c.err {
69                         t.Fatalf("case %d got err %v want err = %v", i, err, c.err)
70                 }
71
72                 got := []uint64{}
73                 for _, utxo := range utxos {
74                         got = append(got, utxo.Amount/chainTxMergeGas)
75                 }
76
77                 if !testutil.DeepEqual(got, c.want) {
78                         t.Fatalf("case %d got %d want %d", i, got, c.want)
79                 }
80         }
81
82 }
83
84 func TestBuildBtmTxChain(t *testing.T) {
85         chainTxUtxoNum = 3
86         m := mockAccountManager(t)
87         cases := []struct {
88                 inputUtxo  []uint64
89                 wantInput  [][]uint64
90                 wantOutput [][]uint64
91                 wantUtxo   uint64
92         }{
93                 {
94                         inputUtxo:  []uint64{5},
95                         wantInput:  [][]uint64{},
96                         wantOutput: [][]uint64{},
97                         wantUtxo:   5 * chainTxMergeGas,
98                 },
99                 {
100                         inputUtxo: []uint64{5, 4},
101                         wantInput: [][]uint64{
102                                 []uint64{5, 4},
103                         },
104                         wantOutput: [][]uint64{
105                                 []uint64{8},
106                         },
107                         wantUtxo: 8 * chainTxMergeGas,
108                 },
109                 {
110                         inputUtxo: []uint64{5, 4, 1, 1},
111                         wantInput: [][]uint64{
112                                 []uint64{5, 4, 1},
113                                 []uint64{1, 9},
114                         },
115                         wantOutput: [][]uint64{
116                                 []uint64{9},
117                                 []uint64{9},
118                         },
119                         wantUtxo: 9 * chainTxMergeGas,
120                 },
121                 {
122                         inputUtxo: []uint64{22, 123, 53, 234, 23, 4, 2423, 24, 23, 43, 34, 234, 234, 24},
123                         wantInput: [][]uint64{
124                                 []uint64{22, 123, 53},
125                                 []uint64{234, 23, 4},
126                                 []uint64{2423, 24, 23},
127                                 []uint64{43, 34, 234},
128                                 []uint64{234, 24, 197},
129                                 []uint64{260, 2469, 310},
130                                 []uint64{454, 3038},
131                         },
132                         wantOutput: [][]uint64{
133                                 []uint64{197},
134                                 []uint64{260},
135                                 []uint64{2469},
136                                 []uint64{310},
137                                 []uint64{454},
138                                 []uint64{3038},
139                                 []uint64{3491},
140                         },
141                         wantUtxo: 3491 * chainTxMergeGas,
142                 },
143         }
144
145         acct, err := m.Create([]chainkd.XPub{testutil.TestXPub}, 1, "testAccount")
146         if err != nil {
147                 t.Fatal(err)
148         }
149
150         acp, err := m.CreateAddress(acct.ID, false)
151         if err != nil {
152                 t.Fatal(err)
153         }
154
155         for caseIndex, c := range cases {
156                 utxos := []*UTXO{}
157                 for _, amount := range c.inputUtxo {
158                         utxos = append(utxos, &UTXO{
159                                 Amount:         amount * chainTxMergeGas,
160                                 AssetID:        *consensus.BTMAssetID,
161                                 Address:        acp.Address,
162                                 ControlProgram: acp.ControlProgram,
163                         })
164                 }
165
166                 tpls, gotUtxo, err := m.buildBtmTxChain(utxos, acct.Signer)
167                 if err != nil {
168                         t.Fatal(err)
169                 }
170
171                 for i, tpl := range tpls {
172                         gotInput := []uint64{}
173                         for _, input := range tpl.Transaction.Inputs {
174                                 gotInput = append(gotInput, input.Amount()/chainTxMergeGas)
175                         }
176
177                         gotOutput := []uint64{}
178                         for _, output := range tpl.Transaction.Outputs {
179                                 gotOutput = append(gotOutput, output.Amount/chainTxMergeGas)
180                         }
181
182                         if !testutil.DeepEqual(c.wantInput[i], gotInput) {
183                                 t.Fatalf("case %d tx %d input got %d want %d", caseIndex, i, gotInput, c.wantInput[i])
184                         }
185                         if !testutil.DeepEqual(c.wantOutput[i], gotOutput) {
186                                 t.Fatalf("case %d tx %d output got %d want %d", caseIndex, i, gotOutput, c.wantOutput[i])
187                         }
188                 }
189
190                 if c.wantUtxo != gotUtxo.Amount {
191                         t.Fatalf("case %d got utxo=%d want utxo=%d", caseIndex, gotUtxo.Amount, c.wantUtxo)
192                 }
193         }
194
195 }
196
197 func TestMergeSpendAction(t *testing.T) {
198         testBTM := &bc.AssetID{}
199         if err := testBTM.UnmarshalText([]byte("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); err != nil {
200                 t.Fatal(err)
201         }
202
203         testAssetID1 := &bc.AssetID{}
204         if err := testAssetID1.UnmarshalText([]byte("50ec80b6bc48073f6aa8fa045131a71213c33f3681203b15ddc2e4b81f1f4730")); err != nil {
205                 t.Fatal(err)
206         }
207
208         testAssetID2 := &bc.AssetID{}
209         if err := testAssetID2.UnmarshalText([]byte("43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c")); err != nil {
210                 t.Fatal(err)
211         }
212
213         cases := []struct {
214                 testActions     []txbuilder.Action
215                 wantActions     []txbuilder.Action
216                 testActionCount int
217                 wantActionCount int
218         }{
219                 {
220                         testActions: []txbuilder.Action{
221                                 txbuilder.Action(&spendAction{
222                                         AssetAmount: bc.AssetAmount{
223                                                 AssetId: testBTM,
224                                                 Amount:  100,
225                                         },
226                                         AccountID: "test_account",
227                                 }),
228                                 txbuilder.Action(&spendAction{
229                                         AssetAmount: bc.AssetAmount{
230                                                 AssetId: testBTM,
231                                                 Amount:  200,
232                                         },
233                                         AccountID: "test_account",
234                                 }),
235                                 txbuilder.Action(&spendAction{
236                                         AssetAmount: bc.AssetAmount{
237                                                 AssetId: testBTM,
238                                                 Amount:  300,
239                                         },
240                                         AccountID: "test_account",
241                                 }),
242                                 txbuilder.Action(&spendAction{
243                                         AssetAmount: bc.AssetAmount{
244                                                 AssetId: testAssetID1,
245                                                 Amount:  300,
246                                         },
247                                         AccountID: "test_account",
248                                 }),
249                         },
250                         wantActions: []txbuilder.Action{
251                                 txbuilder.Action(&spendAction{
252                                         AssetAmount: bc.AssetAmount{
253                                                 AssetId: testBTM,
254                                                 Amount:  600,
255                                         },
256                                         AccountID: "test_account",
257                                 }),
258                                 txbuilder.Action(&spendAction{
259                                         AssetAmount: bc.AssetAmount{
260                                                 AssetId: testAssetID1,
261                                                 Amount:  300,
262                                         },
263                                         AccountID: "test_account",
264                                 }),
265                         },
266                         testActionCount: 4,
267                         wantActionCount: 2,
268                 },
269                 {
270                         testActions: []txbuilder.Action{
271                                 txbuilder.Action(&spendAction{
272                                         AssetAmount: bc.AssetAmount{
273                                                 AssetId: testBTM,
274                                                 Amount:  100,
275                                         },
276                                         AccountID: "test_account",
277                                 }),
278                                 txbuilder.Action(&spendAction{
279                                         AssetAmount: bc.AssetAmount{
280                                                 AssetId: testAssetID1,
281                                                 Amount:  200,
282                                         },
283                                         AccountID: "test_account",
284                                 }),
285                                 txbuilder.Action(&spendAction{
286                                         AssetAmount: bc.AssetAmount{
287                                                 AssetId: testBTM,
288                                                 Amount:  500,
289                                         },
290                                         AccountID: "test_account",
291                                 }),
292                                 txbuilder.Action(&spendAction{
293                                         AssetAmount: bc.AssetAmount{
294                                                 AssetId: testAssetID1,
295                                                 Amount:  300,
296                                         },
297                                         AccountID: "test_account",
298                                 }),
299                         },
300                         wantActions: []txbuilder.Action{
301                                 txbuilder.Action(&spendAction{
302                                         AssetAmount: bc.AssetAmount{
303                                                 AssetId: testBTM,
304                                                 Amount:  600,
305                                         },
306                                         AccountID: "test_account",
307                                 }),
308                                 txbuilder.Action(&spendAction{
309                                         AssetAmount: bc.AssetAmount{
310                                                 AssetId: testAssetID1,
311                                                 Amount:  500,
312                                         },
313                                         AccountID: "test_account",
314                                 }),
315                         },
316                         testActionCount: 4,
317                         wantActionCount: 2,
318                 },
319                 {
320                         testActions: []txbuilder.Action{
321                                 txbuilder.Action(&spendAction{
322                                         AssetAmount: bc.AssetAmount{
323                                                 AssetId: testBTM,
324                                                 Amount:  100,
325                                         },
326                                         AccountID: "test_account",
327                                 }),
328                                 txbuilder.Action(&spendAction{
329                                         AssetAmount: bc.AssetAmount{
330                                                 AssetId: testAssetID1,
331                                                 Amount:  200,
332                                         },
333                                         AccountID: "test_account",
334                                 }),
335                                 txbuilder.Action(&spendAction{
336                                         AssetAmount: bc.AssetAmount{
337                                                 AssetId: testAssetID2,
338                                                 Amount:  300,
339                                         },
340                                         AccountID: "test_account",
341                                 }),
342                                 txbuilder.Action(&spendAction{
343                                         AssetAmount: bc.AssetAmount{
344                                                 AssetId: testAssetID1,
345                                                 Amount:  300,
346                                         },
347                                         AccountID: "test_account",
348                                 }),
349                                 txbuilder.Action(&spendAction{
350                                         AssetAmount: bc.AssetAmount{
351                                                 AssetId: testAssetID2,
352                                                 Amount:  500,
353                                         },
354                                         AccountID: "test_account",
355                                 }),
356                         },
357                         wantActions: []txbuilder.Action{
358                                 txbuilder.Action(&spendAction{
359                                         AssetAmount: bc.AssetAmount{
360                                                 AssetId: testBTM,
361                                                 Amount:  100,
362                                         },
363                                         AccountID: "test_account",
364                                 }),
365                                 txbuilder.Action(&spendAction{
366                                         AssetAmount: bc.AssetAmount{
367                                                 AssetId: testAssetID1,
368                                                 Amount:  500,
369                                         },
370                                         AccountID: "test_account",
371                                 }),
372                                 txbuilder.Action(&spendAction{
373                                         AssetAmount: bc.AssetAmount{
374                                                 AssetId: testAssetID2,
375                                                 Amount:  800,
376                                         },
377                                         AccountID: "test_account",
378                                 }),
379                         },
380                         testActionCount: 5,
381                         wantActionCount: 3,
382                 },
383                 {
384                         testActions: []txbuilder.Action{
385                                 txbuilder.Action(&spendAction{
386                                         AssetAmount: bc.AssetAmount{
387                                                 AssetId: testBTM,
388                                                 Amount:  100,
389                                         },
390                                         AccountID: "test_account",
391                                 }),
392                                 txbuilder.Action(&spendAction{
393                                         AssetAmount: bc.AssetAmount{
394                                                 AssetId: testBTM,
395                                                 Amount:  200,
396                                         },
397                                         AccountID: "test_account1",
398                                 }),
399                                 txbuilder.Action(&spendAction{
400                                         AssetAmount: bc.AssetAmount{
401                                                 AssetId: testBTM,
402                                                 Amount:  500,
403                                         },
404                                         AccountID: "test_account",
405                                 }),
406                                 txbuilder.Action(&spendAction{
407                                         AssetAmount: bc.AssetAmount{
408                                                 AssetId: testAssetID1,
409                                                 Amount:  300,
410                                         },
411                                         AccountID: "test_account1",
412                                 }),
413                         },
414                         wantActions: []txbuilder.Action{
415                                 txbuilder.Action(&spendAction{
416                                         AssetAmount: bc.AssetAmount{
417                                                 AssetId: testBTM,
418                                                 Amount:  600,
419                                         },
420                                         AccountID: "test_account",
421                                 }),
422                                 txbuilder.Action(&spendAction{
423                                         AssetAmount: bc.AssetAmount{
424                                                 AssetId: testBTM,
425                                                 Amount:  200,
426                                         },
427                                         AccountID: "test_account1",
428                                 }),
429                                 txbuilder.Action(&spendAction{
430                                         AssetAmount: bc.AssetAmount{
431                                                 AssetId: testAssetID1,
432                                                 Amount:  300,
433                                         },
434                                         AccountID: "test_account1",
435                                 }),
436                         },
437                         testActionCount: 4,
438                         wantActionCount: 3,
439                 },
440                 {
441                         testActions: []txbuilder.Action{
442                                 txbuilder.Action(&spendUTXOAction{
443                                         OutputID: &bc.Hash{V0: 128},
444                                 }),
445                                 txbuilder.Action(&spendAction{
446                                         AssetAmount: bc.AssetAmount{
447                                                 AssetId: testBTM,
448                                                 Amount:  100,
449                                         },
450                                         AccountID: "test_account",
451                                 }),
452                                 txbuilder.Action(&spendAction{
453                                         AssetAmount: bc.AssetAmount{
454                                                 AssetId: testAssetID1,
455                                                 Amount:  200,
456                                         },
457                                         AccountID: "test_account1",
458                                 }),
459                                 txbuilder.Action(&spendUTXOAction{
460                                         OutputID: &bc.Hash{V0: 256},
461                                 }),
462                                 txbuilder.Action(&spendAction{
463                                         AssetAmount: bc.AssetAmount{
464                                                 AssetId: testAssetID2,
465                                                 Amount:  300,
466                                         },
467                                         AccountID: "test_account2",
468                                 }),
469                         },
470                         wantActions: []txbuilder.Action{
471                                 txbuilder.Action(&spendUTXOAction{
472                                         OutputID: &bc.Hash{V0: 128},
473                                 }),
474                                 txbuilder.Action(&spendAction{
475                                         AssetAmount: bc.AssetAmount{
476                                                 AssetId: testBTM,
477                                                 Amount:  100,
478                                         },
479                                         AccountID: "test_account",
480                                 }),
481                                 txbuilder.Action(&spendAction{
482                                         AssetAmount: bc.AssetAmount{
483                                                 AssetId: testAssetID1,
484                                                 Amount:  200,
485                                         },
486                                         AccountID: "test_account1",
487                                 }),
488                                 txbuilder.Action(&spendUTXOAction{
489                                         OutputID: &bc.Hash{V0: 256},
490                                 }),
491                                 txbuilder.Action(&spendAction{
492                                         AssetAmount: bc.AssetAmount{
493                                                 AssetId: testAssetID2,
494                                                 Amount:  300,
495                                         },
496                                         AccountID: "test_account2",
497                                 }),
498                         },
499                         testActionCount: 5,
500                         wantActionCount: 5,
501                 },
502         }
503
504         for _, c := range cases {
505                 gotActions := MergeSpendAction(c.testActions)
506
507                 gotMap := make(map[string]uint64)
508                 wantMap := make(map[string]uint64)
509                 for _, got := range gotActions {
510                         switch got := got.(type) {
511                         case *spendAction:
512                                 gotKey := got.AssetId.String() + got.AccountID
513                                 gotMap[gotKey] = got.Amount
514                         default:
515                                 continue
516                         }
517                 }
518
519                 for _, want := range c.wantActions {
520                         switch want := want.(type) {
521                         case *spendAction:
522                                 wantKey := want.AssetId.String() + want.AccountID
523                                 wantMap[wantKey] = want.Amount
524                         default:
525                                 continue
526                         }
527                 }
528
529                 for key := range gotMap {
530                         if gotMap[key] != wantMap[key] {
531                                 t.Fatalf("gotMap[%s]=%v, wantMap[%s]=%v", key, gotMap[key], key, wantMap[key])
532                         }
533                 }
534
535                 if len(gotActions) != c.wantActionCount {
536                         t.Fatalf("number of gotActions=%d, wantActions=%d", len(gotActions), c.wantActionCount)
537                 }
538         }
539 }
540
541 func TestCalcMergeGas(t *testing.T) {
542         chainTxUtxoNum = 10
543         cases := []struct {
544                 utxoNum int
545                 gas     uint64
546         }{
547                 {
548                         utxoNum: 0,
549                         gas:     0,
550                 },
551                 {
552                         utxoNum: 1,
553                         gas:     0,
554                 },
555                 {
556                         utxoNum: 9,
557                         gas:     chainTxMergeGas,
558                 },
559                 {
560                         utxoNum: 10,
561                         gas:     chainTxMergeGas,
562                 },
563                 {
564                         utxoNum: 11,
565                         gas:     chainTxMergeGas * 2,
566                 },
567                 {
568                         utxoNum: 20,
569                         gas:     chainTxMergeGas * 3,
570                 },
571                 {
572                         utxoNum: 21,
573                         gas:     chainTxMergeGas * 3,
574                 },
575                 {
576                         utxoNum: 74,
577                         gas:     chainTxMergeGas * 9,
578                 },
579         }
580
581         for i, c := range cases {
582                 gas := calcMergeGas(c.utxoNum)
583                 if gas != c.gas {
584                         t.Fatalf("case %d got %d want %d", i, gas, c.gas)
585                 }
586         }
587 }