github.com/dim4egster/coreth@v0.10.2/plugin/evm/atomic_state.go (about)

     1  // (c) 2020-2021, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package evm
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/dim4egster/qmallgo/chains/atomic"
    10  	"github.com/dim4egster/qmallgo/database"
    11  	"github.com/dim4egster/qmallgo/ids"
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethereum/go-ethereum/log"
    14  )
    15  
    16  var _ AtomicState = &atomicState{}
    17  
    18  // AtomicState is an abstraction created through AtomicBackend
    19  // and can be used to apply the VM's state change for atomic txs
    20  // or reject them to free memory.
    21  // The root of the atomic trie after applying the state change
    22  // is accessible through this interface as well.
    23  type AtomicState interface {
    24  	// Root of the atomic trie after applying the state change.
    25  	Root() common.Hash
    26  	// Accept applies the state change to VM's persistent storage
    27  	// Changes are persisted atomically along with the provided [commitBatch].
    28  	Accept(commitBatch database.Batch) error
    29  	// Reject frees memory associated with the state change.
    30  	Reject() error
    31  }
    32  
    33  // atomicState implements the AtomicState interface using
    34  // a pointer to the atomicBackend.
    35  type atomicState struct {
    36  	backend     *atomicBackend
    37  	blockHash   common.Hash
    38  	blockHeight uint64
    39  	txs         []*Tx
    40  	atomicOps   map[ids.ID]*atomic.Requests
    41  	atomicRoot  common.Hash
    42  }
    43  
    44  func (a *atomicState) Root() common.Hash {
    45  	return a.atomicRoot
    46  }
    47  
    48  // Accept applies the state change to VM's persistent storage.
    49  func (a *atomicState) Accept(commitBatch database.Batch) error {
    50  	// Update the atomic tx repository. Note it is necessary to invoke
    51  	// the correct method taking bonus blocks into consideration.
    52  	if a.backend.IsBonus(a.blockHeight, a.blockHash) {
    53  		if err := a.backend.repo.WriteBonus(a.blockHeight, a.txs); err != nil {
    54  			return err
    55  		}
    56  	} else {
    57  		if err := a.backend.repo.Write(a.blockHeight, a.txs); err != nil {
    58  			return err
    59  		}
    60  	}
    61  
    62  	// Accept the root of this atomic trie (will be persisted if at a commit interval)
    63  	if _, err := a.backend.atomicTrie.AcceptTrie(a.blockHeight, a.atomicRoot); err != nil {
    64  		return err
    65  	}
    66  	// Update the last accepted block to this block and remove it from
    67  	// the map tracking undecided blocks.
    68  	a.backend.lastAcceptedHash = a.blockHash
    69  	delete(a.backend.verifiedRoots, a.blockHash)
    70  
    71  	// get changes from the atomic trie and repository in a batch
    72  	// to be committed atomically with [commitBatch] and shared memory.
    73  	atomicChangesBatch, err := a.backend.db.CommitBatch()
    74  	if err != nil {
    75  		return fmt.Errorf("could not create commit batch in atomicState accept: %w", err)
    76  	}
    77  
    78  	// If this is a bonus block, write [commitBatch] without applying atomic ops
    79  	// to shared memory.
    80  	if a.backend.IsBonus(a.blockHeight, a.blockHash) {
    81  		log.Info("skipping atomic tx acceptance on bonus block", "block", a.blockHash)
    82  		return atomic.WriteAll(commitBatch, atomicChangesBatch)
    83  	}
    84  
    85  	// Otherwise, atomically commit pending changes in the version db with
    86  	// atomic ops to shared memory.
    87  	return a.backend.sharedMemory.Apply(a.atomicOps, commitBatch, atomicChangesBatch)
    88  }
    89  
    90  // Reject frees memory associated with the state change.
    91  func (a *atomicState) Reject() error {
    92  	// Remove the block from the map of undecided blocks.
    93  	delete(a.backend.verifiedRoots, a.blockHash)
    94  	// Unpin the rejected atomic trie root from memory.
    95  	return a.backend.atomicTrie.RejectTrie(a.atomicRoot)
    96  }