Skip to content

Commit

Permalink
Add BlockEnergyLimit Update
Browse files Browse the repository at this point in the history
  • Loading branch information
soer8647 committed Sep 14, 2023
1 parent fdccf7a commit e540055
Show file tree
Hide file tree
Showing 14 changed files with 305 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Added

- Support for block energy limit chain update.

## 1.5.0

### Added
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 @@ -22,6 +22,7 @@ import {
TimeParameters,
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
} from '~/utils/types';
import { pipe } from '~/utils/basicHelpers';

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

signBlockEnergyLimit(
transaction: UpdateInstruction<BlockEnergyLimit>,
serializedPayload: Buffer,
path: number[]
): Promise<Buffer> {
return toBuffer(
window.ledger.signBlockEnergyLimit(
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 @@ -43,6 +43,7 @@ import {
TimeParameters,
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
} from '~/utils/types';
import { AccountPathInput, getAccountPath } from './Path';
import getAppAndVersion, { AppAndVersion } from './GetAppAndVersion';
Expand Down Expand Up @@ -400,6 +401,20 @@ export default class ConcordiumLedgerClientMain {
);
}

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

getAppAndVersion(): Promise<AppAndVersion> {
return getAppAndVersion(this.transport);
}
Expand Down
11 changes: 10 additions & 1 deletion app/pages/multisig/menu/MultiSignatureCreateProposalList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { proposalsSelector } from '~/features/MultiSignatureSlice';
import { expireProposals } from '~/utils/ProposalHelper';
import routes from '~/constants/routes.json';
import { useProtocolVersion } from '~/utils/dataHooks';
import { hasDelegationProtocol } from '~/utils/protocolVersion';
import {
hasDelegationProtocol,
hasConsensusUpdateProtocol,
} from '~/utils/protocolVersion';
import { not } from '~/utils/functionHelpers';

import styles from '../MultiSignaturePage/MultiSignaturePage.module.scss';
Expand Down Expand Up @@ -127,6 +130,12 @@ const updateInstructionTypes: TypeTuple[] = [
'Update time parameters',
hasDelegationProtocol,
],
[
TransactionTypes.UpdateInstruction,
UpdateType.BlockEnergyLimit,
'Update block energy limit',
hasConsensusUpdateProtocol,
],
];

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import { isChainParametersV0, isChainParametersV1 } from '@concordium/web-sdk';
import Loading from '~/cross-app-components/Loading';
import { BlockEnergyLimit } from '~/utils/types';
import withChainData, { ChainData } from '~/utils/withChainData';
import Label from '~/components/Label';

interface Props extends ChainData {
blockEnergyLimit: BlockEnergyLimit;
}

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

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

return (
<>
<div>
<Label className="mB5">Current block energy limit:</Label>
<div className="body3 mono">
{chainParameters.blockEnergyLimit.toString()}
</div>
</div>
<div>
<Label className="mB5">New block energy limit:</Label>
<div className="body3 mono">
{blockEnergyLimit.blockEnergyLimit.toString()}
</div>
</div>
</>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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';

export interface BlockEnergyLimitFields {
blockEnergyLimit: bigint;
}

const fieldNames: EqualRecord<BlockEnergyLimitFields> = {
blockEnergyLimit: 'blockEnergyLimit',
};

export const fieldDisplays = {
blockEnergyLimit: 'block energy limit',
};

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

const currentBlockEnergyLimit = chainParameters.blockEnergyLimit;

return (
<div>
<div className="body3 mono mB10">
Current {fieldDisplays.blockEnergyLimit}:{' '}
{currentBlockEnergyLimit.toString()} NRG
</div>
<Form.Input
className="body2"
name={fieldNames.blockEnergyLimit}
defaultValue={
defaults.blockEnergyLimit ||
currentBlockEnergyLimit.toString()
}
label={`New ${fieldDisplays.blockEnergyLimit} (NRG)`}
placeholder={enterHere(fieldDisplays.blockEnergyLimit)}
rules={{
required: requiredMessage(fieldDisplays.blockEnergyLimit),
min: {
value: 1,
message: 'Block energy limit must be positive',
},
max: {
value: '18446744073709551615',
message:
'Block energy limit must be below 18446744073709551615',
},
validate: {
mustBeAnInteger,
},
}}
/>
</div>
);
}
12 changes: 12 additions & 0 deletions app/preload/ledger/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
TimeParameters,
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
} from '~/utils/types';
import { LedgerCommands } from '~/preload/preloadTypes';

Expand Down Expand Up @@ -277,6 +278,17 @@ export default function exposedMethods(
keypath
);
},
signBlockEnergyLimit: (
transaction: UpdateInstruction<BlockEnergyLimit>,
serializedPayload: Buffer,
keypath: number[]
) => {
return getLedgerClient().signBlockEnergyLimit(
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 @@ -24,6 +24,7 @@ import {
TimeParameters,
CooldownParameters,
PoolParameters,
BlockEnergyLimit,
} from '~/utils/types';
import { AppAndVersion } from '../features/ledger/GetAppAndVersion';
import { AccountPathInput } from '../features/ledger/Path';
Expand Down Expand Up @@ -107,6 +108,7 @@ type LedgerCommands = {
signTimeParameters: SignUpdate<TimeParameters>;
signCooldownParameters: SignUpdate<CooldownParameters>;
signPoolParameters: SignUpdate<PoolParameters>;
signBlockEnergyLimit: SignUpdate<BlockEnergyLimit>;
signHigherLevelKeysUpdate: SignKeyUpdate<HigherLevelKeyUpdate>;
signAuthorizationKeysUpdate: SignVersionedKeyUpdate<AuthorizationKeysUpdate>;
getAppAndVersion: () => Promise<AppAndVersion>;
Expand Down
15 changes: 15 additions & 0 deletions app/utils/UpdateSerialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
CommissionRates,
CommissionRanges,
AuthorizationKeysUpdateType,
BlockEnergyLimit,
} from './types';

/**
Expand Down Expand Up @@ -62,6 +63,7 @@ export enum OnChainUpdateType {
UpdatePoolParameters = 15,
UpdateTimeParameters = 16,
UpdateMintDistributionV1 = 17,
UpdateBlockEnergyLimit = 20,
}

/**
Expand Down Expand Up @@ -209,6 +211,17 @@ export function serializeBakerStakeThreshold(
return serializedBakerStakeThreshold;
}

/**
* Serializes a BlockEnergyLimit to the byte format expected
* by the chain.
*/
export function serializeBlockEnergyLimit(blockEnergyLimit: BlockEnergyLimit) {
const serializedBlockEnergyLimit = encodeWord64(
BigInt(blockEnergyLimit.blockEnergyLimit)
);
return serializedBlockEnergyLimit;
}

/**
* Serializes an ElectionDifficulty to bytes.
*/
Expand Down Expand Up @@ -579,6 +592,8 @@ function mapUpdateTypeToOnChainUpdateType(type: UpdateType): OnChainUpdateType {
return OnChainUpdateType.UpdateTimeParameters;
case UpdateType.UpdateMintDistributionV1:
return OnChainUpdateType.UpdateMintDistributionV1;
case UpdateType.BlockEnergyLimit:
return OnChainUpdateType.UpdateBlockEnergyLimit;
default:
throw new Error(`An invalid update type was given: ${type}`);
}
Expand Down
2 changes: 2 additions & 0 deletions app/utils/protocolVersion.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
// eslint-disable-next-line import/prefer-default-export
export const hasDelegationProtocol = (pv: bigint) => pv >= 4n;

export const hasConsensusUpdateProtocol = (pv: bigint) => pv >= 6n;
94 changes: 94 additions & 0 deletions app/utils/transactionHandlers/BlockEnergyLimitHandler.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import {
isChainParametersV0,
isChainParametersV1,
NextUpdateSequenceNumbers,
} from '@concordium/web-sdk';
import BlockEnergyLimitView from '~/pages/multisig/updates/BlockEnergyLimit/BlockEnergyLimitView';
import UpdateBlockEnergyLimit, {
BlockEnergyLimitFields,
} from '~/pages/multisig/updates/BlockEnergyLimit/UpdateBlockEnergyLimit';
import ConcordiumLedgerClient from '../../features/ledger/ConcordiumLedgerClient';
import { getGovernanceLevel2Path } from '../../features/ledger/Path';
import { createUpdateMultiSignatureTransaction } from '../MultiSignatureTransactionHelper';
import { Authorizations, ChainParameters } from '../../node/NodeApiTypes';
import { UpdateInstructionHandler } from '../transactionTypes';
import {
UpdateInstruction,
isBlockEnergyLimit,
BlockEnergyLimit,
MultiSignatureTransaction,
UpdateType,
} from '../types';
import { serializeBlockEnergyLimit } from '../UpdateSerialization';
import UpdateHandlerBase from './UpdateHandlerBase';

const TYPE = 'Update block energy limit';

type TransactionType = UpdateInstruction<BlockEnergyLimit>;

export default class BlockEnergyLimitHandler
extends UpdateHandlerBase<TransactionType>
implements
UpdateInstructionHandler<TransactionType, ConcordiumLedgerClient> {
constructor() {
super(TYPE, isBlockEnergyLimit);
}

async createTransaction(
chainParameters: ChainParameters,
nextUpdateSequenceNumbers: NextUpdateSequenceNumbers,
{ blockEnergyLimit }: BlockEnergyLimitFields,
effectiveTime: bigint,
expiryTime: bigint
): Promise<Omit<MultiSignatureTransaction, 'id'> | undefined> {
if (!chainParameters || !nextUpdateSequenceNumbers) {
return undefined;
}

if (
isChainParametersV0(chainParameters) ||
isChainParametersV1(chainParameters)
) {
throw new Error('Update incompatible with chain protocol version');
}

const sequenceNumber = nextUpdateSequenceNumbers.blockEnergyLimit;
const { threshold } = chainParameters.level2Keys.electionDifficulty;

return createUpdateMultiSignatureTransaction(
{ blockEnergyLimit: BigInt(blockEnergyLimit) },
UpdateType.BlockEnergyLimit,
sequenceNumber,
threshold,
effectiveTime,
expiryTime
);
}

serializePayload(transaction: TransactionType) {
return serializeBlockEnergyLimit(transaction.payload);
}

signTransaction(
transaction: TransactionType,
ledger: ConcordiumLedgerClient
) {
const path: number[] = getGovernanceLevel2Path();
return ledger.signBlockEnergyLimit(
transaction,
this.serializePayload(transaction),
path
);
}

view(transaction: TransactionType) {
return <BlockEnergyLimitView blockEnergyLimit={transaction.payload} />;
}

getAuthorization(authorizations: Authorizations) {
return authorizations.electionDifficulty;
}

update = UpdateBlockEnergyLimit;
}
Loading

0 comments on commit e540055

Please sign in to comment.