github.com/MetalBlockchain/metalgo@v1.11.9/vms/metervm/block_vm.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package metervm 5 6 import ( 7 "context" 8 9 "github.com/prometheus/client_golang/prometheus" 10 11 "github.com/MetalBlockchain/metalgo/database" 12 "github.com/MetalBlockchain/metalgo/ids" 13 "github.com/MetalBlockchain/metalgo/snow" 14 "github.com/MetalBlockchain/metalgo/snow/consensus/snowman" 15 "github.com/MetalBlockchain/metalgo/snow/engine/common" 16 "github.com/MetalBlockchain/metalgo/snow/engine/snowman/block" 17 "github.com/MetalBlockchain/metalgo/utils/timer/mockable" 18 ) 19 20 var ( 21 _ block.ChainVM = (*blockVM)(nil) 22 _ block.BuildBlockWithContextChainVM = (*blockVM)(nil) 23 _ block.BatchedChainVM = (*blockVM)(nil) 24 _ block.StateSyncableVM = (*blockVM)(nil) 25 ) 26 27 type blockVM struct { 28 block.ChainVM 29 buildBlockVM block.BuildBlockWithContextChainVM 30 batchedVM block.BatchedChainVM 31 ssVM block.StateSyncableVM 32 33 blockMetrics 34 registry prometheus.Registerer 35 clock mockable.Clock 36 } 37 38 func NewBlockVM( 39 vm block.ChainVM, 40 reg prometheus.Registerer, 41 ) block.ChainVM { 42 buildBlockVM, _ := vm.(block.BuildBlockWithContextChainVM) 43 batchedVM, _ := vm.(block.BatchedChainVM) 44 ssVM, _ := vm.(block.StateSyncableVM) 45 return &blockVM{ 46 ChainVM: vm, 47 buildBlockVM: buildBlockVM, 48 batchedVM: batchedVM, 49 ssVM: ssVM, 50 registry: reg, 51 } 52 } 53 54 func (vm *blockVM) Initialize( 55 ctx context.Context, 56 chainCtx *snow.Context, 57 db database.Database, 58 genesisBytes, 59 upgradeBytes, 60 configBytes []byte, 61 toEngine chan<- common.Message, 62 fxs []*common.Fx, 63 appSender common.AppSender, 64 ) error { 65 err := vm.blockMetrics.Initialize( 66 vm.buildBlockVM != nil, 67 vm.batchedVM != nil, 68 vm.ssVM != nil, 69 vm.registry, 70 ) 71 if err != nil { 72 return err 73 } 74 75 return vm.ChainVM.Initialize(ctx, chainCtx, db, genesisBytes, upgradeBytes, configBytes, toEngine, fxs, appSender) 76 } 77 78 func (vm *blockVM) BuildBlock(ctx context.Context) (snowman.Block, error) { 79 start := vm.clock.Time() 80 blk, err := vm.ChainVM.BuildBlock(ctx) 81 end := vm.clock.Time() 82 duration := float64(end.Sub(start)) 83 if err != nil { 84 vm.blockMetrics.buildBlockErr.Observe(duration) 85 return nil, err 86 } 87 vm.blockMetrics.buildBlock.Observe(duration) 88 return &meterBlock{ 89 Block: blk, 90 vm: vm, 91 }, nil 92 } 93 94 func (vm *blockVM) ParseBlock(ctx context.Context, b []byte) (snowman.Block, error) { 95 start := vm.clock.Time() 96 blk, err := vm.ChainVM.ParseBlock(ctx, b) 97 end := vm.clock.Time() 98 duration := float64(end.Sub(start)) 99 if err != nil { 100 vm.blockMetrics.parseBlockErr.Observe(duration) 101 return nil, err 102 } 103 vm.blockMetrics.parseBlock.Observe(duration) 104 return &meterBlock{ 105 Block: blk, 106 vm: vm, 107 }, nil 108 } 109 110 func (vm *blockVM) GetBlock(ctx context.Context, id ids.ID) (snowman.Block, error) { 111 start := vm.clock.Time() 112 blk, err := vm.ChainVM.GetBlock(ctx, id) 113 end := vm.clock.Time() 114 duration := float64(end.Sub(start)) 115 if err != nil { 116 vm.blockMetrics.getBlockErr.Observe(duration) 117 return nil, err 118 } 119 vm.blockMetrics.getBlock.Observe(duration) 120 return &meterBlock{ 121 Block: blk, 122 vm: vm, 123 }, nil 124 } 125 126 func (vm *blockVM) SetPreference(ctx context.Context, id ids.ID) error { 127 start := vm.clock.Time() 128 err := vm.ChainVM.SetPreference(ctx, id) 129 end := vm.clock.Time() 130 vm.blockMetrics.setPreference.Observe(float64(end.Sub(start))) 131 return err 132 } 133 134 func (vm *blockVM) LastAccepted(ctx context.Context) (ids.ID, error) { 135 start := vm.clock.Time() 136 lastAcceptedID, err := vm.ChainVM.LastAccepted(ctx) 137 end := vm.clock.Time() 138 vm.blockMetrics.lastAccepted.Observe(float64(end.Sub(start))) 139 return lastAcceptedID, err 140 } 141 142 func (vm *blockVM) GetBlockIDAtHeight(ctx context.Context, height uint64) (ids.ID, error) { 143 start := vm.clock.Time() 144 blockID, err := vm.ChainVM.GetBlockIDAtHeight(ctx, height) 145 end := vm.clock.Time() 146 vm.blockMetrics.getBlockIDAtHeight.Observe(float64(end.Sub(start))) 147 return blockID, err 148 }