github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/environment/block_info.go (about)

     1  package environment
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/cadence/runtime"
     7  
     8  	"github.com/onflow/flow-go/fvm/errors"
     9  	"github.com/onflow/flow-go/fvm/storage"
    10  	"github.com/onflow/flow-go/fvm/tracing"
    11  	"github.com/onflow/flow-go/model/flow"
    12  	"github.com/onflow/flow-go/module/trace"
    13  	storageErr "github.com/onflow/flow-go/storage"
    14  )
    15  
    16  type BlockInfo interface {
    17  	// GetCurrentBlockHeight returns the current block height.
    18  	GetCurrentBlockHeight() (uint64, error)
    19  
    20  	// GetBlockAtHeight returns the block at the given height.
    21  	GetBlockAtHeight(
    22  		height uint64,
    23  	) (
    24  		runtime.Block,
    25  		bool,
    26  		error,
    27  	)
    28  }
    29  
    30  type ParseRestrictedBlockInfo struct {
    31  	txnState storage.TransactionPreparer
    32  	impl     BlockInfo
    33  }
    34  
    35  func NewParseRestrictedBlockInfo(
    36  	txnState storage.TransactionPreparer,
    37  	impl BlockInfo,
    38  ) BlockInfo {
    39  	return ParseRestrictedBlockInfo{
    40  		txnState: txnState,
    41  		impl:     impl,
    42  	}
    43  }
    44  
    45  func (info ParseRestrictedBlockInfo) GetCurrentBlockHeight() (uint64, error) {
    46  	return parseRestrict1Ret(
    47  		info.txnState,
    48  		trace.FVMEnvGetCurrentBlockHeight,
    49  		info.impl.GetCurrentBlockHeight)
    50  }
    51  
    52  func (info ParseRestrictedBlockInfo) GetBlockAtHeight(
    53  	height uint64,
    54  ) (
    55  	runtime.Block,
    56  	bool,
    57  	error,
    58  ) {
    59  	return parseRestrict1Arg2Ret(
    60  		info.txnState,
    61  		trace.FVMEnvGetBlockAtHeight,
    62  		info.impl.GetBlockAtHeight,
    63  		height)
    64  }
    65  
    66  type BlockInfoParams struct {
    67  	Blocks      Blocks
    68  	BlockHeader *flow.Header
    69  }
    70  
    71  func DefaultBlockInfoParams() BlockInfoParams {
    72  	return BlockInfoParams{
    73  		Blocks:      nil,
    74  		BlockHeader: nil,
    75  	}
    76  }
    77  
    78  type blockInfo struct {
    79  	tracer tracing.TracerSpan
    80  	meter  Meter
    81  
    82  	blockHeader *flow.Header
    83  	blocks      Blocks
    84  }
    85  
    86  func NewBlockInfo(
    87  	tracer tracing.TracerSpan,
    88  	meter Meter,
    89  	blockHeader *flow.Header,
    90  	blocks Blocks,
    91  ) BlockInfo {
    92  	return &blockInfo{
    93  		tracer:      tracer,
    94  		meter:       meter,
    95  		blockHeader: blockHeader,
    96  		blocks:      blocks,
    97  	}
    98  }
    99  
   100  // GetCurrentBlockHeight returns the current block height.
   101  func (info *blockInfo) GetCurrentBlockHeight() (uint64, error) {
   102  	defer info.tracer.StartExtensiveTracingChildSpan(
   103  		trace.FVMEnvGetCurrentBlockHeight).End()
   104  
   105  	err := info.meter.MeterComputation(
   106  		ComputationKindGetCurrentBlockHeight,
   107  		1)
   108  	if err != nil {
   109  		return 0, fmt.Errorf("get current block height failed: %w", err)
   110  	}
   111  
   112  	if info.blockHeader == nil {
   113  		return 0, errors.NewOperationNotSupportedError("GetCurrentBlockHeight")
   114  	}
   115  	return info.blockHeader.Height, nil
   116  }
   117  
   118  // GetBlockAtHeight returns the block at the given height.
   119  func (info *blockInfo) GetBlockAtHeight(
   120  	height uint64,
   121  ) (
   122  	runtime.Block,
   123  	bool,
   124  	error,
   125  ) {
   126  	defer info.tracer.StartChildSpan(trace.FVMEnvGetBlockAtHeight).End()
   127  
   128  	err := info.meter.MeterComputation(
   129  		ComputationKindGetBlockAtHeight,
   130  		1)
   131  	if err != nil {
   132  		return runtime.Block{}, false, fmt.Errorf(
   133  			"get block at height failed: %w", err)
   134  	}
   135  
   136  	if info.blocks == nil {
   137  		return runtime.Block{}, false, errors.NewOperationNotSupportedError(
   138  			"GetBlockAtHeight")
   139  	}
   140  
   141  	if info.blockHeader != nil && height == info.blockHeader.Height {
   142  		return runtimeBlockFromHeader(info.blockHeader), true, nil
   143  	}
   144  
   145  	if height+uint64(flow.DefaultTransactionExpiry) < info.blockHeader.Height {
   146  		return runtime.Block{}, false, nil
   147  	}
   148  
   149  	header, err := info.blocks.ByHeightFrom(height, info.blockHeader)
   150  	// TODO (ramtin): remove dependency on storage and move this if condition
   151  	// to blockfinder
   152  	if errors.Is(err, storageErr.ErrNotFound) {
   153  		return runtime.Block{}, false, nil
   154  	} else if err != nil {
   155  		return runtime.Block{}, false, fmt.Errorf(
   156  			"get block at height failed for height %v: %w", height, err)
   157  	}
   158  
   159  	return runtimeBlockFromHeader(header), true, nil
   160  }