From be13d953099f2df76f88c9c886e373f675f90932 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 20 Sep 2023 10:56:06 -0700 Subject: [PATCH 1/8] wip --- packages/agent/src/agent/http/http.test.ts | 10 ++++++++++ packages/agent/src/agent/http/index.ts | 14 ++++++++++++++ packages/agent/src/canisterStatus/index.ts | 10 ++++++++-- packages/principal/src/index.ts | 4 ++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/agent/src/agent/http/http.test.ts b/packages/agent/src/agent/http/http.test.ts index 1df6284c7..4480a16e2 100644 --- a/packages/agent/src/agent/http/http.test.ts +++ b/packages/agent/src/agent/http/http.test.ts @@ -811,3 +811,13 @@ describe('default host', () => { } }); }); + +describe('fetchSubnetKeys', () => { + it('should fetch subnet keys for a given canister', async () => { + jest.useFakeTimers(); + const abbbb = (await import('isomorphic-fetch')).default; + const agent = new HttpAgent({ fetch: abbbb, host: 'https://icp-api.io' }); + await agent.fetchRootKey(); + const subnetKeys = await agent.fetchSubnetKeys('erxue-5aaaa-aaaab-qaagq-cai'); //? + }); +}); diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index e4b5d1e30..e95e6b711 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -27,6 +27,7 @@ import { SubmitRequestType, } from './types'; import { AgentHTTPResponseError } from './errors'; +import { request } from '../../canisterStatus'; export * from './transforms'; export { Nonce, makeNonce } from './types'; @@ -575,6 +576,19 @@ export class HttpAgent implements Agent { this._identity = Promise.resolve(identity); } + public async fetchSubnetKeys(canisterId: Principal | string): Promise { + const effectiveCanisterId: Principal = Principal.from(canisterId); + const response = await request({ + canisterId: effectiveCanisterId, + paths: ['subnet'], + agent: this, + }); + const subnetResponse = response.get('subnet'); + response.get('time'); //? + console.log(subnetResponse); + return subnetResponse; + } + protected _transform(request: HttpAgentRequest): Promise { let p = Promise.resolve(request); diff --git a/packages/agent/src/canisterStatus/index.ts b/packages/agent/src/canisterStatus/index.ts index 6ff87eab9..ec5d2eec5 100644 --- a/packages/agent/src/canisterStatus/index.ts +++ b/packages/agent/src/canisterStatus/index.ts @@ -1,5 +1,4 @@ /** @module CanisterStatus */ - import { Principal } from '@dfinity/principal'; import { AgentError } from '../errors'; import { HttpAgent } from '../agent/http'; @@ -97,7 +96,8 @@ export const request = async (options: { rootKey: agent.rootKey, canisterId: canisterId, }); - + let decoded = Cbor.decode(new Uint8Array(response.certificate)); + decoded?.delegation; //? const data = cert.lookup(encodePath(uniquePaths[index], canisterId)); if (!data) { // Typically, the cert lookup will throw @@ -108,6 +108,7 @@ export const request = async (options: { status.set(path.key, null); } } else { + path; switch (path) { case 'time': { status.set(path, decodeTime(data)); @@ -121,6 +122,10 @@ export const request = async (options: { status.set(path, decodeHex(data)); break; } + case 'subnet': { + status.set(path, decodeHex(data)); + break; + } case 'candid': { status.set(path, new TextDecoder().decode(data)); break; @@ -153,6 +158,7 @@ export const request = async (options: { } } } catch (error) { + error; // Break on signature verification errors if ((error as AgentError)?.message?.includes('Invalid certificate')) { throw new AgentError((error as AgentError).message); diff --git a/packages/principal/src/index.ts b/packages/principal/src/index.ts index fab88354e..081bb8f3e 100644 --- a/packages/principal/src/index.ts +++ b/packages/principal/src/index.ts @@ -117,6 +117,10 @@ export class Principal { return matches.join('-'); } + public toJSON(): string { + return this.toText(); + } + public toString(): string { return this.toText(); } From 135ff50db360b2d2e7810e3c2c679a87673cc78a Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Tue, 26 Sep 2023 13:00:47 -0700 Subject: [PATCH 2/8] working certificate subnet node keys --- packages/agent/src/agent/http/http.test.ts | 3 +- packages/agent/src/agent/http/index.ts | 1 + packages/agent/src/canisterStatus/index.ts | 8 +- packages/agent/src/certificate.ts | 169 ++++++++++++++++++++- 4 files changed, 174 insertions(+), 7 deletions(-) diff --git a/packages/agent/src/agent/http/http.test.ts b/packages/agent/src/agent/http/http.test.ts index 4480a16e2..c8a567072 100644 --- a/packages/agent/src/agent/http/http.test.ts +++ b/packages/agent/src/agent/http/http.test.ts @@ -813,11 +813,12 @@ describe('default host', () => { }); describe('fetchSubnetKeys', () => { - it('should fetch subnet keys for a given canister', async () => { + it.only('should fetch subnet keys for a given canister', async () => { jest.useFakeTimers(); const abbbb = (await import('isomorphic-fetch')).default; const agent = new HttpAgent({ fetch: abbbb, host: 'https://icp-api.io' }); await agent.fetchRootKey(); const subnetKeys = await agent.fetchSubnetKeys('erxue-5aaaa-aaaab-qaagq-cai'); //? + // const subnetKeys = await agent.fetchSubnetKeys('ryjl3-tyaaa-aaaaa-aaaba-cai'); //? }); }); diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index e95e6b711..5ce2257f0 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -583,6 +583,7 @@ export class HttpAgent implements Agent { paths: ['subnet'], agent: this, }); + const subnetResponse = response.get('subnet'); response.get('time'); //? console.log(subnetResponse); diff --git a/packages/agent/src/canisterStatus/index.ts b/packages/agent/src/canisterStatus/index.ts index ec5d2eec5..dea17c24e 100644 --- a/packages/agent/src/canisterStatus/index.ts +++ b/packages/agent/src/canisterStatus/index.ts @@ -96,8 +96,12 @@ export const request = async (options: { rootKey: agent.rootKey, canisterId: canisterId, }); - let decoded = Cbor.decode(new Uint8Array(response.certificate)); - decoded?.delegation; //? + + response.certificate; + // must pass in the rootKey if we have no delegation + const parsed = cert.cache_node_keys(); //?? + const asdf = Cbor.decode(new Uint8Array(response.certificate)); + const data = cert.lookup(encodePath(uniquePaths[index], canisterId)); if (!data) { // Typically, the cert lookup will throw diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index 1e8576413..7e587289d 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -1,10 +1,12 @@ import * as cbor from './cbor'; import { AgentError } from './errors'; import { hash } from './request_id'; -import { concat, fromHex, toHex } from './utils/buffer'; +import { compare, concat, fromHex, toHex } from './utils/buffer'; import { Principal } from '@dfinity/principal'; import * as bls from './utils/bls'; -import { decodeTime } from './utils/leb'; +import { decodeLeb128, decodeTime } from './utils/leb'; +import { lebDecode, PipeArrayBuffer } from '@dfinity/candid'; +import { assert } from 'console'; /** * A certificate may fail verification with respect to the provided public key @@ -132,6 +134,7 @@ export interface CreateCertificateOptions { export class Certificate { private readonly cert: Cert; + #nodeKeys: string[] = []; /** * Create a new instance of a certificate, automatically verifying it. Throws a @@ -171,10 +174,165 @@ export class Certificate { this.cert = cbor.decode(new Uint8Array(certificate)); } - public lookup(path: Array): ArrayBuffer | undefined { + public lookup(path: Array): ArrayBuffer | HashTree | undefined { return lookup_path(path, this.cert.tree); } + public lookup_label(label: ArrayBuffer): ArrayBuffer | HashTree | undefined { + return this.lookup([label]); + } + + public cache_node_keys(root_key?: Uint8Array): string[] { + const tree = this.cert.tree; + let delegation = this.cert.delegation; + // On local replica, with System type subnet, there is no delegation + if (!delegation && typeof root_key !== 'undefined') { + delegation = { + subnet_id: Principal.selfAuthenticating(root_key).toUint8Array(), + certificate: new ArrayBuffer(0), + }; + } + // otherwise use default NNS subnet id + else if (!delegation) { + delegation = { + subnet_id: Principal.fromText( + 'tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe', + ).toUint8Array(), + certificate: new ArrayBuffer(0), + }; + } + + delegation; + // Map principals into a readable format, with the subnet id as the key + let iter = 0; + + const nodeTree = lookup_path(['subnet', delegation?.subnet_id as ArrayBuffer, 'node'], tree); + const nodeForks = flatten_forks(nodeTree as HashTree) as HashTree[]; + nodeForks.length; + + this.#nodeKeys = nodeForks.map(fork => { + iter++; + const derEncodedPublicKey = lookup_path(['public_key'], fork[2] as HashTree) as ArrayBuffer; + if (derEncodedPublicKey.byteLength !== 44) { + throw new Error('Invalid public key length'); + } else { + return toHex(derEncodedPublicKey); + } + }); + + return this.#nodeKeys; + } + + // turn the certificate into a JavaScript object + public parse(): Record { + // utf-8 decoder + const decoder = new TextDecoder(); + const tree = this.cert.tree; + const signature = this.cert.signature; + const delegation = this.cert.delegation; + const result: Record = {}; + if (delegation) { + result.delegation = delegation; + } + + result.signature = toHex(new Uint8Array(signature)); + + const subnet_id = this.lookup(['subnet']) as HashTree; + const subnet_forks = flatten_forks(subnet_id) as HashTree[]; + // Map principals into a readable format, with the subnet id as the key + let iter = 0; + + const nodeTree = lookup_path(['subnet', delegation?.subnet_id as ArrayBuffer, 'node'], tree); + const nodeForks = flatten_forks(nodeTree as HashTree) as HashTree[]; + nodeForks.length; + + const hexNodeKeys = nodeForks.map(fork => { + iter++; + const derEncodedPublicKey = lookup_path(['public_key'], fork[2] as HashTree) as ArrayBuffer; + if (derEncodedPublicKey.byteLength !== 44) { + throw new Error('Invalid public key length'); + } else { + return toHex(derEncodedPublicKey); + } + }); + + hexNodeKeys; //? + + iter; + // const mapped = subnet_forks.reduce((start, next) => { + // if (next[2]) { + // const idBuffer = new Uint8Array(next[1] as ArrayBuffer); + // const textId = Principal.fromUint8Array(idBuffer).toText(); + + // textId; + + // const nodeTree = lookup_path( + // ['subnet', delegation?.subnet_id as ArrayBuffer, 'node'], + // tree, + // ); + // const nodeForks = flatten_forks(nodeTree as HashTree) as HashTree[]; + // nodeForks.length; + + // toHex(new Uint8Array(public_key as ArrayBuffer)); //? + + // start[textId] = next[2]; + // } + // return start; + // }, {} as Record); + iter; + try { + toHex(new Uint8Array(subnet_forks[0][1] as ArrayBuffer)); //? + Principal.fromUint8Array(new Uint8Array(subnet_forks[0][1] as ArrayBuffer)).toText(); //? + } catch (error) { + console.log(error); + } + + // subnet_forks.forEach(fork => { + // const label = new Uint8Array(fork[1] as ArrayBuffer); //? + + // }); + + // recursively parse the tree using flatten_forks + // to get a list of all the nodes in the tree + + // de all ArrayBuffer values + const process_node = (node: HashTree): Record => { + const result: Record = {}; + + switch (node[0]) { + case NodeId.Empty: + result.type = 'empty'; + break; + case NodeId.Fork: + result.type = 'fork'; + result.left = process_node(node[1] as HashTree); + result.right = process_node(node[2] as HashTree); + + break; + case NodeId.Labeled: + result.type = 'labeled'; + result.label = toHex(new Uint8Array(node[1] as ArrayBuffer)); + result.sub = process_node(node[2] as HashTree); + break; + case NodeId.Leaf: + result.type = 'leaf'; + result.data = toHex(new Uint8Array(node[1] as ArrayBuffer)); + break; + case NodeId.Pruned: + result.type = 'pruned'; + result.data = toHex(new Uint8Array(node[1] as ArrayBuffer)); + break; + default: + throw new Error('unreachable'); + } + + return result; + }; + + result.tree = process_node(tree); + return result; + } + private async verify(): Promise { const rootHash = await reconstruct(this.cert.tree); const derKey = await this._checkDelegationAndGetKey(this.cert.delegation); @@ -332,12 +490,15 @@ function domain_sep(s: string): ArrayBuffer { export function lookup_path( path: Array, tree: HashTree, -): ArrayBuffer | undefined { +): ArrayBuffer | HashTree | undefined { if (path.length === 0) { switch (tree[0]) { case NodeId.Leaf: { return new Uint8Array(tree[1]).buffer; } + case NodeId.Fork: { + return tree; + } default: { return undefined; } From 23ba75421979e6bc95eadfe4bee8f85f08553756 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Tue, 26 Sep 2023 15:36:38 -0700 Subject: [PATCH 3/8] cleaning up --- packages/agent/src/agent/http/index.ts | 8 +- packages/agent/src/canisterStatus/index.ts | 37 ++++-- packages/agent/src/certificate.ts | 138 +++------------------ 3 files changed, 52 insertions(+), 131 deletions(-) diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index 5ce2257f0..48fef4935 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -28,6 +28,7 @@ import { } from './types'; import { AgentHTTPResponseError } from './errors'; import { request } from '../../canisterStatus'; +import { SubnetStatus } from '../../certificate'; export * from './transforms'; export { Nonce, makeNonce } from './types'; @@ -179,6 +180,8 @@ export class HttpAgent implements Agent { private readonly _retryTimes; // Retry requests N times before erroring by default public readonly _isAgent = true; + #subnetKeys: Map = new Map(); + constructor(options: HttpAgentOptions = {}) { if (options.source) { if (!(options.source instanceof HttpAgent)) { @@ -585,8 +588,9 @@ export class HttpAgent implements Agent { }); const subnetResponse = response.get('subnet'); - response.get('time'); //? - console.log(subnetResponse); + if (subnetResponse && typeof subnetResponse === 'object' && 'nodeKeys' in subnetResponse) { + this.#subnetKeys.set(effectiveCanisterId.toText(), subnetResponse as SubnetStatus); + } return subnetResponse; } diff --git a/packages/agent/src/canisterStatus/index.ts b/packages/agent/src/canisterStatus/index.ts index dea17c24e..b40253ccb 100644 --- a/packages/agent/src/canisterStatus/index.ts +++ b/packages/agent/src/canisterStatus/index.ts @@ -2,7 +2,7 @@ import { Principal } from '@dfinity/principal'; import { AgentError } from '../errors'; import { HttpAgent } from '../agent/http'; -import { Certificate, CreateCertificateOptions } from '../certificate'; +import { Certificate, CreateCertificateOptions, SubnetStatus } from '../certificate'; import { toHex } from '../utils/buffer'; import * as Cbor from '../cbor'; import { decodeLeb128, decodeTime } from '../utils/leb'; @@ -11,7 +11,15 @@ import { decodeLeb128, decodeTime } from '../utils/leb'; * Types of an entry on the canisterStatus map. * An entry of null indicates that the request failed, due to lack of permissions or the result being missing. */ -export type Status = string | ArrayBuffer | Date | ArrayBuffer[] | Principal[] | bigint | null; +export type Status = + | string + | ArrayBuffer + | Date + | ArrayBuffer[] + | Principal[] + | SubnetStatus + | bigint + | null; /** * Interface to define a custom path. Nested paths will be represented as individual buffers, and can be created from text using {@link TextEncoder} @@ -98,11 +106,23 @@ export const request = async (options: { }); response.certificate; - // must pass in the rootKey if we have no delegation - const parsed = cert.cache_node_keys(); //?? - const asdf = Cbor.decode(new Uint8Array(response.certificate)); + const lookup = (cert: Certificate, path: Path) => { + if (path === 'subnet') { + const data = cert.cache_node_keys(); + return { + path: path, + data, + }; + } else { + return { + path: path, + data: cert.lookup(encodePath(path, canisterId)), + }; + } + }; - const data = cert.lookup(encodePath(uniquePaths[index], canisterId)); + // must pass in the rootKey if we have no delegation + const { path, data } = lookup(cert, uniquePaths[index]); if (!data) { // Typically, the cert lookup will throw console.warn(`Expected to find result for path ${path}, but instead found nothing.`); @@ -111,8 +131,7 @@ export const request = async (options: { } else { status.set(path.key, null); } - } else { - path; + } else if (!Array.isArray(data)) { switch (path) { case 'time': { status.set(path, decodeTime(data)); @@ -127,7 +146,7 @@ export const request = async (options: { break; } case 'subnet': { - status.set(path, decodeHex(data)); + status.set(path, data); break; } case 'candid': { diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index 7e587289d..092a32732 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -38,6 +38,17 @@ export type HashTree = | [NodeId.Leaf, ArrayBuffer] | [NodeId.Pruned, ArrayBuffer]; +/** + * Represents the useful information about a subnet + * @param {string} subnetId the principal id of the canister's subnet + * @param {string[]} nodeKeys the keys of the individual nodes in the subnet + */ +export type SubnetStatus = { + // Principal as a string + subnetId: string; + nodeKeys: string[]; +}; + /** * Make a human readable string out of a hash tree. * @param tree @@ -182,7 +193,7 @@ export class Certificate { return this.lookup([label]); } - public cache_node_keys(root_key?: Uint8Array): string[] { + public cache_node_keys(root_key?: Uint8Array): SubnetStatus { const tree = this.cert.tree; let delegation = this.cert.delegation; // On local replica, with System type subnet, there is no delegation @@ -201,17 +212,11 @@ export class Certificate { certificate: new ArrayBuffer(0), }; } - - delegation; - // Map principals into a readable format, with the subnet id as the key - let iter = 0; - const nodeTree = lookup_path(['subnet', delegation?.subnet_id as ArrayBuffer, 'node'], tree); const nodeForks = flatten_forks(nodeTree as HashTree) as HashTree[]; nodeForks.length; this.#nodeKeys = nodeForks.map(fork => { - iter++; const derEncodedPublicKey = lookup_path(['public_key'], fork[2] as HashTree) as ArrayBuffer; if (derEncodedPublicKey.byteLength !== 44) { throw new Error('Invalid public key length'); @@ -220,117 +225,10 @@ export class Certificate { } }); - return this.#nodeKeys; - } - - // turn the certificate into a JavaScript object - public parse(): Record { - // utf-8 decoder - const decoder = new TextDecoder(); - const tree = this.cert.tree; - const signature = this.cert.signature; - const delegation = this.cert.delegation; - const result: Record = {}; - if (delegation) { - result.delegation = delegation; - } - - result.signature = toHex(new Uint8Array(signature)); - - const subnet_id = this.lookup(['subnet']) as HashTree; - const subnet_forks = flatten_forks(subnet_id) as HashTree[]; - // Map principals into a readable format, with the subnet id as the key - let iter = 0; - - const nodeTree = lookup_path(['subnet', delegation?.subnet_id as ArrayBuffer, 'node'], tree); - const nodeForks = flatten_forks(nodeTree as HashTree) as HashTree[]; - nodeForks.length; - - const hexNodeKeys = nodeForks.map(fork => { - iter++; - const derEncodedPublicKey = lookup_path(['public_key'], fork[2] as HashTree) as ArrayBuffer; - if (derEncodedPublicKey.byteLength !== 44) { - throw new Error('Invalid public key length'); - } else { - return toHex(derEncodedPublicKey); - } - }); - - hexNodeKeys; //? - - iter; - // const mapped = subnet_forks.reduce((start, next) => { - // if (next[2]) { - // const idBuffer = new Uint8Array(next[1] as ArrayBuffer); - // const textId = Principal.fromUint8Array(idBuffer).toText(); - - // textId; - - // const nodeTree = lookup_path( - // ['subnet', delegation?.subnet_id as ArrayBuffer, 'node'], - // tree, - // ); - // const nodeForks = flatten_forks(nodeTree as HashTree) as HashTree[]; - // nodeForks.length; - - // toHex(new Uint8Array(public_key as ArrayBuffer)); //? - - // start[textId] = next[2]; - // } - // return start; - // }, {} as Record); - iter; - try { - toHex(new Uint8Array(subnet_forks[0][1] as ArrayBuffer)); //? - Principal.fromUint8Array(new Uint8Array(subnet_forks[0][1] as ArrayBuffer)).toText(); //? - } catch (error) { - console.log(error); - } - - // subnet_forks.forEach(fork => { - // const label = new Uint8Array(fork[1] as ArrayBuffer); //? - - // }); - - // recursively parse the tree using flatten_forks - // to get a list of all the nodes in the tree - - // de all ArrayBuffer values - const process_node = (node: HashTree): Record => { - const result: Record = {}; - - switch (node[0]) { - case NodeId.Empty: - result.type = 'empty'; - break; - case NodeId.Fork: - result.type = 'fork'; - result.left = process_node(node[1] as HashTree); - result.right = process_node(node[2] as HashTree); - - break; - case NodeId.Labeled: - result.type = 'labeled'; - result.label = toHex(new Uint8Array(node[1] as ArrayBuffer)); - result.sub = process_node(node[2] as HashTree); - break; - case NodeId.Leaf: - result.type = 'leaf'; - result.data = toHex(new Uint8Array(node[1] as ArrayBuffer)); - break; - case NodeId.Pruned: - result.type = 'pruned'; - result.data = toHex(new Uint8Array(node[1] as ArrayBuffer)); - break; - default: - throw new Error('unreachable'); - } - - return result; + return { + subnetId: Principal.fromUint8Array(new Uint8Array(delegation.subnet_id)).toText(), + nodeKeys: this.#nodeKeys, }; - - result.tree = process_node(tree); - return result; } private async verify(): Promise { @@ -342,7 +240,7 @@ export class Certificate { let sigVer = false; const lookupTime = this.lookup(['time']); - if (!lookupTime) { + if (!lookupTime || !(lookupTime instanceof ArrayBuffer)) { // Should never happen - time is always present in IC certificates throw new CertificateVerificationError('Certificate does not contain a time'); } @@ -396,7 +294,7 @@ export class Certificate { }); const rangeLookup = cert.lookup(['subnet', d.subnet_id, 'canister_ranges']); - if (!rangeLookup) { + if (!rangeLookup || !(rangeLookup instanceof ArrayBuffer)) { throw new CertificateVerificationError( `Could not find canister ranges for subnet 0x${toHex(d.subnet_id)}`, ); @@ -418,7 +316,7 @@ export class Certificate { ); } const publicKeyLookup = cert.lookup(['subnet', d.subnet_id, 'public_key']); - if (!publicKeyLookup) { + if (!publicKeyLookup || !(publicKeyLookup instanceof ArrayBuffer)) { throw new Error(`Could not find subnet key for subnet 0x${toHex(d.subnet_id)}`); } return publicKeyLookup; From 1d8852af50d4526f0a58c44bdd5094711e808492 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 27 Sep 2023 15:41:09 -0700 Subject: [PATCH 4/8] adding certificate node caching tests --- .../goldenCertificates.test.ts | 6 + packages/agent/src/agent/http/http.test.ts | 13 +- packages/agent/src/certificate.test.ts | 216 ++++++++++++++++++ packages/agent/src/certificate.ts | 8 +- 4 files changed, 234 insertions(+), 9 deletions(-) create mode 100644 packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts diff --git a/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts b/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts new file mode 100644 index 000000000..24babb3d4 --- /dev/null +++ b/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts @@ -0,0 +1,6 @@ +export const goldenCertificates = { + mainnetSystem: `d9d9f7a2647472656583018204582064abbe468e0569dc74af0a631fd9205141a6bf956036e09fd193428a6543eaa083018302467375626e65748301830183018301830183018302581d033a778c6c9eac039fdda83dc90d2c12eb846de85c475e36ead6715c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000100000001014a00000000010fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aa544423a45fb0388c43703a159a96208cafd17f01f1e7c400676d2c69f62195f6a5bb564d564f7967047def10b48c22003f38c5d56961d0c47879f9212b93cd206620114bd9e1d4db22d04e294d37e1ff42cedf2322ebf60702c88325c606808302581d0f033c5125db4f6b32e426268df663a5ce98fe3b531d962e1a7a87fa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001c0000001014a0000000001cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100913f6a84f05736c2dd0b2dc3ec838e95419ae0ef426d556f50152a445b9c232495bc051cdabbd46a7bd8879b09720cbb13b3bcd265ff75567dcbf04e9ae1c3a2141229a6757605625b093c5ca34336393e5a88b78df7b0a3a7e5b9841716d0a483018302581d10b647334a5406987796b2f8b6b14cd32f0876d3fd4fc8452105832502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000180000001014a00000000018fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084cbe7a009258947dc30983fede3b98b34cfee5e5d1ae4e1e72891590738ca9a58f9f6364b359a5448b6c5e20ee5310300e4c0c9cca29b07e2d73208f8ec6cd1fb6ca46c168c43393f9e050a05448836b0a6f5c75d2a398c999c42d7c981cb898302581d12790e7661fccd3d4fc83138dcaffd9f188e867b45ae10c8836dd0b802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000150000001014a00000000015fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610086d88ebbd2f1663e65d3a3ff07e8ee9fa420d08b9a6822919f224b8b802d5d9be150dc493f84c23e73a0cc1d2c2ee28709ff140000128fcd5dfbd7b457ef3af344766d7ff0924fe7a7f456ded77ca6de3b1b406b710c4eaed7287ab9a3527669830183018302581d17f67590355e7123aeffabce4c1bddf3a0efd53a2c2e3f6228fc3adf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000d0000001014a0000000000dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100850e5edfb0685d36757643be011f5d3378fef0bfb9b0ef67429912ebb9237f5028979eb33779df7c63acf59b78eba4d904c6b4abad529b9e8e2195321e287f8c51900f5b440872719c7ac56e381c8063bc6176f8e4b74d06de669493e49055678302581d1cc5ad563f1bce937c305be3d12bef627f73b727808672dc2432aef902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001f0000001014a0000000001ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610093907710f0f89af4b5bd35a28e0162171e2f411d11e152152e88e3da4c2079799e4eac7a3a9f3923fb63b33b68928ae91652fae5c2ccce872173632648ef4dd79ae7e8c15b9e97f132ea34a4349506d281bd66bbd0c3afdd78cbe026927a8c1683018302581d2c55b347ecf2686c83781d6c59d1b43e7b4cba8deb6c1b376107f2cd02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000060000001014a00000000006000ae0101824a00000000006000b001014a00000000006fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610090075120778eb21a530a02bcc763e7f4a192933506966af7b54c10a4d2b24de6a86b200e3440bae6267bf4c488d9a11d0472c38c1b6221198f98e4e6882ba38a5a4e3aa5afce899b7f825ed95adfa12629688073556f2747527213e8d73e40ce8302581d2d030caf397e446c03cece4fd072acce432c75b6a700592e73f5d13302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000090000001014a00000000009fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100805230c2da9687218fdfa49bddab093578c2e8a10b27d69fdda097f286abccdae2541c711e3ca771202bfc9b366bf61b17e9f1173d7c9a6eaaa907ccdba3bc86764bc1d552437c4948038e1018a9c49e444189cd55358e37a6f879d88c0a26938301830183018302581d2ecc29447b0eef6c241dcfdf7dab077093ccd6a1266be0fe9c9b127602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000e0000001014a0000000000efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610091541cdc7b65c4828286c911602d9438de5649d698b60fc06aec73589395d0bca71746524ed2ff17b2c8da9fbc897f0f07a40b204871b6fe96d45ef10b51d1f1d530d0679a5db82de96929805fa17c737994ebcc2312d2a25bd94747ecf8f34b8302581d2f1a9548062f52ca0e90e72a4a97cb324fa1dfb62b564ef1b29f38aa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000160000001014a00000000016fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084698ba18ea46f2041353c98fdf6980235fab99a6f5b83c5de3bb32a7ad190ef26fd2afad2dd2e4fb5eaebc4fd177e3c11ed29fb7dab26a6909d366c185cb9d964d3ff3a8e71c0c28adfca715698f679cef6b6346106a78c9f8d3f8e9a66e88083018302581d30580a1a7643049513f8f7d6ffe6f51000570345a63160cab7784c5902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000a0000001014a0000000000afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610085c8811b0caf15f9ad2e34f1841a7820dd1a70642e21362748bf0927c6fd67ddc0c1329fdd840e06a16d383023c4c00f062f173e628528eb801c15258e2e417d511fe4ba3c175469570cc8e1338e5457ed6b31b72b139b537554f00b14fd69158302581d33c2f9ea0f8e2c53e6e54766dbc6cec8da6787b0154260a99925f7a802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000f0000001014a0000000000ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b31b406c9f6648695a88154ae2e4f5fe87883d4ad81c2844c5571b2d91d401cdd40836e763a7c18dccb84629b0d808f7142c3175bc8231dc09bd53637efd6f2568801385ec973d34e6eef9c8c8280a9f4a114163a43a8540941ba367f0c7cb28830183018302581d4164d0b890d702b3cf4f1121e504f24b0f0d94da0e935221220f3a3702830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000040000001014a00000000004fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008ac081401431767be18972543b3ee45c6769c447fb727a1abd72bc1c12487d5c1169522857cbb8d89273847f669563af05833ecee73afa853a16de4aa5549ffea02f3280167129fe026d8aeadc959d73b44570dd18eb9c6ba313edd0a45282748302581d43dcaf1180db82fda708ce3ac7a03a6060abde13e9546c60e8cce65d02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000701014a00000000000000070101824a000000000210000001014a00000000021fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008675b634a43e39726238cfe39c9518bc3e3225cb6f5a8479bfcf2b608fba6f8524dcb80f35a8ae44b47f262f0a6620d41279f06fe0c53a739fcca01a48926fe651a3519b5b329ffbecc9f0cb908b098dd3e8845cfb99c56379e049ac465ec80683018302581d45178b66a407a4d59c0a4d6733bda2ce3f37c111b4257ec41908f4f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000070000001014a00000000007fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100955f52f73c2dec59a637b294e50b934db5d6de29e73bbcf84e7d86a4ac41bad7b539f9817ade8916961d9dd6bf9257010d5857156e8fe6aafcf6fd068795e70bd3399b3411300c9ccc8eba0d068c10e4cfb6f4e27d195b1ead785d618eb393b98302581d4f82b62edffa3fa4e6a5c48327ce8cfb3f850db2e5abc90e955d77f002830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000230000001014a00000000023fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a32153e6271817b87d91d1cd0b727119a2eda7355ee7ef64ee9f10bf6396aed6899a5475d37d6cc51c6a741397d3685318e8e0dabec1b1994112e2c4da3262033ea18fc667dd0ead6e0a151f4d884ee644b799c05e56f502d42f22ffabbca09783018301830183018302581d581b5aa2f10c5f221e45de74a2cecafd3da076be39db0907cbf554bb02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000170000001014a00000000017fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ad28a2bfaae6c9248ef1ea3e4f4bc6ea29101ce533b0075349bb86a88535c216ce434c9aa018b87465441dd997ed23270e2b21e126c74f16293bdba29033e858ecd50bda7be1b692a401e154eb87b65dcf0983635e578e3ea2f6d9b02c7c79dc8302581d5c76b3988ed788abc32d2ea13331bc29debc4f24d19a8f41417eaeb102830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000120000001014a00000000012fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ae04b0b53b4f62ce4a789a6b0f0c9e66dfa5868cb2f3e0e7f628ca6fb93e4f33879a8fe47a23485f30f5a68472c4fd460bc29923b851023792437af3cc690891740a676ffbeb8d836e6ed5b2409dcb32104dde956743e51d3b0e23222ac9487b83018302581d601575e11b35c86fad26229748379d1d9693312bff16e2bca1c1cdd902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000220000001014a00000000022fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100987ce1744dba1052580903a85d6ac697f1619a9ce3119cfa8b06697013a9e2a799b2078763c3119023981410523c52030e00b5d3fd6663e85c59473366ac9846fee6fe9b415c69a96ee9f0f7768673839211f52b19fab495978f100f982d0f618302581d61b718d0b8c31db1ef09451eadd068887c1df5f37e7de0a3afc5a56a02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000010000001014a00000000001fffff0101824a00000000006000af01014a00000000006000af010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084ec5e445306312c9d94e1d1a37cb7d3a6a5a6f86bc85f30ba9bc5a261ab8a37f814786b8e1bae8aa004afb1bba510a411bde94c2a494fb2caa9155abfe0dfc19046854929f7d67726c83e572faa4b812c96196221ed549ef27fb9fb78c2e06d830183018302581d6a8f67d86ecc8307048038ad71599458c131b531dc9bb0b691940db902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000080000001014a00000000008fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008c4e7e55222f134fc3a633620701f6d25a2a5eecd71a3d49c36846ff5d5cd98d382764e81c5869e95e0feb61d132a9f20d4822f7c5bc4c8ed7cb59d52884736864478f1b0e81b1892cfa01ccc7b2fa5fff31586096217c599ff2652368b2f1948302581d806b712f189b5651e7349743820c5f45a81592464c25048e79f25cd602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000b0000001014a0000000000bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100af4f78ab97b3cdc76075f552e83842d5b07c4e35f9f83614b4976e70751f94ea1bc5ebec45892086f4344ea8fb3f7e3a053da28155c0ac501ab6a26ccfc60e729d0bbe91bf0772837cf2911fb4e952d066daf14ea45c08c2104cc69bf221a4f883018302581d9365a8c9f27f413060850835d1859a415c67575cd30c04a183fd096302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001e0000001014a0000000001efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008a91b23b098aeb7dd5e525717f0c29d3967c5f4e61d0b5c7c697172e6f5682aa5e423d42077695c517aba7e3b636da940938d7d5caeee26c3c71cc6888f542c5966e60ea4d91ddb95ad0994283171097e325026bef003128b44641056c86d04a8302581d9c7d405764f197f3611b7a6d3f7756f0c5f7a7dbb02504da09d21f2902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000140000001014a00000000014fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a5d492126a99c65b09c53fe75b5ad8e24d1556a9db2bfe74dffae1816165405923e6fa2b4c58e5adbddf99575fb83b1a06736dc6e4ce20eabf54ca6ca574d3af0d14ef8ae143f9339cf16e62e72b5dfd47d1d642e731c5ee853a00fef69d70db8301830183018302581d9dfdc32362ee85e05f3f36ad947cc62cd276d7b8687d239637de118c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000200000001014a00000000020fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a0e2dffe693d3c75cabacb68760466611df84ddd06e42954cfdf85c665841801319dcaff52cbad03bc37b64061c562920b77389679afb7f888bfc4a36b4772e6cf41374ff8714101f390056e26de88611c93c22eb90e96fe6370ac246ea6faa28302581da22bac610f4e17278d2a0f2cf83a2e2556f6594371615940334d31d302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000190000001014a00000000019fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100afd62f0314d4f866c512d95a649db5c3241d6624b15c62b2fdd3d29af2dee832e3f1af39c60c2389cc4826c181b82d01133dc9f10f727b315c5bf18de580b70a8d8800c570b99b89514922a6476fbf76591e022ca68cdb4b3610e7f642d9bfa083018302581dacc260d8fc5e1421c9aacc9bb5e1a1147aa15bf15304831ba734b9f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000050000001014a00000000005fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aaeeda397b35cf5473ebc1792d7aadf102d085aca490551906f73c4108df12b8478b13b73c8953c148235d0efe99427017451ce8cdd0bd9ee81ede26221c4c3ff0f49af21c6402e6d35fc4c3c61352ff3d8767a3cc8d7ee58a2b50abbbdf2dbe8302581dba488d13a5dd7649d8093fe4897df1cc7c728ab64c856a78c4b97d6a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000110000001014a00000000011fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610088dc7b350da56b6ff41f08332636ab9d162bf3a293a65f795089ef8b8fe9a5af91c51f67e34729408bfdf21b110b7ca405c98af5c1a9ca2ff2995e27ed4e9d0325bd8fa92623e31879247ea508729cf46e0dd2804bea34f3acabe4aa4ef0b973830183018302581dba58b21125381b0567e61f3f2ecd65f37710316084ee791cdfdb4a1a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001d0000001014a0000000001dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100852c9ff8de8c5964d4b6209feaa6f7675a3afab47ab8ec9b67b111ddc158983fd7b034ffcce4958c60ec37040938eb1e18633d7e9a086153e53755008642bf9f87db91d6709a65f242b9e4e31dbeba64a684745a76dee8cfe6729c5ab3c52f148302581dbd26ec81a3360bc8050673531b92b27988bf2a893b506f80e40c11cf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001a0000001014a0000000001afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008e41463b1893989f425af308744b916d9034e83d9382b03b1e30b117fee21a4e1ff03fc59d54f4bc710a51ba04a1e21d0fd863b5329bf68ee67c6d15f82d4a673775604a1c719cb6ce200b2710e425663c7060e5e98e032beda6835c9010158d83018302581dbfca29efbb1f48b67849f2c9bab8a7856fd57882fb99c8ad497cf55202830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001b0000001014a0000000001bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100846c395853586d94a2e546485537d4f81bb7820d5e82c274b507d592d59353a165dd8ed432e8b7c0792d90d52cf968c20c5ae06d69817d814a7ee2d54130baf49b192186890621abc70046ea9939978df172fc1cd16aded5f227cd8c27bcdb658302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb47830183018302581dcff280e32d7f5ccd2246882f94afb20f54ca61a21765e712d43d2789028301830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000001014a00000000000000060101824a000000000000000801014a00000000000fffff01018302446e6f64658301830183018301830183018302581d24c56af1a646bdee74ba2c8cad88ba6e4f2ee098f99055bd0e9640c60283024a7075626c69635f6b65798203582c302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e7988302581d2995ce7aeea59467fb3a634b434dcc965ba147ba2f9804ea2e8f1b5c0283024a7075626c69635f6b65798203582c302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef63683018302581d32442407acaa5ea43e62b1dac1ac20119c64cfd5c23cc0ae1508ee250283024a7075626c69635f6b65798203582c302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe9828508302581d325c033f6f1fd07e7bcb57b7ab8a24b1abf73beffd1ca17ed88cf3ab0283024a7075626c69635f6b65798203582c302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff830183018302581d3c4d78ddee38b0eb2910a004c3a7362017a5c14a9346007a65829ebb0283024a7075626c69635f6b65798203582c302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf8302581d3eda90ac6d378ae7c7917f94fd61c0e685b22f5ced5ad0735af250230283024a7075626c69635f6b65798203582c302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af36083018302581d46e3cfcd286afe6a1f4572d2350facd38f0f8647d58c499e5bc5039d0283024a7075626c69635f6b65798203582c302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd338302581d53e39463ea45264875d00c508e4bb1325722a96a00053dbc2662fc5e0283024a7075626c69635f6b65798203582c302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b58301830183018302581d607eb9a00ad3b4411f5911276879c618a6895fd57fe6c9b0a879f9b00283024a7075626c69635f6b65798203582c302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b998302581d6ad96c153126046203336a5174a04b30f0adea457c2298b976ab674e0283024a7075626c69635f6b65798203582c302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b83018302581d8156c471c227bb551da5ff7603b22e4a1c87f711292502aef5cdae320283024a7075626c69635f6b65798203582c302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da8302581d8465e6cc28f5be102098a7ae96264f6ec72f1c4a858b491cd60e55a50283024a7075626c69635f6b65798203582c302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f830183018302581d8cf60ae159aabf4207328d2a5524675d5c157a8aa1f80a52ec44221b0283024a7075626c69635f6b65798203582c302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b8302581d904ebdc04493093d1f6f7d37a6a91c5fa6616ddf19771fd346cd5aeb0283024a7075626c69635f6b65798203582c302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea242683018302581d9f00ea7b0826aa145abd4348c3656133ed84e188780f63c5151009bf0283024a7075626c69635f6b65798203582c302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e8302581da7835a01f618d7b552d0eae3310aebd0cac6ea2bf02865472f4546fc0283024a7075626c69635f6b65798203582c302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e83018301830183018302581da7bad7420d9671f6992d64ca541ce75fe04a7c51c2561dd9aad945880283024a7075626c69635f6b65798203582c302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d6938302581db1dee04210dded1afbc7e5d31492d7f0b1379b8fea5b203d30b3c03e0283024a7075626c69635f6b65798203582c302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb83018302581db858dfb622c91c481e81e9cdbfb7ab78da5dbb7a09d2e321787a0c1a0283024a7075626c69635f6b65798203582c302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f8302581db8e453c069995d67a5253c43ec43b4b39038d272f4c67fa9155e6e490283024a7075626c69635f6b65798203582c302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287830183018302581dc0588b3d010691102a6dc738ab5517afaa4f27882a3554b006d2b3920283024a7075626c69635f6b65798203582c302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc68302581dc6f9bfce466cc84184b6c0993a1bf50dabc45f0f5a591c8bcd0326bd0283024a7075626c69635f6b65798203582c302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb83018302581dc749a1b9b5c123bdc745883bd4901e311ae90a586a6825d52d99739e0283024a7075626c69635f6b65798203582c302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f1748302581dcec168cc1c818e1bcbf8622c2bf05ead8f63ad21d04e0498fd64fce80283024a7075626c69635f6b65798203582c302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a8301830183018302581dcff1f1e404582ce832e51ef54dd196540af764448da6720f443d28860283024a7075626c69635f6b65798203582c302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab38302581dd0d9bd9de8bde02b0179227caefdb94de48a74231c4aa88c6bba74780283024a7075626c69635f6b65798203582c302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be3283018302581dd52a16f3dc32065f858393468f14585efb701a4cad05c445ba75a1dd0283024a7075626c69635f6b65798203582c302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea288302581dd5607c139fbf027070f48977431c08c47c96199ed4f75642774408930283024a7075626c69635f6b65798203582c302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc830183018302581dd7d81b675fb361616868d4f31793e064c6619a7a3fb4715d340fc2e00283024a7075626c69635f6b65798203582c302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d1548938302581ddbcb3c89c77e2a4bb43c2244752161f5c08d759f97acdca282af8f9d0283024a7075626c69635f6b65798203582c302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b87583018302581ddce94d09354a1751d180df5fe0a8f352c7396bd63c338f8f91fdf5340283024a7075626c69635f6b65798203582c302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d8302581ddeba05a0e095a26bf12507f792863507d32fc012be8e4f4d705dbb7e0283024a7075626c69635f6b65798203582c302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f6700358301830183018302581de058cf7bdd01bc75227405ebfab94752a4d2f43ff113b5ca68e4df4f0283024a7075626c69635f6b65798203582c302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d38302581de8373870d8066d971c415cbdaf1611bcf84cd3644d22b389de95d9e40283024a7075626c69635f6b65798203582c302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd83018302581de85c5ec8051f35f9e3c915e3dbb3c32af6506b2a668b74c0bd003c850283024a7075626c69635f6b65798203582c302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b938302581ded8915a3c359b8e16da92f2c42d6fbcd34fcc23a011770fba5734c990283024a7075626c69635f6b65798203582c302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d830183018302581df032935f1185096317778e4206e8de237a7e090ba0b3289582c0fff50283024a7075626c69635f6b65798203582c302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d238302581df2be1c26024bc9e103d662dfd167cbfe861400e7748b7778e01adc790283024a7075626c69635f6b65798203582c302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c83018302581df92bb6e3332495ffd40fcf37af5fe9482b0667f3d4063d598fe8e8fa0283024a7075626c69635f6b65798203582c302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff8302581dfd8e4151c4762d9b4b6b36e08d36a49b83e9458a5040a1dc26d63b530283024a7075626c69635f6b65798203582c302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e5383024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae8302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe83018302581dfc7d15b27df96b3e98731463a2af13d6e43cf426d0cb487a7120091502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000c0000001014a0000000000cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009053b542dc8d758237ada280dc505846c327b0c43b7e26c0ee6f7729cdebd43639d959c10fe1aa058622437d7ec34a920035dfd55de4f40937b4c419e02b517eb2b7a6aa7f42644352202f8f4c67e726ca8f168ab588764261dbcc3a5c8113938302581dfe320f2fbbb9d49c8e6edbcc9d85ec096bf645351d95bbddf556f7db02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000130000001014a00000000013fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b2a6741083996223f83384666740a3eacf8ce78c6d39fecdee582a5b243c158706bb215f396ba0429d2188df9ef176721306d048aaa58f6b413457dd63ef1a56de2378e71ca444201e29e490e3790098e92ee85e0142a33ef806c8388aec6baf83024474696d65820349e497bab5ceb8b6c417697369676e61747572655830aad9a5bb55b042aecbddb8ead3ac4bba7f7383ee6c46162fea9f80cac8b46516dbe901dc7e7e886ae7f4c2c8b380b5b9`, + mainnetApplication: `d9d9f7a364747265658301820458201974c7c7bcddc5fb14fc025206a4b146f372fc1b4fb33e6b62d1b11ff980afff83018302467375626e65748301830183018301830183018302581d033a778c6c9eac039fdda83dc90d2c12eb846de85c475e36ead6715c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000100000001014a00000000010fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aa544423a45fb0388c43703a159a96208cafd17f01f1e7c400676d2c69f62195f6a5bb564d564f7967047def10b48c22003f38c5d56961d0c47879f9212b93cd206620114bd9e1d4db22d04e294d37e1ff42cedf2322ebf60702c88325c606808302581d0f033c5125db4f6b32e426268df663a5ce98fe3b531d962e1a7a87fa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001c0000001014a0000000001cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100913f6a84f05736c2dd0b2dc3ec838e95419ae0ef426d556f50152a445b9c232495bc051cdabbd46a7bd8879b09720cbb13b3bcd265ff75567dcbf04e9ae1c3a2141229a6757605625b093c5ca34336393e5a88b78df7b0a3a7e5b9841716d0a483018302581d10b647334a5406987796b2f8b6b14cd32f0876d3fd4fc8452105832502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000180000001014a00000000018fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084cbe7a009258947dc30983fede3b98b34cfee5e5d1ae4e1e72891590738ca9a58f9f6364b359a5448b6c5e20ee5310300e4c0c9cca29b07e2d73208f8ec6cd1fb6ca46c168c43393f9e050a05448836b0a6f5c75d2a398c999c42d7c981cb898302581d12790e7661fccd3d4fc83138dcaffd9f188e867b45ae10c8836dd0b802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000150000001014a00000000015fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610086d88ebbd2f1663e65d3a3ff07e8ee9fa420d08b9a6822919f224b8b802d5d9be150dc493f84c23e73a0cc1d2c2ee28709ff140000128fcd5dfbd7b457ef3af344766d7ff0924fe7a7f456ded77ca6de3b1b406b710c4eaed7287ab9a3527669830183018302581d17f67590355e7123aeffabce4c1bddf3a0efd53a2c2e3f6228fc3adf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000d0000001014a0000000000dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100850e5edfb0685d36757643be011f5d3378fef0bfb9b0ef67429912ebb9237f5028979eb33779df7c63acf59b78eba4d904c6b4abad529b9e8e2195321e287f8c51900f5b440872719c7ac56e381c8063bc6176f8e4b74d06de669493e49055678302581d1cc5ad563f1bce937c305be3d12bef627f73b727808672dc2432aef902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001f0000001014a0000000001ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610093907710f0f89af4b5bd35a28e0162171e2f411d11e152152e88e3da4c2079799e4eac7a3a9f3923fb63b33b68928ae91652fae5c2ccce872173632648ef4dd79ae7e8c15b9e97f132ea34a4349506d281bd66bbd0c3afdd78cbe026927a8c1683018302581d2c55b347ecf2686c83781d6c59d1b43e7b4cba8deb6c1b376107f2cd02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000060000001014a00000000006000ae0101824a00000000006000b001014a00000000006fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610090075120778eb21a530a02bcc763e7f4a192933506966af7b54c10a4d2b24de6a86b200e3440bae6267bf4c488d9a11d0472c38c1b6221198f98e4e6882ba38a5a4e3aa5afce899b7f825ed95adfa12629688073556f2747527213e8d73e40ce8302581d2d030caf397e446c03cece4fd072acce432c75b6a700592e73f5d13302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000090000001014a00000000009fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100805230c2da9687218fdfa49bddab093578c2e8a10b27d69fdda097f286abccdae2541c711e3ca771202bfc9b366bf61b17e9f1173d7c9a6eaaa907ccdba3bc86764bc1d552437c4948038e1018a9c49e444189cd55358e37a6f879d88c0a26938301830183018302581d2ecc29447b0eef6c241dcfdf7dab077093ccd6a1266be0fe9c9b127602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000e0000001014a0000000000efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610091541cdc7b65c4828286c911602d9438de5649d698b60fc06aec73589395d0bca71746524ed2ff17b2c8da9fbc897f0f07a40b204871b6fe96d45ef10b51d1f1d530d0679a5db82de96929805fa17c737994ebcc2312d2a25bd94747ecf8f34b8302581d2f1a9548062f52ca0e90e72a4a97cb324fa1dfb62b564ef1b29f38aa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000160000001014a00000000016fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084698ba18ea46f2041353c98fdf6980235fab99a6f5b83c5de3bb32a7ad190ef26fd2afad2dd2e4fb5eaebc4fd177e3c11ed29fb7dab26a6909d366c185cb9d964d3ff3a8e71c0c28adfca715698f679cef6b6346106a78c9f8d3f8e9a66e88083018302581d30580a1a7643049513f8f7d6ffe6f51000570345a63160cab7784c5902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000a0000001014a0000000000afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610085c8811b0caf15f9ad2e34f1841a7820dd1a70642e21362748bf0927c6fd67ddc0c1329fdd840e06a16d383023c4c00f062f173e628528eb801c15258e2e417d511fe4ba3c175469570cc8e1338e5457ed6b31b72b139b537554f00b14fd69158302581d33c2f9ea0f8e2c53e6e54766dbc6cec8da6787b0154260a99925f7a802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000f0000001014a0000000000ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b31b406c9f6648695a88154ae2e4f5fe87883d4ad81c2844c5571b2d91d401cdd40836e763a7c18dccb84629b0d808f7142c3175bc8231dc09bd53637efd6f2568801385ec973d34e6eef9c8c8280a9f4a114163a43a8540941ba367f0c7cb28830183018302581d4164d0b890d702b3cf4f1121e504f24b0f0d94da0e935221220f3a3702830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000040000001014a00000000004fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008ac081401431767be18972543b3ee45c6769c447fb727a1abd72bc1c12487d5c1169522857cbb8d89273847f669563af05833ecee73afa853a16de4aa5549ffea02f3280167129fe026d8aeadc959d73b44570dd18eb9c6ba313edd0a45282748302581d43dcaf1180db82fda708ce3ac7a03a6060abde13e9546c60e8cce65d02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000701014a00000000000000070101824a000000000210000001014a00000000021fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008675b634a43e39726238cfe39c9518bc3e3225cb6f5a8479bfcf2b608fba6f8524dcb80f35a8ae44b47f262f0a6620d41279f06fe0c53a739fcca01a48926fe651a3519b5b329ffbecc9f0cb908b098dd3e8845cfb99c56379e049ac465ec80683018302581d45178b66a407a4d59c0a4d6733bda2ce3f37c111b4257ec41908f4f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000070000001014a00000000007fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100955f52f73c2dec59a637b294e50b934db5d6de29e73bbcf84e7d86a4ac41bad7b539f9817ade8916961d9dd6bf9257010d5857156e8fe6aafcf6fd068795e70bd3399b3411300c9ccc8eba0d068c10e4cfb6f4e27d195b1ead785d618eb393b98302581d4f82b62edffa3fa4e6a5c48327ce8cfb3f850db2e5abc90e955d77f002830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000230000001014a00000000023fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a32153e6271817b87d91d1cd0b727119a2eda7355ee7ef64ee9f10bf6396aed6899a5475d37d6cc51c6a741397d3685318e8e0dabec1b1994112e2c4da3262033ea18fc667dd0ead6e0a151f4d884ee644b799c05e56f502d42f22ffabbca09783018301830183018302581d581b5aa2f10c5f221e45de74a2cecafd3da076be39db0907cbf554bb02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000170000001014a00000000017fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ad28a2bfaae6c9248ef1ea3e4f4bc6ea29101ce533b0075349bb86a88535c216ce434c9aa018b87465441dd997ed23270e2b21e126c74f16293bdba29033e858ecd50bda7be1b692a401e154eb87b65dcf0983635e578e3ea2f6d9b02c7c79dc8302581d5c76b3988ed788abc32d2ea13331bc29debc4f24d19a8f41417eaeb102830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000120000001014a00000000012fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ae04b0b53b4f62ce4a789a6b0f0c9e66dfa5868cb2f3e0e7f628ca6fb93e4f33879a8fe47a23485f30f5a68472c4fd460bc29923b851023792437af3cc690891740a676ffbeb8d836e6ed5b2409dcb32104dde956743e51d3b0e23222ac9487b83018302581d601575e11b35c86fad26229748379d1d9693312bff16e2bca1c1cdd902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000220000001014a00000000022fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100987ce1744dba1052580903a85d6ac697f1619a9ce3119cfa8b06697013a9e2a799b2078763c3119023981410523c52030e00b5d3fd6663e85c59473366ac9846fee6fe9b415c69a96ee9f0f7768673839211f52b19fab495978f100f982d0f618302581d61b718d0b8c31db1ef09451eadd068887c1df5f37e7de0a3afc5a56a02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000010000001014a00000000001fffff0101824a00000000006000af01014a00000000006000af010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084ec5e445306312c9d94e1d1a37cb7d3a6a5a6f86bc85f30ba9bc5a261ab8a37f814786b8e1bae8aa004afb1bba510a411bde94c2a494fb2caa9155abfe0dfc19046854929f7d67726c83e572faa4b812c96196221ed549ef27fb9fb78c2e06d830183018302581d6a8f67d86ecc8307048038ad71599458c131b531dc9bb0b691940db902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000080000001014a00000000008fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008c4e7e55222f134fc3a633620701f6d25a2a5eecd71a3d49c36846ff5d5cd98d382764e81c5869e95e0feb61d132a9f20d4822f7c5bc4c8ed7cb59d52884736864478f1b0e81b1892cfa01ccc7b2fa5fff31586096217c599ff2652368b2f1948302581d806b712f189b5651e7349743820c5f45a81592464c25048e79f25cd602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000b0000001014a0000000000bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100af4f78ab97b3cdc76075f552e83842d5b07c4e35f9f83614b4976e70751f94ea1bc5ebec45892086f4344ea8fb3f7e3a053da28155c0ac501ab6a26ccfc60e729d0bbe91bf0772837cf2911fb4e952d066daf14ea45c08c2104cc69bf221a4f883018302581d9365a8c9f27f413060850835d1859a415c67575cd30c04a183fd096302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001e0000001014a0000000001efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008a91b23b098aeb7dd5e525717f0c29d3967c5f4e61d0b5c7c697172e6f5682aa5e423d42077695c517aba7e3b636da940938d7d5caeee26c3c71cc6888f542c5966e60ea4d91ddb95ad0994283171097e325026bef003128b44641056c86d04a8302581d9c7d405764f197f3611b7a6d3f7756f0c5f7a7dbb02504da09d21f2902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000140000001014a00000000014fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a5d492126a99c65b09c53fe75b5ad8e24d1556a9db2bfe74dffae1816165405923e6fa2b4c58e5adbddf99575fb83b1a06736dc6e4ce20eabf54ca6ca574d3af0d14ef8ae143f9339cf16e62e72b5dfd47d1d642e731c5ee853a00fef69d70db8301830183018302581d9dfdc32362ee85e05f3f36ad947cc62cd276d7b8687d239637de118c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000200000001014a00000000020fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a0e2dffe693d3c75cabacb68760466611df84ddd06e42954cfdf85c665841801319dcaff52cbad03bc37b64061c562920b77389679afb7f888bfc4a36b4772e6cf41374ff8714101f390056e26de88611c93c22eb90e96fe6370ac246ea6faa28302581da22bac610f4e17278d2a0f2cf83a2e2556f6594371615940334d31d302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000190000001014a00000000019fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100afd62f0314d4f866c512d95a649db5c3241d6624b15c62b2fdd3d29af2dee832e3f1af39c60c2389cc4826c181b82d01133dc9f10f727b315c5bf18de580b70a8d8800c570b99b89514922a6476fbf76591e022ca68cdb4b3610e7f642d9bfa083018302581dacc260d8fc5e1421c9aacc9bb5e1a1147aa15bf15304831ba734b9f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000050000001014a00000000005fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aaeeda397b35cf5473ebc1792d7aadf102d085aca490551906f73c4108df12b8478b13b73c8953c148235d0efe99427017451ce8cdd0bd9ee81ede26221c4c3ff0f49af21c6402e6d35fc4c3c61352ff3d8767a3cc8d7ee58a2b50abbbdf2dbe8302581dba488d13a5dd7649d8093fe4897df1cc7c728ab64c856a78c4b97d6a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000110000001014a00000000011fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610088dc7b350da56b6ff41f08332636ab9d162bf3a293a65f795089ef8b8fe9a5af91c51f67e34729408bfdf21b110b7ca405c98af5c1a9ca2ff2995e27ed4e9d0325bd8fa92623e31879247ea508729cf46e0dd2804bea34f3acabe4aa4ef0b973830183018302581dba58b21125381b0567e61f3f2ecd65f37710316084ee791cdfdb4a1a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001d0000001014a0000000001dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100852c9ff8de8c5964d4b6209feaa6f7675a3afab47ab8ec9b67b111ddc158983fd7b034ffcce4958c60ec37040938eb1e18633d7e9a086153e53755008642bf9f87db91d6709a65f242b9e4e31dbeba64a684745a76dee8cfe6729c5ab3c52f148302581dbd26ec81a3360bc8050673531b92b27988bf2a893b506f80e40c11cf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001a0000001014a0000000001afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008e41463b1893989f425af308744b916d9034e83d9382b03b1e30b117fee21a4e1ff03fc59d54f4bc710a51ba04a1e21d0fd863b5329bf68ee67c6d15f82d4a673775604a1c719cb6ce200b2710e425663c7060e5e98e032beda6835c9010158d83018302581dbfca29efbb1f48b67849f2c9bab8a7856fd57882fb99c8ad497cf55202830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001b0000001014a0000000001bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100846c395853586d94a2e546485537d4f81bb7820d5e82c274b507d592d59353a165dd8ed432e8b7c0792d90d52cf968c20c5ae06d69817d814a7ee2d54130baf49b192186890621abc70046ea9939978df172fc1cd16aded5f227cd8c27bcdb658302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b028301830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff01018302476d65747269637382035823a4001901c3011b00000002547ccc1702a2001b00000dc43d2206f80100031a0003649883018302446e6f646583018301830183018302581d8554fbd9569af03e79ccabb8e0df5376da7d9c52c6116d477dc8e7a80283024a7075626c69635f6b65798203582c302a300506032b65700321005b0bdf0329932ab0a78fa7192ad76cf37d67eb2024739774d3b67da7799ebc9c8302581d88729cd45ca059e2af291c1521462cad7d479445170c68b050e4c3ba0283024a7075626c69635f6b65798203582c302a300506032b65700321009776d25542873dafb8099303d1fca8e4aa344e73cf5a3d7df5b40f9c8ed5a08583018302581d8e64078481caf73482c8b734e37523c8e6a0767882bd3a21b7a93c250283024a7075626c69635f6b65798203582c302a300506032b6570032100e5a9296571826cc3be977490296405ae9da1da7d59cce1642421bc19804cc3108302581d9717b99c1bf40cb84611aee69e92e7715eb0a90221aac29be62d7e3d0283024a7075626c69635f6b65798203582c302a300506032b6570032100b761a93e418ab326d2d106d9137268d407f7c8a743127e2833899933337eb09b830183018302581d9b5c9ed769f8dbd6210f4680cadb73beb3852e76ac43e9ea2dd35a280283024a7075626c69635f6b65798203582c302a300506032b6570032100afd56377478dc711cbfe043022423d9f7f7decb709de7501545923274186883f8302581da142f96f269cac297b0d7d651c5a43470d78322e5b5369cd5d04a9ce0283024a7075626c69635f6b65798203582c302a300506032b6570032100ce76939540cac8de3475329517c684e0562fb6cbad1db67fb60362808bdaf46283018302581da870dc773b62cae3c31ca1905ff7c7242a4460bf18594dcc12641c170283024a7075626c69635f6b65798203582c302a300506032b65700321001645a7cb7f3980dd6f9ca6ca0966a4d4bde9d57d90df0f10fc31eac960a8ab418302581db506e1548dbaa9a0d840282a3c5a608a7d90a9435a8d391cfb028c660283024a7075626c69635f6b65798203582c302a300506032b65700321000c441fada59fea1cf21ebc157392338ca56775011c4c5630782823e2a7938c8f8301830183018302581dbe9c9341fcf1ce0cb07e809686431958cf497725f37868f3ef990e020283024a7075626c69635f6b65798203582c302a300506032b6570032100f408b362fc92255a4776666179eba4b9dfbd6d3b9f6b87b3abb80f726878e0a98302581dcc84fb1d9f904589c629c10b052a1214318029e46af6b682c70d52530283024a7075626c69635f6b65798203582c302a300506032b6570032100cab5efd3205fa4b3409b6f5e421ebd776dd36ea6108820c624478016df9c6a2083018302581dd972b647954b754c516162ef7eb651cb3d8d6e264d1c289a76f46fa80283024a7075626c69635f6b65798203582c302a300506032b6570032100e650a1cc4bf264cdc80442d33d7bd00e3de1f15ddd48c7ac0f2fe582f599d9548302581de7d8693d4f6322560cc8b0cab4280f40c1a1957de51576893a11ea9d0283024a7075626c69635f6b65798203582c302a300506032b6570032100be0759d30172a9dfdcc2e11b92e8daf1753c45f126b8413c8e57e621b5626d378302581dfe9763f6e077ef3d42f2225c16bc1ec040f97be6add75cff99b24e020283024a7075626c69635f6b65798203582c302a300506032b65700321006b8ef72b0efb4ef38dc957097cb26dfcf24b083dd6b2b5fcd5269657cd8e59a783024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb47830183018302581dcff280e32d7f5ccd2246882f94afb20f54ca61a21765e712d43d278902830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000001014a00000000000000060101824a000000000000000801014a00000000000fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae8302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe83018302581dfc7d15b27df96b3e98731463a2af13d6e43cf426d0cb487a7120091502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000c0000001014a0000000000cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009053b542dc8d758237ada280dc505846c327b0c43b7e26c0ee6f7729cdebd43639d959c10fe1aa058622437d7ec34a920035dfd55de4f40937b4c419e02b517eb2b7a6aa7f42644352202f8f4c67e726ca8f168ab588764261dbcc3a5c8113938302581dfe320f2fbbb9d49c8e6edbcc9d85ec096bf645351d95bbddf556f7db02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000130000001014a00000000013fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b2a6741083996223f83384666740a3eacf8ce78c6d39fecdee582a5b243c158706bb215f396ba0429d2188df9ef176721306d048aaa58f6b413457dd63ef1a56de2378e71ca444201e29e490e3790098e92ee85e0142a33ef806c8388aec6baf83024474696d65820349d6b2cda6e896b6c417697369676e61747572655830ab3f413732a43a06f1fb9b4b33ca93000f82694ce8939d2f09752d32bee0c48059bcfefb1a78a0c70c6000498b90fbb36a64656c65676174696f6ea2697375626e65745f6964581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b026b6365727469666963617465590257d9d9f7a264747265658301820458201e757e29e560315f8b01e8fd15ec9d0018612d65cc1d7ecddc3c4219e4fcb71083018302467375626e657483018301820458205363d9921c468ac1a0c0475124a1703b0eeab44f12afe4bb721a059eabfbccde8301820458201715cf8e070b9844e1cc2d88b020cddf01463fbdb1a63351c7a2f134b4d22c7883018204582056de5b2239f855d965786fa8fc032c85f07dcd595e7fe19259eadd0808967fbc830182045820ad16bbe070678ae81807dc5a10506cd58ec328abae4a43b3ee93ca27a4062d4b8301820458204d4e6ae2db005b61fa587835203df74b00b2a34626fa1b1d895eb20a899599a08302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb478204582053500b9323caa4e30ecfb70fba000e908670ef4dbb1d8cae818051be76656ccb83024474696d65820349bfbfabb4f6eaadc417697369676e617475726558308be7643a5542a0eb4c031c2945bc71fa46aaf4c5d02151dad26b53f42433e4ef8150ea7bcd2bb8c86db4a53d49e58c3d`, + localSystem: `d9d9f7a264747265658301820458201d7d7679b4b9276bc98296be92a3e0af4b294ec8642a00b6e930a83b4bc65bc083018302467375626e65748301830183018301830183018302581d033a778c6c9eac039fdda83dc90d2c12eb846de85c475e36ead6715c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000100000001014a00000000010fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aa544423a45fb0388c43703a159a96208cafd17f01f1e7c400676d2c69f62195f6a5bb564d564f7967047def10b48c22003f38c5d56961d0c47879f9212b93cd206620114bd9e1d4db22d04e294d37e1ff42cedf2322ebf60702c88325c606808302581d0f033c5125db4f6b32e426268df663a5ce98fe3b531d962e1a7a87fa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001c0000001014a0000000001cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100913f6a84f05736c2dd0b2dc3ec838e95419ae0ef426d556f50152a445b9c232495bc051cdabbd46a7bd8879b09720cbb13b3bcd265ff75567dcbf04e9ae1c3a2141229a6757605625b093c5ca34336393e5a88b78df7b0a3a7e5b9841716d0a483018302581d10b647334a5406987796b2f8b6b14cd32f0876d3fd4fc8452105832502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000180000001014a00000000018fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084cbe7a009258947dc30983fede3b98b34cfee5e5d1ae4e1e72891590738ca9a58f9f6364b359a5448b6c5e20ee5310300e4c0c9cca29b07e2d73208f8ec6cd1fb6ca46c168c43393f9e050a05448836b0a6f5c75d2a398c999c42d7c981cb898302581d12790e7661fccd3d4fc83138dcaffd9f188e867b45ae10c8836dd0b802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000150000001014a00000000015fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610086d88ebbd2f1663e65d3a3ff07e8ee9fa420d08b9a6822919f224b8b802d5d9be150dc493f84c23e73a0cc1d2c2ee28709ff140000128fcd5dfbd7b457ef3af344766d7ff0924fe7a7f456ded77ca6de3b1b406b710c4eaed7287ab9a3527669830183018302581d17f67590355e7123aeffabce4c1bddf3a0efd53a2c2e3f6228fc3adf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000d0000001014a0000000000dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100850e5edfb0685d36757643be011f5d3378fef0bfb9b0ef67429912ebb9237f5028979eb33779df7c63acf59b78eba4d904c6b4abad529b9e8e2195321e287f8c51900f5b440872719c7ac56e381c8063bc6176f8e4b74d06de669493e49055678302581d1cc5ad563f1bce937c305be3d12bef627f73b727808672dc2432aef902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001f0000001014a0000000001ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610093907710f0f89af4b5bd35a28e0162171e2f411d11e152152e88e3da4c2079799e4eac7a3a9f3923fb63b33b68928ae91652fae5c2ccce872173632648ef4dd79ae7e8c15b9e97f132ea34a4349506d281bd66bbd0c3afdd78cbe026927a8c1683018302581d2c55b347ecf2686c83781d6c59d1b43e7b4cba8deb6c1b376107f2cd02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000060000001014a00000000006000ae0101824a00000000006000b001014a00000000006fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610090075120778eb21a530a02bcc763e7f4a192933506966af7b54c10a4d2b24de6a86b200e3440bae6267bf4c488d9a11d0472c38c1b6221198f98e4e6882ba38a5a4e3aa5afce899b7f825ed95adfa12629688073556f2747527213e8d73e40ce8302581d2d030caf397e446c03cece4fd072acce432c75b6a700592e73f5d13302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000090000001014a00000000009fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100805230c2da9687218fdfa49bddab093578c2e8a10b27d69fdda097f286abccdae2541c711e3ca771202bfc9b366bf61b17e9f1173d7c9a6eaaa907ccdba3bc86764bc1d552437c4948038e1018a9c49e444189cd55358e37a6f879d88c0a26938301830183018302581d2ecc29447b0eef6c241dcfdf7dab077093ccd6a1266be0fe9c9b127602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000e0000001014a0000000000efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610091541cdc7b65c4828286c911602d9438de5649d698b60fc06aec73589395d0bca71746524ed2ff17b2c8da9fbc897f0f07a40b204871b6fe96d45ef10b51d1f1d530d0679a5db82de96929805fa17c737994ebcc2312d2a25bd94747ecf8f34b8302581d2f1a9548062f52ca0e90e72a4a97cb324fa1dfb62b564ef1b29f38aa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000160000001014a00000000016fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084698ba18ea46f2041353c98fdf6980235fab99a6f5b83c5de3bb32a7ad190ef26fd2afad2dd2e4fb5eaebc4fd177e3c11ed29fb7dab26a6909d366c185cb9d964d3ff3a8e71c0c28adfca715698f679cef6b6346106a78c9f8d3f8e9a66e88083018302581d30580a1a7643049513f8f7d6ffe6f51000570345a63160cab7784c5902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000a0000001014a0000000000afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610085c8811b0caf15f9ad2e34f1841a7820dd1a70642e21362748bf0927c6fd67ddc0c1329fdd840e06a16d383023c4c00f062f173e628528eb801c15258e2e417d511fe4ba3c175469570cc8e1338e5457ed6b31b72b139b537554f00b14fd69158302581d33c2f9ea0f8e2c53e6e54766dbc6cec8da6787b0154260a99925f7a802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000f0000001014a0000000000ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b31b406c9f6648695a88154ae2e4f5fe87883d4ad81c2844c5571b2d91d401cdd40836e763a7c18dccb84629b0d808f7142c3175bc8231dc09bd53637efd6f2568801385ec973d34e6eef9c8c8280a9f4a114163a43a8540941ba367f0c7cb28830183018302581d4164d0b890d702b3cf4f1121e504f24b0f0d94da0e935221220f3a3702830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000040000001014a00000000004fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008ac081401431767be18972543b3ee45c6769c447fb727a1abd72bc1c12487d5c1169522857cbb8d89273847f669563af05833ecee73afa853a16de4aa5549ffea02f3280167129fe026d8aeadc959d73b44570dd18eb9c6ba313edd0a45282748302581d43dcaf1180db82fda708ce3ac7a03a6060abde13e9546c60e8cce65d02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000701014a00000000000000070101824a000000000210000001014a00000000021fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008675b634a43e39726238cfe39c9518bc3e3225cb6f5a8479bfcf2b608fba6f8524dcb80f35a8ae44b47f262f0a6620d41279f06fe0c53a739fcca01a48926fe651a3519b5b329ffbecc9f0cb908b098dd3e8845cfb99c56379e049ac465ec80683018302581d45178b66a407a4d59c0a4d6733bda2ce3f37c111b4257ec41908f4f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000070000001014a00000000007fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100955f52f73c2dec59a637b294e50b934db5d6de29e73bbcf84e7d86a4ac41bad7b539f9817ade8916961d9dd6bf9257010d5857156e8fe6aafcf6fd068795e70bd3399b3411300c9ccc8eba0d068c10e4cfb6f4e27d195b1ead785d618eb393b98302581d4f82b62edffa3fa4e6a5c48327ce8cfb3f850db2e5abc90e955d77f002830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000230000001014a00000000023fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a32153e6271817b87d91d1cd0b727119a2eda7355ee7ef64ee9f10bf6396aed6899a5475d37d6cc51c6a741397d3685318e8e0dabec1b1994112e2c4da3262033ea18fc667dd0ead6e0a151f4d884ee644b799c05e56f502d42f22ffabbca09783018301830183018302581d581b5aa2f10c5f221e45de74a2cecafd3da076be39db0907cbf554bb02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000170000001014a00000000017fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ad28a2bfaae6c9248ef1ea3e4f4bc6ea29101ce533b0075349bb86a88535c216ce434c9aa018b87465441dd997ed23270e2b21e126c74f16293bdba29033e858ecd50bda7be1b692a401e154eb87b65dcf0983635e578e3ea2f6d9b02c7c79dc8302581d5c76b3988ed788abc32d2ea13331bc29debc4f24d19a8f41417eaeb102830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000120000001014a00000000012fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ae04b0b53b4f62ce4a789a6b0f0c9e66dfa5868cb2f3e0e7f628ca6fb93e4f33879a8fe47a23485f30f5a68472c4fd460bc29923b851023792437af3cc690891740a676ffbeb8d836e6ed5b2409dcb32104dde956743e51d3b0e23222ac9487b83018302581d601575e11b35c86fad26229748379d1d9693312bff16e2bca1c1cdd902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000220000001014a00000000022fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100987ce1744dba1052580903a85d6ac697f1619a9ce3119cfa8b06697013a9e2a799b2078763c3119023981410523c52030e00b5d3fd6663e85c59473366ac9846fee6fe9b415c69a96ee9f0f7768673839211f52b19fab495978f100f982d0f618302581d61b718d0b8c31db1ef09451eadd068887c1df5f37e7de0a3afc5a56a02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000010000001014a00000000001fffff0101824a00000000006000af01014a00000000006000af010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084ec5e445306312c9d94e1d1a37cb7d3a6a5a6f86bc85f30ba9bc5a261ab8a37f814786b8e1bae8aa004afb1bba510a411bde94c2a494fb2caa9155abfe0dfc19046854929f7d67726c83e572faa4b812c96196221ed549ef27fb9fb78c2e06d830183018302581d6a8f67d86ecc8307048038ad71599458c131b531dc9bb0b691940db902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000080000001014a00000000008fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008c4e7e55222f134fc3a633620701f6d25a2a5eecd71a3d49c36846ff5d5cd98d382764e81c5869e95e0feb61d132a9f20d4822f7c5bc4c8ed7cb59d52884736864478f1b0e81b1892cfa01ccc7b2fa5fff31586096217c599ff2652368b2f1948302581d806b712f189b5651e7349743820c5f45a81592464c25048e79f25cd602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000b0000001014a0000000000bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100af4f78ab97b3cdc76075f552e83842d5b07c4e35f9f83614b4976e70751f94ea1bc5ebec45892086f4344ea8fb3f7e3a053da28155c0ac501ab6a26ccfc60e729d0bbe91bf0772837cf2911fb4e952d066daf14ea45c08c2104cc69bf221a4f883018302581d9365a8c9f27f413060850835d1859a415c67575cd30c04a183fd096302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001e0000001014a0000000001efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008a91b23b098aeb7dd5e525717f0c29d3967c5f4e61d0b5c7c697172e6f5682aa5e423d42077695c517aba7e3b636da940938d7d5caeee26c3c71cc6888f542c5966e60ea4d91ddb95ad0994283171097e325026bef003128b44641056c86d04a8302581d9c7d405764f197f3611b7a6d3f7756f0c5f7a7dbb02504da09d21f2902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000140000001014a00000000014fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a5d492126a99c65b09c53fe75b5ad8e24d1556a9db2bfe74dffae1816165405923e6fa2b4c58e5adbddf99575fb83b1a06736dc6e4ce20eabf54ca6ca574d3af0d14ef8ae143f9339cf16e62e72b5dfd47d1d642e731c5ee853a00fef69d70db8301830183018302581d9dfdc32362ee85e05f3f36ad947cc62cd276d7b8687d239637de118c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000200000001014a00000000020fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a0e2dffe693d3c75cabacb68760466611df84ddd06e42954cfdf85c665841801319dcaff52cbad03bc37b64061c562920b77389679afb7f888bfc4a36b4772e6cf41374ff8714101f390056e26de88611c93c22eb90e96fe6370ac246ea6faa28302581da22bac610f4e17278d2a0f2cf83a2e2556f6594371615940334d31d302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000190000001014a00000000019fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100afd62f0314d4f866c512d95a649db5c3241d6624b15c62b2fdd3d29af2dee832e3f1af39c60c2389cc4826c181b82d01133dc9f10f727b315c5bf18de580b70a8d8800c570b99b89514922a6476fbf76591e022ca68cdb4b3610e7f642d9bfa083018302581dacc260d8fc5e1421c9aacc9bb5e1a1147aa15bf15304831ba734b9f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000050000001014a00000000005fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aaeeda397b35cf5473ebc1792d7aadf102d085aca490551906f73c4108df12b8478b13b73c8953c148235d0efe99427017451ce8cdd0bd9ee81ede26221c4c3ff0f49af21c6402e6d35fc4c3c61352ff3d8767a3cc8d7ee58a2b50abbbdf2dbe8302581dba488d13a5dd7649d8093fe4897df1cc7c728ab64c856a78c4b97d6a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000110000001014a00000000011fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610088dc7b350da56b6ff41f08332636ab9d162bf3a293a65f795089ef8b8fe9a5af91c51f67e34729408bfdf21b110b7ca405c98af5c1a9ca2ff2995e27ed4e9d0325bd8fa92623e31879247ea508729cf46e0dd2804bea34f3acabe4aa4ef0b973830183018302581dba58b21125381b0567e61f3f2ecd65f37710316084ee791cdfdb4a1a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001d0000001014a0000000001dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100852c9ff8de8c5964d4b6209feaa6f7675a3afab47ab8ec9b67b111ddc158983fd7b034ffcce4958c60ec37040938eb1e18633d7e9a086153e53755008642bf9f87db91d6709a65f242b9e4e31dbeba64a684745a76dee8cfe6729c5ab3c52f148302581dbd26ec81a3360bc8050673531b92b27988bf2a893b506f80e40c11cf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001a0000001014a0000000001afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008e41463b1893989f425af308744b916d9034e83d9382b03b1e30b117fee21a4e1ff03fc59d54f4bc710a51ba04a1e21d0fd863b5329bf68ee67c6d15f82d4a673775604a1c719cb6ce200b2710e425663c7060e5e98e032beda6835c9010158d83018302581dbfca29efbb1f48b67849f2c9bab8a7856fd57882fb99c8ad497cf55202830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001b0000001014a0000000001bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100846c395853586d94a2e546485537d4f81bb7820d5e82c274b507d592d59353a165dd8ed432e8b7c0792d90d52cf968c20c5ae06d69817d814a7ee2d54130baf49b192186890621abc70046ea9939978df172fc1cd16aded5f227cd8c27bcdb658302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb47830183018302581dcff280e32d7f5ccd2246882f94afb20f54ca61a21765e712d43d2789028301830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000001014a00000000000000060101824a000000000000000801014a00000000000fffff01018302446e6f64658301830183018301830183018302581d24c56af1a646bdee74ba2c8cad88ba6e4f2ee098f99055bd0e9640c60283024a7075626c69635f6b65798203582c302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e7988302581d2995ce7aeea59467fb3a634b434dcc965ba147ba2f9804ea2e8f1b5c0283024a7075626c69635f6b65798203582c302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef63683018302581d32442407acaa5ea43e62b1dac1ac20119c64cfd5c23cc0ae1508ee250283024a7075626c69635f6b65798203582c302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe9828508302581d325c033f6f1fd07e7bcb57b7ab8a24b1abf73beffd1ca17ed88cf3ab0283024a7075626c69635f6b65798203582c302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff830183018302581d3c4d78ddee38b0eb2910a004c3a7362017a5c14a9346007a65829ebb0283024a7075626c69635f6b65798203582c302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf8302581d3eda90ac6d378ae7c7917f94fd61c0e685b22f5ced5ad0735af250230283024a7075626c69635f6b65798203582c302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af36083018302581d46e3cfcd286afe6a1f4572d2350facd38f0f8647d58c499e5bc5039d0283024a7075626c69635f6b65798203582c302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd338302581d53e39463ea45264875d00c508e4bb1325722a96a00053dbc2662fc5e0283024a7075626c69635f6b65798203582c302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b58301830183018302581d607eb9a00ad3b4411f5911276879c618a6895fd57fe6c9b0a879f9b00283024a7075626c69635f6b65798203582c302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b998302581d6ad96c153126046203336a5174a04b30f0adea457c2298b976ab674e0283024a7075626c69635f6b65798203582c302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b83018302581d8156c471c227bb551da5ff7603b22e4a1c87f711292502aef5cdae320283024a7075626c69635f6b65798203582c302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da8302581d8465e6cc28f5be102098a7ae96264f6ec72f1c4a858b491cd60e55a50283024a7075626c69635f6b65798203582c302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f830183018302581d8cf60ae159aabf4207328d2a5524675d5c157a8aa1f80a52ec44221b0283024a7075626c69635f6b65798203582c302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b8302581d904ebdc04493093d1f6f7d37a6a91c5fa6616ddf19771fd346cd5aeb0283024a7075626c69635f6b65798203582c302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea242683018302581d9f00ea7b0826aa145abd4348c3656133ed84e188780f63c5151009bf0283024a7075626c69635f6b65798203582c302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e8302581da7835a01f618d7b552d0eae3310aebd0cac6ea2bf02865472f4546fc0283024a7075626c69635f6b65798203582c302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e83018301830183018302581da7bad7420d9671f6992d64ca541ce75fe04a7c51c2561dd9aad945880283024a7075626c69635f6b65798203582c302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d6938302581db1dee04210dded1afbc7e5d31492d7f0b1379b8fea5b203d30b3c03e0283024a7075626c69635f6b65798203582c302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb83018302581db858dfb622c91c481e81e9cdbfb7ab78da5dbb7a09d2e321787a0c1a0283024a7075626c69635f6b65798203582c302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f8302581db8e453c069995d67a5253c43ec43b4b39038d272f4c67fa9155e6e490283024a7075626c69635f6b65798203582c302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287830183018302581dc0588b3d010691102a6dc738ab5517afaa4f27882a3554b006d2b3920283024a7075626c69635f6b65798203582c302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc68302581dc6f9bfce466cc84184b6c0993a1bf50dabc45f0f5a591c8bcd0326bd0283024a7075626c69635f6b65798203582c302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb83018302581dc749a1b9b5c123bdc745883bd4901e311ae90a586a6825d52d99739e0283024a7075626c69635f6b65798203582c302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f1748302581dcec168cc1c818e1bcbf8622c2bf05ead8f63ad21d04e0498fd64fce80283024a7075626c69635f6b65798203582c302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a8301830183018302581dcff1f1e404582ce832e51ef54dd196540af764448da6720f443d28860283024a7075626c69635f6b65798203582c302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab38302581dd0d9bd9de8bde02b0179227caefdb94de48a74231c4aa88c6bba74780283024a7075626c69635f6b65798203582c302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be3283018302581dd52a16f3dc32065f858393468f14585efb701a4cad05c445ba75a1dd0283024a7075626c69635f6b65798203582c302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea288302581dd5607c139fbf027070f48977431c08c47c96199ed4f75642774408930283024a7075626c69635f6b65798203582c302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc830183018302581dd7d81b675fb361616868d4f31793e064c6619a7a3fb4715d340fc2e00283024a7075626c69635f6b65798203582c302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d1548938302581ddbcb3c89c77e2a4bb43c2244752161f5c08d759f97acdca282af8f9d0283024a7075626c69635f6b65798203582c302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b87583018302581ddce94d09354a1751d180df5fe0a8f352c7396bd63c338f8f91fdf5340283024a7075626c69635f6b65798203582c302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d8302581ddeba05a0e095a26bf12507f792863507d32fc012be8e4f4d705dbb7e0283024a7075626c69635f6b65798203582c302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f6700358301830183018302581de058cf7bdd01bc75227405ebfab94752a4d2f43ff113b5ca68e4df4f0283024a7075626c69635f6b65798203582c302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d38302581de8373870d8066d971c415cbdaf1611bcf84cd3644d22b389de95d9e40283024a7075626c69635f6b65798203582c302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd83018302581de85c5ec8051f35f9e3c915e3dbb3c32af6506b2a668b74c0bd003c850283024a7075626c69635f6b65798203582c302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b938302581ded8915a3c359b8e16da92f2c42d6fbcd34fcc23a011770fba5734c990283024a7075626c69635f6b65798203582c302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d830183018302581df032935f1185096317778e4206e8de237a7e090ba0b3289582c0fff50283024a7075626c69635f6b65798203582c302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d238302581df2be1c26024bc9e103d662dfd167cbfe861400e7748b7778e01adc790283024a7075626c69635f6b65798203582c302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c83018302581df92bb6e3332495ffd40fcf37af5fe9482b0667f3d4063d598fe8e8fa0283024a7075626c69635f6b65798203582c302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff8302581dfd8e4151c4762d9b4b6b36e08d36a49b83e9458a5040a1dc26d63b530283024a7075626c69635f6b65798203582c302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e5383024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae8302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe83018302581dfc7d15b27df96b3e98731463a2af13d6e43cf426d0cb487a7120091502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000c0000001014a0000000000cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009053b542dc8d758237ada280dc505846c327b0c43b7e26c0ee6f7729cdebd43639d959c10fe1aa058622437d7ec34a920035dfd55de4f40937b4c419e02b517eb2b7a6aa7f42644352202f8f4c67e726ca8f168ab588764261dbcc3a5c8113938302581dfe320f2fbbb9d49c8e6edbcc9d85ec096bf645351d95bbddf556f7db02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000130000001014a00000000013fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b2a6741083996223f83384666740a3eacf8ce78c6d39fecdee582a5b243c158706bb215f396ba0429d2188df9ef176721306d048aaa58f6b413457dd63ef1a56de2378e71ca444201e29e490e3790098e92ee85e0142a33ef806c8388aec6baf83024474696d6582034998e98fdac4dbb6c417697369676e61747572655830957863c11a54909e3ade079efa35c27ce5a350cf483f889c6297112f36d70170e114d305fe720dbc84c70c93eb64c221`, + localApplication: `d9d9f7a26474726565830182045820b06c8a8b1f5eb2cf3c0ecb21e8f4384057ca8a6f9c3c615e819c1a53d5c89e1f83018302467375626e65748301830183018301830183018302581d033a778c6c9eac039fdda83dc90d2c12eb846de85c475e36ead6715c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000100000001014a00000000010fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aa544423a45fb0388c43703a159a96208cafd17f01f1e7c400676d2c69f62195f6a5bb564d564f7967047def10b48c22003f38c5d56961d0c47879f9212b93cd206620114bd9e1d4db22d04e294d37e1ff42cedf2322ebf60702c88325c606808302581d0f033c5125db4f6b32e426268df663a5ce98fe3b531d962e1a7a87fa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001c0000001014a0000000001cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100913f6a84f05736c2dd0b2dc3ec838e95419ae0ef426d556f50152a445b9c232495bc051cdabbd46a7bd8879b09720cbb13b3bcd265ff75567dcbf04e9ae1c3a2141229a6757605625b093c5ca34336393e5a88b78df7b0a3a7e5b9841716d0a483018302581d10b647334a5406987796b2f8b6b14cd32f0876d3fd4fc8452105832502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000180000001014a00000000018fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084cbe7a009258947dc30983fede3b98b34cfee5e5d1ae4e1e72891590738ca9a58f9f6364b359a5448b6c5e20ee5310300e4c0c9cca29b07e2d73208f8ec6cd1fb6ca46c168c43393f9e050a05448836b0a6f5c75d2a398c999c42d7c981cb898302581d12790e7661fccd3d4fc83138dcaffd9f188e867b45ae10c8836dd0b802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000150000001014a00000000015fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610086d88ebbd2f1663e65d3a3ff07e8ee9fa420d08b9a6822919f224b8b802d5d9be150dc493f84c23e73a0cc1d2c2ee28709ff140000128fcd5dfbd7b457ef3af344766d7ff0924fe7a7f456ded77ca6de3b1b406b710c4eaed7287ab9a3527669830183018302581d17f67590355e7123aeffabce4c1bddf3a0efd53a2c2e3f6228fc3adf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000d0000001014a0000000000dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100850e5edfb0685d36757643be011f5d3378fef0bfb9b0ef67429912ebb9237f5028979eb33779df7c63acf59b78eba4d904c6b4abad529b9e8e2195321e287f8c51900f5b440872719c7ac56e381c8063bc6176f8e4b74d06de669493e49055678302581d1cc5ad563f1bce937c305be3d12bef627f73b727808672dc2432aef902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001f0000001014a0000000001ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610093907710f0f89af4b5bd35a28e0162171e2f411d11e152152e88e3da4c2079799e4eac7a3a9f3923fb63b33b68928ae91652fae5c2ccce872173632648ef4dd79ae7e8c15b9e97f132ea34a4349506d281bd66bbd0c3afdd78cbe026927a8c1683018302581d2c55b347ecf2686c83781d6c59d1b43e7b4cba8deb6c1b376107f2cd02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000060000001014a00000000006000ae0101824a00000000006000b001014a00000000006fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610090075120778eb21a530a02bcc763e7f4a192933506966af7b54c10a4d2b24de6a86b200e3440bae6267bf4c488d9a11d0472c38c1b6221198f98e4e6882ba38a5a4e3aa5afce899b7f825ed95adfa12629688073556f2747527213e8d73e40ce8302581d2d030caf397e446c03cece4fd072acce432c75b6a700592e73f5d13302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000090000001014a00000000009fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100805230c2da9687218fdfa49bddab093578c2e8a10b27d69fdda097f286abccdae2541c711e3ca771202bfc9b366bf61b17e9f1173d7c9a6eaaa907ccdba3bc86764bc1d552437c4948038e1018a9c49e444189cd55358e37a6f879d88c0a26938301830183018302581d2ecc29447b0eef6c241dcfdf7dab077093ccd6a1266be0fe9c9b127602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000e0000001014a0000000000efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610091541cdc7b65c4828286c911602d9438de5649d698b60fc06aec73589395d0bca71746524ed2ff17b2c8da9fbc897f0f07a40b204871b6fe96d45ef10b51d1f1d530d0679a5db82de96929805fa17c737994ebcc2312d2a25bd94747ecf8f34b8302581d2f1a9548062f52ca0e90e72a4a97cb324fa1dfb62b564ef1b29f38aa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000160000001014a00000000016fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084698ba18ea46f2041353c98fdf6980235fab99a6f5b83c5de3bb32a7ad190ef26fd2afad2dd2e4fb5eaebc4fd177e3c11ed29fb7dab26a6909d366c185cb9d964d3ff3a8e71c0c28adfca715698f679cef6b6346106a78c9f8d3f8e9a66e88083018302581d30580a1a7643049513f8f7d6ffe6f51000570345a63160cab7784c5902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000a0000001014a0000000000afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610085c8811b0caf15f9ad2e34f1841a7820dd1a70642e21362748bf0927c6fd67ddc0c1329fdd840e06a16d383023c4c00f062f173e628528eb801c15258e2e417d511fe4ba3c175469570cc8e1338e5457ed6b31b72b139b537554f00b14fd69158302581d33c2f9ea0f8e2c53e6e54766dbc6cec8da6787b0154260a99925f7a802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000f0000001014a0000000000ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b31b406c9f6648695a88154ae2e4f5fe87883d4ad81c2844c5571b2d91d401cdd40836e763a7c18dccb84629b0d808f7142c3175bc8231dc09bd53637efd6f2568801385ec973d34e6eef9c8c8280a9f4a114163a43a8540941ba367f0c7cb28830183018302581d4164d0b890d702b3cf4f1121e504f24b0f0d94da0e935221220f3a3702830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000040000001014a00000000004fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008ac081401431767be18972543b3ee45c6769c447fb727a1abd72bc1c12487d5c1169522857cbb8d89273847f669563af05833ecee73afa853a16de4aa5549ffea02f3280167129fe026d8aeadc959d73b44570dd18eb9c6ba313edd0a45282748302581d43dcaf1180db82fda708ce3ac7a03a6060abde13e9546c60e8cce65d02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000701014a00000000000000070101824a000000000210000001014a00000000021fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008675b634a43e39726238cfe39c9518bc3e3225cb6f5a8479bfcf2b608fba6f8524dcb80f35a8ae44b47f262f0a6620d41279f06fe0c53a739fcca01a48926fe651a3519b5b329ffbecc9f0cb908b098dd3e8845cfb99c56379e049ac465ec80683018302581d45178b66a407a4d59c0a4d6733bda2ce3f37c111b4257ec41908f4f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000070000001014a00000000007fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100955f52f73c2dec59a637b294e50b934db5d6de29e73bbcf84e7d86a4ac41bad7b539f9817ade8916961d9dd6bf9257010d5857156e8fe6aafcf6fd068795e70bd3399b3411300c9ccc8eba0d068c10e4cfb6f4e27d195b1ead785d618eb393b98302581d4f82b62edffa3fa4e6a5c48327ce8cfb3f850db2e5abc90e955d77f002830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000230000001014a00000000023fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a32153e6271817b87d91d1cd0b727119a2eda7355ee7ef64ee9f10bf6396aed6899a5475d37d6cc51c6a741397d3685318e8e0dabec1b1994112e2c4da3262033ea18fc667dd0ead6e0a151f4d884ee644b799c05e56f502d42f22ffabbca09783018301830183018302581d581b5aa2f10c5f221e45de74a2cecafd3da076be39db0907cbf554bb02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000170000001014a00000000017fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ad28a2bfaae6c9248ef1ea3e4f4bc6ea29101ce533b0075349bb86a88535c216ce434c9aa018b87465441dd997ed23270e2b21e126c74f16293bdba29033e858ecd50bda7be1b692a401e154eb87b65dcf0983635e578e3ea2f6d9b02c7c79dc8302581d5c76b3988ed788abc32d2ea13331bc29debc4f24d19a8f41417eaeb102830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000120000001014a00000000012fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ae04b0b53b4f62ce4a789a6b0f0c9e66dfa5868cb2f3e0e7f628ca6fb93e4f33879a8fe47a23485f30f5a68472c4fd460bc29923b851023792437af3cc690891740a676ffbeb8d836e6ed5b2409dcb32104dde956743e51d3b0e23222ac9487b83018302581d601575e11b35c86fad26229748379d1d9693312bff16e2bca1c1cdd902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000220000001014a00000000022fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100987ce1744dba1052580903a85d6ac697f1619a9ce3119cfa8b06697013a9e2a799b2078763c3119023981410523c52030e00b5d3fd6663e85c59473366ac9846fee6fe9b415c69a96ee9f0f7768673839211f52b19fab495978f100f982d0f618302581d61b718d0b8c31db1ef09451eadd068887c1df5f37e7de0a3afc5a56a02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000010000001014a00000000001fffff0101824a00000000006000af01014a00000000006000af010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084ec5e445306312c9d94e1d1a37cb7d3a6a5a6f86bc85f30ba9bc5a261ab8a37f814786b8e1bae8aa004afb1bba510a411bde94c2a494fb2caa9155abfe0dfc19046854929f7d67726c83e572faa4b812c96196221ed549ef27fb9fb78c2e06d830183018302581d6a8f67d86ecc8307048038ad71599458c131b531dc9bb0b691940db902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000080000001014a00000000008fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008c4e7e55222f134fc3a633620701f6d25a2a5eecd71a3d49c36846ff5d5cd98d382764e81c5869e95e0feb61d132a9f20d4822f7c5bc4c8ed7cb59d52884736864478f1b0e81b1892cfa01ccc7b2fa5fff31586096217c599ff2652368b2f1948302581d806b712f189b5651e7349743820c5f45a81592464c25048e79f25cd602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000b0000001014a0000000000bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100af4f78ab97b3cdc76075f552e83842d5b07c4e35f9f83614b4976e70751f94ea1bc5ebec45892086f4344ea8fb3f7e3a053da28155c0ac501ab6a26ccfc60e729d0bbe91bf0772837cf2911fb4e952d066daf14ea45c08c2104cc69bf221a4f883018302581d9365a8c9f27f413060850835d1859a415c67575cd30c04a183fd096302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001e0000001014a0000000001efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008a91b23b098aeb7dd5e525717f0c29d3967c5f4e61d0b5c7c697172e6f5682aa5e423d42077695c517aba7e3b636da940938d7d5caeee26c3c71cc6888f542c5966e60ea4d91ddb95ad0994283171097e325026bef003128b44641056c86d04a8302581d9c7d405764f197f3611b7a6d3f7756f0c5f7a7dbb02504da09d21f2902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000140000001014a00000000014fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a5d492126a99c65b09c53fe75b5ad8e24d1556a9db2bfe74dffae1816165405923e6fa2b4c58e5adbddf99575fb83b1a06736dc6e4ce20eabf54ca6ca574d3af0d14ef8ae143f9339cf16e62e72b5dfd47d1d642e731c5ee853a00fef69d70db8301830183018302581d9dfdc32362ee85e05f3f36ad947cc62cd276d7b8687d239637de118c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000200000001014a00000000020fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a0e2dffe693d3c75cabacb68760466611df84ddd06e42954cfdf85c665841801319dcaff52cbad03bc37b64061c562920b77389679afb7f888bfc4a36b4772e6cf41374ff8714101f390056e26de88611c93c22eb90e96fe6370ac246ea6faa28302581da22bac610f4e17278d2a0f2cf83a2e2556f6594371615940334d31d302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000190000001014a00000000019fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100afd62f0314d4f866c512d95a649db5c3241d6624b15c62b2fdd3d29af2dee832e3f1af39c60c2389cc4826c181b82d01133dc9f10f727b315c5bf18de580b70a8d8800c570b99b89514922a6476fbf76591e022ca68cdb4b3610e7f642d9bfa083018302581dacc260d8fc5e1421c9aacc9bb5e1a1147aa15bf15304831ba734b9f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000050000001014a00000000005fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aaeeda397b35cf5473ebc1792d7aadf102d085aca490551906f73c4108df12b8478b13b73c8953c148235d0efe99427017451ce8cdd0bd9ee81ede26221c4c3ff0f49af21c6402e6d35fc4c3c61352ff3d8767a3cc8d7ee58a2b50abbbdf2dbe8302581dba488d13a5dd7649d8093fe4897df1cc7c728ab64c856a78c4b97d6a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000110000001014a00000000011fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610088dc7b350da56b6ff41f08332636ab9d162bf3a293a65f795089ef8b8fe9a5af91c51f67e34729408bfdf21b110b7ca405c98af5c1a9ca2ff2995e27ed4e9d0325bd8fa92623e31879247ea508729cf46e0dd2804bea34f3acabe4aa4ef0b973830183018302581dba58b21125381b0567e61f3f2ecd65f37710316084ee791cdfdb4a1a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001d0000001014a0000000001dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100852c9ff8de8c5964d4b6209feaa6f7675a3afab47ab8ec9b67b111ddc158983fd7b034ffcce4958c60ec37040938eb1e18633d7e9a086153e53755008642bf9f87db91d6709a65f242b9e4e31dbeba64a684745a76dee8cfe6729c5ab3c52f148302581dbd26ec81a3360bc8050673531b92b27988bf2a893b506f80e40c11cf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001a0000001014a0000000001afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008e41463b1893989f425af308744b916d9034e83d9382b03b1e30b117fee21a4e1ff03fc59d54f4bc710a51ba04a1e21d0fd863b5329bf68ee67c6d15f82d4a673775604a1c719cb6ce200b2710e425663c7060e5e98e032beda6835c9010158d83018302581dbfca29efbb1f48b67849f2c9bab8a7856fd57882fb99c8ad497cf55202830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001b0000001014a0000000001bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100846c395853586d94a2e546485537d4f81bb7820d5e82c274b507d592d59353a165dd8ed432e8b7c0792d90d52cf968c20c5ae06d69817d814a7ee2d54130baf49b192186890621abc70046ea9939978df172fc1cd16aded5f227cd8c27bcdb658302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb47830183018302581dcff280e32d7f5ccd2246882f94afb20f54ca61a21765e712d43d2789028301830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000001014a00000000000000060101824a000000000000000801014a00000000000fffff01018302446e6f64658301830183018301830183018302581d24c56af1a646bdee74ba2c8cad88ba6e4f2ee098f99055bd0e9640c60283024a7075626c69635f6b65798203582c302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e7988302581d2995ce7aeea59467fb3a634b434dcc965ba147ba2f9804ea2e8f1b5c0283024a7075626c69635f6b65798203582c302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef63683018302581d32442407acaa5ea43e62b1dac1ac20119c64cfd5c23cc0ae1508ee250283024a7075626c69635f6b65798203582c302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe9828508302581d325c033f6f1fd07e7bcb57b7ab8a24b1abf73beffd1ca17ed88cf3ab0283024a7075626c69635f6b65798203582c302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff830183018302581d3c4d78ddee38b0eb2910a004c3a7362017a5c14a9346007a65829ebb0283024a7075626c69635f6b65798203582c302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf8302581d3eda90ac6d378ae7c7917f94fd61c0e685b22f5ced5ad0735af250230283024a7075626c69635f6b65798203582c302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af36083018302581d46e3cfcd286afe6a1f4572d2350facd38f0f8647d58c499e5bc5039d0283024a7075626c69635f6b65798203582c302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd338302581d53e39463ea45264875d00c508e4bb1325722a96a00053dbc2662fc5e0283024a7075626c69635f6b65798203582c302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b58301830183018302581d607eb9a00ad3b4411f5911276879c618a6895fd57fe6c9b0a879f9b00283024a7075626c69635f6b65798203582c302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b998302581d6ad96c153126046203336a5174a04b30f0adea457c2298b976ab674e0283024a7075626c69635f6b65798203582c302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b83018302581d8156c471c227bb551da5ff7603b22e4a1c87f711292502aef5cdae320283024a7075626c69635f6b65798203582c302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da8302581d8465e6cc28f5be102098a7ae96264f6ec72f1c4a858b491cd60e55a50283024a7075626c69635f6b65798203582c302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f830183018302581d8cf60ae159aabf4207328d2a5524675d5c157a8aa1f80a52ec44221b0283024a7075626c69635f6b65798203582c302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b8302581d904ebdc04493093d1f6f7d37a6a91c5fa6616ddf19771fd346cd5aeb0283024a7075626c69635f6b65798203582c302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea242683018302581d9f00ea7b0826aa145abd4348c3656133ed84e188780f63c5151009bf0283024a7075626c69635f6b65798203582c302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e8302581da7835a01f618d7b552d0eae3310aebd0cac6ea2bf02865472f4546fc0283024a7075626c69635f6b65798203582c302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e83018301830183018302581da7bad7420d9671f6992d64ca541ce75fe04a7c51c2561dd9aad945880283024a7075626c69635f6b65798203582c302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d6938302581db1dee04210dded1afbc7e5d31492d7f0b1379b8fea5b203d30b3c03e0283024a7075626c69635f6b65798203582c302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb83018302581db858dfb622c91c481e81e9cdbfb7ab78da5dbb7a09d2e321787a0c1a0283024a7075626c69635f6b65798203582c302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f8302581db8e453c069995d67a5253c43ec43b4b39038d272f4c67fa9155e6e490283024a7075626c69635f6b65798203582c302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287830183018302581dc0588b3d010691102a6dc738ab5517afaa4f27882a3554b006d2b3920283024a7075626c69635f6b65798203582c302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc68302581dc6f9bfce466cc84184b6c0993a1bf50dabc45f0f5a591c8bcd0326bd0283024a7075626c69635f6b65798203582c302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb83018302581dc749a1b9b5c123bdc745883bd4901e311ae90a586a6825d52d99739e0283024a7075626c69635f6b65798203582c302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f1748302581dcec168cc1c818e1bcbf8622c2bf05ead8f63ad21d04e0498fd64fce80283024a7075626c69635f6b65798203582c302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a8301830183018302581dcff1f1e404582ce832e51ef54dd196540af764448da6720f443d28860283024a7075626c69635f6b65798203582c302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab38302581dd0d9bd9de8bde02b0179227caefdb94de48a74231c4aa88c6bba74780283024a7075626c69635f6b65798203582c302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be3283018302581dd52a16f3dc32065f858393468f14585efb701a4cad05c445ba75a1dd0283024a7075626c69635f6b65798203582c302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea288302581dd5607c139fbf027070f48977431c08c47c96199ed4f75642774408930283024a7075626c69635f6b65798203582c302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc830183018302581dd7d81b675fb361616868d4f31793e064c6619a7a3fb4715d340fc2e00283024a7075626c69635f6b65798203582c302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d1548938302581ddbcb3c89c77e2a4bb43c2244752161f5c08d759f97acdca282af8f9d0283024a7075626c69635f6b65798203582c302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b87583018302581ddce94d09354a1751d180df5fe0a8f352c7396bd63c338f8f91fdf5340283024a7075626c69635f6b65798203582c302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d8302581ddeba05a0e095a26bf12507f792863507d32fc012be8e4f4d705dbb7e0283024a7075626c69635f6b65798203582c302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f6700358301830183018302581de058cf7bdd01bc75227405ebfab94752a4d2f43ff113b5ca68e4df4f0283024a7075626c69635f6b65798203582c302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d38302581de8373870d8066d971c415cbdaf1611bcf84cd3644d22b389de95d9e40283024a7075626c69635f6b65798203582c302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd83018302581de85c5ec8051f35f9e3c915e3dbb3c32af6506b2a668b74c0bd003c850283024a7075626c69635f6b65798203582c302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b938302581ded8915a3c359b8e16da92f2c42d6fbcd34fcc23a011770fba5734c990283024a7075626c69635f6b65798203582c302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d830183018302581df032935f1185096317778e4206e8de237a7e090ba0b3289582c0fff50283024a7075626c69635f6b65798203582c302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d238302581df2be1c26024bc9e103d662dfd167cbfe861400e7748b7778e01adc790283024a7075626c69635f6b65798203582c302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c83018302581df92bb6e3332495ffd40fcf37af5fe9482b0667f3d4063d598fe8e8fa0283024a7075626c69635f6b65798203582c302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff8302581dfd8e4151c4762d9b4b6b36e08d36a49b83e9458a5040a1dc26d63b530283024a7075626c69635f6b65798203582c302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e5383024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae8302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe83018302581dfc7d15b27df96b3e98731463a2af13d6e43cf426d0cb487a7120091502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000c0000001014a0000000000cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009053b542dc8d758237ada280dc505846c327b0c43b7e26c0ee6f7729cdebd43639d959c10fe1aa058622437d7ec34a920035dfd55de4f40937b4c419e02b517eb2b7a6aa7f42644352202f8f4c67e726ca8f168ab588764261dbcc3a5c8113938302581dfe320f2fbbb9d49c8e6edbcc9d85ec096bf645351d95bbddf556f7db02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000130000001014a00000000013fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b2a6741083996223f83384666740a3eacf8ce78c6d39fecdee582a5b243c158706bb215f396ba0429d2188df9ef176721306d048aaa58f6b413457dd63ef1a56de2378e71ca444201e29e490e3790098e92ee85e0142a33ef806c8388aec6baf83024474696d65820349d6d2f0d7dbd5b6c417697369676e61747572655830ae1324ba253591ef6c5e58053d0c266ad2914c63a730e9f0dbac7763be24a1fc20fa2fde4847a07d0089c8984774129b`, +}; diff --git a/packages/agent/src/agent/http/http.test.ts b/packages/agent/src/agent/http/http.test.ts index c8a567072..c7377066d 100644 --- a/packages/agent/src/agent/http/http.test.ts +++ b/packages/agent/src/agent/http/http.test.ts @@ -813,12 +813,15 @@ describe('default host', () => { }); describe('fetchSubnetKeys', () => { - it.only('should fetch subnet keys for a given canister', async () => { + it.skip('should fetch node keys on application canisters for mainnet.', async () => { jest.useFakeTimers(); - const abbbb = (await import('isomorphic-fetch')).default; - const agent = new HttpAgent({ fetch: abbbb, host: 'https://icp-api.io' }); - await agent.fetchRootKey(); - const subnetKeys = await agent.fetchSubnetKeys('erxue-5aaaa-aaaab-qaagq-cai'); //? + // const abbbb = (await import('isomorphic-fetch')).default; + // const agent = new HttpAgent({ fetch: abbbb, host: 'https://icp-api.io' }); + // await agent.fetchRootKey(); + // const subnetKeys = await agent.fetchSubnetKeys('erxue-5aaaa-aaaab-qaagq-cai'); //? // const subnetKeys = await agent.fetchSubnetKeys('ryjl3-tyaaa-aaaaa-aaaba-cai'); //? + + // docs bkyz2-fmaaa-aaaaa-qaaaq-cai + // docs system bnz7o-iuaaa-aaaaa-qaaaa-cai }); }); diff --git a/packages/agent/src/certificate.test.ts b/packages/agent/src/certificate.test.ts index 29c7b2db2..4ddaf98ec 100644 --- a/packages/agent/src/certificate.test.ts +++ b/packages/agent/src/certificate.test.ts @@ -9,6 +9,7 @@ import { fromHex, toHex } from './utils/buffer'; import { Principal } from '@dfinity/principal'; import { decodeTime } from './utils/leb'; import { lookup_path } from './certificate'; +import { goldenCertificates } from './agent/http/__certificates__/goldenCertificates.test'; function label(str: string): ArrayBuffer { return new TextEncoder().encode(str); @@ -256,3 +257,218 @@ test('certificate verification fails if the time of the certificate is > 5 minut }), ).rejects.toThrow('Invalid certificate: Certificate is signed more than 5 minutes in the future'); }); + +describe('node keys', () => { + it('should return the node keys from a mainnet application subnet certificate', async () => { + const { mainnetApplication } = goldenCertificates; + jest.useFakeTimers(); + jest.setSystemTime(new Date(Date.parse('2023-09-27T19:38:58.129Z'))); + const cert = await Cert.Certificate.create({ + certificate: fromHex(mainnetApplication), + canisterId: Principal.fromText('erxue-5aaaa-aaaab-qaagq-cai'), + rootKey: fromHex(IC_ROOT_KEY), + }); + + const nodeKeys = cert.cache_node_keys(); + expect(nodeKeys).toMatchInlineSnapshot(` + Object { + "nodeKeys": Array [ + "302a300506032b65700321005b0bdf0329932ab0a78fa7192ad76cf37d67eb2024739774d3b67da7799ebc9c", + "302a300506032b65700321009776d25542873dafb8099303d1fca8e4aa344e73cf5a3d7df5b40f9c8ed5a085", + "302a300506032b6570032100e5a9296571826cc3be977490296405ae9da1da7d59cce1642421bc19804cc310", + "302a300506032b6570032100b761a93e418ab326d2d106d9137268d407f7c8a743127e2833899933337eb09b", + "302a300506032b6570032100afd56377478dc711cbfe043022423d9f7f7decb709de7501545923274186883f", + "302a300506032b6570032100ce76939540cac8de3475329517c684e0562fb6cbad1db67fb60362808bdaf462", + "302a300506032b65700321001645a7cb7f3980dd6f9ca6ca0966a4d4bde9d57d90df0f10fc31eac960a8ab41", + "302a300506032b65700321000c441fada59fea1cf21ebc157392338ca56775011c4c5630782823e2a7938c8f", + "302a300506032b6570032100f408b362fc92255a4776666179eba4b9dfbd6d3b9f6b87b3abb80f726878e0a9", + "302a300506032b6570032100cab5efd3205fa4b3409b6f5e421ebd776dd36ea6108820c624478016df9c6a20", + "302a300506032b6570032100e650a1cc4bf264cdc80442d33d7bd00e3de1f15ddd48c7ac0f2fe582f599d954", + "302a300506032b6570032100be0759d30172a9dfdcc2e11b92e8daf1753c45f126b8413c8e57e621b5626d37", + "302a300506032b65700321006b8ef72b0efb4ef38dc957097cb26dfcf24b083dd6b2b5fcd5269657cd8e59a7", + ], + "subnetId": "pae4o-o6dxf-xki7q-ezclx-znyd6-fnk6w-vkv5z-5lfwh-xym2i-otrrw-fqe", + } + `); + }); + + it('should return the node keys from a mainnet system subnet certificate', async () => { + const { mainnetSystem } = goldenCertificates; + jest.useFakeTimers(); + jest.setSystemTime(new Date(Date.parse('2023-09-27T19:58:19.412Z'))); + const cert = await Cert.Certificate.create({ + certificate: fromHex(mainnetSystem), + canisterId: Principal.fromText('ryjl3-tyaaa-aaaaa-aaaba-cai'), + rootKey: fromHex(IC_ROOT_KEY), + }); + + const nodeKeys = cert.cache_node_keys(); + expect(nodeKeys).toMatchInlineSnapshot(` + Object { + "nodeKeys": Array [ + "302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e798", + "302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef636", + "302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe982850", + "302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff", + "302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf", + "302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af360", + "302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd33", + "302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b5", + "302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b99", + "302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b", + "302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da", + "302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f", + "302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b", + "302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea2426", + "302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e", + "302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e", + "302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d693", + "302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb", + "302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f", + "302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287", + "302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc6", + "302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb", + "302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f174", + "302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a", + "302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab3", + "302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be32", + "302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea28", + "302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc", + "302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d154893", + "302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b875", + "302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d", + "302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f670035", + "302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d3", + "302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd", + "302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b93", + "302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d", + "302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d23", + "302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c", + "302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff", + "302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e53", + ], + "subnetId": "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe", + } + `); + }); + + it('should return the node keys from a local application subnet certificate', async () => { + const { localApplication } = goldenCertificates; + jest.useFakeTimers(); + jest.setSystemTime(new Date(Date.parse('2023-09-27T20:14:59.406Z'))); + const cert = await Cert.Certificate.create({ + certificate: fromHex(localApplication), + canisterId: Principal.fromText('ryjl3-tyaaa-aaaaa-aaaba-cai'), + rootKey: fromHex(IC_ROOT_KEY), + }); + + const nodeKeys = cert.cache_node_keys(); + expect(nodeKeys).toMatchInlineSnapshot(` + Object { + "nodeKeys": Array [ + "302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e798", + "302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef636", + "302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe982850", + "302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff", + "302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf", + "302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af360", + "302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd33", + "302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b5", + "302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b99", + "302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b", + "302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da", + "302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f", + "302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b", + "302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea2426", + "302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e", + "302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e", + "302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d693", + "302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb", + "302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f", + "302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287", + "302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc6", + "302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb", + "302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f174", + "302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a", + "302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab3", + "302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be32", + "302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea28", + "302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc", + "302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d154893", + "302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b875", + "302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d", + "302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f670035", + "302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d3", + "302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd", + "302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b93", + "302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d", + "302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d23", + "302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c", + "302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff", + "302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e53", + ], + "subnetId": "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe", + } + `); + }); + + it('should return the node keys from a local system subnet certificate', async () => { + const { localSystem } = goldenCertificates; + jest.useFakeTimers(); + jest.setSystemTime(new Date(Date.parse('2023-09-27T20:15:03.406Z'))); + const cert = await Cert.Certificate.create({ + certificate: fromHex(localSystem), + canisterId: Principal.fromText('ryjl3-tyaaa-aaaaa-aaaba-cai'), + rootKey: fromHex(IC_ROOT_KEY), + }); + + const nodeKeys = cert.cache_node_keys(); + expect(nodeKeys).toMatchInlineSnapshot(` + Object { + "nodeKeys": Array [ + "302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e798", + "302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef636", + "302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe982850", + "302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff", + "302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf", + "302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af360", + "302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd33", + "302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b5", + "302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b99", + "302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b", + "302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da", + "302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f", + "302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b", + "302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea2426", + "302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e", + "302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e", + "302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d693", + "302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb", + "302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f", + "302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287", + "302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc6", + "302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb", + "302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f174", + "302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a", + "302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab3", + "302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be32", + "302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea28", + "302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc", + "302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d154893", + "302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b875", + "302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d", + "302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f670035", + "302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d3", + "302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd", + "302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b93", + "302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d", + "302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d23", + "302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c", + "302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff", + "302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e53", + ], + "subnetId": "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe", + } + `); + }); +}); diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index 092a32732..fc50224c1 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -1,12 +1,10 @@ import * as cbor from './cbor'; import { AgentError } from './errors'; import { hash } from './request_id'; -import { compare, concat, fromHex, toHex } from './utils/buffer'; +import { concat, fromHex, toHex } from './utils/buffer'; import { Principal } from '@dfinity/principal'; import * as bls from './utils/bls'; -import { decodeLeb128, decodeTime } from './utils/leb'; -import { lebDecode, PipeArrayBuffer } from '@dfinity/candid'; -import { assert } from 'console'; +import { decodeTime } from './utils/leb'; /** * A certificate may fail verification with respect to the provided public key @@ -170,6 +168,8 @@ export class Certificate { blsVerify, options.maxAgeInMinutes, ); + + console.log(toHex(options.certificate)); await cert.verify(); return cert; } From 6634162fc5c5a6c158acc42a5ba79c6c669ab266 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 27 Sep 2023 15:49:02 -0700 Subject: [PATCH 5/8] fixing canisterStatus test for extra call --- packages/agent/src/canisterStatus/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/agent/src/canisterStatus/index.test.ts b/packages/agent/src/canisterStatus/index.test.ts index 15b4943f3..5691d8fd1 100644 --- a/packages/agent/src/canisterStatus/index.test.ts +++ b/packages/agent/src/canisterStatus/index.test.ts @@ -188,6 +188,6 @@ describe('Canister Status utility', () => { expect(status.get('asdf' as unknown as Path)).toBe(null); // Expect undefined for unset value expect(status.get('test123')).toBe(undefined); - expect(consoleSpy).toBeCalledTimes(2); + expect(consoleSpy).toBeCalledTimes(3); }); }); From ca980c00c8dbc3f9776f2fb31a855cbd18181519 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 28 Sep 2023 14:51:53 -0700 Subject: [PATCH 6/8] tests passing --- .../goldenCertificates.test.ts | 4 + packages/agent/src/certificate.test.ts | 10 ++- packages/agent/src/certificate.ts | 84 ++++++++++++++----- packages/agent/src/polling/index.ts | 14 ++-- packages/principal/src/index.ts | 4 - 5 files changed, 83 insertions(+), 33 deletions(-) diff --git a/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts b/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts index 24babb3d4..a5f89bae5 100644 --- a/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts +++ b/packages/agent/src/agent/http/__certificates__/goldenCertificates.test.ts @@ -1,3 +1,7 @@ +test.skip('goldenCertificates', () => { + // file needs to include at least one test +}); + export const goldenCertificates = { mainnetSystem: `d9d9f7a2647472656583018204582064abbe468e0569dc74af0a631fd9205141a6bf956036e09fd193428a6543eaa083018302467375626e65748301830183018301830183018302581d033a778c6c9eac039fdda83dc90d2c12eb846de85c475e36ead6715c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000100000001014a00000000010fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aa544423a45fb0388c43703a159a96208cafd17f01f1e7c400676d2c69f62195f6a5bb564d564f7967047def10b48c22003f38c5d56961d0c47879f9212b93cd206620114bd9e1d4db22d04e294d37e1ff42cedf2322ebf60702c88325c606808302581d0f033c5125db4f6b32e426268df663a5ce98fe3b531d962e1a7a87fa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001c0000001014a0000000001cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100913f6a84f05736c2dd0b2dc3ec838e95419ae0ef426d556f50152a445b9c232495bc051cdabbd46a7bd8879b09720cbb13b3bcd265ff75567dcbf04e9ae1c3a2141229a6757605625b093c5ca34336393e5a88b78df7b0a3a7e5b9841716d0a483018302581d10b647334a5406987796b2f8b6b14cd32f0876d3fd4fc8452105832502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000180000001014a00000000018fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084cbe7a009258947dc30983fede3b98b34cfee5e5d1ae4e1e72891590738ca9a58f9f6364b359a5448b6c5e20ee5310300e4c0c9cca29b07e2d73208f8ec6cd1fb6ca46c168c43393f9e050a05448836b0a6f5c75d2a398c999c42d7c981cb898302581d12790e7661fccd3d4fc83138dcaffd9f188e867b45ae10c8836dd0b802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000150000001014a00000000015fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610086d88ebbd2f1663e65d3a3ff07e8ee9fa420d08b9a6822919f224b8b802d5d9be150dc493f84c23e73a0cc1d2c2ee28709ff140000128fcd5dfbd7b457ef3af344766d7ff0924fe7a7f456ded77ca6de3b1b406b710c4eaed7287ab9a3527669830183018302581d17f67590355e7123aeffabce4c1bddf3a0efd53a2c2e3f6228fc3adf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000d0000001014a0000000000dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100850e5edfb0685d36757643be011f5d3378fef0bfb9b0ef67429912ebb9237f5028979eb33779df7c63acf59b78eba4d904c6b4abad529b9e8e2195321e287f8c51900f5b440872719c7ac56e381c8063bc6176f8e4b74d06de669493e49055678302581d1cc5ad563f1bce937c305be3d12bef627f73b727808672dc2432aef902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001f0000001014a0000000001ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610093907710f0f89af4b5bd35a28e0162171e2f411d11e152152e88e3da4c2079799e4eac7a3a9f3923fb63b33b68928ae91652fae5c2ccce872173632648ef4dd79ae7e8c15b9e97f132ea34a4349506d281bd66bbd0c3afdd78cbe026927a8c1683018302581d2c55b347ecf2686c83781d6c59d1b43e7b4cba8deb6c1b376107f2cd02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000060000001014a00000000006000ae0101824a00000000006000b001014a00000000006fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610090075120778eb21a530a02bcc763e7f4a192933506966af7b54c10a4d2b24de6a86b200e3440bae6267bf4c488d9a11d0472c38c1b6221198f98e4e6882ba38a5a4e3aa5afce899b7f825ed95adfa12629688073556f2747527213e8d73e40ce8302581d2d030caf397e446c03cece4fd072acce432c75b6a700592e73f5d13302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000090000001014a00000000009fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100805230c2da9687218fdfa49bddab093578c2e8a10b27d69fdda097f286abccdae2541c711e3ca771202bfc9b366bf61b17e9f1173d7c9a6eaaa907ccdba3bc86764bc1d552437c4948038e1018a9c49e444189cd55358e37a6f879d88c0a26938301830183018302581d2ecc29447b0eef6c241dcfdf7dab077093ccd6a1266be0fe9c9b127602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000e0000001014a0000000000efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610091541cdc7b65c4828286c911602d9438de5649d698b60fc06aec73589395d0bca71746524ed2ff17b2c8da9fbc897f0f07a40b204871b6fe96d45ef10b51d1f1d530d0679a5db82de96929805fa17c737994ebcc2312d2a25bd94747ecf8f34b8302581d2f1a9548062f52ca0e90e72a4a97cb324fa1dfb62b564ef1b29f38aa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000160000001014a00000000016fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084698ba18ea46f2041353c98fdf6980235fab99a6f5b83c5de3bb32a7ad190ef26fd2afad2dd2e4fb5eaebc4fd177e3c11ed29fb7dab26a6909d366c185cb9d964d3ff3a8e71c0c28adfca715698f679cef6b6346106a78c9f8d3f8e9a66e88083018302581d30580a1a7643049513f8f7d6ffe6f51000570345a63160cab7784c5902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000a0000001014a0000000000afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610085c8811b0caf15f9ad2e34f1841a7820dd1a70642e21362748bf0927c6fd67ddc0c1329fdd840e06a16d383023c4c00f062f173e628528eb801c15258e2e417d511fe4ba3c175469570cc8e1338e5457ed6b31b72b139b537554f00b14fd69158302581d33c2f9ea0f8e2c53e6e54766dbc6cec8da6787b0154260a99925f7a802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000f0000001014a0000000000ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b31b406c9f6648695a88154ae2e4f5fe87883d4ad81c2844c5571b2d91d401cdd40836e763a7c18dccb84629b0d808f7142c3175bc8231dc09bd53637efd6f2568801385ec973d34e6eef9c8c8280a9f4a114163a43a8540941ba367f0c7cb28830183018302581d4164d0b890d702b3cf4f1121e504f24b0f0d94da0e935221220f3a3702830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000040000001014a00000000004fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008ac081401431767be18972543b3ee45c6769c447fb727a1abd72bc1c12487d5c1169522857cbb8d89273847f669563af05833ecee73afa853a16de4aa5549ffea02f3280167129fe026d8aeadc959d73b44570dd18eb9c6ba313edd0a45282748302581d43dcaf1180db82fda708ce3ac7a03a6060abde13e9546c60e8cce65d02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000701014a00000000000000070101824a000000000210000001014a00000000021fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008675b634a43e39726238cfe39c9518bc3e3225cb6f5a8479bfcf2b608fba6f8524dcb80f35a8ae44b47f262f0a6620d41279f06fe0c53a739fcca01a48926fe651a3519b5b329ffbecc9f0cb908b098dd3e8845cfb99c56379e049ac465ec80683018302581d45178b66a407a4d59c0a4d6733bda2ce3f37c111b4257ec41908f4f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000070000001014a00000000007fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100955f52f73c2dec59a637b294e50b934db5d6de29e73bbcf84e7d86a4ac41bad7b539f9817ade8916961d9dd6bf9257010d5857156e8fe6aafcf6fd068795e70bd3399b3411300c9ccc8eba0d068c10e4cfb6f4e27d195b1ead785d618eb393b98302581d4f82b62edffa3fa4e6a5c48327ce8cfb3f850db2e5abc90e955d77f002830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000230000001014a00000000023fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a32153e6271817b87d91d1cd0b727119a2eda7355ee7ef64ee9f10bf6396aed6899a5475d37d6cc51c6a741397d3685318e8e0dabec1b1994112e2c4da3262033ea18fc667dd0ead6e0a151f4d884ee644b799c05e56f502d42f22ffabbca09783018301830183018302581d581b5aa2f10c5f221e45de74a2cecafd3da076be39db0907cbf554bb02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000170000001014a00000000017fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ad28a2bfaae6c9248ef1ea3e4f4bc6ea29101ce533b0075349bb86a88535c216ce434c9aa018b87465441dd997ed23270e2b21e126c74f16293bdba29033e858ecd50bda7be1b692a401e154eb87b65dcf0983635e578e3ea2f6d9b02c7c79dc8302581d5c76b3988ed788abc32d2ea13331bc29debc4f24d19a8f41417eaeb102830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000120000001014a00000000012fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ae04b0b53b4f62ce4a789a6b0f0c9e66dfa5868cb2f3e0e7f628ca6fb93e4f33879a8fe47a23485f30f5a68472c4fd460bc29923b851023792437af3cc690891740a676ffbeb8d836e6ed5b2409dcb32104dde956743e51d3b0e23222ac9487b83018302581d601575e11b35c86fad26229748379d1d9693312bff16e2bca1c1cdd902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000220000001014a00000000022fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100987ce1744dba1052580903a85d6ac697f1619a9ce3119cfa8b06697013a9e2a799b2078763c3119023981410523c52030e00b5d3fd6663e85c59473366ac9846fee6fe9b415c69a96ee9f0f7768673839211f52b19fab495978f100f982d0f618302581d61b718d0b8c31db1ef09451eadd068887c1df5f37e7de0a3afc5a56a02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000010000001014a00000000001fffff0101824a00000000006000af01014a00000000006000af010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084ec5e445306312c9d94e1d1a37cb7d3a6a5a6f86bc85f30ba9bc5a261ab8a37f814786b8e1bae8aa004afb1bba510a411bde94c2a494fb2caa9155abfe0dfc19046854929f7d67726c83e572faa4b812c96196221ed549ef27fb9fb78c2e06d830183018302581d6a8f67d86ecc8307048038ad71599458c131b531dc9bb0b691940db902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000080000001014a00000000008fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008c4e7e55222f134fc3a633620701f6d25a2a5eecd71a3d49c36846ff5d5cd98d382764e81c5869e95e0feb61d132a9f20d4822f7c5bc4c8ed7cb59d52884736864478f1b0e81b1892cfa01ccc7b2fa5fff31586096217c599ff2652368b2f1948302581d806b712f189b5651e7349743820c5f45a81592464c25048e79f25cd602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000b0000001014a0000000000bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100af4f78ab97b3cdc76075f552e83842d5b07c4e35f9f83614b4976e70751f94ea1bc5ebec45892086f4344ea8fb3f7e3a053da28155c0ac501ab6a26ccfc60e729d0bbe91bf0772837cf2911fb4e952d066daf14ea45c08c2104cc69bf221a4f883018302581d9365a8c9f27f413060850835d1859a415c67575cd30c04a183fd096302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001e0000001014a0000000001efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008a91b23b098aeb7dd5e525717f0c29d3967c5f4e61d0b5c7c697172e6f5682aa5e423d42077695c517aba7e3b636da940938d7d5caeee26c3c71cc6888f542c5966e60ea4d91ddb95ad0994283171097e325026bef003128b44641056c86d04a8302581d9c7d405764f197f3611b7a6d3f7756f0c5f7a7dbb02504da09d21f2902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000140000001014a00000000014fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a5d492126a99c65b09c53fe75b5ad8e24d1556a9db2bfe74dffae1816165405923e6fa2b4c58e5adbddf99575fb83b1a06736dc6e4ce20eabf54ca6ca574d3af0d14ef8ae143f9339cf16e62e72b5dfd47d1d642e731c5ee853a00fef69d70db8301830183018302581d9dfdc32362ee85e05f3f36ad947cc62cd276d7b8687d239637de118c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000200000001014a00000000020fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a0e2dffe693d3c75cabacb68760466611df84ddd06e42954cfdf85c665841801319dcaff52cbad03bc37b64061c562920b77389679afb7f888bfc4a36b4772e6cf41374ff8714101f390056e26de88611c93c22eb90e96fe6370ac246ea6faa28302581da22bac610f4e17278d2a0f2cf83a2e2556f6594371615940334d31d302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000190000001014a00000000019fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100afd62f0314d4f866c512d95a649db5c3241d6624b15c62b2fdd3d29af2dee832e3f1af39c60c2389cc4826c181b82d01133dc9f10f727b315c5bf18de580b70a8d8800c570b99b89514922a6476fbf76591e022ca68cdb4b3610e7f642d9bfa083018302581dacc260d8fc5e1421c9aacc9bb5e1a1147aa15bf15304831ba734b9f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000050000001014a00000000005fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aaeeda397b35cf5473ebc1792d7aadf102d085aca490551906f73c4108df12b8478b13b73c8953c148235d0efe99427017451ce8cdd0bd9ee81ede26221c4c3ff0f49af21c6402e6d35fc4c3c61352ff3d8767a3cc8d7ee58a2b50abbbdf2dbe8302581dba488d13a5dd7649d8093fe4897df1cc7c728ab64c856a78c4b97d6a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000110000001014a00000000011fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610088dc7b350da56b6ff41f08332636ab9d162bf3a293a65f795089ef8b8fe9a5af91c51f67e34729408bfdf21b110b7ca405c98af5c1a9ca2ff2995e27ed4e9d0325bd8fa92623e31879247ea508729cf46e0dd2804bea34f3acabe4aa4ef0b973830183018302581dba58b21125381b0567e61f3f2ecd65f37710316084ee791cdfdb4a1a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001d0000001014a0000000001dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100852c9ff8de8c5964d4b6209feaa6f7675a3afab47ab8ec9b67b111ddc158983fd7b034ffcce4958c60ec37040938eb1e18633d7e9a086153e53755008642bf9f87db91d6709a65f242b9e4e31dbeba64a684745a76dee8cfe6729c5ab3c52f148302581dbd26ec81a3360bc8050673531b92b27988bf2a893b506f80e40c11cf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001a0000001014a0000000001afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008e41463b1893989f425af308744b916d9034e83d9382b03b1e30b117fee21a4e1ff03fc59d54f4bc710a51ba04a1e21d0fd863b5329bf68ee67c6d15f82d4a673775604a1c719cb6ce200b2710e425663c7060e5e98e032beda6835c9010158d83018302581dbfca29efbb1f48b67849f2c9bab8a7856fd57882fb99c8ad497cf55202830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001b0000001014a0000000001bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100846c395853586d94a2e546485537d4f81bb7820d5e82c274b507d592d59353a165dd8ed432e8b7c0792d90d52cf968c20c5ae06d69817d814a7ee2d54130baf49b192186890621abc70046ea9939978df172fc1cd16aded5f227cd8c27bcdb658302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb47830183018302581dcff280e32d7f5ccd2246882f94afb20f54ca61a21765e712d43d2789028301830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000001014a00000000000000060101824a000000000000000801014a00000000000fffff01018302446e6f64658301830183018301830183018302581d24c56af1a646bdee74ba2c8cad88ba6e4f2ee098f99055bd0e9640c60283024a7075626c69635f6b65798203582c302a300506032b6570032100526742592f1e331aa13db7d1ebf224ff0b8231e0626eeefad0b629413a93e7988302581d2995ce7aeea59467fb3a634b434dcc965ba147ba2f9804ea2e8f1b5c0283024a7075626c69635f6b65798203582c302a300506032b657003210099c734e5f28c50741b04b63e87c77533d47dc2347524ed1ec8c266e429cef63683018302581d32442407acaa5ea43e62b1dac1ac20119c64cfd5c23cc0ae1508ee250283024a7075626c69635f6b65798203582c302a300506032b657003210054432c37b495e9206b46b5ce85da87a7eb2d853cd3f02feec4acf39efe9828508302581d325c033f6f1fd07e7bcb57b7ab8a24b1abf73beffd1ca17ed88cf3ab0283024a7075626c69635f6b65798203582c302a300506032b657003210059ef19e6aec7336d0912a80fe269ed4f0e8360cff9dc6fbe7a941643142bb4ff830183018302581d3c4d78ddee38b0eb2910a004c3a7362017a5c14a9346007a65829ebb0283024a7075626c69635f6b65798203582c302a300506032b657003210076f7f52d74955cc045838a6ef71b882dd5339ba058bdcf1085f893b3545d44bf8302581d3eda90ac6d378ae7c7917f94fd61c0e685b22f5ced5ad0735af250230283024a7075626c69635f6b65798203582c302a300506032b65700321000b4ca05b18b5dff4efc88badc802bccc4bae5ce2f16febe6a893904a240af36083018302581d46e3cfcd286afe6a1f4572d2350facd38f0f8647d58c499e5bc5039d0283024a7075626c69635f6b65798203582c302a300506032b65700321003f29994149099aa1b1d2dcdaabe5eda73aea6866d067e2c45b97e216532bcd338302581d53e39463ea45264875d00c508e4bb1325722a96a00053dbc2662fc5e0283024a7075626c69635f6b65798203582c302a300506032b65700321004323320684d4e1edb89bdcdee00844830a0f7de3e3cc7346e5a3868d1aef02b58301830183018302581d607eb9a00ad3b4411f5911276879c618a6895fd57fe6c9b0a879f9b00283024a7075626c69635f6b65798203582c302a300506032b6570032100a8fa77ad6c1da6d50d04fbc96bf33d0e30a67c1e8ba97fa3ce7c3d9c868a7b998302581d6ad96c153126046203336a5174a04b30f0adea457c2298b976ab674e0283024a7075626c69635f6b65798203582c302a300506032b65700321005e12ef0eae2809a5468471ee2d9745d23f20b1c0da7129fa447d96a67336be5b83018302581d8156c471c227bb551da5ff7603b22e4a1c87f711292502aef5cdae320283024a7075626c69635f6b65798203582c302a300506032b6570032100995e3dcf4b0fe927bee5172cef595b53bace86185890f052939a63d24eabf0da8302581d8465e6cc28f5be102098a7ae96264f6ec72f1c4a858b491cd60e55a50283024a7075626c69635f6b65798203582c302a300506032b6570032100dc624cca12ec1daebedd007ec838e77990a6da3f8dff968ceebf3a0e8390562f830183018302581d8cf60ae159aabf4207328d2a5524675d5c157a8aa1f80a52ec44221b0283024a7075626c69635f6b65798203582c302a300506032b6570032100d1955dd0b79c84d036422763c3a29154f31ab907ecdcfc9870db91db3e9dba7b8302581d904ebdc04493093d1f6f7d37a6a91c5fa6616ddf19771fd346cd5aeb0283024a7075626c69635f6b65798203582c302a300506032b6570032100767f31d2bb762bc9fa9b2cbe9f86504f16422f206fe4e61ec57b73a97fea242683018302581d9f00ea7b0826aa145abd4348c3656133ed84e188780f63c5151009bf0283024a7075626c69635f6b65798203582c302a300506032b65700321003dac46790dd80a38b0238ac3e1c1766fb3049a3b46d406c4ad85ccff42317a1e8302581da7835a01f618d7b552d0eae3310aebd0cac6ea2bf02865472f4546fc0283024a7075626c69635f6b65798203582c302a300506032b6570032100b80f4705b1420119acf881fb01e90f50044df72b1893cca44b4e81129e7a3e6e83018301830183018302581da7bad7420d9671f6992d64ca541ce75fe04a7c51c2561dd9aad945880283024a7075626c69635f6b65798203582c302a300506032b65700321008aa5bb79948b296c12c14131b35f9009ce331981b08c7ec57a595c6eda59d6938302581db1dee04210dded1afbc7e5d31492d7f0b1379b8fea5b203d30b3c03e0283024a7075626c69635f6b65798203582c302a300506032b6570032100031739d3139245f101349d4d2fb8cdc2e2707084d3fef1d033042d64ebd452bb83018302581db858dfb622c91c481e81e9cdbfb7ab78da5dbb7a09d2e321787a0c1a0283024a7075626c69635f6b65798203582c302a300506032b6570032100cd59f18eea954c1fc8e315099657d929b6bfb7fefadb7bb214448809f4a9d19f8302581db8e453c069995d67a5253c43ec43b4b39038d272f4c67fa9155e6e490283024a7075626c69635f6b65798203582c302a300506032b657003210079d79503838b2b01791f66c18bc7614e19d3a6aba73bae00b92bb99edeea5287830183018302581dc0588b3d010691102a6dc738ab5517afaa4f27882a3554b006d2b3920283024a7075626c69635f6b65798203582c302a300506032b6570032100879ee566edf8a11717120cca3e4b1521f07a781c6d79ddda637b3a4c770f6fc68302581dc6f9bfce466cc84184b6c0993a1bf50dabc45f0f5a591c8bcd0326bd0283024a7075626c69635f6b65798203582c302a300506032b6570032100d8e091572c325ee4edf561c8f0c85f59203f4b79e955f2adcaf39dc9037b59cb83018302581dc749a1b9b5c123bdc745883bd4901e311ae90a586a6825d52d99739e0283024a7075626c69635f6b65798203582c302a300506032b6570032100bfa1b1575803d5fb21032a69ff50a04a3394dba63c509e9a1ae9edf781b3f1748302581dcec168cc1c818e1bcbf8622c2bf05ead8f63ad21d04e0498fd64fce80283024a7075626c69635f6b65798203582c302a300506032b6570032100dc1a8cd77897793bb5b6bbbbbab2ac828f212c31ef7d8cd1a5e9da71d4368a1a8301830183018302581dcff1f1e404582ce832e51ef54dd196540af764448da6720f443d28860283024a7075626c69635f6b65798203582c302a300506032b6570032100b9f3c99d054c571483371cabababeba71a95af2f1db75a9eff5362a00168bab38302581dd0d9bd9de8bde02b0179227caefdb94de48a74231c4aa88c6bba74780283024a7075626c69635f6b65798203582c302a300506032b6570032100cd8d2ec2ff21561e2772d9e68ea249dbe874c214899c33c5503444b34786be3283018302581dd52a16f3dc32065f858393468f14585efb701a4cad05c445ba75a1dd0283024a7075626c69635f6b65798203582c302a300506032b6570032100013eb950162c07d85df53e01759052f239e953b592d13121ca5c038e28b6ea288302581dd5607c139fbf027070f48977431c08c47c96199ed4f75642774408930283024a7075626c69635f6b65798203582c302a300506032b65700321004558f956c1197f57de5eda61e88f6feb2bcd97cb69992edf3ed77326376447cc830183018302581dd7d81b675fb361616868d4f31793e064c6619a7a3fb4715d340fc2e00283024a7075626c69635f6b65798203582c302a300506032b6570032100455044dd9eaf7a0dd463d8e194f4c10bd4943cfc9beaf0e7ae4074373d1548938302581ddbcb3c89c77e2a4bb43c2244752161f5c08d759f97acdca282af8f9d0283024a7075626c69635f6b65798203582c302a300506032b6570032100b1c163e31457e5af99033c20a313371c3a00237a3bedf2ce8cdfef475db5b87583018302581ddce94d09354a1751d180df5fe0a8f352c7396bd63c338f8f91fdf5340283024a7075626c69635f6b65798203582c302a300506032b65700321000391e646f29f87929474489743d2958abd973ded1826d146b1d5cd67ae05b55d8302581ddeba05a0e095a26bf12507f792863507d32fc012be8e4f4d705dbb7e0283024a7075626c69635f6b65798203582c302a300506032b657003210004623b4767a979d854f118eaad12777b5ffa0ab0d9640708f68579cb4f6700358301830183018302581de058cf7bdd01bc75227405ebfab94752a4d2f43ff113b5ca68e4df4f0283024a7075626c69635f6b65798203582c302a300506032b657003210072de1b160077674e745a9d03e75a9432622aada8229d36d12b48ce567882e0d38302581de8373870d8066d971c415cbdaf1611bcf84cd3644d22b389de95d9e40283024a7075626c69635f6b65798203582c302a300506032b6570032100c8cf4e899a7227b656028521ba6d7c305528e120498db2e145b5448b96f824cd83018302581de85c5ec8051f35f9e3c915e3dbb3c32af6506b2a668b74c0bd003c850283024a7075626c69635f6b65798203582c302a300506032b65700321002f2e7160e775b899b3921b3a9676373a542c7ee4965d3b43952781820b880b938302581ded8915a3c359b8e16da92f2c42d6fbcd34fcc23a011770fba5734c990283024a7075626c69635f6b65798203582c302a300506032b65700321003db88746a7def775447aebeab07f35a7ab325a1e156c1d076da2ef988cf4cf8d830183018302581df032935f1185096317778e4206e8de237a7e090ba0b3289582c0fff50283024a7075626c69635f6b65798203582c302a300506032b657003210088eccdb0ceab1a41a33496dbfc7abac145d1674363c527f36707b53b354f7d238302581df2be1c26024bc9e103d662dfd167cbfe861400e7748b7778e01adc790283024a7075626c69635f6b65798203582c302a300506032b65700321006fed5c19bfcdf67f1e8d9a866f826d89cb05bdcd40cb633a5d7645f82394665c83018302581df92bb6e3332495ffd40fcf37af5fe9482b0667f3d4063d598fe8e8fa0283024a7075626c69635f6b65798203582c302a300506032b657003210038e87a8fcc24cdaad8541ad88a0d1f521a8c9bbc29379382055602ca59d226ff8302581dfd8e4151c4762d9b4b6b36e08d36a49b83e9458a5040a1dc26d63b530283024a7075626c69635f6b65798203582c302a300506032b65700321001909d5eefbb0075b3176069b7ac4a6e99934342a8fe5b3ec301d20b6cf453e5383024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae8302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe83018302581dfc7d15b27df96b3e98731463a2af13d6e43cf426d0cb487a7120091502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000c0000001014a0000000000cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009053b542dc8d758237ada280dc505846c327b0c43b7e26c0ee6f7729cdebd43639d959c10fe1aa058622437d7ec34a920035dfd55de4f40937b4c419e02b517eb2b7a6aa7f42644352202f8f4c67e726ca8f168ab588764261dbcc3a5c8113938302581dfe320f2fbbb9d49c8e6edbcc9d85ec096bf645351d95bbddf556f7db02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000130000001014a00000000013fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b2a6741083996223f83384666740a3eacf8ce78c6d39fecdee582a5b243c158706bb215f396ba0429d2188df9ef176721306d048aaa58f6b413457dd63ef1a56de2378e71ca444201e29e490e3790098e92ee85e0142a33ef806c8388aec6baf83024474696d65820349e497bab5ceb8b6c417697369676e61747572655830aad9a5bb55b042aecbddb8ead3ac4bba7f7383ee6c46162fea9f80cac8b46516dbe901dc7e7e886ae7f4c2c8b380b5b9`, mainnetApplication: `d9d9f7a364747265658301820458201974c7c7bcddc5fb14fc025206a4b146f372fc1b4fb33e6b62d1b11ff980afff83018302467375626e65748301830183018301830183018302581d033a778c6c9eac039fdda83dc90d2c12eb846de85c475e36ead6715c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000100000001014a00000000010fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aa544423a45fb0388c43703a159a96208cafd17f01f1e7c400676d2c69f62195f6a5bb564d564f7967047def10b48c22003f38c5d56961d0c47879f9212b93cd206620114bd9e1d4db22d04e294d37e1ff42cedf2322ebf60702c88325c606808302581d0f033c5125db4f6b32e426268df663a5ce98fe3b531d962e1a7a87fa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001c0000001014a0000000001cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100913f6a84f05736c2dd0b2dc3ec838e95419ae0ef426d556f50152a445b9c232495bc051cdabbd46a7bd8879b09720cbb13b3bcd265ff75567dcbf04e9ae1c3a2141229a6757605625b093c5ca34336393e5a88b78df7b0a3a7e5b9841716d0a483018302581d10b647334a5406987796b2f8b6b14cd32f0876d3fd4fc8452105832502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000180000001014a00000000018fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084cbe7a009258947dc30983fede3b98b34cfee5e5d1ae4e1e72891590738ca9a58f9f6364b359a5448b6c5e20ee5310300e4c0c9cca29b07e2d73208f8ec6cd1fb6ca46c168c43393f9e050a05448836b0a6f5c75d2a398c999c42d7c981cb898302581d12790e7661fccd3d4fc83138dcaffd9f188e867b45ae10c8836dd0b802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000150000001014a00000000015fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610086d88ebbd2f1663e65d3a3ff07e8ee9fa420d08b9a6822919f224b8b802d5d9be150dc493f84c23e73a0cc1d2c2ee28709ff140000128fcd5dfbd7b457ef3af344766d7ff0924fe7a7f456ded77ca6de3b1b406b710c4eaed7287ab9a3527669830183018302581d17f67590355e7123aeffabce4c1bddf3a0efd53a2c2e3f6228fc3adf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000d0000001014a0000000000dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100850e5edfb0685d36757643be011f5d3378fef0bfb9b0ef67429912ebb9237f5028979eb33779df7c63acf59b78eba4d904c6b4abad529b9e8e2195321e287f8c51900f5b440872719c7ac56e381c8063bc6176f8e4b74d06de669493e49055678302581d1cc5ad563f1bce937c305be3d12bef627f73b727808672dc2432aef902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001f0000001014a0000000001ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610093907710f0f89af4b5bd35a28e0162171e2f411d11e152152e88e3da4c2079799e4eac7a3a9f3923fb63b33b68928ae91652fae5c2ccce872173632648ef4dd79ae7e8c15b9e97f132ea34a4349506d281bd66bbd0c3afdd78cbe026927a8c1683018302581d2c55b347ecf2686c83781d6c59d1b43e7b4cba8deb6c1b376107f2cd02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000060000001014a00000000006000ae0101824a00000000006000b001014a00000000006fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610090075120778eb21a530a02bcc763e7f4a192933506966af7b54c10a4d2b24de6a86b200e3440bae6267bf4c488d9a11d0472c38c1b6221198f98e4e6882ba38a5a4e3aa5afce899b7f825ed95adfa12629688073556f2747527213e8d73e40ce8302581d2d030caf397e446c03cece4fd072acce432c75b6a700592e73f5d13302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000090000001014a00000000009fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100805230c2da9687218fdfa49bddab093578c2e8a10b27d69fdda097f286abccdae2541c711e3ca771202bfc9b366bf61b17e9f1173d7c9a6eaaa907ccdba3bc86764bc1d552437c4948038e1018a9c49e444189cd55358e37a6f879d88c0a26938301830183018302581d2ecc29447b0eef6c241dcfdf7dab077093ccd6a1266be0fe9c9b127602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000e0000001014a0000000000efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610091541cdc7b65c4828286c911602d9438de5649d698b60fc06aec73589395d0bca71746524ed2ff17b2c8da9fbc897f0f07a40b204871b6fe96d45ef10b51d1f1d530d0679a5db82de96929805fa17c737994ebcc2312d2a25bd94747ecf8f34b8302581d2f1a9548062f52ca0e90e72a4a97cb324fa1dfb62b564ef1b29f38aa02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000160000001014a00000000016fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084698ba18ea46f2041353c98fdf6980235fab99a6f5b83c5de3bb32a7ad190ef26fd2afad2dd2e4fb5eaebc4fd177e3c11ed29fb7dab26a6909d366c185cb9d964d3ff3a8e71c0c28adfca715698f679cef6b6346106a78c9f8d3f8e9a66e88083018302581d30580a1a7643049513f8f7d6ffe6f51000570345a63160cab7784c5902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000a0000001014a0000000000afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610085c8811b0caf15f9ad2e34f1841a7820dd1a70642e21362748bf0927c6fd67ddc0c1329fdd840e06a16d383023c4c00f062f173e628528eb801c15258e2e417d511fe4ba3c175469570cc8e1338e5457ed6b31b72b139b537554f00b14fd69158302581d33c2f9ea0f8e2c53e6e54766dbc6cec8da6787b0154260a99925f7a802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000f0000001014a0000000000ffffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b31b406c9f6648695a88154ae2e4f5fe87883d4ad81c2844c5571b2d91d401cdd40836e763a7c18dccb84629b0d808f7142c3175bc8231dc09bd53637efd6f2568801385ec973d34e6eef9c8c8280a9f4a114163a43a8540941ba367f0c7cb28830183018302581d4164d0b890d702b3cf4f1121e504f24b0f0d94da0e935221220f3a3702830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000040000001014a00000000004fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008ac081401431767be18972543b3ee45c6769c447fb727a1abd72bc1c12487d5c1169522857cbb8d89273847f669563af05833ecee73afa853a16de4aa5549ffea02f3280167129fe026d8aeadc959d73b44570dd18eb9c6ba313edd0a45282748302581d43dcaf1180db82fda708ce3ac7a03a6060abde13e9546c60e8cce65d02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000701014a00000000000000070101824a000000000210000001014a00000000021fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008675b634a43e39726238cfe39c9518bc3e3225cb6f5a8479bfcf2b608fba6f8524dcb80f35a8ae44b47f262f0a6620d41279f06fe0c53a739fcca01a48926fe651a3519b5b329ffbecc9f0cb908b098dd3e8845cfb99c56379e049ac465ec80683018302581d45178b66a407a4d59c0a4d6733bda2ce3f37c111b4257ec41908f4f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000070000001014a00000000007fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100955f52f73c2dec59a637b294e50b934db5d6de29e73bbcf84e7d86a4ac41bad7b539f9817ade8916961d9dd6bf9257010d5857156e8fe6aafcf6fd068795e70bd3399b3411300c9ccc8eba0d068c10e4cfb6f4e27d195b1ead785d618eb393b98302581d4f82b62edffa3fa4e6a5c48327ce8cfb3f850db2e5abc90e955d77f002830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000230000001014a00000000023fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a32153e6271817b87d91d1cd0b727119a2eda7355ee7ef64ee9f10bf6396aed6899a5475d37d6cc51c6a741397d3685318e8e0dabec1b1994112e2c4da3262033ea18fc667dd0ead6e0a151f4d884ee644b799c05e56f502d42f22ffabbca09783018301830183018302581d581b5aa2f10c5f221e45de74a2cecafd3da076be39db0907cbf554bb02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000170000001014a00000000017fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ad28a2bfaae6c9248ef1ea3e4f4bc6ea29101ce533b0075349bb86a88535c216ce434c9aa018b87465441dd997ed23270e2b21e126c74f16293bdba29033e858ecd50bda7be1b692a401e154eb87b65dcf0983635e578e3ea2f6d9b02c7c79dc8302581d5c76b3988ed788abc32d2ea13331bc29debc4f24d19a8f41417eaeb102830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000120000001014a00000000012fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100ae04b0b53b4f62ce4a789a6b0f0c9e66dfa5868cb2f3e0e7f628ca6fb93e4f33879a8fe47a23485f30f5a68472c4fd460bc29923b851023792437af3cc690891740a676ffbeb8d836e6ed5b2409dcb32104dde956743e51d3b0e23222ac9487b83018302581d601575e11b35c86fad26229748379d1d9693312bff16e2bca1c1cdd902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000220000001014a00000000022fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100987ce1744dba1052580903a85d6ac697f1619a9ce3119cfa8b06697013a9e2a799b2078763c3119023981410523c52030e00b5d3fd6663e85c59473366ac9846fee6fe9b415c69a96ee9f0f7768673839211f52b19fab495978f100f982d0f618302581d61b718d0b8c31db1ef09451eadd068887c1df5f37e7de0a3afc5a56a02830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000010000001014a00000000001fffff0101824a00000000006000af01014a00000000006000af010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610084ec5e445306312c9d94e1d1a37cb7d3a6a5a6f86bc85f30ba9bc5a261ab8a37f814786b8e1bae8aa004afb1bba510a411bde94c2a494fb2caa9155abfe0dfc19046854929f7d67726c83e572faa4b812c96196221ed549ef27fb9fb78c2e06d830183018302581d6a8f67d86ecc8307048038ad71599458c131b531dc9bb0b691940db902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000080000001014a00000000008fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008c4e7e55222f134fc3a633620701f6d25a2a5eecd71a3d49c36846ff5d5cd98d382764e81c5869e95e0feb61d132a9f20d4822f7c5bc4c8ed7cb59d52884736864478f1b0e81b1892cfa01ccc7b2fa5fff31586096217c599ff2652368b2f1948302581d806b712f189b5651e7349743820c5f45a81592464c25048e79f25cd602830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000b0000001014a0000000000bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100af4f78ab97b3cdc76075f552e83842d5b07c4e35f9f83614b4976e70751f94ea1bc5ebec45892086f4344ea8fb3f7e3a053da28155c0ac501ab6a26ccfc60e729d0bbe91bf0772837cf2911fb4e952d066daf14ea45c08c2104cc69bf221a4f883018302581d9365a8c9f27f413060850835d1859a415c67575cd30c04a183fd096302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001e0000001014a0000000001efffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008a91b23b098aeb7dd5e525717f0c29d3967c5f4e61d0b5c7c697172e6f5682aa5e423d42077695c517aba7e3b636da940938d7d5caeee26c3c71cc6888f542c5966e60ea4d91ddb95ad0994283171097e325026bef003128b44641056c86d04a8302581d9c7d405764f197f3611b7a6d3f7756f0c5f7a7dbb02504da09d21f2902830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000140000001014a00000000014fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a5d492126a99c65b09c53fe75b5ad8e24d1556a9db2bfe74dffae1816165405923e6fa2b4c58e5adbddf99575fb83b1a06736dc6e4ce20eabf54ca6ca574d3af0d14ef8ae143f9339cf16e62e72b5dfd47d1d642e731c5ee853a00fef69d70db8301830183018302581d9dfdc32362ee85e05f3f36ad947cc62cd276d7b8687d239637de118c02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000200000001014a00000000020fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100a0e2dffe693d3c75cabacb68760466611df84ddd06e42954cfdf85c665841801319dcaff52cbad03bc37b64061c562920b77389679afb7f888bfc4a36b4772e6cf41374ff8714101f390056e26de88611c93c22eb90e96fe6370ac246ea6faa28302581da22bac610f4e17278d2a0f2cf83a2e2556f6594371615940334d31d302830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000190000001014a00000000019fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100afd62f0314d4f866c512d95a649db5c3241d6624b15c62b2fdd3d29af2dee832e3f1af39c60c2389cc4826c181b82d01133dc9f10f727b315c5bf18de580b70a8d8800c570b99b89514922a6476fbf76591e022ca68cdb4b3610e7f642d9bfa083018302581dacc260d8fc5e1421c9aacc9bb5e1a1147aa15bf15304831ba734b9f802830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000050000001014a00000000005fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100aaeeda397b35cf5473ebc1792d7aadf102d085aca490551906f73c4108df12b8478b13b73c8953c148235d0efe99427017451ce8cdd0bd9ee81ede26221c4c3ff0f49af21c6402e6d35fc4c3c61352ff3d8767a3cc8d7ee58a2b50abbbdf2dbe8302581dba488d13a5dd7649d8093fe4897df1cc7c728ab64c856a78c4b97d6a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000110000001014a00000000011fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610088dc7b350da56b6ff41f08332636ab9d162bf3a293a65f795089ef8b8fe9a5af91c51f67e34729408bfdf21b110b7ca405c98af5c1a9ca2ff2995e27ed4e9d0325bd8fa92623e31879247ea508729cf46e0dd2804bea34f3acabe4aa4ef0b973830183018302581dba58b21125381b0567e61f3f2ecd65f37710316084ee791cdfdb4a1a02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001d0000001014a0000000001dfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100852c9ff8de8c5964d4b6209feaa6f7675a3afab47ab8ec9b67b111ddc158983fd7b034ffcce4958c60ec37040938eb1e18633d7e9a086153e53755008642bf9f87db91d6709a65f242b9e4e31dbeba64a684745a76dee8cfe6729c5ab3c52f148302581dbd26ec81a3360bc8050673531b92b27988bf2a893b506f80e40c11cf02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001a0000001014a0000000001afffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008e41463b1893989f425af308744b916d9034e83d9382b03b1e30b117fee21a4e1ff03fc59d54f4bc710a51ba04a1e21d0fd863b5329bf68ee67c6d15f82d4a673775604a1c719cb6ce200b2710e425663c7060e5e98e032beda6835c9010158d83018302581dbfca29efbb1f48b67849f2c9bab8a7856fd57882fb99c8ad497cf55202830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000001b0000001014a0000000001bfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100846c395853586d94a2e546485537d4f81bb7820d5e82c274b507d592d59353a165dd8ed432e8b7c0792d90d52cf968c20c5ae06d69817d814a7ee2d54130baf49b192186890621abc70046ea9939978df172fc1cd16aded5f227cd8c27bcdb658302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b028301830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff01018302476d65747269637382035823a4001901c3011b00000002547ccc1702a2001b00000dc43d2206f80100031a0003649883018302446e6f646583018301830183018302581d8554fbd9569af03e79ccabb8e0df5376da7d9c52c6116d477dc8e7a80283024a7075626c69635f6b65798203582c302a300506032b65700321005b0bdf0329932ab0a78fa7192ad76cf37d67eb2024739774d3b67da7799ebc9c8302581d88729cd45ca059e2af291c1521462cad7d479445170c68b050e4c3ba0283024a7075626c69635f6b65798203582c302a300506032b65700321009776d25542873dafb8099303d1fca8e4aa344e73cf5a3d7df5b40f9c8ed5a08583018302581d8e64078481caf73482c8b734e37523c8e6a0767882bd3a21b7a93c250283024a7075626c69635f6b65798203582c302a300506032b6570032100e5a9296571826cc3be977490296405ae9da1da7d59cce1642421bc19804cc3108302581d9717b99c1bf40cb84611aee69e92e7715eb0a90221aac29be62d7e3d0283024a7075626c69635f6b65798203582c302a300506032b6570032100b761a93e418ab326d2d106d9137268d407f7c8a743127e2833899933337eb09b830183018302581d9b5c9ed769f8dbd6210f4680cadb73beb3852e76ac43e9ea2dd35a280283024a7075626c69635f6b65798203582c302a300506032b6570032100afd56377478dc711cbfe043022423d9f7f7decb709de7501545923274186883f8302581da142f96f269cac297b0d7d651c5a43470d78322e5b5369cd5d04a9ce0283024a7075626c69635f6b65798203582c302a300506032b6570032100ce76939540cac8de3475329517c684e0562fb6cbad1db67fb60362808bdaf46283018302581da870dc773b62cae3c31ca1905ff7c7242a4460bf18594dcc12641c170283024a7075626c69635f6b65798203582c302a300506032b65700321001645a7cb7f3980dd6f9ca6ca0966a4d4bde9d57d90df0f10fc31eac960a8ab418302581db506e1548dbaa9a0d840282a3c5a608a7d90a9435a8d391cfb028c660283024a7075626c69635f6b65798203582c302a300506032b65700321000c441fada59fea1cf21ebc157392338ca56775011c4c5630782823e2a7938c8f8301830183018302581dbe9c9341fcf1ce0cb07e809686431958cf497725f37868f3ef990e020283024a7075626c69635f6b65798203582c302a300506032b6570032100f408b362fc92255a4776666179eba4b9dfbd6d3b9f6b87b3abb80f726878e0a98302581dcc84fb1d9f904589c629c10b052a1214318029e46af6b682c70d52530283024a7075626c69635f6b65798203582c302a300506032b6570032100cab5efd3205fa4b3409b6f5e421ebd776dd36ea6108820c624478016df9c6a2083018302581dd972b647954b754c516162ef7eb651cb3d8d6e264d1c289a76f46fa80283024a7075626c69635f6b65798203582c302a300506032b6570032100e650a1cc4bf264cdc80442d33d7bd00e3de1f15ddd48c7ac0f2fe582f599d9548302581de7d8693d4f6322560cc8b0cab4280f40c1a1957de51576893a11ea9d0283024a7075626c69635f6b65798203582c302a300506032b6570032100be0759d30172a9dfdcc2e11b92e8daf1753c45f126b8413c8e57e621b5626d378302581dfe9763f6e077ef3d42f2225c16bc1ec040f97be6add75cff99b24e020283024a7075626c69635f6b65798203582c302a300506032b65700321006b8ef72b0efb4ef38dc957097cb26dfcf24b083dd6b2b5fcd5269657cd8e59a783024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb47830183018302581dcff280e32d7f5ccd2246882f94afb20f54ca61a21765e712d43d278902830183024f63616e69737465725f72616e67657382035832d9d9f782824a000000000000000001014a00000000000000060101824a000000000000000801014a00000000000fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae8302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe83018302581dfc7d15b27df96b3e98731463a2af13d6e43cf426d0cb487a7120091502830183024f63616e69737465725f72616e6765738203581bd9d9f781824a0000000000c0000001014a0000000000cfffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009053b542dc8d758237ada280dc505846c327b0c43b7e26c0ee6f7729cdebd43639d959c10fe1aa058622437d7ec34a920035dfd55de4f40937b4c419e02b517eb2b7a6aa7f42644352202f8f4c67e726ca8f168ab588764261dbcc3a5c8113938302581dfe320f2fbbb9d49c8e6edbcc9d85ec096bf645351d95bbddf556f7db02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000130000001014a00000000013fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100b2a6741083996223f83384666740a3eacf8ce78c6d39fecdee582a5b243c158706bb215f396ba0429d2188df9ef176721306d048aaa58f6b413457dd63ef1a56de2378e71ca444201e29e490e3790098e92ee85e0142a33ef806c8388aec6baf83024474696d65820349d6b2cda6e896b6c417697369676e61747572655830ab3f413732a43a06f1fb9b4b33ca93000f82694ce8939d2f09752d32bee0c48059bcfefb1a78a0c70c6000498b90fbb36a64656c65676174696f6ea2697375626e65745f6964581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b026b6365727469666963617465590257d9d9f7a264747265658301820458201e757e29e560315f8b01e8fd15ec9d0018612d65cc1d7ecddc3c4219e4fcb71083018302467375626e657483018301820458205363d9921c468ac1a0c0475124a1703b0eeab44f12afe4bb721a059eabfbccde8301820458201715cf8e070b9844e1cc2d88b020cddf01463fbdb1a63351c7a2f134b4d22c7883018204582056de5b2239f855d965786fa8fc032c85f07dcd595e7fe19259eadd0808967fbc830182045820ad16bbe070678ae81807dc5a10506cd58ec328abae4a43b3ee93ca27a4062d4b8301820458204d4e6ae2db005b61fa587835203df74b00b2a34626fa1b1d895eb20a899599a08302581dc3b96ea47e04c8977cb703f15aaf5aaaaf73d596c7be19a43a718d8b02830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000030000001014a00000000003fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c0503020103610087bcc7281aa5620454d5621da57502fd0ac9f10031cecc9df6715994c30ac76f212788d23dba8aa05c8ec109090561ce07c5ce7aef9f248eecd1d0a97bcab22977fb9856f4bfb5ced1fc5693320b7b6ef5fe28c69688b92a8dae61cae762eb478204582053500b9323caa4e30ecfb70fba000e908670ef4dbb1d8cae818051be76656ccb83024474696d65820349bfbfabb4f6eaadc417697369676e617475726558308be7643a5542a0eb4c031c2945bc71fa46aaf4c5d02151dad26b53f42433e4ef8150ea7bcd2bb8c86db4a53d49e58c3d`, diff --git a/packages/agent/src/certificate.test.ts b/packages/agent/src/certificate.test.ts index 4ddaf98ec..44bd5e0a0 100644 --- a/packages/agent/src/certificate.test.ts +++ b/packages/agent/src/certificate.test.ts @@ -8,7 +8,7 @@ import * as Cert from './certificate'; import { fromHex, toHex } from './utils/buffer'; import { Principal } from '@dfinity/principal'; import { decodeTime } from './utils/leb'; -import { lookup_path } from './certificate'; +import { lookupResultToBuffer, lookup_path } from './certificate'; import { goldenCertificates } from './agent/http/__certificates__/goldenCertificates.test'; function label(str: string): ArrayBuffer { @@ -127,12 +127,14 @@ test('lookup', () => { return new TextEncoder().encode(str); } expect(Cert.lookup_path([fromText('a'), fromText('a')], tree)).toEqual(undefined); - expect(toText(Cert.lookup_path([fromText('a'), fromText('y')], tree))).toEqual('world'); + expect( + toText(lookupResultToBuffer(Cert.lookup_path([fromText('a'), fromText('y')], tree))!), + ).toEqual('world'); expect(Cert.lookup_path([fromText('aa')], tree)).toEqual(undefined); expect(Cert.lookup_path([fromText('ax')], tree)).toEqual(undefined); expect(Cert.lookup_path([fromText('b')], tree)).toEqual(undefined); expect(Cert.lookup_path([fromText('bb')], tree)).toEqual(undefined); - expect(toText(Cert.lookup_path([fromText('d')], tree))).toEqual('morning'); + expect(toText(lookupResultToBuffer(Cert.lookup_path([fromText('d')], tree))!)).toEqual('morning'); expect(Cert.lookup_path([fromText('e')], tree)).toEqual(undefined); }); @@ -144,7 +146,7 @@ const SAMPLE_CERT: string = const parseTimeFromCert = (cert: ArrayBuffer): Date => { const certObj = cbor.decode(new Uint8Array(cert)) as any; if (!certObj.tree) throw new Error('Invalid certificate'); - const lookup = lookup_path(['time'], certObj.tree); + const lookup = lookupResultToBuffer(lookup_path(['time'], certObj.tree)); if (!lookup) throw new Error('Invalid certificate'); return decodeTime(lookup); diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index fc50224c1..8974999e1 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -21,20 +21,24 @@ interface Cert { delegation?: Delegation; } -const enum NodeId { - Empty = 0, - Fork = 1, - Labeled = 2, - Leaf = 3, - Pruned = 4, -} +const NodeId = { + Empty: 0, + Fork: 1, + Labeled: 2, + Leaf: 3, + Pruned: 4, +}; + +export type NodeIdType = typeof NodeId[keyof typeof NodeId]; + +export { NodeId }; export type HashTree = - | [NodeId.Empty] - | [NodeId.Fork, HashTree, HashTree] - | [NodeId.Labeled, ArrayBuffer, HashTree] - | [NodeId.Leaf, ArrayBuffer] - | [NodeId.Pruned, ArrayBuffer]; + | [typeof NodeId.Empty] + | [typeof NodeId.Fork, HashTree, HashTree] + | [typeof NodeId.Labeled, ArrayBuffer, HashTree] + | [typeof NodeId.Leaf, ArrayBuffer] + | [typeof NodeId.Pruned, ArrayBuffer]; /** * Represents the useful information about a subnet @@ -70,19 +74,38 @@ export function hashTreeToString(tree: HashTree): string { case NodeId.Empty: return '()'; case NodeId.Fork: { - const left = hashTreeToString(tree[1]); - const right = hashTreeToString(tree[2]); - return `sub(\n left:\n${indent(left)}\n---\n right:\n${indent(right)}\n)`; + if (tree[1] instanceof Array && tree[2] instanceof ArrayBuffer) { + const left = hashTreeToString(tree[1]); + const right = hashTreeToString(tree[2]); + return `sub(\n left:\n${indent(left)}\n---\n right:\n${indent(right)}\n)`; + } else { + throw new Error('Invalid tree structure for fork'); + } } case NodeId.Labeled: { - const label = labelToString(tree[1]); - const sub = hashTreeToString(tree[2]); - return `label(\n label:\n${indent(label)}\n sub:\n${indent(sub)}\n)`; + if (tree[1] instanceof ArrayBuffer && tree[2] instanceof ArrayBuffer) { + const label = labelToString(tree[1]); + const sub = hashTreeToString(tree[2]); + return `label(\n label:\n${indent(label)}\n sub:\n${indent(sub)}\n)`; + } else { + throw new Error('Invalid tree structure for labeled'); + } } case NodeId.Leaf: { + if (!tree[1]) { + throw new Error('Invalid tree structure for leaf'); + } else if (Array.isArray(tree[1])) { + return JSON.stringify(tree[1]); + } return `leaf(...${tree[1].byteLength} bytes)`; } case NodeId.Pruned: { + if (!tree[1]) { + throw new Error('Invalid tree structure for pruned'); + } else if (Array.isArray(tree[1])) { + return JSON.stringify(tree[1]); + } + return `pruned(${toHex(new Uint8Array(tree[1]))}`; } default: { @@ -169,7 +192,6 @@ export class Certificate { options.maxAgeInMinutes, ); - console.log(toHex(options.certificate)); await cert.verify(); return cert; } @@ -343,6 +365,22 @@ function extractDER(buf: ArrayBuffer): ArrayBuffer { return buf.slice(DER_PREFIX.byteLength); } +/** + * utility function to constrain the type of a path + * @param {ArrayBuffer | HashTree | undefined} result - the result of a lookup + * @returns ArrayBuffer or Undefined + */ +export function lookupResultToBuffer( + result: ArrayBuffer | HashTree | undefined, +): ArrayBuffer | undefined { + if (result instanceof ArrayBuffer) { + return result; + } else if (result instanceof Uint8Array) { + return result.buffer; + } + return undefined; +} + /** * @param t */ @@ -392,7 +430,13 @@ export function lookup_path( if (path.length === 0) { switch (tree[0]) { case NodeId.Leaf: { - return new Uint8Array(tree[1]).buffer; + // should not be undefined + if (!tree[1]) throw new Error('Invalid tree structure for leaf'); + if (tree[1] instanceof ArrayBuffer) { + return tree[1]; + } else if (tree[1] instanceof Uint8Array) { + return tree[1].buffer; + } else return tree[1]; } case NodeId.Fork: { return tree; diff --git a/packages/agent/src/polling/index.ts b/packages/agent/src/polling/index.ts index 09c1e445d..84401ade1 100644 --- a/packages/agent/src/polling/index.ts +++ b/packages/agent/src/polling/index.ts @@ -1,6 +1,6 @@ import { Principal } from '@dfinity/principal'; import { Agent, RequestStatusResponseStatus } from '../agent'; -import { Certificate, CreateCertificateOptions } from '../certificate'; +import { Certificate, CreateCertificateOptions, lookupResultToBuffer } from '../certificate'; import { RequestId } from '../request_id'; import { toHex } from '../utils/buffer'; @@ -41,7 +41,7 @@ export async function pollForResponse( canisterId: canisterId, blsVerify, }); - const maybeBuf = cert.lookup([...path, new TextEncoder().encode('status')]); + const maybeBuf = lookupResultToBuffer(cert.lookup([...path, new TextEncoder().encode('status')])); let status; if (typeof maybeBuf === 'undefined') { // Missing requestId means we need to wait @@ -52,7 +52,7 @@ export async function pollForResponse( switch (status) { case RequestStatusResponseStatus.Replied: { - return cert.lookup([...path, 'reply'])!; + return lookupResultToBuffer(cert.lookup([...path, 'reply']))!; } case RequestStatusResponseStatus.Received: @@ -63,8 +63,12 @@ export async function pollForResponse( return pollForResponse(agent, canisterId, requestId, strategy, currentRequest); case RequestStatusResponseStatus.Rejected: { - const rejectCode = new Uint8Array(cert.lookup([...path, 'reject_code'])!)[0]; - const rejectMessage = new TextDecoder().decode(cert.lookup([...path, 'reject_message'])!); + const rejectCode = new Uint8Array( + lookupResultToBuffer(cert.lookup([...path, 'reject_code']))!, + )[0]; + const rejectMessage = new TextDecoder().decode( + lookupResultToBuffer(cert.lookup([...path, 'reject_message']))!, + ); throw new Error( `Call was rejected:\n` + ` Request ID: ${toHex(requestId)}\n` + diff --git a/packages/principal/src/index.ts b/packages/principal/src/index.ts index 081bb8f3e..fab88354e 100644 --- a/packages/principal/src/index.ts +++ b/packages/principal/src/index.ts @@ -117,10 +117,6 @@ export class Principal { return matches.join('-'); } - public toJSON(): string { - return this.toText(); - } - public toString(): string { return this.toText(); } From ca8a33f2508a86ed98a14fd51aabcf2d2db7e04c Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 28 Sep 2023 16:23:39 -0700 Subject: [PATCH 7/8] cleaning up lookup, changelog --- docs/generated/changelog.html | 8 +++++++- packages/agent/src/certificate.ts | 4 ++-- packages/agent/src/polling/index.ts | 14 +++++--------- packages/assets/src/index.ts | 3 ++- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/generated/changelog.html b/docs/generated/changelog.html index 1edf0a1cb..8d8cf012b 100644 --- a/docs/generated/changelog.html +++ b/docs/generated/changelog.html @@ -11,7 +11,13 @@

Agent-JS Changelog

Version x.x.x

-
    +
      +
    • + feat!: adds certificate logic to decode subnet and node key paths from the hashtree. + Changes the interface for `lookup_path` to allow returning a HashTree, but also constrains + `lookup` response to an ArrayBuffer using a new `lookupResultToBuffer` export +
    • +

    Version 0.19.3

    • fix: Principal JSON is compatible with @dfinity/utils jsonReviver helper
    • diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index 8974999e1..5b193fc1e 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -207,8 +207,8 @@ export class Certificate { this.cert = cbor.decode(new Uint8Array(certificate)); } - public lookup(path: Array): ArrayBuffer | HashTree | undefined { - return lookup_path(path, this.cert.tree); + public lookup(path: Array): ArrayBuffer | undefined { + return lookupResultToBuffer(lookup_path(path, this.cert.tree)); } public lookup_label(label: ArrayBuffer): ArrayBuffer | HashTree | undefined { diff --git a/packages/agent/src/polling/index.ts b/packages/agent/src/polling/index.ts index 84401ade1..09c1e445d 100644 --- a/packages/agent/src/polling/index.ts +++ b/packages/agent/src/polling/index.ts @@ -1,6 +1,6 @@ import { Principal } from '@dfinity/principal'; import { Agent, RequestStatusResponseStatus } from '../agent'; -import { Certificate, CreateCertificateOptions, lookupResultToBuffer } from '../certificate'; +import { Certificate, CreateCertificateOptions } from '../certificate'; import { RequestId } from '../request_id'; import { toHex } from '../utils/buffer'; @@ -41,7 +41,7 @@ export async function pollForResponse( canisterId: canisterId, blsVerify, }); - const maybeBuf = lookupResultToBuffer(cert.lookup([...path, new TextEncoder().encode('status')])); + const maybeBuf = cert.lookup([...path, new TextEncoder().encode('status')]); let status; if (typeof maybeBuf === 'undefined') { // Missing requestId means we need to wait @@ -52,7 +52,7 @@ export async function pollForResponse( switch (status) { case RequestStatusResponseStatus.Replied: { - return lookupResultToBuffer(cert.lookup([...path, 'reply']))!; + return cert.lookup([...path, 'reply'])!; } case RequestStatusResponseStatus.Received: @@ -63,12 +63,8 @@ export async function pollForResponse( return pollForResponse(agent, canisterId, requestId, strategy, currentRequest); case RequestStatusResponseStatus.Rejected: { - const rejectCode = new Uint8Array( - lookupResultToBuffer(cert.lookup([...path, 'reject_code']))!, - )[0]; - const rejectMessage = new TextDecoder().decode( - lookupResultToBuffer(cert.lookup([...path, 'reject_message']))!, - ); + const rejectCode = new Uint8Array(cert.lookup([...path, 'reject_code'])!)[0]; + const rejectMessage = new TextDecoder().decode(cert.lookup([...path, 'reject_message'])!); throw new Error( `Call was rejected:\n` + ` Request ID: ${toHex(requestId)}\n` + diff --git a/packages/assets/src/index.ts b/packages/assets/src/index.ts index 626ebb78f..9c4e91618 100644 --- a/packages/assets/src/index.ts +++ b/packages/assets/src/index.ts @@ -8,6 +8,7 @@ import { getDefaultAgent, HashTree, lookup_path, + lookupResultToBuffer, reconstruct, uint8ToBuf, } from '@dfinity/agent'; @@ -563,7 +564,7 @@ class Asset { } // Lookup hash of asset in tree - const treeSha = lookup_path(['http_assets', this._key], hashTree); + const treeSha = lookupResultToBuffer(lookup_path(['http_assets', this._key], hashTree)); return !!treeSha && !!this.sha256 && compare(this.sha256.buffer, treeSha) === 0; } From 6cad1c3897c29dfca81378823e525f41734eba70 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Fri, 29 Sep 2023 10:12:34 -0700 Subject: [PATCH 8/8] more cleanup --- packages/agent/src/agent/http/http.test.ts | 14 -------------- packages/agent/src/canisterStatus/index.ts | 12 ++++++++---- packages/agent/src/certificate.ts | 7 ++++--- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/agent/src/agent/http/http.test.ts b/packages/agent/src/agent/http/http.test.ts index c7377066d..1df6284c7 100644 --- a/packages/agent/src/agent/http/http.test.ts +++ b/packages/agent/src/agent/http/http.test.ts @@ -811,17 +811,3 @@ describe('default host', () => { } }); }); - -describe('fetchSubnetKeys', () => { - it.skip('should fetch node keys on application canisters for mainnet.', async () => { - jest.useFakeTimers(); - // const abbbb = (await import('isomorphic-fetch')).default; - // const agent = new HttpAgent({ fetch: abbbb, host: 'https://icp-api.io' }); - // await agent.fetchRootKey(); - // const subnetKeys = await agent.fetchSubnetKeys('erxue-5aaaa-aaaab-qaagq-cai'); //? - // const subnetKeys = await agent.fetchSubnetKeys('ryjl3-tyaaa-aaaaa-aaaba-cai'); //? - - // docs bkyz2-fmaaa-aaaaa-qaaaq-cai - // docs system bnz7o-iuaaa-aaaaa-qaaaa-cai - }); -}); diff --git a/packages/agent/src/canisterStatus/index.ts b/packages/agent/src/canisterStatus/index.ts index b40253ccb..7c92b1da0 100644 --- a/packages/agent/src/canisterStatus/index.ts +++ b/packages/agent/src/canisterStatus/index.ts @@ -2,7 +2,12 @@ import { Principal } from '@dfinity/principal'; import { AgentError } from '../errors'; import { HttpAgent } from '../agent/http'; -import { Certificate, CreateCertificateOptions, SubnetStatus } from '../certificate'; +import { + Certificate, + CreateCertificateOptions, + SubnetStatus, + lookupResultToBuffer, +} from '../certificate'; import { toHex } from '../utils/buffer'; import * as Cbor from '../cbor'; import { decodeLeb128, decodeTime } from '../utils/leb'; @@ -116,7 +121,7 @@ export const request = async (options: { } else { return { path: path, - data: cert.lookup(encodePath(path, canisterId)), + data: lookupResultToBuffer(cert.lookup(encodePath(path, canisterId))), }; } }; @@ -131,7 +136,7 @@ export const request = async (options: { } else { status.set(path.key, null); } - } else if (!Array.isArray(data)) { + } else { switch (path) { case 'time': { status.set(path, decodeTime(data)); @@ -181,7 +186,6 @@ export const request = async (options: { } } } catch (error) { - error; // Break on signature verification errors if ((error as AgentError)?.message?.includes('Invalid certificate')) { throw new AgentError((error as AgentError).message); diff --git a/packages/agent/src/certificate.ts b/packages/agent/src/certificate.ts index 5b193fc1e..3682c9b9b 100644 --- a/packages/agent/src/certificate.ts +++ b/packages/agent/src/certificate.ts @@ -208,6 +208,7 @@ export class Certificate { } public lookup(path: Array): ArrayBuffer | undefined { + // constrain the type of the result, so that empty HashTree is undefined return lookupResultToBuffer(lookup_path(path, this.cert.tree)); } @@ -262,7 +263,7 @@ export class Certificate { let sigVer = false; const lookupTime = this.lookup(['time']); - if (!lookupTime || !(lookupTime instanceof ArrayBuffer)) { + if (!lookupTime) { // Should never happen - time is always present in IC certificates throw new CertificateVerificationError('Certificate does not contain a time'); } @@ -316,7 +317,7 @@ export class Certificate { }); const rangeLookup = cert.lookup(['subnet', d.subnet_id, 'canister_ranges']); - if (!rangeLookup || !(rangeLookup instanceof ArrayBuffer)) { + if (!rangeLookup) { throw new CertificateVerificationError( `Could not find canister ranges for subnet 0x${toHex(d.subnet_id)}`, ); @@ -338,7 +339,7 @@ export class Certificate { ); } const publicKeyLookup = cert.lookup(['subnet', d.subnet_id, 'public_key']); - if (!publicKeyLookup || !(publicKeyLookup instanceof ArrayBuffer)) { + if (!publicKeyLookup) { throw new Error(`Could not find subnet key for subnet 0x${toHex(d.subnet_id)}`); } return publicKeyLookup;