syncbase: simplify store_util and its clients

This resolves a number of TODOs.

Change-Id: I510a549b74ce6ff3affd69006c57e8b25c8343cc
diff --git a/v23/syncbase/nosql/exec_test/exec_test.go b/v23/syncbase/nosql/exec_test/exec_test.go
index fdd63ca..e188585 100644
--- a/v23/syncbase/nosql/exec_test/exec_test.go
+++ b/v23/syncbase/nosql/exec_test/exec_test.go
@@ -922,7 +922,7 @@
 		{
 			"select v from Unknown",
 			// The following error text is dependent on the implementation of the query_db.Database interface.
-			syncql.NewErrTableCantAccess(ctx, 14, "Unknown", errors.New("exec_test.test:\"a/db\".Exec: Does not exist: Unknown")),
+			syncql.NewErrTableCantAccess(ctx, 14, "Unknown", errors.New("exec_test.test:\"a/db\".Exec: Does not exist: $table:Unknown")),
 		},
 		{
 			"select v from Customer offset -1",
diff --git a/v23/syncbase/util/glob.go b/v23/syncbase/util/glob.go
index 1f12149..5303521 100644
--- a/v23/syncbase/util/glob.go
+++ b/v23/syncbase/util/glob.go
@@ -13,8 +13,7 @@
 	"v.io/v23/naming"
 )
 
-// List does namespace.Glob("name/*") and returns a sorted slice of results or
-// a VDL-compatible error.
+// List does namespace.Glob("name/*") and returns a sorted slice of results.
 func List(ctx *context.T, name string) ([]string, error) {
 	// TODO(sadovsky): Why can't Glob be a method on the stub, just like every
 	// other streaming method? Even if we encourage clients to use the namespace
diff --git a/x/ref/services/syncbase/server/app.go b/x/ref/services/syncbase/server/app.go
index a2b081a..48338f5 100644
--- a/x/ref/services/syncbase/server/app.go
+++ b/x/ref/services/syncbase/server/app.go
@@ -35,7 +35,6 @@
 var (
 	_ wire.AppServerMethods = (*app)(nil)
 	_ interfaces.App        = (*app)(nil)
-	_ util.Layer            = (*app)(nil)
 )
 
 ////////////////////////////////////////
@@ -69,7 +68,7 @@
 		return nil, "", verror.New(verror.ErrNoExist, ctx, a.name)
 	}
 	data := &appData{}
-	if err := util.Get(ctx, call, a.s.st, a, data); err != nil {
+	if err := util.GetWithAuth(ctx, call, a.s.st, a.stKey(), data); err != nil {
 		return nil, "", err
 	}
 	return data.Perms, util.FormatVersion(data.Version), nil
@@ -84,7 +83,7 @@
 	closeSnapshot := func() error {
 		return sn.Close()
 	}
-	if err := util.Get(ctx, call, sn, a, &appData{}); err != nil {
+	if err := util.GetWithAuth(ctx, call, sn, a.stKey(), &appData{}); err != nil {
 		closeSnapshot()
 		return nil, err
 	}
@@ -150,7 +149,7 @@
 	aData := &appData{}
 	if err := store.RunInTransaction(a.s.st, func(st store.StoreReadWriter) error {
 		// Check appData perms.
-		if err := util.Get(ctx, call, st, a, aData); err != nil {
+		if err := util.GetWithAuth(ctx, call, st, a.stKey(), aData); err != nil {
 			return err
 		}
 		// Check for "database already exists".
@@ -267,20 +266,17 @@
 	return d.SetPermsInternal(ctx, call, perms, version)
 }
 
-////////////////////////////////////////
-// util.Layer methods
-
 func (a *app) Name() string {
 	return a.name
 }
 
-func (a *app) StKey() string {
-	return util.JoinKeyParts(util.AppPrefix, a.stKeyPart())
-}
-
 ////////////////////////////////////////
 // Internal helpers
 
+func (a *app) stKey() string {
+	return util.JoinKeyParts(util.AppPrefix, a.stKeyPart())
+}
+
 func (a *app) stKeyPart() string {
 	return a.name
 }
diff --git a/x/ref/services/syncbase/server/db_info.go b/x/ref/services/syncbase/server/db_info.go
index cbfcebd..39ffdc8 100644
--- a/x/ref/services/syncbase/server/db_info.go
+++ b/x/ref/services/syncbase/server/db_info.go
@@ -19,58 +19,30 @@
 	"v.io/v23/context"
 )
 
-type dbInfoLayer struct {
-	name string
-	a    *app
-}
-
-var (
-	_ util.Layer = (*dbInfoLayer)(nil)
-)
-
-////////////////////////////////////////
-// dbInfoLayer util.Layer methods
-
-func (d *dbInfoLayer) Name() string {
-	return d.name
-}
-
-func (d *dbInfoLayer) StKey() string {
-	return util.JoinKeyParts(util.DbInfoPrefix, d.stKeyPart())
-}
-
-////////////////////////////////////////
-// Internal helpers
-
-func (d *dbInfoLayer) stKeyPart() string {
-	return util.JoinKeyParts(d.a.stKeyPart(), d.name)
+func dbInfoStKey(a *app, dbName string) string {
+	return util.JoinKeyParts(util.DbInfoPrefix, a.stKeyPart(), dbName)
 }
 
 // getDbInfo reads data from the storage engine.
-// Returns a VDL-compatible error.
 func (a *app) getDbInfo(ctx *context.T, st store.StoreReader, dbName string) (*dbInfo, error) {
 	info := &dbInfo{}
-	if err := util.GetWithoutAuth(ctx, st, &dbInfoLayer{dbName, a}, info); err != nil {
+	if err := util.Get(ctx, st, dbInfoStKey(a, dbName), info); err != nil {
 		return nil, err
 	}
 	return info, nil
 }
 
 // putDbInfo writes data to the storage engine.
-// Returns a VDL-compatible error.
 func (a *app) putDbInfo(ctx *context.T, st store.StoreWriter, dbName string, info *dbInfo) error {
-	return util.Put(ctx, st, &dbInfoLayer{dbName, a}, info)
+	return util.Put(ctx, st, dbInfoStKey(a, dbName), info)
 }
 
 // delDbInfo deletes data from the storage engine.
-// Returns a VDL-compatible error.
 func (a *app) delDbInfo(ctx *context.T, st store.StoreWriter, dbName string) error {
-	return util.Delete(ctx, st, &dbInfoLayer{dbName, a})
+	return util.Delete(ctx, st, dbInfoStKey(a, dbName))
 }
 
-// updateDbInfo performs a read-modify-write.
-// fn should "modify" v, and should return a VDL-compatible error.
-// Returns a VDL-compatible error.
+// updateDbInfo performs a read-modify-write. fn should "modify" v.
 func (a *app) updateDbInfo(ctx *context.T, st store.StoreReadWriter, dbName string, fn func(info *dbInfo) error) error {
 	_ = st.(store.Transaction) // panics on failure, as desired
 	info, err := a.getDbInfo(ctx, st, dbName)
diff --git a/x/ref/services/syncbase/server/db_info_test.go b/x/ref/services/syncbase/server/db_info_test.go
index 47db158..7bc0870 100644
--- a/x/ref/services/syncbase/server/db_info_test.go
+++ b/x/ref/services/syncbase/server/db_info_test.go
@@ -8,23 +8,18 @@
 	"testing"
 )
 
-type stk struct {
-	appName string
-	dbName  string
-	stkey   string
-}
-
-var stTestKey stk = stk{"app1", "db1", "$dbInfo:app1:db1"}
-
-var dbinfo *dbInfoLayer = &dbInfoLayer{
-	name: stTestKey.dbName,
-	a: &app{
-		name: stTestKey.appName,
-	},
-}
-
 func TestStKey(t *testing.T) {
-	if stTestKey.stkey != dbinfo.StKey() {
-		t.Errorf("dbInfoLayer stkey expected to be %q but found to be %q", stTestKey.stkey, dbinfo.StKey())
+	tests := []struct {
+		appName string
+		dbName  string
+		stKey   string
+	}{
+		{"app1", "db1", "$dbInfo:app1:db1"},
+	}
+	for _, test := range tests {
+		got, want := dbInfoStKey(&app{name: test.appName}, test.dbName), test.stKey
+		if got != want {
+			t.Errorf("wrong stKey: got %q, want %q", got, want)
+		}
 	}
 }
diff --git a/x/ref/services/syncbase/server/interfaces/app.go b/x/ref/services/syncbase/server/interfaces/app.go
index 8ac9990..b1d5d4f 100644
--- a/x/ref/services/syncbase/server/interfaces/app.go
+++ b/x/ref/services/syncbase/server/interfaces/app.go
@@ -5,15 +5,12 @@
 package interfaces
 
 import (
-	"v.io/syncbase/x/ref/services/syncbase/server/util"
-
 	"v.io/v23/context"
 	"v.io/v23/rpc"
 	"v.io/v23/security/access"
 )
 
 // App is an internal interface to the app layer.
-// All methods return VDL-compatible errors.
 type App interface {
 	// Service returns the service handle for this app.
 	Service() Service
@@ -33,5 +30,6 @@
 	// SetDatabasePerms sets the perms for the specified database.
 	SetDatabasePerms(ctx *context.T, call rpc.ServerCall, dbName string, perms access.Permissions, version string) error
 
-	util.Layer
+	// Name returns the name of this app.
+	Name() string
 }
diff --git a/x/ref/services/syncbase/server/interfaces/database.go b/x/ref/services/syncbase/server/interfaces/database.go
index 832a940..bf518a4 100644
--- a/x/ref/services/syncbase/server/interfaces/database.go
+++ b/x/ref/services/syncbase/server/interfaces/database.go
@@ -5,7 +5,6 @@
 package interfaces
 
 import (
-	"v.io/syncbase/x/ref/services/syncbase/server/util"
 	"v.io/syncbase/x/ref/services/syncbase/store"
 	"v.io/v23/context"
 	"v.io/v23/rpc"
@@ -13,7 +12,6 @@
 )
 
 // Database is an internal interface to the database layer.
-// All methods return VDL-compatible errors.
 type Database interface {
 	// St returns the storage engine instance for this database.
 	St() store.Store
@@ -30,5 +28,6 @@
 	// Designed for use from within App.SetDatabasePerms.
 	SetPermsInternal(ctx *context.T, call rpc.ServerCall, perms access.Permissions, version string) error
 
-	util.Layer
+	// Name returns the name of this database.
+	Name() string
 }
diff --git a/x/ref/services/syncbase/server/interfaces/service.go b/x/ref/services/syncbase/server/interfaces/service.go
index 4505dce..ce665e2 100644
--- a/x/ref/services/syncbase/server/interfaces/service.go
+++ b/x/ref/services/syncbase/server/interfaces/service.go
@@ -11,7 +11,6 @@
 )
 
 // Service is an internal interface to the service layer.
-// All methods return VDL-compatible errors.
 type Service interface {
 	// St returns the storage engine instance for this service.
 	St() store.Store
diff --git a/x/ref/services/syncbase/server/nosql/database.go b/x/ref/services/syncbase/server/nosql/database.go
index f12d437..62ad371 100644
--- a/x/ref/services/syncbase/server/nosql/database.go
+++ b/x/ref/services/syncbase/server/nosql/database.go
@@ -62,7 +62,6 @@
 var (
 	_ wire.DatabaseServerMethods = (*databaseReq)(nil)
 	_ interfaces.Database        = (*database)(nil)
-	_ util.Layer                 = (*database)(nil)
 )
 
 // DatabaseOptions configures a database.
@@ -99,7 +98,6 @@
 }
 
 // NewDatabase creates a new database instance and returns it.
-// Returns a VDL-compatible error.
 // Designed for use from within App.CreateNoSQLDatabase.
 func NewDatabase(ctx *context.T, a interfaces.App, name string, opts DatabaseOptions) (*database, error) {
 	if opts.Perms == nil {
@@ -113,7 +111,7 @@
 		Name:  d.name,
 		Perms: opts.Perms,
 	}
-	if err := util.Put(ctx, d.st, d, data); err != nil {
+	if err := util.Put(ctx, d.st, d.stKey(), data); err != nil {
 		return nil, err
 	}
 	return d, nil
@@ -275,7 +273,7 @@
 		return nil, "", wire.NewErrBoundToBatch(ctx)
 	}
 	data := &databaseData{}
-	if err := util.Get(ctx, call, d.st, d, data); err != nil {
+	if err := util.GetWithAuth(ctx, call, d.st, d.stKey(), data); err != nil {
 		return nil, "", err
 	}
 	return data.Perms, util.FormatVersion(data.Version), nil
@@ -293,7 +291,7 @@
 	closeSnapshot := func() error {
 		return sn.Close()
 	}
-	if err := util.Get(ctx, call, sn, d, &databaseData{}); err != nil {
+	if err := util.GetWithAuth(ctx, call, sn, d.stKey(), &databaseData{}); err != nil {
 		closeSnapshot()
 		return nil, err
 	}
@@ -348,7 +346,7 @@
 	if !d.exists {
 		vlog.Fatalf("database %q does not exist", d.name)
 	}
-	return util.Get(ctx, call, st, d, &databaseData{})
+	return util.GetWithAuth(ctx, call, st, d.stKey(), &databaseData{})
 }
 
 func (d *database) SetPermsInternal(ctx *context.T, call rpc.ServerCall, perms access.Permissions, version string) error {
@@ -357,7 +355,7 @@
 	}
 	return store.RunInTransaction(d.st, func(st store.StoreReadWriter) error {
 		data := &databaseData{}
-		return util.Update(ctx, call, st, d, data, func() error {
+		return util.UpdateWithAuth(ctx, call, st, d.stKey(), data, func() error {
 			if err := util.CheckVersion(ctx, version, data.Version); err != nil {
 				return err
 			}
@@ -368,19 +366,12 @@
 	})
 }
 
-////////////////////////////////////////
-// util.Layer methods
-
 func (d *database) Name() string {
 	return d.name
 }
 
-func (d *database) StKey() string {
-	return util.DatabasePrefix
-}
-
 ////////////////////////////////////////
-// query_db implementations
+// query_db implementation
 
 // Implement query_db's Database, Table and KeyValueStream interfaces.
 type queryDb struct {
@@ -403,7 +394,7 @@
 		},
 	}
 	// Now that we have a table, we need to check permissions.
-	if err := util.Get(db.ctx, db.call, db.st, tDb.req, &tableData{}); err != nil {
+	if err := util.GetWithAuth(db.ctx, db.call, db.st, tDb.req.stKey(), &tableData{}); err != nil {
 		return nil, err
 	}
 	return tDb, nil
@@ -505,6 +496,10 @@
 ////////////////////////////////////////
 // Internal helpers
 
+func (d *database) stKey() string {
+	return util.DatabasePrefix
+}
+
 func (d *databaseReq) batchReader() store.StoreReader {
 	if d.batchId == nil {
 		return nil
diff --git a/x/ref/services/syncbase/server/nosql/row.go b/x/ref/services/syncbase/server/nosql/row.go
index 542224a..88c08c7 100644
--- a/x/ref/services/syncbase/server/nosql/row.go
+++ b/x/ref/services/syncbase/server/nosql/row.go
@@ -21,7 +21,6 @@
 
 var (
 	_ wire.RowServerMethods = (*rowReq)(nil)
-	_ util.Layer            = (*rowReq)(nil)
 )
 
 ////////////////////////////////////////
@@ -73,41 +72,32 @@
 }
 
 ////////////////////////////////////////
-// util.Layer methods
+// Internal helpers
 
-func (r *rowReq) Name() string {
-	return r.key
-}
-
-func (r *rowReq) StKey() string {
+func (r *rowReq) stKey() string {
 	return util.JoinKeyParts(util.RowPrefix, r.stKeyPart())
 }
 
-////////////////////////////////////////
-// Internal helpers
-
 func (r *rowReq) stKeyPart() string {
 	return util.JoinKeyParts(r.t.stKeyPart(), r.key)
 }
 
 // checkAccess checks that this row's table exists in the database, and performs
 // an authorization check.
-// Returns a VDL-compatible error.
 func (r *rowReq) checkAccess(ctx *context.T, call rpc.ServerCall, st store.StoreReader) error {
 	return r.t.checkAccess(ctx, call, st, r.key)
 }
 
 // get reads data from the storage engine.
 // Performs authorization check.
-// Returns a VDL-compatible error.
 func (r *rowReq) get(ctx *context.T, call rpc.ServerCall, st store.StoreReader) ([]byte, error) {
 	if err := r.checkAccess(ctx, call, st); err != nil {
 		return nil, err
 	}
-	value, err := st.Get([]byte(r.StKey()), nil)
+	value, err := st.Get([]byte(r.stKey()), nil)
 	if err != nil {
 		if verror.ErrorID(err) == store.ErrUnknownKey.ID {
-			return nil, verror.New(verror.ErrNoExist, ctx, r.Name())
+			return nil, verror.New(verror.ErrNoExist, ctx, r.stKey())
 		}
 		return nil, verror.New(verror.ErrInternal, ctx, err)
 	}
@@ -116,12 +106,11 @@
 
 // put writes data to the storage engine.
 // Performs authorization check.
-// Returns a VDL-compatible error.
 func (r *rowReq) put(ctx *context.T, call rpc.ServerCall, st store.StoreReadWriter, value []byte) error {
 	if err := r.checkAccess(ctx, call, st); err != nil {
 		return err
 	}
-	if err := st.Put([]byte(r.StKey()), value); err != nil {
+	if err := st.Put([]byte(r.stKey()), value); err != nil {
 		return verror.New(verror.ErrInternal, ctx, err)
 	}
 	return nil
@@ -129,12 +118,11 @@
 
 // delete deletes data from the storage engine.
 // Performs authorization check.
-// Returns a VDL-compatible error.
 func (r *rowReq) delete(ctx *context.T, call rpc.ServerCall, st store.StoreReadWriter) error {
 	if err := r.checkAccess(ctx, call, st); err != nil {
 		return err
 	}
-	if err := st.Delete([]byte(r.StKey())); err != nil {
+	if err := st.Delete([]byte(r.stKey())); err != nil {
 		return verror.New(verror.ErrInternal, ctx, err)
 	}
 	return nil
diff --git a/x/ref/services/syncbase/server/nosql/table.go b/x/ref/services/syncbase/server/nosql/table.go
index 82a0cab..37e1fbe 100644
--- a/x/ref/services/syncbase/server/nosql/table.go
+++ b/x/ref/services/syncbase/server/nosql/table.go
@@ -25,7 +25,6 @@
 
 var (
 	_ wire.TableServerMethods = (*tableReq)(nil)
-	_ util.Layer              = (*tableReq)(nil)
 )
 
 ////////////////////////////////////////
@@ -38,11 +37,11 @@
 	return store.RunInTransaction(t.d.st, func(st store.StoreReadWriter) error {
 		// Check databaseData perms.
 		dData := &databaseData{}
-		if err := util.Get(ctx, call, st, t.d, dData); err != nil {
+		if err := util.GetWithAuth(ctx, call, st, t.d.stKey(), dData); err != nil {
 			return err
 		}
 		// Check for "table already exists".
-		if err := util.GetWithoutAuth(ctx, st, t, &tableData{}); verror.ErrorID(err) != verror.ErrNoExist.ID {
+		if err := util.Get(ctx, st, t.stKey(), &tableData{}); verror.ErrorID(err) != verror.ErrNoExist.ID {
 			if err != nil {
 				return err
 			}
@@ -57,7 +56,7 @@
 			Name:  t.name,
 			Perms: perms,
 		}
-		return util.Put(ctx, st, t, data)
+		return util.Put(ctx, st, t.stKey(), data)
 	})
 }
 
@@ -67,14 +66,14 @@
 	}
 	return store.RunInTransaction(t.d.st, func(st store.StoreReadWriter) error {
 		// Read-check-delete tableData.
-		if err := util.Get(ctx, call, st, t, &tableData{}); err != nil {
+		if err := util.GetWithAuth(ctx, call, st, t.stKey(), &tableData{}); err != nil {
 			if verror.ErrorID(err) == verror.ErrNoExist.ID {
 				return nil // delete is idempotent
 			}
 			return err
 		}
 		// TODO(sadovsky): Delete all rows in this table.
-		return util.Delete(ctx, st, t)
+		return util.Delete(ctx, st, t.stKey())
 	})
 }
 
@@ -199,7 +198,7 @@
 		}
 		if prefix == "" {
 			data := &tableData{}
-			return util.Update(ctx, call, st, t, data, func() error {
+			return util.UpdateWithAuth(ctx, call, st, t.stKey(), data, func() error {
 				data.Perms = perms
 				return nil
 			})
@@ -224,10 +223,10 @@
 		stPrefixLimit := stPrefix + util.PrefixRangeLimitSuffix
 		prefixPerms = stPrefixPerms{Parent: parent, Perms: perms}
 		// Put the (prefix, perms) pair to the database.
-		if err := util.PutObject(st, stPrefix, prefixPerms); err != nil {
+		if err := util.Put(ctx, st, stPrefix, prefixPerms); err != nil {
 			return err
 		}
-		return util.PutObject(st, stPrefixLimit, prefixPerms)
+		return util.Put(ctx, st, stPrefixLimit, prefixPerms)
 	}
 	if t.d.batchId != nil {
 		if st, err := t.d.batchReadWriter(); err != nil {
@@ -315,19 +314,12 @@
 }
 
 ////////////////////////////////////////
-// util.Layer methods
+// Internal helpers
 
-func (t *tableReq) Name() string {
-	return t.name
-}
-
-func (t *tableReq) StKey() string {
+func (t *tableReq) stKey() string {
 	return util.JoinKeyParts(util.TablePrefix, t.stKeyPart())
 }
 
-////////////////////////////////////////
-// Internal helpers
-
 func (t *tableReq) stKeyPart() string {
 	return t.name
 }
@@ -348,7 +340,7 @@
 			return verror.New(verror.ErrInternal, ctx, err)
 		}
 		prefixPerms.Parent = newParent
-		if err := util.PutObject(st, string(key), prefixPerms); err != nil {
+		if err := util.Put(ctx, st, string(key), prefixPerms); err != nil {
 			it.Cancel()
 			return err
 		}
@@ -359,31 +351,29 @@
 	return nil
 }
 
-// lock invalidates all concurrent transactions with ErrConcurrentTransaction
-// that have accessed this table.
-// Returns a VDL-compatible error.
+// lock invalidates all in-flight transactions that have touched this table,
+// such that any subsequent tx.Commit() will return ErrConcurrentTransaction.
 //
-// It is necessary to call lock() every time prefix permissions are updated,
-// so snapshots inside all transactions reflect up-to-date permissions. Since
+// It is necessary to call lock() every time prefix permissions are updated so
+// that snapshots inside all transactions reflect up-to-date permissions. Since
 // every public function that touches this table has to read the table-level
-// permissions object, it is enough to add the key of table-level permissions
-// to the write set of the current transaction.
+// permissions object, it suffices to add the key of this object to the write
+// set of the current transaction.
 //
 // TODO(rogulenko): Revisit this behavior to provide more granularity.
-// A possible option would be to add prefix and its parent to the write set
-// of the current transaction when permissions object for a prefix is updated.
+// One option is to add a prefix and its parent to the write set of the current
+// transaction when the permissions object for that prefix is updated.
 func (t *tableReq) lock(ctx *context.T, st store.StoreReadWriter) error {
 	var data tableData
-	if err := util.GetWithoutAuth(ctx, st, t, &data); err != nil {
+	if err := util.Get(ctx, st, t.stKey(), &data); err != nil {
 		return err
 	}
-	return util.Put(ctx, st, t, data)
+	return util.Put(ctx, st, t.stKey(), data)
 }
 
 // checkAccess checks that this table exists in the database, and performs
 // an authorization check. The access is checked at table level and at the
 // level of the most specific prefix for the given key.
-// Returns a VDL-compatible error.
 // TODO(rogulenko): Revisit this behavior. Eventually we'll want the table-level
 // access check to be a check for "Resolve", i.e. also check access to
 // service, app and database.
@@ -393,7 +383,7 @@
 		return err
 	}
 	if prefix != "" {
-		if err := util.Get(ctx, call, st, t, &tableData{}); err != nil {
+		if err := util.GetWithAuth(ctx, call, st, t.stKey(), &tableData{}); err != nil {
 			return err
 		}
 	}
@@ -405,15 +395,14 @@
 }
 
 // permsForKey returns the longest prefix of the given key that has
-// associated permissions with its permissions object.
+// associated permissions, along with its permissions object.
 // permsForKey doesn't perform an authorization check.
-// Returns a VDL-compatible error.
 //
-// Virtually we represent all prefixes as a forest T, where each vertex maps to
-// a prefix. A parent for a string is the maximum proper prefix of it that
+// Effectively, we represent all prefixes as a forest T, where each vertex maps
+// to a prefix. A parent for a string is the maximum proper prefix of it that
 // belongs to T. Each prefix P from T is represented as a pair of entries with
-// keys P and P~ with values of type stPrefixPerms (parent + perms).
-// High level of how this function works:
+// keys P and P~ with values of type stPrefixPerms (parent + perms). High level
+// explanation of how this function works:
 // 1	iter = db.Scan(K, "")
 // 		Here last character of iter.Key() is removed automatically if it is '~'
 // 2	if hasPrefix(K, iter.Key()) return iter.Value()
@@ -452,17 +441,16 @@
 
 // permsForPrefix returns the permissions object associated with the
 // provided prefix.
-// Returns a VDL-compatible error.
 func (t *tableReq) permsForPrefix(ctx *context.T, st store.StoreReader, prefix string) (stPrefixPerms, error) {
 	if prefix == "" {
 		var data tableData
-		if err := util.GetWithoutAuth(ctx, st, t, &data); err != nil {
+		if err := util.Get(ctx, st, t.stKey(), &data); err != nil {
 			return stPrefixPerms{}, err
 		}
 		return stPrefixPerms{Perms: data.Perms}, nil
 	}
 	var prefixPerms stPrefixPerms
-	if err := util.GetObject(st, t.prefixPermsKey(prefix), &prefixPerms); err != nil {
+	if err := util.Get(ctx, st, t.prefixPermsKey(prefix), &prefixPerms); err != nil {
 		return stPrefixPerms{}, verror.New(verror.ErrInternal, ctx, err)
 	}
 	return prefixPerms, nil
diff --git a/x/ref/services/syncbase/server/service.go b/x/ref/services/syncbase/server/service.go
index 9f9e5b3..8ed1480 100644
--- a/x/ref/services/syncbase/server/service.go
+++ b/x/ref/services/syncbase/server/service.go
@@ -39,7 +39,6 @@
 var (
 	_ wire.ServiceServerMethods = (*service)(nil)
 	_ interfaces.Service        = (*service)(nil)
-	_ util.Layer                = (*service)(nil)
 )
 
 // ServiceOptions configures a service.
@@ -56,7 +55,6 @@
 }
 
 // NewService creates a new service instance and returns it.
-// Returns a VDL-compatible error.
 // TODO(sadovsky): If possible, close all stores when the server is stopped.
 func NewService(ctx *context.T, call rpc.ServerCall, opts ServiceOptions) (*service, error) {
 	if opts.Perms == nil {
@@ -74,7 +72,7 @@
 	data := &serviceData{
 		Perms: opts.Perms,
 	}
-	if err := util.GetWithoutAuth(ctx, st, s, &serviceData{}); verror.ErrorID(err) != verror.ErrNoExist.ID {
+	if err := util.Get(ctx, st, s.stKey(), &serviceData{}); verror.ErrorID(err) != verror.ErrNoExist.ID {
 		if err != nil {
 			return nil, err
 		}
@@ -125,7 +123,7 @@
 		}
 	} else {
 		// Service does not exist.
-		if err := util.Put(ctx, st, s, data); err != nil {
+		if err := util.Put(ctx, st, s.stKey(), data); err != nil {
 			return nil, err
 		}
 	}
@@ -143,7 +141,7 @@
 func (s *service) SetPermissions(ctx *context.T, call rpc.ServerCall, perms access.Permissions, version string) error {
 	return store.RunInTransaction(s.st, func(st store.StoreReadWriter) error {
 		data := &serviceData{}
-		return util.Update(ctx, call, st, s, data, func() error {
+		return util.UpdateWithAuth(ctx, call, st, s.stKey(), data, func() error {
 			if err := util.CheckVersion(ctx, version, data.Version); err != nil {
 				return err
 			}
@@ -156,7 +154,7 @@
 
 func (s *service) GetPermissions(ctx *context.T, call rpc.ServerCall) (perms access.Permissions, version string, err error) {
 	data := &serviceData{}
-	if err := util.Get(ctx, call, s.st, s, data); err != nil {
+	if err := util.GetWithAuth(ctx, call, s.st, s.stKey(), data); err != nil {
 		return nil, "", err
 	}
 	return data.Perms, util.FormatVersion(data.Version), nil
@@ -168,7 +166,7 @@
 	closeSnapshot := func() error {
 		return sn.Close()
 	}
-	if err := util.Get(ctx, call, sn, s, &serviceData{}); err != nil {
+	if err := util.GetWithAuth(ctx, call, sn, s.stKey(), &serviceData{}); err != nil {
 		closeSnapshot()
 		return nil, err
 	}
@@ -230,11 +228,11 @@
 	if err := store.RunInTransaction(s.st, func(st store.StoreReadWriter) error {
 		// Check serviceData perms.
 		sData := &serviceData{}
-		if err := util.Get(ctx, call, st, s, sData); err != nil {
+		if err := util.GetWithAuth(ctx, call, st, s.stKey(), sData); err != nil {
 			return err
 		}
 		// Check for "app already exists".
-		if err := util.GetWithoutAuth(ctx, st, a, &appData{}); verror.ErrorID(err) != verror.ErrNoExist.ID {
+		if err := util.Get(ctx, st, a.stKey(), &appData{}); verror.ErrorID(err) != verror.ErrNoExist.ID {
 			if err != nil {
 				return err
 			}
@@ -248,7 +246,7 @@
 			Name:  appName,
 			Perms: perms,
 		}
-		return util.Put(ctx, st, a, data)
+		return util.Put(ctx, st, a.stKey(), data)
 	}); err != nil {
 		return err
 	}
@@ -267,14 +265,14 @@
 
 	if err := store.RunInTransaction(s.st, func(st store.StoreReadWriter) error {
 		// Read-check-delete appData.
-		if err := util.Get(ctx, call, st, a, &appData{}); err != nil {
+		if err := util.GetWithAuth(ctx, call, st, a.stKey(), &appData{}); err != nil {
 			if verror.ErrorID(err) == verror.ErrNoExist.ID {
 				return nil // delete is idempotent
 			}
 			return err
 		}
 		// TODO(sadovsky): Delete all databases in this app.
-		return util.Delete(ctx, st, a)
+		return util.Delete(ctx, st, a.stKey())
 	}); err != nil {
 		return err
 	}
@@ -292,7 +290,7 @@
 	}
 	return store.RunInTransaction(s.st, func(st store.StoreReadWriter) error {
 		data := &appData{}
-		return util.Update(ctx, call, st, a, data, func() error {
+		return util.UpdateWithAuth(ctx, call, st, a.stKey(), data, func() error {
 			if err := util.CheckVersion(ctx, version, data.Version); err != nil {
 				return err
 			}
@@ -304,12 +302,8 @@
 }
 
 ////////////////////////////////////////
-// util.Layer methods
+// Other internal helpers
 
-func (s *service) Name() string {
-	return "service"
-}
-
-func (s *service) StKey() string {
+func (s *service) stKey() string {
 	return util.ServicePrefix
 }
diff --git a/x/ref/services/syncbase/server/util/store_util.go b/x/ref/services/syncbase/server/util/store_util.go
index a30f487..d62c222 100644
--- a/x/ref/services/syncbase/server/util/store_util.go
+++ b/x/ref/services/syncbase/server/util/store_util.go
@@ -29,100 +29,73 @@
 	return nil
 }
 
-////////////////////////////////////////////////////////////
-// RPC-aware, higher-level get/put
-
-type Layer interface {
-	// Name returns the name of this instance, e.g. "fooapp" or "bardb".
-	Name() string
-	// StKey returns the storage engine key to use for metadata about this layer,
-	// e.g. "$table:baztable".
-	StKey() string
-}
+// TODO(sadovsky): Perhaps these functions should strip key prefixes such as
+// "$table:" from the error messages they return.
 
 type Permser interface {
 	// GetPerms returns the Permissions for this Layer.
 	GetPerms() access.Permissions
 }
 
-// GetWithoutAuth does st.Get(l.StKey(), v), populating v.
-// Returns a VDL-compatible error.
-func GetWithoutAuth(ctx *context.T, st store.StoreReader, l Layer, v interface{}) error {
-	if err := GetObject(st, l.StKey(), v); err != nil {
+// Get does st.Get(k, v) and wraps the returned error.
+func Get(ctx *context.T, st store.StoreReader, k string, v interface{}) error {
+	bytes, err := st.Get([]byte(k), nil)
+	if err != nil {
 		if verror.ErrorID(err) == store.ErrUnknownKey.ID {
-			return verror.New(verror.ErrNoExist, ctx, l.Name())
+			return verror.New(verror.ErrNoExist, ctx, k)
 		}
 		return verror.New(verror.ErrInternal, ctx, err)
 	}
+	if err = vom.Decode(bytes, v); err != nil {
+		return verror.New(verror.ErrInternal, ctx, err)
+	}
 	return nil
 }
 
-// Get does GetWithoutAuth followed by an auth check.
-// Returns a VDL-compatible error.
-func Get(ctx *context.T, call rpc.ServerCall, st store.StoreReader, l Layer, v Permser) error {
-	if err := GetWithoutAuth(ctx, st, l, v); err != nil {
+// GetWithAuth does Get followed by an auth check.
+func GetWithAuth(ctx *context.T, call rpc.ServerCall, st store.StoreReader, k string, v Permser) error {
+	if err := Get(ctx, st, k, v); err != nil {
 		return err
 	}
 	auth, _ := access.PermissionsAuthorizer(v.GetPerms(), access.TypicalTagType())
 	if err := auth.Authorize(ctx, call.Security()); err != nil {
-		return verror.New(verror.ErrNoAccess, ctx, l.Name())
+		return verror.New(verror.ErrNoAccess, ctx, err)
 	}
 	return nil
 }
 
-// Put does st.Put(l.StKey(), v).
-// Returns a VDL-compatible error.
-// If you need to perform an authorization check, use Update().
-func Put(ctx *context.T, st store.StoreWriter, l Layer, v interface{}) error {
-	if err := PutObject(st, l.StKey(), v); err != nil {
+// Put does st.Put(k, v) and wraps the returned error.
+func Put(ctx *context.T, st store.StoreWriter, k string, v interface{}) error {
+	bytes, err := vom.Encode(v)
+	if err != nil {
+		return verror.New(verror.ErrInternal, ctx, err)
+	}
+	if err = st.Put([]byte(k), bytes); err != nil {
 		return verror.New(verror.ErrInternal, ctx, err)
 	}
 	return nil
 }
 
-// Delete does st.Delete(l.StKey()).
-// Returns a VDL-compatible error.
-// If you need to perform an authorization check, call Get() first.
-func Delete(ctx *context.T, st store.StoreWriter, l Layer) error {
-	if err := st.Delete([]byte(l.StKey())); err != nil {
+// Delete does st.Delete(k, v) and wraps the returned error.
+func Delete(ctx *context.T, st store.StoreWriter, k string) error {
+	if err := st.Delete([]byte(k)); err != nil {
 		return verror.New(verror.ErrInternal, ctx, err)
 	}
 	return nil
 }
 
-// Update performs a read-modify-write.
-// Input v is populated by the "read" step. fn should "modify" v, and should
-// return a VDL-compatible error.
+// UpdateWithAuth performs a read-modify-write.
+// Input v is populated by the "read" step. fn should "modify" v.
 // Performs an auth check as part of the "read" step.
-// Returns a VDL-compatible error.
-func Update(ctx *context.T, call rpc.ServerCall, st store.StoreReadWriter, l Layer, v Permser, fn func() error) error {
+func UpdateWithAuth(ctx *context.T, call rpc.ServerCall, st store.StoreReadWriter, k string, v Permser, fn func() error) error {
 	_ = st.(store.Transaction) // panics on failure, as desired
-	if err := Get(ctx, call, st, l, v); err != nil {
+	if err := GetWithAuth(ctx, call, st, k, v); err != nil {
 		return err
 	}
 	if err := fn(); err != nil {
 		return err
 	}
-	return Put(ctx, st, l, v)
-}
-
-////////////////////////////////////////////////////////////
-// RPC-oblivious, lower-level helpers
-
-func GetObject(st store.StoreReader, k string, v interface{}) error {
-	bytes, err := st.Get([]byte(k), nil)
-	if err != nil {
-		return err
-	}
-	return vom.Decode(bytes, v)
-}
-
-func PutObject(st store.StoreWriter, k string, v interface{}) error {
-	bytes, err := vom.Encode(v)
-	if err != nil {
-		return err
-	}
-	return st.Put([]byte(k), bytes)
+	return Put(ctx, st, k, v)
 }
 
 type OpenOptions struct {
diff --git a/x/ref/services/syncbase/server/watchable/transaction.go b/x/ref/services/syncbase/server/watchable/transaction.go
index d5206b1..9890b6a 100644
--- a/x/ref/services/syncbase/server/watchable/transaction.go
+++ b/x/ref/services/syncbase/server/watchable/transaction.go
@@ -81,7 +81,6 @@
 	if !tx.st.managesKey(key) {
 		return tx.itx.Put(key, value)
 	}
-
 	version, err := putVersioned(tx.itx, key, value)
 	if err != nil {
 		return err
@@ -99,12 +98,14 @@
 	}
 	var err error
 	if !tx.st.managesKey(key) {
-		err = tx.itx.Delete(key)
-	} else {
-		err = deleteVersioned(tx.itx, key)
-		tx.ops = append(tx.ops, &OpDelete{DeleteOp{Key: key}})
+		return tx.itx.Delete(key)
 	}
-	return err
+	err = deleteVersioned(tx.itx, key)
+	if err != nil {
+		return err
+	}
+	tx.ops = append(tx.ops, &OpDelete{DeleteOp{Key: key}})
+	return nil
 }
 
 // Commit implements the store.Transaction interface.
@@ -132,7 +133,7 @@
 			FromSync:        tx.fromSync,
 			Continued:       i < len(tx.ops)-1,
 		}
-		if err := util.PutObject(tx.itx, key, value); err != nil {
+		if err := util.Put(nil, tx.itx, key, value); err != nil {
 			return err
 		}
 		seq++
diff --git a/x/ref/services/syncbase/vsync/dag.go b/x/ref/services/syncbase/vsync/dag.go
index 72e8d91..c0d8efa 100644
--- a/x/ref/services/syncbase/vsync/dag.go
+++ b/x/ref/services/syncbase/vsync/dag.go
@@ -713,10 +713,7 @@
 		return verror.New(verror.ErrInternal, ctx, "invalid version", version)
 	}
 
-	if err := util.PutObject(tx, nodeKey(oid, version), node); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, nodeKey(oid, version), node)
 }
 
 // getNode retrieves the DAG node entry for the given (oid, version).
@@ -727,8 +724,8 @@
 
 	var node dagNode
 	key := nodeKey(oid, version)
-	if err := util.GetObject(st, key, &node); err != nil {
-		return nil, translateError(ctx, err, key)
+	if err := util.Get(ctx, st, key, &node); err != nil {
+		return nil, err
 	}
 	return &node, nil
 }
@@ -741,10 +738,7 @@
 		return verror.New(verror.ErrInternal, ctx, "invalid version", version)
 	}
 
-	if err := tx.Delete([]byte(nodeKey(oid, version))); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Delete(ctx, tx, nodeKey(oid, version))
 }
 
 // hasNode returns true if the node (oid, version) exists in the DAG.
@@ -769,18 +763,15 @@
 		return verror.New(verror.ErrInternal, ctx, fmt.Errorf("invalid version: %s", version))
 	}
 
-	if err := util.PutObject(tx, headKey(oid), version); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, headKey(oid), version)
 }
 
 // getHead retrieves the DAG object head.
 func getHead(ctx *context.T, st store.StoreReader, oid string) (string, error) {
 	var version string
 	key := headKey(oid)
-	if err := util.GetObject(st, key, &version); err != nil {
-		return NoVersion, translateError(ctx, err, key)
+	if err := util.Get(ctx, st, key, &version); err != nil {
+		return NoVersion, err
 	}
 	return version, nil
 }
@@ -788,11 +779,7 @@
 // delHead deletes the DAG object head.
 func delHead(ctx *context.T, tx store.StoreReadWriter, oid string) error {
 	_ = tx.(store.Transaction)
-
-	if err := tx.Delete([]byte(headKey(oid))); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Delete(ctx, tx, headKey(oid))
 }
 
 // batchKey returns the key used to access the DAG batch info.
@@ -808,10 +795,7 @@
 		return verror.New(verror.ErrInternal, ctx, "invalid batch id", btid)
 	}
 
-	if err := util.PutObject(tx, batchKey(btid), info); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, batchKey(btid), info)
 }
 
 // getBatch retrieves the DAG batch entry.
@@ -822,8 +806,8 @@
 
 	var info batchInfo
 	key := batchKey(btid)
-	if err := util.GetObject(st, key, &info); err != nil {
-		return nil, translateError(ctx, err, key)
+	if err := util.Get(ctx, st, key, &info); err != nil {
+		return nil, err
 	}
 	return &info, nil
 }
@@ -836,10 +820,7 @@
 		return verror.New(verror.ErrInternal, ctx, "invalid batch id", btid)
 	}
 
-	if err := tx.Delete([]byte(batchKey(btid))); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Delete(ctx, tx, batchKey(btid))
 }
 
 // getParentMap is a testing and debug helper function that returns for an
diff --git a/x/ref/services/syncbase/vsync/sync.go b/x/ref/services/syncbase/vsync/sync.go
index 6d787e1..d268843 100644
--- a/x/ref/services/syncbase/vsync/sync.go
+++ b/x/ref/services/syncbase/vsync/sync.go
@@ -19,7 +19,6 @@
 
 	"v.io/syncbase/x/ref/services/syncbase/server/interfaces"
 	"v.io/syncbase/x/ref/services/syncbase/server/util"
-	"v.io/syncbase/x/ref/services/syncbase/store"
 
 	"v.io/v23/context"
 	"v.io/v23/rpc"
@@ -73,7 +72,6 @@
 	rng     = rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
 	rngLock sync.Mutex
 	_       interfaces.SyncServerMethods = (*syncService)(nil)
-	_       util.Layer                   = (*syncService)(nil)
 )
 
 // rand64 generates an unsigned 64-bit pseudo-random number.
@@ -105,15 +103,15 @@
 	}
 
 	data := &syncData{}
-	if err := util.GetObject(sv.St(), s.StKey(), data); err != nil {
-		if verror.ErrorID(err) != store.ErrUnknownKey.ID {
-			return nil, verror.New(verror.ErrInternal, ctx, err)
+	if err := util.Get(ctx, sv.St(), s.stKey(), data); err != nil {
+		if verror.ErrorID(err) != verror.ErrNoExist.ID {
+			return nil, err
 		}
 		// First invocation of vsync.New().
 		// TODO(sadovsky): Maybe move guid generation and storage to serviceData.
 		data.Id = rand64()
-		if err := util.PutObject(sv.St(), s.StKey(), data); err != nil {
-			return nil, verror.New(verror.ErrInternal, ctx, err)
+		if err := util.Put(ctx, sv.St(), s.stKey(), data); err != nil {
+			return nil, err
 		}
 	}
 
@@ -150,13 +148,6 @@
 	return &syncDatabase{db: db}
 }
 
-////////////////////////////////////////
-// util.Layer methods.
-
-func (s *syncService) Name() string {
-	return "sync"
-}
-
-func (s *syncService) StKey() string {
+func (s *syncService) stKey() string {
 	return util.SyncPrefix
 }
diff --git a/x/ref/services/syncbase/vsync/sync_state.go b/x/ref/services/syncbase/vsync/sync_state.go
index 49d9ff5..f57ccbd 100644
--- a/x/ref/services/syncbase/vsync/sync_state.go
+++ b/x/ref/services/syncbase/vsync/sync_state.go
@@ -261,17 +261,14 @@
 // putDbSyncState persists the sync state object for a given Database.
 func putDbSyncState(ctx *context.T, tx store.StoreReadWriter, ds *dbSyncState) error {
 	_ = tx.(store.Transaction)
-	if err := util.PutObject(tx, dbSyncStateKey(), ds); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, dbSyncStateKey(), ds)
 }
 
 // getDbSyncState retrieves the sync state object for a given Database.
 func getDbSyncState(ctx *context.T, st store.StoreReader) (*dbSyncState, error) {
 	var ds dbSyncState
-	if err := util.GetObject(st, dbSyncStateKey(), &ds); err != nil {
-		return nil, translateError(ctx, err, dbSyncStateKey())
+	if err := util.Get(ctx, st, dbSyncStateKey(), &ds); err != nil {
+		return nil, err
 	}
 	return &ds, nil
 }
@@ -311,7 +308,9 @@
 func hasLogRec(st store.StoreReader, id, gen uint64) bool {
 	// TODO(hpucha): optimize to avoid the unneeded fetch/decode of the data.
 	var rec localLogRec
-	if err := util.GetObject(st, logRecKey(id, gen), &rec); err != nil {
+	// NOTE(sadovsky): This implementation doesn't explicitly handle
+	// non-ErrNoExist errors. Is that intentional?
+	if err := util.Get(nil, st, logRecKey(id, gen), &rec); err != nil {
 		return false
 	}
 	return true
@@ -320,17 +319,14 @@
 // putLogRec stores the log record.
 func putLogRec(ctx *context.T, tx store.StoreReadWriter, rec *localLogRec) error {
 	_ = tx.(store.Transaction)
-	if err := util.PutObject(tx, logRecKey(rec.Metadata.Id, rec.Metadata.Gen), rec); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, logRecKey(rec.Metadata.Id, rec.Metadata.Gen), rec)
 }
 
 // getLogRec retrieves the log record for a given (devid, gen).
 func getLogRec(ctx *context.T, st store.StoreReader, id, gen uint64) (*localLogRec, error) {
 	var rec localLogRec
-	if err := util.GetObject(st, logRecKey(id, gen), &rec); err != nil {
-		return nil, translateError(ctx, err, logRecKey(id, gen))
+	if err := util.Get(ctx, st, logRecKey(id, gen), &rec); err != nil {
+		return nil, err
 	}
 	return &rec, nil
 }
@@ -338,9 +334,5 @@
 // delLogRec deletes the log record for a given (devid, gen).
 func delLogRec(ctx *context.T, tx store.StoreReadWriter, id, gen uint64) error {
 	_ = tx.(store.Transaction)
-
-	if err := tx.Delete([]byte(logRecKey(id, gen))); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Delete(ctx, tx, logRecKey(id, gen))
 }
diff --git a/x/ref/services/syncbase/vsync/syncgroup.go b/x/ref/services/syncbase/vsync/syncgroup.go
index 31eaff0..9613489 100644
--- a/x/ref/services/syncbase/vsync/syncgroup.go
+++ b/x/ref/services/syncbase/vsync/syncgroup.go
@@ -301,7 +301,9 @@
 func hasSGDataEntry(st store.StoreReader, gid interfaces.GroupId) bool {
 	// TODO(rdaoud): optimize to avoid the unneeded fetch/decode of the data.
 	var sg interfaces.SyncGroup
-	if err := util.GetObject(st, sgDataKey(gid), &sg); err != nil {
+	// NOTE(sadovsky): This implementation doesn't explicitly handle
+	// non-ErrNoExist errors. Is that intentional?
+	if err := util.Get(nil, st, sgDataKey(gid), &sg); err != nil {
 		return false
 	}
 	return true
@@ -311,7 +313,9 @@
 func hasSGNameEntry(st store.StoreReader, name string) bool {
 	// TODO(rdaoud): optimize to avoid the unneeded fetch/decode of the data.
 	var gid interfaces.GroupId
-	if err := util.GetObject(st, sgNameKey(name), &gid); err != nil {
+	// NOTE(sadovsky): This implementation doesn't explicitly handle
+	// non-ErrNoExist errors. Is that intentional?
+	if err := util.Get(nil, st, sgNameKey(name), &gid); err != nil {
 		return false
 	}
 	return true
@@ -320,28 +324,20 @@
 // setSGDataEntry stores the SyncGroup data entry.
 func setSGDataEntry(ctx *context.T, tx store.StoreReadWriter, gid interfaces.GroupId, sg *interfaces.SyncGroup) error {
 	_ = tx.(store.Transaction)
-
-	if err := util.PutObject(tx, sgDataKey(gid), sg); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, sgDataKey(gid), sg)
 }
 
 // setSGNameEntry stores the SyncGroup name entry.
 func setSGNameEntry(ctx *context.T, tx store.StoreReadWriter, name string, gid interfaces.GroupId) error {
 	_ = tx.(store.Transaction)
-
-	if err := util.PutObject(tx, sgNameKey(name), gid); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, sgNameKey(name), gid)
 }
 
 // getSGDataEntry retrieves the SyncGroup data for a given group ID.
 func getSGDataEntry(ctx *context.T, st store.StoreReader, gid interfaces.GroupId) (*interfaces.SyncGroup, error) {
 	var sg interfaces.SyncGroup
-	if err := util.GetObject(st, sgDataKey(gid), &sg); err != nil {
-		return nil, verror.New(verror.ErrInternal, ctx, err)
+	if err := util.Get(ctx, st, sgDataKey(gid), &sg); err != nil {
+		return nil, err
 	}
 	return &sg, nil
 }
@@ -349,8 +345,8 @@
 // getSGNameEntry retrieves the SyncGroup name to ID mapping.
 func getSGNameEntry(ctx *context.T, st store.StoreReader, name string) (interfaces.GroupId, error) {
 	var gid interfaces.GroupId
-	if err := util.GetObject(st, sgNameKey(name), &gid); err != nil {
-		return gid, verror.New(verror.ErrNoExist, ctx, err)
+	if err := util.Get(ctx, st, sgNameKey(name), &gid); err != nil {
+		return gid, err
 	}
 	return gid, nil
 }
@@ -358,21 +354,13 @@
 // delSGDataEntry deletes the SyncGroup data entry.
 func delSGDataEntry(ctx *context.T, tx store.StoreReadWriter, gid interfaces.GroupId) error {
 	_ = tx.(store.Transaction)
-
-	if err := tx.Delete([]byte(sgDataKey(gid))); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Delete(ctx, tx, sgDataKey(gid))
 }
 
 // delSGNameEntry deletes the SyncGroup name to ID mapping.
 func delSGNameEntry(ctx *context.T, tx store.StoreReadWriter, name string) error {
 	_ = tx.(store.Transaction)
-
-	if err := tx.Delete([]byte(sgNameKey(name))); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Delete(ctx, tx, sgNameKey(name))
 }
 
 ////////////////////////////////////////////////////////////
@@ -381,7 +369,6 @@
 // TODO(hpucha): Pass blessings along.
 func (sd *syncDatabase) CreateSyncGroup(ctx *context.T, call rpc.ServerCall, sgName string, spec wire.SyncGroupSpec, myInfo wire.SyncGroupMemberInfo) error {
 	err := store.RunInTransaction(sd.db.St(), func(tx store.StoreReadWriter) error {
-
 		// Check permissions on Database.
 		if err := sd.db.CheckPermsInternal(ctx, call, tx); err != nil {
 			return err
diff --git a/x/ref/services/syncbase/vsync/util.go b/x/ref/services/syncbase/vsync/util.go
index 65d47eb..3622672 100644
--- a/x/ref/services/syncbase/vsync/util.go
+++ b/x/ref/services/syncbase/vsync/util.go
@@ -12,7 +12,6 @@
 	"v.io/syncbase/x/ref/services/syncbase/store"
 	"v.io/v23/context"
 	"v.io/v23/rpc"
-	"v.io/v23/verror"
 	"v.io/x/lib/vlog"
 )
 
@@ -75,14 +74,6 @@
 	return db.St(), nil
 }
 
-// translateError translates store errors.
-func translateError(ctx *context.T, err error, key string) error {
-	if verror.ErrorID(err) == store.ErrUnknownKey.ID {
-		return verror.New(verror.ErrNoExist, ctx, key)
-	}
-	return verror.New(verror.ErrInternal, ctx, key, err)
-}
-
 // unixNanoToTime converts a Unix timestamp in nanoseconds to a Time object.
 func unixNanoToTime(timestamp int64) time.Time {
 	if timestamp < 0 {
diff --git a/x/ref/services/syncbase/vsync/watcher.go b/x/ref/services/syncbase/vsync/watcher.go
index 804907c..50aad26 100644
--- a/x/ref/services/syncbase/vsync/watcher.go
+++ b/x/ref/services/syncbase/vsync/watcher.go
@@ -434,19 +434,15 @@
 // setResMark stores the watcher resume marker for a database.
 func setResMark(ctx *context.T, tx store.StoreReadWriter, resMark string) error {
 	_ = tx.(store.Transaction)
-
-	if err := util.PutObject(tx, resMarkKey(), resMark); err != nil {
-		return verror.New(verror.ErrInternal, ctx, err)
-	}
-	return nil
+	return util.Put(ctx, tx, resMarkKey(), resMark)
 }
 
 // getResMark retrieves the watcher resume marker for a database.
 func getResMark(ctx *context.T, st store.StoreReader) (string, error) {
 	var resMark string
 	key := resMarkKey()
-	if err := util.GetObject(st, key, &resMark); err != nil {
-		return NoVersion, translateError(ctx, err, key)
+	if err := util.Get(ctx, st, key, &resMark); err != nil {
+		return NoVersion, err
 	}
 	return resMark, nil
 }