Skip to content

Commit

Permalink
implement better privkey validation with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
zoeyTM committed Nov 4, 2021
1 parent 771fef4 commit f1912f5
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 46 deletions.
128 changes: 113 additions & 15 deletions packages/hardhat-core/src/internal/core/config/config-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import * as t from "io-ts";
import { Context, getFunctionName, ValidationError } from "io-ts/lib";
import { Reporter } from "io-ts/lib/Reporter";

import {
HardhatConfig,
HardhatNetworkAccountsUserConfig,
HardhatNetworkAccountUserConfig,
} from "../../../types";
import {
HARDHAT_NETWORK_NAME,
HARDHAT_NETWORK_SUPPORTED_HARDFORKS,
Expand Down Expand Up @@ -53,6 +58,58 @@ function getErrorMessage(path: string, value: any, expectedType: string) {
)} for ${path} - Expected a value of type ${expectedType}.`;
}

function getPrivateKeyError(account: any, network: string, message: string) {
return `Invalid account: ${account} for network: ${network} - ${message}`;
}

function validatePrivateKey(
privateKey: any,
network: string,
errors: string[]
) {
if (typeof privateKey !== "string") {
errors.push(
getPrivateKeyError(
privateKey,
network,
`Expected string, received ${typeof privateKey}`
)
);
} else {
// private key validation
const pkWithPrefix = /^0x/.test(privateKey)
? privateKey
: `0x${privateKey}`;

// 32 bytes = 64 characters + 2 char prefix = 66
if (pkWithPrefix.length < 66) {
errors.push(
getPrivateKeyError(
privateKey,
network,
"privateKey too short, expected 32 bytes"
)
);
} else if (pkWithPrefix.length > 66) {
errors.push(
getPrivateKeyError(
privateKey,
network,
"privateKey too long, expected 32 bytes"
)
);
} else if (hexString.decode(pkWithPrefix).isLeft()) {
errors.push(
getPrivateKeyError(
privateKey,
network,
"invalid hex character(s) found in string"
)
);
}
}
}

export function failure(es: ValidationError[]): string[] {
return es.map(getMessage);
}
Expand Down Expand Up @@ -224,7 +281,7 @@ export function validateConfig(config: any) {
}

export function getValidationErrors(config: any): string[] {
const errors = [];
const errors: string[] = [];

// These can't be validated with io-ts
if (config !== undefined && typeof config.networks === "object") {
Expand All @@ -237,8 +294,7 @@ export function getValidationErrors(config: any): string[] {
}

// Validating the accounts with io-ts leads to very confusing errors messages
const configExceptAccounts = { ...hardhatNetwork };
delete configExceptAccounts.accounts;
const { accounts, ...configExceptAccounts } = hardhatNetwork;

const netConfigResult = HardhatNetworkConfig.decode(configExceptAccounts);
if (netConfigResult.isLeft()) {
Expand All @@ -251,31 +307,37 @@ export function getValidationErrors(config: any): string[] {
);
}

if (Array.isArray(hardhatNetwork.accounts)) {
for (const account of hardhatNetwork.accounts) {
if (typeof account.privateKey !== "string") {
// manual validation of accounts
if (Array.isArray(accounts)) {
for (const account of accounts) {
if (typeof account !== "object") {
errors.push(
getErrorMessage(
`HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].privateKey`,
account.privateKey,
"string"
getPrivateKeyError(
account,
HARDHAT_NETWORK_NAME,
`Expected object, received ${typeof account}`
)
);
continue;
}

if (typeof account.balance !== "string") {
const { privateKey, balance } = account;

validatePrivateKey(privateKey, HARDHAT_NETWORK_NAME, errors);

if (typeof balance !== "string") {
errors.push(
getErrorMessage(
`HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].balance`,
account.balance,
balance,
"string"
)
);
} else if (decimalString.decode(account.balance).isLeft()) {
} else if (decimalString.decode(balance).isLeft()) {
errors.push(
getErrorMessage(
`HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].balance`,
account.balance,
balance,
"decimal(wei)"
)
);
Expand Down Expand Up @@ -340,7 +402,9 @@ export function getValidationErrors(config: any): string[] {
}
}

const netConfigResult = HttpNetworkConfig.decode(netConfig);
const { accounts, ...configExceptAccounts } = netConfig;

const netConfigResult = HttpNetworkConfig.decode(configExceptAccounts);
if (netConfigResult.isLeft()) {
errors.push(
getErrorMessage(
Expand All @@ -350,6 +414,40 @@ export function getValidationErrors(config: any): string[] {
)
);
}

// manual validation of accounts
if (typeof accounts === "string" && accounts !== "remote") {
errors.push(
getPrivateKeyError(
accounts,
networkName,
`Expected "remote", received ${accounts}`
)
);
} else if (Array.isArray(accounts)) {
accounts.forEach((privateKey) =>
validatePrivateKey(privateKey, networkName, errors)
);
} else if (typeof accounts === "object") {
const hdConfigResult = HDAccountsConfig.decode(accounts);
if (hdConfigResult.isLeft()) {
errors.push(
getErrorMessage(
`HardhatConfig.networks.${networkName}`,
accounts,
"HttpNetworkHDAccountsConfig"
)
);
}
} else if (accounts !== undefined) {
errors.push(
getErrorMessage(
`HardhatConfig.networks.${networkName}.accounts`,
accounts,
'"remote" | string[] | HttpNetworkHDAccountsConfig | undefined'
)
);
}
}
}

Expand Down
13 changes: 0 additions & 13 deletions packages/hardhat-core/src/internal/core/errors-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,19 +201,6 @@ Please run: npm install --save-dev typescript`,
Please run this and try again: \`npm install --save-dev typescript\``,
shouldBeReported: false,
},
INVALID_PRIVATE_KEY: {
number: 15,
message: `There's one or more invalid private keys in your config file:
%keys%
To learn more about Hardhat's configuration, please go to https://hardhat.org/config/`,
title: "Invalid private key",
description: `You have one or more errors in your config file.
Check the error message for details, or go to the [documentation](https://hardhat.org/config/) to learn more.`,
shouldBeReported: false,
},
},
NETWORK: {
CONFIG_NOT_FOUND: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,18 +257,6 @@ describe("Config validation", function () {
});
});

/**
* networkConfig.accounts
if string => must === "remote"
if object => ~
if array =>
if network === hardhat =>
each => isValidHexString(each.privateKey)
&& isValidBalance?(each.balance)
else (network === http) =>
each => isValidHexString(each)
*/

/**
* This describe block will encompass all private key tests
* for both Hardhat and HTTP networks
Expand Down Expand Up @@ -316,7 +304,7 @@ describe("Config validation", function () {
},
},
}),
ERRORS.GENERAL.INVALID_PRIVATE_KEY
ERRORS.GENERAL.INVALID_CONFIG
);
});

Expand All @@ -331,7 +319,7 @@ describe("Config validation", function () {
},
},
}),
ERRORS.GENERAL.INVALID_PRIVATE_KEY
ERRORS.GENERAL.INVALID_CONFIG
);

expectHardhatError(
Expand All @@ -346,7 +334,24 @@ describe("Config validation", function () {
},
},
}),
ERRORS.GENERAL.INVALID_PRIVATE_KEY
ERRORS.GENERAL.INVALID_CONFIG
);
});

it("Should not allow invalid private keys", function () {
expectHardhatError(
() =>
validateConfig({
networks: {
custom: {
url: "http://localhost",
accounts: [
"0xgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg",
],
},
},
}),
ERRORS.GENERAL.INVALID_CONFIG
);
});
});
Expand Down Expand Up @@ -409,7 +414,7 @@ describe("Config validation", function () {
},
},
}),
ERRORS.GENERAL.INVALID_PRIVATE_KEY
ERRORS.GENERAL.INVALID_CONFIG
);
});

Expand All @@ -428,7 +433,7 @@ describe("Config validation", function () {
},
},
}),
ERRORS.GENERAL.INVALID_PRIVATE_KEY
ERRORS.GENERAL.INVALID_CONFIG
);

expectHardhatError(
Expand All @@ -446,7 +451,27 @@ describe("Config validation", function () {
},
},
}),
ERRORS.GENERAL.INVALID_PRIVATE_KEY
ERRORS.GENERAL.INVALID_CONFIG
);
});

it("Should not allow invalid private keys", function () {
expectHardhatError(
() =>
validateConfig({
networks: {
[HARDHAT_NETWORK_NAME]: {
accounts: [
{
balance: "123",
privateKey:
"0xgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg",
},
],
},
},
}),
ERRORS.GENERAL.INVALID_CONFIG
);
});
});
Expand Down

0 comments on commit f1912f5

Please sign in to comment.