@typeberry/lib 0.5.2-9afefa7 → 0.5.2-ff62cc9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/jam/safrole/bandersnatch-vrf.d.ts +2 -0
- package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-vrf.js +11 -0
- package/packages/jam/safrole/bandersnatch-wasm.d.ts +1 -0
- package/packages/jam/safrole/bandersnatch-wasm.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-wasm.js +3 -0
- package/packages/jam/safrole/safrole-seal.d.ts +1 -3
- package/packages/jam/safrole/safrole-seal.d.ts.map +1 -1
- package/packages/jam/safrole/safrole-seal.js +14 -25
package/package.json
CHANGED
|
@@ -8,12 +8,14 @@ import { type Opaque, Result } from "#@typeberry/utils";
|
|
|
8
8
|
import type { BandernsatchWasm } from "./bandersnatch-wasm.js";
|
|
9
9
|
declare const FUNCTIONS: {
|
|
10
10
|
verifySeal: typeof verifySeal;
|
|
11
|
+
verifyHeaderSeals: typeof verifyHeaderSeals;
|
|
11
12
|
verifyTickets: typeof verifyTickets;
|
|
12
13
|
getRingCommitment: typeof getRingCommitment;
|
|
13
14
|
generateSeal: typeof generateSeal;
|
|
14
15
|
getVrfOutputHash: typeof getVrfOutputHash;
|
|
15
16
|
};
|
|
16
17
|
export default FUNCTIONS;
|
|
18
|
+
declare function verifyHeaderSeals(bandersnatch: BandernsatchWasm, authorKey: BandersnatchKey, signature: BandersnatchVrfSignature, payload: BytesBlob, encodedUnsealedHeader: BytesBlob, entropySignature: BandersnatchVrfSignature, entropyPayloadPrefix: BytesBlob): Promise<Result<[EntropyHash, EntropyHash], null>>;
|
|
17
19
|
declare function verifySeal(bandersnatch: BandernsatchWasm, authorKey: BandersnatchKey, signature: BandersnatchVrfSignature, payload: BytesBlob, encodedUnsealedHeader: BytesBlob): Promise<Result<EntropyHash, null>>;
|
|
18
20
|
declare function getRingCommitment(bandersnatch: BandernsatchWasm, validators: BandersnatchKey[]): Promise<Result<BandersnatchRingRoot, null>>;
|
|
19
21
|
declare function verifyTickets(bandersnatch: BandernsatchWasm, numberOfValidators: number, epochRoot: BandersnatchRingRoot, tickets: readonly SignedTicket[], entropy: EntropyHash): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bandersnatch-vrf.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-vrf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAS,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAwB/D,QAAA,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"bandersnatch-vrf.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-vrf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAS,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAwB/D,QAAA,MAAM,SAAS;;;;;;;CAOd,CAAC;AAKF,eAAe,SAAS,CAAC;AAEzB,iBAAe,iBAAiB,CAC9B,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,wBAAwB,EACnC,OAAO,EAAE,SAAS,EAClB,qBAAqB,EAAE,SAAS,EAChC,gBAAgB,EAAE,wBAAwB,EAC1C,oBAAoB,EAAE,SAAS,GAC9B,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,CAkBnD;AAED,iBAAe,UAAU,CACvB,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,wBAAwB,EACnC,OAAO,EAAE,SAAS,EAClB,qBAAqB,EAAE,SAAS,GAC/B,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAapC;AAED,iBAAS,iBAAiB,CACxB,YAAY,EAAE,gBAAgB,EAC9B,UAAU,EAAE,eAAe,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC,CAmB7C;AAkBD,iBAAe,aAAa,CAC1B,YAAY,EAAE,gBAAgB,EAC9B,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,WAAW,CAAA;CAAE,EAAE,CAAC,CAqB3D;AAED,iBAAe,YAAY,CACzB,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,sBAAsB,EACjC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAQjD;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAElE,iBAAe,gBAAgB,CAC7B,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,sBAAsB,EACjC,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAQtC"}
|
|
@@ -20,6 +20,7 @@ var ResultValues;
|
|
|
20
20
|
const ringCommitmentCache = [];
|
|
21
21
|
const FUNCTIONS = {
|
|
22
22
|
verifySeal,
|
|
23
|
+
verifyHeaderSeals,
|
|
23
24
|
verifyTickets,
|
|
24
25
|
getRingCommitment,
|
|
25
26
|
generateSeal,
|
|
@@ -29,6 +30,16 @@ const FUNCTIONS = {
|
|
|
29
30
|
// Ideally we would just export functions and figure out how to mock
|
|
30
31
|
// properly in ESM.
|
|
31
32
|
export default FUNCTIONS;
|
|
33
|
+
async function verifyHeaderSeals(bandersnatch, authorKey, signature, payload, encodedUnsealedHeader, entropySignature, entropyPayloadPrefix) {
|
|
34
|
+
const sealResult = await bandersnatch.verifyHeaderSeals(authorKey.raw, signature.raw, payload.raw, encodedUnsealedHeader.raw, entropySignature.raw, entropyPayloadPrefix.raw);
|
|
35
|
+
if (sealResult[RESULT_INDEX] === ResultValues.Error) {
|
|
36
|
+
return Result.error(null, () => "Bandersnatch VRF seal verification failed");
|
|
37
|
+
}
|
|
38
|
+
return Result.ok([
|
|
39
|
+
Bytes.fromBlob(sealResult.subarray(1, 33), HASH_SIZE).asOpaque(),
|
|
40
|
+
Bytes.fromBlob(sealResult.subarray(33), HASH_SIZE).asOpaque(),
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
32
43
|
async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUnsealedHeader) {
|
|
33
44
|
const sealResult = await bandersnatch.verifySeal(authorKey.raw, signature.raw, payload.raw, encodedUnsealedHeader.raw);
|
|
34
45
|
if (sealResult[RESULT_INDEX] === ResultValues.Error) {
|
|
@@ -2,6 +2,7 @@ export declare class BandernsatchWasm {
|
|
|
2
2
|
private constructor();
|
|
3
3
|
static new(): Promise<BandernsatchWasm>;
|
|
4
4
|
verifySeal(authorKey: Uint8Array, signature: Uint8Array, payload: Uint8Array, auxData: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
5
|
+
verifyHeaderSeals(authorKey: Uint8Array, headerSeal: Uint8Array, headerSealPayload: Uint8Array, unsealedHeader: Uint8Array, entropySeal: Uint8Array, entropyPayloadPrefix: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
5
6
|
getRingCommitment(keys: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
6
7
|
batchVerifyTicket(ringSize: number, commitment: Uint8Array, ticketsData: Uint8Array, contextLength: number): Promise<Uint8Array<ArrayBufferLike>>;
|
|
7
8
|
generateSeal(authorKey: Uint8Array, input: Uint8Array, auxData: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bandersnatch-wasm.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-wasm.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,OAAO;WAEM,GAAG;IAKV,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAIjG,iBAAiB,CAAC,IAAI,EAAE,UAAU;IAIlC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM;IAI1G,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAI1E,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;CAGhE"}
|
|
1
|
+
{"version":3,"file":"bandersnatch-wasm.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-wasm.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,OAAO;WAEM,GAAG;IAKV,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAIjG,iBAAiB,CACrB,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,UAAU,EAC7B,cAAc,EAAE,UAAU,EAC1B,WAAW,EAAE,UAAU,EACvB,oBAAoB,EAAE,UAAU;IAY5B,iBAAiB,CAAC,IAAI,EAAE,UAAU;IAIlC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM;IAI1G,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAI1E,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;CAGhE"}
|
|
@@ -8,6 +8,9 @@ export class BandernsatchWasm {
|
|
|
8
8
|
async verifySeal(authorKey, signature, payload, auxData) {
|
|
9
9
|
return bandersnatchWasm.verify_seal(authorKey, signature, payload, auxData);
|
|
10
10
|
}
|
|
11
|
+
async verifyHeaderSeals(authorKey, headerSeal, headerSealPayload, unsealedHeader, entropySeal, entropyPayloadPrefix) {
|
|
12
|
+
return bandersnatchWasm.verify_header_seals(authorKey, headerSeal, headerSealPayload, unsealedHeader, entropySeal, entropyPayloadPrefix);
|
|
13
|
+
}
|
|
11
14
|
async getRingCommitment(keys) {
|
|
12
15
|
return bandersnatchWasm.ring_commitment(keys);
|
|
13
16
|
}
|
|
@@ -8,8 +8,7 @@ export declare enum SafroleSealError {
|
|
|
8
8
|
InvalidValidatorIndex = 0,
|
|
9
9
|
InvalidValidator = 1,
|
|
10
10
|
InvalidTicket = 2,
|
|
11
|
-
IncorrectSeal = 3
|
|
12
|
-
IncorrectEntropySource = 4
|
|
11
|
+
IncorrectSeal = 3
|
|
13
12
|
}
|
|
14
13
|
export type SafroleSealState = Pick<State, "currentValidatorData" | "sealingKeySeries"> & {
|
|
15
14
|
currentEntropy: EntropyHash;
|
|
@@ -22,7 +21,6 @@ export declare class SafroleSeal {
|
|
|
22
21
|
* hence the state is passed as an argument for more control.
|
|
23
22
|
*/
|
|
24
23
|
verifyHeaderSeal(headerView: HeaderView, state: SafroleSealState): Promise<Result<EntropyHash, SafroleSealError>>;
|
|
25
|
-
private verifySeal;
|
|
26
24
|
/** Regular (non-fallback) mode of Safrole. */
|
|
27
25
|
verifySealWithTicket(tickets: PerEpochBlock<Ticket>, timeSlot: TimeSlot, entropy: EntropyHash, validatorData: ValidatorData, headerView: HeaderView): Promise<Result<EntropyHash, SafroleSealError>>;
|
|
28
26
|
/** Fallback mode of Safrole. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safrole-seal.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/safrole-seal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,oBAAY,gBAAgB;IAC1B,qBAAqB,IAAI;IACzB,gBAAgB,IAAI;IACpB,aAAa,IAAI;IACjB,aAAa,IAAI;
|
|
1
|
+
{"version":3,"file":"safrole-seal.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/safrole-seal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,oBAAY,gBAAgB;IAC1B,qBAAqB,IAAI;IACzB,gBAAgB,IAAI;IACpB,aAAa,IAAI;IACjB,aAAa,IAAI;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,EAAE,sBAAsB,GAAG,kBAAkB,CAAC,GAAG;IACxF,cAAc,EAAE,WAAW,CAAC;CAC7B,CAAC;AAIF,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,GAAE,OAAO,CAAC,gBAAgB,CAA0B;IAC7F;;;OAGG;IACG,gBAAgB,CACpB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAuBjD,8CAA8C;IACxC,oBAAoB,CACxB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,EACpB,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAmCjD,gCAAgC;IAC1B,kBAAkB,CACtB,IAAI,EAAE,aAAa,CAAC,eAAe,CAAC,EACpC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;CA8BlD"}
|
|
@@ -12,7 +12,6 @@ export var SafroleSealError;
|
|
|
12
12
|
SafroleSealError[SafroleSealError["InvalidValidator"] = 1] = "InvalidValidator";
|
|
13
13
|
SafroleSealError[SafroleSealError["InvalidTicket"] = 2] = "InvalidTicket";
|
|
14
14
|
SafroleSealError[SafroleSealError["IncorrectSeal"] = 3] = "IncorrectSeal";
|
|
15
|
-
SafroleSealError[SafroleSealError["IncorrectEntropySource"] = 4] = "IncorrectEntropySource";
|
|
16
15
|
})(SafroleSealError || (SafroleSealError = {}));
|
|
17
16
|
const BANDERSNATCH_ZERO_KEY = Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque();
|
|
18
17
|
export class SafroleSeal {
|
|
@@ -25,21 +24,6 @@ export class SafroleSeal {
|
|
|
25
24
|
* hence the state is passed as an argument for more control.
|
|
26
25
|
*/
|
|
27
26
|
async verifyHeaderSeal(headerView, state) {
|
|
28
|
-
const sealResult = await this.verifySeal(headerView, state);
|
|
29
|
-
if (sealResult.isError) {
|
|
30
|
-
return sealResult;
|
|
31
|
-
}
|
|
32
|
-
// verify entropySource
|
|
33
|
-
const payload = BytesBlob.blobFromParts(JAM_ENTROPY, sealResult.ok.raw);
|
|
34
|
-
const blockAuthorIndex = headerView.bandersnatchBlockAuthorIndex.materialize();
|
|
35
|
-
const blockAuthorKey = state.currentValidatorData.at(blockAuthorIndex)?.bandersnatch;
|
|
36
|
-
const entropySourceResult = await bandersnatchVrf.verifySeal(await this.bandersnatch, blockAuthorKey ?? BANDERSNATCH_ZERO_KEY, headerView.entropySource.materialize(), payload, BytesBlob.blobFromNumbers([]));
|
|
37
|
-
if (entropySourceResult.isError) {
|
|
38
|
-
return Result.error(SafroleSealError.IncorrectEntropySource, () => "Safrole: incorrect entropy source in header seal");
|
|
39
|
-
}
|
|
40
|
-
return Result.ok(entropySourceResult.ok);
|
|
41
|
-
}
|
|
42
|
-
async verifySeal(headerView, state) {
|
|
43
27
|
// we use transitioned keys already
|
|
44
28
|
const validatorIndex = headerView.bandersnatchBlockAuthorIndex.materialize();
|
|
45
29
|
const authorKeys = state.currentValidatorData.at(validatorIndex);
|
|
@@ -58,17 +42,21 @@ export class SafroleSeal {
|
|
|
58
42
|
async verifySealWithTicket(tickets, timeSlot, entropy, validatorData, headerView) {
|
|
59
43
|
const index = timeSlot % tickets.length;
|
|
60
44
|
const ticket = tickets.at(index);
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
if (ticket === undefined) {
|
|
46
|
+
return Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: missing ticket");
|
|
47
|
+
}
|
|
48
|
+
const payload = BytesBlob.blobFromParts(JAM_TICKET_SEAL, entropy.raw, new Uint8Array([ticket.attempt]));
|
|
49
|
+
// verify seal and entropy source correctness
|
|
63
50
|
const authorKey = validatorData.bandersnatch;
|
|
64
|
-
const result = await bandersnatchVrf.
|
|
51
|
+
const result = await bandersnatchVrf.verifyHeaderSeals(await this.bandersnatch, authorKey ?? BANDERSNATCH_ZERO_KEY, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView), headerView.entropySource.materialize(), BytesBlob.blobFrom(JAM_ENTROPY));
|
|
65
52
|
if (result.isError) {
|
|
66
53
|
return Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with ticket");
|
|
67
54
|
}
|
|
68
|
-
|
|
69
|
-
|
|
55
|
+
const [sealOutput, entropyOutput] = result.ok;
|
|
56
|
+
if (!ticket.id.isEqualTo(sealOutput)) {
|
|
57
|
+
return Result.error(SafroleSealError.InvalidTicket, () => `Safrole: invalid ticket, expected ${ticket.id} got ${sealOutput}`);
|
|
70
58
|
}
|
|
71
|
-
return Result.ok(
|
|
59
|
+
return Result.ok(entropyOutput);
|
|
72
60
|
}
|
|
73
61
|
/** Fallback mode of Safrole. */
|
|
74
62
|
async verifySealWithKeys(keys, timeSlot, entropy, authorKey, headerView) {
|
|
@@ -78,12 +66,13 @@ export class SafroleSeal {
|
|
|
78
66
|
if (sealingKey === undefined || !sealingKey.isEqualTo(authorBandersnatchKey)) {
|
|
79
67
|
return Result.error(SafroleSealError.InvalidValidator, () => `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
|
|
80
68
|
}
|
|
81
|
-
// verify seal correctness
|
|
69
|
+
// verify seal and entropy source correctness
|
|
82
70
|
const payload = BytesBlob.blobFromParts(JAM_FALLBACK_SEAL, entropy.raw);
|
|
83
|
-
const result = await bandersnatchVrf.
|
|
71
|
+
const result = await bandersnatchVrf.verifyHeaderSeals(await this.bandersnatch, authorBandersnatchKey, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView), headerView.entropySource.materialize(), BytesBlob.blobFrom(JAM_ENTROPY));
|
|
84
72
|
if (result.isError) {
|
|
85
73
|
return Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with keys");
|
|
86
74
|
}
|
|
87
|
-
|
|
75
|
+
const [_, entropyOutput] = result.ok;
|
|
76
|
+
return Result.ok(entropyOutput);
|
|
88
77
|
}
|
|
89
78
|
}
|