chore: synchronization improvements applied to keycards

This is the second step of improvements over keypairs/keycards/accounts.
- `SyncKeycardAction` protobuf removed
- `SyncKeypair` protobuf is used for syncing keycards state as well as for all
keycards related changes
- `last_update_clock` column removed from `keypairs` table cause as well as
for accounts, any keycard related change is actually a change made on a related
keypair, thus a keypair's clock keeps the clock of the last change
- `position` column added to `keypairs` table, needed to display keycards in
the same order accross devices
This commit is contained in:
Sale Djenic 2023-07-05 14:41:58 +02:00 committed by saledjenic
parent ca5075c149
commit 7063ad11aa
23 changed files with 1463 additions and 2256 deletions

View File

@ -1 +1 @@
0.161.4 0.161.5

View File

@ -999,7 +999,7 @@ func TestConvertAccount(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Check that there is no registered keycards // Check that there is no registered keycards
keycards, err := db.GetKeycardByKeyUID(genAccInfo.KeyUID) keycards, err := db.GetKeycardsWithSameKeyUID(genAccInfo.KeyUID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, len(keycards)) require.Equal(t, 0, len(keycards))
@ -1026,7 +1026,7 @@ func TestConvertAccount(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Check that there is a registered keycard // Check that there is a registered keycard
keycards, err = db1.GetKeycardByKeyUID(genAccInfo.KeyUID) keycards, err = db1.GetKeycardsWithSameKeyUID(genAccInfo.KeyUID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(keycards)) require.Equal(t, 1, len(keycards))
@ -1059,7 +1059,7 @@ func TestConvertAccount(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Check that there is no registered keycards // Check that there is no registered keycards
keycards, err = db2.GetKeycardByKeyUID(genAccInfo.KeyUID) keycards, err = db2.GetKeycardsWithSameKeyUID(genAccInfo.KeyUID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, len(keycards)) require.Equal(t, 0, len(keycards))

View File

@ -923,24 +923,26 @@ func (b *GethStatusBackend) ConvertToKeycardAccount(account multiaccounts.Accoun
return err return err
} }
position, err := accountDB.GetPositionForNextNewKeycard()
if err != nil {
return err
}
kc := accounts.Keycard{ kc := accounts.Keycard{
KeycardUID: keycardUID, KeycardUID: keycardUID,
KeycardName: displayName, KeycardName: displayName,
KeycardLocked: false, KeycardLocked: false,
KeyUID: account.KeyUID, KeyUID: account.KeyUID,
LastUpdateClock: uint64(time.Now().Unix()), Position: position,
} }
for _, acc := range keypair.Accounts { for _, acc := range keypair.Accounts {
kc.AccountsAddresses = append(kc.AccountsAddresses, acc.Address) kc.AccountsAddresses = append(kc.AccountsAddresses, acc.Address)
} }
addedKc, _, err := accountDB.AddKeycardOrAddAccountsIfKeycardIsAdded(kc) err = accountDB.SaveOrUpdateKeycard(kc, uint64(time.Now().Unix()), true)
if err != nil { if err != nil {
return err return err
} }
if !addedKc {
return errors.New("couldn't register a keycard to keycards table")
}
} }
masterAddress, err := accountDB.GetMasterAddress() masterAddress, err := accountDB.GetMasterAddress()
@ -1191,7 +1193,7 @@ func (b *GethStatusBackend) ConvertToRegularAccount(mnemonic string, currPasswor
return err return err
} }
err = db.DeleteAllKeycardsWithKeyUID(accountInfo.KeyUID) err = db.DeleteAllKeycardsWithKeyUID(accountInfo.KeyUID, uint64(time.Now().Unix()))
if err != nil { if err != nil {
return err return err
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
ALTER TABLE keycards RENAME TO keycards_old;
ALTER TABLE keycards_accounts RENAME TO keycards_accounts_old;
CREATE TABLE IF NOT EXISTS keycards (
keycard_uid VARCHAR NOT NULL PRIMARY KEY,
keycard_name VARCHAR NOT NULL,
keycard_locked BOOLEAN DEFAULT FALSE,
key_uid VARCHAR NOT NULL,
position INT NOT NULL DEFAULT 0,
FOREIGN KEY(key_uid) REFERENCES keypairs(key_uid)
ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS keycards_accounts (
keycard_uid VARCHAR NOT NULL,
account_address VARCHAR NOT NULL,
PRIMARY KEY (keycard_uid, account_address),
FOREIGN KEY(keycard_uid) REFERENCES keycards(keycard_uid)
ON UPDATE CASCADE
ON DELETE CASCADE
);
INSERT INTO keycards
SELECT keycard_uid, keycard_name, keycard_locked, key_uid, last_update_clock
FROM keycards_old
ORDER BY last_update_clock;
INSERT INTO keycards_accounts
SELECT keycard_uid, account_address
FROM keycards_accounts_old;
UPDATE keycards SET position = rowid - 1;
DROP TABLE keycards_accounts_old;
DROP TABLE keycards_old;

View File

@ -220,7 +220,6 @@ func (a *Keypair) CopyKeypair() *Keypair {
KeycardLocked: kc.KeycardLocked, KeycardLocked: kc.KeycardLocked,
AccountsAddresses: kc.AccountsAddresses, AccountsAddresses: kc.AccountsAddresses,
KeyUID: kc.KeyUID, KeyUID: kc.KeyUID,
LastUpdateClock: kc.LastUpdateClock,
} }
} }
@ -242,7 +241,6 @@ type Database struct {
*settings.Database *settings.Database
*notificationssettings.NotificationsSettings *notificationssettings.NotificationsSettings
*sociallinkssettings.SocialLinksSettings *sociallinkssettings.SocialLinksSettings
*Keycards
db *sql.DB db *sql.DB
} }
@ -254,9 +252,8 @@ func NewDB(db *sql.DB) (*Database, error) {
} }
sn := notificationssettings.NewNotificationsSettings(db) sn := notificationssettings.NewNotificationsSettings(db)
ssl := sociallinkssettings.NewSocialLinksSettings(db) ssl := sociallinkssettings.NewSocialLinksSettings(db)
kc := NewKeycards(db)
return &Database{sDB, sn, ssl, kc, db}, nil return &Database{sDB, sn, ssl, db}, nil
} }
// DB Gets db sql.DB // DB Gets db sql.DB
@ -486,7 +483,7 @@ func (db *Database) getKeypairs(tx *sql.Tx, keyUID string) ([]*Keypair, error) {
} }
for _, kp := range keypairs { for _, kp := range keypairs {
keycards, err := db.getAllRows(tx, true) keycards, err := db.getKeycards(tx, kp.KeyUID, "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -803,11 +800,6 @@ func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account, update
} }
keyUID = &acc.KeyUID keyUID = &acc.KeyUID
} }
var exists bool
err = tx.QueryRow("SELECT EXISTS (SELECT 1 FROM keypairs_accounts WHERE address = ?)", acc.Address).Scan(&exists)
if err != nil {
return err
}
_, err = tx.Exec(` _, err = tx.Exec(`
INSERT OR IGNORE INTO INSERT OR IGNORE INTO
@ -882,6 +874,7 @@ func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account, update
return nil return nil
} }
// Saves accounts, if an account already exists, it will be updated.
func (db *Database) SaveOrUpdateAccounts(accounts []*Account, updateKeypairClock bool) error { func (db *Database) SaveOrUpdateAccounts(accounts []*Account, updateKeypairClock bool) error {
if len(accounts) == 0 { if len(accounts) == 0 {
return errors.New("no provided accounts to save/update") return errors.New("no provided accounts to save/update")
@ -902,6 +895,10 @@ func (db *Database) SaveOrUpdateAccounts(accounts []*Account, updateKeypairClock
return err return err
} }
// Saves a keypair and its accounts, if a keypair with `key_uid` already exists, it will be updated,
// if any of its accounts exists it will be updated as well, otherwise it will be added.
// Since keypair type contains `Keycards` as well, they are excluded from the saving/updating this way regardless they
// are set or not.
func (db *Database) SaveOrUpdateKeypair(keypair *Keypair) error { func (db *Database) SaveOrUpdateKeypair(keypair *Keypair) error {
if keypair == nil { if keypair == nil {
return errDbPassedParameterIsNil return errDbPassedParameterIsNil
@ -1063,6 +1060,23 @@ func (db *Database) GetAddresses() (rst []types.Address, err error) {
return rst, nil return rst, nil
} }
func (db *Database) keypairExists(tx *sql.Tx, keyUID string) (exists bool, err error) {
query := `SELECT EXISTS (SELECT 1 FROM keypairs WHERE key_uid = ?)`
if tx == nil {
err = db.db.QueryRow(query, keyUID).Scan(&exists)
} else {
err = tx.QueryRow(query, keyUID).Scan(&exists)
}
return exists, err
}
// KeypairExists returns true if given address is stored in database.
func (db *Database) KeypairExists(keyUID string) (exists bool, err error) {
return db.keypairExists(nil, keyUID)
}
// AddressExists returns true if given address is stored in database. // AddressExists returns true if given address is stored in database.
func (db *Database) AddressExists(address types.Address) (exists bool, err error) { func (db *Database) AddressExists(address types.Address) (exists bool, err error) {
err = db.db.QueryRow("SELECT EXISTS (SELECT 1 FROM keypairs_accounts WHERE address = ?)", address).Scan(&exists) err = db.db.QueryRow("SELECT EXISTS (SELECT 1 FROM keypairs_accounts WHERE address = ?)", address).Scan(&exists)

View File

@ -10,7 +10,11 @@ import (
"github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/protobuf"
) )
var errKeycardDbTransactionIsNil = errors.New("keycard: database transaction is nil") var (
errKeycardDbTransactionIsNil = errors.New("keycard: database transaction is nil")
errCannotAddKeycardForUnknownKeypair = errors.New("keycard: cannot add keycard for an unknown keyapir")
ErrNoKeycardForPassedKeycardUID = errors.New("keycard: no keycard for the passed keycard uid")
)
type Keycard struct { type Keycard struct {
KeycardUID string `json:"keycard-uid"` KeycardUID string `json:"keycard-uid"`
@ -18,22 +22,16 @@ type Keycard struct {
KeycardLocked bool `json:"keycard-locked"` KeycardLocked bool `json:"keycard-locked"`
AccountsAddresses []types.Address `json:"accounts-addresses"` AccountsAddresses []types.Address `json:"accounts-addresses"`
KeyUID string `json:"key-uid"` KeyUID string `json:"key-uid"`
LastUpdateClock uint64 Position uint64
}
type KeycardAction struct {
Action string `json:"action"`
OldKeycardUID string `json:"old-keycard-uid,omitempty"`
Keycard *Keycard `json:"keycard"`
} }
func (kp *Keycard) ToSyncKeycard() *protobuf.SyncKeycard { func (kp *Keycard) ToSyncKeycard() *protobuf.SyncKeycard {
kc := &protobuf.SyncKeycard{ kc := &protobuf.SyncKeycard{
Uid: kp.KeycardUID, Uid: kp.KeycardUID,
Name: kp.KeycardName, Name: kp.KeycardName,
Locked: kp.KeycardLocked, Locked: kp.KeycardLocked,
KeyUid: kp.KeyUID, KeyUid: kp.KeyUID,
Clock: kp.LastUpdateClock, Position: kp.Position,
} }
for _, addr := range kp.AccountsAddresses { for _, addr := range kp.AccountsAddresses {
@ -48,30 +46,13 @@ func (kp *Keycard) FromSyncKeycard(kc *protobuf.SyncKeycard) {
kp.KeycardName = kc.Name kp.KeycardName = kc.Name
kp.KeycardLocked = kc.Locked kp.KeycardLocked = kc.Locked
kp.KeyUID = kc.KeyUid kp.KeyUID = kc.KeyUid
kp.LastUpdateClock = kc.Clock kp.Position = kc.Position
for _, addr := range kc.Addresses { for _, addr := range kc.Addresses {
kp.AccountsAddresses = append(kp.AccountsAddresses, types.BytesToAddress(addr)) kp.AccountsAddresses = append(kp.AccountsAddresses, types.BytesToAddress(addr))
} }
} }
func removeElementAtIndex[T any](s []T, index int) []T {
if index < 0 || index >= len(s) {
panic("keycard: index out of the range")
}
return append(s[:index], s[index+1:]...)
}
type Keycards struct {
db *sql.DB
}
func NewKeycards(db *sql.DB) *Keycards {
return &Keycards{
db: db,
}
}
func containsAddress(addresses []types.Address, address types.Address) bool { func containsAddress(addresses []types.Address, address types.Address) bool {
for _, addr := range addresses { for _, addr := range addresses {
if addr == address { if addr == address {
@ -81,29 +62,27 @@ func containsAddress(addresses []types.Address, address types.Address) bool {
return false return false
} }
func (kp *Keycards) processResult(rows *sql.Rows, groupByKeycard bool) ([]*Keycard, error) { func (db *Database) processResult(rows *sql.Rows) ([]*Keycard, error) {
keycards := []*Keycard{} keycards := []*Keycard{}
for rows.Next() { for rows.Next() {
keycard := &Keycard{} keycard := &Keycard{}
addr := types.Address{} var accAddress sql.NullString
err := rows.Scan(&keycard.KeycardUID, &keycard.KeycardName, &keycard.KeycardLocked, &addr, &keycard.KeyUID, err := rows.Scan(&keycard.KeycardUID, &keycard.KeycardName, &keycard.KeycardLocked, &accAddress, &keycard.KeyUID,
&keycard.LastUpdateClock) &keycard.Position)
if err != nil { if err != nil {
return nil, err return nil, err
} }
addr := types.Address{}
if accAddress.Valid {
addr = types.BytesToAddress([]byte(accAddress.String))
}
foundAtIndex := -1 foundAtIndex := -1
for i := range keycards { for i := range keycards {
if groupByKeycard { if keycards[i].KeycardUID == keycard.KeycardUID {
if keycards[i].KeycardUID == keycard.KeycardUID { foundAtIndex = i
foundAtIndex = i break
break
}
} else {
if keycards[i].KeyUID == keycard.KeyUID {
foundAtIndex = i
break
}
} }
} }
if foundAtIndex == -1 { if foundAtIndex == -1 {
@ -120,170 +99,113 @@ func (kp *Keycards) processResult(rows *sql.Rows, groupByKeycard bool) ([]*Keyca
return keycards, nil return keycards, nil
} }
func (kp *Keycards) getAllRows(tx *sql.Tx, groupByKeycard bool) ([]*Keycard, error) { func (db *Database) getKeycards(tx *sql.Tx, keyUID string, keycardUID string) ([]*Keycard, error) {
query := `
SELECT
kc.keycard_uid,
kc.keycard_name,
kc.keycard_locked,
ka.account_address,
kc.key_uid,
kc.position
FROM
keycards AS kc
LEFT JOIN
keycards_accounts AS ka
ON
kc.keycard_uid = ka.keycard_uid
LEFT JOIN
keypairs_accounts AS kpa
ON
ka.account_address = kpa.address
%s
ORDER BY
kc.position, kpa.position`
var where string
var args []interface{}
if keyUID != "" {
where = "WHERE kc.key_uid = ?"
args = append(args, keyUID)
if keycardUID != "" {
where += " AND kc.keycard_uid = ?"
args = append(args, keycardUID)
}
} else if keycardUID != "" {
where = "WHERE kc.keycard_uid = ?"
args = append(args, keycardUID)
}
query = fmt.Sprintf(query, where)
var ( var (
rows *sql.Rows stmt *sql.Stmt
err error err error
) )
query := // nolint: gosec
`
SELECT
k.keycard_uid,
k.keycard_name,
k.keycard_locked,
ka.account_address,
k.key_uid,
k.last_update_clock
FROM
keycards AS k
LEFT JOIN
keycards_accounts AS ka
ON
k.keycard_uid = ka.keycard_uid
ORDER BY
key_uid`
if tx == nil { if tx == nil {
rows, err = kp.db.Query(query) stmt, err = db.db.Prepare(query)
if err != nil {
return nil, err
}
} else { } else {
stmt, err := tx.Prepare(query) stmt, err = tx.Prepare(query)
if err != nil {
return nil, err
}
defer stmt.Close()
rows, err = stmt.Query()
if err != nil {
return nil, err
}
} }
defer rows.Close()
return kp.processResult(rows, groupByKeycard)
}
func (kp *Keycards) GetAllKnownKeycards() ([]*Keycard, error) {
return kp.getAllRows(nil, true)
}
func (kp *Keycards) GetAllKnownKeycardsGroupedByKeyUID() ([]*Keycard, error) {
return kp.getAllRows(nil, false)
}
func (kp *Keycards) GetKeycardByKeyUID(keyUID string) ([]*Keycard, error) {
rows, err := kp.db.Query(`
SELECT
k.keycard_uid,
k.keycard_name,
k.keycard_locked,
ka.account_address,
k.key_uid,
k.last_update_clock
FROM
keycards AS k
LEFT JOIN
keycards_accounts AS ka
ON
k.keycard_uid = ka.keycard_uid
WHERE
k.key_uid = ?
ORDER BY
k.keycard_uid
`, keyUID)
if err != nil { if err != nil {
if err == sql.ErrNoRows {
return []*Keycard{}, nil
}
return nil, err return nil, err
} }
defer stmt.Close()
defer rows.Close() rows, err := stmt.Query(args...)
return kp.processResult(rows, false)
}
func (kp *Keycards) startTransactionAndCheckIfNeedToProceed(kcUID string, clock uint64) (tx *sql.Tx, proceed bool, err error) {
tx, err = kp.db.Begin()
if err != nil {
return nil, false, err
}
var dbLastUpdateClock uint64
err = tx.QueryRow(`SELECT last_update_clock FROM keycards WHERE keycard_uid = ?`, kcUID).Scan(&dbLastUpdateClock)
if err != nil {
return tx, err == sql.ErrNoRows, err
}
return tx, dbLastUpdateClock <= clock, nil
}
func (kp *Keycards) setLastUpdateClock(tx *sql.Tx, kcUID string, clock uint64) (err error) {
if tx == nil {
return errKeycardDbTransactionIsNil
}
_, err = tx.Exec(`
UPDATE
keycards
SET
last_update_clock = ?
WHERE
keycard_uid = ?`,
clock, kcUID)
return err
}
func (kp *Keycards) getAccountsForKeycard(tx *sql.Tx, kcUID string) ([]types.Address, error) {
var accountAddresses []types.Address
if tx == nil {
return accountAddresses, errKeycardDbTransactionIsNil
}
rows, err := tx.Query(`SELECT account_address FROM keycards_accounts WHERE keycard_uid = ?`, kcUID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
for rows.Next() { return db.processResult(rows)
var accAddress types.Address
err = rows.Scan(&accAddress)
if err != nil {
return nil, err
}
accountAddresses = append(accountAddresses, accAddress)
}
return accountAddresses, nil
} }
func (kp *Keycards) addAccounts(tx *sql.Tx, kcUID string, accountsAddresses []types.Address) (err error) { func (db *Database) getKeycardByKeycardUID(tx *sql.Tx, keycardUID string) (*Keycard, error) {
keycards, err := db.getKeycards(tx, "", keycardUID)
if err != nil {
return nil, err
}
if len(keycards) == 0 {
return nil, ErrNoKeycardForPassedKeycardUID
}
return keycards[0], nil
}
func (db *Database) GetAllKnownKeycards() ([]*Keycard, error) {
return db.getKeycards(nil, "", "")
}
func (db *Database) GetKeycardsWithSameKeyUID(keyUID string) ([]*Keycard, error) {
return db.getKeycards(nil, keyUID, "")
}
func (db *Database) GetKeycardByKeycardUID(keycardUID string) (*Keycard, error) {
return db.getKeycardByKeycardUID(nil, keycardUID)
}
func (db *Database) saveOrUpdateKeycardAccounts(tx *sql.Tx, kcUID string, accountsAddresses []types.Address) (err error) {
if tx == nil { if tx == nil {
return errKeycardDbTransactionIsNil return errKeycardDbTransactionIsNil
} }
insertKcAcc, err := tx.Prepare(`
INSERT INTO
keycards_accounts
(
keycard_uid,
account_address
)
VALUES
(?, ?);
`)
if err != nil {
return err
}
defer insertKcAcc.Close()
for i := range accountsAddresses { for i := range accountsAddresses {
addr := accountsAddresses[i] addr := accountsAddresses[i]
_, err = insertKcAcc.Exec(kcUID, addr) _, err = tx.Exec(`
INSERT OR IGNORE INTO
keycards_accounts
(
keycard_uid,
account_address
)
VALUES
(?, ?);
`, kcUID, addr)
if err != nil { if err != nil {
return err return err
} }
@ -292,7 +214,7 @@ func (kp *Keycards) addAccounts(tx *sql.Tx, kcUID string, accountsAddresses []ty
return nil return nil
} }
func (kp *Keycards) deleteKeycard(tx *sql.Tx, kcUID string) (err error) { func (db *Database) deleteKeycard(tx *sql.Tx, kcUID string) (err error) {
if tx == nil { if tx == nil {
return errKeycardDbTransactionIsNil return errKeycardDbTransactionIsNil
} }
@ -314,145 +236,102 @@ func (kp *Keycards) deleteKeycard(tx *sql.Tx, kcUID string) (err error) {
return err return err
} }
func (kp *Keycards) AddKeycardOrAddAccountsIfKeycardIsAdded(keycard Keycard) (addedKc bool, addedAccs bool, err error) { func (db *Database) deleteKeycardAccounts(tx *sql.Tx, kcUID string, accountAddresses []types.Address) (err error) {
tx, proceed, err := kp.startTransactionAndCheckIfNeedToProceed(keycard.KeycardUID, keycard.LastUpdateClock) if tx == nil {
defer func() { return errKeycardDbTransactionIsNil
if err == nil {
err = tx.Commit()
return
}
_ = tx.Rollback()
}()
if proceed {
// insert only if there is no such keycard, otherwise just add accounts
if err != nil && err == sql.ErrNoRows {
_, err = tx.Exec(`
INSERT INTO
keycards
(
keycard_uid,
keycard_name,
keycard_locked,
key_uid,
last_update_clock
)
VALUES
(?, ?, ?, ?, ?);`,
keycard.KeycardUID, keycard.KeycardName, keycard.KeycardLocked, keycard.KeyUID, keycard.LastUpdateClock)
if err != nil {
return false, false, err
}
err = kp.addAccounts(tx, keycard.KeycardUID, keycard.AccountsAddresses)
return err == nil, false, err
}
err = kp.setLastUpdateClock(tx, keycard.KeycardUID, keycard.LastUpdateClock)
if err != nil {
return false, false, err
}
err = kp.addAccounts(tx, keycard.KeycardUID, keycard.AccountsAddresses)
return false, err == nil, err
} }
return false, false, err inVector := strings.Repeat(",?", len(accountAddresses)-1)
} query := `
DELETE
FROM
keycards_accounts
WHERE
keycard_uid = ?
AND
account_address IN (?` + inVector + `)`
func (kp *Keycards) ApplyKeycardsForKeypairWithKeyUID(keyUID string, keycardsToSync []*Keycard) (err error) { delete, err := tx.Prepare(query)
tx, err := kp.db.Begin()
if err != nil { if err != nil {
return
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
_ = tx.Rollback()
}()
rows, err := tx.Query(`SELECT * FROM keycards WHERE key_uid = ?`, keyUID)
if err != nil && err != sql.ErrNoRows {
return err return err
} }
defer rows.Close() defer delete.Close()
var dbKeycards []*Keycard args := make([]interface{}, len(accountAddresses)+1)
for rows.Next() { args[0] = kcUID
keycard := &Keycard{} for i, addr := range accountAddresses {
err := rows.Scan(&keycard.KeycardUID, &keycard.KeycardName, &keycard.KeycardLocked, &keycard.KeyUID, args[i+1] = addr
&keycard.LastUpdateClock)
if err != nil {
return err
}
dbKeycards = append(dbKeycards, keycard)
} }
// apply those from `keycardsToSync` which are newer _, err = delete.Exec(args...)
for _, syncKc := range keycardsToSync {
foundAtIndex := -1 return err
for i := range dbKeycards { }
if dbKeycards[i].KeycardUID == syncKc.KeycardUID {
foundAtIndex = i func (db *Database) SaveOrUpdateKeycard(keycard Keycard, clock uint64, updateKeypairClock bool) error {
break tx, err := db.db.Begin()
} if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
} }
_ = tx.Rollback()
}()
if foundAtIndex > -1 { relatedKeypairExists, err := db.keypairExists(tx, keycard.KeyUID)
dbClock := dbKeycards[foundAtIndex].LastUpdateClock if err != nil {
dbKeycards = removeElementAtIndex(dbKeycards, foundAtIndex) return err
if dbClock > syncKc.LastUpdateClock {
continue
}
err = kp.deleteKeycard(tx, syncKc.KeycardUID)
if err != nil {
return err
}
}
_, err = tx.Exec(`
INSERT OR REPLACE INTO
keycards
(
keycard_uid,
keycard_name,
keycard_locked,
key_uid,
last_update_clock
)
VALUES
(?, ?, ?, ?, ?);`,
syncKc.KeycardUID, syncKc.KeycardName, syncKc.KeycardLocked, syncKc.KeyUID, syncKc.LastUpdateClock)
if err != nil {
return err
}
err = kp.addAccounts(tx, syncKc.KeycardUID, syncKc.AccountsAddresses)
if err != nil {
return err
}
} }
// remove those from the db if they are not in `keycardsToSync` if !relatedKeypairExists {
for _, dbKp := range dbKeycards { return errCannotAddKeycardForUnknownKeypair
err = kp.deleteKeycard(tx, dbKp.KeycardUID) }
if err != nil {
return err _, err = tx.Exec(`
} INSERT OR IGNORE INTO
keycards
(
keycard_uid,
keycard_name,
key_uid
)
VALUES
(?, ?, ?);
UPDATE
keycards
SET
keycard_name = ?,
keycard_locked = ?,
position = ?
WHERE
keycard_uid = ?;
`, keycard.KeycardUID, keycard.KeycardName, keycard.KeyUID,
keycard.KeycardName, keycard.KeycardLocked, keycard.Position, keycard.KeycardUID)
if err != nil {
return err
}
err = db.saveOrUpdateKeycardAccounts(tx, keycard.KeycardUID, keycard.AccountsAddresses)
if err != nil {
return err
}
if updateKeypairClock {
return db.updateKeypairClock(tx, keycard.KeyUID, clock)
} }
return nil return nil
} }
func (kp *Keycards) RemoveMigratedAccountsForKeycard(kcUID string, accountAddresses []types.Address, func (db *Database) execKeycardUpdateQuery(kcUID string, clock uint64, field string, value interface{}) (err error) {
clock uint64) (err error) { tx, err := db.db.Begin()
tx, proceed, err := kp.startTransactionAndCheckIfNeedToProceed(kcUID, clock) if err != nil {
return err
}
defer func() { defer func() {
if err == nil { if err == nil {
err = tx.Commit() err = tx.Commit()
@ -461,70 +340,41 @@ func (kp *Keycards) RemoveMigratedAccountsForKeycard(kcUID string, accountAddres
_ = tx.Rollback() _ = tx.Rollback()
}() }()
keycard, err := db.getKeycardByKeycardUID(tx, kcUID)
if err != nil { if err != nil {
return err return err
} }
if proceed { sql := fmt.Sprintf(`UPDATE keycards SET %s = ? WHERE keycard_uid = ?`, field) // nolint: gosec
err = kp.setLastUpdateClock(tx, kcUID, clock) _, err = tx.Exec(sql, value, kcUID)
if err != nil { if err != nil {
return err
}
dbAccountAddresses, err := kp.getAccountsForKeycard(tx, kcUID)
if err != nil {
return err
}
deleteKeycard := true
for _, dbAddr := range dbAccountAddresses {
found := false
for _, addr := range accountAddresses {
if dbAddr == addr {
found = true
}
}
if !found {
deleteKeycard = false
}
}
if deleteKeycard {
return kp.deleteKeycard(tx, kcUID)
}
inVector := strings.Repeat(",?", len(accountAddresses)-1)
query := `
DELETE
FROM
keycards_accounts
WHERE
keycard_uid = ?
AND
account_address IN (?` + inVector + `)
`
delete, err := tx.Prepare(query)
if err != nil {
return err
}
args := make([]interface{}, len(accountAddresses)+1)
args[0] = kcUID
for i, addr := range accountAddresses {
args[i+1] = addr
}
defer delete.Close()
_, err = delete.Exec(args...)
return err return err
} }
return err return db.updateKeypairClock(tx, keycard.KeyUID, clock)
} }
func (kp *Keycards) execUpdateQuery(kcUID string, clock uint64, field string, value interface{}) (err error) { func (db *Database) KeycardLocked(kcUID string, clock uint64) (err error) {
tx, proceed, err := kp.startTransactionAndCheckIfNeedToProceed(kcUID, clock) return db.execKeycardUpdateQuery(kcUID, clock, "keycard_locked", true)
}
func (db *Database) KeycardUnlocked(kcUID string, clock uint64) (err error) {
return db.execKeycardUpdateQuery(kcUID, clock, "keycard_locked", false)
}
func (db *Database) UpdateKeycardUID(oldKcUID string, newKcUID string, clock uint64) (err error) {
return db.execKeycardUpdateQuery(oldKcUID, clock, "keycard_uid", newKcUID)
}
func (db *Database) SetKeycardName(kcUID string, kpName string, clock uint64) (err error) {
return db.execKeycardUpdateQuery(kcUID, clock, "keycard_name", kpName)
}
func (db *Database) DeleteKeycardAccounts(kcUID string, accountAddresses []types.Address, clock uint64) (err error) {
tx, err := db.db.Begin()
if err != nil {
return err
}
defer func() { defer func() {
if err == nil { if err == nil {
err = tx.Commit() err = tx.Commit()
@ -533,37 +383,24 @@ func (kp *Keycards) execUpdateQuery(kcUID string, clock uint64, field string, va
_ = tx.Rollback() _ = tx.Rollback()
}() }()
keycard, err := db.getKeycardByKeycardUID(tx, kcUID)
if err != nil { if err != nil {
return err return err
} }
if proceed { err = db.deleteKeycardAccounts(tx, kcUID, accountAddresses)
sql := fmt.Sprintf(`UPDATE keycards SET %s = ?, last_update_clock = ? WHERE keycard_uid = ?`, field) // nolint: gosec if err != nil {
_, err = tx.Exec(sql, value, clock, kcUID)
return err return err
} }
return nil return db.updateKeypairClock(tx, keycard.KeyUID, clock)
} }
func (kp *Keycards) KeycardLocked(kcUID string, clock uint64) (err error) { func (db *Database) DeleteKeycard(kcUID string, clock uint64) (err error) {
return kp.execUpdateQuery(kcUID, clock, "keycard_locked", true) tx, err := db.db.Begin()
} if err != nil {
return err
func (kp *Keycards) KeycardUnlocked(kcUID string, clock uint64) (err error) { }
return kp.execUpdateQuery(kcUID, clock, "keycard_locked", false)
}
func (kp *Keycards) UpdateKeycardUID(oldKcUID string, newKcUID string, clock uint64) (err error) {
return kp.execUpdateQuery(oldKcUID, clock, "keycard_uid", newKcUID)
}
func (kp *Keycards) SetKeycardName(kcUID string, kpName string, clock uint64) (err error) {
return kp.execUpdateQuery(kcUID, clock, "keycard_name", kpName)
}
func (kp *Keycards) DeleteKeycard(kcUID string, clock uint64) (err error) {
tx, proceed, err := kp.startTransactionAndCheckIfNeedToProceed(kcUID, clock)
defer func() { defer func() {
if err == nil { if err == nil {
err = tx.Commit() err = tx.Commit()
@ -572,19 +409,33 @@ func (kp *Keycards) DeleteKeycard(kcUID string, clock uint64) (err error) {
_ = tx.Rollback() _ = tx.Rollback()
}() }()
keycard, err := db.getKeycardByKeycardUID(tx, kcUID)
if err != nil { if err != nil {
return err return err
} }
if proceed { err = db.deleteKeycard(tx, kcUID)
return kp.deleteKeycard(tx, kcUID) if err != nil {
return err
} }
return err return db.updateKeypairClock(tx, keycard.KeyUID, clock)
} }
func (kp *Keycards) DeleteAllKeycardsWithKeyUID(keyUID string) (err error) { func (db *Database) DeleteAllKeycardsWithKeyUID(keyUID string, clock uint64) (err error) {
delete, err := kp.db.Prepare(` tx, err := db.db.Begin()
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
_ = tx.Rollback()
}()
delete, err := tx.Prepare(`
DELETE DELETE
FROM FROM
keycards keycards
@ -595,6 +446,23 @@ func (kp *Keycards) DeleteAllKeycardsWithKeyUID(keyUID string) (err error) {
return err return err
} }
defer delete.Close() defer delete.Close()
_, err = delete.Exec(keyUID) _, err = delete.Exec(keyUID)
return err if err != nil {
return err
}
return db.updateKeypairClock(tx, keyUID, clock)
}
func (db *Database) GetPositionForNextNewKeycard() (uint64, error) {
var pos sql.NullInt64
err := db.db.QueryRow("SELECT MAX(position) FROM keycards").Scan(&pos)
if err != nil {
return 0, err
}
if pos.Valid {
return uint64(pos.Int64) + 1, nil
}
return 0, nil
} }

View File

@ -12,8 +12,6 @@ func TestKeycards(t *testing.T) {
db, stop := setupTestDB(t) db, stop := setupTestDB(t)
defer stop() defer stop()
keycardUID := "00000000000000000000000000000000"
kp1 := GetProfileKeypairForTest(true, true, true) kp1 := GetProfileKeypairForTest(true, true, true)
keycard1 := GetProfileKeycardForTest() keycard1 := GetProfileKeycardForTest()
@ -23,266 +21,151 @@ func TestKeycards(t *testing.T) {
keycard2Copy := GetKeycardForSeedImportedKeypair1ForTest() keycard2Copy := GetKeycardForSeedImportedKeypair1ForTest()
keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 keycard2Copy.Position = keycard2Copy.Position + 1
kp3 := GetSeedImportedKeypair2ForTest()
keycard3 := GetKeycardForSeedImportedKeypair2ForTest()
// Pre-condition // Pre-condition
err := db.SaveOrUpdateKeypair(kp1) err := db.SaveOrUpdateKeypair(kp1)
require.NoError(t, err) require.NoError(t, err)
err = db.SaveOrUpdateKeypair(kp2) err = db.SaveOrUpdateKeypair(kp2)
require.NoError(t, err) require.NoError(t, err)
err = db.SaveOrUpdateKeypair(kp3)
require.NoError(t, err)
dbKeypairs, err := db.GetKeypairs() dbKeypairs, err := db.GetKeypairs()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 3, len(dbKeypairs)) require.Equal(t, 2, len(dbKeypairs))
// Test adding key pairs // Test adding/reading keycards
addedKc, addedAccs, err := db.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = db.SaveOrUpdateKeycard(*keycard1, 0, false)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, true, addedKc) dbKeycard1, err := db.GetKeycardByKeycardUID(keycard1.KeycardUID)
require.Equal(t, false, addedAccs)
addedKc, addedAccs, err = db.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, true, addedKc) require.True(t, SameKeycards(keycard1, dbKeycard1))
require.Equal(t, false, addedAccs)
addedKc, addedAccs, err = db.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy)
require.NoError(t, err)
require.Equal(t, true, addedKc)
require.Equal(t, false, addedAccs)
// this should be added
addedKc, addedAccs, err = db.AddKeycardOrAddAccountsIfKeycardIsAdded(Keycard{
KeycardUID: keycard2Copy.KeycardUID,
AccountsAddresses: []types.Address{{0x03}},
LastUpdateClock: keycard2Copy.LastUpdateClock + 1,
})
require.NoError(t, err)
require.Equal(t, false, addedKc)
require.Equal(t, true, addedAccs)
// this should not be added as it has clock value less than last updated clock value
addedKc, addedAccs, err = db.AddKeycardOrAddAccountsIfKeycardIsAdded(Keycard{
KeycardUID: keycard2Copy.KeycardUID,
AccountsAddresses: []types.Address{{0x04}},
LastUpdateClock: keycard2Copy.LastUpdateClock,
})
require.NoError(t, err)
require.Equal(t, false, addedKc)
require.Equal(t, false, addedAccs)
addedKc, addedAccs, err = db.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3)
require.NoError(t, err)
require.Equal(t, true, addedKc)
require.Equal(t, false, addedAccs)
// Test reading migrated key pairs err = db.SaveOrUpdateKeycard(*keycard2, 0, false)
rows, err := db.GetAllKnownKeycardsGroupedByKeyUID()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 3, len(rows)) dbKeycard2, err := db.GetKeycardByKeycardUID(keycard2.KeycardUID)
for _, kp := range rows { require.NoError(t, err)
if kp.KeyUID == keycard1.KeyUID { require.True(t, SameKeycards(keycard2, dbKeycard2))
require.Equal(t, keycard1.KeycardUID, kp.KeycardUID)
require.Equal(t, keycard1.KeycardName, kp.KeycardName)
require.Equal(t, keycard1.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keycard1.AccountsAddresses), len(kp.AccountsAddresses))
} else if kp.KeyUID == keycard2.KeyUID { // keycard 2 and 3, cause 3 is a copy of 2
require.Equal(t, keycard2.KeycardUID, kp.KeycardUID)
require.Equal(t, keycard2.KeycardName, kp.KeycardName)
require.Equal(t, keycard2.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keycard2.AccountsAddresses)+1, len(kp.AccountsAddresses)) // Add 1, cause one account is additionally added for the same keycard.
} else {
require.Equal(t, keycard3.KeycardUID, kp.KeycardUID)
require.Equal(t, keycard3.KeycardName, kp.KeycardName)
require.Equal(t, keycard3.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keycard3.AccountsAddresses), len(kp.AccountsAddresses))
}
}
rows, err = db.GetKeycardByKeyUID(keycard1.KeyUID) err = db.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(rows)) dbKeycard2Copy, err := db.GetKeycardByKeycardUID(keycard2Copy.KeycardUID)
require.Equal(t, keycard1.KeyUID, rows[0].KeyUID) require.NoError(t, err)
require.Equal(t, keycard1.KeycardUID, rows[0].KeycardUID) require.True(t, SameKeycards(keycard2Copy, dbKeycard2Copy))
require.Equal(t, keycard1.KeycardName, rows[0].KeycardName)
require.Equal(t, keycard1.KeycardLocked, rows[0].KeycardLocked)
require.Equal(t, len(keycard1.AccountsAddresses), len(rows[0].AccountsAddresses))
require.Equal(t, keycard1.LastUpdateClock, rows[0].LastUpdateClock)
rows, err = db.GetAllKnownKeycards() dbKeycards, err := db.GetKeycardsWithSameKeyUID(keycard2.KeyUID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 4, len(rows)) require.Equal(t, 2, len(dbKeycards))
for _, kp := range rows { require.True(t, Contains(dbKeycards, keycard2, SameKeycards))
if kp.KeycardUID == keycard1.KeycardUID { require.True(t, Contains(dbKeycards, keycard2Copy, SameKeycards))
require.Equal(t, keycard1.KeycardUID, kp.KeycardUID)
require.Equal(t, keycard1.KeycardName, kp.KeycardName) dbKeycards, err = db.GetAllKnownKeycards()
require.Equal(t, keycard1.KeycardLocked, kp.KeycardLocked) require.NoError(t, err)
require.Equal(t, len(keycard1.AccountsAddresses), len(kp.AccountsAddresses)) require.Equal(t, 3, len(dbKeycards))
require.Equal(t, keycard1.LastUpdateClock, kp.LastUpdateClock) require.True(t, Contains(dbKeycards, keycard1, SameKeycards))
} else if kp.KeycardUID == keycard2.KeycardUID { require.True(t, Contains(dbKeycards, keycard2, SameKeycards))
require.Equal(t, keycard2.KeycardUID, kp.KeycardUID) require.True(t, Contains(dbKeycards, keycard2Copy, SameKeycards))
require.Equal(t, keycard2.KeycardName, kp.KeycardName)
require.Equal(t, keycard2.KeycardLocked, kp.KeycardLocked) nextPosition, err := db.GetPositionForNextNewKeycard()
require.Equal(t, len(keycard2.AccountsAddresses), len(kp.AccountsAddresses)) require.NoError(t, err)
require.Equal(t, keycard2.LastUpdateClock, kp.LastUpdateClock) require.Equal(t, uint64(len(dbKeycards)), nextPosition)
} else if kp.KeycardUID == keycard2Copy.KeycardUID {
require.Equal(t, keycard2Copy.KeycardUID, kp.KeycardUID) // test adding additional accounts to keycard
require.Equal(t, keycard2Copy.KeycardName, kp.KeycardName) keycard1.AccountsAddresses = append(keycard1.AccountsAddresses, types.Address{0x05}, types.Address{0x06})
require.Equal(t, keycard2Copy.KeycardLocked, kp.KeycardLocked) err = db.SaveOrUpdateKeycard(*keycard1, 0, false)
require.Equal(t, len(keycard2Copy.AccountsAddresses)+1, len(kp.AccountsAddresses)) // Add 1, cause one account is additionally added. require.NoError(t, err)
require.Equal(t, keycard2Copy.LastUpdateClock+1, kp.LastUpdateClock) dbKeycard1, err = db.GetKeycardByKeycardUID(keycard1.KeycardUID)
} else { require.NoError(t, err)
require.Equal(t, keycard3.KeycardUID, kp.KeycardUID) require.Equal(t, len(keycard1.AccountsAddresses), len(dbKeycard1.AccountsAddresses))
require.Equal(t, keycard3.KeycardName, kp.KeycardName) require.True(t, SameKeycards(keycard1, dbKeycard1))
require.Equal(t, keycard3.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keycard3.AccountsAddresses), len(kp.AccountsAddresses))
require.Equal(t, keycard3.LastUpdateClock, kp.LastUpdateClock)
}
}
// Test seting a new keycard name // Test seting a new keycard name
err = db.SetKeycardName(keycard1.KeycardUID, "Card101", 1000) keycard1.KeycardName = "Card101"
err = db.SetKeycardName(keycard1.KeycardUID, keycard1.KeycardName, 1000)
require.NoError(t, err) require.NoError(t, err)
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID() dbKeycard1, err = db.GetKeycardByKeycardUID(keycard1.KeycardUID)
require.NoError(t, err) require.NoError(t, err)
newKeycardName := "" require.True(t, SameKeycards(keycard1, dbKeycard1))
for _, kp := range rows {
if kp.KeyUID == keycard1.KeyUID {
newKeycardName = kp.KeycardName
}
}
require.Equal(t, "Card101", newKeycardName)
// Test seting a new keycard name with an old clock value
err = db.SetKeycardName(keycard1.KeycardUID, "Card102", 999) // clock is less than the last one
require.NoError(t, err)
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID()
require.NoError(t, err)
newKeycardName = ""
for _, kp := range rows {
if kp.KeyUID == keycard1.KeyUID {
newKeycardName = kp.KeycardName
}
}
require.Equal(t, "Card101", newKeycardName)
// Test locking a keycard // Test locking a keycard
keycard1.KeycardLocked = true
err = db.KeycardLocked(keycard1.KeycardUID, 1001) err = db.KeycardLocked(keycard1.KeycardUID, 1001)
require.NoError(t, err) require.NoError(t, err)
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID() dbKeycard1, err = db.GetKeycardByKeycardUID(keycard1.KeycardUID)
require.NoError(t, err) require.NoError(t, err)
locked := false require.True(t, SameKeycards(keycard1, dbKeycard1))
for _, kp := range rows {
if kp.KeyUID == keycard1.KeyUID { // Test unlocking a keycard
locked = kp.KeycardLocked keycard1.KeycardLocked = false
} err = db.KeycardUnlocked(keycard1.KeycardUID, 1002)
} require.NoError(t, err)
require.Equal(t, true, locked) dbKeycard1, err = db.GetKeycardByKeycardUID(keycard1.KeycardUID)
require.NoError(t, err)
require.True(t, SameKeycards(keycard1, dbKeycard1))
// Test update keycard uid
oldKeycardUID := keycard1.KeycardUID
keycard1.KeycardUID = "00000000000000000000000000000000"
err = db.UpdateKeycardUID(oldKeycardUID, keycard1.KeycardUID, 1003)
require.NoError(t, err)
dbKeycard1, err = db.GetKeycardByKeycardUID(keycard1.KeycardUID)
require.NoError(t, err)
require.True(t, SameKeycards(keycard1, dbKeycard1))
// Test detleting accounts (addresses) for a certain keycard // Test detleting accounts (addresses) for a certain keycard
const numOfAccountsToRemove = 2 const numOfAccountsToRemove = 2
require.Greater(t, len(keycard1.AccountsAddresses), numOfAccountsToRemove) require.Greater(t, len(keycard1.AccountsAddresses), numOfAccountsToRemove)
accountsToRemove := keycard1.AccountsAddresses[:numOfAccountsToRemove] accountsToRemove := keycard1.AccountsAddresses[:numOfAccountsToRemove]
err = db.RemoveMigratedAccountsForKeycard(keycard1.KeycardUID, accountsToRemove, 1002) keycard1.AccountsAddresses = keycard1.AccountsAddresses[numOfAccountsToRemove:]
err = db.DeleteKeycardAccounts(keycard1.KeycardUID, accountsToRemove, 1004)
require.NoError(t, err) require.NoError(t, err)
rows, err = db.GetKeycardByKeyUID(keycard1.KeyUID) dbKeycard1, err = db.GetKeycardByKeycardUID(keycard1.KeycardUID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(rows)) require.True(t, SameKeycards(keycard1, dbKeycard1))
require.Equal(t, len(keycard1.AccountsAddresses)-numOfAccountsToRemove, len(rows[0].AccountsAddresses))
// Test deleting accounts one by one, with the last deleted account keycard should be delete as well
for i, addr := range keycard3.AccountsAddresses {
err = db.RemoveMigratedAccountsForKeycard(keycard3.KeycardUID, []types.Address{addr}, 1003+uint64(i))
require.NoError(t, err)
}
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID()
require.NoError(t, err)
// Test if correct keycard is deleted
deletedKeycard3 := true
for _, kp := range rows {
if kp.KeycardUID == keycard3.KeycardUID {
deletedKeycard3 = false
}
}
require.Equal(t, true, deletedKeycard3)
// Test update keycard uid
err = db.UpdateKeycardUID(keycard1.KeycardUID, keycardUID, 1100)
require.NoError(t, err)
// Test unlocking a locked keycard
err = db.KeycardUnlocked(keycardUID, 1101)
require.NoError(t, err)
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID()
require.NoError(t, err)
locked = true
for _, kp := range rows {
if kp.KeycardUID == keycardUID {
locked = kp.KeycardLocked
}
}
require.Equal(t, false, locked)
// Test detleting a keycard // Test detleting a keycard
err = db.DeleteKeycard(keycardUID, 1102) err = db.DeleteKeycard(keycard1.KeycardUID, 1006)
require.NoError(t, err) require.NoError(t, err)
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID() dbKeycards, err = db.GetAllKnownKeycards()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(rows)) require.Equal(t, 2, len(dbKeycards))
// Test if correct keycard is deleted dbKeycards, err = db.GetKeycardsWithSameKeyUID(keycard1.KeyUID)
deletedKeyCard := true require.NoError(t, err)
for _, kp := range rows { require.Equal(t, 0, len(dbKeycards))
if kp.KeycardUID == keycardUID { dbKeycard, err := db.GetKeycardByKeycardUID(keycard1.KeycardUID)
deletedKeyCard = false require.Error(t, err)
} require.True(t, err == ErrNoKeycardForPassedKeycardUID)
} require.Nil(t, dbKeycard)
require.Equal(t, true, deletedKeyCard)
// Test detleting a keycard // Test detleting all keycards for KeyUID
err = db.DeleteAllKeycardsWithKeyUID(keycard2.KeyUID) dbKeycards, err = db.GetKeycardsWithSameKeyUID(keycard2.KeyUID)
require.NoError(t, err) require.NoError(t, err)
rows, err = db.GetAllKnownKeycardsGroupedByKeyUID() require.Equal(t, 2, len(dbKeycards))
err = db.DeleteAllKeycardsWithKeyUID(keycard2.KeyUID, 1007)
require.NoError(t, err) require.NoError(t, err)
// Test if correct keycard is deleted dbKeycards, err = db.GetAllKnownKeycards()
deletedKeycard2And3 := true require.NoError(t, err)
for _, kp := range rows { require.Equal(t, 0, len(dbKeycards))
if kp.KeyUID == keycard2.KeyUID { dbKeycards, err = db.GetKeycardsWithSameKeyUID(keycard2.KeyUID)
deletedKeycard2And3 = false require.NoError(t, err)
} require.Equal(t, 0, len(dbKeycards))
} dbKeycard, err = db.GetKeycardByKeycardUID(keycard2.KeycardUID)
require.Equal(t, true, deletedKeycard2And3) require.Error(t, err)
require.True(t, err == ErrNoKeycardForPassedKeycardUID)
require.Nil(t, dbKeycard)
} }
func TestKeycardsRemovalWhenDeletingKeypair(t *testing.T) { func TestKeycardsRemovalWhenDeletingKeypair(t *testing.T) {
db, stop := setupTestDB(t) db, stop := setupTestDB(t)
defer stop() defer stop()
kp2 := &Keypair{ kp2 := GetSeedImportedKeypair1ForTest()
KeyUID: "0000000000000000000000000000000000000000000000000000000000000002", keycard2 := GetKeycardForSeedImportedKeypair1ForTest()
Name: "Keypair Name 2",
Type: KeypairTypeSeed,
DerivedFrom: "0x0001",
}
kp2.Accounts = append(kp2.Accounts, &Account{Address: types.Address{0x11}, KeyUID: kp2.KeyUID})
kp2.Accounts = append(kp2.Accounts, &Account{Address: types.Address{0x12}, KeyUID: kp2.KeyUID})
keycard2 := Keycard{ keycard2Copy := GetKeycardForSeedImportedKeypair1ForTest()
KeycardUID: "00000000000000000000000000000002", keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
KeycardName: "Card02", keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
KeycardLocked: false, keycard2Copy.Position = keycard2Copy.Position + 1
AccountsAddresses: []types.Address{{0x11}, {0x12}},
KeyUID: kp2.KeyUID,
LastUpdateClock: 200,
}
keycard3 := Keycard{
KeycardUID: "00000000000000000000000000000003",
KeycardName: "Card02 Copy",
KeycardLocked: false,
AccountsAddresses: []types.Address{{0x11}, {0x12}},
KeyUID: kp2.KeyUID,
LastUpdateClock: 300,
}
// Pre-condition - save keypair // Pre-condition
err := db.SaveOrUpdateKeypair(kp2) err := db.SaveOrUpdateKeypair(kp2)
require.NoError(t, err) require.NoError(t, err)
dbKeypairs, err := db.GetKeypairs() dbKeypairs, err := db.GetKeypairs()
@ -290,27 +173,24 @@ func TestKeycardsRemovalWhenDeletingKeypair(t *testing.T) {
require.Equal(t, 1, len(dbKeypairs)) require.Equal(t, 1, len(dbKeypairs))
// Pre-condition - save keycards referring to previously added keypair // Pre-condition - save keycards referring to previously added keypair
addedKc, addedAccs, err := db.AddKeycardOrAddAccountsIfKeycardIsAdded(keycard2) err = db.SaveOrUpdateKeycard(*keycard2, 0, false)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, true, addedKc) dbKeycard2, err := db.GetKeycardByKeycardUID(keycard2.KeycardUID)
require.Equal(t, false, addedAccs)
addedKc, addedAccs, err = db.AddKeycardOrAddAccountsIfKeycardIsAdded(keycard3)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, true, addedKc) require.True(t, SameKeycards(keycard2, dbKeycard2))
require.Equal(t, false, addedAccs)
err = db.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
require.NoError(t, err)
dbKeycard2Copy, err := db.GetKeycardByKeycardUID(keycard2Copy.KeycardUID)
require.NoError(t, err)
require.True(t, SameKeycards(keycard2Copy, dbKeycard2Copy))
// Check db state // Check db state
keycardsWithSameKeyUID, err := db.GetAllKnownKeycards() dbKeycards, err := db.GetKeycardsWithSameKeyUID(keycard2.KeyUID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(keycardsWithSameKeyUID)) require.Equal(t, 2, len(dbKeycards))
require.True(t, Contains(dbKeycards, keycard2, SameKeycards))
require.Equal(t, len(kp2.KeyUID), len(dbKeypairs[0].KeyUID)) require.True(t, Contains(dbKeycards, keycard2Copy, SameKeycards))
require.Equal(t, len(kp2.KeyUID), len(keycardsWithSameKeyUID[0].KeyUID))
require.Equal(t, len(kp2.KeyUID), len(keycardsWithSameKeyUID[1].KeyUID))
require.Equal(t, len(kp2.Accounts), len(dbKeypairs[0].Accounts))
require.Equal(t, len(kp2.Accounts), len(keycardsWithSameKeyUID[0].AccountsAddresses))
require.Equal(t, len(kp2.Accounts), len(keycardsWithSameKeyUID[1].AccountsAddresses))
// Remove keypair // Remove keypair
err = db.DeleteKeypair(kp2.KeyUID) err = db.DeleteKeypair(kp2.KeyUID)
@ -321,7 +201,14 @@ func TestKeycardsRemovalWhenDeletingKeypair(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, len(dbKeypairs)) require.Equal(t, 0, len(dbKeypairs))
keycardsWithSameKeyUID, err = db.GetAllKnownKeycards() dbKeycards, err = db.GetAllKnownKeycards()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, len(keycardsWithSameKeyUID)) require.Equal(t, 0, len(dbKeycards))
dbKeycards, err = db.GetKeycardsWithSameKeyUID(kp2.KeyUID)
require.NoError(t, err)
require.Equal(t, 0, len(dbKeycards))
dbKeycard, err := db.GetKeycardByKeycardUID(keycard2.KeycardUID)
require.Error(t, err)
require.True(t, err == ErrNoKeycardForPassedKeycardUID)
require.Nil(t, dbKeycard)
} }

View File

@ -257,7 +257,7 @@ func GetProfileKeycardForTest() *Keycard {
KeycardLocked: false, KeycardLocked: false,
AccountsAddresses: keycard1Addresses, AccountsAddresses: keycard1Addresses,
KeyUID: profileKp.KeyUID, KeyUID: profileKp.KeyUID,
LastUpdateClock: 100, Position: 0,
} }
} }
@ -273,7 +273,7 @@ func GetKeycardForSeedImportedKeypair1ForTest() *Keycard {
KeycardLocked: false, KeycardLocked: false,
AccountsAddresses: keycard2Addresses, AccountsAddresses: keycard2Addresses,
KeyUID: seed1Kp.KeyUID, KeyUID: seed1Kp.KeyUID,
LastUpdateClock: 200, Position: 1,
} }
} }
@ -289,10 +289,28 @@ func GetKeycardForSeedImportedKeypair2ForTest() *Keycard {
KeycardLocked: false, KeycardLocked: false,
AccountsAddresses: keycard4Addresses, AccountsAddresses: keycard4Addresses,
KeyUID: seed2Kp.KeyUID, KeyUID: seed2Kp.KeyUID,
LastUpdateClock: 300, Position: 2,
} }
} }
func Contains[T comparable](container []T, element T, isEqual func(T, T) bool) bool {
for _, e := range container {
if isEqual(e, element) {
return true
}
}
return false
}
func HaveSameElements[T comparable](a []T, b []T, isEqual func(T, T) bool) bool {
for _, v := range a {
if !Contains(b, v, isEqual) {
return false
}
}
return true
}
func SameAccounts(expected, real *Account) bool { func SameAccounts(expected, real *Account) bool {
return expected.Address == real.Address && return expected.Address == real.Address &&
expected.KeyUID == real.KeyUID && expected.KeyUID == real.KeyUID &&
@ -379,7 +397,7 @@ func SameKeycards(expected, real *Keycard) bool {
expected.KeyUID == real.KeyUID && expected.KeyUID == real.KeyUID &&
expected.KeycardName == real.KeycardName && expected.KeycardName == real.KeycardName &&
expected.KeycardLocked == real.KeycardLocked && expected.KeycardLocked == real.KeycardLocked &&
expected.LastUpdateClock == real.LastUpdateClock && expected.Position == real.Position &&
len(expected.AccountsAddresses) == len(real.AccountsAddresses) len(expected.AccountsAddresses) == len(real.AccountsAddresses)
if same { if same {

View File

@ -4315,20 +4315,6 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
allMessagesProcessed = false allMessagesProcessed = false
continue continue
} }
case protobuf.SyncKeycardAction:
if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) {
logger.Warn("not coming from us, ignoring")
continue
}
p := msg.ParsedMessage.Interface().(protobuf.SyncKeycardAction)
m.outputToCSV(msg.TransportMessage.Timestamp, msg.ID, senderID, filter.Topic, filter.ChatID, msg.Type, p)
err = m.handleSyncKeycardActivity(messageState, p)
if err != nil {
logger.Warn("failed to handle SyncKeycardAction", zap.Error(err))
allMessagesProcessed = false
continue
}
case protobuf.SyncSocialLinks: case protobuf.SyncSocialLinks:
if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) { if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) {
logger.Warn("not coming from us, ignoring") logger.Warn("not coming from us, ignoring")

View File

@ -757,7 +757,7 @@ func (s *MessengerBackupSuite) TestBackupKeypairs() {
s.Require().Equal(accounts.SyncedFromBackup, dbProfileKp2.SyncedFrom) s.Require().Equal(accounts.SyncedFromBackup, dbProfileKp2.SyncedFrom)
for _, acc := range profileKp.Accounts { for _, acc := range profileKp.Accounts {
s.Require().True(contains(dbProfileKp2.Accounts, acc, accounts.SameAccounts)) s.Require().True(accounts.Contains(dbProfileKp2.Accounts, acc, accounts.SameAccounts))
} }
dbSeedKp2, err := bob2.settings.GetKeypairByKeyUID(seedKp.KeyUID) dbSeedKp2, err := bob2.settings.GetKeypairByKeyUID(seedKp.KeyUID)
@ -778,7 +778,6 @@ func (s *MessengerBackupSuite) TestBackupKeycards() {
keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1
kp3 := accounts.GetSeedImportedKeypair2ForTest() kp3 := accounts.GetSeedImportedKeypair2ForTest()
keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
@ -794,22 +793,14 @@ func (s *MessengerBackupSuite) TestBackupKeycards() {
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(3, len(dbKeypairs)) s.Require().Equal(3, len(dbKeypairs))
addedKc, addedAccs, err := bob1.settings.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = bob1.settings.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc) err = bob1.settings.SaveOrUpdateKeycard(*keycard2, 0, false)
s.Require().Equal(false, addedAccs)
addedKc, addedAccs, err = bob1.settings.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc) err = bob1.settings.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
s.Require().Equal(false, addedAccs)
addedKc, addedAccs, err = bob1.settings.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc) err = bob1.settings.SaveOrUpdateKeycard(*keycard3, 0, false)
s.Require().Equal(false, addedAccs)
addedKc, addedAccs, err = bob1.settings.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Create bob2 // Create bob2
bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil) bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
@ -835,10 +826,10 @@ func (s *MessengerBackupSuite) TestBackupKeycards() {
syncedKeycards, err := bob2.settings.GetAllKnownKeycards() syncedKeycards, err := bob2.settings.GetAllKnownKeycards()
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(4, len(syncedKeycards)) s.Require().Equal(4, len(syncedKeycards))
s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) s.Require().True(accounts.Contains(syncedKeycards, keycard1, accounts.SameKeycards))
s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) s.Require().True(accounts.Contains(syncedKeycards, keycard2, accounts.SameKeycards))
s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards)) s.Require().True(accounts.Contains(syncedKeycards, keycard2Copy, accounts.SameKeycards))
s.Require().True(contains(syncedKeycards, keycard3, accounts.SameKeycards)) s.Require().True(accounts.Contains(syncedKeycards, keycard3, accounts.SameKeycards))
} }
func (s *MessengerBackupSuite) TestBackupWatchOnlyAccounts() { func (s *MessengerBackupSuite) TestBackupWatchOnlyAccounts() {

View File

@ -3036,13 +3036,13 @@ func (m *Messenger) resolveAccountOperability(syncAcc *protobuf.SyncAccount, syn
// We're here when we receive a keypair from the paired device which is either: // We're here when we receive a keypair from the paired device which is either:
// 1. regular keypair or // 1. regular keypair or
// 2. was just converted from keycard to a regular keypair. // 2. was just converted from keycard to a regular keypair.
dbKeycardsForKeyUID, err := m.settings.GetKeycardByKeyUID(syncAcc.KeyUid) dbKeycardsForKeyUID, err := m.settings.GetKeycardsWithSameKeyUID(syncAcc.KeyUid)
if err != nil && err != accounts.ErrDbKeypairNotFound { if err != nil {
return accounts.AccountNonOperable, err return accounts.AccountNonOperable, err
} }
if len(dbKeycardsForKeyUID) > 0 { if len(dbKeycardsForKeyUID) > 0 {
// We're here in 2. case from above and in this case we need to mark all accounts for this keypair non operable // We're here in case 2. from above and in this case we need to mark all accounts for this keypair non operable
return accounts.AccountNonOperable, nil return accounts.AccountNonOperable, nil
} }
} }
@ -3174,7 +3174,7 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
} }
} }
err = m.settings.DeleteKeypair(message.KeyUid) err = m.settings.DeleteKeypair(message.KeyUid) // deleting keypair will delete related keycards as well
if err != nil && err != accounts.ErrDbKeypairNotFound { if err != nil && err != accounts.ErrDbKeypairNotFound {
return nil, err return nil, err
} }
@ -3192,14 +3192,13 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
for _, sKc := range message.Keycards { for _, sKc := range message.Keycards {
kc := accounts.Keycard{} kc := accounts.Keycard{}
kc.FromSyncKeycard(sKc) kc.FromSyncKeycard(sKc)
err = m.settings.SaveOrUpdateKeycard(kc, message.Clock, false)
if err != nil {
return nil, err
}
kp.Keycards = append(kp.Keycards, &kc) kp.Keycards = append(kp.Keycards, &kc)
} }
err = m.settings.ApplyKeycardsForKeypairWithKeyUID(kp.KeyUID, kp.Keycards)
if err != nil {
return nil, err
}
return kp, nil return kp, nil
} }

View File

@ -3,24 +3,18 @@ package protocol
import ( import (
"context" "context"
"github.com/golang/protobuf/proto"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/protobuf"
) )
func (m *Messenger) prepareSyncKeycardsMessage(keyUID string) (message []*protobuf.SyncKeycard, err error) { func (m *Messenger) prepareSyncKeycardsMessage(keyUID string) (message []*protobuf.SyncKeycard, err error) {
allKeycards, err := m.settings.GetAllKnownKeycards() keycards, err := m.settings.GetKeycardsWithSameKeyUID(keyUID)
if err != nil { if err != nil {
return message, err return
} }
for _, kc := range allKeycards { for _, kc := range keycards {
if kc.KeyUID != keyUID {
continue
}
syncKeycard := kc.ToSyncKeycard() syncKeycard := kc.ToSyncKeycard()
message = append(message, syncKeycard) message = append(message, syncKeycard)
} }
@ -28,198 +22,91 @@ func (m *Messenger) prepareSyncKeycardsMessage(keyUID string) (message []*protob
return return
} }
func (m *Messenger) dispatchKeycardActivity(ctx context.Context, syncMessage protobuf.SyncKeycardAction) error { func (m *Messenger) dispatchKeycardActivity(keyUID string, keycardUID string, newKeycardUID string, accountAddresses []types.Address,
if !m.hasPairedDevices() { callback func(uint64) error) error {
return nil clock, _ := m.getLastClockWithRelatedChat()
finalKeyUID := keyUID
if finalKeyUID == "" {
dbKeycard, err := m.settings.GetKeycardByKeycardUID(keycardUID)
if err != nil {
return err
}
finalKeyUID = dbKeycard.KeyUID
} }
clock, chat := m.getLastClockWithRelatedChat() if err := callback(clock); err != nil {
encodedMessage, err := proto.Marshal(&syncMessage)
if err != nil {
return err return err
} }
rawMessage := common.RawMessage{ return m.resolveAndSyncKeypairOrJustWalletAccount(finalKeyUID, types.Address{}, clock, m.dispatchMessage)
LocalChatID: chat.ID, }
Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_SYNC_KEYCARD_ACTION,
ResendAutomatically: true,
}
_, err = m.dispatchMessage(ctx, rawMessage) // This function stores keycard to db and notifies paired devices about that if keycard with `KeycardUID` is not already stored.
if err != nil { // Keycard position is fully maintained by the backend.
// If keycard is already stored, this function updates `KeycardName` and adds accounts which are not already added, in this case
// `KeycardLocked` and `Position` remains as they were, they won't be changed.
func (m *Messenger) SaveOrUpdateKeycard(ctx context.Context, keycard *accounts.Keycard) (err error) {
dbKeycard, err := m.settings.GetKeycardByKeycardUID(keycard.KeycardUID)
if err != nil && err != accounts.ErrNoKeycardForPassedKeycardUID {
return err return err
} }
chat.LastClockValue = clock if dbKeycard == nil {
return m.saveChat(chat) position, err := m.settings.GetPositionForNextNewKeycard()
if err != nil {
return err
}
keycard.Position = position
keycard.KeycardLocked = false
} else {
keycard.Position = dbKeycard.Position
keycard.KeycardLocked = dbKeycard.KeycardLocked
}
return m.dispatchKeycardActivity(keycard.KeyUID, "", "", []types.Address{}, func(clock uint64) error {
return m.settings.SaveOrUpdateKeycard(*keycard, clock, true)
})
} }
func (m *Messenger) handleSyncKeycardActivity(state *ReceivedMessageState, syncMessage protobuf.SyncKeycardAction) (err error) { func (m *Messenger) SetKeycardName(ctx context.Context, keycardUID string, kpName string) error {
return m.dispatchKeycardActivity("", keycardUID, "", []types.Address{}, func(clock uint64) error {
var kcAction = &accounts.KeycardAction{ return m.settings.SetKeycardName(keycardUID, kpName, clock)
Action: protobuf.SyncKeycardAction_Action_name[int32(syncMessage.Action)], })
OldKeycardUID: syncMessage.OldKeycardUid,
Keycard: &accounts.Keycard{},
}
kcAction.Keycard.FromSyncKeycard(syncMessage.Keycard)
switch syncMessage.Action {
case protobuf.SyncKeycardAction_KEYCARD_ADDED,
protobuf.SyncKeycardAction_ACCOUNTS_ADDED:
_, _, err = m.settings.AddKeycardOrAddAccountsIfKeycardIsAdded(*kcAction.Keycard)
case protobuf.SyncKeycardAction_KEYCARD_DELETED:
err = m.settings.DeleteKeycard(kcAction.Keycard.KeycardUID, kcAction.Keycard.LastUpdateClock)
case protobuf.SyncKeycardAction_ACCOUNTS_REMOVED:
err = m.settings.RemoveMigratedAccountsForKeycard(kcAction.Keycard.KeycardUID, kcAction.Keycard.AccountsAddresses,
kcAction.Keycard.LastUpdateClock)
case protobuf.SyncKeycardAction_LOCKED:
err = m.settings.KeycardLocked(kcAction.Keycard.KeycardUID, kcAction.Keycard.LastUpdateClock)
case protobuf.SyncKeycardAction_UNLOCKED:
err = m.settings.KeycardUnlocked(kcAction.Keycard.KeycardUID, kcAction.Keycard.LastUpdateClock)
case protobuf.SyncKeycardAction_UID_UPDATED:
err = m.settings.UpdateKeycardUID(kcAction.OldKeycardUID, kcAction.Keycard.KeycardUID,
kcAction.Keycard.LastUpdateClock)
case protobuf.SyncKeycardAction_NAME_CHANGED:
err = m.settings.SetKeycardName(kcAction.Keycard.KeycardUID, kcAction.Keycard.KeycardName,
kcAction.Keycard.LastUpdateClock)
default:
panic("unknown action for handling keycard activity")
}
if err != nil {
return err
}
state.Response.AddKeycardAction(kcAction)
return nil
} }
func (m *Messenger) AddKeycardOrAddAccountsIfKeycardIsAdded(ctx context.Context, kp *accounts.Keycard) (added bool, err error) { func (m *Messenger) KeycardLocked(ctx context.Context, keycardUID string) error {
addedKc, addedAccs, err := m.settings.AddKeycardOrAddAccountsIfKeycardIsAdded(*kp) return m.dispatchKeycardActivity("", keycardUID, "", []types.Address{}, func(clock uint64) error {
if err != nil { return m.settings.KeycardLocked(keycardUID, clock)
return addedKc || addedAccs, err })
}
activityMessage := protobuf.SyncKeycardAction{
Keycard: kp.ToSyncKeycard(),
}
if addedKc {
activityMessage.Action = protobuf.SyncKeycardAction_KEYCARD_ADDED
} else if addedAccs {
activityMessage.Action = protobuf.SyncKeycardAction_ACCOUNTS_ADDED
}
return addedKc || addedAccs, m.dispatchKeycardActivity(ctx, activityMessage)
} }
func (m *Messenger) RemoveMigratedAccountsForKeycard(ctx context.Context, kcUID string, addresses []types.Address, clock uint64) error { func (m *Messenger) KeycardUnlocked(ctx context.Context, keycardUID string) error {
return m.dispatchKeycardActivity("", keycardUID, "", []types.Address{}, func(clock uint64) error {
err := m.settings.RemoveMigratedAccountsForKeycard(kcUID, addresses, clock) return m.settings.KeycardUnlocked(keycardUID, clock)
if err != nil { })
return err
}
activityMessage := protobuf.SyncKeycardAction{
Action: protobuf.SyncKeycardAction_ACCOUNTS_REMOVED,
Keycard: &protobuf.SyncKeycard{
Uid: kcUID,
Clock: clock,
},
}
for _, addr := range addresses {
activityMessage.Keycard.Addresses = append(activityMessage.Keycard.Addresses, addr.Bytes())
}
return m.dispatchKeycardActivity(ctx, activityMessage)
} }
func (m *Messenger) SetKeycardName(ctx context.Context, kcUID string, kpName string, clock uint64) error { func (m *Messenger) DeleteKeycardAccounts(ctx context.Context, keycardUID string, accountAddresses []types.Address) error {
err := m.settings.SetKeycardName(kcUID, kpName, clock) return m.dispatchKeycardActivity("", keycardUID, "", accountAddresses, func(clock uint64) error {
if err != nil { return m.settings.DeleteKeycardAccounts(keycardUID, accountAddresses, clock)
return err })
}
activityMessage := protobuf.SyncKeycardAction{
Action: protobuf.SyncKeycardAction_NAME_CHANGED,
Keycard: &protobuf.SyncKeycard{
Uid: kcUID,
Name: kpName,
Clock: clock,
},
}
return m.dispatchKeycardActivity(ctx, activityMessage)
} }
func (m *Messenger) KeycardLocked(ctx context.Context, kcUID string, clock uint64) error { func (m *Messenger) DeleteKeycard(ctx context.Context, keycardUID string) error {
err := m.settings.KeycardLocked(kcUID, clock) return m.dispatchKeycardActivity("", keycardUID, "", []types.Address{}, func(clock uint64) error {
if err != nil { return m.settings.DeleteKeycard(keycardUID, clock)
return err })
}
activityMessage := protobuf.SyncKeycardAction{
Action: protobuf.SyncKeycardAction_LOCKED,
Keycard: &protobuf.SyncKeycard{
Uid: kcUID,
Clock: clock,
},
}
return m.dispatchKeycardActivity(ctx, activityMessage)
} }
func (m *Messenger) KeycardUnlocked(ctx context.Context, kcUID string, clock uint64) error { func (m *Messenger) DeleteAllKeycardsWithKeyUID(ctx context.Context, keyUID string) error {
err := m.settings.KeycardUnlocked(kcUID, clock) return m.dispatchKeycardActivity(keyUID, "", "", []types.Address{}, func(clock uint64) error {
if err != nil { return m.settings.DeleteAllKeycardsWithKeyUID(keyUID, clock)
return err })
}
activityMessage := protobuf.SyncKeycardAction{
Action: protobuf.SyncKeycardAction_UNLOCKED,
Keycard: &protobuf.SyncKeycard{
Uid: kcUID,
Clock: clock,
},
}
return m.dispatchKeycardActivity(ctx, activityMessage)
} }
func (m *Messenger) DeleteKeycard(ctx context.Context, kcUID string, clock uint64) error { func (m *Messenger) UpdateKeycardUID(ctx context.Context, oldKeycardUID string, newKeycardUID string) error {
err := m.settings.DeleteKeycard(kcUID, clock) return m.dispatchKeycardActivity("", oldKeycardUID, newKeycardUID, []types.Address{}, func(clock uint64) error {
if err != nil { return m.settings.UpdateKeycardUID(oldKeycardUID, newKeycardUID, clock)
return err })
}
activityMessage := protobuf.SyncKeycardAction{
Action: protobuf.SyncKeycardAction_KEYCARD_DELETED,
Keycard: &protobuf.SyncKeycard{
Uid: kcUID,
Clock: clock,
},
}
return m.dispatchKeycardActivity(ctx, activityMessage)
}
func (m *Messenger) UpdateKeycardUID(ctx context.Context, oldKcUID string, newKcUID string, clock uint64) error {
err := m.settings.UpdateKeycardUID(oldKcUID, newKcUID, clock)
if err != nil {
return err
}
activityMessage := protobuf.SyncKeycardAction{
Action: protobuf.SyncKeycardAction_UID_UPDATED,
OldKeycardUid: oldKcUID,
Keycard: &protobuf.SyncKeycard{
Uid: newKcUID,
Clock: clock,
},
}
return m.dispatchKeycardActivity(ctx, activityMessage)
} }

View File

@ -74,7 +74,6 @@ type MessengerResponse struct {
trustStatus map[string]verification.TrustStatus trustStatus map[string]verification.TrustStatus
emojiReactions map[string]*EmojiReaction emojiReactions map[string]*EmojiReaction
savedAddresses map[string]*wallet.SavedAddress savedAddresses map[string]*wallet.SavedAddress
keycardActions []*accounts.KeycardAction
SocialLinksInfo *identity.SocialLinksInfo SocialLinksInfo *identity.SocialLinksInfo
ensUsernameDetails []*ensservice.UsernameDetail ensUsernameDetails []*ensservice.UsernameDetail
} }
@ -116,7 +115,6 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) {
DiscordMessages []*protobuf.DiscordMessage `json:"discordMessages,omitempty"` DiscordMessages []*protobuf.DiscordMessage `json:"discordMessages,omitempty"`
DiscordMessageAttachments []*protobuf.DiscordMessageAttachment `json:"discordMessageAtachments,omitempty"` DiscordMessageAttachments []*protobuf.DiscordMessageAttachment `json:"discordMessageAtachments,omitempty"`
SavedAddresses []*wallet.SavedAddress `json:"savedAddresses,omitempty"` SavedAddresses []*wallet.SavedAddress `json:"savedAddresses,omitempty"`
KeycardActions []*accounts.KeycardAction `json:"keycardActions,omitempty"`
SocialLinksInfo *identity.SocialLinksInfo `json:"socialLinksInfo,omitempty"` SocialLinksInfo *identity.SocialLinksInfo `json:"socialLinksInfo,omitempty"`
EnsUsernameDetails []*ensservice.UsernameDetail `json:"ensUsernameDetails,omitempty"` EnsUsernameDetails []*ensservice.UsernameDetail `json:"ensUsernameDetails,omitempty"`
}{ }{
@ -151,7 +149,6 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) {
DiscordCategories: r.DiscordCategories, DiscordCategories: r.DiscordCategories,
DiscordChannels: r.DiscordChannels, DiscordChannels: r.DiscordChannels,
DiscordOldestMessageTimestamp: r.DiscordOldestMessageTimestamp, DiscordOldestMessageTimestamp: r.DiscordOldestMessageTimestamp,
KeycardActions: r.KeycardActions(),
SocialLinksInfo: r.SocialLinksInfo, SocialLinksInfo: r.SocialLinksInfo,
EnsUsernameDetails: r.EnsUsernameDetails(), EnsUsernameDetails: r.EnsUsernameDetails(),
} }
@ -279,7 +276,6 @@ func (r *MessengerResponse) IsEmpty() bool {
len(r.verificationRequests)+ len(r.verificationRequests)+
len(r.RequestsToJoinCommunity)+ len(r.RequestsToJoinCommunity)+
len(r.savedAddresses)+ len(r.savedAddresses)+
len(r.keycardActions) == 0 &&
len(r.ensUsernameDetails) == 0 && len(r.ensUsernameDetails) == 0 &&
r.currentStatus == nil && r.currentStatus == nil &&
r.activityCenterState == nil && r.activityCenterState == nil &&
@ -312,7 +308,6 @@ func (r *MessengerResponse) Merge(response *MessengerResponse) error {
r.AddEmojiReactions(response.EmojiReactions()) r.AddEmojiReactions(response.EmojiReactions())
r.AddInstallations(response.Installations) r.AddInstallations(response.Installations)
r.AddSavedAddresses(response.SavedAddresses()) r.AddSavedAddresses(response.SavedAddresses())
r.AddKeycardActions(response.KeycardActions())
r.AddEnsUsernameDetails(response.EnsUsernameDetails()) r.AddEnsUsernameDetails(response.EnsUsernameDetails())
r.AddRequestsToJoinCommunity(response.RequestsToJoinCommunity) r.AddRequestsToJoinCommunity(response.RequestsToJoinCommunity)
r.AddBookmarks(response.GetBookmarks()) r.AddBookmarks(response.GetBookmarks())
@ -463,18 +458,6 @@ func (r *MessengerResponse) SavedAddresses() []*wallet.SavedAddress {
return ers return ers
} }
func (r *MessengerResponse) AddKeycardAction(keycardAction *accounts.KeycardAction) {
r.keycardActions = append(r.keycardActions, keycardAction)
}
func (r *MessengerResponse) AddKeycardActions(keycardActions []*accounts.KeycardAction) {
r.keycardActions = append(r.keycardActions, keycardActions...)
}
func (r *MessengerResponse) KeycardActions() []*accounts.KeycardAction {
return r.keycardActions
}
func (r *MessengerResponse) AddEnsUsernameDetail(detail *ensservice.UsernameDetail) { func (r *MessengerResponse) AddEnsUsernameDetail(detail *ensservice.UsernameDetail) {
r.ensUsernameDetails = append(r.ensUsernameDetails, detail) r.ensUsernameDetails = append(r.ensUsernameDetails, detail)
} }

View File

@ -79,6 +79,9 @@ func (s *MessengerSyncKeycardChangeSuite) SetupTest() {
kp1 := accounts.GetProfileKeypairForTest(true, true, true) kp1 := accounts.GetProfileKeypairForTest(true, true, true)
kp2 := accounts.GetSeedImportedKeypair1ForTest() kp2 := accounts.GetSeedImportedKeypair1ForTest()
// kp3 := accounts.GetSeedImportedKeypair2ForTest() // kp3 := accounts.GetSeedImportedKeypair2ForTest()
kp1.Clock = 1
kp2.Clock = 1
// kp3.Clock = 1
err = s.main.settings.SaveOrUpdateKeypair(kp1) err = s.main.settings.SaveOrUpdateKeypair(kp1)
s.Require().NoError(err) s.Require().NoError(err)
@ -90,11 +93,15 @@ func (s *MessengerSyncKeycardChangeSuite) SetupTest() {
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(2, len(dbKeypairs)) s.Require().Equal(2, len(dbKeypairs))
err = s.other.SaveOrUpdateKeypair(kp1) kp1.Clock = 0
kp2.Clock = 0
// kp3.Clock = 0
err = s.other.settings.SaveOrUpdateKeypair(kp1)
s.Require().NoError(err) s.Require().NoError(err)
err = s.other.SaveOrUpdateKeypair(kp2) err = s.other.settings.SaveOrUpdateKeypair(kp2)
s.Require().NoError(err) s.Require().NoError(err)
// err = s.other.SaveOrUpdateKeypair(kp3) // err = s.other.settings.SaveOrUpdateKeypair(kp3)
// s.Require().NoError(err) // s.Require().NoError(err)
dbKeypairs, err = s.other.settings.GetKeypairs() dbKeypairs, err = s.other.settings.GetKeypairs()
s.Require().NoError(err) s.Require().NoError(err)
@ -124,19 +131,16 @@ func (s *MessengerSyncKeycardChangeSuite) TestAddingNewKeycards() {
keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
added, err := s.main.AddKeycardOrAddAccountsIfKeycardIsAdded(context.Background(), keycard1) err := s.main.SaveOrUpdateKeycard(context.Background(), keycard1)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, added) err = s.main.SaveOrUpdateKeycard(context.Background(), keycard2)
added, err = s.main.AddKeycardOrAddAccountsIfKeycardIsAdded(context.Background(), keycard2)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, added)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 2 return len(r.Keypairs) == 2
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
@ -145,14 +149,14 @@ func (s *MessengerSyncKeycardChangeSuite) TestAddingNewKeycards() {
senderKeycards, err := s.main.settings.GetAllKnownKeycards() senderKeycards, err := s.main.settings.GetAllKnownKeycards()
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(2, len(senderKeycards)) s.Require().Equal(2, len(senderKeycards))
s.Require().True(contains(senderKeycards, keycard1, accounts.SameKeycards)) s.Require().True(accounts.Contains(senderKeycards, keycard1, accounts.SameKeycards))
s.Require().True(contains(senderKeycards, keycard2, accounts.SameKeycards)) s.Require().True(accounts.Contains(senderKeycards, keycard2, accounts.SameKeycards))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(2, len(syncedKeycards)) s.Require().Equal(2, len(syncedKeycards))
s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) s.Require().True(accounts.Contains(syncedKeycards, keycard1, accounts.SameKeycards))
s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) s.Require().True(accounts.Contains(syncedKeycards, keycard2, accounts.SameKeycards))
} }
func (s *MessengerSyncKeycardChangeSuite) TestAddingAccountsToKeycard() { func (s *MessengerSyncKeycardChangeSuite) TestAddingAccountsToKeycard() {
@ -164,27 +168,22 @@ func (s *MessengerSyncKeycardChangeSuite) TestAddingAccountsToKeycard() {
keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add additional accounts to sender // Add additional accounts to sender
added, err := s.main.AddKeycardOrAddAccountsIfKeycardIsAdded(context.Background(), keycard2) err = s.main.SaveOrUpdateKeycard(context.Background(), keycard2)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, added)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
@ -210,31 +209,26 @@ func (s *MessengerSyncKeycardChangeSuite) TestRemovingAccountsFromKeycard() {
keycard1 := accounts.GetProfileKeycardForTest() keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison // Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest() updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.AccountsAddresses = updatedKeycard1.AccountsAddresses[2:] updatedKeycard1.AccountsAddresses = updatedKeycard1.AccountsAddresses[2:]
// Remove accounts from sender // Remove accounts from sender
err = s.main.RemoveMigratedAccountsForKeycard(context.Background(), keycard1.KeycardUID, err = s.main.DeleteKeycardAccounts(context.Background(), keycard1.KeycardUID, keycard1.AccountsAddresses[:2])
keycard1.AccountsAddresses[:2], updatedKeycard1.LastUpdateClock)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
@ -251,44 +245,39 @@ func (s *MessengerSyncKeycardChangeSuite) TestRemovingAccountsFromKeycard() {
s.Require().True(contains(syncedKeycards, updatedKeycard1, accounts.SameKeycards)) s.Require().True(contains(syncedKeycards, updatedKeycard1, accounts.SameKeycards))
} }
func (s *MessengerSyncKeycardChangeSuite) TestRemovingAllAccountsFromKeycard() { func (s *MessengerSyncKeycardChangeSuite) TestRemovingAllAccountsForKeyUID() {
senderDb := s.main.settings senderDb := s.main.settings
dbOnReceiver := s.other.settings dbOnReceiver := s.other.settings
keycard1 := accounts.GetProfileKeycardForTest() keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Remove all accounts from sender // Remove all accounts from sender for KeyUID
err = s.main.RemoveMigratedAccountsForKeycard(context.Background(), keycard1.KeycardUID, err = s.main.DeleteAllKeycardsWithKeyUID(context.Background(), keycard1.KeyUID)
keycard1.AccountsAddresses, keycard1.LastUpdateClock)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
s.Require().NoError(err) s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards() senderKeycards, err := senderDb.GetKeycardsWithSameKeyUID(keycard1.KeyUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(0, len(senderKeycards)) s.Require().Equal(0, len(senderKeycards))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycards, err := dbOnReceiver.GetKeycardsWithSameKeyUID(keycard1.KeyUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(0, len(syncedKeycards)) s.Require().Equal(0, len(syncedKeycards))
} }
@ -300,38 +289,36 @@ func (s *MessengerSyncKeycardChangeSuite) TestDeleteKeycard() {
keycard1 := accounts.GetProfileKeycardForTest() keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Remove keycard from sender // Remove keycard from sender
err = s.main.DeleteKeycard(context.Background(), keycard1.KeycardUID, keycard1.LastUpdateClock) err = s.main.DeleteKeycard(context.Background(), keycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
s.Require().NoError(err) s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards() senderKeycard, err := senderDb.GetKeycardByKeycardUID(keycard1.KeycardUID)
s.Require().NoError(err) s.Require().Error(err)
s.Require().Equal(0, len(senderKeycards)) s.Require().True(err == accounts.ErrNoKeycardForPassedKeycardUID)
s.Require().Nil(senderKeycard)
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycard, err := dbOnReceiver.GetKeycardByKeycardUID(keycard1.KeycardUID)
s.Require().NoError(err) s.Require().Error(err)
s.Require().Equal(0, len(syncedKeycards)) s.Require().True(err == accounts.ErrNoKeycardForPassedKeycardUID)
s.Require().Nil(syncedKeycard)
} }
func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardName() { func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardName() {
@ -341,94 +328,38 @@ func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardName() {
keycard1 := accounts.GetProfileKeycardForTest() keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison // Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest() updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardName = "New Keycard Name" updatedKeycard1.KeycardName = "New Keycard Name"
// Set new keycard name to sender // Set new keycard name to sender
err = s.main.SetKeycardName(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.KeycardName, err = s.main.SetKeycardName(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.KeycardName)
updatedKeycard1.LastUpdateClock)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
s.Require().NoError(err) s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards() senderKeycard, err := senderDb.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycard, err := dbOnReceiver.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycards[0]))
}
func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardNameWithOlderClock() {
senderDb := s.main.settings
dbOnReceiver := s.other.settings
keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardName = "New Keycard Name"
updatedKeycard1.LastUpdateClock = updatedKeycard1.LastUpdateClock - 1
// Set new keycard name to sender
err = s.main.SetKeycardName(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.KeycardName,
updatedKeycard1.LastUpdateClock)
s.Require().NoError(err)
// Wait for the response
_, err = WaitOnMessengerResponse(
s.other,
func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1
},
"expected to receive keycard activities",
)
s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards))
s.Require().True(accounts.SameKeycards(keycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards))
s.Require().True(accounts.SameKeycards(keycard1, syncedKeycards[0]))
} }
func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardLocked() { func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardLocked() {
@ -438,90 +369,37 @@ func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardLocked() {
keycard1 := accounts.GetProfileKeycardForTest() keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison // Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest() updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardLocked = true updatedKeycard1.KeycardLocked = true
err = s.main.KeycardLocked(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.LastUpdateClock) err = s.main.KeycardLocked(context.Background(), updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
s.Require().NoError(err) s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards() senderKeycard, err := senderDb.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycard, err := dbOnReceiver.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycards[0]))
}
func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardLockedOlderClock() {
senderDb := s.main.settings
dbOnReceiver := s.other.settings
keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardLocked = true
updatedKeycard1.LastUpdateClock = updatedKeycard1.LastUpdateClock - 1
err = s.main.KeycardLocked(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.LastUpdateClock)
s.Require().NoError(err)
// Wait for the response
_, err = WaitOnMessengerResponse(
s.other,
func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1
},
"expected to receive keycard activities",
)
s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards))
s.Require().True(accounts.SameKeycards(keycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards))
s.Require().True(accounts.SameKeycards(keycard1, syncedKeycards[0]))
} }
func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardUnlocked() { func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardUnlocked() {
@ -532,91 +410,37 @@ func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardUnlocked() {
keycard1.KeycardLocked = true keycard1.KeycardLocked = true
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison // Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest() updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardLocked = false updatedKeycard1.KeycardLocked = false
err = s.main.KeycardUnlocked(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.LastUpdateClock) err = s.main.KeycardUnlocked(context.Background(), updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
s.Require().NoError(err) s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards() senderKeycard, err := senderDb.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycard, err := dbOnReceiver.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycards[0]))
}
func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardUnlockedOlderClock() {
senderDb := s.main.settings
dbOnReceiver := s.other.settings
keycard1 := accounts.GetProfileKeycardForTest()
keycard1.KeycardLocked = true
// Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardLocked = false
updatedKeycard1.LastUpdateClock = updatedKeycard1.LastUpdateClock - 1
err = s.main.KeycardUnlocked(context.Background(), updatedKeycard1.KeycardUID, updatedKeycard1.LastUpdateClock)
s.Require().NoError(err)
// Wait for the response
_, err = WaitOnMessengerResponse(
s.other,
func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1
},
"expected to receive keycard activities",
)
s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards))
s.Require().True(accounts.SameKeycards(keycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards))
s.Require().True(accounts.SameKeycards(keycard1, syncedKeycards[0]))
} }
func (s *MessengerSyncKeycardChangeSuite) TestUpdatingKeycardUid() { func (s *MessengerSyncKeycardChangeSuite) TestUpdatingKeycardUid() {
@ -626,92 +450,36 @@ func (s *MessengerSyncKeycardChangeSuite) TestUpdatingKeycardUid() {
keycard1 := accounts.GetProfileKeycardForTest() keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender // Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver // Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison // Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest() updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardUID = "00000000000000000000000000000000" updatedKeycard1.KeycardUID = "00000000000000000000000000000000"
// Update keycard uid on sender // Update keycard uid on sender
err = s.main.UpdateKeycardUID(context.Background(), keycard1.KeycardUID, updatedKeycard1.KeycardUID, err = s.main.UpdateKeycardUID(context.Background(), keycard1.KeycardUID, updatedKeycard1.KeycardUID)
updatedKeycard1.LastUpdateClock)
s.Require().NoError(err) s.Require().NoError(err)
// Wait for the response // Wait for the response
_, err = WaitOnMessengerResponse( _, err = WaitOnMessengerResponse(
s.other, s.other,
func(r *MessengerResponse) bool { func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1 return len(r.Keypairs) == 1
}, },
"expected to receive keycard activities", "expected to receive keycard activities",
) )
s.Require().NoError(err) s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards() senderKeycard, err := senderDb.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() syncedKeycard, err := dbOnReceiver.GetKeycardByKeycardUID(updatedKeycard1.KeycardUID)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards)) s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycard))
s.Require().True(accounts.SameKeycards(updatedKeycard1, syncedKeycards[0]))
}
func (s *MessengerSyncKeycardChangeSuite) TestUpdatingKeycardUidOldClock() {
senderDb := s.main.settings
dbOnReceiver := s.other.settings
keycard1 := accounts.GetProfileKeycardForTest()
// Add keycard on sender
addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Add the same keycard on receiver
addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
s.Require().NoError(err)
s.Require().Equal(true, addedKc)
s.Require().Equal(false, addedAccs)
// Prepare expected keycard for comparison
updatedKeycard1 := accounts.GetProfileKeycardForTest()
updatedKeycard1.KeycardUID = "00000000000000000000000000000000"
updatedKeycard1.LastUpdateClock = updatedKeycard1.LastUpdateClock - 1
// Update keycard uid on sender
err = s.main.UpdateKeycardUID(context.Background(), keycard1.KeycardUID, updatedKeycard1.KeycardUID,
updatedKeycard1.LastUpdateClock)
s.Require().NoError(err)
// Wait for the response
_, err = WaitOnMessengerResponse(
s.other,
func(r *MessengerResponse) bool {
return len(r.KeycardActions()) == 1
},
"expected to receive keycard activities",
)
s.Require().NoError(err)
senderKeycards, err := senderDb.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(senderKeycards))
s.Require().True(accounts.SameKeycards(keycard1, senderKeycards[0]))
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
s.Require().NoError(err)
s.Require().Equal(1, len(syncedKeycards))
s.Require().True(accounts.SameKeycards(keycard1, syncedKeycards[0]))
} }

View File

@ -79,6 +79,9 @@ func (s *MessengerSyncKeycardsStateSuite) SetupTest() {
kp1 := accounts.GetProfileKeypairForTest(true, true, true) kp1 := accounts.GetProfileKeypairForTest(true, true, true)
kp2 := accounts.GetSeedImportedKeypair1ForTest() kp2 := accounts.GetSeedImportedKeypair1ForTest()
kp3 := accounts.GetSeedImportedKeypair2ForTest() kp3 := accounts.GetSeedImportedKeypair2ForTest()
kp1.Clock = 1
kp2.Clock = 1
kp3.Clock = 1
err = s.main.settings.SaveOrUpdateKeypair(kp1) err = s.main.settings.SaveOrUpdateKeypair(kp1)
s.Require().NoError(err) s.Require().NoError(err)
@ -90,11 +93,15 @@ func (s *MessengerSyncKeycardsStateSuite) SetupTest() {
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Equal(3, len(dbKeypairs)) s.Require().Equal(3, len(dbKeypairs))
err = s.other.SaveOrUpdateKeypair(kp1) kp1.Clock = 0
kp2.Clock = 0
kp3.Clock = 0
err = s.other.settings.SaveOrUpdateKeypair(kp1)
s.Require().NoError(err) s.Require().NoError(err)
err = s.other.SaveOrUpdateKeypair(kp2) err = s.other.settings.SaveOrUpdateKeypair(kp2)
s.Require().NoError(err) s.Require().NoError(err)
err = s.other.SaveOrUpdateKeypair(kp3) err = s.other.settings.SaveOrUpdateKeypair(kp3)
s.Require().NoError(err) s.Require().NoError(err)
dbKeypairs, err = s.other.settings.GetKeypairs() dbKeypairs, err = s.other.settings.GetKeypairs()
s.Require().NoError(err) s.Require().NoError(err)
@ -116,338 +123,173 @@ func (s *MessengerSyncKeycardsStateSuite) newMessenger(shh types.Waku) *Messenge
return messenger return messenger
} }
// TODO: commented tests below will be handled in the seocnd step of planned improvements func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNoKeycards() {
senderDb := s.main.settings
dbOnReceiver := s.other.settings
// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNoKeycards() { keycard1 := accounts.GetProfileKeycardForTest()
// senderDb := s.main.settings
// dbOnReceiver := s.other.settings
// keycard1 := accounts.GetProfileKeycardForTest() keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
// keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
// keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
// keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
// keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1
// keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() // Add keycards on sender
err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
s.Require().NoError(err)
err = senderDb.SaveOrUpdateKeycard(*keycard2, 0, false)
s.Require().NoError(err)
err = senderDb.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
s.Require().NoError(err)
err = senderDb.SaveOrUpdateKeycard(*keycard3, 0, false)
s.Require().NoError(err)
// // Add keycards on sender // Trigger's a sync between devices
// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
// s.Require().NoError(err) s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Trigger's a sync between devices // Wait for the response
// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) _, err = WaitOnMessengerResponse(
// s.Require().NoError(err) s.other,
func(r *MessengerResponse) bool {
success := len(r.Keypairs) == 3
for _, kp := range r.Keypairs {
if kp.KeyUID == keycard1.KeyUID {
success = success && len(kp.Keycards) == 1
} else if kp.KeyUID == keycard2.KeyUID {
success = success && len(kp.Keycards) == 2
} else if kp.KeyUID == keycard3.KeyUID {
success = success && len(kp.Keycards) == 1
}
}
return success
},
"expected to receive keycards",
)
s.Require().NoError(err)
// // Wait for the response syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
// _, err = WaitOnMessengerResponse( s.Require().NoError(err)
// s.other, s.Require().Equal(4, len(syncedKeycards))
// func(r *MessengerResponse) bool { s.Require().True(accounts.Contains(syncedKeycards, keycard1, accounts.SameKeycards))
// success := len(r.Keypairs) == 3 s.Require().True(accounts.Contains(syncedKeycards, keycard2, accounts.SameKeycards))
// for _, kp := range r.Keypairs { s.Require().True(accounts.Contains(syncedKeycards, keycard2Copy, accounts.SameKeycards))
// if kp.KeyUID == keycard1.KeyUID { s.Require().True(accounts.Contains(syncedKeycards, keycard3, accounts.SameKeycards))
// success = success && len(kp.Keycards) == 1 }
// } else if kp.KeyUID == keycard2.KeyUID {
// success = success && len(kp.Keycards) == 2
// } else if kp.KeyUID == keycard3.KeyUID {
// success = success && len(kp.Keycards) == 1
// }
// }
// return success
// },
// "expected to receive keycards",
// )
// s.Require().NoError(err)
// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfKeycardsWereDeletedOnSenderSide() {
// s.Require().NoError(err) senderDb := s.main.settings
// s.Require().Equal(4, len(syncedKeycards)) dbOnReceiver := s.other.settings
// s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycard3, accounts.SameKeycards))
// }
// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsOlderThanSender() { // Add keycards on sender
// senderDb := s.main.settings keycard1 := accounts.GetProfileKeycardForTest()
// dbOnReceiver := s.other.settings
// keycard1 := accounts.GetProfileKeycardForTest() keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
// // Add keycards on sender keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Add keycards on receiver - partially // Add keycards on sender
// keycardR1 := accounts.GetProfileKeycardForTest() err := senderDb.SaveOrUpdateKeycard(*keycard1, 0, false)
// keycardR1.KeycardName = "CardNameToBeChanged-0" s.Require().NoError(err)
// keycardR1.AccountsAddresses = keycardR1.AccountsAddresses[2:3] err = senderDb.SaveOrUpdateKeycard(*keycard2, 0, false)
// keycardR1.LastUpdateClock = keycardR1.LastUpdateClock - 1 s.Require().NoError(err)
// keycardR2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() // Add keycards on receiver
// keycardR2.KeycardName = "CardNameToBeChanged-1" err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
// keycardR2.LastUpdateClock = keycardR2.LastUpdateClock - 1 s.Require().NoError(err)
err = dbOnReceiver.SaveOrUpdateKeycard(*keycard2, 0, false)
s.Require().NoError(err)
err = dbOnReceiver.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
s.Require().NoError(err)
err = dbOnReceiver.SaveOrUpdateKeycard(*keycard3, 0, false)
s.Require().NoError(err)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR1) // Trigger's a sync between devices
// s.Require().NoError(err) err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
// s.Require().Equal(true, addedKc) s.Require().NoError(err)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Trigger's a sync between devices // Wait for the response
// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) _, err = WaitOnMessengerResponse(
// s.Require().NoError(err) s.other,
func(r *MessengerResponse) bool {
success := len(r.Keypairs) == 3
for _, kp := range r.Keypairs {
if kp.KeyUID == keycard1.KeyUID {
success = success && len(kp.Keycards) == 1
} else if kp.KeyUID == keycard2.KeyUID {
success = success && len(kp.Keycards) == 1
}
}
return success
},
"expected to receive keycards",
)
s.Require().NoError(err)
// // Wait for the response syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
// _, err = WaitOnMessengerResponse( s.Require().NoError(err)
// s.other, s.Require().Equal(2, len(syncedKeycards))
// func(r *MessengerResponse) bool { s.Require().True(accounts.Contains(syncedKeycards, keycard1, accounts.SameKeycards))
// success := len(r.Keypairs) == 3 s.Require().True(accounts.Contains(syncedKeycards, keycard2, accounts.SameKeycards))
// for _, kp := range r.Keypairs { }
// if kp.KeyUID == keycardR1.KeyUID {
// success = success && len(kp.Keycards) == 1
// } else if kp.KeyUID == keycardR2.KeyUID {
// success = success && len(kp.Keycards) == 1
// }
// }
// return success
// },
// "expected to receive keycards",
// )
// s.Require().NoError(err)
// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverAndSenderHasNoKeycardsInCommon() {
// s.Require().NoError(err) senderDb := s.main.settings
// s.Require().Equal(2, len(syncedKeycards)) dbOnReceiver := s.other.settings
// s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards))
// }
// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsNewerThanSender() { // Add keycards on sender
// senderDb := s.main.settings keycard1 := accounts.GetProfileKeycardForTest()
// dbOnReceiver := s.other.settings
// keycard1 := accounts.GetProfileKeycardForTest() keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
// // Add keycards on sender keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Add keycards on receiver - partially // Add keycards on sender
// keycardR1 := accounts.GetProfileKeycardForTest() err := senderDb.SaveOrUpdateKeycard(*keycard2, 0, false)
// keycardR1.KeycardName = "CardNameToBeChanged-0" s.Require().NoError(err)
// keycardR1.AccountsAddresses = keycardR1.AccountsAddresses[2:3] err = senderDb.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
// keycardR1.LastUpdateClock = keycardR1.LastUpdateClock + 1 s.Require().NoError(err)
// keycardR2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() // Add keycards on receiver
// keycardR2.KeycardName = "CardNameToBeChanged-1" err = dbOnReceiver.SaveOrUpdateKeycard(*keycard1, 0, false)
// keycardR2.LastUpdateClock = keycardR2.LastUpdateClock + 1 s.Require().NoError(err)
err = dbOnReceiver.SaveOrUpdateKeycard(*keycard3, 0, false)
s.Require().NoError(err)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR1) // Trigger's a sync between devices
// s.Require().NoError(err) err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
// s.Require().Equal(true, addedKc) s.Require().NoError(err)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Trigger's a sync between devices // Wait for the response
// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) _, err = WaitOnMessengerResponse(
// s.Require().NoError(err) s.other,
func(r *MessengerResponse) bool {
success := len(r.Keypairs) == 3
for _, kp := range r.Keypairs {
if kp.KeyUID == keycard2.KeyUID {
success = success && len(kp.Keycards) == 2
}
}
return success
},
"expected to receive keycards",
)
s.Require().NoError(err)
// // Wait for the response syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
// _, err = WaitOnMessengerResponse( s.Require().NoError(err)
// s.other, s.Require().Equal(2, len(syncedKeycards))
// func(r *MessengerResponse) bool { s.Require().True(accounts.Contains(syncedKeycards, keycard2, accounts.SameKeycards))
// success := len(r.Keypairs) == 3 s.Require().True(accounts.Contains(syncedKeycards, keycard2Copy, accounts.SameKeycards))
// for _, kp := range r.Keypairs { }
// if kp.KeyUID == keycardR1.KeyUID {
// success = success && len(kp.Keycards) == 1
// } else if kp.KeyUID == keycardR2.KeyUID {
// success = success && len(kp.Keycards) == 1
// }
// }
// return success
// },
// "expected to receive keycards",
// )
// s.Require().NoError(err)
// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
// s.Require().NoError(err)
// s.Require().Equal(2, len(syncedKeycards))
// s.Require().True(contains(syncedKeycards, keycardR1, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycardR2, accounts.SameKeycards))
// }
// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfKeycardsWereDeletedOnSenderSide() {
// senderDb := s.main.settings
// dbOnReceiver := s.other.settings
// // Add keycards on sender
// keycard1 := accounts.GetProfileKeycardForTest()
// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
// keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
// keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1
// keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
// // Add keycards on sender
// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Add keycards on receiver
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Trigger's a sync between devices
// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
// s.Require().NoError(err)
// // Wait for the response
// _, err = WaitOnMessengerResponse(
// s.other,
// func(r *MessengerResponse) bool {
// success := len(r.Keypairs) == 3
// for _, kp := range r.Keypairs {
// if kp.KeyUID == keycard1.KeyUID {
// success = success && len(kp.Keycards) == 1
// } else if kp.KeyUID == keycard2.KeyUID {
// success = success && len(kp.Keycards) == 1
// }
// }
// return success
// },
// "expected to receive keycards",
// )
// s.Require().NoError(err)
// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
// s.Require().NoError(err)
// s.Require().Equal(2, len(syncedKeycards))
// s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards))
// }
// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverAndSenderHasNoKeycardsInCommon() {
// senderDb := s.main.settings
// dbOnReceiver := s.other.settings
// // Add keycards on sender
// keycard1 := accounts.GetProfileKeycardForTest()
// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
// keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
// keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
// keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1
// keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
// // Add keycards on sender
// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Add keycards on receiver
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3)
// s.Require().NoError(err)
// s.Require().Equal(true, addedKc)
// s.Require().Equal(false, addedAccs)
// // Trigger's a sync between devices
// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
// s.Require().NoError(err)
// // Wait for the response
// _, err = WaitOnMessengerResponse(
// s.other,
// func(r *MessengerResponse) bool {
// success := len(r.Keypairs) == 3
// for _, kp := range r.Keypairs {
// if kp.KeyUID == keycard2.KeyUID {
// success = success && len(kp.Keycards) == 2
// }
// }
// return success
// },
// "expected to receive keycards",
// )
// s.Require().NoError(err)
// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
// s.Require().NoError(err)
// s.Require().Equal(2, len(syncedKeycards))
// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards))
// s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards))
// }

View File

@ -198,7 +198,7 @@ func (m *Messenger) deleteKeystoreFileForAddress(address types.Address) error {
lastAcccountOfKeypairWithTheSameKey := len(kp.Accounts) == 1 lastAcccountOfKeypairWithTheSameKey := len(kp.Accounts) == 1
knownKeycardsForKeyUID, err := m.settings.GetKeycardByKeyUID(acc.KeyUID) knownKeycardsForKeyUID, err := m.settings.GetKeycardsWithSameKeyUID(acc.KeyUID)
if err != nil { if err != nil {
return err return err
} }
@ -219,23 +219,6 @@ func (m *Messenger) deleteKeystoreFileForAddress(address types.Address) error {
} }
} }
} }
} else {
if lastAcccountOfKeypairWithTheSameKey {
knownKeycards, err := m.settings.GetAllKnownKeycards()
if err != nil {
return err
}
for _, kc := range knownKeycards {
if kc.KeyUID == acc.KeyUID {
clock := uint64(time.Now().Unix())
err = m.RemoveMigratedAccountsForKeycard(context.Background(), kc.KeycardUID, kc.AccountsAddresses, clock)
if err != nil {
return err
}
}
}
}
} }
} }

View File

@ -85,13 +85,12 @@ const (
ApplicationMetadataMessage_COMMUNITY_CANCEL_REQUEST_TO_JOIN ApplicationMetadataMessage_Type = 60 ApplicationMetadataMessage_COMMUNITY_CANCEL_REQUEST_TO_JOIN ApplicationMetadataMessage_Type = 60
ApplicationMetadataMessage_CANCEL_CONTACT_VERIFICATION ApplicationMetadataMessage_Type = 61 ApplicationMetadataMessage_CANCEL_CONTACT_VERIFICATION ApplicationMetadataMessage_Type = 61
ApplicationMetadataMessage_SYNC_KEYPAIR ApplicationMetadataMessage_Type = 62 ApplicationMetadataMessage_SYNC_KEYPAIR ApplicationMetadataMessage_Type = 62
ApplicationMetadataMessage_SYNC_KEYCARD_ACTION ApplicationMetadataMessage_Type = 63 ApplicationMetadataMessage_SYNC_SOCIAL_LINKS ApplicationMetadataMessage_Type = 63
ApplicationMetadataMessage_SYNC_SOCIAL_LINKS ApplicationMetadataMessage_Type = 64 ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL ApplicationMetadataMessage_Type = 64
ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL ApplicationMetadataMessage_Type = 65 ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION ApplicationMetadataMessage_Type = 65
ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION ApplicationMetadataMessage_Type = 66 ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE ApplicationMetadataMessage_Type = 66
ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE ApplicationMetadataMessage_Type = 67 ApplicationMetadataMessage_COMMUNITY_ADMIN_MESSAGE ApplicationMetadataMessage_Type = 67
ApplicationMetadataMessage_COMMUNITY_ADMIN_MESSAGE ApplicationMetadataMessage_Type = 68 ApplicationMetadataMessage_COMMUNITY_EDIT_SHARED_ADDRESSES ApplicationMetadataMessage_Type = 68
ApplicationMetadataMessage_COMMUNITY_EDIT_SHARED_ADDRESSES ApplicationMetadataMessage_Type = 69
) )
var ApplicationMetadataMessage_Type_name = map[int32]string{ var ApplicationMetadataMessage_Type_name = map[int32]string{
@ -157,13 +156,12 @@ var ApplicationMetadataMessage_Type_name = map[int32]string{
60: "COMMUNITY_CANCEL_REQUEST_TO_JOIN", 60: "COMMUNITY_CANCEL_REQUEST_TO_JOIN",
61: "CANCEL_CONTACT_VERIFICATION", 61: "CANCEL_CONTACT_VERIFICATION",
62: "SYNC_KEYPAIR", 62: "SYNC_KEYPAIR",
63: "SYNC_KEYCARD_ACTION", 63: "SYNC_SOCIAL_LINKS",
64: "SYNC_SOCIAL_LINKS", 64: "SYNC_ENS_USERNAME_DETAIL",
65: "SYNC_ENS_USERNAME_DETAIL", 65: "SYNC_ACTIVITY_CENTER_NOTIFICATION",
66: "SYNC_ACTIVITY_CENTER_NOTIFICATION", 66: "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE",
67: "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE", 67: "COMMUNITY_ADMIN_MESSAGE",
68: "COMMUNITY_ADMIN_MESSAGE", 68: "COMMUNITY_EDIT_SHARED_ADDRESSES",
69: "COMMUNITY_EDIT_SHARED_ADDRESSES",
} }
var ApplicationMetadataMessage_Type_value = map[string]int32{ var ApplicationMetadataMessage_Type_value = map[string]int32{
@ -229,13 +227,12 @@ var ApplicationMetadataMessage_Type_value = map[string]int32{
"COMMUNITY_CANCEL_REQUEST_TO_JOIN": 60, "COMMUNITY_CANCEL_REQUEST_TO_JOIN": 60,
"CANCEL_CONTACT_VERIFICATION": 61, "CANCEL_CONTACT_VERIFICATION": 61,
"SYNC_KEYPAIR": 62, "SYNC_KEYPAIR": 62,
"SYNC_KEYCARD_ACTION": 63, "SYNC_SOCIAL_LINKS": 63,
"SYNC_SOCIAL_LINKS": 64, "SYNC_ENS_USERNAME_DETAIL": 64,
"SYNC_ENS_USERNAME_DETAIL": 65, "SYNC_ACTIVITY_CENTER_NOTIFICATION": 65,
"SYNC_ACTIVITY_CENTER_NOTIFICATION": 66, "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE": 66,
"SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE": 67, "COMMUNITY_ADMIN_MESSAGE": 67,
"COMMUNITY_ADMIN_MESSAGE": 68, "COMMUNITY_EDIT_SHARED_ADDRESSES": 68,
"COMMUNITY_EDIT_SHARED_ADDRESSES": 69,
} }
func (x ApplicationMetadataMessage_Type) String() string { func (x ApplicationMetadataMessage_Type) String() string {
@ -314,67 +311,67 @@ func init() {
} }
var fileDescriptor_ad09a6406fcf24c7 = []byte{ var fileDescriptor_ad09a6406fcf24c7 = []byte{
// 990 bytes of a gzipped FileDescriptorProto // 982 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x6b, 0x73, 0x53, 0x37, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x6d, 0x73, 0x13, 0x37,
0x10, 0x6d, 0x80, 0x26, 0xa0, 0xbc, 0x36, 0x22, 0x0f, 0xe7, 0x9d, 0x18, 0x08, 0x01, 0x5a, 0xd3, 0x10, 0x6e, 0x80, 0xf2, 0xa2, 0xbc, 0x6d, 0x44, 0x5e, 0x9c, 0xf7, 0xc4, 0x40, 0x08, 0xd0, 0x9a,
0x42, 0xdb, 0x69, 0x4b, 0x69, 0x2b, 0x4b, 0x1b, 0x5b, 0xf8, 0x5e, 0xdd, 0x8b, 0xa4, 0xeb, 0x8e, 0x16, 0xda, 0x4e, 0x5b, 0x4a, 0x5b, 0x59, 0xda, 0xc4, 0xc2, 0x77, 0xd2, 0x21, 0xe9, 0xdc, 0x71,
0xfb, 0x45, 0x63, 0x8a, 0xcb, 0x64, 0x06, 0x88, 0x87, 0x98, 0x0f, 0xf9, 0x85, 0xfd, 0x15, 0xfd, 0xbf, 0x68, 0x4c, 0x71, 0x99, 0xcc, 0x00, 0xf1, 0x10, 0xf3, 0x21, 0x7f, 0xaa, 0xbf, 0xa2, 0x3f,
0x2f, 0x1d, 0xdd, 0xa7, 0x93, 0x38, 0xcd, 0xa7, 0xc4, 0xbb, 0x47, 0x2b, 0xed, 0xd9, 0xb3, 0xe7, 0xac, 0xa3, 0x3b, 0xdf, 0x9d, 0x93, 0x38, 0xcd, 0xa7, 0xc4, 0xfb, 0x3c, 0x5a, 0x69, 0x9f, 0x7d,
0x92, 0x7a, 0x7f, 0x38, 0x7c, 0x7f, 0xfc, 0x57, 0x7f, 0x74, 0x7c, 0xf2, 0xd1, 0x7d, 0x18, 0x8c, 0x76, 0x8f, 0xd4, 0x7b, 0x83, 0xc1, 0xfb, 0xa3, 0xbf, 0x7a, 0xc3, 0xa3, 0xe3, 0x8f, 0xfe, 0x43,
0xfa, 0x6f, 0xfb, 0xa3, 0xbe, 0xfb, 0x30, 0x38, 0x3d, 0xed, 0xbf, 0x1b, 0x34, 0x86, 0x9f, 0x4e, 0x7f, 0xd8, 0x7b, 0xdb, 0x1b, 0xf6, 0xfc, 0x87, 0xfe, 0xc9, 0x49, 0xef, 0x5d, 0xbf, 0x31, 0xf8,
0x46, 0x27, 0xf4, 0x76, 0xfa, 0xe7, 0xcd, 0xe7, 0xbf, 0xeb, 0xff, 0x02, 0xd9, 0x60, 0xd5, 0x81, 0x74, 0x3c, 0x3c, 0xa6, 0xb7, 0xb3, 0x3f, 0x6f, 0x3e, 0xff, 0x5d, 0xff, 0x17, 0xc8, 0x1a, 0xab,
0x30, 0xc7, 0x87, 0x19, 0x9c, 0x6e, 0x91, 0x3b, 0xa7, 0xc7, 0xef, 0x3e, 0xf6, 0x47, 0x9f, 0x3f, 0x0e, 0xc4, 0x23, 0x7e, 0x9c, 0xd3, 0xe9, 0x06, 0xb9, 0x73, 0x72, 0xf4, 0xee, 0x63, 0x6f, 0xf8,
0x0d, 0x6a, 0x53, 0x7b, 0x53, 0x87, 0x73, 0xba, 0x0a, 0xd0, 0x1a, 0x99, 0x19, 0xf6, 0xcf, 0xde, 0xf9, 0x53, 0xbf, 0x36, 0xb5, 0x33, 0xb5, 0x3f, 0x63, 0xaa, 0x00, 0xad, 0x91, 0x5b, 0x83, 0xde,
0x9f, 0xf4, 0xdf, 0xd6, 0x6e, 0xa4, 0xb9, 0xe2, 0x27, 0x7d, 0x49, 0x6e, 0x8d, 0xce, 0x86, 0x83, 0xe9, 0xfb, 0xe3, 0xde, 0xdb, 0xda, 0xb5, 0x0c, 0x2b, 0x7e, 0xd2, 0x97, 0xe4, 0xc6, 0xf0, 0x74,
0xda, 0xcd, 0xbd, 0xa9, 0xc3, 0x85, 0x67, 0x8f, 0x1a, 0xc5, 0x7d, 0x8d, 0xab, 0xef, 0x6a, 0xd8, 0xd0, 0xaf, 0x5d, 0xdf, 0x99, 0xda, 0x9f, 0x7b, 0xf6, 0xa8, 0x51, 0xdc, 0xd7, 0xb8, 0xfc, 0xae,
0xb3, 0xe1, 0x40, 0xa7, 0xc7, 0xea, 0xff, 0x2c, 0x92, 0x5b, 0xfe, 0x27, 0x9d, 0x25, 0x33, 0x89, 0x86, 0x3b, 0x1d, 0xf4, 0x4d, 0x76, 0xac, 0xfe, 0xcf, 0x3c, 0xb9, 0x11, 0x7e, 0xd2, 0x69, 0x72,
0xea, 0xa8, 0xe8, 0x0f, 0x05, 0x5f, 0x50, 0x20, 0x73, 0xbc, 0xcd, 0xac, 0x0b, 0xd1, 0x18, 0xd6, 0x2b, 0x55, 0x6d, 0xa5, 0xff, 0x50, 0xf0, 0x05, 0x05, 0x32, 0xc3, 0x5b, 0xcc, 0xf9, 0x18, 0xad,
0x42, 0x98, 0xa2, 0x94, 0x2c, 0xf0, 0x48, 0x59, 0xc6, 0xad, 0x4b, 0x62, 0xc1, 0x2c, 0xc2, 0x0d, 0x65, 0x87, 0x08, 0x53, 0x94, 0x92, 0x39, 0xae, 0x95, 0x63, 0xdc, 0xf9, 0x34, 0x11, 0xcc, 0x21,
0xba, 0x4d, 0xd6, 0x43, 0x0c, 0x9b, 0xa8, 0x4d, 0x5b, 0xc6, 0x79, 0xb8, 0x3c, 0x72, 0x93, 0xae, 0x5c, 0xa3, 0x9b, 0x64, 0x35, 0xc6, 0xb8, 0x89, 0xc6, 0xb6, 0x64, 0x32, 0x0a, 0x97, 0x47, 0xae,
0x90, 0xa5, 0x98, 0x49, 0xed, 0xa4, 0x32, 0x96, 0x05, 0x01, 0xb3, 0x32, 0x52, 0x70, 0xcb, 0x87, 0xd3, 0x25, 0xb2, 0x90, 0x30, 0x69, 0xbc, 0x54, 0xd6, 0xb1, 0x28, 0x62, 0x4e, 0x6a, 0x05, 0x37,
0x4d, 0x4f, 0xf1, 0xf3, 0xe1, 0x2f, 0xe9, 0x3d, 0xb2, 0xab, 0xf1, 0x75, 0x82, 0xc6, 0x3a, 0x26, 0x42, 0xd8, 0x76, 0x15, 0x3f, 0x1b, 0xfe, 0x92, 0xde, 0x23, 0xdb, 0x06, 0x5f, 0xa7, 0x68, 0x9d,
0x84, 0x46, 0x63, 0xdc, 0x51, 0xa4, 0x9d, 0xd5, 0x4c, 0x19, 0xc6, 0x53, 0xd0, 0x34, 0x7d, 0x4c, 0x67, 0x42, 0x18, 0xb4, 0xd6, 0x1f, 0x68, 0xe3, 0x9d, 0x61, 0xca, 0x32, 0x9e, 0x91, 0x6e, 0xd2,
0x0e, 0x18, 0xe7, 0x18, 0x5b, 0x77, 0x1d, 0x76, 0x86, 0x3e, 0x21, 0x0f, 0x05, 0xf2, 0x40, 0x2a, 0xc7, 0x64, 0x8f, 0x71, 0x8e, 0x89, 0xf3, 0x57, 0x71, 0x6f, 0xd1, 0x27, 0xe4, 0xa1, 0x40, 0x1e,
0xbc, 0x16, 0x7c, 0x9b, 0xae, 0x91, 0xbb, 0x05, 0x68, 0x3c, 0x71, 0x87, 0x2e, 0x13, 0x30, 0xa8, 0x49, 0x85, 0x57, 0x92, 0x6f, 0xd3, 0x15, 0x72, 0xb7, 0x20, 0x8d, 0x03, 0x77, 0xe8, 0x22, 0x01,
0xc4, 0xb9, 0x28, 0xa1, 0xbb, 0x64, 0xf3, 0x62, 0xed, 0x71, 0xc0, 0xac, 0xa7, 0xe6, 0x52, 0x93, 0x8b, 0x4a, 0x9c, 0x89, 0x12, 0xba, 0x4d, 0xd6, 0xcf, 0xe7, 0x1e, 0x27, 0x4c, 0x07, 0x69, 0x2e,
0x2e, 0x27, 0x10, 0xe6, 0x26, 0xa7, 0x19, 0xe7, 0x51, 0xa2, 0x2c, 0xcc, 0xd3, 0x7d, 0xb2, 0x7d, 0x14, 0xe9, 0x47, 0x02, 0xc2, 0xcc, 0x64, 0x98, 0x71, 0xae, 0x53, 0xe5, 0x60, 0x96, 0xee, 0x92,
0x39, 0x1d, 0x27, 0xcd, 0x40, 0x72, 0xe7, 0xe7, 0x02, 0x0b, 0x74, 0x87, 0x6c, 0x14, 0xf3, 0xe0, 0xcd, 0x8b, 0x70, 0x92, 0x36, 0x23, 0xc9, 0x7d, 0xe8, 0x0b, 0xcc, 0xd1, 0x2d, 0xb2, 0x56, 0xf4,
0x91, 0x40, 0xc7, 0x44, 0x17, 0xb5, 0x95, 0x06, 0x43, 0x54, 0x16, 0x16, 0x69, 0x9d, 0xec, 0xc4, 0x83, 0x6b, 0x81, 0x9e, 0x89, 0x0e, 0x1a, 0x27, 0x2d, 0xc6, 0xa8, 0x1c, 0xcc, 0xd3, 0x3a, 0xd9,
0x89, 0x69, 0x3b, 0x15, 0x59, 0x79, 0x24, 0x79, 0x56, 0x42, 0x63, 0x4b, 0x1a, 0xab, 0x33, 0xca, 0x4a, 0x52, 0xdb, 0xf2, 0x4a, 0x3b, 0x79, 0x20, 0x79, 0x9e, 0xc2, 0xe0, 0xa1, 0xb4, 0xce, 0xe4,
0xc1, 0x33, 0xf4, 0xff, 0x18, 0xa7, 0xd1, 0xc4, 0x91, 0x32, 0x08, 0x4b, 0x74, 0x93, 0xac, 0x5d, 0x92, 0x43, 0x50, 0xe8, 0xff, 0x39, 0xde, 0xa0, 0x4d, 0xb4, 0xb2, 0x08, 0x0b, 0x74, 0x9d, 0xac,
0x06, 0xbf, 0x4e, 0x50, 0xf7, 0x80, 0xd2, 0xfb, 0x64, 0xef, 0x8a, 0x64, 0x55, 0xe2, 0xae, 0xef, 0x5c, 0x24, 0xbf, 0x4e, 0xd1, 0x74, 0x81, 0xd2, 0xfb, 0x64, 0xe7, 0x12, 0xb0, 0x4a, 0x71, 0x37,
0x7a, 0xd2, 0x7d, 0x29, 0x7f, 0xb0, 0xec, 0x5b, 0x9a, 0x94, 0xce, 0x8f, 0xaf, 0x78, 0x09, 0x62, 0x54, 0x3d, 0xe9, 0xbe, 0x4c, 0x3f, 0x58, 0x0c, 0x25, 0x4d, 0x82, 0x47, 0xc7, 0x97, 0x82, 0x05,
0x18, 0xbd, 0x92, 0x4e, 0x63, 0xce, 0xf3, 0x2a, 0x5d, 0x27, 0x2b, 0x2d, 0x1d, 0x25, 0x71, 0x4a, 0x31, 0xd6, 0xaf, 0xa4, 0x37, 0x38, 0xd2, 0x79, 0x99, 0xae, 0x92, 0xa5, 0x43, 0xa3, 0xd3, 0x24,
0x8b, 0x93, 0xaa, 0x2b, 0x6d, 0xd6, 0xdd, 0x1a, 0x5d, 0x22, 0xf3, 0x59, 0x50, 0xa0, 0xb2, 0xd2, 0x93, 0xc5, 0x4b, 0xd5, 0x91, 0x2e, 0xaf, 0x6e, 0x85, 0x2e, 0x90, 0xd9, 0x3c, 0x28, 0x50, 0x39,
0xf6, 0xa0, 0xe6, 0xd1, 0x3c, 0x0a, 0xc3, 0x44, 0x49, 0xdb, 0x73, 0x02, 0x0d, 0xd7, 0x32, 0x4e, 0xe9, 0xba, 0x50, 0x0b, 0x6c, 0xae, 0xe3, 0x38, 0x55, 0xd2, 0x75, 0xbd, 0x40, 0xcb, 0x8d, 0x4c,
0xd1, 0xeb, 0xb4, 0x46, 0x96, 0xab, 0xd4, 0x58, 0x9d, 0x0d, 0xff, 0xea, 0x2a, 0x53, 0x4e, 0x3b, 0x32, 0xf6, 0x2a, 0xad, 0x91, 0xc5, 0x0a, 0x1a, 0xcb, 0xb3, 0x16, 0x5e, 0x5d, 0x21, 0x65, 0xb7,
0x72, 0xaf, 0x22, 0xa9, 0x60, 0x93, 0x2e, 0x92, 0xd9, 0x58, 0xaa, 0x52, 0xf6, 0x5b, 0x7e, 0x77, 0xb5, 0x7f, 0xa5, 0xa5, 0x82, 0x75, 0x3a, 0x4f, 0xa6, 0x13, 0xa9, 0x4a, 0xdb, 0x6f, 0x84, 0xd9,
0x50, 0xc8, 0x6a, 0x77, 0xb6, 0xfd, 0x4b, 0x8c, 0x65, 0x36, 0x31, 0xc5, 0xea, 0xec, 0xf8, 0x5e, 0x41, 0x21, 0xab, 0xd9, 0xd9, 0x0c, 0x2f, 0xb1, 0x8e, 0xb9, 0xd4, 0x16, 0xa3, 0xb3, 0x15, 0x6a,
0x04, 0x06, 0x38, 0xb6, 0x2f, 0xbb, 0x5e, 0x54, 0x93, 0x34, 0x93, 0x5f, 0x0d, 0x7b, 0x74, 0x83, 0x11, 0x18, 0xe1, 0xd8, 0xbc, 0x6c, 0x07, 0x53, 0x4d, 0xf2, 0xcc, 0xe8, 0x6a, 0xd8, 0xa1, 0x6b,
0xac, 0x32, 0x15, 0xa9, 0x5e, 0x18, 0x25, 0xc6, 0x85, 0x68, 0xb5, 0xe4, 0xae, 0xc9, 0x2c, 0x6f, 0x64, 0x99, 0x29, 0xad, 0xba, 0xb1, 0x4e, 0xad, 0x8f, 0xd1, 0x19, 0xc9, 0x7d, 0x93, 0x39, 0xde,
0xc3, 0x7e, 0xb9, 0x55, 0x69, 0xcb, 0x1a, 0xc3, 0xa8, 0x8b, 0x02, 0xea, 0x7e, 0x6a, 0x55, 0x38, 0x82, 0xdd, 0x72, 0xaa, 0xb2, 0x92, 0x0d, 0xc6, 0xba, 0x83, 0x02, 0xea, 0xa1, 0x6b, 0x55, 0x78,
0xbf, 0xca, 0x78, 0x02, 0x05, 0xdc, 0xa3, 0x84, 0x4c, 0x37, 0x19, 0xef, 0x24, 0x31, 0xdc, 0x2f, 0x74, 0x95, 0x0d, 0x02, 0x0a, 0xb8, 0x47, 0x09, 0xb9, 0xd9, 0x64, 0xbc, 0x9d, 0x26, 0x70, 0xbf,
0x15, 0xe9, 0x99, 0xed, 0xfa, 0x4e, 0x39, 0x2a, 0x8b, 0x3a, 0x83, 0x3e, 0x28, 0x15, 0x79, 0x31, 0x74, 0x64, 0x50, 0xb6, 0x13, 0x2a, 0xe5, 0xa8, 0x1c, 0x9a, 0x9c, 0xfa, 0xa0, 0x74, 0xe4, 0x79,
0x9d, 0x6d, 0x23, 0x0a, 0x38, 0xf0, 0x8a, 0x9b, 0x08, 0x11, 0xd2, 0x84, 0xd2, 0x18, 0x14, 0xf0, 0x38, 0x9f, 0x46, 0x14, 0xb0, 0x17, 0x1c, 0x37, 0x91, 0x22, 0xa4, 0x8d, 0xa5, 0xb5, 0x28, 0xe0,
0x30, 0x65, 0xc2, 0x63, 0x9a, 0x51, 0xd4, 0x09, 0x99, 0xee, 0xc0, 0x21, 0x5d, 0x25, 0x34, 0x7b, 0x61, 0xa6, 0x44, 0xe0, 0x34, 0xb5, 0x6e, 0xc7, 0xcc, 0xb4, 0x61, 0x9f, 0x2e, 0x13, 0x9a, 0xbf,
0x61, 0x80, 0x4c, 0xbb, 0xb6, 0x34, 0x36, 0xd2, 0x3d, 0x78, 0xe4, 0x69, 0x4c, 0xe3, 0x06, 0xad, 0x30, 0x42, 0x66, 0x7c, 0x4b, 0x5a, 0xa7, 0x4d, 0x17, 0x1e, 0x05, 0x19, 0xb3, 0xb8, 0x45, 0xe7,
0x95, 0xaa, 0x05, 0x8f, 0xe9, 0x1e, 0xd9, 0xaa, 0x06, 0xc1, 0x34, 0x6f, 0xcb, 0x2e, 0xba, 0x90, 0xa4, 0x3a, 0x84, 0xc7, 0x74, 0x87, 0x6c, 0x54, 0x8d, 0x60, 0x86, 0xb7, 0x64, 0x07, 0x7d, 0xcc,
0xb5, 0x14, 0xda, 0x40, 0xaa, 0x0e, 0x3c, 0xf1, 0x43, 0x4c, 0xcf, 0xc4, 0x3a, 0x3a, 0x92, 0x01, 0x0e, 0x15, 0xba, 0x48, 0xaa, 0x36, 0x3c, 0x09, 0x4d, 0xcc, 0xce, 0x24, 0x46, 0x1f, 0xc8, 0x08,
0xba, 0x58, 0x72, 0x9b, 0x68, 0x84, 0xaf, 0xca, 0x6a, 0xc5, 0x8e, 0x7d, 0x9d, 0x92, 0x99, 0x59, 0x7d, 0x22, 0xb9, 0x4b, 0x0d, 0xc2, 0x57, 0x65, 0xb6, 0x62, 0xc6, 0xbe, 0xce, 0xc4, 0xcc, 0x57,
0x49, 0xb1, 0x47, 0x85, 0x12, 0x1b, 0x9e, 0x35, 0x8d, 0x56, 0x67, 0xcb, 0x75, 0x3e, 0xf9, 0x94, 0x49, 0x31, 0x47, 0x85, 0x13, 0x1b, 0x41, 0x35, 0x83, 0xce, 0xe4, 0xc3, 0x75, 0x16, 0x7c, 0x4a,
0x1e, 0x90, 0xfa, 0x95, 0x7a, 0xa8, 0xe4, 0xfa, 0x4d, 0x45, 0x7d, 0x09, 0xce, 0x5b, 0x31, 0xf0, 0xf7, 0x48, 0xfd, 0x52, 0x3f, 0x54, 0x76, 0xfd, 0xa6, 0x92, 0xbe, 0x24, 0x8f, 0x4a, 0xb1, 0xf0,
0xad, 0xef, 0xa5, 0x38, 0x5a, 0xdc, 0xd0, 0x45, 0x5d, 0xca, 0x1e, 0x9e, 0x79, 0x35, 0x5c, 0x78, 0x6d, 0xa8, 0xa5, 0x38, 0x5a, 0xdc, 0xd0, 0x41, 0x53, 0xda, 0x1e, 0x9e, 0x05, 0x37, 0x9c, 0x7b,
0xdf, 0x39, 0xc0, 0x73, 0x5f, 0xa2, 0xf0, 0xa0, 0x89, 0x88, 0xef, 0x4a, 0x4d, 0x58, 0x9d, 0x18, 0xdf, 0x19, 0xc2, 0xf3, 0x90, 0xa2, 0xd8, 0x41, 0x13, 0x19, 0xdf, 0x95, 0x9e, 0x70, 0x26, 0xb5,
0x8b, 0xc2, 0x25, 0x06, 0x35, 0x7c, 0x5f, 0x8e, 0x7a, 0x1c, 0x5d, 0xf6, 0xf7, 0x43, 0x39, 0xea, 0x0e, 0x85, 0x4f, 0x2d, 0x1a, 0xf8, 0xbe, 0x6c, 0xf5, 0x38, 0xbb, 0xac, 0xef, 0x87, 0xb2, 0xd5,
0x0b, 0x9d, 0x3b, 0x81, 0x5c, 0x1a, 0x5f, 0xf8, 0xc7, 0xcc, 0x7c, 0x26, 0x50, 0x10, 0x20, 0xeb, 0xe7, 0x2a, 0xf7, 0x02, 0xb9, 0xb4, 0x21, 0xf1, 0x8f, 0xf9, 0xf2, 0x99, 0x20, 0x41, 0x84, 0xac,
0x22, 0xfc, 0xe4, 0xf3, 0x69, 0x89, 0x5c, 0xe2, 0xde, 0x6e, 0xc3, 0x4a, 0xe9, 0x3f, 0x97, 0x33, 0x83, 0xf0, 0x53, 0xc0, 0xb3, 0x14, 0x23, 0x8b, 0x87, 0x75, 0x1b, 0x57, 0x4e, 0xff, 0xb9, 0xec,
0x37, 0xac, 0x8b, 0xa2, 0x70, 0x65, 0x78, 0xe1, 0x6d, 0xa4, 0xaa, 0xcb, 0x99, 0xe2, 0x18, 0x5c, 0xb9, 0x65, 0x1d, 0x14, 0xc5, 0x56, 0x86, 0x17, 0x61, 0x8d, 0x54, 0x79, 0x39, 0x53, 0x1c, 0xa3,
0xda, 0xb8, 0x5f, 0x3c, 0x33, 0x79, 0x6e, 0x62, 0xdf, 0x2f, 0xcb, 0x61, 0x77, 0xb0, 0xe7, 0x3f, 0x0b, 0x13, 0xf7, 0x4b, 0x50, 0x66, 0x84, 0x4d, 0xac, 0xfb, 0x65, 0xd9, 0xec, 0x36, 0x76, 0xc3,
0x40, 0xf0, 0xab, 0xb7, 0xf7, 0x22, 0xc2, 0x99, 0x16, 0x2e, 0xf7, 0x8f, 0xdf, 0x4a, 0x8a, 0x4c, 0x07, 0x08, 0x7e, 0x2d, 0x95, 0xb0, 0x9a, 0x4b, 0x16, 0xf9, 0x60, 0x17, 0x0b, 0xbf, 0xd1, 0x0d,
0xc4, 0x25, 0x0b, 0x9c, 0xd7, 0x91, 0x81, 0xdf, 0xe9, 0x16, 0xa9, 0xa5, 0x61, 0x54, 0x26, 0x65, 0x52, 0xcb, 0xc2, 0xa8, 0x6c, 0x26, 0x8e, 0x62, 0x31, 0x7a, 0x81, 0x8e, 0xc9, 0x08, 0x7e, 0xa7,
0x4d, 0xb1, 0x10, 0x9d, 0x40, 0xcb, 0x64, 0x00, 0x8c, 0x3e, 0x20, 0xfb, 0x13, 0x95, 0x3e, 0x6e, 0x0f, 0xc8, 0xee, 0x44, 0x43, 0x8f, 0xef, 0x27, 0x60, 0x61, 0x8b, 0x5e, 0x49, 0xf3, 0x61, 0xfe,
0x5c, 0xd0, 0xf4, 0xf6, 0x7a, 0x2d, 0xcc, 0x79, 0x63, 0x40, 0xe0, 0x5e, 0x2d, 0x63, 0xe2, 0x16, 0x11, 0x9a, 0xc1, 0x14, 0x63, 0x1e, 0x16, 0xf1, 0xd8, 0xe6, 0xe0, 0xe1, 0x13, 0x58, 0x81, 0xd9,
0xe1, 0x98, 0xa5, 0x08, 0xff, 0x6d, 0xac, 0x92, 0xa9, 0xb9, 0x98, 0x36, 0xd3, 0x15, 0x75, 0x68, 0x0e, 0xb1, 0x2d, 0x66, 0x2a, 0x85, 0xd0, 0x82, 0x68, 0xce, 0xfe, 0x39, 0xdd, 0x78, 0xfa, 0xa2,
0x00, 0x9b, 0xf3, 0x7f, 0xce, 0x36, 0x9e, 0xbe, 0x28, 0x3e, 0xff, 0x6f, 0xa6, 0xd3, 0xff, 0x9e, 0xf8, 0xca, 0xbf, 0xb9, 0x99, 0xfd, 0xf7, 0xfc, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xad,
0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xcd, 0xaa, 0x54, 0xe4, 0xa5, 0x08, 0x00, 0x00, 0xe6, 0x80, 0x8c, 0x08, 0x00, 0x00,
} }

View File

@ -75,12 +75,11 @@ message ApplicationMetadataMessage {
COMMUNITY_CANCEL_REQUEST_TO_JOIN = 60; COMMUNITY_CANCEL_REQUEST_TO_JOIN = 60;
CANCEL_CONTACT_VERIFICATION = 61; CANCEL_CONTACT_VERIFICATION = 61;
SYNC_KEYPAIR = 62; SYNC_KEYPAIR = 62;
SYNC_KEYCARD_ACTION = 63; SYNC_SOCIAL_LINKS = 63;
SYNC_SOCIAL_LINKS = 64; SYNC_ENS_USERNAME_DETAIL = 64;
SYNC_ENS_USERNAME_DETAIL = 65; SYNC_ACTIVITY_CENTER_NOTIFICATION = 65;
SYNC_ACTIVITY_CENTER_NOTIFICATION = 66; SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE = 66;
SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE = 67; COMMUNITY_ADMIN_MESSAGE = 67;
COMMUNITY_ADMIN_MESSAGE = 68; COMMUNITY_EDIT_SHARED_ADDRESSES = 68;
COMMUNITY_EDIT_SHARED_ADDRESSES = 69;
} }
} }

View File

@ -230,49 +230,6 @@ func (SyncContactRequestDecision_DecisionStatus) EnumDescriptor() ([]byte, []int
return fileDescriptor_d61ab7221f0b5518, []int{32, 0} return fileDescriptor_d61ab7221f0b5518, []int{32, 0}
} }
type SyncKeycardAction_Action int32
const (
SyncKeycardAction_KEYCARD_ADDED SyncKeycardAction_Action = 0
SyncKeycardAction_ACCOUNTS_ADDED SyncKeycardAction_Action = 1
SyncKeycardAction_KEYCARD_DELETED SyncKeycardAction_Action = 2
SyncKeycardAction_ACCOUNTS_REMOVED SyncKeycardAction_Action = 3
SyncKeycardAction_LOCKED SyncKeycardAction_Action = 4
SyncKeycardAction_UNLOCKED SyncKeycardAction_Action = 5
SyncKeycardAction_UID_UPDATED SyncKeycardAction_Action = 6
SyncKeycardAction_NAME_CHANGED SyncKeycardAction_Action = 7
)
var SyncKeycardAction_Action_name = map[int32]string{
0: "KEYCARD_ADDED",
1: "ACCOUNTS_ADDED",
2: "KEYCARD_DELETED",
3: "ACCOUNTS_REMOVED",
4: "LOCKED",
5: "UNLOCKED",
6: "UID_UPDATED",
7: "NAME_CHANGED",
}
var SyncKeycardAction_Action_value = map[string]int32{
"KEYCARD_ADDED": 0,
"ACCOUNTS_ADDED": 1,
"KEYCARD_DELETED": 2,
"ACCOUNTS_REMOVED": 3,
"LOCKED": 4,
"UNLOCKED": 5,
"UID_UPDATED": 6,
"NAME_CHANGED": 7,
}
func (x SyncKeycardAction_Action) String() string {
return proto.EnumName(SyncKeycardAction_Action_name, int32(x))
}
func (SyncKeycardAction_Action) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_d61ab7221f0b5518, []int{37, 0}
}
// `FetchingBackedUpDataDetails` is used to describe how many messages a single backup data structure consists of // `FetchingBackedUpDataDetails` is used to describe how many messages a single backup data structure consists of
type FetchingBackedUpDataDetails struct { type FetchingBackedUpDataDetails struct {
DataNumber uint32 `protobuf:"varint,1,opt,name=data_number,json=dataNumber,proto3" json:"data_number,omitempty"` DataNumber uint32 `protobuf:"varint,1,opt,name=data_number,json=dataNumber,proto3" json:"data_number,omitempty"`
@ -3214,7 +3171,7 @@ type SyncKeycard struct {
Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"`
KeyUid string `protobuf:"bytes,4,opt,name=key_uid,json=keyUid,proto3" json:"key_uid,omitempty"` KeyUid string `protobuf:"bytes,4,opt,name=key_uid,json=keyUid,proto3" json:"key_uid,omitempty"`
Addresses [][]byte `protobuf:"bytes,5,rep,name=addresses,proto3" json:"addresses,omitempty"` Addresses [][]byte `protobuf:"bytes,5,rep,name=addresses,proto3" json:"addresses,omitempty"`
Clock uint64 `protobuf:"varint,6,opt,name=clock,proto3" json:"clock,omitempty"` Position uint64 `protobuf:"varint,6,opt,name=position,proto3" json:"position,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -3280,68 +3237,13 @@ func (m *SyncKeycard) GetAddresses() [][]byte {
return nil return nil
} }
func (m *SyncKeycard) GetClock() uint64 { func (m *SyncKeycard) GetPosition() uint64 {
if m != nil { if m != nil {
return m.Clock return m.Position
} }
return 0 return 0
} }
type SyncKeycardAction struct {
Action SyncKeycardAction_Action `protobuf:"varint,1,opt,name=action,proto3,enum=protobuf.SyncKeycardAction_Action" json:"action,omitempty"`
OldKeycardUid string `protobuf:"bytes,2,opt,name=oldKeycardUid,proto3" json:"oldKeycardUid,omitempty"`
Keycard *SyncKeycard `protobuf:"bytes,3,opt,name=keycard,proto3" json:"keycard,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SyncKeycardAction) Reset() { *m = SyncKeycardAction{} }
func (m *SyncKeycardAction) String() string { return proto.CompactTextString(m) }
func (*SyncKeycardAction) ProtoMessage() {}
func (*SyncKeycardAction) Descriptor() ([]byte, []int) {
return fileDescriptor_d61ab7221f0b5518, []int{37}
}
func (m *SyncKeycardAction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SyncKeycardAction.Unmarshal(m, b)
}
func (m *SyncKeycardAction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SyncKeycardAction.Marshal(b, m, deterministic)
}
func (m *SyncKeycardAction) XXX_Merge(src proto.Message) {
xxx_messageInfo_SyncKeycardAction.Merge(m, src)
}
func (m *SyncKeycardAction) XXX_Size() int {
return xxx_messageInfo_SyncKeycardAction.Size(m)
}
func (m *SyncKeycardAction) XXX_DiscardUnknown() {
xxx_messageInfo_SyncKeycardAction.DiscardUnknown(m)
}
var xxx_messageInfo_SyncKeycardAction proto.InternalMessageInfo
func (m *SyncKeycardAction) GetAction() SyncKeycardAction_Action {
if m != nil {
return m.Action
}
return SyncKeycardAction_KEYCARD_ADDED
}
func (m *SyncKeycardAction) GetOldKeycardUid() string {
if m != nil {
return m.OldKeycardUid
}
return ""
}
func (m *SyncKeycardAction) GetKeycard() *SyncKeycard {
if m != nil {
return m.Keycard
}
return nil
}
type SyncSocialLinks struct { type SyncSocialLinks struct {
SocialLinks []*SocialLink `protobuf:"bytes,1,rep,name=social_links,json=socialLinks,proto3" json:"social_links,omitempty"` SocialLinks []*SocialLink `protobuf:"bytes,1,rep,name=social_links,json=socialLinks,proto3" json:"social_links,omitempty"`
Clock uint64 `protobuf:"varint,2,opt,name=clock,proto3" json:"clock,omitempty"` Clock uint64 `protobuf:"varint,2,opt,name=clock,proto3" json:"clock,omitempty"`
@ -3354,7 +3256,7 @@ func (m *SyncSocialLinks) Reset() { *m = SyncSocialLinks{} }
func (m *SyncSocialLinks) String() string { return proto.CompactTextString(m) } func (m *SyncSocialLinks) String() string { return proto.CompactTextString(m) }
func (*SyncSocialLinks) ProtoMessage() {} func (*SyncSocialLinks) ProtoMessage() {}
func (*SyncSocialLinks) Descriptor() ([]byte, []int) { func (*SyncSocialLinks) Descriptor() ([]byte, []int) {
return fileDescriptor_d61ab7221f0b5518, []int{38} return fileDescriptor_d61ab7221f0b5518, []int{37}
} }
func (m *SyncSocialLinks) XXX_Unmarshal(b []byte) error { func (m *SyncSocialLinks) XXX_Unmarshal(b []byte) error {
@ -3396,7 +3298,6 @@ func init() {
proto.RegisterEnum("protobuf.SyncTrustedUser_TrustStatus", SyncTrustedUser_TrustStatus_name, SyncTrustedUser_TrustStatus_value) proto.RegisterEnum("protobuf.SyncTrustedUser_TrustStatus", SyncTrustedUser_TrustStatus_name, SyncTrustedUser_TrustStatus_value)
proto.RegisterEnum("protobuf.SyncVerificationRequest_VerificationStatus", SyncVerificationRequest_VerificationStatus_name, SyncVerificationRequest_VerificationStatus_value) proto.RegisterEnum("protobuf.SyncVerificationRequest_VerificationStatus", SyncVerificationRequest_VerificationStatus_name, SyncVerificationRequest_VerificationStatus_value)
proto.RegisterEnum("protobuf.SyncContactRequestDecision_DecisionStatus", SyncContactRequestDecision_DecisionStatus_name, SyncContactRequestDecision_DecisionStatus_value) proto.RegisterEnum("protobuf.SyncContactRequestDecision_DecisionStatus", SyncContactRequestDecision_DecisionStatus_name, SyncContactRequestDecision_DecisionStatus_value)
proto.RegisterEnum("protobuf.SyncKeycardAction_Action", SyncKeycardAction_Action_name, SyncKeycardAction_Action_value)
proto.RegisterType((*FetchingBackedUpDataDetails)(nil), "protobuf.FetchingBackedUpDataDetails") proto.RegisterType((*FetchingBackedUpDataDetails)(nil), "protobuf.FetchingBackedUpDataDetails")
proto.RegisterType((*Backup)(nil), "protobuf.Backup") proto.RegisterType((*Backup)(nil), "protobuf.Backup")
proto.RegisterType((*MultiAccount)(nil), "protobuf.MultiAccount") proto.RegisterType((*MultiAccount)(nil), "protobuf.MultiAccount")
@ -3437,7 +3338,6 @@ func init() {
proto.RegisterType((*RawMessage)(nil), "protobuf.RawMessage") proto.RegisterType((*RawMessage)(nil), "protobuf.RawMessage")
proto.RegisterType((*SyncRawMessage)(nil), "protobuf.SyncRawMessage") proto.RegisterType((*SyncRawMessage)(nil), "protobuf.SyncRawMessage")
proto.RegisterType((*SyncKeycard)(nil), "protobuf.SyncKeycard") proto.RegisterType((*SyncKeycard)(nil), "protobuf.SyncKeycard")
proto.RegisterType((*SyncKeycardAction)(nil), "protobuf.SyncKeycardAction")
proto.RegisterType((*SyncSocialLinks)(nil), "protobuf.SyncSocialLinks") proto.RegisterType((*SyncSocialLinks)(nil), "protobuf.SyncSocialLinks")
} }
@ -3446,225 +3346,216 @@ func init() {
} }
var fileDescriptor_d61ab7221f0b5518 = []byte{ var fileDescriptor_d61ab7221f0b5518 = []byte{
// 3517 bytes of a gzipped FileDescriptorProto // 3368 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3a, 0x4d, 0x73, 0x23, 0x49, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3a, 0x3d, 0x6f, 0x24, 0x47,
0x56, 0xa3, 0x0f, 0xeb, 0xe3, 0x49, 0x96, 0xcb, 0x69, 0xcf, 0x58, 0xed, 0xf6, 0x6c, 0x77, 0x57, 0x76, 0x9a, 0x0f, 0xce, 0xc7, 0x9b, 0x21, 0xd9, 0x2c, 0x52, 0xcb, 0x59, 0x2e, 0x57, 0xbb, 0xdb,
0xef, 0xc4, 0x36, 0xc4, 0xe0, 0x01, 0x0f, 0xb0, 0xec, 0xf4, 0x4c, 0x0c, 0x6a, 0x49, 0xd3, 0xed, 0x6b, 0x41, 0x6b, 0x43, 0xa6, 0xec, 0x95, 0x6d, 0x59, 0x5a, 0x09, 0x32, 0x97, 0xa4, 0xb4, 0xdc,
0x76, 0x5b, 0x36, 0x69, 0x7b, 0x86, 0x25, 0x88, 0x28, 0xd2, 0x55, 0xd9, 0x56, 0xad, 0x4b, 0x55, 0x0f, 0x2e, 0x5d, 0x24, 0x25, 0xdb, 0x30, 0xd0, 0x2e, 0x76, 0xd7, 0x72, 0x4a, 0xec, 0xe9, 0x6e,
0xa2, 0x32, 0x65, 0xa3, 0x3d, 0x10, 0x40, 0x04, 0x67, 0x22, 0xb8, 0x2c, 0xc7, 0x39, 0x73, 0x24, 0x77, 0xd5, 0x90, 0x1e, 0x05, 0x86, 0x6d, 0xc0, 0xb1, 0x01, 0x27, 0xca, 0x0c, 0xc5, 0x0e, 0x0d,
0x82, 0x03, 0x11, 0x1c, 0x38, 0x11, 0xfb, 0x1f, 0xe0, 0xca, 0x85, 0xe0, 0xc2, 0x8d, 0x03, 0x07, 0x38, 0x38, 0xe0, 0xe2, 0x83, 0xfe, 0xc3, 0x5d, 0x7a, 0xc9, 0xe1, 0x92, 0xcb, 0x2e, 0xb8, 0xe0,
0xe2, 0x65, 0x66, 0x95, 0xaa, 0xf4, 0x61, 0xec, 0xe0, 0xc4, 0xc9, 0xf5, 0x5e, 0xbe, 0x7c, 0xf9, 0x50, 0xaf, 0xaa, 0x7b, 0xba, 0xe7, 0x83, 0x47, 0xe2, 0xa2, 0x8b, 0xd8, 0xef, 0xd5, 0xab, 0x57,
0x32, 0xdf, 0xf7, 0xb3, 0x60, 0x7d, 0xcc, 0xfc, 0xd8, 0x0f, 0xaf, 0xf6, 0xc7, 0x71, 0x24, 0x23, 0xaf, 0x5e, 0xbd, 0xef, 0x21, 0x2c, 0x26, 0x4c, 0xa4, 0x22, 0x3a, 0xdb, 0x4a, 0xd2, 0x58, 0xc5,
0x52, 0x53, 0x7f, 0x2e, 0x27, 0xef, 0x77, 0xb7, 0xdc, 0x21, 0x93, 0x8e, 0xef, 0xf1, 0x50, 0xfa, 0xa4, 0x85, 0x7f, 0x4e, 0x87, 0x6f, 0x36, 0x56, 0xfd, 0x3e, 0x53, 0x9e, 0x08, 0x78, 0xa4, 0x84,
0x72, 0xaa, 0x97, 0x77, 0xb7, 0xc4, 0x34, 0x74, 0x1d, 0xc1, 0xa5, 0xf4, 0xc3, 0x2b, 0x61, 0x90, 0x1a, 0x99, 0xe5, 0x8d, 0x55, 0x39, 0x8a, 0x7c, 0x4f, 0x72, 0xa5, 0x44, 0x74, 0x26, 0x2d, 0xd2,
0x36, 0x1b, 0x8f, 0x03, 0xdf, 0x65, 0xd2, 0x8f, 0x42, 0x67, 0xc4, 0x25, 0xf3, 0x98, 0x64, 0xce, 0x65, 0x49, 0x12, 0x0a, 0x9f, 0x29, 0x11, 0x47, 0xde, 0x80, 0x2b, 0x16, 0x30, 0xc5, 0xbc, 0x01,
0x88, 0x0b, 0xc1, 0xae, 0xb8, 0xa1, 0xd9, 0x74, 0xa3, 0xd1, 0x68, 0x12, 0xfa, 0xd2, 0xe7, 0x66, 0x97, 0x92, 0x9d, 0x71, 0x4b, 0xb3, 0xe2, 0xc7, 0x83, 0xc1, 0x30, 0x12, 0x4a, 0x70, 0xbb, 0xcd,
0x9b, 0xcd, 0xe0, 0xf1, 0x37, 0x5c, 0xba, 0x43, 0x3f, 0xbc, 0x7a, 0xc5, 0xdc, 0x6b, 0xee, 0x5d, 0x65, 0x70, 0xe7, 0x0b, 0xae, 0xfc, 0xbe, 0x88, 0xce, 0x9e, 0x32, 0xff, 0x9c, 0x07, 0x27, 0xc9,
0x8c, 0x7b, 0x4c, 0xb2, 0x1e, 0x97, 0xcc, 0x0f, 0x04, 0x79, 0x02, 0x0d, 0xc5, 0x27, 0x9c, 0x8c, 0x2e, 0x53, 0x6c, 0x97, 0x2b, 0x26, 0x42, 0x49, 0xee, 0x41, 0x07, 0xf9, 0x44, 0xc3, 0xc1, 0x29,
0x2e, 0x79, 0xdc, 0x2e, 0x3c, 0x2d, 0xbc, 0x58, 0xa7, 0x80, 0xa8, 0x81, 0xc2, 0x90, 0x67, 0xd0, 0x4f, 0x7b, 0x95, 0xfb, 0x95, 0x47, 0x8b, 0x14, 0x34, 0xea, 0x00, 0x31, 0xe4, 0x01, 0x74, 0x55,
0x94, 0x91, 0x64, 0x41, 0x42, 0x51, 0x54, 0x14, 0x0d, 0x85, 0xd3, 0x24, 0xf6, 0x7f, 0x57, 0xa0, 0xac, 0x58, 0x98, 0x51, 0x54, 0x91, 0xa2, 0x83, 0x38, 0x43, 0xe2, 0xfe, 0xa6, 0x01, 0x0d, 0xcd,
0x82, 0xbc, 0x27, 0x63, 0xb2, 0x0d, 0x6b, 0x6e, 0x10, 0xb9, 0xd7, 0x8a, 0x51, 0x99, 0x6a, 0x80, 0x7b, 0x98, 0x90, 0x35, 0x58, 0xf0, 0xc3, 0xd8, 0x3f, 0x47, 0x46, 0x75, 0x6a, 0x00, 0xb2, 0x04,
0xb4, 0xa0, 0xe8, 0x7b, 0x6a, 0x67, 0x9d, 0x16, 0x7d, 0x8f, 0x7c, 0x0d, 0x35, 0x37, 0x0a, 0x25, 0x55, 0x11, 0xe0, 0xce, 0x36, 0xad, 0x8a, 0x80, 0x7c, 0x0e, 0x2d, 0x3f, 0x8e, 0x14, 0xf3, 0x95,
0x73, 0xa5, 0x68, 0x97, 0x9e, 0x96, 0x5e, 0x34, 0x0e, 0x9e, 0xef, 0x27, 0x2f, 0xb2, 0x7f, 0x36, 0xec, 0xd5, 0xee, 0xd7, 0x1e, 0x75, 0x1e, 0x3f, 0xdc, 0xca, 0x34, 0xb2, 0x75, 0x34, 0x8a, 0xfc,
0x0d, 0xdd, 0xc3, 0x50, 0x48, 0x16, 0x04, 0xea, 0xae, 0x5d, 0x4d, 0xf9, 0xed, 0x01, 0x4d, 0x37, 0xfd, 0x48, 0x2a, 0x16, 0x86, 0x78, 0xd7, 0x1d, 0x43, 0xf9, 0xd5, 0x63, 0x9a, 0x6f, 0x22, 0x1f,
0x91, 0x9f, 0x40, 0x23, 0x73, 0xd3, 0x76, 0x59, 0xf1, 0xd8, 0xc9, 0xf3, 0xe8, 0x1a, 0x82, 0x29, 0x43, 0xa7, 0x70, 0xd3, 0x5e, 0x1d, 0x79, 0xac, 0x97, 0x79, 0xec, 0x58, 0x82, 0x11, 0x2d, 0xd2,
0xcd, 0xd2, 0x92, 0x13, 0xd8, 0x48, 0xd8, 0x98, 0x37, 0x68, 0xaf, 0x3d, 0x2d, 0xbc, 0x68, 0x1c, 0x92, 0xd7, 0xb0, 0x9c, 0xb1, 0xb1, 0x3a, 0xe8, 0x2d, 0xdc, 0xaf, 0x3c, 0xea, 0x3c, 0x7e, 0x77,
0x7c, 0x32, 0xdb, 0x7e, 0xc7, 0x83, 0xd1, 0xf9, 0xdd, 0xe4, 0x02, 0x48, 0x86, 0x7f, 0xc2, 0xb3, 0xbc, 0xfd, 0x0a, 0x85, 0xd1, 0xc9, 0xdd, 0xe4, 0x04, 0x48, 0x81, 0x7f, 0xc6, 0xb3, 0x71, 0x13,
0xf2, 0x10, 0x9e, 0x4b, 0x18, 0x90, 0xcf, 0xa1, 0x3a, 0x8e, 0xa3, 0xf7, 0x7e, 0xc0, 0xdb, 0x55, 0x9e, 0x33, 0x18, 0x90, 0x0f, 0xa1, 0x99, 0xa4, 0xf1, 0x1b, 0x11, 0xf2, 0x5e, 0x13, 0x79, 0xdd,
0xc5, 0xeb, 0xd1, 0x8c, 0x57, 0xc2, 0xe3, 0x54, 0x13, 0xd0, 0x84, 0x92, 0x1c, 0x43, 0xcb, 0x7c, 0x1e, 0xf3, 0xca, 0x78, 0x1c, 0x1a, 0x02, 0x9a, 0x51, 0x92, 0x57, 0xb0, 0x64, 0x3f, 0x33, 0x39,
0x26, 0x72, 0xd4, 0x1e, 0x22, 0xc7, 0xdc, 0x66, 0xf2, 0x19, 0x54, 0x8d, 0x11, 0xb6, 0xeb, 0x8a, 0x5a, 0x37, 0x91, 0x63, 0x62, 0x33, 0xf9, 0x00, 0x9a, 0xd6, 0x08, 0x7b, 0x6d, 0xe4, 0xf3, 0x76,
0xcf, 0x87, 0xf9, 0x27, 0x3e, 0xd3, 0x8b, 0x34, 0xa1, 0xc2, 0xc7, 0x4d, 0xac, 0x36, 0x11, 0x00, 0x59, 0xc5, 0x47, 0x66, 0x91, 0x66, 0x54, 0x5a, 0xb9, 0x99, 0xd5, 0x66, 0x02, 0xc0, 0x8d, 0x94,
0x1e, 0xf4, 0xb8, 0x73, 0xbb, 0x51, 0x82, 0x6b, 0x3e, 0x45, 0xe7, 0x69, 0x37, 0x96, 0x49, 0x70, 0x3b, 0xb1, 0x5b, 0x4b, 0x70, 0xce, 0x47, 0xda, 0x79, 0x7a, 0x9d, 0x59, 0x12, 0xbc, 0x30, 0x8b,
0xa4, 0x17, 0x69, 0x42, 0x85, 0x2f, 0x60, 0x3e, 0x13, 0x01, 0x9a, 0x0f, 0x7a, 0x81, 0xfc, 0x66, 0x34, 0xa3, 0xd2, 0x1a, 0xb0, 0x9f, 0x99, 0x00, 0xdd, 0x1b, 0x69, 0xa0, 0xbc, 0x99, 0x6c, 0x83,
0xd2, 0x01, 0xeb, 0x96, 0x49, 0x77, 0x78, 0x12, 0x06, 0xd3, 0x8e, 0xeb, 0x46, 0x93, 0x50, 0xb6, 0x73, 0xc9, 0x94, 0xdf, 0x7f, 0x1d, 0x85, 0xa3, 0x6d, 0xdf, 0x8f, 0x87, 0x91, 0xea, 0x2d, 0xce,
0xd7, 0x97, 0x09, 0x62, 0x16, 0xe9, 0x02, 0x39, 0x71, 0x60, 0x67, 0x1e, 0x97, 0x88, 0xd6, 0x7a, 0x12, 0xc4, 0x2e, 0xd2, 0x29, 0x72, 0xe2, 0xc1, 0xfa, 0x24, 0x2e, 0x13, 0x6d, 0xe9, 0x26, 0xa2,
0x88, 0x68, 0xab, 0xb8, 0xd8, 0xff, 0x51, 0x86, 0xe6, 0xf1, 0x24, 0x90, 0x7e, 0x72, 0x22, 0x81, 0xcd, 0xe3, 0xe2, 0xfe, 0xb2, 0x0e, 0xdd, 0x57, 0xc3, 0x50, 0x89, 0xec, 0x44, 0x02, 0xf5, 0x88,
0x72, 0xc8, 0x46, 0x5c, 0xf9, 0x60, 0x9d, 0xaa, 0x6f, 0xb2, 0x07, 0x75, 0xe9, 0x8f, 0xb8, 0x90, 0x0d, 0x38, 0xfa, 0x60, 0x9b, 0xe2, 0x37, 0xd9, 0x84, 0xb6, 0x12, 0x03, 0x2e, 0x15, 0x1b, 0x24,
0x6c, 0x34, 0x56, 0x9e, 0x58, 0xa2, 0x33, 0x04, 0xae, 0xea, 0x10, 0xe4, 0x46, 0x61, 0xbb, 0xa4, 0xe8, 0x89, 0x35, 0x3a, 0x46, 0xe8, 0x55, 0x13, 0x82, 0xfc, 0x38, 0xea, 0xd5, 0x70, 0xdb, 0x18,
0xb6, 0xcd, 0x10, 0xe4, 0x6b, 0x00, 0x37, 0x0a, 0xa2, 0xd8, 0x19, 0x32, 0x31, 0x34, 0xce, 0xf6, 0x41, 0x3e, 0x07, 0xf0, 0xe3, 0x30, 0x4e, 0xbd, 0x3e, 0x93, 0x7d, 0xeb, 0x6c, 0xf7, 0xc7, 0x42,
0x74, 0x26, 0x74, 0xf6, 0xec, 0xfd, 0x2e, 0x12, 0xbe, 0x61, 0x62, 0x48, 0xeb, 0x6e, 0xf2, 0x49, 0x17, 0xcf, 0xde, 0xda, 0xd1, 0x84, 0xcf, 0x98, 0xec, 0xd3, 0xb6, 0x9f, 0x7d, 0x92, 0xdb, 0xda,
0x1e, 0xa1, 0xbf, 0x23, 0x03, 0xdf, 0x53, 0xce, 0x56, 0xa2, 0x55, 0x05, 0x1f, 0x7a, 0xe4, 0x47, 0xdf, 0x35, 0x03, 0x11, 0xa0, 0xb3, 0xd5, 0x68, 0x13, 0xe1, 0xfd, 0x80, 0xbc, 0x07, 0xcb, 0xe7,
0xb0, 0x71, 0xcd, 0xa7, 0x2e, 0x8b, 0x3d, 0xc7, 0x84, 0x48, 0xe5, 0x3a, 0x75, 0xa5, 0x09, 0x44, 0x7c, 0xe4, 0xb3, 0x34, 0xf0, 0x6c, 0x88, 0x44, 0xd7, 0x69, 0xe3, 0x4b, 0x68, 0xf4, 0xa1, 0xc1,
0x9f, 0x6a, 0x2c, 0xd9, 0x51, 0x96, 0xe0, 0x4c, 0x7c, 0x4f, 0xf9, 0x43, 0x9d, 0x56, 0xae, 0xf9, 0x92, 0x75, 0xb4, 0x04, 0x6f, 0x28, 0x02, 0xf4, 0x87, 0x36, 0x6d, 0x9c, 0xf3, 0xd1, 0x89, 0x08,
0xf4, 0xc2, 0xf7, 0xc8, 0x97, 0x50, 0xf1, 0x47, 0xec, 0x8a, 0xa3, 0xad, 0xa3, 0x64, 0x3f, 0x5c, 0xc8, 0xa7, 0xd0, 0x10, 0x03, 0x76, 0xc6, 0xb5, 0xad, 0x6b, 0xc9, 0xfe, 0x68, 0x8e, 0x64, 0xfb,
0x21, 0xd9, 0xa1, 0x89, 0xb1, 0x87, 0x48, 0x4c, 0xcd, 0x1e, 0xf2, 0x19, 0x6c, 0xb9, 0x13, 0x21, 0x36, 0xc6, 0xee, 0x6b, 0x62, 0x6a, 0xf7, 0x90, 0x0f, 0x60, 0xd5, 0x1f, 0x4a, 0x15, 0x0f, 0xc4,
0xa3, 0x91, 0xff, 0x73, 0x1d, 0x59, 0x95, 0x60, 0xca, 0xdc, 0xeb, 0x94, 0xe4, 0x96, 0xd4, 0xd5, 0xb7, 0x26, 0xb2, 0xa2, 0x60, 0x68, 0xee, 0x6d, 0x4a, 0x4a, 0x4b, 0x78, 0xb5, 0x8d, 0x07, 0xd0,
0x76, 0x9f, 0x41, 0x3d, 0xbd, 0x23, 0x86, 0x3b, 0x3f, 0xf4, 0xf8, 0x9f, 0xb4, 0x0b, 0x4f, 0x4b, 0xce, 0xef, 0xa8, 0xc3, 0x9d, 0x88, 0x02, 0xfe, 0x2f, 0xbd, 0xca, 0xfd, 0xda, 0xa3, 0x1a, 0x35,
0x2f, 0x4a, 0x54, 0x03, 0xbb, 0xff, 0x52, 0x80, 0xf5, 0xdc, 0x69, 0x59, 0xe1, 0x0b, 0x39, 0xe1, 0xc0, 0xc6, 0x4f, 0x2b, 0xb0, 0x58, 0x3a, 0xad, 0x28, 0x7c, 0xa5, 0x24, 0x7c, 0xf6, 0x54, 0xd5,
0x13, 0x55, 0x15, 0x33, 0xaa, 0x6a, 0x43, 0x75, 0xcc, 0xa6, 0x41, 0xc4, 0x3c, 0xa5, 0x8a, 0x26, 0xc2, 0x53, 0xf5, 0xa0, 0x99, 0xb0, 0x51, 0x18, 0xb3, 0x00, 0x9f, 0xa2, 0x4b, 0x33, 0x50, 0x1f,
0x4d, 0x40, 0x3c, 0xee, 0xd6, 0xf7, 0x24, 0xea, 0x00, 0x1f, 0x51, 0x03, 0xe4, 0x23, 0xa8, 0x0c, 0x77, 0x29, 0x02, 0xa5, 0xdf, 0x40, 0x2b, 0xd1, 0x00, 0xe4, 0x16, 0x34, 0xfa, 0x5c, 0x9c, 0xf5,
0xb9, 0x7f, 0x35, 0x94, 0xe6, 0x6d, 0x0d, 0x44, 0x76, 0xa1, 0x86, 0xce, 0x2c, 0xfc, 0x9f, 0x73, 0x95, 0xd5, 0xad, 0x85, 0xc8, 0x06, 0xb4, 0xb4, 0x33, 0x4b, 0xf1, 0x2d, 0x47, 0x9d, 0xd6, 0x68,
0xf5, 0xa6, 0x25, 0x9a, 0xc2, 0xe4, 0x39, 0xac, 0xc7, 0xea, 0xcb, 0x91, 0x2c, 0xbe, 0xe2, 0x52, 0x0e, 0x93, 0x87, 0xb0, 0x98, 0xe2, 0x97, 0xa7, 0x58, 0x7a, 0xc6, 0x15, 0xea, 0xb4, 0x46, 0xbb,
0xbd, 0x69, 0x89, 0x36, 0x35, 0xf2, 0x5c, 0xe1, 0x66, 0xc1, 0xbc, 0x96, 0x09, 0xe6, 0xf6, 0x2f, 0x06, 0x79, 0x8c, 0xb8, 0x71, 0x30, 0x6f, 0x15, 0x82, 0xb9, 0xfb, 0x5d, 0x15, 0x56, 0x5f, 0xc6,
0x8a, 0xb0, 0xf5, 0x2e, 0x72, 0x59, 0x60, 0x34, 0x73, 0x6a, 0x84, 0xfb, 0x2d, 0x28, 0x5f, 0xf3, 0x3e, 0x0b, 0xed, 0xcb, 0x1c, 0x5a, 0xe1, 0xfe, 0x12, 0xea, 0xe7, 0x7c, 0x24, 0x51, 0x15, 0x9d,
0xa9, 0x50, 0x4f, 0xd1, 0x38, 0x78, 0x36, 0xd3, 0xc2, 0x12, 0xe2, 0xfd, 0x23, 0x3e, 0xa5, 0x8a, 0xc7, 0x0f, 0xc6, 0xaf, 0x30, 0x83, 0x78, 0xeb, 0x05, 0x1f, 0x51, 0x24, 0x27, 0x9f, 0x40, 0x77,
0x9c, 0x7c, 0x01, 0xcd, 0x11, 0xaa, 0x89, 0x19, 0xef, 0x2a, 0x2a, 0x9f, 0xf8, 0x68, 0xb9, 0x12, 0xa0, 0x9f, 0x89, 0x59, 0xef, 0xaa, 0xa2, 0x4f, 0xdc, 0x9a, 0xfd, 0x88, 0xb4, 0x44, 0xab, 0x6f,
0x69, 0x8e, 0x16, 0x6f, 0x38, 0x66, 0x42, 0xdc, 0x46, 0xb1, 0x67, 0xac, 0x36, 0x85, 0xf1, 0x15, 0x98, 0x30, 0x29, 0x2f, 0xe3, 0x34, 0xb0, 0x56, 0x9b, 0xc3, 0x5a, 0x8b, 0x3a, 0xb5, 0xbe, 0xe0,
0x31, 0xb5, 0x1e, 0xf1, 0xa9, 0x7a, 0xad, 0x3a, 0x4d, 0x40, 0xf2, 0x22, 0x35, 0x39, 0x23, 0x94, 0x23, 0xd4, 0x56, 0x9b, 0x66, 0x20, 0x79, 0x94, 0x9b, 0x9c, 0x15, 0xca, 0x64, 0x80, 0x36, 0x9d,
0xce, 0x00, 0x75, 0x3a, 0x8f, 0xde, 0xfd, 0x35, 0x28, 0xe1, 0x86, 0x65, 0xfe, 0x44, 0xa0, 0x8c, 0x44, 0x6f, 0xfc, 0x29, 0xd4, 0xf4, 0x86, 0x59, 0xfe, 0x44, 0xa0, 0xae, 0x93, 0x24, 0x8a, 0xdb,
0x49, 0x52, 0x89, 0xdb, 0xa4, 0xea, 0xdb, 0xfe, 0x87, 0x02, 0x7c, 0x98, 0xbb, 0x2c, 0xe7, 0xf1, 0xa5, 0xf8, 0xed, 0xfe, 0xa8, 0x02, 0x6f, 0x97, 0x2e, 0xcb, 0x79, 0xfa, 0x8c, 0x87, 0x61, 0xac,
0x1b, 0x1e, 0x04, 0x11, 0x5a, 0xb9, 0xb1, 0x6e, 0xe7, 0x86, 0xc7, 0xc2, 0x8f, 0x42, 0xc5, 0x6c, 0xad, 0xdc, 0x5a, 0xb7, 0x77, 0xc1, 0x53, 0x29, 0xe2, 0x08, 0x99, 0x2d, 0xd0, 0x25, 0x8b, 0xfe,
0x8d, 0xb6, 0x0c, 0xfa, 0x5b, 0x8d, 0x45, 0x43, 0x19, 0x73, 0xae, 0x1c, 0x45, 0x73, 0xae, 0x20, 0xca, 0x60, 0xb5, 0xa1, 0x24, 0x9c, 0xa3, 0xa3, 0x18, 0xce, 0x0d, 0x0d, 0xee, 0x07, 0x98, 0xa7,
0x78, 0xe8, 0xa9, 0x3c, 0xcd, 0x6f, 0x7c, 0x97, 0x3b, 0x4a, 0x14, 0x7d, 0x5b, 0xd0, 0xa8, 0x01, 0xf9, 0x85, 0xf0, 0xb9, 0x87, 0xa2, 0x98, 0xdb, 0x82, 0x41, 0x1d, 0x68, 0x81, 0xc6, 0x04, 0x6a,
0x0a, 0x34, 0x23, 0x90, 0xd3, 0x31, 0x37, 0x77, 0x36, 0x04, 0xe7, 0xd3, 0xb1, 0x8a, 0x00, 0xc2, 0x94, 0x70, 0x7b, 0x67, 0x4b, 0x70, 0x3c, 0x4a, 0x30, 0x02, 0x48, 0x71, 0x16, 0x31, 0x35, 0x4c,
0xbf, 0x0a, 0x99, 0x9c, 0xc4, 0x5c, 0x5d, 0xb8, 0x49, 0x67, 0x08, 0xfb, 0xfb, 0x02, 0x58, 0x28, 0x39, 0x5e, 0xb8, 0x4b, 0xc7, 0x08, 0xf7, 0xfb, 0x0a, 0x38, 0x5a, 0xec, 0x62, 0xe6, 0x9d, 0x93,
0x76, 0x36, 0xf3, 0xae, 0xc8, 0xe6, 0x3f, 0x82, 0x0d, 0x3f, 0x43, 0xe5, 0xa4, 0xa9, 0xbd, 0x95, 0xcd, 0xdf, 0x83, 0x65, 0x51, 0xa0, 0xf2, 0xf2, 0xd4, 0xbe, 0x54, 0x44, 0x97, 0x64, 0x46, 0x91,
0x45, 0xe7, 0x64, 0x56, 0x22, 0x95, 0x16, 0x44, 0x4a, 0x1e, 0xb6, 0x9c, 0xb7, 0xfe, 0xe4, 0x89, 0x6a, 0x53, 0x22, 0x65, 0x8a, 0xad, 0x97, 0xad, 0x3f, 0x53, 0xd1, 0x02, 0x96, 0x1a, 0x19, 0xe8,
0xd6, 0x54, 0xa9, 0x91, 0x80, 0xf6, 0xbf, 0x17, 0x60, 0x67, 0x45, 0x71, 0x70, 0xcf, 0xba, 0xe3, 0xfe, 0xa2, 0x02, 0xeb, 0x73, 0x8a, 0x83, 0x6b, 0xd6, 0x1d, 0x0f, 0x61, 0xd1, 0x66, 0x38, 0x0f,
0x39, 0xac, 0x9b, 0x0c, 0xe7, 0x28, 0xf7, 0x37, 0x22, 0x35, 0x0d, 0x52, 0xfb, 0xea, 0x23, 0xa8, 0xdd, 0xdf, 0x8a, 0xd4, 0xb5, 0x48, 0xe3, 0xab, 0xb7, 0xa1, 0xc5, 0x23, 0xe9, 0x15, 0x04, 0x6b,
0xf1, 0x50, 0x38, 0x19, 0xc1, 0xaa, 0x3c, 0x14, 0xea, 0x8d, 0x9f, 0x41, 0x33, 0x60, 0x42, 0x3a, 0xf2, 0x48, 0xa2, 0x8e, 0x1f, 0x40, 0x37, 0x64, 0x52, 0x79, 0xc3, 0x24, 0x60, 0x8a, 0x9b, 0x58,
0x93, 0xb1, 0xc7, 0x24, 0xd7, 0xb1, 0xac, 0x4c, 0x1b, 0x88, 0xbb, 0xd0, 0x28, 0xbc, 0xb3, 0x98, 0x56, 0xa7, 0x1d, 0x8d, 0x3b, 0x31, 0x28, 0x7d, 0x67, 0x39, 0x92, 0x8a, 0x0f, 0x3c, 0xc5, 0xce,
0x0a, 0xc9, 0x47, 0x8e, 0x64, 0x57, 0x58, 0x06, 0x94, 0xf0, 0xce, 0x1a, 0x75, 0xce, 0xae, 0x04, 0x74, 0x19, 0x50, 0xd3, 0x77, 0x36, 0xa8, 0x63, 0x76, 0x26, 0xc9, 0xbb, 0xb0, 0x14, 0x6a, 0x1b,
0xf9, 0x04, 0x5a, 0x01, 0xda, 0x88, 0x13, 0xfa, 0xee, 0xb5, 0x3a, 0x44, 0x87, 0xb3, 0x75, 0x85, 0xf1, 0x22, 0xe1, 0x9f, 0xe3, 0x21, 0x26, 0x9c, 0x2d, 0x22, 0xf6, 0xc0, 0x22, 0xdd, 0x7f, 0x6f,
0x1d, 0x18, 0xa4, 0xfd, 0xe7, 0x15, 0x78, 0xb4, 0xb2, 0x12, 0x22, 0xbf, 0x0e, 0xdb, 0x59, 0x41, 0xc0, 0xed, 0xb9, 0x95, 0x10, 0xf9, 0x33, 0x58, 0x2b, 0x0a, 0xe2, 0xe1, 0xde, 0x70, 0x64, 0x6f,
0x1c, 0xb5, 0x37, 0x98, 0x9a, 0xdb, 0x93, 0x8c, 0x40, 0xef, 0xf4, 0xca, 0xff, 0xe3, 0xa7, 0x40, 0x4f, 0x0a, 0x02, 0xbd, 0x34, 0x2b, 0x7f, 0xc0, 0xaa, 0xd0, 0x6f, 0xcb, 0x82, 0x80, 0x07, 0x18,
0xdd, 0x32, 0xcf, 0xe3, 0x9e, 0x0a, 0xca, 0x35, 0xaa, 0x01, 0xb4, 0x93, 0x4b, 0x54, 0x32, 0xf7, 0x94, 0x5b, 0xd4, 0x00, 0xda, 0x4e, 0x4e, 0xf5, 0x23, 0xf3, 0x00, 0x4b, 0x8c, 0x16, 0xcd, 0x40,
0x54, 0x89, 0x51, 0xa3, 0x09, 0x88, 0xf4, 0xa3, 0x09, 0xca, 0xd4, 0xd0, 0xf4, 0x0a, 0x40, 0xfa, 0x4d, 0x3f, 0x18, 0x6a, 0x99, 0x3a, 0x86, 0x1e, 0x01, 0x4d, 0x9f, 0xf2, 0x41, 0x7c, 0xc1, 0x03,
0x98, 0x8f, 0xa2, 0x1b, 0xee, 0xa9, 0x8a, 0xa0, 0x46, 0x13, 0x90, 0x3c, 0x85, 0xe6, 0x90, 0x09, 0xac, 0x08, 0x5a, 0x34, 0x03, 0xc9, 0x7d, 0xe8, 0xf6, 0x99, 0xf4, 0x90, 0xad, 0x37, 0x94, 0x98,
0x47, 0xb1, 0x75, 0x26, 0x42, 0xe5, 0xf7, 0x1a, 0x85, 0x21, 0x13, 0x1d, 0x44, 0x5d, 0xa8, 0x24, 0xdf, 0x5b, 0x14, 0xfa, 0x4c, 0x6e, 0x6b, 0xd4, 0x09, 0x26, 0x89, 0x0b, 0x9e, 0x8a, 0x37, 0x59,
0x71, 0xc3, 0x63, 0xff, 0x7d, 0x52, 0x7d, 0x0b, 0xc9, 0xe4, 0x44, 0xa7, 0xef, 0x12, 0x25, 0xd9, 0xf5, 0x2d, 0x15, 0x53, 0x43, 0x93, 0xbe, 0x6b, 0x94, 0x14, 0x97, 0x8e, 0x70, 0x05, 0x8b, 0xe6,
0xa5, 0x33, 0xb5, 0xa2, 0x8a, 0xe6, 0x78, 0x22, 0x64, 0x42, 0xb9, 0xa1, 0x28, 0x1b, 0x0a, 0x67, 0x74, 0x28, 0x55, 0x46, 0xb9, 0x8c, 0x94, 0x1d, 0xc4, 0x59, 0x92, 0xcf, 0xe0, 0x8e, 0xad, 0x24,
0x48, 0xbe, 0x82, 0xc7, 0xa6, 0x92, 0x74, 0x62, 0xfe, 0xc7, 0x13, 0x2e, 0xa4, 0xd6, 0xa2, 0xda, 0xbd, 0x94, 0xff, 0xf3, 0x90, 0x4b, 0x65, 0x5e, 0x11, 0xb7, 0xf0, 0x9e, 0x83, 0x3b, 0x7a, 0x96,
0xc2, 0xdb, 0x96, 0xda, 0xd1, 0x36, 0x24, 0x54, 0x53, 0x28, 0x65, 0xe2, 0x7e, 0xbe, 0x7a, 0xbb, 0x84, 0x1a, 0x0a, 0x7c, 0x4c, 0xbd, 0x9f, 0xcf, 0xdf, 0x6e, 0xdc, 0x60, 0x65, 0xee, 0xf6, 0x1d,
0x76, 0x83, 0xcd, 0x95, 0xdb, 0xbb, 0xca, 0x33, 0xbe, 0x86, 0xbd, 0xf9, 0xed, 0xf8, 0x1c, 0x92, 0xf4, 0x8c, 0xcf, 0x61, 0x73, 0x72, 0xbb, 0x56, 0x87, 0xe2, 0xf6, 0x78, 0x82, 0xfb, 0x6f, 0x97,
0x9b, 0xe3, 0x89, 0xda, 0xff, 0x28, 0xbf, 0x9f, 0x2a, 0x0a, 0x7d, 0xfe, 0x6a, 0x06, 0x5a, 0x80, 0xf7, 0x53, 0xa4, 0x30, 0xe7, 0xcf, 0x67, 0x60, 0x04, 0x58, 0x9d, 0xcf, 0xc0, 0x48, 0xf0, 0x00,
0xad, 0xd5, 0x0c, 0xb4, 0x04, 0xcf, 0xa0, 0xe9, 0xf9, 0x62, 0x1c, 0xb0, 0xa9, 0xb6, 0xaf, 0x6d, 0xba, 0x81, 0x90, 0x49, 0xc8, 0x46, 0xc6, 0xbe, 0xd6, 0xf0, 0xe9, 0x3b, 0x16, 0xa7, 0x6d, 0xcc,
0xa5, 0xfa, 0x86, 0xc1, 0xa1, 0x8d, 0xd9, 0xb7, 0x8b, 0xfe, 0x9e, 0x94, 0x38, 0xcb, 0xfd, 0x7d, 0xbd, 0x9c, 0xf6, 0xf7, 0xac, 0xc4, 0x99, 0xed, 0xef, 0x53, 0x46, 0x5d, 0x9d, 0x61, 0xd4, 0x93,
0xc1, 0xa8, 0x8b, 0x4b, 0x8c, 0x7a, 0xde, 0x72, 0x4b, 0x0b, 0x96, 0x6b, 0xbf, 0x82, 0xdd, 0xf9, 0x96, 0x5b, 0x9b, 0xb2, 0x5c, 0xf7, 0x29, 0x6c, 0x4c, 0x1e, 0x7c, 0x38, 0x3c, 0x0d, 0x85, 0xbf,
0x83, 0x4f, 0x27, 0x97, 0x81, 0xef, 0x76, 0x87, 0xec, 0x9e, 0xb1, 0xc6, 0xfe, 0xfb, 0x12, 0xac, 0xd3, 0x67, 0xd7, 0x8c, 0x35, 0xee, 0xff, 0xd7, 0x60, 0xb1, 0xd4, 0x86, 0xfc, 0xce, 0x7d, 0x5d,
0xe7, 0xda, 0x90, 0xff, 0x75, 0x5f, 0x53, 0x39, 0xe6, 0x13, 0x68, 0x8c, 0x63, 0xff, 0x86, 0x49, 0x74, 0xcc, 0x7b, 0xd0, 0x49, 0x52, 0x71, 0xc1, 0x14, 0xf7, 0xce, 0xf9, 0xc8, 0x56, 0x00, 0x60,
0xee, 0x5c, 0xf3, 0xa9, 0xa9, 0x00, 0xc0, 0xa0, 0x30, 0x1b, 0x3d, 0xc5, 0xa8, 0x2a, 0xdc, 0xd8, 0x51, 0x3a, 0x1b, 0xdd, 0xd7, 0x51, 0x55, 0xfa, 0xa9, 0x48, 0xb4, 0x5c, 0xe8, 0x97, 0x5d, 0x5a,
0x1f, 0xa3, 0x5c, 0xca, 0x2f, 0x9b, 0x34, 0x8b, 0xc2, 0x82, 0xe0, 0x67, 0x91, 0x1f, 0x1a, 0xaf, 0x44, 0xe9, 0x82, 0xe0, 0x9b, 0x58, 0x44, 0xd6, 0x2b, 0x5b, 0xd4, 0x42, 0x3a, 0x5d, 0x1a, 0x5b,
0xac, 0x51, 0x03, 0x61, 0xba, 0xd4, 0xb6, 0xca, 0x3d, 0x55, 0x10, 0xd4, 0x68, 0x0a, 0xcf, 0x9c, 0xe5, 0x01, 0x16, 0x04, 0x2d, 0x9a, 0xc3, 0x63, 0xa7, 0x69, 0x16, 0x9d, 0xe6, 0x35, 0x38, 0xf6,
0xa6, 0x9a, 0x75, 0x9a, 0x13, 0xb0, 0x8c, 0x76, 0x85, 0x23, 0x23, 0x07, 0xf9, 0x98, 0x2a, 0xeb, 0x75, 0xa5, 0xa7, 0x62, 0x4f, 0xf3, 0xb1, 0x55, 0xd6, 0xbb, 0xf3, 0x9a, 0x2d, 0x4b, 0x7e, 0x1c,
0x93, 0x55, 0xcd, 0x96, 0x21, 0x3f, 0x8f, 0xde, 0x46, 0x7e, 0x48, 0x5b, 0x71, 0x0e, 0x26, 0x2f, 0x3f, 0x8f, 0x45, 0x44, 0x97, 0xd2, 0x12, 0x4c, 0x9e, 0x40, 0x2b, 0x2b, 0xf1, 0x6d, 0x4b, 0x71,
0xa1, 0x96, 0x94, 0xf8, 0xa6, 0xa5, 0x78, 0xb2, 0x82, 0x91, 0xe9, 0x2d, 0x04, 0x4d, 0x37, 0x60, 0x6f, 0x0e, 0x23, 0xdb, 0x5b, 0x48, 0x9a, 0x6f, 0xd0, 0x19, 0x8c, 0x47, 0x7e, 0x3a, 0x4a, 0x54,
0x06, 0xe3, 0xa1, 0x1b, 0x4f, 0xc7, 0x32, 0x75, 0xfa, 0x19, 0x42, 0xe5, 0xb7, 0x31, 0x77, 0x25, 0xee, 0xf4, 0x63, 0x04, 0xe6, 0xb7, 0x84, 0xfb, 0x8a, 0x8d, 0x5d, 0x7f, 0x8c, 0xd0, 0x49, 0xcb,
0x9b, 0xb9, 0xfe, 0x0c, 0x81, 0x49, 0xcb, 0x90, 0xa2, 0x03, 0xab, 0x42, 0xa5, 0xa9, 0x5e, 0xae, 0x92, 0x6a, 0x07, 0xc6, 0x42, 0xa5, 0x8b, 0x9a, 0x5b, 0x1a, 0xa3, 0x5f, 0xf0, 0x91, 0xd4, 0xe5,
0x35, 0x43, 0x1f, 0xf1, 0xa9, 0xc0, 0xf2, 0xe6, 0xf1, 0x1d, 0x37, 0x32, 0xfa, 0x2a, 0xa4, 0xfa, 0xcd, 0x9d, 0x2b, 0x6e, 0x64, 0xdf, 0xab, 0x92, 0xbf, 0xd7, 0x5d, 0x80, 0x04, 0x6d, 0x03, 0x9f,
0xfa, 0x18, 0x60, 0xac, 0x6c, 0x43, 0xa9, 0x4b, 0xeb, 0xbf, 0xae, 0x31, 0xa8, 0xad, 0x54, 0xe9, 0xcb, 0xbc, 0x7f, 0xdb, 0x60, 0xf4, 0x6b, 0xe5, 0x8f, 0x5e, 0x2b, 0x3e, 0xfa, 0x15, 0x81, 0x75,
0xa5, 0xac, 0xd2, 0xef, 0x08, 0xac, 0x3b, 0xba, 0x6e, 0x49, 0x4a, 0xe5, 0x3a, 0xad, 0x20, 0x78, 0xdd, 0xd4, 0x2d, 0x59, 0xa9, 0xdc, 0xa6, 0x0d, 0x0d, 0xee, 0x07, 0xda, 0x6e, 0xb3, 0x36, 0x71,
0xe8, 0xa1, 0xdd, 0x26, 0x6d, 0xe2, 0x14, 0x57, 0x2b, 0x5a, 0xf1, 0x29, 0xee, 0x50, 0x29, 0x51, 0xa4, 0x57, 0x1b, 0xe6, 0xe1, 0x73, 0xdc, 0x3e, 0x3e, 0xa2, 0x71, 0xdf, 0xa6, 0x39, 0x0c, 0x01,
0xbb, 0x6f, 0x55, 0x1f, 0xa6, 0x00, 0xf2, 0x0d, 0x6c, 0xc6, 0xfc, 0x86, 0xb3, 0x80, 0x7b, 0x8e, 0xf2, 0x05, 0xac, 0xa4, 0xfc, 0x82, 0xb3, 0x90, 0x07, 0x9e, 0xad, 0x9c, 0xb2, 0x5a, 0xb9, 0xd0,
0xa9, 0x9c, 0x92, 0x5a, 0x39, 0xd3, 0x53, 0x52, 0x43, 0x92, 0x36, 0x32, 0x71, 0x1e, 0x21, 0xec, 0x53, 0x52, 0x4b, 0x92, 0x37, 0x32, 0x69, 0x19, 0x21, 0xdd, 0xff, 0xae, 0x82, 0x33, 0xe9, 0x16,
0xbf, 0x2e, 0x82, 0x35, 0xef, 0x16, 0xe4, 0xab, 0x4c, 0x2b, 0xbf, 0x50, 0xf9, 0xad, 0x48, 0x60, 0xe4, 0xb3, 0x42, 0x2b, 0x3f, 0x55, 0xf9, 0xcd, 0x49, 0x60, 0x85, 0x46, 0xfe, 0x4b, 0xe8, 0x5a,
0x99, 0x46, 0xfe, 0x35, 0x34, 0xcd, 0xeb, 0xe1, 0x2d, 0x45, 0xbb, 0x38, 0x5f, 0xc2, 0xaf, 0xf6, 0xed, 0xe9, 0x5b, 0xca, 0x5e, 0x75, 0xb2, 0x84, 0x9f, 0xef, 0x87, 0xb4, 0x93, 0xe4, 0xdf, 0x92,
0x43, 0xda, 0x18, 0xa7, 0xdf, 0x82, 0xbc, 0x84, 0x6a, 0x52, 0x41, 0x96, 0x94, 0x5d, 0xdd, 0x21, 0x3c, 0x81, 0x66, 0x56, 0x41, 0xd6, 0xd0, 0xae, 0xae, 0x10, 0x23, 0xbb, 0x62, 0xb6, 0xe3, 0xf7,
0x46, 0x72, 0xc5, 0x64, 0xc7, 0xff, 0x61, 0x9c, 0x60, 0xff, 0x18, 0x36, 0xd4, 0x2a, 0x0a, 0x64, 0x18, 0x27, 0xb8, 0x1f, 0xc1, 0x32, 0xae, 0x6a, 0x81, 0x6c, 0x3e, 0xb9, 0x5e, 0x7c, 0xf8, 0x14,
0xf2, 0xc9, 0xfd, 0xe2, 0xc3, 0x97, 0xb0, 0x9d, 0x6c, 0x3c, 0xd6, 0x33, 0x1c, 0x41, 0x39, 0xbb, 0xd6, 0xb2, 0x8d, 0xaf, 0xcc, 0x0c, 0x47, 0x52, 0xce, 0xae, 0xbb, 0xfb, 0x6f, 0xe0, 0x96, 0xe9,
0xef, 0xee, 0xdf, 0x85, 0x8f, 0x74, 0xd7, 0x29, 0xfd, 0x1b, 0x5f, 0x4e, 0xbb, 0x3c, 0x94, 0x3c, 0x3a, 0x95, 0xb8, 0x10, 0x6a, 0xb4, 0xc3, 0x23, 0xc5, 0xd3, 0x2b, 0xf6, 0x3b, 0x50, 0x13, 0x81,
0xbe, 0x63, 0xbf, 0x05, 0x25, 0xdf, 0xd3, 0xcf, 0xdb, 0xa4, 0xf8, 0x69, 0xf7, 0x74, 0x8c, 0xcb, 0x51, 0x6f, 0x97, 0xea, 0x4f, 0x77, 0xd7, 0xc4, 0xb8, 0x32, 0x87, 0x6d, 0xdf, 0xe7, 0xe8, 0x4c,
0x73, 0xe8, 0xb8, 0x2e, 0x57, 0xce, 0x74, 0x5f, 0x2e, 0x7d, 0xed, 0x2c, 0x79, 0x2e, 0x3d, 0x5f, 0xd7, 0xe5, 0xb2, 0x67, 0x9c, 0xa5, 0xcc, 0x65, 0x57, 0xc8, 0x81, 0x90, 0xf2, 0x06, 0x6c, 0x3c,
0x8c, 0x7c, 0x21, 0x1e, 0xc0, 0xc6, 0x81, 0xe7, 0x8b, 0x6c, 0x06, 0x91, 0xcc, 0xe5, 0x55, 0x8e, 0x78, 0x38, 0xcd, 0xe6, 0x20, 0x56, 0xa5, 0xbc, 0xca, 0xb5, 0xaf, 0x65, 0x15, 0x0f, 0x53, 0x96,
0xbe, 0x96, 0x54, 0x3c, 0x4c, 0x1a, 0x9e, 0x75, 0x83, 0xe9, 0x48, 0xf4, 0x2a, 0x4c, 0xe4, 0x82, 0x67, 0xdb, 0x62, 0xb6, 0x95, 0xf6, 0x2a, 0x9d, 0xc8, 0x25, 0xe7, 0x11, 0xaa, 0xaa, 0x45, 0x9b,
0xf3, 0x50, 0x3d, 0x55, 0x8d, 0x56, 0x87, 0x4c, 0x9c, 0x71, 0x1e, 0xda, 0x7f, 0x55, 0x80, 0x27, 0x7d, 0x26, 0x8f, 0x38, 0x8f, 0xdc, 0xff, 0xaa, 0xc0, 0xbd, 0xab, 0x4f, 0x90, 0x24, 0x84, 0xbb,
0x77, 0x9f, 0x20, 0x48, 0x00, 0x1f, 0x33, 0xb3, 0xec, 0xb8, 0x6a, 0xdd, 0x09, 0xb3, 0x04, 0xc6, 0xcc, 0x2e, 0x7b, 0x3e, 0xae, 0x7b, 0x51, 0x91, 0xc0, 0xda, 0xf7, 0xa3, 0xc9, 0xc6, 0x7f, 0x1e,
0xbe, 0x5f, 0xcc, 0x37, 0xfe, 0xab, 0x38, 0xd2, 0xc7, 0x6c, 0xf5, 0x69, 0xf6, 0x3f, 0xd6, 0xe1, 0x47, 0x7a, 0x87, 0xcd, 0x3f, 0xcd, 0xfd, 0x71, 0x1b, 0xde, 0xb9, 0x7a, 0xff, 0x54, 0xa8, 0x99,
0x07, 0x77, 0xef, 0x5f, 0x08, 0x35, 0x0b, 0x3d, 0x7c, 0x39, 0xdb, 0xc3, 0xbf, 0x87, 0xcd, 0xac, 0xea, 0xe1, 0xeb, 0xc5, 0x1e, 0xfe, 0x0d, 0xac, 0x14, 0xc5, 0x1d, 0xd7, 0xdc, 0x4b, 0x8f, 0x3f,
0xb8, 0xb3, 0x9a, 0xbb, 0x75, 0xf0, 0x93, 0xfb, 0x8a, 0xbc, 0x9f, 0x05, 0xb0, 0x44, 0xa7, 0x56, 0xbe, 0xae, 0xc8, 0x5b, 0x45, 0x40, 0x97, 0xe8, 0xd4, 0x89, 0x26, 0x30, 0xc5, 0x00, 0x55, 0x2f,
0x38, 0x87, 0xc9, 0x06, 0xa8, 0x72, 0x2e, 0x40, 0x11, 0x28, 0xc7, 0x9c, 0x25, 0x49, 0x47, 0x7d, 0x05, 0x28, 0x02, 0xf5, 0x94, 0xb3, 0x2c, 0xe9, 0xe0, 0xb7, 0x16, 0x39, 0xc8, 0xac, 0xc1, 0xe6,
0xa3, 0xc8, 0x5e, 0x62, 0x0d, 0x26, 0xe7, 0xcc, 0x10, 0x98, 0x90, 0x98, 0xb1, 0x38, 0x93, 0x77, 0x9c, 0x31, 0x42, 0x27, 0x24, 0x66, 0x2d, 0xce, 0xe6, 0x9d, 0x1c, 0xd6, 0xf5, 0x9a, 0x9d, 0x6d,
0x52, 0x18, 0xeb, 0x35, 0x33, 0xdb, 0x54, 0xed, 0x67, 0x93, 0x26, 0x20, 0xa6, 0x37, 0x36, 0x91, 0x62, 0xfb, 0xd9, 0xa5, 0x19, 0xa8, 0xd3, 0x1b, 0x1b, 0xaa, 0x7e, 0xde, 0xa5, 0x5b, 0xc8, 0xf4,
0xc3, 0xb4, 0x4b, 0x37, 0x90, 0xee, 0x69, 0xc7, 0xc1, 0x34, 0x99, 0x89, 0xaa, 0x14, 0xd1, 0xc4, 0xb4, 0x49, 0x38, 0xca, 0x66, 0xa2, 0x98, 0x22, 0xba, 0xba, 0xa7, 0x4d, 0xc2, 0x91, 0xf5, 0xb1,
0x9e, 0x76, 0x1c, 0x4c, 0x8d, 0x8f, 0x2d, 0x44, 0xd1, 0x86, 0x2e, 0x3b, 0xb2, 0x51, 0xf4, 0x3d, 0xa9, 0x28, 0xda, 0x31, 0x65, 0x47, 0x31, 0x8a, 0xbe, 0x81, 0x95, 0x01, 0x1f, 0x9c, 0xf2, 0x54,
0x6c, 0x8e, 0xf8, 0xe8, 0x92, 0xc7, 0x62, 0xe8, 0x8f, 0x93, 0x0a, 0xae, 0xf9, 0xc0, 0x87, 0x3c, 0xf6, 0x45, 0x92, 0x55, 0x70, 0xdd, 0x1b, 0x2a, 0xf2, 0x55, 0xce, 0xc1, 0xd4, 0x7b, 0xd4, 0x19,
0x4e, 0x39, 0xe8, 0x7a, 0x8f, 0x5a, 0xa3, 0x39, 0x0c, 0xf9, 0x8b, 0xc2, 0xac, 0x86, 0x5b, 0x56, 0x4c, 0x60, 0xc8, 0x7f, 0x54, 0xc6, 0x35, 0xdc, 0xac, 0xf2, 0x72, 0x11, 0x8f, 0x7c, 0x7a, 0xed,
0x5e, 0xae, 0xab, 0x23, 0x5f, 0xdd, 0xfb, 0xc8, 0xa4, 0x3d, 0x58, 0x28, 0x47, 0xd3, 0x32, 0x6c, 0x23, 0xb3, 0xf6, 0x60, 0xaa, 0x1c, 0xcd, 0xcb, 0xb0, 0xe9, 0x25, 0xad, 0xe6, 0x80, 0x87, 0x5c,
0x71, 0x09, 0x9f, 0xd9, 0xe3, 0x01, 0x47, 0x0d, 0xb4, 0xb4, 0xcb, 0x18, 0x70, 0xce, 0xd9, 0x36, 0xbf, 0xc0, 0x92, 0x71, 0x19, 0x0b, 0x4e, 0x38, 0xdb, 0xf2, 0x84, 0xb3, 0xb9, 0xbf, 0xaa, 0x80,
0xe6, 0x9c, 0xcd, 0xfe, 0xcf, 0x02, 0x58, 0xf3, 0xd6, 0x42, 0x00, 0x2a, 0x83, 0x08, 0xbf, 0xac, 0x33, 0x69, 0x2d, 0x04, 0xa0, 0x71, 0x10, 0xeb, 0x2f, 0xe7, 0x2d, 0xb2, 0x0c, 0x9d, 0x03, 0x7e,
0x0f, 0xc8, 0x06, 0x34, 0x06, 0xfc, 0xf6, 0x24, 0xe4, 0xe7, 0xd1, 0x49, 0xc8, 0xad, 0x02, 0xd9, 0xf9, 0x3a, 0xe2, 0xc7, 0xf1, 0xeb, 0x88, 0x3b, 0x15, 0xb2, 0x0e, 0xab, 0x07, 0xfc, 0xf2, 0xd0,
0x81, 0xad, 0x01, 0xbf, 0x3d, 0xd5, 0x95, 0xcc, 0xeb, 0x38, 0x9a, 0x8c, 0x31, 0xf8, 0x59, 0x45, 0x54, 0x32, 0x5f, 0xa6, 0xf1, 0x30, 0xd1, 0xc1, 0xcf, 0xa9, 0x92, 0x0e, 0x34, 0x5f, 0xf1, 0x48,
0xd2, 0x80, 0xea, 0x31, 0x0f, 0x91, 0x89, 0x55, 0x22, 0x75, 0x58, 0xa3, 0xa8, 0x30, 0xab, 0x4c, 0x33, 0x71, 0x6a, 0xa4, 0x0d, 0x0b, 0x54, 0x3f, 0x98, 0x53, 0x27, 0x04, 0x96, 0x76, 0x4a, 0xf5,
0x08, 0xb4, 0xba, 0xb9, 0xfa, 0xd1, 0x5a, 0x43, 0x26, 0x69, 0x24, 0x3e, 0x0c, 0x6f, 0x7c, 0xa9, 0xa3, 0xb3, 0xa0, 0x99, 0xe4, 0x91, 0x78, 0x3f, 0xba, 0x10, 0x0a, 0x0f, 0x77, 0x1a, 0x64, 0x0d,
0x0e, 0xb7, 0x2a, 0x64, 0x1b, 0xac, 0xf9, 0x94, 0x6d, 0x55, 0xc9, 0x0f, 0x60, 0x37, 0xc5, 0xce, 0x9c, 0xc9, 0x94, 0xed, 0x34, 0xc9, 0x3b, 0xb0, 0x91, 0x63, 0xc7, 0x4f, 0x92, 0xad, 0xb7, 0xc8,
0x54, 0x92, 0xac, 0xd7, 0xc8, 0x16, 0x6c, 0xa4, 0xeb, 0x47, 0x3e, 0xb6, 0x0f, 0x56, 0x5d, 0x9f, 0x2a, 0x2c, 0xe7, 0xeb, 0x2f, 0x84, 0x6e, 0x1f, 0x9c, 0xb6, 0x39, 0x63, 0x4a, 0x61, 0x0e, 0xb8,
0xb1, 0xf0, 0x60, 0x16, 0xd8, 0x7f, 0x59, 0x00, 0x6b, 0x5e, 0xb1, 0xa4, 0x0d, 0xdb, 0xf3, 0xb8, 0xff, 0x59, 0x01, 0x67, 0xf2, 0x61, 0x49, 0x0f, 0xd6, 0x26, 0x71, 0xfb, 0x41, 0xa8, 0x35, 0x70,
0x43, 0x2f, 0xc0, 0x17, 0x78, 0x0c, 0x3b, 0xf3, 0x2b, 0xa7, 0x3c, 0xf4, 0xfc, 0xf0, 0xca, 0x2a, 0x07, 0xd6, 0x27, 0x57, 0x0e, 0x79, 0x14, 0x88, 0xe8, 0xcc, 0xa9, 0x90, 0x4d, 0xe8, 0x4d, 0x2e,
0x90, 0x3d, 0x68, 0xcf, 0x2f, 0x26, 0xd1, 0xd7, 0x2a, 0x2e, 0x5b, 0xed, 0x71, 0x37, 0xc0, 0x32, 0x66, 0xd1, 0xd7, 0xa9, 0xce, 0x5a, 0xdd, 0xe5, 0x7e, 0xa8, 0xcb, 0x38, 0xa7, 0xe6, 0xfe, 0x5b,
0xce, 0x2a, 0xd9, 0x7f, 0x56, 0x80, 0x47, 0x2b, 0xb5, 0x8d, 0xcf, 0x79, 0x11, 0x5e, 0x87, 0xd1, 0x05, 0x6e, 0xcf, 0x7d, 0x6d, 0xad, 0xce, 0x93, 0xe8, 0x3c, 0x8a, 0x2f, 0x23, 0xe7, 0x2d, 0x0d,
0x6d, 0x68, 0x7d, 0x80, 0xc0, 0xec, 0xcc, 0x26, 0xd4, 0x32, 0x67, 0x34, 0xa1, 0x36, 0xe3, 0x49, 0x8c, 0xcf, 0xec, 0x42, 0xab, 0x70, 0x46, 0x17, 0x5a, 0x63, 0x9e, 0x64, 0x11, 0xda, 0x3b, 0x2c,
0xd6, 0xa1, 0xde, 0x65, 0xa1, 0xcb, 0x83, 0x80, 0x7b, 0x56, 0x19, 0xf7, 0x9d, 0x63, 0xb7, 0xc2, 0xf2, 0x79, 0x18, 0xf2, 0xc0, 0xa9, 0xeb, 0x7d, 0xc7, 0xba, 0x5b, 0xe1, 0x81, 0xb3, 0x40, 0x56,
0x3d, 0x6b, 0x8d, 0x6c, 0xc2, 0xfa, 0x45, 0xa8, 0xc0, 0xef, 0xa2, 0x58, 0x0e, 0xa7, 0x56, 0xc5, 0x60, 0xf1, 0x24, 0x42, 0xf0, 0xeb, 0x38, 0x55, 0xfd, 0x91, 0xd3, 0x70, 0xbf, 0xaf, 0x40, 0x57,
0xfe, 0xbe, 0x00, 0x4d, 0xb4, 0xc7, 0x57, 0x51, 0x74, 0x3d, 0x62, 0xf1, 0xf5, 0xea, 0x50, 0x3f, 0xdb, 0xe3, 0xd3, 0x38, 0x3e, 0x1f, 0xb0, 0xf4, 0x7c, 0x7e, 0xa8, 0x1f, 0xa6, 0xa1, 0x4d, 0x5c,
0x89, 0x03, 0x93, 0xb8, 0xf0, 0x33, 0xed, 0xf9, 0x4b, 0x99, 0x9e, 0xff, 0x31, 0xd4, 0x55, 0xbd, 0xfa, 0x33, 0xef, 0xf9, 0x6b, 0x85, 0x9e, 0xff, 0x0e, 0xb4, 0xb1, 0x5e, 0xf7, 0x34, 0xad, 0x09,
0xee, 0x20, 0xad, 0x0e, 0x2a, 0x35, 0x85, 0xb8, 0x88, 0x83, 0x6c, 0xe3, 0xb6, 0x96, 0x6f, 0xdc, 0x2a, 0x2d, 0x44, 0x9c, 0xa4, 0x61, 0xb1, 0x71, 0x5b, 0x28, 0x37, 0x6e, 0x77, 0x01, 0xac, 0xb1,
0x3e, 0x06, 0x30, 0xc6, 0x8a, 0x16, 0x5a, 0xd1, 0x16, 0x6a, 0x30, 0x1d, 0x69, 0xff, 0x29, 0x7c, 0x6a, 0x0b, 0x6d, 0x18, 0x0b, 0xb5, 0x98, 0x6d, 0xe5, 0xfe, 0x2b, 0xbc, 0xad, 0x25, 0xdc, 0x8b,
0x88, 0x12, 0xf6, 0x43, 0x71, 0x21, 0x78, 0x8c, 0x07, 0xe9, 0x89, 0xe9, 0x0a, 0x51, 0x77, 0xa1, 0xe4, 0x89, 0xe4, 0xa9, 0x3e, 0xc8, 0x4c, 0x4c, 0xe7, 0x88, 0xba, 0x01, 0xad, 0xa1, 0xa5, 0xb3,
0x36, 0x31, 0x74, 0x46, 0xde, 0x14, 0x56, 0x03, 0xcc, 0x21, 0xf3, 0xd5, 0xac, 0x43, 0x17, 0x72, 0xf2, 0xe6, 0x30, 0x0e, 0x30, 0xfb, 0x4c, 0xe0, 0xac, 0xc3, 0x14, 0x72, 0x4d, 0x84, 0xf7, 0x4b,
0x55, 0x05, 0x1f, 0xe6, 0xfa, 0xca, 0x72, 0x4e, 0x3c, 0xfb, 0xad, 0x2e, 0x97, 0xba, 0x01, 0x67, 0x7d, 0x65, 0xbd, 0x24, 0x9e, 0xfb, 0xdc, 0x94, 0x4b, 0x3b, 0x21, 0x67, 0xe9, 0x33, 0x21, 0x55,
0xf1, 0x1b, 0x5f, 0xc8, 0x28, 0x9e, 0x66, 0x83, 0x67, 0x21, 0x17, 0x3c, 0x3f, 0x06, 0x70, 0x91, 0x9c, 0x8e, 0x8a, 0xc1, 0xb3, 0x52, 0x0a, 0x9e, 0x77, 0x01, 0x7c, 0x4d, 0x68, 0xee, 0x62, 0x83,
0x50, 0xdf, 0xc5, 0x04, 0x77, 0x83, 0xe9, 0x48, 0xfb, 0x97, 0x05, 0x20, 0xc8, 0xcc, 0x4c, 0xfc, 0xbb, 0xc5, 0x6c, 0x2b, 0xf7, 0x87, 0x0a, 0x10, 0xcd, 0xcc, 0x4e, 0xfc, 0x0f, 0x85, 0xaf, 0x86,
0x4f, 0x7d, 0x57, 0x4e, 0x62, 0xbe, 0x74, 0x32, 0x95, 0x19, 0x1f, 0x16, 0x57, 0x8c, 0x0f, 0x4b, 0x29, 0x9f, 0x39, 0x99, 0x2a, 0x8c, 0x0f, 0xab, 0x73, 0xc6, 0x87, 0x35, 0x1c, 0xac, 0x4c, 0x8d,
0x6a, 0xb0, 0xb2, 0x30, 0x3e, 0x2c, 0x2b, 0x74, 0x32, 0x3e, 0x7c, 0x0c, 0x75, 0xd5, 0x49, 0xa9, 0x0f, 0xeb, 0x88, 0xce, 0xc6, 0x87, 0x77, 0xa0, 0x8d, 0x9d, 0x14, 0xce, 0x0f, 0xcd, 0x28, 0x06,
0xf9, 0xa1, 0x1e, 0xc5, 0xa8, 0xf9, 0xe1, 0xd9, 0xd2, 0xf9, 0x61, 0x45, 0x11, 0xac, 0x98, 0x1f, 0xe7, 0x87, 0x47, 0x33, 0xe7, 0x87, 0x0d, 0x24, 0x98, 0x33, 0x3f, 0x6c, 0x16, 0xe7, 0x87, 0x7d,
0x56, 0xb3, 0xf3, 0xc3, 0x21, 0x6c, 0x2d, 0xde, 0x44, 0xac, 0x1e, 0x91, 0xfe, 0x0e, 0xd4, 0xc6, 0x58, 0x9d, 0xbe, 0x89, 0x9c, 0x3f, 0x22, 0xfd, 0x6b, 0x68, 0x25, 0x96, 0xc8, 0x96, 0x87, 0x9b,
0x86, 0xc8, 0x94, 0x87, 0x7b, 0xf9, 0x90, 0x98, 0xe7, 0x44, 0x53, 0x6a, 0xfb, 0x97, 0x45, 0x68, 0xe5, 0x90, 0x58, 0xe6, 0x44, 0x73, 0x6a, 0xf7, 0x87, 0x2a, 0x74, 0x0a, 0xb3, 0xf9, 0x39, 0xef,
0x64, 0x66, 0xf3, 0x2b, 0xf4, 0xde, 0x86, 0x2a, 0xf3, 0xbc, 0x98, 0x0b, 0x91, 0xbc, 0x97, 0x01, 0xde, 0x83, 0x26, 0x0b, 0x82, 0x94, 0x4b, 0x99, 0xe9, 0xcb, 0x82, 0x45, 0x91, 0x6a, 0x25, 0x91,
0xb3, 0x22, 0x95, 0x72, 0x22, 0xe5, 0x6b, 0x7e, 0xdd, 0x81, 0x65, 0x6a, 0x7e, 0x02, 0xe5, 0x31, 0xca, 0x35, 0xbf, 0xe9, 0xc0, 0x0a, 0x35, 0x3f, 0x81, 0x7a, 0xc2, 0x54, 0xdf, 0xd6, 0xef, 0xf8,
0x93, 0x43, 0x53, 0xbf, 0xab, 0xef, 0x54, 0x53, 0x95, 0x8c, 0xa6, 0xb2, 0x63, 0xf1, 0xaa, 0x99, 0x9d, 0xbf, 0x54, 0xa3, 0xf0, 0x52, 0xc5, 0xb1, 0x78, 0xd3, 0xce, 0x28, 0xed, 0x58, 0x7c, 0x0d,
0x51, 0x9a, 0xb1, 0xf8, 0x36, 0xac, 0xf1, 0x51, 0xf4, 0x33, 0x5f, 0xe5, 0xbe, 0x3a, 0xd5, 0x00, 0x16, 0xf8, 0x20, 0xfe, 0x46, 0x60, 0xee, 0x6b, 0x53, 0x03, 0xe8, 0xa7, 0xba, 0x64, 0x61, 0xc8,
0xaa, 0xea, 0x96, 0x05, 0x01, 0x97, 0x66, 0x14, 0x62, 0x20, 0x64, 0x8e, 0x66, 0x64, 0x7a, 0x22, 0x95, 0x1d, 0x85, 0x58, 0x48, 0x33, 0xd7, 0x66, 0x64, 0x7b, 0x22, 0xfc, 0xc6, 0x67, 0x15, 0x41,
0xf5, 0xad, 0xd4, 0xea, 0x7b, 0x1e, 0x0f, 0x4d, 0x2f, 0x64, 0xa0, 0x3b, 0xe6, 0x20, 0xbb, 0x50, 0xc0, 0x23, 0xdb, 0x0b, 0x59, 0xe8, 0x8a, 0x39, 0xc8, 0x06, 0xb4, 0x92, 0x58, 0x0a, 0xec, 0x2a,
0x1b, 0x47, 0xc2, 0x57, 0x5d, 0xe5, 0xba, 0x9e, 0x17, 0x27, 0xb0, 0xfd, 0x6f, 0xe6, 0x29, 0xcd, 0x17, 0xcd, 0xbc, 0x38, 0x83, 0xdd, 0x9f, 0x5b, 0x55, 0xda, 0xdf, 0x5b, 0xe6, 0xa8, 0xb2, 0xa0,
0xff, 0x5b, 0x56, 0x3c, 0x65, 0xe6, 0xc1, 0x8a, 0x4b, 0xc7, 0xdc, 0xa5, 0xfc, 0x04, 0x35, 0x33, 0xb0, 0xea, 0xcc, 0x31, 0x77, 0xad, 0x3c, 0x41, 0x2d, 0x4c, 0x2a, 0xf1, 0x1b, 0x87, 0x02, 0x3c,
0xa9, 0x54, 0xdf, 0x6a, 0x28, 0xc0, 0x63, 0xff, 0x86, 0x7b, 0xce, 0xfb, 0x38, 0x1a, 0x99, 0x17, 0x15, 0x17, 0x3c, 0xf0, 0xde, 0xa4, 0xf1, 0xc0, 0x6a, 0xb0, 0x63, 0x71, 0x5f, 0xa4, 0xf1, 0x80,
0x6c, 0x18, 0xdc, 0x37, 0x71, 0x34, 0x22, 0x2f, 0x61, 0x57, 0xb7, 0xef, 0x82, 0x7b, 0x8e, 0x5a, 0x3c, 0x81, 0x0d, 0xd3, 0xbe, 0x4b, 0x1e, 0x78, 0xb8, 0x60, 0xa7, 0x90, 0x38, 0x87, 0x37, 0x41,
0x30, 0x53, 0x48, 0x35, 0x87, 0xd7, 0x41, 0x60, 0x47, 0x35, 0xf3, 0x82, 0x7b, 0xbd, 0x74, 0xfd, 0x60, 0x1d, 0x9b, 0x79, 0xc9, 0x83, 0xdd, 0x7c, 0x7d, 0x5f, 0x2f, 0x9b, 0x91, 0x54, 0xe4, 0x67,
0x10, 0x97, 0xf5, 0x48, 0x2a, 0x74, 0x13, 0xf6, 0xfa, 0xd1, 0x41, 0xa3, 0x14, 0xf7, 0xdf, 0x50, 0xec, 0x8d, 0xd2, 0xc1, 0xa0, 0x90, 0xfb, 0x9f, 0x63, 0x45, 0x52, 0x6c, 0x91, 0xe6, 0xfc, 0xce,
0x15, 0x49, 0xb6, 0x45, 0x5a, 0xf1, 0x7f, 0x9e, 0x94, 0x0c, 0xb7, 0x98, 0xb9, 0x31, 0xb6, 0xb4, 0x93, 0x93, 0xe9, 0x2d, 0x76, 0x6e, 0xac, 0x5b, 0xda, 0xda, 0xcc, 0xdf, 0xa8, 0xf4, 0x2a, 0xcd,
0xa5, 0xa5, 0xff, 0xa3, 0xc2, 0x55, 0x9a, 0x92, 0x65, 0x75, 0x00, 0xf9, 0x98, 0xf1, 0x5f, 0x05, 0xc9, 0x8a, 0x6f, 0x00, 0xe5, 0x98, 0xf1, 0xeb, 0x8a, 0x09, 0x1a, 0x47, 0xec, 0x82, 0x07, 0xdb,
0x1d, 0x34, 0xce, 0xd8, 0x0d, 0xf7, 0x3a, 0xc6, 0x0e, 0x33, 0x16, 0x5a, 0xc8, 0x5b, 0xe8, 0xb2, 0xd6, 0x0e, 0x0b, 0x16, 0x5a, 0x29, 0x5b, 0xe8, 0xac, 0x9f, 0x0f, 0x36, 0xa1, 0xfd, 0x86, 0x5d,
0x7f, 0x1f, 0xec, 0x41, 0xfd, 0x3d, 0xbb, 0x89, 0x26, 0xb1, 0x2f, 0xf5, 0x83, 0xd7, 0xe8, 0x0c, 0xc4, 0xc3, 0x54, 0x28, 0xa3, 0xf0, 0x16, 0x1d, 0x23, 0xae, 0x88, 0xa6, 0x0f, 0xa0, 0x6b, 0xb2,
0x71, 0x47, 0x34, 0x7d, 0x06, 0x4d, 0x9d, 0xdd, 0x9d, 0xac, 0xd3, 0x36, 0x34, 0x4e, 0xcf, 0x6c, 0xbb, 0x57, 0x74, 0xda, 0x8e, 0xc1, 0x99, 0x99, 0xcd, 0x9f, 0xc0, 0x8a, 0x09, 0x83, 0xb2, 0x1f,
0x7e, 0x15, 0x36, 0x75, 0x18, 0x14, 0xc3, 0x28, 0x96, 0xaa, 0x7d, 0x15, 0xc6, 0x42, 0x37, 0xd4, 0xa7, 0x0a, 0xdb, 0x57, 0x69, 0x2d, 0x74, 0x19, 0x17, 0x8e, 0x34, 0x5e, 0xb7, 0xb1, 0x52, 0x47,
0xc2, 0x19, 0xe2, 0xb1, 0x8d, 0x15, 0x18, 0xf9, 0x79, 0x28, 0x4c, 0x89, 0x86, 0x9f, 0x68, 0x1d, 0x7e, 0x1e, 0x49, 0x5b, 0xa2, 0xe9, 0x4f, 0x6d, 0x1d, 0x42, 0x7a, 0x8a, 0xcb, 0xcc, 0x50, 0x1b,
0xbe, 0x70, 0x24, 0x17, 0x89, 0xa1, 0x56, 0x7c, 0x71, 0xce, 0x85, 0x7c, 0x5b, 0xae, 0x95, 0xad, 0x42, 0x1e, 0x73, 0xa9, 0x9e, 0xd7, 0x5b, 0x75, 0x67, 0xc1, 0xfd, 0xae, 0x62, 0xe2, 0xf5, 0xd4,
0x35, 0xfb, 0x17, 0x05, 0x1d, 0xaf, 0x17, 0x26, 0x00, 0x2b, 0x8c, 0x6d, 0xbe, 0x92, 0x2b, 0x2e, 0x04, 0x60, 0x8e, 0xb1, 0x4d, 0x56, 0x72, 0xd5, 0xe9, 0x4a, 0x6e, 0x0f, 0xee, 0xf5, 0x4d, 0xe0,
0x56, 0x72, 0x7d, 0x78, 0x32, 0xd4, 0x81, 0xd7, 0x61, 0xb1, 0x3b, 0xf4, 0x6f, 0xb8, 0x23, 0x26, 0xf5, 0x58, 0xea, 0xf7, 0xc5, 0x05, 0xf7, 0xe4, 0x30, 0x49, 0xb4, 0xec, 0x3c, 0x62, 0xa7, 0xa1,
0xe3, 0x31, 0xca, 0xce, 0x43, 0x76, 0x19, 0x98, 0xe9, 0x4f, 0x8d, 0xee, 0x19, 0xb2, 0x8e, 0xa6, 0x9d, 0xfe, 0xb4, 0xe8, 0xa6, 0x25, 0xdb, 0x36, 0x54, 0x47, 0x86, 0x68, 0xcf, 0xd0, 0xb8, 0xff,
0x3a, 0xd3, 0x44, 0x7d, 0x4d, 0x63, 0xff, 0x5d, 0x41, 0x37, 0x79, 0x26, 0x21, 0x62, 0x36, 0xb9, 0x57, 0x31, 0x4d, 0x9e, 0x4d, 0x88, 0x3a, 0x9b, 0x5c, 0x73, 0xe0, 0xfc, 0x19, 0x34, 0x6c, 0x31,
0xe7, 0xc0, 0xf9, 0x2b, 0xa8, 0x98, 0x62, 0x4e, 0x17, 0xe2, 0x73, 0x53, 0x93, 0x0c, 0xc3, 0xfd, 0x67, 0x0a, 0xf1, 0x89, 0xa9, 0x49, 0x81, 0xe1, 0xd6, 0xf1, 0x78, 0x36, 0x48, 0xed, 0x26, 0xf7,
0xf3, 0xd9, 0x6c, 0x90, 0x9a, 0x4d, 0xf6, 0x17, 0xd0, 0xc8, 0xa0, 0x55, 0x62, 0x1f, 0x1c, 0x0d, 0x13, 0xe8, 0x14, 0xd0, 0x98, 0xd8, 0x0f, 0x5e, 0x1c, 0xbc, 0xfe, 0xfa, 0xc0, 0x24, 0xf6, 0x63,
0x4e, 0xbe, 0x1b, 0xe8, 0xc4, 0x7e, 0x4e, 0x2f, 0xce, 0xce, 0xfb, 0x3d, 0xab, 0xa0, 0x12, 0xf4, 0x7a, 0x72, 0x74, 0xbc, 0xb7, 0xeb, 0x54, 0x30, 0x41, 0x1f, 0x20, 0xf8, 0xf5, 0x6b, 0x7a, 0xfc,
0x40, 0x81, 0xdf, 0x9d, 0xd0, 0xf3, 0x37, 0x3f, 0xb5, 0x8a, 0xf6, 0xf7, 0x25, 0x3d, 0x3d, 0xcb, 0xec, 0xef, 0x9d, 0xaa, 0xfb, 0x7d, 0xcd, 0x4c, 0xcf, 0x8a, 0x05, 0x82, 0xad, 0x7b, 0xe6, 0x08,
0x16, 0x08, 0xa6, 0xee, 0x59, 0x21, 0x3c, 0x81, 0xb2, 0xf2, 0x0a, 0x63, 0x4c, 0xf8, 0x8d, 0x17, 0x4f, 0xa0, 0x8e, 0x5e, 0x61, 0x8d, 0x49, 0x7f, 0xeb, 0x0b, 0xa9, 0xd8, 0xba, 0x6d, 0x55, 0xc5,
0x92, 0x91, 0x71, 0xdb, 0xa2, 0x8c, 0xd0, 0xb8, 0xdc, 0x21, 0x06, 0x9d, 0xf0, 0x2a, 0xf1, 0xdc, 0xda, 0xb8, 0xfc, 0xbe, 0x0e, 0x3a, 0xd1, 0x59, 0xe6, 0xb9, 0x63, 0x84, 0x7e, 0x12, 0x3b, 0xef,
0x19, 0x02, 0x55, 0x62, 0xe6, 0x3d, 0x3a, 0x8d, 0x99, 0xa1, 0x70, 0x8a, 0xeb, 0xa8, 0x7f, 0xd9, 0x31, 0x69, 0xcc, 0x0e, 0x85, 0x73, 0xdc, 0x36, 0xfe, 0x64, 0x93, 0x72, 0x99, 0xc4, 0x91, 0xcc,
0xc4, 0x5c, 0x8c, 0xa3, 0x50, 0x24, 0xb1, 0x30, 0x85, 0x31, 0xac, 0x62, 0xad, 0xee, 0xeb, 0xcd, 0x62, 0x61, 0x0e, 0xeb, 0xb0, 0xaa, 0x6b, 0x75, 0x61, 0x36, 0x1b, 0xfb, 0x6b, 0x5b, 0xcc, 0xb6,
0xda, 0xfe, 0xea, 0x06, 0xd3, 0x91, 0x84, 0x2f, 0x9f, 0xc2, 0xd6, 0xd4, 0xcb, 0xfe, 0x66, 0xfe, 0x22, 0x7c, 0xf6, 0x14, 0xb6, 0x85, 0x9a, 0xfd, 0x8b, 0xb2, 0x66, 0x67, 0xdc, 0x7a, 0x6b, 0x46,
0x65, 0x97, 0xdc, 0x7a, 0x7f, 0x49, 0x61, 0xbc, 0x6c, 0x76, 0xab, 0x75, 0x58, 0x4f, 0x5b, 0xed, 0x61, 0x3c, 0x6b, 0x76, 0x6b, 0xde, 0xb0, 0x9d, 0xb7, 0xda, 0x7f, 0x07, 0x64, 0x4e, 0x91, 0x55,
0xdf, 0x07, 0xb2, 0xa2, 0xc8, 0xca, 0xea, 0xe2, 0xb4, 0x3f, 0xe8, 0x1d, 0x0e, 0x5e, 0x9b, 0x22, 0x7c, 0x8b, 0xc3, 0xbd, 0x83, 0xdd, 0xfd, 0x83, 0x2f, 0x6d, 0x91, 0xb5, 0xb3, 0xb3, 0x77, 0xa8,
0xab, 0xdb, 0xed, 0x9f, 0xa2, 0x66, 0x74, 0x91, 0xd5, 0xef, 0xbe, 0x3b, 0x1c, 0xf4, 0x7b, 0x56, 0x5f, 0xc6, 0x14, 0x59, 0x7b, 0x3b, 0x2f, 0xf7, 0x0f, 0xf6, 0x76, 0x9d, 0x9a, 0x86, 0x76, 0xb6,
0x09, 0xa1, 0x6e, 0x67, 0xd0, 0xed, 0xbf, 0xeb, 0xf7, 0xac, 0xb2, 0xfd, 0xaf, 0x05, 0xdd, 0x83, 0x0f, 0x76, 0xf6, 0x5e, 0xee, 0xed, 0x3a, 0x75, 0xf7, 0x67, 0x15, 0xd3, 0x83, 0x97, 0x8b, 0xdc,
0xe7, 0x8b, 0xdc, 0x1e, 0x77, 0x7d, 0xb1, 0xfa, 0xbf, 0x2f, 0x7b, 0x50, 0x37, 0xef, 0x79, 0x98, 0x5d, 0xee, 0x0b, 0x39, 0xff, 0xd7, 0x97, 0x4d, 0x68, 0x5b, 0x7d, 0xee, 0x67, 0x96, 0x36, 0x46,
0x58, 0xda, 0x0c, 0x41, 0xfe, 0x10, 0x36, 0x3c, 0xb3, 0xdf, 0xc9, 0x59, 0xde, 0xe7, 0xf3, 0xd3, 0x90, 0x7f, 0x84, 0xe5, 0xc0, 0xee, 0xf7, 0x4a, 0x96, 0xf7, 0xe1, 0xe4, 0x34, 0x63, 0xd6, 0x91,
0x8c, 0x65, 0x47, 0xee, 0x27, 0x1f, 0xe6, 0x79, 0x5a, 0x5e, 0x0e, 0xb6, 0x3f, 0x85, 0x56, 0x9e, 0x5b, 0xd9, 0x87, 0x55, 0xcf, 0x52, 0x50, 0x82, 0xdd, 0xf7, 0x61, 0xa9, 0x4c, 0x51, 0xba, 0xec,
0x22, 0x77, 0xd9, 0x0f, 0x72, 0x97, 0x2d, 0xd8, 0xff, 0x5c, 0x84, 0x8d, 0xb9, 0x5f, 0x2a, 0xac, 0x5b, 0xa5, 0xcb, 0x56, 0xdc, 0x9f, 0x54, 0x61, 0x79, 0xe2, 0x3f, 0x15, 0xe6, 0x67, 0xf9, 0xc9,
0xce, 0xf2, 0xf3, 0xe3, 0xe0, 0xe2, 0xc2, 0x38, 0x98, 0x7c, 0x0a, 0x24, 0x4b, 0xe2, 0x64, 0xe7, 0x71, 0x70, 0x75, 0x6a, 0x1c, 0x4c, 0xde, 0x07, 0x52, 0x24, 0xf1, 0x8a, 0x73, 0x35, 0xa7, 0x40,
0x6a, 0x56, 0x86, 0x50, 0xc7, 0xaa, 0x6c, 0xd9, 0x50, 0x7e, 0x48, 0xd9, 0x40, 0xbe, 0x84, 0xa6, 0x68, 0x62, 0x55, 0xb1, 0x6c, 0xa8, 0xdf, 0xa4, 0x6c, 0x20, 0x9f, 0x42, 0x57, 0xc6, 0xbe, 0x60,
0x88, 0x5c, 0x9f, 0x05, 0x4e, 0xe0, 0x87, 0xd7, 0xc9, 0xcf, 0x43, 0x1e, 0xcd, 0xfd, 0xf4, 0x41, 0xa1, 0x17, 0x8a, 0xe8, 0x3c, 0xfb, 0xf7, 0x90, 0xdb, 0x13, 0xff, 0xfa, 0x80, 0x14, 0x2f, 0x35,
0x51, 0xbc, 0x43, 0x02, 0xda, 0x10, 0x33, 0x80, 0xfc, 0x1e, 0x6c, 0xf3, 0x50, 0x38, 0x49, 0xe9, 0x01, 0xed, 0xc8, 0x31, 0x40, 0xfe, 0x16, 0xd6, 0x78, 0x24, 0xbd, 0xac, 0x74, 0xf4, 0x82, 0xfc,
0xe8, 0x78, 0xe9, 0x0f, 0x42, 0x4a, 0x8b, 0xd3, 0xce, 0x85, 0xda, 0x94, 0x12, 0x3e, 0x8f, 0x12, 0x1f, 0x42, 0x6a, 0xd3, 0xd3, 0xce, 0xa9, 0xda, 0x94, 0x12, 0x3e, 0x89, 0x92, 0xae, 0x04, 0xa0,
0xb6, 0x00, 0xa0, 0xec, 0x36, 0xe9, 0x60, 0x33, 0xf5, 0x5d, 0x21, 0x5f, 0xdf, 0x1d, 0x41, 0xc3, 0xec, 0x32, 0xeb, 0x60, 0x0b, 0xf5, 0x5d, 0xa5, 0x5c, 0xdf, 0xbd, 0x80, 0x8e, 0x6d, 0x7d, 0x75,
0xb4, 0xbe, 0xd8, 0x82, 0xa9, 0x27, 0x6c, 0x1d, 0xfc, 0xca, 0xec, 0xc4, 0xce, 0xec, 0x07, 0x44, 0x0b, 0x86, 0x2a, 0x5c, 0x7a, 0xfc, 0xc7, 0xe3, 0x13, 0xb7, 0xc7, 0xff, 0x40, 0xf4, 0xca, 0xfe,
0xc7, 0xe6, 0xf7, 0x43, 0x86, 0xe9, 0xbe, 0xea, 0xf5, 0xb3, 0xbb, 0xed, 0xbf, 0x2d, 0x40, 0x0b, 0xff, 0x90, 0x65, 0xba, 0x85, 0xbd, 0x7e, 0x71, 0xb7, 0xfb, 0xbf, 0x15, 0x58, 0xd2, 0x22, 0x16,
0x45, 0xcc, 0x9c, 0xfc, 0xdb, 0xd0, 0x88, 0x53, 0x28, 0x19, 0x87, 0x6c, 0x67, 0x46, 0x88, 0xe9, 0x4e, 0xfe, 0x2b, 0xe8, 0xa4, 0x39, 0x94, 0x8d, 0x43, 0xd6, 0x0a, 0x23, 0xc4, 0x7c, 0x91, 0x16,
0x22, 0xcd, 0x12, 0x92, 0x03, 0xd8, 0x16, 0x93, 0xcb, 0x64, 0x8e, 0xf8, 0x56, 0x44, 0xe1, 0xab, 0x09, 0xc9, 0x63, 0x58, 0x93, 0xc3, 0xd3, 0x6c, 0x8e, 0xf8, 0x5c, 0xc6, 0xd1, 0xd3, 0x91, 0xe2,
0xa9, 0xe4, 0x49, 0xb9, 0xb5, 0x74, 0x8d, 0x7c, 0x0a, 0x9b, 0xc9, 0xdc, 0x77, 0xb6, 0x41, 0x0f, 0x59, 0xb9, 0x35, 0x73, 0x8d, 0xbc, 0x0f, 0x2b, 0xd9, 0xdc, 0x77, 0xbc, 0xc1, 0x0c, 0xc3, 0xa7,
0xc3, 0x17, 0x17, 0xec, 0xbf, 0x29, 0xa4, 0xe5, 0x09, 0x66, 0x58, 0xd5, 0x76, 0xa4, 0x26, 0x86, 0x17, 0xdc, 0xff, 0xa9, 0xe4, 0xe5, 0x89, 0xce, 0xb0, 0xd8, 0x76, 0xe4, 0x26, 0xa6, 0x3f, 0x67,
0x9f, 0x4b, 0x33, 0xe5, 0x47, 0x50, 0x31, 0xff, 0x41, 0xd2, 0x59, 0xc0, 0x40, 0x59, 0x23, 0x2d, 0x66, 0xca, 0x5b, 0xd0, 0xb0, 0xbf, 0x20, 0x99, 0x2c, 0x60, 0xa1, 0xa2, 0x91, 0xd6, 0x4b, 0x46,
0xe7, 0x8c, 0x74, 0x0f, 0xea, 0x26, 0xf3, 0x72, 0x34, 0x8b, 0x12, 0x96, 0x7d, 0x29, 0x62, 0xe6, 0xba, 0x09, 0x6d, 0x9b, 0x79, 0xb9, 0x36, 0x8b, 0x9a, 0x2e, 0xfb, 0x72, 0x44, 0xa9, 0x7e, 0x32,
0xaf, 0x95, 0x6c, 0xb9, 0xfb, 0x4f, 0x45, 0xd8, 0xcc, 0x88, 0x86, 0xfd, 0x7b, 0x14, 0x92, 0x2f, 0x75, 0xc8, 0xb8, 0x7e, 0xfa, 0x27, 0x93, 0x41, 0x0a, 0x56, 0x43, 0x3e, 0x9a, 0x30, 0xb3, 0x29,
0xa0, 0xc2, 0xd4, 0x97, 0x92, 0xb1, 0x75, 0x60, 0x2f, 0x2d, 0x19, 0x34, 0xf1, 0xbe, 0xfe, 0x43, 0x75, 0x8e, 0x89, 0xcb, 0x16, 0x96, 0xc7, 0x85, 0x6a, 0x21, 0x2e, 0x3c, 0x5d, 0xfc, 0x87, 0xce,
0xcd, 0x0e, 0xf2, 0x43, 0x58, 0x8f, 0x02, 0xcf, 0x90, 0x5c, 0xa4, 0xf9, 0x26, 0x8f, 0x34, 0xbf, 0xd6, 0x07, 0x4f, 0xb2, 0xcd, 0xa7, 0x0d, 0xfc, 0xfa, 0xf0, 0xb7, 0x01, 0x00, 0x00, 0xff, 0xff,
0x9c, 0x41, 0xc8, 0x0c, 0x44, 0x57, 0x54, 0x25, 0x09, 0x15, 0xe6, 0xdf, 0x8a, 0x91, 0x6e, 0x13, 0x17, 0xe1, 0xf7, 0xaf, 0x79, 0x26, 0x00, 0x00,
0xd6, 0x8f, 0xfa, 0x3f, 0xed, 0x76, 0x68, 0xcf, 0xe9, 0xf4, 0x7a, 0xca, 0xb5, 0x09, 0xb4, 0x3a,
0xdd, 0xee, 0xc9, 0xc5, 0xe0, 0xfc, 0xcc, 0xe0, 0x0a, 0xd8, 0x3c, 0x27, 0x64, 0xbd, 0xfe, 0xbb,
0xbe, 0x0e, 0x78, 0xdb, 0x60, 0xa5, 0x84, 0xb4, 0x7f, 0x7c, 0xf2, 0xad, 0x0a, 0x7c, 0x00, 0x95,
0x77, 0x27, 0xdd, 0x23, 0x0c, 0x7b, 0x18, 0x25, 0x2e, 0x06, 0x06, 0x5a, 0x23, 0x1b, 0xd0, 0xb8,
0x38, 0xec, 0x39, 0x17, 0xa7, 0xbd, 0x0e, 0x32, 0xa8, 0x10, 0x0b, 0x9a, 0x83, 0xce, 0x71, 0xdf,
0xe9, 0xbe, 0xe9, 0x0c, 0x5e, 0xf7, 0x7b, 0x56, 0xd5, 0xfe, 0x23, 0x9d, 0x7e, 0x33, 0x2e, 0x47,
0x7e, 0x3c, 0xe7, 0xa3, 0x0b, 0xb6, 0x38, 0x23, 0xce, 0xbb, 0x67, 0xaa, 0xa4, 0x62, 0x46, 0x49,
0xaf, 0xd6, 0xff, 0xa0, 0xb1, 0xff, 0xd9, 0xcb, 0x64, 0xf3, 0x65, 0x45, 0x7d, 0x7d, 0xfe, 0x3f,
0x01, 0x00, 0x00, 0xff, 0xff, 0x9a, 0xb1, 0xaf, 0x0c, 0xb6, 0x27, 0x00, 0x00,
} }

View File

@ -402,24 +402,7 @@ message SyncKeycard {
bool locked = 3; bool locked = 3;
string key_uid = 4; string key_uid = 4;
repeated bytes addresses = 5; repeated bytes addresses = 5;
uint64 clock = 6; uint64 position = 6;
}
message SyncKeycardAction {
Action action = 1;
string oldKeycardUid = 2;
SyncKeycard keycard = 3;
enum Action {
KEYCARD_ADDED = 0;
ACCOUNTS_ADDED = 1;
KEYCARD_DELETED = 2;
ACCOUNTS_REMOVED = 3;
LOCKED = 4;
UNLOCKED = 5;
UID_UPDATED = 6;
NAME_CHANGED = 7;
}
} }
message SyncSocialLinks { message SyncSocialLinks {

View File

@ -320,8 +320,6 @@ func (m *StatusMessage) HandleApplication() error {
return m.unmarshalProtobufData((new(protobuf.SyncContactRequestDecision))) return m.unmarshalProtobufData((new(protobuf.SyncContactRequestDecision)))
case protobuf.ApplicationMetadataMessage_SYNC_SAVED_ADDRESS: case protobuf.ApplicationMetadataMessage_SYNC_SAVED_ADDRESS:
return m.unmarshalProtobufData(new(protobuf.SyncSavedAddress)) return m.unmarshalProtobufData(new(protobuf.SyncSavedAddress))
case protobuf.ApplicationMetadataMessage_SYNC_KEYCARD_ACTION:
return m.unmarshalProtobufData(new(protobuf.SyncKeycardAction))
case protobuf.ApplicationMetadataMessage_SYNC_SOCIAL_LINKS: case protobuf.ApplicationMetadataMessage_SYNC_SOCIAL_LINKS:
return m.unmarshalProtobufData(new(protobuf.SyncSocialLinks)) return m.unmarshalProtobufData(new(protobuf.SyncSocialLinks))
case protobuf.ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL: case protobuf.ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL:

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"strings" "strings"
"time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -52,7 +51,7 @@ func (api *API) SaveAccount(ctx context.Context, account *accounts.Account) erro
return nil return nil
} }
// Setting `Keypair` without `Accounts` will update keypair only. // Setting `Keypair` without `Accounts` will update keypair only, `Keycards` won't be saved/updated this way.
func (api *API) SaveKeypair(ctx context.Context, keypair *accounts.Keypair) error { func (api *API) SaveKeypair(ctx context.Context, keypair *accounts.Keypair) error {
log.Info("[AccountsAPI::SaveKeypair]") log.Info("[AccountsAPI::SaveKeypair]")
err := (*api.messenger).SaveOrUpdateKeypair(keypair) err := (*api.messenger).SaveOrUpdateKeypair(keypair)
@ -327,13 +326,14 @@ func (api *API) VerifyPassword(password string) bool {
} }
// If keypair is migrated from keycard to app, then `accountsComingFromKeycard` should be set to true, otherwise false. // If keypair is migrated from keycard to app, then `accountsComingFromKeycard` should be set to true, otherwise false.
func (api *API) AddKeycardOrAddAccountsIfKeycardIsAdded(ctx context.Context, kcUID string, kpName string, keyUID string, // If keycard is new `Position` will be determined and set by the backend and `KeycardLocked` will be set to false.
accountAddresses []string, accountsComingFromKeycard bool) error { // If keycard is already added, `Position` and `KeycardLocked` will be unchanged.
if len(accountAddresses) == 0 { func (api *API) SaveOrUpdateKeycard(ctx context.Context, keycard *accounts.Keycard, accountsComingFromKeycard bool) error {
if len(keycard.AccountsAddresses) == 0 {
return errors.New("cannot migrate a keypair without accounts") return errors.New("cannot migrate a keypair without accounts")
} }
kpDb, err := api.db.GetKeypairByKeyUID(keyUID) kpDb, err := api.db.GetKeypairByKeyUID(keycard.KeyUID)
if err != nil { if err != nil {
if err == accounts.ErrDbKeypairNotFound { if err == accounts.ErrDbKeypairNotFound {
return errors.New("cannot migrate an unknown keypair") return errors.New("cannot migrate an unknown keypair")
@ -341,23 +341,12 @@ func (api *API) AddKeycardOrAddAccountsIfKeycardIsAdded(ctx context.Context, kcU
return err return err
} }
kp := accounts.Keycard{ relatedKeycardsByKeyUID, err := api.db.GetKeycardsWithSameKeyUID(keycard.KeyUID)
KeycardUID: kcUID,
KeycardName: kpName,
KeycardLocked: false,
KeyUID: keyUID,
LastUpdateClock: uint64(time.Now().Unix()),
}
for _, addr := range accountAddresses {
kp.AccountsAddresses = append(kp.AccountsAddresses, types.Address(common.HexToAddress(addr)))
}
knownKeycardsForKeyUID, err := api.db.GetKeycardByKeyUID(keyUID)
if err != nil { if err != nil {
return err return err
} }
added, err := (*api.messenger).AddKeycardOrAddAccountsIfKeycardIsAdded(ctx, &kp) err = (*api.messenger).SaveOrUpdateKeycard(ctx, keycard)
if err != nil { if err != nil {
return err return err
} }
@ -365,8 +354,8 @@ func (api *API) AddKeycardOrAddAccountsIfKeycardIsAdded(ctx context.Context, kcU
if !accountsComingFromKeycard { if !accountsComingFromKeycard {
// Once we migrate a keypair, corresponding keystore files need to be deleted // Once we migrate a keypair, corresponding keystore files need to be deleted
// if the keypair being migrated is not already migrated (in case user is creating a copy of an existing Keycard) // if the keypair being migrated is not already migrated (in case user is creating a copy of an existing Keycard)
if added && len(knownKeycardsForKeyUID) == 0 { if len(relatedKeycardsByKeyUID) == 0 {
for _, addr := range kp.AccountsAddresses { for _, addr := range keycard.AccountsAddresses {
err = api.manager.DeleteAccount(addr) err = api.manager.DeleteAccount(addr)
if err != nil { if err != nil {
return err return err
@ -383,52 +372,42 @@ func (api *API) AddKeycardOrAddAccountsIfKeycardIsAdded(ctx context.Context, kcU
return nil return nil
} }
func (api *API) RemoveMigratedAccountsForKeycard(ctx context.Context, kcUID string, accountAddresses []string) error {
clock := uint64(time.Now().Unix())
var addresses []types.Address
for _, addr := range accountAddresses {
addresses = append(addresses, types.HexToAddress(addr))
}
return (*api.messenger).RemoveMigratedAccountsForKeycard(ctx, kcUID, addresses, clock)
}
func (api *API) GetAllKnownKeycards(ctx context.Context) ([]*accounts.Keycard, error) { func (api *API) GetAllKnownKeycards(ctx context.Context) ([]*accounts.Keycard, error) {
return api.db.GetAllKnownKeycards() return api.db.GetAllKnownKeycards()
} }
func (api *API) GetAllKnownKeycardsGroupedByKeyUID(ctx context.Context) ([]*accounts.Keycard, error) { func (api *API) GetKeycardsWithSameKeyUID(ctx context.Context, keyUID string) ([]*accounts.Keycard, error) {
return api.db.GetAllKnownKeycardsGroupedByKeyUID() return api.db.GetKeycardsWithSameKeyUID(keyUID)
} }
func (api *API) GetKeycardByKeyUID(ctx context.Context, keyUID string) ([]*accounts.Keycard, error) { func (api *API) GetKeycardByKeycardUID(ctx context.Context, keycardUID string) (*accounts.Keycard, error) {
return api.db.GetKeycardByKeyUID(keyUID) return api.db.GetKeycardByKeycardUID(keycardUID)
} }
func (api *API) SetKeycardName(ctx context.Context, kcUID string, kpName string) error { func (api *API) SetKeycardName(ctx context.Context, keycardUID string, kpName string) error {
clock := uint64(time.Now().Unix()) return (*api.messenger).SetKeycardName(ctx, keycardUID, kpName)
return (*api.messenger).SetKeycardName(ctx, kcUID, kpName, clock)
} }
func (api *API) KeycardLocked(ctx context.Context, kcUID string) error { func (api *API) KeycardLocked(ctx context.Context, keycardUID string) error {
clock := uint64(time.Now().Unix()) return (*api.messenger).KeycardLocked(ctx, keycardUID)
return (*api.messenger).KeycardLocked(ctx, kcUID, clock)
} }
func (api *API) KeycardUnlocked(ctx context.Context, kcUID string) error { func (api *API) KeycardUnlocked(ctx context.Context, keycardUID string) error {
clock := uint64(time.Now().Unix()) return (*api.messenger).KeycardUnlocked(ctx, keycardUID)
return (*api.messenger).KeycardUnlocked(ctx, kcUID, clock)
} }
func (api *API) DeleteKeycard(ctx context.Context, kcUID string) error { func (api *API) DeleteKeycardAccounts(ctx context.Context, keycardUID string, accountAddresses []types.Address) error {
clock := uint64(time.Now().Unix()) return (*api.messenger).DeleteKeycardAccounts(ctx, keycardUID, accountAddresses)
return (*api.messenger).DeleteKeycard(ctx, kcUID, clock) }
func (api *API) DeleteKeycard(ctx context.Context, keycardUID string) error {
return (*api.messenger).DeleteKeycard(ctx, keycardUID)
} }
func (api *API) DeleteAllKeycardsWithKeyUID(ctx context.Context, keyUID string) error { func (api *API) DeleteAllKeycardsWithKeyUID(ctx context.Context, keyUID string) error {
return api.db.DeleteAllKeycardsWithKeyUID(keyUID) return (*api.messenger).DeleteAllKeycardsWithKeyUID(ctx, keyUID)
} }
func (api *API) UpdateKeycardUID(ctx context.Context, oldKcUID string, newKcUID string) error { func (api *API) UpdateKeycardUID(ctx context.Context, oldKeycardUID string, newKeycardUID string) error {
clock := uint64(time.Now().Unix()) return (*api.messenger).UpdateKeycardUID(ctx, oldKeycardUID, newKeycardUID)
return (*api.messenger).UpdateKeycardUID(ctx, oldKcUID, newKcUID, clock)
} }