OSDN Git Service

Merge pull request #1 from Bytom/master
[bytom/bytom.git] / protocol / block_test.go
1 package protocol
2
3 /*
4 func TestGetBlock(t *testing.T) {
5         ctx := context.Background()
6
7         b1 := &legacy.Block{BlockHeader: legacy.BlockHeader{Height: 1}}
8         noBlocks := memstore.New()
9         oneBlock := memstore.New()
10         oneBlock.SaveBlock(ctx, b1)
11         oneBlock.SaveSnapshot(ctx, 1, state.Empty())
12
13         cases := []struct {
14                 store   Store
15                 want    *legacy.Block
16                 wantErr bool
17         }{
18                 {noBlocks, nil, true},
19                 {oneBlock, b1, false},
20         }
21
22         for _, test := range cases {
23                 c, err := NewChain(ctx, b1.Hash(), test.store, nil)
24                 if err != nil {
25                         testutil.FatalErr(t, err)
26                 }
27                 got, gotErr := c.GetBlock(ctx, c.Height())
28                 if !testutil.DeepEqual(got, test.want) {
29                         t.Errorf("got latest = %+v want %+v", got, test.want)
30                 }
31                 if (gotErr != nil) != test.wantErr {
32                         t.Errorf("got latest err = %q want err?: %t", gotErr, test.wantErr)
33                 }
34         }
35 }
36
37 func TestNoTimeTravel(t *testing.T) {
38         ctx := context.Background()
39         c, err := NewChain(ctx, bc.Hash{}, memstore.New(), nil)
40         if err != nil {
41                 t.Fatal(err)
42         }
43
44         c.setHeight(1)
45         c.setHeight(2)
46
47         c.setHeight(1) // don't go backward
48         if c.state.height != 2 {
49                 t.Fatalf("c.state.height = %d want 2", c.state.height)
50         }
51 }
52
53 func TestWaitForBlockSoonAlreadyExists(t *testing.T) {
54         c, _ := newTestChain(t, time.Now())
55         makeEmptyBlock(t, c) // height=2
56         makeEmptyBlock(t, c) // height=3
57
58         err := <-c.BlockSoonWaiter(context.Background(), 2)
59         if err != nil {
60                 t.Fatal(err)
61         }
62 }
63
64 func TestWaitForBlockSoonDistantFuture(t *testing.T) {
65         c, _ := newTestChain(t, time.Now())
66
67         got := <-c.BlockSoonWaiter(context.Background(), 100) // distant future
68         want := ErrTheDistantFuture
69         if got != want {
70                 t.Errorf("BlockSoonWaiter(100) = %+v want %+v", got, want)
71         }
72 }
73
74 func TestWaitForBlockSoonWaits(t *testing.T) {
75         // This test is inherently racy. It's possible
76         // that the block creation might run before
77         // the wait's internal test loop finds no block.
78         // In that case, the test will pass, but it will
79         // not have tested anything.
80         //
81         // It's the best we can do.
82
83         c, _ := newTestChain(t, time.Now())
84         makeEmptyBlock(t, c) // height=2
85
86         go func() {
87                 time.Sleep(10 * time.Millisecond) // sorry for the slow test 
88                 makeEmptyBlock(t, c)              // height=3
89         }()
90
91         err := <-c.BlockSoonWaiter(context.Background(), 3)
92         if err != nil {
93                 t.Fatal(err)
94         }
95         if g := c.Height(); g != 3 {
96                 t.Errorf("height after waiting = %d want 3", g)
97         }
98 }
99
100 func TestWaitForBlockSoonTimesout(t *testing.T) {
101         c, _ := newTestChain(t, time.Now())
102         go func() {
103                 makeEmptyBlock(t, c) // height=2
104         }()
105
106         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
107         defer cancel()
108
109         err := <-c.BlockSoonWaiter(ctx, 3)
110         if err != ctx.Err() {
111                 t.Fatalf("expected timeout err, got %v", err)
112         }
113 }
114
115 func TestGenerateBlock(t *testing.T) {
116         ctx := context.Background()
117         now := time.Unix(233400000, 0)
118         c, b1 := newTestChain(t, now)
119
120         initialBlockHash := b1.Hash()
121         assetID := bc.ComputeAssetID(nil, &initialBlockHash, 1, &bc.EmptyStringHash)
122
123         txs := []*legacy.Tx{
124                 legacy.NewTx(legacy.TxData{
125                         Version: 1,
126                         MinTime: 233400000000,
127                         MaxTime: 233400000001,
128                         Inputs: []*legacy.TxInput{
129                                 legacy.NewIssuanceInput([]byte{1}, 50, nil, initialBlockHash, nil, [][]byte{
130                                         nil,
131                                         mustDecodeHex("30450221009037e1d39b7d59d24eba8012baddd5f4ab886a51b46f52b7c479ddfa55eeb5c5022076008409243475b25dfba6db85e15cf3d74561a147375941e4830baa69769b5101"),
132                                         mustDecodeHex("51210210b002870438af79b829bc22c4505e14779ef0080c411ad497d7a0846ee0af6f51ae")}, nil),
133                         },
134                         Outputs: []*legacy.TxOutput{
135                                 legacy.NewTxOutput(assetID, 50, mustDecodeHex("a9145881cd104f8d64635751ac0f3c0decf9150c110687"), nil),
136                         },
137                 }),
138                 legacy.NewTx(legacy.TxData{
139                         Version: 1,
140                         MinTime: 233400000000,
141                         MaxTime: 233400000001,
142                         Inputs: []*legacy.TxInput{
143                                 legacy.NewIssuanceInput([]byte{2}, 50, nil, initialBlockHash, nil, [][]byte{
144                                         nil,
145                                         mustDecodeHex("3045022100f3bcffcfd6a1ce9542b653500386cd0ee7b9c86c59390ca0fc0238c0ebe3f1d6022065ac468a51a016842660c3a616c99a9aa5109a3bad1877ba3e0f010f3972472e01"),
146                                         mustDecodeHex("51210210b002870438af79b829bc22c4505e14779ef0080c411ad497d7a0846ee0af6f51ae"),
147                                 }, nil),
148                         },
149                         Outputs: []*legacy.TxOutput{
150                                 legacy.NewTxOutput(assetID, 50, mustDecodeHex("a914c171e443e05b953baa7b7d834028ed91e47b4d0b87"), nil),
151                         },
152                 }),
153         }
154
155         got, _, err := c.GenerateBlock(ctx, b1, state.Empty(), now, txs)
156         if err != nil {
157                 t.Fatalf("err got = %v want nil", err)
158         }
159
160         // TODO(bobg): verify these hashes are correct
161         wantTxRoot := mustDecodeHash("ab5f5f111beb1e6b49da8334360589c7da3aac1cdd61067ea9a55bec47cb745c")
162         wantAssetsRoot := mustDecodeHash("a31a9b5f71a6d6fa0c87361db4a98c9a82f603f9d9ff584f6613b9d56ccf5ebd")
163
164         want := &legacy.Block{
165                 BlockHeader: legacy.BlockHeader{
166                         Version:           1,
167                         Height:            2,
168                         PreviousBlockHash: b1.Hash(),
169                         TimestampMS:       bc.Millis(now),
170                         BlockCommitment: legacy.BlockCommitment{
171                                 TransactionsMerkleRoot: wantTxRoot,
172                                 AssetsMerkleRoot:       wantAssetsRoot,
173                         },
174                 },
175                 Transactions: txs,
176         }
177
178         if !testutil.DeepEqual(got, want) {
179                 t.Errorf("generated block:\ngot:  %+v\nwant: %+v", got, want)
180         }
181 }
182
183 // newTestChain returns a new Chain using memstore for storage,
184 // along with an initial block b1 (with a 0/0 multisig program).
185 // It commits b1 before returning.
186 func newTestChain(tb testing.TB, ts time.Time) (c *Chain, b1 *legacy.Block) {
187         ctx := context.Background()
188
189         var err error
190
191         b1, err = NewInitialBlock(ts)
192         if err != nil {
193                 testutil.FatalErr(tb, err)
194         }
195         c, err = NewChain(ctx, b1.Hash(), memstore.New(), nil)
196         if err != nil {
197                 testutil.FatalErr(tb, err)
198         }
199         // TODO(tessr): consider adding MaxIssuanceWindow to NewChain
200         c.MaxIssuanceWindow = 48 * time.Hour
201         err = c.CommitAppliedBlock(ctx, b1, state.Empty())
202         if err != nil {
203                 testutil.FatalErr(tb, err)
204         }
205         return c, b1
206 }
207
208 func makeEmptyBlock(tb testing.TB, c *Chain) {
209         ctx := context.Background()
210
211         curBlock, err := c.GetBlock(ctx, c.Height())
212         if err != nil {
213                 testutil.FatalErr(tb, err)
214         }
215
216         if len(curBlock.Transactions) > 0 {
217                 tb.Fatal("cannot make nonempty block")
218         }
219
220         curState := state.Empty()
221
222         nextBlock, nextState, err := c.GenerateBlock(ctx, curBlock, curState, time.Now(), nil)
223         if err != nil {
224                 testutil.FatalErr(tb, err)
225         }
226         err = c.CommitAppliedBlock(ctx, nextBlock, nextState)
227         if err != nil {
228                 testutil.FatalErr(tb, err)
229         }
230 }
231
232 func mustDecodeHex(s string) []byte {
233         data, err := hex.DecodeString(s)
234         if err != nil {
235                 panic(err)
236         }
237         return data
238 }
239
240 func mustDecodeHash(s string) (h bc.Hash) {
241         err := h.UnmarshalText([]byte(s))
242         if err != nil {
243                 panic(err)
244         }
245         return h
246 }*/