@aztec/prover-client 0.73.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/dest/bin/get-proof-inputs.js +18 -16
  2. package/dest/block_builder/index.js +0 -1
  3. package/dest/block_builder/light.js +23 -13
  4. package/dest/config.js +9 -11
  5. package/dest/index.js +0 -1
  6. package/dest/mocks/fixtures.js +28 -26
  7. package/dest/mocks/test_context.js +55 -31
  8. package/dest/orchestrator/block-building-helpers.js +90 -90
  9. package/dest/orchestrator/block-proving-state.js +95 -70
  10. package/dest/orchestrator/epoch-proving-state.js +53 -40
  11. package/dest/orchestrator/index.js +0 -1
  12. package/dest/orchestrator/orchestrator.js +649 -653
  13. package/dest/orchestrator/orchestrator_metrics.js +4 -3
  14. package/dest/orchestrator/tx-proving-state.js +52 -51
  15. package/dest/prover-agent/index.js +0 -1
  16. package/dest/prover-agent/memory-proving-queue.js +237 -248
  17. package/dest/prover-agent/prover-agent.js +184 -187
  18. package/dest/prover-agent/proving-error.js +0 -1
  19. package/dest/prover-agent/queue_metrics.js +6 -5
  20. package/dest/prover-agent/rpc.js +6 -4
  21. package/dest/prover-client/factory.js +0 -1
  22. package/dest/prover-client/index.js +0 -1
  23. package/dest/prover-client/prover-client.js +30 -25
  24. package/dest/prover-client/server-epoch-prover.js +4 -4
  25. package/dest/proving_broker/broker_prover_facade.js +70 -59
  26. package/dest/proving_broker/config.js +22 -37
  27. package/dest/proving_broker/factory.js +1 -2
  28. package/dest/proving_broker/fixtures.js +0 -1
  29. package/dest/proving_broker/index.js +0 -1
  30. package/dest/proving_broker/proof_store/factory.js +9 -12
  31. package/dest/proving_broker/proof_store/gcs_proof_store.js +11 -7
  32. package/dest/proving_broker/proof_store/index.js +0 -1
  33. package/dest/proving_broker/proof_store/inline_proof_store.js +11 -7
  34. package/dest/proving_broker/proof_store/proof_store.js +3 -2
  35. package/dest/proving_broker/proving_agent.js +121 -110
  36. package/dest/proving_broker/proving_agent_instrumentation.js +3 -3
  37. package/dest/proving_broker/proving_broker.js +491 -451
  38. package/dest/proving_broker/proving_broker_database/memory.js +19 -13
  39. package/dest/proving_broker/proving_broker_database/persisted.js +41 -21
  40. package/dest/proving_broker/proving_broker_database.js +3 -2
  41. package/dest/proving_broker/proving_broker_instrumentation.js +28 -21
  42. package/dest/proving_broker/proving_job_controller.js +81 -62
  43. package/dest/proving_broker/rpc.js +23 -15
  44. package/dest/test/mock_prover.js +11 -9
  45. package/package.json +13 -11
  46. package/src/index.ts +1 -1
  47. package/src/orchestrator/block-building-helpers.ts +1 -1
  48. package/src/proving_broker/proving_agent.ts +30 -11
  49. package/src/proving_broker/proving_broker.ts +53 -27
  50. package/src/proving_broker/rpc.ts +8 -2
  51. package/dest/bin/get-proof-inputs.d.ts +0 -2
  52. package/dest/bin/get-proof-inputs.d.ts.map +0 -1
  53. package/dest/block_builder/index.d.ts +0 -6
  54. package/dest/block_builder/index.d.ts.map +0 -1
  55. package/dest/block_builder/light.d.ts +0 -31
  56. package/dest/block_builder/light.d.ts.map +0 -1
  57. package/dest/config.d.ts +0 -17
  58. package/dest/config.d.ts.map +0 -1
  59. package/dest/index.d.ts +0 -4
  60. package/dest/index.d.ts.map +0 -1
  61. package/dest/mocks/fixtures.d.ts +0 -19
  62. package/dest/mocks/fixtures.d.ts.map +0 -1
  63. package/dest/mocks/test_context.d.ts +0 -49
  64. package/dest/mocks/test_context.d.ts.map +0 -1
  65. package/dest/orchestrator/block-building-helpers.d.ts +0 -50
  66. package/dest/orchestrator/block-building-helpers.d.ts.map +0 -1
  67. package/dest/orchestrator/block-proving-state.d.ts +0 -71
  68. package/dest/orchestrator/block-proving-state.d.ts.map +0 -1
  69. package/dest/orchestrator/epoch-proving-state.d.ts +0 -56
  70. package/dest/orchestrator/epoch-proving-state.d.ts.map +0 -1
  71. package/dest/orchestrator/index.d.ts +0 -2
  72. package/dest/orchestrator/index.d.ts.map +0 -1
  73. package/dest/orchestrator/orchestrator.d.ts +0 -108
  74. package/dest/orchestrator/orchestrator.d.ts.map +0 -1
  75. package/dest/orchestrator/orchestrator_metrics.d.ts +0 -8
  76. package/dest/orchestrator/orchestrator_metrics.d.ts.map +0 -1
  77. package/dest/orchestrator/tx-proving-state.d.ts +0 -31
  78. package/dest/orchestrator/tx-proving-state.d.ts.map +0 -1
  79. package/dest/prover-agent/index.d.ts +0 -4
  80. package/dest/prover-agent/index.d.ts.map +0 -1
  81. package/dest/prover-agent/memory-proving-queue.d.ts +0 -82
  82. package/dest/prover-agent/memory-proving-queue.d.ts.map +0 -1
  83. package/dest/prover-agent/prover-agent.d.ts +0 -43
  84. package/dest/prover-agent/prover-agent.d.ts.map +0 -1
  85. package/dest/prover-agent/proving-error.d.ts +0 -5
  86. package/dest/prover-agent/proving-error.d.ts.map +0 -1
  87. package/dest/prover-agent/queue_metrics.d.ts +0 -10
  88. package/dest/prover-agent/queue_metrics.d.ts.map +0 -1
  89. package/dest/prover-agent/rpc.d.ts +0 -11
  90. package/dest/prover-agent/rpc.d.ts.map +0 -1
  91. package/dest/prover-client/factory.d.ts +0 -6
  92. package/dest/prover-client/factory.d.ts.map +0 -1
  93. package/dest/prover-client/index.d.ts +0 -3
  94. package/dest/prover-client/index.d.ts.map +0 -1
  95. package/dest/prover-client/prover-client.d.ts +0 -42
  96. package/dest/prover-client/prover-client.d.ts.map +0 -1
  97. package/dest/prover-client/server-epoch-prover.d.ts +0 -25
  98. package/dest/prover-client/server-epoch-prover.d.ts.map +0 -1
  99. package/dest/proving_broker/broker_prover_facade.d.ts +0 -39
  100. package/dest/proving_broker/broker_prover_facade.d.ts.map +0 -1
  101. package/dest/proving_broker/config.d.ts +0 -61
  102. package/dest/proving_broker/config.d.ts.map +0 -1
  103. package/dest/proving_broker/factory.d.ts +0 -5
  104. package/dest/proving_broker/factory.d.ts.map +0 -1
  105. package/dest/proving_broker/fixtures.d.ts +0 -5
  106. package/dest/proving_broker/fixtures.d.ts.map +0 -1
  107. package/dest/proving_broker/index.d.ts +0 -10
  108. package/dest/proving_broker/index.d.ts.map +0 -1
  109. package/dest/proving_broker/proof_store/factory.d.ts +0 -6
  110. package/dest/proving_broker/proof_store/factory.d.ts.map +0 -1
  111. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +0 -13
  112. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +0 -1
  113. package/dest/proving_broker/proof_store/index.d.ts +0 -4
  114. package/dest/proving_broker/proof_store/index.d.ts.map +0 -1
  115. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +0 -14
  116. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +0 -1
  117. package/dest/proving_broker/proof_store/proof_store.d.ts +0 -35
  118. package/dest/proving_broker/proof_store/proof_store.d.ts.map +0 -1
  119. package/dest/proving_broker/proving_agent.d.ts +0 -44
  120. package/dest/proving_broker/proving_agent.d.ts.map +0 -1
  121. package/dest/proving_broker/proving_agent_instrumentation.d.ts +0 -8
  122. package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +0 -1
  123. package/dest/proving_broker/proving_broker.d.ts +0 -75
  124. package/dest/proving_broker/proving_broker.d.ts.map +0 -1
  125. package/dest/proving_broker/proving_broker_database/memory.d.ts +0 -16
  126. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +0 -1
  127. package/dest/proving_broker/proving_broker_database/persisted.d.ts +0 -21
  128. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +0 -1
  129. package/dest/proving_broker/proving_broker_database.d.ts +0 -39
  130. package/dest/proving_broker/proving_broker_database.d.ts.map +0 -1
  131. package/dest/proving_broker/proving_broker_instrumentation.d.ts +0 -25
  132. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +0 -1
  133. package/dest/proving_broker/proving_job_controller.d.ts +0 -31
  134. package/dest/proving_broker/proving_job_controller.d.ts.map +0 -1
  135. package/dest/proving_broker/rpc.d.ts +0 -11
  136. package/dest/proving_broker/rpc.d.ts.map +0 -1
  137. package/dest/test/mock_prover.d.ts +0 -33
  138. package/dest/test/mock_prover.d.ts.map +0 -1
@@ -1,8 +1,8 @@
1
- import { Body, MerkleTreeId, TxEffect, getTreeHeight, } from '@aztec/circuit-types';
2
- import { ARCHIVE_HEIGHT, AppendOnlyTreeSnapshot, BlockHeader, ContentCommitment, Fr, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MerkleTreeCalculator, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NullifierLeafPreimage, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage, StateReference, } from '@aztec/circuits.js';
3
- import { ConstantRollupData, PrivateBaseRollupHints, PrivateBaseStateDiffHints, PublicBaseRollupHints, PublicBaseStateDiffHints, } from '@aztec/circuits.js/rollup';
1
+ import { Blob } from '@aztec/blob-lib';
2
+ import { Body, MerkleTreeId, TxEffect, getTreeHeight } from '@aztec/circuit-types';
3
+ import { ARCHIVE_HEIGHT, AppendOnlyTreeSnapshot, BlockHeader, ContentCommitment, Fr, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MerkleTreeCalculator, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NullifierLeafPreimage, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage, StateReference } from '@aztec/circuits.js';
4
+ import { ConstantRollupData, PrivateBaseRollupHints, PrivateBaseStateDiffHints, PublicBaseRollupHints, PublicBaseStateDiffHints } from '@aztec/circuits.js/rollup';
4
5
  import { makeTuple } from '@aztec/foundation/array';
5
- import { Blob } from '@aztec/foundation/blob';
6
6
  import { padArrayEnd } from '@aztec/foundation/collection';
7
7
  import { sha256Trunc } from '@aztec/foundation/crypto';
8
8
  import { assertLength, serializeToBuffer, toFriendlyJSON } from '@aztec/foundation/serialize';
@@ -13,14 +13,14 @@ import { computeFeePayerBalanceLeafSlot } from '@aztec/simulator/server';
13
13
  import { Attributes, runInSpan } from '@aztec/telemetry-client';
14
14
  import { inspect } from 'util';
15
15
  // Builds the hints for base rollup. Updating the contract, nullifier, and data trees in the process.
16
- export const buildBaseRollupHints = runInSpan('BlockBuilderHelpers', 'buildBaseRollupHints', async (span, tx, globalVariables, db, startSpongeBlob) => {
16
+ export const buildBaseRollupHints = runInSpan('BlockBuilderHelpers', 'buildBaseRollupHints', async (span, tx, globalVariables, db, startSpongeBlob)=>{
17
17
  span.setAttribute(Attributes.TX_HASH, tx.hash.toString());
18
18
  // Get trees info before any changes hit
19
19
  const constants = await getConstantRollupData(globalVariables, db);
20
20
  const start = new PartialStateReference(await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db), await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db), await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db));
21
21
  // Get the subtree sibling paths for the circuit
22
22
  const noteHashSubtreeSiblingPathArray = await getSubtreeSiblingPath(MerkleTreeId.NOTE_HASH_TREE, NOTE_HASH_SUBTREE_HEIGHT, db);
23
- const noteHashSubtreeSiblingPath = makeTuple(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, i => i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO);
23
+ const noteHashSubtreeSiblingPath = makeTuple(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, (i)=>i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO);
24
24
  // Update the note hash trees with the new items being inserted to get the new roots
25
25
  // that will be used by the next iteration of the base rollup circuit, skipping the empty ones
26
26
  const noteHashes = padArrayEnd(tx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX);
@@ -29,33 +29,29 @@ export const buildBaseRollupHints = runInSpan('BlockBuilderHelpers', 'buildBaseR
29
29
  // All reads that refer to writes in the same tx are transient and can be simplified out.
30
30
  const txPublicDataUpdateRequestInfo = await processPublicDataUpdateRequests(tx, db);
31
31
  // Update the nullifier tree, capturing the low nullifier info for each individual operation
32
- const { lowLeavesWitnessData: nullifierWitnessLeaves, newSubtreeSiblingPath: nullifiersSubtreeSiblingPath, sortedNewLeaves: sortednullifiers, sortedNewLeavesIndexes, } = await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()), NULLIFIER_SUBTREE_HEIGHT);
32
+ const { lowLeavesWitnessData: nullifierWitnessLeaves, newSubtreeSiblingPath: nullifiersSubtreeSiblingPath, sortedNewLeaves: sortednullifiers, sortedNewLeavesIndexes } = await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map((n)=>n.toBuffer()), NULLIFIER_SUBTREE_HEIGHT);
33
33
  if (nullifierWitnessLeaves === undefined) {
34
34
  throw new Error(`Could not craft nullifier batch insertion proofs`);
35
35
  }
36
36
  // Extract witness objects from returned data
37
- const nullifierPredecessorMembershipWitnessesWithoutPadding = nullifierWitnessLeaves.map(l => MembershipWitness.fromBufferArray(l.index, assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT)));
37
+ const nullifierPredecessorMembershipWitnessesWithoutPadding = nullifierWitnessLeaves.map((l)=>MembershipWitness.fromBufferArray(l.index, assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT)));
38
38
  const nullifierSubtreeSiblingPathArray = nullifiersSubtreeSiblingPath.toFields();
39
- const nullifierSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, i => i < nullifierSubtreeSiblingPathArray.length ? nullifierSubtreeSiblingPathArray[i] : Fr.ZERO);
39
+ const nullifierSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, (i)=>i < nullifierSubtreeSiblingPathArray.length ? nullifierSubtreeSiblingPathArray[i] : Fr.ZERO);
40
40
  // Append new data to startSpongeBlob
41
41
  const inputSpongeBlob = startSpongeBlob.clone();
42
42
  await startSpongeBlob.absorb(tx.txEffect.toBlobFields());
43
43
  if (tx.avmProvingRequest) {
44
44
  // Build public base rollup hints
45
45
  const stateDiffHints = PublicBaseStateDiffHints.from({
46
- nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i => i < nullifierWitnessLeaves.length
47
- ? nullifierWitnessLeaves[i].leafPreimage
48
- : NullifierLeafPreimage.empty()),
49
- nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i => i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
50
- ? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
51
- : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT)),
52
- sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
53
- sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
46
+ nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>i < nullifierWitnessLeaves.length ? nullifierWitnessLeaves[i].leafPreimage : NullifierLeafPreimage.empty()),
47
+ nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>i < nullifierPredecessorMembershipWitnessesWithoutPadding.length ? nullifierPredecessorMembershipWitnessesWithoutPadding[i] : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT)),
48
+ sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>Fr.fromBuffer(sortednullifiers[i])),
49
+ sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>sortedNewLeavesIndexes[i]),
54
50
  noteHashSubtreeSiblingPath,
55
51
  nullifierSubtreeSiblingPath,
56
52
  lowPublicDataWritesPreimages: padArrayEnd(txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages, PublicDataTreeLeafPreimage.empty(), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX),
57
53
  lowPublicDataWritesMembershipWitnesses: padArrayEnd(txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses, MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX),
58
- publicDataTreeSiblingPaths: padArrayEnd(txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths, makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX),
54
+ publicDataTreeSiblingPaths: padArrayEnd(txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths, makeTuple(PUBLIC_DATA_TREE_HEIGHT, ()=>Fr.ZERO), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX)
59
55
  });
60
56
  const blockHash = await tx.constants.historicalHeader.hash();
61
57
  const archiveRootMembershipWitness = await getMembershipWitnessFor(blockHash, MerkleTreeId.ARCHIVE, ARCHIVE_HEIGHT, db);
@@ -64,40 +60,29 @@ export const buildBaseRollupHints = runInSpan('BlockBuilderHelpers', 'buildBaseR
64
60
  startSpongeBlob: inputSpongeBlob,
65
61
  stateDiffHints,
66
62
  archiveRootMembershipWitness,
67
- constants,
63
+ constants
68
64
  });
69
- }
70
- else {
71
- if (txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses.length > 1 ||
72
- txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages.length > 1 ||
73
- txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths.length > 1) {
65
+ } else {
66
+ if (txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses.length > 1 || txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages.length > 1 || txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths.length > 1) {
74
67
  throw new Error(`More than one public data write in a private only tx`);
75
68
  }
76
69
  // Create data hint for reading fee payer initial balance in Fee Juice
77
70
  // If no fee payer is set, read hint should be empty
78
71
  const leafSlot = await computeFeePayerBalanceLeafSlot(tx.data.feePayer);
79
- const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero()
80
- ? PublicDataHint.empty()
81
- : await getPublicDataHint(db, leafSlot.toBigInt());
72
+ const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero() ? PublicDataHint.empty() : await getPublicDataHint(db, leafSlot.toBigInt());
82
73
  const feeWriteLowLeafPreimage = txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages[0] || PublicDataTreeLeafPreimage.empty();
83
- const feeWriteLowLeafMembershipWitness = txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses[0] ||
84
- MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT);
85
- const feeWriteSiblingPath = txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths[0] ||
86
- makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO);
74
+ const feeWriteLowLeafMembershipWitness = txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses[0] || MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT);
75
+ const feeWriteSiblingPath = txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths[0] || makeTuple(PUBLIC_DATA_TREE_HEIGHT, ()=>Fr.ZERO);
87
76
  const stateDiffHints = PrivateBaseStateDiffHints.from({
88
- nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i => i < nullifierWitnessLeaves.length
89
- ? nullifierWitnessLeaves[i].leafPreimage
90
- : NullifierLeafPreimage.empty()),
91
- nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i => i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
92
- ? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
93
- : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT)),
94
- sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
95
- sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
77
+ nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>i < nullifierWitnessLeaves.length ? nullifierWitnessLeaves[i].leafPreimage : NullifierLeafPreimage.empty()),
78
+ nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>i < nullifierPredecessorMembershipWitnessesWithoutPadding.length ? nullifierPredecessorMembershipWitnessesWithoutPadding[i] : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT)),
79
+ sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>Fr.fromBuffer(sortednullifiers[i])),
80
+ sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, (i)=>sortedNewLeavesIndexes[i]),
96
81
  noteHashSubtreeSiblingPath,
97
82
  nullifierSubtreeSiblingPath,
98
83
  feeWriteLowLeafPreimage,
99
84
  feeWriteLowLeafMembershipWitness,
100
- feeWriteSiblingPath,
85
+ feeWriteSiblingPath
101
86
  });
102
87
  const blockHash = await tx.constants.historicalHeader.hash();
103
88
  const archiveRootMembershipWitness = await getMembershipWitnessFor(blockHash, MerkleTreeId.ARCHIVE, ARCHIVE_HEIGHT, db);
@@ -107,18 +92,18 @@ export const buildBaseRollupHints = runInSpan('BlockBuilderHelpers', 'buildBaseR
107
92
  stateDiffHints,
108
93
  feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint,
109
94
  archiveRootMembershipWitness,
110
- constants,
95
+ constants
111
96
  });
112
97
  }
113
98
  });
114
99
  export async function getPublicDataHint(db, leafSlot) {
115
- const { index } = (await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot)) ?? {};
100
+ const { index } = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot) ?? {};
116
101
  if (index === undefined) {
117
102
  throw new Error(`Cannot find the previous value index for public data ${leafSlot}.`);
118
103
  }
119
104
  const siblingPath = await db.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, index);
120
105
  const membershipWitness = new MembershipWitness(PUBLIC_DATA_TREE_HEIGHT, index, siblingPath.toTuple());
121
- const leafPreimage = (await db.getLeafPreimage(MerkleTreeId.PUBLIC_DATA_TREE, index));
106
+ const leafPreimage = await db.getLeafPreimage(MerkleTreeId.PUBLIC_DATA_TREE, index);
122
107
  if (!leafPreimage) {
123
108
  throw new Error(`Cannot find the leaf preimage for public data tree at index ${index}.`);
124
109
  }
@@ -126,76 +111,90 @@ export async function getPublicDataHint(db, leafSlot) {
126
111
  const value = exists ? leafPreimage.value : Fr.ZERO;
127
112
  return new PublicDataHint(new Fr(leafSlot), value, membershipWitness, leafPreimage);
128
113
  }
129
- export const buildBlobHints = runInSpan('BlockBuilderHelpers', 'buildBlobHints', async (_span, txEffects) => {
130
- const blobFields = txEffects.flatMap(tx => tx.toBlobFields());
114
+ export const buildBlobHints = runInSpan('BlockBuilderHelpers', 'buildBlobHints', async (_span, txEffects)=>{
115
+ const blobFields = txEffects.flatMap((tx)=>tx.toBlobFields());
131
116
  const blobs = await Blob.getBlobs(blobFields);
132
- const blobCommitments = blobs.map(b => b.commitmentToFields());
117
+ const blobCommitments = blobs.map((b)=>b.commitmentToFields());
133
118
  const blobsHash = new Fr(getBlobsHashFromBlobs(blobs));
134
- return { blobFields, blobCommitments, blobs, blobsHash };
119
+ return {
120
+ blobFields,
121
+ blobCommitments,
122
+ blobs,
123
+ blobsHash
124
+ };
135
125
  });
136
- export const buildHeaderFromCircuitOutputs = runInSpan('BlockBuilderHelpers', 'buildHeaderFromCircuitOutputs', async (_span, previousRollupData, parityPublicInputs, rootRollupOutputs, endState, logger) => {
126
+ export const buildHeaderFromCircuitOutputs = runInSpan('BlockBuilderHelpers', 'buildHeaderFromCircuitOutputs', async (_span, previousRollupData, parityPublicInputs, rootRollupOutputs, endState, logger)=>{
137
127
  if (previousRollupData.length > 2) {
138
128
  throw new Error(`There can't be more than 2 previous rollups. Received ${previousRollupData.length}.`);
139
129
  }
140
130
  const blobsHash = rootRollupOutputs.blobPublicInputs[0].getBlobsHash();
141
- const numTxs = previousRollupData.reduce((sum, d) => sum + d.numTxs, 0);
142
- const outHash = previousRollupData.length === 0
143
- ? Fr.ZERO.toBuffer()
144
- : previousRollupData.length === 1
145
- ? previousRollupData[0].outHash.toBuffer()
146
- : sha256Trunc(Buffer.concat([previousRollupData[0].outHash.toBuffer(), previousRollupData[1].outHash.toBuffer()]));
131
+ const numTxs = previousRollupData.reduce((sum, d)=>sum + d.numTxs, 0);
132
+ const outHash = previousRollupData.length === 0 ? Fr.ZERO.toBuffer() : previousRollupData.length === 1 ? previousRollupData[0].outHash.toBuffer() : sha256Trunc(Buffer.concat([
133
+ previousRollupData[0].outHash.toBuffer(),
134
+ previousRollupData[1].outHash.toBuffer()
135
+ ]));
147
136
  const contentCommitment = new ContentCommitment(new Fr(numTxs), blobsHash, parityPublicInputs.shaRoot.toBuffer(), outHash);
148
- const accumulatedFees = previousRollupData.reduce((sum, d) => sum.add(d.accumulatedFees), Fr.ZERO);
149
- const accumulatedManaUsed = previousRollupData.reduce((sum, d) => sum.add(d.accumulatedManaUsed), Fr.ZERO);
137
+ const accumulatedFees = previousRollupData.reduce((sum, d)=>sum.add(d.accumulatedFees), Fr.ZERO);
138
+ const accumulatedManaUsed = previousRollupData.reduce((sum, d)=>sum.add(d.accumulatedManaUsed), Fr.ZERO);
150
139
  const header = new BlockHeader(rootRollupOutputs.previousArchive, contentCommitment, endState, rootRollupOutputs.endGlobalVariables, accumulatedFees, accumulatedManaUsed);
151
140
  if (!(await header.hash()).equals(rootRollupOutputs.endBlockHash)) {
152
- logger?.error(`Block header mismatch when building header from circuit outputs.` +
153
- `\n\nHeader: ${inspect(header)}` +
154
- `\n\nCircuit: ${toFriendlyJSON(rootRollupOutputs)}`);
141
+ logger?.error(`Block header mismatch when building header from circuit outputs.` + `\n\nHeader: ${inspect(header)}` + `\n\nCircuit: ${toFriendlyJSON(rootRollupOutputs)}`);
155
142
  throw new Error(`Block header mismatch when building from circuit outputs`);
156
143
  }
157
144
  return header;
158
145
  });
159
- export const buildHeaderAndBodyFromTxs = runInSpan('BlockBuilderHelpers', 'buildHeaderAndBodyFromTxs', async (span, txs, globalVariables, l1ToL2Messages, db) => {
146
+ export const buildHeaderAndBodyFromTxs = runInSpan('BlockBuilderHelpers', 'buildHeaderAndBodyFromTxs', async (span, txs, globalVariables, l1ToL2Messages, db)=>{
160
147
  span.setAttribute(Attributes.BLOCK_NUMBER, globalVariables.blockNumber.toNumber());
161
148
  const stateReference = new StateReference(await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db), new PartialStateReference(await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db), await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db), await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db)));
162
149
  const previousArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
163
- const txEffects = txs.map(tx => tx.txEffect);
150
+ const txEffects = txs.map((tx)=>tx.txEffect);
164
151
  const body = new Body(txEffects);
165
152
  const numTxs = body.txEffects.length;
166
- const outHash = numTxs === 0
167
- ? Fr.ZERO.toBuffer()
168
- : numTxs === 1
169
- ? body.txEffects[0].txOutHash()
170
- : computeUnbalancedMerkleRoot(body.txEffects.map(tx => tx.txOutHash()), TxEffect.empty().txOutHash());
153
+ const outHash = numTxs === 0 ? Fr.ZERO.toBuffer() : numTxs === 1 ? body.txEffects[0].txOutHash() : computeUnbalancedMerkleRoot(body.txEffects.map((tx)=>tx.txOutHash()), TxEffect.empty().txOutHash());
171
154
  l1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
172
- const hasher = (left, right) => Promise.resolve(sha256Trunc(Buffer.concat([left, right])));
155
+ const hasher = (left, right)=>Promise.resolve(sha256Trunc(Buffer.concat([
156
+ left,
157
+ right
158
+ ])));
173
159
  const parityHeight = Math.ceil(Math.log2(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
174
160
  const parityCalculator = await MerkleTreeCalculator.create(parityHeight, Fr.ZERO.toBuffer(), hasher);
175
- const parityShaRoot = await parityCalculator.computeTreeRoot(l1ToL2Messages.map(msg => msg.toBuffer()));
161
+ const parityShaRoot = await parityCalculator.computeTreeRoot(l1ToL2Messages.map((msg)=>msg.toBuffer()));
176
162
  const blobsHash = getBlobsHashFromBlobs(await Blob.getBlobs(body.toBlobFields()));
177
163
  const contentCommitment = new ContentCommitment(new Fr(numTxs), blobsHash, parityShaRoot, outHash);
178
- const fees = body.txEffects.reduce((acc, tx) => acc.add(tx.transactionFee), Fr.ZERO);
179
- const manaUsed = txs.reduce((acc, tx) => acc.add(new Fr(tx.gasUsed.totalGas.l2Gas)), Fr.ZERO);
164
+ const fees = body.txEffects.reduce((acc, tx)=>acc.add(tx.transactionFee), Fr.ZERO);
165
+ const manaUsed = txs.reduce((acc, tx)=>acc.add(new Fr(tx.gasUsed.totalGas.l2Gas)), Fr.ZERO);
180
166
  const header = new BlockHeader(previousArchive, contentCommitment, stateReference, globalVariables, fees, manaUsed);
181
- return { header, body };
167
+ return {
168
+ header,
169
+ body
170
+ };
182
171
  });
183
172
  export function getBlobsHashFromBlobs(inputs) {
184
- const blobHashes = serializeToBuffer(inputs.map(b => b.getEthVersionedBlobHash()));
173
+ const blobHashes = serializeToBuffer(inputs.map((b)=>b.getEthVersionedBlobHash()));
185
174
  return sha256Trunc(serializeToBuffer(blobHashes));
186
175
  }
187
176
  // Validate that the roots of all local trees match the output of the root circuit simulation
188
177
  export async function validateBlockRootOutput(blockRootOutput, blockHeader, db) {
189
178
  await Promise.all([
190
179
  validateState(blockHeader.state, db),
191
- validateSimulatedTree(await getTreeSnapshot(MerkleTreeId.ARCHIVE, db), blockRootOutput.newArchive, 'Archive'),
180
+ validateSimulatedTree(await getTreeSnapshot(MerkleTreeId.ARCHIVE, db), blockRootOutput.newArchive, 'Archive')
192
181
  ]);
193
182
  }
194
- export const validateState = runInSpan('BlockBuilderHelpers', 'validateState', async (_span, state, db) => {
195
- const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(async (id) => {
196
- return { key: id, value: await getTreeSnapshot(id, db) };
183
+ export const validateState = runInSpan('BlockBuilderHelpers', 'validateState', async (_span, state, db)=>{
184
+ const promises = [
185
+ MerkleTreeId.NOTE_HASH_TREE,
186
+ MerkleTreeId.NULLIFIER_TREE,
187
+ MerkleTreeId.PUBLIC_DATA_TREE
188
+ ].map(async (id)=>{
189
+ return {
190
+ key: id,
191
+ value: await getTreeSnapshot(id, db)
192
+ };
197
193
  });
198
- const snapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
194
+ const snapshots = new Map((await Promise.all(promises)).map((obj)=>[
195
+ obj.key,
196
+ obj.value
197
+ ]));
199
198
  validatePartialState(state.partial, snapshots);
200
199
  validateSimulatedTree(await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db), state.l1ToL2MessageTree, 'L1ToL2MessageTree');
201
200
  });
@@ -204,12 +203,12 @@ export async function getRootTreeSiblingPath(treeId, db) {
204
203
  const path = await db.getSiblingPath(treeId, size);
205
204
  return padArrayEnd(path.toFields(), Fr.ZERO, getTreeHeight(treeId));
206
205
  }
207
- export const getConstantRollupData = runInSpan('BlockBuilderHelpers', 'getConstantRollupData', async (_span, globalVariables, db) => {
206
+ export const getConstantRollupData = runInSpan('BlockBuilderHelpers', 'getConstantRollupData', async (_span, globalVariables, db)=>{
208
207
  return ConstantRollupData.from({
209
208
  vkTreeRoot: await getVKTreeRoot(),
210
209
  protocolContractTreeRoot,
211
210
  lastArchive: await getTreeSnapshot(MerkleTreeId.ARCHIVE, db),
212
- globalVariables,
211
+ globalVariables
213
212
  });
214
213
  });
215
214
  export async function getTreeSnapshot(id, db) {
@@ -217,20 +216,20 @@ export async function getTreeSnapshot(id, db) {
217
216
  return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size));
218
217
  }
219
218
  export function makeEmptyMembershipWitness(height) {
220
- return new MembershipWitness(height, 0n, makeTuple(height, () => Fr.ZERO));
219
+ return new MembershipWitness(height, 0n, makeTuple(height, ()=>Fr.ZERO));
221
220
  }
222
- const processPublicDataUpdateRequests = runInSpan('BlockBuilderHelpers', 'processPublicDataUpdateRequests', async (span, tx, db) => {
221
+ const processPublicDataUpdateRequests = runInSpan('BlockBuilderHelpers', 'processPublicDataUpdateRequests', async (span, tx, db)=>{
223
222
  span.setAttribute(Attributes.TX_HASH, tx.hash.toString());
224
- const allPublicDataWrites = tx.txEffect.publicDataWrites.map(({ leafSlot, value }) => new PublicDataTreeLeaf(leafSlot, value));
225
- const { lowLeavesWitnessData, insertionWitnessData } = await db.sequentialInsert(MerkleTreeId.PUBLIC_DATA_TREE, allPublicDataWrites.map(write => {
223
+ const allPublicDataWrites = tx.txEffect.publicDataWrites.map(({ leafSlot, value })=>new PublicDataTreeLeaf(leafSlot, value));
224
+ const { lowLeavesWitnessData, insertionWitnessData } = await db.sequentialInsert(MerkleTreeId.PUBLIC_DATA_TREE, allPublicDataWrites.map((write)=>{
226
225
  if (write.isEmpty()) {
227
226
  throw new Error(`Empty public data write in tx: ${toFriendlyJSON(tx)}`);
228
227
  }
229
228
  return write.toBuffer();
230
229
  }));
231
- const lowPublicDataWritesPreimages = lowLeavesWitnessData.map(lowLeafWitness => lowLeafWitness.leafPreimage);
232
- const lowPublicDataWritesMembershipWitnesses = lowLeavesWitnessData.map(lowLeafWitness => MembershipWitness.fromBufferArray(lowLeafWitness.index, assertLength(lowLeafWitness.siblingPath.toBufferArray(), PUBLIC_DATA_TREE_HEIGHT)));
233
- const publicDataWritesSiblingPaths = insertionWitnessData.map(w => {
230
+ const lowPublicDataWritesPreimages = lowLeavesWitnessData.map((lowLeafWitness)=>lowLeafWitness.leafPreimage);
231
+ const lowPublicDataWritesMembershipWitnesses = lowLeavesWitnessData.map((lowLeafWitness)=>MembershipWitness.fromBufferArray(lowLeafWitness.index, assertLength(lowLeafWitness.siblingPath.toBufferArray(), PUBLIC_DATA_TREE_HEIGHT)));
232
+ const publicDataWritesSiblingPaths = insertionWitnessData.map((w)=>{
234
233
  const insertionSiblingPath = w.siblingPath.toFields();
235
234
  assertLength(insertionSiblingPath, PUBLIC_DATA_TREE_HEIGHT);
236
235
  return insertionSiblingPath;
@@ -238,11 +237,11 @@ const processPublicDataUpdateRequests = runInSpan('BlockBuilderHelpers', 'proces
238
237
  return {
239
238
  lowPublicDataWritesPreimages,
240
239
  lowPublicDataWritesMembershipWitnesses,
241
- publicDataWritesSiblingPaths,
240
+ publicDataWritesSiblingPaths
242
241
  };
243
242
  });
244
243
  export async function getSubtreeSiblingPath(treeId, subtreeHeight, db) {
245
- const nextAvailableLeafIndex = await db.getTreeInfo(treeId).then(t => t.size);
244
+ const nextAvailableLeafIndex = await db.getTreeInfo(treeId).then((t)=>t.size);
246
245
  const fullSiblingPath = await db.getSiblingPath(treeId, nextAvailableLeafIndex);
247
246
  // Drop the first subtreeHeight items since we only care about the path to the subtree root
248
247
  return fullSiblingPath.getSubtreeSiblingPath(subtreeHeight).toFields();
@@ -253,7 +252,9 @@ export async function getMembershipWitnessFor(value, treeId, height, db) {
253
252
  if (value.isZero()) {
254
253
  return makeEmptyMembershipWitness(height);
255
254
  }
256
- const index = (await db.findLeafIndices(treeId, [value.toBuffer()]))[0];
255
+ const index = (await db.findLeafIndices(treeId, [
256
+ value.toBuffer()
257
+ ]))[0];
257
258
  if (index === undefined) {
258
259
  throw new Error(`Leaf with value ${value} not found in tree ${MerkleTreeId[treeId]}`);
259
260
  }
@@ -289,4 +290,3 @@ export function validateTx(tx) {
289
290
  throw new Error(`Empty public data tree in tx: ${toFriendlyJSON(tx)}`);
290
291
  }
291
292
  }
292
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2stYnVpbGRpbmctaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vcmNoZXN0cmF0b3IvYmxvY2stYnVpbGRpbmctaGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsSUFBSSxFQUNKLFlBQVksRUFHWixRQUFRLEVBQ1IsYUFBYSxHQUNkLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUNMLGNBQWMsRUFDZCxzQkFBc0IsRUFDdEIsV0FBVyxFQUNYLGlCQUFpQixFQUNqQixFQUFFLEVBRUYsc0JBQXNCLEVBQ3RCLHFCQUFxQixFQUNyQiw0Q0FBNEMsRUFDNUMsaUJBQWlCLEVBQ2pCLG9CQUFvQixFQUNwQix3QkFBd0IsRUFDeEIscUNBQXFDLEVBQ3JDLHdCQUF3QixFQUN4QixxQ0FBcUMsRUFDckMscUJBQXFCLEVBQ3JCLG1DQUFtQyxFQUNuQyxxQkFBcUIsRUFDckIsdUJBQXVCLEVBRXZCLHFCQUFxQixFQUNyQixjQUFjLEVBQ2Qsa0JBQWtCLEVBQ2xCLDBCQUEwQixFQUMxQixjQUFjLEdBQ2YsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QixPQUFPLEVBR0wsa0JBQWtCLEVBQ2xCLHNCQUFzQixFQUN0Qix5QkFBeUIsRUFDekIscUJBQXFCLEVBQ3JCLHdCQUF3QixHQUN6QixNQUFNLDJCQUEyQixDQUFDO0FBQ25DLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RCxPQUFPLEVBQWMsWUFBWSxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzFHLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsVUFBVSxFQUFhLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzNFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFXL0IscUdBQXFHO0FBQ3JHLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLFNBQVMsQ0FDM0MscUJBQXFCLEVBQ3JCLHNCQUFzQixFQUN0QixLQUFLLEVBQ0gsSUFBVSxFQUNWLEVBQWUsRUFDZixlQUFnQyxFQUNoQyxFQUE2QixFQUM3QixlQUEyQixFQUMzQixFQUFFO0lBQ0YsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUMxRCx3Q0FBd0M7SUFDeEMsTUFBTSxTQUFTLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkUsTUFBTSxLQUFLLEdBQUcsSUFBSSxxQkFBcUIsQ0FDckMsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsRUFDdEQsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsRUFDdEQsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUN6RCxDQUFDO0lBQ0YsZ0RBQWdEO0lBQ2hELE1BQU0sK0JBQStCLEdBQUcsTUFBTSxxQkFBcUIsQ0FDakUsWUFBWSxDQUFDLGNBQWMsRUFDM0Isd0JBQXdCLEVBQ3hCLEVBQUUsQ0FDSCxDQUFDO0lBRUYsTUFBTSwwQkFBMEIsR0FBRyxTQUFTLENBQUMscUNBQXFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FDdEYsQ0FBQyxHQUFHLCtCQUErQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsK0JBQStCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQzFGLENBQUM7SUFFRixvRkFBb0Y7SUFDcEYsOEZBQThGO0lBQzlGLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsSUFBSSxFQUFFLHNCQUFzQixDQUFDLENBQUM7SUFDeEYsTUFBTSxFQUFFLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFFL0Qsc0dBQXNHO0lBQ3RHLHlGQUF5RjtJQUN6RixNQUFNLDZCQUE2QixHQUFHLE1BQU0sK0JBQStCLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXBGLDRGQUE0RjtJQUM1RixNQUFNLEVBQ0osb0JBQW9CLEVBQUUsc0JBQXNCLEVBQzVDLHFCQUFxQixFQUFFLDRCQUE0QixFQUNuRCxlQUFlLEVBQUUsZ0JBQWdCLEVBQ2pDLHNCQUFzQixHQUN2QixHQUFHLE1BQU0sRUFBRSxDQUFDLFdBQVcsQ0FDdEIsWUFBWSxDQUFDLGNBQWMsRUFDM0IsV0FBVyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxJQUFJLEVBQUUscUJBQXFCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDMUYsd0JBQXdCLENBQ3pCLENBQUM7SUFFRixJQUFJLHNCQUFzQixLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBRUQsNkNBQTZDO0lBQzdDLE1BQU0scURBQXFELEdBQ3pELHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUM3QixpQkFBaUIsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxhQUFhLEVBQUUsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQy9HLENBQUM7SUFFSixNQUFNLGdDQUFnQyxHQUFHLDRCQUE0QixDQUFDLFFBQVEsRUFBRSxDQUFDO0lBRWpGLE1BQU0sMkJBQTJCLEdBQUcsU0FBUyxDQUFDLHFDQUFxQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQ3ZGLENBQUMsR0FBRyxnQ0FBZ0MsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLGdDQUFnQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUM1RixDQUFDO0lBRUYscUNBQXFDO0lBQ3JDLE1BQU0sZUFBZSxHQUFHLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNoRCxNQUFNLGVBQWUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBRXpELElBQUksRUFBRSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsaUNBQWlDO1FBQ2pDLE1BQU0sY0FBYyxHQUFHLHdCQUF3QixDQUFDLElBQUksQ0FBQztZQUNuRCw2QkFBNkIsRUFBRSxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FDbEUsQ0FBQyxHQUFHLHNCQUFzQixDQUFDLE1BQU07Z0JBQy9CLENBQUMsQ0FBRSxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFzQztnQkFDbkUsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLEtBQUssRUFBRSxDQUNsQztZQUNELHVDQUF1QyxFQUFFLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUM1RSxDQUFDLEdBQUcscURBQXFELENBQUMsTUFBTTtnQkFDOUQsQ0FBQyxDQUFDLHFEQUFxRCxDQUFDLENBQUMsQ0FBQztnQkFDMUQsQ0FBQyxDQUFDLDBCQUEwQixDQUFDLHFCQUFxQixDQUFDLENBQ3REO1lBQ0QsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNGLHNCQUFzQixFQUFFLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hGLDBCQUEwQjtZQUMxQiwyQkFBMkI7WUFDM0IsNEJBQTRCLEVBQUUsV0FBVyxDQUN2Qyw2QkFBNkIsQ0FBQyw0QkFBNEIsRUFDMUQsMEJBQTBCLENBQUMsS0FBSyxFQUFFLEVBQ2xDLDRDQUE0QyxDQUM3QztZQUNELHNDQUFzQyxFQUFFLFdBQVcsQ0FDakQsNkJBQTZCLENBQUMsc0NBQXNDLEVBQ3BFLGlCQUFpQixDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxFQUNoRCw0Q0FBNEMsQ0FDN0M7WUFDRCwwQkFBMEIsRUFBRSxXQUFXLENBQ3JDLDZCQUE2QixDQUFDLDRCQUE0QixFQUMxRCxTQUFTLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUNqRCw0Q0FBNEMsQ0FDN0M7U0FDRixDQUFDLENBQUM7UUFFSCxNQUFNLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDN0QsTUFBTSw0QkFBNEIsR0FBRyxNQUFNLHVCQUF1QixDQUNoRSxTQUFTLEVBQ1QsWUFBWSxDQUFDLE9BQU8sRUFDcEIsY0FBYyxFQUNkLEVBQUUsQ0FDSCxDQUFDO1FBRUYsT0FBTyxxQkFBcUIsQ0FBQyxJQUFJLENBQUM7WUFDaEMsS0FBSztZQUNMLGVBQWUsRUFBRSxlQUFlO1lBQ2hDLGNBQWM7WUFDZCw0QkFBNEI7WUFDNUIsU0FBUztTQUNWLENBQUMsQ0FBQztJQUNMLENBQUM7U0FBTSxDQUFDO1FBQ04sSUFDRSw2QkFBNkIsQ0FBQyxzQ0FBc0MsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUMvRSw2QkFBNkIsQ0FBQyw0QkFBNEIsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUNyRSw2QkFBNkIsQ0FBQyw0QkFBNEIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUNyRSxDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxzREFBc0QsQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFFRCxzRUFBc0U7UUFDdEUsb0RBQW9EO1FBQ3BELE1BQU0sUUFBUSxHQUFHLE1BQU0sOEJBQThCLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN4RSxNQUFNLCtCQUErQixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRTtZQUMvRCxDQUFDLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRTtZQUN4QixDQUFDLENBQUMsTUFBTSxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFFckQsTUFBTSx1QkFBdUIsR0FDM0IsNkJBQTZCLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDLElBQUksMEJBQTBCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDdEcsTUFBTSxnQ0FBZ0MsR0FDcEMsNkJBQTZCLENBQUMsc0NBQXNDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZFLGlCQUFpQixDQUFDLEtBQUssQ0FBaUMsdUJBQXVCLENBQUMsQ0FBQztRQUNuRixNQUFNLG1CQUFtQixHQUN2Qiw2QkFBNkIsQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDLENBQUM7WUFDN0QsU0FBUyxDQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVwRCxNQUFNLGNBQWMsR0FBRyx5QkFBeUIsQ0FBQyxJQUFJLENBQUM7WUFDcEQsNkJBQTZCLEVBQUUsU0FBUyxDQUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxFQUFFLENBQ2xFLENBQUMsR0FBRyxzQkFBc0IsQ0FBQyxNQUFNO2dCQUMvQixDQUFDLENBQUUsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBc0M7Z0JBQ25FLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLEVBQUUsQ0FDbEM7WUFDRCx1Q0FBdUMsRUFBRSxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FDNUUsQ0FBQyxHQUFHLHFEQUFxRCxDQUFDLE1BQU07Z0JBQzlELENBQUMsQ0FBQyxxREFBcUQsQ0FBQyxDQUFDLENBQUM7Z0JBQzFELENBQUMsQ0FBQywwQkFBMEIsQ0FBQyxxQkFBcUIsQ0FBQyxDQUN0RDtZQUNELGdCQUFnQixFQUFFLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzRixzQkFBc0IsRUFBRSxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4RiwwQkFBMEI7WUFDMUIsMkJBQTJCO1lBQzNCLHVCQUF1QjtZQUN2QixnQ0FBZ0M7WUFDaEMsbUJBQW1CO1NBQ3BCLENBQUMsQ0FBQztRQUVILE1BQU0sU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM3RCxNQUFNLDRCQUE0QixHQUFHLE1BQU0sdUJBQXVCLENBQ2hFLFNBQVMsRUFDVCxZQUFZLENBQUMsT0FBTyxFQUNwQixjQUFjLEVBQ2QsRUFBRSxDQUNILENBQUM7UUFFRixPQUFPLHNCQUFzQixDQUFDLElBQUksQ0FBQztZQUNqQyxLQUFLO1lBQ0wsZUFBZSxFQUFFLGVBQWU7WUFDaEMsY0FBYztZQUNkLCtCQUErQixFQUFFLCtCQUErQjtZQUNoRSw0QkFBNEI7WUFDNUIsU0FBUztTQUNWLENBQUMsQ0FBQztJQUNMLENBQUM7QUFDSCxDQUFDLENBQ0YsQ0FBQztBQUVGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsaUJBQWlCLENBQUMsRUFBNkIsRUFBRSxRQUFnQjtJQUNyRixNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDbEcsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsUUFBUSxHQUFHLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsTUFBTSxFQUFFLENBQUMsY0FBYyxDQUFpQyxZQUFZLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEgsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLGlCQUFpQixDQUFDLHVCQUF1QixFQUFFLEtBQUssRUFBRSxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUV2RyxNQUFNLFlBQVksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLENBQStCLENBQUM7SUFDcEgsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0RBQStELEtBQUssR0FBRyxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEtBQUssUUFBUSxDQUFDO0lBQ3pELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQztJQUVwRCxPQUFPLElBQUksY0FBYyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUN0RixDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLFNBQVMsQ0FDckMscUJBQXFCLEVBQ3JCLGdCQUFnQixFQUNoQixLQUFLLEVBQUUsS0FBVyxFQUFFLFNBQXFCLEVBQUUsRUFBRTtJQUMzQyxNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7SUFDOUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLE1BQU0sZUFBZSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO0lBQy9ELE1BQU0sU0FBUyxHQUFHLElBQUksRUFBRSxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQzNELENBQUMsQ0FDRixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQUcsU0FBUyxDQUNwRCxxQkFBcUIsRUFDckIsK0JBQStCLEVBQy9CLEtBQUssRUFDSCxLQUFLLEVBQ0wsa0JBQW1ELEVBQ25ELGtCQUFzQyxFQUN0QyxpQkFBb0QsRUFDcEQsUUFBd0IsRUFDeEIsTUFBZSxFQUNmLEVBQUU7SUFDRixJQUFJLGtCQUFrQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHlEQUF5RCxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3pHLENBQUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN2RSxNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RSxNQUFNLE9BQU8sR0FDWCxrQkFBa0IsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUM3QixDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7UUFDcEIsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQ2pDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFO1lBQzFDLENBQUMsQ0FBQyxXQUFXLENBQ1QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUNwRyxDQUFDO0lBQ1IsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLGlCQUFpQixDQUM3QyxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFDZCxTQUFTLEVBQ1Qsa0JBQWtCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUNyQyxPQUFPLENBQ1IsQ0FBQztJQUVGLE1BQU0sZUFBZSxHQUFHLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuRyxNQUFNLG1CQUFtQixHQUFHLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNHLE1BQU0sTUFBTSxHQUFHLElBQUksV0FBVyxDQUM1QixpQkFBaUIsQ0FBQyxlQUFlLEVBQ2pDLGlCQUFpQixFQUNqQixRQUFRLEVBQ1IsaUJBQWlCLENBQUMsa0JBQWtCLEVBQ3BDLGVBQWUsRUFDZixtQkFBbUIsQ0FDcEIsQ0FBQztJQUNGLElBQUksQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7UUFDbEUsTUFBTSxFQUFFLEtBQUssQ0FDWCxrRUFBa0U7WUFDaEUsZUFBZSxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDaEMsZ0JBQWdCLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQ3RELENBQUM7UUFDRixNQUFNLElBQUksS0FBSyxDQUFDLDBEQUEwRCxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FDRixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsU0FBUyxDQUNoRCxxQkFBcUIsRUFDckIsMkJBQTJCLEVBQzNCLEtBQUssRUFDSCxJQUFJLEVBQ0osR0FBa0IsRUFDbEIsZUFBZ0MsRUFDaEMsY0FBb0IsRUFDcEIsRUFBNEIsRUFDNUIsRUFBRTtJQUNGLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDbkYsTUFBTSxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQ3ZDLE1BQU0sZUFBZSxDQUFDLFlBQVksQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLENBQUMsRUFDN0QsSUFBSSxxQkFBcUIsQ0FDdkIsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsRUFDdEQsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsRUFDdEQsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUN6RCxDQUNGLENBQUM7SUFFRixNQUFNLGVBQWUsR0FBRyxNQUFNLGVBQWUsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXhFLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDN0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFakMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7SUFDckMsTUFBTSxPQUFPLEdBQ1gsTUFBTSxLQUFLLENBQUM7UUFDVixDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7UUFDcEIsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQ2QsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFO1lBQy9CLENBQUMsQ0FBQywyQkFBMkIsQ0FDekIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUMsRUFDeEMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUM3QixDQUFDO0lBRVIsY0FBYyxHQUFHLFdBQVcsQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxtQ0FBbUMsQ0FBQyxDQUFDO0lBQzNGLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBWSxFQUFFLEtBQWEsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDO0lBQy9FLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDckcsTUFBTSxhQUFhLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEcsTUFBTSxTQUFTLEdBQUcscUJBQXFCLENBQUMsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFbEYsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLGlCQUFpQixDQUFDLElBQUksRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFbkcsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckYsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFOUYsTUFBTSxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsZUFBZSxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBRXBILE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFDMUIsQ0FBQyxDQUNGLENBQUM7QUFFRixNQUFNLFVBQVUscUJBQXFCLENBQUMsTUFBYztJQUNsRCxNQUFNLFVBQVUsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLHVCQUF1QixFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25GLE9BQU8sV0FBVyxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVELDZGQUE2RjtBQUM3RixNQUFNLENBQUMsS0FBSyxVQUFVLHVCQUF1QixDQUMzQyxlQUFrRCxFQUNsRCxXQUF3QixFQUN4QixFQUE0QjtJQUU1QixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7UUFDaEIsYUFBYSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ3BDLHFCQUFxQixDQUFDLE1BQU0sZUFBZSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLEVBQUUsZUFBZSxDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUM7S0FDOUcsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQ3BDLHFCQUFxQixFQUNyQixlQUFlLEVBQ2YsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFxQixFQUFFLEVBQTRCLEVBQUUsRUFBRTtJQUNuRSxNQUFNLFFBQVEsR0FBRyxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxHQUFHLENBQzVHLEtBQUssRUFBRSxFQUFnQixFQUFFLEVBQUU7UUFDekIsT0FBTyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzNELENBQUMsQ0FDRixDQUFDO0lBQ0YsTUFBTSxTQUFTLEdBQThDLElBQUksR0FBRyxDQUNsRSxDQUFDLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDL0QsQ0FBQztJQUNGLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDL0MscUJBQXFCLENBQ25CLE1BQU0sZUFBZSxDQUFDLFlBQVksQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLENBQUMsRUFDN0QsS0FBSyxDQUFDLGlCQUFpQixFQUN2QixtQkFBbUIsQ0FDcEIsQ0FBQztBQUNKLENBQUMsQ0FDRixDQUFDO0FBRUYsTUFBTSxDQUFDLEtBQUssVUFBVSxzQkFBc0IsQ0FBMkIsTUFBVyxFQUFFLEVBQTRCO0lBQzlHLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUMsTUFBTSxJQUFJLEdBQUcsTUFBTSxFQUFFLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNuRCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUN0RSxDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsU0FBUyxDQUM1QyxxQkFBcUIsRUFDckIsdUJBQXVCLEVBQ3ZCLEtBQUssRUFBRSxLQUFLLEVBQUUsZUFBZ0MsRUFBRSxFQUE0QixFQUErQixFQUFFO0lBQzNHLE9BQU8sa0JBQWtCLENBQUMsSUFBSSxDQUFDO1FBQzdCLFVBQVUsRUFBRSxNQUFNLGFBQWEsRUFBRTtRQUNqQyx3QkFBd0I7UUFDeEIsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQzVELGVBQWU7S0FDaEIsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUNGLENBQUM7QUFFRixNQUFNLENBQUMsS0FBSyxVQUFVLGVBQWUsQ0FBQyxFQUFnQixFQUFFLEVBQTRCO0lBQ2xGLE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxQyxPQUFPLElBQUksc0JBQXNCLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3pGLENBQUM7QUFFRCxNQUFNLFVBQVUsMEJBQTBCLENBQW1CLE1BQVM7SUFDcEUsT0FBTyxJQUFJLGlCQUFpQixDQUMxQixNQUFNLEVBQ04sRUFBRSxFQUNGLFNBQVMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUNqQyxDQUFDO0FBQ0osQ0FBQztBQUVELE1BQU0sK0JBQStCLEdBQUcsU0FBUyxDQUMvQyxxQkFBcUIsRUFDckIsaUNBQWlDLEVBQ2pDLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBZSxFQUFFLEVBQTZCLEVBQUUsRUFBRTtJQUM3RCxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQzFELE1BQU0sbUJBQW1CLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQzFELENBQUMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLElBQUksa0JBQWtCLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUNqRSxDQUFDO0lBRUYsTUFBTSxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLENBQzlFLFlBQVksQ0FBQyxnQkFBZ0IsRUFDN0IsbUJBQW1CLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQzlCLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsY0FBYyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDMUIsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUVGLE1BQU0sNEJBQTRCLEdBQUcsb0JBQW9CLENBQUMsR0FBRyxDQUMzRCxjQUFjLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxZQUEwQyxDQUM1RSxDQUFDO0lBQ0YsTUFBTSxzQ0FBc0MsR0FBRyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FDdkYsaUJBQWlCLENBQUMsZUFBZSxDQUMvQixjQUFjLENBQUMsS0FBSyxFQUNwQixZQUFZLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxhQUFhLEVBQUUsRUFBRSx1QkFBdUIsQ0FBQyxDQUNsRixDQUNGLENBQUM7SUFDRixNQUFNLDRCQUE0QixHQUFHLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNoRSxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDdEQsWUFBWSxDQUFDLG9CQUFvQixFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDNUQsT0FBTyxvQkFBaUUsQ0FBQztJQUMzRSxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU87UUFDTCw0QkFBNEI7UUFDNUIsc0NBQXNDO1FBQ3RDLDRCQUE0QjtLQUM3QixDQUFDO0FBQ0osQ0FBQyxDQUNGLENBQUM7QUFFRixNQUFNLENBQUMsS0FBSyxVQUFVLHFCQUFxQixDQUN6QyxNQUFvQixFQUNwQixhQUFxQixFQUNyQixFQUE0QjtJQUU1QixNQUFNLHNCQUFzQixHQUFHLE1BQU0sRUFBRSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUUsTUFBTSxlQUFlLEdBQUcsTUFBTSxFQUFFLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO0lBRWhGLDJGQUEyRjtJQUMzRixPQUFPLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxhQUFhLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUN6RSxDQUFDO0FBRUQsMEZBQTBGO0FBQzFGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsdUJBQXVCLENBQzNDLEtBQVMsRUFDVCxNQUFvQixFQUNwQixNQUFTLEVBQ1QsRUFBNEI7SUFFNUIsa0RBQWtEO0lBQ2xELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDbkIsT0FBTywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsbUJBQW1CLEtBQUssc0JBQXNCLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDeEYsQ0FBQztJQUNELE1BQU0sSUFBSSxHQUFHLE1BQU0sRUFBRSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDcEQsT0FBTyxJQUFJLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ3JGLENBQUM7QUFFRCxNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLFlBQW1DLEVBQ25DLGFBQXdEO0lBRXhELHFCQUFxQixDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBRSxFQUFFLFlBQVksQ0FBQyxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDbEgscUJBQXFCLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFFLEVBQUUsWUFBWSxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUNwSCxxQkFBcUIsQ0FDbkIsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUUsRUFDakQsWUFBWSxDQUFDLGNBQWMsRUFDM0IsZ0JBQWdCLENBQ2pCLENBQUM7QUFDSixDQUFDO0FBRUQsMkNBQTJDO0FBQzNDLFNBQVMscUJBQXFCLENBQzVCLFNBQWlDLEVBQ2pDLGFBQXFDLEVBQ3JDLElBQWUsRUFDZixLQUFjO0lBRWQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ3JFLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLElBQUksSUFBSSw4QkFBOEIsU0FBUyxDQUFDLElBQUksZUFBZSxhQUFhLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNwSCxDQUFDO0lBQ0QsSUFBSSxhQUFhLENBQUMsc0JBQXNCLEtBQUssU0FBUyxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDOUUsTUFBTSxJQUFJLEtBQUssQ0FDYixHQUFHLEtBQUssSUFBSSxJQUFJLG1EQUFtRCxTQUFTLENBQUMsc0JBQXNCLGVBQ2pHLGFBQWEsQ0FBQyxzQkFDaEIsR0FBRyxDQUNKLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sVUFBVSxVQUFVLENBQUMsRUFBZTtJQUN4QyxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDO0lBQy9DLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLGNBQWMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUNELElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsY0FBYyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNsRCxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixjQUFjLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFDRCxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ25ELE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLGNBQWMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekUsQ0FBQztBQUNILENBQUMifQ==