-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MWA 2.0 Auth Repository #605
Conversation
...c/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsSchema.java
Show resolved
Hide resolved
@@ -9,7 +9,7 @@ | |||
String COLUMN_AUTHORIZATIONS_ID = "id"; // type: int | |||
String COLUMN_AUTHORIZATIONS_IDENTITY_ID = "identity_id"; // type: long | |||
String COLUMN_AUTHORIZATIONS_ISSUED = "issued"; // type: long | |||
String COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID = "public_key_id"; // type: long | |||
String COLUMN_AUTHORIZATIONS_ACCOUNT_ID = "public_key_id"; // type: long |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is COLUMN_AUTHORIZATIONS_ACCOUNT_ID
value suppose to be "public_key_id"
? It's unchanged from the previous schema.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, good callout. this made it easy(easier) to migrate, as I don't need to migrate this column. This column will be changed again anyways when we move to multi account.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah ya know, now that I think about this more, I might not be handling migration of these ids correctly...
I am only migrating the publickey records over to the new AccountRecord but I do not actually update these ids. hmm. will get this fixed asap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summarizing my understanding of the issue:
Pre-migrated databases will have an Authorizations Table with rows that contain a column (public_key_id
) that contains a publicKeyId
. When the migration step (onUpgrade
) occurs, the Authorizations Table is not updated and the public_key_id
column will still contain publicKeyIds
rather than accountIds
.
This is problematic because certain parts of code will assume that the column contains accountIds
when they are actually still publicKeyIds
. I'll add comments for spots where I see this being problematic.
Solutions:
-
Create a new column for
account_id
in Authorizations Table then populate it during the migration steponUpgrade
. Migrated DBs will just have a redundantpublic_key_id
column that isn't used anymore. -
On upgrade/migration, alter each row in Authorizations Table so that
public_key_id
==account_id
, by editing/updating eachpublic_key_id
value. (Is it possible to change a row's id? Where is the row's id even determined?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The names of the columns does not really matter, as long as the name is respected in our code (the schema is not exposed publicly).
- we cant drop a column in SQLite but we can rename it. So rather than deleting the table and recreating it with the new schema, I opted to rename the
public_key_id
column toaccount_id
then migrate the ids over. its maybe not the most ideal solution but it should work okay. - I don't think we can change the primary key of a row in SQL. If we did, we'd also need to update all of the references on that ID. So I instead just updated the stored id for auth authorization record.
@@ -29,18 +35,35 @@ public void onConfigure(SQLiteDatabase db) { | |||
public void onCreate(SQLiteDatabase db) { | |||
db.execSQL(IdentityRecordSchema.CREATE_TABLE_IDENTITIES); | |||
db.execSQL(AuthorizationsSchema.CREATE_TABLE_AUTHORIZATIONS); | |||
db.execSQL(PublicKeysSchema.CREATE_TABLE_PUBLIC_KEYS); | |||
db.execSQL(AccountRecordsSchema.CREATE_TABLE_ACCOUNTS); | |||
db.execSQL(WalletUriBaseSchema.CREATE_TABLE_WALLET_URI_BASE); | |||
} | |||
|
|||
@Override | |||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When does onUpgrade
trigger? Or, in other words, how does walletlib know when to onUpgrade
the database?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onUpgrade is called whenever the database schema version changes (5->6 in this case)
@NonNull @Size(min = 1) | ||
public final AuthorizedAccount[] accounts; | ||
@NonNull | ||
public final AuthorizedAccount account; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summarizing my understanding:
We're going from AuthorizedAccount[]
to AuthorizedAccount
because only the first item of the array was ever used anyways. Change it to a single account for clarity (until its actually implemented).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in v1.x, this was never even an array, just a single public key and account label. the AuthorizedAccount
struct was added in the 2.0 upgrade. This is reverting some of the original 2.0 changes to be single account tho for clarity, yes.
import androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
|
||
public class AccountRecordsDao extends DbContentProvider<AccountRecord> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summarizing my understanding:
We're changing our "account" model from PublicKeyRecord
-> AccountRecord
because in MWA 2.0, the "account" model needs to be expanded to include chains/features/etc. A public key is now a part of the larger AccountRecord
model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep exactly. adding new account metadata fields to the database.
having this already done will make it easier to migrate to multi-account too. we still need to store a list of AccountRecords for each authorization, but at least now the AccountRecord itself is there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had some more time to read through the changes and have a better understanding now. Left my reasoning in the comments, but please correct me if I have a misunderstanding!
" = " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_ID + | ||
" INNER JOIN " + TABLE_ACCOUNTS + | ||
" ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ACCOUNT_ID + | ||
" = " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_ID + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getAuthorizations()
is incorrect ifCOLUMN_AUTHORIZATIONS_ACCOUNT_ID
still refers to apublicKeyId
.
The INNER_JOIN
will try to match COLUMN_AUTHORIZATIONS_ACCOUNT_ID == COLUMN_ACCOUNTS_ID
, but COLUMN_AUTHORIZATIONS_ACCOUNT_ID
columns will all be publicKeyId
values while its expecting accountId
values. This results in an empty join.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed with migration from public_key_id column to account_id
@@ -9,7 +9,7 @@ | |||
String COLUMN_AUTHORIZATIONS_ID = "id"; // type: int | |||
String COLUMN_AUTHORIZATIONS_IDENTITY_ID = "identity_id"; // type: long | |||
String COLUMN_AUTHORIZATIONS_ISSUED = "issued"; // type: long | |||
String COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID = "public_key_id"; // type: long | |||
String COLUMN_AUTHORIZATIONS_ACCOUNT_ID = "public_key_id"; // type: long |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summarizing my understanding of the issue:
Pre-migrated databases will have an Authorizations Table with rows that contain a column (public_key_id
) that contains a publicKeyId
. When the migration step (onUpgrade
) occurs, the Authorizations Table is not updated and the public_key_id
column will still contain publicKeyIds
rather than accountIds
.
This is problematic because certain parts of code will assume that the column contains accountIds
when they are actually still publicKeyIds
. I'll add comments for spots where I see this being problematic.
Solutions:
-
Create a new column for
account_id
in Authorizations Table then populate it during the migration steponUpgrade
. Migrated DBs will just have a redundantpublic_key_id
column that isn't used anymore. -
On upgrade/migration, alter each row in Authorizations Table so that
public_key_id
==account_id
, by editing/updating eachpublic_key_id
value. (Is it possible to change a row's id? Where is the row's id even determined?).
|
||
@Override | ||
public void deleteUnreferencedAccounts() { | ||
final SQLiteStatement deleteUnreferencedPublicKeys = super.compileStatement( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleteUnreferencedPublicKeys
should be renamed to deleteUnreferencedAccounts
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
final SQLiteStatement deleteUnreferencedPublicKeys = super.compileStatement( | ||
"DELETE FROM " + TABLE_ACCOUNTS + | ||
" WHERE " + COLUMN_ACCOUNTS_ID + " NOT IN " + | ||
"(SELECT DISTINCT " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_ACCOUNT_ID + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Another problematic spot for migrated DBs in
deleteUnreferencedAccounts
.
COLUMN_ACCOUNTS_ID
is expecting accountIds
but AuthorizationsSchema.COLUMN_AUTHORIZATIONS_ACCOUNT_ID
are still publicKeyIds
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed with migration from public_key_id
column to account_id
Updates the
walletlib
AuthDatabase
to store new authorized account parameters (account icon, chains, features). Updates the database schema version from 5>6 and handles database migration.This PR does not address multiple authorized accounts per auth token. those changes got too complex and will come in a future PR.
Testing database migration:
fakewallet
built from v1.x branchfakedapp
to fill the auth repositoryfakewallet
with build form this branch