gitlab.com/flarenetwork/coreth@v0.1.1/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  	"fmt"
     8  	"math/big"
     9  	"time"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/log"
    13  	"github.com/ethereum/go-ethereum/rlp"
    14  
    15  	"gitlab.com/flarenetwork/coreth/core/types"
    16  	"gitlab.com/flarenetwork/coreth/params"
    17  
    18  	"github.com/ava-labs/avalanchego/ids"
    19  	"github.com/ava-labs/avalanchego/snow/choices"
    20  )
    21  
    22  var bonusBlocks = ids.Set{}
    23  
    24  func init() {
    25  	blockIDStrs := []string{
    26  		"XMoEsew2DhSgQaydcJFJUQAQYP8BTNTYbEJZvtbrV2QsX7iE3",
    27  		"2QiHZwLhQ3xLuyyfcdo5yCUfoSqWDvRZox5ECU19HiswfroCGp",
    28  		"tLLijh7oKfvWT1yk9zRv4FQvuQ5DAiuvb5kHCNN9zh4mqkFMG",
    29  		"2db2wMbVAoCc5EUJrsBYWvNZDekqyY8uNpaaVapdBAQZ5oRaou",
    30  		"2rAsBj3emqQa13CV8r5fTtHogs4sXnjvbbXVzcKPi3WmzhpK9D",
    31  		"amgH2C1s9H3Av7vSW4y7n7TXb9tKyKHENvrDXutgNN6nsejgc",
    32  		"dWBsRYRwFrcyi3DPdLoHsL67QkZ5h86hwtVfP94ZBaY18EkmF",
    33  		"PgaRk1UAoUvRybhnXsrLq5t6imWhEa6ksNjbN6hWgs4qPrSzm",
    34  		"b7XfDDLgwB12DfL7UTWZoxwBpkLPL5mdHtXngD94Y2RoeWXSh",
    35  		"2i2FP6nJyvhX9FR15qN2D9AVoK5XKgBD2i2AQ7FoSpfowxvQDX",
    36  		"2J8z7HNv4nwh82wqRGyEHqQeuw4wJ6mCDCSvUgusBu35asnshK",
    37  		"2cUPPHy1hspr2nAKpQrrAEisLKkaWSS9iF2wjNFyFRs8vnSkKK",
    38  		"2gTygYckZgFZfN5QQWPaPBD3nabqjidV55mwy1x1Nd4JmJAwaM",
    39  		"5MptSdP6dBMPSwk9GJjeVe39deZJTRh9i82cgNibjeDffrrTf",
    40  		"2v3smb35s4GLACsK4Zkd2RcLBLdWA4huqrvq8Y3VP4CVe8kfTM",
    41  		"7KCZKBpxovtX9opb7rMRie9WmW5YbZ8A4HwBBokJ9eSHpZPqx",
    42  		"2oueNTj4dUE2FFtGyPpawnmCCsy6EUQeVHVLZy8NHeQmkAciP4",
    43  		"Nzs93kFTvcXanFUp9Y8VQkKYnzmH8xykxVNFJTkdyAEeuxWbP",
    44  		"2YHZ1KymFjiBhpXzgt6HXJhLSt5SV9UQ4tJuUNjfN1nQQdm5zz",
    45  		"Qv5v5Ru8ArfnWKB1w6s4G5EYPh7TybHJtF6UsVwAkfvZFoqmj",
    46  		"z3BgePPpCXq1mRBRvUi28rYYxnEtJizkUEHnDBrcZeVA7MFVk",
    47  		"Ry2sfjFfGEnJxRkUGFSyZNn7GR3m4aKAf1scDW2uXSNQB568Y",
    48  		"2YgxGHns7Z2hMMHJsPCgVXuJaL7x1b3gnHbmSCfCdyAcYGr6mx",
    49  		"cwJusfmn98TW3DjAbfLRN9utYR24KAQ82qpAXmVSvjHyJZuM2",
    50  		"2JbuExUGKW5mYz5KfXATwq1ibRDimgks9wEdYGNSC6Ttey1R4U",
    51  		"21Jys8UNURmtckKSV89S2hntEWymJszrLQbdLaNcbXcxDAsQSa",
    52  		"MjExz2z1qhwugc1tAyiGxRsCq4GvJwKfyyS29nr4tRVB8ooic",
    53  		"9oZh4qyBCcVwSGyDoUzRAuausvPJN3xH6nopKS6bwYzMfLoQ2",
    54  		"uK5Ff9iBfDtREpVv9NgCQ1STD1nzLJG3yrfibHG4mGvmybw6f",
    55  		"22ck2Z7cC38hmBfX2v3jMWxun8eD8psNaicfYeokS67DxwmPTx",
    56  		"2AfTQ2FXNj9bkSUQnud9pFXULx6EbF7cbbw6i3ayvc2QNhgxfF",
    57  		"pTf7gfk1ksj7bqMrLyMCij8FBKth1uRqQrtfykMFeXhx5xnrL",
    58  		"2AXxT3PSEnaYHNtBTnYrVTf24TtKDWjky9sqoFEhydrGXE9iKH",
    59  		"PJTkRrHvKZ1m4AQdPND1MBpUXpCrGN4DDmXmJQAiUrsxPoLQX",
    60  		"fV8k1U8oQDmfVwK66kAwN73aSsWiWhm8quNpVnKmSznBycV2W",
    61  		"sg6wAwFBsPQiS5Yfyh41cVkCRQbrrXsxXmeNyQ1xkunf2sdyv",
    62  		"soPweZ8DGaoUMjrnzjH3V2bypa7ZvvfqBan4UCsMUxMP759gw",
    63  		"2dNkpQF4mooveyUDfBYQTBfsGDV4wkncQPpEw4kHKfSTSTo5x",
    64  		"63YLdYXfXc5tY3mwWLaDsbXzQHYmwWVxMP7HKbRh4Du3C2iM1",
    65  		"2tCe88ur6MLQcVgwE5XxoaHiTGtSrthwKN3SdbHE4kWiQ7MSTV",
    66  		"2nG4exd9eUoAGzELfksmBR8XDCKhohY1uDKRFzEXJG4M8p3qA7",
    67  		"2F5tSQbdTfhZxvkxZqdFp7KR3FrJPKEsDLQK7KtPhNXj1EZAh4",
    68  		"21o2fVTnzzmtgXqkV1yuQeze7YEQhR5JB31jVVD9oVUnaaV8qm",
    69  		"2pSjfo7rkFCfZ2CqAxqfw8vqM2CU2nVLHrFZe3rwxz43gkVuGo",
    70  		"2QBNMMFJmhVHaGF45GAPszKyj1gK6ToBERRxYvXtM7yfrdUGPK",
    71  		"2ez4CA7w4HHr8SSobHQUAwFgj2giRNjNFUZK9JvrZFa1AuRj6X",
    72  		"2DpCuBaH94zKKFNY2XTs4GeJcwsEv6qT2DHc59S8tdg97GZpcJ",
    73  		"i1HoerJ1axognkUKKL58FvF9aLrbZKtv7TdKLkT5kgzoeU1vB",
    74  		"2SiSziHHqPjb1qkw7CdGYupokiYpd2b7mMqRiyszurctcA5AKr",
    75  		"esx5J962LtYm2aSrskpLai5e4CMMsaS1dsu9iuLGJ3KWgSu2M",
    76  		"2czmtnBS44VCWNRFUM89h4Fe9m3ZeZVYyh7Pe3FhNqjRNgPXhZ",
    77  		"DK9NqAJGry1wAo767uuYc1dYXAjUhzwka6vi8d9tNheqzGUTd",
    78  		"pE93VXY3N5QKfwsEFcM9i59UpPFgeZ8nxpJNaGaDQyDgsscNf",
    79  		"AfWvJH3rB2fdHuPWQp6qYNCFVT29MooQPRigD88rKKwUDEDhq",
    80  		"2KPW9G5tiNF14tZNfG4SqHuQrtUYVZyxuof37aZ7AnTKrQdsHn",
    81  		"BYqLB6xpqy7HsAgP2XNfGE8Ubg1uEzse5mBPTSJH9z5s8pvMa",
    82  		"Njm9TcLUXRojZk8YhEM6ksvfiPdC1TME4zJvGaDXgzMCyB6oB",
    83  	}
    84  	for _, blkIDStr := range blockIDStrs {
    85  		blkID, err := ids.FromString(blkIDStr)
    86  		if err != nil {
    87  			panic(err)
    88  		}
    89  		bonusBlocks.Add(blkID)
    90  	}
    91  }
    92  
    93  // Block implements the snowman.Block interface
    94  type Block struct {
    95  	id       ids.ID
    96  	ethBlock *types.Block
    97  	vm       *VM
    98  	status   choices.Status
    99  }
   100  
   101  // ID implements the snowman.Block interface
   102  func (b *Block) ID() ids.ID { return b.id }
   103  
   104  // Accept implements the snowman.Block interface
   105  func (b *Block) Accept() error {
   106  	vm := b.vm
   107  
   108  	// Although returning an error from Accept is considered fatal, it is good
   109  	// practice to cleanup the batch we were modifying in the case of an error.
   110  	defer vm.db.Abort()
   111  
   112  	b.status = choices.Accepted
   113  	log.Debug(fmt.Sprintf("Accepting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
   114  	if err := vm.chain.Accept(b.ethBlock); err != nil {
   115  		return fmt.Errorf("chain could not accept %s: %w", b.ID(), err)
   116  	}
   117  	if err := vm.acceptedBlockDB.Put(lastAcceptedKey, b.id[:]); err != nil {
   118  		return fmt.Errorf("failed to put %s as the last accepted block: %w", b.ID(), err)
   119  	}
   120  
   121  	tx, err := vm.extractAtomicTx(b.ethBlock)
   122  	if err != nil {
   123  		return err
   124  	}
   125  	if tx == nil {
   126  		return vm.db.Commit()
   127  	}
   128  
   129  	// Remove the accepted transaction from the mempool
   130  	vm.mempool.RemoveTx(tx.ID())
   131  
   132  	// Save the accepted atomic transaction
   133  	if err := vm.writeAtomicTx(b, tx); err != nil {
   134  		return err
   135  	}
   136  
   137  	if bonusBlocks.Contains(b.id) {
   138  		log.Info("skipping atomic tx acceptance on bonus block", "block", b.id)
   139  		return vm.db.Commit()
   140  	}
   141  
   142  	batch, err := vm.db.CommitBatch()
   143  	if err != nil {
   144  		return fmt.Errorf("failed to create commit batch due to: %w", err)
   145  	}
   146  
   147  	return tx.UnsignedAtomicTx.Accept(vm.ctx, batch)
   148  }
   149  
   150  // Reject implements the snowman.Block interface
   151  // If [b] contains an atomic transaction, attempt to re-issue it
   152  func (b *Block) Reject() error {
   153  	b.status = choices.Rejected
   154  	log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
   155  	tx, _ := b.vm.extractAtomicTx(b.ethBlock)
   156  	if tx != nil {
   157  		b.vm.mempool.RejectTx(tx.ID())
   158  	}
   159  
   160  	return b.vm.chain.Reject(b.ethBlock)
   161  }
   162  
   163  // SetStatus implements the InternalBlock interface allowing ChainState
   164  // to set the status on an existing block
   165  func (b *Block) SetStatus(status choices.Status) { b.status = status }
   166  
   167  // Status implements the snowman.Block interface
   168  func (b *Block) Status() choices.Status {
   169  	return b.status
   170  }
   171  
   172  // Parent implements the snowman.Block interface
   173  func (b *Block) Parent() ids.ID {
   174  	return ids.ID(b.ethBlock.ParentHash())
   175  }
   176  
   177  // Height implements the snowman.Block interface
   178  func (b *Block) Height() uint64 {
   179  	return b.ethBlock.Number().Uint64()
   180  }
   181  
   182  // Timestamp implements the snowman.Block interface
   183  func (b *Block) Timestamp() time.Time {
   184  	return time.Unix(int64(b.ethBlock.Time()), 0)
   185  }
   186  
   187  // syntacticVerify verifies that a *Block is well-formed.
   188  func (b *Block) syntacticVerify() (params.Rules, error) {
   189  	if b == nil || b.ethBlock == nil {
   190  		return params.Rules{}, errInvalidBlock
   191  	}
   192  
   193  	header := b.ethBlock.Header()
   194  	rules := b.vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time))
   195  	return rules, b.vm.getBlockValidator(rules).SyntacticVerify(b)
   196  }
   197  
   198  // Verify implements the snowman.Block interface
   199  func (b *Block) Verify() error {
   200  	return b.verify(true)
   201  }
   202  
   203  func (b *Block) verify(writes bool) error {
   204  	rules, err := b.syntacticVerify()
   205  	if err != nil {
   206  		return fmt.Errorf("syntactic block verification failed: %w", err)
   207  	}
   208  
   209  	vm := b.vm
   210  
   211  	// Ensure that the parent was verified and inserted correctly.
   212  	ancestorID := b.Parent()
   213  	ancestorHash := common.Hash(ancestorID)
   214  	if !vm.chain.BlockChain().HasBlock(ancestorHash, b.Height()-1) {
   215  		return errRejectedParent
   216  	}
   217  
   218  	// If the tx is an atomic tx, ensure that it doesn't conflict with any of
   219  	// its processing ancestry.
   220  	atomicTx, err := vm.extractAtomicTx(b.ethBlock)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	if atomicTx != nil {
   225  		// If the ancestor is unknown, then the parent failed verification when
   226  		// it was called.
   227  		// If the ancestor is rejected, then this block shouldn't be inserted
   228  		// into the canonical chain because the parent is will be missing.
   229  		ancestorInf, err := vm.GetBlockInternal(ancestorID)
   230  		if err != nil {
   231  			return errRejectedParent
   232  		}
   233  
   234  		if blkStatus := ancestorInf.Status(); blkStatus == choices.Unknown || blkStatus == choices.Rejected {
   235  			return errRejectedParent
   236  		}
   237  		ancestor, ok := ancestorInf.(*Block)
   238  		if !ok {
   239  			return fmt.Errorf("expected %s, parent of %s, to be *Block but is %T", ancestor.ID(), b.ID(), ancestorInf)
   240  		}
   241  
   242  		if bonusBlocks.Contains(b.id) {
   243  			log.Info("skipping atomic tx verification on bonus block", "block", b.id)
   244  		} else {
   245  			utx := atomicTx.UnsignedAtomicTx
   246  			if err := utx.SemanticVerify(vm, atomicTx, ancestor, b.ethBlock.BaseFee(), rules); err != nil {
   247  				return fmt.Errorf("invalid block due to failed semanatic verify: %w at height %d", err, b.Height())
   248  			}
   249  		}
   250  	}
   251  
   252  	bc := vm.chain.BlockChain()
   253  	return bc.InsertBlockManual(b.ethBlock, writes)
   254  }
   255  
   256  // Bytes implements the snowman.Block interface
   257  func (b *Block) Bytes() []byte {
   258  	res, err := rlp.EncodeToBytes(b.ethBlock)
   259  	if err != nil {
   260  		panic(err)
   261  	}
   262  	return res
   263  }
   264  
   265  func (b *Block) String() string { return fmt.Sprintf("EVM block, ID = %s", b.ID()) }