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

feat(tangle-dapp): Added Logic To Handle Ledger Signature #2301

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 62 additions & 2 deletions apps/tangle-dapp/app/claim/EligibleSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

import type { SubmittableExtrinsic } from '@polkadot/api/types';
import type { ISubmittableResult } from '@polkadot/types/types';
import { BN_ZERO, hexToU8a, stringToU8a, u8aToString } from '@polkadot/util';
import {
BN_ZERO,
hexToU8a,
stringToU8a,
u8aToHex,
u8aToString,
} from '@polkadot/util';
import {
decodeAddress,
isEthereumAddress,
Expand Down Expand Up @@ -140,13 +146,14 @@ const EligibleSection: FC<Props> = ({
);

const signature = await activeApi.sign(payload);
const validSignature = ensureValidLedgerSignature(signature, isEvmSigner);

setStep(Step.SENDING_TX);

const tx = api.tx.claims.claimAttest(
isEvmRecipient ? { EVM: recipient } : { Native: recipient }, // destAccount
isEvmSigner ? { EVM: accountId } : { Native: accountId }, // signer
isEvmSigner ? { EVM: signature } : { Native: signature }, // signature
isEvmSigner ? { EVM: validSignature } : { Native: validSignature }, // signature
statementSentence
);

Expand Down Expand Up @@ -393,3 +400,56 @@ function getLoadingText(step: Step) {
return '';
}
}

/**
*
* @param signature the signature to check and format to be used in the claimAttest extrinsic call
* @param isEvmSigner whether the signer is an EVM address
*/
function ensureValidLedgerSignature(
signature: string,
isEvmSigner: boolean
): string {
if (isEvmSigner) {
return handleEvmSignature(signature);
} else {
return handleSubstrateSignature(signature);
}
}

/**
* @see https://mirror.xyz/coa.eth/mvPbLPXvy375CXi1_XwMTzG84lwlSKYUBHDx_R1TIgU
*/
function handleEvmSignature(signature: string): string {
const evmSignatureRegex = /(^0[xX]|^)[0-9a-fA-F]{128}(00|01)$/;

if (evmSignatureRegex.test(signature)) {
// Ledger devices produces vrs signatures with a canonical v value of 0 or 1. When signing
// a message on a Ledger and then relaying the signature to MetaMask, the v byte is still
// going to be 0 or 1 when it is sent to the dapp, instead of the expected 27 or 28. The
// invalid last byte will cause validation of the signature to fail. This fixes the issue.

// [details] https://github.com/ethereum/go-ethereum/issues/19751#issuecomment-504900739

const vValue = parseInt(signature.slice(-2), 16);
const validVValue = (vValue + 27).toString(16);

const validSignature = signature.slice(0, -2) + validVValue;
return validSignature;
}

// If the signature is not in the expected format, return it as is as it is invalid
return signature;
}

function handleSubstrateSignature(signature: string): string {
const signatureBytes = hexToU8a(signature);
const maxSignatureLength = 64;

// If the signature is greater than 64 bytes, we return the last 64 bytes
if (signatureBytes.length > maxSignatureLength) {
return u8aToHex(signatureBytes.slice(-maxSignatureLength));
}

return signature;
}
Loading