Compute emojiHash on-the-fly

This commit is contained in:
Vitaliy Vlasov 2023-03-06 10:51:09 +02:00
parent 8a296407f3
commit 27a76f43ba
9 changed files with 99 additions and 51 deletions

View File

@ -1 +1 @@
0.136.2 0.136.3

View File

@ -6,7 +6,7 @@ import (
"encoding/json" "encoding/json"
"time" "time"
"github.com/status-im/status-go/api/multiformat" accountJson "github.com/status-im/status-go/account/json"
"github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/extkeys" "github.com/status-im/status-go/extkeys"
@ -69,20 +69,11 @@ type AccountInfo struct {
func (a AccountInfo) MarshalJSON() ([]byte, error) { func (a AccountInfo) MarshalJSON() ([]byte, error) {
type Alias AccountInfo type Alias AccountInfo
item := struct { ext, err := accountJson.ExtendStructWithPubKeyData(a.PublicKey, Alias(a))
Alias
CompressedKey string `json:"compressedKey"`
}{
Alias: (Alias)(a),
}
compressedKey, err := multiformat.SerializeLegacyKey(item.PublicKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
item.CompressedKey = compressedKey return json.Marshal(ext)
return json.Marshal(item)
} }
// IdentifiedAccountInfo contains AccountInfo and the ID of an account. // IdentifiedAccountInfo contains AccountInfo and the ID of an account.

58
account/json/utils.go Normal file
View File

@ -0,0 +1,58 @@
package json
import (
"reflect"
"github.com/status-im/status-go/api/multiformat"
"github.com/status-im/status-go/protocol/identity/emojihash"
)
type PublicKeyData struct {
CompressedKey string `json:"compressedKey"`
EmojiHash []string `json:"emojiHash"`
}
func getPubKeyData(publicKey string) (*PublicKeyData, error) {
compressedKey, err := multiformat.SerializeLegacyKey(publicKey)
if err != nil {
return nil, err
}
emojiHash, err := emojihash.GenerateFor(publicKey)
if err != nil {
return nil, err
}
return &PublicKeyData{compressedKey, emojiHash}, nil
}
func ExtendStructWithPubKeyData(publicKey string, item any) (any, error) {
pkd, err := getPubKeyData(publicKey)
if err != nil {
return nil, err
}
// Create a struct with 2 embedded substruct fields in order to circumvent
// "embedded field type cannot be a (pointer to a) type parameter"
// compiler error that arises if we were to use a generic function instead
typ := reflect.StructOf([]reflect.StructField{
{
Name: "Item",
Anonymous: true,
Type: reflect.TypeOf(item),
},
{
Name: "Pkd",
Anonymous: true,
Type: reflect.TypeOf(pkd),
},
})
v := reflect.New(typ).Elem()
v.Field(0).Set(reflect.ValueOf(item))
v.Field(1).Set(reflect.ValueOf(pkd))
s := v.Addr().Interface()
return s, nil
}

View File

@ -52,7 +52,8 @@ func TestJSONEncoding(t *testing.T) {
encoded, err := json.Marshal(settings) encoded, err := json.Marshal(settings)
require.NoError(t, err) require.NoError(t, err)
require.True(t, strings.Contains(string(encoded), "\"compressed-key\":\"zQ3shudJrBctPznsRLvbsCtvZFTdi3b34uzYDuqE9Wq9m9T1C\"")) require.True(t, strings.Contains(string(encoded), "\"compressedKey\":\"zQ3shudJrBctPznsRLvbsCtvZFTdi3b34uzYDuqE9Wq9m9T1C\""))
require.True(t, strings.Contains(string(encoded), "\"emojiHash\""))
} }
// TestGetFieldFromProtobufType checks if all the protobuf.SyncSetting_Type_value are assigned to a SettingField // TestGetFieldFromProtobufType checks if all the protobuf.SyncSetting_Type_value are assigned to a SettingField

View File

@ -3,7 +3,7 @@ package settings
import ( import (
"encoding/json" "encoding/json"
"github.com/status-im/status-go/api/multiformat" accountJson "github.com/status-im/status-go/account/json"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/protobuf"
@ -190,19 +190,13 @@ type Settings struct {
} }
func (s Settings) MarshalJSON() ([]byte, error) { func (s Settings) MarshalJSON() ([]byte, error) {
// We need this typedef in order to overcome stack overflow
// when marshaling JSON
type Alias Settings type Alias Settings
item := struct {
Alias
CompressedKey string `json:"compressed-key"`
}{
Alias: (Alias)(s),
}
compressedKey, err := multiformat.SerializeLegacyKey(item.PublicKey) ext, err := accountJson.ExtendStructWithPubKeyData(s.PublicKey, Alias(s))
if err != nil { if err != nil {
return nil, err return nil, err
} }
item.CompressedKey = compressedKey return json.Marshal(ext)
return json.Marshal(item)
} }

View File

@ -18,7 +18,7 @@ import (
"github.com/status-im/markdown" "github.com/status-im/markdown"
"github.com/status-im/markdown/ast" "github.com/status-im/markdown/ast"
"github.com/status-im/status-go/api/multiformat" accountJson "github.com/status-im/status-go/account/json"
"github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/images" "github.com/status-im/status-go/images"
"github.com/status-im/status-go/protocol/audio" "github.com/status-im/status-go/protocol/audio"
@ -222,11 +222,11 @@ func (m *Message) MarshalJSON() ([]byte, error) {
Pack int32 `json:"pack"` Pack int32 `json:"pack"`
URL string `json:"url"` URL string `json:"url"`
} }
item := struct {
type MessageStructType struct {
ID string `json:"id"` ID string `json:"id"`
WhisperTimestamp uint64 `json:"whisperTimestamp"` WhisperTimestamp uint64 `json:"whisperTimestamp"`
From string `json:"from"` From string `json:"from"`
CompressedKey string `json:"compressedKey"`
Alias string `json:"alias"` Alias string `json:"alias"`
Identicon string `json:"identicon"` Identicon string `json:"identicon"`
Seen bool `json:"seen"` Seen bool `json:"seen"`
@ -268,7 +268,8 @@ func (m *Message) MarshalJSON() ([]byte, error) {
ContactRequestState ContactRequestState `json:"contactRequestState,omitempty"` ContactRequestState ContactRequestState `json:"contactRequestState,omitempty"`
ContactVerificationState ContactVerificationState `json:"contactVerificationState,omitempty"` ContactVerificationState ContactVerificationState `json:"contactVerificationState,omitempty"`
DiscordMessage *protobuf.DiscordMessage `json:"discordMessage,omitempty"` DiscordMessage *protobuf.DiscordMessage `json:"discordMessage,omitempty"`
}{ }
item := MessageStructType{
ID: m.ID, ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp, WhisperTimestamp: m.WhisperTimestamp,
From: m.From, From: m.From,
@ -308,13 +309,6 @@ func (m *Message) MarshalJSON() ([]byte, error) {
ContactRequestState: m.ContactRequestState, ContactRequestState: m.ContactRequestState,
ContactVerificationState: m.ContactVerificationState, ContactVerificationState: m.ContactVerificationState,
} }
if item.From != "" {
compressedKey, err := multiformat.SerializeLegacyKey(item.From)
if err != nil {
return nil, err
}
item.CompressedKey = compressedKey
}
if sticker := m.GetSticker(); sticker != nil { if sticker := m.GetSticker(); sticker != nil {
item.Sticker = &StickerAlias{ item.Sticker = &StickerAlias{
@ -337,6 +331,14 @@ func (m *Message) MarshalJSON() ([]byte, error) {
if discordMessage := m.GetDiscordMessage(); discordMessage != nil { if discordMessage := m.GetDiscordMessage(); discordMessage != nil {
item.DiscordMessage = discordMessage item.DiscordMessage = discordMessage
} }
if item.From != "" {
ext, err := accountJson.ExtendStructWithPubKeyData(item.From, item)
if err != nil {
return nil, err
}
return json.Marshal(ext)
}
return json.Marshal(item) return json.Marshal(item)
} }

View File

@ -3,6 +3,7 @@ package common
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"strings" "strings"
"testing" "testing"
@ -140,5 +141,8 @@ func TestMarshalMessageJSON(t *testing.T) {
encodedMessage, err := json.Marshal(message) encodedMessage, err := json.Marshal(message)
require.NoError(t, err) require.NoError(t, err)
log.Println("### encodedMessage", string(encodedMessage))
require.True(t, strings.Contains(string(encodedMessage), "compressedKey\":\"zQ")) require.True(t, strings.Contains(string(encodedMessage), "compressedKey\":\"zQ"))
require.True(t, strings.Contains(string(encodedMessage), "emojiHash"))
} }

View File

@ -4,7 +4,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding/json" "encoding/json"
"github.com/status-im/status-go/api/multiformat" accountJson "github.com/status-im/status-go/account/json"
"github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/images" "github.com/status-im/status-go/images"
@ -401,26 +401,20 @@ func (c *Contact) ProcessSyncContactRequestState(remoteState ContactRequestState
func (c *Contact) MarshalJSON() ([]byte, error) { func (c *Contact) MarshalJSON() ([]byte, error) {
type Alias Contact type Alias Contact
item := struct { type ContactType struct {
*Alias *Alias
CompressedKey string `json:"compressedKey"`
Added bool `json:"added"` Added bool `json:"added"`
ContactRequestState ContactRequestState `json:"contactRequestState"` ContactRequestState ContactRequestState `json:"contactRequestState"`
HasAddedUs bool `json:"hasAddedUs"` HasAddedUs bool `json:"hasAddedUs"`
Mutual bool `json:"mutual"` Mutual bool `json:"mutual"`
Active bool `json:"active"` Active bool `json:"active"`
PrimaryName string `json:"primaryName"` PrimaryName string `json:"primaryName"`
SecondaryName string `json:"secondaryName,omitempty"` SecondaryName string `json:"secondaryName,omitempty"`
}{
Alias: (*Alias)(c),
} }
compressedKey, err := multiformat.SerializeLegacyKey(item.ID) item := ContactType{
if err != nil { Alias: (*Alias)(c),
return nil, err
} }
item.CompressedKey = compressedKey
item.Added = c.added() item.Added = c.added()
item.HasAddedUs = c.hasAddedUs() item.HasAddedUs = c.hasAddedUs()
@ -428,7 +422,6 @@ func (c *Contact) MarshalJSON() ([]byte, error) {
item.Active = c.active() item.Active = c.active()
item.PrimaryName = c.PrimaryName() item.PrimaryName = c.PrimaryName()
item.SecondaryName = c.SecondaryName() item.SecondaryName = c.SecondaryName()
item.Active = c.active()
if c.mutual() { if c.mutual() {
item.ContactRequestState = ContactRequestStateMutual item.ContactRequestState = ContactRequestStateMutual
@ -437,8 +430,12 @@ func (c *Contact) MarshalJSON() ([]byte, error) {
} else if c.hasAddedUs() { } else if c.hasAddedUs() {
item.ContactRequestState = ContactRequestStateReceived item.ContactRequestState = ContactRequestStateReceived
} }
ext, err := accountJson.ExtendStructWithPubKeyData(item.ID, item)
if err != nil {
return nil, err
}
return json.Marshal(item) return json.Marshal(ext)
} }
// ContactRequestPropagatedStateReceived handles the propagation of state from // ContactRequestPropagatedStateReceived handles the propagation of state from

View File

@ -570,6 +570,7 @@ func TestMarshalContactJSON(t *testing.T) {
require.True(t, strings.Contains(string(encodedContact), "active\":true")) require.True(t, strings.Contains(string(encodedContact), "active\":true"))
require.True(t, strings.Contains(string(encodedContact), "primaryName\":\"primary-name")) require.True(t, strings.Contains(string(encodedContact), "primaryName\":\"primary-name"))
require.True(t, strings.Contains(string(encodedContact), "secondaryName\":\"secondary-name")) require.True(t, strings.Contains(string(encodedContact), "secondaryName\":\"secondary-name"))
require.True(t, strings.Contains(string(encodedContact), "emojiHash"))
} }
func TestContactContactRequestPropagatedStateReceivedOutOfDateLocalStateOnTheirSide(t *testing.T) { func TestContactContactRequestPropagatedStateReceivedOutOfDateLocalStateOnTheirSide(t *testing.T) {