github.com/dim4egster/coreth@v0.10.2/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  	"github.com/dim4egster/coreth/core/types"
    16  
    17  	"github.com/dim4egster/qmallgo/ids"
    18  	"github.com/dim4egster/qmallgo/snow/choices"
    19  )
    20  
    21  var (
    22  	bonusBlockMainnetHeights = make(map[uint64]ids.ID)
    23  	// first height that processed a TX included on a
    24  	// bonus block is the canonical height for that TX.
    25  	canonicalBlockMainnetHeights = []uint64{
    26  		102928, 103035, 103038, 103114, 103193,
    27  		103234, 103338, 103444, 103480, 103491,
    28  		103513, 103533, 103535, 103538, 103541,
    29  		103546, 103571, 103572, 103619,
    30  		103287, 103624, 103591,
    31  	}
    32  )
    33  
    34  func init() {
    35  	mainnetBonusBlocks := map[uint64]string{
    36  		102972: "Njm9TcLUXRojZk8YhEM6ksvfiPdC1TME4zJvGaDXgzMCyB6oB",
    37  		103105: "BYqLB6xpqy7HsAgP2XNfGE8Ubg1uEzse5mBPTSJH9z5s8pvMa",
    38  		103143: "AfWvJH3rB2fdHuPWQp6qYNCFVT29MooQPRigD88rKKwUDEDhq",
    39  		103183: "2KPW9G5tiNF14tZNfG4SqHuQrtUYVZyxuof37aZ7AnTKrQdsHn",
    40  		103197: "pE93VXY3N5QKfwsEFcM9i59UpPFgeZ8nxpJNaGaDQyDgsscNf",
    41  		103203: "2czmtnBS44VCWNRFUM89h4Fe9m3ZeZVYyh7Pe3FhNqjRNgPXhZ",
    42  		103208: "esx5J962LtYm2aSrskpLai5e4CMMsaS1dsu9iuLGJ3KWgSu2M",
    43  		103209: "DK9NqAJGry1wAo767uuYc1dYXAjUhzwka6vi8d9tNheqzGUTd",
    44  		103259: "i1HoerJ1axognkUKKL58FvF9aLrbZKtv7TdKLkT5kgzoeU1vB",
    45  		103261: "2DpCuBaH94zKKFNY2XTs4GeJcwsEv6qT2DHc59S8tdg97GZpcJ",
    46  		103266: "2ez4CA7w4HHr8SSobHQUAwFgj2giRNjNFUZK9JvrZFa1AuRj6X",
    47  		103287: "2QBNMMFJmhVHaGF45GAPszKyj1gK6ToBERRxYvXtM7yfrdUGPK",
    48  		103339: "2pSjfo7rkFCfZ2CqAxqfw8vqM2CU2nVLHrFZe3rwxz43gkVuGo",
    49  		103346: "2SiSziHHqPjb1qkw7CdGYupokiYpd2b7mMqRiyszurctcA5AKr",
    50  		103350: "2F5tSQbdTfhZxvkxZqdFp7KR3FrJPKEsDLQK7KtPhNXj1EZAh4",
    51  		103358: "2tCe88ur6MLQcVgwE5XxoaHiTGtSrthwKN3SdbHE4kWiQ7MSTV",
    52  		103437: "21o2fVTnzzmtgXqkV1yuQeze7YEQhR5JB31jVVD9oVUnaaV8qm",
    53  		103472: "2nG4exd9eUoAGzELfksmBR8XDCKhohY1uDKRFzEXJG4M8p3qA7",
    54  		103478: "63YLdYXfXc5tY3mwWLaDsbXzQHYmwWVxMP7HKbRh4Du3C2iM1",
    55  		103493: "soPweZ8DGaoUMjrnzjH3V2bypa7ZvvfqBan4UCsMUxMP759gw",
    56  		103514: "2dNkpQF4mooveyUDfBYQTBfsGDV4wkncQPpEw4kHKfSTSTo5x",
    57  		103536: "PJTkRrHvKZ1m4AQdPND1MBpUXpCrGN4DDmXmJQAiUrsxPoLQX",
    58  		103545: "22ck2Z7cC38hmBfX2v3jMWxun8eD8psNaicfYeokS67DxwmPTx",
    59  		103547: "pTf7gfk1ksj7bqMrLyMCij8FBKth1uRqQrtfykMFeXhx5xnrL",
    60  		103554: "9oZh4qyBCcVwSGyDoUzRAuausvPJN3xH6nopKS6bwYzMfLoQ2",
    61  		103555: "MjExz2z1qhwugc1tAyiGxRsCq4GvJwKfyyS29nr4tRVB8ooic",
    62  		103559: "cwJusfmn98TW3DjAbfLRN9utYR24KAQ82qpAXmVSvjHyJZuM2",
    63  		103561: "2YgxGHns7Z2hMMHJsPCgVXuJaL7x1b3gnHbmSCfCdyAcYGr6mx",
    64  		103563: "2AXxT3PSEnaYHNtBTnYrVTf24TtKDWjky9sqoFEhydrGXE9iKH",
    65  		103564: "Ry2sfjFfGEnJxRkUGFSyZNn7GR3m4aKAf1scDW2uXSNQB568Y",
    66  		103569: "21Jys8UNURmtckKSV89S2hntEWymJszrLQbdLaNcbXcxDAsQSa",
    67  		103570: "sg6wAwFBsPQiS5Yfyh41cVkCRQbrrXsxXmeNyQ1xkunf2sdyv",
    68  		103575: "z3BgePPpCXq1mRBRvUi28rYYxnEtJizkUEHnDBrcZeVA7MFVk",
    69  		103577: "uK5Ff9iBfDtREpVv9NgCQ1STD1nzLJG3yrfibHG4mGvmybw6f",
    70  		103578: "Qv5v5Ru8ArfnWKB1w6s4G5EYPh7TybHJtF6UsVwAkfvZFoqmj",
    71  		103582: "7KCZKBpxovtX9opb7rMRie9WmW5YbZ8A4HwBBokJ9eSHpZPqx",
    72  		103587: "2AfTQ2FXNj9bkSUQnud9pFXULx6EbF7cbbw6i3ayvc2QNhgxfF",
    73  		103590: "2gTygYckZgFZfN5QQWPaPBD3nabqjidV55mwy1x1Nd4JmJAwaM",
    74  		103591: "2cUPPHy1hspr2nAKpQrrAEisLKkaWSS9iF2wjNFyFRs8vnSkKK",
    75  		103594: "5MptSdP6dBMPSwk9GJjeVe39deZJTRh9i82cgNibjeDffrrTf",
    76  		103597: "2J8z7HNv4nwh82wqRGyEHqQeuw4wJ6mCDCSvUgusBu35asnshK",
    77  		103598: "2i2FP6nJyvhX9FR15qN2D9AVoK5XKgBD2i2AQ7FoSpfowxvQDX",
    78  		103603: "2v3smb35s4GLACsK4Zkd2RcLBLdWA4huqrvq8Y3VP4CVe8kfTM",
    79  		103604: "b7XfDDLgwB12DfL7UTWZoxwBpkLPL5mdHtXngD94Y2RoeWXSh",
    80  		103607: "PgaRk1UAoUvRybhnXsrLq5t6imWhEa6ksNjbN6hWgs4qPrSzm",
    81  		103612: "2oueNTj4dUE2FFtGyPpawnmCCsy6EUQeVHVLZy8NHeQmkAciP4",
    82  		103614: "2YHZ1KymFjiBhpXzgt6HXJhLSt5SV9UQ4tJuUNjfN1nQQdm5zz",
    83  		103617: "amgH2C1s9H3Av7vSW4y7n7TXb9tKyKHENvrDXutgNN6nsejgc",
    84  		103618: "fV8k1U8oQDmfVwK66kAwN73aSsWiWhm8quNpVnKmSznBycV2W",
    85  		103621: "Nzs93kFTvcXanFUp9Y8VQkKYnzmH8xykxVNFJTkdyAEeuxWbP",
    86  		103623: "2rAsBj3emqQa13CV8r5fTtHogs4sXnjvbbXVzcKPi3WmzhpK9D",
    87  		103624: "2JbuExUGKW5mYz5KfXATwq1ibRDimgks9wEdYGNSC6Ttey1R4U",
    88  		103627: "tLLijh7oKfvWT1yk9zRv4FQvuQ5DAiuvb5kHCNN9zh4mqkFMG",
    89  		103628: "dWBsRYRwFrcyi3DPdLoHsL67QkZ5h86hwtVfP94ZBaY18EkmF",
    90  		103629: "XMoEsew2DhSgQaydcJFJUQAQYP8BTNTYbEJZvtbrV2QsX7iE3",
    91  		103630: "2db2wMbVAoCc5EUJrsBYWvNZDekqyY8uNpaaVapdBAQZ5oRaou",
    92  		103633: "2QiHZwLhQ3xLuyyfcdo5yCUfoSqWDvRZox5ECU19HiswfroCGp",
    93  	}
    94  
    95  	for height, blkIDStr := range mainnetBonusBlocks {
    96  		blkID, err := ids.FromString(blkIDStr)
    97  		if err != nil {
    98  			panic(err)
    99  		}
   100  		bonusBlockMainnetHeights[height] = blkID
   101  	}
   102  }
   103  
   104  // Block implements the snowman.Block interface
   105  type Block struct {
   106  	id        ids.ID
   107  	ethBlock  *types.Block
   108  	vm        *VM
   109  	status    choices.Status
   110  	atomicTxs []*Tx
   111  }
   112  
   113  // newBlock returns a new Block wrapping the ethBlock type and implementing the snowman.Block interface
   114  func (vm *VM) newBlock(ethBlock *types.Block) (*Block, error) {
   115  	isApricotPhase5 := vm.chainConfig.IsApricotPhase5(new(big.Int).SetUint64(ethBlock.Time()))
   116  	atomicTxs, err := ExtractAtomicTxs(ethBlock.ExtData(), isApricotPhase5, vm.codec)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	return &Block{
   122  		id:        ids.ID(ethBlock.Hash()),
   123  		ethBlock:  ethBlock,
   124  		vm:        vm,
   125  		atomicTxs: atomicTxs,
   126  	}, nil
   127  }
   128  
   129  // ID implements the snowman.Block interface
   130  func (b *Block) ID() ids.ID { return b.id }
   131  
   132  // Accept implements the snowman.Block interface
   133  func (b *Block) Accept() error {
   134  	vm := b.vm
   135  
   136  	// Although returning an error from Accept is considered fatal, it is good
   137  	// practice to cleanup the batch we were modifying in the case of an error.
   138  	defer vm.db.Abort()
   139  
   140  	b.status = choices.Accepted
   141  	log.Debug(fmt.Sprintf("Accepting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
   142  	if err := vm.blockChain.Accept(b.ethBlock); err != nil {
   143  		return fmt.Errorf("chain could not accept %s: %w", b.ID(), err)
   144  	}
   145  	if err := vm.acceptedBlockDB.Put(lastAcceptedKey, b.id[:]); err != nil {
   146  		return fmt.Errorf("failed to put %s as the last accepted block: %w", b.ID(), err)
   147  	}
   148  
   149  	for _, tx := range b.atomicTxs {
   150  		// Remove the accepted transaction from the mempool
   151  		vm.mempool.RemoveTx(tx)
   152  	}
   153  
   154  	// Update VM state for atomic txs in this block. This includes updating the
   155  	// atomic tx repo, atomic trie, and shared memory.
   156  	atomicState, err := b.vm.atomicBackend.GetVerifiedAtomicState(common.Hash(b.ID()))
   157  	if err != nil {
   158  		// should never occur since [b] must be verified before calling Accept
   159  		return err
   160  	}
   161  	commitBatch, err := b.vm.db.CommitBatch()
   162  	if err != nil {
   163  		return fmt.Errorf("could not create commit batch processing block[%s]: %w", b.ID(), err)
   164  	}
   165  	return atomicState.Accept(commitBatch)
   166  }
   167  
   168  // Reject implements the snowman.Block interface
   169  // If [b] contains an atomic transaction, attempt to re-issue it
   170  func (b *Block) Reject() error {
   171  	b.status = choices.Rejected
   172  	log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height()))
   173  	for _, tx := range b.atomicTxs {
   174  		b.vm.mempool.RemoveTx(tx)
   175  		if err := b.vm.issueTx(tx, false /* set local to false when re-issuing */); err != nil {
   176  			log.Debug("Failed to re-issue transaction in rejected block", "txID", tx.ID(), "err", err)
   177  		}
   178  	}
   179  	atomicState, err := b.vm.atomicBackend.GetVerifiedAtomicState(common.Hash(b.ID()))
   180  	if err != nil {
   181  		// should never occur since [b] must be verified before calling Reject
   182  		return err
   183  	}
   184  	if err := atomicState.Reject(); err != nil {
   185  		return err
   186  	}
   187  	return b.vm.blockChain.Reject(b.ethBlock)
   188  }
   189  
   190  // SetStatus implements the InternalBlock interface allowing ChainState
   191  // to set the status on an existing block
   192  func (b *Block) SetStatus(status choices.Status) { b.status = status }
   193  
   194  // Status implements the snowman.Block interface
   195  func (b *Block) Status() choices.Status {
   196  	return b.status
   197  }
   198  
   199  // Parent implements the snowman.Block interface
   200  func (b *Block) Parent() ids.ID {
   201  	return ids.ID(b.ethBlock.ParentHash())
   202  }
   203  
   204  // Height implements the snowman.Block interface
   205  func (b *Block) Height() uint64 {
   206  	return b.ethBlock.NumberU64()
   207  }
   208  
   209  // Timestamp implements the snowman.Block interface
   210  func (b *Block) Timestamp() time.Time {
   211  	return time.Unix(int64(b.ethBlock.Time()), 0)
   212  }
   213  
   214  // syntacticVerify verifies that a *Block is well-formed.
   215  func (b *Block) syntacticVerify() error {
   216  	if b == nil || b.ethBlock == nil {
   217  		return errInvalidBlock
   218  	}
   219  
   220  	header := b.ethBlock.Header()
   221  	rules := b.vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time))
   222  	return b.vm.syntacticBlockValidator.SyntacticVerify(b, rules)
   223  }
   224  
   225  // Verify implements the snowman.Block interface
   226  func (b *Block) Verify() error {
   227  	return b.verify(true)
   228  }
   229  
   230  func (b *Block) verify(writes bool) error {
   231  	if err := b.syntacticVerify(); err != nil {
   232  		return fmt.Errorf("syntactic block verification failed: %w", err)
   233  	}
   234  
   235  	err := b.vm.blockChain.InsertBlockManual(b.ethBlock, writes)
   236  	if err != nil || !writes {
   237  		// if an error occurred inserting the block into the chain
   238  		// or if we are not pinning to memory, unpin the atomic trie
   239  		// changes from memory (if they were pinned).
   240  		if atomicState, err := b.vm.atomicBackend.GetVerifiedAtomicState(b.ethBlock.Hash()); err == nil {
   241  			_ = atomicState.Reject() // ignore this error so we can return the original error instead.
   242  		}
   243  	}
   244  	return err
   245  }
   246  
   247  // Bytes implements the snowman.Block interface
   248  func (b *Block) Bytes() []byte {
   249  	res, err := rlp.EncodeToBytes(b.ethBlock)
   250  	if err != nil {
   251  		panic(err)
   252  	}
   253  	return res
   254  }
   255  
   256  func (b *Block) String() string { return fmt.Sprintf("EVM block, ID = %s", b.ID()) }