github.com/onflow/flow-go@v0.33.17/fvm/evm/handler/blockstore.go (about)

     1  package handler
     2  
     3  import (
     4  	gethCommon "github.com/ethereum/go-ethereum/common"
     5  	"github.com/onflow/atree"
     6  
     7  	"github.com/onflow/flow-go/fvm/evm/types"
     8  	"github.com/onflow/flow-go/model/flow"
     9  )
    10  
    11  var FlexLatestBlockKey = "LatestBlock"
    12  
    13  type BlockStore struct {
    14  	led           atree.Ledger
    15  	flexAddress   flow.Address
    16  	blockProposal *types.Block
    17  }
    18  
    19  var _ types.BlockStore = &BlockStore{}
    20  
    21  // NewBlockStore constructs a new block store
    22  func NewBlockStore(led atree.Ledger, flexAddress flow.Address) (*BlockStore, error) {
    23  	return &BlockStore{
    24  		led:         led,
    25  		flexAddress: flexAddress,
    26  	}, nil
    27  }
    28  
    29  // BlockProposal returns the block proposal to be updated by the handler
    30  func (bs *BlockStore) BlockProposal() (*types.Block, error) {
    31  	if bs.blockProposal != nil {
    32  		return bs.blockProposal, nil
    33  	}
    34  
    35  	lastExecutedBlock, err := bs.LatestBlock()
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	parentHash, err := lastExecutedBlock.Hash()
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	bs.blockProposal = &types.Block{
    46  		Height:            lastExecutedBlock.Height + 1,
    47  		ParentBlockHash:   parentHash,
    48  		TotalSupply:       lastExecutedBlock.TotalSupply,
    49  		TransactionHashes: make([]gethCommon.Hash, 0),
    50  	}
    51  	return bs.blockProposal, nil
    52  }
    53  
    54  // CommitBlockProposal commits the block proposal to the chain
    55  func (bs *BlockStore) CommitBlockProposal() error {
    56  	bp, err := bs.BlockProposal()
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	blockBytes, err := bp.ToBytes()
    62  	if err != nil {
    63  		return types.NewFatalError(err)
    64  	}
    65  
    66  	err = bs.led.SetValue(bs.flexAddress[:], []byte(FlexLatestBlockKey), blockBytes)
    67  	if err != nil {
    68  		return types.NewFatalError(err)
    69  	}
    70  
    71  	bs.blockProposal = nil
    72  
    73  	return nil
    74  }
    75  
    76  // ResetBlockProposal resets the block proposal
    77  func (bs *BlockStore) ResetBlockProposal() error {
    78  	bs.blockProposal = nil
    79  	return nil
    80  }
    81  
    82  // LatestBlock returns the latest executed block
    83  func (bs *BlockStore) LatestBlock() (*types.Block, error) {
    84  	data, err := bs.led.GetValue(bs.flexAddress[:], []byte(FlexLatestBlockKey))
    85  	if len(data) == 0 {
    86  		return types.GenesisBlock, err
    87  	}
    88  	if err != nil {
    89  		return nil, types.NewFatalError(err)
    90  	}
    91  	return types.NewBlockFromBytes(data)
    92  }
    93  
    94  // BlockHash returns the block hash for the last x blocks
    95  //
    96  // TODO: implement this properly to keep the last 256 block hashes
    97  // and connect use it inside the handler to pass as a config to the emulator
    98  func (bs *BlockStore) BlockHash(height int) (gethCommon.Hash, error) {
    99  	return gethCommon.Hash{}, nil
   100  }