Skip to content

Commit

Permalink
Update Trezor cvote registration signing
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmisiak committed Aug 18, 2023
1 parent 13f121f commit 93dced0
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 150 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@emurgo/cardano-serialization-lib-nodejs": "^8.0.0",
"@ledgerhq/hw-transport": "^6.27.10",
"@ledgerhq/hw-transport-node-hid-noevents": "^6.24.1",
"@trezor/connect": "^9.0.4",
"@trezor/connect": "^9.0.11",
"argparse": "^2.0.1",
"bignumber": "^1.1.0",
"cardano-crypto.js": "^5.3.6-rc.6",
Expand Down
80 changes: 39 additions & 41 deletions src/crypto-providers/trezorCryptoProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ import {

const {bech32} = require('cardano-crypto.js')

type _TrezorDestination =
| {
address: string
}
| {
addressParameters: TrezorTypes.CardanoAddressParameters
}

export const TrezorCryptoProvider: () => Promise<CryptoProvider> = async () => {
const getVersion = async (): Promise<string> => {
const {payload: features} = await TrezorConnect.getFeatures()
Expand Down Expand Up @@ -215,13 +223,7 @@ export const TrezorCryptoProvider: () => Promise<CryptoProvider> = async () => {
address: Buffer,
changeAddressParams: _AddressParameters | null,
signingMode: SigningMode,
):
| {
address: string
}
| {
addressParameters: TrezorTypes.CardanoAddressParameters
} => {
): _TrezorDestination => {
if (changeAddressParams && areAddressParamsAllowed(signingMode)) {
// paymentPath should always be defined if changeAddressParams are defined
if (!changeAddressParams.paymentPath) throw Error(Errors.Unreachable)
Expand Down Expand Up @@ -741,53 +743,39 @@ export const TrezorCryptoProvider: () => Promise<CryptoProvider> = async () => {

const prepareVoteDelegations = (
delegations: CVoteDelegation[],
): TrezorTypes.CardanoGovernanceRegistrationDelegation[] =>
): TrezorTypes.CardanoCVoteRegistrationDelegation[] =>
delegations.map(({votePublicKey, voteWeight}) => {
if (Number(voteWeight) > Number.MAX_SAFE_INTEGER) {
throw Error(Errors.InvalidCVoteWeight)
}
return {
votingPublicKey: votePublicKey,
votePublicKey,
weight: Number(voteWeight),
}
})

const prepareVoteAuxiliaryData = (
delegations: CVoteDelegation[],
hwStakeSigningFile: HwSigningData,
addressParameters: _AddressParameters,
paymentDestination: _TrezorDestination,
nonce: bigint,
votingPurpose: bigint,
): TrezorTypes.CardanoAuxiliaryData => {
const prepareAddressParameters = () => {
if (
addressParameters.addressType === TrezorEnums.CardanoAddressType.BASE
) {
return {
addressType: addressParameters.addressType,
path: addressParameters.paymentPath as BIP32Path,
stakingPath: addressParameters.stakePath,
}
}
if (
addressParameters.addressType === TrezorEnums.CardanoAddressType.REWARD
) {
return {
addressType: addressParameters.addressType,
stakingPath: addressParameters.stakePath as BIP32Path,
}
}
throw Error(Errors.InvalidCIP36RegistrationAddressType)
const destination: {
address?: string
addressParameters?: TrezorTypes.CardanoAddressParameters
} = paymentDestination
if (Number(votingPurpose) > Number.MAX_SAFE_INTEGER) {
throw Error(Errors.InvalidCVoteVotingPurpose)
}

return {
governanceRegistrationParameters: {
format: TrezorEnums.CardanoGovernanceRegistrationFormat.CIP36,
cVoteRegistrationParameters: {
format: TrezorEnums.CardanoCVoteRegistrationFormat.CIP36,
delegations: prepareVoteDelegations(delegations),
stakingPath: hwStakeSigningFile.path,
rewardAddressParameters: prepareAddressParameters(),
paymentAddressParameters: destination.addressParameters,
paymentAddress: destination.address,
nonce: `${nonce}`,
// TODO change the type in Trezor Connect? or do some validation here
votingPurpose: Number(votingPurpose),
},
}
Expand Down Expand Up @@ -833,21 +821,30 @@ export const TrezorCryptoProvider: () => Promise<CryptoProvider> = async () => {
derivationType?: DerivationType,
): Promise<CIP36RegistrationMetaDataCborHex> => {
const {data: address}: {data: Buffer} = bech32.decode(paymentAddressBech32)

let destination: _TrezorDestination
const addressParams = getAddressParameters(
paymentAddressSigningFiles,
address,
network,
)
if (!addressParams) {
throw Error(Errors.AuxSigningFileNotFoundForCIP36PaymentAddress)
if (addressParams) {
validateCIP36RegistrationAddressType(addressParams.addressType)
destination = {
addressParameters: {
addressType: addressParams.addressType,
path: addressParams.paymentPath,
stakingPath: addressParams.stakePath,
},
}
} else {
destination = {address: paymentAddressBech32}
}

validateCIP36RegistrationAddressType(addressParams.addressType)

const trezorAuxData = prepareVoteAuxiliaryData(
delegations,
hwStakeSigningFile,
addressParams,
destination,
nonce,
votingPurpose,
)
Expand All @@ -862,7 +859,7 @@ export const TrezorCryptoProvider: () => Promise<CryptoProvider> = async () => {
}
if (!response.payload.auxiliaryDataSupplement)
throw Error(Errors.MissingAuxiliaryDataSupplement)
if (!response.payload.auxiliaryDataSupplement.governanceSignature) {
if (!response.payload.auxiliaryDataSupplement.cVoteRegistrationSignature) {
throw Error(Errors.MissingCIP36RegistrationSignature)
}

Expand All @@ -873,7 +870,8 @@ export const TrezorCryptoProvider: () => Promise<CryptoProvider> = async () => {
nonce,
votingPurpose,
response.payload.auxiliaryDataSupplement.auxiliaryDataHash as HexString,
response.payload.auxiliaryDataSupplement.governanceSignature as HexString,
response.payload.auxiliaryDataSupplement
.cVoteRegistrationSignature as HexString,
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export const enum Errors {
InternalInvalidTypeError = 'Internal invalid type error',
InvalidCVotePublicKey = 'Invalid CIP36 vote public key',
InvalidCVoteWeight = 'Invalid CIP36 vote weight',
InvalidCVoteVotingPurpose = 'Invalid CIP36 voting purpose',
InvalidCVoteDelegations = 'Invalid CIP36 delegations (either a single vote public key or several vote public keys with their weights are expected)',
AuxSigningFileNotFoundForCIP36PaymentAddress = "CIP36 payment address doesn't match with supplied auxiliary signing keys --- Trezor does not support third-party reward addresses yet", // TODO should be removed after the support is added
ByronSigningFilesFoundInCIP36Registration = 'Byron addresses are not allowed for CIP36 registration',
TrezorVersionError = 'Failed to retrieve trezor version',
InvalidCIP36RegistrationAddressType = 'CIP36 registration address type must be either BASE or REWARD',
Expand Down
17 changes: 17 additions & 0 deletions test/integration/trezor/node/cip36Registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,23 @@ const cip36Registrations = {
signedCIP36RegistrationMetaDataHex:
'a219ef64a501828258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7018258201af8fa0b754ff99253d983894e63a2b09cbb56c833ba18c3384210163f63dcfc02025820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e03581de1122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277041a000286bc050019ef65a10158408dcc41c03e7fe9b281f00c9ac2a8418d4fce9c0673f163088f45a014ad30d8740cb60b065ecdb073d44bb0595e519f9e584c6620258f27e20432706999e7a604',
},
withThirdPartyPaymentAddress: {
delegations: [
{
votePublicKey:
'3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7',
voteWeight: 2,
},
],
hwStakeSigningFile: signingFiles.stake0,
paymentAddressBech32: addresses.mainnet.base0,
nonce: 165564,
votingPurpose: 1,
network: 'MAINNET',
auxiliarySigningFiles: [],
signedCIP36RegistrationMetaDataHex:
'a219ef64a501818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b702025820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e0358390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277041a000286bc050119ef65a10158404893bdbcf02dd0169de641996db41619cdba64f5d36adb4964ba861139ff5306737e9618a558c4ade41e9118cece138df21cebd56175759de18e20349510f607',
},
}

async function testCIP36RegistrationMetaDataSigning(
Expand Down
Loading

0 comments on commit 93dced0

Please sign in to comment.