Skip to content

Commit

Permalink
Add FinalizationCommitteeParameters Update
Browse files Browse the repository at this point in the history
  • Loading branch information
soer8647 committed Sep 15, 2023
1 parent e540055 commit 783d921
Show file tree
Hide file tree
Showing 14 changed files with 387 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added

- Support for block energy limit chain update.
- Support for finalization committee parameters chain update.

## 1.5.0

Expand Down
15 changes: 15 additions & 0 deletions app/features/ledger/ConcordiumLedgerClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
FinalizationCommitteeParameters,
} from '~/utils/types';
import { pipe } from '~/utils/basicHelpers';

Expand Down Expand Up @@ -351,4 +352,18 @@ export default class ConcordiumLedgerClient {
)
);
}

signFinalizationCommitteeParameters(
transaction: UpdateInstruction<FinalizationCommitteeParameters>,
serializedPayload: Buffer,
path: number[]
): Promise<Buffer> {
return toBuffer(
window.ledger.signFinalizationCommitteeParameters(
transaction,
serializedPayload,
path
)
);
}
}
15 changes: 15 additions & 0 deletions app/features/ledger/ConcordiumLedgerClientMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
FinalizationCommitteeParameters,
} from '~/utils/types';
import { AccountPathInput, getAccountPath } from './Path';
import getAppAndVersion, { AppAndVersion } from './GetAppAndVersion';
Expand Down Expand Up @@ -415,6 +416,20 @@ export default class ConcordiumLedgerClientMain {
);
}

signFinalizationCommitteeParameters(
transaction: UpdateInstruction<FinalizationCommitteeParameters>,
serializedPayload: Buffer,
path: number[]
): Promise<Buffer> {
return signUpdateTransaction(
this.transport,
0x46,
path,
transaction,
serializedPayload
);
}

getAppAndVersion(): Promise<AppAndVersion> {
return getAppAndVersion(this.transport);
}
Expand Down
6 changes: 6 additions & 0 deletions app/pages/multisig/menu/MultiSignatureCreateProposalList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ const updateInstructionTypes: TypeTuple[] = [
'Update block energy limit',
hasConsensusUpdateProtocol,
],
[
TransactionTypes.UpdateInstruction,
UpdateType.FinalizationCommitteeParameters,
'Update finalization committee parameters',
hasConsensusUpdateProtocol,
],
];

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { RewardFractionField } from '../common/RewardFractionField/RewardFractionField';
import { fieldDisplays } from './util';
import Label from '~/components/Label';
import { FinalizationCommitteeParameters } from '~/utils/types';

interface PoolParametersShowProps {
parameters: FinalizationCommitteeParameters;
title: string;
}

export default function ShowFinalizationCommitteeParameters({
parameters: {
minFinalizers,
maxFinalizers,
relativeStakeThresholdFraction,
},
title,
}: PoolParametersShowProps): JSX.Element {
return (
<section className="mB40">
<h3>{title}</h3>
<div>
<Label className="mB5">{fieldDisplays.minFinalizers}:</Label>
<div className="body3 mono mB10">{minFinalizers}</div>
<Label className="mB5">{fieldDisplays.maxFinalizers}:</Label>
<div className="body3 mono mB10">{maxFinalizers}</div>
<RewardFractionField
label={fieldDisplays.relativeStakeThresholdFraction}
value={relativeStakeThresholdFraction}
disabled
/>
</div>
</section>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { isChainParametersV0, isChainParametersV1 } from '@concordium/web-sdk';
import Loading from '~/cross-app-components/Loading';
import { FinalizationCommitteeParameters } from '~/utils/types';
import withChainData, { ChainData } from '~/utils/withChainData';
import ShowFinalizationCommitteeParameters from './FinalizationCommitteeParametersShow';
import { getCurrentFinalizationCommitteeParameters } from './util';

interface Props extends ChainData {
finalizationCommitteeParameters: FinalizationCommitteeParameters;
}

/**
* Displays an overview of a baker stake threshold.
*/
export default withChainData(function FinalizationCommitteeParametersView({
finalizationCommitteeParameters,
chainParameters,
}: Props) {
if (!chainParameters) {
return <Loading inline />;
}

if (
isChainParametersV0(chainParameters) ||
isChainParametersV1(chainParameters)
) {
throw new Error('Connected node used outdated chainParameters format');
}

const current = getCurrentFinalizationCommitteeParameters(chainParameters);

return (
<>
<ShowFinalizationCommitteeParameters
parameters={current}
title="Current finalization committee parameters"
/>
<ShowFinalizationCommitteeParameters
parameters={finalizationCommitteeParameters}
title="New finalization committee parameters"
/>
</>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from 'react';
import { isChainParametersV0, isChainParametersV1 } from '@concordium/web-sdk';
import { EqualRecord } from '~/utils/types';
import { UpdateProps } from '~/utils/transactionTypes';
import Form from '~/components/Form/';
import { mustBeAnInteger, requiredMessage, enterHere } from '../common/util';
import {
FinalizationCommitteeParametersFields,
fieldDisplays,
getCurrentFinalizationCommitteeParameters,
} from './util';
import ShowFinalizationCommitteeParameters from './FinalizationCommitteeParametersShow';
import { FormRewardFractionField as FractionFieldForm } from '../common/RewardFractionField/RewardFractionField';

const fieldNames: EqualRecord<FinalizationCommitteeParametersFields> = {
minFinalizers: 'minFinalizers',
maxFinalizers: 'maxFinalizers',
relativeStakeThresholdFraction: 'relativeStakeThresholdFraction',
};

const UINT32_MAX = 2 ** 32 - 1; // UInt32 upper bound

const validationRules = (name: string) => ({
required: requiredMessage(name),
min: {
value: 1,
message: `${name} must be positive`,
},
max: {
value: UINT32_MAX,
message: `${name} may not exceed ${UINT32_MAX}`,
},
validate: {
mustBeAnInteger,
},
});

/**
* Component for creating an update block energy limit transaction.
*/
export default function UpdateFinalizationCommitteeParametersFields({
defaults,
chainParameters,
}: UpdateProps): JSX.Element | null {
if (
isChainParametersV0(chainParameters) ||
isChainParametersV1(chainParameters)
) {
throw new Error('Connected node used outdated chainParameters format');
}

const current = getCurrentFinalizationCommitteeParameters(chainParameters);

return (
<div>
<ShowFinalizationCommitteeParameters
parameters={current}
title="Current finalization committee parameters"
/>
<h3>New finalization committee parameters</h3>
<Form.Input
className="body2 mB5"
name={fieldNames.minFinalizers}
defaultValue={
defaults.minFinalizers || current.minFinalizers.toString()
}
label={`New ${fieldDisplays.minFinalizers}`}
placeholder={enterHere(fieldDisplays.minFinalizers)}
rules={validationRules(fieldDisplays.minFinalizers)}
/>
<Form.Input
className="body2"
name={fieldNames.maxFinalizers}
defaultValue={
defaults.maxFinalizers || current.maxFinalizers.toString()
}
label={`New ${fieldDisplays.maxFinalizers}`}
placeholder={enterHere(fieldDisplays.maxFinalizers)}
rules={validationRules(fieldDisplays.maxFinalizers)}
/>
<FractionFieldForm
label={fieldDisplays.relativeStakeThresholdFraction}
name={fieldNames.relativeStakeThresholdFraction}
className="mV20"
defaultValue={
defaults.relativeStakeThresholdFraction ||
current.relativeStakeThresholdFraction.toString()
}
/>
</div>
);
}
26 changes: 26 additions & 0 deletions app/pages/multisig/updates/FinalizationCommitteeParameters/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ChainParametersV2 } from '@concordium/common-sdk';
import updateConstants from '~/constants/updateConstants.json';

export interface FinalizationCommitteeParametersFields {
minFinalizers: number;
maxFinalizers: number;
relativeStakeThresholdFraction: number;
}

export const fieldDisplays = {
minFinalizers: 'Minimum number of finalizers',
maxFinalizers: 'Maximum number of finalizers',
relativeStakeThresholdFraction: 'Relative stake threshold fraction',
};

export function getCurrentFinalizationCommitteeParameters(
chainParameters: ChainParametersV2
): FinalizationCommitteeParametersFields {
return {
relativeStakeThresholdFraction:
chainParameters.finalizerRelativeStakeThreshold *
updateConstants.rewardFractionResolution,
minFinalizers: chainParameters.minimumFinalizers,
maxFinalizers: chainParameters.maximumFinalizers,
};
}
12 changes: 12 additions & 0 deletions app/preload/ledger/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
FinalizationCommitteeParameters,
} from '~/utils/types';
import { LedgerCommands } from '~/preload/preloadTypes';

Expand Down Expand Up @@ -289,6 +290,17 @@ export default function exposedMethods(
keypath
);
},
signFinalizationCommitteeParameters: (
transaction: UpdateInstruction<FinalizationCommitteeParameters>,
serializedPayload: Buffer,
keypath: number[]
) => {
return getLedgerClient().signFinalizationCommitteeParameters(
transaction,
serializedPayload,
keypath
);
},
getAppAndVersion: () => getLedgerClient().getAppAndVersion(),
subscribe: () => subscribeLedger(eventEmitter),
closeTransport,
Expand Down
2 changes: 2 additions & 0 deletions app/preload/preloadLedgerTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
FinalizationCommitteeParameters,
} from '~/utils/types';
import { AppAndVersion } from '../features/ledger/GetAppAndVersion';
import { AccountPathInput } from '../features/ledger/Path';
Expand Down Expand Up @@ -109,6 +110,7 @@ type LedgerCommands = {
signCooldownParameters: SignUpdate<CooldownParameters>;
signPoolParameters: SignUpdate<PoolParameters>;
signBlockEnergyLimit: SignUpdate<BlockEnergyLimit>;
signFinalizationCommitteeParameters: SignUpdate<FinalizationCommitteeParameters>;
signHigherLevelKeysUpdate: SignKeyUpdate<HigherLevelKeyUpdate>;
signAuthorizationKeysUpdate: SignVersionedKeyUpdate<AuthorizationKeysUpdate>;
getAppAndVersion: () => Promise<AppAndVersion>;
Expand Down
20 changes: 20 additions & 0 deletions app/utils/UpdateSerialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
CommissionRanges,
AuthorizationKeysUpdateType,
BlockEnergyLimit,
FinalizationCommitteeParameters,
} from './types';

/**
Expand Down Expand Up @@ -64,6 +65,7 @@ export enum OnChainUpdateType {
UpdateTimeParameters = 16,
UpdateMintDistributionV1 = 17,
UpdateBlockEnergyLimit = 20,
UpdateFinalizationCommitteeParameters = 22,
}

/**
Expand Down Expand Up @@ -222,6 +224,22 @@ export function serializeBlockEnergyLimit(blockEnergyLimit: BlockEnergyLimit) {
return serializedBlockEnergyLimit;
}

/**
* Serializes a FinalizationCommitteeParameters to the byte format expected
* by the chain.
*/
export function serializeFinalizationCommitteeParameters(
finalizationCommitteeParameters: FinalizationCommitteeParameters
) {
return Buffer.concat([
encodeWord32(finalizationCommitteeParameters.minFinalizers),
encodeWord32(finalizationCommitteeParameters.maxFinalizers),
encodeWord32(
finalizationCommitteeParameters.relativeStakeThresholdFraction
),
]);
}

/**
* Serializes an ElectionDifficulty to bytes.
*/
Expand Down Expand Up @@ -594,6 +612,8 @@ function mapUpdateTypeToOnChainUpdateType(type: UpdateType): OnChainUpdateType {
return OnChainUpdateType.UpdateMintDistributionV1;
case UpdateType.BlockEnergyLimit:
return OnChainUpdateType.UpdateBlockEnergyLimit;
case UpdateType.FinalizationCommitteeParameters:
return OnChainUpdateType.UpdateFinalizationCommitteeParameters;
default:
throw new Error(`An invalid update type was given: ${type}`);
}
Expand Down
Loading

0 comments on commit 783d921

Please sign in to comment.