Skip to content

Commit

Permalink
Add cosmwasm-vm config
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Oct 12, 2024
1 parent 4f7575a commit bc859c9
Show file tree
Hide file tree
Showing 10 changed files with 374 additions and 156 deletions.
6 changes: 1 addition & 5 deletions internal/api/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,7 @@ typedef struct GasReport {
uint64_t used_internally;
} GasReport;

struct cache_t *init_cache(struct ByteSliceView data_dir,
struct ByteSliceView available_capabilities,
uint32_t cache_size,
uint32_t instance_memory_limit,
struct UnmanagedVector *error_msg);
struct cache_t *init_cache(struct ByteSliceView config, struct UnmanagedVector *error_msg);

struct UnmanagedVector save_wasm(struct cache_t *cache,
struct ByteSliceView wasm,
Expand Down
22 changes: 11 additions & 11 deletions internal/api/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"golang.org/x/sys/unix"

"github.com/CosmWasm/wasmvm/v2/types"
"github.com/shamaton/msgpack/v2"
)

// Value types
Expand Down Expand Up @@ -41,14 +42,14 @@ type Cache struct {

type Querier = types.Querier

func InitCache(dataDir string, supportedCapabilities []string, cacheSize uint32, instanceMemoryLimit uint32) (Cache, error) {
func InitCache(config types.Config) (Cache, error) {
// libwasmvm would create this directory too but we need it earlier for the lockfile
err := os.MkdirAll(dataDir, 0o755)
err := os.MkdirAll(config.Cache.BaseDir, 0o755)
if err != nil {
return Cache{}, fmt.Errorf("Could not create base directory")
}

lockfile, err := os.OpenFile(dataDir+"/exclusive.lock", os.O_WRONLY|os.O_CREATE, 0o666)
lockfile, err := os.OpenFile(config.Cache.BaseDir+"/exclusive.lock", os.O_WRONLY|os.O_CREATE, 0o666)
if err != nil {
return Cache{}, fmt.Errorf("Could not open exclusive.lock")
}
Expand All @@ -62,17 +63,16 @@ func InitCache(dataDir string, supportedCapabilities []string, cacheSize uint32,
return Cache{}, fmt.Errorf("Could not lock exclusive.lock. Is a different VM running in the same directory already?")
}

dataDirBytes := []byte(dataDir)
supportedCapabilitiesBytes := []byte(strings.Join(supportedCapabilities, ","))

d := makeView(dataDirBytes)
defer runtime.KeepAlive(dataDirBytes)
capabilitiesView := makeView(supportedCapabilitiesBytes)
defer runtime.KeepAlive(supportedCapabilitiesBytes)
configBytes, err := msgpack.Marshal(config)
if err != nil {
return Cache{}, fmt.Errorf("Could not serialize config")
}
configView := makeView(configBytes)
defer runtime.KeepAlive(configBytes)

errmsg := uninitializedUnmanagedVector()

ptr, err := C.init_cache(d, capabilitiesView, cu32(cacheSize), cu32(instanceMemoryLimit), &errmsg)
ptr, err := C.init_cache(configView, &errmsg)
if err != nil {
return Cache{}, errorWithMessage(err, errmsg)
}
Expand Down
110 changes: 99 additions & 11 deletions internal/api/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ func TestInitAndReleaseCache(t *testing.T) {
require.NoError(t, err)
defer os.RemoveAll(tmpdir)

cache, err := InitCache(tmpdir, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache, err := InitCache(config)
require.NoError(t, err)
ReleaseCache(cache)
}
Expand All @@ -46,7 +54,15 @@ func TestInitCacheWorksForNonExistentDir(t *testing.T) {
defer os.RemoveAll(tmpdir)

createMe := filepath.Join(tmpdir, "does-not-yet-exist")
cache, err := InitCache(createMe, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config := types.Config{
Cache: types.CacheOptions{
BaseDir: createMe,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache, err := InitCache(config)
require.NoError(t, err)
ReleaseCache(cache)
}
Expand All @@ -56,7 +72,15 @@ func TestInitCacheErrorsForBrokenDir(t *testing.T) {
// https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3
// On Unix we should not have permission to create this.
cannotBeCreated := "/foo:bar"
_, err := InitCache(cannotBeCreated, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config := types.Config{
Cache: types.CacheOptions{
BaseDir: cannotBeCreated,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
_, err := InitCache(config)
require.ErrorContains(t, err, "Could not create base directory")
}

Expand All @@ -65,16 +89,40 @@ func TestInitLockingPreventsConcurrentAccess(t *testing.T) {
require.NoError(t, err)
defer os.RemoveAll(tmpdir)

cache1, err1 := InitCache(tmpdir, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config1 := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache1, err1 := InitCache(config1)
require.NoError(t, err1)

_, err2 := InitCache(tmpdir, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config2 := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
_, err2 := InitCache(config2)
require.ErrorContains(t, err2, "Could not lock exclusive.lock")

ReleaseCache(cache1)

// Now we can try again
cache3, err3 := InitCache(tmpdir, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config3 := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache3, err3 := InitCache(config3)
require.NoError(t, err3)
ReleaseCache(cache3)
}
Expand All @@ -90,11 +138,35 @@ func TestInitLockingAllowsMultipleInstancesInDifferentDirs(t *testing.T) {
defer os.RemoveAll(tmpdir2)
defer os.RemoveAll(tmpdir3)

cache1, err1 := InitCache(tmpdir1, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config1 := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir1,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache1, err1 := InitCache(config1)
require.NoError(t, err1)
cache2, err2 := InitCache(tmpdir2, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config2 := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir2,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache2, err2 := InitCache(config2)
require.NoError(t, err2)
cache3, err3 := InitCache(tmpdir3, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config3 := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir3,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache3, err3 := InitCache(config3)
require.NoError(t, err3)

ReleaseCache(cache1)
Expand All @@ -106,15 +178,31 @@ func TestInitCacheEmptyCapabilities(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "wasmvm-testing")
require.NoError(t, err)
defer os.RemoveAll(tmpdir)
cache, err := InitCache(tmpdir, []string{}, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir,
AvailableCapabilities: []string{},
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache, err := InitCache(config)
require.NoError(t, err)
ReleaseCache(cache)
}

func withCache(t testing.TB) (Cache, func()) {
tmpdir, err := os.MkdirTemp("", "wasmvm-testing")
require.NoError(t, err)
cache, err := InitCache(tmpdir, TESTING_CAPABILITIES, TESTING_CACHE_SIZE, TESTING_MEMORY_LIMIT)
config := types.Config{
Cache: types.CacheOptions{
BaseDir: tmpdir,
AvailableCapabilities: TESTING_CAPABILITIES,
MemoryCacheSize: types.NewSizeMebi(TESTING_CACHE_SIZE),
InstanceMemoryLimit: types.NewSizeMebi(TESTING_MEMORY_LIMIT),
},
}
cache, err := InitCache(config)
require.NoError(t, err)

cleanup := func() {
Expand Down
10 changes: 9 additions & 1 deletion lib_libwasmvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ type VM struct {
// `cacheSize` sets the size in MiB of an in-memory cache for e.g. module caching. Set to 0 to disable.
// `deserCost` sets the gas cost of deserializing one byte of data.
func NewVM(dataDir string, supportedCapabilities []string, memoryLimit uint32, printDebug bool, cacheSize uint32) (*VM, error) {
cache, err := api.InitCache(dataDir, supportedCapabilities, cacheSize, memoryLimit)
// TODO: expose config variant of NewVM
cache, err := api.InitCache(types.Config{
Cache: types.CacheOptions{
BaseDir: dataDir,
AvailableCapabilities: supportedCapabilities,
MemoryCacheSize: types.NewSizeMebi(cacheSize),
InstanceMemoryLimit: types.NewSizeMebi(memoryLimit),
},
})
if err != nil {
return nil, err
}
Expand Down
6 changes: 1 addition & 5 deletions libwasmvm/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,7 @@ typedef struct GasReport {
uint64_t used_internally;
} GasReport;

struct cache_t *init_cache(struct ByteSliceView data_dir,
struct ByteSliceView available_capabilities,
uint32_t cache_size,
uint32_t instance_memory_limit,
struct UnmanagedVector *error_msg);
struct cache_t *init_cache(struct ByteSliceView config, struct UnmanagedVector *error_msg);

struct UnmanagedVector save_wasm(struct cache_t *cache,
struct ByteSliceView wasm,
Expand Down
3 changes: 1 addition & 2 deletions libwasmvm/src/args.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// store some common string for argument names
pub const DATA_DIR_ARG: &str = "data_dir";
pub const AVAILABLE_CAPABILITIES_ARG: &str = "available_capabilities";
pub const CONFIG_ARG: &str = "config";
pub const CACHE_ARG: &str = "cache";
pub const WASM_ARG: &str = "wasm";
pub const CHECKSUM_ARG: &str = "checksum";
Expand Down
Loading

0 comments on commit bc859c9

Please sign in to comment.