Skip to content

Commit

Permalink
handle requiredSigners
Browse files Browse the repository at this point in the history
  • Loading branch information
yushih committed Mar 21, 2023
1 parent c978a4c commit 0e9ca32
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 48 deletions.
Expand Up @@ -757,6 +757,7 @@ export function toLedgerSignRequest(
outputs.push(formatOutput(txBody.outputs().get(i)));
}

const additionalWitnessPaths = [];
const formattedRequiredSigners = [];
const requiredSigners = txBody.required_signers();
if (requiredSigners) {
Expand All @@ -772,6 +773,7 @@ export function toLedgerSignRequest(
type: TxRequiredSignerType.PATH,
path: ownAddressPath,
});
additionalWitnessPaths.push(ownAddressPath);
} else {
formattedRequiredSigners.push({
type: TxRequiredSignerType.HASH,
Expand Down Expand Up @@ -867,6 +869,49 @@ export function toLedgerSignRequest(
totalCollateral: txBody.total_collateral()?.to_str() ?? null,
referenceInputs: formattedReferenceInputs,
},
additionalWitnessPaths: [],
additionalWitnessPaths,
};
}

export function buildConnectorSignedTransaction(
txBody: RustModule.WalletV4.TransactionBody,
witnesses: Array<Witness>,
publicKey: {|
...Addressing,
key: RustModule.WalletV4.Bip32PublicKey,
|},
metadata: RustModule.WalletV4.AuxiliaryData | void
): RustModule.WalletV4.Transaction {
const keyLevel = publicKey.addressing.startLevel + publicKey.addressing.path.length - 1;

const vkeyWitWasm = RustModule.WalletV4.Vkeywitnesses.new();

for (const witness of witnesses) {
const addressing = {
path: witness.path,
startLevel: 1,
};
verifyFromBip44Root(addressing);

const witnessKey = derivePublicByAddressing({
addressing,
startingFrom: {
level: keyLevel,
key: publicKey.key,
}
});
const vkeyWit = RustModule.WalletV4.Vkeywitness.new(
RustModule.WalletV4.Vkey.new(witnessKey.to_raw_key()),
RustModule.WalletV4.Ed25519Signature.from_bytes(Buffer.from(witness.witnessSignatureHex, 'hex')),
);
vkeyWitWasm.add(vkeyWit);
}
const witSet = RustModule.WalletV4.TransactionWitnessSet.new();
witSet.set_vkeys(vkeyWitWasm);

return RustModule.WalletV4.Transaction.new(
txBody,
witSet,
metadata
);
}
Expand Up @@ -19,7 +19,7 @@ import {
CERTIFICATE_TYPE,
ADDRESS_TYPE,
} from 'trezor-connect/lib/constants/cardano';
import { CardanoTxSigningMode } from 'trezor-connect';
import { CardanoTxSigningMode, CardanoTxWitnessType, } from 'trezor-connect';
import type {
Address, Value, Addressing,
} from '../../lib/storage/models/PublicDeriver/interfaces';
Expand Down Expand Up @@ -644,6 +644,7 @@ export function toTrezorSignRequest(
}

const formattedRequiredSigners = [];
const additionalWitnessRequests = [];
const requiredSigners = txBody.required_signers();
if (requiredSigners) {
for (let i = 0; i < requiredSigners.len(); i++) {
Expand All @@ -657,6 +658,7 @@ export function toTrezorSignRequest(
formattedRequiredSigners.push({
keyPath: ownAddressPath,
});
additionalWitnessRequests.push(ownAddressPath);
} else {
formattedRequiredSigners.push({
keyHash: hash.to_hex(),
Expand Down Expand Up @@ -813,5 +815,39 @@ export function toTrezorSignRequest(
result.requiredSigners = formattedRequiredSigners;
}

if (additionalWitnessRequests) {
result.additionalWitnessRequests = additionalWitnessRequests;
}

return result;
}

export function buildConnectorSignedTransaction(
txBody: RustModule.WalletV4.TransactionBody,
witnesses: Array<CardanoSignedTxWitness>,
metadata: RustModule.WalletV4.AuxiliaryData | void,
): RustModule.WalletV4.Transaction {
const vkeyWitnesses = RustModule.WalletV4.Vkeywitnesses.new();
for (const witness of witnesses) {
if (witness.type === CardanoTxWitnessType.BYRON_WITNESS) {
throw new Error('Byron wallet does not support connector API');
} else if (witness.type === CardanoTxWitnessType.SHELLEY_WITNESS) {
const vkeyWitness = RustModule.WalletV4.Vkeywitness.new(
RustModule.WalletV4.Vkey.new(
RustModule.WalletV4.PublicKey.from_hex(witness.pubKey)
),
RustModule.WalletV4.Ed25519Signature.from_hex(witness.signature),
);
vkeyWitnesses.add(vkeyWitness);
} else {
throw new Error('unexpected witness type');
}
}
const witnessSet = RustModule.WalletV4.TransactionWitnessSet.new();
witnessSet.set_vkeys(vkeyWitnesses);
return RustModule.WalletV4.Transaction.new(
txBody,
witnessSet,
metadata
);
}
48 changes: 2 additions & 46 deletions packages/yoroi-extension/app/connector/stores/ConnectorStore.js
Expand Up @@ -86,11 +86,11 @@ import { LedgerConnect } from '../../utils/hwConnectHandler';
import { getAllAddressesWithPaths } from '../../api/ada/lib/storage/bridge/traitUtils'
import {
toLedgerSignRequest,
buildSignedTransaction as buildSignedLedgerTransaction,
buildConnectorSignedTransaction as buildSignedLedgerTransaction,
} from '../../api/ada/transactions/shelley/ledgerTx';
import {
toTrezorSignRequest,
buildSignedTransaction as buildSignedTrezorTransaction,
buildConnectorSignedTransaction as buildSignedTrezorTransaction,
} from '../../api/ada/transactions/shelley/trezorTx';
import type { CardanoAddressedUtxo } from '../../api/ada/transactions/types';
import blake2b from 'blake2b';
Expand Down Expand Up @@ -1153,41 +1153,9 @@ export default class ConnectorStore extends Store<StoresMap, ActionsMap> {
throw new Error('hash mismatch');
}

const withLevels = asHasLevels<ConceptualWallet>(publicDeriver);
if (withLevels == null) {
throw new Error('No public deriver level for this public deriver');
}

const withPublicKey = asGetPublicKey(withLevels);
if (withPublicKey == null) throw new Error('No public key for this public deriver');
const publicKey = await withPublicKey.getPublicKey();

const publicKeyInfo = {
key: RustModule.WalletV4.Bip32PublicKey.from_bytes(
Buffer.from(publicKey.Hash, 'hex')
),
addressing: {
startLevel: 1,
path: withLevels.getPathToPublic(),
},
};

// `addressedUtxos` is all UTXOs of this wallet
// `ownUtxos` is own UTXOs used by this tx as inputs
const txInputs = new Set();
for (let i = 0; i < txBody.inputs().len(); i++) {
const input = txBody.inputs().get(i);
txInputs.add(`${input.transaction_id().to_hex()}${input.index()}`);
}
const ownUtxos = addressedUtxos.filter(utxo =>
txInputs.has(`${utxo.tx_hash}${utxo.tx_index}`)
);

return buildSignedTrezorTransaction(
txBody,
ownUtxos,
trezorSignTxResp.witnesses,
publicKeyInfo,
undefined
);
}
Expand Down Expand Up @@ -1281,20 +1249,8 @@ export default class ConnectorStore extends Store<StoresMap, ActionsMap> {
},
};

// `addressedUtxos` is all UTXOs of this wallet
// `ownUtxos` is own UTXOs used by this tx as inputs
const txInputs = new Set();
for (let i = 0; i < txBody.inputs().len(); i++) {
const input = txBody.inputs().get(i);
txInputs.add(`${input.transaction_id().to_hex()}${input.index()}`);
}
const ownUtxos = addressedUtxos.filter(utxo =>
txInputs.has(`${utxo.tx_hash}${utxo.tx_index}`)
);

return buildSignedLedgerTransaction(
txBody,
ownUtxos,
ledgerSignResult.witnesses,
publicKeyInfo,
undefined
Expand Down

0 comments on commit 0e9ca32

Please sign in to comment.