-
Notifications
You must be signed in to change notification settings - Fork 662
/
block.go
104 lines (86 loc) · 2.56 KB
/
block.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package executor
import (
"context"
"fmt"
"time"
"go.uber.org/zap"
"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/snow/choices"
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
"github.com/ava-labs/avalanchego/vms/platformvm/block"
)
var (
_ snowman.Block = (*Block)(nil)
_ snowman.OracleBlock = (*Block)(nil)
)
// Exported for testing in platformvm package.
type Block struct {
block.Block
manager *manager
}
func (b *Block) Verify(context.Context) error {
blkID := b.ID()
if _, ok := b.manager.blkIDToState[blkID]; ok {
// This block has already been verified.
return nil
}
return b.Visit(b.manager.verifier)
}
func (b *Block) Accept(context.Context) error {
return b.Visit(b.manager.acceptor)
}
func (b *Block) Reject(context.Context) error {
return b.Visit(b.manager.rejector)
}
func (b *Block) Status() choices.Status {
blkID := b.ID()
// If this block is an accepted Proposal block with no accepted children, it
// will be in [blkIDToState], but we should return accepted, not processing,
// so we do this check.
if b.manager.lastAccepted == blkID {
return choices.Accepted
}
// Check if the block is in memory. If so, it's processing.
if _, ok := b.manager.blkIDToState[blkID]; ok {
return choices.Processing
}
// Block isn't in memory. Check in the database.
_, err := b.manager.state.GetStatelessBlock(blkID)
switch err {
case nil:
return choices.Accepted
case database.ErrNotFound:
// choices.Unknown means we don't have the bytes of the block.
// In this case, we do, so we return choices.Processing.
return choices.Processing
default:
// TODO: correctly report this error to the consensus engine.
b.manager.ctx.Log.Error(
"dropping unhandled database error",
zap.Error(err),
)
return choices.Processing
}
}
func (b *Block) Timestamp() time.Time {
return b.manager.getTimestamp(b.ID())
}
func (b *Block) Options(context.Context) ([2]snowman.Block, error) {
options := options{}
if err := b.Block.Visit(&options); err != nil {
return [2]snowman.Block{}, err
}
commitBlock := b.manager.NewBlock(options.commitBlock)
abortBlock := b.manager.NewBlock(options.abortBlock)
blkID := b.ID()
blkState, ok := b.manager.blkIDToState[blkID]
if !ok {
return [2]snowman.Block{}, fmt.Errorf("block %s state not found", blkID)
}
if blkState.initiallyPreferCommit {
return [2]snowman.Block{commitBlock, abortBlock}, nil
}
return [2]snowman.Block{abortBlock, commitBlock}, nil
}