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  }