From b81a63451a3a3b749d9fd96d44fdcebdb35d8a5a Mon Sep 17 00:00:00 2001
From: Jake Taylor <jtaylorapps@gmail.com>
Date: Tue, 6 Jun 2023 12:35:32 -0500
Subject: [PATCH] move cipher tracker up into wasm

---
 go.mod                |   2 +-
 go.sum                |   4 +-
 main.go               |   2 +-
 wasm/channels.go      | 151 ++-------------------------
 wasm/channels_test.go |   4 +-
 wasm/cipher.go        | 232 ++++++++++++++++++++++++++++++++++++++++++
 wasm/dm.go            | 175 +------------------------------
 wasm/dm_test.go       |   8 +-
 8 files changed, 251 insertions(+), 327 deletions(-)
 create mode 100644 wasm/cipher.go

diff --git a/go.mod b/go.mod
index 64e7faf1..20f6d453 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/stretchr/testify v1.8.2
-	gitlab.com/elixxir/client/v4 v4.6.4-0.20230531170755-2174efc87f84
+	gitlab.com/elixxir/client/v4 v4.6.4-0.20230606172346-f59d48cefbc5
 	gitlab.com/elixxir/crypto v0.0.7-0.20230531164732-6951a4e33a55
 	gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c
 	gitlab.com/elixxir/wasm-utils v0.0.0-20230522231408-a43b2c1481b2
diff --git a/go.sum b/go.sum
index 979c9e7e..a8792a64 100644
--- a/go.sum
+++ b/go.sum
@@ -407,8 +407,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
 github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8 h1:uAFCyBkXprQoPkcDDfxXtaMyL5x+xSGrAWzR907xROQ=
 gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8/go.mod h1:1X8gRIAPDisS3W6Vtr/ymiUmZMJUIwDV1o5DEOo/pzw=
-gitlab.com/elixxir/client/v4 v4.6.4-0.20230531170755-2174efc87f84 h1:dwJ65HKgc7yAjoW8tpuzwaEDZIeG3eKuUWdAT+1TTmA=
-gitlab.com/elixxir/client/v4 v4.6.4-0.20230531170755-2174efc87f84/go.mod h1:c1QPbv7Qr7r7Es5h0NoziawiIgVS24VYhbY7WQm1w8Q=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230606172346-f59d48cefbc5 h1:+l53p9Dy735OIJPI/v9XloWJk5Ql+/DqzHQrtvVTjxA=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230606172346-f59d48cefbc5/go.mod h1:c1QPbv7Qr7r7Es5h0NoziawiIgVS24VYhbY7WQm1w8Q=
 gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938 h1:f27+QUFiGWrprKm+fstOg3ABkYLpWcZi3+8Lf5eDnqY=
 gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938/go.mod h1:z+qW0D9VpY5QKTd7wRlb5SK4kBNqLYsa4DXBcUXue9Q=
 gitlab.com/elixxir/crypto v0.0.7-0.20230531164732-6951a4e33a55 h1:J0h3APo7OcIWPnmtIJCyeMOkE9wT6vI8Bw+oZq53S8E=
diff --git a/main.go b/main.go
index 60aa541c..0699d664 100644
--- a/main.go
+++ b/main.go
@@ -152,7 +152,7 @@ func setGlobals() {
 	js.Global().Set("NewDMClientWithIndexedDbUnsafe",
 		js.FuncOf(wasm.NewDMClientWithIndexedDbUnsafe))
 	js.Global().Set("NewDMsDatabaseCipher",
-		js.FuncOf(wasm.NewDMsDatabaseCipher))
+		js.FuncOf(wasm.NewDatabaseCipher))
 
 	// wasm/cmix.go
 	js.Global().Set("NewCmix", js.FuncOf(wasm.NewCmix))
diff --git a/wasm/channels.go b/wasm/channels.go
index b1e27a21..843b3a55 100644
--- a/wasm/channels.go
+++ b/wasm/channels.go
@@ -386,7 +386,7 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 	cUI := newChannelUI(args[5])
 	cipherID := args[6].Int()
 
-	cipher, err := bindings.GetDbCipherTrackerFromID(cipherID)
+	cipher, err := dbCipherTrackerSingleton.get(cipherID)
 	if err != nil {
 		exception.ThrowTrace(err)
 	}
@@ -444,10 +444,10 @@ func NewChannelsManagerWithIndexedDbUnsafe(_ js.Value, args []js.Value) any {
 func newChannelsManagerWithIndexedDb(cmixID int, wasmJsPath string,
 	privateIdentity, extensionBuilderIDsJSON []byte, notificationsID int,
 	channelsCbs bindings.ChannelUICallbacks,
-	cipher *bindings.DbCipher) any {
+	cipher *DbCipher) any {
 
 	model := channelsDb.NewWASMEventModelBuilder(
-		wasmJsPath, cipher, channelsCbs)
+		wasmJsPath, cipher.api, channelsCbs)
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
 		cm, err := bindings.NewChannelsManagerGoEventModel(cmixID,
@@ -504,7 +504,7 @@ func LoadChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 	channelsCbs := newChannelUI(args[5])
 	cipherID := args[6].Int()
 
-	cipher, err := bindings.GetDbCipherTrackerFromID(cipherID)
+	cipher, err := dbCipherTrackerSingleton.get(cipherID)
 	if err != nil {
 		exception.ThrowTrace(err)
 	}
@@ -557,10 +557,10 @@ func LoadChannelsManagerWithIndexedDbUnsafe(_ js.Value, args []js.Value) any {
 
 func loadChannelsManagerWithIndexedDb(cmixID int, wasmJsPath, storageTag string,
 	extensionBuilderIDsJSON []byte, notificationsID int, channelsCbs bindings.ChannelUICallbacks,
-	cipher *bindings.DbCipher) any {
+	cipher *DbCipher) any {
 
 	model := channelsDb.NewWASMEventModelBuilder(
-		wasmJsPath, cipher, channelsCbs)
+		wasmJsPath, cipher.api, channelsCbs)
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
 		cm, err := bindings.LoadChannelsManagerGoEventModel(
@@ -2315,145 +2315,6 @@ type MessageAndError struct {
 	Error string
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Channel Cipher                                                             //
-////////////////////////////////////////////////////////////////////////////////
-
-// DbCipher wraps the [bindings.DbCipher] object so its methods
-// can be wrapped to be Javascript compatible.
-type DbCipher struct {
-	api *bindings.DbCipher
-}
-
-// newDbCipherJS creates a new Javascript compatible object
-// (map[string]any) that matches the [DbCipher] structure.
-func newDbCipherJS(api *bindings.DbCipher) map[string]any {
-	c := DbCipher{api}
-	DbCipherMap := map[string]any{
-		"GetID":         js.FuncOf(c.GetID),
-		"Encrypt":       js.FuncOf(c.Encrypt),
-		"Decrypt":       js.FuncOf(c.Decrypt),
-		"MarshalJSON":   js.FuncOf(c.MarshalJSON),
-		"UnmarshalJSON": js.FuncOf(c.UnmarshalJSON),
-	}
-
-	return DbCipherMap
-}
-
-// NewDatabaseCipher constructs a [DbCipher] object.
-//
-// Parameters:
-//   - args[0] - The tracked [Cmix] object ID (int).
-//   - args[1] - The password for storage. This should be the same password
-//     passed into [NewCmix] (Uint8Array).
-//   - args[2] - The maximum size of a payload to be encrypted. A payload passed
-//     into [DbCipher.Encrypt] that is larger than this value will result
-//     in an error (int).
-//
-// Returns:
-//   - JavaScript representation of the [DbCipher] object.
-//   - Throws an error if creating the cipher fails.
-func NewDatabaseCipher(_ js.Value, args []js.Value) any {
-	cmixId := args[0].Int()
-	password := utils.CopyBytesToGo(args[1])
-	plaintTextBlockSize := args[2].Int()
-
-	cipher, err := bindings.NewDatabaseCipher(
-		cmixId, password, plaintTextBlockSize)
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return newDbCipherJS(cipher)
-}
-
-// GetID returns the ID for this [bindings.DbCipher] in the
-// DbCipherTracker.
-//
-// Returns:
-//   - Tracker ID (int).
-func (c *DbCipher) GetID(js.Value, []js.Value) any {
-	return c.api.GetID()
-}
-
-// Encrypt will encrypt the raw data. It will return a ciphertext. Padding is
-// done on the plaintext so all encrypted data looks uniform at rest.
-//
-// Parameters:
-//   - args[0] - The data to be encrypted (Uint8Array). This must be smaller
-//     than the block size passed into [NewDatabaseCipher]. If it is
-//     larger, this will return an error.
-//
-// Returns:
-//   - The ciphertext of the plaintext passed in (Uint8Array).
-//   - Throws an error if it fails to encrypt the plaintext.
-func (c *DbCipher) Encrypt(_ js.Value, args []js.Value) any {
-	ciphertext, err := c.api.Encrypt(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(ciphertext)
-}
-
-// Decrypt will decrypt the passed in encrypted value. The plaintext will be
-// returned by this function. Any padding will be discarded within this
-// function.
-//
-// Parameters:
-//   - args[0] - the encrypted data returned by [DbCipher.Encrypt]
-//     (Uint8Array).
-//
-// Returns:
-//   - The plaintext of the ciphertext passed in (Uint8Array).
-//   - Throws an error if it fails to encrypt the plaintext.
-func (c *DbCipher) Decrypt(_ js.Value, args []js.Value) any {
-	plaintext, err := c.api.Decrypt(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(plaintext)
-}
-
-// MarshalJSON marshals the cipher into valid JSON.
-//
-// Returns:
-//   - JSON of the cipher (Uint8Array).
-//   - Throws an error if marshalling fails.
-func (c *DbCipher) MarshalJSON(js.Value, []js.Value) any {
-	data, err := c.api.MarshalJSON()
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(data)
-}
-
-// UnmarshalJSON unmarshalls JSON into the cipher.
-//
-// Note that this function does not transfer the internal RNG. Use
-// [channel.NewCipherFromJSON] to properly reconstruct a cipher from JSON.
-//
-// Parameters:
-//   - args[0] - JSON data to unmarshal (Uint8Array).
-//
-// Returns:
-//   - JSON of the cipher (Uint8Array).
-//   - Throws an error if marshalling fails.
-func (c *DbCipher) UnmarshalJSON(_ js.Value, args []js.Value) any {
-	err := c.api.UnmarshalJSON(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-	return nil
-}
-
 // newChannelUI maps the methods on the Javascript object to the
 // channelUI callbacks implementation struct.
 func newChannelUI(cbImpl js.Value) *channelUI {
diff --git a/wasm/channels_test.go b/wasm/channels_test.go
index f56f33fb..1aa9b7fa 100644
--- a/wasm/channels_test.go
+++ b/wasm/channels_test.go
@@ -65,7 +65,7 @@ func Test_ChannelsManagerMethods(t *testing.T) {
 func Test_newChannelDbCipherJS(t *testing.T) {
 	cipherType := reflect.TypeOf(&DbCipher{})
 
-	cipher := newDbCipherJS(&bindings.DbCipher{})
+	cipher := newDbCipherJS(&DbCipher{})
 	if len(cipher) != cipherType.NumMethod() {
 		t.Errorf("ChannelDbCipher JS object does not have all methods."+
 			"\nexpected: %d\nreceived: %d", cipherType.NumMethod(), len(cipher))
@@ -84,7 +84,7 @@ func Test_newChannelDbCipherJS(t *testing.T) {
 // [bindings.ChannelDbCipher] has.
 func Test_ChannelDbCipherMethods(t *testing.T) {
 	cipherType := reflect.TypeOf(&DbCipher{})
-	binCipherType := reflect.TypeOf(&bindings.DbCipher{})
+	binCipherType := reflect.TypeOf(&DbCipher{})
 
 	if binCipherType.NumMethod() != cipherType.NumMethod() {
 		t.Errorf("WASM ChannelDbCipher object does not have all methods from "+
diff --git a/wasm/cipher.go b/wasm/cipher.go
new file mode 100644
index 00000000..ab522398
--- /dev/null
+++ b/wasm/cipher.go
@@ -0,0 +1,232 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 xx foundation                                             //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file.                                                              //
+////////////////////////////////////////////////////////////////////////////////
+
+//go:build js && wasm
+
+package wasm
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/v4/bindings"
+	"gitlab.com/elixxir/client/v4/storage/utility"
+	"gitlab.com/elixxir/crypto/indexedDb"
+	"gitlab.com/elixxir/wasm-utils/exception"
+	"gitlab.com/elixxir/wasm-utils/utils"
+	"sync"
+	"syscall/js"
+)
+
+// dbCipherTrackerSingleton is used to track DbCipher objects
+// so that they can be referenced by ID back over the bindings.
+var dbCipherTrackerSingleton = &DbCipherTracker{
+	tracked: make(map[int]*DbCipher),
+	count:   0,
+}
+
+// DbCipherTracker is a singleton used to keep track of extant
+// DbCipher objects, preventing race conditions created by passing it
+// over the bindings.
+type DbCipherTracker struct {
+	tracked map[int]*DbCipher
+	count   int
+	mux     sync.RWMutex
+}
+
+// create creates a DbCipher from a [indexedDb.Cipher], assigns it a unique
+// ID, and adds it to the DbCipherTracker.
+func (ct *DbCipherTracker) create(c indexedDb.Cipher) *DbCipher {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	chID := ct.count
+	ct.count++
+
+	ct.tracked[chID] = &DbCipher{
+		api: c,
+		id:  chID,
+	}
+
+	return ct.tracked[chID]
+}
+
+// get an DbCipher from the DbCipherTracker given its ID.
+func (ct *DbCipherTracker) get(id int) (*DbCipher, error) {
+	ct.mux.RLock()
+	defer ct.mux.RUnlock()
+
+	c, exist := ct.tracked[id]
+	if !exist {
+		return nil, errors.Errorf(
+			"Cannot get DbCipher for ID %d, does not exist", id)
+	}
+
+	return c, nil
+}
+
+// delete removes a DMDbCipher from the DMDbCipherTracker.
+func (ct *DbCipherTracker) delete(id int) {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	delete(ct.tracked, id)
+}
+
+// DbCipher wraps the [indexedDb.Cipher] object so its methods
+// can be wrapped to be Javascript compatible.
+type DbCipher struct {
+	api  indexedDb.Cipher
+	salt []byte
+	id   int
+}
+
+// newDbCipherJS creates a new Javascript compatible object
+// (map[string]any) that matches the [DbCipher] structure.
+func newDbCipherJS(c *DbCipher) map[string]any {
+	DbCipherMap := map[string]any{
+		"GetID":         js.FuncOf(c.GetID),
+		"Encrypt":       js.FuncOf(c.Encrypt),
+		"Decrypt":       js.FuncOf(c.Decrypt),
+		"MarshalJSON":   js.FuncOf(c.MarshalJSON),
+		"UnmarshalJSON": js.FuncOf(c.UnmarshalJSON),
+	}
+
+	return DbCipherMap
+}
+
+// NewDatabaseCipher constructs a [DbCipher] object.
+//
+// Parameters:
+//   - args[0] - The tracked [Cmix] object ID (int).
+//   - args[1] - The password for storage. This should be the same password
+//     passed into [NewCmix] (Uint8Array).
+//   - args[2] - The maximum size of a payload to be encrypted. A payload passed
+//     into [DbCipher.Encrypt] that is larger than this value will result
+//     in an error (int).
+//
+// Returns:
+//   - JavaScript representation of the [DbCipher] object.
+//   - Throws an error if creating the cipher fails.
+func NewDatabaseCipher(_ js.Value, args []js.Value) any {
+	cmixId := args[0].Int()
+	password := utils.CopyBytesToGo(args[1])
+	plaintTextBlockSize := args[2].Int()
+
+	// Get user from singleton
+	user, err := bindings.GetCMixInstance(cmixId)
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	// Generate RNG
+	stream := user.GetRng().GetStream()
+
+	// Load or generate a salt
+	salt, err := utility.NewOrLoadSalt(
+		user.GetStorage().GetKV(), stream)
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	// Construct a cipher
+	c, err := indexedDb.NewCipher(
+		password, salt, plaintTextBlockSize, stream)
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	// Add to singleton and return
+	return newDbCipherJS(dbCipherTrackerSingleton.create(c))
+}
+
+// GetID returns the ID for this [DbCipher] in the
+// DbCipherTracker.
+//
+// Returns:
+//   - Tracker ID (int).
+func (c *DbCipher) GetID(js.Value, []js.Value) any {
+	return c.id
+}
+
+// Encrypt will encrypt the raw data. It will return a ciphertext. Padding is
+// done on the plaintext so all encrypted data looks uniform at rest.
+//
+// Parameters:
+//   - args[0] - The data to be encrypted (Uint8Array). This must be smaller
+//     than the block size passed into [NewDatabaseCipher]. If it is
+//     larger, this will return an error.
+//
+// Returns:
+//   - The ciphertext of the plaintext passed in (String).
+//   - Throws an error if it fails to encrypt the plaintext.
+func (c *DbCipher) Encrypt(_ js.Value, args []js.Value) any {
+	ciphertext, err := c.api.Encrypt(utils.CopyBytesToGo(args[0]))
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	return ciphertext
+}
+
+// Decrypt will decrypt the passed in encrypted value. The plaintext will be
+// returned by this function. Any padding will be discarded within this
+// function.
+//
+// Parameters:
+//   - args[0] - the encrypted data returned by [DbCipher.Encrypt]
+//     (String).
+//
+// Returns:
+//   - The plaintext of the ciphertext passed in (Uint8Array).
+//   - Throws an error if it fails to encrypt the plaintext.
+func (c *DbCipher) Decrypt(_ js.Value, args []js.Value) any {
+	plaintext, err := c.api.Decrypt(args[0].String())
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	return utils.CopyBytesToJS(plaintext)
+}
+
+// MarshalJSON marshals the cipher into valid JSON.
+//
+// Returns:
+//   - JSON of the cipher (Uint8Array).
+//   - Throws an error if marshalling fails.
+func (c *DbCipher) MarshalJSON(js.Value, []js.Value) any {
+	data, err := c.api.MarshalJSON()
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	return utils.CopyBytesToJS(data)
+}
+
+// UnmarshalJSON unmarshalls JSON into the cipher.
+//
+// Note that this function does not transfer the internal RNG. Use
+// [indexedDb.NewCipherFromJSON] to properly reconstruct a cipher from JSON.
+//
+// Parameters:
+//   - args[0] - JSON data to unmarshal (Uint8Array).
+//
+// Returns:
+//   - JSON of the cipher (Uint8Array).
+//   - Throws an error if marshalling fails.
+func (c *DbCipher) UnmarshalJSON(_ js.Value, args []js.Value) any {
+	err := c.api.UnmarshalJSON(utils.CopyBytesToGo(args[0]))
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+	return nil
+}
diff --git a/wasm/dm.go b/wasm/dm.go
index e8345025..ce64a454 100644
--- a/wasm/dm.go
+++ b/wasm/dm.go
@@ -142,7 +142,7 @@ func NewDMClientWithIndexedDb(_ js.Value, args []js.Value) any {
 	messageReceivedCB := args[3]
 	cipherID := args[4].Int()
 
-	cipher, err := bindings.GetDbCipherTrackerFromID(cipherID)
+	cipher, err := dbCipherTrackerSingleton.get(cipherID)
 	if err != nil {
 		exception.ThrowTrace(err)
 	}
@@ -190,7 +190,7 @@ func NewDMClientWithIndexedDbUnsafe(_ js.Value, args []js.Value) any {
 }
 
 func newDMClientWithIndexedDb(cmixID int, wasmJsPath string,
-	privateIdentity []byte, cb js.Value, cipher *bindings.DbCipher) any {
+	privateIdentity []byte, cb js.Value, cipher *DbCipher) any {
 
 	messageReceivedCB := func(uuid uint64, pubKey ed25519.PublicKey,
 		messageUpdate, conversationUpdate bool) {
@@ -206,7 +206,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string,
 		}
 		dmPath := base64.RawStdEncoding.EncodeToString(pi.PubKey[:])
 		model, err := indexDB.NewWASMEventModel(
-			dmPath, wasmJsPath, cipher, messageReceivedCB)
+			dmPath, wasmJsPath, cipher.api, messageReceivedCB)
 		if err != nil {
 			reject(exception.NewTrace(err))
 		}
@@ -671,35 +671,6 @@ func DecodeDMShareURL(_ js.Value, args []js.Value) any {
 	return utils.CopyBytesToJS(report)
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Channel Receiving Logic and Callback Registration                          //
-////////////////////////////////////////////////////////////////////////////////
-
-// channelMessageReceptionCallback wraps Javascript callbacks to adhere to the
-// [bindings.ChannelMessageReceptionCallback] interface.
-type dmReceptionCallback struct {
-	callback func(args ...any) js.Value
-}
-
-// Callback returns the context for a channel message.
-//
-// Parameters:
-//   - receivedChannelMessageReport - Returns the JSON of
-//     [bindings.ReceivedChannelMessageReport] (Uint8Array).
-//   - err - Returns an error on failure (Error).
-//
-// Returns:
-//   - It must return a unique UUID for the message that it can be referenced by
-//     later (int).
-func (cmrCB *dmReceptionCallback) Callback(
-	receivedChannelMessageReport []byte, err error) int {
-	uuid := cmrCB.callback(
-		utils.CopyBytesToJS(receivedChannelMessageReport),
-		exception.NewTrace(err))
-
-	return uuid.Int()
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Event Model Logic                                                          //
 ////////////////////////////////////////////////////////////////////////////////
@@ -990,146 +961,6 @@ func (em *dmReceiver) GetConversations() []byte {
 	return conversationsBytes
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// DM DB Cipher                                                               //
-////////////////////////////////////////////////////////////////////////////////
-
-// DMDbCipher wraps the [bindings.DMDbCipher] object so its methods
-// can be wrapped to be Javascript compatible.
-type DMDbCipher struct {
-	api *bindings.DbCipher
-}
-
-// newDMDbCipherJS creates a new Javascript compatible object
-// (map[string]any) that matches the [DMDbCipher] structure.
-func newDMDbCipherJS(api *bindings.DbCipher) map[string]any {
-	c := DMDbCipher{api}
-	channelDbCipherMap := map[string]any{
-		"GetID":         js.FuncOf(c.GetID),
-		"Encrypt":       js.FuncOf(c.Encrypt),
-		"Decrypt":       js.FuncOf(c.Decrypt),
-		"MarshalJSON":   js.FuncOf(c.MarshalJSON),
-		"UnmarshalJSON": js.FuncOf(c.UnmarshalJSON),
-	}
-
-	return channelDbCipherMap
-}
-
-// NewDMsDatabaseCipher constructs a [DMDbCipher] object.
-//
-// Parameters:
-//   - args[0] - The tracked [Cmix] object ID (int).
-//   - args[1] - The password for storage. This should be the same password
-//     passed into [NewCmix] (Uint8Array).
-//   - args[2] - The maximum size of a payload to be encrypted. A payload passed
-//     into [DMDbCipher.Encrypt] that is larger than this value will result
-//     in an error (int).
-//
-// Returns:
-//   - JavaScript representation of the [DMDbCipher] object.
-//   - Throws an error if creating the cipher fails.
-func NewDMsDatabaseCipher(_ js.Value, args []js.Value) any {
-	cmixId := args[0].Int()
-	password := utils.CopyBytesToGo(args[1])
-	plaintTextBlockSize := args[2].Int()
-
-	cipher, err := bindings.NewDatabaseCipher(
-		cmixId, password, plaintTextBlockSize)
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return newDMDbCipherJS(cipher)
-}
-
-// GetID returns the ID for this [bindings.DMDbCipher] in the
-// channelDbCipherTracker.
-//
-// Returns:
-//   - Tracker ID (int).
-func (c *DMDbCipher) GetID(js.Value, []js.Value) any {
-	return c.api.GetID()
-}
-
-// Encrypt will encrypt the raw data. It will return a ciphertext. Padding is
-// done on the plaintext so all encrypted data looks uniform at rest.
-//
-// Parameters:
-//   - args[0] - The data to be encrypted (Uint8Array). This must be smaller
-//     than the block size passed into [NewDMsDatabaseCipher]. If it is
-//     larger, this will return an error.
-//
-// Returns:
-//   - The ciphertext of the plaintext passed in (Uint8Array).
-//   - Throws an error if it fails to encrypt the plaintext.
-func (c *DMDbCipher) Encrypt(_ js.Value, args []js.Value) any {
-	ciphertext, err := c.api.Encrypt(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(ciphertext)
-}
-
-// Decrypt will decrypt the passed in encrypted value. The plaintext will be
-// returned by this function. Any padding will be discarded within this
-// function.
-//
-// Parameters:
-//   - args[0] - the encrypted data returned by [DMDbCipher.Encrypt]
-//     (Uint8Array).
-//
-// Returns:
-//   - The plaintext of the ciphertext passed in (Uint8Array).
-//   - Throws an error if it fails to encrypt the plaintext.
-func (c *DMDbCipher) Decrypt(_ js.Value, args []js.Value) any {
-	plaintext, err := c.api.Decrypt(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(plaintext)
-}
-
-// MarshalJSON marshals the cipher into valid JSON.
-//
-// Returns:
-//   - JSON of the cipher (Uint8Array).
-//   - Throws an error if marshalling fails.
-func (c *DMDbCipher) MarshalJSON(js.Value, []js.Value) any {
-	data, err := c.api.MarshalJSON()
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(data)
-}
-
-// UnmarshalJSON unmarshalls JSON into the cipher. This function adheres to the
-// json.Unmarshaler interface.
-//
-// Note that this function does not transfer the internal RNG. Use
-// [channel.NewCipherFromJSON] to properly reconstruct a cipher from JSON.
-//
-// Parameters:
-//   - args[0] - JSON data to unmarshal (Uint8Array).
-//
-// Returns:
-//   - JSON of the cipher (Uint8Array).
-//   - Throws an error if marshalling fails.
-func (c *DMDbCipher) UnmarshalJSON(_ js.Value, args []js.Value) any {
-	err := c.api.UnmarshalJSON(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		exception.ThrowTrace(err)
-		return nil
-	}
-	return nil
-}
-
 // truncate truncates the string to length n. If the string is trimmed, then
 // ellipses (...) are appended.
 func truncate(s string, n int) string {
diff --git a/wasm/dm_test.go b/wasm/dm_test.go
index ff5fbb1c..b6c5aff7 100644
--- a/wasm/dm_test.go
+++ b/wasm/dm_test.go
@@ -66,9 +66,9 @@ func Test_DMClientMethods(t *testing.T) {
 // Tests that the map representing DMDbCipher returned by newDMDbCipherJS
 // contains all of the methods on DMDbCipher.
 func Test_newDMDbCipherJS(t *testing.T) {
-	cipherType := reflect.TypeOf(&DMDbCipher{})
+	cipherType := reflect.TypeOf(&DbCipher{})
 
-	cipher := newDMDbCipherJS(&bindings.DbCipher{})
+	cipher := newDbCipherJS(&DbCipher{})
 	if len(cipher) != cipherType.NumMethod() {
 		t.Errorf("DMDbCipher JS object does not have all methods."+
 			"\nexpected: %d\nreceived: %d", cipherType.NumMethod(), len(cipher))
@@ -85,8 +85,8 @@ func Test_newDMDbCipherJS(t *testing.T) {
 
 // Tests that DMDbCipher has all the methods that [bindings.DMDbCipher] has.
 func Test_DMDbCipherMethods(t *testing.T) {
-	cipherType := reflect.TypeOf(&DMDbCipher{})
-	binCipherType := reflect.TypeOf(&bindings.DbCipher{})
+	cipherType := reflect.TypeOf(&DbCipher{})
+	binCipherType := reflect.TypeOf(&DbCipher{})
 
 	if binCipherType.NumMethod() != cipherType.NumMethod() {
 		t.Errorf("WASM DMDbCipher object does not have all methods from "+
-- 
GitLab