9 "github.com/bytom/protocol/bc"
10 "github.com/bytom/protocol/bc/legacy"
11 "github.com/bytom/protocol/prottest/memstore"
12 "github.com/bytom/protocol/state"
13 "github.com/bytom/testutil"
16 func TestGetBlock(t *testing.T) {
17 ctx := context.Background()
19 b1 := &legacy.Block{BlockHeader: legacy.BlockHeader{Height: 1}}
20 noBlocks := memstore.New()
21 oneBlock := memstore.New()
22 oneBlock.SaveBlock(ctx, b1)
23 oneBlock.SaveSnapshot(ctx, 1, state.Empty())
30 {noBlocks, nil, true},
31 {oneBlock, b1, false},
34 for _, test := range cases {
35 c, err := NewChain(ctx, b1.Hash(), test.store, nil)
37 testutil.FatalErr(t, err)
39 got, gotErr := c.GetBlock(ctx, c.Height())
40 if !testutil.DeepEqual(got, test.want) {
41 t.Errorf("got latest = %+v want %+v", got, test.want)
43 if (gotErr != nil) != test.wantErr {
44 t.Errorf("got latest err = %q want err?: %t", gotErr, test.wantErr)
49 func TestNoTimeTravel(t *testing.T) {
50 ctx := context.Background()
51 c, err := NewChain(ctx, bc.Hash{}, memstore.New(), nil)
59 c.setHeight(1) // don't go backward
60 if c.state.height != 2 {
61 t.Fatalf("c.state.height = %d want 2", c.state.height)
65 func TestWaitForBlockSoonAlreadyExists(t *testing.T) {
66 c, _ := newTestChain(t, time.Now())
67 makeEmptyBlock(t, c) // height=2
68 makeEmptyBlock(t, c) // height=3
70 err := <-c.BlockSoonWaiter(context.Background(), 2)
76 func TestWaitForBlockSoonDistantFuture(t *testing.T) {
77 c, _ := newTestChain(t, time.Now())
79 got := <-c.BlockSoonWaiter(context.Background(), 100) // distant future
80 want := ErrTheDistantFuture
82 t.Errorf("BlockSoonWaiter(100) = %+v want %+v", got, want)
86 func TestWaitForBlockSoonWaits(t *testing.T) {
87 // This test is inherently racy. It's possible
88 // that the block creation might run before
89 // the wait's internal test loop finds no block.
90 // In that case, the test will pass, but it will
91 // not have tested anything.
93 // It's the best we can do.
95 c, _ := newTestChain(t, time.Now())
96 makeEmptyBlock(t, c) // height=2
99 time.Sleep(10 * time.Millisecond) // sorry for the slow test
100 makeEmptyBlock(t, c) // height=3
103 err := <-c.BlockSoonWaiter(context.Background(), 3)
107 if g := c.Height(); g != 3 {
108 t.Errorf("height after waiting = %d want 3", g)
112 func TestWaitForBlockSoonTimesout(t *testing.T) {
113 c, _ := newTestChain(t, time.Now())
115 makeEmptyBlock(t, c) // height=2
118 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
121 err := <-c.BlockSoonWaiter(ctx, 3)
122 if err != ctx.Err() {
123 t.Fatalf("expected timeout err, got %v", err)
127 func TestGenerateBlock(t *testing.T) {
128 ctx := context.Background()
129 now := time.Unix(233400000, 0)
130 c, b1 := newTestChain(t, now)
132 initialBlockHash := b1.Hash()
133 assetID := bc.ComputeAssetID(nil, &initialBlockHash, 1, &bc.EmptyStringHash)
136 legacy.NewTx(legacy.TxData{
138 MinTime: 233400000000,
139 MaxTime: 233400000001,
140 Inputs: []*legacy.TxInput{
141 legacy.NewIssuanceInput([]byte{1}, 50, nil, initialBlockHash, nil, [][]byte{
143 mustDecodeHex("30450221009037e1d39b7d59d24eba8012baddd5f4ab886a51b46f52b7c479ddfa55eeb5c5022076008409243475b25dfba6db85e15cf3d74561a147375941e4830baa69769b5101"),
144 mustDecodeHex("51210210b002870438af79b829bc22c4505e14779ef0080c411ad497d7a0846ee0af6f51ae")}, nil),
146 Outputs: []*legacy.TxOutput{
147 legacy.NewTxOutput(assetID, 50, mustDecodeHex("a9145881cd104f8d64635751ac0f3c0decf9150c110687"), nil),
150 legacy.NewTx(legacy.TxData{
152 MinTime: 233400000000,
153 MaxTime: 233400000001,
154 Inputs: []*legacy.TxInput{
155 legacy.NewIssuanceInput([]byte{2}, 50, nil, initialBlockHash, nil, [][]byte{
157 mustDecodeHex("3045022100f3bcffcfd6a1ce9542b653500386cd0ee7b9c86c59390ca0fc0238c0ebe3f1d6022065ac468a51a016842660c3a616c99a9aa5109a3bad1877ba3e0f010f3972472e01"),
158 mustDecodeHex("51210210b002870438af79b829bc22c4505e14779ef0080c411ad497d7a0846ee0af6f51ae"),
161 Outputs: []*legacy.TxOutput{
162 legacy.NewTxOutput(assetID, 50, mustDecodeHex("a914c171e443e05b953baa7b7d834028ed91e47b4d0b87"), nil),
167 got, _, err := c.GenerateBlock(ctx, b1, state.Empty(), now, txs)
169 t.Fatalf("err got = %v want nil", err)
172 // TODO(bobg): verify these hashes are correct
173 wantTxRoot := mustDecodeHash("ab5f5f111beb1e6b49da8334360589c7da3aac1cdd61067ea9a55bec47cb745c")
174 wantAssetsRoot := mustDecodeHash("a31a9b5f71a6d6fa0c87361db4a98c9a82f603f9d9ff584f6613b9d56ccf5ebd")
176 want := &legacy.Block{
177 BlockHeader: legacy.BlockHeader{
180 PreviousBlockHash: b1.Hash(),
181 TimestampMS: bc.Millis(now),
182 BlockCommitment: legacy.BlockCommitment{
183 TransactionsMerkleRoot: wantTxRoot,
184 AssetsMerkleRoot: wantAssetsRoot,
185 ConsensusProgram: b1.ConsensusProgram,
191 if !testutil.DeepEqual(got, want) {
192 t.Errorf("generated block:\ngot: %+v\nwant: %+v", got, want)
196 func TestValidateBlockForSig(t *testing.T) {
197 initialBlock, err := NewInitialBlock(testutil.TestPubs, 1, time.Now())
199 t.Fatal("unexpected error ", err)
202 ctx := context.Background()
203 c, err := NewChain(ctx, initialBlock.Hash(), memstore.New(), nil)
205 t.Fatal("unexpected error ", err)
208 err = c.ValidateBlockForSig(ctx, initialBlock)
210 t.Error("unexpected error ", err)
214 // newTestChain returns a new Chain using memstore for storage,
215 // along with an initial block b1 (with a 0/0 multisig program).
216 // It commits b1 before returning.
217 func newTestChain(tb testing.TB, ts time.Time) (c *Chain, b1 *legacy.Block) {
218 ctx := context.Background()
222 b1, err = NewInitialBlock(nil, 0, ts)
224 testutil.FatalErr(tb, err)
226 c, err = NewChain(ctx, b1.Hash(), memstore.New(), nil)
228 testutil.FatalErr(tb, err)
230 // TODO(tessr): consider adding MaxIssuanceWindow to NewChain
231 c.MaxIssuanceWindow = 48 * time.Hour
232 err = c.CommitAppliedBlock(ctx, b1, state.Empty())
234 testutil.FatalErr(tb, err)
239 func makeEmptyBlock(tb testing.TB, c *Chain) {
240 ctx := context.Background()
242 curBlock, err := c.GetBlock(ctx, c.Height())
244 testutil.FatalErr(tb, err)
247 if len(curBlock.Transactions) > 0 {
248 tb.Fatal("cannot make nonempty block")
251 curState := state.Empty()
253 nextBlock, nextState, err := c.GenerateBlock(ctx, curBlock, curState, time.Now(), nil)
255 testutil.FatalErr(tb, err)
257 err = c.CommitAppliedBlock(ctx, nextBlock, nextState)
259 testutil.FatalErr(tb, err)
263 func mustDecodeHex(s string) []byte {
264 data, err := hex.DecodeString(s)
271 func mustDecodeHash(s string) (h bc.Hash) {
272 err := h.UnmarshalText([]byte(s))