Skip to content

Commit 0b8baab

Browse files
Simplify test block creation (#4095)
1 parent 3fd29b9 commit 0b8baab

File tree

3 files changed

+88
-156
lines changed

3 files changed

+88
-156
lines changed

simplex/block.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,7 @@ func (bt *blockTracker) verifyAndTrackBlock(ctx context.Context, block *Block) e
172172
return nil
173173
}
174174

175-
// verify the block
176-
err := block.vmBlock.Verify(ctx)
177-
if err != nil {
175+
if err := block.vmBlock.Verify(ctx); err != nil {
178176
return fmt.Errorf("failed to verify block: %w", err)
179177
}
180178

simplex/block_test.go

Lines changed: 57 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/ava-labs/simplex"
1414
"github.com/stretchr/testify/require"
1515

16+
"github.com/ava-labs/avalanchego/ids"
1617
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
1718
"github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmantest"
1819
"github.com/ava-labs/avalanchego/snow/engine/enginetest"
@@ -103,13 +104,11 @@ func TestBlockSerialization(t *testing.T) {
103104
func TestVerifyPrevNotFound(t *testing.T) {
104105
ctx := context.Background()
105106

106-
tracker := newBlockTracker(newBlock(t, nil))
107-
b := newBlock(t, &testBlockConfig{
108-
blockTracker: tracker,
109-
round: 1,
110-
seq: 1,
111-
prev: [32]byte{0x00, 0x012}, // Invalid prev digest
107+
genesis := newBlock(t, newBlockConfig{})
108+
b := newBlock(t, newBlockConfig{
109+
prev: genesis,
112110
})
111+
b.metadata.Prev[0]++ // Invalid prev digest
113112

114113
_, err := b.Verify(ctx)
115114
require.ErrorIs(t, err, errDigestNotFound)
@@ -119,7 +118,11 @@ func TestVerifyPrevNotFound(t *testing.T) {
119118
// have its Verify method called once, even if Verify is called multiple times.
120119
func TestVerifyTwice(t *testing.T) {
121120
ctx := context.Background()
122-
b := newBlock(t, nil)
121+
122+
genesis := newBlock(t, newBlockConfig{})
123+
b := newBlock(t, newBlockConfig{
124+
prev: genesis,
125+
})
123126

124127
// Verify the block for the first time
125128
_, err := b.Verify(ctx)
@@ -135,15 +138,18 @@ func TestVerifyTwice(t *testing.T) {
135138
func TestVerifyGenesis(t *testing.T) {
136139
ctx := context.Background()
137140

138-
// Verify the block for the first time
139-
_, err := newGenesisBlock(t).Verify(ctx)
141+
genesis := newBlock(t, newBlockConfig{})
142+
_, err := genesis.Verify(ctx)
140143
require.ErrorIs(t, err, errGenesisVerification)
141144
}
142145

143146
func TestVerify(t *testing.T) {
144147
ctx := context.Background()
145148

146-
b := newBlock(t, nil)
149+
genesis := newBlock(t, newBlockConfig{})
150+
b := newBlock(t, newBlockConfig{
151+
prev: genesis,
152+
})
147153

148154
verifiedBlock, err := b.Verify(ctx)
149155
require.NoError(t, err)
@@ -157,139 +163,87 @@ func TestVerify(t *testing.T) {
157163
require.Equal(t, blockBytes, vBlockBytes, "block bytes should match after verification")
158164
}
159165

160-
// TestVerifyPrevIsLatest tests that a block with a prev digest that is not found in the block tracker
161-
// successfully verifies the block if it is the latest accepted block.
162-
func TestVerifyPrevIsLatest(t *testing.T) {
163-
ctx := context.Background()
164-
165-
b := newBlock(t, nil)
166-
tracker := b.blockTracker
167-
168-
_, err := b.Verify(ctx)
169-
require.NoError(t, err)
170-
171-
require.NoError(t, tracker.indexBlock(ctx, b.digest))
172-
require.Equal(t, snowtest.Accepted, b.vmBlock.(*snowmantest.Block).Decidable.Status)
173-
174-
// Ensure future blocks are verified on the new last accepted id and digest
175-
nextVMBlock := snowmantest.BuildChild(b.vmBlock.(*snowmantest.Block))
176-
nextBlock := newBlock(t, &testBlockConfig{
177-
vmBlock: nextVMBlock,
178-
blockTracker: tracker,
179-
round: 2,
180-
seq: 2,
181-
prev: b.digest,
182-
})
183-
184-
_, err = nextBlock.Verify(ctx)
185-
require.NoError(t, err)
186-
require.NoError(t, tracker.indexBlock(ctx, nextBlock.digest))
187-
require.Equal(t, snowtest.Accepted, nextVMBlock.Decidable.Status)
188-
}
189-
190-
// TestVerifyParentAccepted tests that a block, whose parent has been verified and indexed, can
191-
// also be verified and indexed successfully.
166+
// TestVerifyParentAccepted tests that a block, whose parent has been verified
167+
// and indexed, can also be verified and indexed successfully.
192168
func TestVerifyParentAccepted(t *testing.T) {
193169
ctx := context.Background()
194170

195-
seq1Block := newBlock(t, nil)
196-
tracker := seq1Block.blockTracker
197-
198-
vmBlock2 := snowmantest.BuildChild(seq1Block.vmBlock.(*snowmantest.Block))
199-
seq2Block := newBlock(t, &testBlockConfig{
200-
vmBlock: vmBlock2,
201-
blockTracker: tracker,
202-
round: 2,
203-
seq: 2,
204-
prev: seq1Block.digest,
171+
genesis := newBlock(t, newBlockConfig{})
172+
seq1Block := newBlock(t, newBlockConfig{
173+
prev: genesis,
174+
})
175+
seq2Block := newBlock(t, newBlockConfig{
176+
prev: seq1Block,
205177
})
206178

207179
_, err := seq1Block.Verify(ctx)
208180
require.NoError(t, err)
209-
210-
require.NoError(t, tracker.indexBlock(ctx, seq1Block.digest))
181+
require.NoError(t, seq1Block.blockTracker.indexBlock(ctx, seq1Block.digest))
211182
require.Equal(t, snowtest.Accepted, seq1Block.vmBlock.(*snowmantest.Block).Decidable.Status)
212183

213184
// Verify the second block with the first block as its parent
214185
_, err = seq2Block.Verify(ctx)
215186
require.NoError(t, err)
216-
require.NoError(t, tracker.indexBlock(ctx, seq2Block.digest))
217-
require.Equal(t, snowtest.Accepted, vmBlock2.Decidable.Status)
187+
require.NoError(t, seq2Block.blockTracker.indexBlock(ctx, seq2Block.digest))
188+
require.Equal(t, snowtest.Accepted, seq2Block.vmBlock.(*snowmantest.Block).Decidable.Status)
218189

219190
// ensure tracker cleans up the block
220-
require.Nil(t, tracker.simplexDigestsToBlock[seq1Block.digest])
191+
require.NotContains(t, genesis.blockTracker.simplexDigestsToBlock, seq1Block.digest)
221192
}
222193

223194
func TestVerifyBlockRejectsSiblings(t *testing.T) {
224195
ctx := context.Background()
225-
genesisBlock := newGenesisBlock(t)
226-
genesisChild0 := snowmantest.BuildChild(snowmantest.Genesis)
227-
genesisChild1 := snowmantest.BuildChild(snowmantest.Genesis)
228-
229-
// round1Block and round2Block are siblings, both children of seq0
230-
// this can happen if we notarize a block for round 1, but the rest
231-
// of the network notarizes a dummy block for round 1. Then
232-
// we will verify a sibling block for round 2 and must reject the round 1 block.
233-
round1Block := newBlock(t, &testBlockConfig{
234-
vmBlock: genesisChild0,
235-
seq: 1,
236-
round: 1,
237-
prev: genesisBlock.digest,
238-
})
239-
240-
tracker := round1Block.blockTracker
241196

242-
round2Block := newBlock(t, &testBlockConfig{
243-
vmBlock: genesisChild1,
244-
blockTracker: tracker,
245-
seq: 1,
246-
round: 2,
247-
prev: genesisBlock.digest,
197+
genesis := newBlock(t, newBlockConfig{})
198+
// genesisChild0 and genesisChild1 are siblings, both children of genesis.
199+
// This can happen if we verify a block for round 1, but the network
200+
// notarizes the dummy block. Then we will verify a sibling block for round
201+
// 2 and must reject the round 1 block.
202+
genesisChild0 := newBlock(t, newBlockConfig{
203+
prev: genesis,
204+
})
205+
genesisChild1 := newBlock(t, newBlockConfig{
206+
prev: genesis,
207+
round: genesisChild0.metadata.Round + 1,
248208
})
249209

250210
// Verify the second block with the first block as its parent
251-
_, err := round1Block.Verify(ctx)
211+
_, err := genesisChild0.Verify(ctx)
252212
require.NoError(t, err)
253-
_, err = round2Block.Verify(ctx)
213+
_, err = genesisChild1.Verify(ctx)
254214
require.NoError(t, err)
255215

256216
// When the we index the second block, the first block should be rejected
257-
require.NoError(t, tracker.indexBlock(ctx, round2Block.digest))
258-
require.Equal(t, snowtest.Rejected, round1Block.vmBlock.(*snowmantest.Block).Decidable.Status)
259-
require.Equal(t, snowtest.Accepted, round2Block.vmBlock.(*snowmantest.Block).Decidable.Status)
217+
require.NoError(t, genesis.blockTracker.indexBlock(ctx, genesisChild1.digest))
218+
require.Equal(t, snowtest.Rejected, genesisChild0.vmBlock.(*snowmantest.Block).Decidable.Status)
219+
require.Equal(t, snowtest.Accepted, genesisChild1.vmBlock.(*snowmantest.Block).Decidable.Status)
260220

261-
_, exists := tracker.getBlockByDigest(genesisBlock.digest)
221+
_, exists := genesis.blockTracker.getBlockByDigest(genesis.digest)
262222
require.False(t, exists)
263223
}
264224

265225
func TestVerifyInnerBlockBreaksHashChain(t *testing.T) {
266226
ctx := context.Background()
267227

268-
// We verify this valid block
269-
seq1Block := newBlock(t, nil)
270-
tracker := seq1Block.blockTracker
228+
genesis := newBlock(t, newBlockConfig{})
229+
b := newBlock(t, newBlockConfig{
230+
prev: genesis,
231+
})
271232

272-
_, err := seq1Block.Verify(ctx)
273-
require.NoError(t, err)
233+
// This block does not extend the genesis, however it has a valid previous
234+
// digest.
235+
b.vmBlock.(*snowmantest.Block).ParentV[0]++
274236

275-
// This block does not extend seq1, however it has a valid previous digest(since seq1Block was verified)
276-
seq2 := snowmantest.BuildChild(snowmantest.Genesis)
277-
seq2Block := newBlock(t, &testBlockConfig{
278-
vmBlock: seq2,
279-
blockTracker: tracker,
280-
round: 2,
281-
seq: 2,
282-
prev: seq1Block.digest,
283-
})
284-
_, err = seq2Block.Verify(ctx)
237+
_, err := b.Verify(ctx)
285238
require.ErrorIs(t, err, errMismatchedPrevDigest)
286239
}
287240

288241
func TestIndexBlockDigestNotFound(t *testing.T) {
289-
tracker := newBlockTracker(newBlock(t, nil))
290242
ctx := context.Background()
291243

292-
seq1Block := newBlock(t, nil)
293-
err := tracker.indexBlock(ctx, seq1Block.digest)
244+
genesis := newBlock(t, newBlockConfig{})
245+
246+
unknownDigest := ids.GenerateTestID()
247+
err := genesis.blockTracker.indexBlock(ctx, simplex.Digest(unknownDigest))
294248
require.ErrorIs(t, err, errDigestNotFound)
295249
}

simplex/util_test.go

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,72 +10,53 @@ import (
1010
"github.com/stretchr/testify/require"
1111

1212
"github.com/ava-labs/avalanchego/ids"
13-
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
1413
"github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmantest"
1514
"github.com/ava-labs/avalanchego/snow/validators"
1615
"github.com/ava-labs/avalanchego/utils/constants"
1716
"github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner"
1817
)
1918

20-
type testBlockConfig struct {
21-
vmBlock snowman.Block
22-
blockTracker *blockTracker
23-
round uint64
24-
seq uint64
25-
prev simplex.Digest
19+
type newBlockConfig struct {
20+
// If prev is nil, newBlock will create the genesis block
21+
prev *Block
22+
// If round is 0, it will be set to one higher than the prev's round
23+
round uint64
2624
}
2725

28-
// newBlock constructs a random child block of the genesis. This is a helper function
29-
// used for testing. This is helpful since otherwise we would
30-
// need the blockDeserializer to create the block.
31-
func newBlock(t *testing.T, config *testBlockConfig) *Block {
32-
genesisBlock := newGenesisBlock(t)
33-
34-
if config == nil {
35-
config = &testBlockConfig{
36-
vmBlock: snowmantest.BuildChild(snowmantest.Genesis),
37-
blockTracker: newBlockTracker(genesisBlock),
38-
round: 1,
39-
seq: 1,
40-
prev: genesisBlock.digest,
26+
func newBlock(t *testing.T, config newBlockConfig) *Block {
27+
if config.prev == nil {
28+
block := &Block{
29+
vmBlock: snowmantest.Genesis,
30+
metadata: simplex.ProtocolMetadata{
31+
Version: 1,
32+
Epoch: 1,
33+
Round: 0,
34+
Seq: 0,
35+
},
4136
}
37+
bytes, err := block.Bytes()
38+
require.NoError(t, err)
39+
40+
digest := computeDigest(bytes)
41+
block.digest = digest
42+
43+
block.blockTracker = newBlockTracker(block)
44+
return block
4245
}
43-
if config.blockTracker == nil {
44-
config.blockTracker = newBlockTracker(genesisBlock)
45-
}
46-
if config.vmBlock == nil {
47-
config.vmBlock = snowmantest.BuildChild(snowmantest.Genesis)
46+
if config.round == 0 {
47+
config.round = config.prev.metadata.Round + 1
4848
}
4949

50+
vmBlock := snowmantest.BuildChild(config.prev.vmBlock.(*snowmantest.Block))
5051
block := &Block{
51-
vmBlock: config.vmBlock,
52-
blockTracker: config.blockTracker,
52+
vmBlock: vmBlock,
53+
blockTracker: config.prev.blockTracker,
5354
metadata: simplex.ProtocolMetadata{
5455
Version: 1,
5556
Epoch: 1,
5657
Round: config.round,
57-
Seq: config.seq,
58-
Prev: config.prev,
59-
},
60-
}
61-
62-
bytes, err := block.Bytes()
63-
require.NoError(t, err)
64-
65-
digest := computeDigest(bytes)
66-
block.digest = digest
67-
68-
return block
69-
}
70-
71-
func newGenesisBlock(t *testing.T) *Block {
72-
block := &Block{
73-
vmBlock: snowmantest.Genesis,
74-
metadata: simplex.ProtocolMetadata{
75-
Version: 1,
76-
Epoch: 1,
77-
Round: 0,
78-
Seq: 0,
58+
Seq: vmBlock.Height(),
59+
Prev: config.prev.digest,
7960
},
8061
}
8162

@@ -84,7 +65,6 @@ func newGenesisBlock(t *testing.T) *Block {
8465

8566
digest := computeDigest(bytes)
8667
block.digest = digest
87-
8868
return block
8969
}
9070

0 commit comments

Comments
 (0)