diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go index 7194f0429c7bc38268bb418a26138c5ce58308e9..1152d2739cccacf884b32349be4f65bd047e5fb6 100644 --- a/api/authenticatedChannel.go +++ b/api/authenticatedChannel.go @@ -59,8 +59,7 @@ func (c *Client) RegisterAuthCallbacks(request auth.RequestCallback, // An error will be returned if a channel already exists, if a request doest // exist, or if the passed in contact does not exactly match the received // request -func (c *Client) ConfirmAuthenticatedChannel(recipient, me contact.Contact, - message string) error { +func (c *Client) ConfirmAuthenticatedChannel(recipient contact.Contact) error { jww.INFO.Printf("RequestAuthenticatedChannel(%s)", recipient.ID) if !c.network.GetHealthTracker().IsHealthy() { diff --git a/auth/callback.go b/auth/callback.go index 5817bd39886b5130e24c954c74769ad3813fdabf..a8eed00f1c5b30b51634a6bfb826ca183606d368 100644 --- a/auth/callback.go +++ b/auth/callback.go @@ -153,7 +153,7 @@ func handleRequest(cmixMsg format.Message, myHistoricalPrivKey *cyclic.Int, } //process the inner payload - facts, msg, err := contact.UnstringifyFacts( + facts, msg, err := contact.UnstringifyFactList( string(requestFmt.msgPayload)) if err != nil { jww.WARN.Printf("failed to parse facts and message "+ diff --git a/auth/request.go b/auth/request.go index fe0b621f2e9f55b71b6a245f8a64e6b6ff2e17fc..ba231d297821e97f3e06c819bb109867cd585078 100644 --- a/auth/request.go +++ b/auth/request.go @@ -75,7 +75,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, } //check the payload fits - facts := me.StringifyFacts() + facts := me.Facts.Stringify() msgPayload := facts + message + eol msgPayloadBytes := []byte(msgPayload) diff --git a/bindings/authenticatedChannels.go b/bindings/authenticatedChannels.go index 7acd5d39962f29b5cf7ed0f2f127891bd3587550..623a452503f5655c9d79bb52d7d9d49e4e3eb253 100644 --- a/bindings/authenticatedChannels.go +++ b/bindings/authenticatedChannels.go @@ -1,8 +1,105 @@ package bindings -import "gitlab.com/elixxir/client/interfaces/bind" +import ( + "errors" + "fmt" + "gitlab.com/elixxir/client/interfaces/contact" +) // Create an insecure e2e relationship with a precanned user -func (c *Client) MakePrecannedAuthenticatedChannel(precannedID int) bind.Contact { - return c.api.MakePrecannedContact(uint(precannedID)) +func (c *Client) MakePrecannedAuthenticatedChannel(precannedID int) (*Contact, error) { + precannedContact, err := c.api.MakePrecannedAuthenticatedChannel(uint(precannedID)) + if err != nil { + return nil, errors.New(fmt.Sprintf("Failed to "+ + "MakePrecannedAuthenticatedChannel: %+v", err)) + } + return &Contact{c: &precannedContact}, nil } + +// RequestAuthenticatedChannel sends a request to another party to establish an +// authenticated channel +// It will not run if the network status is not healthy +// An error will be returned if a channel already exists, if a request was +// already received, or if a request was already sent +// When a confirmation occurs, the channel will be created and the callback +// will be called +// +// This function takes the marshaled send report to ensure a memory leak does +// not occur as a result of both sides of the bindings holding a refrence to +// the same pointer. +func (c *Client) RequestAuthenticatedChannel(recipientMarshaled, + meMarshaled []byte, message string) error { + recipent, err := contact.Unmarshal(recipientMarshaled) + + if err != nil { + return errors.New(fmt.Sprintf("Failed to "+ + "RequestAuthenticatedChannel: Failed to Unmarshal Recipent: "+ + "%+v", err)) + } + + me, err := contact.Unmarshal(meMarshaled) + + if err != nil { + return errors.New(fmt.Sprintf("Failed to "+ + "RequestAuthenticatedChannel: Failed to Unmarshal Me: %+v", err)) + } + + return c.api.RequestAuthenticatedChannel(recipent, me, message) +} + +// RegisterAuthCallbacks registers both callbacks for authenticated channels. +// This can only be called once +func (c *Client) RegisterAuthCallbacks(request AuthRequestCallback, + confirm AuthConfirmCallback) error { + + requestFunc := func(requestor contact.Contact, message string) { + requestorBind := &Contact{c: &requestor} + request.Callback(requestorBind, message) + } + + confirmFunc := func(partner contact.Contact) { + partnerBind := &Contact{c: &partner} + confirm.Callback(partnerBind) + } + + return c.api.RegisterAuthCallbacks(requestFunc, confirmFunc) +} + +// ConfirmAuthenticatedChannel creates an authenticated channel out of a valid +// received request and sends a message to the requestor that the request has +// been confirmed +// It will not run if the network status is not healthy +// An error will be returned if a channel already exists, if a request doest +// exist, or if the passed in contact does not exactly match the received +// request +func (c *Client) ConfirmAuthenticatedChannel(recipientMarshaled []byte) error { + recipent, err := contact.Unmarshal(recipientMarshaled) + + if err != nil { + return errors.New(fmt.Sprintf("Failed to "+ + "ConfirmAuthenticatedChannel: Failed to Unmarshal Recipient: "+ + "%+v", err)) + } + + return c.api.ConfirmAuthenticatedChannel(recipent) +} + +// VerifyOwnership checks if the ownership proof on a passed contact matches the +// identity in a verified contact +func (c *Client) VerifyOwnership(receivedMarshaled, verifiedMarshaled []byte) (bool, error) { + received, err := contact.Unmarshal(receivedMarshaled) + + if err != nil { + return false, errors.New(fmt.Sprintf("Failed to "+ + "VerifyOwnership: Failed to Unmarshal Received: %+v", err)) + } + + verified, err := contact.Unmarshal(verifiedMarshaled) + + if err != nil { + return false, errors.New(fmt.Sprintf("Failed to "+ + "VerifyOwnership: Failed to Unmarshal Verified: %+v", err)) + } + + return c.api.VerifyOwnership(received, verified), nil +} \ No newline at end of file diff --git a/bindings/callback.go b/bindings/callback.go index a3d9e2b8e19af71d26cf62a2f2251e7349b8220e..0dd0fbbc9112968e71a6dca1008454454e5c5713 100644 --- a/bindings/callback.go +++ b/bindings/callback.go @@ -30,6 +30,23 @@ type RoundEventCallback interface { EventCallback(rid, state int, timedOut bool) } +// RoundEventHandler handles round events happening on the cMix network. +type MessageDeliveryCallback interface { + EventCallback(msgID []byte, delivered, timedOut bool) +} + +// AuthRequestCallback notifies the register whenever they receive an auth +// request +type AuthRequestCallback interface { + Callback(requestor *Contact, message string) +} + +// AuthConfirmCallback notifies the register whenever they receive an auth +// request confirmation +type AuthConfirmCallback interface { + Callback(partner *Contact) +} + // Generic Unregister - a generic return used for all callbacks which can be // unregistered // Interface which allows the un-registration of a listener @@ -38,23 +55,34 @@ type Unregister struct { } //Call unregisters a callback -func (u Unregister) Unregister() { +func (u *Unregister) Unregister() { u.f() } //creates an unregister interface for listeners -func newListenerUnregister(lid switchboard.ListenerID, sw interfaces.Switchboard) Unregister { +func newListenerUnregister(lid switchboard.ListenerID, sw interfaces.Switchboard) *Unregister { f := func() { sw.Unregister(lid) } - return Unregister{f: f} + return &Unregister{f: f} } //creates an unregister interface for round events func newRoundUnregister(rid id.Round, ec *dataStructures.EventCallback, - re interfaces.RoundEvents) Unregister { + re interfaces.RoundEvents) *Unregister { f := func() { re.Remove(rid, ec) } - return Unregister{f: f} + return &Unregister{f: f} +} + +//creates an unregister interface for round events +func newRoundListUnregister(rounds []id.Round, ec []*dataStructures.EventCallback, + re interfaces.RoundEvents) *Unregister { + f := func() { + for i, r := range rounds { + re.Remove(r, ec[i]) + } + } + return &Unregister{f: f} } diff --git a/bindings/client.go b/bindings/client.go index 2d71a5af7621c1095b107c603d37f053832685d6..11f00973408be5f973936408e79c7ed2833cd0f5 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -7,17 +7,22 @@ package bindings import ( + "encoding/json" "errors" + "fmt" "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/interfaces/bind" "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/message" + "gitlab.com/elixxir/client/interfaces/utility" + "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" "time" + ds "gitlab.com/elixxir/comms/network/dataStructures" + ) // BindingsClient wraps the api.Client, implementing additional functions @@ -34,7 +39,12 @@ type Client struct { // Users of this function should delete the storage directory on error. func NewClient(network, storageDir string, password []byte, regCode string) error { jwalterweatherman.SetLogThreshold(jwalterweatherman.LevelInfo) - return api.NewClient(network, storageDir, password, regCode) + + if err := api.NewClient(network, storageDir, password, regCode); err != nil { + return errors.New(fmt.Sprintf("Failed to create new client: %+v", + err)) + } + return nil } // NewPrecannedClient creates an insecure user with predetermined keys with nodes @@ -50,7 +60,11 @@ func NewPrecannedClient(precannedID int, network, storageDir string, password [] return errors.New("Cannot create precanned client with negative ID") } - return api.NewPrecannedClient(uint(precannedID), network, storageDir, password) + if err := api.NewPrecannedClient(uint(precannedID), network, storageDir, password); err != nil { + return errors.New(fmt.Sprintf("Failed to create new precanned "+ + "client: %+v", err)) + } + return nil } // Login will load an existing client from the storageDir @@ -67,14 +81,29 @@ func Login(storageDir string, password []byte) (*Client, error) { client, err := api.Login(storageDir, password) if err != nil { - return nil, err + return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err)) } return &Client{*client}, nil } -//Unmarshals a marshaled contact object -func UnmarshalContact(b []byte) (bind.Contact, error) { - return contact.Unmarshal(b) +//Unmarshals a marshaled contact object, returns an error if it fails +func UnmarshalContact(b []byte) (*Contact, error) { + c, err := contact.Unmarshal(b) + if err != nil { + return nil, errors.New(fmt.Sprintf("Failed to Unmarshal "+ + "Contact: %+v", err)) + } + return &Contact{c: &c}, nil +} + +//Unmarshals a marshaled send report object, returns an error if it fails +func UnmarshalSendReport(b []byte) (*SendReport, error) { + sr := &SendReport{} + if err := json.Unmarshal(b, sr); err != nil { + return nil, errors.New(fmt.Sprintf("Failed to Unmarshal "+ + "Send Report: %+v", err)) + } + return sr, nil } // StartNetworkFollower kicks off the tracking of the network. It starts @@ -106,7 +135,11 @@ func UnmarshalContact(b []byte) (bind.Contact, error) { // - KeyExchange Confirm (/keyExchange/confirm.go) // Responds to confirmations of successful rekey operations func (c *Client) StartNetworkFollower() error { - return c.api.StartNetworkFollower() + if err := c.api.StartNetworkFollower(); err != nil { + return errors.New(fmt.Sprintf("Failed to start the "+ + "network follower: %+v", err)) + } + return nil } // StopNetworkFollower stops the network follower if it is running. @@ -116,7 +149,11 @@ func (c *Client) StartNetworkFollower() error { // most likely be in an unrecoverable state and need to be trashed. func (c *Client) StopNetworkFollower(timeoutMS int) error { timeout := time.Duration(timeoutMS) * time.Millisecond - return c.api.StopNetworkFollower(timeout) + if err := c.api.StopNetworkFollower(timeout); err != nil { + return errors.New(fmt.Sprintf("Failed to stop the "+ + "network follower: %+v", err)) + } + return nil } // Gets the state of the network follower. Returns: @@ -144,25 +181,39 @@ func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) { // matching specific uid, msgType, and/or username // Returns a ListenerUnregister interface which can be // +// to register for any userID, pass in an id with length 0 or an id with +// all zeroes +// +// to register for any message type, pass in a message type of 0 +// // Message Types can be found in client/interfaces/message/type.go // Make sure to not conflict with ANY default message types func (c *Client) RegisterListener(uid []byte, msgType int, - listener Listener) error { + listener Listener) (*Unregister, error) { name := listener.Name() - u, err := id.Unmarshal(uid) - if err != nil { - return err + + var u *id.ID + if len(uid) == 0 { + u = &id.ID{} + } else { + var err error + u, err = id.Unmarshal(uid) + if err != nil { + return nil, errors.New(fmt.Sprintf("Failed to "+ + "ResgisterListener: %+v", err)) + } } + mt := message.Type(msgType) f := func(item message.Receive) { listener.Hear(item) } - c.api.GetSwitchboard().RegisterFunc(name, u, mt, f) + lid := c.api.GetSwitchboard().RegisterFunc(name, u, mt, f) - return nil + return newListenerUnregister(lid, c.api.GetSwitchboard()), nil } // RegisterRoundEventsHandler registers a callback interface for round @@ -181,7 +232,7 @@ func (c *Client) RegisterListener(uid []byte, msgType int, // 0x06 - FAILED // These states are defined in elixxir/primitives/states/state.go func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback, - timeoutMS int, il *IntList) Unregister { + timeoutMS int, il *IntList) *Unregister { rcb := func(ri *mixmessages.RoundInfo, timedOut bool) { cb.EventCallback(int(ri.ID), int(ri.State), timedOut) @@ -201,11 +252,55 @@ func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback, return newRoundUnregister(roundID, ec, c.api.GetRoundEvents()) } +// RegisterMessageDeliveryCB allows the caller to get notified if the rounds a +// message was sent in sucesfully completed. Under the hood, this uses the same +// interface as RegisterRoundEventsHandler, but provides a convienet way to use +// the interface in its most common form, looking up the result of message +// retreval +// +// The callbacks will return at timeoutMS if no state update occurs +// +// This function takes the marshaled send report to ensure a memory leak does +// not occur as a result of both sides of the bindings holding a refrence to +// the same pointer. +func (c *Client) RegisterMessageDeliveryCB(marshaledSendReport []byte, + mdc MessageDeliveryCallback, timeoutMS int) (*Unregister, error) { + + sr, err := UnmarshalSendReport(marshaledSendReport) + if err != nil { + return nil, errors.New(fmt.Sprintf("Failed to "+ + "RegisterMessageDeliveryCB: %+v", err)) + } + + /*check message delivery*/ + sendResults := make(chan ds.EventReturn, len(sr.rl.list)) + roundEvents := c.api.GetRoundEvents() + + reventObjs := make([]*ds.EventCallback, len(sr.rl.list)) + + for i, r := range sr.rl.list { + reventObjs[i] = roundEvents.AddRoundEventChan(r, sendResults, + time.Duration(timeoutMS)*time.Millisecond, states.COMPLETED, + states.FAILED) + } + + go func() { + success, _, numTmeout := utility.TrackResults(sendResults, len(sr.rl.list)) + if !success { + mdc.EventCallback(sr.mid[:], false, numTmeout > 0) + } else { + mdc.EventCallback(sr.mid[:], true, false) + } + }() + + return newRoundListUnregister(sr.rl.list, reventObjs, roundEvents), nil +} + // Returns a user object from which all information about the current user // can be gleaned -func (c *Client) GetUser() User { +func (c *Client) GetUser() *User { u := c.api.GetUser() - return &u + return &User{u: &u} } /* diff --git a/bindings/contact.go b/bindings/contact.go index 0c96fc41685a56257544a3cd107986fb3357295e..012eada71c84fc1a196cfc95acb24268b6a2f8f9 100644 --- a/bindings/contact.go +++ b/bindings/contact.go @@ -1,7 +1,6 @@ package bindings import ( - "encoding/json" "errors" "gitlab.com/elixxir/client/interfaces/contact" ) @@ -19,6 +18,7 @@ func (f *Fact) Type() int { return int(f.f.T) } + /* contact object*/ type Contact struct { c *contact.Contact @@ -44,6 +44,11 @@ func (c *Contact) GetFactList() *FactList { return &FactList{c: c.c} } +func (c *Contact) Marshal() ([]byte, error) { + return c.c.Marshal() +} + +/* FactList object*/ type FactList struct { c *contact.Contact } @@ -69,7 +74,5 @@ func (fl *FactList) Add(fact string, factType int) error { } func (fl *FactList) Marshal() ([]byte, error) { - return json.Marshal(&fl.c.Facts) + return []byte(fl.c.Facts.Stringify()), nil } - -func unmarshalFactList diff --git a/bindings/interfaces.go b/bindings/interfaces.go index ac882f2756a0e5879a8e4e4cfa239a4381bd885b..cee69db76dfe49479868a97e69da58796c2cb8ab 100644 --- a/bindings/interfaces.go +++ b/bindings/interfaces.go @@ -198,16 +198,4 @@ type Message interface { GetTimestampMS() int // Returns the message's timestamp in ns since unix epoc GetTimestampNano() int -} - -type User interface { - GetID() []byte - GetSalt() []byte - GetRSAPrivateKeyPem() []byte - GetRSAPublicKeyPem() []byte - //IsPrecanned() int - GetCmixDhPrivateKey() []byte - GetCmixDhPublicKey() []byte - GetE2EDhPrivateKey() []byte - GetE2EDhPublicKey() []byte } \ No newline at end of file diff --git a/bindings/list.go b/bindings/list.go index f47c4ea01b1aa6c4cb2e992a13fc74a2a02a6c02..0edfb41be5402cba75e7123d1445b159bfa399ba 100644 --- a/bindings/list.go +++ b/bindings/list.go @@ -28,25 +28,17 @@ func (il *IntList) Get(i int) (int, error) { return il.lst[i], nil } -type roundList struct { +type RoundList struct { list []id.Round } -// RoundList contains a list of contacts -type RoundList interface { - // Len returns the number of contacts in the list - Len() int - // Get returns the round ID at index i - Get(i int) (int, error) -} - // Gets the number of round IDs stored -func (rl *roundList) Len() int { +func (rl *RoundList) Len() int { return len(rl.list) } // Gets a stored round ID at the given index -func (rl *roundList) Get(i int) (int, error) { +func (rl *RoundList) Get(i int) (int, error) { if i < 0 || i > len(rl.list) { return -1, errors.New("round ID cannot be under 0 or over" + " list len") diff --git a/bindings/send.go b/bindings/send.go index 9da5afb93bb5afa521b8cd3c9cdbd22909d982c2..a554017877b666eab5b9126a700c516b5852a7af 100644 --- a/bindings/send.go +++ b/bindings/send.go @@ -1,6 +1,7 @@ package bindings import ( + "encoding/json" "errors" "fmt" "gitlab.com/elixxir/client/interfaces/message" @@ -25,19 +26,22 @@ import ( func (c *Client) SendCmix(recipient, contents []byte) (int, error) { u, err := id.Unmarshal(recipient) if err != nil { - return -1, err + return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v", + err)) } msg, err := c.api.NewCMIXMessage(u, contents) if err != nil { - return -1, err + return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v", + err)) } rid, err := c.api.SendCMIX(msg, params.GetDefaultCMIX()) if err != nil { - return -1, err + return -1, errors.New(fmt.Sprintf("Failed to sendCmix: %+v", + err)) } - return int(rid), err + return int(rid), nil } // SendUnsafe sends an unencrypted payload to the provided recipient @@ -49,10 +53,10 @@ func (c *Client) SendCmix(recipient, contents []byte) (int, error) { // Message Types can be found in client/interfaces/message/type.go // Make sure to not conflict with ANY default message types with custom types func (c *Client) SendUnsafe(recipient, payload []byte, - messageType int) (RoundList, error) { + messageType int) (*RoundList, error) { u, err := id.Unmarshal(recipient) if err != nil { - return nil, errors.New(fmt.Sprintf("Failed to sendUnsafew: %+v", + return nil, errors.New(fmt.Sprintf("Failed to sendUnsafe: %+v", err)) } @@ -64,11 +68,11 @@ func (c *Client) SendUnsafe(recipient, payload []byte, rids, err := c.api.SendUnsafe(m, params.GetDefaultUnsafe()) if err != nil { - return nil, errors.New(fmt.Sprintf("Failed to sendUnsafew: %+v", + return nil, errors.New(fmt.Sprintf("Failed to sendUnsafe: %+v", err)) } - return &roundList{list: rids}, nil + return &RoundList{list: rids}, nil } @@ -78,11 +82,10 @@ func (c *Client) SendUnsafe(recipient, payload []byte, // // Message Types can be found in client/interfaces/message/type.go // Make sure to not conflict with ANY default message types -func (c *Client) SendE2E(recipient, payload []byte, - messageType int) (*SendReport, error) { +func (c *Client) SendE2E(recipient, payload []byte, messageType int) (*SendReport, error) { u, err := id.Unmarshal(recipient) if err != nil { - return nil, err + return nil, errors.New(fmt.Sprintf("Failed SendE2E: %+v", err)) } m := message.Send{ @@ -93,26 +96,31 @@ func (c *Client) SendE2E(recipient, payload []byte, rids, mid, err := c.api.SendE2E(m, params.GetDefaultE2E()) if err != nil { - return nil, err + return nil, errors.New(fmt.Sprintf("Failed SendE2E: %+v", err)) } sr := SendReport{ - rl: &roundList{list: rids}, + rl: &RoundList{list: rids}, mid: mid, } return &sr, nil } +// the send report is the mechanisim by which sendE2E returns a single type SendReport struct { - rl RoundList + rl *RoundList mid e2e.MessageID } -func (sr *SendReport) GetRoundList() RoundList { +func (sr *SendReport) GetRoundList() *RoundList { return sr.rl } func (sr *SendReport) GetMessageID() []byte { return sr.mid[:] +} + +func (sr *SendReport) Marshal() ([]byte, error) { + return json.Marshal(sr) } \ No newline at end of file diff --git a/bindings/user.go b/bindings/user.go new file mode 100644 index 0000000000000000000000000000000000000000..e006f0c1e20d7f0a6055cd0d5612ee57e719a3a8 --- /dev/null +++ b/bindings/user.go @@ -0,0 +1,51 @@ +package bindings + +import ( + "gitlab.com/elixxir/client/interfaces/user" + "gitlab.com/xx_network/crypto/signature/rsa" +) + +type User struct { + u *user.User +} + +func (u *User) GetID() []byte { + return u.u.ID.Marshal() +} + +func (u *User) GetSalt() []byte { + return u.u.Salt +} + +func (u *User) GetRSAPrivateKeyPem() []byte { + return rsa.CreatePrivateKeyPem(u.u.RSA) +} + +func (u *User) GetRSAPublicKeyPem() []byte { + return rsa.CreatePublicKeyPem(u.u.RSA.GetPublic()) +} + +func (u *User) IsPrecanned() bool { + return u.u.Precanned +} + +func (u *User) GetCmixDhPrivateKey() []byte { + return u.u.CmixDhPrivateKey.Bytes() +} + +func (u *User) GetCmixDhPublicKey() []byte { + return u.u.CmixDhPublicKey.Bytes() +} + +func (u *User) GetE2EDhPrivateKey() []byte { + return u.u.E2eDhPrivateKey.Bytes() +} + +func (u *User) GetE2EDhPublicKey() []byte { + return u.u.E2eDhPublicKey.Bytes() +} + +func (u *User) GetContact() *Contact { + c := u.u.GetContact() + return &Contact{c: &c} +} diff --git a/interfaces/bind/contact.go b/interfaces/bind/contact.go deleted file mode 100644 index e02edc37e4eb25e5dc8990ef25db13931e0c5742..0000000000000000000000000000000000000000 --- a/interfaces/bind/contact.go +++ /dev/null @@ -1,20 +0,0 @@ -package bind - -type Contact interface { - GetID() []byte - GetDHPublicKey() []byte - GetOwnershipProof() []byte - GetFactList() FactList - Marshal() ([]byte, error) -} - -type FactList interface { - Num() int - Get(int) Fact - Add(string, int) error -} - -type Fact interface { - Get() string - Type() int -} diff --git a/interfaces/contact/contact.go b/interfaces/contact/contact.go index 1d6d84b304a80a1733ddb37857ec67dd4d71581b..2579f7a0501c1e6633c81fe2a8f147b6ab73b024 100644 --- a/interfaces/contact/contact.go +++ b/interfaces/contact/contact.go @@ -3,11 +3,8 @@ package contact import ( "encoding/json" "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces/bind" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/primitives/id" - "strings" - jww "github.com/spf13/jwalterweatherman" ) const factDelimiter = "," @@ -21,45 +18,13 @@ type Contact struct { ID *id.ID DhPubKey *cyclic.Int OwnershipProof []byte - Facts []Fact + Facts FactList } -// GetID returns the user ID for this user. -func (c Contact) GetID() []byte { - return c.ID.Bytes() -} - -// GetDHPublicKey returns the public key associated with the Contact. -func (c Contact) GetDHPublicKey() []byte { - return c.DhPubKey.Bytes() -} - -// GetDHPublicKey returns hash of a DH proof of key ownership. -func (c Contact) GetOwnershipProof() []byte { - return c.OwnershipProof -} - -// Returns a fact list for adding and getting facts to and from the contact -func (c Contact) GetFactList() bind.FactList { - return factList{source: &c} -} - -// json marshals the contact func (c Contact) Marshal() ([]byte, error) { return json.Marshal(&c) } -// converts facts to a delineated string with an ending character for transfer -// over the network -func (c Contact) StringifyFacts() string { - stringList := make([]string, len(c.Facts)) - for index, f := range c.Facts { - stringList[index] = f.Stringify() - } - - return strings.Join(stringList, factDelimiter) + factBreak -} - func Unmarshal(b []byte) (Contact, error) { c := Contact{} err := json.Unmarshal(b, &c) @@ -73,27 +38,4 @@ func Unmarshal(b []byte) (Contact, error) { } } return c, nil -} - -// splits the "facts" portion of the payload from the rest and returns them as -// facts -func UnstringifyFacts(s string) ([]Fact, string, error) { - parts := strings.SplitN(s, factBreak, 1) - if len(parts) != 2 { - return nil, "", errors.New("Invalid fact string passed") - } - factStrings := strings.Split(parts[0], factDelimiter) - - var factList []Fact - for _, fString := range factStrings { - fact, err := UnstringifyFact(fString) - if err != nil { - jww.WARN.Printf("Fact failed to unstringify, dropped: %s", - err) - } else { - factList = append(factList, fact) - } - - } - return factList, parts[1], nil -} +} \ No newline at end of file diff --git a/interfaces/contact/fact.go b/interfaces/contact/fact.go index 298b80b2ac68036374feb33a0b65e192a62574f4..bc838160dc33f6952d9b21ab6de8af2fb5c03cad 100644 --- a/interfaces/contact/fact.go +++ b/interfaces/contact/fact.go @@ -13,14 +13,6 @@ func NewFact(ft FactType, fact string) (Fact, error) { }, nil } -func (f Fact) Get() string { - return f.Fact -} - -func (f Fact) Type() int { - return int(f.T) -} - // marshal is for transmission for UDB, not a part of the fact interface func (f Fact) Stringify() string { return f.T.Stringify() + f.Fact diff --git a/interfaces/contact/factList.go b/interfaces/contact/factList.go index 6df341c1f96ad637d10303f6835a2e698a3b3464..7db95d0c51eb2ed6a5b46fdef3aba85b9f1d7ede 100644 --- a/interfaces/contact/factList.go +++ b/interfaces/contact/factList.go @@ -2,31 +2,40 @@ package contact import ( "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces/bind" + "strings" + jww "github.com/spf13/jwalterweatherman" ) -type factList struct { - source *Contact -} +type FactList []Fact -func (fl factList) Num() int { - return len(fl.source.Facts) -} +func (fl FactList) Stringify() string { + stringList := make([]string, len(fl)) + for index, f := range fl { + stringList[index] = f.Stringify() + } -func (fl factList) Get(i int) bind.Fact { - return fl.source.Facts[i] + return strings.Join(stringList, factDelimiter) + factBreak } -func (fl factList) Add(fact string, factType int) error { - ft := FactType(factType) - if !ft.IsValid() { - return errors.New("Invalid fact type") - } - f, err := NewFact(ft, fact) - if err != nil { - return err +// unstrignifys facts followed by a facts break and with arbatrary data +// atttached at the end +func UnstringifyFactList(s string) ([]Fact, string, error) { + parts := strings.SplitN(s, factBreak, 1) + if len(parts) != 2 { + return nil, "", errors.New("Invalid fact string passed") } + factStrings := strings.Split(parts[0], factDelimiter) - fl.source.Facts = append(fl.source.Facts, f) - return nil -} + var factList []Fact + for _, fString := range factStrings { + fact, err := UnstringifyFact(fString) + if err != nil { + jww.WARN.Printf("Fact failed to unstringify, dropped: %s", + err) + } else { + factList = append(factList, fact) + } + + } + return factList, parts[1], nil +} \ No newline at end of file diff --git a/interfaces/user/user.go b/interfaces/user/user.go index c5d2018567f68ad795c053fdac554f3411563ec1..a4fdb7d86e6e6f82ed4b5572bf70d7f379554836 100644 --- a/interfaces/user/user.go +++ b/interfaces/user/user.go @@ -1,7 +1,6 @@ package user import ( - "gitlab.com/elixxir/client/interfaces/bind" "gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/crypto/signature/rsa" @@ -24,46 +23,10 @@ type User struct { E2eDhPublicKey *cyclic.Int } -func (u *User) GetID() []byte { - return u.ID.Marshal() -} - -func (u *User) GetSalt() []byte { - return u.Salt -} - -func (u *User) GetRSAPrivateKeyPem() []byte { - return rsa.CreatePrivateKeyPem(u.RSA) -} - -func (u *User) GetRSAPublicKeyPem() []byte { - return rsa.CreatePublicKeyPem(u.RSA.GetPublic()) -} - -func (u *User) IsPrecanned() bool { - return u.Precanned -} - -func (u *User) GetCmixDhPrivateKey() []byte { - return u.CmixDhPrivateKey.Bytes() -} - -func (u *User) GetCmixDhPublicKey() []byte { - return u.CmixDhPublicKey.Bytes() -} - -func (u *User) GetE2EDhPrivateKey() []byte { - return u.E2eDhPrivateKey.Bytes() -} - -func (u *User) GetE2EDhPublicKey() []byte { - return u.E2eDhPublicKey.Bytes() -} - -func (u *User) GetContact() bind.Contact { +func (u *User) GetContact() contact.Contact { return contact.Contact{ ID: u.ID.DeepCopy(), DhPubKey: u.E2eDhPublicKey, Facts: make([]contact.Fact, 0), } -} +} \ No newline at end of file