Skip to content

Commit

Permalink
Merge pull request #2179 from OffchainLabs/das-replace-cache
Browse files Browse the repository at this point in the history
Das replace cache
  • Loading branch information
Tristan-Wilson committed Mar 11, 2024
2 parents 2ad7f7f + d023b00 commit 3ed2d0d
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 150 deletions.
116 changes: 0 additions & 116 deletions das/bigcache_storage_service.go

This file was deleted.

95 changes: 95 additions & 0 deletions das/cache_storage_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE

package das

import (
"context"
"fmt"

"github.com/offchainlabs/nitro/arbstate"
"github.com/offchainlabs/nitro/das/dastree"
"github.com/offchainlabs/nitro/util/pretty"
flag "github.com/spf13/pflag"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/log"
)

type CacheConfig struct {
Enable bool `koanf:"enable"`
Capacity int `koanf:"capacity"`
}

var DefaultCacheConfig = CacheConfig{
Capacity: 20_000,
}

var TestCacheConfig = CacheConfig{
Capacity: 1_000,
}

func CacheConfigAddOptions(prefix string, f *flag.FlagSet) {
f.Bool(prefix+".enable", DefaultCacheConfig.Enable, "Enable local in-memory caching of sequencer batch data")
f.Int(prefix+".capacity", DefaultCacheConfig.Capacity, "Maximum number of entries (up to 64KB each) to store in the cache.")
}

type CacheStorageService struct {
baseStorageService StorageService
cache *lru.Cache[common.Hash, []byte]
}

func NewCacheStorageService(cacheConfig CacheConfig, baseStorageService StorageService) *CacheStorageService {
return &CacheStorageService{
baseStorageService: baseStorageService,
cache: lru.NewCache[common.Hash, []byte](cacheConfig.Capacity),
}
}

func (c *CacheStorageService) GetByHash(ctx context.Context, key common.Hash) ([]byte, error) {
log.Trace("das.CacheStorageService.GetByHash", "key", pretty.PrettyHash(key), "this", c)

if val, wasCached := c.cache.Get(key); wasCached {
return val, nil
}

val, err := c.baseStorageService.GetByHash(ctx, key)
if err != nil {
return nil, err
}

c.cache.Add(key, val)

return val, nil
}

func (c *CacheStorageService) Put(ctx context.Context, value []byte, timeout uint64) error {
logPut("das.CacheStorageService.Put", value, timeout, c)
err := c.baseStorageService.Put(ctx, value, timeout)
if err != nil {
return err
}
c.cache.Add(common.Hash(dastree.Hash(value)), value)
return nil
}

func (c *CacheStorageService) Sync(ctx context.Context) error {
return c.baseStorageService.Sync(ctx)
}

func (c *CacheStorageService) Close(ctx context.Context) error {
return c.baseStorageService.Close(ctx)
}

func (c *CacheStorageService) ExpirationPolicy(ctx context.Context) (arbstate.ExpirationPolicy, error) {
return c.baseStorageService.ExpirationPolicy(ctx)
}

func (c *CacheStorageService) String() string {
return fmt.Sprintf("CacheStorageService(size:%+v)", len(c.cache.Keys()))
}

func (c *CacheStorageService) HealthCheck(ctx context.Context) error {
return c.baseStorageService.HealthCheck(ctx)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,32 @@ import (
"context"
"errors"
"testing"
"time"

"github.com/allegro/bigcache"
"github.com/offchainlabs/nitro/das/dastree"
)

func TestBigCacheStorageService(t *testing.T) {
func TestCacheStorageService(t *testing.T) {
ctx := context.Background()
timeout := uint64(time.Now().Add(time.Hour).Unix())
baseStorageService := NewMemoryBackedStorageService(ctx)
bigCache, err := bigcache.NewBigCache(bigcache.DefaultConfig(TestBigCacheConfig.Expiration))
Require(t, err)
bigCacheService := &BigCacheStorageService{
baseStorageService: baseStorageService,
bigCacheConfig: TestBigCacheConfig,
bigCache: bigCache,
}
Require(t, err)
cacheService := NewCacheStorageService(TestCacheConfig, baseStorageService)

val1 := []byte("The first value")
val1CorrectKey := dastree.Hash(val1)
val1IncorrectKey := dastree.Hash(append(val1, 0))

_, err = bigCacheService.GetByHash(ctx, val1CorrectKey)
_, err := cacheService.GetByHash(ctx, val1CorrectKey)
if !errors.Is(err, ErrNotFound) {
t.Fatal(err)
}

err = bigCacheService.Put(ctx, val1, timeout)
err = cacheService.Put(ctx, val1, 1)
Require(t, err)

_, err = bigCacheService.GetByHash(ctx, val1IncorrectKey)
_, err = cacheService.GetByHash(ctx, val1IncorrectKey)
if !errors.Is(err, ErrNotFound) {
t.Fatal(err)
}
val, err := bigCacheService.GetByHash(ctx, val1CorrectKey)
val, err := cacheService.GetByHash(ctx, val1CorrectKey)
Require(t, err)
if !bytes.Equal(val, val1) {
t.Fatal(val, val1)
Expand All @@ -54,34 +44,33 @@ func TestBigCacheStorageService(t *testing.T) {
val2CorrectKey := dastree.Hash(val2)
val2IncorrectKey := dastree.Hash(append(val2, 0))

err = baseStorageService.Put(ctx, val2, timeout)
err = baseStorageService.Put(ctx, val2, 1)
Require(t, err)

_, err = bigCacheService.GetByHash(ctx, val2IncorrectKey)
_, err = cacheService.GetByHash(ctx, val2IncorrectKey)
if !errors.Is(err, ErrNotFound) {
t.Fatal(err)
}
val, err = bigCacheService.GetByHash(ctx, val2CorrectKey)
val, err = cacheService.GetByHash(ctx, val2CorrectKey)
Require(t, err)
if !bytes.Equal(val, val2) {
t.Fatal(val, val2)
}

// For Case where the value is present in the cache storage but not present in the base.
emptyBaseStorageService := NewMemoryBackedStorageService(ctx)
bigCacheServiceWithEmptyBaseStorage := &BigCacheStorageService{
cacheServiceWithEmptyBaseStorage := &CacheStorageService{
baseStorageService: emptyBaseStorageService,
bigCacheConfig: TestBigCacheConfig,
bigCache: bigCache,
cache: cacheService.cache,
}
val, err = bigCacheServiceWithEmptyBaseStorage.GetByHash(ctx, val1CorrectKey)
val, err = cacheServiceWithEmptyBaseStorage.GetByHash(ctx, val1CorrectKey)
Require(t, err)
if !bytes.Equal(val, val1) {
t.Fatal(val, val1)
}

// Closes the base storage properly.
err = bigCacheService.Close(ctx)
err = cacheService.Close(ctx)
Require(t, err)
_, err = baseStorageService.GetByHash(ctx, val1CorrectKey)
if !errors.Is(err, ErrClosed) {
Expand Down
6 changes: 3 additions & 3 deletions das/das.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ type DataAvailabilityConfig struct {

RequestTimeout time.Duration `koanf:"request-timeout"`

LocalCache BigCacheConfig `koanf:"local-cache"`
RedisCache RedisConfig `koanf:"redis-cache"`
LocalCache CacheConfig `koanf:"local-cache"`
RedisCache RedisConfig `koanf:"redis-cache"`

LocalDBStorage LocalDBStorageConfig `koanf:"local-db-storage"`
LocalFileStorage LocalFileStorageConfig `koanf:"local-file-storage"`
Expand Down Expand Up @@ -109,7 +109,7 @@ func dataAvailabilityConfigAddOptions(prefix string, f *flag.FlagSet, r role) {
f.Bool(prefix+".disable-signature-checking", DefaultDataAvailabilityConfig.DisableSignatureChecking, "disables signature checking on Data Availability Store requests (DANGEROUS, FOR TESTING ONLY)")

// Cache options
BigCacheConfigAddOptions(prefix+".local-cache", f)
CacheConfigAddOptions(prefix+".local-cache", f)
RedisConfigAddOptions(prefix+".redis-cache", f)

// Storage options
Expand Down
7 changes: 2 additions & 5 deletions das/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func WrapStorageWithCache(
return nil, nil
}

// Enable caches, Redis and (local) BigCache. Local is the outermost, so it will be tried first.
// Enable caches, Redis and (local) Cache. Local is the outermost, so it will be tried first.
var err error
if config.RedisCache.Enable {
storageService, err = NewRedisStorageService(config.RedisCache, storageService)
Expand All @@ -130,11 +130,8 @@ func WrapStorageWithCache(
}
}
if config.LocalCache.Enable {
storageService, err = NewBigCacheStorageService(config.LocalCache, storageService)
storageService = NewCacheStorageService(config.LocalCache, storageService)
lifecycleManager.Register(storageService)
if err != nil {
return nil, err
}
}
return storageService, nil
}
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ require (
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
github.com/Shopify/toxiproxy v2.1.4+incompatible
github.com/alicebob/miniredis/v2 v2.21.0
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156
github.com/andybalholm/brotli v1.0.4
github.com/aws/aws-sdk-go-v2 v1.16.4
github.com/aws/aws-sdk-go-v2/config v1.15.5
Expand Down
2 changes: 1 addition & 1 deletion system_tests/das_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) {
serverConfig := das.DataAvailabilityConfig{
Enable: true,

LocalCache: das.TestBigCacheConfig,
LocalCache: das.TestCacheConfig,

LocalFileStorage: das.LocalFileStorageConfig{
Enable: true,
Expand Down

0 comments on commit 3ed2d0d

Please sign in to comment.