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 }