Skip to content
Snippets Groups Projects
Commit feb6d97f authored by Jono Wenger's avatar Jono Wenger
Browse files

Bug fixes

parent 659ab727
Branches
Tags
2 merge requests!60Revert "Fail a test to be sure it works",!8Updates to match the client fullyDecentrilizedChannels branch
......@@ -7,8 +7,8 @@ require (
github.com/hack-pad/go-indexeddb v0.2.0
github.com/pkg/errors v0.9.1
github.com/spf13/jwalterweatherman v1.1.0
gitlab.com/elixxir/client v1.5.1-0.20220928170652-fe87f3ae67b4
gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6
gitlab.com/elixxir/client v1.5.1-0.20221003205254-6cfac3468914
gitlab.com/elixxir/crypto v0.0.7-0.20221003185354-b091598d2322
gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6
gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548
)
......
......@@ -636,6 +636,18 @@ gitlab.com/elixxir/client v1.5.1-0.20220925005456-24eb354b1d6f h1:m0jwFnBatQH/3u
gitlab.com/elixxir/client v1.5.1-0.20220925005456-24eb354b1d6f/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ=
gitlab.com/elixxir/client v1.5.1-0.20220928170652-fe87f3ae67b4 h1:WgpR5CjPDXSRF5lpRhyyexmNsMQq9xiwMJd3HeDOb68=
gitlab.com/elixxir/client v1.5.1-0.20220928170652-fe87f3ae67b4/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ=
gitlab.com/elixxir/client v1.5.1-0.20221003171000-d0367733252c h1:3Vegb3loIg9UGj6tG4je5jUSmum6I1vv5848InsJk9w=
gitlab.com/elixxir/client v1.5.1-0.20221003171000-d0367733252c/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ=
gitlab.com/elixxir/client v1.5.1-0.20221003181318-ad80fa9efc50 h1:4BMaEwzDZIkDEqMJTqnhoZGTUbLIxldSa7JgDOXBVk4=
gitlab.com/elixxir/client v1.5.1-0.20221003181318-ad80fa9efc50/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ=
gitlab.com/elixxir/client v1.5.1-0.20221003182734-3e6c09af242a h1:c3oTU3DtOhDG2DU1jNyUMziNOWVsRzpoSqrLdOUrezo=
gitlab.com/elixxir/client v1.5.1-0.20221003182734-3e6c09af242a/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ=
gitlab.com/elixxir/client v1.5.1-0.20221003194042-5539ac20b937 h1:a0AM2V07rtUhTyZGfBNIXQtihMM3ZmcRktcgb5WTsxE=
gitlab.com/elixxir/client v1.5.1-0.20221003194042-5539ac20b937/go.mod h1:wuTIcLuMnvIGSo8i/Gg/SbYF57bE+CbKPpA1Xbk2AKk=
gitlab.com/elixxir/client v1.5.1-0.20221003200717-5f4afe50a1fe h1:q5TtT4szh+0+1iM+CRm3IYkWuP09VB5QQ6l/2/PDkcY=
gitlab.com/elixxir/client v1.5.1-0.20221003200717-5f4afe50a1fe/go.mod h1:wuTIcLuMnvIGSo8i/Gg/SbYF57bE+CbKPpA1Xbk2AKk=
gitlab.com/elixxir/client v1.5.1-0.20221003205254-6cfac3468914 h1:ZWf+WxkfoRh41hoeVPZ7L5AI1puJw324bXT9QI4Er4I=
gitlab.com/elixxir/client v1.5.1-0.20221003205254-6cfac3468914/go.mod h1:wuTIcLuMnvIGSo8i/Gg/SbYF57bE+CbKPpA1Xbk2AKk=
gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939 h1:+VRx2ULHKs040bBhDAOKNCZnbcXxUk3jD9JoKQzQpLk=
gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939/go.mod h1:AO6XkMhaHJW8eXlgL5m3UUcJqsSP8F5Wm1GX+wyq/rw=
gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
......@@ -643,6 +655,8 @@ gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp0
gitlab.com/elixxir/crypto v0.0.7-0.20220913220142-ab0771bad0af/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6 h1:ZCMqzKB86nrs9ldIoF2ZHvcExrkXIIIeH2RlNVwZx2A=
gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
gitlab.com/elixxir/crypto v0.0.7-0.20221003185354-b091598d2322 h1:8unQE70BDNRXTWUbjOO9d4kWyh19LySlTZo0Jqx0gPE=
gitlab.com/elixxir/crypto v0.0.7-0.20221003185354-b091598d2322/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is=
gitlab.com/elixxir/ekv v0.2.1/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU=
gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
......
......@@ -149,34 +149,31 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) {
// It may be called multiple times on the same message; it is incumbent on the
// user of the API to filter such called by message ID.
func (w *wasmModel) ReceiveMessage(channelID *id.ID,
messageID cryptoChannel.MessageID,
nickname, text string, identity cryptoChannel.Identity,
timestamp time.Time, lease time.Duration, round rounds.Round,
messageID cryptoChannel.MessageID, nickname, text string,
identity cryptoChannel.Identity, timestamp time.Time, lease time.Duration,
round rounds.Round, mType channels.MessageType,
status channels.SentStatus) uint64 {
parentErr := errors.New("failed to ReceiveMessage")
msgToInsert := buildMessage(channelID.Marshal(),
messageID.Bytes(), nil, nickname, text, identity,
timestamp, lease, status)
msgToInsert := buildMessage(channelID.Marshal(), messageID.Bytes(), nil,
nickname, text, identity, timestamp, lease, round.ID, mType, status)
// Attempt a lookup on the MessageID if it is non-zero to find
// an existing entry for it. This occurs any time a sender
// receives their own message from the mixnet.
// Attempt a lookup on the MessageID if it is non-zero to find an existing
// entry for it. This occurs any time a sender receives their own message
// from the mixnet.
if !messageID.Equals(cryptoChannel.MessageID{}) {
uuid, err := w.msgIDLookup(messageID)
if err != nil {
// NOTE: No stack is OK here
jww.WARN.Printf(err.Error())
// message is already in the database, no insert necessary
return uuid
}
msgToInsert.ID = uuid
}
uuid, err := w.receiveHelper(msgToInsert)
if err != nil {
jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error()))
jww.ERROR.Printf("Failed to receiver message: %+v", err)
}
go w.receivedMessageCB(uuid, channelID)
go w.receivedMessageCB(uuid, channelID, false)
return uuid
}
......@@ -187,19 +184,32 @@ func (w *wasmModel) ReceiveMessage(channelID *id.ID,
// Messages may arrive our of order, so a reply, in theory, can arrive before
// the initial message. As a result, it may be important to buffer replies.
func (w *wasmModel) ReceiveReply(channelID *id.ID,
messageID cryptoChannel.MessageID,
replyTo cryptoChannel.MessageID, nickname, text string,
identity cryptoChannel.Identity, timestamp time.Time,
lease time.Duration, round rounds.Round, status channels.SentStatus) uint64 {
parentErr := errors.New("failed to ReceiveReply")
messageID cryptoChannel.MessageID, replyTo cryptoChannel.MessageID,
nickname, text string, identity cryptoChannel.Identity, timestamp time.Time,
lease time.Duration, round rounds.Round, mType channels.MessageType,
status channels.SentStatus) uint64 {
msgToInsert := buildMessage(channelID.Marshal(), messageID.Bytes(),
replyTo.Bytes(), nickname, text, identity, timestamp, lease, round.ID,
mType, status)
// Attempt a lookup on the MessageID if it is non-zero to find an existing
// entry for it. This occurs any time a sender receives their own message
// from the mixnet.
if !messageID.Equals(cryptoChannel.MessageID{}) {
uuid, err := w.msgIDLookup(messageID)
if err != nil {
// message is already in the database, no insert necessary
return uuid
}
}
uuid, err := w.receiveHelper(msgToInsert)
uuid, err := w.receiveHelper(buildMessage(channelID.Marshal(),
messageID.Bytes(), replyTo.Bytes(), nickname, text, identity,
timestamp, lease, status))
if err != nil {
jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error()))
jww.ERROR.Printf("Failed to receive reply: %+v", err)
}
go w.receivedMessageCB(uuid, channelID)
go w.receivedMessageCB(uuid, channelID, false)
return uuid
}
......@@ -209,25 +219,39 @@ func (w *wasmModel) ReceiveReply(channelID *id.ID,
//
// Messages may arrive our of order, so a reply, in theory, can arrive before
// the initial message. As a result, it may be important to buffer reactions.
func (w *wasmModel) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID,
reactionTo cryptoChannel.MessageID, nickname, reaction string,
identity cryptoChannel.Identity, timestamp time.Time,
lease time.Duration, round rounds.Round, status channels.SentStatus) uint64 {
parentErr := errors.New("failed to ReceiveReaction")
func (w *wasmModel) ReceiveReaction(channelID *id.ID,
messageID cryptoChannel.MessageID, reactionTo cryptoChannel.MessageID,
nickname, reaction string, identity cryptoChannel.Identity,
timestamp time.Time, lease time.Duration, round rounds.Round,
mType channels.MessageType, status channels.SentStatus) uint64 {
msgToInsert := buildMessage(channelID.Marshal(), messageID.Bytes(),
reactionTo.Bytes(), nickname, reaction, identity, timestamp, lease,
round.ID, mType, status)
uuid, err := w.receiveHelper(buildMessage(channelID.Marshal(),
messageID.Bytes(), reactionTo.Bytes(), nickname, reaction,
identity, timestamp, lease, status))
// Attempt a lookup on the MessageID if it is non-zero to find
// an existing entry for it. This occurs any time a sender
// receives their own message from the mixnet.
if !messageID.Equals(cryptoChannel.MessageID{}) {
uuid, err := w.msgIDLookup(messageID)
if err != nil {
jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error()))
// message is already in the database, no insert necessary
return uuid
}
}
go w.receivedMessageCB(uuid, channelID)
uuid, err := w.receiveHelper(msgToInsert)
if err != nil {
jww.ERROR.Printf("Failed to receive reaction: %+v", err)
}
go w.receivedMessageCB(uuid, channelID, false)
return uuid
}
// UpdateSentStatus is called whenever the [channels.SentStatus] of a
// message has changed. At this point the message ID goes from
// empty/unknown to populated.
// UpdateSentStatus is called whenever the [channels.SentStatus] of a message
// has changed. At this point the message ID goes from empty/unknown to
// populated.
//
// TODO: Potential race condition due to separate get/update operations.
func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.MessageID,
timestamp time.Time, round rounds.Round, status channels.SentStatus) {
......@@ -255,7 +279,17 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.Messag
return
}
newMessage.Status = uint8(status)
if !messageID.Equals(cryptoChannel.MessageID{}) {
newMessage.MessageID = messageID.Bytes()
}
if round.ID == 0 {
newMessage.Round = uint64(round.ID)
}
if !timestamp.Equal(time.Time{}) {
newMessage.Timestamp = timestamp
}
// Store the updated Message
_, err = w.receiveHelper(newMessage)
......@@ -264,7 +298,7 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.Messag
}
channelID := &id.ID{}
copy(channelID[:], newMessage.ChannelID)
go w.receivedMessageCB(uuid, channelID)
go w.receivedMessageCB(uuid, channelID, true)
}
// buildMessage is a private helper that converts typical [channels.EventModel]
......@@ -273,9 +307,9 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID cryptoChannel.Messag
// autoincrement key by default. If you are trying to overwrite
// an existing message, then you need to set it manually
// yourself.
func buildMessage(channelID, messageID, parentID []byte, nickname,
text string, identity cryptoChannel.Identity, timestamp time.Time,
lease time.Duration,
func buildMessage(channelID, messageID, parentID []byte, nickname, text string,
identity cryptoChannel.Identity, timestamp time.Time, lease time.Duration,
round id.Round, mType channels.MessageType,
status channels.SentStatus) *Message {
return &Message{
MessageID: messageID,
......@@ -288,8 +322,10 @@ func buildMessage(channelID, messageID, parentID []byte, nickname,
Hidden: false,
Pinned: false,
Text: text,
Type: uint16(mType),
Round: uint64(round),
// User Identity Info
Pubkey: []byte(identity.PubKey),
Pubkey: identity.PubKey,
Codename: identity.Codename,
Color: identity.Color,
Extension: identity.Extension,
......
......@@ -29,12 +29,12 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func dummyCallback(uuid uint64, channelID *id.ID) {}
func dummyCallback(uint64, *id.ID, bool) {}
// Test wasmModel.UpdateSentStatus happy path and ensure fields don't change.
func TestWasmModel_UpdateSentStatus(t *testing.T) {
testString := "test"
testMsgId := channel.MakeMessageID([]byte(testString))
testMsgId := channel.MakeMessageID([]byte(testString), &id.ID{1})
eventModel, err := newWASMModel(testString, dummyCallback)
if err != nil {
t.Fatalf("%+v", err)
......@@ -43,9 +43,9 @@ func TestWasmModel_UpdateSentStatus(t *testing.T) {
cid := channel.Identity{}
// Store a test message
testMsg := buildMessage([]byte(testString), testMsgId.Bytes(),
nil, testString, testString, cid, time.Now(),
time.Second, channels.Sent)
testMsg := buildMessage([]byte(testString), testMsgId.Bytes(), nil,
testString, testString, cid, time.Now(), time.Second, 0, 0,
channels.Sent)
uuid, err := eventModel.receiveHelper(testMsg)
if err != nil {
t.Fatalf("%+v", err)
......@@ -148,15 +148,15 @@ func TestWasmModel_UUIDTest(t *testing.T) {
// Store a test message
channelID := id.NewIdFromBytes([]byte(testString), t)
msgID := channel.MessageID{}
copy(msgID[:], []byte(testString+fmt.Sprintf("%d", i)))
copy(msgID[:], testString+fmt.Sprintf("%d", i))
rnd := rounds.Round{ID: id.Round(42)}
uuid := eventModel.ReceiveMessage(channelID, msgID,
"test", testString+fmt.Sprintf("%d", i), cid, time.Now(),
time.Hour, rnd, channels.Sent)
time.Hour, rnd, 0, channels.Sent)
uuids[i] = uuid
}
eventModel.dump(messageStoreName)
_, _ = eventModel.dump(messageStoreName)
for i := 0; i < 10; i++ {
for j := i + 1; j < 10; j++ {
......
......@@ -31,7 +31,8 @@ const (
)
// MessageReceivedCallback is called any time a message is received or updated
type MessageReceivedCallback func(uuid uint64, channelID *id.ID)
// update is true if the row is old and was edited
type MessageReceivedCallback func(uuid uint64, channelID *id.ID, update bool)
// NewWASMEventModelBuilder returns an EventModelBuilder which allows
// the channel manager to define the path but the callback is the same
......
......@@ -58,8 +58,10 @@ type Message struct {
Hidden bool `json:"hidden"`
Pinned bool `json:"pinned"` // Index
Text string `json:"text"`
Type uint16 `json:"type"`
Round uint64 `json:"round"`
// User cryptographic IDentity struct -- could be pulled out
// User cryptographic Identity struct -- could be pulled out
Pubkey []byte `json:"pubkey"` // Index
// Honorific string `json:"honorific"`
// Adjective string `json:"adjective"`
......
......@@ -235,7 +235,8 @@ func LoadChannelsManager(_ js.Value, args []js.Value) interface{} {
// returned as an int and the channelID as a Uint8Array. The row in the
// database that was updated can be found using the UUID. The channel ID is
// provided so that the recipient can filter if they want to the processes
// the update now or not.
// the update now or not. An "update" bool is present which tells you if
// the row is new or if it is an edited old row
//
// Returns a promise:
// - Resolves to a Javascript representation of the [ChannelsManager] object.
......@@ -244,8 +245,8 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) interface{} {
cmixID := args[0].Int()
privateIdentity := utils.CopyBytesToGo(args[1])
fn := func(uuid uint64, channelID *id.ID) {
args[2].Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()))
fn := func(uuid uint64, channelID *id.ID, update bool) {
args[2].Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), update)
}
model := indexedDb.NewWASMEventModelBuilder(fn)
......@@ -281,7 +282,8 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) interface{} {
// returned as an int and the channelID as a Uint8Array. The row in the
// database that was updated can be found using the UUID. The channel ID is
// provided so that the recipient can filter if they want to the processes
// the update now or not.
// the update now or not. An "update" bool is present which tells you if
// the row is new or if it is an edited old row
//
// Returns a promise:
// - Resolves to a Javascript representation of the [ChannelsManager] object.
......@@ -290,8 +292,8 @@ func LoadChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) interface{} {
cmixID := args[0].Int()
storageTag := args[1].String()
fn := func(uuid uint64, channelID *id.ID) {
args[2].Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()))
fn := func(uuid uint64, channelID *id.ID, updated bool) {
args[2].Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), updated)
}
model := indexedDb.NewWASMEventModelBuilder(fn)
......@@ -872,6 +874,7 @@ func (em *eventModel) LeaveChannel(channelID []byte) {
// since unix epoch (int).
// - lease - The number of nanoseconds that the message is valid for (int).
// - roundId - The ID of the round that the message was received on (int).
// - msgType - The type of message ([channels.MessageType]) to send (int).
// - status - The [channels.SentStatus] of the message (int).
//
// Statuses will be enumerated as such:
......@@ -883,10 +886,12 @@ func (em *eventModel) LeaveChannel(channelID []byte) {
// - A non-negative unique UUID for the message that it can be referenced by
// later with [eventModel.UpdateSentStatus].
func (em *eventModel) ReceiveMessage(channelID, messageID []byte, nickname,
text string, identity []byte, timestamp, lease, roundId, status int64) int64 {
text string, identity []byte, timestamp, lease, roundId, msgType,
status int64) int64 {
uuid := em.receiveMessage(utils.CopyBytesToJS(channelID),
utils.CopyBytesToJS(messageID), nickname, text,
utils.CopyBytesToJS(identity), timestamp, lease, roundId, status)
utils.CopyBytesToJS(identity),
timestamp, lease, roundId, msgType, status)
return int64(uuid.Int())
}
......@@ -911,6 +916,7 @@ func (em *eventModel) ReceiveMessage(channelID, messageID []byte, nickname,
// since unix epoch (int).
// - lease - The number of nanoseconds that the message is valid for (int).
// - roundId - The ID of the round that the message was received on (int).
// - msgType - The type of message ([channels.MessageType]) to send (int).
// - status - The [channels.SentStatus] of the message (int).
//
// Statuses will be enumerated as such:
......@@ -923,11 +929,11 @@ func (em *eventModel) ReceiveMessage(channelID, messageID []byte, nickname,
// later with [eventModel.UpdateSentStatus].
func (em *eventModel) ReceiveReply(channelID, messageID, reactionTo []byte,
senderUsername, text string, identity []byte, timestamp, lease, roundId,
status int64) int64 {
msgType, status int64) int64 {
uuid := em.receiveReply(utils.CopyBytesToJS(channelID),
utils.CopyBytesToJS(messageID), utils.CopyBytesToJS(reactionTo),
senderUsername, text, utils.CopyBytesToJS(identity),
timestamp, lease, roundId, status)
timestamp, lease, roundId, msgType, status)
return int64(uuid.Int())
}
......@@ -952,6 +958,7 @@ func (em *eventModel) ReceiveReply(channelID, messageID, reactionTo []byte,
// since unix epoch (int).
// - lease - The number of nanoseconds that the message is valid for (int).
// - roundId - The ID of the round that the message was received on (int).
// - msgType - The type of message ([channels.MessageType]) to send (int).
// - status - The [channels.SentStatus] of the message (int).
//
// Statuses will be enumerated as such:
......@@ -964,11 +971,11 @@ func (em *eventModel) ReceiveReply(channelID, messageID, reactionTo []byte,
// later with [eventModel.UpdateSentStatus].
func (em *eventModel) ReceiveReaction(channelID, messageID, reactionTo []byte,
senderUsername, reaction string, identity []byte, timestamp, lease, roundId,
status int64) int64 {
msgType, status int64) int64 {
uuid := em.receiveReaction(utils.CopyBytesToJS(channelID),
utils.CopyBytesToJS(messageID), utils.CopyBytesToJS(reactionTo),
senderUsername, reaction, utils.CopyBytesToJS(identity),
timestamp, lease, roundId, status)
timestamp, lease, roundId, msgType, status)
return int64(uuid.Int())
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment