github.com/MetalBlockchain/subnet-evm@v0.4.9/plugin/evm/block.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package evm
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"math/big"
    10  	"time"
    11  
    12  	"github.com/ethereum/go-ethereum/log"
    13  	"github.com/ethereum/go-ethereum/rlp"
    14  
    15  	"github.com/MetalBlockchain/subnet-evm/core/types"
    16  
    17  	"github.com/MetalBlockchain/metalgo/ids"
    18  	"github.com/MetalBlockchain/metalgo/snow/choices"
    19  )
    20  
    21  // Block implements the snowman.Block interface
    22  type Block struct {
    23  	id       ids.ID
    24  	ethBlock *types.Block
    25  	vm       *VM
    26  	status   choices.Status
    27  }
    28  
    29  // newBlock returns a new Block wrapping the ethBlock type and implementing the snowman.Block interface
    30  func (vm *VM) newBlock(ethBlock *types.Block) *Block {
    31  	return &Block{
    32  		id:       ids.ID(ethBlock.Hash()),
    33  		ethBlock: ethBlock,
    34  		vm:       vm,
    35  	}
    36  }
    37  
    38  // ID implements the snowman.Block interface
    39  func (b *Block) ID() ids.ID { return b.id }
    40  
    41  // Accept implements the snowman.Block interface
    42  func (b *Block) Accept(context.Context) error {
    43  	vm := b.vm
    44  
    45  	// Although returning an error from Accept is considered fatal, it is good
    46  	// practice to cleanup the batch we were modifying in the case of an error.
    47  	defer vm.db.Abort()
    48  
    49  	b.status = choices.Accepted
    50  	log.Debug(fmt.Sprintf("Accepting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
    51  	if err := vm.blockChain.Accept(b.ethBlock); err != nil {
    52  		return fmt.Errorf("chain could not accept %s: %w", b.ID(), err)
    53  	}
    54  	if err := vm.acceptedBlockDB.Put(lastAcceptedKey, b.id[:]); err != nil {
    55  		return fmt.Errorf("failed to put %s as the last accepted block: %w", b.ID(), err)
    56  	}
    57  
    58  	return vm.db.Commit()
    59  }
    60  
    61  // Reject implements the snowman.Block interface
    62  func (b *Block) Reject(context.Context) error {
    63  	b.status = choices.Rejected
    64  	log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
    65  	return b.vm.blockChain.Reject(b.ethBlock)
    66  }
    67  
    68  // SetStatus implements the InternalBlock interface allowing ChainState
    69  // to set the status on an existing block
    70  func (b *Block) SetStatus(status choices.Status) { b.status = status }
    71  
    72  // Status implements the snowman.Block interface
    73  func (b *Block) Status() choices.Status {
    74  	return b.status
    75  }
    76  
    77  // Parent implements the snowman.Block interface
    78  func (b *Block) Parent() ids.ID {
    79  	return ids.ID(b.ethBlock.ParentHash())
    80  }
    81  
    82  // Height implements the snowman.Block interface
    83  func (b *Block) Height() uint64 {
    84  	return b.ethBlock.NumberU64()
    85  }
    86  
    87  // Timestamp implements the snowman.Block interface
    88  func (b *Block) Timestamp() time.Time {
    89  	return time.Unix(int64(b.ethBlock.Time()), 0)
    90  }
    91  
    92  // syntacticVerify verifies that a *Block is well-formed.
    93  func (b *Block) syntacticVerify() error {
    94  	if b == nil || b.ethBlock == nil {
    95  		return errInvalidBlock
    96  	}
    97  
    98  	header := b.ethBlock.Header()
    99  	rules := b.vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time))
   100  	return b.vm.syntacticBlockValidator.SyntacticVerify(b, rules)
   101  }
   102  
   103  // Verify implements the snowman.Block interface
   104  func (b *Block) Verify(context.Context) error {
   105  	return b.verify(true)
   106  }
   107  
   108  func (b *Block) verify(writes bool) error {
   109  	if err := b.syntacticVerify(); err != nil {
   110  		return fmt.Errorf("syntactic block verification failed: %w", err)
   111  	}
   112  
   113  	return b.vm.blockChain.InsertBlockManual(b.ethBlock, writes)
   114  }
   115  
   116  // Bytes implements the snowman.Block interface
   117  func (b *Block) Bytes() []byte {
   118  	res, err := rlp.EncodeToBytes(b.ethBlock)
   119  	if err != nil {
   120  		panic(err)
   121  	}
   122  	return res
   123  }
   124  
   125  func (b *Block) String() string { return fmt.Sprintf("EVM block, ID = %s", b.ID()) }