Skip to content

Commit

Permalink
feat: wip2
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszjasiuk committed Dec 31, 2024
1 parent ab972b7 commit 6e00ea3
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 37 deletions.
17 changes: 6 additions & 11 deletions apps/extension/src/App/Accounts/ParentAccounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import {
KeyListItem,
Stack,
} from "@namada/components";
import { AccountType, DerivedAccount } from "@namada/types";
import { DerivedAccount } from "@namada/types";
import { ParentAccountsFooter } from "App/Accounts/ParentAccountsFooter";
import { PageHeader } from "App/Common";
import routes from "App/routes";
import { ParentAccount } from "background/keyring";
import { AccountContext } from "context";
import invariant from "invariant";
import { openSetupTab } from "utils";

/**
Expand All @@ -26,20 +27,14 @@ export const ParentAccounts = (): JSX.Element => {
accounts: allAccounts,
changeActiveAccountId,
} = useContext(AccountContext);

// We check which accounts need to be re-imported
const accounts = allAccounts
.filter(
(account) => account.parentId || account.type === AccountType.Ledger
)
.filter((account) => account.parentId)
.map((account) => {
const outdated =
account.type !== AccountType.Ledger &&
typeof account.pseudoExtendedKey === "undefined";
const outdated = typeof account.pseudoExtendedKey === "undefined";

// The only account without a parent is the ledger account
const parent =
parentAccounts.find((pa) => pa.id === account.parentId) || account;
const parent = parentAccounts.find((pa) => pa.id === account.parentId);
invariant(parent, `Parent account not found for account ${account.id}`);

return { ...parent, outdated };
});
Expand Down
2 changes: 2 additions & 0 deletions apps/extension/src/Setup/Ledger/LedgerConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const LedgerConnect: React.FC<Props> = ({ path, setPath }) => {
state: {
address,
publicKey,
viewingKey: asd.xfvk,
pseudoExtendedKey: asd.pex,
},
});
} catch (e) {
Expand Down
7 changes: 6 additions & 1 deletion apps/extension/src/Setup/Ledger/LedgerImport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { useLocation, useNavigate } from "react-router-dom";
type LedgerImportLocationState = {
address: string;
publicKey: string;
viewingKey: string;
pseudoExtendedKey: string;
};

type LedgerProps = {
Expand Down Expand Up @@ -55,12 +57,15 @@ export const LedgerImport = ({
await accountManager.savePassword(password);
}

const { address, publicKey } = locationState;
const { address, publicKey, viewingKey, pseudoExtendedKey } =
locationState;
const account = await accountManager.saveLedgerAccount({
alias,
address,
publicKey,
path,
viewingKey,
pseudoExtendedKey,
});

navigate(routes.ledgerComplete(), {
Expand Down
4 changes: 2 additions & 2 deletions apps/extension/src/Setup/Setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ export const Setup: React.FC = () => {

const prettyAccountSecret =
accountSecret.t === "Mnemonic" ? "mnemonic"
: accountSecret.t === "PrivateKey" ? "private key"
: assertNever(accountSecret);
: accountSecret.t === "PrivateKey" ? "private key"
: assertNever(accountSecret);
setCompletionStatusInfo(`Encrypting and storing ${prettyAccountSecret}.`);

// Create parent account
Expand Down
14 changes: 11 additions & 3 deletions apps/extension/src/Setup/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { DeriveAccountDetails, LedgerAccountDetails } from "./types";

// Wrap account management calls with extension requester instance
export class AccountManager {
constructor(private readonly requester: ExtensionRequester) {}
constructor(private readonly requester: ExtensionRequester) { }

/**
* Set password for the extension
Expand Down Expand Up @@ -88,10 +88,18 @@ export class AccountManager {
async saveLedgerAccount(
details: LedgerAccountDetails
): Promise<AccountStore> {
const { alias, address, publicKey, path } = details;
const { alias, address, publicKey, path, pseudoExtendedKey, viewingKey } =
details;
return (await this.requester.sendMessage(
Ports.Background,
new AddLedgerAccountMsg(alias, address, publicKey, path)
new AddLedgerAccountMsg(
alias,
address,
publicKey,
path,
pseudoExtendedKey,
viewingKey
)
)) as AccountStore;
}
}
2 changes: 2 additions & 0 deletions apps/extension/src/Setup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ export type LedgerAccountDetails = {
path: Bip44Path;
address: string;
publicKey: string;
pseudoExtendedKey: string;
viewingKey: string;
};
20 changes: 17 additions & 3 deletions apps/extension/src/background/keyring/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,22 @@ const handleAddLedgerAccountMsg: (
service: KeyRingService
) => InternalHandler<AddLedgerAccountMsg> = (service) => {
return async (_, msg) => {
const { alias, address, publicKey, bip44Path } = msg;
return await service.saveLedger(alias, address, publicKey, bip44Path);
const {
alias,
address,
publicKey,
bip44Path,
pseudoExtendedKey,
viewingKey,
} = msg;
return await service.saveLedger(
alias,
address,
publicKey,
bip44Path,
pseudoExtendedKey,
viewingKey
);
};
};

Expand Down Expand Up @@ -179,7 +193,7 @@ const handleQueryAccountsMsg: (
const output =
query && query.accountId ?
await service.queryAccountsByParentId(query.accountId)
: await service.queryAccounts();
: await service.queryAccounts();

return output;
};
Expand Down
36 changes: 31 additions & 5 deletions apps/extension/src/background/keyring/keyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class KeyRing {
protected readonly sdkService: SdkService,
protected readonly utilityStore: KVStore<UtilityStore>,
protected readonly localStorage: LocalStorage
) {}
) { }

public get status(): KeyRingStatus {
return this._status;
Expand Down Expand Up @@ -101,7 +101,9 @@ export class KeyRing {
alias: string,
address: string,
publicKey: string,
bip44Path: Bip44Path
bip44Path: Bip44Path,
pseudoExtendedKey: string,
viewingKey: string
): Promise<AccountStore | false> {
const id = generateId(UUID_NAMESPACE, alias, address);
const accountStore: AccountStore = {
Expand All @@ -125,6 +127,30 @@ export class KeyRing {
sensitive,
});

const shieldedId = generateId(UUID_NAMESPACE, alias, address);
const shieldedAccountStore: AccountStore = {
id: shieldedId,
alias,
address,
publicKey,
owner: viewingKey,
path: bip44Path,
pseudoExtendedKey,
parentId: id,
type: AccountType.ShieldedKeys,
source: "imported",
timestamp: 0,
};

const shieldedSensitive = await this.vaultService.encryptSensitiveData({
text: "",
passphrase: "",
});
await this.vaultStorage.add(KeyStore, {
public: shieldedAccountStore,
sensitive: shieldedSensitive,
});

await this.setActiveAccount(id, AccountType.Ledger);
return accountStore;
}
Expand Down Expand Up @@ -436,7 +462,7 @@ export class KeyRing {
const deriveFn = (
type === AccountType.PrivateKey ?
this.deriveTransparentAccount
: this.deriveShieldedAccount).bind(this);
: this.deriveShieldedAccount).bind(this);

const { secret } = await this.getParentSecret(parentId);
const info = deriveFn(secret, derivationPath, parentAccount);
Expand Down Expand Up @@ -719,13 +745,13 @@ export class KeyRing {
const key =
disposableKey ?
disposableKey.privateKey
: await this.getSigningKey(signer);
: await this.getSigningKey(signer);

// If disposable key is provided, use it to map real address to spending key
const spendingKeys =
disposableKey ?
[await this.getSpendingKey(disposableKey.realAddress)]
: [];
: [];

const { signing } = this.sdkService.getSdk();

Expand Down
11 changes: 10 additions & 1 deletion apps/extension/src/background/keyring/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ export class AddLedgerAccountMsg extends Message<AccountStore | false> {
public readonly address: string,
public readonly publicKey: string,
public readonly bip44Path: Bip44Path,
public readonly parentId?: string
public readonly pseudoExtendedKey: string,
public readonly viewingKey: string
) {
super();
}
Expand All @@ -207,6 +208,14 @@ export class AddLedgerAccountMsg extends Message<AccountStore | false> {
if (!this.bip44Path) {
throw new Error("BIP44 Path was not provided!");
}

if (!this.pseudoExtendedKey) {
throw new Error("Pseudo extended key was not provided!");
}

if (!this.viewingKey) {
throw new Error("Viewing key was not provided!");
}
}

route(): string {
Expand Down
8 changes: 6 additions & 2 deletions apps/extension/src/background/keyring/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export class KeyRingService {
alias: string,
address: string,
publicKey: string,
bip44Path: Bip44Path
bip44Path: Bip44Path,
pseudoExtendedKey: string,
viewingKey: string
): Promise<AccountStore | false> {
const account = await this._keyRing.queryAccountByAddress(address);
if (account) {
Expand All @@ -94,7 +96,9 @@ export class KeyRingService {
alias,
address,
publicKey,
bip44Path
bip44Path,
pseudoExtendedKey,
viewingKey
);

await this.broadcaster.updateAccounts();
Expand Down
27 changes: 18 additions & 9 deletions packages/sdk/src/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@ import {
ResponseVersion,
ResponseViewKey,
} from "@zondax/ledger-namada";
import { ExtendedViewingKey, ProofGenerationKey } from "../../shared/src";
import { makeBip44Path, makeSaplingPath } from "./utils";
import {
ExtendedViewingKey,
ProofGenerationKey,
PseudoExtendedKey,
} from "../../shared/src";
import { makeBip44Path } from "./utils";

const { coinType } = chains.namada.bip44;

export type LedgerAddressAndPublicKey = { address: string; publicKey: string };
export type LedgerShieldedKeys = {
xfvk?: string;
pex?: string;
proofGenerationKey: {
ak?: string;
nsk?: string;
Expand Down Expand Up @@ -55,12 +60,7 @@ export const DEFAULT_LEDGER_BIP44_PATH = makeBip44Path(coinType, {
index: 0,
});

export const DEFAULT_LEDGER_ZIP32_PATH = makeSaplingPath(coinType, {
account: 0,
change: 0,
index: 0,
});

export const DEFAULT_LEDGER_ZIP32_PATH = "m/32'/877'/0'";
/**
* Functionality for interacting with NamadaApp for Ledger Hardware Wallets
*/
Expand Down Expand Up @@ -175,7 +175,9 @@ export class Ledger {
NamadaKeys.ViewKey,
promptUser
);
console.log("path", path);
const asd = new ExtendedViewingKey(xfvk!);
const xvk = new ExtendedViewingKey(xfvk!);

const www: ResponseProofGenKey = await this.namadaApp.retrieveKeys(
path,
Expand All @@ -184,9 +186,16 @@ export class Ledger {
);

const xxx = ProofGenerationKey.from_bytes(www.ak!, www.nsk!);
console.log("xxx", xxx);

const pex = PseudoExtendedKey.from(asd, xxx);

console.log(pex.encode());
console.log("XVK2", xvk.encode());

return {
xfvk: xfvk?.toString(),
xfvk: xvk.encode(),
pex: pex.encode(),
proofGenerationKey: {
ak: www?.ak?.toString(),
nsk: www?.nsk?.toString(),
Expand Down
11 changes: 11 additions & 0 deletions packages/shared/lib/src/types/masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ impl PseudoExtendedKey {
.expect("Deserializing ProofGenerationKey should not fail!"),
)
}

pub fn from(xvk: ExtendedViewingKey, pgk: ProofGenerationKey) -> Self {
web_sys::console::log_1(&"PseudoExtendedKey::from".into());
let mut pxk = zip32::PseudoExtendedKey::from(zip32::ExtendedFullViewingKey::from(xvk.0));
web_sys::console::log_1(&"PseudoExtendedKey::from: after from".into());
// TODO: expect
pxk.augment_proof_generation_key(pgk.0)
.expect("Augmenting proof generation key should not fail!");

Self(pxk)
}
}

/// Wrap ExtendedSpendingKey
Expand Down

0 comments on commit 6e00ea3

Please sign in to comment.