Skip to content
Snippets Groups Projects
Commit 5f4afe50 authored by benjamin's avatar benjamin
Browse files

Merge remote-tracking branch 'origin/fullyDecentrilizedChannels' into fullyDecentrilizedChannels

parents e17d5dd1 5539ac20
No related branches found
No related tags found
4 merge requests!510Release,!419rewrote the health tracker to both consider if there are waiting rounds and...,!397Fully Decentralized channels,!340Project/channels
...@@ -47,6 +47,10 @@ type ChannelMessage struct { ...@@ -47,6 +47,10 @@ type ChannelMessage struct {
// nickname is the name which the user is using for this message // nickname is the name which the user is using for this message
// it will not be longer than 24 characters // it will not be longer than 24 characters
Nickname string `protobuf:"bytes,5,opt,name=Nickname,proto3" json:"Nickname,omitempty"` Nickname string `protobuf:"bytes,5,opt,name=Nickname,proto3" json:"Nickname,omitempty"`
// Nonce is 32 bits of randomness to ensure that two messages in the same
// round with that have the same nickname, payload, and lease will not have
// the same message ID.
Nonce []byte `protobuf:"bytes,6,opt,name=Nonce,proto3" json:"Nonce,omitempty"`
} }
func (x *ChannelMessage) Reset() { func (x *ChannelMessage) Reset() {
...@@ -116,6 +120,13 @@ func (x *ChannelMessage) GetNickname() string { ...@@ -116,6 +120,13 @@ func (x *ChannelMessage) GetNickname() string {
return "" return ""
} }
func (x *ChannelMessage) GetNonce() []byte {
if x != nil {
return x.Nonce
}
return nil
}
// UserMessage is a message sent by a user who is a member within the channel. // UserMessage is a message sent by a user who is a member within the channel.
type UserMessage struct { type UserMessage struct {
state protoimpl.MessageState state protoimpl.MessageState
...@@ -194,7 +205,7 @@ var File_channelMessages_proto protoreflect.FileDescriptor ...@@ -194,7 +205,7 @@ var File_channelMessages_proto protoreflect.FileDescriptor
var file_channelMessages_proto_rawDesc = []byte{ var file_channelMessages_proto_rawDesc = []byte{
0x0a, 0x15, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x15, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
0x73, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x22, 0xae, 0x01, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x03, 0x52, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x01, 0x28, 0x03, 0x52, 0x05, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f,
0x75, 0x6e, 0x64, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x75, 0x6e, 0x64, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x52, 0x6f, 0x75,
...@@ -203,17 +214,18 @@ var file_channelMessages_proto_rawDesc = []byte{ ...@@ -203,17 +214,18 @@ var file_channelMessages_proto_rawDesc = []byte{
0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61,
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x69, 0x0a, 0x0b, 0x28, 0x09, 0x52, 0x08, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x4e, 0x6f, 0x6e,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x4d, 0x65, 0x63, 0x65, 0x22, 0x69, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x28, 0x0c, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x53,
0x75, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x45, 0x43, 0x43, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x45, 0x43, 0x43, 0x50, 0x75, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x45, 0x43, 0x43,
0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x0c, 0x45, 0x43, 0x43, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x24, 0x5a,
0x69, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x22, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x69, 0x78,
0x72, 0x6f, 0x74, 0x6f, 0x33, 0x78, 0x69, 0x72, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e,
0x65, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
......
...@@ -32,9 +32,9 @@ message ChannelMessage{ ...@@ -32,9 +32,9 @@ message ChannelMessage{
// it will not be longer than 24 characters // it will not be longer than 24 characters
string Nickname = 5; string Nickname = 5;
// Nonce is 32 bits of randomness to ensure that in the event that in the // Nonce is 32 bits of randomness to ensure that two messages in the same
// same round two messages are send with the same nickname, payload, // round with that have the same nickname, payload, and lease will not have
// and lease, they will not have the same message ID. // the same message ID.
bytes Nonce = 6; bytes Nonce = 6;
} }
......
...@@ -9,6 +9,7 @@ package channels ...@@ -9,6 +9,7 @@ package channels
import ( import (
"crypto/ed25519" "crypto/ed25519"
"github.com/pkg/errors"
"gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix"
"gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/cmix/rounds"
cryptoChannel "gitlab.com/elixxir/crypto/channel" cryptoChannel "gitlab.com/elixxir/crypto/channel"
...@@ -24,6 +25,9 @@ const ( ...@@ -24,6 +25,9 @@ const (
cmixChannelReactionVersion = 0 cmixChannelReactionVersion = 0
) )
// The size of the nonce used in the message ID.
const messageNonceSize = 4
// SendGeneric is used to send a raw message over a channel. In general, it // SendGeneric is used to send a raw message over a channel. In general, it
// should be wrapped in a function which defines the wire protocol // should be wrapped in a function which defines the wire protocol
// If the final message, before being sent over the wire, is too long, this will // If the final message, before being sent over the wire, is too long, this will
...@@ -49,6 +53,21 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType, ...@@ -49,6 +53,21 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
PayloadType: uint32(messageType), PayloadType: uint32(messageType),
Payload: msg, Payload: msg,
Nickname: nickname, Nickname: nickname,
Nonce: make([]byte, messageNonceSize),
}
// Generate random nonce to be used for message ID generation. This makes it
// so two identical messages sent on the same round have different message IDs
rng := m.rng.GetStream()
n, err := rng.Read(chMsg.Nonce)
rng.Close()
if err != nil {
return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{},
errors.Errorf("Failed to generate nonce: %+v", err)
} else if n != messageNonceSize {
return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{},
errors.Errorf(
"Generated %d bytes for %-byte nonce", n, messageNonceSize)
} }
usrMsg := &UserMessage{ usrMsg := &UserMessage{
...@@ -124,8 +143,24 @@ func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID, ...@@ -124,8 +143,24 @@ func (m *manager) SendAdminGeneric(privKey rsa.PrivateKey, channelID *id.ID,
PayloadType: uint32(messageType), PayloadType: uint32(messageType),
Payload: msg, Payload: msg,
Nickname: AdminUsername, Nickname: AdminUsername,
Nonce: make([]byte, messageNonceSize),
} }
//Note: we are not checking check if message is too long before trying to
// Generate random nonce to be used for message ID generation. This makes it
// so two identical messages sent on the same round have different message IDs
rng := m.rng.GetStream()
n, err := rng.Read(chMsg.Nonce)
rng.Close()
if err != nil {
return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{},
errors.Errorf("Failed to generate nonce: %+v", err)
} else if n != messageNonceSize {
return cryptoChannel.MessageID{}, rounds.Round{}, ephemeral.Id{},
errors.Errorf(
"Generated %d bytes for %-byte nonce", n, messageNonceSize)
}
// Note: we are not checking if message is too long before trying to
// find a round // find a round
//Build the function pointer that will build the message //Build the function pointer that will build the message
......
...@@ -15,11 +15,13 @@ import ( ...@@ -15,11 +15,13 @@ import (
"gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/cmix/rounds"
"gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/client/storage/versioned"
cryptoChannel "gitlab.com/elixxir/crypto/channel" cryptoChannel "gitlab.com/elixxir/crypto/channel"
"gitlab.com/elixxir/crypto/fastRNG"
"gitlab.com/elixxir/crypto/rsa" "gitlab.com/elixxir/crypto/rsa"
"gitlab.com/elixxir/ekv" "gitlab.com/elixxir/ekv"
"gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/csprng"
"gitlab.com/xx_network/primitives/netTime" "gitlab.com/xx_network/primitives/netTime"
"math/rand" "math/rand"
"sync"
"testing" "testing"
"time" "time"
...@@ -153,6 +155,8 @@ func TestSendGeneric(t *testing.T) { ...@@ -153,6 +155,8 @@ func TestSendGeneric(t *testing.T) {
m := &manager{ m := &manager{
me: pi, me: pi,
channels: make(map[id.ID]*joinedChannel), channels: make(map[id.ID]*joinedChannel),
mux: sync.RWMutex{},
rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
nicknameManager: &nicknameManager{ nicknameManager: &nicknameManager{
byChannel: make(map[id.ID]string), byChannel: make(map[id.ID]string),
kv: nil, kv: nil,
...@@ -243,6 +247,7 @@ func TestAdminGeneric(t *testing.T) { ...@@ -243,6 +247,7 @@ func TestAdminGeneric(t *testing.T) {
kv: nil, kv: nil,
}, },
me: pi, me: pi,
rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
st: loadSendTracker(&mockBroadcastClient{}, st: loadSendTracker(&mockBroadcastClient{},
versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID,
umi *userMessageInternal, ts time.Time, umi *userMessageInternal, ts time.Time,
...@@ -332,6 +337,7 @@ func TestSendMessage(t *testing.T) { ...@@ -332,6 +337,7 @@ func TestSendMessage(t *testing.T) {
byChannel: make(map[id.ID]string), byChannel: make(map[id.ID]string),
kv: nil, kv: nil,
}, },
rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
st: loadSendTracker(&mockBroadcastClient{}, st: loadSendTracker(&mockBroadcastClient{},
versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID,
umi *userMessageInternal, ts time.Time, umi *userMessageInternal, ts time.Time,
...@@ -426,6 +432,7 @@ func TestSendReply(t *testing.T) { ...@@ -426,6 +432,7 @@ func TestSendReply(t *testing.T) {
byChannel: make(map[id.ID]string), byChannel: make(map[id.ID]string),
kv: nil, kv: nil,
}, },
rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
st: loadSendTracker(&mockBroadcastClient{}, st: loadSendTracker(&mockBroadcastClient{},
versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID,
umi *userMessageInternal, ts time.Time, umi *userMessageInternal, ts time.Time,
...@@ -519,6 +526,7 @@ func TestSendReaction(t *testing.T) { ...@@ -519,6 +526,7 @@ func TestSendReaction(t *testing.T) {
byChannel: make(map[id.ID]string), byChannel: make(map[id.ID]string),
kv: nil, kv: nil,
}, },
rng: fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
channels: make(map[id.ID]*joinedChannel), channels: make(map[id.ID]*joinedChannel),
st: loadSendTracker(&mockBroadcastClient{}, st: loadSendTracker(&mockBroadcastClient{},
versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID, versioned.NewKV(ekv.MakeMemstore()), func(chID *id.ID,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment