Skip to content

Commit

Permalink
feat!: enforce passing purpose when deriving path
Browse files Browse the repository at this point in the history
  • Loading branch information
greatertomi committed May 30, 2024
1 parent 54366d7 commit 82449e7
Show file tree
Hide file tree
Showing 57 changed files with 317 additions and 145 deletions.
18 changes: 12 additions & 6 deletions packages/e2e/src/factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
CommunicationType,
InMemoryKeyAgent,
KeyAgentDependencies,
KeyPurpose,
Witnesser,
util
} from '@cardano-sdk/key-management';
Expand Down Expand Up @@ -204,7 +205,8 @@ keyManagementFactory.register('inMemory', async (params: any): Promise<CreateKey
accountIndex: params.accountIndex,
chainId: params.chainId,
getPassphrase: async () => Buffer.from(params.passphrase),
mnemonicWords
mnemonicWords,
purpose: params.purpose
},
dependencies
)
Expand All @@ -220,7 +222,8 @@ keyManagementFactory.register('ledger', async (params: any): Promise<CreateKeyAg
accountIndex: params.accountIndex,
chainId: params.chainId,
communicationType: CommunicationType.Node,
deviceConnection
deviceConnection,
purpose: params.purpose
},
dependencies
);
Expand All @@ -238,6 +241,7 @@ keyManagementFactory.register(
{
accountIndex: params.accountIndex,
chainId: params.chainId,
purpose: params.purpose,
trezorConfig: {
communicationType: CommunicationType.Node,
manifest: {
Expand Down Expand Up @@ -277,6 +281,7 @@ export type GetWalletProps = {
env: any;
idx?: number;
logger: Logger;
purpose: KeyPurpose;
name: string;
polling?: PollingConfig;
handlePolicyIds?: Cardano.PolicyId[];
Expand All @@ -290,6 +295,7 @@ export type GetSharedWalletProps = {
env: any;
logger: Logger;
name: string;
purpose: KeyPurpose;
polling?: PollingConfig;
handlePolicyIds?: Cardano.PolicyId[];
stores?: storage.WalletStores;
Expand Down Expand Up @@ -321,7 +327,7 @@ const patchInitializeTxToRespectEpochBoundary = <T extends ObservableWallet>(
* @returns an object containing the wallet and providers passed to it
*/
export const getWallet = async (props: GetWalletProps) => {
const { env, idx, logger, name, stores, customKeyParams, keyAgent, witnesser } = props;
const { env, idx, logger, name, stores, customKeyParams, keyAgent, witnesser, purpose } = props;
let polling = props.polling;
const providers = {
addressDiscovery: await addressDiscoveryFactory.create(
Expand Down Expand Up @@ -378,7 +384,7 @@ export const getWallet = async (props: GetWalletProps) => {
}

const wallet = createPersonalWallet(
{ name, polling },
{ name, polling, purpose },
{
...providers,
bip32Account,
Expand All @@ -405,7 +411,7 @@ export const getWallet = async (props: GetWalletProps) => {
* @returns an object containing the wallet and providers passed to it
*/
export const getSharedWallet = async (props: GetSharedWalletProps) => {
const { env, logger, name, polling, stores, paymentScript, stakingScript, witnesser } = props;
const { env, logger, name, polling, stores, paymentScript, stakingScript, witnesser, purpose } = props;
const providers = {
assetProvider: await assetProviderFactory.create(env.ASSET_PROVIDER, env.ASSET_PROVIDER_PARAMS, logger),
chainHistoryProvider: await chainHistoryProviderFactory.create(
Expand Down Expand Up @@ -433,7 +439,7 @@ export const getSharedWallet = async (props: GetSharedWalletProps) => {
utxoProvider: await utxoProviderFactory.create(env.UTXO_PROVIDER, env.UTXO_PROVIDER_PARAMS, logger)
};
const wallet = createSharedWallet(
{ name, polling },
{ name, polling, purpose },
{
...providers,
logger,
Expand Down
5 changes: 3 additions & 2 deletions packages/e2e/src/scripts/mnemonic.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-floating-promises */
import * as Crypto from '@cardano-sdk/crypto';
import { AddressType, InMemoryKeyAgent, util } from '@cardano-sdk/key-management';
import { AddressType, InMemoryKeyAgent, KeyPurpose, util } from '@cardano-sdk/key-management';
import { localNetworkChainId } from '../util';

/** Generates a new set of Mnemonic words and prints them to the console. */
Expand All @@ -14,7 +14,8 @@ import { localNetworkChainId } from '../util';
{
chainId: localNetworkChainId,
getPassphrase: async () => Buffer.from(''),
mnemonicWords: mnemonicArray
mnemonicWords: mnemonicArray,
purpose: KeyPurpose.STANDARD
},
{
bip32Ed25519: new Crypto.SodiumBip32Ed25519(),
Expand Down
23 changes: 16 additions & 7 deletions packages/e2e/src/tools/multi-delegation-data-gen/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable no-console, max-statements, max-params, @typescript-eslint/no-floating-promises */
import { ValueTransferConfig, configLoader } from './config';
import { Cardano } from '@cardano-sdk/core';
import { KeyPurpose, util } from '@cardano-sdk/key-management';
import { logger } from '@cardano-sdk/util-dev';

import { BaseWallet } from '@cardano-sdk/wallet';
import { Cardano } from '@cardano-sdk/core';
import { Files, Paths } from './files';
import {
KeyAgentFactoryProps,
Expand All @@ -16,8 +17,7 @@ import {
} from '../../../';
import { Observable, filter, firstValueFrom, map } from 'rxjs';
import { TaskResult, TerminalProgressMonitor } from './terminal-progress-monitor';
import { logger } from '@cardano-sdk/util-dev';
import { util } from '@cardano-sdk/key-management';
import { ValueTransferConfig, configLoader } from './config';
import chalk from 'chalk';

/**
Expand Down Expand Up @@ -96,8 +96,16 @@ export const loadConfiguration = async (monitor: TerminalProgressMonitor) => {
export const waitForFundingWallet = async (monitor: TerminalProgressMonitor): Promise<BaseWallet> => {
monitor.startTask('Waiting for funding wallet to be ready.');

const fundingWallet = (await getWallet({ env, idx: 0, logger, name: 'Funding wallet', polling: { interval: 500 } }))
.wallet;
const fundingWallet = (
await getWallet({
env,
idx: 0,
logger,
name: 'Funding wallet',
polling: { interval: 500 },
purpose: KeyPurpose.STANDARD
})
).wallet;

await walletReady(fundingWallet);

Expand Down Expand Up @@ -132,7 +140,8 @@ export const createDelegationWallet = async (monitor: TerminalProgressMonitor) =
idx: 0,
logger,
name: 'Delegation Wallet',
polling: { interval: 500 }
polling: { interval: 500 },
purpose: KeyPurpose.STANDARD
})
).wallet;
};
Expand Down
5 changes: 3 additions & 2 deletions packages/e2e/src/util/createMockKeyAgent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Bip32PublicKeyHex, SodiumBip32Ed25519 } from '@cardano-sdk/crypto';
import { Cardano } from '@cardano-sdk/core';
import { GroupedAddress, KeyAgent, KeyAgentType } from '@cardano-sdk/key-management';
import { GroupedAddress, KeyAgent, KeyAgentType, KeyPurpose } from '@cardano-sdk/key-management';

const accountIndex = 0;
const chainId = Cardano.ChainIds.Preview;
Expand All @@ -23,7 +23,8 @@ export const createMockKeyAgent = (deriveAddressesReturn: GroupedAddress[] = [])
accountIndex,
chainId,
encryptedRootPrivateKeyBytes: [],
extendedAccountPublicKey
extendedAccountPublicKey,
purpose: KeyPurpose.STANDARD
},
signBlob: jest.fn(),
signTransaction: jest.fn()
Expand Down
3 changes: 2 additions & 1 deletion packages/e2e/src/util/handle-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Asset, Cardano, Handle, Serialization, metadatum, nativeScriptPolicyId,
import { FinalizeTxProps, ObservableWallet } from '@cardano-sdk/wallet';
import { HexBlob } from '@cardano-sdk/util';
import { InitializeTxProps } from '@cardano-sdk/tx-construction';
import { KeyAgent, KeyRole, util as keyManagementUtil } from '@cardano-sdk/key-management';
import { KeyAgent, KeyPurpose, KeyRole, util as keyManagementUtil } from '@cardano-sdk/key-management';
import { firstValueFrom } from 'rxjs';
import { readFile } from 'fs/promises';
import { submitAndConfirm } from './util';
Expand Down Expand Up @@ -79,6 +79,7 @@ export const createHandleMetadata = (handlePolicyId: string, handleNames: string
export const createHandlePolicy = async (keyAgent: KeyAgent) => {
const derivationPath = {
index: 0,
purpose: KeyPurpose.STANDARD,
role: KeyRole.External
};
const pubKey = await keyAgent.derivePublicKey(derivationPath);
Expand Down
9 changes: 6 additions & 3 deletions packages/e2e/src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
timeout
} from 'rxjs';
import { FAST_OPERATION_TIMEOUT_DEFAULT, SYNC_TIMEOUT_DEFAULT } from '../defaults';
import { InMemoryKeyAgent, TransactionSigner } from '@cardano-sdk/key-management';
import { InMemoryKeyAgent, KeyPurpose, TransactionSigner } from '@cardano-sdk/key-management';
import { InitializeTxProps } from '@cardano-sdk/tx-construction';
import { TestWallet, networkInfoProviderFactory } from '../factories';
import { getEnv, walletVariables } from '../environment';
Expand Down Expand Up @@ -228,17 +228,20 @@ export const submitCertificate = async (certificate: Cardano.Certificate, wallet
* @param mnemonics The random set of mnemonics.
* @param genesis Network genesis parameters
* @param bip32Ed25519 The Ed25519 cryptography implementation.
* @param purpose they key derivation purpose of either 1852 or 1854
*/
export const createStandaloneKeyAgent = async (
mnemonics: string[],
genesis: Cardano.CompactGenesis,
bip32Ed25519: Crypto.Bip32Ed25519
bip32Ed25519: Crypto.Bip32Ed25519,
purpose: KeyPurpose
) =>
await InMemoryKeyAgent.fromBip39MnemonicWords(
{
chainId: genesis,
getPassphrase: async () => Buffer.from(''),
mnemonicWords: mnemonics
mnemonicWords: mnemonics,
purpose
},
{ bip32Ed25519, logger }
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AddressType, GroupedAddress, util } from '@cardano-sdk/key-management';
import { AddressType, GroupedAddress, KeyPurpose, util } from '@cardano-sdk/key-management';
import { AddressesModel, WalletVars } from './types';
import { Cardano } from '@cardano-sdk/core';
import { FunctionHook } from '../artillery';
Expand All @@ -12,6 +12,7 @@ export const mapToGroupedAddress = (addrModel: AddressesModel): GroupedAddress =
address: Cardano.PaymentAddress(addrModel.address),
index: 0,
networkId: addrModel.address.startsWith('addr_test') ? Cardano.NetworkId.Testnet : Cardano.NetworkId.Mainnet,
purpose: KeyPurpose.STANDARD,
rewardAccount: Cardano.RewardAccount(addrModel.stake_address),
type: AddressType.External
});
Expand Down Expand Up @@ -99,7 +100,8 @@ export const walletRestoration: FunctionHook<WalletVars> = async ({ vars, _uid }
keyAgent,
logger,
name: `Test Wallet of VU with id: ${_uid}`,
polling: { interval: 50 }
polling: { interval: 50 },
purpose: KeyPurpose.STANDARD
});

vars.currentWallet = wallet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import path from 'path';
dotenv.config({ path: path.join(__dirname, '../../../.env') });
import { BaseWallet } from '@cardano-sdk/wallet';
import { Cardano } from '@cardano-sdk/core';
import { GroupedAddress, util } from '@cardano-sdk/key-management';
import { GroupedAddress, KeyPurpose, util } from '@cardano-sdk/key-management';
import { Logger } from 'ts-log';
import { MINUTE, createMockKeyAgent, getEnv, getWallet, waitForWalletStateSettle, walletVariables } from '../../../src';
import { logger } from '@cardano-sdk/util-dev';
Expand Down Expand Up @@ -48,7 +48,8 @@ const initWallets = async (walletsNum: number, addresses: GroupedAddress[]): Pro
keyAgent,
logger,
name: 'Test Wallet',
polling: { interval: 50 }
polling: { interval: 50 },
purpose: KeyPurpose.STANDARD
});
wallets.push(wallet);
}
Expand Down
10 changes: 6 additions & 4 deletions packages/e2e/test/local-network/register-pool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import {
walletReady,
walletVariables
} from '../../src';
import { firstValueFrom } from 'rxjs';
import { logger } from '@cardano-sdk/util-dev';

import * as Crypto from '@cardano-sdk/crypto';
import { AddressType, KeyRole } from '@cardano-sdk/key-management';
import { firstValueFrom } from 'rxjs';
import { AddressType, KeyPurpose, KeyRole } from '@cardano-sdk/key-management';

const env = getEnv(walletVariables);

Expand Down Expand Up @@ -54,15 +54,17 @@ describe('local-network/register-pool', () => {
idx: 0,
logger,
name: 'Pool Wallet 1',
polling: { interval: 500 }
polling: { interval: 500 },
purpose: KeyPurpose.STANDARD
});
wallet2 = await getWallet({
customKeyParams: wallet2Params,
env,
idx: 0,
logger,
name: 'Pool Wallet 2',
polling: { interval: 500 }
polling: { interval: 500 },
purpose: KeyPurpose.STANDARD
});

await waitForWalletStateSettle(wallet1.wallet);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Crypto from '@cardano-sdk/crypto';
import { BaseWallet } from '@cardano-sdk/wallet';
import { Cardano, EraSummary, StakePoolProvider, createSlotEpochCalc } from '@cardano-sdk/core';
import { InMemoryKeyAgent, KeyRole } from '@cardano-sdk/key-management';
import { InMemoryKeyAgent, KeyPurpose, KeyRole } from '@cardano-sdk/key-management';
import { MultiSigTx } from './MultiSigTx';
import { MultiSigWallet } from './MultiSigWallet';
import { Observable, filter, firstValueFrom, map, take } from 'rxjs';
Expand Down Expand Up @@ -34,6 +34,7 @@ const charlotteMnemonics =

const DERIVATION_PATH = {
index: 0,
purpose: KeyPurpose.MULTI_SIG,
role: KeyRole.External
};

Expand Down Expand Up @@ -63,7 +64,7 @@ const fundMultiSigWallet = async (sendingWallet: BaseWallet, address: Cardano.Pa
const getKeyAgent = async (mnemonics: string, faucetWallet: BaseWallet, bip32Ed25519: Crypto.Bip32Ed25519) => {
const genesis = await firstValueFrom(faucetWallet.genesisParameters$);

const keyAgent = await createStandaloneKeyAgent(mnemonics.split(' '), genesis, bip32Ed25519);
const keyAgent = await createStandaloneKeyAgent(mnemonics.split(' '), genesis, bip32Ed25519, KeyPurpose.STANDARD);

const pubKey = await keyAgent.derivePublicKey(DERIVATION_PATH);

Expand Down Expand Up @@ -135,7 +136,8 @@ describe('multi signature wallet', () => {
env,
logger,
name: 'Faucet Wallet',
polling: { interval: 50 }
polling: { interval: 50 },
purpose: KeyPurpose.MULTI_SIG
}));

await walletReady(faucetWallet);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BaseWallet } from '@cardano-sdk/wallet';
import { Cardano, StakePoolProvider } from '@cardano-sdk/core';
import { KeyPurpose } from '@cardano-sdk/key-management';
import { buildSharedWallets } from '../wallet_epoch_0/SharedWallet/utils';
import { filter, firstValueFrom, map, take } from 'rxjs';
import {
Expand Down Expand Up @@ -101,7 +102,7 @@ describe('shared wallet delegation rewards', () => {
({
wallet: faucetWallet,
providers: { stakePoolProvider }
} = await getWallet({ env, logger, name: 'Sending Wallet' }));
} = await getWallet({ env, logger, name: 'Sending Wallet', purpose: KeyPurpose.MULTI_SIG }));

// Make sure the wallet has sufficient funds to run this test
await walletReady(faucetWallet, initialFunds);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BaseWallet } from '@cardano-sdk/wallet';
import { Cardano, StakePoolProvider } from '@cardano-sdk/core';
import { KeyPurpose } from '@cardano-sdk/key-management';
import {
TestWallet,
getEnv,
Expand Down Expand Up @@ -85,9 +86,10 @@ describe('simple delegation rewards', () => {
env,
logger,
name: 'Sending Wallet',
polling: { interval: 50 }
polling: { interval: 50 },
purpose: KeyPurpose.STANDARD
}));
({ wallet: wallet2 } = await getWallet({ env, logger, name: 'Receiving Wallet' }));
({ wallet: wallet2 } = await getWallet({ env, logger, name: 'Receiving Wallet', purpose: KeyPurpose.STANDARD }));

await waitForWalletStateSettle(wallet1);
await waitForWalletStateSettle(wallet2);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable sonarjs/no-duplicate-string */
import { BaseWallet } from '@cardano-sdk/wallet';
import { Cardano } from '@cardano-sdk/core';
import { KeyPurpose } from '@cardano-sdk/key-management';
import { createLogger } from '@cardano-sdk/util-dev';
import { filter, firstValueFrom, map, take } from 'rxjs';
import { getEnv, walletVariables } from '../../../src/environment';
Expand All @@ -14,7 +15,7 @@ describe('PersonalWallet/byron', () => {
let wallet: BaseWallet;

beforeAll(async () => {
wallet = (await getWallet({ env, idx: 0, logger, name: 'Wallet' })).wallet;
wallet = (await getWallet({ env, idx: 0, logger, name: 'Wallet', purpose: KeyPurpose.STANDARD })).wallet;
});

afterAll(() => {
Expand Down
Loading

0 comments on commit 82449e7

Please sign in to comment.