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