client_cache.go 2.8 KB

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