Skip to content
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

842 use bufbuild type to storetransmit fvk instead of bech32 string #846

Conversation

Valentine1898
Copy link
Contributor

close #842

@Valentine1898 Valentine1898 linked an issue Mar 28, 2024 that may be closed by this pull request
packages/types/src/wallet.ts Show resolved Hide resolved
packages/types/src/wallet.ts Outdated Show resolved Hide resolved
packages/types/src/wallet.ts Outdated Show resolved Hide resolved
@@ -19,6 +19,7 @@ describe('Connected Sites Slice', () => {

beforeEach(() => {
localStorage = mockLocalExtStorage();
//
useStore = create<AllSlices>()(initializeStore(mockSessionExtStorage(), localStorage));
Copy link
Contributor Author

@Valentine1898 Valentine1898 Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and in a number of other tests I get an error

TS2322: Type 'UseBoundStore<WithImmer<StoreApi<AllSlices>>>' is not assignable to type 'UseBoundStore<StoreApi<AllSlices>>'.
image

As I understand it, this is due to the addition of bufbuild types to WalletsSlice, but I'm not sure if we should rewrite the tests or if we shouldn't use bufbuild types in the slice

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is a downside of zustand+immer 😞 . It's not allowed to store bufbuild classes directly. It seems to be a limitation because immer cannot properly do a safe copy of it. So we likely need to be using WalletJson here. But does this invalidate this whole task? Maybe not, we still should be storing FullViewingKey.toJson() in storage instead of a string.

apps/extension/src/state/wallets.ts Show resolved Hide resolved
@@ -19,6 +19,7 @@ describe('Connected Sites Slice', () => {

beforeEach(() => {
localStorage = mockLocalExtStorage();
//
useStore = create<AllSlices>()(initializeStore(mockSessionExtStorage(), localStorage));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is a downside of zustand+immer 😞 . It's not allowed to store bufbuild classes directly. It seems to be a limitation because immer cannot properly do a safe copy of it. So we likely need to be using WalletJson here. But does this invalidate this whole task? Maybe not, we still should be storing FullViewingKey.toJson() in storage instead of a string.

packages/bech32/src/full-viewing-key.ts Outdated Show resolved Hide resolved
packages/bech32/src/full-viewing-key.ts Outdated Show resolved Hide resolved
packages/storage/src/chrome/local.ts Outdated Show resolved Hide resolved
/// witness_data: `WitnessData``
/// Returns: `Action`
#[wasm_bindgen]
pub fn build_action(
transaction_plan: JsValue,
action_plan: JsValue,
full_viewing_key: &str,
full_viewing_key: JsValue,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat related to #844, but we can do something like this so we get types:

pub fn build_action(
    transaction_plan: JsValue,
    action_plan: JsValue,
    full_viewing_key: &[u8],
    witness_data: JsValue,
) -> WasmResult<JsValue> {
    let full_viewing_key: FullViewingKey = FullViewingKey::decode(full_viewing_key)?;

and then in typescript we pass fullViewingKey.inner

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it better? Do we want to get rid of toJson() serialization and serde_wasm_bindgen?
Should we do this in all cases when handling {inner: Uint8Array} types?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working through these cases in #834. I go back and forth honestly. Perhaps it's not better than JsValue. We still pass an opaque type that needs deserializing on the other side. Maybe ignore this for now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, here's the idea with this:

JsValue can be anything. And it gets typed to an any. However, in some cases, we can encode/decode through binary. If we pass an Uint8Array straight to wasm and receive one back, the typescript signature will be strongly enforced. It increases typesafety. It won't work in every case, but for pb types, it often can.

@Valentine1898
Copy link
Contributor Author

The V1 -> V2 migration was successful, but now that we have V2 in local storage state we get an error

Cannot read properties of undefined (reading 'V1')
image

@grod220
Copy link
Collaborator

grod220 commented Mar 28, 2024

Wherever that bug is, sounds like a good candidate for testing 😅

Comment on lines 80 to 82
let fvk: FullViewingKey = FullViewingKey::decode(full_viewing_key)?;
let result = serde_wasm_bindgen::to_value(&fvk.wallet_id())?;
Ok(result)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grod220
WalletId has no method .encode_to_vec()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like WalletId is missing a trait in the core repo. I'll open a PR to fix there. In the meantime, let's do:

pub fn get_wallet_id(full_viewing_key: JsValue) -> WasmResult<Vec<u8>> {
    utils::set_panic_hook();

    let fvk: FullViewingKey = serde_wasm_bindgen::from_value(full_viewing_key)?;
    // Can do `fvk.wallet_id().encode_to_vec()` when Domain impl added to WalletId in core
    let wallet_id_proto = WalletId::from(fvk.wallet_id());
    Ok(wallet_id_proto.encode_to_vec())
}

@Valentine1898 Valentine1898 force-pushed the 842-use-bufbuild-type-to-storetransmit-fvk-instead-of-bech32-string branch from 828bb2f to 108d4dc Compare March 29, 2024 11:08
@Valentine1898 Valentine1898 force-pushed the 842-use-bufbuild-type-to-storetransmit-fvk-instead-of-bech32-string branch from ed06732 to 888283b Compare April 1, 2024 18:26
@Valentine1898 Valentine1898 marked this pull request as ready for review April 1, 2024 18:53
Comment on lines -6 to -22
export enum LocalStorageVersion {
V1 = 'V1',
}

export interface OriginRecord {
origin: string;
choice: UserChoice;
date: number;
}

export interface LocalStorageState {
wallets: WalletJson[];
grpcEndpoint: string;
passwordKeyPrint?: KeyPrintJson;
fullSyncHeight: number;
knownSites: OriginRecord[];
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the types that were defined @penumbra-zone/storage/src/chrome/local to @penumbra-zone/types/src/local-storage.
This was to avoid a cyclic import which created a bug with the error Cannot read properties of undefined (reading 'V1') .
This also created a lot of import changes in this PR.

Comment on lines +102 to +104
walletId: new WalletId({
inner: Uint8Array.from({ length: 8 }, () => Math.floor(Math.random() * 256)),
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is actually incorrect, if we want to test idb version update, we should not generate a random dbName, only increase the version.
But the thing is, if we fix this test, it causes all storage tests to hang and timeout error. I will open a separate PR for this fix (since this PR is big without it)

@Valentine1898 Valentine1898 changed the title WIP: 842 use bufbuild type to storetransmit fvk instead of bech32 string 842 use bufbuild type to storetransmit fvk instead of bech32 string Apr 1, 2024
Comment on lines -157 to -165
#[wasm_bindgen]
pub fn get_short_address_by_index(full_viewing_key: &str, index: u32) -> WasmResult<JsValue> {
utils::set_panic_hook();

let fvk = FullViewingKey::from_str(full_viewing_key)?;
let (address, _dtk) = fvk.incoming().payment_address(index.into());
let short_address = address.display_short_form();
Ok(JsValue::from_str(&short_address))
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used

Copy link
Collaborator

@grod220 grod220 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really well done! This wasn't easy 😅 . Before you merge, please do some extensive testing with all user flows (migrating from v1/swapping/staking/send/etc) to ensure there aren't any bugs we missed.

grod220 added a commit to penumbra-zone/penumbra that referenced this pull request Apr 2, 2024
Domain types implement the trait `DomainType` which adds proto
encoding/decoding to the struct. This PR adds it for `WalletId`. This is
helpful in the wasm crate when we pass over the wasm-javascript
boundary:
penumbra-zone/web#846 (comment)
@Valentine1898
Copy link
Contributor Author

I'll just point out
Migration works only in case of version increase (V1-->V2).
If you try to rollback extension with V2 version of local storage to V1 version you will just break everything.

I don't think users will have a case when a version is decreased, and developers should just consider that this can happen when switching between branches.

@grod220
Copy link
Collaborator

grod220 commented Apr 2, 2024

If you try to rollback extension with V2 version of local storage to V1 version you will just break everything.

Ah, good point. After you merge, please make a note in #browser-extension in discord.

@Valentine1898 Valentine1898 merged commit 4530faf into main Apr 2, 2024
6 checks passed
@Valentine1898 Valentine1898 deleted the 842-use-bufbuild-type-to-storetransmit-fvk-instead-of-bech32-string branch April 2, 2024 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use bufbuild type to store/transmit FVK instead of bech32 string
2 participants