-
Notifications
You must be signed in to change notification settings - Fork 45
Add validator pem and extend validator signer #657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f48c1a5
f69ca88
5b44df2
3a6839b
d80d3c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| -----BEGIN PRIVATE KEY for f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d----- | ||
| N2MxOWJmM2EwYzU3Y2RkMWZiMDhlNDYwN2NlYmFhMzY0N2Q2YjkyNjFiNDY5M2Y2 | ||
| MWU5NmU1NGIyMThkNDQyYQ== | ||
| -----END PRIVATE KEY for f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d----- | ||
| -----BEGIN PRIVATE KEY for 1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d----- | ||
| MzAzNGIxZDU4NjI4YTg0Mjk4NGRhMGM3MGRhMGI1YTI1MWViYjJhZWJmNTFhZmM1 | ||
| YjU4NmUyODM5YjVlNTI2Mw== | ||
| -----END PRIVATE KEY for 1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d----- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| import { assert } from "chai"; | ||
| import * as fs from "fs"; | ||
| import path from "path"; | ||
| import { getTestWalletsPath } from "../testutils"; | ||
| import { ValidatorPEM } from "./validatorPem"; | ||
|
|
||
| describe("test ValidatorPEMs", () => { | ||
| const walletsPath = path.join("src", "testdata", "testwallets"); | ||
| const pemPath = `${getTestWalletsPath()}/validatorKey00.pem`; | ||
| const savedPath = pemPath.replace(".pem", "-saved.pem"); | ||
|
|
||
| afterEach(() => { | ||
| if (fs.existsSync(savedPath)) { | ||
| fs.unlinkSync(savedPath); // cleanup | ||
| } | ||
| }); | ||
|
|
||
| it("should save pem from file", async function () { | ||
| const contentExpected = fs.readFileSync(pemPath, "utf-8").trim(); | ||
|
|
||
| // fromFile is async → await | ||
| const pem = await ValidatorPEM.fromFile(pemPath); | ||
| pem.save(savedPath); | ||
|
|
||
| const contentActual = fs.readFileSync(savedPath, "utf-8").trim(); | ||
| assert.deepEqual(contentActual, contentExpected); | ||
| }); | ||
|
|
||
| it("should create from text all", async function () { | ||
| let text = fs.readFileSync(path.join(walletsPath, "validatorKey00.pem"), "utf-8"); | ||
|
|
||
| let entries = await ValidatorPEM.fromTextAll(text); | ||
| let entry = entries[0]; | ||
|
|
||
| assert.lengthOf(entries, 1); | ||
| assert.equal( | ||
| entry.label, | ||
| "e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208", | ||
| ); | ||
| assert.equal(entry.secretKey.hex(), "7cff99bd671502db7d15bc8abc0c9a804fb925406fbdd50f1e4c17a4cd774247"); | ||
|
|
||
| text = fs.readFileSync(path.join(walletsPath, "validators.pem"), "utf-8"); | ||
| entries = await ValidatorPEM.fromTextAll(text); | ||
| entry = entries[0]; | ||
|
|
||
| assert.lengthOf(entries, 2); | ||
| assert.equal( | ||
| entry.label, | ||
| "f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d", | ||
| ); | ||
| assert.equal(entry.secretKey.hex(), "7c19bf3a0c57cdd1fb08e4607cebaa3647d6b9261b4693f61e96e54b218d442a"); | ||
|
|
||
| entry = entries[1]; | ||
| assert.equal( | ||
| entry.label, | ||
| "1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d", | ||
| ); | ||
| assert.equal(entry.secretKey.hex(), "3034b1d58628a842984da0c70da0b5a251ebb2aebf51afc5b586e2839b5e5263"); | ||
| }); | ||
|
|
||
| it("should convert to text", async function () { | ||
| let text = fs.readFileSync(path.join(walletsPath, "validatorKey00.pem"), "utf-8").trim(); | ||
| const entry = await ValidatorPEM.fromTextAll(text); | ||
| assert.deepEqual(entry[0].toText(), text); | ||
|
|
||
| text = fs.readFileSync(path.join(walletsPath, "multipleValidatorKeys.pem"), "utf-8").trim(); | ||
| const entries = await ValidatorPEM.fromTextAll(text); | ||
| const actualText = entries.map((entry) => entry.toText()).join("\n"); | ||
| assert.deepEqual(actualText, text); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import { readFileSync, writeFileSync } from "fs"; | ||
| import { resolve } from "path"; | ||
| import { PemEntry } from "../wallet/pemEntry"; | ||
| import { BLS, ValidatorSecretKey } from "../wallet/validatorKeys"; | ||
|
|
||
| export class ValidatorPEM { | ||
| readonly label: string; | ||
| readonly secretKey: ValidatorSecretKey; | ||
|
|
||
| constructor(label: string, secretKey: ValidatorSecretKey) { | ||
| this.label = label; | ||
| this.secretKey = secretKey; | ||
| } | ||
|
|
||
| static async fromFile(path: string, index = 0): Promise<ValidatorPEM> { | ||
| return (await this.fromFileAll(path))[index]; | ||
| } | ||
|
|
||
| static async fromFileAll(path: string): Promise<ValidatorPEM[]> { | ||
| const absPath = resolve(path); | ||
| const text = readFileSync(absPath, "utf-8"); | ||
| return await this.fromTextAll(text); | ||
| } | ||
|
|
||
| static async fromText(text: string, index = 0): Promise<ValidatorPEM> { | ||
| return (await ValidatorPEM.fromTextAll(text))[index]; | ||
| } | ||
|
|
||
| static async fromTextAll(text: string): Promise<ValidatorPEM[]> { | ||
| const entries = PemEntry.fromTextAll(text); | ||
| const resultItems: ValidatorPEM[] = []; | ||
|
|
||
| await BLS.initIfNecessary(); | ||
| for (const entry of entries) { | ||
| const secretKey = new ValidatorSecretKey(entry.message); | ||
| const item = new ValidatorPEM(entry.label, secretKey); | ||
| resultItems.push(item); | ||
| } | ||
|
|
||
| return resultItems; | ||
| } | ||
|
|
||
| save(path: string): void { | ||
| const absPath = resolve(path); | ||
| writeFileSync(absPath, this.toText(), "utf-8"); | ||
| } | ||
|
|
||
| toText(): string { | ||
| const message = this.secretKey.valueOf(); | ||
| return new PemEntry(this.label, message).toText(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,14 +1,26 @@ | ||||||||||||||||||||||||||||||
| import { ErrSignerCannotSign } from "../core/errors"; | ||||||||||||||||||||||||||||||
| import { BLS, ValidatorSecretKey } from "./validatorKeys"; | ||||||||||||||||||||||||||||||
| import { BLS, ValidatorPublicKey, ValidatorSecretKey } from "./validatorKeys"; | ||||||||||||||||||||||||||||||
| import { ValidatorPEM } from "./validatorPem"; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * Validator signer (BLS signer) | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| export class ValidatorSigner { | ||||||||||||||||||||||||||||||
| private readonly secretKey: ValidatorSecretKey; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| constructor(secretKey: ValidatorSecretKey) { | ||||||||||||||||||||||||||||||
| this.secretKey = secretKey; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * * @deprecated This method will be deprecated! Use the sign method directly. | ||||||||||||||||||||||||||||||
| * Signs a message. | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| async signUsingPem(pemText: string, pemIndex: number = 0, signable: Buffer | Uint8Array): Promise<Uint8Array> { | ||||||||||||||||||||||||||||||
| static async signUsingPem( | ||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tiny breaking change in theory, but can be in minor version - since, actually, it's a "design correction change" (it's a fix).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as discussed with @andreibancioiu, I think we can mark this as deprecated since we already have the sign method and this does not seem to bring significant benefits. |
||||||||||||||||||||||||||||||
| pemText: string, | ||||||||||||||||||||||||||||||
| pemIndex: number = 0, | ||||||||||||||||||||||||||||||
| signable: Buffer | Uint8Array, | ||||||||||||||||||||||||||||||
| ): Promise<Uint8Array> { | ||||||||||||||||||||||||||||||
| await BLS.initIfNecessary(); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||
|
|
@@ -18,4 +30,25 @@ export class ValidatorSigner { | |||||||||||||||||||||||||||||
| throw new ErrSignerCannotSign(err); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| static async fromPemFile(path: string, index = 0): Promise<ValidatorSigner> { | ||||||||||||||||||||||||||||||
| const secretKey = (await ValidatorPEM.fromFile(path, index)).secretKey; | ||||||||||||||||||||||||||||||
| return new ValidatorSigner(secretKey); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| sign(data: Uint8Array): Uint8Array { | ||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||
| return this.trySign(data); | ||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||
| throw new ErrSignerCannotSign(err as Error); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
Comment on lines
+39
to
+45
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| private trySign(data: Uint8Array): Uint8Array { | ||||||||||||||||||||||||||||||
|
Comment on lines
+41
to
+47
|
||||||||||||||||||||||||||||||
| return this.trySign(data); | |
| } catch (err) { | |
| throw new ErrSignerCannotSign(err as Error); | |
| } | |
| } | |
| private trySign(data: Uint8Array): Uint8Array { | |
| return this.signWithSecretKey(data); | |
| } catch (err) { | |
| throw new ErrSignerCannotSign(err as Error); | |
| } | |
| } | |
| private signWithSecretKey(data: Uint8Array): Uint8Array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's no test for
toText(), but maybe this one forsave()is sufficient?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added tests for toText, save is already tested via the other tests