github.com/Unheilbar/quorum@v1.0.0/qlight/client_cache.go (about)

     1  package qlight
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	"github.com/ethereum/go-ethereum/core/rawdb"
     9  	"github.com/ethereum/go-ethereum/ethdb"
    10  	"github.com/ethereum/go-ethereum/log"
    11  	"github.com/ethereum/go-ethereum/private"
    12  	"github.com/ethereum/go-ethereum/private/cache"
    13  	"github.com/ethereum/go-ethereum/private/engine/qlightptm"
    14  	gocache "github.com/patrickmn/go-cache"
    15  )
    16  
    17  type clientCache struct {
    18  	txCache           CacheWithEmpty
    19  	privateBlockCache *gocache.Cache
    20  	db                ethdb.Database
    21  }
    22  
    23  func NewClientCache(db ethdb.Database) (PrivateClientCache, error) {
    24  	cachingTXManager, ok := private.P.(*qlightptm.CachingProxyTxManager)
    25  	if !ok {
    26  		return nil, fmt.Errorf("unable to initialize txCache")
    27  	}
    28  	return NewClientCacheWithEmpty(db, cachingTXManager, gocache.New(cache.DefaultExpiration, cache.CleanupInterval))
    29  }
    30  
    31  func NewClientCacheWithEmpty(db ethdb.Database, cacheWithEmpty CacheWithEmpty, gocache *gocache.Cache) (PrivateClientCache, error) {
    32  	return &clientCache{
    33  		txCache:           cacheWithEmpty,
    34  		privateBlockCache: gocache,
    35  		db:                db,
    36  	}, nil
    37  }
    38  
    39  func (c *clientCache) AddPrivateBlock(blockPrivateData BlockPrivateData) error {
    40  	for _, pvtTx := range blockPrivateData.PrivateTransactions {
    41  		if err := c.txCache.Cache(pvtTx.ToCachable()); err != nil {
    42  			return err
    43  		}
    44  	}
    45  	if !common.EmptyHash(blockPrivateData.PrivateStateRoot) {
    46  		return c.privateBlockCache.Add(blockPrivateData.BlockHash.ToBase64(), blockPrivateData.PrivateStateRoot.ToBase64(), gocache.DefaultExpiration)
    47  	}
    48  	return nil
    49  }
    50  
    51  func (c *clientCache) CheckAndAddEmptyEntry(hash common.EncryptedPayloadHash) {
    52  	c.txCache.CheckAndAddEmptyToCache(hash)
    53  }
    54  
    55  func (c *clientCache) ValidatePrivateStateRoot(blockHash common.Hash, publicStateRoot common.Hash) error {
    56  	dbPrivateStateRoot := rawdb.GetPrivateStateRoot(c.db, publicStateRoot)
    57  
    58  	cachePrivateStateRootStr, found := c.privateBlockCache.Get(blockHash.ToBase64())
    59  	if !found {
    60  		// this means that we don't have private data for this block or that the server does not have the corresponding
    61  		// private state root (which can happen when caching is enabled on the server side)
    62  		return nil
    63  	}
    64  	cachePrivateStateRootB64, ok := cachePrivateStateRootStr.(string)
    65  	if !ok {
    66  		return fmt.Errorf("Invalid private block cache item")
    67  	}
    68  	cachePrivateStateRoot, err := common.Base64ToHash(cachePrivateStateRootB64)
    69  	if err != nil {
    70  		return fmt.Errorf("Invalid encoding for private state root: %s", cachePrivateStateRootB64)
    71  	}
    72  	if !bytes.Equal(cachePrivateStateRoot.Bytes(), dbPrivateStateRoot.Bytes()) {
    73  		log.Error("QLight - Private state root hash check failure for block", "hash", blockHash)
    74  		return fmt.Errorf("Private root hash missmatch for block %s", blockHash)
    75  	}
    76  	log.Info("QLight - Private state root hash check successful for block", "hash", blockHash)
    77  	return nil
    78  }