Skip to content

Commit 1912f17

Browse files
authored
fix: added additional validation, fixed validation for reshare (#1247)
* fix: added additional validation, fixed validation for reshare * fix: fixed cmd, validation improve * fix: small fix
1 parent 5cdbece commit 1912f17

File tree

10 files changed

+61
-58
lines changed

10 files changed

+61
-58
lines changed

src/app/routes/create-cluster/distribute-offline.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,15 @@ export const DistributeOffline: FC = () => {
4242
const health = useOperatorsDKGHealth(operators.data ?? [], {
4343
enabled: isNew,
4444
});
45-
46-
const hasUnhealthyOperators =
47-
isNew &&
48-
health.data?.some(
49-
({ isHealthy, isMismatchId }) => !isHealthy || isMismatchId,
50-
);
45+
const hasOutdatedOperator = health.data?.some(({ isOutdated }) => isOutdated);
46+
const isAllOperatorsAreOutdated =
47+
health.data?.every(({ isOutdated }) => isOutdated) || false;
48+
const hasUnhealthyOperators = health.data?.some(
49+
({ isHealthy, isMismatchId }) => !isHealthy || isMismatchId,
50+
);
51+
const hasIssuedOperator = hasOutdatedOperator
52+
? hasUnhealthyOperators || !isAllOperatorsAreOutdated
53+
: hasUnhealthyOperators;
5154

5255
return (
5356
<Container size="lg" variant="vertical" className="py-6">
@@ -73,7 +76,7 @@ export const DistributeOffline: FC = () => {
7376
isLoading={health.isLoading}
7477
/>
7578
</div>
76-
{selectedOption === "new" && hasUnhealthyOperators && (
79+
{isNew && hasIssuedOperator && (
7780
<>
7881
<UnhealthyOperatorsList
7982
operators={operators.data ?? []}
@@ -91,11 +94,12 @@ export const DistributeOffline: FC = () => {
9194
)}
9295
</>
9396
)}
94-
{selectedOption === "new" &&
95-
!hasUnhealthyOperators &&
96-
health.isSuccess && (
97-
<DockerInstructions operators={operators.data ?? []} />
98-
)}
97+
{selectedOption === "new" && !hasIssuedOperator && health.isSuccess && (
98+
<DockerInstructions
99+
isOutdatedOperators={isAllOperatorsAreOutdated}
100+
operators={operators.data ?? []}
101+
/>
102+
)}
99103
{selectedOption === "existing" && (
100104
<SSVKeysInstructions operators={operators.data ?? []} />
101105
)}

src/app/routes/protected-cluster-route.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ export const ProtectedClusterRoute: FC<ComponentPropsWithoutRef<"div">> = ({
1818
const location = useLocation();
1919
const currentPath = location.pathname;
2020
const [enabled] = useLocalStorage("reshareFlowEnabled", false);
21-
2221
if (isUndefined(clusterHash)) return <Navigate to="/clusters" />;
2322
if (cluster.isLoading) return <Loading />;
2423
if (cluster.isError || !cluster.data) return <Navigate to="/clusters" />;
25-
if (isFrom("/clusters/:clusterHash")) resetState();
24+
if (isFrom("/clusters/:clusterHash") && currentPath.includes("reshare"))
25+
resetState();
2626
if (!enabled && currentPath.includes("reshare")) {
2727
return <Navigate to={`/clusters/${clusterHash}`} />;
2828
}

src/app/routes/reshare-dkg/ceremony-section.tsx

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@ import { LuCheck, LuCopy } from "react-icons/lu";
66
import CeremonySummary from "@/app/routes/create-cluster/ceremony-summary.tsx";
77
import { useQuery } from "@tanstack/react-query";
88
import { stringifyBigints } from "@/lib/utils/bigint.ts";
9-
import {
10-
DKG_VERSIONS,
11-
generateSSVKeysDockerCMD,
12-
} from "@/lib/utils/keyshares.ts";
9+
import { generateSSVKeysDockerCMD } from "@/lib/utils/keyshares.ts";
1310
import type { Address } from "viem";
1411
import { useAccount } from "@/hooks/account/use-account.ts";
1512
import { useSSVAccount } from "@/hooks/use-ssv-account.ts";
1613
import { useBulkActionContext } from "@/guard/bulk-action-guard.tsx";
1714
import { useReshareDkg } from "@/hooks/use-reshare-dkg.ts";
1815
import { useCopyToClipboard } from "react-use";
1916
import { CompletedBadge } from "@/components/ui/completed-badge.tsx";
20-
import { useOperatorsDKGHealth } from "@/hooks/operator/use-operator-dkg-health.ts";
2117

2218
const VALIDATOR_COUNT_THRESHOLD = 20;
2319

@@ -45,16 +41,6 @@ const CeremonySection = ({
4541
const context = useBulkActionContext();
4642
const reshareContext = useReshareDkg();
4743
const [copyState, copy] = useCopyToClipboard();
48-
const health = useOperatorsDKGHealth(
49-
context.dkgReshareState.newOperators.length
50-
? context.dkgReshareState.newOperators
51-
: context.dkgReshareState.operators,
52-
);
53-
const version = health.data?.every(
54-
({ isHealthy, isOutdated }) => isHealthy && isOutdated,
55-
)
56-
? DKG_VERSIONS.OLD
57-
: DKG_VERSIONS.NEW;
5844

5945
const cmd = useQuery({
6046
queryKey: stringifyBigints([
@@ -85,7 +71,6 @@ const CeremonySection = ({
8571
signatures,
8672
os: context.dkgReshareState.selectedOs,
8773
proofsString,
88-
version,
8974
}),
9075
);
9176
},

src/app/routes/reshare-dkg/reshare.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ const Reshare = () => {
2323
? health.data?.every(
2424
({ isHealthy, isEthClientConnected, isOutdated, isMismatchId }) =>
2525
isHealthy && isEthClientConnected && !isOutdated && !isMismatchId,
26-
) ||
27-
health.data?.every(
28-
({ isHealthy, isOutdated, isMismatchId }) =>
29-
isHealthy && isOutdated && !isMismatchId,
3026
)
3127
: health.data?.every(
32-
({ isHealthy, isMismatchId }) => isHealthy && !isMismatchId,
28+
({ isHealthy, isMismatchId, isOutdated }) =>
29+
isHealthy && !isMismatchId && !isOutdated,
3330
);
3431

3532
if (health.isLoading) {

src/components/offline-generation/docker-instructions.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type FC } from "react";
22
import { Button } from "@/components/ui/button";
33
import { Text } from "@/components/ui/text";
44
import { Spinner } from "@/components/ui/spinner";
5-
import { generateSSVKeysDockerCMD } from "@/lib/utils/keyshares";
5+
import { DKG_VERSIONS, generateSSVKeysDockerCMD } from "@/lib/utils/keyshares";
66
import type { Operator } from "@/types/api";
77
import { LuCheck, LuCopy } from "react-icons/lu";
88
import { useRegisterValidatorContext } from "@/guard/register-validator-guard";
@@ -29,6 +29,7 @@ import { useNavigate } from "react-router";
2929

3030
interface DockerInstructionsProps {
3131
operators: Operator[];
32+
isOutdatedOperators: boolean;
3233
}
3334

3435
const schema = z.object({
@@ -45,6 +46,7 @@ const schema = z.object({
4546

4647
export const DockerInstructions: FC<DockerInstructionsProps> = ({
4748
operators,
49+
isOutdatedOperators,
4850
}) => {
4951
const navigate = useNavigate();
5052

@@ -71,14 +73,15 @@ export const DockerInstructions: FC<DockerInstructionsProps> = ({
7173
isAddress(withdrawalAddress) &&
7274
validators > 0 &&
7375
hasConfirmed;
74-
76+
const cliVersion = isOutdatedOperators ? DKG_VERSIONS.OLD : DKG_VERSIONS.NEW;
7577
const cmd = useQuery({
7678
queryKey: stringifyBigints([
7779
"docker-cmd",
7880
ssvAccount.data,
7981
account.address,
8082
validators,
8183
withdrawalAddress,
84+
cliVersion,
8285
dkgCeremonyState.selectedOs,
8386
account.chainId,
8487
]),
@@ -90,6 +93,7 @@ export const DockerInstructions: FC<DockerInstructionsProps> = ({
9093
account: account.address!,
9194
withdrawalAddress: withdrawalAddress as Address,
9295
chainId: account.chainId,
96+
version: cliVersion,
9397
validatorsCount: validators,
9498
os: dkgCeremonyState.selectedOs,
9599
}),

src/components/offline-generation/unhealthy-operators-list.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ const getBadgeInfo = (
2525
text: "ID/IP Mismatch",
2626
};
2727
}
28+
if (healthData.isOutdated) {
29+
return {
30+
variant: "warning" as BadgeVariants["variant"],
31+
text: "Dkg Outdated",
32+
};
33+
}
2834
if (isReshareFlow) {
29-
if (healthData.isOutdated) {
30-
return {
31-
variant: "warning" as BadgeVariants["variant"],
32-
text: "Dkg Outdated",
33-
};
34-
}
3535
if (!healthData.isEthClientConnected) {
3636
return {
3737
variant: "error" as BadgeVariants["variant"],

src/hooks/operator/use-reshare-signature-payload.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,25 @@ export const useReshareSignaturePayload = ({
2525
const nonce = await getOwnerNonce(ownerAddress);
2626
const chainId = FORKS[getChainId(config)];
2727
const payload = (proofsQuery.data?.validators || []).map(
28-
({ publicKey, proofs }) => ({
29-
messageData: {
28+
({ publicKey, proofs }, index: number) => {
29+
const messageData: MessageData = {
3030
publicKey,
3131
oldOperators: context.dkgReshareState.operators,
3232
chainId,
3333
withdrawalCredentials: withdrawAddress,
3434
ownerAddress,
35-
nonce,
35+
nonce: nonce + index,
3636
amount: DEFAULT_AMOUNT,
37-
} as MessageData,
38-
proofs: proofs,
39-
}),
37+
};
38+
if (context.dkgReshareState.newOperators.length) {
39+
messageData.newOperators = context.dkgReshareState.newOperators;
40+
}
41+
return {
42+
messageData,
43+
proofs,
44+
};
45+
},
4046
);
41-
4247
return sign.signMessageAsync({
4348
message: getSignaturePayload(payload),
4449
});

src/hooks/use-validate-proofs.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,14 @@ export const useValidateProofs = (files: File[]) => {
122122
);
123123
}
124124
state.dkgReshareState.selectedValidatorsCount = validators.length;
125-
125+
if (
126+
json.every((proof: Proof | Proof[]) => Array.isArray(proof)) &&
127+
json.length > validators.length
128+
) {
129+
throw new Error(
130+
"proofs.json must only contain validators that are registered.",
131+
);
132+
}
126133
return {
127134
proofs: json,
128135
validators,

src/lib/utils/dkg.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ const serializedResignMessage = (message: {
118118
const serializedReshareMessage = (message: {
119119
messageData: MessageData;
120120
proofs: ProofType[];
121-
}) =>
122-
ReshareMessageType.serialize({
121+
}) => {
122+
return ReshareMessageType.serialize({
123123
Reshare: {
124124
ValidatorPubKey: parseHexToBuffer(message.messageData.publicKey),
125125
OldOperators: message.messageData.oldOperators.map(
@@ -134,8 +134,8 @@ const serializedReshareMessage = (message: {
134134
PubKey: Buffer.from(op.public_key),
135135
}),
136136
),
137-
OldT: message.messageData.oldOperators.length % 3,
138-
NewT: (message.messageData.newOperators || []).length % 3,
137+
OldT: Number(message.messageData.oldOperators.length % 3),
138+
NewT: Number((message.messageData.newOperators || []).length % 3),
139139
Fork: parseHexToBuffer(message.messageData.chainId).slice(0, 4),
140140
WithdrawalCredentials: parseHexToBuffer(
141141
message.messageData.withdrawalCredentials,
@@ -154,6 +154,7 @@ const serializedReshareMessage = (message: {
154154
Signature: parseHexToBuffer(proof.signature),
155155
})),
156156
});
157+
};
157158

158159
export const getSignaturePayload = (
159160
data: {

src/lib/utils/keyshares.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export const generateSSVKeysDockerCMD = ({
132132
chainId = getChainId(config),
133133
validatorsCount = 1,
134134
os = getOSName(),
135-
version = DKG_VERSIONS.OLD,
135+
version = DKG_VERSIONS.NEW,
136136
newOperators,
137137
signatures,
138138
proofsString,
@@ -166,7 +166,7 @@ export const generateSSVKeysDockerCMD = ({
166166
.map((op) => op.id)
167167
.join(",")}`
168168
: ""
169-
} --withdrawAddress ${withdrawalAddress} --owner ${account} --nonce ${nonce} --network ${chainName} ${proofsString ? `--proofsString ${proofsString}` : "--proofsFilePath /data/proofs.json"} --operatorsInfo ${newOperators ? getOperatorsData([...operators, ...newOperators]) : getOperatorsData(operators)} --signatures ${signatures} --outputPath /output --logLevel info --logFormat json --logLevelFormat capitalColor --logFilePath /data/debug.log --tlsInsecure`;
169+
} --withdrawAddress ${withdrawalAddress} --owner ${account} --nonce ${nonce} --network ${chainName} ${proofsString ? `--proofsString '${proofsString}'` : "--proofsFilePath ./data/proofs.json"} --operatorsInfo ${newOperators ? getOperatorsData([...operators, ...newOperators]) : getOperatorsData(operators)} --signatures ${signatures} --outputPath ./output --logLevel info --logFormat json --logLevelFormat capitalColor --logFilePath ./data/debug.log --tlsInsecure`;
170170
}
171-
return `docker pull bloxstaking/ssv-dkg:v2.1.0 && docker run --rm -v ${dynamicFullPath}:/data -it "bloxstaking/ssv-dkg:v${version}" init --owner ${account} --nonce ${nonce} --withdrawAddress ${withdrawalAddress} --operatorIDs ${operatorIds} --operatorsInfo ${getOperatorsData(sortedOperators)} --network ${chainName} --validators ${validatorsCount} --logFilePath /data/debug.log --outputPath /data`;
171+
return `docker pull bloxstaking/ssv-dkg:v${version} && docker run --rm -v ${dynamicFullPath}:/data -it "bloxstaking/ssv-dkg:v${version}" init --owner ${account} --nonce ${nonce} --withdrawAddress ${withdrawalAddress} --operatorIDs ${operatorIds} --operatorsInfo ${getOperatorsData(sortedOperators)} --network ${chainName} --validators ${validatorsCount} ${version === DKG_VERSIONS.OLD ? "--logFilePath /data/debug.log --outputPath /data" : "--logFilePath ./data/debug.log --outputPath ./data --tlsInsecure"}}`;
172172
};

0 commit comments

Comments
 (0)