Skip to content

Commit

Permalink
[DDW-534] Fix Ledger TXs to Byron addresses (#2299)
Browse files Browse the repository at this point in the history
* [DDW-534] Introduce a fix for Ledger txs to Byron address

* [DDW-534] CHANGELOG update

* [DDW-534] Add LOGS for debugging purpose

* [DDW-534] Fix outputs (unsigned) order

* [DDW-534] Removes logging

Co-authored-by: Nikola Glumac <niglumac@gmail.com>
  • Loading branch information
Tomislav Horaček and nikolaglumac committed Jan 14, 2021
1 parent 1214984 commit 9aed847
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,10 @@ Changelog
- Improve Mnemonic Phrase Input UX [PR 2280](https://github.com/input-output-hk/daedalus/pull/2280)
- Added wallet public key viewing feature ([PR 2271](https://github.com/input-output-hk/daedalus/pull/2271))

### Fixes

- Fixed Ledger TXs to Byron addresses ([PR 2299](https://github.com/input-output-hk/daedalus/pull/2299))

### Chores

- Improved "Settings" screen scrolling actions ([PR 2302](https://github.com/input-output-hk/daedalus/pull/2302))
Expand Down
6 changes: 3 additions & 3 deletions source/common/types/hardware-wallets.types.js
Expand Up @@ -109,9 +109,9 @@ export type StakingBlockchainPointer = {|

export type LedgerSignTransactionInputsType = Array<LedgerSignTransactionInputType>;

export type LedgerSignTransactionOutputsType = Array<
LedgerOutputTypeAddress | LedgerOutputTypeChange
>;
export type LedgerSignTransactionOutputsType =
| []
| Array<LedgerOutputTypeAddress | LedgerOutputTypeChange>;

export type TrezorSignTransactionInputType = {
path: string,
Expand Down
3 changes: 2 additions & 1 deletion source/renderer/app/api/addresses/requests/inspectAddress.js
@@ -1,11 +1,12 @@
// @flow
import { request } from '../../utils/request';
import type { RequestConfig } from '../../common/types';
import type { InspectAddressResponse } from '../types';

export const inspectAddress = (
config: RequestConfig,
{ addressId }: any // @TODO
): Promise<any> =>
): Promise<InspectAddressResponse> =>
request(
{
method: 'GET',
Expand Down
20 changes: 20 additions & 0 deletions source/renderer/app/api/addresses/types.js
@@ -1,6 +1,10 @@
// @flow
export type AddressState = 'used' | 'unused';

export type AddressStyle = 'Byron' | 'Shelley' | 'Icarus';

export type StakeReference = 'none' | 'by value' | 'by pointer';

export type GetAddressesRequestQueryParams = {
state: AddressState,
};
Expand All @@ -19,6 +23,22 @@ export type GetAddressesRequest = {
isHardwareWallet?: boolean,
};

export type InspectAddressResponse = {
address_style: AddressStyle,
stake_reference: StakeReference,
network_tag?: number,
spending_key_hash?: string,
stake_key_hash?: string,
script_hash?: string,
pointer?: {
slot_num: number,
transaction_index: number,
output_index: number,
},
address_root?: string,
derivation_path?: string,
};

// Byron related types

export type CreateByronWalletAddressRequest = {
Expand Down
7 changes: 4 additions & 3 deletions source/renderer/app/api/api.js
Expand Up @@ -109,6 +109,7 @@ import type {
Address,
GetAddressesRequest,
CreateByronWalletAddressRequest,
InspectAddressResponse,
} from './addresses/types';

// Common Types
Expand Down Expand Up @@ -996,9 +997,9 @@ export default class AdaApi {
}
};

inspectAddress = async (
request: any // @TODO
): Promise<any> => {
inspectAddress = async (request: {
addressId: string,
}): Promise<InspectAddressResponse> => {
logger.debug('AdaApi::inspectAddress called', {
parameters: filterLogData(request),
});
Expand Down
2 changes: 1 addition & 1 deletion source/renderer/app/components/settings/SettingsLayout.js
Expand Up @@ -20,7 +20,7 @@ export default class SettingsLayout extends Component<Props> {
);
}

componentDidUpdate(prevProps) {
componentDidUpdate(prevProps: Props) {
const didActivePageChange = this.props.activePage !== prevProps.activePage;
if (
this.scrollableDomElement instanceof HTMLElement &&
Expand Down
2 changes: 1 addition & 1 deletion source/renderer/app/config/hardwareWalletsConfig.js
Expand Up @@ -20,7 +20,7 @@ export const HW_SHELLEY_CONFIG = {
TESTNET: {
name: 'testnet',
networkId: 0,
protocolMagic: 42,
protocolMagic: 1097911063,
trezorProtocolMagic: 1097911063,
eraStartSlot: 4492800,
ttl: 3600,
Expand Down
11 changes: 11 additions & 0 deletions source/renderer/app/domains/WalletAddress.js
@@ -1,11 +1,22 @@
// @flow
import { observable } from 'mobx';
import type { AddressStyle } from '../api/addresses/types';

type WalletAddressProps = {
id: string,
used: boolean,
};

export const AddressStyles: {
ADDRESS_BYRON: AddressStyle,
ADDRESS_SHELLEY: AddressStyle,
ADDRESS_ICARUS: AddressStyle,
} = {
ADDRESS_BYRON: 'Byron',
ADDRESS_SHELLEY: 'Shelley',
ADDRESS_ICARUS: 'Icarus',
};

export default class WalletAddress {
@observable id: string = '';
@observable used: boolean = false;
Expand Down
15 changes: 14 additions & 1 deletion source/renderer/app/stores/AddressesStore.js
Expand Up @@ -6,7 +6,7 @@ import CachedRequest from './lib/LocalizedCachedRequest';
import WalletAddress from '../domains/WalletAddress';
import Request from './lib/LocalizedRequest';
import LocalizableError from '../i18n/LocalizableError';
import type { Address } from '../api/addresses/types';
import type { Address, InspectAddressResponse } from '../api/addresses/types';

export default class AddressesStore extends Store {
@observable lastGeneratedAddress: ?WalletAddress = null;
Expand All @@ -21,6 +21,10 @@ export default class AddressesStore extends Store {
@observable createByronWalletAddressRequest: Request<Address> = new Request(
this.api.ada.createAddress
);
@observable
inspectAddressRequest: Request<InspectAddressResponse> = new Request(
this.api.ada.inspectAddress
);

setup() {
const actions = this.actions.addresses;
Expand Down Expand Up @@ -58,6 +62,15 @@ export default class AddressesStore extends Store {
}
};

_inspectAddress = async (params: { addressId: string }) => {
const { addressId } = params;
this.inspectAddressRequest.reset();
const addressDetails = await this.inspectAddressRequest.execute({
addressId,
}).promise;
return addressDetails;
};

@computed get all(): Array<WalletAddress> {
const wallet = this.stores.wallets.active;
if (!wallet) return [];
Expand Down
20 changes: 12 additions & 8 deletions source/renderer/app/stores/HardwareWalletsStore.js
Expand Up @@ -110,10 +110,6 @@ export default class HardwareWalletsStore extends Store {
constructAddressRequest: Request<any> = new Request(
this.api.ada.constructAddress
);
// @TODO - improve types
inspectAddressRequest: Request<any> = new Request(
this.api.ada.inspectAddress
);
@observable
hardwareWalletsLocalDataRequest: Request<HardwareWalletsLocalData> = new Request(
this.api.localStorage.getHardwareWalletsLocalData
Expand Down Expand Up @@ -1265,11 +1261,18 @@ export default class HardwareWalletsStore extends Store {
});

const unsignedTxOutputs = [];
const outputsData = map(outputs, (output) => {
const shelleyTxOutput = ShelleyTxOutput(output);
const outputsData = [];
for (const output of outputs) {
const {
address_style: addressStyle,
} = await this.stores.addresses._inspectAddress({
addressId: output.address,
});
const shelleyTxOutput = ShelleyTxOutput(output, addressStyle);
unsignedTxOutputs.push(shelleyTxOutput);
return prepareLedgerOutput(output);
});
const ledgerOutput = prepareLedgerOutput(output, addressStyle);
outputsData.push(ledgerOutput);
}

const unsignedTxCerts = [];
const _certificatesData = map(certificates, async (certificate) => {
Expand Down Expand Up @@ -1311,6 +1314,7 @@ export default class HardwareWalletsStore extends Store {
metadataHashHex,
devicePath,
});

// Prepare unsigned transaction structure for serialzation
const unsignedTx = prepareTxAux({
txInputs: unsignedTxInputs,
Expand Down
24 changes: 20 additions & 4 deletions source/renderer/app/utils/shelleyLedger.js
Expand Up @@ -7,6 +7,7 @@ import {
CERTIFICATE_TYPE,
} from './hardwareWalletUtils';
import { deriveXpubChannel } from '../ipc/getHardwareWalletChannel';
import { AddressStyles } from '../domains/WalletAddress';

// Types
import type {
Expand All @@ -18,6 +19,7 @@ import type {
BIP32Path,
Certificate,
} from '../../../common/types/hardware-wallets.types';
import type { AddressStyle } from '../api/addresses/types';

export type ShelleyTxInputType = {
coins: number,
Expand Down Expand Up @@ -105,12 +107,18 @@ export const ShelleyTxInputFromUtxo = (utxoInput: CoinSelectionInput) => {
};
};

export const ShelleyTxOutput = (output: CoinSelectionOutput) => {
export const ShelleyTxOutput = (
output: CoinSelectionOutput,
addressStyle: AddressStyle
) => {
const { address, amount, derivationPath } = output;
const coins = amount.quantity;

function encodeCBOR(encoder: any) {
const addressBuff = utils.bech32_decodeAddress(address);
const addressBuff =
addressStyle === AddressStyles.ADDRESS_SHELLEY
? utils.bech32_decodeAddress(address)
: utils.base58_decode(address);
return encoder.pushAny([addressBuff, coins]);
}
const isChange = derivationPath !== null;
Expand Down Expand Up @@ -303,7 +311,10 @@ export const prepareLedgerInput = (input: CoinSelectionInput) => {
};
};

export const prepareLedgerOutput = (output: CoinSelectionOutput) => {
export const prepareLedgerOutput = (
output: CoinSelectionOutput,
addressStyle: AddressStyle
) => {
const isChange = output.derivationPath !== null;
if (isChange) {
return {
Expand All @@ -313,9 +324,14 @@ export const prepareLedgerOutput = (output: CoinSelectionOutput) => {
stakingPath: utils.str_to_path("1852'/1815'/0'/2/0"),
};
}

const isSheeleyAddress = addressStyle === AddressStyles.ADDRESS_SHELLEY;
const decodedAddress = isSheeleyAddress
? utils.bech32_decodeAddress(output.address)
: utils.base58_decode(output.address);
return {
amountStr: output.amount.quantity.toString(),
addressHex: utils.buf_to_hex(utils.bech32_decodeAddress(output.address)),
addressHex: utils.buf_to_hex(decodedAddress),
};
};

Expand Down

0 comments on commit 9aed847

Please sign in to comment.