From 0a3b6287c57bfda0e9df41c0bdecce98fe0ff4eb Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 15 Dec 2022 09:09:54 -0300 Subject: [PATCH] - [#679] Implementation of the File-system based block cache Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`. --- CHANGELOG.md | 54 +- .../xcshareddata/swiftpm/Package.resolved | 3 +- .../ZcashLightClientSample/AppDelegate.swift | 22 +- .../Get UTXOs/GetUTXOsViewController.swift | 3 +- MIGRATING.md | 46 +- Package.resolved | 3 +- Package.swift | 5 +- .../Block/CompactBlockProcessor.swift | 154 +- .../Block/CompactBlockProcessor.swift.orig | 1368 ++ .../DatabaseStorage/CompactBlockStorage.swift | 119 - .../DatabaseStorage/ConnectorProvider.swift | 12 + .../DatabaseMigrationManager.swift | 32 +- ...Error.swift => DatabaseStorageError.swift} | 2 +- ...ger.swift => DatabaseStorageManager.swift} | 4 +- .../Block/Download/BlockDownloader.swift | 14 +- .../Download/BlockDownloaderService.swift | 25 +- .../FSCompactBlockRepository.swift | 378 + .../Processor/CompactBlockScanning.swift | 5 +- .../CompactBlockValidationInformation.swift | 9 +- .../Block/Utils/InternalSyncProgress.swift | 2 +- .../Constants/ZcashSDK.swift | 29 +- .../DAO/CompactBlockDAO.swift | 26 - .../DAO/PendingTransactionDao.swift | 14 +- .../DAO/TransactionDao.swift | 12 +- .../DAO/UnspentTransactionOutputDao.swift | 8 +- .../Entity/AccountEntity.swift | 4 +- .../Entity/CompactBlockEntity.swift | 13 - Sources/ZcashLightClientKit/Initializer.swift | 132 +- .../Initializer.swift.orig | 456 + .../Providers/ResourceProvider.swift | 13 + .../Repository/CompactBlockRepository.swift | 77 +- .../Rust/ZcashRustBackend.swift | 127 +- .../Rust/ZcashRustBackendWelding.swift | 214 +- .../Service/Model/ZcashCompactBlock.swift | 19 + .../ZcashLightClientKit/Synchronizer.swift | 3 +- .../Synchronizer/SDKSynchronizer.swift | 7 +- .../PersistentTransactionManager.swift | 6 +- .../Transaction/TransactionEncoder.swift | 3 +- .../Transaction/TransactionManager.swift | 1 + .../WalletTransactionEncoder.swift | 13 +- Tests/DarksideTests/AdvancedReOrgTests.swift | 6 +- .../DarksideTests/BlockDownloaderTests.swift | 20 +- .../DarksideSanityCheckTests.swift | 2 +- .../InternalStateConsistencyTests.swift | 155 + .../PendingTransactionUpdatesTest.swift | 2 +- Tests/DarksideTests/ReOrgTests.swift | 2 +- Tests/DarksideTests/RewindRescanTests.swift | 2 +- Tests/DarksideTests/ShieldFundsTests.swift | 16 +- .../SychronizerDarksideTests.swift | 2 +- Tests/DarksideTests/SynchronizerTests.swift | 2 +- .../TransactionEnhancementTests.swift | 24 +- Tests/DarksideTests/Z2TReceiveTests.swift | 2 +- Tests/NetworkTests/BlockScanTests.swift | 102 +- Tests/NetworkTests/BlockStreamingTest.swift | 46 +- .../CompactBlockProcessorTests.swift | 37 +- .../NetworkTests/CompactBlockReorgTests.swift | 36 +- Tests/NetworkTests/DownloadTests.swift | 40 +- .../BlockBatchValidationTests.swift | 95 +- .../CompactBlockProcessorOfflineTests.swift | 33 +- .../CompactBlockRepositoryTests.swift | 229 + .../CompactBlockStorageTests.swift | 138 - Tests/OfflineTests/FsBlockStorageTests.swift | 541 + .../PendingTransactionRepositoryTests.swift | 2 +- Tests/OfflineTests/WalletTests.swift | 33 +- .../OfflineTests/ZcashRustBackendTests.swift | 50 +- .../PerformanceTests/SynchronizerTests.swift | 4 +- Tests/TestUtils/DarkSideWalletService.swift | 2 + Tests/TestUtils/FakeStorage.swift | 48 +- .../TestUtils/MockTransactionRepository.swift | 7 +- .../Resources/sandblasted_mainnet_block.json | 10325 ++++++++++++++++ Tests/TestUtils/Stubs.swift | 93 +- Tests/TestUtils/TestCoordinator.swift | 54 +- Tests/TestUtils/TestDbBuilder.swift | 36 +- Tests/TestUtils/Tests+Utils.swift | 4 - 74 files changed, 14770 insertions(+), 857 deletions(-) create mode 100644 Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift.orig delete mode 100644 Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift create mode 100644 Sources/ZcashLightClientKit/Block/DatabaseStorage/ConnectorProvider.swift rename Sources/ZcashLightClientKit/Block/DatabaseStorage/{StorageError.swift => DatabaseStorageError.swift} (94%) rename Sources/ZcashLightClientKit/Block/DatabaseStorage/{StorageManager.swift => DatabaseStorageManager.swift} (96%) create mode 100644 Sources/ZcashLightClientKit/Block/FilesystemStorage/FSCompactBlockRepository.swift delete mode 100644 Sources/ZcashLightClientKit/DAO/CompactBlockDAO.swift delete mode 100644 Sources/ZcashLightClientKit/Entity/CompactBlockEntity.swift create mode 100644 Sources/ZcashLightClientKit/Initializer.swift.orig create mode 100644 Tests/DarksideTests/InternalStateConsistencyTests.swift create mode 100644 Tests/OfflineTests/CompactBlockRepositoryTests.swift delete mode 100644 Tests/OfflineTests/CompactBlockStorageTests.swift create mode 100644 Tests/OfflineTests/FsBlockStorageTests.swift create mode 100644 Tests/TestUtils/Resources/sandblasted_mainnet_block.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 51f07e11a..f3d98b5a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,49 @@ +# Unreleased + +## File system backed block cache + +File system based block cache. Compact blocks will now be stored +on the file system. Caller must provide a `URL` pointing to the +filesystem root directory where the fsBlock cache is. this directory +is expected to contain a `/blocks` sub-directory with the blocks stored +in the convened filename format `{height}-{hash}-block`. This directory +must be granted both read and write permissions. + +the file system cache will have a "bookkeeping" database that the rust +welding layer will use to know the state of the cache and locate the +cached compact blocks. This directory can be deleted provided that the +Compactblock processor or Synchronizer are not running. Upon deletion +caller is responsible for initializing these objects for the cache to +be created. + +Implementation notes: Users of the SDK will know the path they will +provide but must assume nobehavior whatsoever or rely on the cached +information in any way since it is an internal state of the SDK. +Maintainers might provide no support for problems related to speculative +use of the file system cache. If you consider your application needs any +other information than the ones available through public APIs, please +file the corresponding feature request. + +### Added +- `Initializer.migrateCacheDb()` helps you move to filesystem based +block cache + +- `Synchronizer.shieldFunds(spendingKey:memo:shieldingThreshold)` shieldingThreshold +was added allowing wallets to manage their own shielding policies. + +### Removed +- `InitializerError.cacheDbMigrationFailed` + +### Deprecations +CacheDb references that were deprecated instead of **deleted** are pointing out +that they should be useful for you to migrate from using cacheDb. + +- `ResourceProvider.cacheDbURL` deprecated but left for one release cycle for clients +to move away from cacheDb. + +- `NetworkConstants.defaultCacheDbName` deprecated but left for one release cycle for clients +to move away from cacheDb. + # 0.18.0-beta ## Farewell Cocoapods. @@ -42,10 +88,9 @@ Sources/ZcashLightClientKit/Resources/checkpoints/testnet/2200000.json - [#645] Default rewind after ReOrg is 20 blocks when it should be 10 This fixes an issue where the default reorg was 20 blocks rewind instead of 10. The reorg count was incremented before calling the rewind height computing function. - - -## Change in how we represent transactions. +## Use Librustzcash database views to query and represent transactions + - [#556] Change data structures which represent transactions. These data types are gone: `Transaction`, `TransactionEntity`, `ConfirmedTransaction`, @@ -64,8 +109,7 @@ the `SDKSynchronizer` has now new methods to fetch those: - `func getMemos(for receivedTransaction: ZcashTransaction.Received) throws -> [Memo]` - `func getMemos(for sentTransaction: ZcashTransaction.Sent) throws -> [Memo]` -## Compact Block Processor is not public anymore. - +## CompactBlockProcessor is now internal - [#671] Make CompactBlockProcessor Internal. The CompactBlockProcessor is no longer a public class/API. Any direct access will diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d6493e1a3..ae4d13f13 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -140,8 +140,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi", "state" : { - "revision" : "b6013b8b313523b2c72ce62dbdc17f6ffad3a500", - "version" : "0.1.1" + "revision" : "4bf7225c4f668249661eb4b54dde3dd356a15365" } } ], diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift index e3d131a04..5d49105d8 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift @@ -5,7 +5,7 @@ // Created by Francisco Gindre on 06/09/2019. // Copyright © 2019 Electric Coin Company. All rights reserved. // - +// swiftlint:disable force_cast force_try force_unwrapping import UIKit import ZcashLightClientKit import NotificationBubbles @@ -38,7 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { .deriveFullViewingKey() let wallet = Initializer( - cacheDbURL: try! cacheDbURLHelper(), + fsBlockDbRoot: try! fsBlockDbRootURLHelper(), dataDbURL: try! dataDbURLHelper(), pendingDbURL: try! pendingDbURLHelper(), endpoint: DemoAppConfig.endpoint, @@ -84,7 +84,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. - _ = self.sharedWallet subscribeToMinedTxNotifications() return true @@ -127,7 +126,13 @@ extension AppDelegate { } catch { loggerProxy.error("error clearing cache DB: \(error)") } - + + do { + try FileManager.default.removeItem(at: try fsBlockDbRootURLHelper()) + } catch { + loggerProxy.error("error clearing FsBlockDBRoot: \(error)") + } + do { try FileManager.default.removeItem(at: try dataDbURLHelper()) } catch { @@ -158,6 +163,15 @@ func documentsDirectoryHelper() throws -> URL { try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) } +func fsBlockDbRootURLHelper() throws -> URL { + try documentsDirectoryHelper() + .appendingPathComponent(kZcashNetwork.networkType.chainName) + .appendingPathComponent( + ZcashSDK.defaultFsCacheName, + isDirectory: true + ) +} + func cacheDbURLHelper() throws -> URL { try documentsDirectoryHelper() .appendingPathComponent( diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift index 2e4bf38c0..bf95f1ff2 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift @@ -49,7 +49,8 @@ class GetUTXOsViewController: UIViewController { Task { @MainActor in let transaction = try await AppDelegate.shared.sharedSynchronizer.shieldFunds( spendingKey: usk, - memo: try Memo(string: "shielding is fun!") + memo: try Memo(string: "shielding is fun!"), + shieldingThreshold: Zatoshi(10000) ) KRProgressHUD.dismiss() self.messageLabel.text = "funds shielded \(transaction)" diff --git a/MIGRATING.md b/MIGRATING.md index 6c7e75665..9a569ef97 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -1,3 +1,47 @@ +# Migrating from previous versions to +Compact block cache no longer uses a sqlite database. The existing database +should be deleted. `Initializer` now takes an `fsBlockDbRootURL` which is a +URL pointing to a RW directory in the filesystem that will be used to store +the cached blocks and the companion database managed internally by the SDK. + +`Initializer` provides a convenience initializer that takes the an optional +URL to the `cacheDb` location to migrate the internal state of the +`CompactBlockProcessor` and delete that database. + +````Swift + convenience public init ( + cacheDbURL: URL?, + fsBlockDbRoot: URL, + dataDbURL: URL, + pendingDbURL: URL, + endpoint: LightWalletEndpoint, + network: ZcashNetwork, + spendParamsURL: URL, + outputParamsURL: URL, + viewingKeys: [UnifiedFullViewingKey], + walletBirthday: BlockHeight, + alias: String = "", + loggerProxy: Logger? = nil + ) +```` + +We do not make any efforts to extract the cached blocks in the sqlite +`cacheDb` and storing them on disk. Although this might be the logical +step to do, we think such migration as little to gain since a migration +function will be a "run once" function with many different scenarios to +consider and possibly very error prone. On the other hand, we rather delete +the `cacheDb` altogether and free up that space on the users' devices since +we have surveyed that the `cacheDb` as been growing exponentially taking up +many gigabyte of disk space. We forsee that many possible attempts to copy +information from one cache to another, would possibly fail + +Consuming block cache information for other purposes is discouraged. Users +must not make assumptions on its contents or rely on its contents in any way. +Maintainers assume that this state is internal and won't consider further +uses other than the intended for the current development. If you consider +your application needs any other information than the ones available through +public APIs, please file the corresponding feature request. + # Migrating from 0.16.x-beta to 0.17.0-alpha.x ## Changes to Demo APP @@ -78,4 +122,4 @@ async environment. SDK Clients will likely be affected by some `async` methods on `SDKSynchronizer`. -We recommend clients that don't support structured concurrency features, to work around this by surrounding the these function calls either in @MainActor contexts either by marking callers as @MainActor or launching tasks on that actor with `Task { @MainActor in ... }` \ No newline at end of file +We recommend clients that don't support structured concurrency features, to work around this by surrounding the these function calls either in @MainActor contexts either by marking callers as @MainActor or launching tasks on that actor with `Task { @MainActor in ... }` diff --git a/Package.resolved b/Package.resolved index 95f740de5..b16f003f5 100644 --- a/Package.resolved +++ b/Package.resolved @@ -86,8 +86,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi", "state" : { - "revision" : "b6013b8b313523b2c72ce62dbdc17f6ffad3a500", - "version" : "0.1.1" + "revision" : "ce66b2f1b354ff8eb192cf87866ef0f27a6f594f" } } ], diff --git a/Package.swift b/Package.swift index 0f2b9afa6..e8fb16e6a 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.8.0"), .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1"), - .package(name: "libzcashlc", url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", from: "0.1.1") + .package(name: "libzcashlc", url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", revision: "ce66b2f1b354ff8eb192cf87866ef0f27a6f594f") ], targets: [ .target( @@ -46,7 +46,8 @@ let package = Package( .copy("Resources/cache.db"), .copy("Resources/darkside_caches.db"), .copy("Resources/darkside_data.db"), - .copy("Resources/darkside_pending.db") + .copy("Resources/darkside_pending.db"), + .copy("Resources/sandblasted_mainnet_block.json") ] ), .testTarget( diff --git a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift index ba3697779..a8bc897a1 100644 --- a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift +++ b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift @@ -207,12 +207,12 @@ public extension Notification.Name { actor CompactBlockProcessor { /// Compact Block Processor configuration /// - /// Property: cacheDbPath absolute file path of the DB where raw, unprocessed compact blocks are stored. - /// Property: dataDbPath absolute file path of the DB where all information derived from the cache DB is stored. - /// Property: spendParamsURL absolute file path of the sapling-spend.params file - /// Property: outputParamsURL absolute file path of the sapling-output.params file + /// - parameter fsBlockCacheRoot: absolute root path where the filesystem block cache will be stored. + /// - parameter dataDb: absolute file path of the DB where all information derived from the cache DB is stored. + /// - parameter spendParamsURL: absolute file path of the sapling-spend.params file + /// - parameter outputParamsURL: absolute file path of the sapling-output.params file struct Configuration { - public var cacheDb: URL + public var fsBlockCacheRoot: URL public var dataDb: URL public var spendParamsURL: URL public var outputParamsURL: URL @@ -226,13 +226,14 @@ actor CompactBlockProcessor { public private(set) var downloadBufferSize: Int = 10 private(set) var network: ZcashNetwork private(set) var saplingActivation: BlockHeight - + private(set) var cacheDbURL: URL? var blockPollInterval: TimeInterval { TimeInterval.random(in: ZcashSDK.defaultPollInterval / 2 ... ZcashSDK.defaultPollInterval * 1.5) } init ( - cacheDb: URL, + cacheDbURL: URL? = nil, + fsBlockCacheRoot: URL, dataDb: URL, spendParamsURL: URL, outputParamsURL: URL, @@ -244,7 +245,7 @@ actor CompactBlockProcessor { saplingActivation: BlockHeight, network: ZcashNetwork ) { - self.cacheDb = cacheDb + self.fsBlockCacheRoot = fsBlockCacheRoot self.dataDb = dataDb self.spendParamsURL = spendParamsURL self.outputParamsURL = outputParamsURL @@ -255,25 +256,26 @@ actor CompactBlockProcessor { self.rewindDistance = rewindDistance self.walletBirthday = walletBirthday self.saplingActivation = saplingActivation - + self.cacheDbURL = cacheDbURL assert(downloadBatchSize >= scanningBatchSize) } init( - cacheDb: URL, + fsBlockCacheRoot: URL, dataDb: URL, spendParamsURL: URL, outputParamsURL: URL, walletBirthday: BlockHeight, network: ZcashNetwork ) { - self.cacheDb = cacheDb + self.fsBlockCacheRoot = fsBlockCacheRoot self.dataDb = dataDb self.spendParamsURL = spendParamsURL self.outputParamsURL = outputParamsURL self.walletBirthday = walletBirthday self.saplingActivation = network.constants.saplingActivationHeight self.network = network + self.cacheDbURL = nil assert(downloadBatchSize >= scanningBatchSize) } @@ -346,7 +348,7 @@ actor CompactBlockProcessor { var service: LightWalletService let blockDownloaderService: BlockDownloaderService let blockDownloader: BlockDownloader - var storage: CompactBlockStorage + var storage: CompactBlockRepository var transactionRepository: TransactionRepository var accountRepository: AccountRepository var rustBackend: ZcashRustBackendWelding.Type @@ -371,12 +373,12 @@ actor CompactBlockProcessor { /// Initializes a CompactBlockProcessor instance /// - Parameters: /// - service: concrete implementation of `LightWalletService` protocol - /// - storage: concrete implementation of `CompactBlockStorage` protocol + /// - storage: concrete implementation of `CompactBlockRepository` protocol /// - backend: a class that complies to `ZcashRustBackendWelding` /// - config: `Configuration` struct for this processor init( service: LightWalletService, - storage: CompactBlockStorage, + storage: CompactBlockRepository, backend: ZcashRustBackendWelding.Type, config: Configuration ) { @@ -393,13 +395,15 @@ actor CompactBlockProcessor { } /// Initializes a CompactBlockProcessor instance from an Initialized object + /// - Parameters: + /// - initializer: an instance that complies to CompactBlockDownloading protocol init(initializer: Initializer) { self.init( service: initializer.lightWalletService, storage: initializer.storage, backend: initializer.rustBackend, config: Configuration( - cacheDb: initializer.cacheDbURL, + fsBlockCacheRoot: initializer.fsBlockDbRoot, dataDb: initializer.dataDbURL, spendParamsURL: initializer.spendParamsURL, outputParamsURL: initializer.outputParamsURL, @@ -416,7 +420,7 @@ actor CompactBlockProcessor { internal init( service: LightWalletService, - storage: CompactBlockStorage, + storage: CompactBlockRepository, backend: ZcashRustBackendWelding.Type, config: Configuration, repository: TransactionRepository, @@ -513,6 +517,14 @@ actor CompactBlockProcessor { return } + do { + if let legacyCacheDbURL = self.config.cacheDbURL { + try await self.migrateCacheDb(legacyCacheDbURL) + } + } catch { + await self.fail(error) + } + await self.nextBatch() } @@ -530,12 +542,10 @@ actor CompactBlockProcessor { self.retryAttempts = 0 } - /** - Rewinds to provided height. - If nil is provided, it will rescan to nearest height (quick rescan) - - If this is called while sync is in progress then `CompactBlockProcessorError.rewindAttemptWhileProcessing` is thrown. - */ + /// Rewinds to provided height. + /// - Parameter height: height to rewind to. If nil is provided, it will rescan to nearest height (quick rescan) + /// + /// - Note: If this is called while sync is in progress then `CompactBlockProcessorError.rewindAttemptWhileProcessing` is thrown. func rewindTo(_ height: BlockHeight?) async throws -> BlockHeight { guard shouldStart else { throw CompactBlockProcessorError.rewindAttemptWhileProcessing } @@ -581,8 +591,11 @@ actor CompactBlockProcessor { } state = .stopped - blockDownloaderService.closeDBConnection() + + try await self.storage.clear() await internalSyncProgress.rewind(to: 0) + + wipeLegacyCacheDbIfNeeded() } func validateServer() async { @@ -623,7 +636,7 @@ actor CompactBlockProcessor { var anyActionExecuted = false - try storage.createTable() + try storage.create() if let range = ranges.downloadedButUnscannedRange { LoggerProxy.debug("Starting scan with downloaded but not scanned blocks with range: \(range.lowerBound)...\(range.upperBound)") @@ -648,17 +661,17 @@ actor CompactBlockProcessor { } try await handleSaplingParametersIfNeeded() - try await blockDownloader.removeCacheDB(at: config.cacheDb) + try await clearCompactBlockCache() if !Task.isCancelled { await processBatchFinished(height: anyActionExecuted ? ranges.latestBlockHeight : nil) } } catch { - LoggerProxy.error("Sync failed with error: \(error)") - if !(Task.isCancelled) { + LoggerProxy.error("processing failed with error: \(error)") await fail(error) } else { + LoggerProxy.info("processing cancelled.") state = .stopped if needsToStartScanningWhenStopped { await nextBatch() @@ -695,7 +708,7 @@ actor CompactBlockProcessor { ) try await compactBlockValidation() try await scanBlocks(at: processingRange, totalProgressRange: totalProgressRange) - try await blockDownloader.removeCacheDB(at: config.cacheDb) + try await clearCompactBlockCache() let progress = BlockProgress( startHeight: totalProgressRange.lowerBound, @@ -822,8 +835,8 @@ actor CompactBlockProcessor { } private func validateConfiguration() throws { - guard FileManager.default.isReadableFile(atPath: config.cacheDb.absoluteString) else { - throw CompactBlockProcessorError.missingDbPath(path: config.cacheDb.absoluteString) + guard FileManager.default.isReadableFile(atPath: config.fsBlockCacheRoot.absoluteString) else { + throw CompactBlockProcessorError.missingDbPath(path: config.fsBlockCacheRoot.absoluteString) } guard FileManager.default.isReadableFile(atPath: config.dataDb.absoluteString) else { @@ -930,6 +943,11 @@ actor CompactBlockProcessor { ) } + private func clearCompactBlockCache() async throws { + try await storage.clear() + LoggerProxy.info("Cache removed") + } + private func setTimer() async { let interval = self.config.blockPollInterval self.backoffTimer?.invalidate() @@ -1010,7 +1028,7 @@ extension CompactBlockProcessor.Configuration { static func standard(for network: ZcashNetwork, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration { let pathProvider = DefaultResourceProvider(network: network) return CompactBlockProcessor.Configuration( - cacheDb: pathProvider.cacheDbURL, + fsBlockCacheRoot: pathProvider.fsCacheURL, dataDb: pathProvider.dataDbURL, spendParamsURL: pathProvider.spendParamsURL, outputParamsURL: pathProvider.outputParamsURL, @@ -1241,7 +1259,9 @@ extension CompactBlockProcessor { rustBackend: rustBackend ) - await internalSyncProgress.migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB: try downloaderService.lastDownloadedBlockHeight()) + let latestDownloadHeight = try downloaderService.lastDownloadedBlockHeight() + + await internalSyncProgress.migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB: latestDownloadHeight) let latestBlockHeight = try service.latestBlockHeight() let latestScannedHeight = try transactionRepository.lastScannedHeight() @@ -1257,3 +1277,73 @@ extension CompactBlockProcessor { } } } + +/// This extension contains asociated types and functions needed to clean up the +/// `cacheDb` in favor of `FsBlockDb`. Once this cleanup functionality is deprecated, +/// delete the whole extension and reference to it in other parts of the code including tests. +extension CompactBlockProcessor { + public enum CacheDbMigrationError: Error { + case fsCacheMigrationFailedSameURL + case failedToDeleteLegacyDb(Error) + case failedToInitFsBlockDb(Error) + case failedToSetDownloadHeight(Error) + } + + /// Deletes the SQLite cacheDb and attempts to initialize the fsBlockDbRoot + /// - parameter legacyCacheDbURL: the URL where the cache Db used to be stored. + /// - Throws `InitializerError.fsCacheInitFailedSameURL` when the given URL + /// is the same URL than the one provided as `self.fsBlockDbRoot` assuming that's a + /// programming error being the `legacyCacheDbURL` a sqlite database file and not a + /// directory. Also throws errors from initializing the fsBlockDbRoot. + /// + /// - Note: Errors from deleting the `legacyCacheDbURL` won't be throwns. + func migrateCacheDb(_ legacyCacheDbURL: URL) async throws { + guard legacyCacheDbURL != config.fsBlockCacheRoot else { + throw CacheDbMigrationError.fsCacheMigrationFailedSameURL + } + + // if the URL provided is not readable, it means that the client has a reference + // to the cacheDb file but it has been deleted in a prior sync cycle. there's + // nothing to do here. + guard FileManager.default.isReadableFile(atPath: legacyCacheDbURL.path) else { + return + } + + do { + // if there's a readable file at the provided URL, delete it. + try FileManager.default.removeItem(at: legacyCacheDbURL) + } catch { + throw CacheDbMigrationError.failedToDeleteLegacyDb(error) + } + + // create the storage + do { + try self.storage.create() + } catch { + throw CacheDbMigrationError.failedToInitFsBlockDb(error) + } + + // The database has been deleted, so we have adjust the internal state of the + // `CompactBlockProcessor` so that it doesn't rely on download heights set + // by a previous processing cycle. + do { + let lastScannedHeight = try self.transactionRepository.lastScannedHeight() + + await internalSyncProgress.set(lastScannedHeight, .latestDownloadedBlockHeight) + } catch { + throw CacheDbMigrationError.failedToSetDownloadHeight(error) + } + } + + func wipeLegacyCacheDbIfNeeded() { + guard let cacheDbURL = config.cacheDbURL else { + return + } + + guard FileManager.default.isDeletableFile(atPath: cacheDbURL.pathExtension) else { + return + } + + try? FileManager.default.removeItem(at: cacheDbURL) + } +} diff --git a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift.orig b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift.orig new file mode 100644 index 000000000..ca1b7afea --- /dev/null +++ b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift.orig @@ -0,0 +1,1368 @@ +// +// CompactBlockProcessor.swift +// ZcashLightClientKit +// +// Created by Francisco Gindre on 18/09/2019. +// Copyright © 2019 Electric Coin Company. All rights reserved. +// +// swiftlint:disable file_length type_body_length + +import Foundation +import GRPC + +public typealias RefreshedUTXOs = (inserted: [UnspentTransactionOutputEntity], skipped: [UnspentTransactionOutputEntity]) + +/** +Errors thrown by CompactBlock Processor +*/ +public enum CompactBlockProcessorError: Error { + case invalidConfiguration + case missingDbPath(path: String) + case dataDbInitFailed(path: String) + case connectionError(underlyingError: Error) + case grpcError(statusCode: Int, message: String) + case connectionTimeout + case generalError(message: String) + case maxAttemptsReached(attempts: Int) + case unspecifiedError(underlyingError: Error) + case criticalError + case invalidAccount + case wrongConsensusBranchId(expectedLocally: ConsensusBranchID, found: ConsensusBranchID) + case networkMismatch(expected: NetworkType, found: NetworkType) + case saplingActivationMismatch(expected: BlockHeight, found: BlockHeight) + case unknown + case rewindAttemptWhileProcessing + case wipeAttemptWhileProcessing +} + +/** +CompactBlockProcessor notification userInfo object keys. +check Notification.Name extensions for more details. +*/ +public enum CompactBlockProcessorNotificationKey { + public static let progress = "CompactBlockProcessorNotificationKey.progress" + public static let progressBlockTime = "CompactBlockProcessorNotificationKey.progressBlockTime" + public static let reorgHeight = "CompactBlockProcessorNotificationKey.reorgHeight" + public static let latestScannedBlockHeight = "CompactBlockProcessorNotificationKey.latestScannedBlockHeight" + public static let rewindHeight = "CompactBlockProcessorNotificationKey.rewindHeight" + public static let foundTransactions = "CompactBlockProcessorNotificationKey.foundTransactions" + public static let foundBlocks = "CompactBlockProcessorNotificationKey.foundBlocks" + public static let foundTransactionsRange = "CompactBlockProcessorNotificationKey.foundTransactionsRange" + public static let error = "error" + public static let refreshedUTXOs = "CompactBlockProcessorNotificationKey.refreshedUTXOs" + public static let enhancementProgress = "CompactBlockProcessorNotificationKey.enhancementProgress" + public static let previousStatus = "CompactBlockProcessorNotificationKey.previousStatus" + public static let newStatus = "CompactBlockProcessorNotificationKey.newStatus" + public static let currentConnectivityStatus = "CompactBlockProcessorNotificationKey.currentConnectivityStatus" + public static let previousConnectivityStatus = "CompactBlockProcessorNotificationKey.previousConnectivityStatus" +} + +public enum CompactBlockProgress { + case syncing(_ progress: BlockProgress) + case enhance(_ progress: EnhancementStreamProgress) + case fetch + + public var progress: Float { + switch self { + case .syncing(let blockProgress): + return blockProgress.progress + case .enhance(let enhancementProgress): + return enhancementProgress.progress + default: + return 0 + } + } + + public var progressHeight: BlockHeight? { + switch self { + case .syncing(let blockProgress): + return blockProgress.progressHeight + case .enhance(let enhancementProgress): + return enhancementProgress.lastFoundTransaction?.minedHeight + default: + return 0 + } + } + + public var blockDate: Date? { + if case .enhance(let enhancementProgress) = self, let time = enhancementProgress.lastFoundTransaction?.blockTime { + return Date(timeIntervalSince1970: time) + } + + return nil + } + + public var targetHeight: BlockHeight? { + switch self { + case .syncing(let blockProgress): + return blockProgress.targetHeight + default: + return nil + } + } +} + +protocol EnhancementStreamDelegate: AnyObject { + func transactionEnhancementProgressUpdated(_ progress: EnhancementProgress) async +} + +public protocol EnhancementProgress { + var totalTransactions: Int { get } + var enhancedTransactions: Int { get } + var lastFoundTransaction: ZcashTransaction.Overview? { get } + var range: CompactBlockRange { get } +} + +public struct EnhancementStreamProgress: EnhancementProgress { + public var totalTransactions: Int + public var enhancedTransactions: Int + public var lastFoundTransaction: ZcashTransaction.Overview? + public var range: CompactBlockRange + + public var progress: Float { + totalTransactions > 0 ? Float(enhancedTransactions) / Float(totalTransactions) : 0 + } +} + +public extension Notification.Name { + /** + Processing progress update + + Query the userInfo object for the key CompactBlockProcessorNotificationKey.progress for a CompactBlockProgress struct + */ + static let blockProcessorUpdated = Notification.Name(rawValue: "CompactBlockProcessorUpdated") + + /** + notification sent when processor status changed + */ + static let blockProcessorStatusChanged = Notification.Name(rawValue: "CompactBlockProcessorStatusChanged") + + /** + Notification sent when a compact block processor starts syncing + */ + static let blockProcessorStartedSyncing = Notification.Name(rawValue: "CompactBlockProcessorStartedSyncing") + + /** + Notification sent when the compact block processor stop() method is called + */ + static let blockProcessorStopped = Notification.Name(rawValue: "CompactBlockProcessorStopped") + + /** + Notification sent when the compact block processor presented an error. + + Query userInfo object on the key CompactBlockProcessorNotificationKey.error + */ + static let blockProcessorFailed = Notification.Name(rawValue: "CompactBlockProcessorFailed") + + /** + Notification sent when the compact block processor has finished syncing the blockchain to latest height + */ + static let blockProcessorFinished = Notification.Name(rawValue: "CompactBlockProcessorFinished") + + /** + Notification sent when the compact block processor is doing nothing + */ + static let blockProcessorIdle = Notification.Name(rawValue: "CompactBlockProcessorIdle") + + /** + Notification sent when something odd happened. probably going from a state to another state that shouldn't be the next state. + */ + static let blockProcessorUnknownTransition = Notification.Name(rawValue: "CompactBlockProcessorTransitionUnknown") + + /** + Notification sent when the compact block processor handled a ReOrg. + + Query the userInfo object on the key CompactBlockProcessorNotificationKey.reorgHeight for the height on which the reorg was detected. CompactBlockProcessorNotificationKey.rewindHeight for the height that the processor backed to in order to solve the Reorg + */ + static let blockProcessorHandledReOrg = Notification.Name(rawValue: "CompactBlockProcessorHandledReOrg") + + /** + Notification sent when the compact block processor enhanced a bunch of transactions + Query the user info object for CompactBlockProcessorNotificationKey.foundTransactions which will contain an [ConfirmedTransactionEntity] Array with the found transactions and CompactBlockProcessorNotificationKey.foundTransactionsrange + */ + static let blockProcessorFoundTransactions = Notification.Name(rawValue: "CompactBlockProcessorFoundTransactions") + + /** + Notification sent when the compact block processor fetched utxos from lightwalletd attempted to store them + Query the user info object for CompactBlockProcessorNotificationKey.blockProcessorStoredUTXOs which will contain a RefreshedUTXOs tuple with the collection of UTXOs stored or skipped + */ + static let blockProcessorStoredUTXOs = Notification.Name(rawValue: "CompactBlockProcessorStoredUTXOs") + + static let blockProcessorStartedEnhancing = Notification.Name(rawValue: "CompactBlockProcessorStartedEnhancing") + + static let blockProcessorEnhancementProgress = Notification.Name("CompactBlockProcessorEnhancementProgress") + + static let blockProcessorStartedFetching = Notification.Name(rawValue: "CompactBlockProcessorStartedFetching") + + static let blockProcessorHandlingSaplingFiles = Notification.Name(rawValue: "blockProcessorHandlingSaplingFiles") + + /** + Notification sent when the grpc service connection detects a change. Query the user info object for status change details `currentConnectivityStatus` for current and previous with `previousConnectivityStatus` + */ + static let blockProcessorConnectivityStateChanged = Notification.Name("CompactBlockProcessorConnectivityStateChanged") +} + +/// The compact block processor is in charge of orchestrating the download and caching of compact blocks from a LightWalletEndpoint +/// when started the processor downloads does a download - validate - scan cycle until it reaches latest height on the blockchain. +actor CompactBlockProcessor { + /// Compact Block Processor configuration + /// + /// - parameter fsBlockCacheRoot: absolute root path where the filesystem block cache will be stored. + /// - parameter dataDb: absolute file path of the DB where all information derived from the cache DB is stored. + /// - parameter spendParamsURL: absolute file path of the sapling-spend.params file + /// - parameter outputParamsURL: absolute file path of the sapling-output.params file + struct Configuration { + public var fsBlockCacheRoot: URL + public var dataDb: URL + public var spendParamsURL: URL + public var outputParamsURL: URL + public var downloadBatchSize = ZcashSDK.DefaultDownloadBatch + public var scanningBatchSize = ZcashSDK.DefaultScanningBatch + public var retries = ZcashSDK.defaultRetries + public var maxBackoffInterval = ZcashSDK.defaultMaxBackOffInterval + public var maxReorgSize = ZcashSDK.maxReorgSize + public var rewindDistance = ZcashSDK.defaultRewindDistance + public var walletBirthday: BlockHeight + public private(set) var downloadBufferSize: Int = 10 + private(set) var network: ZcashNetwork + private(set) var saplingActivation: BlockHeight + private(set) var cacheDbURL: URL? + var blockPollInterval: TimeInterval { + TimeInterval.random(in: ZcashSDK.defaultPollInterval / 2 ... ZcashSDK.defaultPollInterval * 1.5) + } + + init ( + cacheDbURL: URL? = nil, + fsBlockCacheRoot: URL, + dataDb: URL, + spendParamsURL: URL, + outputParamsURL: URL, + downloadBatchSize: Int, + retries: Int, + maxBackoffInterval: TimeInterval, + rewindDistance: Int, + walletBirthday: BlockHeight, + saplingActivation: BlockHeight, + network: ZcashNetwork + ) { + self.fsBlockCacheRoot = fsBlockCacheRoot + self.dataDb = dataDb + self.spendParamsURL = spendParamsURL + self.outputParamsURL = outputParamsURL + self.network = network + self.downloadBatchSize = downloadBatchSize + self.retries = retries + self.maxBackoffInterval = maxBackoffInterval + self.rewindDistance = rewindDistance + self.walletBirthday = walletBirthday + self.saplingActivation = saplingActivation + self.cacheDbURL = cacheDbURL + assert(downloadBatchSize >= scanningBatchSize) + } + + init( + fsBlockCacheRoot: URL, + dataDb: URL, + spendParamsURL: URL, + outputParamsURL: URL, + walletBirthday: BlockHeight, + network: ZcashNetwork + ) { + self.fsBlockCacheRoot = fsBlockCacheRoot + self.dataDb = dataDb + self.spendParamsURL = spendParamsURL + self.outputParamsURL = outputParamsURL + self.walletBirthday = walletBirthday + self.saplingActivation = network.constants.saplingActivationHeight + self.network = network + self.cacheDbURL = nil + + assert(downloadBatchSize >= scanningBatchSize) + } + } + + /** + Represents the possible states of a CompactBlockProcessor + */ + enum State { + /** + connected and downloading blocks + */ + case syncing + + /** + was doing something but was paused + */ + case stopped + + /** + Processor is Enhancing transactions + */ + case enhancing + + /** + fetching utxos + */ + case fetching + + /** + was processing but erred + */ + case error(_ error: Error) + + /// Download sapling param files if needed. + case handlingSaplingFiles + + /** + Processor is up to date with the blockchain and you can now make transactions. + */ + case synced + } + + var state: State = .stopped { + didSet { + transitionState(from: oldValue, to: self.state) + } + } + + private var needsToStartScanningWhenStopped = false + var config: Configuration { + willSet { + self.stop() + } + } + + var maxAttemptsReached: Bool { + self.retryAttempts >= self.config.retries + } + + var shouldStart: Bool { + switch self.state { + case .stopped, .synced, .error: + return !maxAttemptsReached + default: + return false + } + } + + var service: LightWalletService +<<<<<<< HEAD:Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift + let blockDownloaderService: BlockDownloaderService + let blockDownloader: BlockDownloader + var storage: CompactBlockStorage +======= + private(set) var downloader: CompactBlockDownloading + var storage: CompactBlockRepository +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache):Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift + var transactionRepository: TransactionRepository + var accountRepository: AccountRepository + var rustBackend: ZcashRustBackendWelding.Type + private var retryAttempts: Int = 0 + private var backoffTimer: Timer? + private var lastChainValidationFailure: BlockHeight? + private var consecutiveChainValidationErrors: Int = 0 + var processingError: Error? + private var foundBlocks = false + private var maxAttempts: Int { + config.retries + } + + var batchSize: BlockHeight { + BlockHeight(self.config.downloadBatchSize) + } + + private var cancelableTask: Task? + + let internalSyncProgress = InternalSyncProgress(storage: UserDefaults.standard) + + /// Initializes a CompactBlockProcessor instance + /// - Parameters: + /// - service: concrete implementation of `LightWalletService` protocol + /// - storage: concrete implementation of `CompactBlockRepository` protocol + /// - backend: a class that complies to `ZcashRustBackendWelding` + /// - config: `Configuration` struct for this processor + init( + service: LightWalletService, + storage: CompactBlockRepository, + backend: ZcashRustBackendWelding.Type, + config: Configuration + ) { + self.init( + service: service, + storage: storage, + backend: backend, + config: config, + repository: TransactionRepositoryBuilder.build( + dataDbURL: config.dataDb + ), + accountRepository: AccountRepositoryBuilder.build(dataDbURL: config.dataDb, readOnly: true) + ) + } + + /// Initializes a CompactBlockProcessor instance from an Initialized object + init(initializer: Initializer) { + self.init( + service: initializer.lightWalletService, + storage: initializer.storage, + backend: initializer.rustBackend, + config: Configuration( + fsBlockCacheRoot: initializer.fsBlockDbRoot, + dataDb: initializer.dataDbURL, + spendParamsURL: initializer.spendParamsURL, + outputParamsURL: initializer.outputParamsURL, + walletBirthday: Checkpoint.birthday( + with: initializer.walletBirthday, + network: initializer.network + ).height, + network: initializer.network + ), + repository: initializer.transactionRepository, + accountRepository: initializer.accountRepository + ) + } + + internal init( + service: LightWalletService, + storage: CompactBlockRepository, + backend: ZcashRustBackendWelding.Type, + config: Configuration, + repository: TransactionRepository, + accountRepository: AccountRepository + ) { + let blockDownloaderService = BlockDownloaderServiceImpl(service: service, storage: storage) + let blockDownloader = BlockDownloaderImpl( + service: service, + downloaderService: blockDownloaderService, + storage: storage, + internalSyncProgress: internalSyncProgress + ) + + self.service = service + self.blockDownloaderService = blockDownloaderService + self.blockDownloader = blockDownloader + self.rustBackend = backend + self.storage = storage + self.config = config + self.transactionRepository = repository + self.accountRepository = accountRepository + } + + deinit { + cancelableTask?.cancel() + } + + static func validateServerInfo( + _ info: LightWalletdInfo, + saplingActivation: BlockHeight, + localNetwork: ZcashNetwork, + rustBackend: ZcashRustBackendWelding.Type + ) throws { + // check network types + guard let remoteNetworkType = NetworkType.forChainName(info.chainName) else { + throw CompactBlockProcessorError.generalError( + message: "Chain name does not match. Expected either 'test' or 'main' but received '\(info.chainName)'." + + "this is probably an API or programming error" + ) + } + + guard remoteNetworkType == localNetwork.networkType else { + throw CompactBlockProcessorError.networkMismatch(expected: localNetwork.networkType, found: remoteNetworkType) + } + + guard saplingActivation == info.saplingActivationHeight else { + throw CompactBlockProcessorError.saplingActivationMismatch(expected: saplingActivation, found: BlockHeight(info.saplingActivationHeight)) + } + + // check branch id + let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight), networkType: localNetwork.networkType) + + guard let remoteBranchID = ConsensusBranchID.fromString(info.consensusBranchID) else { + throw CompactBlockProcessorError.generalError(message: "Consensus BranchIDs don't match this is probably an API or programming error") + } + + guard remoteBranchID == localBranch else { + throw CompactBlockProcessorError.wrongConsensusBranchId(expectedLocally: localBranch, found: remoteBranchID) + } + } + + /// Starts the CompactBlockProcessor instance and starts downloading and processing blocks + /// + /// triggers the blockProcessorStartedDownloading notification + /// + /// - Important: subscribe to the notifications before calling this method + func start(retry: Bool = false) async { + if retry { + self.retryAttempts = 0 + self.processingError = nil + self.backoffTimer?.invalidate() + self.backoffTimer = nil + } + + guard shouldStart else { + switch self.state { + case .error(let error): + // max attempts have been reached + LoggerProxy.info("max retry attempts reached with error: \(error)") + notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.maxAttempts)) + state = .stopped + case .stopped: + // max attempts have been reached + LoggerProxy.info("max retry attempts reached") + notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.maxAttempts)) + case .synced: + // max attempts have been reached + LoggerProxy.warn("max retry attempts reached on synced state, this indicates malfunction") + notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.maxAttempts)) + case .syncing, .enhancing, .fetching, .handlingSaplingFiles: + LoggerProxy.debug("Warning: compact block processor was started while busy!!!!") + self.needsToStartScanningWhenStopped = true + } + return + } + + do { + if let legacyCacheDbURL = self.config.cacheDbURL { + try await self.migrateCacheDb(legacyCacheDbURL) + } + } catch { + await self.fail(error) + } + + await self.nextBatch() + } + + /** + Stops the CompactBlockProcessor + + Note: retry count is reset + */ + func stop() { + self.backoffTimer?.invalidate() + self.backoffTimer = nil + + cancelableTask?.cancel() + + self.retryAttempts = 0 + } + + /// Rewinds to provided height. + /// - Parameter height: height to rewind to. If nil is provided, it will rescan to nearest height (quick rescan) + /// + /// - Note: If this is called while sync is in progress then `CompactBlockProcessorError.rewindAttemptWhileProcessing` is thrown. + func rewindTo(_ height: BlockHeight?) async throws -> BlockHeight { + guard shouldStart else { throw CompactBlockProcessorError.rewindAttemptWhileProcessing } + + let lastDownloaded = await internalSyncProgress.latestDownloadedBlockHeight + let height = Int32(height ?? lastDownloaded) + let nearestHeight = rustBackend.getNearestRewindHeight( + dbData: config.dataDb, + height: height, + networkType: self.config.network.networkType + ) + + guard nearestHeight > 0 else { + let error = rustBackend.lastError() ?? RustWeldingError.genericError( + message: "unknown error getting nearest rewind height for height: \(height)" + ) + await fail(error) + throw error + } + + // FIXME: [#719] this should be done on the rust layer, https://github.com/zcash/ZcashLightClientKit/issues/719 + let rewindHeight = max(Int32(nearestHeight - 1), Int32(config.walletBirthday)) + guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network.networkType) else { + let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)") + await fail(error) + throw error + } + + // clear cache + let rewindBlockHeight = BlockHeight(rewindHeight) + try blockDownloaderService.rewind(to: rewindBlockHeight) + await internalSyncProgress.rewind(to: rewindBlockHeight) + + self.lastChainValidationFailure = nil + return rewindBlockHeight + } + + func wipe() async throws { + switch self.state { + case .syncing, .enhancing, .fetching, .handlingSaplingFiles: + throw CompactBlockProcessorError.wipeAttemptWhileProcessing + case .stopped, .error, .synced: + break + } + + state = .stopped +<<<<<<< HEAD:Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift + blockDownloaderService.closeDBConnection() +======= + + try await self.storage.clear() +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache):Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift + await internalSyncProgress.rewind(to: 0) + + wipeLegacyCacheDbIfNeeded() + } + + func validateServer() async { + do { + let info = try await self.service.getInfo() + try Self.validateServerInfo( + info, + saplingActivation: self.config.saplingActivation, + localNetwork: self.config.network, + rustBackend: self.rustBackend + ) + } catch let error as LightWalletServiceError { + self.severeFailure(error.mapToProcessorError()) + } catch { + self.severeFailure(error) + } + } + + /// Processes new blocks on the given range based on the configuration set for this instance + func processNewBlocks(ranges: SyncRanges) async { + self.foundBlocks = true + self.backoffTimer?.invalidate() + self.backoffTimer = nil + + cancelableTask = Task(priority: .userInitiated) { + do { + let totalProgressRange = computeTotalProgressRange(from: ranges) + + LoggerProxy.debug(""" + Syncing with ranges: + downloaded but not scanned: \ + \(ranges.downloadedButUnscannedRange?.lowerBound ?? -1)...\(ranges.downloadedButUnscannedRange?.upperBound ?? -1) + download and scan: \(ranges.downloadAndScanRange?.lowerBound ?? -1)...\(ranges.downloadAndScanRange?.upperBound ?? -1) + enhance range: \(ranges.enhanceRange?.lowerBound ?? -1)...\(ranges.enhanceRange?.upperBound ?? -1) + fetchUTXO range: \(ranges.fetchUTXORange?.lowerBound ?? -1)...\(ranges.fetchUTXORange?.upperBound ?? -1) + total progress range: \(totalProgressRange.lowerBound)...\(totalProgressRange.upperBound) + """) + + var anyActionExecuted = false + + try storage.create() + + if let range = ranges.downloadedButUnscannedRange { + LoggerProxy.debug("Starting scan with downloaded but not scanned blocks with range: \(range.lowerBound)...\(range.upperBound)") + try await scanBlocks(at: range, totalProgressRange: totalProgressRange) + } + + if let range = ranges.downloadAndScanRange { + LoggerProxy.debug("Starting sync with range: \(range.lowerBound)...\(range.upperBound)") + try await downloadAndScanBlocks(at: range, totalProgressRange: totalProgressRange) + } + + if let range = ranges.enhanceRange { + anyActionExecuted = true + LoggerProxy.debug("Enhancing with range: \(range.lowerBound)...\(range.upperBound)") + try await compactBlockEnhancement(range: range) + } + + if let range = ranges.fetchUTXORange { + anyActionExecuted = true + LoggerProxy.debug("Fetching UTXO with range: \(range.lowerBound)...\(range.upperBound)") + try await fetchUnspentTxOutputs(range: range) + } + + try await handleSaplingParametersIfNeeded() +<<<<<<< HEAD:Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift + try await blockDownloader.removeCacheDB(at: config.cacheDb) +======= + try await clearCompactBlockCache() +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache):Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift + + if !Task.isCancelled { + await processBatchFinished(height: anyActionExecuted ? ranges.latestBlockHeight : nil) + } + } catch { + if !(Task.isCancelled) { + LoggerProxy.error("processing failed with error: \(error)") + await fail(error) + } else { + LoggerProxy.info("processing cancelled.") + state = .stopped + if needsToStartScanningWhenStopped { + await nextBatch() + } + } + } + } + } + + private func downloadAndScanBlocks(at range: CompactBlockRange, totalProgressRange: CompactBlockRange) async throws { + let downloadStream = try await blockDownloader.compactBlocksDownloadStream( + startHeight: range.lowerBound, + targetHeight: range.upperBound + ) + + // Divide `range` by `batchSize` and compute how many time do we need to run to download and scan all the blocks. + // +1 must be done here becase `range` is closed range. So even if upperBound and lowerBound are same there is one block to sync. + let blocksCountToSync = (range.upperBound - range.lowerBound) + 1 + var loopsCount = blocksCountToSync / batchSize + if blocksCountToSync % batchSize != 0 { + loopsCount += 1 + } + + for i in 0..>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache):Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift + + let progress = BlockProgress( + startHeight: totalProgressRange.lowerBound, + targetHeight: totalProgressRange.upperBound, + progressHeight: processingRange.upperBound + ) + notifyProgress(.syncing(progress)) + } + } + + /* + Here range for one batch is computed. For example if we want to sync blocks 0...1000 with batchSize 100 we want to generage blocks like + this: + 0...99 + 100...199 + 200...299 + 300...399 + ... + 900...999 + 1000...1000 + */ + func computeSingleLoopDownloadRange(fullRange: CompactBlockRange, loopCounter: Int, batchSize: BlockHeight) -> CompactBlockRange { + let lowerBound = fullRange.lowerBound + (loopCounter * batchSize) + let upperBound = min(fullRange.lowerBound + ((loopCounter + 1) * batchSize) - 1, fullRange.upperBound) + return lowerBound...upperBound + } + + /// It may happen that sync process start with syncing blocks that were downloaded but not synced in previous run of the sync process. This + /// methods analyses what must be done and computes range that should be used to compute reported progress. + private func computeTotalProgressRange(from syncRanges: SyncRanges) -> CompactBlockRange { + guard syncRanges.downloadedButUnscannedRange != nil || syncRanges.downloadAndScanRange != nil else { + // In this case we are sure that no downloading or scanning happens so this returned range won't be even used. And it's easier to return + // this "fake" range than to handle nil. + return 0...0 + } + + // Thanks to guard above we can be sure that one of these two ranges is not nil. + let lowerBound = syncRanges.downloadedButUnscannedRange?.lowerBound ?? syncRanges.downloadAndScanRange?.lowerBound ?? 0 + let upperBound = syncRanges.downloadAndScanRange?.upperBound ?? syncRanges.downloadedButUnscannedRange?.upperBound ?? 0 + + return lowerBound...upperBound + } + + func notifyProgress(_ progress: CompactBlockProgress) { + var userInfo: [AnyHashable: Any] = [:] + userInfo[CompactBlockProcessorNotificationKey.progress] = progress + + LoggerProxy.debug("progress: \(progress)") + + NotificationSender.default.post( + name: Notification.Name.blockProcessorUpdated, + object: self, + userInfo: userInfo + ) + } + + func notifyTransactions(_ txs: [ZcashTransaction.Overview], in range: BlockRange) { + NotificationSender.default.post( + name: .blockProcessorFoundTransactions, + object: self, + userInfo: [ + CompactBlockProcessorNotificationKey.foundTransactions: txs, + CompactBlockProcessorNotificationKey.foundTransactionsRange: ClosedRange(uncheckedBounds: (range.start.height, range.end.height)) + ] + ) + } + + func determineLowerBound( + errorHeight: Int, + consecutiveErrors: Int, + walletBirthday: BlockHeight + ) -> BlockHeight { + let offset = min(ZcashSDK.maxReorgSize, ZcashSDK.defaultRewindDistance * (consecutiveErrors + 1)) + return max(errorHeight - offset, walletBirthday - ZcashSDK.maxReorgSize) + } + + func severeFailure(_ error: Error) { + cancelableTask?.cancel() + LoggerProxy.error("show stopper failure: \(error)") + self.backoffTimer?.invalidate() + self.retryAttempts = config.retries + self.processingError = error + state = .error(error) + self.notifyError(error) + } + + func fail(_ error: Error) async { + // TODO: [#713] specify: failure. https://github.com/zcash/ZcashLightClientKit/issues/713 + LoggerProxy.error("\(error)") + cancelableTask?.cancel() + self.retryAttempts += 1 + self.processingError = error + switch self.state { + case .error: + notifyError(error) + default: + break + } + state = .error(error) + guard self.maxAttemptsReached else { return } + // don't set a new timer if there are no more attempts. + await self.setTimer() + } + + func mapError(_ error: Error) -> CompactBlockProcessorError { + if let processorError = error as? CompactBlockProcessorError { + return processorError + } + if let lwdError = error as? LightWalletServiceError { + return lwdError.mapToProcessorError() + } else if let rpcError = error as? GRPC.GRPCStatus { + switch rpcError { + case .ok: + LoggerProxy.warn("Error Raised when status is OK") + return CompactBlockProcessorError.grpcError( + statusCode: rpcError.code.rawValue, + message: rpcError.message ?? "Error Raised when status is OK" + ) + default: + return CompactBlockProcessorError.grpcError(statusCode: rpcError.code.rawValue, message: rpcError.message ?? "No message") + } + } + return .unspecifiedError(underlyingError: error) + } + + private func validateConfiguration() throws { + guard FileManager.default.isReadableFile(atPath: config.fsBlockCacheRoot.absoluteString) else { + throw CompactBlockProcessorError.missingDbPath(path: config.fsBlockCacheRoot.absoluteString) + } + + guard FileManager.default.isReadableFile(atPath: config.dataDb.absoluteString) else { + throw CompactBlockProcessorError.missingDbPath(path: config.dataDb.absoluteString) + } + } + + private func nextBatch() async { + state = .syncing + do { + let nextState = try await NextStateHelper.nextStateAsync( + service: self.service, + downloaderService: blockDownloaderService, + transactionRepository: transactionRepository, + config: self.config, + rustBackend: self.rustBackend, + internalSyncProgress: internalSyncProgress + ) + switch nextState { + case .finishProcessing(let height): + await self.processingFinished(height: height) + case .processNewBlocks(let ranges): + await self.processNewBlocks(ranges: ranges) + case let .wait(latestHeight, latestDownloadHeight): + // Lightwalletd might be syncing + LoggerProxy.info( + "Lightwalletd might be syncing: latest downloaded block height is: \(latestDownloadHeight) " + + "while latest blockheight is reported at: \(latestHeight)" + ) + await self.processingFinished(height: latestDownloadHeight) + } + } catch { + self.severeFailure(error) + } + } + + internal func validationFailed(at height: BlockHeight) async { + // cancel all Tasks + cancelableTask?.cancel() + + // register latest failure + self.lastChainValidationFailure = height + + // rewind + let rewindHeight = determineLowerBound( + errorHeight: height, + consecutiveErrors: consecutiveChainValidationErrors, + walletBirthday: self.config.walletBirthday + ) + + self.consecutiveChainValidationErrors += 1 + + guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network.networkType) else { + await fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)")) + return + } + + do { + try blockDownloaderService.rewind(to: rewindHeight) + await internalSyncProgress.rewind(to: rewindHeight) + + // notify reorg + NotificationSender.default.post( + name: Notification.Name.blockProcessorHandledReOrg, + object: self, + userInfo: [ + CompactBlockProcessorNotificationKey.reorgHeight: height, CompactBlockProcessorNotificationKey.rewindHeight: rewindHeight + ] + ) + + // process next batch + await self.nextBatch() + } catch { + await self.fail(error) + } + } + + internal func processBatchFinished(height: BlockHeight?) async { + retryAttempts = 0 + consecutiveChainValidationErrors = 0 + + if let height { + await processingFinished(height: height) + } else { + await nextBatch() + } + } + + private func processingFinished(height: BlockHeight) async { + NotificationSender.default.post( + name: Notification.Name.blockProcessorFinished, + object: self, + userInfo: [ + CompactBlockProcessorNotificationKey.latestScannedBlockHeight: height, + CompactBlockProcessorNotificationKey.foundBlocks: self.foundBlocks + ] + ) + state = .synced + await setTimer() + NotificationSender.default.post( + name: Notification.Name.blockProcessorIdle, + object: self, + userInfo: nil + ) + } + + private func clearCompactBlockCache() async throws { + try await storage.clear() + LoggerProxy.info("Cache removed") + } + + private func setTimer() async { + let interval = self.config.blockPollInterval + self.backoffTimer?.invalidate() + let timer = Timer( + timeInterval: interval, + repeats: true, + block: { [weak self] _ in + Task { [self] in + guard let self = self else { return } + if await self.shouldStart { + LoggerProxy.debug( + """ + Timer triggered: Starting compact Block processor!. + Processor State: \(await self.state) + latestHeight: \(try await self.transactionRepository.lastScannedHeight()) + attempts: \(await self.retryAttempts) + """ + ) + await self.start() + } else if await self.maxAttemptsReached { + await self.fail(CompactBlockProcessorError.maxAttemptsReached(attempts: self.config.retries)) + } + } + } + ) + RunLoop.main.add(timer, forMode: .default) + + self.backoffTimer = timer + } + + private func transitionState(from oldValue: State, to newValue: State) { + guard oldValue != newValue else { + return + } + + NotificationSender.default.post( + name: .blockProcessorStatusChanged, + object: self, + userInfo: [ + CompactBlockProcessorNotificationKey.previousStatus: oldValue, + CompactBlockProcessorNotificationKey.newStatus: newValue + ] + ) + + switch newValue { + case .error(let err): + notifyError(err) + case .stopped: + NotificationSender.default.post(name: Notification.Name.blockProcessorStopped, object: self) + case .enhancing: + NotificationSender.default.post(name: Notification.Name.blockProcessorStartedEnhancing, object: self) + case .fetching: + NotificationSender.default.post(name: Notification.Name.blockProcessorStartedFetching, object: self) + case .handlingSaplingFiles: + NotificationSender.default.post(name: Notification.Name.blockProcessorHandlingSaplingFiles, object: self) + case .synced: + // transition to this state is handled by `processingFinished(height: BlockHeight)` + break + case .syncing: + NotificationSender.default.post(name: Notification.Name.blockProcessorStartedSyncing, object: self) + } + } + + private func notifyError(_ err: Error) { + NotificationSender.default.post( + name: Notification.Name.blockProcessorFailed, + object: self, + userInfo: [CompactBlockProcessorNotificationKey.error: mapError(err)] + ) + } + // TODO: [#713] encapsulate service errors better, https://github.com/zcash/ZcashLightClientKit/issues/713 +} + +extension CompactBlockProcessor.Configuration { + /** + Standard configuration for most compact block processors + */ + static func standard(for network: ZcashNetwork, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration { + let pathProvider = DefaultResourceProvider(network: network) + return CompactBlockProcessor.Configuration( + fsBlockCacheRoot: pathProvider.fsCacheURL, + dataDb: pathProvider.dataDbURL, + spendParamsURL: pathProvider.spendParamsURL, + outputParamsURL: pathProvider.outputParamsURL, + walletBirthday: walletBirthday, + network: network + ) + } +} + +extension LightWalletServiceError { + func mapToProcessorError() -> CompactBlockProcessorError { + switch self { + case let .failed(statusCode, message): + return CompactBlockProcessorError.grpcError(statusCode: statusCode, message: message) + case .invalidBlock: + return CompactBlockProcessorError.generalError(message: "\(self)") + case .generalError(let message): + return CompactBlockProcessorError.generalError(message: message) + case .sentFailed(let error): + return CompactBlockProcessorError.connectionError(underlyingError: error) + case .genericError(let error): + return CompactBlockProcessorError.unspecifiedError(underlyingError: error) + case .timeOut: + return CompactBlockProcessorError.connectionTimeout + case .criticalError: + return CompactBlockProcessorError.criticalError + case .userCancelled: + return CompactBlockProcessorError.connectionTimeout + case .unknown: + return CompactBlockProcessorError.unspecifiedError(underlyingError: self) + } + } +} +extension CompactBlockProcessor.State: Equatable { + public static func == (lhs: CompactBlockProcessor.State, rhs: CompactBlockProcessor.State) -> Bool { + switch (lhs, rhs) { + case + (.syncing, .syncing), + (.stopped, .stopped), + (.error, .error), + (.synced, .synced), + (.enhancing, .enhancing), + (.fetching, .fetching): + return true + default: + return false + } + } +} + +extension CompactBlockProcessor { + func getUnifiedAddress(accountIndex: Int) -> UnifiedAddress? { + try? rustBackend.getCurrentAddress( + dbData: config.dataDb, + account: Int32(accountIndex), + networkType: config.network.networkType + ) + } + + func getSaplingAddress(accountIndex: Int) -> SaplingAddress? { + getUnifiedAddress(accountIndex: accountIndex)?.saplingReceiver() + } + + func getTransparentAddress(accountIndex: Int) -> TransparentAddress? { + getUnifiedAddress(accountIndex: accountIndex)?.transparentReceiver() + } + + func getTransparentBalance(accountIndex: Int) throws -> WalletBalance { + guard accountIndex >= 0 else { + throw CompactBlockProcessorError.invalidAccount + } + + return WalletBalance( + verified: Zatoshi( + try rustBackend.getVerifiedTransparentBalance( + dbData: config.dataDb, + account: Int32(accountIndex), + networkType: config.network.networkType + ) + ), + total: Zatoshi( + try rustBackend.getTransparentBalance( + dbData: config.dataDb, + account: Int32(accountIndex), + networkType: config.network.networkType + ) + ) + ) + } +} + +extension CompactBlockProcessor { + func refreshUTXOs(tAddress: TransparentAddress, startHeight: BlockHeight) async throws -> RefreshedUTXOs { + let dataDb = self.config.dataDb + + let stream: AsyncThrowingStream = blockDownloaderService.fetchUnspentTransactionOutputs( + tAddress: tAddress.stringEncoded, + startHeight: startHeight + ) + var utxos: [UnspentTransactionOutputEntity] = [] + + do { + for try await utxo in stream { + utxos.append(utxo) + } + return storeUTXOs(utxos, in: dataDb) + } catch { + throw mapError(error) + } + } + + private func storeUTXOs(_ utxos: [UnspentTransactionOutputEntity], in dataDb: URL) -> RefreshedUTXOs { + var refreshed: [UnspentTransactionOutputEntity] = [] + var skipped: [UnspentTransactionOutputEntity] = [] + for utxo in utxos { + do { + if try self.rustBackend.putUnspentTransparentOutput( + dbData: dataDb, + txid: utxo.txid.bytes, + index: utxo.index, + script: utxo.script.bytes, + value: Int64(utxo.valueZat), + height: utxo.height, + networkType: self.config.network.networkType + ) { + refreshed.append(utxo) + } else { + skipped.append(utxo) + } + } catch { + LoggerProxy.info("failed to put utxo - error: \(error)") + skipped.append(utxo) + } + } + return (inserted: refreshed, skipped: skipped) + } +} + +extension CompactBlockProcessorError: LocalizedError { + /// A localized message describing what error occurred. + public var errorDescription: String? { + switch self { + case .dataDbInitFailed(let path): + return "Data Db file couldn't be initialized at path: \(path)" + case .connectionError(let underlyingError): + return "There's a problem with the Network Connection. Underlying error: \(underlyingError.localizedDescription)" + case .connectionTimeout: + return "Network connection timeout" + case .criticalError: + return "Critical Error" + case .generalError(let message): + return "Error Processing Blocks - \(message)" + case let .grpcError(statusCode, message): + return "Error on gRPC - Status Code: \(statusCode) - Message: \(message)" + case .invalidAccount: + return "Invalid Account" + case .invalidConfiguration: + return "CompactBlockProcessor was started with an Invalid Configuration" + case .maxAttemptsReached(let attempts): + return "Compact Block failed \(attempts) times and reached the maximum amount of retries it was set up to do" + case .missingDbPath(let path): + return "CompactBlockProcessor was set up with path \(path) but that location couldn't be reached" + case let .networkMismatch(expected, found): + // swiftlint:disable:next line_length + return "A server was reached, but it's targeting the wrong network Type. App Expected \(expected) but found \(found). Make sure you are pointing to the right server" + case .rewindAttemptWhileProcessing: + return "Can't execute rewind while sync process is in progress." + case let .saplingActivationMismatch(expected, found): + // swiftlint:disable:next line_length + return "A server was reached, it's showing a different sapling activation. App expected sapling activation height to be \(expected) but instead it found \(found). Are you sure you are pointing to the right server?" + case .unspecifiedError(let underlyingError): + return "Unspecified error caused by this underlying error: \(underlyingError)" + case let .wrongConsensusBranchId(expectedLocally, found): + // swiftlint:disable:next line_length + return "The remote server you are connecting to is publishing a different branch ID \(found) than the one your App is expecting to be (\(expectedLocally)). This could be caused by your App being out of date or the server you are connecting you being either on a different network or out of date after a network upgrade." + case .unknown: return "Unknown error occured." + case .wipeAttemptWhileProcessing: + return "Can't execute wipe while sync process is in progress." + } + } + + /// A localized message describing the reason for the failure. + public var failureReason: String? { + self.localizedDescription + } + + /// A localized message describing how one might recover from the failure. + public var recoverySuggestion: String? { + self.localizedDescription + } + + /// A localized message providing "help" text if the user requests help. + public var helpAnchor: String? { + self.localizedDescription + } +} + +extension CompactBlockProcessor: EnhancementStreamDelegate { + func transactionEnhancementProgressUpdated(_ progress: EnhancementProgress) { + NotificationSender.default.post( + name: .blockProcessorEnhancementProgress, + object: self, + userInfo: [CompactBlockProcessorNotificationKey.enhancementProgress: progress] + ) + } +} + +extension CompactBlockProcessor { + enum NextStateHelper { + // swiftlint:disable:next function_parameter_count + static func nextStateAsync( + service: LightWalletService, + downloaderService: BlockDownloaderService, + transactionRepository: TransactionRepository, + config: Configuration, + rustBackend: ZcashRustBackendWelding.Type, + internalSyncProgress: InternalSyncProgress + ) async throws -> CompactBlockProcessor.NextState { + // It should be ok to not create new Task here because this method is already async. But for some reason something not good happens + // when Task is not created here. For example tests start failing. Reason is unknown at this time. + let task = Task(priority: .userInitiated) { + let info = try await service.getInfo() + + try CompactBlockProcessor.validateServerInfo( + info, + saplingActivation: config.saplingActivation, + localNetwork: config.network, + rustBackend: rustBackend + ) + +<<<<<<< HEAD:Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift + await internalSyncProgress.migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB: try downloaderService.lastDownloadedBlockHeight()) +======= + let latestDownloadHeight = try downloader.lastDownloadedBlockHeight() + + await internalSyncProgress.migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB: latestDownloadHeight) +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache):Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift + + let latestBlockHeight = try service.latestBlockHeight() + let latestScannedHeight = try transactionRepository.lastScannedHeight() + + return try await internalSyncProgress.computeNextState( + latestBlockHeight: latestBlockHeight, + latestScannedHeight: latestScannedHeight, + walletBirthday: config.walletBirthday + ) + } + + return try await task.value + } + } +} + +/// This extension contains asociated types and functions needed to clean up the +/// `cacheDb` in favor of `FsBlockDb`. Once this cleanup functionality is deprecated, +/// delete the whole extension and reference to it in other parts of the code including tests. +extension CompactBlockProcessor { + public enum CacheDbMigrationError: Error { + case fsCacheMigrationFailedSameURL + case failedToDeleteLegacyDb(Error) + case failedToInitFsBlockDb(Error) + case failedToSetDownloadHeight(Error) + } + + /// Deletes the SQLite cacheDb and attempts to initialize the fsBlockDbRoot + /// - parameter legacyCacheDbURL: the URL where the cache Db used to be stored. + /// - Throws `InitializerError.fsCacheInitFailedSameURL` when the given URL + /// is the same URL than the one provided as `self.fsBlockDbRoot` assuming that's a + /// programming error being the `legacyCacheDbURL` a sqlite database file and not a + /// directory. Also throws errors from initializing the fsBlockDbRoot. + /// + /// - Note: Errors from deleting the `legacyCacheDbURL` won't be throwns. + func migrateCacheDb(_ legacyCacheDbURL: URL) async throws { + guard legacyCacheDbURL != config.fsBlockCacheRoot else { + throw CacheDbMigrationError.fsCacheMigrationFailedSameURL + } + + // if the URL provided is not readable, it means that the client has a reference + // to the cacheDb file but it has been deleted in a prior sync cycle. there's + // nothing to do here. + guard FileManager.default.isReadableFile(atPath: legacyCacheDbURL.path) else { + return + } + + do { + // if there's a readable file at the provided URL, delete it. + try FileManager.default.removeItem(at: legacyCacheDbURL) + } catch { + throw CacheDbMigrationError.failedToDeleteLegacyDb(error) + } + + // create the storage + do { + try self.storage.create() + } catch { + throw CacheDbMigrationError.failedToInitFsBlockDb(error) + } + + // The database has been deleted, so we have adjust the internal state of the + // `CompactBlockProcessor` so that it doesn't rely on download heights set + // by a previous processing cycle. + do { + let lastScannedHeight = try self.transactionRepository.lastScannedHeight() + + await internalSyncProgress.set(lastScannedHeight, .latestDownloadedBlockHeight) + } catch { + throw CacheDbMigrationError.failedToSetDownloadHeight(error) + } + } + + func wipeLegacyCacheDbIfNeeded() { + guard let cacheDbURL = config.cacheDbURL else { + return + } + + guard FileManager.default.isDeletableFile(atPath: cacheDbURL.pathExtension) else { + return + } + + try? FileManager.default.removeItem(at: cacheDbURL) + } +} diff --git a/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift b/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift deleted file mode 100644 index 5da1d1baa..000000000 --- a/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift +++ /dev/null @@ -1,119 +0,0 @@ -// -// CompactBlockStorage.swift -// ZcashLightClientKit -// -// Created by Francisco Gindre on 10/13/19. -// Copyright © 2019 Electric Coin Company. All rights reserved. -// - -import Foundation -import SQLite - -protocol ConnectionProvider { - func connection() throws -> Connection - func close() -} - -class CompactBlockStorage: CompactBlockDAO { - var dbProvider: ConnectionProvider - - convenience init(url: URL, readonly: Bool) { - self.init(connectionProvider: SimpleConnectionProvider(path: url.absoluteString, readonly: readonly)) - } - - init(connectionProvider: ConnectionProvider) { - dbProvider = connectionProvider - } - - private func compactBlocksTable() -> Table { - Table("compactblocks") - } - private func heightColumn() -> Expression { - Expression("height") - } - private func dataColumn() -> Expression { - Expression("data") - } - - func closeDBConnection() { - dbProvider.close() - } - - func createTable() throws { - do { - let compactBlocks = compactBlocksTable() - let height = heightColumn() - let data = dataColumn() - - let db = try dbProvider.connection() - - try db.run( - compactBlocks.create(ifNotExists: true) { table in - table.column(height, primaryKey: true) - table.column(data) - } - ) - - try db.run(compactBlocks.createIndex(height, ifNotExists: true)) - } catch { - throw StorageError.couldNotCreate - } - } - - func insert(_ block: ZcashCompactBlock) throws { - try dbProvider.connection().run(compactBlocksTable().insert(block)) - } - - func insert(_ blocks: [ZcashCompactBlock]) throws { - let compactBlocks = compactBlocksTable() - let db = try dbProvider.connection() - try db.transaction(.immediate) { - for block in blocks { - try db.run(compactBlocks.insert(block)) - } - } - } - - func latestBlockHeight() throws -> BlockHeight { - guard let maxHeight = try dbProvider.connection().scalar(compactBlocksTable().select(heightColumn().max)) else { - return BlockHeight.empty() - } - - guard let blockHeight = BlockHeight(exactly: maxHeight) else { - throw StorageError.operationFailed - } - - return blockHeight - } - - func rewind(to height: BlockHeight) throws { - try dbProvider.connection().run(compactBlocksTable().filter(heightColumn() >= Int64(height)).delete()) - } -} - -extension CompactBlockStorage: CompactBlockRepository { - func latestHeight() throws -> BlockHeight { - try latestBlockHeight() - } - - func latestHeightAsync() async throws -> BlockHeight { - let task = Task(priority: .userInitiated) { - try latestBlockHeight() - } - return try await task.value - } - - func write(blocks: [ZcashCompactBlock]) async throws { - let task = Task(priority: .userInitiated) { - try insert(blocks) - } - try await task.value - } - - func rewindAsync(to height: BlockHeight) async throws { - let task = Task(priority: .userInitiated) { - try rewind(to: height) - } - try await task.value - } -} diff --git a/Sources/ZcashLightClientKit/Block/DatabaseStorage/ConnectorProvider.swift b/Sources/ZcashLightClientKit/Block/DatabaseStorage/ConnectorProvider.swift new file mode 100644 index 000000000..8a9d56742 --- /dev/null +++ b/Sources/ZcashLightClientKit/Block/DatabaseStorage/ConnectorProvider.swift @@ -0,0 +1,12 @@ +// +// ConnectorProvider.swift +// +// +// Created by Francisco Gindre on 1/12/23. +// +import SQLite + +protocol ConnectionProvider { + func connection() throws -> Connection + func close() +} diff --git a/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift b/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift index b3eb7f564..e8188223d 100644 --- a/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift +++ b/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift @@ -9,10 +9,6 @@ import Foundation import SQLite class MigrationManager { - enum CacheDbMigration: Int32, CaseIterable { - case none = 0 - } - // swiftlint:disable identifier_name enum PendingDbMigration: Int32, CaseIterable { case none = 0 @@ -20,25 +16,20 @@ class MigrationManager { case v2 = 2 } - static let nextCacheDbMigration = CacheDbMigration.none static let nextPendingDbMigration = PendingDbMigration.v2 - var cacheDb: ConnectionProvider var pendingDb: ConnectionProvider var network: NetworkType init( - cacheDbConnection: ConnectionProvider, pendingDbConnection: ConnectionProvider, networkType: NetworkType ) { - self.cacheDb = cacheDbConnection self.pendingDb = pendingDbConnection self.network = networkType } func performMigration() throws { - try migrateCacheDb() try migratePendingDb() } } @@ -64,7 +55,7 @@ private extension MigrationManager { // unreachable due to the bound on the loop. break case nil: - throw StorageError.migrationFailedWithMessage(message: "Invalid migration version: \(version).") + throw DatabaseStorageError.migrationFailedWithMessage(message: "Invalid migration version: \(version).") } } } @@ -149,27 +140,6 @@ private extension MigrationManager { try pendingDb.connection().setUserVersion(PendingDbMigration.v2.rawValue) } } - - func migrateCacheDb() throws { - // getUserVersion returns a default value of zero for an unmigrated database. - let currentCacheDbVersion = try cacheDb.connection().getUserVersion() - - LoggerProxy.debug( - "Attempting to perform migration for cache Db - currentVersion: \(currentCacheDbVersion)." + - "Latest version is: \(Self.nextCacheDbMigration.rawValue)" - ) - - for version in (currentCacheDbVersion.. BlockDownloaderStream { try Task.checkCancellation() let stream = service.blockStream(startHeight: startHeight, endHeight: targetHeight) @@ -126,13 +123,6 @@ extension BlockDownloaderImpl: BlockDownloader { await blocksBufferWritten(buffer) } - func removeCacheDB(at cacheDBURL: URL) async throws { - storage.closeDBConnection() - try FileManager.default.removeItem(at: cacheDBURL) - try storage.createTable() - LoggerProxy.info("Cache removed") - } - private func blocksBufferWritten(_ buffer: [ZcashCompactBlock]) async { guard let lastBlock = buffer.last else { return } await internalSyncProgress.set(lastBlock.height, .latestDownloadedBlockHeight) diff --git a/Sources/ZcashLightClientKit/Block/Download/BlockDownloaderService.swift b/Sources/ZcashLightClientKit/Block/Download/BlockDownloaderService.swift index 6f9e28393..b15159d01 100644 --- a/Sources/ZcashLightClientKit/Block/Download/BlockDownloaderService.swift +++ b/Sources/ZcashLightClientKit/Block/Download/BlockDownloaderService.swift @@ -72,8 +72,6 @@ protocol BlockDownloaderService { func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight) -> AsyncThrowingStream func closeConnection() - - func closeDBConnection() } /** @@ -98,10 +96,6 @@ extension BlockDownloaderServiceImpl: BlockDownloaderService { func closeConnection() { lightwalletService.closeConnection() } - - func closeDBConnection() { - storage.closeDBConnection() - } func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight ) -> AsyncThrowingStream { lightwalletService.fetchUTXOs(for: tAddresses, height: startHeight) @@ -139,22 +133,17 @@ extension BlockDownloaderServiceImpl: BlockDownloaderService { throw error } } - - func lastDownloadedBlockHeightAsync() async throws -> BlockHeight { - do { - let latestHeight = try await storage.latestHeightAsync() - return latestHeight - } catch { - throw BlockDownloaderServiceError.generalError(error: error) - } - } func rewind(to height: BlockHeight) throws { try self.storage.rewind(to: height) } - - func lastDownloadedBlockHeight() throws -> BlockHeight { - try self.storage.latestHeight() + + func lastDownloadedBlockHeightAsync() async -> BlockHeight { + await Task { self.lastDownloadedBlockHeight() }.value + } + + func lastDownloadedBlockHeight() -> BlockHeight { + self.storage.latestHeight() } func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched { diff --git a/Sources/ZcashLightClientKit/Block/FilesystemStorage/FSCompactBlockRepository.swift b/Sources/ZcashLightClientKit/Block/FilesystemStorage/FSCompactBlockRepository.swift new file mode 100644 index 000000000..3884d15c1 --- /dev/null +++ b/Sources/ZcashLightClientKit/Block/FilesystemStorage/FSCompactBlockRepository.swift @@ -0,0 +1,378 @@ +// +// CompactBlockFsStorage.swift +// +// +// Created by Francisco Gindre on 12/15/22. +// + +import Foundation + +class FSCompactBlockRepository { + let cacheDirectory: URL + let blockDescriptor: ZcashCompactBlockDescriptor + let contentProvider: SortedDirectoryListing + let fileWriter: FSBlockFileWriter + let metadataStore: FSMetadataStore + + private let fileManager = FileManager() + private let storageBatchSize = 10 + + var blocksDirectory: URL { + cacheDirectory.appendingPathComponent("blocks", isDirectory: true) + } + + /// Initializes an instance of the Filesystem based compact block repository + /// - Parameter cacheDirectory: The `URL` pointing to where the blocks should be writen + /// write access must be **guaranteed**. + /// - Parameter blockDescriptor: A `ZcashCompactBlockDescriptor` that is used to turn a + /// `ZcashCompactBlock` into the filename that will hold it on cache + /// - parameter contentProvider: `SortedDirectoryListing` implementation. This injects the + /// behaviour of traversing a Directory in an ordered fashion which is not guaranteed by `Foundation`'s `FileManager` + init( + cacheDirectory: URL, + metadataStore: FSMetadataStore, + blockDescriptor: ZcashCompactBlockDescriptor, + contentProvider: SortedDirectoryListing, + fileWriter: FSBlockFileWriter = .atomic + ) { + self.cacheDirectory = cacheDirectory + self.metadataStore = metadataStore + self.blockDescriptor = blockDescriptor + self.contentProvider = contentProvider + self.fileWriter = fileWriter + } +} + +extension FSCompactBlockRepository: CompactBlockRepository { + func create() throws { + if !fileManager.fileExists(atPath: blocksDirectory.path) { + try fileManager.createDirectory(at: blocksDirectory, withIntermediateDirectories: true) + } + + guard try self.metadataStore.initFsBlockDbRoot(self.cacheDirectory) else { + throw CompactBlockRepositoryError.failedToInitializeCache + } + } + + func latestHeight() -> BlockHeight { + metadataStore.latestHeight() + } + + func latestHeightAsync() async -> BlockHeight { + await metadataStore.latestHeightAsync() + } + + func write(blocks: [ZcashCompactBlock]) async throws { + try await withThrowingTaskGroup(of: ZcashCompactBlock.self) { group in + for block in blocks { + group.addTask { + // check if file exists + let blockURL = self.urlForBlock(block) + + if self.blockExistsInCache(block) { + // remove if needed + try self.fileManager.removeItem(at: blockURL) + } + + // store atomically + do { + try self.fileWriter.writeToURL(block.data, blockURL) + } catch { + LoggerProxy.error("Failed to write block: \(block.height) to path: \(blockURL.path).") + throw CompactBlockRepositoryError.failedToWriteBlock(block) + } + + return block + } + } + + var savedBlocks: [ZcashCompactBlock] = [] + + do { + for try await block in group { + savedBlocks.append(block) + + if (savedBlocks.count % storageBatchSize) == 0 { + try await self.metadataStore.saveBlocksMeta(savedBlocks) + savedBlocks.removeAll(keepingCapacity: true) + } + } + + // if there are any remaining blocks on the cache store them + try await self.metadataStore.saveBlocksMeta(savedBlocks) + } catch { + LoggerProxy.error("failed to Block save to cache error: \(error.localizedDescription)") + throw error + } + } + } + + func rewind(to height: BlockHeight) throws { + try metadataStore.rewindToHeight(height) + // Reverse the cached contents to browse from higher to lower heights + let sortedCachedContents = try contentProvider.listContents(of: blocksDirectory) + + // it that bears no elements then there's nothing to do. + guard let deleteList = try Self.filterBlockFiles( + from: sortedCachedContents, + toRewind: height, + with: self.blockDescriptor + ), + !deleteList.isEmpty + else { return } + + for item in deleteList { + try self.fileManager.removeItem(at: item) + } + } + + func rewindAsync(to height: BlockHeight) async throws { + try await Task { + try rewind(to: height) + }.value + } + + func clear() async throws { + try await Task { + try self.fileManager.removeItem(at: self.cacheDirectory) + try create() + }.value + } +} + +extension FSCompactBlockRepository { + static let filenameComparison: (String, String) -> Int? = { lhs, rhs in + guard + let leftHeightStr = lhs.split(separator: "-").first, + let leftHeight = BlockHeight(leftHeightStr), + let rightHeightStr = rhs.split(separator: "-").first, + let rightHeight = BlockHeight(rightHeightStr) + else { return nil } + + return leftHeight - rightHeight + } + + static let filenameDescription: (ZcashCompactBlock) -> String = { block in + [ + "\(block.height)", + block.meta.hash.toHexStringTxId(), + "compactblock" + ] + .joined(separator: "-") + } + + static let filenameToHeight: (String) -> BlockHeight? = { block in + block.split(separator: "-") + .first + .flatMap { BlockHeight(String($0)) } + } +} + +extension FSCompactBlockRepository { + /// Filters block files from a sorted list of filenames from the FsCache directory + /// with the goal of rewinding up to height `toHeight` and parsing the filenames + /// with the given `blockDescriptor` + /// - note: it is assumed that the `sortedList` is ascending. + /// - Parameter sortedList: ascending list of block filenames + /// - Parameter toHeight: + static func filterBlockFiles( + from sortedList: [URL], + toRewind toHeight: BlockHeight, + with blockDescriptor: ZcashCompactBlockDescriptor + ) throws -> [URL]? { + // Reverse the cached contents to browse from higher to lower heights + let sortedCachedContents = sortedList.reversed() + + // pick the blocks that are higher than the rewind height + // then return their URLs + let deleteList = try sortedCachedContents.filter({ url in + guard let filename = try url.resourceValues(forKeys: [.nameKey]).name else { + throw CompactBlockRepositoryError.malformedCacheEntry("failed to get url \(url) from cache") + } + + return try filename.filterGreaterThan(toHeight, with: blockDescriptor) + }) + + guard !deleteList.isEmpty else { return nil } + + return deleteList + } + + func urlForBlock(_ block: ZcashCompactBlock) -> URL { + self.blocksDirectory.appendingPathComponent( + self.blockDescriptor.describe(block) + ) + } + + func blockExistsInCache(_ block: ZcashCompactBlock) -> Bool { + self.fileManager.fileExists( + atPath: urlForBlock(block).path + ) + } +} +// MARK: Associated and Helper types + +struct FSBlockFileWriter { + var writeToURL: (Data, URL) throws -> Void +} + +extension FSBlockFileWriter { + static let atomic = FSBlockFileWriter(writeToURL: { data, url in + try data.write(to: url, options: .atomic) + }) +} + +struct FSMetadataStore { + var saveBlocksMeta: ([ZcashCompactBlock]) async throws -> Void + var rewindToHeight: (BlockHeight) throws -> Void + var initFsBlockDbRoot: (URL) throws -> Bool + var latestHeightAsync: () async -> BlockHeight + var latestHeight: () -> BlockHeight +} + +extension FSMetadataStore { + static func live(fsBlockDbRoot: URL, rustBackend: ZcashRustBackendWelding.Type) -> FSMetadataStore { + FSMetadataStore { blocks in + try await FSMetadataStore.saveBlocksMeta( + blocks, + fsBlockDbRoot: fsBlockDbRoot, + rustBackend: rustBackend + ) + } rewindToHeight: { height in + guard rustBackend.rewindCacheToHeight(fsBlockDbRoot: fsBlockDbRoot, height: Int32(height)) else { + throw CompactBlockRepositoryError.failedToRewind(height) + } + } initFsBlockDbRoot: { dbRootURL in + try rustBackend.initBlockMetadataDb(fsBlockDbRoot: dbRootURL) + } latestHeightAsync: { + await Task { rustBackend.latestCachedBlockHeight(fsBlockDbRoot: fsBlockDbRoot) }.value + } latestHeight: { + rustBackend.latestCachedBlockHeight(fsBlockDbRoot: fsBlockDbRoot) + } + } +} + +extension FSMetadataStore { + /// saves blocks to the FsBlockDb metadata database. + /// - Parameter blocks: Array of `ZcashCompactBlock` to save + /// - Throws `CompactBlockRepositoryError.failedToWriteMetadata` if the + /// operation fails. the underlying error is logged through `LoggerProxy` + /// - Note: This shouldn't be called in parallel by many threads or workers. Won't do anything if `blocks` is empty + static func saveBlocksMeta(_ blocks: [ZcashCompactBlock], fsBlockDbRoot: URL, rustBackend: ZcashRustBackendWelding.Type) async throws { + guard !blocks.isEmpty else { return } + + do { + guard try rustBackend.writeBlocksMetadata(fsBlockDbRoot: fsBlockDbRoot, blocks: blocks) else { + throw CompactBlockRepositoryError.failedToWriteMetadata + } + } catch { + LoggerProxy.error("Failed to write metadata with error: \(error)") + throw CompactBlockRepositoryError.failedToWriteMetadata + } + } +} + +struct ZcashCompactBlockDescriptor { + var height: (String) -> BlockHeight? + var describe: (ZcashCompactBlock) -> String + var compare: (String, String) -> Int? +} + +extension ZcashCompactBlockDescriptor { + /// describes the block following this convention: `HEIGHT-BLOCKHASHHEX-compactblock` + static let live = ZcashCompactBlockDescriptor( + height: FSCompactBlockRepository.filenameToHeight, + describe: FSCompactBlockRepository.filenameDescription, + compare: FSCompactBlockRepository.filenameComparison + ) +} + +enum DirectoryListingProviders { + /// returns an ascending list of files from a given directory. + static let `defaultSorted` = SortedDirectoryContentProvider( + fileManager: FileManager.default, + sorting: URL.areInIncreasingOrderByFilename + ) + + /// the default sorting of FileManager + static let naive = FileManager.default +} + +class SortedDirectoryContentProvider: SortedDirectoryListing { + let fileManager: FileManager + let sorting: (URL, URL) throws -> Bool + let recursive: Bool + + /// inits the `SortedDirectoryContentProvider` + /// - Parameter fileManager: an instance of `FileManager` + /// - Parameter sorting: A predicate that returns `true` if its + /// first argument should be ordered before its second argument; + /// otherwise, `false`. + /// - Parameter recursive: make this list subdirectories. Default + init(fileManager: FileManager, sorting: @escaping (URL, URL) throws -> Bool, recursive: Bool = false) { + self.fileManager = fileManager + self.sorting = sorting + self.recursive = recursive + } + + /// lists the contents of the given directory on `url` using the + /// sorting provided by `sorting` property of this provider. + /// - Parameter url: url to list the contents from. It must be a directory or the call will fail. + /// - Returns an array with the contained files or an empty one if the directory is empty + /// - Throws rethrows any errors from the underlying `FileManager` + func listContents(of url: URL) throws -> [URL] { + try fileManager.contentsOfDirectory( + at: url, + includingPropertiesForKeys: [.nameKey, .isDirectoryKey], + options: recursive ? [] : .skipsSubdirectoryDescendants + ) + .sorted(by: sorting) + } +} + +protocol SortedDirectoryListing { + func listContents(of url: URL) throws -> [URL] +} + +// MARK: Extensions +extension URL { + /// asumes that URLs are from the same directory for efficiency reasons + static let areInIncreasingOrderByFilename: (URL, URL) throws -> Bool = { lhs, rhs in + guard + let lhsName = try lhs.resourceValues(forKeys: [.nameKey, .isDirectoryKey]).name, + let rhsName = try rhs.resourceValues(forKeys: [.nameKey, .isDirectoryKey]).name else { + throw URLError(URLError.badURL) + } + + guard let strcmp = FSCompactBlockRepository.filenameComparison(lhsName, rhsName) else { throw URLError(URLError.badURL) } + + return strcmp < 0 + } +} + +extension FileManager: SortedDirectoryListing { + func listContents(of url: URL) throws -> [URL] { + try contentsOfDirectory( + at: url, + includingPropertiesForKeys: [.nameKey, .isDirectoryKey], + options: .skipsSubdirectoryDescendants + ) + } +} + +extension String { + /// a sorting filter to be used on URL or path arrays from `FileManager`. + /// - Parameter height: the height of the block we want to filter from + /// - Parameter descriptor: The block descriptor that corresponds to the filename + /// convention of the FsBlockDb + /// - Returns if the height from this filename is greater that the one received by parameter + /// - Throws `CompactBlockRepositoryError.malformedCacheEntry` if this String + /// can't be parsed by the given `ZcashCompactBlockDescriptor` + func filterGreaterThan(_ height: BlockHeight, with descriptor: ZcashCompactBlockDescriptor) throws -> Bool { + guard let blockHeight = descriptor.height(self) else { + throw CompactBlockRepositoryError.malformedCacheEntry("couldn't retrieve filename from file \(self)") + } + + return blockHeight > height + } +} diff --git a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockScanning.swift b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockScanning.swift index 99a270ea6..95cf91741 100644 --- a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockScanning.swift +++ b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockScanning.swift @@ -44,7 +44,7 @@ extension CompactBlockProcessor { let scanStartTime = Date() guard self.rustBackend.scanBlocks( - dbCache: config.cacheDb, + fsBlockDbRoot: config.fsBlockCacheRoot, dbData: config.dataDb, limit: batchSize, networkType: config.network.networkType @@ -74,7 +74,6 @@ extension CompactBlockProcessor { batchSize: Int(batchSize), operation: .scanBlocks ) - let heightCount = lastScannedHeight - previousScannedHeight let seconds = scanFinishTime.timeIntervalSinceReferenceDate - scanStartTime.timeIntervalSinceReferenceDate LoggerProxy.debug("Scanned \(heightCount) blocks in \(seconds) seconds") @@ -116,7 +115,7 @@ extension CompactBlockProcessor { ) throws { try Task.checkCancellation() - guard rustBackend.scanBlocks(dbCache: cacheDb, dbData: dataDb, limit: limit, networkType: networkType) else { + guard rustBackend.scanBlocks(fsBlockDbRoot: cacheDb, dbData: dataDb, limit: limit, networkType: networkType) else { let error: Error = rustBackend.lastError() ?? CompactBlockProcessorError.unknown LoggerProxy.debug("block scanning failed with error: \(String(describing: error))") throw error diff --git a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift index 685361893..a25206a44 100644 --- a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift +++ b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift @@ -18,7 +18,14 @@ extension CompactBlockProcessor { try Task.checkCancellation() let startTime = Date() - let result = rustBackend.validateCombinedChain(dbCache: config.cacheDb, dbData: config.dataDb, networkType: config.network.networkType) + + let result = rustBackend.validateCombinedChain( + fsBlockDbRoot: config.fsBlockCacheRoot, + dbData: config.dataDb, + networkType: config.network.networkType, + limit: 0 + ) + let finishTime = Date() SDKMetrics.shared.pushProgressReport( diff --git a/Sources/ZcashLightClientKit/Block/Utils/InternalSyncProgress.swift b/Sources/ZcashLightClientKit/Block/Utils/InternalSyncProgress.swift index b589475c3..6fb606c4a 100644 --- a/Sources/ZcashLightClientKit/Block/Utils/InternalSyncProgress.swift +++ b/Sources/ZcashLightClientKit/Block/Utils/InternalSyncProgress.swift @@ -66,7 +66,7 @@ actor InternalSyncProgress { } /// `InternalSyncProgress` is from now on used to track which block were already downloaded. Previous versions of the SDK were using cache DB to - /// track this. Because of this we have to migrace height of latest downloaded block from cache DB to here. + /// track this. Because of this we have to migrate height of latest downloaded block from cache DB to here. /// /// - Parameter latestDownloadedBlockHeight: Height of latest downloaded block from cache DB. func migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB latestDownloadedBlockHeight: BlockHeight) { diff --git a/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift b/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift index 1abe5fd8b..9f5b8fdfb 100644 --- a/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift +++ b/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift @@ -41,6 +41,17 @@ extension NetworkType { } } +extension NetworkType { + public var chainName: String { + switch self { + case .mainnet: + return "main" + case .testnet: + return "test" + } + } +} + public enum ZcashNetworkBuilder { public static func network(for networkType: NetworkType) -> ZcashNetwork { switch networkType { @@ -111,6 +122,9 @@ public enum ZcashSDK { /// Default Name for LibRustZcash data.db public static var defaultDataDbName = "data.db" + /// Default Name for Compact Block file system based db + public static var defaultFsCacheName = "fs_cache" + /// Default Name for Compact Block caches db public static var defaultCacheDbName = "caches.db" @@ -137,7 +151,10 @@ public protocol NetworkConstants { /// Default Name for LibRustZcash data.db static var defaultDataDbName: String { get } + static var defaultFsBlockDbRootName: String { get } + /// Default Name for Compact Block caches db + @available(*, deprecated, message: "use this name to clean up the sqlite compact block database") static var defaultCacheDbName: String { get } /// Default name for pending transactions db @@ -172,9 +189,7 @@ public extension NetworkConstants { } } -public class ZcashSDKMainnetConstants: NetworkConstants { - private init() {} - +public enum ZcashSDKMainnetConstants: NetworkConstants { /// The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks /// prior to this height, at all. public static var saplingActivationHeight: BlockHeight = 419_200 @@ -182,6 +197,8 @@ public class ZcashSDKMainnetConstants: NetworkConstants { /// Default Name for LibRustZcash data.db public static var defaultDataDbName = "data.db" + public static var defaultFsBlockDbRootName = "fs_cache" + /// Default Name for Compact Block caches db public static var defaultCacheDbName = "caches.db" @@ -193,9 +210,7 @@ public class ZcashSDKMainnetConstants: NetworkConstants { public static var feeChangeHeight: BlockHeight = 1_077_550 } -public class ZcashSDKTestnetConstants: NetworkConstants { - private init() {} - +public enum ZcashSDKTestnetConstants: NetworkConstants { /// The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks /// prior to this height, at all. public static var saplingActivationHeight: BlockHeight = 280_000 @@ -206,6 +221,8 @@ public class ZcashSDKTestnetConstants: NetworkConstants { /// Default Name for Compact Block caches db public static var defaultCacheDbName = "caches.db" + public static var defaultFsBlockDbRootName = "fs_cache" + /// Default name for pending transactions db public static var defaultPendingDbName = "pending.db" diff --git a/Sources/ZcashLightClientKit/DAO/CompactBlockDAO.swift b/Sources/ZcashLightClientKit/DAO/CompactBlockDAO.swift deleted file mode 100644 index 72eb934d0..000000000 --- a/Sources/ZcashLightClientKit/DAO/CompactBlockDAO.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// CompactBlockDAO.swift -// ZcashLightClientKit -// -// Created by Francisco Gindre on 10/16/19. -// Copyright © 2019 Electric Coin Company. All rights reserved. -// - -import Foundation - -protocol CompactBlockDAO { - func closeDBConnection() - - func createTable() throws - - func insert(_ block: ZcashCompactBlock) throws - - func insert(_ blocks: [ZcashCompactBlock]) throws - - /** - Query the latest block height, returns -1 if no block is stored - */ - func latestBlockHeight() throws -> BlockHeight - - func rewind(to height: BlockHeight) throws -} diff --git a/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift b/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift index 7a1d83f81..39fa7e627 100644 --- a/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift +++ b/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift @@ -111,13 +111,13 @@ struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable { switch (toAddress, toInternalAccount) { case let (.some(address), nil): guard let recipient = Recipient.forEncodedAddress(encoded: address) else { - throw StorageError.malformedEntity(fields: ["toAddress"]) + throw DatabaseStorageError.malformedEntity(fields: ["toAddress"]) } self.recipient = .address(recipient.0) case let (nil, .some(accountId)): self.recipient = .internalAccount(UInt32(accountId)) default: - throw StorageError.malformedEntity(fields: ["toAddress", "toInternalAccount"]) + throw DatabaseStorageError.malformedEntity(fields: ["toAddress", "toInternalAccount"]) } self.accountIndex = try container.decode(Int.self, forKey: .accountIndex) @@ -248,7 +248,7 @@ class PendingTransactionSQLDAO: PendingTransactionRepository { func update(_ transaction: PendingTransactionEntity) throws { let pendingTx = transaction as? PendingTransaction ?? PendingTransaction.from(entity: transaction) guard let id = pendingTx.id else { - throw StorageError.malformedEntity(fields: ["id"]) + throw DatabaseStorageError.malformedEntity(fields: ["id"]) } let updatedRows = try dbProvider.connection().run(Self.table.filter(TableColumns.id == id).update(pendingTx)) @@ -259,13 +259,13 @@ class PendingTransactionSQLDAO: PendingTransactionRepository { func delete(_ transaction: PendingTransactionEntity) throws { guard let id = transaction.id else { - throw StorageError.malformedEntity(fields: ["id"]) + throw DatabaseStorageError.malformedEntity(fields: ["id"]) } do { try dbProvider.connection().run(Self.table.filter(TableColumns.id == id).delete()) } catch { - throw StorageError.updateFailed + throw DatabaseStorageError.updateFailed } } @@ -273,7 +273,7 @@ class PendingTransactionSQLDAO: PendingTransactionRepository { var pendingTx = transaction as? PendingTransaction ?? PendingTransaction.from(entity: transaction) pendingTx.cancelled = 1 guard let txId = pendingTx.id else { - throw StorageError.malformedEntity(fields: ["id"]) + throw DatabaseStorageError.malformedEntity(fields: ["id"]) } try dbProvider.connection().run(Self.table.filter(TableColumns.id == txId).update(pendingTx)) @@ -289,7 +289,7 @@ class PendingTransactionSQLDAO: PendingTransactionRepository { return pendingTx } catch { - throw StorageError.operationFailed + throw DatabaseStorageError.operationFailed } } diff --git a/Sources/ZcashLightClientKit/DAO/TransactionDao.swift b/Sources/ZcashLightClientKit/DAO/TransactionDao.swift index 149f93592..102554a92 100644 --- a/Sources/ZcashLightClientKit/DAO/TransactionDao.swift +++ b/Sources/ZcashLightClientKit/DAO/TransactionDao.swift @@ -96,16 +96,18 @@ class TransactionSQLDAO: TransactionRepository { let transactionIndex = transaction.index, let transactionBlockTime = transaction.blockTime else { throw TransactionRepositoryError.transactionMissingRequiredFields } - + let query = transactionsView - .order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc) + .order( + (ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc + ) .filter( - Int64(transactionBlockTime) > ZcashTransaction.Overview.Column.blockTime && - transactionIndex > ZcashTransaction.Overview.Column.index + Int64(transactionBlockTime) > ZcashTransaction.Overview.Column.blockTime + && transactionIndex > ZcashTransaction.Overview.Column.index ) .filterQueryFor(kind: kind) .limit(limit) - + return try execute(query) { try ZcashTransaction.Overview(row: $0) } } diff --git a/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift b/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift index 0acfc153f..b2599ba32 100644 --- a/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift +++ b/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift @@ -116,7 +116,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository { } } } catch { - throw StorageError.transactionFailed(underlyingError: error) + throw DatabaseStorageError.transactionFailed(underlyingError: error) } } @@ -125,13 +125,13 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository { do { try dbProvider.connection().run(table.filter(TableColumns.address == tAddr).delete()) } catch { - throw StorageError.operationFailed + throw DatabaseStorageError.operationFailed } } else { do { try dbProvider.connection().run(table.delete()) } catch { - throw StorageError.operationFailed + throw DatabaseStorageError.operationFailed } } } @@ -171,7 +171,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository { total: Zatoshi(Int64(total)) ) } catch { - throw StorageError.operationFailed + throw DatabaseStorageError.operationFailed } } } diff --git a/Sources/ZcashLightClientKit/Entity/AccountEntity.swift b/Sources/ZcashLightClientKit/Entity/AccountEntity.swift index a5331ad06..81a14d0b8 100644 --- a/Sources/ZcashLightClientKit/Entity/AccountEntity.swift +++ b/Sources/ZcashLightClientKit/Entity/AccountEntity.swift @@ -75,12 +75,12 @@ class AccountSQDAO: AccountRepository { func update(_ account: AccountEntity) throws { guard let acc = account as? Account else { - throw StorageError.updateFailed + throw DatabaseStorageError.updateFailed } let updatedRows = try dbProvider.connection().run(table.filter(TableColums.account == acc.account).update(acc)) if updatedRows == 0 { LoggerProxy.error("attempted to update pending transactions but no rows were updated") - throw StorageError.updateFailed + throw DatabaseStorageError.updateFailed } } } diff --git a/Sources/ZcashLightClientKit/Entity/CompactBlockEntity.swift b/Sources/ZcashLightClientKit/Entity/CompactBlockEntity.swift deleted file mode 100644 index 7a0225094..000000000 --- a/Sources/ZcashLightClientKit/Entity/CompactBlockEntity.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// CompactBlockEntity.swift -// ZcashLightClientKit -// -// Created by Francisco Gindre on 11/16/19. -// - -import Foundation - -protocol CompactBlockEntity { - var height: BlockHeight { get set } - var data: Data { get set } -} diff --git a/Sources/ZcashLightClientKit/Initializer.swift b/Sources/ZcashLightClientKit/Initializer.swift index a26910699..86307cf5b 100644 --- a/Sources/ZcashLightClientKit/Initializer.swift +++ b/Sources/ZcashLightClientKit/Initializer.swift @@ -13,7 +13,7 @@ Wrapper for the Rust backend. This class basically represents all the Rust-walle capabilities and the supporting data required to exercise those abilities. */ public enum InitializerError: Error { - case cacheDbInitFailed(Error) + case fsCacheInitFailed(Error) case dataDbInitFailed(Error) case accountInitFailed(Error) case invalidViewingKey(key: String) @@ -70,7 +70,7 @@ public class Initializer { private(set) var endpoint: LightWalletEndpoint private var lowerBoundHeight: BlockHeight - private(set) var cacheDbURL: URL + private(set) var fsBlockDbRoot: URL private(set) var dataDbURL: URL private(set) var pendingDbURL: URL private(set) var spendParamsURL: URL @@ -78,7 +78,7 @@ public class Initializer { private(set) var lightWalletService: LightWalletService private(set) var transactionRepository: TransactionRepository private(set) var accountRepository: AccountRepository - private(set) var storage: CompactBlockStorage + private(set) var storage: CompactBlockRepository private(set) var blockDownloaderService: BlockDownloaderService private(set) var network: ZcashNetwork private(set) public var viewingKeys: [UnifiedFullViewingKey] @@ -86,18 +86,80 @@ public class Initializer { /// and the checkpoints available on this SDK private(set) public var walletBirthday: BlockHeight - /** - Constructs the Initializer - - Parameters: - - cacheDbURL: location of the compact blocks cache db - - dataDbURL: Location of the data db - - pendingDbURL: location of the pending transactions database - - endpoint: the endpoint representing the lightwalletd instance you want to point to - - spendParamsURL: location of the spend parameters - - outputParamsURL: location of the output parameters - */ + /// The purpose of this to migrate from cacheDb to fsBlockDb + private var cacheDbURL: URL? + + /// Constructs the Initializer + /// - Parameters: + /// - fsBlockDbRoot: location of the compact blocks cache + /// - dataDbURL: Location of the data db + /// - pendingDbURL: location of the pending transactions database + /// - endpoint: the endpoint representing the lightwalletd instance you want to point to + /// - spendParamsURL: location of the spend parameters + /// - outputParamsURL: location of the output parameters convenience public init ( - cacheDbURL: URL, + fsBlockDbRoot: URL, + dataDbURL: URL, + pendingDbURL: URL, + endpoint: LightWalletEndpoint, + network: ZcashNetwork, + spendParamsURL: URL, + outputParamsURL: URL, + viewingKeys: [UnifiedFullViewingKey], + walletBirthday: BlockHeight, + alias: String = "", + loggerProxy: Logger? = nil + ) { + self.init( + rustBackend: ZcashRustBackend.self, + lowerBoundHeight: walletBirthday, + network: network, + cacheDbURL: nil, + fsBlockDbRoot: fsBlockDbRoot, + dataDbURL: dataDbURL, + pendingDbURL: pendingDbURL, + endpoint: endpoint, + service: LightWalletGRPCService(endpoint: endpoint), + repository: TransactionRepositoryBuilder.build(dataDbURL: dataDbURL), + accountRepository: AccountRepositoryBuilder.build( + dataDbURL: dataDbURL, + readOnly: true, + caching: true + ), + storage: FSCompactBlockRepository( + cacheDirectory: fsBlockDbRoot, + metadataStore: .live( + fsBlockDbRoot: fsBlockDbRoot, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ), + spendParamsURL: spendParamsURL, + outputParamsURL: outputParamsURL, + viewingKeys: viewingKeys, + walletBirthday: walletBirthday, + alias: alias, + loggerProxy: loggerProxy + ) + } + + /// Constructs the Initializer and migrates an old cacheDb to the new file system block cache if + /// a `cacheDbURL` is provided. + /// - Parameters: + /// - cacheDbURL: previous location of the cacheDb. Use this constru + /// - fsBlockDbRoot: location of the compact blocks cache + /// - dataDbURL: Location of the data db + /// - pendingDbURL: location of the pending transactions database + /// - endpoint: the endpoint representing the lightwalletd instance you want to point to + /// - spendParamsURL: location of the spend parameters + /// - outputParamsURL: location of the output parameters + /// + /// - note: If you don't know what a cacheDb is and you are adopting + /// this SDK for the first time then you just need to invoke `convenience init(fsBlockDbRoot: URL, dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, network: ZcashNetwork, spendParamsURL: URL, outputParamsURL: URL, viewingKeys: [UnifiedFullViewingKey], walletBirthday: BlockHeight, alias: String = "", loggerProxy: Logger? = nil)` instead + convenience public init ( + cacheDbURL: URL?, + fsBlockDbRoot: URL, dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, @@ -111,14 +173,12 @@ public class Initializer { ) { let lwdService = LightWalletGRPCService(endpoint: endpoint) - let storageConnectionProvider = SimpleConnectionProvider(path: cacheDbURL.absoluteString, readonly: false) - let storage = CompactBlockStorage(connectionProvider: storageConnectionProvider) - self.init( rustBackend: ZcashRustBackend.self, lowerBoundHeight: walletBirthday, network: network, cacheDbURL: cacheDbURL, + fsBlockDbRoot: fsBlockDbRoot, dataDbURL: dataDbURL, pendingDbURL: pendingDbURL, endpoint: endpoint, @@ -129,7 +189,15 @@ public class Initializer { readOnly: true, caching: true ), - storage: storage, + storage: FSCompactBlockRepository( + cacheDirectory: fsBlockDbRoot, + metadataStore: .live( + fsBlockDbRoot: fsBlockDbRoot, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ), spendParamsURL: spendParamsURL, outputParamsURL: outputParamsURL, viewingKeys: viewingKeys, @@ -138,7 +206,7 @@ public class Initializer { loggerProxy: loggerProxy ) } - + /** Internal for dependency injection purposes */ @@ -146,14 +214,15 @@ public class Initializer { rustBackend: ZcashRustBackendWelding.Type, lowerBoundHeight: BlockHeight, network: ZcashNetwork, - cacheDbURL: URL, + cacheDbURL: URL?, + fsBlockDbRoot: URL, dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, service: LightWalletService, repository: TransactionRepository, accountRepository: AccountRepository, - storage: CompactBlockStorage, + storage: CompactBlockRepository, spendParamsURL: URL, outputParamsURL: URL, viewingKeys: [UnifiedFullViewingKey], @@ -162,9 +231,10 @@ public class Initializer { loggerProxy: Logger? = nil ) { logger = loggerProxy + self.cacheDbURL = cacheDbURL self.rustBackend = rustBackend self.lowerBoundHeight = lowerBoundHeight - self.cacheDbURL = cacheDbURL + self.fsBlockDbRoot = fsBlockDbRoot self.dataDbURL = dataDbURL self.pendingDbURL = pendingDbURL self.endpoint = endpoint @@ -196,9 +266,9 @@ public class Initializer { /// `InitializerError.accountInitFailed` if the account table can't be initialized. public func initialize(with seed: [UInt8]?) throws -> InitializationResult { do { - try storage.createTable() + try storage.create() } catch { - throw InitializerError.cacheDbInitFailed(error) + throw InitializerError.fsCacheInitFailed(error) } do { @@ -225,10 +295,6 @@ public class Initializer { throw InitializerError.dataDbInitFailed(error) } self.walletBirthday = checkpoint.height - - let lastDownloaded = (try? blockDownloaderService.storage.latestHeight()) ?? walletBirthday - // resume from last downloaded block - lowerBoundHeight = max(walletBirthday, lastDownloaded) do { try rustBackend.initAccountsTable( @@ -245,13 +311,15 @@ public class Initializer { } let migrationManager = MigrationManager( - cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path), networkType: self.network.networkType ) try migrationManager.performMigration() + // resume from last downloaded block + lowerBoundHeight = max(walletBirthday, storage.latestHeight()) + return .success } @@ -323,7 +391,7 @@ enum CompactBlockProcessorBuilder { static func buildProcessor( configuration: CompactBlockProcessor.Configuration, service: LightWalletService, - storage: CompactBlockStorage, + storage: CompactBlockRepository, transactionRepository: TransactionRepository, accountRepository: AccountRepository, backend: ZcashRustBackendWelding.Type @@ -344,12 +412,12 @@ extension InitializerError: LocalizedError { switch self { case .invalidViewingKey: return "The provided viewing key is invalid" - case .cacheDbInitFailed(let error): - return "cacheDb Init failed with error: \(error.localizedDescription)" case .dataDbInitFailed(let error): return "dataDb init failed with error: \(error.localizedDescription)" case .accountInitFailed(let error): return "account table init failed with error: \(error.localizedDescription)" + case .fsCacheInitFailed(let error): + return "Compact Block Cache failed to initialize with error: \(error.localizedDescription)" } } } diff --git a/Sources/ZcashLightClientKit/Initializer.swift.orig b/Sources/ZcashLightClientKit/Initializer.swift.orig new file mode 100644 index 000000000..249baa4ba --- /dev/null +++ b/Sources/ZcashLightClientKit/Initializer.swift.orig @@ -0,0 +1,456 @@ +// +// Initializer.swift +// ZcashLightClientKit +// +// Created by Francisco Gindre on 13/09/2019. +// Copyright © 2019 Electric Coin Company. All rights reserved. +// + +import Foundation + +/** +Wrapper for the Rust backend. This class basically represents all the Rust-wallet +capabilities and the supporting data required to exercise those abilities. +*/ +public enum InitializerError: Error { + case fsCacheInitFailed(Error) + case dataDbInitFailed(Error) + case accountInitFailed(Error) + case invalidViewingKey(key: String) +} + +/** +Represents a lightwallet instance endpoint to connect to +*/ +public struct LightWalletEndpoint { + public var host: String + public var port: Int + public var secure: Bool + public var singleCallTimeoutInMillis: Int64 + public var streamingCallTimeoutInMillis: Int64 + + /** + initializes a LightWalletEndpoint + - Parameters: + - address: a String containing the host address + - port: string with the port of the host address + - secure: true if connecting through TLS. Default value is true + - singleCallTimeoutInMillis: timeout for single calls in Milliseconds. Default 30 seconds + - streamingCallTimeoutInMillis: timeout for streaming calls in Milliseconds. Default 100 seconds + */ + public init( + address: String, + port: Int, + secure: Bool = true, + singleCallTimeoutInMillis: Int64 = 30000, + streamingCallTimeoutInMillis: Int64 = 100000 + ) { + self.host = address + self.port = port + self.secure = secure + self.singleCallTimeoutInMillis = singleCallTimeoutInMillis + self.streamingCallTimeoutInMillis = streamingCallTimeoutInMillis + } +} + +/** +Wrapper for all the Rust backend functionality that does not involve processing blocks. This +class initializes the Rust backend and the supporting data required to exercise those abilities. +The [cash.z.wallet.sdk.block.CompactBlockProcessor] handles all the remaining Rust backend +functionality, related to processing blocks. +*/ +public class Initializer { + public enum InitializationResult { + case success + case seedRequired + } + + private(set) var rustBackend: ZcashRustBackendWelding.Type + private(set) var alias: String + private(set) var endpoint: LightWalletEndpoint + + private var lowerBoundHeight: BlockHeight + private(set) var fsBlockDbRoot: URL + private(set) var dataDbURL: URL + private(set) var pendingDbURL: URL + private(set) var spendParamsURL: URL + private(set) var outputParamsURL: URL + private(set) var lightWalletService: LightWalletService + private(set) var transactionRepository: TransactionRepository + private(set) var accountRepository: AccountRepository +<<<<<<< HEAD + private(set) var storage: CompactBlockStorage + private(set) var blockDownloaderService: BlockDownloaderService +======= + private(set) var storage: CompactBlockRepository + private(set) var downloader: CompactBlockDownloader +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache) + private(set) var network: ZcashNetwork + private(set) public var viewingKeys: [UnifiedFullViewingKey] + /// The effective birthday of the wallet based on the height provided when initializing + /// and the checkpoints available on this SDK + private(set) public var walletBirthday: BlockHeight + + /// The purpose of this to migrate from cacheDb to fsBlockDb + private var cacheDbURL: URL? + + /// Constructs the Initializer + /// - Parameters: + /// - fsBlockDbRoot: location of the compact blocks cache + /// - dataDbURL: Location of the data db + /// - pendingDbURL: location of the pending transactions database + /// - endpoint: the endpoint representing the lightwalletd instance you want to point to + /// - spendParamsURL: location of the spend parameters + /// - outputParamsURL: location of the output parameters + convenience public init ( + fsBlockDbRoot: URL, + dataDbURL: URL, + pendingDbURL: URL, + endpoint: LightWalletEndpoint, + network: ZcashNetwork, + spendParamsURL: URL, + outputParamsURL: URL, + viewingKeys: [UnifiedFullViewingKey], + walletBirthday: BlockHeight, + alias: String = "", + loggerProxy: Logger? = nil + ) { + self.init( + rustBackend: ZcashRustBackend.self, + lowerBoundHeight: walletBirthday, + network: network, + cacheDbURL: nil, + fsBlockDbRoot: fsBlockDbRoot, + dataDbURL: dataDbURL, + pendingDbURL: pendingDbURL, + endpoint: endpoint, + service: LightWalletGRPCService(endpoint: endpoint), + repository: TransactionRepositoryBuilder.build(dataDbURL: dataDbURL), + accountRepository: AccountRepositoryBuilder.build( + dataDbURL: dataDbURL, + readOnly: true, + caching: true + ), + storage: FSCompactBlockRepository( + cacheDirectory: fsBlockDbRoot, + metadataStore: .live( + fsBlockDbRoot: fsBlockDbRoot, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ), + spendParamsURL: spendParamsURL, + outputParamsURL: outputParamsURL, + viewingKeys: viewingKeys, + walletBirthday: walletBirthday, + alias: alias, + loggerProxy: loggerProxy + ) + } + + /// Constructs the Initializer and migrates an old cacheDb to the new file system block cache if + /// a `cacheDbURL` is provided. + /// - Parameters: + /// - cacheDbURL: previous location of the cacheDb. Use this constru + /// - fsBlockDbRoot: location of the compact blocks cache + /// - dataDbURL: Location of the data db + /// - pendingDbURL: location of the pending transactions database + /// - endpoint: the endpoint representing the lightwalletd instance you want to point to + /// - spendParamsURL: location of the spend parameters + /// - outputParamsURL: location of the output parameters + /// + /// - note: If you don't know what a cacheDb is and you are adopting + /// this SDK for the first time then you just need to invoke `convenience init(fsBlockDbRoot: URL, dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, network: ZcashNetwork, spendParamsURL: URL, outputParamsURL: URL, viewingKeys: [UnifiedFullViewingKey], walletBirthday: BlockHeight, alias: String = "", loggerProxy: Logger? = nil)` instead + convenience public init ( + cacheDbURL: URL?, + fsBlockDbRoot: URL, + dataDbURL: URL, + pendingDbURL: URL, + endpoint: LightWalletEndpoint, + network: ZcashNetwork, + spendParamsURL: URL, + outputParamsURL: URL, + viewingKeys: [UnifiedFullViewingKey], + walletBirthday: BlockHeight, + alias: String = "", + loggerProxy: Logger? = nil + ) { + let lwdService = LightWalletGRPCService(endpoint: endpoint) + +<<<<<<< HEAD + let storageConnectionProvider = SimpleConnectionProvider(path: cacheDbURL.absoluteString, readonly: false) + let storage = CompactBlockStorage(connectionProvider: storageConnectionProvider) + +======= +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache) + self.init( + rustBackend: ZcashRustBackend.self, + lowerBoundHeight: walletBirthday, + network: network, + cacheDbURL: cacheDbURL, + fsBlockDbRoot: fsBlockDbRoot, + dataDbURL: dataDbURL, + pendingDbURL: pendingDbURL, + endpoint: endpoint, + service: lwdService, + repository: TransactionRepositoryBuilder.build(dataDbURL: dataDbURL), + accountRepository: AccountRepositoryBuilder.build( + dataDbURL: dataDbURL, + readOnly: true, + caching: true + ), +<<<<<<< HEAD + storage: storage, +======= + storage: FSCompactBlockRepository( + cacheDirectory: fsBlockDbRoot, + metadataStore: .live( + fsBlockDbRoot: fsBlockDbRoot, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ), +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache) + spendParamsURL: spendParamsURL, + outputParamsURL: outputParamsURL, + viewingKeys: viewingKeys, + walletBirthday: walletBirthday, + alias: alias, + loggerProxy: loggerProxy + ) + } + + /** + Internal for dependency injection purposes + */ + init( + rustBackend: ZcashRustBackendWelding.Type, + lowerBoundHeight: BlockHeight, + network: ZcashNetwork, + cacheDbURL: URL?, + fsBlockDbRoot: URL, + dataDbURL: URL, + pendingDbURL: URL, + endpoint: LightWalletEndpoint, + service: LightWalletService, + repository: TransactionRepository, + accountRepository: AccountRepository, + storage: CompactBlockRepository, + spendParamsURL: URL, + outputParamsURL: URL, + viewingKeys: [UnifiedFullViewingKey], + walletBirthday: BlockHeight, + alias: String = "", + loggerProxy: Logger? = nil + ) { + logger = loggerProxy + self.cacheDbURL = cacheDbURL + self.rustBackend = rustBackend + self.lowerBoundHeight = lowerBoundHeight + self.fsBlockDbRoot = fsBlockDbRoot + self.dataDbURL = dataDbURL + self.pendingDbURL = pendingDbURL + self.endpoint = endpoint + self.spendParamsURL = spendParamsURL + self.outputParamsURL = outputParamsURL + self.alias = alias + self.lightWalletService = service + self.transactionRepository = repository + self.accountRepository = accountRepository + self.storage = storage + self.blockDownloaderService = BlockDownloaderServiceImpl(service: service, storage: storage) + self.viewingKeys = viewingKeys + self.walletBirthday = walletBirthday + self.network = network + } + + /// Initialize the wallet. The ZIP-32 seed bytes can optionally be passed to perform + /// database migrations. most of the times the seed won't be needed. If they do and are + /// not provided this will fail with `InitializationResult.seedRequired`. It could + /// be the case that this method is invoked by a wallet that does not contain the seed phrase + /// and is view-only, or by a wallet that does have the seed but the process does not have the + /// consent of the OS to fetch the keys from the secure storage, like on background tasks. + /// + /// 'cache.db' and 'data.db' files are created by this function (if they + /// do not already exist). These files can be given a prefix for scenarios where multiple wallets + /// + /// - Parameter seed: ZIP-32 Seed bytes for the wallet that will be initialized + /// - Throws: `InitializerError.dataDbInitFailed` if the creation of the dataDb fails + /// `InitializerError.accountInitFailed` if the account table can't be initialized. + public func initialize(with seed: [UInt8]?) throws -> InitializationResult { + do { + try storage.create() + } catch { + throw InitializerError.fsCacheInitFailed(error) + } + + do { + if case .seedRequired = try rustBackend.initDataDb(dbData: dataDbURL, seed: seed, networkType: network.networkType) { + return .seedRequired + } + } catch { + throw InitializerError.dataDbInitFailed(error) + } + + let checkpoint = Checkpoint.birthday(with: self.walletBirthday, network: network) + do { + try rustBackend.initBlocksTable( + dbData: dataDbURL, + height: Int32(checkpoint.height), + hash: checkpoint.hash, + time: checkpoint.time, + saplingTree: checkpoint.saplingTree, + networkType: network.networkType + ) + } catch RustWeldingError.dataDbNotEmpty { + // this is fine + } catch { + throw InitializerError.dataDbInitFailed(error) + } + self.walletBirthday = checkpoint.height +<<<<<<< HEAD + + let lastDownloaded = (try? blockDownloaderService.storage.latestHeight()) ?? walletBirthday + // resume from last downloaded block + lowerBoundHeight = max(walletBirthday, lastDownloaded) +======= +>>>>>>> f1f7b11 (- [#679] Implementation of the File-system based block cache) + + do { + try rustBackend.initAccountsTable( + dbData: dataDbURL, + ufvks: viewingKeys, + networkType: network.networkType + ) + } catch RustWeldingError.dataDbNotEmpty { + // this is fine + } catch RustWeldingError.malformedStringInput { + throw RustWeldingError.malformedStringInput + } catch { + throw InitializerError.accountInitFailed(error) + } + + let migrationManager = MigrationManager( + pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path), + networkType: self.network.networkType + ) + + try migrationManager.performMigration() + + // resume from last downloaded block + lowerBoundHeight = max(walletBirthday, downloader.lastDownloadedBlockHeight()) + + return .success + } + + /// get (unverified) balance from the given account index + /// - Parameter account: the index of the account + @available(*, deprecated, message: "This function will be removed soon. Use the function returning `Zatoshi` instead") + public func getBalance(account index: Int = 0) -> Int64 { + guard let balance = try? rustBackend.getBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType) else { return 0 } + + return balance + } + + /// get (unverified) balance from the given account index + /// - Parameter account: the index of the account + /// - Returns: balance in `Zatoshi` + public func getBalance(account index: Int = 0) -> Zatoshi { + guard let balance = try? rustBackend.getBalance( + dbData: dataDbURL, + account: Int32(index), + networkType: network.networkType + ) else { + return .zero + } + + return Zatoshi(balance) + } + + /// get verified balance from the given account index + /// - Parameter account: the index of the account + @available(*, deprecated, message: "This function will be removed soon. Use the one returning `Zatoshi` instead") + public func getVerifiedBalance(account index: Int = 0) -> Int64 { + guard let balance = try? rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType) else { + return 0 + } + + return balance + } + + /// get verified balance from the given account index + /// - Parameter account: the index of the account + /// - Returns: balance in `Zatoshi` + public func getVerifiedBalance(account index: Int = 0) -> Zatoshi { + guard let balance = try? rustBackend.getVerifiedBalance( + dbData: dataDbURL, + account: Int32(index), + networkType: network.networkType + ) else { return .zero } + + return Zatoshi(balance) + } + + /** + checks if the provided address is a valid sapling address + */ + public func isValidSaplingAddress(_ address: String) -> Bool { + rustBackend.isValidSaplingAddress(address, networkType: network.networkType) + } + + /** + checks if the provided address is a transparent zAddress + */ + public func isValidTransparentAddress(_ address: String) -> Bool { + rustBackend.isValidTransparentAddress(address, networkType: network.networkType) + } +} + +enum CompactBlockProcessorBuilder { + // swiftlint:disable:next function_parameter_count + static func buildProcessor( + configuration: CompactBlockProcessor.Configuration, + service: LightWalletService, + storage: CompactBlockRepository, + transactionRepository: TransactionRepository, + accountRepository: AccountRepository, + backend: ZcashRustBackendWelding.Type + ) -> CompactBlockProcessor { + return CompactBlockProcessor( + service: service, + storage: storage, + backend: backend, + config: configuration, + repository: transactionRepository, + accountRepository: accountRepository + ) + } +} + +extension InitializerError: LocalizedError { + public var errorDescription: String? { + switch self { + case .invalidViewingKey: + return "The provided viewing key is invalid" + case .dataDbInitFailed(let error): + return "dataDb init failed with error: \(error.localizedDescription)" + case .accountInitFailed(let error): + return "account table init failed with error: \(error.localizedDescription)" + case .fsCacheInitFailed(let error): + return "Compact Block Cache failed to initialize with error: \(error.localizedDescription)" + } + } +} + +/// Synchronous helpers that support clients that don't use structured concurrency yet +extension Initializer { + func getCurrentAddress(accountIndex: Int) -> UnifiedAddress? { + try? self.rustBackend.getCurrentAddress( + dbData: self.dataDbURL, + account: Int32(accountIndex), + networkType: self.network.networkType + ) + } +} diff --git a/Sources/ZcashLightClientKit/Providers/ResourceProvider.swift b/Sources/ZcashLightClientKit/Providers/ResourceProvider.swift index 981091b4a..96813653f 100644 --- a/Sources/ZcashLightClientKit/Providers/ResourceProvider.swift +++ b/Sources/ZcashLightClientKit/Providers/ResourceProvider.swift @@ -13,6 +13,9 @@ public enum ResourceProviderError: Error { } public protocol ResourceProvider { var dataDbURL: URL { get } + var fsCacheURL: URL { get } + + @available(*, deprecated, message: "you should use this to delete the existing cache.db sqlite.") var cacheDbURL: URL { get } } /** @@ -30,6 +33,16 @@ public struct DefaultResourceProvider: ResourceProvider { return URL(fileURLWithPath: "file://\(constants.defaultDataDbName)") } } + + public var fsCacheURL: URL { + let constants = network.constants + do { + let path = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) + return path.appendingPathComponent(constants.defaultFsBlockDbRootName) + } catch { + return URL(fileURLWithPath: "file://\(constants.defaultFsBlockDbRootName)") + } + } public var cacheDbURL: URL { let constants = network.constants diff --git a/Sources/ZcashLightClientKit/Repository/CompactBlockRepository.swift b/Sources/ZcashLightClientKit/Repository/CompactBlockRepository.swift index 360f9b113..a11420d90 100644 --- a/Sources/ZcashLightClientKit/Repository/CompactBlockRepository.swift +++ b/Sources/ZcashLightClientKit/Repository/CompactBlockRepository.swift @@ -11,24 +11,67 @@ import Foundation /** A Zcash compact block to store on cache DB */ -public struct ZcashCompactBlock: CompactBlockEntity { +public struct ZcashCompactBlock { + struct Meta { + var hash: Data + var time: UInt32 + var saplingOutputs: UInt32 + var orchardOutputs: UInt32 + } + public var height: BlockHeight public var data: Data + + var meta: Meta +} + +extension ZcashCompactBlock: Encodable { + enum CodingKeys: CodingKey { + case height + case data + case meta + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(data, forKey: .data) + try container.encode(height, forKey: .height) + } } -extension ZcashCompactBlock: Encodable { } +enum CompactBlockRepositoryError: Error, Equatable { + /// cache is empty + case cacheEmpty + /// It was expected to have some cache entry but upon retrieval + /// it couldn't be parsed. + case malformedCacheEntry(String) + /// There was a failure when attempting to clear the repository + case cacheClearFailed + /// There was a problem storing a given block + case failedToWriteBlock(ZcashCompactBlock) + /// there was a problem saving the metadata of the cached blocks + /// the underlying error is returned as the associated value + case failedToWriteMetadata + /// failed to initialize cache with no underlying error + case failedToInitializeCache + /// failed to rewind the repository to given blockheight + case failedToRewind(BlockHeight) +} protocol CompactBlockRepository { + /// Creates the underlying repository + func create() throws + /** Gets the height of the highest block that is currently stored. */ - func latestHeight() throws -> BlockHeight + func latestHeight() -> BlockHeight /** Gets the highest block that is currently stored. Non-Blocking */ - func latestHeightAsync() async throws -> BlockHeight + func latestHeightAsync() async -> BlockHeight /** Write the given blocks to this store, which may be anything from an in-memory cache to a DB. @@ -50,7 +93,7 @@ protocol CompactBlockRepository { func rewind(to height: BlockHeight) throws /** - Remove every block above and including the given height. + Removes every block above and including the given height. After this operation, the data store will look the same as one that has not yet stored the given block height. Meaning, if max height is 100 block and rewindTo(50) is called, then the highest block remaining will be 49. @@ -59,5 +102,27 @@ protocol CompactBlockRepository { */ func rewindAsync(to height: BlockHeight) async throws - func closeDBConnection() + /// Clears the repository + func clear() async throws +} + +extension CompactBlockRepositoryError: LocalizedError { + public var errorDescription: String? { + switch self { + case .failedToWriteBlock(let block): + return "Failed to write compact block of height \(block.height)." + case .malformedCacheEntry(let message): + return "Malformed cache entry: \(message)." + case .cacheEmpty: + return "Cache is Empty." + case .cacheClearFailed: + return "Cache could not be cleared." + case .failedToWriteMetadata: + return "Failed to write metadata to FsBlockDb." + case .failedToInitializeCache: + return "Failed to initialize metadata FsBlockDb." + case .failedToRewind(let height): + return "Failed to rewind FsBlockDb to height \(height)." + } + } } diff --git a/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift b/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift index 5469d6d6b..1661bb17e 100644 --- a/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift +++ b/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift @@ -510,7 +510,86 @@ class ZcashRustBackend: ZcashRustBackendWelding { throw lastError() ?? .genericError(message: "`initAccountsTable` failed with unknown error") } } - + + static func initBlockMetadataDb(fsBlockDbRoot: URL) throws -> Bool { + let blockDb = fsBlockDbRoot.osPathStr() + + let result = zcashlc_init_block_metadata_db(blockDb.0, blockDb.1) + + guard result else { + throw lastError() ?? .genericError(message: "`initAccountsTable` failed with unknown error") + } + + return result + } + + static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashCompactBlock]) throws -> Bool { + var ffiBlockMetaVec: [FFIBlockMeta] = [] + + for block in blocks { + let meta = block.meta + let hashPtr = UnsafeMutablePointer.allocate(capacity: meta.hash.count) + + let contiguousHashBytes = ContiguousArray(meta.hash.bytes) + + let result: Void? = contiguousHashBytes.withContiguousStorageIfAvailable { hashBytesPtr in + // swiftlint:disable:next force_unwrapping + hashPtr.initialize(from: hashBytesPtr.baseAddress!, count: hashBytesPtr.count) + } + + guard result != nil else { + defer { + hashPtr.deallocate() + ffiBlockMetaVec.deallocateElements() + } + return false + } + + ffiBlockMetaVec.append( + FFIBlockMeta( + height: UInt32(block.height), + block_hash_ptr: hashPtr, + block_hash_ptr_len: UInt(contiguousHashBytes.count), + block_time: meta.time, + sapling_outputs_count: meta.saplingOutputs, + orchard_actions_count: meta.orchardOutputs + ) + ) + } + + var contiguousFFIBlocks = ContiguousArray(ffiBlockMetaVec) + + let len = UInt(contiguousFFIBlocks.count) + + let fsBlocks = UnsafeMutablePointer.allocate(capacity: 1) + + defer { ffiBlockMetaVec.deallocateElements() } + + let result = try contiguousFFIBlocks.withContiguousMutableStorageIfAvailable { ptr in + var meta = FFIBlocksMeta() + meta.ptr = ptr.baseAddress + meta.len = len + + fsBlocks.initialize(to: meta) + + let fsDb = fsBlockDbRoot.osPathStr() + + let res = zcashlc_write_block_metadata(fsDb.0, fsDb.1, fsBlocks) + + guard res else { + throw lastError() ?? RustWeldingError.genericError(message: "failed to write block metadata") + } + + return res + } + + guard let value = result else { + return false + } + + return value + } + // swiftlint:disable function_parameter_count static func initBlocksTable( dbData: URL, @@ -543,6 +622,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { } } + static func latestCachedBlockHeight(fsBlockDbRoot: URL) -> BlockHeight { + let fsBlockDb = fsBlockDbRoot.osPathStr() + + return BlockHeight(zcashlc_latest_cached_block_height(fsBlockDb.0, fsBlockDb.1)) + } + static func listTransparentReceivers( dbData: URL, account: Int32, @@ -599,28 +684,37 @@ class ZcashRustBackend: ZcashRustBackendWelding { return true } - static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 { - let dbCache = dbCache.osStr() + static func validateCombinedChain(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType, limit: UInt32 = 0) -> Int32 { + let dbCache = fsBlockDbRoot.osPathStr() let dbData = dbData.osStr() - return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkType.networkId) + return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkType.networkId, limit) } static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool { let dbData = dbData.osStr() return zcashlc_rewind_to_height(dbData.0, dbData.1, height, networkType.networkId) } - - static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32 = 0, networkType: NetworkType) -> Bool { - let dbCache = dbCache.osStr() + + static func rewindCacheToHeight( + fsBlockDbRoot: URL, + height: Int32 + ) -> Bool { + let fsBlockCache = fsBlockDbRoot.osPathStr() + + return zcashlc_rewind_fs_block_cache_to_height(fsBlockCache.0, fsBlockCache.1, height) + } + + static func scanBlocks(fsBlockDbRoot: URL, dbData: URL, limit: UInt32 = 0, networkType: NetworkType) -> Bool { + let dbCache = fsBlockDbRoot.osPathStr() let dbData = dbData.osStr() return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit, networkType.networkId) != 0 } static func shieldFunds( - dbCache: URL, dbData: URL, usk: UnifiedSpendingKey, memo: MemoBytes?, + shieldingThreshold: Zatoshi, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType @@ -634,11 +728,13 @@ class ZcashRustBackend: ZcashRustBackendWelding { uskBuffer.baseAddress, UInt(usk.bytes.count), memo?.bytes, + UInt64(shieldingThreshold.amount), spendParamsPath, UInt(spendParamsPath.lengthOfBytes(using: .utf8)), outputParamsPath, UInt(outputParamsPath.lengthOfBytes(using: .utf8)), networkType.networkId, + minimumConfirmations, useZIP317Fees ) } @@ -730,6 +826,12 @@ private extension URL { let path = self.absoluteString return (path, UInt(path.lengthOfBytes(using: .utf8))) } + + /// use when the rust ffi needs to make filesystem operations + func osPathStr() -> (String, UInt) { + let path = self.path + return (path, UInt(path.lengthOfBytes(using: .utf8))) + } } extension String { @@ -767,7 +869,6 @@ extension UnsafeMutablePointer where Pointee == UInt8 { return bytes } } - extension RustWeldingError: LocalizedError { var errorDescription: String? { switch self { @@ -794,3 +895,11 @@ extension RustWeldingError: LocalizedError { } } } + +extension Array where Element == FFIBlockMeta { + func deallocateElements() { + self.forEach { element in + element.block_hash_ptr.deallocate() + } + } +} diff --git a/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift b/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift index 60314f95c..18ad3ae50 100644 --- a/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift +++ b/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift @@ -46,10 +46,9 @@ protocol ZcashRustBackendWelding { /// By convention, wallets should only allow a new account to be generated after funds /// have been received by the currently-available account (in order to enable /// automated account recovery). - /// - Parameters: - /// - dbData: location of the data db - /// - seed: byte array of the zip32 seed - /// - networkType: network type of this key + /// - parameter dbData: location of the data db + /// - parameter seed: byte array of the zip32 seed + /// - parameter networkType: network type of this key /// - Returns: The `UnifiedSpendingKey` structs for the number of accounts created /// static func createAccount( @@ -81,12 +80,10 @@ protocol ZcashRustBackendWelding { /// Scans a transaction for any information that can be decrypted by the accounts in the /// wallet, and saves it to the wallet. - /// - /// - Parameters: - /// - dbData: location of the data db file - /// - tx: the transaction to decrypt - /// - minedHeight: height on which this transaction was mined. this is used to fetch the consensus branch ID. - /// - networkType: network type of this key + /// - parameter dbData: location of the data db file + /// - parameter tx: the transaction to decrypt + /// - parameter minedHeight: height on which this transaction was mined. this is used to fetch the consensus branch ID. + /// - parameter networkType: network type of this key /// returns false if fails to decrypt. static func decryptAndStoreTransaction( dbData: URL, @@ -108,10 +105,9 @@ protocol ZcashRustBackendWelding { ) throws -> UnifiedSpendingKey /// get the (unverified) balance from the given account - /// - Parameters: - /// - dbData: location of the data db - /// - account: index of the given account - /// - networkType: network type of this key + /// - parameter dbData: location of the data db + /// - parameter account: index of the given account + /// - parameter networkType: network type of this key static func getBalance( dbData: URL, account: Int32, @@ -119,10 +115,9 @@ protocol ZcashRustBackendWelding { ) throws -> Int64 /// Returns the most-recently-generated unified payment address for the specified account. - /// - Parameters: - /// - dbData: location of the data db - /// - account: index of the given account - /// - networkType: network type of this key + /// - parameter dbData: location of the data db + /// - parameter account: index of the given account + /// - parameter networkType: network type of this key static func getCurrentAddress( dbData: URL, account: Int32, @@ -136,10 +131,9 @@ protocol ZcashRustBackendWelding { /// of sapling witnesses older than 100 blocks. So in order to reconstruct the witness /// tree that allows to spend notes from the given wallet the rewind can't be more than /// 100 blocks or back to the oldest unspent note that this wallet contains. - /// - Parameters: - /// - dbData: location of the data db file - /// - height: height you would like to rewind to. - /// - networkType: network type of this key] + /// - parameter dbData: location of the data db file + /// - parameter height: height you would like to rewind to. + /// - parameter networkType: network type of this key] /// - Returns: the blockheight of the nearest rewind height. /// static func getNearestRewindHeight( @@ -149,10 +143,9 @@ protocol ZcashRustBackendWelding { ) -> Int32 /// Returns a newly-generated unified payment address for the specified account, with the next available diversifier. - /// - Parameters: - /// - dbData: location of the data db - /// - account: index of the given account - /// - networkType: network type of this key + /// - parameter dbData: location of the data db + /// - parameter account: index of the given account + /// - parameter networkType: network type of this key static func getNextAvailableAddress( dbData: URL, account: Int32, @@ -160,10 +153,9 @@ protocol ZcashRustBackendWelding { ) throws -> UnifiedAddress /// get received memo from note - /// - Parameters: - /// - dbData: location of the data db file - /// - idNote: note_id of note where the memo is located - /// - networkType: network type of this key + /// - parameter dbData: location of the data db file + /// - parameter idNote: note_id of note where the memo is located + /// - parameter networkType: network type of this key @available(*, deprecated, message: "This function will be deprecated soon. Use `getReceivedMemo(dbData:idNote:networkType)` instead") static func getReceivedMemoAsUTF8( dbData: URL, @@ -172,10 +164,9 @@ protocol ZcashRustBackendWelding { ) -> String? /// get received memo from note - /// - Parameters: - /// - dbData: location of the data db file - /// - idNote: note_id of note where the memo is located - /// - networkType: network type of this key + /// - parameter dbData: location of the data db file + /// - parameter idNote: note_id of note where the memo is located + /// - parameter networkType: network type of this key static func getReceivedMemo( dbData: URL, idNote: Int64, @@ -189,10 +180,9 @@ protocol ZcashRustBackendWelding { static func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress? /// get sent memo from note - /// - Parameters: - /// - dbData: location of the data db file - /// - idNote: note_id of note where the memo is located - /// - networkType: network type of this key + /// - parameter dbData: location of the data db file + /// - parameter idNote: note_id of note where the memo is located + /// - parameter networkType: network type of this key @available(*, deprecated, message: "This function will be deprecated soon. Use `getSentMemo(dbData:idNote:networkType)` instead") static func getSentMemoAsUTF8( dbData: URL, @@ -201,10 +191,9 @@ protocol ZcashRustBackendWelding { ) -> String? /// get sent memo from note - /// - Parameters: - /// - dbData: location of the data db file - /// - idNote: note_id of note where the memo is located - /// - networkType: network type of this key + /// - parameter dbData: location of the data db file + /// - parameter idNote: note_id of note where the memo is located + /// - parameter networkType: network type of this key /// - Returns: a `Memo` if any static func getSentMemo( dbData: URL, @@ -213,10 +202,9 @@ protocol ZcashRustBackendWelding { ) -> Memo? /// Get the verified cached transparent balance for the given address - /// - Parameters: - /// - dbData: location of the data db file - /// - account; the account index to query - /// - networkType: network type of this key + /// - parameter dbData: location of the data db file + /// - parameter account; the account index to query + /// - parameter networkType: network type of this key static func getTransparentBalance( dbData: URL, account: Int32, @@ -224,7 +212,7 @@ protocol ZcashRustBackendWelding { ) throws -> Int64 /// Returns the transparent receiver within the given Unified Address, if any. - // - Parameter uAddr: a `UnifiedAddress` + /// - parameter uAddr: a `UnifiedAddress` /// - Returns a `TransparentAddress` if any /// - Throws `receiverNotFound` when the receiver is not found. `invalidUnifiedAddress` if the UA provided is not valid static func getTransparentReceiver(for uAddr: UnifiedAddress) throws -> TransparentAddress? @@ -308,14 +296,13 @@ protocol ZcashRustBackendWelding { /// - Throws: Error when there's another problem not related to validity of the string in question static func isValidUnifiedFullViewingKey(_ ufvk: String, networkType: NetworkType) -> Bool - /// initialize the blocks table from a given checkpoint (height, hash, time, saplingTree and networkType) - /// - Parameters: - /// - dbData: location of the data db - /// - height: represents the block height of the given checkpoint - /// - hash: hash of the merkle tree - /// - time: in milliseconds from reference - /// - saplingTree: hash of the sapling tree - /// - networkType: `NetworkType` signaling testnet or mainnet + /// initialize the blocks table from a given checkpoint (heigh, hash, time, saplingTree and networkType) + /// - parameter dbData: location of the data db + /// - parameter height: represents the block height of the given checkpoint + /// - parameter hash: hash of the merkle tree + /// - parameter time: in milliseconds from reference + /// - parameter saplingTree: hash of the sapling tree + /// - parameter networkType: `NetworkType` signaling testnet or mainnet static func initBlocksTable( dbData: URL, height: Int32, @@ -327,10 +314,9 @@ protocol ZcashRustBackendWelding { /// Returns a list of the transparent receivers for the diversified unified addresses that have /// been allocated for the provided account. - /// - Parameters: - /// - dbData: location of the data db - /// - account: index of the given account - /// - networkType: the network type + /// - parameter dbData: location of the data db + /// - parameter account: index of the given account + /// - parameter networkType: the network type static func listTransparentReceivers( dbData: URL, account: Int32, @@ -338,10 +324,9 @@ protocol ZcashRustBackendWelding { ) throws -> [TransparentAddress] /// get the verified balance from the given account - /// - Parameters: - /// - dbData: location of the data db - /// - account: index of the given account - /// - networkType: the network type + /// - parameter dbData: location of the data db + /// - parameter account: index of the given account + /// - parameter networkType: the network type static func getVerifiedBalance( dbData: URL, account: Int32, @@ -349,10 +334,9 @@ protocol ZcashRustBackendWelding { ) throws -> Int64 /// Get the verified cached transparent balance for the given account - /// - Parameters: - /// - dbData: location of the data db - /// - account: account index to query the balance for. - /// - networkType: the network type + /// - parameter dbData: location of the data db + /// - parameter account: account index to query the balance for. + /// - parameter networkType: the network type static func getVerifiedTransparentBalance( dbData: URL, account: Int32, @@ -365,10 +349,12 @@ protocol ZcashRustBackendWelding { /// cache database is more likely to be accurate than the previously-scanned information. /// This follows from the design (and trust) assumption that the `lightwalletd` server /// provides accurate block information as of the time it was requested. - /// - Parameters: - /// - dbCache: location of the cache db file - /// - dbData: location of the data db file - /// - networkType: the network type + /// - parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is. + /// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename + /// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions. + /// - parameter dbData: location of the data db file + /// - parameter networkType: the network type + /// - parameter limit: a limit to validate a fixed number of blocks instead of the whole cache. /// - Returns: /// - `-1` if the combined chain is valid. /// - `upper_bound` if the combined chain is invalid. @@ -376,22 +362,33 @@ protocol ZcashRustBackendWelding { /// - `0` if there was an error during validation unrelated to chain validity. /// - Important: This function does not mutate either of the databases. static func validateCombinedChain( - dbCache: URL, + fsBlockDbRoot: URL, dbData: URL, - networkType: NetworkType + networkType: NetworkType, + limit: UInt32 ) -> Int32 /// Resets the state of the database to only contain block and transaction information up to the given height. clears up all derived data as well - /// - Parameters: - /// - dbData: location of the data db file - /// - height: height to rewind to. DON'T PASS ARBITRARY HEIGHT. Use getNearestRewindHeight when unsure - /// - networkType: the network type + /// - parameter dbData: `URL` pointing to the filesystem root directory where the fsBlock cache is. + /// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename + /// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions. + /// - parameter height: height to rewind to. static func rewindToHeight( dbData: URL, height: Int32, networkType: NetworkType ) -> Bool - + + /// Resets the state of the FsBlock database to only contain block and transaction information up to the given height. + /// - Note: this does not delete the files. Only rolls back the database. + /// - parameter fsBlockDbRoot: location of the data db file + /// - parameter height: height to rewind to. DON'T PASS ARBITRARY HEIGHT. Use getNearestRewindHeight when unsure + /// - parameter networkType: the network type + static func rewindCacheToHeight( + fsBlockDbRoot: URL, + height: Int32 + ) -> Bool + /// Scans new blocks added to the cache for any transactions received by the tracked /// accounts. /// This function pays attention only to cached blocks with heights greater than the @@ -404,29 +401,29 @@ protocol ZcashRustBackendWelding { /// Scanned blocks are required to be height-sequential. If a block is missing from the /// cache, an error will be signalled. /// - /// - Parameters: - /// - dbCache: location of the compact block cache db - /// - dbData: location of the data db file - /// - limit: scan up to limit blocks. pass 0 to set no limit. - /// - networkType: the network type + /// - parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is. + /// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename + /// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions. + /// - parameter dbData: location of the data db sqlite file + /// - parameter limit: scan up to limit blocks. pass 0 to set no limit. + /// - parameter networkType: the network type /// returns false if fails to scan. static func scanBlocks( - dbCache: URL, + fsBlockDbRoot: URL, dbData: URL, limit: UInt32, networkType: NetworkType ) -> Bool - /// puts a UTXO into the data db database - /// - Parameters: - /// - dbData: location of the data db file - /// - txid: the txid bytes for the UTXO - /// - index: the index of the UTXO - /// - script: the script of the UTXO - /// - value: the value of the UTXO - /// - height: the mined height for the UTXO - /// - networkType: the network type - /// - Returns: true if the operation succeeded or false otherwise + /// Upserts a UTXO into the data db database + /// - parameter dbData: location of the data db file + /// - parameter txid: the txid bytes for the UTXO + /// - parameter index: the index of the UTXO + /// - parameter script: the script of the UTXO + /// - parameter value: the value of the UTXO + /// - parameter height: the mined height for the UTXO + /// - parameter networkType: the network type + /// - Returns: true if the operation succeded or false otherwise static func putUnspentTransparentOutput( dbData: URL, txid: [UInt8], @@ -437,8 +434,7 @@ protocol ZcashRustBackendWelding { networkType: NetworkType ) throws -> Bool - /// Creates a transaction to shield all found UTXOs in cache db for the account the provided `UnifiedSpendingKey` has spend authority for. - /// - Parameter dbCache: URL for the Cache DB + /// Creates a transaction to shield all found UTXOs in data db for the account the provided `UnifiedSpendingKey` has spend authority for. /// - Parameter dbData: URL for the Data DB /// - Parameter usk: `UnifiedSpendingKey` that spend transparent funds and where the funds will be shielded to. /// - Parameter memo: the `Memo` for this transaction @@ -446,10 +442,10 @@ protocol ZcashRustBackendWelding { /// - Parameter outputParamsPath: path escaped String for the filesystem locations where the output parameters are located /// - Parameter networkType: the network type static func shieldFunds( - dbCache: URL, dbData: URL, usk: UnifiedSpendingKey, memo: MemoBytes?, + shieldingThreshold: Zatoshi, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType @@ -478,4 +474,28 @@ protocol ZcashRustBackendWelding { from spendingKey: UnifiedSpendingKey, networkType: NetworkType ) throws -> UnifiedFullViewingKey + + /// initializes Filesystem based block cache + /// - Parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is. + /// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename + /// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions. + /// - returns `true` when successful, `false` when fails but no throwing information was found + /// - throws `RustWeldingError` when fails to initialize + static func initBlockMetadataDb(fsBlockDbRoot: URL) throws -> Bool + + /// Write compact block metadata to a database known to the Rust layer + /// - Parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is. + /// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename + /// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions. + /// - Parameter blocks: The `ZcashCompactBlock`s that are going to be marked as stored by the + /// metadata Db. + /// - Returns `true` if the operation was successful, `false` otherwise. + static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashCompactBlock]) throws -> Bool + + /// Gets the latest block height stored in the filesystem based cache. + /// - Parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is. + /// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename + /// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions. + /// - Returns `BlockHeight` of the latest cached block or `.empty` if no blocks are stored. + static func latestCachedBlockHeight(fsBlockDbRoot: URL) -> BlockHeight } diff --git a/Sources/ZcashLightClientKit/Service/Model/ZcashCompactBlock.swift b/Sources/ZcashLightClientKit/Service/Model/ZcashCompactBlock.swift index 20ecbf8b8..10dc66a88 100644 --- a/Sources/ZcashLightClientKit/Service/Model/ZcashCompactBlock.swift +++ b/Sources/ZcashLightClientKit/Service/Model/ZcashCompactBlock.swift @@ -25,9 +25,28 @@ extension ZcashCompactBlock { init(compactBlock: CompactBlock) { self.height = Int(compactBlock.height) self.data = (try? compactBlock.serializedData()) ?? Data() + let outputs = compactBlock.outputCount + self.meta = Meta( + hash: compactBlock.hash, + time: compactBlock.time, + saplingOutputs: outputs.0, + orchardOutputs: outputs.1 + ) } } +extension CompactBlock { + /// O(n) sum of all CompactTx sapling outputs and Orchard Actions + /// - Returns: a tuple (SaplingOutputs, OrchardActions) + var outputCount: (UInt32, UInt32) { + vtx.compactMap { compactTx -> (UInt32, UInt32) in + (UInt32(compactTx.outputs.count), UInt32(compactTx.actions.count)) + } + .reduce((0, 0)) { partialResult, txOutputActionPair in + (partialResult.0 + txOutputActionPair.0, partialResult.1 + txOutputActionPair.1) + } + } +} extension ZcashCompactBlock: Equatable { public static func == (lhs: Self, rhs: Self) -> Bool { if lhs.height != rhs.height { diff --git a/Sources/ZcashLightClientKit/Synchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer.swift index 264223b2f..3b1509bba 100644 --- a/Sources/ZcashLightClientKit/Synchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer.swift @@ -119,7 +119,8 @@ public protocol Synchronizer { /// - Parameter memo: the optional memo to include as part of the transaction. func shieldFunds( spendingKey: UnifiedSpendingKey, - memo: Memo + memo: Memo, + shieldingThreshold: Zatoshi ) async throws -> PendingTransactionEntity /// Attempts to cancel a transaction that is about to be sent. Typically, cancellation is only diff --git a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift index 00171cf34..8cd56f47a 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift @@ -473,7 +473,8 @@ public class SDKSynchronizer: Synchronizer { public func shieldFunds( spendingKey: UnifiedSpendingKey, - memo: Memo + memo: Memo, + shieldingThreshold: Zatoshi ) async throws -> PendingTransactionEntity { // let's see if there are funds to shield let accountIndex = Int(spendingKey.account) @@ -495,6 +496,7 @@ public class SDKSynchronizer: Synchronizer { // TODO: [#487] Task will be removed when this method is changed to async, issue 487, https://github.com/zcash/ZcashLightClientKit/issues/487 let transaction = try await transactionManager.encodeShieldingTransaction( spendingKey: spendingKey, + shieldingThreshold: shieldingThreshold, pendingTransaction: shieldingSpend ) @@ -592,6 +594,7 @@ public class SDKSynchronizer: Synchronizer { let stream = initializer.lightWalletService.fetchUTXOs(for: address, height: network.constants.saplingActivationHeight) do { + // swiftlint:disable:next array_constructor var utxos: [UnspentTransactionOutputEntity] = [] for try await transactionEntity in stream { utxos.append(transactionEntity) @@ -683,7 +686,7 @@ public class SDKSynchronizer: Synchronizer { transactionManager.closeDBConnection() transactionRepository.closeDBConnection() - try? FileManager.default.removeItem(at: initializer.cacheDbURL) + try? FileManager.default.removeItem(at: initializer.fsBlockDbRoot) try? FileManager.default.removeItem(at: initializer.pendingDbURL) try? FileManager.default.removeItem(at: initializer.dataDbURL) diff --git a/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift b/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift index 9ef43a159..56e35259e 100644 --- a/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift +++ b/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift @@ -67,11 +67,13 @@ class PersistentTransactionManager: OutboundTransactionManager { func encodeShieldingTransaction( spendingKey: UnifiedSpendingKey, + shieldingThreshold: Zatoshi, pendingTransaction: PendingTransactionEntity ) async throws -> PendingTransactionEntity { do { let transaction = try await self.encoder.createShieldingTransaction( spendingKey: spendingKey, + shieldingThreshold: shieldingThreshold, memoBytes: try pendingTransaction.memo?.intoMemoBytes(), from: pendingTransaction.accountIndex ) @@ -86,7 +88,7 @@ class PersistentTransactionManager: OutboundTransactionManager { try self.repository.update(pending) return pending - } catch StorageError.updateFailed { + } catch DatabaseStorageError.updateFailed { throw TransactionManagerError.updateFailed(pendingTransaction) } catch MemoBytes.Errors.invalidUTF8 { throw TransactionManagerError.shieldingEncodingFailed(pendingTransaction, reason: "Memo contains invalid UTF-8 bytes") @@ -135,7 +137,7 @@ class PersistentTransactionManager: OutboundTransactionManager { try self.repository.update(pending) return pending - } catch StorageError.updateFailed { + } catch DatabaseStorageError.updateFailed { throw TransactionManagerError.updateFailed(pendingTransaction) } catch { do { diff --git a/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift b/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift index a23dd8602..120ab02f5 100644 --- a/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift +++ b/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift @@ -38,7 +38,7 @@ protocol TransactionEncoder { ) async throws -> ZcashTransaction.Overview /** - Creates a transaction that will attempt to shield transparent funds that are present on the cacheDB .throwing an exception whenever things are missing. When the provided wallet implementation doesn't throw an exception, we wrap the issue into a descriptive exception ourselves (rather than using double-bangs for things). + Creates a transaction that will attempt to shield transparent funds that are present on the blocks cache .throwing an exception whenever things are missing. When the provided wallet implementation doesn't throw an exception, we wrap the issue into a descriptive exception ourselves (rather than using double-bangs for things). Blocking - Parameters: @@ -49,6 +49,7 @@ protocol TransactionEncoder { */ func createShieldingTransaction( spendingKey: UnifiedSpendingKey, + shieldingThreshold: Zatoshi, memoBytes: MemoBytes?, from accountIndex: Int ) async throws -> ZcashTransaction.Overview diff --git a/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift b/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift index 27588f6b8..13f8854b4 100644 --- a/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift +++ b/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift @@ -23,6 +23,7 @@ protocol OutboundTransactionManager { func encodeShieldingTransaction( spendingKey: UnifiedSpendingKey, + shieldingThreshold: Zatoshi, pendingTransaction: PendingTransactionEntity ) async throws -> PendingTransactionEntity diff --git a/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift b/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift index 95a4ab8cb..210064cb8 100644 --- a/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift +++ b/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift @@ -14,13 +14,13 @@ class WalletTransactionEncoder: TransactionEncoder { private var outputParamsURL: URL private var spendParamsURL: URL private var dataDbURL: URL - private var cacheDbURL: URL + private var fsBlockDbRoot: URL private var networkType: NetworkType init( rust: ZcashRustBackendWelding.Type, dataDb: URL, - cacheDb: URL, + fsBlockDbRoot: URL, repository: TransactionRepository, outputParams: URL, spendParams: URL, @@ -28,7 +28,7 @@ class WalletTransactionEncoder: TransactionEncoder { ) { self.rustBackend = rust self.dataDbURL = dataDb - self.cacheDbURL = cacheDb + self.fsBlockDbRoot = fsBlockDbRoot self.repository = repository self.outputParamsURL = outputParams self.spendParamsURL = spendParams @@ -39,7 +39,7 @@ class WalletTransactionEncoder: TransactionEncoder { self.init( rust: initializer.rustBackend, dataDb: initializer.dataDbURL, - cacheDb: initializer.cacheDbURL, + fsBlockDbRoot: initializer.fsBlockDbRoot, repository: initializer.transactionRepository, outputParams: initializer.outputParamsURL, spendParams: initializer.spendParamsURL, @@ -101,11 +101,13 @@ class WalletTransactionEncoder: TransactionEncoder { func createShieldingTransaction( spendingKey: UnifiedSpendingKey, + shieldingThreshold: Zatoshi, memoBytes: MemoBytes?, from accountIndex: Int ) async throws -> ZcashTransaction.Overview { let txId = try createShieldingSpend( spendingKey: spendingKey, + shieldingThreshold: shieldingThreshold, memo: memoBytes, accountIndex: accountIndex ) @@ -120,6 +122,7 @@ class WalletTransactionEncoder: TransactionEncoder { func createShieldingSpend( spendingKey: UnifiedSpendingKey, + shieldingThreshold: Zatoshi, memo: MemoBytes?, accountIndex: Int ) throws -> Int { @@ -128,10 +131,10 @@ class WalletTransactionEncoder: TransactionEncoder { } let txId = rustBackend.shieldFunds( - dbCache: self.cacheDbURL, dbData: self.dataDbURL, usk: spendingKey, memo: memo, + shieldingThreshold: shieldingThreshold, spendParamsPath: self.spendParamsURL.path, outputParamsPath: self.outputParamsURL.path, networkType: networkType diff --git a/Tests/DarksideTests/AdvancedReOrgTests.swift b/Tests/DarksideTests/AdvancedReOrgTests.swift index ff17de3a6..d702f3c45 100644 --- a/Tests/DarksideTests/AdvancedReOrgTests.swift +++ b/Tests/DarksideTests/AdvancedReOrgTests.swift @@ -46,7 +46,7 @@ class AdvancedReOrgTests: XCTestCase { try super.tearDownWithError() NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } @@ -1276,7 +1276,7 @@ class AdvancedReOrgTests: XCTestCase { try coordinator.applyStaged(blockheight: birthday + fullSyncLength) - sleep(10) + sleep(20) let firstSyncExpectation = XCTestExpectation(description: "first sync") @@ -1304,7 +1304,7 @@ class AdvancedReOrgTests: XCTestCase { } } - wait(for: [firstSyncExpectation], timeout: 500) + wait(for: [firstSyncExpectation], timeout: 600) let latestScannedHeight = coordinator.synchronizer.latestScannedHeight XCTAssertEqual(latestScannedHeight, birthday + fullSyncLength) diff --git a/Tests/DarksideTests/BlockDownloaderTests.swift b/Tests/DarksideTests/BlockDownloaderTests.swift index b3a027995..d783d5d0f 100644 --- a/Tests/DarksideTests/BlockDownloaderTests.swift +++ b/Tests/DarksideTests/BlockDownloaderTests.swift @@ -10,22 +10,32 @@ import XCTest @testable import TestUtils @testable import ZcashLightClientKit -// swiftlint:disable implicitly_unwrapped_optional force_cast force_try +// swiftlint:disable implicitly_unwrapped_optional force_cast class BlockDownloaderTests: XCTestCase { let branchID = "2bb40e60" let chainName = "main" + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + let testFileManager = FileManager() var darksideWalletService: DarksideWalletService! var downloader: BlockDownloaderService! var service: LightWalletService! var storage: CompactBlockRepository! - var cacheDB = try! __cacheDbURL() var network = DarksideWalletDNetwork() override func setUpWithError() throws { try super.setUpWithError() service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) - storage = try! TestDbBuilder.diskCompactBlockStorage(at: cacheDB) + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live(fsBlockDbRoot: testTempDirectory, rustBackend: ZcashRustBackend.self), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) downloader = BlockDownloaderServiceImpl(service: service, storage: storage) darksideWalletService = DarksideWalletService(service: service as! LightWalletGRPCService) @@ -37,10 +47,10 @@ class BlockDownloaderTests: XCTestCase { override func tearDown() { super.tearDown() + try? testFileManager.removeItem(at: testTempDirectory) service = nil storage = nil downloader = nil - try? FileManager.default.removeItem(at: cacheDB) } func testSmallDownloadAsync() async { @@ -52,7 +62,7 @@ class BlockDownloaderTests: XCTestCase { try await downloader.downloadBlockRange(range) // check what was 'stored' - let latestHeight = try await self.storage.latestHeightAsync() + let latestHeight = await self.storage.latestHeightAsync() XCTAssertEqual(latestHeight, upperRange) let resultHeight = try await self.downloader.lastDownloadedBlockHeightAsync() diff --git a/Tests/DarksideTests/DarksideSanityCheckTests.swift b/Tests/DarksideTests/DarksideSanityCheckTests.swift index 40232743d..bed355db6 100644 --- a/Tests/DarksideTests/DarksideSanityCheckTests.swift +++ b/Tests/DarksideTests/DarksideSanityCheckTests.swift @@ -46,7 +46,7 @@ class DarksideSanityCheckTests: XCTestCase { override func tearDownWithError() throws { try super.tearDownWithError() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/DarksideTests/InternalStateConsistencyTests.swift b/Tests/DarksideTests/InternalStateConsistencyTests.swift new file mode 100644 index 000000000..7ea5aabba --- /dev/null +++ b/Tests/DarksideTests/InternalStateConsistencyTests.swift @@ -0,0 +1,155 @@ +// +// InternalStateConsistencyTests.swift +// DarksideTests +// +// Created by Francisco Gindre on 1/26/23. +// +// swiftlint:disable:all implicitly_unwrapped_optional force_unwrapping +import XCTest +@testable import TestUtils +@testable import ZcashLightClientKit +final class InternalStateConsistencyTests: XCTestCase { + // TODO: [#715] Parameterize this from environment, https://github.com/zcash/ZcashLightClientKit/issues/715 + // swiftlint:disable:next line_length + var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" + + // TODO: [#715] Parameterize this from environment, https://github.com/zcash/ZcashLightClientKit/issues/715 + let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" + + let sendAmount = Zatoshi(1000) + var birthday: BlockHeight = 663150 + let defaultLatestHeight: BlockHeight = 663175 + var coordinator: TestCoordinator! + var firstSyncExpectation = XCTestExpectation(description: "first sync expectation") + var expectedReorgHeight: BlockHeight = 665188 + var expectedRewindHeight: BlockHeight = 665188 + var reorgExpectation = XCTestExpectation(description: "reorg") + let branchID = "2bb40e60" + let chainName = "main" + let network = DarksideWalletDNetwork() + var firstSyncContinuation: CheckedContinuation<(), Error>? + override func setUpWithError() throws { + try super.setUpWithError() + self.coordinator = try TestCoordinator( + seed: seedPhrase, + walletBirthday: birthday + 50, // don't use an exact birthday, users never do. + channelProvider: ChannelProvider(), + network: network + ) + try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + NotificationCenter.default.removeObserver(self) + try coordinator.stop() + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) + try? FileManager.default.removeItem(at: coordinator.databases.dataDB) + try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) + } + + func testInternalStateIsConsistentWhenMigrating() async throws { + NotificationCenter.default.addObserver(self, selector: #selector(self.processorStopped(_:)), name: .blockProcessorStopped, object: nil) + + let fullSyncLength = 1000 + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength) + + sleep(1) + + // apply the height + try coordinator.applyStaged(blockheight: 664150) + + sleep(1) + + try await withCheckedThrowingContinuation { continuation in + do { + try coordinator.sync( + completion: { _ in + XCTFail("shouldn't have completed") + continuation.resume() + }, error: { error in + guard let error else { + XCTFail("there was an unknown error") + continuation.resume() + return + } + continuation.resume(throwing: error) + } + ) + + self.firstSyncContinuation = continuation + DispatchQueue.global().asyncAfter(deadline: .now() + 1) { + self.coordinator.synchronizer.stop() + } + } catch { + continuation.resume(throwing: error) + } + } + + wait(for: [firstSyncExpectation], timeout: 2) + + XCTAssertFalse(coordinator.synchronizer.status.isSyncing) + XCTAssertEqual(coordinator.synchronizer.status, .stopped) + + let internalSyncState = InternalSyncProgress(storage: UserDefaults.standard) + + let latestDownloadHeight = await internalSyncState.latestDownloadedBlockHeight + let latestScanHeight = try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight() + let dbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedDarksideCacheDb()!) + try dbHandle.setUp() + + if latestDownloadHeight > latestScanHeight { + try await coordinator.synchronizer.blockProcessor.migrateCacheDb(dbHandle.readWriteDb) + + let afterMigrationDownloadedHeight = await internalSyncState.latestDownloadedBlockHeight + + XCTAssertNotEqual(latestDownloadHeight, afterMigrationDownloadedHeight) + XCTAssertEqual(latestScanHeight, afterMigrationDownloadedHeight) + } else { + try await coordinator.synchronizer.blockProcessor.migrateCacheDb(dbHandle.readWriteDb) + + let afterMigrationDownloadedHeight = await internalSyncState.latestDownloadedBlockHeight + + XCTAssertEqual(latestDownloadHeight, afterMigrationDownloadedHeight) + XCTAssertEqual(latestScanHeight, afterMigrationDownloadedHeight) + } + + XCTAssertFalse(FileManager.default.isReadableFile(atPath: dbHandle.readWriteDb.path)) + + // clear to simulate a clean slate from the FsBlockDb + try await coordinator.synchronizer.blockProcessor.storage.clear() + + // Now let's resume scanning and see how it goes. + let secondSyncAttemptExpectation = XCTestExpectation(description: "second sync attempt") + + try await withCheckedThrowingContinuation { continuation in + do { + try coordinator.sync( + completion: { _ in + XCTAssertTrue(true) + secondSyncAttemptExpectation.fulfill() + continuation.resume() + }, + error: { error in + secondSyncAttemptExpectation.fulfill() + guard let error else { + XCTFail("there was an unknown error") + continuation.resume() + return + } + continuation.resume(throwing: error) + } + ) + } catch { + continuation.resume(throwing: error) + } + } + + wait(for: [secondSyncAttemptExpectation], timeout: 10) + } + + @objc func processorStopped(_ notification: Notification) { + firstSyncContinuation?.resume() + self.firstSyncExpectation.fulfill() + } +} diff --git a/Tests/DarksideTests/PendingTransactionUpdatesTest.swift b/Tests/DarksideTests/PendingTransactionUpdatesTest.swift index ffac2b35a..150d8d821 100644 --- a/Tests/DarksideTests/PendingTransactionUpdatesTest.swift +++ b/Tests/DarksideTests/PendingTransactionUpdatesTest.swift @@ -45,7 +45,7 @@ class PendingTransactionUpdatesTest: XCTestCase { try super.tearDownWithError() NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/DarksideTests/ReOrgTests.swift b/Tests/DarksideTests/ReOrgTests.swift index e65ff8cce..0d251df63 100644 --- a/Tests/DarksideTests/ReOrgTests.swift +++ b/Tests/DarksideTests/ReOrgTests.swift @@ -68,7 +68,7 @@ class ReOrgTests: XCTestCase { override func tearDownWithError() throws { try super.tearDownWithError() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/DarksideTests/RewindRescanTests.swift b/Tests/DarksideTests/RewindRescanTests.swift index f68945a09..89df7340d 100644 --- a/Tests/DarksideTests/RewindRescanTests.swift +++ b/Tests/DarksideTests/RewindRescanTests.swift @@ -49,7 +49,7 @@ class RewindRescanTests: XCTestCase { NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/DarksideTests/ShieldFundsTests.swift b/Tests/DarksideTests/ShieldFundsTests.swift index 6895810e7..73244dfe7 100644 --- a/Tests/DarksideTests/ShieldFundsTests.swift +++ b/Tests/DarksideTests/ShieldFundsTests.swift @@ -46,7 +46,7 @@ class ShieldFundsTests: XCTestCase { try super.tearDownWithError() NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } @@ -223,7 +223,8 @@ class ShieldFundsTests: XCTestCase { do { let pendingTx = try await coordinator.synchronizer.shieldFunds( spendingKey: coordinator.spendingKey, - memo: try Memo(string: "shield funds") + memo: try Memo(string: "shield funds"), + shieldingThreshold: Zatoshi(10000) ) shouldContinue = true XCTAssertEqual(pendingTx.value, Zatoshi(10000)) @@ -294,12 +295,11 @@ class ShieldFundsTests: XCTestCase { // Fees at the time of writing the tests are 1000 zatoshi as defined on ZIP-313 let postShieldingShieldedBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) - // FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720 - XCTAssertEqual(postShieldingShieldedBalance.total, Zatoshi(10000)) - // FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720 - XCTAssertEqual(postShieldingShieldedBalance.verified, Zatoshi(10000)) - // FIXME: [#720] this should be 9000, https://github.com/zcash/ZcashLightClientKit/issues/720 - XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), .zero) + XCTAssertEqual(postShieldingShieldedBalance.total, .zero) + + XCTAssertEqual(postShieldingShieldedBalance.verified, .zero) + + XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), Zatoshi(9000)) // 14. proceed confirm the shielded funds by staging ten more blocks try coordinator.service.applyStaged(nextLatestHeight: utxoHeight + 10 + 1 + 10) diff --git a/Tests/DarksideTests/SychronizerDarksideTests.swift b/Tests/DarksideTests/SychronizerDarksideTests.swift index 5ce9dd16e..adcc0e040 100644 --- a/Tests/DarksideTests/SychronizerDarksideTests.swift +++ b/Tests/DarksideTests/SychronizerDarksideTests.swift @@ -49,7 +49,7 @@ class SychronizerDarksideTests: XCTestCase { try super.tearDownWithError() NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/DarksideTests/SynchronizerTests.swift b/Tests/DarksideTests/SynchronizerTests.swift index d777a0e0d..efa1ec27c 100644 --- a/Tests/DarksideTests/SynchronizerTests.swift +++ b/Tests/DarksideTests/SynchronizerTests.swift @@ -47,7 +47,7 @@ final class SynchronizerTests: XCTestCase { try super.tearDownWithError() NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/DarksideTests/TransactionEnhancementTests.swift b/Tests/DarksideTests/TransactionEnhancementTests.swift index 89a346d55..26cee8c2c 100644 --- a/Tests/DarksideTests/TransactionEnhancementTests.swift +++ b/Tests/DarksideTests/TransactionEnhancementTests.swift @@ -17,6 +17,12 @@ class TransactionEnhancementTests: XCTestCase { let network = DarksideWalletDNetwork() let branchID = "2bb40e60" let chainName = "main" + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() var initializer: Initializer! var processorConfig: CompactBlockProcessor.Configuration! @@ -34,6 +40,7 @@ class TransactionEnhancementTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) XCTestCase.wait { await InternalSyncProgress(storage: UserDefaults.standard).rewind(to: 0) } logger = OSLogger(logLevel: .debug) @@ -54,7 +61,7 @@ class TransactionEnhancementTests: XCTestCase { let rustBackend = ZcashRustBackend.self processorConfig = config - try? FileManager.default.removeItem(at: processorConfig.cacheDb) + try? FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot) try? FileManager.default.removeItem(at: processorConfig.dataDb) let dbInit = try rustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: network.networkType) @@ -94,8 +101,17 @@ class TransactionEnhancementTests: XCTestCase { let service = DarksideWalletService() darksideWalletService = service - let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) - try! storage.createTable() + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: rustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + try! storage.create() downloader = BlockDownloaderServiceImpl(service: service, storage: storage) processor = CompactBlockProcessor( @@ -115,7 +131,7 @@ class TransactionEnhancementTests: XCTestCase { override func tearDownWithError() throws { try super.tearDownWithError() - try? FileManager.default.removeItem(at: processorConfig.cacheDb) + try? FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot) try? FileManager.default.removeItem(at: processorConfig.dataDb) syncStartedExpect.unsubscribeFromNotifications() stopNotificationExpectation.unsubscribeFromNotifications() diff --git a/Tests/DarksideTests/Z2TReceiveTests.swift b/Tests/DarksideTests/Z2TReceiveTests.swift index de91c1b46..6a30cc41e 100644 --- a/Tests/DarksideTests/Z2TReceiveTests.swift +++ b/Tests/DarksideTests/Z2TReceiveTests.swift @@ -47,7 +47,7 @@ class Z2TReceiveTests: XCTestCase { NotificationCenter.default.removeObserver(self) try coordinator.stop() - try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: coordinator.databases.dataDB) try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) } diff --git a/Tests/NetworkTests/BlockScanTests.swift b/Tests/NetworkTests/BlockScanTests.swift index b968ee86c..df05ba125 100644 --- a/Tests/NetworkTests/BlockScanTests.swift +++ b/Tests/NetworkTests/BlockScanTests.swift @@ -11,11 +11,10 @@ import SQLite @testable import TestUtils @testable import ZcashLightClientKit -// swiftlint:disable implicitly_unwrapped_optional force_try force_unwrapping print_function_usage +// swiftlint:disable implicitly_unwrapped_optional force_try print_function_usage class BlockScanTests: XCTestCase { let rustWelding = ZcashRustBackend.self - var cacheDbURL: URL! var dataDbURL: URL! var spendParamsURL: URL! var outputParamsURL: URL! @@ -30,30 +29,37 @@ class BlockScanTests: XCTestCase { var network = ZcashNetworkBuilder.network(for: .testnet) var blockRepository: BlockRepository! - override func setUp() { + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + + override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. - super.setUp() - self.cacheDbURL = try! __cacheDbURL() + try super.setUpWithError() self.dataDbURL = try! __dataDbURL() self.spendParamsURL = try! __spendParamsURL() self.outputParamsURL = try! __outputParamsURL() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + deleteDBs() } private func deleteDBs() { - try? FileManager.default.removeItem(at: cacheDbURL) try? FileManager.default.removeItem(at: dataDbURL) } - override func tearDown() { + override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - - try? FileManager.default.removeItem(at: cacheDbURL) - try? FileManager.default.removeItem(at: dataDbURL) - try? FileManager.default.removeItem(at: spendParamsURL) - try? FileManager.default.removeItem(at: outputParamsURL) + try super.tearDownWithError() + + try? testFileManager.removeItem(at: dataDbURL) + try? testFileManager.removeItem(at: spendParamsURL) + try? testFileManager.removeItem(at: outputParamsURL) + try? testFileManager.removeItem(at: testTempDirectory) } func testSingleDownloadAndScan() async throws { @@ -61,7 +67,6 @@ class BlockScanTests: XCTestCase { XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType)) - let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() let service = LightWalletGRPCService( endpoint: LightWalletEndpoint( address: "lightwalletd.testnet.electriccoin.co", @@ -71,37 +76,48 @@ class BlockScanTests: XCTestCase { let blockCount = 100 let range = network.constants.saplingActivationHeight ... network.constants.saplingActivationHeight + blockCount - let sqliteStorage = CompactBlockStorage(url: cacheDbURL, readonly: false) - guard (try? sqliteStorage.createTable()) != nil else { return XCTFail("Can't prepare SQLite storage for BlockDownloaderServiceImpl") } - let downloader = BlockDownloaderServiceImpl(service: service, storage: sqliteStorage) + let fsDbRootURL = self.testTempDirectory + + let rustBackend = ZcashRustBackend.self + let fsBlockRepository = FSCompactBlockRepository( + cacheDirectory: fsDbRootURL, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: fsDbRootURL, + rustBackend: rustBackend + ), + blockDescriptor: ZcashCompactBlockDescriptor.live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try fsBlockRepository.create() + let downloader = BlockDownloaderServiceImpl(service: service, storage: fsBlockRepository) let processorConfig = CompactBlockProcessor.Configuration.standard( for: network, walletBirthday: network.constants.saplingActivationHeight ) + let compactBlockProcessor = CompactBlockProcessor( service: service, - storage: storage, - backend: ZcashRustBackend.self, + storage: fsBlockRepository, + backend: rustBackend, config: processorConfig ) let repository = BlockSQLDAO(dbProvider: SimpleConnectionProvider.init(path: self.dataDbURL.absoluteString, readonly: true)) var latestScannedheight = BlockHeight.empty() - do { - try await compactBlockProcessor.blockDownloaderService.downloadBlockRange(range) - XCTAssertFalse(Task.isCancelled) - try await compactBlockProcessor.compactBlockScanning( - rustWelding: rustWelding, - cacheDb: cacheDbURL, - dataDb: dataDbURL, - networkType: network.networkType - ) - latestScannedheight = repository.lastScannedBlockHeight() - XCTAssertEqual(latestScannedheight, range.upperBound) - } catch { - XCTFail("Download failed with error: \(error)") - } + + try await compactBlockProcessor.blockDownloaderService.downloadBlockRange(range) + + XCTAssertFalse(Task.isCancelled) + try await compactBlockProcessor.compactBlockScanning( + rustWelding: rustWelding, + cacheDb: fsDbRootURL, + dataDb: dataDbURL, + networkType: network.networkType + ) + latestScannedheight = repository.lastScannedBlockHeight() + XCTAssertEqual(latestScannedheight, range.upperBound) } @objc func observeBenchmark(_ notification: Notification) { @@ -157,11 +173,23 @@ class BlockScanTests: XCTestCase { ) let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet) - let storage = CompactBlockStorage(url: cacheDbURL, readonly: false) - try storage.createTable() + + let fsDbRootURL = self.testTempDirectory + + let fsBlockRepository = FSCompactBlockRepository( + cacheDirectory: fsDbRootURL, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: fsDbRootURL, + rustBackend: rustWelding + ), + blockDescriptor: ZcashCompactBlockDescriptor.live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try fsBlockRepository.create() var processorConfig = CompactBlockProcessor.Configuration( - cacheDb: cacheDbURL, + fsBlockCacheRoot: fsDbRootURL, dataDb: dataDbURL, spendParamsURL: spendParamsURL, outputParamsURL: outputParamsURL, @@ -172,7 +200,7 @@ class BlockScanTests: XCTestCase { let compactBlockProcessor = CompactBlockProcessor( service: service, - storage: storage, + storage: fsBlockRepository, backend: rustWelding, config: processorConfig ) diff --git a/Tests/NetworkTests/BlockStreamingTest.swift b/Tests/NetworkTests/BlockStreamingTest.swift index df0ba5a4e..a11dc73a5 100644 --- a/Tests/NetworkTests/BlockStreamingTest.swift +++ b/Tests/NetworkTests/BlockStreamingTest.swift @@ -11,14 +11,23 @@ import XCTest // swiftlint:disable print_function_usage class BlockStreamingTest: XCTestCase { + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + override func setUpWithError() throws { try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) logger = OSLogger(logLevel: .debug) } override func tearDownWithError() throws { try super.tearDownWithError() try? FileManager.default.removeItem(at: __dataDbURL()) + try? testFileManager.removeItem(at: testTempDirectory) } func testStream() async throws { @@ -58,7 +67,20 @@ class BlockStreamingTest: XCTestCase { streamingCallTimeout: 10000 ) - let storage = try TestDbBuilder.inMemoryCompactBlockStorage() + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let latestBlockHeight = try service.latestBlockHeight() let startHeight = latestBlockHeight - 100_000 let processorConfig = CompactBlockProcessor.Configuration.standard( @@ -69,7 +91,7 @@ class BlockStreamingTest: XCTestCase { let compactBlockProcessor = CompactBlockProcessor( service: service, storage: storage, - backend: ZcashRustBackend.self, + backend: realRustBackend, config: processorConfig ) @@ -101,11 +123,25 @@ class BlockStreamingTest: XCTestCase { port: 9067, secure: true, singleCallTimeout: 1000, - streamingCallTimeout: 3000 + streamingCallTimeout: 1000 ) - let storage = try TestDbBuilder.inMemoryCompactBlockStorage() + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let latestBlockHeight = try service.latestBlockHeight() + let startHeight = latestBlockHeight - 100_000 let processorConfig = CompactBlockProcessor.Configuration.standard( @@ -116,7 +152,7 @@ class BlockStreamingTest: XCTestCase { let compactBlockProcessor = CompactBlockProcessor( service: service, storage: storage, - backend: ZcashRustBackend.self, + backend: realRustBackend, config: processorConfig ) diff --git a/Tests/NetworkTests/CompactBlockProcessorTests.swift b/Tests/NetworkTests/CompactBlockProcessorTests.swift index 11dc05e40..d0afbfe29 100644 --- a/Tests/NetworkTests/CompactBlockProcessorTests.swift +++ b/Tests/NetworkTests/CompactBlockProcessorTests.swift @@ -10,7 +10,7 @@ import XCTest @testable import TestUtils @testable import ZcashLightClientKit -// swiftlint:disable force_try implicitly_unwrapped_optional +// swiftlint:disable implicitly_unwrapped_optional class CompactBlockProcessorTests: XCTestCase { let processorConfig = CompactBlockProcessor.Configuration.standard( for: ZcashNetworkBuilder.network(for: .testnet), @@ -23,9 +23,15 @@ class CompactBlockProcessorTests: XCTestCase { var idleNotificationExpectation: XCTestExpectation! let network = ZcashNetworkBuilder.network(for: .testnet) let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight + 2000 - + let testFileManager = FileManager() + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + override func setUpWithError() throws { try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) logger = OSLogger(logLevel: .debug) let service = MockLightWalletService( @@ -43,17 +49,28 @@ class CompactBlockProcessorTests: XCTestCase { info.estimatedHeight = UInt64(mockLatestHeight) info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) }) - - let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) - try! storage.createTable() + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: processorConfig.fsBlockCacheRoot, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() processor = CompactBlockProcessor( service: service, storage: storage, - backend: ZcashRustBackend.self, + backend: realRustBackend, config: processorConfig ) - let dbInit = try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet) + let dbInit = try realRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet) guard case .success = dbInit else { XCTFail("Failed to initDataDb. Expected `.success` got: \(dbInit)") @@ -72,9 +89,9 @@ class CompactBlockProcessorTests: XCTestCase { ) } - override func tearDown() { - super.tearDown() - try! FileManager.default.removeItem(at: processorConfig.cacheDb) + override func tearDownWithError() throws { + try super.tearDownWithError() + try FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot) try? FileManager.default.removeItem(at: processorConfig.dataDb) syncStartedExpect.unsubscribeFromNotifications() stopNotificationExpectation.unsubscribeFromNotifications() diff --git a/Tests/NetworkTests/CompactBlockReorgTests.swift b/Tests/NetworkTests/CompactBlockReorgTests.swift index d95aad233..5d9b16653 100644 --- a/Tests/NetworkTests/CompactBlockReorgTests.swift +++ b/Tests/NetworkTests/CompactBlockReorgTests.swift @@ -16,6 +16,13 @@ class CompactBlockReorgTests: XCTestCase { for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight ) + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + var processor: CompactBlockProcessor! var syncStartedExpect: XCTestExpectation! var updatedNotificationExpectation: XCTestExpectation! @@ -27,6 +34,7 @@ class CompactBlockReorgTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) logger = OSLogger(logLevel: .debug) let service = MockLightWalletService( @@ -44,15 +52,26 @@ class CompactBlockReorgTests: XCTestCase { info.estimatedHeight = UInt64(mockLatestHeight) info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) } - - guard case .success = try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet) else { + + let realRustBackend = ZcashRustBackend.self + + let realCache = FSCompactBlockRepository( + cacheDirectory: processorConfig.fsBlockCacheRoot, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try realCache.create() + + guard case .success = try realRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet) else { XCTFail("initDataDb failed. Expected Success but got .seedRequired") return } - - let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) - try! storage.createTable() - + let mockBackend = MockRustBackend.self mockBackend.mockValidateCombinedChainFailAfterAttempts = 3 mockBackend.mockValidateCombinedChainKeepFailing = false @@ -60,7 +79,7 @@ class CompactBlockReorgTests: XCTestCase { processor = CompactBlockProcessor( service: service, - storage: storage, + storage: realCache, backend: mockBackend, config: processorConfig ) @@ -88,7 +107,8 @@ class CompactBlockReorgTests: XCTestCase { override func tearDown() { super.tearDown() - try? FileManager.default.removeItem(at: processorConfig.cacheDb) + try? testFileManager.removeItem(at: testTempDirectory) + try! FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot) try? FileManager.default.removeItem(at: processorConfig.dataDb) syncStartedExpect.unsubscribeFromNotifications() stopNotificationExpectation.unsubscribeFromNotifications() diff --git a/Tests/NetworkTests/DownloadTests.swift b/Tests/NetworkTests/DownloadTests.swift index 97cac0cf3..355f23cd1 100644 --- a/Tests/NetworkTests/DownloadTests.swift +++ b/Tests/NetworkTests/DownloadTests.swift @@ -11,17 +11,44 @@ import SQLite @testable import TestUtils @testable import ZcashLightClientKit -// swiftlint:disable force_try class DownloadTests: XCTestCase { + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + var network = ZcashNetworkBuilder.network(for: .testnet) - override func tearDown() { - super.tearDown() + override func setUpWithError() throws { + try super.setUpWithError() + + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + try? testFileManager.removeItem(at: testTempDirectory) } func testSingleDownload() async throws { let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet) - let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let downloader = BlockDownloaderServiceImpl(service: service, storage: storage) let blockCount = 100 let activationHeight = network.constants.saplingActivationHeight @@ -31,10 +58,11 @@ class DownloadTests: XCTestCase { for: network, walletBirthday: network.constants.saplingActivationHeight ) + let compactBlockProcessor = CompactBlockProcessor( service: service, storage: storage, - backend: ZcashRustBackend.self, + backend: realRustBackend, config: processorConfig ) @@ -44,6 +72,6 @@ class DownloadTests: XCTestCase { XCTFail("Download failed with error: \(error)") } - XCTAssertEqual(try! storage.latestHeight(), range.upperBound) + XCTAssertEqual(storage.latestHeight(), range.upperBound) } } diff --git a/Tests/OfflineTests/BlockBatchValidationTests.swift b/Tests/OfflineTests/BlockBatchValidationTests.swift index 318c643f8..b3e26090b 100644 --- a/Tests/OfflineTests/BlockBatchValidationTests.swift +++ b/Tests/OfflineTests/BlockBatchValidationTests.swift @@ -11,17 +11,48 @@ import XCTest // swiftlint:disable force_try type_body_length class BlockBatchValidationTests: XCTestCase { + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + + override func setUpWithError() throws { + try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + try? testFileManager.removeItem(at: testTempDirectory) + } + func testBranchIdFailure() async throws { let network = ZcashNetworkBuilder.network(for: .mainnet) let service = MockLightWalletService( latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) ) - let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), @@ -72,11 +103,25 @@ class BlockBatchValidationTests: XCTestCase { latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) ) - let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), @@ -127,11 +172,25 @@ class BlockBatchValidationTests: XCTestCase { latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) ) - let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), @@ -182,11 +241,25 @@ class BlockBatchValidationTests: XCTestCase { latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default) ) - let storage = try! TestDbBuilder.inMemoryCompactBlockStorage() + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try storage.create() + let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), @@ -253,7 +326,7 @@ class BlockBatchValidationTests: XCTestCase { let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), @@ -342,7 +415,7 @@ class BlockBatchValidationTests: XCTestCase { let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight) let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), @@ -422,7 +495,7 @@ class BlockBatchValidationTests: XCTestCase { let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight) let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) let config = CompactBlockProcessor.Configuration( - cacheDb: try! __cacheDbURL(), + fsBlockCacheRoot: testTempDirectory, dataDb: try! __dataDbURL(), spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL(), diff --git a/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift b/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift index 951965ed8..5e7f1bb1f 100644 --- a/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift @@ -10,9 +10,28 @@ import XCTest @testable import ZcashLightClientKit class CompactBlockProcessorOfflineTests: XCTestCase { + let testFileManager = FileManager() + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + override func setUpWithError() throws { + try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + try FileManager.default.removeItem(at: self.testTempDirectory) + } + func testComputeProcessingRangeForSingleLoop() async throws { + let network = ZcashNetworkBuilder.network(for: .testnet) + let realRustBackend = ZcashRustBackend.self + let processorConfig = CompactBlockProcessor.Configuration.standard( - for: ZcashNetworkBuilder.network(for: .testnet), + for: network, walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight ) @@ -20,7 +39,17 @@ class CompactBlockProcessorOfflineTests: XCTestCase { latestBlockHeight: 690000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet) ) - let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString)) + + let storage = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: realRustBackend + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + let processor = CompactBlockProcessor(service: service, storage: storage, backend: ZcashRustBackend.self, config: processorConfig) let fullRange = 0...1000 diff --git a/Tests/OfflineTests/CompactBlockRepositoryTests.swift b/Tests/OfflineTests/CompactBlockRepositoryTests.swift new file mode 100644 index 000000000..8638a0f57 --- /dev/null +++ b/Tests/OfflineTests/CompactBlockRepositoryTests.swift @@ -0,0 +1,229 @@ +// +// CompactBlockStorageTests.swift +// ZcashLightClientKitTests +// +// Created by Francisco Gindre on 10/13/19. +// Copyright © 2019 Electric Coin Company. All rights reserved. +// + +import Foundation +@testable import TestUtils +@testable import ZcashLightClientKit +import XCTest + +class CompactBlockRepositoryTests: XCTestCase { + let network = ZcashNetworkBuilder.network(for: .testnet) + + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + + override func setUpWithError() throws { + try super.setUpWithError() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + try? testFileManager.removeItem(at: testTempDirectory) + } + + func testEmptyStorage() throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + XCTAssertEqual(compactBlockRepository.latestHeight(), .empty()) + } + + func testEmptyStorageAsync() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let latestHeight = await compactBlockRepository.latestHeightAsync() + + XCTAssertEqual(latestHeight, BlockHeight.empty()) + } + + func testStoreThousandBlocks() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let initialHeight = await compactBlockRepository.latestHeightAsync() + let startHeight = self.network.constants.saplingActivationHeight + let blockCount = Int(1_000) + let finalHeight = startHeight + blockCount + + do { + try await TestDbBuilder.seed(db: compactBlockRepository, with: startHeight...finalHeight) + } catch { + XCTFail("seed failed with error: \(error)") + return + } + + let latestHeight = compactBlockRepository.latestHeight() + XCTAssertNotEqual(initialHeight, latestHeight) + XCTAssertEqual(latestHeight, finalHeight) + } + + func testStoreThousandBlocksAsync() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let initialHeight = compactBlockRepository.latestHeight() + let startHeight = self.network.constants.saplingActivationHeight + let blockCount = Int(1_000) + let finalHeight = startHeight + blockCount + + try await TestDbBuilder.seed(db: compactBlockRepository, with: startHeight...finalHeight) + + let latestHeight = await compactBlockRepository.latestHeightAsync() + XCTAssertNotEqual(initialHeight, latestHeight) + XCTAssertEqual(latestHeight, finalHeight) + } + + func testStoreOneBlockFromEmpty() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let expectedHeight = BlockHeight(123_456) + guard let block = StubBlockCreator.createRandomDataBlock(with: expectedHeight) else { + XCTFail("could not create random block with height: \(expectedHeight)") + return + } + + try await compactBlockRepository.write(blocks: [block]) + + XCTAssertEqual(compactBlockRepository.latestHeight(), expectedHeight) + } + + func testStoreOneBlockFromEmptyAsync() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let expectedHeight = BlockHeight(123_456) + guard let block = StubBlockCreator.createRandomDataBlock(with: expectedHeight) else { + XCTFail("could not create random block with height: \(expectedHeight)") + return + } + try await compactBlockRepository.write(blocks: [block]) + + let result = await compactBlockRepository.latestHeightAsync() + XCTAssertEqual(result, expectedHeight) + } + + func testRewindTo() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let startHeight = self.network.constants.saplingActivationHeight + let blockCount = Int(1_000) + let finalHeight = startHeight + blockCount + + do { + try await TestDbBuilder.seed(db: compactBlockRepository, with: startHeight...finalHeight) + } catch { + XCTFail("seed failed with error: \(error)") + return + } + let rewindHeight = BlockHeight(finalHeight - 233) + + do { + try await compactBlockRepository.rewindAsync(to: rewindHeight) + + XCTAssertEqual(compactBlockRepository.latestHeight(), rewindHeight) + } catch { + XCTFail("Rewind latest block failed with error: \(error)") + } + } + + func testRewindToAsync() async throws { + let compactBlockRepository: CompactBlockRepository = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try compactBlockRepository.create() + + let startHeight = self.network.constants.saplingActivationHeight + let blockCount = Int(1_000) + let finalHeight = startHeight + blockCount + + try await TestDbBuilder.seed(db: compactBlockRepository, with: startHeight...finalHeight) + let rewindHeight = BlockHeight(finalHeight - 233) + + try await compactBlockRepository.rewindAsync(to: rewindHeight) + let latestHeight = await compactBlockRepository.latestHeightAsync() + XCTAssertEqual(latestHeight, rewindHeight) + } +} diff --git a/Tests/OfflineTests/CompactBlockStorageTests.swift b/Tests/OfflineTests/CompactBlockStorageTests.swift deleted file mode 100644 index 4216ed213..000000000 --- a/Tests/OfflineTests/CompactBlockStorageTests.swift +++ /dev/null @@ -1,138 +0,0 @@ -// -// CompactBlockStorageTests.swift -// ZcashLightClientKitTests -// -// Created by Francisco Gindre on 10/13/19. -// Copyright © 2019 Electric Coin Company. All rights reserved. -// - -import Foundation -@testable import TestUtils -import XCTest - -// swiftlint:disable force_try -@testable import ZcashLightClientKit -class CompactBlockStorageTests: XCTestCase { - let network = ZcashNetworkBuilder.network(for: .testnet) - var compactBlockDao: CompactBlockRepository = try! TestDbBuilder.inMemoryCompactBlockStorage() - - func testEmptyStorage() { - XCTAssertEqual(try! compactBlockDao.latestHeight(), BlockHeight.empty()) - } - - func testEmptyStorageAsync() async throws { - let latestHeight = try await compactBlockDao.latestHeightAsync() - XCTAssertEqual(latestHeight, BlockHeight.empty()) - } - - func testStoreThousandBlocks() async { - let initialHeight = try! compactBlockDao.latestHeight() - let startHeight = self.network.constants.saplingActivationHeight - let blockCount = Int(1_000) - let finalHeight = startHeight + blockCount - - do { - try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight) - } catch { - XCTFail("seed failed with error: \(error)") - return - } - - let latestHeight = try! compactBlockDao.latestHeight() - XCTAssertNotEqual(initialHeight, latestHeight) - XCTAssertEqual(latestHeight, finalHeight) - } - - func testStoreThousandBlocksAsync() async throws { - let initialHeight = try! compactBlockDao.latestHeight() - let startHeight = self.network.constants.saplingActivationHeight - let blockCount = Int(1_000) - let finalHeight = startHeight + blockCount - - try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight) - - let latestHeight = try await compactBlockDao.latestHeightAsync() - XCTAssertNotEqual(initialHeight, latestHeight) - XCTAssertEqual(latestHeight, finalHeight) - } - - func testStoreOneBlockFromEmpty() async { - let initialHeight = try! compactBlockDao.latestHeight() - guard initialHeight == BlockHeight.empty() else { - XCTFail("database not empty, latest height: \(initialHeight)") - return - } - - let expectedHeight = BlockHeight(123_456) - guard let block = StubBlockCreator.createRandomDataBlock(with: expectedHeight) else { - XCTFail("could not create random block with height: \(expectedHeight)") - return - } - do { - try await compactBlockDao.write(blocks: [block]) - } catch { - XCTFail("unexpected testStoreOneBlockFromEmpty fail") - } - - do { - let result = try compactBlockDao.latestHeight() - XCTAssertEqual(result, expectedHeight) - } catch { - XCTFail("latestBlockHeight failed") - return - } - } - - func testStoreOneBlockFromEmptyAsync() async throws { - let initialHeight = try await compactBlockDao.latestHeightAsync() - guard initialHeight == BlockHeight.empty() else { - XCTFail("database not empty, latest height: \(initialHeight)") - return - } - - let expectedHeight = BlockHeight(123_456) - guard let block = StubBlockCreator.createRandomDataBlock(with: expectedHeight) else { - XCTFail("could not create random block with height: \(expectedHeight)") - return - } - try await compactBlockDao.write(blocks: [block]) - - let result = try await compactBlockDao.latestHeightAsync() - XCTAssertEqual(result, expectedHeight) - } - - func testRewindTo() async { - let startHeight = self.network.constants.saplingActivationHeight - let blockCount = Int(1_000) - let finalHeight = startHeight + blockCount - - do { - try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight) - } catch { - XCTFail("seed failed with error: \(error)") - return - } - let rewindHeight = BlockHeight(finalHeight - 233) - - do { - try await compactBlockDao.rewindAsync(to: rewindHeight) - let latestHeight = try compactBlockDao.latestHeight() - XCTAssertEqual(latestHeight, rewindHeight - 1) - } catch { - XCTFail("Rewind latest block failed with error: \(error)") - } - } - - func testRewindToAsync() async throws { - let startHeight = self.network.constants.saplingActivationHeight - let blockCount = Int(1_000) - let finalHeight = startHeight + blockCount - - try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight) - let rewindHeight = BlockHeight(finalHeight - 233) - - try await compactBlockDao.rewindAsync(to: rewindHeight) - let latestHeight = try await compactBlockDao.latestHeightAsync() - XCTAssertEqual(latestHeight, rewindHeight - 1) - } -} diff --git a/Tests/OfflineTests/FsBlockStorageTests.swift b/Tests/OfflineTests/FsBlockStorageTests.swift new file mode 100644 index 000000000..3600bc4de --- /dev/null +++ b/Tests/OfflineTests/FsBlockStorageTests.swift @@ -0,0 +1,541 @@ +// +// FsBlockStorageTests.swift +// +// +// Created by Francisco Gindre on 12/15/22. +// +// swiftlint:disable type_body_length implicitly_unwrapped_optional force_unwrapping +import XCTest +@testable import TestUtils +@testable import ZcashLightClientKit + +var logger = OSLogger(logLevel: .debug) + +final class FsBlockStorageTests: XCTestCase { + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + + var fsBlockDb: URL! + + override func setUpWithError() throws { + try super.setUpWithError() + // Put setup code here. This method is called before the invocation of each test method in the class. + self.fsBlockDb = self.testTempDirectory.appendingPathComponent("FsBlockDb-\(Int.random(in: 0 ... .max))") + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + try self.testFileManager.createDirectory(at: self.fsBlockDb, withIntermediateDirectories: false) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + try? testFileManager.removeItem(at: testTempDirectory) + } + + func testLatestHeightEmptyCache() throws { + let emptyCache: FSCompactBlockRepository = .emptyTemporaryCache + + try emptyCache.create() + + XCTAssertEqual(emptyCache.latestHeight(), .empty()) + } + + func testRewindEmptyCacheDoesNothing() throws { + let emptyCache: FSCompactBlockRepository = .emptyTemporaryCache + + try emptyCache.create() + + try emptyCache.rewind(to: 1000000) + } + + func testRewindEmptyCacheDoesNothingAsync() async throws { + let emptyCache: FSCompactBlockRepository = .emptyTemporaryCache + + try emptyCache.create() + + try await emptyCache.rewindAsync(to: 1000000) + } + + func testWhenBlockIsStoredItFollowsTheDescribedFormat() async throws { + let blockNameFixture = "This-is-a-fixture" + + let freshCache = FSCompactBlockRepository( + cacheDirectory: self.testTempDirectory, + metadataStore: .mock, + blockDescriptor: ZcashCompactBlockDescriptor( + height: { _ in nil }, + describe: { _ in blockNameFixture }, + compare: { _, _ in nil } + ), + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try freshCache.create() + + let fakeBlock = StubBlockCreator.createRandomDataBlock(with: 1234)! + + try await freshCache.write(blocks: [fakeBlock]) + + let blockFilename = freshCache.blocksDirectory + .appendingPathComponent(blockNameFixture) + .path + + XCTAssertTrue(FileManager.default.isReadableFile(atPath: blockFilename)) + } + + func testWhenBlockIsStoredItFollowsTheFilenameConvention() async throws { + let freshCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .mock, + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try freshCache.create() + + let fakeBlock = StubBlockCreator.createRandomDataBlock(with: 1234)! + let fakeBlockHash = fakeBlock.meta.hash.toHexStringTxId() + + try await freshCache.write(blocks: [fakeBlock]) + + let blockFilename = freshCache.blocksDirectory + .appendingPathComponent( + "\(1234)-\(fakeBlockHash)-compactblock" + ) + .path + + XCTAssertTrue(FileManager.default.isReadableFile(atPath: blockFilename)) + } + + func testRewindDeletesTheRightBlocks() async throws { + let contentProvider = DirectoryListingProviders.defaultSorted + let freshCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .mock, + blockDescriptor: .live, + contentProvider: contentProvider + ) + + try freshCache.create() + + let blockRange = CompactBlockRange(uncheckedBounds: (1000, 2000)) + + let fakeBlocks = StubBlockCreator.createBlockRange(blockRange)! + + let rewindHeight = BlockHeight(1500) + + try await freshCache.write(blocks: fakeBlocks) + + let contents = try contentProvider.listContents(of: freshCache.blocksDirectory) + + XCTAssertEqual(contents.count, blockRange.count) + + guard let firstStoredBlock = contents.first else { + XCTFail("no stored block") + return + } + + guard let filename = try firstStoredBlock.resourceValues(forKeys: [URLResourceKey.nameKey]).name else { + XCTFail("no filename") + return + } + + XCTAssertEqual(ZcashCompactBlockDescriptor.live.height(filename), 1000) + + guard let lastStoredBlock = contents.last else { + XCTFail("no stored block") + return + } + + XCTAssertEqual(ZcashCompactBlockDescriptor.live.height(lastStoredBlock.lastPathComponent), 2000) + + try await freshCache.rewindAsync(to: rewindHeight) + + let afterRewindContents = try contentProvider.listContents(of: freshCache.blocksDirectory) + + XCTAssertEqual(afterRewindContents.count, 501) + + guard let firstStoredBlockAfterRewind = afterRewindContents.first else { + XCTFail("no stored block") + return + } + + XCTAssertEqual(ZcashCompactBlockDescriptor.live.height(firstStoredBlockAfterRewind.lastPathComponent), 1000) + + guard let lastStoredBlockAfterRewind = afterRewindContents.last else { + XCTFail("no stored block") + return + } + + XCTAssertEqual(ZcashCompactBlockDescriptor.live.height(lastStoredBlockAfterRewind.lastPathComponent), 1500) + } + + func testGetLatestHeight() async throws { + let freshCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .live(fsBlockDbRoot: testTempDirectory, rustBackend: ZcashRustBackend.self), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try freshCache.create() + + let blockRange = CompactBlockRange(uncheckedBounds: (1000, 2000)) + + let fakeBlocks = StubBlockCreator.createBlockRange(blockRange)! + + try await freshCache.write(blocks: fakeBlocks) + + let latestHeight = freshCache.latestHeight() + + XCTAssertEqual(latestHeight, 2000) + } + + func testBlockDescriptorFiltersBlocksGreaterThan() throws { + let cacheList = [ + "1000-DEADBEEF-block", + "1001-DEADBEEF1-block", + "1002-DEADBEEF2-block", + "1003-DEADBEEF3-block", + "1004-DEADBEEF4-block", + "1005-DEADBEEF5-block", + "1006-DEADBEEF6-block", + "1007-DEADBEEF7-block", + "1008-DEADBEEF8-block", + "1009-DEADBEEF9-block", + "1010-DEADBEEFA-block" + ] + + XCTAssertEqual( + try cacheList.filter { try $0.filterGreaterThan(1006, with: .live) }, + [ + "1007-DEADBEEF7-block", + "1008-DEADBEEF8-block", + "1009-DEADBEEF9-block", + "1010-DEADBEEFA-block" + ] + ) + } + + func testBlockDescriptorFiltersThrowsIfFileDescriptorFails() throws { + let cacheList = [ + "1000-DEADBEEF-block", + "1001-DEADBEEF1-block", + "1002-DEADBEEF2-block", + "1003-DEADBEEF3-block", + "1004-DEADBEEF4-block", + "1005-DEADBEEF5-block", + "a-DEADBEEF6-block", + "1007-DEADBEEF7-block", + "1008-DEADBEEF8-block", + "1009-DEADBEEF9-block", + "1010-DEADBEEFA-block" + ] + + XCTAssertThrowsError(try cacheList.filter { try $0.filterGreaterThan(1006, with: .live) }) + } + + func testRewindBlockSelectTheProperFilesByName() throws { + let cacheList = try [ + "1000-DEADBEEF-block", + "1001-DEADBEEF1-block", + "1002-DEADBEEF2-block", + "1003-DEADBEEF3-block", + "1004-DEADBEEF4-block", + "1005-DEADBEEF5-block", + "1006-DEADBEEF6-block", + "1007-DEADBEEF7-block", + "1008-DEADBEEF8-block", + "1009-DEADBEEF9-block", + "1010-DEADBEEFA-block" + ].map { filename in + var url = self.fsBlockDb.appendingPathComponent(filename) + guard self.testFileManager.createFile(atPath: url.path, contents: nil) else { + XCTFail("couldn't create file at \(url.absoluteString)") + throw CompactBlockRepositoryError.malformedCacheEntry("couldn't create file at \(url.path)") + } + var resourceValues = URLResourceValues() + resourceValues.name = filename + + try url.setResourceValues(resourceValues) + + return url + } + + let expectedDeleteList = try [ + "1007-DEADBEEF7-block", + "1008-DEADBEEF8-block", + "1009-DEADBEEF9-block", + "1010-DEADBEEFA-block" + ].reversed().map { filename in + var url = self.fsBlockDb.appendingPathComponent(filename) + var resourceValues = URLResourceValues() + resourceValues.name = filename + try url.setResourceValues(resourceValues) + return url + } + + XCTAssertEqual( + try FSCompactBlockRepository.filterBlockFiles(from: cacheList, toRewind: 1006, with: .live), + expectedDeleteList + ) + } + + func testClearTheCache() async throws { + let fsBlockCache = FSCompactBlockRepository( + cacheDirectory: self.testTempDirectory, + metadataStore: .live(fsBlockDbRoot: testTempDirectory, rustBackend: ZcashRustBackend.self), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.naive + ) + + try fsBlockCache.create() + + guard let stubBlocks = StubBlockCreator.createBlockRange(1000 ... 1010) else { + XCTFail("Something Happened. Creating Stub blocks failed") + return + } + + try await fsBlockCache.write(blocks: stubBlocks) + XCTAssertEqual(fsBlockCache.latestHeight(), 1010) + + try await fsBlockCache.clear() + + XCTAssertEqual(fsBlockCache.latestHeight(), .empty()) + } + + func testCreateDoesntFailWhenAlreadyCreated() throws { + let freshCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .mock, + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try freshCache.create() + + XCTAssertNoThrow(try freshCache.create()) + } + + func testStoringTenSandblastedBlocks() async throws { + let realRustBackend = ZcashRustBackend.self + + let realCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .live(fsBlockDbRoot: testTempDirectory, rustBackend: realRustBackend), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try realCache.create() + + guard let sandblastedBlocks = try SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else { + XCTFail("failed to create sandblasted blocks") + return + } + + let startTime = Date() + try await realCache.write(blocks: sandblastedBlocks) + let endTime = Date() + + let timePassed = startTime.distance(to: endTime) + + XCTAssertLessThan(timePassed, 0.5) + + let latestHeight = await realCache.latestHeightAsync() + + XCTAssertEqual(latestHeight, 19) + } + + func testStoringTenSandblastedBlocksFailsAndThrows() async throws { + let realRustBackend = ZcashRustBackend.self + + let realCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .live(fsBlockDbRoot: testTempDirectory, rustBackend: realRustBackend), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted, + fileWriter: FSBlockFileWriter(writeToURL: { _, _ in throw FixtureError.arbitraryError }) + ) + + try realCache.create() + + guard let sandblastedBlocks = try SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else { + XCTFail("failed to create sandblasted blocks") + return + } + + do { + try await realCache.write(blocks: sandblastedBlocks) + XCTFail("This call should have failed") + } catch { + XCTAssertEqual(error as? CompactBlockRepositoryError, CompactBlockRepositoryError.failedToWriteBlock(sandblastedBlocks[0])) + } + } + + func testStoringTenSandblastedBlocksAndRewindFiveThenStoreThemBack() async throws { + let realRustBackend = ZcashRustBackend.self + + let realCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .live(fsBlockDbRoot: testTempDirectory, rustBackend: realRustBackend), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try realCache.create() + + guard let sandblastedBlocks = try SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else { + XCTFail("failed to create sandblasted blocks") + return + } + + let startTime = Date() + try await realCache.write(blocks: sandblastedBlocks) + let endTime = Date() + + let timePassed = startTime.distance(to: endTime) + + XCTAssertLessThan(timePassed, 0.5) + + let latestHeight = await realCache.latestHeightAsync() + + XCTAssertEqual(latestHeight, 19) + + try realCache.rewind(to: 14) + + let rewoundHeight = await realCache.latestHeightAsync() + + XCTAssertEqual(rewoundHeight, 14) + + let blockSlice = [ZcashCompactBlock](sandblastedBlocks[5...]) + try await realCache.write(blocks: blockSlice) + + let newLatestHeight = await realCache.latestHeightAsync() + + XCTAssertEqual(newLatestHeight, 19) + } + + func testMetadataStoreThrowsWhenCallReturnsFalse() async { + guard let sandblastedBlocks = try? SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else { + XCTFail("failed to create sandblasted blocks") + return + } + + MockRustBackend.writeBlocksMetadataResult = { false } + + do { + try await FSMetadataStore.saveBlocksMeta(sandblastedBlocks, fsBlockDbRoot: testTempDirectory, rustBackend: MockRustBackend.self) + } catch CompactBlockRepositoryError.failedToWriteMetadata { + // this is fine + } catch { + XCTFail("Expected `CompactBlockRepositoryError.failedToWriteMetadata` but found: \(error.localizedDescription)") + } + } + + func testMetadataStoreThrowsWhenRustThrows() async { + guard let sandblastedBlocks = try? SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else { + XCTFail("failed to create sandblasted blocks") + return + } + + MockRustBackend.writeBlocksMetadataResult = { throw RustWeldingError.genericError(message: "oops") } + + do { + try await FSMetadataStore.saveBlocksMeta(sandblastedBlocks, fsBlockDbRoot: testTempDirectory, rustBackend: MockRustBackend.self) + } catch CompactBlockRepositoryError.failedToWriteMetadata { + // this is fine + } catch { + XCTFail("Expected `CompactBlockRepositoryError.failedToWriteMetadata` but found: \(error.localizedDescription)") + } + } + + func testMetadataStoreThrowsWhenRewindFails() { + MockRustBackend.rewindCacheToHeightResult = { false } + let expectedHeight = BlockHeight(1000) + + XCTAssertThrowsError( + try FSMetadataStore.live( + fsBlockDbRoot: testTempDirectory, + rustBackend: MockRustBackend.self + ) + .rewindToHeight(expectedHeight) + ) { error in + guard let repositoryError = error as? CompactBlockRepositoryError else { + XCTFail("Expected CompactBlockRepositoryError. Found \(error)") + return + } + + switch repositoryError { + case .failedToRewind(let height): + XCTAssertEqual(height, expectedHeight) + default: + XCTFail("Expected `CompactBlockRepositoryError.failedToRewind`. Found \(error)") + } + } + } + + func testPerformanceExample() async throws { + // NOTE: performance tests don't work with async code. Thanks Apple! + let freshCache = FSCompactBlockRepository( + cacheDirectory: testTempDirectory, + metadataStore: .live(fsBlockDbRoot: testTempDirectory, rustBackend: ZcashRustBackend.self), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + + try freshCache.create() + + let blockRange = CompactBlockRange(uncheckedBounds: (1000, 2000)) + + let fakeBlocks = try SandblastSimulator().sandblast(with: blockRange)! + + let startTime = Date() + try await freshCache.write(blocks: fakeBlocks) + let endTime = Date() + + let latestHeight = await freshCache.latestHeightAsync() + + XCTAssertEqual(latestHeight, 2000) + + let total = startTime.distance(to: endTime) + // let totalKiloBytes = fakeBlocks.map { $0.data.count }.reduce(0, +) / 1024 // 245055 + XCTAssertGreaterThan(1.5, total) + } +} + +extension FSCompactBlockRepository { + static var emptyTemporaryCache: FSCompactBlockRepository { + FSCompactBlockRepository( + cacheDirectory: URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ).appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")), + metadataStore: .mock, + blockDescriptor: ZcashCompactBlockDescriptor( + height: { _ in BlockHeight() }, + describe: { _ in "123456-deadbeef-block" }, + compare: { _, _ in nil } + ), + contentProvider: SortedDirectoryContentProvider( + fileManager: FileManager.default, + sorting: { _, _ in false } + ) + ) + } +} + +enum FixtureError: Error, Equatable { + case arbitraryError +} + +extension FSMetadataStore { + static let mock = FSMetadataStore { _ in } + rewindToHeight: { _ in } + initFsBlockDbRoot: { _ in true } + latestHeightAsync: { .empty() } + latestHeight: { + .empty() + } +} diff --git a/Tests/OfflineTests/PendingTransactionRepositoryTests.swift b/Tests/OfflineTests/PendingTransactionRepositoryTests.swift index bf2e34d84..8905b2be1 100644 --- a/Tests/OfflineTests/PendingTransactionRepositoryTests.swift +++ b/Tests/OfflineTests/PendingTransactionRepositoryTests.swift @@ -20,7 +20,7 @@ class PendingTransactionRepositoryTests: XCTestCase { super.setUp() cleanUpDb() let pendingDbProvider = SimpleConnectionProvider(path: try! TestDbBuilder.pendingTransactionsDbURL().absoluteString) - let migrations = try! MigrationManager(cacheDbConnection: InMemoryDbProvider(), pendingDbConnection: pendingDbProvider, networkType: .testnet) + let migrations = MigrationManager(pendingDbConnection: pendingDbProvider, networkType: .testnet) try! migrations.performMigration() pendingRepository = PendingTransactionSQLDAO(dbProvider: pendingDbProvider) } diff --git a/Tests/OfflineTests/WalletTests.swift b/Tests/OfflineTests/WalletTests.swift index 826ad8826..28ee75c0a 100644 --- a/Tests/OfflineTests/WalletTests.swift +++ b/Tests/OfflineTests/WalletTests.swift @@ -11,26 +11,33 @@ import XCTest @testable import TestUtils @testable import ZcashLightClientKit -// swiftlint:disable implicitly_unwrapped_optional force_try force_unwrapping +// swiftlint:disable implicitly_unwrapped_optional force_unwrapping class WalletTests: XCTestCase { + let testTempDirectory = URL(fileURLWithPath: NSString( + string: NSTemporaryDirectory() + ) + .appendingPathComponent("tmp-\(Int.random(in: 0 ... .max))")) + + let testFileManager = FileManager() + var dbData: URL! = nil var paramDestination: URL! = nil - var cacheData: URL! = nil var network = ZcashNetworkBuilder.network(for: .testnet) var seedData = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! - override func setUp() { - super.setUp() - dbData = try! __dataDbURL() - cacheData = try! __cacheDbURL() - paramDestination = try! __documentsDirectory().appendingPathComponent("parameters") + override func setUpWithError() throws { + try super.setUpWithError() + dbData = try __dataDbURL() + try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false) + paramDestination = try __documentsDirectory().appendingPathComponent("parameters") } - override func tearDown() { - super.tearDown() - if FileManager.default.fileExists(atPath: dbData.absoluteString) { - try! FileManager.default.trashItem(at: dbData, resultingItemURL: nil) + override func tearDownWithError() throws { + try super.tearDownWithError() + if testFileManager.fileExists(atPath: dbData.absoluteString) { + try testFileManager.trashItem(at: dbData, resultingItemURL: nil) } + try? self.testFileManager.removeItem(at: self.testTempDirectory) } func testWalletInitialization() throws { @@ -38,7 +45,7 @@ class WalletTests: XCTestCase { let ufvk = try derivationTool.deriveUnifiedSpendingKey(seed: seedData.bytes, accountIndex: 0) .map({ try derivationTool.deriveUnifiedFullViewingKey(from: $0) }) let wallet = Initializer( - cacheDbURL: try __cacheDbURL(), + fsBlockDbRoot: self.testTempDirectory, dataDbURL: try __dataDbURL(), pendingDbURL: try TestDbBuilder.pendingTransactionsDbURL(), endpoint: LightWalletEndpointBuilder.default, @@ -61,7 +68,5 @@ class WalletTests: XCTestCase { // fileExists actually sucks, so attempting to delete the file and checking what happens is far better :) XCTAssertNoThrow( try FileManager.default.removeItem(at: dbData!) ) - // TODO: [#717] Initialize cacheDB on start, will be done when Synchronizer is ready and integrated, https://github.com/zcash/ZcashLightClientKit/issues/717 -// XCTAssertNoThrow( try FileManager.default.removeItem(at: cacheData!) ) } } diff --git a/Tests/OfflineTests/ZcashRustBackendTests.swift b/Tests/OfflineTests/ZcashRustBackendTests.swift index cfd489f84..631526c98 100644 --- a/Tests/OfflineTests/ZcashRustBackendTests.swift +++ b/Tests/OfflineTests/ZcashRustBackendTests.swift @@ -14,7 +14,7 @@ import XCTest class ZcashRustBackendTests: XCTestCase { var dbData: URL! var dataDbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedDataDbURL()!) - var cacheDbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedCacheDbURL()!) + let spendingKey = // swiftlint:disable:next line_length "secret-extended-key-test1qvpevftsqqqqpqy52ut2vv24a2qh7nsukew7qg9pq6djfwyc3xt5vaxuenshp2hhspp9qmqvdh0gs2ljpwxders5jkwgyhgln0drjqaguaenfhehz4esdl4kwlm5t9q0l6wmzcrvcf5ed6dqzvct3e2ge7f6qdvzhp02m7sp5a0qjssrwpdh7u6tq89hl3wchuq8ljq8r8rwd6xdwh3nry9at80z7amnj3s6ah4jevnvfr08gxpws523z95g6dmn4wm6l3658kd4xcq9rc0qn" @@ -49,54 +49,6 @@ class ZcashRustBackendTests: XCTestCase { XCTAssertThrowsError(try ZcashRustBackend.createAccount(dbData: dbData!, seed: Array(seed.utf8), networkType: networkType)) } - func testInitAndScanBlocks() throws { - guard let cacheDb = TestDbBuilder.prePopulatedCacheDbURL() else { - XCTFail("pre populated Db not present") - return - } - let seed = "testreferencealicetestreferencealice" - - var dbInit: DbInitResult! - XCTAssertNoThrow(try { dbInit = try ZcashRustBackend.initDataDb( - dbData: self.dbData!, - seed: Array(seed.utf8), - networkType: self.networkType - ) }()) - - guard case .success = dbInit else { - XCTFail("Failed to initDataDb. Expected `.success` got: \(String(describing: dbInit))") - return - } - - XCTAssertEqual(ZcashRustBackend.getLastError(), nil) - let ufvks = [ - try DerivationTool(networkType: networkType).deriveUnifiedSpendingKey(seed: Array(seed.utf8), accountIndex: 0) - .deriveFullViewingKey() - ] - do { - try ZcashRustBackend.initAccountsTable(dbData: dbData!, ufvks: ufvks, networkType: networkType) - } catch { - XCTFail("failed with error: \(String(describing: ZcashRustBackend.lastError()))") - return - } - - XCTAssertNotNil( - try ZcashRustBackend.createAccount( - dbData: dbData!, - seed: Array(seed.utf8), - networkType: networkType - ) - ) - XCTAssertEqual(ZcashRustBackend.getLastError(), nil) - - let addr = try ZcashRustBackend.getCurrentAddress(dbData: dbData!, account: 0, networkType: networkType) - XCTAssertEqual(ZcashRustBackend.getLastError(), nil) - // swiftlint:disable:next line_length - XCTAssertEqual(addr.saplingReceiver()?.stringEncoded, Optional("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc")) - - XCTAssertTrue(ZcashRustBackend.scanBlocks(dbCache: cacheDb, dbData: dbData, networkType: networkType)) - } - func testIsValidTransparentAddressFalse() { XCTAssertFalse( ZcashRustBackend.isValidTransparentAddress( diff --git a/Tests/PerformanceTests/SynchronizerTests.swift b/Tests/PerformanceTests/SynchronizerTests.swift index 622202144..65c1b0b1a 100644 --- a/Tests/PerformanceTests/SynchronizerTests.swift +++ b/Tests/PerformanceTests/SynchronizerTests.swift @@ -50,7 +50,7 @@ class SynchronizerTests: XCTestCase { for _ in 1...5 { let databases = TemporaryDbBuilder.build() let initializer = Initializer( - cacheDbURL: databases.cacheDB, + fsBlockDbRoot: databases.fsCacheDbRoot, dataDbURL: databases.dataDB, pendingDbURL: databases.pendingDB, endpoint: endpoint, @@ -63,7 +63,7 @@ class SynchronizerTests: XCTestCase { loggerProxy: OSLogger(logLevel: .debug) ) - try? FileManager.default.removeItem(at: databases.cacheDB) + try? FileManager.default.removeItem(at: databases.fsCacheDbRoot) try? FileManager.default.removeItem(at: databases.dataDB) try? FileManager.default.removeItem(at: databases.pendingDB) diff --git a/Tests/TestUtils/DarkSideWalletService.swift b/Tests/TestUtils/DarkSideWalletService.swift index 39bdc85ec..82295a95e 100644 --- a/Tests/TestUtils/DarkSideWalletService.swift +++ b/Tests/TestUtils/DarkSideWalletService.swift @@ -177,6 +177,8 @@ class DarksideWalletService: LightWalletService { } enum DarksideWalletDConstants: NetworkConstants { + static var defaultFsBlockDbRootName = "fs_cache" + static var saplingActivationHeight: BlockHeight { 663150 } diff --git a/Tests/TestUtils/FakeStorage.swift b/Tests/TestUtils/FakeStorage.swift index 3efc91712..59595c16b 100644 --- a/Tests/TestUtils/FakeStorage.swift +++ b/Tests/TestUtils/FakeStorage.swift @@ -5,14 +5,16 @@ // Created by Francisco Gindre on 12/09/2019. // Copyright © 2019 Electric Coin Company. All rights reserved. // - +// swiftlint:disable force_unwrapping import Foundation @testable import ZcashLightClientKit class ZcashConsoleFakeStorage: CompactBlockRepository { - func closeDBConnection() { } + func create() throws {} - func latestHeightAsync() async throws -> BlockHeight { + func clear() async throws {} + + func latestHeightAsync() async -> BlockHeight { latestBlockHeight } @@ -24,12 +26,21 @@ class ZcashConsoleFakeStorage: CompactBlockRepository { fakeRewind(to: height) } - func latestHeight() throws -> Int { + func latestHeight() -> Int { return self.latestBlockHeight } - func latestBlocks(count: Int) throws -> [ZcashLightClientKit.ZcashCompactBlock] { - return (0.. ZcashLightClientKit.ZcashCompactBlock { + return ZcashCompactBlock( + height: latestBlockHeight, + data: Data(), + meta: ZcashCompactBlock.Meta( + hash: Data(), + time: 1, + saplingOutputs: 2, + orchardOutputs: 2 + ) + ) } func rewind(to height: BlockHeight) throws { @@ -55,3 +66,28 @@ class ZcashConsoleFakeStorage: CompactBlockRepository { self.latestBlockHeight = min(self.latestBlockHeight, height) } } + +import GRPC +struct SandblastSimulator { + /// Creates an array of Zcash CompactBlock from a mainnet sandblasted block of 500K bytes + /// this is not good for syncing but for performance benchmarking of block storage. + func sandblast(with range: CompactBlockRange) throws -> [ZcashCompactBlock]? { + let jsonFile = Bundle.module.url(forResource: "sandblasted_mainnet_block", withExtension: "json")! + let fileHandle = try FileHandle(forReadingFrom: jsonFile) + + let sandblastedBlock = try CompactBlock(jsonUTF8Data: fileHandle.availableData) + + return [CompactBlock](repeating: sandblastedBlock, count: range.count) + .enumerated() + .map { sandblastedBlock in + let height = range.lowerBound + sandblastedBlock.offset + + var block = sandblastedBlock.element + + block.height = UInt64(height) + + return block + } + .asZcashCompactBlocks() + } +} diff --git a/Tests/TestUtils/MockTransactionRepository.swift b/Tests/TestUtils/MockTransactionRepository.swift index d2e9d3fcf..80ecd07bf 100644 --- a/Tests/TestUtils/MockTransactionRepository.swift +++ b/Tests/TestUtils/MockTransactionRepository.swift @@ -220,11 +220,8 @@ extension Array { var idx: [Int] = [] - for index in 0 ..< self.count { - // swiftlint:disable:next for_where - if function(self[index]) { - idx.append(index) - } + for index in 0 ..< self.count where function(self[index]) { + idx.append(index) } guard !idx.isEmpty else { return nil } diff --git a/Tests/TestUtils/Resources/sandblasted_mainnet_block.json b/Tests/TestUtils/Resources/sandblasted_mainnet_block.json new file mode 100644 index 000000000..d6ee9add0 --- /dev/null +++ b/Tests/TestUtils/Resources/sandblasted_mainnet_block.json @@ -0,0 +1,10325 @@ +{ + "height": "1735000", + "hash": "YPI5ZPH9WJptOMOjedIWcyXY0OECYQQ37bobAAAAAAA=", + "prevHash": "d2VyCLSkDJJqzLhd48e9KyQBHhmWzODWCY8gAQAAAAA=", + "time": 1657631015, + "vtx": [ + { + "index": "11", + "hash": "PsF+VxlPSmscpwDpaOE5AD3fibjLQ71JrIuZdUHuICY=", + "spends": [ + { + "nf": "wFgztoL1XG7ctRmjfGHKeRVs649qlXA+JFqTdurdaQw=" + } + ], + "outputs": [ + { + "cmu": "y0xEo54Sv75ZRbxe5yLE6SMXPv/gAqkiHFksHWWWQmw=", + "epk": "PhSBwxxZ9pL5d/2fB30gW4eEVI+jxD1WtVVozkp36rk=", + "ciphertext": "P6JQVcNXmgeWGaplCRxTTatWZAVTcFyx93T7MRPmOJfHQPo0kfAKeuL47/b1FmmrKG4SYA==" + }, + { + "cmu": "9x9J8H6EeIJCabJvUC2P6DFXWtA5Ao3XbqHQLPcZdkA=", + "epk": "XHoaw2Z46iwFJPqRFn50QJOfmYtkJ9+FJYQudz5Dntk=", + "ciphertext": "wcoePNC4lAeoPftACq85ZyetDMna9q/O1qYDhbpwy8qeek7FsIxc9UWrIo+XGMXhG9vxfA==" + } + ] + }, + { + "index": "12", + "hash": "W7qShMtFebEHsscWzFwv/d6q5poetFDdFyJa2sBI8lE=", + "outputs": [ + { + "cmu": "ci7GFkPFmfpL3qXy1jNDrmplvMlASl7exGPGRe5l4So=", + "epk": "10h3R6yRxgsejp+iMQ0/XfBB28ORNpmuNBVTvJcrfrY=", + "ciphertext": "rZOkuNIotPKDJP03SgUDMlNd3pDxdGuO6KPJI44ZuCODzm4bh0jiNrgbDb4vxbQQQDjoMw==" + } + ] + }, + { + "index": "13", + "hash": "jhk/Bv44Rnd3TOZMHk2kOxiVcyYkD0EOs1wKb+lh4lc=", + "spends": [ + { + "nf": "6PemziztGm01SOMj7ahc3IQHGtQMJDP9MD20DBOiKhM=" + } + ], + "outputs": [ + { + "cmu": "/UlHDt/SfSuRILq9WVMqRYF7vLsf1hmPe0kmYU99vWs=", + "epk": "lyF93u8gzTYeT16kOilZNj3t83koyIozGFk1kAtHaRU=", + "ciphertext": "XdTc0V5yvmDPePKgRKpMAWa+SgcLXsU2h0053LKD3HyZwgHG/22QsLfFmfxQKzpQuWBLDw==" + }, + { + "cmu": "YgkgOM/yVM4chaf8Z/nJhhHEnqofaP3M2SA/7KU9qF0=", + "epk": "ezpg2Im5N1qYKxz/dJ4iNqmAG7aSdfugbPo+Zs8VgAI=", + "ciphertext": "WIa8Cn+BhuYrT/nl5XlY8aUYftvWxLGEp9wtgIDXATDaFaahsqpmwVVVYyrBPELJ0MqhUg==" + }, + { + "cmu": "tyXPujNIiCgEjupMcWA/UbFfcJW/NgxMpYJi228Zo1M=", + "epk": "RyQyfB8vFLXjeM1KzdfrzZxQtinnShM5PHvoxnYJ46s=", + "ciphertext": "fVbDXfxhIoMzBOyzhdm1/YmyNKx/+ggNU6+I75BQRTHgv1u84nnkvl+V09R19YfuEO/FZg==" + }, + { + "cmu": "7XU3hJzrBsQ+lqaR6e2SU/AHG1ji9zDmY0hJFpicQEs=", + "epk": "uwJpgGR5yBbIBr7Nl7lCdnOvZ+1xEpUYUH1cazR2Yzg=", + "ciphertext": "SrKDezJWNnvDn5fFfv9mMIdDR3gkUrCxJaqvf1QcNnxJdMP4brEoqW0+OdevFnPqyAb2tw==" + }, + { + "cmu": "ghnKgIgv4hC1Mr51jzwQuyKFWkhBk1ba1sjZVbzV30k=", + "epk": "FoJHTSKdZauhNQwq2ZnomYLIDDFMQOy18rNBsm+Fcc0=", + "ciphertext": "beStSCpycbgFFuF+aEfepN/ptnchofOVBIxkS+sUlpmJQ4qcowLkmVVy19kSAc1n7iJ6iA==" + }, + { + "cmu": "vvKWuVouTzYSK2AiwMDbrV0lbL3NS9H1sLHKCRL80k8=", + "epk": "1h2tkrXXFI4pGnC2n62d4JRDdyQun0MmAO/PBg9QoMM=", + "ciphertext": "v6xtl0wseX25kcLKioZZxdBkSML1UYcRLIiCNEGsm6aOZ1vKhSTzCSFnd8LHDCHZJbemdQ==" + }, + { + "cmu": "63XfD5UispD4dt41y3/gY6Ll+DQnDwFaKFX6Oj42fRE=", + "epk": "LatWpTVPcIaiXuINb9QjkLSQpYEywOZNBN0pNzu5NLY=", + "ciphertext": "pbbTK1+LV1Gnn3X6UGZ4Jw+e7oxQ+PY70WB7nFqIJSev+aciYlaa280X4cERYWSl18+6vQ==" + }, + { + "cmu": "kbnVnQJZlKJzZ3xnY5P3dubF0bl4l/K+9kXHn5/UWDw=", + "epk": "o5lckYPVJyFHzrIUfrm+CnS/CbnKdACoKbaCEzve4sw=", + "ciphertext": "SBjrLJcO8QqCkqVVwWzo3TvrzbqpfHfMxZvufXYnkXoc2ohE4vS1Cx1hwblw5m4Wu1E1XA==" + }, + { + "cmu": "0rzgAvKXOOWUaUk37YzBhj1G/fEi0NEcz0WYQW2Ehhs=", + "epk": "bnxHo6hbNPtZ04WEBNglBOY7LsWMmDlieugqHe0uJsQ=", + "ciphertext": "n90pAmaVT2/dXfWN+YJAhMy8pNelwitZlE+TI1MVxfRpS3EHP9Q86dIOi/YgIYctHVsvSA==" + }, + { + "cmu": "FcRyQREN+G2I6LMCo4Z+QcL5PpZQT0iHwExWVMfbQDQ=", + "epk": "E1JRGQJtanrXwNuEDnykfY/nreA+rXrRvt8EyJ2SmQM=", + "ciphertext": "NVbtg/kYigYp28UFRFJEbppSlulrQQsNKepjJcjbs0M8+9OnZslJ9cOXQZmun74cGY5L3w==" + }, + { + "cmu": "KkPIQT2QpRijttKrZaJ8+JKDM8kX3JnJluCOB4QeKQM=", + "epk": "RUZ+BzxstXXgdXAKdZyHoVBVGMXVGWCsVDMW9Zqsn+Y=", + "ciphertext": "NGpiECxFfTYq2szV79RpkHUEUkMzB27YhM5TTCSsXsikNJ44jBagjuNRX2xL3WviA3TTbg==" + }, + { + "cmu": "TOQov7VSRrQCbTXWrTJQRoJqdM89caW7+AxmbC9uFzA=", + "epk": "LH656YYC3s0xHqfOWsl7g7HaFp5PShctFesU/MMyX+c=", + "ciphertext": "uQlDqiVN6O1hgpZhAYsrcDEsV/yovNVbAPhipBGol3k/CKKqz8Q4ysZgsynJ6U8IdYZlEw==" + }, + { + "cmu": "TQ+TSfb5+qfUj2JE3r1I1++d1HQx1ciSF4vvLvlD8ig=", + "epk": "2+jAHxc6g1vF30tsokCl8v8GYB8nx4sCB3MdW1SPsI4=", + "ciphertext": "3EZ+2pLT2v/E2t8TeMDYyyUotvyRilvoLURPc7ypKYnyTuXIHjVGoq5G+6FG9KII0wdnFg==" + }, + { + "cmu": "P09bALmdKgzEkSntVe2+vOxT7IisavXK0R6grUhE2mY=", + "epk": "HtmfwYSIoV8NF5AUpJQQaj+08TGY3/dAe7diy5/kLr8=", + "ciphertext": "NayCtV6ldxFIsQuJEGls2FOFTIkmtG9VIVaW/LVL115xF8SjGWju83bWMFPpyQ6QqqYNig==" + }, + { + "cmu": "yg0F86mYBxF2GVYSgGAZiIzhYt6hmIHYoBZG/58kMhM=", + "epk": "PpBXR0KpltyJeNcfBpiWSOLO7XbmYYe4sEpgmjBW2F4=", + "ciphertext": "kFGG1ab4opdYF4081mQwKlN7DH8QXY7EAk/E7hHFjdo+Rh4SnoVg3OAcoBHNEHpGI+6ang==" + }, + { + "cmu": "KqycDuB6QYYDmTfg2Wu2QO8HQT0W/rcN5Y0gwr8faiU=", + "epk": "63ne9w94hN+dsakl5f37iZrXLt0pmg2RHhcq1EgMe50=", + "ciphertext": "Pylhbd6cZxpt8h01b9AarKWEhJcLL3p5yU8AV+FyRHf78xdbPxCnWkyAh1pF/oXSF0fQVA==" + }, + { + "cmu": "uHx+kPhvbG255PwmyvcZubF+vGGmJV7+wmpF0StYXDg=", + "epk": "rEU+Qezq15O9+GmU8zhez4rNIgduphArooao/oIvaY8=", + "ciphertext": "tgN0wu7pJcQadrqV/yfhglkp8uGe8594lVSVRLk/Twydb07n0IEKd4hWFp/8nqRDhWXQAg==" + }, + { + "cmu": "l0DVB8jI6FgZDE3QdeT74IB0gJsIXHdpkaNv7Ue+sUU=", + "epk": "Gzp8dmNRPNhzCqqnEMZxvVv1TSbyiEDPiAsGp/Nd55s=", + "ciphertext": "adk0SGpHNGsw5EINFnytsPGEhCE2wnSoFlUtddeAOk8gNngCPA4V1IH3qmNNE8bEmQivBw==" + }, + { + "cmu": "dmhLGkPJyEJyN82p4WOO0i5MhbSOsApb07P+YzI3jxQ=", + "epk": "4nuEcgZxWJQ99pJIreF4CECciHCBXEtWcTy7MoI78sU=", + "ciphertext": "LMNBCGxJsomVtqsdSG+uUnC0lgN2SnltB7Iuy5j4Ifm7tGRggmCHM7belrW22fM78sud0w==" + }, + { + "cmu": "ASIbmPXWxWszlTYOTOb/7PFwe5Q4B/5S6kmKrWQ4ewI=", + "epk": "wDxhF1RgViNSOAlpGUkEkVYYAYhmgpzQLwrIlONVWCE=", + "ciphertext": "My8M1G25ixSi6oO55fHDhaoYBLd5R1+q1c7NVQEtMcOWqizoddS1EScV5vftIJP+bUboWQ==" + }, + { + "cmu": "ZOLqW7O8vZtYme1n9SanzgHLIRVSq86LnlULGB9BLwE=", + "epk": "n1ve/tz8WkUQF4nZX0HK/X/EYzNhHDdOJvTK9/UyA6A=", + "ciphertext": "MbhZsSRLFy2dSflL6qWBqWnlE3aGqE7aR8bwECyqlajyV+NyWdKpJQwGRySwxNJTl87z4Q==" + }, + { + "cmu": "MkpzBaoDGKIzF2q8jHGGS6hCLR6Y0w2C/DZ6+9F6jzI=", + "epk": "d8OezmSF36hmrjRpMaD9LiyYO4/at38zgYM2ux4P0sI=", + "ciphertext": "QQhGwWuwut8OBoBfWhRH9mzuK3LsoGYjVdrxV9VolmElEfs5CWN2m013FCzKi3mM7QFlsw==" + }, + { + "cmu": "WFyBfGemGr657oFmxPNnPMPRDZpCaupmTJ9Pnx4arWk=", + "epk": "5LRdg03wzJecgKu4/1g0NTPIFop7eRFSVOhUHcQ2zMk=", + "ciphertext": "tH3pwZEYz7xAixn/O1f1fPeOSDYyx/BqESmowMsev5cQ4ERaCZpiD1CxEBJYgPOlyLJ/OQ==" + }, + { + "cmu": "tc9juB0NzAff6KWELhgwBDQT6ZFgX86jHHwhFd+8pR8=", + "epk": "Do5JyeaAPCSVHaRjISuXTHSdEO1QBPT3Ldcfl8itxjQ=", + "ciphertext": "lmMk/cR8EclWCuRHcer6zwOkSDEqRL/dIokALgS0KzmPhREB4D3UYmSapIWDg3zu+5YW9w==" + }, + { + "cmu": "MU89NbSxwLsI2GPpJdBvX4GwP2p2bpka7G0vg72QpCk=", + "epk": "u7eG/AmItSNKR1xTTQ56Zsun9Ug+RCjqeXJyYljDjAA=", + "ciphertext": "kmZ/Oeb2VK2B32Uz2tSb95Kpm4eAff1BfvMDpTA+55gdMb3PALCcAFlwbvmlpaEvIHnNcQ==" + }, + { + "cmu": "42rCNFnhuURzI/R4Al+TQaYWJIlCv9bD71YmWYPirzo=", + "epk": "whLrFPM1m4kQaZ4MR7cWUBVBXH5O+4yRvmNMGYyIRLI=", + "ciphertext": "dflqh7yUhI8W6Zs1+3DZHcJ/qTHrzUCYo1TkaDejruYmoPJRphVxjXfyznRkYuvRxV+jWg==" + }, + { + "cmu": "sEtdB0JAyh9PkH42/Q3lOWLAoPVC9xyrL4qYcs7fASc=", + "epk": "I6CMuwaemcgeN+7wooZj25ztW18fUGKOQEPWoHQNGq4=", + "ciphertext": "GB7n7rK4o2Ohg9QdRSHB1Verr7LzAQcHaU9XbugS3N9HuaUga+hsfeW8RNditKuABe4dMw==" + }, + { + "cmu": "R9RTCtSpQlXjU+e0bATxfEwNYgK8L3q2Jp2eL/9q20g=", + "epk": "bSqtl5B7jkavY8xF6A6JkPC1vvTpWeuovNUPQT2P/EY=", + "ciphertext": "tVIiZ/tBWUVuYMWek31lmat/INOQmitxFmPTY2aQzCli2r7b5xRjAXuaNXTYRm2jd8/bjA==" + }, + { + "cmu": "s9eX1jz2OHdnKQ4SCfvslcLemDSpmvfBkz7y75hs/XA=", + "epk": "otBSROMv8Rnu/T8jncWbfSc7rrjGcKgadMuPfscHR6s=", + "ciphertext": "JY/1AeolRB1Ohmw8fLmede2AELf3GEz96vT2T4vM6hI/LlCqHBAStIxc9t+w7ycwpEtv6A==" + }, + { + "cmu": "KtcX/dbkxeK7B7MtboQ1vTVinRTcOVu81+UtjU5spA0=", + "epk": "ZtIK0xbHFhd3HxF6aYHRT/BWT1rGSOJ6yxrYZjMOl+I=", + "ciphertext": "ZX/QcFKKrmfRUuEz1L/8a0KJN6f/5A7Yo709LnGBoKKn3KWj6flm5ZjOUlCno1LD6emJRA==" + }, + { + "cmu": "ptPCX4n6NQxPeMDv9fuM6ky3MQH8bmG1ybbiwCtmLho=", + "epk": "OUspk7oIkffbL4oJF5Q6TWc/4Kyg2Xj5kTdWj+dpHSY=", + "ciphertext": "iI5GEVsbJqaPinvK0XOxRfyQkTRgnu7+3sdjQQ3/hhMIb3W16n+icGrs3jBOooYsITlrDg==" + }, + { + "cmu": "cdzaMA5CfJ82SK72kbNBmp0o3Pf0pFr3ZGFl1imuoik=", + "epk": "Hs9HD0RdNU2YGCOr4ScjcayPUPMuZqvj5w5IY6b4YgU=", + "ciphertext": "b48n/w4EW3EcUzaAPLAeT29aFamQeiHU1hN5kauy2qSwgdCBg17FY/lEDfPgd1nZYT6Sxw==" + }, + { + "cmu": "UZZV+PinYfDmkiIVAKUBlWkbQoWiFf+Ty4l5tPgtnEI=", + "epk": "cCOaZd2wX7Xq21BE1nZ2cjXUGt9DZIqphinuJgL0+iQ=", + "ciphertext": "3Rw3yUMwwIStoFCOR9BjySds/Hr/v8vNDz9XHMgeo3tCVwSpBaGMti6KdW5bMksFAM5xXw==" + }, + { + "cmu": "ySeqDJ4F78UB708UdgOZRuOJMl9K/Ic7NmZ4B1ozUEM=", + "epk": "wBznTWf7tEsf1DUF7M5uEOMfEVDFlneFGvT+nMkTvLY=", + "ciphertext": "siOOKV9vnoIYX1DM5Bad/4RNsbUp8trNcb6ASdw0RdSbaKwrmvN+l4mx8kbm5LWKguUZrg==" + }, + { + "cmu": "U0E62q5LM+4ZNP2IMKxZKtg3rKVbWd3T171sYAK2sHE=", + "epk": "GT2XndWkcNHCDUjiVrnh9p317DJMDSPsO0cNNBoAF20=", + "ciphertext": "/nGZHq2QG/W5SJkDPaWAkCoEnKM7mAKsgafpELIOIH5mm8Ebj/Ys3T4fO9G4mDjlXBD+Bw==" + }, + { + "cmu": "SMhUlieCtXea4Dp75AIM3E8xh8jLeP0DeCKzfpgF1F0=", + "epk": "X/OZbELJWLsv74jEG6Hs1Qcf/UI4QeLDrP0+kXgtHGM=", + "ciphertext": "X256PDACtsEm0NcDyRw/ejnqPfJMX3tS+TCocPJkh0occVdSX0rvYKpVJDTqKHuimcEXMw==" + }, + { + "cmu": "xosmDXNbQE9uQAt/ZfNmYoYwVPJmQevivSRqbKN/FA8=", + "epk": "kMChh03wlZSnyKsBvyZHHJ9SK7xp9I1em8NCpU0d6AA=", + "ciphertext": "gDPx3kDUJjYjqrvxolKmzuY5j0gLheLotMJWmieCgXkPxIYj8UzcTs3rg6eJ0d2FA8AHvg==" + }, + { + "cmu": "Q+2V0EoMSSEFjzUqWhou7O7qzmEilGo2VnJNEpvRq1g=", + "epk": "Brw/CPKbChruZfvguPNV/FFMoDPc9yAFpfOdJugeru4=", + "ciphertext": "/lf65MJkdkI7sfkLb/xpYVlzz4z6MrYJBxQGXjR6dd/lx1wOlhP3OXgO+u0sKvAPsyRJ7w==" + }, + { + "cmu": "U2f4pPtp3kdUXIqG/MSM471aliaj+AkDaPwX2WaumGQ=", + "epk": "G+mK3XnnpTe+3nbo0scH2dZg/Q4KqEg4fJgUlkz4fjs=", + "ciphertext": "VPgf32V+PlJQImZOnkZGhF/1i6a5SppUqMT6eZLU54o/zBPKRI+q4hY8HRcI5oKi8TeT9Q==" + }, + { + "cmu": "IMDvrU6ytT9IoX60KBB/aVqL1HgG4mhDME5PQybrqDo=", + "epk": "HUfTmhEqcGATgQtTBT5AmMwoSnVXuyDsqp59hfYceD0=", + "ciphertext": "rJJrY0n/inlOkEmqKDTSOqYkMG3Lqun8h2H1GV/5sF6Bg4UAtk8+ifLva5fe1UNH92EKFQ==" + }, + { + "cmu": "mK8xw17kutn0NhGrWzFlCSWOTLTzvyt8Sa2egx2R+wI=", + "epk": "JKi59eGbFq+4PgHvZqbXZ5b8cYIRgCpyqMTt7t7t6Lc=", + "ciphertext": "oqiTNOSnlPSwb3cNyqBYo05gmII2sEyNnqRLMFwXHVEREbEqmtexySJxPpj6n0rXp4rLRQ==" + }, + { + "cmu": "R1y5h5N6Yemp8Mg7nK40jwGZuRMnLpMUFX1S1yZLgCM=", + "epk": "0xq3DNYVKjrb2NisaePi60aQJ95FLLTuRCakWF/ldOU=", + "ciphertext": "0DsM9hISMPOxkTNCBv+59A+aUpe/Pejibl8eQliikPw/I7sQ75jCbE/zLu90b6MLwNyXVw==" + }, + { + "cmu": "zUPvAvFX6wpMXwcQTNFyi6xCWCioS3oljqpbxEePIgM=", + "epk": "7z3avbiVm1ZvH83UZEWafJ0MTH8IqaOppkVCJ0V9NEo=", + "ciphertext": "72ilMJteKcobDk/uvxJL7cy8Lc7Xg5AP3MJB+R5rC7LIba210Je3V5v9m7KiuToRiZbo/Q==" + }, + { + "cmu": "Twp9iLz/6y4gemqbISXyJhvn+N9PKDdlNWA8K7DlZ10=", + "epk": "Z0SXOIUO7FQ+5Hh9myVOiEX0ZYQTMlHGO05OCe7KatY=", + "ciphertext": "wEmm2l8tJ8C88Nd2NA5Mqt3p546OK+3GwB/RQPuQKS3vtVlW6l7wKVk79yNQ5n5VG9v1Gw==" + }, + { + "cmu": "relPbDsyxhRqQV9fdcQnqZZVDOZGJLaF3Eqbmvqp+Ck=", + "epk": "xpQf32k61v0l/R11VFFPWqbTQ7ivtzgbG0LBJzy73gU=", + "ciphertext": "1IeDr4+IUTjcYEdYNl/3H/LXE31l5OiMq6ioXKLlcJV/GGVaDVJtTQKbw42GGyCW6MLkXw==" + }, + { + "cmu": "VOJJo4XylM7eL0j7FVKu8NHEoL0KkYOrPtan8p8gpHM=", + "epk": "ZU6Mb4oQ4iOVFS2L8yXOIEZON6yB836SENWe/bbvIss=", + "ciphertext": "Cflzc71nyYfKRfZL3rDHKbxy5WnSWNXKKrFkEjUlcotDCveQVSTGSaHtPSIk/gQblGiB1w==" + }, + { + "cmu": "eKPZe6SNGBXMIKJQbFHtIebjqPd6IoDVqsvH1xsQwEg=", + "epk": "i5gO1Z7TdZC+6uwW//koxpYXoFV0v45+JZUKRYlaYjw=", + "ciphertext": "669V9T5R3daSpsKoYe0AakGwGiIQqC5RTJZsuIn+Lcg8QDjvI982RnUvfF3uK9YZLacHRA==" + }, + { + "cmu": "WBw57pjxO5FCJrSP9IikCl1lBukf29/K2NRgJCpJiDM=", + "epk": "6BX4i8LjDDJRE1yk/u/v+1lmK1aWTsqIWMKq1Yf4NJ0=", + "ciphertext": "/qLnj7nxeacWuqfZ8oR0+yrwkmLSRF9mufnQ4FT45sDLMFFveAl1lEtJ51I+KBtGgFN3mA==" + }, + { + "cmu": "8rkgBbCRhmv9sEEFCD2kOp/pSVXbN6iTvHU6dLeZoRM=", + "epk": "UhlGden6WR9DIbeqWv+1LcI3FB1lk6KtzDmugqt3A10=", + "ciphertext": "KSHrAUPSmJcfxxspstAs+hPyD36aABoyQv1AM6ory3xh1b0ojH9spxcsi41s1wKAiM7zEw==" + }, + { + "cmu": "P0NhRIS9TeNJeZnADuYbgAPaMQLDPRGibsP1GMESREw=", + "epk": "IJpze+WAKNgTvttI5WQ0Q+6AqFlbcg3kg8KRfXXN38Q=", + "ciphertext": "UMd3toPXqEJTvcA3qjfOp0/aEfsBZTskoJGi2KXQ1ZsSw/PyA/NvFOmXtAoK/OHwaBuCdA==" + }, + { + "cmu": "eng6bEO1jsgGPs22qRRT6Jnk6UldS6J2Fv2k75gNkgE=", + "epk": "nVo4He7GYVGdUYhl6Vq5o4j241r4VqTuqNpz2P8EJrs=", + "ciphertext": "/Au5HGpn1pQamaYwg9ze698u3jc46WxeI1wIaF4vNKZJY0PxWI7dk22nRCDhq6hqDeoHaA==" + }, + { + "cmu": "C7suSssjpPPY7o20fcqKIYJ8nnCUm6lop3LmI5bu5E4=", + "epk": "8Yj/lH5fvDHsX2LP2gsSOLN/MXucCeDwHB66k7UUBNg=", + "ciphertext": "7JC3tTIOkvrJoYGtdPOubibJC5jtQWq9C+T4WwvKV/YopWPGreJbkkcPwt6ckXvXnCtpfw==" + }, + { + "cmu": "WYY/I8J3I4O4kf+F+Yh3s2NQ+wZbFoOWoGjcpQRfPF4=", + "epk": "txYxgHhMD9vv386ODeeqAbvTAe7mPdiw93TPjaP/Kxc=", + "ciphertext": "wGdWwhEF+ORauMLxBmFQhpk/UruffaVqfmnHU9gE+RbdgOblwg7v6st0IhZZBECIwGNDTQ==" + }, + { + "cmu": "9ApuaaBtoh0SbNAP+x2vWQ0Tvztsja+s+75U9LpLmDQ=", + "epk": "KbkebcenehZ3HPJG6aPaadZp9IsjcCJQQVbtO+HIrsw=", + "ciphertext": "SgQ2t5bZZRmArwfxfLVsrL1u0M1wpGR6mBcH+PIw/VsyNMcldzFfI38qIbM4HPmTrRkYHQ==" + }, + { + "cmu": "PFIvbz9KBN3bwO47U6d75QwLugOLP4Z5HQvoIO31im8=", + "epk": "DK0nicaA0GUzgYQ8FYr3P3RBZIzfx5VtJhFHHirfAic=", + "ciphertext": "EpoAeuCMMx2Z6Z8OPxfiNkF+4+ElP2AqoVt7Sxue7M1m9Nf8bHaI/6hiKrCTBXHy/ua1cA==" + }, + { + "cmu": "I3awm9vhSJxAH2WFMaSkTIwChTBHWoXelMs5COUa1m8=", + "epk": "rn2Cu05XlV35fxMfNqKTN+4JcT7iMM1yHoz/++D5HIQ=", + "ciphertext": "ZjP1eS4WM1ymybYNHOw5uwneqwH/OXewTHiqfGWi9lBkEiMA7CVYSj9hrggiL06Ad4RDOA==" + }, + { + "cmu": "eG2MJylqXBtvSZhTdCWwzr8JHOdXhqqZuQCv8Jd1bxY=", + "epk": "jWeKpEfLr3D9cwcDqMjUnTcqM6aNVZmkP7fTwOVsuG8=", + "ciphertext": "C1f4+LcfI8Dlm1BXwmjmmLfXQ/kgPyVRH0r5vx86KXUALIeuHvjkZCB7VIxKLCiexzeYdw==" + }, + { + "cmu": "3gvE1yRj7U3JuA4ArLnuTur3lh2cZsFox+pEbK6Mdlc=", + "epk": "GI2gF5pc2ysvMkXI/g8wP6f7mG5rVA3/HTKQFIGJIQU=", + "ciphertext": "5rx7H5v/huiqgu/U3C3rvUtk+iMHu3VjHCErADk+vvSeGnRrquvkN3XYh4D7Z6mDBvg9QA==" + }, + { + "cmu": "tBdgcbCloJbMAbNrzadEop6eOELb4LE/mRuMoZHnHXM=", + "epk": "nW2W5VH+PshySuVFvHuwbOsIIDQv4pDoG0sTLg34iLU=", + "ciphertext": "71RXXyzlvQG8g7BSKGqWY6utwqSqXhshmxFeYPFDflCAka+sw84xf2EK124XBfai5xUrBw==" + }, + { + "cmu": "TskKsrbiRfW06A83l3uuPO/2mtNjO5Dlsfm4zYQuilk=", + "epk": "EABMoZ6YitC32covgvCMiugBzO286GjKL+/th3lWQyA=", + "ciphertext": "1PCX9W520mss961VN4sCbUOVtrLe6ow4aEs6UYMclDBjI3ohc6zIxt8swSXqMaQ262maew==" + }, + { + "cmu": "80GX8/PklqxE7Bk5Jzh7JwSJrnGZpW5mKYore2FEqGo=", + "epk": "5e08Crq/6xFLBizVzqia/7BWeXm7Zm8aUIOs32r0KeI=", + "ciphertext": "i5vd8lP7LDQ+cpYyZUrUjwwzYcAfvNdA9ELKLPmn5GaccXt1FjZFYXmSOioW4wCfVFlJaQ==" + }, + { + "cmu": "sBlPrxLszrc6BAIX+BEIURr1wXcHy2tgpH6+w0f+rjM=", + "epk": "TYZW4FzPxo0VKGNuzTTDN4QOTxdmiI1lAsJvhdBIazE=", + "ciphertext": "yg07r1VPsfIZFtBdjNOSkxhCNTfkQ+9Il//Okh6lcd2K+QBHCwkqQ4BVFHKaSJkCH1YOQg==" + }, + { + "cmu": "YzhuH9w4tTiFVOL214nHkcqL9vmZ9ZHCPL2NEvesDQA=", + "epk": "ioNvBjFIsITNb/evQFI6OZfWOrJ2nRY2hJX6OUydo6E=", + "ciphertext": "n7GC+7jQx+VcyBTDd7kg1WPejkvHV//nD48DLVf5t+W6tlmP/8aJ+XbmiX5egS1yx0zBFA==" + }, + { + "cmu": "UudrWNDZ9Z124Ps+FqIwql53C1iteg8r9XM6fzfuYW8=", + "epk": "hm/GKD9HEVz6olVscyELya8y/OPEE4w01ryKR4KYhCw=", + "ciphertext": "oi5tRIAtKFrrNadpyOAr34wvsfFJ1H1c4oVOEZsEzGXCqRbS6ZmJhTBpkVqSaMCf6NwKXw==" + }, + { + "cmu": "FddW6gQvJ6ELHUroRnu8lEvoaWgaNgqA7os0aNXugmM=", + "epk": "6/b7v6oqCSMO+MP9/DaoalumjdbXxXtg25F7MXN31NI=", + "ciphertext": "q9sy1q0+izlPkcvKDDih85dRBemDbnnYFTIbLblpvOfco/JWOBLEnoTcjPWrRbSQKG/qqQ==" + }, + { + "cmu": "JlcX5EMlS1ofQA85mFNPwfr5VFZi4Q1U6/RvX/I/eFU=", + "epk": "m++Sc9AFggWz28PVTun1I+DG669EA4P4jvXLIT5HbFQ=", + "ciphertext": "De1ngqJP9Xi4Z88NxikBmSHbmxWM3gMa45okm6uEMrCHOjKQMCSNv0rrGli1loYZwUb3iw==" + }, + { + "cmu": "91JoOlM2Wj/at9YefmcJAUWHEJjQiMRCFbGXOegGFQM=", + "epk": "J8STZFn9Bz77cjIlsSE2PXjcsfGOtVy/1R/hx1V4zkw=", + "ciphertext": "dCahXR923Mljr60b9p9HUanenYrZTSg497dYlHcI8tehQWWM/+C3+D+2CNtkCYAvwp9Qsg==" + }, + { + "cmu": "nyJHpUspK498TxZy0swKIPTYh4wIxNcqIK9UYJbZM1w=", + "epk": "2c16n0UIJ/ljj0fmDCLLuFnI41i2Ac84V03y9FU9h4w=", + "ciphertext": "yGAWhVZqfvgQ3q9WLIm47ruMm3tWwsazRj2bso1r2IuJAIzLIoFJjjpkzD+V/Dbo/69iYQ==" + } + ] + }, + { + "index": "14", + "hash": "cVVGACt5eBCEAIs5oALXki3gzWMqdDvXM2JFUhCkc6c=", + "spends": [ + { + "nf": "5z3WsOwtNLD1TSC0MzOtq8noPJsjDzFR80c5FS051zA=" + } + ], + "outputs": [ + { + "cmu": "LsTV75LLIGL/voU6epEaVFKiDjmG+0CldT9HPiNuZBw=", + "epk": "iAwoWcZBUeO0EZhbL/xHH+mqmKiLX1FPhekdhs+j+zw=", + "ciphertext": "WRuJKv0/8OhmO+apYTaEBouPuGeJbaNJNo35qgbjwM+IJoL2HTIYrJjjToklGSZd1eO3Fw==" + }, + { + "cmu": "BJ0aK0bciJ6ZhAINTXI31t0L0iGlTW1XJUOIWVYL+Q8=", + "epk": "A/wNMQexNCJpb3qPDymfGKjn9jD8N+6+yoETa9kH+b4=", + "ciphertext": "PFgwOf9HuzaWuwj7Ia+0LtpteAcdnH/Ub/PrMCHzZV6UQEEaY3bBZFGcDjhMbLdzoC6SHA==" + }, + { + "cmu": "Upz8Dpk4cykebBkLNEG9wuG6lgNX/uw2uN6KyP4T5WM=", + "epk": "JW2UJ9n65s2bYt9QLA0TwDxaPg+LLml6/wQfSAKsLaM=", + "ciphertext": "f75bB13stT9Q30WC2ryf7T+/oFZGj6u8LwmI0flIH3MCHulX6F2gh2hJnZR0TvZ5ru8J4w==" + }, + { + "cmu": "rVHFtT4pzd9lzilzDHMGPAPTIcL18n+J90v8x9nQHVc=", + "epk": "vXgfIlCTXjh6ejba4uiEGlxHLWZtdgYlb7WL6nNgbek=", + "ciphertext": "Zw1hqefLaRuXtq61gA01oM0i+f2PCEoNzVPo6jXk0U1DPZ26jNauWduq+bBoBgqU6kiGiA==" + }, + { + "cmu": "/AgFP/ThAOXV+Jfm85E7NDFB54v1Qbbwpyu97lADMGY=", + "epk": "4HPmzP6Muq/80J1ZIflsjSnDMPtWQgftAjcbBHQITOM=", + "ciphertext": "c0hiD12p37+kS5UZWUHEH4TMtA4lJdXraCJpoAcV1rffPD6FQAeVDEr828Y9QMbNUud/PQ==" + }, + { + "cmu": "TMPZ0iEkAHvhL2bxJmt7EzlcNUK69zLMzZb+qC8W7i0=", + "epk": "nyyyZJksUu81i0CT4LCWRCH6P68+qMM4dfYmQh7p2gA=", + "ciphertext": "aUNNUeYXouCABvY963JDxteozSXX7Gf+Y3in1TC24GcbmjtxV0wG1F7CZwD7rTdQ1Rsv8w==" + }, + { + "cmu": "AFmlymGR14iEs/GW2WoyCZJuN8KsCfWtHKPgHvy8tUQ=", + "epk": "0WcZk7wvKQOVTBukVL0fwSd/KskiMZDwlSIX62iSXU0=", + "ciphertext": "ErGsLSj0fxBMQiJ5R6bFbDDPaGFt7f/qlSm6aNg6UIIFNUMWWb7bacThazvVBZ0IuwwnXA==" + }, + { + "cmu": "K/Xc8p2yNi4CRCaMmHrK495Mb4mms1kkOWCvEhEB/BI=", + "epk": "NmqsFegkKGOKx61ttVRhtcnbq4cR2SgkpH5zc6An1vM=", + "ciphertext": "uLwCva2U8Qv0xeFb6MASKV8inxX+7eG3tTp9SUuzJPgpOptVw0xKRlLtFGfN5QX9TPwdHA==" + }, + { + "cmu": "WuHuJN8Qti8qLVMvdbXResiP1oZdBx55cwhIYmTe4Eg=", + "epk": "6IktdOHCD1v6pWI+XyxfNxkufj6MvlOvyEoZFH0CLOM=", + "ciphertext": "yL1JMDuse6KgpCOiRc5Yo0CPNMjkbYw4Ku8aJ5J8aIkmyKAcyoWfy0dmT4XKcDT20yRiXg==" + }, + { + "cmu": "3J2u/E/RXaTq8pwMihrPkQThr2vf25gh84N2Hwx3oy0=", + "epk": "YLxz1QWU9mRv5B53+r62BKQa/hLc25RA/RGweStRuTo=", + "ciphertext": "pI+hl/G4XG7dnTx/nan6fWs4YR/bycHPzJL/ilVqOejtXfoGyNrRPiyWx+kxzNq2b4FesA==" + }, + { + "cmu": "kTptMtIx+HjPPPbsKB96dwsarJKfRJnkViOMifB+FS8=", + "epk": "RH9ZpDVvGpMX37cwo4bFpM2jt2KUwEBYgUArD9wee6A=", + "ciphertext": "v2/q0Q31dY9GrLFNF6INyKbJjvOKE6fmPDganIjYevLq04Eb11J5VEJGcL3BakVbdaSEHw==" + }, + { + "cmu": "j3ZEzh98YedyyPhenTjqytL+mgkHr1OUFd2XPquK5iI=", + "epk": "ON/edBLp7r+W3JWKARF/LA3Kl3TykkjuYrAeeAnK4ls=", + "ciphertext": "M6nClHU6xgEfIc/iX5JpLt7gH5NO+4BsJVASYf1XAXOH4IVDXfwCi3g4rdciz37ZqXZPEw==" + }, + { + "cmu": "6IH4uRAvOlpAyKki2bEpZ6LuyUuS9XnAvuVJDDZoPwM=", + "epk": "AjI5cl4l2E/FeFbiQ7pensyyob5HbSMdrE9E3WI40EI=", + "ciphertext": "I8J5y1V2Wk9rCgqOaZ8lxZM2hhzgs+A6JyRlCnEph6K7jU/oY8Kla25p/Uv6JchQA0BEzQ==" + }, + { + "cmu": "Lb8FGpotlpOmwyijDyGr3nFe3Um11VB2ODjXkf54pV4=", + "epk": "Ud343uLgWEJh2WH+VDLeb3pRbsTHYGwgOEXWR2ic2ew=", + "ciphertext": "+qlAkunefusdVtAn+rY7nqXl0m4K6bsAQe2mRwV+NN6yWtef3vNFPkoyIR76ge5Ea0o0Qw==" + }, + { + "cmu": "BPUQ2WIb6zaitTSqb51jK2NK0CMJfUxDAHFZO5QDxTo=", + "epk": "W9VwjBOTrQ+rK1ZNACUWIvbj9w2oVsVrjWMB4ATRIiI=", + "ciphertext": "V1gd1dyPHrImXQUymDxZzHQxBC0tKXCZSi4+IaErjVzd85q9rzyq/6RpHi32BJhIp4Neeg==" + }, + { + "cmu": "xjj+59gejeugcT2FBvsjxSXGWqK0ny2S+v6nghp92Cc=", + "epk": "E8jb/VfMc2tlyA6qW7QWCq4G0f84TioFBjsFXQuR7Lc=", + "ciphertext": "bHKCbxbxIUI14H7OoG3EFBHZRKcU163nZ2ZYyrCpj49N7SI2x2cYJyDuoeTrZGtsyaCyFA==" + }, + { + "cmu": "RQqXTsW1FMW/lTRv+Rr9apqpfW1iQK4k7lcFgeo8Klo=", + "epk": "GxHgXGEwwj8XzCDvBYV4+IazELD4RuHhiyiS88Qq4TA=", + "ciphertext": "WLSwRjNpEsubv6lnMogMDySWJwf9uLzvKvoQZwQzTVXC4HJ06BLJmfPby8pdkZCW5vWAAg==" + }, + { + "cmu": "DvZh8extB5d4kupBGUwh+yo8E3a+PkDG9MyK+4iSETA=", + "epk": "ymOffl6Bcq2Kv8SDpUnRuVuoj1np79P41XGV5WoZvhw=", + "ciphertext": "/hili8kxnTnNTw+vehT8bVvdfEJymfsguSmSxeMIoGE3CculD/lfJGEif0dhpoVSguUc9Q==" + }, + { + "cmu": "b68fwHyVXV19vp7wAvTNbV9nTC3GdwMVTCm4iMJl41Q=", + "epk": "h2PQjjCTqjMwg3p2PTMtsIreC71tRXTDn6j+mahIxCo=", + "ciphertext": "0Iaq2fNHEAcFkLUAnqTPDBPJ4Y4oqYTYE4j4593heUxWUhAl/WxW8KwAHw+B7cr7sF5zrg==" + }, + { + "cmu": "4XLLkrYu2t44j+M9RQByPbkrvMyQwrSAFWWf2wVoFW0=", + "epk": "ik/s0wIFhn2aqTExkOnakao1eeroobblRiBS++gm6Bo=", + "ciphertext": "dFuFisP8IzM8qqKZFlDwOMD1VKVbviPKs+XrTmD3QTtSaMel/ddATHAE/9z5xyKL90/Rrw==" + }, + { + "cmu": "mdID4wjQV0uNgNuLYQVLJxWpWZ3zaGglHou/cZw5cwY=", + "epk": "U8dpM3x+mMHu1VXPbwqe4iwb73GJ0f9fAmwvUki46Bg=", + "ciphertext": "THUAKeWxmy3F3t9SsCceXxNNoPodsRFHziJC2FBibkQ0SbBQwNtZtnBsUyJxoBmiSN6utg==" + }, + { + "cmu": "oejbZfChTlbPlBUnGr4wyXs6bqjMLR+FlAh1tl8GQkw=", + "epk": "zFDFPddzLHB/z/WisAdAXZaa9MyXj+7hIAnyAMse95c=", + "ciphertext": "ZfkUdi1ytuWrp2+zzpV84YLF636e5QhH3K38Mb6YJTsZazTQstd2uVv2zTkvbmgFhBNvqQ==" + }, + { + "cmu": "yofq+nQxaQ5Fx+m6uxmlDvkcTuGjx05SplNg3SpEfGY=", + "epk": "Ck27evJs6j0eGke3HdLs7C1VUvjUoSaM989xFSP31xc=", + "ciphertext": "bADKwFuyyX6V+QhT/+hJt05g96vBARAbj+jTqsuvfX2PX91Gtk+P8DNCr14wRzQCD0azyg==" + }, + { + "cmu": "Qw4sd+09EOOfXwbT2xHoanwp2pheuobVXrNRSKBS3Cg=", + "epk": "EEa3Yi/W5dfqaQZc9VRmSWlUiKe0tPjmPIL4rd2fGpI=", + "ciphertext": "YBJPO56KsrGOqy8jNqu5zJg2VemBYnrD53E6JOtNIBFlQrAnEYJ75J/NKf5JVib0uR9d9g==" + }, + { + "cmu": "n+2Qg/aK1iGlLLdyAOWSBMjKL1MaHd6OzpEHKi6paBk=", + "epk": "96+SbwOZN0b7ETKHFpOd0g1QIc9gETdjSJfrLLTIxuI=", + "ciphertext": "pcWPjY+hmO+TAXLA06aO9t2pvnVdemPBIirSOU5IkWZSIkV6mkYJJReFYLuoi5eRvH3mUQ==" + }, + { + "cmu": "BNQgUg4vgnQDWANcVRIonF2WZYnFOMxU0CrBBGXDmzQ=", + "epk": "CxnZVOxsDiOpl4SOfDsI+q4pI18+H6nM3W1+cotGCUs=", + "ciphertext": "Njk/8MWS+Ewv8So9reeApZ634Ozc+28bJsm2ZSCeZ8MeG1f7EE+zHnqeKRA2DC/vwSF86A==" + }, + { + "cmu": "cFtaZb6n3VqcoP1OZfNgdrX95IoskVAs4nNk4QYpyjo=", + "epk": "apweHnBOj+qIZFoUdC09BG5tpHSjTYM1zsY2nE3LgPE=", + "ciphertext": "m5HDZw5Scf6NnYNdFlMRkS51jaExoQ0OACo0H4QiMa4dycuk/44Sjuz+spj8neFSFvRTXw==" + }, + { + "cmu": "J+iOmxx25SUOPeDKtPpf3uCorHQY8GX7KE3opm5F9RA=", + "epk": "mNxWH3JTFsQcHfcVRmryxlxdp4cRTC09kSiGHTqHDTU=", + "ciphertext": "mynkvcxQ2po+XLXeK0J85/HA3Y8ewdeoge9OCUZKBUKIcdH1TO9G+JIHJKSq/LVvn1Oi+A==" + }, + { + "cmu": "P+64gUFRhG+JHNZDMkThzsNLRrvRg8fKapJfHp2HjRo=", + "epk": "P67P0RyfJ18LnFwCQkGGB6xuahAQ4QkQsLcS3tgFOeU=", + "ciphertext": "xtlXSQmFmZVu+qZ6+Or/KNJkADsKtwC4xY+yFBmoI0kAIX9WDS97yt4e64QZ2626YxnYJg==" + }, + { + "cmu": "STXcvuKFjk81O0SchLR3k4Kq7BJTCTeonn1esTdnIiA=", + "epk": "pup74DIhstec1Zg6ZdovHaPICucw8ngtTiQuIYd2Oqo=", + "ciphertext": "dAb8b0LCKpLytJcck9PZ1zb/JiSdFq9CUgxsJEWY1h4FflT6TnOmBDFiqg8w/8iHZlLOsg==" + }, + { + "cmu": "2ANoqGqjKKRoSTqIXi2IFwZXHq2QoHsXN2PexkcEAGI=", + "epk": "UD7XyWKwUhmXqPUiyIXaPzreEISASwvEqTtfsUcyysg=", + "ciphertext": "hXDVDHVeRifFevOJK6OoNN8Dacf3vIdMgDjo+bvG2yPvFML7Q3R0Yq/m6JRZMwPBB3JRJA==" + }, + { + "cmu": "RTNnL948Wc43BAv4uvxs3ULHJEgytJw1qJetiCakKjk=", + "epk": "+JdjNwzpot7ogtYCduqACepCHbA1YTMvB57PyLWzKBc=", + "ciphertext": "dbvjtZf4D+8dlnzIHSkTQCcsZwIQUI5qi2SUTtLZvqIT5GpOX78e4LIZM2t+kDhekrob0w==" + }, + { + "cmu": "nZw8awWsVz0OQOp/VjPH3Cdgwkyzs+CChBK4hJfAtjc=", + "epk": "FuUsSTssCXfA3VO9edE1TwTJuCEmlRDKzMy1hiCAeJ0=", + "ciphertext": "eVSq1pM7eL62/AnuLtGxrkkFmlVb6auR6P9Wv33xIc763QO0C+ZUlL+w1fwcgl9vNGzQjg==" + }, + { + "cmu": "86hcPCI1zQNZp3bMPqkGZiW2JR/mqMJHA7sKoO9W8Gc=", + "epk": "lrAAfXN0zhoVf7mPozwrDZZjEina4+OssR+cRBBeKSE=", + "ciphertext": "Mm0DY8haIx9KQAfRRIE+5+sHw0IWzCjma0RluujUPptKpHyuvbUk6zdTgzWBwWwEh+/YXw==" + }, + { + "cmu": "yUH03DNtsxGGJ/jOIk1T59kXgLm0MH27g7aGZ91C1TY=", + "epk": "zQLSY/IxcEMp47Kk0Uqb/FNm/yW1CPIoknaBRKx73EM=", + "ciphertext": "1NJOBK1HjHeJLqCaU9vxnP+citDMr3LlxYljN3TPJ8n91qLBYwnQoU3PjQLNMmF60V6e8w==" + }, + { + "cmu": "BocqyuPvOWo3oojnuYrFLFJWwbuIDzx3nL6p4eEvPRk=", + "epk": "iY/zAvH7QjFD89vgu/CZOe5SPGIUOcgx97F9fA7jALA=", + "ciphertext": "vJMydLdJsrtA11idp0gTeVDLKZfEzrC3eT+JhW4+2N7z4nVqBDjv615GYEjux61T4+xpUg==" + }, + { + "cmu": "C5XNCAHVwXuhcxIfBP81ZtpnxyZl+La38KHTW8+ZNlc=", + "epk": "pmikpCJbU9tlf+ajAfba4+y4g0DnZELkYKmfNEuFToM=", + "ciphertext": "QYO3uU/KMku73LJbWQrukAlTcCD+CLhXUwT0aSRici8Ek+FrHm9zrPbVV5CvmrHUpZYC4w==" + }, + { + "cmu": "iCw2UiNRU1o+xuLVz5Bd87TIC0x5NWmcxn/KxyAHElI=", + "epk": "XikwHxG+z1r9QwTHBVs5w3/0p7MSuFUf2V44AKQM+/E=", + "ciphertext": "vHBhkeAt3OiMP71Bi7KB4xw/xE3Bh1O4OlDnJWWL4nC18wLnhWNruUEzhfSJ4YPBCHxaaQ==" + }, + { + "cmu": "TWlX4CrUOzDviS8AX2TwaA45sMY68l0XS5j3jPpSuz8=", + "epk": "WI14ugwwabnbIpfrxpT1yETSQVwYhCZg++qBu7KrZdA=", + "ciphertext": "svxglr4lxXnCmd8bvqvpCCi82bmp+8ovWX5PaxP3j8VX5dGfGAN9x3UekRijmUngECXOfw==" + }, + { + "cmu": "b+FbvwfrAEW+5b0QhvJSjjl/3yn/6EHGouFX6fPRmCQ=", + "epk": "TmSZ/6KwoP2jbxaGkyH6N8clofq5LPZYRoLGdJ9diFk=", + "ciphertext": "tzwW/ZOfnvXrN9/6Dto4JrdJeyWY/4qC5BCOnfKIufqx05/p0xlnHL+k0kaaDEIIuCzS5A==" + }, + { + "cmu": "jyqx8FXwwfRqXfm0c/+C6Zcmwi1uQ34lGsoFJgdgZVo=", + "epk": "WhnaFVOEC2HLuy8yzmsP7aF1DzyGy19SwMs5J/h8HO4=", + "ciphertext": "c6OsyKjxRRGtO4x9OSxG61Tp1sgP560bzCZ8RIho8KWqnR93YKxbt4m9k5ok5mfXjlX2IQ==" + }, + { + "cmu": "EcCLs2pt0IQrEosJ5rLFv9XlDlWLyVn8jyhVT9+bAxw=", + "epk": "mmGCTHiABSlH9mecsx7PdxryaC9ffM5uf7wIW+hqeQI=", + "ciphertext": "i/0KGRycZ8iGl4+kjQwGlCPwsCvdctwTJKCov5M5hALyQtNmW/2iIPOv8Nn87ZdPZbrs9g==" + }, + { + "cmu": "wXigUvrrWpy/udaa3IbQJBdg8JPl7KFLrVyl/K0C+2Q=", + "epk": "LL0Cy2+Q5H1eTfHO80OyixR8ZlaL7oviFRAZ7/vpsZk=", + "ciphertext": "ZxSc0Ww/cWTacC5+MCy8sZxHeiA1CPrWOxHcpcl1FIAKdU5i5XNPF/EoWYBZIyyHRP4w7Q==" + }, + { + "cmu": "zd55yo4PFrv0h+2oQDVyFZMY5S3eySZe5TybhCeWh2I=", + "epk": "U3LRZdBE5OQRtCzMnxXoqUVn+Q7ckbyaE0Y+hCNJT2o=", + "ciphertext": "YrZvBrEbSUzJajAnGsIOf6rDzWH1B13//XRnmGJGnnsnuz+ql8hISj993AEyDNdcyJN64g==" + }, + { + "cmu": "K9xHSYmSVYzMuxugcR0PTdStGbFc8CnUFCn+8oXA3FM=", + "epk": "J/EPxvVOBhrVW09XS7rGh70gV3SQV1anzcfsVeZ/Fp4=", + "ciphertext": "q433S/o7VKsGwCRc1dg4QngduA7SGamjhLRWxP7BSD/oYxDzgP1AaH1i3+yGqkpx4gztzw==" + }, + { + "cmu": "y2Hln7Vp0oFbsagAXkdtoM2ejMqUfuG5UlpljLxiEQY=", + "epk": "wYe0Taq5jnwAYHK78A2lGM8AJE9vGlgwhYvGRKLGlao=", + "ciphertext": "WRiBM/dNgb7ycIF/ki5qMDodzAdHkWut478lzvscRWa2V4qV+7q3qdUGcveApg9PqrswLQ==" + }, + { + "cmu": "MPZP9RB8MCdE8p//b4zsAKanLIr7RZ47/WINoOSHB24=", + "epk": "XO4PSaYtr+ev+z+WpS9E0u9lz1Y1WSqX6mFaXNOJRNE=", + "ciphertext": "ybOBCWl13HalnDQbI66ynN8rF5+T/AHgIL2URKk7gd0QxCRb6Lnd/CUdRjlUpRKS3hLLMQ==" + }, + { + "cmu": "sg+333vJZnmFngA5r4FjNFVFC/o35Ef1umJ5Bqtq9GA=", + "epk": "ZBD2qhZJCBhoonTltYTjUYKGWFHcZ16SktDQAB4Nstw=", + "ciphertext": "H+ZF9GzIMV3lfV7JRCjlDuLXFJTE7z30hnVA6BQfwJfDNvWtXrIfY/HK6glKtPVrBe0ETQ==" + }, + { + "cmu": "0n8rqSZp1X99WzsnxctPiEtHq2ukJi4PjQ5zy98J8AY=", + "epk": "3qCZKApiJla2jLQmXKUTHcyEfgObAhaou4HhyrFbI9A=", + "ciphertext": "ZwQ6SfU50Y+hrgRBpVsTsy628XA2QFq8mW/w5xI25CP1pDlo6YgSNZ8aYBp2DDbJWTy5vw==" + }, + { + "cmu": "wZi6QCQeVfjlCKgXgTB8pkTqICQCmKNL6Ti7NuDvR0g=", + "epk": "h57ODkdofqoKZFLt5Yb5E65Jlv46/EkXPhGRd4ajgwk=", + "ciphertext": "uZ7yLPcubHLtQo5ZpcVzwwPjN+4PeLsPNxtCw7vulq8W27odFEEGQLYoTpPUhgT1Zvm4Rg==" + }, + { + "cmu": "egHI/eP1iRp324kSvyK29V9FRnxyo6K/AXP7w9szrT8=", + "epk": "17b7+VaTmOKt1hvaLk9P53nwHextXUiHO2SIdLDMuCA=", + "ciphertext": "1zjgjLGWNzOO3lGhmAHAzBneIFh79W7nmk6s3zhWto33HpZI8jZF1snZzQHTn6OjTNm9zA==" + }, + { + "cmu": "PKd9tx9HM4DcRydy416c4vZP4GuNs74K0588GIHSuWQ=", + "epk": "yztu3fzH8ReG4vF43mdX4eZuu9XZSuVV3liAiojhXUc=", + "ciphertext": "EvjRJ9lH78cmutQ3B8DAKdA8l1H5gO+qgBLVVfZ70KN33wFtu6FBk5rQRqZQOCYYZBNLuQ==" + }, + { + "cmu": "EGMa6CKFYMuQHegvaXDB8qcP8uJlWOpOFto9+/rm6B0=", + "epk": "eMofU6IRcg9a8SvQjmzg8qwkhGApGtjlkLWnTxxEKW0=", + "ciphertext": "DyA5gLzF6OOcJ3PyLQrw3/HAQjJOCi5U2RrKwg/jJeDxQGiJ/RdGBAGoIO4Kyo7wpWvIzA==" + }, + { + "cmu": "InkdqkOk3yPUC2DvNEsxAZo3fqcJ3N00dGCqjhHkCTw=", + "epk": "WqS5qKBUumPsfNw9+bc6f2HUF3MJts5iNOILADTFKq8=", + "ciphertext": "Z/DEzEC1N/3p7YNbxd2iSPOP547a9NgzGM+YObCiaEu1dWPgM6etapmbDeUJ4lHCddWPAg==" + }, + { + "cmu": "DjZmeWJuDPl+iPosX9TvcXhMluzzMPbYvvnjBXtkuW8=", + "epk": "I+9wfZH8EGmd+k376FEToA4ilZcxfmRfOtNIWYX8TDg=", + "ciphertext": "fnRp7W179mrml3Bh1xm6X7AAkT7tHgcwqYCOO8kjZcBb/HOKKeTmgneKx17p8K491I4P6g==" + }, + { + "cmu": "wVFc06irc83GTepqri665GVzvakwx+89d3O1mLF55yA=", + "epk": "G8ZvvxZX5+63GgsVWV7EVSQCj3ibYMu2mbQ0ddr8oFU=", + "ciphertext": "ej7NCw1mQ6YRbqkzmZP6YK2QfN4Inw84spUEd5VfcdjzX65AY2EvV1ut7KgQfypjSoXI4Q==" + }, + { + "cmu": "ruJIQk757uBVbakclkRuV/K/W9WcN3DNO0vqURRjXg8=", + "epk": "rRKWmnqwt2qXeqYWt+3hNHI1thGaPs/DdZUzIAI28gI=", + "ciphertext": "cue07/5juoj5PjcQY1fG6L2jPaBmBhbIF//UNAtA23zP5905blZMXPekMRrc0xbdabog9w==" + }, + { + "cmu": "W8OGLxzsI3nLfp9Wu1BgOASAgHdNbrt/iLS2hbvQ/Ak=", + "epk": "MFCpwTPGljp7OXBx2d4S7SCONLVS2BW1dxJGts8GT9A=", + "ciphertext": "8vhlm7tqonNWF82sy2hHcN/hfZSTWvr2zEtG7uR81CpSlRwvLcPUiBC4F+3r29CO81q9vg==" + }, + { + "cmu": "mfJ3wSbl+vwzp8FIdigY87vYPZ5OPgQ/g/LTWLE7MxU=", + "epk": "k2mZt1OcIPtOVk7dHHePQJ+XxkzwS3TCGJx/kk3/ghI=", + "ciphertext": "1cSEPdq5WUSMVO/JyqFwWA0lO7/fbQ93K0w445AJou+FJNM+Yn+e7nxaqq4kIt3n/A4X2A==" + }, + { + "cmu": "RgPmDadACh04ATcIfP7kEZbQz2g52SfFfeK5yxFEg00=", + "epk": "cKoTS3OZETJ+Rs3voOotoa2dLZZOHO6fCAcgys3lIrk=", + "ciphertext": "KZ5Vb6ZfWrjdUPgTfRHbFdUOc4gNbBx2wi5RfOsh0oQitY51RotQryVj0+d5NPlUK4DdQA==" + }, + { + "cmu": "lBz3er3EpYp5d2bxNF2pnQvgaaH5lV1EJ6ENEZC2SFQ=", + "epk": "Lrx3cvqtqa6EZYTV7ABEn5UT7LMi5Neg+hpU2TwiH9c=", + "ciphertext": "qcf8MZ1eOglmuLHgwFaCbwyXTBlBEuVsmTzUDaplvmIP8fjLL5pIc1N61Jnd4V1oFjdhUA==" + }, + { + "cmu": "DgB05eu4HdZAn2FQt0wocbKxZCkewiXerkfNsdR6wGc=", + "epk": "g4aIiQzvfDzxyrBHyYPmrbOB2jPcTSjybKLa3Bx2goE=", + "ciphertext": "1QYdpEQuiEbIwyI3QZf8uqDWKa+JKlRB2Vj2gUbGoO+7VZcXTNypKoeuUyc0u/PLuPozlA==" + }, + { + "cmu": "ua2LhwqqAzEK2Q3YyHXJPveMA5TIcIrw54GAFVDYFEU=", + "epk": "MH0SZn0XzlVfVhWCzletF5D+2IInq163crDtWj6/0hM=", + "ciphertext": "H2LNUyTzIR9uQ+Rl5HL/FosB4V5BNRxnTNUUGwQgqnlBoD4Hr8Ih/OIYFh0st52Z1Gy+Yw==" + }, + { + "cmu": "x/dpWxMod5xVqOHV55kYP7c1Gjr1DCOZHB07oX3eeFY=", + "epk": "6eRmBTg8zqHtxpjyokv2qkK3wv1ok4M75t+psKSFWYM=", + "ciphertext": "S3Fxv4NSvOwe+c21hbkn6C2wUCrT8WQ1BfbndkusMzskxuc9LOaYRzwp81UC9PT6+hypaA==" + }, + { + "cmu": "P0pGOwmkEvqH1bptf/2EDC6vNwUSBJ6B1PyILY5JNiY=", + "epk": "69pvh6nqGJRR0XSSMC3LZjFvUPK7V05nV8pLL8CnUZI=", + "ciphertext": "We2yQWqibkH1w/aFJv6uCU52dRk0f95sZphOkP6ExfQ9nRN9bB1nZDXmcAGG+hsHMyY4aw==" + }, + { + "cmu": "xYdCc+heqMVw93EOOnuEl/cratIkJTfpolF/M9xZ0D0=", + "epk": "E/QRMOnU6Jgpgf13u0a/xq8chZwmzTika670nMwZUkQ=", + "ciphertext": "JLSjfCDu/ETPmh1Ao3mLJLiJITCDwfstASTvxTlME4RLGjd48yweyxEO1KUf9bEj14/b6w==" + } + ] + }, + { + "index": "15", + "hash": "9M8aXeCEuT2YMxw9ZamGT6W0z5/jWd1LZ2SJkLTzuDQ=", + "spends": [ + { + "nf": "1gB7RkAiUYZ7/HKWceoFDbDK/UTQLru3UDYVKzxEkrQ=" + } + ], + "outputs": [ + { + "cmu": "qM8yRfh3lii5aI5ej952zCyw8C0UoiJNAmNxRCsOSyg=", + "epk": "Hw8Qm4cmzvjKrOTfwgcV7iB3OVtnujsIhIZBB3klFEA=", + "ciphertext": "NsnnXqBC3t/NV3I+cj8CcJY5tuPvcBWlbYijp7KAlprXY9NPGMLK5YXHC9BpdKURvu8Ihg==" + }, + { + "cmu": "9hott5HpHO+kUXgU4/E1ul7bouoBkTCzaDA3a7Vdv18=", + "epk": "+KiL8IHRYRROYX/j5FoOEQ5HGk3/fMAy7Ragyik4HmU=", + "ciphertext": "+89BaQEfGTsEQZW/h7M8Xx757YGLCFW3WROrGlGUF5B85V3LtspxE+BuguFUHWHNvIYa6g==" + }, + { + "cmu": "QG4BFbdAURQ9InD+UwhqM2z4ApDx4of57lbG5OjnlEM=", + "epk": "kmuKKQNNhsgkZXOcbWbhi0QdYSCrcq3G+LCLNWvtNwE=", + "ciphertext": "u6eNmiS0iUEtu+mhRqVEAN6uvKduF0/4EIqp025DFbmaW+MBUlQUKDsO8Tg+mDm/bEzsvA==" + }, + { + "cmu": "QLmP6NJUifCTDqmyZTiLCIr7zwLlPS6fEuzGqMHgRCM=", + "epk": "oj4ojBgZC8IiOft6x5pOJQazLq8sdt0d614UUlrUO5w=", + "ciphertext": "EXWaoW47jDfxUZXCx2BNkOfh/yFX6fn8JZHYlR0Zqu2/X0Gd9D7pG0T4UCyJMKz+OBz8PQ==" + }, + { + "cmu": "G00rwcclaHJGKWT4eu3PEyK0SH4dfeTTjvKUcB3a+BQ=", + "epk": "Aj2cqMSR/zslD0lb69cAXbV7vfkhIplolYmrdTnInGg=", + "ciphertext": "Ln6JivHXTiX4/TE8eX+3n0uSWUEMKJ57ykwhypDTo7sSrglv19S4mp27B7tYXvqgP+uRyQ==" + }, + { + "cmu": "H19QCX+JW25Do67AkoBKper6HKX0GJmV+mexHm+3lUM=", + "epk": "LQe04vhghxz2SbeQiZBAy+/SQDtsVfk6fm22FM03JQw=", + "ciphertext": "piY/+3jEzQOsBQ9Ik22hUc/QfbDPswaRrJcvTyZc/MwhfvJs6OiZyGBlFWhGvBHKr2NNmQ==" + }, + { + "cmu": "ohf4gR7DlhY3ITH+m/f69X/1OcLu/fXz1+ib2vnPYGY=", + "epk": "QMIhT1lZBl7FLLgb5BfQNdPfjzsQPyhEpdgEnc4dYrM=", + "ciphertext": "FgRE4h+y7+c/0cr5spxM4REv2WBsptKI62Psv/MrZOFJ5wlh3oxEeU6wSqsetbet/n3QuA==" + }, + { + "cmu": "V6gE8wc2J9/+maxYa3aRUE4/BuICnyYyPMqFzfeAFmc=", + "epk": "fkzRd6Or4bffQ6bJyMPISwkXSFah91N2lnzGE2Ms200=", + "ciphertext": "uNgvPnmXauV6yxbYZNkjkm8S3S06XlJxvmYb228KyOmfGlwPPOIPdG/RPQUTTC7lEQ1feQ==" + }, + { + "cmu": "Y9tsWIgqtekFUk/A07rTFkIBTG+paGKVymd7Jy+emCI=", + "epk": "wqwfDUomZDhXkUxzT63ke1v7JqDG2a9vHT00rxW5Wac=", + "ciphertext": "4HjcLV51+KdMfOOiDgh8WFKBdEv3gVzY/A7iraICrCHecg+NWXyaVeuQ2sp7GF9t+Ar80A==" + }, + { + "cmu": "HgNrblbWPXFi99Um3y3MkmTF+xHaL99rpGcxNOzK6wI=", + "epk": "zC0GF9TfjqXwsK1SbERo2C4eftsL9d0c+tVo08HVoR0=", + "ciphertext": "o6KuP09e/+u5kZrmn2xkLet3jpnU01oEQY6AkwP3H+wZWgBJVuFVcy9aYmJh8A4MH75Mxg==" + }, + { + "cmu": "oc8SteyA63z2Kilwb7xO8QEXmDv9wuuc3bxt/tUEygk=", + "epk": "nlak5IoTgAs1ZSMUP3TB1AG1yUauFX1G8DDjxrWpl9U=", + "ciphertext": "gsjTgPYhC/MKNAwhpCOnENnXsAhR7OdWnzqYpnqjb+A6r3uPoq/FNL3ACE3vRg+f68a8Ag==" + }, + { + "cmu": "ReUsuUV9zm/5SRec/LcF3wETmAaDNURlDxtiUmdKxRk=", + "epk": "zq71IG4afxGQKomCiqe5pqLXAUmzLRiZEALh6XCQBow=", + "ciphertext": "Gq0zhnARCNvJaBvdxoom4rtv3ynaKjKZcS9y1qdNas8Kh1AjQfEwFTc1r9Asa0e3K6TEMQ==" + }, + { + "cmu": "M2nLkSG6c6/e0sWzfHF5k01X6fQc5A1uf8c6E4wXJUQ=", + "epk": "nYI0YzLBSHx302G275glumZ4vgOo83neK4JWRvQoruc=", + "ciphertext": "+93rZi2Jk33hyPckGfYWP6BXc7lwNzvQsdJ3YMwLBIgfb6Yj9MYzw7JC20uR2WF8wQ+tMg==" + }, + { + "cmu": "IM4GxXM1YXpvidA5TLbs2ka/iwjR03PSPHPDiup9YyA=", + "epk": "bE3mqvjTHmiFNdkKcJ6NbwbCcvSSA10dZKBv7qcxyMw=", + "ciphertext": "iATknL2QZVwOEKRP867/nWsiVmSDX9OtfVyRB/K6JYZo+Nq6GXTHJ7LuYGnlw1CoBibbIA==" + }, + { + "cmu": "UdWUvgdluJaMCGNnJcICZObKHRuT8QDdbJL6RZ4ykA0=", + "epk": "o03BYn4QpLDEXiFypgVPcVE5GwA66buZgDPp8UnxRh8=", + "ciphertext": "lEmZwv/FFISndk24BOt5OBD3VAyIKfMJClvCppeeB+uwJ+rXOj91ms2+3W2BjluQqAhs5w==" + }, + { + "cmu": "OSxdxF0wMQB6qbrNx0Rl2zrwN4bBlKIgtGJhrmm66ig=", + "epk": "lpFU5D5ZkW1Q9BzGweFVC1DSVeiz+hJEEA7e7TBxnlE=", + "ciphertext": "WDNw1Lojx1mAr970dxSFe9Q9+mCqCAWvbZNEBSl6xikiuDonAUJ1e8v/3ivgJb9uVoSbMg==" + }, + { + "cmu": "PTnSUjdWlQ/4e6Eo4yF8LX4774iYB1hdSAzuVsyKgDk=", + "epk": "63cXp+hZxyEBDsDo4u/ZSs9SGzpb0mzjdF3Zl8Ci96o=", + "ciphertext": "A2+DepoRbT6zHok1Cll6oXwVvFMlY7Tn4tSFYfEFL64JmX9cQvf36MmtUPCF1asueAkoVg==" + }, + { + "cmu": "5U0L4lspUUZRUAUdAFiymobXMD7T9aT2LngCOXummEE=", + "epk": "8et12nbssypup07FJ28i+ZiFTFZSJ6PFUK2BIN+RPzU=", + "ciphertext": "Eg33FpJdjplFLoTsQB5L/TxUtWE2wfTVxWg/AppAOE58Gyhk2i9rxQ+scyYL8Sr22Rmcjw==" + }, + { + "cmu": "xd52s4NXmAEC6YRXhnEro2uL6M+hnsTjGbhQQiPPFXM=", + "epk": "cLYQowkd7jDs4QqixuSZdzx4ll5RDtsPp6snZ9hr1F0=", + "ciphertext": "jln3bCRP5xYg5VDaemE2udO1Rs11eOwLroT+9+9seYTkqcC/ErAvG32ZXSdG7c9uoj/x4Q==" + }, + { + "cmu": "qk45ysYb3ZnFLwSYgzB3gNFkJcf/HnsBUS2goCq0Uyc=", + "epk": "lZcg1U208IsKRnUeFTvx6O9umWCUluA4RHE4F9V739E=", + "ciphertext": "4EZBVvLtRJMUJIXBJDdJ0Gs00FeT9mDp1g4QIodzJz0vK3HoygSocV6x+0l7d4K+M2EIrw==" + }, + { + "cmu": "QldZ+PXRkTfw2mp8MPupWiEQF7r1K4jQBr0zpnQPdjU=", + "epk": "yyO5zK6/nSlrwkm9vwvIZAIc3HCqIHPMgNrwm2tt7rY=", + "ciphertext": "w47ifhRcSmnrZref4LsqGH/jAU/PbtaMR60zq8ISa71rsfbs2ALkgGMenUKRy8Xhfn2SWA==" + }, + { + "cmu": "Bl2SECRChNGs6wCsuxMEC7HGQDLlyhSxafRtMnb7n1c=", + "epk": "ZvagCbobGmP3O6CW3DRvacymSVHQxBQF8FOuhBZRjSQ=", + "ciphertext": "ztxLWuHVp2N7P4YY+Iz5mLvPlcDw3oC42SX30tOJqBaNHKABmTy13VM3zdUAWMM0CmBVRw==" + }, + { + "cmu": "wJEksX8Jph3MImNDKs7usd71p1nhysgMSCQoNVNWnUM=", + "epk": "Cfz/QqzQPAGLlYDT7blhihnPU7WLLAXlqJ5OJR3Vg9c=", + "ciphertext": "U08OiB/QQwuVKXv8CCdUWQvHZ37owXRipS/IzV/3f3A7mzlzI8x4zOtpF2+s1tIGEPhl0w==" + }, + { + "cmu": "cFvkDgzZn3Y+7EyfuRDRo1N3+9pPsIXhZsNF5/bdu3I=", + "epk": "Ehh4ua7rs31TiKJrvMfHeoFHq0zL1gsNjH2fhLf0tkY=", + "ciphertext": "5RlJaqjvk96DLDtok8IY0nsmMJGNTt0TROKs9zk9pMW/t/rQ/GRHjfmpsJiT2usSYuMuKA==" + }, + { + "cmu": "2WysskeYaJsURZynApRizLQswGdY91rDP3qWpiLwSBY=", + "epk": "/o3SbESlPBw1qSiXAcS7wnDLgUx55z3aLPB0+NvPaco=", + "ciphertext": "IPpMY3h+RxMD8XrgOmonOs0yv1HhsXVWRSlELLPWRx27bYAzWZ280K+nTfpmU2tzlYKMBw==" + }, + { + "cmu": "savtYlOB/8iTrljn5c9hTI/8vlDvUCtzblDFlSHezwM=", + "epk": "p5jj1/F/SAEzxq+Omy+DZ1d9AeR80ct0utdT8kVyTjg=", + "ciphertext": "yLe1oRrg91j1zlauV9nkUWRBiBCRiY4fB0M0owrgOMRh8nal751JVn/VtHchI27/vIng6w==" + }, + { + "cmu": "GlxBK/KvYBlI2QXGcF5RjQ5qwUDQWhRS5nvXwYS771I=", + "epk": "AwxShDRlmR5No6jJRu/yFZJuz7/43VUertUaCT9iNaU=", + "ciphertext": "bWfVy4IK45fDp2ILXxYLoAaWVsII8tx3zeb2YsdDlB3vWvo/Jx99lmTnlCwErwZNZDIOMQ==" + }, + { + "cmu": "paDANGL8mzYDtrXBiYDbZ4rA7BbDnR/piGxgiZJotWY=", + "epk": "tBuH5yp6kcWaJxHfJ9czA0+2ssW3B5NyhVmd9M4/0FI=", + "ciphertext": "rh7g/pFRyB3CBvuni+0M+ebaMQPaWPjnGukxYfgeFbC9a3D16wqX1fPKlWbLw6wKR1Rk+w==" + }, + { + "cmu": "ldE01uP5vKFhAwn/Txb7G8qWCjaJOwAjdY88WyEpoT8=", + "epk": "7Y+wRyBkbZxrd2K0bSJr+Ww1VA7FMpeB7zscI6Zvs5o=", + "ciphertext": "PWHE1TYG7zVWlcNPGZVqO3DQNmpNCqMJkDjDS7PTDcbpXbqodXNJfeDeZ01vZgEzUyLmjQ==" + }, + { + "cmu": "Ky9dIY79KdB+3N2UiAUaoSTfvkQj3TiA55jx904pSFo=", + "epk": "0HkIbpXdMNZEd9ju7KlYqSP5BKuF7aHXMqpStkTP8kg=", + "ciphertext": "UrCDdSr2HM9DwkuowH9MJf0GbxOEY4GiPeGIgJAorgfEgmfp9X3/zGN9AsryfsKXHtCY3g==" + }, + { + "cmu": "hI8aef5FAtnAo2a2OqdsXOkqw/5uWfMTNx0CCUHaqDI=", + "epk": "c1E5eK6z+twfEbp6ee0bwrqGqiScPEYBFOBeghGALJc=", + "ciphertext": "XIKP6G5nYpH3uTuNJqTt3Pwnot2+iekghZR/pRPq9CtIONPpz7p/o7DtRyKnf0UuUU9G2g==" + }, + { + "cmu": "HH5nNKtgZa0uBsqEcA6tjuQZtpY7HcnIq6Ms/8hDiyc=", + "epk": "ANJuO/8kKfO2o6/V3e5YjyfGZgkP1ipff8W+hnP3/jc=", + "ciphertext": "y9TapdB+/4f9bqKQWEUZ3PN85/SWFiK2UukQNJhGCmUAqf3Hb0FhL5AuEnh2mckaZgZdOA==" + }, + { + "cmu": "DohpJhx/GNnvjzfRiEICFXBw4U8tBJG5+jaE8dqOUGE=", + "epk": "kCRG/t0bN+kL2my8amocD1v3sA8oirfQgM90B4UVU+Y=", + "ciphertext": "9KuuLJeHSMKPq1I1O0kSRLlX5W5/2CkTjf/A856nkg+VnJH0tVvhic7LcWm9UD5jVVO6KA==" + }, + { + "cmu": "RVvlU5PXILi5WxXpCPAPOYVWBWY8KKammStKIXWSRmw=", + "epk": "/ZRzf31fhdGk2ifTGLHZiJ6G/BYlEW28U5Ht53n1EOM=", + "ciphertext": "bheOSxr2sQsHDrlYw2dCfixkpYjx9H+E7FwRGPO0Vx7nKryTJhssVZhZJKIyFgkNRrKqRw==" + }, + { + "cmu": "xHuH5AnGmOn53TdR37DUol9qAa/ja1hj3Y0vKnOdeiA=", + "epk": "hZbPikDB2o1N2y5CR62/n1qhGvqeCz4/ftntXGayUkY=", + "ciphertext": "q1q4xsDElNmcL/uECJGYxRP6M3X6qyD0NwFJ2rvgOPUHynaeQhVTD7+rJ632qAWNGVt6gA==" + }, + { + "cmu": "wYYYjretVrS0SqIPaWlPseE4CJFSaJh+ALOIdTbMnVw=", + "epk": "mpxQzTkECb/JZK8GkOvsTrMTuqm7t8kHZ6kml68XKpI=", + "ciphertext": "6XKCOk52CdsVMwIHoUvHhITDog/b56tgHHX5j7qogoJdYm8jI3GalU/FQREdQDw0PXBfzA==" + }, + { + "cmu": "qc3O6daVSwziYDqGGCpHft3DAZXI5ib5TXsitdfSWlA=", + "epk": "d8Xj0GRyouMEZZF67Ys+1Bz2Aht2NpM0kDBhTuLpi7s=", + "ciphertext": "sXcR35ZofQ6zD4XYT9woGQqkX0sfLY3ERBq+FzLermJ4IBzAYFtiusadDfuz6iNH+kDYkQ==" + }, + { + "cmu": "YNetDn5YRJNtOBW3tNXUlNQroH98n/GtDXq5clcPdwI=", + "epk": "qvj36rBd3owSzoLuuXZWQA8LOzJnaj60CT59DuoJLm8=", + "ciphertext": "WNarw3vf+sKXT27Elh4fe3Lg5ljdvK4T5nPMMALR1oYV/J6UBi7z4tPP04YVLme6Fs75wA==" + }, + { + "cmu": "4dPWsc9SG9M+MWng1fhHQG4bY/NsJ3U4subb4ok/EyE=", + "epk": "YEF52vOm6peev0keCznKnR0AoDmXlmNIv8Z9JfLDKLE=", + "ciphertext": "s8uj5mnbzR3Z0RnmGlkytXInzNI79xDJrGfGBvkw+GXE6buD89k3tTL5IuzZGBm1rNEBZg==" + }, + { + "cmu": "a+9ApzVJinv08WdIBABKYR3VNHOHuntSP+T6aTyH0Ak=", + "epk": "AryytD2WcJsL7VWHaaFsUX3wMozNtHoZfVdTyRHJ7gQ=", + "ciphertext": "VorQbxVsYJB7V1Nha2Bg4gr+m4Ga8BM7iyLKL4YLp3z29F0MDLJlSloTqCrbzfXlfa/EYg==" + }, + { + "cmu": "Bm1kYFliD3/oPE+9f+v+He/ERnXF6gMiD+Bd4kGWIGs=", + "epk": "w/qsNyfLO8vK9JPQZzts0MPIyQXDhqzL95dt/nTai+s=", + "ciphertext": "eCVze3Jf2w7mpvzlsYGlYIQmGL2psu2ePxpX1is+Bz0OIsPH31TourIVEnlGtIaknYbHnw==" + }, + { + "cmu": "2y/Msm/TVeknDJHeuzzd8I0sU/NQ1yLg8j/l0gjZZ0o=", + "epk": "utm5AJRV9va3bzepiftUjA+XkdQG+7iKLlTqOB/O2Bo=", + "ciphertext": "c7uRuNXcfo9Nv4AVwo2YbRBvYUPViDFdxaVqtRvEBpVhmc3d4YeRfd1Rt1z4+xl1ypqF2Q==" + }, + { + "cmu": "JYXEol+fNU1kfIyfhAWGbbh/GoJBkHZwsFbErO+Zw1k=", + "epk": "ZpPv9sslQ4czA6MQEI8YnYSJ59jWw+qfQEPKOu1rvZA=", + "ciphertext": "E3y7szp35i33tsnKaVaoFYpijWJ1qDjJMAjwLsGkKe3xYKTKofDVEOnjbCl2IrzV3G4jTw==" + }, + { + "cmu": "eTfDUYv6D6f6RNtOOWr/uSCwL64q18k/+UlS1+H7eiQ=", + "epk": "pRUloU0DfS8Aq6nLnV8vNnXCJB51aLyrpUY4wB9J8m8=", + "ciphertext": "RFIgeOYsn8niDzPC5QcmZvqI/1OWUgjVdV/XqNwSlzYctcr7F1trkrhk+6AgWX9iI0pojQ==" + }, + { + "cmu": "3bFN4ezn9av4IhrEff+ZF/bCcYLmjKvQULDJkG5R0ww=", + "epk": "Yt9tKIB4X1+DXjD1Jc7U1A+XWcSDOpXxZsHg2sXsylI=", + "ciphertext": "J82ur9ECT24BlnJzluv4FesoNExpleOUlsoAaYnTcGMLB+d1omiIjkoUDi1ZXsF1lG1UUg==" + }, + { + "cmu": "GylIFTXoMWTWN7DLHjswI9qesLZ/wxuWSfsTvBWutlU=", + "epk": "HSwCxMV9mRI8yHFdh/vQYQqJfWDSkaIW+z9PDBzJRdw=", + "ciphertext": "eQyFd9KBp0ETf+Nb84tkRXFlSiE8GMSQ8MY968plWiuyQuLSxNzpVuPPS65ioFwPscsg/A==" + }, + { + "cmu": "f8lxvPNiCa4H+1n203WXMvRbhofGgGZUJ4E1MOknnBE=", + "epk": "BJkYtL6bkkfECy0GsbDNoDyNGmP4eeU//Crl3JXC/2g=", + "ciphertext": "T3yP52+PV5cj8WADcbI2/AW7fpw3CvjHJ7kTazL9VdAW1ICjSvHe0xow99hAa+sz/QmwqA==" + }, + { + "cmu": "5NZxbGc66XmXUC0GT1D4DSme1sDsh3muE4A/qREeCEg=", + "epk": "pjvJtBjV+XAXdLqcIR1xnJi7jLrNTaHRp8rHSaI0Xhg=", + "ciphertext": "ueOzsAOMWzzNVwOidJW6LI0cbIjSa/bOihKUMp+940hfWPphn5LpB++a/a+O150NejFB+A==" + }, + { + "cmu": "xandkkDaWNVmeTA0AbYsNinM6IedFkGPih9Kv86ctw8=", + "epk": "Em6/IkGSGrFUehtK2neFV6sx8OOL8hnVsyGZK7j9HO0=", + "ciphertext": "nCvAzJk8A6Pc+Yof1ew8inYwipVoBP1qs7oxJgE7y/ttFKWsSdVyiBy12JZx8USAJO5d/A==" + }, + { + "cmu": "Uc0Hr4FcuA9hE/fBbRFL7CMXQm8dZVfOvLEb6jxIeQ4=", + "epk": "Uqt0sND29GyIFGPPUAR0G/FMTHhBaaKbGITtXonoMwE=", + "ciphertext": "i2GtBmKgaHRApZvpsTSH3Z0hDnL1gJSMuorwX4bNvvOO1woPvkjnDSLV9GWrYsQmPJv5Wg==" + }, + { + "cmu": "KSFMgNJWYbw7c0vLoZb1LypDA9OEzs7ZdhdVnBoDH1U=", + "epk": "gML75mvv0LudS87HJsf6YYa5jPRwAJVIrfRrcue8WeE=", + "ciphertext": "6Z4H8h2eWx8thSUE749mPbHc/41l5DWHeF3Mekz3OOxnGROKstV8g/QvcMEAZZmm3ntqUg==" + }, + { + "cmu": "xLK+UbTHFbiJD0aSOYiOcanZlKfMzgb5OdiCK/d8izY=", + "epk": "gSsja9GQT8e6p/nXJGcwdTLyY0n/fyQh+9yO+ZOSJ2I=", + "ciphertext": "1gG93om4p2ntMtkxNqHUzc0iQOpoxxMok6/wAXKQr2pa1Fq1arpqFLcnU/cnCKuO8beTLw==" + }, + { + "cmu": "ugJ7HiSWI4Q4TCBAlrj/gOu7Vg6HB+g+tMfJ3WcwE0Y=", + "epk": "RS0bt13F6eZSQGy2lMd42rTVnjwaim+WMkTUm7vW+O8=", + "ciphertext": "3CkcWBmcmxwIx+5AtmMGVcryQ6DNfvizQ2ydVcJfljJLRYW0D8Bz5W0lmyOw86TqjZ7DkQ==" + }, + { + "cmu": "93IiNApFashjug8OX06EZHuVHMt9y/rmVnBHUWG2UV4=", + "epk": "P7JqpsxdmiKUA+KpJGCHKNhbY9XnqgNvBd80xQFu58I=", + "ciphertext": "Wsf9V6CIha5/nnPLBHeSNMTjNxD8Jh5FLtjwR5lTZDyHwXsQMm5RprQ29jUbDTrTMPWNiA==" + }, + { + "cmu": "rFgxs/etucSpc2RfjM4wyAN3d04bINk9RtsgQTpAeko=", + "epk": "ulgj2h5XEdiNYemvfJUsGBkJ6cpYtmW/8SmnM2i1BcE=", + "ciphertext": "kCzJh1bq/41m6r10FLTx9498BLTcc1rD4ht4qh59IElC4cYgE5iGwXi9WYrazk+GHa5UHw==" + }, + { + "cmu": "E18Sjqa5Tw+AzusrKPBIpRJXL0j5vxfYDNMqZgWLBE4=", + "epk": "4MgXTN9udHwifovecq9YAYAjfhn4NaD9876c/L4I7qE=", + "ciphertext": "lC+A+2NDSfvmoz9fGi+sno+hnE65JZjgXc1ukaZczL9qesa2nqnKLpI4s9K8a5DhG7i9MQ==" + }, + { + "cmu": "8aTxuQdo+uTD/qw9a/gkh8uC/l0hyTWCyFXF8fsJC2o=", + "epk": "W4hT07B+q3F4FNADdWLTnr8nxjzySdfqm5stS8cfT+4=", + "ciphertext": "0Qiy30yfBHPLHWZFpxp9YtSzGoE+YWT67PHnR9DjQTyUygOKMv+cMpEBWSxSlXmFIMBfaA==" + }, + { + "cmu": "8yNhKthQ/lW2LFtndFKxB4mBJwH2egupmYbTf4Razk8=", + "epk": "MQHf8gBrO0j4ETJXXWMQoYG0YMWUERyoHsQX5Re33L0=", + "ciphertext": "hOkxvtMQEVjYXnzfNk1I2khjKFtT4oA/z9/g1GOwgcRWr9y4DlGPsCiiRi0a5lIalkvLhA==" + }, + { + "cmu": "eIAZGMBB0ZQijh6XzqxWXKnbkZAcP6eY1p0U2eQuygE=", + "epk": "5Qpk9p4vDXiDdaRh6WMSS9zRl9mhKLHo/yQK39cEAFo=", + "ciphertext": "fpH006N2T8b8iwuO1gkcNl5IoVbN0VOx5AXQiqTv5cI6W+SU01h+S9s0JzdAuGgj5XKzkg==" + }, + { + "cmu": "Xwz2TydWMWgMl0dCgjCx4YP8tpgmv3lhsZeNPkVxoDU=", + "epk": "hiyKkKv88HhitLtkDGnxh5fEvoVkXnxJVjvohS0i1Uk=", + "ciphertext": "Ynu2buHfn/Xl/SXe+OUBc93TULXJK4shPc3rYoPlsnP6HQAkaxc+JrduiHqTV6Ua9Dzu0Q==" + }, + { + "cmu": "geNUbmuqGo3XUzGPoc69B2vbXA7y7ocSSqRcfSCjUTc=", + "epk": "sRJREaubXuc5wjdyierA37AnqWAyqBliHRU3n4ZFBr0=", + "ciphertext": "8Ur5puiJb4HOh3hJwxn+d9wdOBLry5rj3r6M/TVdb53wWFs1ltfylvmE5XD7uwpd1Cr/pA==" + }, + { + "cmu": "+X8IkNMkxXpnobCr7eUaebvsfZyEJpZputJWwf7+Rho=", + "epk": "+LcvF7bKBVEYKo1BSAnaosqx2pydrQ8ItqAnj1d7+Jk=", + "ciphertext": "Jqn5T6ID+7Q2A+D6fgMkvp1+SW7hgBgV9O5Esc+h7VPlXwNrE2qGpNx2KQdbOU2Zx8Ix3Q==" + }, + { + "cmu": "r6rJzh07so4XOiMoUOo6/Yad0FBRkLZ8lo/i/x5qmTY=", + "epk": "mYejZE60MiMD3v8gv/vlKUeUOFhps9tbSw72hm3eO6k=", + "ciphertext": "AFXb+8xspaSBWezqEknCeivceFNQZijA4d7yl3M+wLYYqes/25XPQPQWQ5fffS73VcbdsQ==" + }, + { + "cmu": "JnQNx6HbLSnlj5laQAJ9jMwL6aNCahbQlWJ8WhQtBkw=", + "epk": "qDtZ1lwiQqOjSJOFGa5Fkjf37I9kvepc3xX/Oi0nV1k=", + "ciphertext": "mTyIOyQbU8A4aHoN46wBbWNQQCW+gTDcYfNMl5InF9VEOqJOYI0CWjociewNTO/VWMtcqQ==" + }, + { + "cmu": "1AgDJXEF2a62nVSfcGbMiUyAEg+2FI6azhKw3Pkp2y8=", + "epk": "99D9pXTEdcZ/QK3XAKwKhFZ2kk1cr8U81mn+HBmrfZc=", + "ciphertext": "oSXgqS1fe0+MUMlZeKkA9rYw2VopCuS+xjswCZke0k/Bl5IRGR2ixk4qP/8G7zQrSQbNZA==" + }, + { + "cmu": "+H9NE5sUZJgf3u03MwP9t2/+gw5YvFrYKwRcZEafVik=", + "epk": "JLEG6Pwv/gSd6bB/nhecL7mTOGKE+KxSU575V0fBzxc=", + "ciphertext": "Rif7zfH/lWKf3ias3h7+LxrroqtL4HPpfLdUk6bNcsOZMYiizRIwGfxMH2pnfzy0BFdrEQ==" + } + ] + }, + { + "index": "16", + "hash": "tjn46WeOMDzQrYuulI6wfBp2Qc7HUZZ562IGnRi6Wqw=", + "spends": [ + { + "nf": "tP53TQp0lyTmYCjw9AwxouZfUjUwvUkD3X13l4e1a8U=" + } + ], + "outputs": [ + { + "cmu": "1x7QX84KJhpkOuiEFxgztZGY1U1oNDsaaoFtSdA/hzk=", + "epk": "hYUqL8JA4/PVRk6YUwe2cGcRYa2NwI5PtZ3z0BNe5GE=", + "ciphertext": "5eNRmfPd1B4pLUdYTONwUZDNQPl86zA0fC3wb4gbg+V9KZMvMLzt2QMW0/xRa4x4RM5VSQ==" + }, + { + "cmu": "DzIFlA+6n/DBUsQhVhIOkAcJbwEVhj6AKFRmLl4urBY=", + "epk": "FbskwlSs0ip0CLD9nPioeS6AzwSu1a8ztyenBySjFOc=", + "ciphertext": "rtP3cS3q0oR7Ujf7mXyFQSZ6qptgpSrGj6se6Q270t3ubGv867fPW/GwL/Eqsdcn50VQPw==" + }, + { + "cmu": "TTwEH7P6wxgivXlVdqQZF51+E8sVk/drGv59OthisRE=", + "epk": "h2PGhySbfJNw/QbrV7cwcAOjzJZRLx14kkprbVQaXp4=", + "ciphertext": "NM7yoLENfTY67LpZXE3VJ6Uyi6S0zIzswqMtbFtLNPIeZBv1PsjI4dS4uBlJtSLgleje0g==" + }, + { + "cmu": "nJ+N/59n/K5XkyVXLUSFOPaUmjHQj2VEoGPs/IDqFjw=", + "epk": "uCjeZFY7kdP8raBgA9k9A5CE8g+ohK4enBkkHroyYYc=", + "ciphertext": "YegDYjjomaAnaQ7pyZJram0GdMFTUk7Om/wEOS8xZuo8Xt2qwtd0metLjw3B23vnGWnNJQ==" + }, + { + "cmu": "oDj3wp3Tdx4LMLciUqG7w3AoPDBDgHRXjPkDN2oACBY=", + "epk": "u6oyuKCvCC40KX4hNzJqL+RcsX9yruzpKN2/1t/AQhk=", + "ciphertext": "3OutRTZz8hHf7Ci7IMDuDyqTblCziaOF/O/jL1jtfTcjk1C1wzHVFGnYjm/kHazzRKI8Pw==" + }, + { + "cmu": "58g0oynI0GCm3JKqFGfJjxQ1A3l/TNeHhgTBq1bH0zY=", + "epk": "d3axba8JfZ94HrkSM8CceJsNgWP7Nnz8/9oyU7lCipU=", + "ciphertext": "oBV7pZUeYeb7lriq0LM1eMV1cxZS9IQL8HTv33A99sHYtvfaGH8nqXFIiIgDDD5GOH/eSQ==" + }, + { + "cmu": "zPdCryzA9zq/iV43/VLdm8KnyiD5E3kQYDcGp2Cb0yM=", + "epk": "d0BMJLzItUq9E2vd6VVvR/1VzhJjeEDUa0xZBOJuyBo=", + "ciphertext": "TEHO97edpuxXueaJG5ICWGHxs4I71Zw7MGi54wuvN2BZEej7SKiD8fHqaR8Aqv+XOyyXKQ==" + }, + { + "cmu": "RDOslET6q73ThuNbZDJ090nWWvxuhiZxzBPREbjdzGY=", + "epk": "kR+b0pIPfcTLNP455KHoZWU6i8NN+9TmHRGHGMJosUU=", + "ciphertext": "1Wv3g0mjJVeTNNJK2C/dCKYyYxJforiw0k7IKD5UdYPAsJKtcHYNH4ytrzDblqek/q6Wmw==" + }, + { + "cmu": "ZRy1Pjz4xlrPGBCfR5e59BfEedUGNZaXuY2PQcDONhg=", + "epk": "8KKSj2pxDKd9Ux8bJzF05oyfC0nsbQb5NBto5dqF11E=", + "ciphertext": "w8nzJcqlcnNbOA4hnOQxyD4xO1cU16xJ0iCaJyrdud1TWJv662emxqkdqnINcSDteyZ+Tg==" + }, + { + "cmu": "WVqII7vcFf6mFZnj/Iy7dV+p2iYV4UIOzcTZoqYbowY=", + "epk": "O3jI5XN/JvzK09zLadf3/v1EgqMroxoxLOvFsp8hHsc=", + "ciphertext": "qZGj/kvGznpVOBWOjZFEGac654J/QbZ4wiSuRnt/Vee6nWy/GBmVrMGwHwYy0LhNrm5rpg==" + }, + { + "cmu": "h+qUMwjt0FqI8535fZechv6ZrNBWROW/icloC8FF7mE=", + "epk": "kMIINQYkZp2Cs7wOTvJWtXx3YVo9Uv63LjmTOAmWB94=", + "ciphertext": "MahemFXnyE+1i5v1xUj7EIf2VY/B4K+DjyAdPBVam/mcYF7MKb285S5lsKnIssRdivoSag==" + }, + { + "cmu": "zINyfYnRpF2Q6yOTa2VNEIbTSqz9xxNx3fdSd0JxEHI=", + "epk": "1jbZGKoroLFHsfJAL1Is3nOiAy3BeMSB1hJl02QreF8=", + "ciphertext": "rqs/BNdFJjLa1caYJEWqMB1Px/0Me/N9f5BziLUtDCbH6YDdeVg6p1BO4lwdMp3SQijvdg==" + }, + { + "cmu": "y38Aszkg/lKrbLr95a9ixPeXG7REWs4quHLAfRhi0jQ=", + "epk": "gPHaN/L0/nsg0KMW3WEkXA24tRM7mRSTFzqsT9z1Z5E=", + "ciphertext": "NrhqpD8qKLYQZfgKfrG2gr7m68ubV7/7KI5s60pyCXscLT6yBIHuHzw45U2X5DDlRLfObQ==" + }, + { + "cmu": "qhVyvsdDomBOY9lVvlwmagjmFwZj0YlZZPkW2I2PbwQ=", + "epk": "qiBSDF473/ke63BPF38ofGgDtFBr0MSFIHbl8u+GG+o=", + "ciphertext": "W18w9wRr2UBA2fUM2g2Ln+JmGkyEz3MXuWq1wOJ5qV3o9PhLU37CFAL7NvGAtObZMR0lSw==" + }, + { + "cmu": "teHunaGrlhJUgtSm/FF2WV1GTI+FJlWKVUOdHrgUJ0U=", + "epk": "oSrTyQket3xCoGNY3wyS2Q3ri7aXRLDPUuyi11RWx9k=", + "ciphertext": "39gpTPj4bCCBDyMXlvqy0r+3dCPHQ4p4BfBCdF+93NYsVgeJyntI5P7CUxCjw1l1hYt7Xg==" + }, + { + "cmu": "7zJiuZWGukxq0WgGWTZBI3MzVM8Nb4EZhr0mIK6f6AA=", + "epk": "LNLyCKhNT/sHTWktjYCTBYXVzklKgV8eUFj8zVoxpJE=", + "ciphertext": "YXoZWBzGAhs5TcvkMFxTNqUssNFUI8MTATYjB816TsIhQ/yJCUOlkp0/5/LYJx6qjLPz4g==" + }, + { + "cmu": "FCXMZ54u4kmE8ygRSXiQtXhMXXHMWABGymsaT8ZCzjI=", + "epk": "LuOLv1P0nGgEXPbZoYXRaTYVnJo5EjYlj8DfRof94M0=", + "ciphertext": "afHZyVknk4i6ZtMYB2ZlaPv4VZ7jUpT3yuhdIvBA8Abjq9eazSmdMnQJB3wciweS4P0iPA==" + }, + { + "cmu": "xy8NeukQ+ig6ccSCNotERrMlGrHI7QcWO2+IUhzbyUw=", + "epk": "NhzBiWZMjHiGL+rolJJrOZ8k6DBjVoZknTmFB9yEqiQ=", + "ciphertext": "i84+dVUpdqvtFvuNaoM8rAiQnEBw//bgT9QSSC/17OFwnDSqarWJM9ZzLNapdyUIElpNhQ==" + }, + { + "cmu": "BLb+v2JOy9iU5pu1yx0KK2secNTKODa9Mr0SrmMyZhc=", + "epk": "F9DAa1elKAQv0qEs1dWJrGHMaUgaj08gLVZxLieL98Q=", + "ciphertext": "dQuivM0i2PU4JQK34cI80djcAhfvriHg5RJR+0TW/JPt8YFexJTdfwczEm1R+ZeOf7rmsg==" + }, + { + "cmu": "HMrURYNW5tRXcmIy85y65YBEc8fuHaFF8ljnC/x6Zxw=", + "epk": "Tnz2wYEvSc4Gsmxp3FzmXK+S/2qS5o0Uhr/T6JYVfZc=", + "ciphertext": "/8rr0p1a4qcMoKjRH20WRzh5hQArd9oUpsgUG6YJJUCMwvfytx6S3clyhY9DJndmDHoqBg==" + }, + { + "cmu": "eCjbdy6iSnDgbcov4y6kCJ7+eoNymyOB/vPlY6ForAE=", + "epk": "zKoihT+ekBIThxzxAl36TNxyIfkrT9B/bOjBnKBXXmA=", + "ciphertext": "gJygYgkyHfqyM1jYytSJCuwNzv+0RxDWWLm7F/51OyiT2j5XaXlV2prmwZ0U2fh853o9ww==" + }, + { + "cmu": "hpPkblkdrvvJZqsPMDjMR4pbw83bedHlJ2jyfa1XrGs=", + "epk": "YtYVRsuvFkru+PWjGrle1Coog0jkRZvTu//hJoSxUsQ=", + "ciphertext": "ykvbevYsfvwNSQP46dWU5Y0ZkfifGidh7Zt4HlZb5ZvbZkD2PNiYPWeR8fiawPYEdVoDiA==" + }, + { + "cmu": "/nFT3TXkKdM1mLJOw0QrFcX1GS8OvmVy64YQz/6dSG4=", + "epk": "ctA06itp1TawCNo2cYV3/B1HStg3uVE8FmDxTH1Bqt4=", + "ciphertext": "f22wj+Sd3v3vpfWbfjVyClGMPmTrOyZgM9KJ016NNgVACnU8RMpThOzbKmJ2K12sasqMFw==" + }, + { + "cmu": "O4DhNsRFuy1FZXL275NhTYAxQ474e/2ZdEOFe8OKqFQ=", + "epk": "xKgojfs6r+Kzanpr4SFl3XMcoraGQTq7Sorer/FUyMo=", + "ciphertext": "pV49pOfUy77dKnbxV30G30ofqEKFGlN2PftSqZ+Ajqd1EX6VRKp7yUUoSJ1iI/yEz4B74w==" + }, + { + "cmu": "eQlXXmuzojXhR3xPUD/sqU9kpiehFY5bg/SSnHr611E=", + "epk": "yrzOGy91ysUd+HPe0Ce5/xm4PERhaFBPOyHjgvwNNOw=", + "ciphertext": "6FYOb9KFLnolp35xmad6v5gkGVeLadZ8sDM7mL0sbAqMdvAtF56IvWQ14c8irkaO/9rQPg==" + }, + { + "cmu": "p30brXA9RkLcmDrUpL7zwckyqy4S63WhUqWJHXkhcBA=", + "epk": "vMy9CpcSNbt399YpQaS+ROJFUfYvLKDL1OqVBhqHxj0=", + "ciphertext": "lPwUK4GncxbmWcspomm1m6CYBeNzqDn/BZ8WMObj7iAff/3/H1y2O5d48QwYsJDqvWhsbg==" + }, + { + "cmu": "s/zGj9zSbhJ9PHapJMuR6JzzQszMU+qv5BHmgVHKaiA=", + "epk": "q+MhBNlW31ZbAaRFMTTADpgEwQweYd+qOxLw4+X1qAM=", + "ciphertext": "f9SCf/hd2ppyXTpnD4SHxBsV6d9GTaQe+RzaEjzrWvUvEbp1csCH09BxPBlKzOcVEEaIbg==" + }, + { + "cmu": "CJbmgIRKPb097XbRBQmb0IuoTlkU3aB4g5iaaR4W6wA=", + "epk": "6qNyR0WABYyN5q/57nSFbsd+lfkWOP9UEP1BlMtBdS4=", + "ciphertext": "yHAE5CNNsSg4V8GO22mosqSXZErBcjU31Yr0bLylU6e4VsoxE9qs09mACtHol2y8chLQSw==" + }, + { + "cmu": "HfLDaLTxz06GPARJiYlDDDiBVUp+gtynzgI1Fgwx7RA=", + "epk": "U5pZqj3YoOEUZ4nAbStifz47QT/XRnRRPS3strrHumc=", + "ciphertext": "rZQI7lbMXSM9JTACPihmx1mxnz02iGAkpWUQSMPrxFgwI/RtEZsnKQ/SpC/49oCGa/RNnQ==" + }, + { + "cmu": "v1SlBb1y3K27GmKkfdIgkq3kf7xN3AAV5q9i/5tcWA0=", + "epk": "MupeUFaAv1wxjCru6I+b/k4Gc2eYJYATWC7hD1eD+LE=", + "ciphertext": "+uahwyycxyvkUdR3RJy5lIERmNktrblO3cflXE7+zaENvXl74rwhzqoTGTq+GLfzfS6hWw==" + }, + { + "cmu": "Jm2bZdqRTR2mC0hN0i1Gan40uD5qKy8Bgyo2BcG9vUE=", + "epk": "Vl06+dfthjhm4tA5ZOdUjwrKgVFejYf0+KO3zLp8eJk=", + "ciphertext": "7EV5J7foU3JD2N6/83af6Wr+4dKaiyphmoQm8CZhnmJlak4b2MYtF2ovE9XIslosbO/tCA==" + }, + { + "cmu": "H0WNEa3rM7910lycd3qTtbEvPxyaRtSyLpNbUfFBsx0=", + "epk": "RpmDsgn7IqZFDiKeyBlubrbPpqKDUyFzbu/xv4hlJh0=", + "ciphertext": "bOZmeRqPFjNWEiNa7PHrZGdxP3vyAEvjSqAQ02sPtek4kjQFUInuFfi4hslK4H7lU1LvMA==" + }, + { + "cmu": "s1W9KVjaHxly/a4LZ4bLiCBrHiLwrG4LPGtmseAGHlY=", + "epk": "T6lMI7FX4Z5hYdTffSkQ0V6pbr6pVxCAVrGv2fRxHfI=", + "ciphertext": "7JQPVkw8yy8IlguafGH1rttybOneuJfdDhC7DFC5aiG1VnpMRsPb+Onc1I3CKud16zjzrQ==" + }, + { + "cmu": "/0BDphjnmTkIzQ4coCOmHDUjny35X4+K9gulRCyFXWA=", + "epk": "RtIgweIZB+/i4W1ugXW0vixf0wztley9xuMHz+keHZc=", + "ciphertext": "xKJ5AV80WpQqMwecgYMbzBAEumQitwdpiAkHupZhf/dsgDAvZQGd4GEm+S+QlMFc3SrhnA==" + }, + { + "cmu": "Qleym+gmi3uI3bFHyNzC2kisLFipY0sgCc2HLCZ4flA=", + "epk": "2x3CkI7+MllyXy2bHRpJAUrBdP17dhNzyzsTx/6zTm0=", + "ciphertext": "DU528IZH13STX7+7rl49vQrUND5d9/64kl5AqyQfP61BhbhlzHT1vLDELbN6hpOo/NwvZA==" + }, + { + "cmu": "hOH6jcZZKEQldA98Zd2qwPTXYHM+7q7OTHO1ytQnghQ=", + "epk": "T2XK+gTjGcAsCRk+/8Ch7rU32WzqWFTdwnR2PUyo11g=", + "ciphertext": "V8CDBrKvQCkLePAe7iNb405fjyLz5J1DgSBdXVB79yR9BmQ7exs17LqlddO15dEqUag0sw==" + }, + { + "cmu": "WkkRLJLwS+9Zfk/N6nl47pj2bu+sh1z+EfB1OMfl4Vo=", + "epk": "0WEJRtWnoNRNduPgVtii/IomJZkRZYYUrl/geIAQ0Lk=", + "ciphertext": "qCj/6hyM11ISJ6B6VDAZFy5+pU3QUj6LoK2TtpQGfWVMSxn+fGoFA/Px4xCmJsGUZ9QUsw==" + }, + { + "cmu": "GTwhsP56zWBWj1BRgl8+31mxRreJHqdHjNh4YhsMIGk=", + "epk": "WNog/JW/AEsfwc6eSryWkU8Ihga4N3IYjKc0FhqjZXI=", + "ciphertext": "15DDc6sgrAZX+d674R6l6Qk3hBCx5A1nziRt8OJSm23CJRa4pWv5HdxK3DpXpS9SfNDSgg==" + }, + { + "cmu": "yhjusgd3Ha7tARtLwhQ14Ri/iDEa4wanXoYZ36hPvG0=", + "epk": "FLqzHXekeXErnRhmH+UNB7bEy3dP230B+4N70b7R0ho=", + "ciphertext": "+uqUc0P/NpQk6qI80n4eU9IQVqfM1q/vP1xDOS82jXmwT3TNnfVMgYr95nlATb5b+sWIHg==" + }, + { + "cmu": "8UmPATVXuvDCzUvzi+aWaJRFTzLmjjCv1a8F6y9fbAY=", + "epk": "ax35VzWDt/oKN6oEedsJQJhdMdpakLImNQw9L4S8nnI=", + "ciphertext": "3sVuN0QgQlGe+W2M4+ri4XqJhqOUi2fPN95V+3kIBb+rKOU1eIHrHaRcEt0eKCO1ncsT0g==" + }, + { + "cmu": "DQGaReXrNQ+srRETP99UsLDNNKmO9VCNTTI4AIvugD0=", + "epk": "9WlxgvvIw+ZiDQdH1o9oRmFQ022Dm4tvejoJ+zd5K54=", + "ciphertext": "7BkKHw2r3z5+zUufpCRUEJv8kCvDDo33UuEeNoyjizwnKxXWsia+WXGYusR6qdHJnL+8WA==" + }, + { + "cmu": "dk0JzMjMbJ27pyHBxFshbuCJKpPxxFNgBUEN8oO0zlk=", + "epk": "tWh1ieeAXsOKbVnxnO3nTh+voXencZNRwi5XxB20stQ=", + "ciphertext": "zq80jXSxFCuiRC2frAaJ/5wVmaxrj1FtwLiFSPPqgLIa6xVE2QNC3J/v8pDHMb/9x6JQ1w==" + }, + { + "cmu": "3RHnSuXJNc8IUnvehV/Pm4bQqbEpaeQqLh7SWZEjeF8=", + "epk": "pRv0F4fJqgP4k2kln3u/rYCUqPBbm/xQTqJw0I58nkA=", + "ciphertext": "71a10JB9/WqLzrJV3IYi62nhjXRow+ZhbZfpj8/KN59k1y0YtEj/tcCEnXxoHgE/IiUlCg==" + }, + { + "cmu": "oWca6cpNrM7vxn8cc8mBenP0R+Xfg7mQD+E8YWy1EFU=", + "epk": "3SnRzZRuaRJe+u4qLRDsMQR7/wiNF/CKUsjdzhgvz6E=", + "ciphertext": "PhG2OJN/E6ZFLhQ7K1/RrgqXLip3d5VUD6x3Ve3HBCvTVrUNQc+32XimFGzfjGuTz0Yv5A==" + }, + { + "cmu": "EZplAvtDDNZP+oi8q3AfGUxe96YU1BnRUUoq11sYPWM=", + "epk": "pqUa0I4vBk5ntSzQyI+u8cxVhDuUXsNRRExzdXZVVoY=", + "ciphertext": "oYqjcLv2cbYfw+i+E9FvFmFWoFJIiMKsG0fmCMDYgOUpXnDodbqMoSlq38JiJ87c+FCZxA==" + }, + { + "cmu": "ApWIY7jFbqHX1awazWjRdpJqn06nlK40201ot+wiHkk=", + "epk": "G9LXMIFkBxFmj8iTJdozY9VOJsCVNFhd4VVPg+e/Meg=", + "ciphertext": "kSIUVeJmXYWS7RferAs5S2h4TAB66MgJGcsswS4LZM+Q/wxP8UysgioFgZkZKsPToflzdg==" + }, + { + "cmu": "SFA1BLFMU0SA29g6mkxgOf3htTpV6Dp9uvJOo438qT4=", + "epk": "OFB6u3hmSYuA5DahFY5do9tTy4KRk8+wQBb5QuTu2VU=", + "ciphertext": "3JAfaGVPx5JSTY8vU9EuU1Fu5rdrKbUmiNn3b4zqRjy1EqMkq9SbzL7BPUVbX9cXXlV6PA==" + }, + { + "cmu": "bTCuaXThx8r/RiQNQOcWBPaRPnMYErDwCoo+4tk5WWE=", + "epk": "5hudCpcuxkaVUWMFkyz8MyYCBE10yzVn2UHIPYCS5rI=", + "ciphertext": "AB+k5DiCvDdfBrSRtsAX4BQ4ZLedmPejxGuEDlk4F7wYlbYv7CtMgBnaFwk0qtQDX6DY5g==" + }, + { + "cmu": "2wu/mHpizwAHMfSXlwkfIujjM0GLKCbcwX+HJ8tZsBk=", + "epk": "ymrzgVNqmUfeAwARPfLo5q4Qqa3gnc2ZkocossWOXtQ=", + "ciphertext": "ba9Ibptn3y1dUFciZ8kO74yjCy8rmHic+Ar8Q5lpos6sePdcgazSbemYkvJrD3GkCMcTBg==" + }, + { + "cmu": "ysRilTtrjOz4dmbANiGUIkKsWkHGjH1aMoEZdAAK5DA=", + "epk": "IhRDKBiPqcKJ0vNeA5jA50XBf6AQQoCvU0Dtq+PhMQE=", + "ciphertext": "3GE504jA6qIuOC+waUQDxrbAEBTup9fcLbrweLdaOh9UiupetYM4Q77JMhiE7KdzTf8sTQ==" + }, + { + "cmu": "0FUlElHdDoLg8rTN57uhqDyxbZhCmNC5HItwMfVYRGw=", + "epk": "eRnhTB4U/lRjc3f+JgDHFSelbhNPVRv2tvSilKanwDo=", + "ciphertext": "2NmfqK9vp5jJwQNI0otsbFzcSqNpjaDCt85vJToEx9JHhRxNdNYG0CW2BSEsZ+T+56Z6Vw==" + }, + { + "cmu": "h86nXLetfND3ZVLVk3IgcYTSmS2CISqDJRdgeXNRXhk=", + "epk": "5/oh5mA8b0wOdf1e+GZYutR2dQMQ8fc4DOfH345Dm7Q=", + "ciphertext": "EqHOgc55/2WZCXhabuqG8hmnb9H9R8s2nfcY0QqbOV4KggHMfnwaIiGkCUslhGHPGVrNHg==" + }, + { + "cmu": "2YgEm8zV2wAWYtwaztuwRCxzctY4+47aQJJ8wJ3w6UA=", + "epk": "7ZigGgDblY8zGnvcTbiQ6yOZ3rp7D1WKjnD/W0mFO78=", + "ciphertext": "UZynHJo9A6nThoSnl6kWO6kItAJVOFQGMzBYHtZN+aUqP/POG4NrqFwvfGA1+tsYBt3Smw==" + }, + { + "cmu": "p/VyauqBVVILsFJ7Fj8xf1IC83PnAqejL8m4HXaNrxg=", + "epk": "DiYpTPyv7i+1q2HOEbL7dV1HN/oN+ih14tOZuPsR2aM=", + "ciphertext": "2cmC6V7wZ7DdktarD8jPZJnl2qvFjaT6BqMk3G3Q6ivnyFCTL10FBqA4pps+im+00sREww==" + }, + { + "cmu": "vp9AW3CQdKh87FvXQF8dlGBAKy7TugSL+yycuqqHbjc=", + "epk": "WpuXW6M282/Xe8sNKeGvN7/0BDXFnNUcdYEvPbbYYiw=", + "ciphertext": "HLRxbZ49zGvbSLq4IQyHKUo8IbW/ZHveBAuJG/vxGtGjjOBSpVtOQ4VWCsqmylyGq0yWFg==" + }, + { + "cmu": "6titmQf8clmxh0j1Z69PUo3+r7s5y9DT/no8BgekZSg=", + "epk": "CoqDp9mtVhdY4zi82hZ37PhjUNYAIdRg2K5N5Ml4tJA=", + "ciphertext": "Ozv2AG5x4kQGCzQNDNjalTLKvwlEL5zW0O10Hs481HwQo/qDOnT4UdctUentxTUCM6m1Tw==" + }, + { + "cmu": "C4+VUmXrURMCh2S9WWdLbpbH7p6Peo1zaw/oTdJqox4=", + "epk": "+ItiaBrDH2nR0blviEO9Fjzy9V5To2ApZezrat455x4=", + "ciphertext": "rGU9XErqliyPz1TrA+UfxhtHaxTlSWAEVvDF26yTZkXLIGipmzxNQbYTnXX5BOLXT6kpiw==" + }, + { + "cmu": "VE4qeJDVpW9d/2k7Bvd3w9Avp15sYXgndZUkw5VDsT4=", + "epk": "ExDmskOWPNvLlOy6QK9ZMbsAvwr79pb3FfAlTOY1dSA=", + "ciphertext": "krx5qFdMaHquMFkrCE/lCFHBmVFcF06uYs020F64ewNklVUYgyX0oPgvoBIXBIvObffILw==" + }, + { + "cmu": "kyEhX+DfBhcPX+YDIglN5XlgtQxb2wXB6iMoMOuM71o=", + "epk": "K1FH7ffBK+Nzjwzw+vNmvruh21Hp++NuBkRNjhk04cU=", + "ciphertext": "n8LZHDqU9V5BPRH+r6dVyKnB6NkhusZZqNjFP0guM/m3emiIzf48mt7xAGLzq6ohr+U8jw==" + }, + { + "cmu": "ByPk/Jgget81zTnV0Ilucb9KMBsyhxj/iSmjR3YBAz0=", + "epk": "VeRqJQugkZu5Gucga9mKhu8LDlkuQt6QAnMRi5SA2r0=", + "ciphertext": "7kezcMMb3kWl3HeC/p0HC8XipHwX0MNpsNssqb6YesQ3RbAkz7a3BeUN2Q+VQysWeAVAUg==" + }, + { + "cmu": "L2X6ETl9DUkXmGbLI3xWmttmoCNGnRrA2/OWctZT5ww=", + "epk": "XOJLzHnzJwGwEzcLhRk/ZTYC6K1/KQr7lXrU80tgEBA=", + "ciphertext": "Oh/y7HKzag5ZkVOUSGmWXRUQpWmFqvLdQja4p8pYEtbQf4XowrCXgbyfPn1X+8ZOEGKJHA==" + }, + { + "cmu": "pw2B2y0XX4rc/CKJiN1Ui+FB2iwnGbzf5vazif+xGwc=", + "epk": "KQCUq6WNOwqwmh6XEhxZQSKg3VBn94jYK0a/+mSlV0g=", + "ciphertext": "z7epk2TIZdj3j/m1+5Nxmx9vwJGAYIf8zYEk7lbh4Vyfxav74jzCA9ePodSICwy+VcORAw==" + }, + { + "cmu": "QvXLkVW+tsEfYH4N1emRvkMRHOeKPK7i6WM5pNIwjj4=", + "epk": "f1ffLK/u/WtzCer9jVgVrMu4y/j4ymm/Cl6OPGALCbc=", + "ciphertext": "4e+NsSd6CFAdagJKe8nYALGBHHibaYs7aB78YLJfrm7mnAqmFCk0rqhcEvmzd9hKSNqoNg==" + }, + { + "cmu": "87z7XJ7GoCZVrjCUp6RYvil35gWON6aHCf1ZLSDeyA4=", + "epk": "n12B+W8jEwpZjoIewFvPc5ZfmVx6e75MPsG3Xdmk5d8=", + "ciphertext": "q9e6ntJ51rjVU6V489uuD83ZNJgMpwAlmqnYdI95ap1HMPEJS/W8q61mopJgctIyeFLGSA==" + }, + { + "cmu": "Jty1duFW5zQbQ/EKQo9TA3+IrGb+wx2Ohm90MLqxXmU=", + "epk": "lqR4aC95+FQsNF5hcvZAXdxbnhNVZCD5vnsWmpo0nQc=", + "ciphertext": "uVRSz579o9COt6QI1HFuOLnCBPgQTOloxniYJX4HxuuXPIE1acqN/XHuX+qAo3YnbYzpGg==" + }, + { + "cmu": "OBeuVwo/7DVFBUN/yFlAH1Ef4nVqKJ7UleONZuOg6zE=", + "epk": "L1kLgVLkd29/0MjcETnRYBgXPDx22WOGfzDi7vPlElc=", + "ciphertext": "qW4nkd3y8fv1UCsQCG3FU6Jlf7PLxqEzYruktQx7aXZbEh1uXt5KGX3oIQE54p8LyVLcjQ==" + }, + { + "cmu": "uW8lYSDWSZA3pZYJMUEGMIyfOoNINiwjCfMQwfGQqCg=", + "epk": "LbD4Q1S5df0wjeuysylwCQZQUQKYOhAJAuzrmDyz8BY=", + "ciphertext": "rtH7xpYf6ycj9/wx3L0vz7fXX/cNSaov6ApW+QpLrLl91nmYmeevxDjXsrYY6tGYATBOKg==" + }, + { + "cmu": "bp0/VBeu5JbM6EnwFurpmupJNZpd4iunw7k7A/dneXI=", + "epk": "jNO1EIix6lLefVtei2hLka95rFLo+tba/nunfYdqh+I=", + "ciphertext": "fg4VyBlbyNZty1HFOAjc7ZMH77lxM+UICwoc911Sd0DT9uNFYyIHGopJmjniGKuZlWTpOQ==" + }, + { + "cmu": "ps1D0M+IvHPxycPfomzp2YPxK3QVNkYTGoAd0ZkndAQ=", + "epk": "04jJKfq3QkJKts6YALNPahdvuHKYXSsS1bZGSP4TN2Q=", + "ciphertext": "ILvGS51mxOs2XgU+TDw7ft98ruC70aUxiLUiCKVdzrLS5eMIVqntaUFnCoKYCxEhukswWA==" + }, + { + "cmu": "mwef3DDaye08XreXmRP5Sdup3adKtFQZxSllhK11ITo=", + "epk": "pfIJu+kdZRXViI7ZyQd+jnrnR2VTPzi1Hynri/uU/1w=", + "ciphertext": "v2VwbOPsfDVYxDq7Q1YO9vAtlvz+LXnY2EyZgcZxTmVJ+S6B/JaK4S5GVAJ0UhwJh3uSdg==" + } + ] + }, + { + "index": "17", + "hash": "HcR9yY+SRF+18fMFL+WxdVlskqagOwiPbOaEkG7E+OM=", + "spends": [ + { + "nf": "UkOxWiLX/F4XrG0MLVRvM82cvF9h4G3veTgf/6gMi+g=" + } + ], + "outputs": [ + { + "cmu": "GboaOkG80NRmGp4b4GXL9H2PbpbIsFjl5aFKmTSknkM=", + "epk": "bElM8RceGBxYqOYFNpeFbtmYqyVZnarTIOhZZ/hBWU4=", + "ciphertext": "yyVVx/anbxtscHoTX5+5tmrsNhyMxSSs6ONMW3sfJ5X9DFd3qeEUHVkeLGeubhq6tqIKyQ==" + }, + { + "cmu": "39/DmRQcaIJ1+Zi5IJpd0DKRqIal67FU/LpzDgbdZhI=", + "epk": "PkCTmRQnKhpNi8ho/dTfxLOvr53RjjvmG4Hiussm4+E=", + "ciphertext": "GCNJOG4O+6igQfY+inIFBhJNusjIEo111QA1gzWQ76Gbz2Sksa5JS0ajjeu3s2N3lFYSKw==" + }, + { + "cmu": "U1Cw5mZpMlSCaiv1PJRKtDM3hxFdC1taJCrnUVo4aRc=", + "epk": "pKPsQPzt/bnWFUhBpNSJ7oA+z96Sr64r7jXI5YAbuaQ=", + "ciphertext": "UKeQXtx2TdMX/oapjIJ12Jego7ZBov8pRrkF4PcweAHU3NZw3h6LHmees2fzCAcSeOwrrA==" + }, + { + "cmu": "bqg/uC51xAJjMOOjImaHM+EpSspts6QSLHcmj4AhFGI=", + "epk": "N8BGKaepaAtIBjbZhPEV0UMlCHlgk3MnhFn7WF/a+B4=", + "ciphertext": "DOH+jfvrLBVIiVu9ACFVgkZgrfJ4rvIboVVKFd5amrlWGL2gLoVpYm1uiNwu7cSGFobTaQ==" + }, + { + "cmu": "73iSceLg5xTp6xB3i7cs2ncRl/eOj90DoICyK2Rhtkg=", + "epk": "OkKaJSCeR7ueAAp2L3csb+8xAt3M8x2GTsPUcb/pPbM=", + "ciphertext": "9tCYNT7hqYo3qwHc5fDdKtflbbiiBos8NZwLblzuZ/zqz92j6e4qQXlLWIGzyF4Ev1PKzw==" + }, + { + "cmu": "YPB2+sUa55+HrqZZ33Ip7jAvHHAQSmq6XRyaDfV3dgg=", + "epk": "MPxt+Tlv3Mw6WV+hD4HFBdAylOrwicfwCH5dNMBAEt4=", + "ciphertext": "Te0qc+Wdb+aHPJgzrqcdl6ymhaasfgR+9HHf6V9R/BoNjUDagYTRWF3M2Ic3u88lXbWRzA==" + }, + { + "cmu": "ueNw0qYuUlviL9GP5l4n52Rg7oNYzYxr4HWkjYfgpEE=", + "epk": "uJaxuaLtkaap1rfx5C2y8ZQsvoRkBtxUqP7YfgyUdbM=", + "ciphertext": "pCjQbAZyeemnA0Z7FAzMGhPKxvmVduGT6dr8mfaVOIMqnT3eUXll/yaU+5omUu4guQBZHA==" + }, + { + "cmu": "0iBupKrFtWmSlCsR4yqFfSFCvP8GBzB8hHLcdPoVDxY=", + "epk": "69YVJgsTMpAZxzwUdZ+pjjcdGeBkl6dVp/wXno7vrVc=", + "ciphertext": "3ub8wBfut4gDIRspqnfrlYDx20DPMM5GDMgTERdjP04snsExRkwlutSmck9gMhA6qPkshg==" + }, + { + "cmu": "dNX+qNPo4NExemcyBuMDUSMzfi/pNZKu2HWBYwIoOVM=", + "epk": "QUmT4igoAI4xHlBm6KzeyKolAkiZucxQo93boef0Fu4=", + "ciphertext": "covbJ+XvQn49xLOXd7NSqTEOeGG0C0SM+sKMLFkdz+pUB98Bp5rvy541TefTL2M/GPd2EQ==" + }, + { + "cmu": "PMQd5JZvFc+NyXcLFnEIvD/+2SS7BN/dtZafXhEldhQ=", + "epk": "3zvfRI8rzB6LG5rviqeXYP0e2O0g3dGOqHHpXdS9AxY=", + "ciphertext": "1wRo21BrE0HYWxbAj5USx2+NTSgdktTyX+HeyHwAfKklAvHlAMOU9OacXZAUwsi15wgHjQ==" + }, + { + "cmu": "04JCsGKUKDRUY99t4Nio2xdPJhSEVT2m+Pp1zQA0T2E=", + "epk": "Pj2oCF1SRrmSPZi9aoWtQjXTEiWSXLsXz0oJzGc00U0=", + "ciphertext": "cQ5YaNoGqcWZjn2azWkJI31XMiS/KGAKotyH2+ktKmruOolk3nVmoCqCZL1t2iaJnaUpow==" + }, + { + "cmu": "LJIfARERpxc0AT7F9VRBCDf1qvxENKbO9K5ULP+ap1A=", + "epk": "+ONVxhPkQhTI3zt4TqX5rC0DJFvA44zt4eJA+ych98M=", + "ciphertext": "q8strXzCRU5H5wRK8wnpjrJyLqaGVQx0Hmv9+bBse943jhgKsEFnRT9kHd+DfKUEi5cpTw==" + }, + { + "cmu": "UYLQP+K3eGffgYGtoNez//x9dDY812AgNpf/YlzUw0c=", + "epk": "F9m/D+F6b3vPS7FSPOOlLEyuw5djCacETWWOicQ65Cc=", + "ciphertext": "rUVB0Penbq/V5l1UY5CXaw7R8/kG8V4UWug6vjhP2bp74XapCCb9sKLdV0c7unh32PTRMw==" + }, + { + "cmu": "k/0f9/f61bU9WPdwGMAf4PR/YBq792A9qDX4RuyylGc=", + "epk": "VKyQUKUgMDkBpYYAThk2ENrD3geAolkYqGD4JHQVnVo=", + "ciphertext": "slAXU/WY5nRrrBDW5V2zgqvPr5Vwym+kTHcUKpIu6+D4tbDGn/hYLIDzSFRWqQh+tRiKBA==" + }, + { + "cmu": "Ci/sbR+2RG3yRqDFp1o3X6l/55WJtJBeqGttQVWd+DM=", + "epk": "M1nFAMoLQdyDISg9FomJdjy9f92V50dc3ssFtICKryU=", + "ciphertext": "tEcbZf/uwZ7vewZva+85BYuG0m0rbrBvY0oDaUMOmBG594akIFgmkA06YyxblRCDy7Nr9Q==" + }, + { + "cmu": "wbtnL7FhSqZpaM9yz8rTj8xiyi/EapDlk3S33kWPWDI=", + "epk": "RK/SOvOc32KGePm60B65i0HlveCefMyBSvAYAWphqIc=", + "ciphertext": "JGGbzn4jHF+dLV4e0swuupm2NibCJJyU7GiV6AtnM+AHl9PqPZxJEolk7wBiHQ8Vopzh6A==" + }, + { + "cmu": "iWBYgfByCus2HszByzchw/8NN4v4QLOZkDr3qlSc5iU=", + "epk": "UiAlCiaW9WSWwheKYVKCRVbehMDrQs1rFzvl61BVF18=", + "ciphertext": "2uqaIL8ijXDrzkNdIktPbT05m8Wsx6elqG0asPWKnXYv8is6LHmxY9l4D9Uy9SE2Li3s4g==" + }, + { + "cmu": "C1dBE+GL+Mtl+bxQLDDq628Xzp3FqzsRAZ5LvZpEYWk=", + "epk": "scv3N7Axb+5+NcMf5IQaLvSJNeUnsDAR01EDs3AkF5c=", + "ciphertext": "MITSNaF2b3CAASUFgwzdDbnJa5SM9yqZrGJU961IaVq568yowvjg++JZhF0ckxnTvT1ZgA==" + }, + { + "cmu": "qkStn1FAcJkp0QcM5x+c/onsiVIJx9nICY90LYxQawk=", + "epk": "9ak+azj9PeJ532hJZ1UEx3UK+ak3Jv5ydVnP83Ocs1A=", + "ciphertext": "dzZG7ugq6mC4FO22CFaq130qRDCy1bN+YrNMvWXIbuaTGsF4bpPPAnB+oUgVe+Ql1zBQ/A==" + }, + { + "cmu": "eYqfQ5K7qS5XkFusbxIuP/bBd2Zr8DTSwUbY+TQdgGU=", + "epk": "SPEG3vcUpN4ku2rcMIV731l2FvXkx+9emTWIq7lveT0=", + "ciphertext": "4+ICCopXhFpCI6nNLCzXeE7ji60e9vlVv00/3clVh4Kl5296flyof6HGXJGtuJILSVjJvg==" + }, + { + "cmu": "PV11jVrzIBOaHVHQDfxwX2zhzHQGGaL2Chpvptg5gTs=", + "epk": "NlQmHVKbjAX7TbFN2wVGkSsQjU5+lPxP4+mEYrOU8xA=", + "ciphertext": "srXYxMvj74oD40eda/rocz4jPnkDhZMblqUD/wcNRoWxNrt3tk9Tces6Sc0qBouWObnzGg==" + }, + { + "cmu": "5fgZKKJzr+5KoGxh16ElkHNo423QuLn5AMu0SGWMsUI=", + "epk": "HxVixKgzBGPjs0P1oOLJBsHln3FUEyrM4N3FshPZUZo=", + "ciphertext": "9cjJISJlacYYgQL1XwJhlnwwKnFNgTmPgPVDSzre8eoAsG3+LsnrwmOAiqSHkLGN/070Ag==" + }, + { + "cmu": "lzseeXRMgmTY6igx5Ng6R7rdNauI2LLS2nuZNU8SBmE=", + "epk": "O0dE99kQ5kCZoE15VqxRSU7FnitiScriPq5iAGT39WM=", + "ciphertext": "ab+JL59y+hPybe4aef7rPh3BJ04nS2c93Pyg3u63Hs3IJxxASvIa8C//FbTg+C5lrUzPLQ==" + }, + { + "cmu": "LTR5qF/gb7CzDXUGDWKYKGqBAjBdWSgde6KFJ+lWThs=", + "epk": "ORAfFAUE5QFCjjyV0uc0lfVhxARHMy18dm/TF9NzeYk=", + "ciphertext": "ZGXPeyNyiCe+dKQRZ2/nXKf3Fgxipux6AaTx/+vzAr+ZLAXNchYlKcIH1rxF5DSa0HZOiQ==" + }, + { + "cmu": "df3OVWPbEqa0DCozV/qYOPv8IOHES6UJahSYEAhHnh0=", + "epk": "9HJg0t6QrZ0f1Ed9iqEPNwVYspJci23bdPv/Rk3cQ28=", + "ciphertext": "jgVZsnf5yJW0k4njWvaYu9w/rsaIcJ9WSsUUq1dmUCzQLdLQa1yOyCVKKMzH65Kpsy2XZA==" + }, + { + "cmu": "sytN6upQnISR/3tgm705pVbY/Y/RBnv/xDqmBcepmjI=", + "epk": "HfjCBu30JHbvEyWW7N2ItdZmxYqtc3RZF9h/0g+RCDI=", + "ciphertext": "cm/WVUdEuOq3TeSSUO3ZlBCXjM4vnYC7mtbvuHA/SKXjtRd9JKRkvZ6R3uqwTEemuwcZfQ==" + }, + { + "cmu": "VSWPFQw6aBOM6Nmrp6Thifa7DzfWHTlCNGEzKFqC/Qo=", + "epk": "K3UuIesLT3x0hqM5DVR+ir1zNXV5WaaujKPs29DTNNo=", + "ciphertext": "y1qEL2sBLCwlS0JeFygm1UiXyCA6EVHQxUxX6GmflAK/65QH3OfGbdOYInVcgPHSjgrTag==" + }, + { + "cmu": "Muq6Uac9c1seIaUa0NkSoWu+3AuHX5QUhCWws7E0wHA=", + "epk": "BBc6DkziEFe80zTQ48ZJjiZuE9ev43s3TDFlawxDJbQ=", + "ciphertext": "ZqskQ5Tci1NdlqTuKKyPZW0sYLl3PlRhLh5ha+/T5rd/D4M7jgnHcA9q6H6ZOLVIq3VOVQ==" + }, + { + "cmu": "TueQ8xUC7vS3fWuEYtXLBmoQjew/D06gg3hrASKJnFw=", + "epk": "Q8Za5ftdSWXc/vGz4cDNzFRTmz1+2OqnaalOlrF4lBA=", + "ciphertext": "LolS52TPSs8ul+Ph1iqmQ9V9T6n0venSpNzOL18F9DJYo3ERKeaHOk8KC0EGw28ID1ZEcw==" + }, + { + "cmu": "LzNiT0LN1oeJmWEHUGKx8HrfbNWOJ1f04L8+4qX35hw=", + "epk": "y46FTpysKY7t1c/Am1l0esH/nX1yzzpcsqr3bn/j+XE=", + "ciphertext": "9MT0s63xX7d0giYHBNNSoKCj/zy858JWAnx5/zvknx24QHofngl6hlQL/bhX5KJFxDLCPQ==" + }, + { + "cmu": "3aoKyqgXZSkZ2/o3HnSk/e1jTHyPZWqP/2kGYpgcs00=", + "epk": "k+D88KkuubWhhgrwbbERM38QGfWN6Q0Q59fVP8oRJts=", + "ciphertext": "LqEJht70CsvDRE0l9Bc0yuD3gGtnK4eL+doONx6gPHU3AZ49AGKtuoRhd5e1y6wMwa2x6Q==" + }, + { + "cmu": "Io5B54a5IidlZL0usnJ7YoaB9MZ2hzXO593Fl5UHQDk=", + "epk": "7cuVfN0OVXsd1mLbX+QjWyJgQ2Fur/XpOGnW/mFi+e8=", + "ciphertext": "Mm4WaV2wQRQKkY4RupiZQ9Q6UdmGd7HaevcsdU8lhcllJKJUugffEqjcprjH/bmt4u/LKg==" + }, + { + "cmu": "0disoPeA9Uq0ygGXCyQjSmcAXnitGJNE/uKyvpzK/BA=", + "epk": "V+fCjD7Vg9YTbdfmtevXGpv+wXizALFBg0IhaW1nDMw=", + "ciphertext": "xy6xrZhOK96oX/UA0xYKyM9L01spfRw9wME//CdDF93rD+QN2SQzWjVyaeVuLQGwK8U84Q==" + }, + { + "cmu": "qdt0DGpKiIWLXUVrmqIWskbQw+ufzmxs7C4BXHWyZRw=", + "epk": "pKypSJMsgrwBDg2ECGcJZqWL3M/oYzZB+FmU2rO76r4=", + "ciphertext": "A32Vk43j0yCP7rvUYCcqbnYVcKboQQX8JzG2lkjVfWDQPFkhTs4bkjWnjyC4iVWE3LCeKg==" + }, + { + "cmu": "gVHHbd2LJdGDkracbBU8adfyL0x3uzEXOqOBsywW6xA=", + "epk": "i8eDeZYlS9LfORE01JUg0Wi7Po3oNO3eCeYyY6M3gRk=", + "ciphertext": "fncQ4VTVfeBrTto39kT4aOyuygozZYcpGdvPoLbOpjf6deVWKsbvkvexcvF3Cp80EfgdlA==" + }, + { + "cmu": "CEAK+uz20fuKLG3SLnnZsQ0ReNkDMeMLRURReCe1JQ0=", + "epk": "XrWzBQZId9n5PQcFj4fgxTueqBL1vakVlMGfOWoGeWA=", + "ciphertext": "is9hnJQEuO2GhFwoFZ2wMoPBjKSYs1Tt9ZKouWkyYG7RfNfXnZlgrOOapEmCu/e7IO9e0A==" + }, + { + "cmu": "Ir21eAyLkjjsQQ3qc8rlnWNpDosElYraQ+kj8TFpOi0=", + "epk": "lSpCgAUBHSs9EpbrT7mC5BpZGlAKZS6YFxLAC3l4Tpc=", + "ciphertext": "vBxZ8euadylLujTmHZiML+vdeSOe7WRuJ4ycN3PIm/kvwGeYmeaxA2CwkR8e1nYDKVQKDQ==" + }, + { + "cmu": "kzwjAUhmj33Oql3yOw+ZfJy6yUNT3Yl+NjkhvPcp61k=", + "epk": "J08jRwcs/nMGgAc/S7YIA3qdKzVICGm7NHZlQ5qfnCA=", + "ciphertext": "vHJT6V+xg0AksXkEIgG2LYcGdqVM5HZzxWJYtXzdw0l6QLeDfLoAXH1Q1xWh+KiX6XLlLA==" + }, + { + "cmu": "skXLVwXNnajNHRxZSoHAr2r1Hfq6iXwgxsaCWF0SRjI=", + "epk": "dOTmTRh0+sboSJtgO5sdspPTaYasmPT1myhy5QhkV7Y=", + "ciphertext": "aV8rsE4LHU9pjmiH9WL2dthu4Bbo5ijIzm9Ygv4vxNQ1vBshJQ/HLbNYlW6SEfJCz4Y6mw==" + }, + { + "cmu": "LylfDTP/vtLa+3QvMbzX29a7xO+lIRQVE3kvDuEmiQs=", + "epk": "9Lruk1qi9yqA1RaPozk5blo8Xed429qBmdCl158xgD4=", + "ciphertext": "baY0Y9diaJd4b+hksiNIMhqsewnqaAAOHA2dBwVkqYh/EPCBxDUb/5hQTMJD4Ptpp310Ew==" + }, + { + "cmu": "+ze7BQ/uuMBmqPDGoS3xETo6uAUqXFuRZujzvfSf4iY=", + "epk": "rJY0e26oGGZJukmrbs6bvu+ybFYTgWs6oEdT2fFEtDI=", + "ciphertext": "56gGu2fWQk+iR7QmNVXCDrgaJKErzYn5CkgA/VrxMIU5P2/cQq4cgfEdd2q4sIHmZUyspw==" + }, + { + "cmu": "opSc2MVfwb2Q5Q89aIuWk761TFE2u8Vgmf6lZLxx7BQ=", + "epk": "mFJFJ/WVyz7BhXNKHlh3R4+EbjDYu5LnWV6wJtDc1c8=", + "ciphertext": "gPtV6L9J+brVLLUVmCpzAS8oDHrbbOt+RNeH6Na+7qW/3K/2Ey7+11de2Lkcd85G5D581w==" + }, + { + "cmu": "JjqAcWkvou9FysrW5O8flJUwT6Fis9f5qGscdTUikmI=", + "epk": "XvxZsAu3tpDnyYpIIPYcDlV5oHrPesfyHeTn5getwyk=", + "ciphertext": "l83mC3sDp1WZWEjUCNVId7+Z1stMI63QYBpbP7sGK/I2W1FzbvfWFR7d0WkTFDr9737Pdg==" + }, + { + "cmu": "KEudH4AgwQXqu0sRPtRkGzUmr2O5akaRHpeo+3iEDzo=", + "epk": "Bn6LAJqBkdEdqG823T9mnP7SvlnvPH9DBVqPSlORcMg=", + "ciphertext": "Wxl+xJh1HayiPy7/CGLqGfTSULrsA3K1wgV8R4qhFlsH025Uz3Qr6qkkWCvMWRO5HqEgLw==" + }, + { + "cmu": "g11iqhUlpOdT3OCNoqANxHuPwLTea0QCIcxkhHdIb2c=", + "epk": "2RMETmwGQy/PoZdtvBhJRv8axUvzwdRcStLwIz4tfLM=", + "ciphertext": "rnH8fhMmO2EHRzo3cn+sX3T0RMs4pH8aKC/MYKPu+Kcfvi1W/N7wNN5bFV2WD3UElLnyZw==" + }, + { + "cmu": "U4k1LMYGJM689wMMGVeMjlqQLPg6Irbl6FCoiV30/Uo=", + "epk": "/yVILzkMX7Dr3u6/cP2/KrxJc3bz8iJNPUXXcdbsRm8=", + "ciphertext": "UR0tuZER79b6JNbAjdyJMAU0iIOFqQIJHq/qu/7AkMHGogV1Wr2uIrnVZ/QfeD4Xra4HXw==" + }, + { + "cmu": "3IbJX/0eLT9AHoe6qjhUufClsyLpGQzsgrmhcyEZY2w=", + "epk": "CWNzYZmtcndKXoF1Z2KSmY8cH27pfgYgyhBvfojGJDs=", + "ciphertext": "tGIkNKctE6iVHQNv1viWRhd+XkKufYgnC9Jb6+/07UtmBY5EoDpAWB+RpKImO1QwBnLl7A==" + }, + { + "cmu": "5mbmh3w2b81GjLOwh2bA3+Vr/THJqZoQfZn8q+kLWHI=", + "epk": "d74rSq33lvUv9q7QSpBEZG4yaF84NaU7sXcBqUJ7k6M=", + "ciphertext": "FZufydd4Fyl2t5AvKv1QO8uQXI/TSaUnxmQRKSgiR4pUVjm2irp8PB7eSRAv43bOVj/k5g==" + }, + { + "cmu": "5eVGKFkZSN430lQREy4BBOj5lSpJRS2WHjP5428aKwI=", + "epk": "0nX4mtInwubUPl7AfEeFbexgUldGQYzFWOqOoYwuUVg=", + "ciphertext": "+LDbPdCHf0DIme6LAJAroNK3YCD0sCvCtjgQtxEfcwInyjv/AYSFlAylmT4/GTwj+3ip7A==" + }, + { + "cmu": "B2tDIH0sws9xXYlZvmvQb4unEQ48fGMF5ndxi54coFc=", + "epk": "+g2erZQYgEgzPCNNCmoMq/y4237bvC89PjqbuOZsnpk=", + "ciphertext": "RQLLGZFuAHlGQ7B5zFINozxgy+DCKKfPfADIaMGRReAMD7ErnOc2myFFefXbhOG7VyhRRQ==" + }, + { + "cmu": "RqmBqX0PghtHQFdzQd10w1LMSDWnL2XLRGIW23lCylY=", + "epk": "DpANanudOLBs/EeTmu86/C0ZhtaWmKJqcBUbPqKlgjA=", + "ciphertext": "i41+fbfT5c9OqDvSkRzY9XfL+F9U72EMqW71ua5IT+eGKGX0ZF+Tts121yqDSp1eJlOHlA==" + }, + { + "cmu": "VHJubkSE6STqnaUmQp54vzMODFHOohtrnRlCgpQo1EU=", + "epk": "lgIe7fR7kig/VaivHvY1kjrpKTuB3AvksW0r6tbyypY=", + "ciphertext": "vv0By+NajuGkIjM6G/0GS67iVCaUjRFyRNwqiWkrAeMoP10Qffx/19QAQWLjGCvaCmgy5A==" + }, + { + "cmu": "FgLOZ+B0Es5QDt3q3F4RjfhfhQ0cSuJAPd1CPbvAHzc=", + "epk": "KEkxJkre5/5luuKAI19Yl+xEyBPzHM/Q/v8j1ZtkJYE=", + "ciphertext": "x4LrGvoVYkSOxy+m6GVfK+phVoI3FNOELS1xbZKlKq7IiVPIAGBqv9VyoY1Pp3XcMOAPdQ==" + }, + { + "cmu": "Nl1ojwzyvC0QrQV6i0/nh8bgCS51syEN9DCEtvYlsms=", + "epk": "qqt0JvXngn93XKOp6XUlsTmUI5K39gWjDmmF85O4R8I=", + "ciphertext": "rYRHTWSLNA/TKDXFKkorO0Mn/0YW5PGl1MAFlfCuWlB5QSR4F32YwlSfUB2v71osMdyXlg==" + }, + { + "cmu": "hbs6P4Iw45pHlFCjz5TmPweIhfmmyOlsO60ZeP70h2U=", + "epk": "+LUVkYqNcpupAqrH0mMODwyJ3AI7GmxNXteo0MOLW7E=", + "ciphertext": "BKI9qnSy+4VPEFJMFzI0jiIU1O66BagjPxoncXhcFeKMuEJmv6gy4JbeFmjeDHKk78skBw==" + }, + { + "cmu": "lCmtZ7h8X0evtCS5GY9xlgJ1zdSVr7KS6b7YUl1pdm8=", + "epk": "sEg8R73z/W6z9HR8DGAfqlDTy7xc2UCjHrfTyjsjjhM=", + "ciphertext": "YpVGwkEljRjULDTByFujDZE6sCwPreVkDYfPZ7xZzrGmj/mcK6Y0VWAzA6T7Bvikj0lWJA==" + }, + { + "cmu": "bPYOVpHkgps7bu1IJRy8i5iElpnXZzKM8TeO8Ngm6Dc=", + "epk": "smPSGG+FV4Fvorpz8S6lqs6ObbEIJLSuU5jp0U82+d0=", + "ciphertext": "Y6xiFvh2zwpdevAaSD1P+lLoJNTLQ1li4LaYVPWH9LrEhwWG9v1CIvnpNMgsG43A1NpnCQ==" + }, + { + "cmu": "6bYTU7DsjLjY4ZQu9gSmWjJP2FP0uFfInPT6+uyIXiQ=", + "epk": "fzBgbDBX8y5jMrQtLoku6MgsbYflOLWEk56yW1vc+JU=", + "ciphertext": "W4WyJMf7Ng6KLVwMewgynOxhB9mwTpz8VXI6VBloO0LGS4MsJB32MM0ni5i3A4WYedimuQ==" + }, + { + "cmu": "0sDepn88AxyLpADm1H2HVfzfGNq6mz5BsZr7exb+hkc=", + "epk": "OIKbJFnHZf4SH2fg+/DCzZ6/Ga/64IJQJKJUt3Lzszw=", + "ciphertext": "BlTb3PAmp0tH2NS2cBLiqqIuGcrGv2K/5gwZTE3/LK7cIMomPb5ztHDdF1CYKec9Zjn3QQ==" + }, + { + "cmu": "0Zoy19AWMqpAfkEkN0G/o+jw3QjH5LaPnD7w83AAmw8=", + "epk": "q16cSNx38MqarlgELuAAZ84khDkPBbc/MQIqmNkMXjg=", + "ciphertext": "0EvDocLrBzOrSADJI4cnhcyQCsSqG5Yqk6ub07Rp5mQMaeBWOMRWC391NAnkMAPNnt+Ijg==" + }, + { + "cmu": "mvQ9AbNVuk3CIYpOlRXcGVyxsJe+VVqqLNJaJccfdGY=", + "epk": "XVMny/RgeuVX0sHEKYzZ7yK3fTFOyI5BZC22GMQm6KA=", + "ciphertext": "+zT8ZJo2PPBCuzYy1ksWxq7OC8DB5/z9Ad2bsiHgOk1zoK+o6aQAZYKgSbw3hpbwTKucXw==" + }, + { + "cmu": "8QUOwB3QBxPJaN3ZXPIWb5UaMxt40b56Nsn449nLcVw=", + "epk": "o4Ju1/2D1N1i6b61seQaqwa8KmDUJDXKq9BhWV4CZNA=", + "ciphertext": "iahJShoewvdDVIh2yMc3fsmHNr4WsWx2YDchRHqfqVyI8x4/2FbYEapmEqdpXIK3Y6Rgjw==" + }, + { + "cmu": "1pMSd2A3KumclDyVUsNUmKrv3tvZPuH6umBJcfMg0j0=", + "epk": "FmOStR14sB2K7v/XDb/F9nkl7kIgfu6B1r0KoQQktoo=", + "ciphertext": "Pqxxo2XvYG1/Ufl9OlTnmGBQJNx2KxXXYr2h/lkgHeKv7q4frbvxAF3T33f2bnP5phSdfg==" + }, + { + "cmu": "3SfRJqmMA3o95iJo/9lqmxKbOYOEtqb41GngGvmCM18=", + "epk": "GNh32uTvedXY4DsysEqdLsLwuz7/ZwOApYDY3xZU/Jk=", + "ciphertext": "2v2GsRrzzGn6Geh5EaQKLnq/ZkNhcaSAdDv18h1Pv/TCOokWLVtsqN5k2Sz6u1DJM/IIEg==" + }, + { + "cmu": "V6wjEBsWVIaRSClFwCK+dZPOL7JK4ghkgubSrRHxUBI=", + "epk": "wEHXAvCsr1XGq6XbUTgXmeOg2w+WPdoQxnB6tEN10r8=", + "ciphertext": "g5hI2mRwHanDYs4Tgfbe2iC9bZyGy5t/VpBh2578NxlHXNdFx5CiDsUQeaeL8r7gr4vSeA==" + }, + { + "cmu": "9G3EfHbc/C85lthc5XHi3j7oSR+a+XnV5Y/a5UjpE2Y=", + "epk": "Uu6eZkF7WwkmowtItrJboY55U2vawIJrbjaXcupygUQ=", + "ciphertext": "AHJgV0uPvRch1g8FH1Vy1fJYdZCVff4j8fn7yh6yS0Jp/OzFCtZn/8srePNa1sJUaqvBcQ==" + }, + { + "cmu": "kaaP+9I7WUztXzfQn6c4I7F3UZjpcUkarrpFzYWsWDU=", + "epk": "DCGGESfF41T8s6W5/vjVd0BBx0WKlEInKDtlcDT0nWk=", + "ciphertext": "WYsCgWwDI8Zh+gDetBmWvkxPHVHHmoaxk3n13sl1RH/2yWvGhHXfUFPSccKsPYlA2iNWPA==" + }, + { + "cmu": "6hP3MgQ+idZJ35aYGUEp0Aj3qYGDnvqt/vetP+QdtkE=", + "epk": "/eC56oWCKKpMzHWNUBpNJ/gPWEN3U6SJCwlSSgTvqAY=", + "ciphertext": "bqBmcviLnJFRPe99ewdG6ok9vItoN0H5lVeSt4RUZtPHjZgc5DaHgZ5MO7RyEZHW5TXDaQ==" + }, + { + "cmu": "y6vM11AkycAKOxEVkIl8wA0pJj0tEiPa/H7Bg8lOpmo=", + "epk": "cQOQ/Gwdf7otMH2EO6N7xPMmeyeJdZrHpwwMoKrbjCo=", + "ciphertext": "kCCTVk1qvQ1+YNyQUgD0DujF06qqggzGXNzgOYXf1H3KOOAESD23ELl4voYQkIA58duGrw==" + }, + { + "cmu": "8xur4LsR3p8b5Zq+Fj7AcET1Tcf9D4BzzrGhuJhKDDQ=", + "epk": "6ExFSbUMhJ6PjSaL1+v9Pq7MvkXTqsfq1Vb1ybI7k2g=", + "ciphertext": "/lylPonRXouydWpzaokF7TZoDurwkrx2mBj+rP9gL0zgzlyRU/Xi4Gu49N98dLo7aEkF5Q==" + } + ] + }, + { + "index": "18", + "hash": "YZ1YztQZM5u5yQhnhzePxPjcnnAC6QNfcnYXzYTFQcY=", + "spends": [ + { + "nf": "Kiz+qtoSlzl4eDFoD3Da9r8w+WwslDnfjJp7PNL8tcM=" + } + ], + "outputs": [ + { + "cmu": "v3sUyw6MeMR2/K2a0q/aJQc4/EEHtfK310hE2LU+G24=", + "epk": "pay6b5YjYd3NbJ/gb7Nr7fYtY2s+lUAvNyKEz/PssSY=", + "ciphertext": "L73q4y211zSMUTnAjexBKm9muZVXGWz9vVtSwBad/qoeSCxK4OEIonlTksY/5OfA1PYEfA==" + }, + { + "cmu": "Pt5mBXi1DFLoLHD4EGIwIevnVBjKYP3hzPqXzXYE4Ac=", + "epk": "gUn5b7Q2HdIC4xGBEloy8ikDLVTybjcTCaYuwP2Ow7c=", + "ciphertext": "RI3Kx8H5cMFy/XuO2qRwxh0Neh2AmX44m/XSXv1w/Bq/1bNLXlLcweBI3b/FsjU7qMIL0Q==" + }, + { + "cmu": "uDaRD02MjyvcE1Fmp1M/4VMmhUcI6ZVqjZ19S7lmS1c=", + "epk": "+eY5rsBIK1voR61pStilZXzZ83uNgRKuAEu18U9nQ4A=", + "ciphertext": "1vCxINkFZhqQdQFE5ipm57PTDwnOBY94qdst5lClZUKr6Re6i+Y6Hagn2mfVVU7pjqHpNw==" + }, + { + "cmu": "R2OrSI7tGBdyjTHItK8ZSehKqqJkqR1/GmhmgMHzAkY=", + "epk": "0o4f5K/KgUOwMQYTHJO0oPfROZ0Xb2C4tlIOHc0IIQU=", + "ciphertext": "5Eo9IOakB/N2EvhMsTIQypbXPs3GoGAOchqqP1JLpeEm/2PDG1rDogeedLhouzXnGWuCTw==" + }, + { + "cmu": "+xNdzs6G5/ZdxeLkENH7863F2FHL5mwJPH+Zf0mF3xk=", + "epk": "Kz3L1txARJhtwX+TRix/W8BRFS/AKRpv5o4s60SJ4vA=", + "ciphertext": "ZbDWC4moU61kJKs7NruLT3HW/+97CLtaUzR7px/ECudeXqy0bDOVVJEjDd88S73gM1/wQA==" + }, + { + "cmu": "yiw31XjqhfKvj2FrPwYoRf7o5rtvhrSeFfGPqP5Cgwg=", + "epk": "dvPpm0bxpfp/mJd/2Evc04zhQTiuVV8R2mJ0bkZA4Cg=", + "ciphertext": "Je3lsASnc2PioPr36TNocjofiaxsr7uxP1ca4E7H8g0gif1K8WU/1ZoA6DQc9f9WXu1ALw==" + }, + { + "cmu": "YS8p2xSUGcEcZJjiZ0yYHc0SMBC8CjDsTkW+xtF24h4=", + "epk": "4L5vh7tLFTkf83GB8nyTMWpPXjUEE6+oCrsxTn2X3NE=", + "ciphertext": "P/HjqjPWNbF6n8qXaMl68NqGhtRCzJvldKOlwdZe3oUy8ual/3OgU+7c+dgMMOi5KLIX9g==" + }, + { + "cmu": "hESNETfncY2+t03/o4ZqTJ3sIq/rXkBohg48tfve01Y=", + "epk": "/nDUfEYw8t3zUzZslnSAvUrToamWcmjk8gJH8gk9tWE=", + "ciphertext": "07wM0BxtrmSQ1OaqiKAGFi23KJqtWCgDADzqD8vOFmcTrICSPcl/3EOtvsfp0TyMx4CCsw==" + }, + { + "cmu": "YL78dt61XfZJx/KT5hUU8aQvc1WR5wZ5ZKYP/lvP2x0=", + "epk": "73Hw0WAsFCg2Aqkwkx2QqVMyBmVMZD1e1oPDr8VYjdI=", + "ciphertext": "thpka/BK0lLn9881usjmEvh5YrD6u6bp8OH2aGMhT3UQnGj5P+2ogsXdsghGJOdCKww4aw==" + }, + { + "cmu": "bzqxlyNeGWRF1ROYIP0QTjzMAzmjNPaQTfQrlTEJDgM=", + "epk": "ytLdznHkVoPTtu7T+XMGRWYaJFbHnThfMXEFoFaXJ9E=", + "ciphertext": "PifSj5EzKG+cbDC3WCXe/4HQq3+OZ9iKjVsvdmeCcyQ4kDmdeEbpL5YzMlq3/VOFbruFPg==" + }, + { + "cmu": "VgqrQbK3o/0CubESlTa6fOvdzoy9JnRcWKe4SmyuJGM=", + "epk": "2gB2x9fY4xJxTFBizvDpaGz84VdPxfRLaFWYUGjL1rw=", + "ciphertext": "rUTfm4mY88IaMB5t0LREWMEGgOEC9YlKBuNpZmGeEiXNuq02JCDzDkIfiDBoBwvbT9osGA==" + }, + { + "cmu": "hN8B9ixow+nauR8sUTQ4Q0L0HWJjCeKO2PvDAob6p0M=", + "epk": "PA8kHI0PSMUz1+plxHEQ+OJl8IULjS/Q3A5Kxgs68+U=", + "ciphertext": "a3nZwAKxenAKYsU04yidlhnnu9GNExSJPnt5Rud490eEBoJHgDFexZMRw3YsDQvAS2V4nQ==" + }, + { + "cmu": "l7QqIth74Iw1HtqFUo5D1JS6q/cWCVD93S92LGDbpxc=", + "epk": "pDUqUl9ytdL/SGYodglao+p5++9UsXiVaaxWe4oLcDM=", + "ciphertext": "rJU6rPPsV4WRgRhsBi1Y2uVlU9JuZx6DmkHjegxuQBtg1F3hoYi2D8fPJfbg65Wofukueg==" + }, + { + "cmu": "rasY8KO3Vn9sMYg7THgXvDDM8nRkKEXxhMSGYPAjLD8=", + "epk": "xRIrzJ5kAqYnbP5/siic6LKuhflBD+1zyh/t3FzXFLU=", + "ciphertext": "Txt3mfTj0qWnaBVhp39TPBFLdbF2I2lVY3doHBe9wPTYlq6sdCJw00Dp9pB6YVZO56sQsg==" + }, + { + "cmu": "TKdQARa5S1G2fXAD/cZgdUPr4sHBwiQemRXSx/y9vjI=", + "epk": "HCpQHwqunAFVqIa8mF0bSF4n/IcVwZCZGaXlpsQZG1w=", + "ciphertext": "Ay3oJ2rgyJw1eNEAfOszD8nynMBEW3iTOQKF4R7VU/pxSq36Dxy8swTvqEFwA+ttFTeFjA==" + }, + { + "cmu": "NVojsuxdfeyoQqVyCr5YbTgpsZ9g+8dpe+snH/HdSSA=", + "epk": "xfdcE8jxKvm9qfIUNjluZaEk+nEQZa/LH0iu6F1/QPM=", + "ciphertext": "JuYRKXxhBD4HWTmJsSiTZdBLtKaHBXMHUtumYHmpbcCeLrW4gCLSdHHkPuoWYUt8mzlgCA==" + }, + { + "cmu": "63vMsSyEK3ziDsWPycMlFbVIf/CtNqamVE+TGneuDVk=", + "epk": "MBeuEQcwAMJmh/xr8sroL87aLOBvWYGOzBYayko9MmM=", + "ciphertext": "XMXA3VM7KDCEcyRBzNLtOoEm8xBnuTOSNpCvG/oB0aXoxPd7Ve/0MWGfh/RLAWVtaAkswA==" + }, + { + "cmu": "QAIM8dz2ieAX12CVlNUIJ0hLbuOavyjxKi6C76ToxEA=", + "epk": "lFzbEMvx4/xmAXCTR8rkguMUAcweg1eq/0d+e2AQ4A4=", + "ciphertext": "Aj6GfU/ghlnIXt9RzjNEUu6OAjIZoEHAtpbJlgztQ7t37qpKjToB1JCdruguB6ROP3i+ig==" + }, + { + "cmu": "DCeBn1dRvqTGfBC4O0amWt+ZfwJNNEgwhwFidiNrklo=", + "epk": "ZLLDfMAFrNKtIjWq97IGbQonW4NXKopP1w1+N53t0I4=", + "ciphertext": "U2ZNyKLqXpRS8kvRuXKy3LaUWMRax+HWvVh/5Iz8D91LxV+IM9S6lVaWevRE464kmoTxkQ==" + }, + { + "cmu": "N1BlIl/CG0mpGqZNAV7Sv7eXS3wXF0zp5juD0GTPLjQ=", + "epk": "z6vbOv0hRfbzPjsxjWxqRF8Fm1l6G8nc7mA8cOQiKIM=", + "ciphertext": "2KFqBEpcMhZp+Hz+bN+BihYp43Fd2nOjkr8oD0f8Vl7IvRZH5fsK9xd/X1yaPKv6+MgB1A==" + }, + { + "cmu": "IasC70/r2LjJpa0ISGjg9Z/Xzt6neA0rfLZnSP1DrhE=", + "epk": "BcqHHVWeBIKjf7KzUCGJN3q3QE1yJwvu8fFUOuLedws=", + "ciphertext": "ANhZw1lcvUATZvbXaXz0ANz+420wbp0/ozjtWakANaZBLQLARx33ahslbQePcUIqVlv6WQ==" + }, + { + "cmu": "0AZPcke7iyLC9BsTUNKV+MRm3SxmWSCR7nhEBKz3+FI=", + "epk": "CL6N6xEpr3Lk0SbRKGA8DfrLCVpGpjC5c8tUw/vByhY=", + "ciphertext": "iaNKYwY89dcNO1gS5tMeO+osT8aXVFIhRWKYdugVhlaIjm26WtfKGLgVWpqGlmkB8C7Hcg==" + }, + { + "cmu": "mUZj/ditUmv5ALZkRgS21v4EfX5dKoHt6MKpEROTPxg=", + "epk": "WDGl4GlKeSvr50ap0iEc0xFbMjIn7fLtspZ4jsRDex4=", + "ciphertext": "VcwwU5hVroR0+yjHdElXs3Je3xs3l1euIAtTIMqqcXLQOWud2yFSAs6+S+fRIfP0oetLJQ==" + }, + { + "cmu": "K41YN5s+Z293iMUCFZN8viVgmzJZiA1gOllKJly3A2A=", + "epk": "43NbtZYiV6KlhqjjNFC/ensz4itWnEM8W9uUO9NuR+I=", + "ciphertext": "z3AO2/KeU2zpyoF3KJQ0h+jAtoynxRjF/IRiPmWFe/yYJmOeXBSbTcYhSskl0ahYEpjF4w==" + }, + { + "cmu": "6PGvrjCVPld/u0lAbkwgVmgvKzn+SEcgPzpbwLyaBSU=", + "epk": "rb9/LIOPPhs122kXv5sODKb5eXQ1UC0yy1Q8tyN6CYA=", + "ciphertext": "VPEP9S8VWk8sb6pJvye/3HKLUGWfmyniu2O5UOZtJ+q6aVnHWR+UB99FylNLiTXYW8UHzQ==" + }, + { + "cmu": "AfejZUenVslsGDIk6brAG0toETJo2u4vFDr7mHlnjSI=", + "epk": "TPueiKMzWrEBQwj9waYZGjFwV3di7hPkP8uIizMGLTY=", + "ciphertext": "13cfgQtAoSokfNmKzr672vj8I5dvqjlYAFW/eVx1O7vkmxdbpnFgY4RDYRZG3bXR1m1OHQ==" + }, + { + "cmu": "FyqhKdhQtgWj8VAOtg0t0pFaLoBsC/HnVNGQivFG3ig=", + "epk": "hkPQ8i/cRekBcAEn9vg6mCdzJeGgcJAwbCmdj5E1XZU=", + "ciphertext": "FD9voDxPIhD3pfb+fhNY5VR9Mk6hjoAfyOs8/Iuk8Pn8pa1jxW50ywfV5R6JvxDWGKGw4Q==" + }, + { + "cmu": "YJGPOVBIriZJL/A9tvjZPEXR5f07FlP3fAGCEg8SYAI=", + "epk": "cv/4HbNwDykaomgRgQ1kGK2bdDBFbAKenRDMx50Go6Q=", + "ciphertext": "gCnUvj4Uc7BIHXuWRNMSLfdA4Fq5RxthbU74CAJRRw/uyLhMA2hn0K1dghxgiGZgwksm/w==" + }, + { + "cmu": "8ux36t9VjdsTf10+pRQrk5J1A4sE8W8sqLfyw3mSSw8=", + "epk": "4g5yj6Ld+BTCzJOPXAtGvAMvdXLZfmbMNDer2CnpT+0=", + "ciphertext": "UMTMyoO3XKh30b0OKvZ8mbtce3AyYNASOGbkQgkkivDZBxBRnglE8XlSRNFxuSh6LuwyOg==" + }, + { + "cmu": "MnX/65ynLCiVoq8Ys+ZVBbluXSTLIzuJMRQDJ1JfMRc=", + "epk": "+XhAoxzUWqfZ7w4lFPkUGBX2FbjK9FXWd4RMknf7WSw=", + "ciphertext": "eIXZQT0mZ7kOe79c9Zz3uES9TXdNGb/9GWEibmQnxqFCWzesIH57vwmJn+6qDtMeV4uuMg==" + }, + { + "cmu": "8bLmumk/tCAxnGdwjqtMWGuJRh16EjHk9te+XJHOO3M=", + "epk": "QEk6sxOc5cWzkr7n1kE7FfvUfIdDu0KJ3gsigPqduzc=", + "ciphertext": "0TncM6eMbzqxIUL9fudXoHePWQi6N6m4PAbqZ+LLzxE77J11xk7P8zvYFESCDbQrapG/fQ==" + }, + { + "cmu": "5wuqmhsVKzyz0LNBpmdWGC9sMjSg9vZdb30MZ5ByTBM=", + "epk": "khABegz7uqHbz29xvRTmAQtTD7GepEtgUhtK5hnNwow=", + "ciphertext": "MRLRqSC3jjFaDIZAqBivYQqWjjC1+q9eWWrZEAIVxLV3oD8RgIB7gOyvwC/+nitYxf+Kaw==" + }, + { + "cmu": "NvJQKrGoGqc8QyMQds2PqXpEIAWlmCRtRcN1NqHDLkc=", + "epk": "ysgk5hR7bywFZSd0ksR6gG+EzSuxMa7cOWhxdhOjCr4=", + "ciphertext": "kgO+ce9B19JX1lXH53ngYGkJKF4yoRGUfaFCB4dFNBTpYl7qxCcTdDdhXbhwD9KPWAsSxA==" + }, + { + "cmu": "fpRXLrUykCVxboJL/HVtFl04yJ5tTEI6/Qu6eZgkeAc=", + "epk": "bAq4OCzaeK11EjDeSYeM8DjAEdfSWRCuqTS1aJMO0rk=", + "ciphertext": "nVR8BLuDq5fgH9Crv1urziJxAWZ7ndltI9yYNOb67G8MZMS2+hWaKLybYvTvu4NaNou0Ug==" + }, + { + "cmu": "j/pfz3acFmPP9G3gReysXjQ8Ep6eZBYSSLpEGtwnMiE=", + "epk": "2L42mxG3+oUSj+sUjLpclTcNBLfgrRh0udEs82goL7k=", + "ciphertext": "wsPzbZcmsNPzTodGOia5EggPT6+pZBfrXMUwySLGx0cL6O4NXxc4M8Z6vw07IEA1Oti+qg==" + }, + { + "cmu": "eEno94lAtKoyAMn1p6/KxevdgAGywiO42RfhwOEp5VQ=", + "epk": "J7w3SFgwweH44Wh3tAy8kPBZ9jKE+qduuM5OSzNdSVk=", + "ciphertext": "4K3HNLXS1Ox6nbZnjJXH7ZJJB05HlO1ojcoCk4oigkV195zsW6FX7YoPNZnuoGelE45q7A==" + }, + { + "cmu": "l+Q//H+PIcdgnwuPIHKeUszYU/0yZoLRBlBKVEBInB0=", + "epk": "7OfgNFmZJMat0TT24u3NbwxTDss1wtl19UnsITQx7RE=", + "ciphertext": "wnQzdUb+XQJ9Kcw/V0UtfL7JpnfrlaxRhl+kXXA9QkzvhHDSnCWWpg2pu4fjM3SOBSbUkA==" + }, + { + "cmu": "zIiP0EL38qdhocTRwUiUcAn5okNbsGdjg3YUAm9mGWc=", + "epk": "tQmUXv2IMM9v8PuBlv0eX2030pwv1GRzt1PgoEfJET8=", + "ciphertext": "155y0dUD3sgefxJ6dUf1SwhARjR5fpbWeSD+zueCOU89d87CHgltVmeyut4tfpCAaCqTJg==" + }, + { + "cmu": "oZ4dGLG7eyElumT/ItA47KhvWOyfr5Yvy+s6U4UXwww=", + "epk": "vrhhWBhKlN332h/29hByoHWArmBztRn4STrSD8kLPh4=", + "ciphertext": "t3+XArRSyYsLVhRvmzKHAY9uC47okE0ZnJrVOYgZQKx47rOzOQCdEFp2QnAXoemQZlIa3g==" + }, + { + "cmu": "WCkWLYnb+/ZGecULq7UTuDqoXUUN/gBWxDivWmS96Eg=", + "epk": "2Bel7NrYwXV3SAbCogqFoLuQfBVlWMJhasEIClxWxxw=", + "ciphertext": "1a17XNtCLGkXoofjTv1aAn4i4TSChoYlaMX6za/mgJFAXMHY7UQmcLW7fwMz5YZmRa/qjg==" + }, + { + "cmu": "mSnO18Y0qpMUfQNxUb0fKDAbUjbP+50sW6o/FDPQjFU=", + "epk": "SfPe3hJhG5elzoQRYo+jdagPIq2xKQy5XTYhRI9PIZI=", + "ciphertext": "XpGSrUuBQDiJRiVzvRsxnAJwVYMdsZFPCzFPhvCsDNLzvkEbvvmc4phUgVXiG33i1+YzRw==" + }, + { + "cmu": "SE9P2DpqBENMLn25yzX/nHuHPt/CG6SCoY3KD5s3NE8=", + "epk": "cpHCVh79shrM70bL4vqynGHH3tmU/cW1mwH4UyMuRBM=", + "ciphertext": "YtEaDA9xqUCS/jBeoNpi2YWcsON8uBpG0G7TmOvCU1Oe7FOfv72M+JOcnn5qHWoDyO809w==" + }, + { + "cmu": "mgJRfy4EIwvAFrVdFQzSenAWDOBDx2j07hbJkk4J/h0=", + "epk": "CrToSpSiUsLBx/UBeGbGquD03BmY4HepdDQxHi0KZxk=", + "ciphertext": "iO+ZtNLn1dUYSMQmh4yL2E2APrH/nKyH/TATXLUp2wiPXcTNJY9fBsECOF6hl55Z29cDFg==" + }, + { + "cmu": "83XPjauqkQQV2Qkex4lFO79vNb55tyAkQyU1SUtg3Ck=", + "epk": "bakAyobfYzy3K7p4LZclsb/8jiwJBXC26oXdInv03ew=", + "ciphertext": "vkNivlKPkTspn8pJh4ANrUqBeGBuYxWPi34ysEhFNQAEry8uRS2rHEugj0NBibqsw7OhZA==" + }, + { + "cmu": "BeQlpwC+rtnltlykGprHNw8p3UbpB3hpiraBzDebA0U=", + "epk": "hF1B7tXGI7F8DQcBVvZqaTc9kPOf7WsVKL0oDcAZuro=", + "ciphertext": "pcb/qUZafWBXg1VCrQeOBzbhapuihToySvEprvA7oWt3iUMwnfVKtaHgALd57PAg8V6GCw==" + }, + { + "cmu": "aiovEhFOIrI1mHHx8BvlR6FR/MR4OyAK9Q/Vj3LWiyo=", + "epk": "x0G9GgMTnihDyVrrXuoTQdaKTcDMNQ5enMxBi2/WkV0=", + "ciphertext": "25KvQfRPl5IFn13e9txDYSIHLH+VraE8FKRvzTySl/v/LslsTUbQ7p7wsnFkAsmuBLnEXQ==" + }, + { + "cmu": "GDN8mR60j5TaXnGy9TE/+lGEjK9vQD8ij8fhPaeTuS0=", + "epk": "Vo+wK0D/CL6Fjn/XJv9QopknODMVfK/5OtK3qGfpzsc=", + "ciphertext": "Z/srUZcUNaxd4eaDjciG8+0hgeZnTwr52L6eT5/64kBSDuPPRuedEGl+Pz8kr7I+xr5djg==" + }, + { + "cmu": "uXQE84bRS5JHx6TN/jIHYYhmx5u7xod9twbrsqmVFCw=", + "epk": "e8gRYoZr4DSpclMkZanV5KBrallibnRWimxPP686g1Q=", + "ciphertext": "+1ooCxZkuTsUnbWkAgW7nDhhyDXG6TkfCm7MmV5Xo17Q9z3OZ/h4rHIhfs6BSuS9+k0/OQ==" + }, + { + "cmu": "+4TiA49RL6QCARD4ZnCzug1H90D+jwO3Lr1uvh0aigQ=", + "epk": "dpYcKxEenRIK5XOvxrNgKhPwveAukORmj9UVCvFgJck=", + "ciphertext": "TPxuMiQhcMfyG38EnaKvflbzAQ2DrGDqrKe3bsd+HEzNHbxFwi51K99ALdSKGBmCML3Mqw==" + }, + { + "cmu": "OtqTgKmKguIybBzLukM1sUlf9SDBO4ccSUprydfsZQs=", + "epk": "nfo4vW7CIM5uTbco4AYspK2aZ0bQMEmY35pYh3k+R24=", + "ciphertext": "zM2kORST6DfjnrbblT9qkENeNjr2Dg5O7vbPJv40v3wOhaw4wCEAk3HvRjgs4IYJfjigyQ==" + }, + { + "cmu": "Rk99PPuuBJb8HJoTIuW25yw3q0n4/nhnAoTsPYIFb0A=", + "epk": "QfmzRXKwXwJscGshColxygEk0W/QsiZu3CZaHvOtXUY=", + "ciphertext": "SRjv0pPoMFg/qOxPlWcAMS7J7RqfoTEHdKrv/3HGjSeumthryx2c4o3kxMBHr6SYjR00cQ==" + }, + { + "cmu": "kYLp/3fULtN5d5cBxSgbGkVoqkSr67GcIuEmoxIU/yU=", + "epk": "AIKtT08YszrS3G9eatSYX9DG4qOSMgeksFjZjZpUPJA=", + "ciphertext": "JhRS4QDyKypW9lbXYdDR1fzKt47hw/yaeGLArFnhB5ubdaJ4CI4fSv4bjAuXF1Do3DRLzg==" + }, + { + "cmu": "1wGrM5laKS45qeOwXlg/+OjaJffyJUk73LfPNKeNFzc=", + "epk": "P+5BDpw4Xueq6rnKTiLKgum4/Gh5jC9EzaQtJINv8r0=", + "ciphertext": "MecnGDC90jUw4iu6jUNuy/hBLMVwRqdwE+YoJv25r0E323H0qB7+gkDmfaNE+5koNW+/uA==" + }, + { + "cmu": "ntBIuyio2lmN+UOR/eXG0s15gYGOd/jrLcknFSFkziI=", + "epk": "1EvifBuhHrfY9eJocGA3VQDiCW2SIXgkazENI+hoaMs=", + "ciphertext": "ewGSvlXo5rNgDbavlzpSHL/rHZS0Zg/42MpxByzMwUhO6nxjSalq2HwCAOb7YAkF0gkH+Q==" + }, + { + "cmu": "Kcfp1S4PTCsPvPzExjs8pQGeayF2cr01PvNOETBRABk=", + "epk": "xiu11UfOVSDh+esW+mRn+pb4AwGWopI6va2EUrA8E7c=", + "ciphertext": "GmUAapGZaN++EbeOMBvLUO0WcmUnSyn17RTQwBEPZYBwNIpdqemTL5cvUouDj3zdLINS+Q==" + }, + { + "cmu": "baPewI1I5TOsQTxsS4cVasW7z5MGAS/zTE4Gdjes/Qo=", + "epk": "D40Acr1IAUk1e6Sf9KYnEjVN1DhYhwXHe/TC7/QmfSY=", + "ciphertext": "O+tdBZu+SEJbs0fJW3KWG7c12UAwUS793yBWYVa/+zn0jbWBLjevLf7amfwjLHYyLmM8TQ==" + }, + { + "cmu": "o9IFsz7NFTjV60rrycWyEiVWEwu6TARi9QDsgAnEYTA=", + "epk": "Ed53Muxbx3y2ITv3GvyrSc089EWiOwHblCzpRKRbyWU=", + "ciphertext": "o/OEohjmAfRcMeuWAfqLaFW5LNQfuuLH537suG21LrBjBqeJHxBP7G414bSY1/m8LodN9A==" + }, + { + "cmu": "ztP7YRJxxQw84zCKxd5nkYLrEm7ecZkAH1/JlAa45AY=", + "epk": "NpLAayYrRYHwcVQjYxCI5Uuf/eJIFSEhhdbIKrJOylo=", + "ciphertext": "hu4SOIzz9/+YgwJQq14vLVyRpSW0dQRIydhH5CCdGURsoq+WZnOaDtPQBzTXYMkktcoAiQ==" + }, + { + "cmu": "58yfn/q8EBb2f9Rf4MzM+/RMsCSaiLz/ru8w0JJv3mM=", + "epk": "FOQK0lsH4qDaKxyiBkMsi/X7aBd1mYsmVPG+sSHLC1s=", + "ciphertext": "t/GCLcvPP8Gqrmh2Nocui15+WjidJc/l4f+GiN5cL3s60+ckTccvrIIPfQKCyFQqRSlvyg==" + }, + { + "cmu": "S2JoRPPscmZp/LbFt86B0XDc13nXeukrTdmCf3qFdh4=", + "epk": "7H9xN8lA8Dag1Taf996Hr6LWeISiBFVGgeyw4GCWLaQ=", + "ciphertext": "XBVPuSANXbLXeJl4MbUPhVUzgUHCYyWHscUeN+z+4dLh9LuRTQCBeGf5N8i16mQohDqTIg==" + }, + { + "cmu": "iU2cQI7IJKbcpSfmz/xnW+P9Jjb4jL+1lAtIQ7wAt18=", + "epk": "a3oK0BssYDbR1XjxP6pUjZ8n5ZS+zS3aRWo5ama5sBw=", + "ciphertext": "wSJaspiNp5PLJVAq40xoo44/dcfILUbtomObkinAS1g/jFbommeEZIrPfHZOLsFy74iFTg==" + }, + { + "cmu": "X2YqI7OG/g2N8qoKd1kuAicZpSYSf/HIyUaQlAUuNUE=", + "epk": "o7mV5MSkDlKH5ctA/wE9RW2dD7CYOrRDQDEpzP6edT8=", + "ciphertext": "Dbv8bXD0nfs3uknUfs/j4O0e3di+GjY/DwiYUk9ksQWlfL8ESgClxPMX8pOBIGNcRc83dw==" + }, + { + "cmu": "CNGxTDcK7V+nmYqw1uwIgtZ61dT/n3NgwSgPPy9kfgg=", + "epk": "FkFY+3DohvfpBZ71Ae7lTDF9ImQqoyEM524G4sTLLtk=", + "ciphertext": "Qv9QmJ9gn5B0iU3rxJdPJ7rw+D9cOJoz7egZifRpQH1X/ygB89G8ESAigm38cD5EvJ7e0A==" + }, + { + "cmu": "4FQyiIc52oD453bfxZ7fq7rRyRP3AarpbZxpWbmAyx4=", + "epk": "HzPbZeJhNFBU9f2PlbuBFq51wAhtozaQu69upldf5ys=", + "ciphertext": "Y/+LUMoKo9cle8UGObAtQ9c3R6Jj4Cl42bp07hNGiBcQYJvdfoRfod4zekiWohG9qh/QnA==" + }, + { + "cmu": "kC/rFNqi5Jl/tAeI7UOh65b5cJvDMdfyzRCXjeOyHWs=", + "epk": "+4Ld5p/WxQQIWpe5PV5tBtiiATIyr7rzZoHS5B+C7J4=", + "ciphertext": "qoEaKgQkr3E4tRVdGKfGLReEctEabG/Fw+52GkyZHu0gRNqCSTKZ8FXj8J7JZiSgJyBgXg==" + }, + { + "cmu": "4fmBvr2e9UUfAi/CRMv2/uqQ6ZZsizUYMDBA8vAorRw=", + "epk": "C/VbnlEu/kEnmV1b3fDeazO0Y8ELhJCOiHP6dRiS9cU=", + "ciphertext": "R0rH5+TEZXNLqq2U/LG82Wl9YZuo76IkG/2rsOsjnkIj6WVFPAkQOWetw5j9rOw4C2QJOA==" + }, + { + "cmu": "41hPjLKooPyt2388sP2ztAcGioD/SBOgZdDRd93BeWM=", + "epk": "RiKejWXNVSROpNZk0s4geCLSXO+cLXB19VlPITocVNM=", + "ciphertext": "HkXMcMpaOEppWZ98WTvn28a8EoCT3tL+Di1wW2wkK2jVvgEzxYI/g/UcOb1JE8mv3wFz/A==" + }, + { + "cmu": "DjGT/Gj+Vtdc8R4wNCv8WcPAVqgT3lWlwflfujo2TU0=", + "epk": "OtTRgsabz9vL2SV05FEDcKDWF9HkxlaJge4vWcle4Z4=", + "ciphertext": "GLiLyyRgpxZOrb3quzYopIp5gMI0pKYD2DL8HRBdiKWAhcquNwQpKzokM7LKfcNmmwKkgA==" + }, + { + "cmu": "eTfX1cYTRiBiOdHh4s9IOdME8S7Jd4rbQHcMkzSUTUY=", + "epk": "FPqcBRbf3ZwBGwju8iRChqRfpIjE8rbcN/8uLzQHrWY=", + "ciphertext": "QmVLkoux6dXOEQOrPohpHCBwX9/CwhE0PF2QwVsNaEk6i4s9odIJcu5V3SFrQk6FVcSOjQ==" + }, + { + "cmu": "tGu2gWGhxEz2WZtrYpjSddJV9ISEZRR4811kxH2K3mc=", + "epk": "1URDvMUUeYal1/69UdYZSoJx843bxNoo70vwqqrDpO4=", + "ciphertext": "JOsampJkw6IQLCTLYXd/dTSvsZj7t3hXCJeW4HbmNpgP/ROs8Oa5R7+4w6McmXAtrulmZg==" + }, + { + "cmu": "jRKwLuIUqL2bFxMzMCdQzGOlBkolEsIdx2ekE1JBw28=", + "epk": "ZaU18x3RA1Cn7sID7FnxvpdS751l6Xosd4Sp4vaIMpg=", + "ciphertext": "flIPe5syZiiEjnGYKUQHATkN0uJpQ4dgI90Igdq+nQXi4owAh5mXNGCR8+qdT9zdB1vsuw==" + }, + { + "cmu": "KBkqhD7srTKRzE9CnVkM5WJpW8nOSdsvppHVJKa+EwM=", + "epk": "t3klKqKgGVq1jGq+glaEOs8xARPl032LZjgMHPGNol4=", + "ciphertext": "qQVDWcAvhwMeRBgAuxz8RL9iv85h2cSqTgr3Y/B8r9QUG1f7KVijZFEe2Se9scfN1irNkQ==" + }, + { + "cmu": "Ea6+9skRkdCFf62cwEh/lX/S1slpIG1cKfLZ7up4LTg=", + "epk": "IBg0Lpsl6cnp8OVq+SFlEqGHPt+NKhrJ2vr0r6E00t0=", + "ciphertext": "7Xx/3y+/rCJqTewTGvUtX8z0UVwHhXTIUVqHWTCNrfkS6Y27AZozwdJdQEodP8OKWWBgzg==" + }, + { + "cmu": "evhgsNtveingpqLIGZvGl2Tunssxy6w9QedyC9bobz4=", + "epk": "Y2Kd7Epd4OCI74JTjre2Bkkl3HUPnQs+/BNUGjV+6DM=", + "ciphertext": "rKKez0zXfkLezFW9oPA87mtEAVQE9cPNMKhCJSo3lpVjCkiGLg2c0K2leQWv1cdATKmpag==" + } + ] + }, + { + "index": "19", + "hash": "k+f5p813kqzjC0Hj00MUOp4mGlBAfxdXfV7ZGuwcDyY=", + "spends": [ + { + "nf": "//u0BoexDSXLL1NSgENAHSLv8bMPvQe4MDEtRhqtKBw=" + } + ], + "outputs": [ + { + "cmu": "WTle/rTptPq1NgfXDb/pyG9KTiSrKuPP+T6H/6iyugg=", + "epk": "2a5Ycr+zHOK4kLtQMePAtS7z+nXqpNXyc7BgjLN06AM=", + "ciphertext": "IIMmAFdUdHVbW8sCjLBQ660hJph8ZLqAlDf0j8Nxuw8yhMSUsFrihRjz/YAX93VjmQNZKQ==" + }, + { + "cmu": "AVwqLv78LVlR40hbjuTHDMQSbmHWxi0qdlN+xUDaEEk=", + "epk": "Rub1cT1RIdu9r0WS3hNa/TI4JscSqqGWuYhNLAB7CQM=", + "ciphertext": "bX8+yhSoVhZ3X0U5jh2BbyZXWM5Da9iktEPdQfVCA4/mzNALOMWEpCqB6deppUuu+EQggw==" + }, + { + "cmu": "qN6OwkZVRaGPqOwdyyJOOBxolQQA7KZiKu9qGspXElA=", + "epk": "ttvhynbS5D6yOWII0roal9mofI410+Zeg3cUaTvv2tE=", + "ciphertext": "MfUZGnjLteXi1RkcTEszernuxGJs+CCQ56xQ/Aw/1/1gnrmqyha1Rg7kX6uimckh+sMT5Q==" + }, + { + "cmu": "0hdCjDsrp/Psx4+ZLftKBdpSV+0twSmnMe/7G/pEbmw=", + "epk": "6ch35NqSiIDNiLz9CcxZ0zFIWvCjGLltnx6S/MysPUk=", + "ciphertext": "SHsu9gwJ2hon+xU0WV9Oa+nNpDW0U1y35/DUecbwVNNVmfI3zTjftRABxTaFCmtx8N3U+g==" + }, + { + "cmu": "sAvjuDdFS7JXGjHLUR1wik5VT9cONz6yKx1Dcifu4kg=", + "epk": "6JBWJZ7uHCa5f1LPFdicCE1ulg81wnK1aWT/+MaAquA=", + "ciphertext": "YVNdKME20kmTtCnP17PF6aiy41O4DPziMH7egmBOOeklckozDX+iTySasSQSh6ymrp52KQ==" + }, + { + "cmu": "Bat9VQg3dyTPP1IMXrZtZ8mEBXxZemPb6udT1Aw/CQo=", + "epk": "45l0RCbNUzXPPe3IvQvpZU2R95AN7xdi19nbuMz/+gs=", + "ciphertext": "pAGAsTr+TKIMWjilfvXOCyGi8OHqwxwZGNc0FHpB9MMH1UzVG+oiBQCG1y6C9b9JeTWOjQ==" + }, + { + "cmu": "L5U/dBFb05fQ5KtSzsuL7YCQoXS728H4QeOvIc4V+mk=", + "epk": "S+ClrTBsCxAZxrj0ZWWeycDTyKUGur8o8y8XgPNhJRU=", + "ciphertext": "X+Cv8igUDhRfMfJtP5ctmroce1G+hg1e4VpOh439TwHSuZ8lsBHYKcyAZ09kMxcCflMN4w==" + }, + { + "cmu": "19hthRUAfDsQ49RZTtGbZn6JrRwA49EwZ4qZGuwrEHM=", + "epk": "3AWdvG2NGMUdxgsHv6tL3RrnMIV4mUNrIOEzTnNRm1A=", + "ciphertext": "oBLauWYMGFdhZrCDwHT3k5RO1uBd3Z2ZOwCaCSE3fxeEUOPJnYOfu/eFUJd4BcUg4bfodQ==" + }, + { + "cmu": "1/HMBM2I1ns0ieeuWaaVyoO4WwEY59lvFvgFvoZ4ulQ=", + "epk": "E8qoBcealeP0dC52clB0LvDsC763m82ykdxHa7D3RvI=", + "ciphertext": "H8JFwQ8JNK9NBXS1if8jby5Skg5gmz945A568BxfKu66CxChPn0lFSUqi0DlRKORtPBfAw==" + }, + { + "cmu": "ghlccw8dUKCZU9F2Z57BnWdYZj5l2mmu/kcyU/e350k=", + "epk": "6PZsmWWLVpF86+CTqSGd50boyOpJjomPv+z1TqsBelg=", + "ciphertext": "vrlcCDXPuaUNf7JkO7VbDgkIu6Rt0pVMAi/0/hVnJmy/dBUGUL23WqxOWIl3yb8UcfiFWg==" + }, + { + "cmu": "Ex2v8enB3OmmyKX7mH1TzQhVCN1KRjQZ97EnEuClcT8=", + "epk": "xdYaXfcyRyJIB/KMPLjqvcgnylw/fciwz6RP6TZc/V4=", + "ciphertext": "7hDgWoBaDu4vU0AdIg10CP95z0ApqKmMXDyv3yDk8Fuma6CzCv4HFI2JXFfSC3efWGSxRg==" + }, + { + "cmu": "cQbvDbHxPQtQ7+wAoVPyBg+7t80GNw9x+hARdRITjzg=", + "epk": "3A7Bx6sA8VEC+3O8YMSwUpAKwWQ09jqDk/hoEcxHIOE=", + "ciphertext": "UkxqKGvOIOedf7NoSzJHHwXBTgLHBOQmNAcZa92Hf4M2Pmhme2nbXt05ZZQVEFZxPq67YA==" + }, + { + "cmu": "I4YBlVrzaqqt0UXE6Tql/K+JxxJBu1aXlW3soHeARhM=", + "epk": "hMTn/fYTgTHcN5S3nkaJrManPli/OjkcMzlDMr+0tyA=", + "ciphertext": "ox3pBejaom7WTEi7fCBPuZ0faz58xBaBdrCeEHrRmSxFfr1vGtheKmpVjbaoR/Re7oN60w==" + }, + { + "cmu": "USNLCesUVg/ka1tZUTaiWC3c10dKYLTJe2lSpeRl6Rs=", + "epk": "oGG7Plfo8PgLQuLFk4kxse1P7vbCcdLpTSJIAPWFwsM=", + "ciphertext": "6iDdSyuEeINpq+iRpUFnkcaOzdnnho3wn/2x92HsYYUONHSNRxe4oqoXy4k2vSENTz+DPg==" + }, + { + "cmu": "zguorBvEtc53ZST7x8diwqN63qt1ul5nn2DB8BxGqkc=", + "epk": "2CsREmNsuf6TR+znQ5hMLJuVOKQpZ2wJEDnlJzscSfM=", + "ciphertext": "CrTDb1QHvCv9JA3B+KREukKm7URoCAdzfNiigiCdv+e4spXtM6E+rZ66CAYma64LyQlQ7g==" + }, + { + "cmu": "W7ymD32G9yPb0mf0lNI4Sf2SBE5x0yPnY4CQucQpATQ=", + "epk": "S0ABe6qiDcEn0hRlOyzgzWX9sTxilhm5LXaZsRrPBm8=", + "ciphertext": "yG+/h2KDEnnZuecrYkrf0J29WtXmLbkqikJgbaIFu1JoCiynlH7Urxlv9L/45HoEgGzLWg==" + }, + { + "cmu": "zaggIB2k5I2y93J87/VuIcT3NMJ3QAIH8INTcngovDU=", + "epk": "hEbfxLxyI1n5IRvx76dhzscvy4c1pRHguHLD6oqP+xA=", + "ciphertext": "cdoPiwtRbvHxbwgjh3rC6lOHt7i04YcyYMmCqoT0ePw+11wlgMEMcP9/PUiJ3aBt1eubpw==" + }, + { + "cmu": "TbI6cT3i3A2FGMc4FNOPkqJU1y4UfcRsOyKTMFBUB2A=", + "epk": "lZOpsFAAan6Bv+X5rI3WCAslYuxyR9c63BvnzttlAKY=", + "ciphertext": "rdB8PxWq5PUCVlFuZxkgNA6Hs/mWKFb6q6Ibm9HbfS6gl79IsrqzhdIX2ndFK6VeFWS3iw==" + }, + { + "cmu": "WDAN+GWkkHiTrAeVKic5LWY2zvfaJgjIUBAqRWK50w4=", + "epk": "fP4DJht3w1qhXoi1AmqkKDWSt9h6F8O8fmoOiXUg/r8=", + "ciphertext": "JDs/Gozjay+sy4lrmkH8/qLe1z3TJ755g0q3JZGycvV/7I4q24ffYzACPnfQno9/eSZyxw==" + }, + { + "cmu": "YoVxSN26zW+v26NfW267Pkd4ZG1LoUvtPw0fiPsdK0w=", + "epk": "mYhwbtmAtuNrkCINc8Hogo9XO5bU8lEC9JPU8vJSGA8=", + "ciphertext": "2hJSV1TyBp5BR2evS+iLyDMGz58KtwCs+IOIg7Qff/3uFNDOGm9S4EQz/UIy+gc8iPHRHQ==" + }, + { + "cmu": "hlCbt8w9/ZaGKel74+neEp4qoMmWbKYo1mrTY8okMAY=", + "epk": "2bQn68UICfIlIL8y9Kob4K/n8MGlkNcLChUznMtA4bc=", + "ciphertext": "gslXliFZUGrNLEYUwhIOI8qD0AqgxrOFK2Ub4mImcRgb/B/5OH8hIeA77zi81B9rYaJdUw==" + }, + { + "cmu": "dijk/XHXj4ZqWD6GofCq2cayU+3arh4Dcqu07TaEtzo=", + "epk": "KTHgSwN3RXG3k5xs/1XX1X6xtvBX7OUpwkgXOy6JhQ8=", + "ciphertext": "+ANLe3I2XibEo0RhTMvq6tlrUtgXawV+g+XxmWhe1oBP5sge++gIJyLFOA4LKxZXK2QuRg==" + }, + { + "cmu": "iA6UOeQXmZ9zfTPnvvd3s8/FmsAcu3s49kn6pMOTUh0=", + "epk": "lcg6WrpBMzByKfN3A5Kh8IJIBX2OQwxJjZ8GouBFXOY=", + "ciphertext": "+gdIz3LClVkb4iI83ivaLm4AwpzkEkY5eYNIrYGnFJYzwagUcLkWrGokEyqjPuKX8HrHKA==" + }, + { + "cmu": "fWOrabc8DXP7lfwuWCZLrhLAct9UtIl53B0cyqW7ehc=", + "epk": "fXua1ne9kSC+nncvMNMoToExgxdUUcOhToCAYR24zUA=", + "ciphertext": "gKClaP+VaCIEvrsJCe861NWz2Ey3RV+tBfDP2x750mVrZpvM110HjFzM8hTXZqN4FhsRPQ==" + }, + { + "cmu": "Wx9pJMVqAlJAhoMuJIgpYU6PPXCNyV0t+9bhhpM7BU4=", + "epk": "3f63v4nragg8e0MR2BVEI/Z3qLUQFHGG4tPtRYNX848=", + "ciphertext": "+ztLcgbqaEdb5NwdsQvVVEU6inVZZ6+Tg1OCYQ4fH8Fy6iAjpEb1d4u5pTWln12QpaQRSQ==" + }, + { + "cmu": "fZ7H6SVkGEnsxZpSAu2DuuaHgC3+IluLS89zZEy5nyE=", + "epk": "tAdV2AlmKcs8/J/5eSqvwZ9kz/GyypJ4FoEU8MQhnUY=", + "ciphertext": "Z7Xmi0gDDIeWH29lB5ki9fpuTW3a1+KhlEW74ckLNeheuv3EI2QF/FiYyVlTQBbWhQZQgw==" + }, + { + "cmu": "cDEJnRpvUx8SsoqBChs3pJz+u9HIGPf/fK+nlqWF82Y=", + "epk": "UeF6a3dRWR3TInYmBLqT/l0EGeHmL21NvLmRbkGO9Ek=", + "ciphertext": "CqJf9LygHNr25Q4w9fv+vpDk3QQt74ujtNVqGc9QA/HqmDqM03AvbWkJfygC7FM5mP3poA==" + }, + { + "cmu": "B3J/nXrHslCi+eWGqw1hX1Trhi1AStvmGMqWJ/JMvGc=", + "epk": "RqQAyoCQ8xKvW/TCR5CSnwmlvzGAflVZrIBcXG6rMs8=", + "ciphertext": "bruP2Q1QXTW5NLoUIWfsgcI8wsrW87gZH80S/o89sUwzX6AuB6kRK0IWR6dT47j7FnCrvQ==" + }, + { + "cmu": "k+tJQyXf21nkMJMiDN6eHuDjY/y1yZoYgQxPvIqrwQI=", + "epk": "rcFgshXNRtBEdzQfRhwLgSuoG5DJ8ohsEjOzrqZbS9c=", + "ciphertext": "Oja3++nz0mZcfyEH5AG0go1y7qu8998FpcDqzjJQ0z4lp8Teh7YpQNzg9K7drzPrBc0jEQ==" + }, + { + "cmu": "3rszLns8/dhJdz+CMwfA2WLgayj50PpY0kw1l3BqNT4=", + "epk": "aUFDrRIRCeOA6RNTmjK1NdFRA04h4tXcVt61Ww/uoV0=", + "ciphertext": "VUEXBHtA9niHHPG+Gs3oMOjLmtWgEtLmeG4J72xV2B0YNKVsLJs0I/VTWNGbZPAQnxpocA==" + }, + { + "cmu": "jQ0A/jbqd3rPaVgpbmuzhTx54xJFWxR8DmiCgeUzExE=", + "epk": "PRZuOExSX5XpdoOvjV9YZ2u2TWBZR2ByQZ10nRH8CY0=", + "ciphertext": "CPEwudkiB5TEzb8OJqhwnVEDYUjjdadYfpx5POXUJStKM0LvgFjpNaoSIZiz+R8iq38SwQ==" + }, + { + "cmu": "yQTnJiBvXkouq/kq4teuBmVy4C/o8k708/67zuHshAY=", + "epk": "QS1pW/1S+WJDGeOALuB6CrDzvpOvLZnQLcQxDFsPuVY=", + "ciphertext": "FxkWfYDUh3b7Q/IUFJixnU8a/qcGGGj8aWPYK5TMNN9k5coRmCi1HWaSh7m4kxUG4sdr4A==" + }, + { + "cmu": "BXSAkEKv8E1FvTi/34OpAmsIfQWnMCfxx0XbPXBKKE8=", + "epk": "zrVHYsbP1D7upFRtF/bQHLfYba5XUP9pI/GTfZrnXKI=", + "ciphertext": "Q7ePLPGfzHI5aNiE7UeR6YhGtmuGUg4pW8TULZQxZQ3lR7vsypUlOSd4V28afSmE3fm/Vg==" + }, + { + "cmu": "EhurdZXnrb/5l3d/KtCpNevJWP0/e3kOaizPImGaUC4=", + "epk": "tTbThxSt3E7uFGJVQA25Styf5nrFrLIb3G9Gap/GtMs=", + "ciphertext": "D0Vt9+hayt+4Tzc4JNV/1NqW/KQUvqwePO5XmB8RhcZTVor5is2PbnM2aXsmUgpTrRrgHg==" + }, + { + "cmu": "QGA4YW3d6TKgQyFd4f+6m6a2Nej3XGsgwAeBNbqvDDk=", + "epk": "LKQq2gOdcGYBPtEUdo5hsOwtfL4gdM0eOMnGOcBw7KE=", + "ciphertext": "wvTIWDgcUXzHhNA3YSZiwXxkc6wo0IEWaMC+S160qNFIw/otRXPtFpHx/RJtGiR6ttRDkQ==" + }, + { + "cmu": "THM00NHIuzPXIwKbLqzWdZpybm/lOWlkLOonZ1Bw4Cw=", + "epk": "tx/75hEUzGIrLc/rjGjDPL/BLpZ9j7CEY51LuCQP0F4=", + "ciphertext": "uCq6KMlMrJnZb+9WB9i1KikS1J3EhWFhj9g/qhMcUJR055idTT0ZhlMl3ZJUpnhaXnL1RQ==" + }, + { + "cmu": "IPJwqEslBDhD9X47dWxJ9nTtkd68d5jKp3L/IJJrZxM=", + "epk": "DB74yqHAEyBmBwmeKK0HXOvpzJK657ytFKxdte247hE=", + "ciphertext": "K9RO8WdHSjQ5yNkYfm5NBoq1XK5ln+9nz3QXaPmSKDHR54PYvXwoyAo72Ulwqo/BzXmLAQ==" + }, + { + "cmu": "+hQICPJrAwhzPTRyBwCFzQ36qX7+uN6QB/n7Vxjtq1I=", + "epk": "wbKfRfyyZCWnV77uK3woNWQ+LQqtxKwBCwW+4KPBalU=", + "ciphertext": "1BKcrD3Dut/L3wmipcXW70tJFmkb6ZSfdzXAtbW1gfmJrprWEBTUMYNR3TQdeNKx/CN20g==" + }, + { + "cmu": "qPcg26RRn8m943qIsdoqMJjS4D904uYKFf1rhKhpfBk=", + "epk": "2dWFMWBt5wqXd81pZOg7hc7QLoOhJkNFy7vWmCBj5dE=", + "ciphertext": "ulbvj5g/YdLk33BwtAE1bicumac9qLZXC6We6CTSoAKHngeP23onEoQnbFaRihQsNo/jAQ==" + }, + { + "cmu": "TE0OpCLJtlFKgivHHILUWbwaKDfXxGyQpsEf7RD5EQ0=", + "epk": "PcfBj9i/TLZ/XWTtWsYAO6ySZreev6x5B0N+w3LoQYU=", + "ciphertext": "W/iHhMjOzbh7u/7iD8J+8rQZgtER3uzlBWa98JvUDSpKS6h0s5mSIPpxsGEYENYojehxww==" + }, + { + "cmu": "8w9sHGiVssYBQ2QbhvglConTTTB4z0BN9CH7GDXNgWs=", + "epk": "sDu8oFBYSQzYzOOuvikfu6BOUMIYgE7xTfgth36kj/A=", + "ciphertext": "6bsu/IACvZ/X1yNscuOSlETjMAWMgYlL2b7Zlrks6uTgngCL773D4utYmSeFsFM08W4kag==" + }, + { + "cmu": "jjej4BAzV2AQX6WonOMS7Tnt8nbh/PiR9bdn7kxHjUc=", + "epk": "P5540bA0bOPRs15JrZLTajmrjLvOePWJYZCj2IN606w=", + "ciphertext": "Y3o85cBmcVI0yk6k4kRYtaJD2lDDMcCR6k73Yv+FZJ4fmMdE/m0fqjD4vMoVZ1ZZGWKfcw==" + }, + { + "cmu": "HwhBN661+6ZNbEZyrChF+F6ET0m3VDf0CnGTnMrPxwo=", + "epk": "AOsFCMC9facW6dvFsCsTdstXXIEgg6Mz0JwaZFLXx5c=", + "ciphertext": "kRjOXjtqH1ZXvLzRn13I1hP1pi/aY1P2KjTxgmkK+fOD1D16xRO/Lp84FKQwnnWh1CDJkQ==" + }, + { + "cmu": "i5F2lLSKJdmSckCTT59fsdv4u+ho2mrsa04d8IAF3w8=", + "epk": "WJ4huZhimWR0XWZ3Z90/vrdyHVrYhRSfoJ5vjEvr+Io=", + "ciphertext": "yhgDpQLs49MV98g2hmeP4hDJJQh6EkpDJuucQxnEwbgmnOlvxhOva/t8NcnJ2dIGRmaAgg==" + }, + { + "cmu": "MYBL9Dso8c3tb8ngtg43LaxGpgNY7u3ccErPzn735Tk=", + "epk": "vx2sYpLDncix+ETS5SgHrjJkbxoYTHXdd0z/CUWQips=", + "ciphertext": "sbmgol+qHsboD/LJBjmXsrr5Y4wY5zYHkVf+F8VhKXlGS5j0LtMhkHaRPZHc5Qu3kADE7Q==" + }, + { + "cmu": "czY5Rcx+IUdg7eQjdP5HPI0RLeXRwA0HhNBzThr+E1M=", + "epk": "74xYTR3Oj0welAyiio2bU7Q0cbesIXFqkWUveu9dZAA=", + "ciphertext": "8xrKiApQEBza5n/jDg9ngOZuP1vKLYKDROdkecsr6PiTnPjebYuGCpY4Jpgzb65CcQ6daQ==" + }, + { + "cmu": "g/GIy79dB5fNorKocvUoUGUtnYwtWnIFYdVo19OvRAQ=", + "epk": "Ytgzbyj2FdPiNhOFaI7HfCvFQeSdga5g6S08u2TrTSo=", + "ciphertext": "KoWfRUnye9+zluV8qv4eufNf/75cRMmbhAJ6t+5RutexBeu8pXZJRGCEaLP5RJRSQV/u7A==" + }, + { + "cmu": "4NYLXr1+pTrdl5FR+EPq06llsuPdOFFXYtAPVC5bmFU=", + "epk": "VJmTJENHC4iLT0/keTRNCJ00mp++4aZHeS76PwpuFB4=", + "ciphertext": "EexZllaLmDVr+3eDcsI4P4s/n+AQS/usW4fpjw8//cZ80K2DSZcmMbp702VFTkpFRkZAOw==" + }, + { + "cmu": "BXRdb6xRj62qhEV8BRqya73CoYtYrYGGg8H7t5fPYh0=", + "epk": "7hKEyA6nJ9jAhAhQLATXMy0BkuBcLDkEmC682ZdzbCk=", + "ciphertext": "yCIzIjKH9bVN/bAPc+O7i1eL6mVSD2E4hwmQx657hCCtWpXkra4pfN6t8tzErFf9tXcgZg==" + }, + { + "cmu": "2rvPrIql7f5mkEETWKnyioqcZ8m1E9TpShVjI3V5+FY=", + "epk": "55iY25hD+f8FWG8lCXuPVJU5Q9tYq5WSM00kMnr+5Io=", + "ciphertext": "XKqPuuJc/Iyp58C6ORUEpxsKheNwu7Ne7L+vbkrL9xfkQsHMplB8DL+4HXb2Hv85osS/fQ==" + }, + { + "cmu": "biAWJ21id/4yXt90HdM3FnhxFEG4AjSiEiHNn7yC40E=", + "epk": "6fY1mzfeS8h5Jj0ZK6wZEzCKX2Vuqyv9dvpT5ZEVzFU=", + "ciphertext": "qI5oFMPRkGf+wdGXCrNh2N9SOeoNJhJkKvJ4Jc95ZHzX2bC6qXUH/Nz9bCv+nuuQ9SgSUA==" + }, + { + "cmu": "OhwKBFaGJ7jM/SWZppPR3X2hIEHhw8gnZ21uXqdd420=", + "epk": "MUA5WzBaWEcCF4w8o2X+A4BUDht5BF0zqRwg2194yxU=", + "ciphertext": "6J5YQbNFba193IFe2JgIRjP/QD3PnXGp8EOOJBnOglyzPl2hjOqXZ0wYoxTc7VegOCIwxg==" + }, + { + "cmu": "gkaH1AMxef9suTBaPgie8lNOtYGBGxOZf6L4jDvYcSM=", + "epk": "MfvkCAVaGHHLW/y987ejnCMyHWtRqVYGHnWDND1hvNk=", + "ciphertext": "fmdHimzJIo598a+AxN8eXRUCzWemTuEVFcFHHruP6DbUFUKwr5mT8x5mE4KMZU60aNgARQ==" + }, + { + "cmu": "TPQFkHahWUP3vZnMOTSgscArQx4bn6+m4B5cdwCd01w=", + "epk": "egUcZT1spnP9CmGv/bZf9m14eyq0gFITSlRDlSDJ280=", + "ciphertext": "39QM2Hcp1IfHa0Ievv/feZHzpS/RH9N8JUNAJjMysqaJAIiIyLFjmXa0CXb9byNvSxe/Hg==" + }, + { + "cmu": "Pi/rEUFoiG4UJdSFK1YkGNCQNI5silDGcufCvMB1XV8=", + "epk": "l9sfzF8iAHAufW58YIf5NFvbhAddfF/TiIL7mPcuKg4=", + "ciphertext": "45XlD4IxkIDNK0bLAkxsnfUYyzwpW3U8rji6KjCMYnAaEsVdxHx9KDrTkKAO9TfAxMArlA==" + }, + { + "cmu": "d2ybNn8S9/pTs42iLaw/96DzHnzEn4v1USql1qKu0gY=", + "epk": "V8KYyQAvkBY3BFUUcUrb3kPH8dV2r/7eQCdHskhJg00=", + "ciphertext": "GuEKlETgzE1l+h+TUg9Rmjbm1374BMhDmwkyEskke7KY13tfslEvHFWJIhgM+L9fWfrwKw==" + }, + { + "cmu": "773+lbHGqVrLIR1VXu2h1GynSbnFQpggm60RbIhUdSI=", + "epk": "7yxzIsDTp8Dm+1sN3QwqHR//RoHXIiyDK8IcnqTO2mI=", + "ciphertext": "2jdw7vNYRPIKjA5YCbMzHsdBXr2Ns2O7v/XN7W4UE1isiXgwWYQ6XJoG1R3uV16y5wwF3A==" + }, + { + "cmu": "BgwyeqaHkGemaveRIVlqSA7nluCR234Gk0vzCGcG9AI=", + "epk": "Iaril671Tv/bwRRyeK0k734YZvamKo1QgT6/J4pqJhw=", + "ciphertext": "bqdgGJswHP11pY4Y1+mGNO5D4Od2VVYCKO0Ota8kYDGHYe2ci8o8BaDNZKhICrePMzlSIg==" + }, + { + "cmu": "/iFun4mMCvVYjM4kADUDHO8A+dBY/j42SyLb3uZvdlM=", + "epk": "2yZgpBZvYGZ32bxh4hMIloiLIq13n1VJ/VHza3US2wo=", + "ciphertext": "H4Rjzo9ffrR2VXGDl/xKaOXFYuFKiVVX2/kw/SNq7vRwiAe7oz5AUTszfBIQZJJKcluGuw==" + }, + { + "cmu": "xPyzkhFqIOvkNLLpmlJrFS7oj/Np1fFwZJ/ikzvfqlE=", + "epk": "QXYC6+b2xshrstPyPpx8q1bHCFISR6A4YvEdbtMTl28=", + "ciphertext": "KhL56jnxXSswTGTCqu+c6cK1/Mc8fHeq9QPxlzuqt7JAb2r8gjdt/tpGWA7x1r7KrHTubw==" + }, + { + "cmu": "tiD68OeCBmzrK/Yp2qnp12Km3XHOqUXBjVEpvHjSOjk=", + "epk": "mf7GpFMPuyPhJyj88YHP0XlojVp3NFWr1S5BQ0wLQ5s=", + "ciphertext": "sGo3+ayeaZrFwXQyzY0xiqXGnvzpwFbRIyX7BeOVuN+gTOHBx+A0f9l8FWkD1fXuBe6rSg==" + }, + { + "cmu": "Y1VChip7C0a/snRfndnLqlod617mgMdSaA5DjGmXqG0=", + "epk": "hFLM/o62xwj4lm8yYf9TAVvtMUjZTLhgLpkE/VgMoug=", + "ciphertext": "UztAiVDmeQPeEPk4ZFACZeCeVqfa185QR2WCc0rS05Y+YXqRj74hfYz6USl7wH07lIcQvA==" + }, + { + "cmu": "fEnQJZE7O3AaIfGDIejD+/0Y2lwHJYFzBnrNKNaARww=", + "epk": "JFV9zBFswpDvXkLAnJ6XFYCaBOTETadl+5iboRD5Zuw=", + "ciphertext": "HULF5SFwBJJZVaYR2b6sBqRryh8edtmZr4Pnrl56Z77KwYqaFUIV6yUsArMqR28HFwYbcQ==" + }, + { + "cmu": "vunzk1STFCrbvVOdRaz6hPZpQX9mnTStpCLv5K4txQY=", + "epk": "cmbQ2I4qVuNOOT4o/AHMS6P8R50VU5zaOwBNwqCRUTg=", + "ciphertext": "q61/rvontGPhN88kJeb2DgecUoaVyL32/pBgvvX615eUAqKl+6AP2nrXQuAq30kvtBoaIQ==" + }, + { + "cmu": "vKhH7wOcNSSakqUtbAIiPnGLmQbCusSgPDmPPQTOdy4=", + "epk": "4VOpw5G5BLzBqfZlB9MD5TqwsiW7x46P1fYydLnVzA8=", + "ciphertext": "aXgZjHWvbiR9UjZ7B37uVy7vcV4IQW3u4L4PY3o9vtEYGgTJn0WMp0ag53LGwR39ftPYhg==" + }, + { + "cmu": "gj1X8uFdh21YyLwoqg5pX8Acwtx4BeuP+QWLBuKQb08=", + "epk": "jqlEY3IAt+G4l2TY3xzgk7oKCj0owO/EsvgW69IhAFs=", + "ciphertext": "sB6ehch1IbGlGUSu9RF6aCcDjH4/xiAyfIHIH+zJdEvc0+nKQ/s5dtD7EagNXJh8xRLaHg==" + }, + { + "cmu": "5lxolGXAfJKs2Jm7sZwiYTqcV0mUNkrj5L33EX/nrx8=", + "epk": "hUi/qCUreHpzyry4CuGc0PMaU83WhHgHejWyYMDhZmo=", + "ciphertext": "FS0PsenhgdY6we+aq6iwGJov0/bRxuOez2dAXgisQg1K+85QQNoj+7WxKP+j1zEamIgNrA==" + }, + { + "cmu": "AIpyoTTn9rg4zhGeahMJgMKhkbmyDIYpViZEuORM21U=", + "epk": "J1MVmfxkOjVmhHN8nRONeHZYfp8a4mSIOlI3HFOsoOQ=", + "ciphertext": "OWYNZSBfHUvvILdiqHZp+jm+s/GB/LFgmGcCj2ljCDoKWZxSQSAkYFn6FQtmB19wGxMXfw==" + }, + { + "cmu": "OQf03Y7+9jIZatjkN9tlDXmV62XYuYK92KgimC2TrUI=", + "epk": "rhtOK4GDBzoGP/VDjuBPI3J/o4AbIGDDdw0PTBHRoCE=", + "ciphertext": "jPQxES835vd8E1KkVequ6MjIprNmLOivYb5AhK6k9XowkhUL8lKoPFnORZCj+ls6H27vZw==" + }, + { + "cmu": "VQs4LL76LkVwumXAgBQ3UgpiXVjDNO5HR7RpOYxe+wc=", + "epk": "cTGp0/yO7X0xlLNUs81urtrSlq/gcZf4MIXTQPxDQJw=", + "ciphertext": "L96KWjAtjL61/v5Kp/xFiBKOITskoOoPdLY5nB5EQEk27JHahhlI3hSftmy/7fmLh69Vgg==" + }, + { + "cmu": "pFndufI5sgf64K9DvgsRJamv+4faEWJAl6sGdkFp6Ck=", + "epk": "DeVyWfqSPGvt9Xq60Lu8NGUc08M1fpnOUgBzrxgSNoE=", + "ciphertext": "nJD7kAmThOtxaSuTjzMgQbl2SCpyKkcuQ3KPFtnyf61k30GzxxuJDUbmWYkwGVV3zUMcuw==" + }, + { + "cmu": "jjTEr3WBMr3NgVppUs8KV+BrpgWaaWnJKd8ECKwD+z0=", + "epk": "OfTK35TG4L4k8p9NKCafyPqTdjI/1X9DxR8JctOmRQA=", + "ciphertext": "llmqstxL4g9HxiNS60p+5Ue6n85ZFrpA2TBGNAq+yE2sSEjOm3XR0vfVrnUhy1XlJmAuNA==" + } + ] + }, + { + "index": "20", + "hash": "k8Sjwdv/sqhmiewMBOeEDv45+2ZoUseKKX/mRWMyN34=", + "spends": [ + { + "nf": "k2+fFugDeSOEurO8j6L9kqUNLCQz4t/4qVS2Dz29VNs=" + } + ], + "outputs": [ + { + "cmu": "VZhlJAob3RlF9gLKSNnR/3QILcv2d5BWTk7m/3wLsFA=", + "epk": "hY8h9fqMzhNP+rzXrPFA9GdxQD15cdf448U3tH4+FO8=", + "ciphertext": "gRv0aX1hi1lsHMKh20vw/W4esMxt8kf2dijzHOqeVs93PQAYH9D0JJ89oWSrf3Fo2J5HTA==" + }, + { + "cmu": "cTh+P/rXSmQ5apZruJvJQpNDqwbC5Kh10kW7VmGl7F0=", + "epk": "Q86ZlvO0zFMtqwNo4pG4YDk2Cl8KpMI84kRU29gRy9U=", + "ciphertext": "af726ij0v8RlVdVU5MVbda7m+9X9zFsVnyvVnWjHPvJgnnxMXJKofYiHOsyw1zkJJj2y9Q==" + }, + { + "cmu": "gQqO3JqCTvNhXSQCDP9b+a9+8S71w29P2lsk+Y4O4hI=", + "epk": "Ssmn6nTQDxQH4mJF5eYMHONejUVbr9DzptzNMVqscdI=", + "ciphertext": "dMUUw5IU5bxiOeGkmEbIhQEkOkU9NMK+mptlx6LzfKoaSUbGtKG/mpipEQrHSgDRznNF0A==" + }, + { + "cmu": "x+AtM3donSI6pms1zaz3lqozYszL2wKCXE8E7yK90DY=", + "epk": "F0k0qQW8QJtqBImROKMLbJN9c/dvRQFkEhqZ88o6DMc=", + "ciphertext": "9krpP5nRr4Nc+scEvBeMhVg57J44LdZgrTf4JngrdZtlxqDjzu3ZEjHYfHjcro2zKRYi4A==" + }, + { + "cmu": "MBAIbwv7xktU2qWBKUxs8DfLnu9UrU6XL+A6sazv8B8=", + "epk": "wAurbFUMBcftk7SD/wgNLJH/12m+u7jmNqb62q7TNbU=", + "ciphertext": "c1d+5MC3lFD3IGA4Lf6ghGfPFI7KU9D2SqzUkMmLmggB0D0TXrNI0G4R3C927Lmb1k/A8g==" + }, + { + "cmu": "qhTqnymmk59WiPz/TlMmI6+Y7JxREOV99ubRHdQvhhw=", + "epk": "BzWlUZHekbyW9gMED2urx79UO8pLYAy8YUnBPjzmyqI=", + "ciphertext": "GERM9cFKRcq1FrB5Vi843gm8HjQRwdNeQpejl9NI0CbcaILel3AUtAeFTpGUGR3bPlwD7A==" + }, + { + "cmu": "5dHLYZV17xUzom9mZuPZnMsgR6NLgNkckdka5nyPKUg=", + "epk": "LecTTm48mRuZ6NzJdskV2gq2VgJ4zMIzZ5iKBbIQaCc=", + "ciphertext": "8Zmb6GywjbmPKubPYYO5MOFXp3lEQQXszE/Q1d3JxuS2ux4zl/Gd2FedNwAiV6oacefBGg==" + }, + { + "cmu": "wroBRFBlI9aze5fybEACY9lvjRF/jkZNAqcus0ZZ5wE=", + "epk": "Fe7Z6AUqfg+6dyaT9PgYjaZFMD9fmZH+E5NMo86PBsc=", + "ciphertext": "NUH4AfKYPcw6I5xpxQPqKzk37F6jPlBosFWskjtN3++2t76O6kufY+kiNoGi3cm6T0OIYQ==" + }, + { + "cmu": "Oy+morSWkvBJqDL2kPL5PchL6E+mDuuGkIVD7jiFxFE=", + "epk": "LZwoRjmTSNAZtUIOQ3e0o+PstkxvAkcEdl8//a4RmwQ=", + "ciphertext": "jGXpBI0yYV5BrKAepnIuVoO0u+J3IJwDsRDmJr/yJ/4CfmGW0y6vkoV7PkMStfeZU8tyRw==" + }, + { + "cmu": "uViq7vw7av63k5OggLPhzwDlirIzaznZl0hc3gPGqiY=", + "epk": "iwPx/ygxYNbhTA+uXUqoJBc6dUwks5Hwgo/9P2kXn90=", + "ciphertext": "dlizWCoJBr/S2MRI28DX6AdeRyU+8E/+95TyCrjdQizsuvN7MrvEWGZNBbcP9/R2MSHG5w==" + }, + { + "cmu": "1hNMjjLFVIsXNujvvFbSlNVsnetqdibe6c5WOA/DySo=", + "epk": "+hsPV/7iYjOxpCB+aG0C5W7j3W9THGFLENlt2xEETxs=", + "ciphertext": "l0JQeZKT/HHp/To+rGlnVGQIbX+kltzfEm+wcZf5uZPJ8vVIA2LY53JZdiqlU6ydIkb5oA==" + }, + { + "cmu": "k6g2vvbF34cIKAZ+qxOmdKJh4KeHm/5xWh/AsKZQuwI=", + "epk": "oRM5rWy4yzuoalzZTxsCyl1BTkgWZcT8bjvtlmBtfkk=", + "ciphertext": "kcllpuN42GdGmQ7Q68EgfpNTsqGp4ooc6WLEwj+Atj1ZPNiVghCYsQxNtzdimTaTRnPthw==" + }, + { + "cmu": "WIS+PyR0KwoWjxVYZNVp3sWTLa4Z43nMRatEJjC/bRU=", + "epk": "+XJumMXYfzNREjaSHfbMV7tF+rcwQrLx+BXl4LfMJMQ=", + "ciphertext": "1idzD5rMuMonN/zEZFP0MTdpajhjTzuYyFV83hMlA1O0E4RStRBN0bhlTBqgAMR0OpfLDQ==" + }, + { + "cmu": "kCN5285koBN+1L97MwIklok18QmwESQ9RvwCBit24j8=", + "epk": "Y15F/Sir0HkGw7BLvRR2rMbKwODhBI41+foMhs1JR0M=", + "ciphertext": "2GZLe/iI3H/A11TIMAWTge9enWoxxqL+Qt9q/KFqfTEOH/RH3Uti+VKWnMVUWo3gFP4BRw==" + }, + { + "cmu": "6o/1cKOqJ18e7iFJ+poUun3dpuitYdLXacMgIBG0AxE=", + "epk": "O/Ih7/EqaJqOOFvEu/O7yczDeb/FSKIuJBGHSB4/+2Q=", + "ciphertext": "OvasovY53F2ud93i1Wp9++lz2wjOGKbXEKkKYJf+35AIUHh0M4NQisQSlW/F2EVUm0HzAw==" + }, + { + "cmu": "WLyJEflnMgCu/WKB37JHsOcarUWqmI+ECuJ2MzvOK2g=", + "epk": "jzlQyC8RamNfTs8o8KJc54p11fxRaGR+63J85863ods=", + "ciphertext": "hmw9KnzmVeF21Pyb6AvCcWJiZSdliKN5bLxSrU3v+DSUdBLRnSnKv6c0c2e/ktDB0nhzzg==" + }, + { + "cmu": "sK5bKaLv0DICZRBVHbqREYnwcih3V7XH1EXMShKvh0A=", + "epk": "5zsPC2vNoELtpDSYlsL6bU0rW1yvSeWMMqgSUtNtM2g=", + "ciphertext": "HibeChKgjLwcHv4v1pOi3FlA75lAQfCrfjUc4rT0pPpxzoT8MzhSH9RTYks1uJBKukcuhA==" + }, + { + "cmu": "2oKRPj8CCv0SCFas15gwT48qFAFe24H9WAvIDKpkOVc=", + "epk": "aKXTya2Er+/EU2tzkSZhL9iDJnhEnvND8WMCQtea74U=", + "ciphertext": "m6yqcyqebJoFrF5gyrrbKVqgLdAFlRo47dLIF1noR6ErJ8Erqa7lU/EdQI9sfvI6jP8c4A==" + }, + { + "cmu": "jOMNz1hVZnwJwAYjoNgQ5a6xSC/ZTsE0PzIOl2uJ9io=", + "epk": "ywL+ohc8QISGcumXm4PvzLtSgGMuyT3vQHSQ5H5DkPE=", + "ciphertext": "4MQZJ4+E9UFhBgkqlnZ2kx7YPN2JYrufBMV6GJqZJE36FqD5eFxg+UIGZKVg4zKMzRddwA==" + }, + { + "cmu": "Cy0NxBKY6y39x2Jrt6tcTjk3SUiR8yZQygtJkzodVCU=", + "epk": "vnnjFq+GoLSqj1uxMQlJumHpWAbvXLvmO8gso38XrCI=", + "ciphertext": "Kh0Eu0sfbWeMihijWvsG/FiSBE76zYEzZEAXht+67W70RX1k815vFTrgdrDIc6QbxLkmAg==" + }, + { + "cmu": "f8BFm9G+uYOAsyNHuZatd5q8Tj5QpRJGCluveMkIXEk=", + "epk": "Zl13sSVYyXvJX538Y/yjDzh3K4FxrjVyDO+Pom1agog=", + "ciphertext": "ywg5U95eTXb5LoEc7AUQTKisrK4xVbByDzbrBCe7kU+ludUpiGiEB3fhv/BtqPj2CEB1fQ==" + }, + { + "cmu": "UZMotM2/LK4iyZFnUt6CQTPdr+OyuqtjvckFJe+qTks=", + "epk": "KkWZDInl1/n/+EwT5T4rJltjovqUbGsOjRyDZsT8j7I=", + "ciphertext": "c9J9hUqVODd12V+b/iYIoWj1hUQ+krA2suVew+ZeKg50cbYF4xBtVraZ7FTUgSg5124ZSg==" + }, + { + "cmu": "lhvkCgb3A8aZCPVDfsIL/zf0IpERqswIAfwNThWohWU=", + "epk": "7Z9K8VE8tQd7qPtjC/Yc0KpABbtdLJ1ySA6vkKV+6qU=", + "ciphertext": "Jg2WXr7lbXP6tDMYHtMQYzMiyZuZnhzaAjQbBmjOLHleAcZzOqCVVZIb/ASjGE1Kz6HW/Q==" + }, + { + "cmu": "q8V/fgGFr2ha0RTQd64gQxAfIPDQw+F3cAkvdBzqBWc=", + "epk": "jkHMlaQ2DNAoeL7Pr2WrYgkyVseJUsyQpHRxy100+cY=", + "ciphertext": "/mCsRVvMgPaRwLD3Mlmp2mZSLaOL8wzH7yK2kfybQH4rDzk4OhqxIZ9NEo+HERvJ90wE4A==" + }, + { + "cmu": "nung9+7+NkRTKwm0q/ylJPD8i59gvoss0COj4VcMmlU=", + "epk": "zQChjzXL39/woE6bOr68CI1Gg+qSQahljDiRqrtnwd8=", + "ciphertext": "x3a6yBwJFWPV6CbhnoGImXAWznj5CRP41xmYEb7piUvWMDXA6GvxIYqNy0hDyoEUutRyqw==" + }, + { + "cmu": "XqdWVtXcAWCm6NG9vl4GFJt6PDBqLSfrkHnDs/aTIF0=", + "epk": "i7i2EC6Z5qRmtpS10jqI0uqFckoCjx9mIz3HQe/nC4o=", + "ciphertext": "ikMMUqSHe0bjCQmvXG6bzlyzADX3NvRO9tNGCygK4wCErO76RQGwgfxCyPOwmliPQaXG6g==" + }, + { + "cmu": "0Y0dD06IIhAnCgXVab4IYPJL2MgoUtWWvzNXVvBY6E0=", + "epk": "rIUO0TLXCoEwD5z64rfvsaLwLsiZFfcKlgphGS5Mg3A=", + "ciphertext": "vCsCY//3arNN0EKPx8JKWIJOrIbbq1rbYl8pdD8cHHBoXBIVXpI9iLXovEm5RVIhsiljrw==" + }, + { + "cmu": "q/sA9TiqgQeyr4Dg9CtP4kGFoFIVJ8DzcZ7GwvLgyy4=", + "epk": "qJKJxNvWqt08SqqHM927zP+MP25QUy+tHvsGmyXqrZU=", + "ciphertext": "1NjmwsDJAaFNpcelxc5TV06h77aiy2ptbYqMNXHO760ySbHMoBFg63pHXiUkSO8wphwOBg==" + }, + { + "cmu": "j/9lZb1F1lho+zdUYi33/vcG9d9DN5b1V+1ihnom7Q8=", + "epk": "IhHEP64pWNUiSO5rPOYnPbTz4VezC/JPOL9l+otoJqc=", + "ciphertext": "BAI8DX/1XttDZVxTJ4AxWPHyXaI7KUVH7GUf7ZfxjalJkTbk4NH1hSRsLOsYUUKLbicwRg==" + }, + { + "cmu": "4+XzdQ4DTZ0Bhgrys3CL6Ky8sO5Vs6opOt/6rOEgDmo=", + "epk": "bkwF/ryZ6I5MedLqHivBTPrcSwiOUD9uFgwW1Q762Jw=", + "ciphertext": "+m9sE+3NU52pTyFJnViifjOzuJ+k4ileCDn7W0ZLPpqhpBYZXOqJUaxe9nZ1FZ0EgSr5ag==" + }, + { + "cmu": "aa2HpTMjX/KlM6jDRAt3gm3MSbG6kulV4zxGOtj8nlk=", + "epk": "ZoLq0nsOiKugwuM845m2azaZBvAQjopZlUx3kdPlMEc=", + "ciphertext": "7lATKzN92dXeDw3dVEao+QBv1GSZMU7xX+oeU3wHBqZgoOV+miwv897mFdZB/dqEaqAXYA==" + }, + { + "cmu": "/TpKOdmMZWdknNUKito2TDuvLn2cJOuLL32le7uQz1I=", + "epk": "h8TxQ3sswiNqcxKjLL03lsb6xC+RJSkMJVtO7KL6XLU=", + "ciphertext": "umMQYlN2mWOqs+0ebz1ABVNijoyLOMz3CQDAdl9z3JmIH9Bat3RTl5Rzd4MyQlwlxjQ6CQ==" + }, + { + "cmu": "Np9yXb7o+KVyxAuwzMJ96D5IXwq84glPc7i8ycXNPlo=", + "epk": "u3L7y52oX0wnnkkAfogc/vx10JHynFM+JmI1ZRgTxxI=", + "ciphertext": "g9V5YfbWkRnJaGvRStpLhVDHWqWSyu20zu4JTz2D3j2TsvYPLh1y8q+EiVBsLQoXREd+MA==" + }, + { + "cmu": "FXivJya8FJKJCTUlFznlQ/NS/duB82T7KZGgF8bUqWY=", + "epk": "zDK4t1EsEd/+qjjI/qjIPlwx3s8InveTzW8qAHZWQjw=", + "ciphertext": "UxKcBNwTyhI52OAM7x4xCtieKrP1YFU4wVOhnf2rfwukFx1HvdIgsYvbM39XRaytbSFZPA==" + }, + { + "cmu": "sWkqv2g0yJKw6HMR0FGRzWpmADVLYSRHKNijSqmsmkg=", + "epk": "60402+zy9YaGwoCatQkCq2SwegOHQ+ToNNFHkRBM5rc=", + "ciphertext": "xy3aTnt0zPZ39rKNASI3aayLGD+DHiUc/U8kdnP9a3tgEsVJC3kIUuXrHJHAX/HZj+Ho1w==" + }, + { + "cmu": "WQtHp90CddSZUyvQat9eGiX4qrpSr4RhyISET94PhVs=", + "epk": "zWmSXtmi6aA9MUZIVdeF4g696qZhikudg9urm93zzqU=", + "ciphertext": "IZ5/d5AseWzEii+Qo5vTjil55ykE6tPezCS8xlVRliW2NNKqEGJLWPY0alZaWvj3ernkLQ==" + }, + { + "cmu": "DS48sTPaQW2i1Y820owC3kDZBP8ZChCGt65otZFf+ig=", + "epk": "pSLcyJ2v8oRpAwYe1l9bAaL2e29szdJXf2/HxHtDyYY=", + "ciphertext": "LZmAjRZp6X1NzgzReTjtoVW9WnL0qt50d8yvFTx6VI9au9YWNHDcWRuiuE+G5YG0q0dDHA==" + }, + { + "cmu": "54jldF0ol9s+e1eupg23iJHF8qgbQeJdMAJndc9jO1U=", + "epk": "Go/KpljJAMyxlCZisATPUafLs8JkDrbry3VrOQUfis8=", + "ciphertext": "RCmS34F2cHwBR1HQL3YibXuoET2CT9yriFfOz+REkd5L0M0rByUCOjfmW+Dm2cCsJPe5ng==" + }, + { + "cmu": "3S9Omg+PpSHmf65SDvvnbNQOABx75qG3brEubNPPEyA=", + "epk": "HPyBp/0sYaQzzwaBfNMdZ77AP0mDFpZXSxb7T/5kIw4=", + "ciphertext": "IkyiO4J22LUcKlgzK/PzAbo+6ntweRUmbKoavrPID9Bm9FdfxyC4wtgOiadx33tFwYLiaw==" + }, + { + "cmu": "LGvLIj5SJHWlXLY7mWU4hd8SDaItSixfbhA7w1K58C8=", + "epk": "I0K0fQxvfkHTvSANn6PVR5ltK1C1IXy9NbQtVxAwjJs=", + "ciphertext": "9mPpCyO/bizp3Pop9xt51u6OnJ68lFhi2n3k8NXjF0OzVcoP8ezDlYDyVXfyW9V4xSYDwA==" + }, + { + "cmu": "oRNsZNuxU3RFDssTeDBIVPOcinpChdCAaS+2jnrQD2k=", + "epk": "0tUpSUw0EdtuvFJhV5o5Ue1RDJPaYzQLyiKk5Ok7BeM=", + "ciphertext": "9SJlOaGqexXKkdhfbHBL6fo/NPbSeyiV8/QhvYTybRux+ieb5vV1r9U/LLolSfDLHmK/9w==" + }, + { + "cmu": "YfwNDR0E5MHF/5OPqD1YWTVgg3eQ91jsVK0ZVORMVjA=", + "epk": "+aTJOkoLoSwsWbwIQ9pbhd8/LaHqIIAjRTndIMtSuVw=", + "ciphertext": "bwsvEz1LH3fo3qDwkAWipNhyVTXGiYJJB/o0Bygj788GQmn9qn33D/NuBSmPYaxZdL7WNQ==" + }, + { + "cmu": "7Np/+ABUuv9qYQWlVhv74kQw7mCewRg6xed3B7d06U0=", + "epk": "8ECp1qua7ZEtBOaLZviqDnwPzFUdID/cmVQIHgv97aU=", + "ciphertext": "F6QsambYlnBdRwz7aw5T8JpensZ7CeJlCmTsWNhQWoI+2qXSPs6itDpmjyYDj3JSVLTktQ==" + }, + { + "cmu": "hAvAhnVkU0ek+mo5AfX+a7aOBckD4i9/ccVRGzlUoxc=", + "epk": "MHEb6OBE591lYbul7hgsOOnT31Xr3HMZb6bEK9bvZhI=", + "ciphertext": "0LShLuiBlWIEasEG9jYhkeje8yhPzL/vYYUPYUgIlSzwQDb0LnZnpKeYpyd2dds3UCJeug==" + }, + { + "cmu": "i4qHs5FdjvIfmE3LezQQ/I2euuaqJeeTIy02Sv5M9Eo=", + "epk": "QmSNZsa8OQt5kFzAfeDMpscr8143X28iZbLTS84cCBY=", + "ciphertext": "MIKKptC1SeehMAEdgKOA63XzgtqxlsXBr8qmfkPvw6Uu9Cx8EXHbtU1ikBOmLYrKW1g22g==" + }, + { + "cmu": "w4B1gJazh85WRyN53K0CtEqhMLLyklc+vz70q8CpZyc=", + "epk": "GESA6jVbhgoXC4ONt9RVVjknM1WLTLYxfGJYCgzlKhk=", + "ciphertext": "g9X/MdD8LFi6lpe3QBgSznOz2Sto9sSh0VBOxJ9B+i1Hqe9D0Usybk+gdJnqPrhI6IbEBA==" + }, + { + "cmu": "ybwJYpkww2eAgobBByR4WE+o3jh/qDk3CDZxdMcJp14=", + "epk": "VznNjT/nQB4IRl7l5fw1o4x76aL7mw1N7YlBEFRjBkw=", + "ciphertext": "G71vubWAafZxeuxdZeEyZe8kyLNGaw2U+pd24V855o2fT35IeL/IUC4R7e5YOK1ZBMnL/A==" + }, + { + "cmu": "oESV9Wrp9HUm5YHagw4LwqLgLtaVOzLVJbIgqkLkpD8=", + "epk": "qRNE3ai05tG+ZEGwhahxWVAh6U3M3IyHb6XWkProZNM=", + "ciphertext": "ONOzu9nEH8GY+obJDqCNFEYwu5+ryVD4V57q7D9CB2mz7nHZrR2sVasqICR6AHKoVI46qw==" + }, + { + "cmu": "OQ42pRMY6hpU2P6Nemk++IxeE68XfcN269Af14AYjyY=", + "epk": "ygUJGK5serL8TnNY/ATY3vu0Bh0sM4Tf0DoCo+f7tI4=", + "ciphertext": "EHLgPU/r05rIFQELI9fZIuc2GdgHXLdm0Tr/jGdQKPmb88iVJpATgyGIE0t1Ea3EN8w92g==" + }, + { + "cmu": "RPmKEpHHSrbZxR98TpUk/HhCkRKXJ5xDN03ozYZxLwU=", + "epk": "6NwlTR1r0MrBFEf/HIr79uELS9h9mcpFZD7MqIswhFE=", + "ciphertext": "wCF0oGaG4AfRjFMkaJDb9uc+pbmxVA8O8AHTyxxAxUUauE+fL7LO3mRUkGd6B3rMpCgGhw==" + }, + { + "cmu": "mjfnGzHzBJsa0iXzXdLTledK7YdtJzn+D9FkIFaqW1w=", + "epk": "wayAnm94/3gvOXlrDZBMopw9ndim0WsnLgdnh7wKoIY=", + "ciphertext": "KzgZw3oobPHDIGOrlf73OyEabfxJ/7LNSn3n5x0AdqBxTKItShlg3gpLm9ym1Fh5Ew4iFQ==" + }, + { + "cmu": "kvfOKK+dxfXb8iSGcUHYUfKWHYqZJ9JZftZj/Mbxggo=", + "epk": "J1P8+vZ5D05hns1eTuF6SiyAesRljzNly/WZqgRAfFU=", + "ciphertext": "k5ZXIMCbD5/3C6Xu/AmjCJuFBVkeMk3cAGp6pMaUsmoAtuFQkQNOKhUkrW/MHh+h28NT2g==" + }, + { + "cmu": "of/7w1Adq9uWxmalHqkSOpFvCPy2OEUTUmgJX7/to1I=", + "epk": "5CsUyCc8IEyeZP9YaApw0X2YzXzz/w+AjPLLJLSHN9A=", + "ciphertext": "mGKTaLRB1t9eHctJMz/RzN0ft5CQjLlVee0iWZlxn47wR7OfXjgw8bYnziG5YN3wE4J9ew==" + }, + { + "cmu": "21zSlu6s9vOaWWF7KWwmUHf0PihbMekMj0i/7Rtz6U4=", + "epk": "jTHmGy5VUuAYkESpSi/sGYYL6ansEoP3+uur6AK2hWk=", + "ciphertext": "sE4Bbi6rFFHb2o71nVtDjJLLGL8JI6bA3LAR5Jq2UhsSa8fHwmwqCsNPELH4zFMpWZeirQ==" + }, + { + "cmu": "ri3zRtft44PVURVV6SFzXilmg+x7AWsrYDpbtXWYbl0=", + "epk": "Xmqn0G0RZz8z1vda2k737GpfQfD0r+E6DwnbYsn9rtg=", + "ciphertext": "O9SynsGaoz6I7WVUkbAzBe/u9B5fYya09WzEvoRcO2AEnW2K1M+txBmYVuRpKabMOClt6Q==" + }, + { + "cmu": "ZQRZ6CQ+NWZFEN9/QqKpOLxitaXJDHraz711791yOms=", + "epk": "mhFEiBKOuwc8WImHXlIlthN3OClqoN0NkDKvMAwoaFU=", + "ciphertext": "Zu55h1llznKo/Dwa44ZTsWWRgbCwJvDOupCzC2ZjjcZCc+clPeiAyFbxv0W+3Elw8hs0Mg==" + }, + { + "cmu": "CUBtASKb8ITGyrVfXM5PTbVrTYufnQGtKxjSOMqM/RU=", + "epk": "AC1jrYNpFP9DOBVNLRBT+jIwfQsfdg0G8ebY0JBU3hk=", + "ciphertext": "2Hd+R7eLKevvBxxutsvc2iGk08hpSYTo+fkgoKs+1FOfNRAFpU42e1ueJfXO8oA5ibD7Tw==" + }, + { + "cmu": "eOSpLuZnfPJUIla+tJBbKejrjuG3MAsY2nv3SDZE828=", + "epk": "FMQ6jg2WvdKBYO48Tf4N6E0l2NMPYTMWydB3TzmzXOM=", + "ciphertext": "0m/KWQZq7NQpCYfGMG05sa7b4cUpVLznlxSjz10kWCj4F77BEkNfySj8+OYmI9HmjaMx7A==" + }, + { + "cmu": "EoQfxvJKZLEGR8744djxUTCM/8OIak4oZb4wlnElahU=", + "epk": "C41fPMjRhaQAPolJ8YlHpXqqntj8nwA66nv1RNMZOs8=", + "ciphertext": "Dx+SLB6F/7TJQXLxJHrj/EHeqsftpUbkD/96Rmga2vrv6Pieuz09y4QQSMOuzOVXDGnEqQ==" + }, + { + "cmu": "pAczythohGkyChes3/4hgn9tBzTG1rKK/t1ldvAASSQ=", + "epk": "YT7gNFH664+s66fZDjjQL8iCU+nkLBRMuRtDOMhVW7o=", + "ciphertext": "dk0NDS4rG2wzjZbCqy2KN5/FvZJ9+h2U8NCF1vPlBHCNYJ/Di9zcO3ywQB6Gw4MKJ1wArA==" + }, + { + "cmu": "hRvybb1y/t0PX36f1KHunRDBhPUs0qZ+PPtMD2DBjmE=", + "epk": "WMAYgXALCtipZvnTDxa58C1BbHOD3wytuAwbcKgTkgg=", + "ciphertext": "yPcEPjypxQhdIbO0AR6uahp/vC3Iw40plY0A8SmeIFLxhBKxKxnD5QTzwn0abJji57lznA==" + }, + { + "cmu": "rJFJIzXrKIEAmDByI0y6ZJmJt20KNcBTi2NfXVlm3kw=", + "epk": "vX/ULfBasgKde0SF+U9EPi/ydEeorQTJg3qJ7ltgw4c=", + "ciphertext": "2YGMz2myCeANM7l8tmU72cLSobj/PzeQdkpyFEjQU6/3mMEbBG4uysfRjLmwtXiW8iTOug==" + }, + { + "cmu": "19qE9NZxkxgih0lOykwGJif9BUlHnzOKwCWlZegVW0E=", + "epk": "iCdKqdU04MuxQkgNReU33yAzyqqlGjJa7pIUmshadZE=", + "ciphertext": "FT0pCfN5bpVCQD3Jv587QYVS+HlnuJuj8RoYNz0zjToD7Q0cyCVFSUbD8blkslV+/lp8dA==" + }, + { + "cmu": "Cg0u5wGOF8zL6XuoDKligsYt1JqvkJxjW2cBIHuLszw=", + "epk": "hB1RAzgjl58QW21fwhzPMh9n+bu4oCgFmrrDmSHC08M=", + "ciphertext": "7Cxah8a2S2WZROsfZoKMDEii5VfMqTJZIgHNtK1vo9hfxtwDU6IDq055mWZv3cIYYx5b/A==" + }, + { + "cmu": "PaF1rduBcdfQ1aVEQmWzEm9EpjH46f8cZoeenqib6Do=", + "epk": "ws4pVq+7rF5e1+5yZa9Wj6NmqkZoTlOkkz55Jzb97Bg=", + "ciphertext": "u/kti5d4lp9XZ/cE+ornHtNYt7WeqtXdx9J6OOh3hV8qHGM3PZ9TqZL1Khu4khoeSWhyCw==" + }, + { + "cmu": "QVGKxHLttRW9HwembmG1cYAE57Myc5sHFlhq7gTifjo=", + "epk": "9Y9nOZNTFhYSb8ZnolbDH/DJ+nv4KrKi2S3BkfC7a/E=", + "ciphertext": "EmxbyNCbxcbo5aKvq9sVmpq5bv2gpHNNsevlpTvuVJMAu7e/m2CTN/wVpTM8i9sIfby8lQ==" + }, + { + "cmu": "dsuR5jgGP3aFu9yn9MaltTU9Vv4sskSYlHPY9CyIOFc=", + "epk": "D0q7akbP+Eitb1wgeHBtFB6it+QkrHb7zoaX+lZGgRY=", + "ciphertext": "jtfImQ4wtkTO3i+6Ybv0De6HQm+df1pXjvBDatddnZzoiY3CzMS/4ZnDO0GMy2fIjuY/5w==" + }, + { + "cmu": "rJNgNBQyMIqel5yAyVmbl+kCCg4SU45ASTwWDNiooSU=", + "epk": "BY6IKfBGBpb/xWo1Jk0Oh0KUwq6+BBNAJB3Zoi679yA=", + "ciphertext": "cOIGprL8Dl/rf4/d+QWinXYECGPs4LcZl7frLWn3v8dGUvNc0noMAMsL3fA00HL2WK2NDA==" + }, + { + "cmu": "9Z/nSzftQ2bh042I6owibnsxNBqFnJb9Xx1ZESrSYAY=", + "epk": "DiBNE0bV6saSPWe+iU1zlrSXyvz1kT3hLoH09gX2QEc=", + "ciphertext": "G0vV/+hEO+YaWWwsb+kcqabgVbeG3LCkCuKKNPZ3rC7gI5YirnmremM2+tYVoay9dC8l3Q==" + }, + { + "cmu": "dmtyz7SMWLK0fBOnPs0d8y6O7QzNTLWmsNwDwVI8v0k=", + "epk": "BQpB9Gw/QIII0wW3t+QKeFrHH9FplIKsOU4gpdwbu6w=", + "ciphertext": "QfUpvwwLHwM/7piyCNO48FNFWOUYuLslGlknvcQwlf/mWzoyevWFelt9FEJD2y2uIjAf7w==" + }, + { + "cmu": "cqIRvFCUfrySi6RtBplGHRbRGuIUi5YlqDKfGpXRHG4=", + "epk": "RzuNBmOdLj8YJBisowAhyiY3lLe0jC+nf3UKSlRARV8=", + "ciphertext": "rbal+nFTgDwD8+3ol/Ay/qlXABBfL9xaHB5CIjP8ifpHwfq/imhiS5rkhHudkQTBXjqqLg==" + }, + { + "cmu": "L2MZORVSgB9OLAHkfaJdzcjGWExejfQ6NIE6BKOR9Bo=", + "epk": "yJzy8Mf88qypa0zczxfV5I/3IlptwTA9BuP3KoEKDAI=", + "ciphertext": "XEe5Nb6JIu8vmY60aT7HGCgNedKg3yCvJfgm3dITTmp4xLZyWbwkje/PL7WiNXn4GjwRMA==" + } + ] + }, + { + "index": "21", + "hash": "rv0oDceDJYmXG4NA8xAg0sLXeTOTeC1kqXxUqHOU8Og=", + "spends": [ + { + "nf": "Fb16cJ0GV0fli0FPmMsLHjV4dTgCaQ38Azbgb3NQWgo=" + } + ], + "outputs": [ + { + "cmu": "EmQRUfTCtB9HFTXMBwqpIBu8IBbQMELplVoTLvLlI0Y=", + "epk": "t/Ohu6lnjB7MWZ4t7L8BRi2bKzCNy6yVyTIXJRjXA2E=", + "ciphertext": "FxNsrQRzKj5cvR1h5ZM3wXsHRaO5DDvFHqts8Tm/jIlwGsIZRiwyrRypyH9rcU+c85q7Hw==" + }, + { + "cmu": "zfOhEnEzguokxvd6affG/YTGY6Zn7FTmRtm0eEsj8zg=", + "epk": "J4d6+aVOtxvFZb9DnpYF7LT0Myp7vV+imz/HulqUylM=", + "ciphertext": "YRno6vMceM9qdEltoFmvUFqEzWS5lohPTLiimoWxxvGjyMcpmOVCTPNpqq9su4L6cTA0jw==" + }, + { + "cmu": "522jtk6U/3T7nSb9l0zUWBUTqmvbuclC4QV231yerBg=", + "epk": "mbBbBgUdJG1BQgmjL5UKAinZsvNXoYiGZ1ZNL7LugxY=", + "ciphertext": "OVp/pbg7R0GiE+MaDSXZ6MN/UYccY6Sq5qpBPCMIPqNVUfPbVRsNQ+6wGBl8nFsYq+jFmA==" + }, + { + "cmu": "EHgDLpBsplCiYgWNiOJKOuV6ZLeBUoW+rfk9XWMzWy8=", + "epk": "A5TTc6/EH74dvl2KhfRt0g39/iA3GcL1UOHOgAjYjyw=", + "ciphertext": "i5H1bq+HyFJBNXgaTKCS355F80jzI/NATMHHL8V6h/uxXkhLzd3ugQfVkV1XDcCgPjPKUw==" + }, + { + "cmu": "js7oxaN4TWrBdfTpCvW7hR2kYbyt4TEZXlmG26sMDj8=", + "epk": "vn6PayQLPlkmEqevzMay7dGI0765yc2034XUrHi+Xtc=", + "ciphertext": "A2zBpkRplZqlS5av/JfxpgFSVshQh7WgtFu4bi9gN2kZ2XrkL6S4tk6tVAJzuY5LeG5aNA==" + }, + { + "cmu": "tT3XFhsPttYUH6jLvIT2iD2VHQO7y2uJCi7b53p6lHE=", + "epk": "qmh4BORQJZHs7ginWNM7GVKy/r33/cuB2qnXOQRqtQg=", + "ciphertext": "njeIdxU96KotmygPBb3t0iobiqrwW4FhCMUW5o6UC2jGy3jp3fzKgP68saZzA7vUbDXe4w==" + }, + { + "cmu": "fbAvaDuPAsPQj2BnRKm0WVZVirgZP56I2x+pInFWCh4=", + "epk": "msl+jpl8LHc0QwvehmqIDE82XxEpcaoetOt8BFwu3pc=", + "ciphertext": "mMNVcRuJOgXJiJz0D83g8h/0xOBnNetpf+6wTItJl3iuRNBhBYtTtvTh59OoRNDELYSFpw==" + }, + { + "cmu": "r+gJ3Dlp7YDNzIHUKhwgnZE85Z8sLWW9nuteLHd6aBg=", + "epk": "3e2uXXbFp5FI1XJPK5gk3P7BajJ35pNzvuoA31C1Qy8=", + "ciphertext": "CgbodS66h26YRhubwBq4NLKw3gLXkfMG89yCayxDeK5m4xQ3Lf+ajcK9mjglDkbs9TN5cQ==" + }, + { + "cmu": "mMr+E8An8cPvo2QPzpFQJO8GQc+S5jyitJy0fB8Qtxg=", + "epk": "kWMxv9sF0ewLUF9mqnO11oX8SjoLwHrSUiXwdmZfpQI=", + "ciphertext": "6G8igW0KI00ASwYpMfcZNZpTlW2OWiWY/50c+ch0inJLBKCEjl3axdXX7q9hEyJKXzl5xw==" + }, + { + "cmu": "gW+VNVlgWGXzG7BIKF1wWrRr9wp0kD/bIydRYdnHAAk=", + "epk": "jxNy44sX+N+JGWES7DdKv3pJzaiBHKUmTsgoOX3Tzr4=", + "ciphertext": "PJrHk8XFumNVvB89Hu9FMuw89UlKS8NuJ4aGypOe0Z1aTvLuQT0tqlNemLXS5vWFUKH15A==" + }, + { + "cmu": "pbUb06U3G5ks9dMkCTSiNtTI1+tMLsDy8qhJCnW0Skc=", + "epk": "E/iiuH+JZSimJiKvbLVeMh422qhowe0t0K2PmtsxEJU=", + "ciphertext": "WwzRKVWnkJjKx9fYEy2e6Uxo0xx0kaRxxtyZrtnvGUx9aWOmhyzq3UY9Xi1TlwrLzKSlag==" + }, + { + "cmu": "WSU45n5t/RLSjhmjf7DGxGwvT9RmjHzIkS0gB6H6qSE=", + "epk": "ZkdBo2PMSdLzusCnQWfCvM8lSFKWkm5gF9rA/3Jt0fI=", + "ciphertext": "EWs/bSQWva4KyT4T/oOu3sb4nHjQEIKke4Yuf1cDF70cVtJL24pPQNSl5gJozTvzRXuC7Q==" + }, + { + "cmu": "eMiy+QBXbW/ii7r+lvMYkQHJyOxjUXkSBjhqetBCzmc=", + "epk": "+zgfaikhvrF+UWpyDUX1p75uNYuei9O2IEqXhIexp94=", + "ciphertext": "ern37btkk+K2S/fsq6Z2tHHEe9YUvAB8f1K7+GrrO71l1p1WWrMOmgBOrQyQbnAp7haciA==" + }, + { + "cmu": "dCKCcPlmt+a0TG/I7GEmlJ9FFY0tj6d/m9jxv/UlhBU=", + "epk": "uqYcXIV9/PW8K0p6WW4UCFLklG7KUKL3MPmZczqFOk8=", + "ciphertext": "9/hfxx7G/DuQDt+W8fNB3bsYL1axuXEcEfz6Je1yRvcYzSeKqb3MRVfkDJB/simsZ0efVA==" + }, + { + "cmu": "4wrwJTnhjT9jKXQqFwIfBa1SM6mMq2I/Ao0D4HLxMl0=", + "epk": "LFtGR1YbDrOSxTHt406w+fPVla1vnoxhoAdsyQpz2As=", + "ciphertext": "oExihGHlQMyRaerD4n1RhGp4zyJ1e5fcaX9AhHKYyfNpexk2NXyISsnw45XInoymFY9EuQ==" + }, + { + "cmu": "2+i3+2YJIYN7opxu1w3YTOremuTZBtwl8UQIkoh/Jws=", + "epk": "j8+UU9ShpoMeO8hEAqza0lC+NLRgsFXu5+xLF1MKQS0=", + "ciphertext": "oA3MMMMN5FDwpaGuCV2YJpKE75E+YRu4z4WtVjgQtwwI+vyQeY2XgHZ6KVVspRvPfFsXZg==" + }, + { + "cmu": "+JUnA7kARkmrwxB9UpEHvBKC0VPKHZNiXjyu9a73qhM=", + "epk": "tXdreACOvIcYEdyH/cS5AWRzpgVvqnjCvt/MuE2Nqwg=", + "ciphertext": "SWJzYSPw/nFAaCnCt4i5lekGFB9rJt2Eta/OG9zFmA30IgaKK7472zcd4NTVhLHbb85jrA==" + }, + { + "cmu": "d31S0ftWy9N3+wSrg01ga49Li9K1rjIp++ufOHnsoAA=", + "epk": "+kPJHf3PQwOtmVi5oWqSZjilnug7h9UXdpuC5oXc6PA=", + "ciphertext": "1uqo4e6z8ka3mZwyGhbSh94RpyJjd5QJ0+Yzw6+v5y0iPk8CjUe+aj5EdnBbzxqN4cKJQg==" + }, + { + "cmu": "jvNJtcOHb4uU1IovxP22Wu3GE1Fss3VQ3syIayZuQ18=", + "epk": "xBFbDMA5klswsPo+P8FBDDOGbzNLmlK+NZpt/p0v6rg=", + "ciphertext": "YzwA5scxAWueeTTsWBJoU12vTxxxAiQjuY61gdTvbqfhBeS3GLxYfhxf+oSGYx3vAArCLg==" + }, + { + "cmu": "gu77HVXRvKnA+rrklItVlIlPijUY+JuE+63nMzLEE2A=", + "epk": "XP/X9UGmA8ccU3UijTEO8lbN7G4QSsgCssJ5zT5i288=", + "ciphertext": "eNrhs8+V/M2+ft8K27PzQ2deIN5A0f/j/ALD4/NJe/8S1GF5oahL2lSjRUs0DXCGz/nKEg==" + }, + { + "cmu": "LMwkyeGVTqAJbVBz45IweY9Jp3PdRwBWDeKYOdPoQSY=", + "epk": "i9Hs8H6WTZYLW9+nycCzYsXY1OGwBRFadCdqCJdIqmY=", + "ciphertext": "pWw5XpjrqCRCHPBB4m9iSGlkK6jElPq7qN6f9sACoTAMqjRUrK9K3L6D4EwRauvE+z3hOQ==" + }, + { + "cmu": "vqB5O4uTlmPneIOOm9v/dthdP0Hm2hgariSFV8y72mA=", + "epk": "SkECKWfFDhxd28NttdwfMAbwOtH4Wbx8AXqA8uhS+D8=", + "ciphertext": "6S7EVu8VsSi2utMQjB+cW1gLyELTpBrQeEtWnO+D1DdW4ignEjfW9awrjS9cJw3NTgZ8RA==" + }, + { + "cmu": "gVJMG7wXcR3CfRhTEDi5IT5cXexnuWsoPi+63qzUamc=", + "epk": "R5Cl8SZKpvI3Vz4bDaRC+yK9ooBHs/7KqrKTZyI/L6A=", + "ciphertext": "l6PsDkXXuf6yLYq88NsXBMDbgvbINnKAsJdlV/0tJJGmGy5C9pA4CyBo6190yZUjsQBfoQ==" + }, + { + "cmu": "8LPsP8a22+9pLLjJITKlPXfrotgFmwLiUM8wwOLL5xs=", + "epk": "41GqcwY57cMGbst2f8GDoTRmjI1bxGqtNeEsxvEXEEA=", + "ciphertext": "t5rL0SnLLmJTLwp4P48l9nSTt2O2JudFqTMSfiQHYdj2b6ZN75rQFKXkkm8HEd75IDIRyQ==" + }, + { + "cmu": "kg0csbgTSTNV0t7gC8oRzOGouCZ9Nfp/TwKzcBkX1RU=", + "epk": "284WrOgyOG3kQC3SjnfiqVhhKs673ohXJh+QCdqBBBw=", + "ciphertext": "fUk6XFf1hRDw4h6zPyaYnByILQAs3EEQbNAS1y8D1ZnWL3qUloLFwqoRajUNleR2H9DELQ==" + }, + { + "cmu": "k/RqPktt+W/njFg5ncqvEkKJCJrBjlCCAZPuLgBqqEY=", + "epk": "BBh33j4mgRPqYDpxjMunJq86O5couBfSGm8cQEdp06s=", + "ciphertext": "qAXjn/IoBLtebvoXcKtQ2dQwjgYfkBk8rfM+sG8D+W9tBFT1BJA6JDvyjRWrCipNuPynhw==" + }, + { + "cmu": "dcoM/B4+wQoC2YD+fAXxaZGmNDJ2V15Uhr2FcMJuNEQ=", + "epk": "lbx9KYlUdx8iPQwmNGXxbbDryZQl+4vrj0wSkrrEA3A=", + "ciphertext": "BQhJocWNpCDDjY5u/OF+fIx5pMsd7fdQl2DjUeuc6ie722TcWeBRaMvVqa7R3gwt4uoY3Q==" + }, + { + "cmu": "jz4L4+c1UFAFptp3OOMmTtfSY1dt1ry9bRJ8fJQgx28=", + "epk": "a2oDD+0KWT+dyb/GOZm3NCMLP2i9bhkxs/k/RBgXLBk=", + "ciphertext": "KwZ3zLXBbJqS6suYzlaSY8XxtLQnXS+b4Co4lEiJ5rLXBQWPhAh/VNVf0gBFNE0T5tWuPA==" + }, + { + "cmu": "e2tp99kCI8QFBT9RbMTq6MmvgTsYwz3V0ZAopOZvbgA=", + "epk": "LOTcrtbGhUI8As6CnqltSOllN9mh3XUsAzmd5yWBiVY=", + "ciphertext": "dcYEyur4VriJpvRkJMrm4Nrgjk8kcPvWo9xzQ3fljMOQZ4DbOluRZkbbCYI8/DqBMkoMXA==" + }, + { + "cmu": "CdKw6TLNb17DQrWS8/4N36+i9+kW3LlJg3K4sL6J8BY=", + "epk": "bS09GjpkTU2zgd5fZSptkoIPOH1w8ABF680fWhLLWcs=", + "ciphertext": "UPmB9XjATAvjk/ACbnkKVku79FEEHhKSondBZahQjCs7/9iwCz+8+z6KaqfjBljI314PhQ==" + }, + { + "cmu": "2i7ywK+xCAsBrJI1kPM6hMl9ob5P6Tph25FTK64H6CA=", + "epk": "jHhtjki8lJF7s0FDAi90DUjBpm8DCFwbbcKXxqwAabc=", + "ciphertext": "9TXCKfVah6WRw753HxmwzVUT7m0uWLBdZBIfkMvh8ftPF3ZCaybWYQFe4b4dtrpLQFu3Vw==" + }, + { + "cmu": "JYixELnKC5tG5KO46uEkZ2sSW67/146v/R3pws/wMhw=", + "epk": "bgmeIJ50llh0PjUJFH+rC+iWL3llh+XmwxOG7PcWPuk=", + "ciphertext": "UjkRmEapZ1AYGWD/Eg5Cbq/f/Cu9YyUNmp4lYfCPDAfBHo72gWxvMz/Tttk4icELwmwQWQ==" + }, + { + "cmu": "yXhEvP7b++hl0tANcFIyr2mwbuOSDTao3lsYThgNxkM=", + "epk": "17fNc0VOvXlYRsYJuQIGyJgh86c0d8x/hD2WZ7yVMoE=", + "ciphertext": "8NRVkLnvU3iPA8mnad+Zjh4rHRqvS1RDXA4ANeegiCVB1lxia88jdP07xIhiWhZdHO8BZQ==" + }, + { + "cmu": "4rl734yEwz6XX8uDwcGYrysLPLVYI9JWA2nJrMA7gxc=", + "epk": "gv5tX1RqqoX7Cveqz7rssdouB+evA3mH4aDGrk64ijM=", + "ciphertext": "m4stHBW4JHjY8VuFEczgUs3EMaJfSODIerkFKcyIjfaRjUIFCN/J0/Xdks8yIsoQTi4bNA==" + }, + { + "cmu": "4uMRcSIaF/NLBOjkeGbTtl+ytKBKd/ev9loUzrp/5jg=", + "epk": "4Ox21R8oWYPJA6s0m2P/nu/iH7i1F9raAK0aaXe+wUs=", + "ciphertext": "GjzUhQ+yhEs6a0hf5NPmr6Lam10Y1TGO/0HFD0wj0T+gfrAzxwmQoGzoydQRSe6C3pLqEQ==" + }, + { + "cmu": "U5wfVSDYMvvG4TjRBZN3YY7VBQORf5x6vnIq0JtRESc=", + "epk": "xRJgb3ugSDB/JbXxpTvCIzVko9/TtcXct1Ldoa3U6ek=", + "ciphertext": "fbFrHRBzVg2kPwxELO6KElJvs4eL6nsYHlGcNaUwbwTGtduSAriQHr1OQvxB8bndWprAhg==" + }, + { + "cmu": "vWZuKxfUX2tNZGbo08nRFRvbpDNS7tloAiWvBKIVxwo=", + "epk": "AjdcBLu/FDL6BaybNLWctjrgJgLlMZRWizhE62qXEF4=", + "ciphertext": "Wx4d/zPsitXxh8KofDfTa8lSclzP8ehPNxH+aUb44F+PEk6RKhQuwa1SiizMKfx4+PrCEw==" + }, + { + "cmu": "DpoLAY6zTjawPs8UURh+n0CZPoXDjjAjYknyZutWAiY=", + "epk": "I5Vs0V4OSz393vdevM2AdC+jPhSEd5SL8PPwcQV3ISI=", + "ciphertext": "4HK5489CWrHbTKPHqptx2K3oQXOsXhiL2eJNSIbyE4e531HXa+pqGk1Z8wLAaFUVUW692w==" + }, + { + "cmu": "Mypp3M65BjY92wDKFE9ba4/7SWVvYYtmVSks+IJ7HyY=", + "epk": "O/95Ex/Siv/PSeVQBGDyT1YxatHAJpXuki2OLa2+MFM=", + "ciphertext": "UaT8kPRSBS+OpcpBz+euyNZX8dMaR8l0ZUiMCFgogooaBhsGlXJ3ZBIXp7JLylVeK1p+hA==" + }, + { + "cmu": "js7qAxw2kXPEFW09VGZu3+SeM9Uy8c8oaRs1DL5gFUE=", + "epk": "s6/oqQlRFdNhSwOoqBzb0HRrM2HpJ6e3WtNyeZHuuKk=", + "ciphertext": "y+FqE5eYI35XhROwUZ7izA+Fw5ekmwL+qLVpT/5MD/bhujxDjlNeYZLlRmB4Npngn8/nwQ==" + }, + { + "cmu": "kB7bZnngn1Z6YyfAdwIuNJC4tC5kD4DHrVOyrYOgliQ=", + "epk": "jreruhekPgdeFNgA5yb0s68pxHizXf/m2/34rwSSEgo=", + "ciphertext": "i3JWOJcAtiivnxaA7m4LkWPwjn5/utfvfZ7f8+Tp6zle7ZkZo9tOiayGYXUt+sgjcwbd9w==" + }, + { + "cmu": "2tfekDFc6toZ2hRuZ9e3CfVTIdaw8Ki9XKLHa56P1lI=", + "epk": "s5Ob/+9RTDPTB8EvmM/uOj3dCYIGDo2OLLk+2DHEDVk=", + "ciphertext": "PAmJu6cHetwDTUaEIRXW2pZ0MSwdXvgHrEJWWgUroq6koUrgKcAhYabDqkpxg0v6nGRy1Q==" + }, + { + "cmu": "UzdJ5IHO4C7tqSZV2V6OzvNdMPMLkqpPrd7nV9wXvm4=", + "epk": "ByT8P96bgiqKlvoiWZW5ewtVHUepku6P+wwfkGaM7Ck=", + "ciphertext": "vHBIUYO2z8srkVwJvhK2xUhaGO96QCPHsk4X2rlvPybnbCoPaGPVIGBZLKSZm4pOqUR/Qw==" + }, + { + "cmu": "p/ruyR4P8LgRIbvNhcit+wufFTq+4SBYjADmjpORTBc=", + "epk": "gjTwAIQcBck+aDdjH4TIBxXF0vWTMVryr4+BTz8t8gU=", + "ciphertext": "ahYGRxsPKg700GEjxV8Bw2iw7JJHUujATYuMa+aVyEtaTON4vb87E6UhN3A+LFqki/pKhg==" + }, + { + "cmu": "iwKLT9DvJbf/MS37Ghh8nS5afy55sc66D8Vstus64nA=", + "epk": "4tTt9T7R0GyRCebpihv1esx1oUFJRHrh3UA3h4sgYKA=", + "ciphertext": "a3ZXcU1TKMH6Akkkp3Xq1r7YkwLFj2rZq82bfSvuWbm+TeroIzVsgS/VXqmsakfQ6uo5HA==" + }, + { + "cmu": "2zaZq1vxWt797pvdnX/4SEc9UNJO4lirfG9d85cK6Eg=", + "epk": "50PoxWyY1uIhR1kgN+LsfsyrnnxSu1EnHyKFQz0j8MI=", + "ciphertext": "WalvLTkp9mC+DZHuXgA8KA/Pvc6N82NC3+KfhlARmN+Q6/tEqkt/DzFFGeg3NLKLYuwDbg==" + }, + { + "cmu": "Vu6BGRlT9FisIcuCqHz3VirHfjbfWn0b73S1Bf65wTU=", + "epk": "JqJpGDueG17jbv2vHxJceoTMBpz1f2IxwmRCAcAsggQ=", + "ciphertext": "OZVpEhs9RB1fUDc/0uxOlN2AneD8IDr+8RAGbAZu6v0PZh6Tnpy5IVyGD/xGRD3ShrgQAg==" + }, + { + "cmu": "pyxyeL+Q7PEi5VW00uqELzeQZnJOABQ0+xXuoGk0GiY=", + "epk": "ol23I6MBNiJhw3whWDcCRO/jqm3STMq7dGf/E8QSOFg=", + "ciphertext": "AzxxiX7IdBDe9Byf0ik+HhVkxn9foWU8BxgjHnU5DTOypRrLjdmO+fTUsIg8EUP18rL5Hw==" + }, + { + "cmu": "M3EtHN1165eAOiGu8ckZlPN0G91RLMXLASCLjTKRSjs=", + "epk": "CE7XRH7GFlqfNOG1dyTz9Y6Jwbege6BwHJTXRUSLaIg=", + "ciphertext": "RoU/2IQThm1HPwE7lTQ3yUyeEIa2HBs6AxIoFLO3DnhhNiovYDpeKTmRkFqJEMZ28j20gg==" + }, + { + "cmu": "Z27WR+dAFpObsvCBgwBzRt0hMOvQxiEy9xb3Emn/6Qw=", + "epk": "Gg5cd+DySbEPwvZvHmZabQ/yKiPUr6TBMFLicLVTJdw=", + "ciphertext": "YRatrsQP8SgdY9XlfAQWwovu+L9e4o7Kr9Xxam8UUP2ij67s4tOwTbxEoApxpkK7RMXhcg==" + }, + { + "cmu": "iqPhTeegsr71R9Gp8YiEMFAT+m1IZYbpFh8R5mAfGGo=", + "epk": "VU+xRCdeNUdA+cXgmKfu90ztVXAjmtcOPFQ1T74MrVw=", + "ciphertext": "hMo3Td73K9zt3MgjUosd4Q3dOK+ggrDCOsoomhAq4IkpGoHfO5/QfpcqhJ0kW6r5KYLGRA==" + }, + { + "cmu": "Nx0I+OTQYr0xzisd96W5SgcF0IrbBLA3HG+tAQ906Ck=", + "epk": "sTGLmTr555CgDnc7sk+JjiMUTNxT1eh45qFSDrOlqJY=", + "ciphertext": "XVsr8UjUO3/8Q24tP/+6VseqruihQqeAyw4PkeLJq2tL0L9f57aCOAsPnEdQYPO6UXj9Qw==" + }, + { + "cmu": "85sF0CY5b0U3bD33WkNYNfT1stNW6I+lHuZOMSuM0ws=", + "epk": "+lLmV9Bk8KDEVmDERrKIksnIZr34dqPkSU26TkIBOgQ=", + "ciphertext": "xFuG19x8TCRSfddxqwwJqOrYxsg00JtlLOVb4bfOd0XIihKvwppGf6lQ/R5fyieyEZC/Jw==" + }, + { + "cmu": "jHUtfVAhqffyhoTJy9oW3Sf5VOShLhBkM3Mbn/cDXFI=", + "epk": "eOHK/6eL2mtl6wTSJtGTqTAUhraQ5YyEwVetJ/I1GGI=", + "ciphertext": "FBQG6ik1m3lTV8IHJuibiT4x85mcua4rwbKtPsUnd/aZMTm/l/A/71Evnu8/TkSlDWprDQ==" + }, + { + "cmu": "t8TqUHFkUkFZYRQon1HOTB0UBjmiWdVpuz81hw6pUTc=", + "epk": "roil04s5yfFW2hHY8zXY89Hevwx771LlM6QQIJcW1QY=", + "ciphertext": "9hlb04iN9qe864KjntBuEy3170u5V8jVwzVwwOD2HwUufB8OT5szW1KtQARuqaVUaEidgw==" + }, + { + "cmu": "JtPebh0KQsP/K0U3W9jSVpOmLkgBqKo7cn5zwWBGMy0=", + "epk": "EkQ0Ojlhlh4s/Be0HQye270HlOGSdmJUBzaEQE5hOw4=", + "ciphertext": "87PMXFxlPq2Kv9Mp3PpLOYr47akCN3qYkD8fc39hVluh0ENxRWKg0xu7l5cS4sGFf56hAQ==" + }, + { + "cmu": "rjQ1dX/dbyoR3TNv1HECigXKdKYMzK829N18Qa+goic=", + "epk": "dHUyGHddcpnbpRSGU1V/mRWDG/a8yJ9FZ8CZG+Gm/Vk=", + "ciphertext": "XypVnIyj4ZbW+ZN1i1F7psdt6AT6q69MHZgyPk6huvjkH/slTppfNztGLpHxOqViSDC6OA==" + }, + { + "cmu": "T4Yt4/DV66gnGAkjfGNRQ3sr2xIDCktG1bwBaI0PECI=", + "epk": "24h/DQ8osZLxz0kew9+Otf7Jukb0Kg2jsFce+f4C2CQ=", + "ciphertext": "84QOa38bsTIupHBfqKFYrL266Rrp0koAkg0luVUL5jvgTUq6grfc16AiLmTsnFwWGYxumQ==" + }, + { + "cmu": "QsmzQele0mfg46aZ9UHL8W2Ia4QKun2kJ87zF0A/TDc=", + "epk": "ZedFjs5uRAZcfZG8k3zAL3tTwpiYuS/CtU4TuB1P3+Q=", + "ciphertext": "LwRXKYOXuj1X36OC7yM7N+FeVxU8WbkSdY8sxmd5tVV5iDHB+laA2+pkpk3jjTmKqRY3tA==" + }, + { + "cmu": "SeN+ly/8b9iF1g1vC1DkTkBDdQBXbPawRo98w3v9XkI=", + "epk": "0jGe9hC9P13R9VwMCyKSWrAA1N5L6dULLrKQoE3Mct0=", + "ciphertext": "xM2XKObJNPb7EzFs2mgOrMAdY2/76Tey+/MiLKELWNzE8L5LnRc1gw8eYLJTWrmVvAQbtA==" + }, + { + "cmu": "y5+5Hg5fwgMNslvOxj0dWcn7lF6rp+DrIa1Vmn/7FCQ=", + "epk": "5Fbc0ER5+wWl2uoPOytiOiHSANsn0Sqo/0cAZdwKpI0=", + "ciphertext": "ZLlVckzGUkGGRYsiayeiPECc2wfY/DIbiArsneCxA3Y5yk2THjOX79hTyfRIoJv5qmWnIw==" + }, + { + "cmu": "/EYHBF3mLxNz2FwSoJCN31o2jxUq+eR2w0DkMKrX9Wk=", + "epk": "8IstDnZ93vmDRhG+oCUx6DnqvDvxYMd2ajn/PvzSs+g=", + "ciphertext": "QGgmTn2olt3r63Sfs0s9BJa+sB6NsiBp8TCwbb+gTzs2XUzLxjM9HKiqdofEFBv5U7vkUQ==" + }, + { + "cmu": "aLRhvIKbXT0dMLwlsoM31l5wWoQmwRkXQgdRYmS9+BE=", + "epk": "ObdUGvrUh14G502aAY1l5dfAYJ8VX06Ipj94BJYbYFA=", + "ciphertext": "m4Uqm/DvefAQs5O4EJBUskE5gnzvEWJ2EGdINw56Q3q+KoahMjHpu+AwFHHisSzVKlc9Tw==" + }, + { + "cmu": "aPdRm5ftJgznVIc0x8q6trGtunLQxIDHJ6bX+QFBSkQ=", + "epk": "ypuflLHA6738JM6uxKI1LNd9D9iOpscH7UvEt/CbKWQ=", + "ciphertext": "qGgcIK83c69chc982RLmZWHgI9WsCoc7TSLYqmRptBZwbxkKouBvkWMivXA+ssFTOMZEUw==" + }, + { + "cmu": "Zx79qbIfL4RYEOezQ3+nTPWgjTYBmhqNQ+rdsu619QY=", + "epk": "WUVcoHPYFRrFjK158nKxzIo57aLMn++0EQuuaOhxLoQ=", + "ciphertext": "IhC8wK8O5/7H3X6x45l9YdGUEfoqdHB+QIg5teUZ2qnuu3i9AAOKrDHkMpvh/Y5cTjwJ+w==" + }, + { + "cmu": "S3174/2paLaB6nb5aZpGhB5f5KzylMmV428vOaKas2s=", + "epk": "NQLus9EDHGADwQmU/ucvo42QJPGlVJi2DeV4LOiW0tY=", + "ciphertext": "lsOCeLXUZt0T28Z4XTdZW6U+8wSv//XlrdpJeq8gxoQtMPkcpEVujxbyHoLUXJr14wMBaQ==" + }, + { + "cmu": "kn2wM+kuiYB1Z4cumjahrTGO071FTmkzsTAsJOlKJAY=", + "epk": "jHkzeacIKFzPPg55wRluUD+NgHcXp/E2R1kmpt46x6c=", + "ciphertext": "8aqLAoBYQc3ZXOan32oinBN8mCqmC9Iui5WUC4kHq+YpwER080g1lRLJREuNXBwgE3rxqQ==" + }, + { + "cmu": "cNFS0uou2bBf98v+jXcUPFbxb7v9LkRT+1sHg6jB2Tk=", + "epk": "byc32lNlNhi9/2aPKnHnYpWlRZvvElJIu2eXSnopomM=", + "ciphertext": "VRKWJ7El64/ANr6t8VyZaK6USMxaXlloVQ6XmVIrnRTZKI6ywn3n5w4+fGJAss2Me2OV8w==" + }, + { + "cmu": "3yrd/LGXdMneh5/TUY6BZjoi6npomrsMooxUQHZc3Rs=", + "epk": "dEcbdXlS9pBRzXixSny75RgaptQwCkHx2M2WzneWBo0=", + "ciphertext": "J/lG2ynADiVYV1OjOphfCIwTGtPpq1/eVebv7uf9RePX3FHBLN2v9lCRf5SWNjLdVv2UiQ==" + }, + { + "cmu": "BgBISTtjnGeq8OI0g/l1RZk8Y9p/ifU1ToWsRin0ox0=", + "epk": "bwpnAPUWR8VgtNhQ+S5hh2l5XwYAKKS5dAd/3KvM/T0=", + "ciphertext": "/ZwQcJnoPyUrDW4WmVSlITFlQvKlgapva3oGxS5hgR/vVcIbwLJT11+u3pN3R1h/anOJag==" + } + ] + }, + { + "index": "22", + "hash": "E91D1L3mTrIGzPi58fSsNreZnmLnPqRT7dEOI3SYvnM=", + "spends": [ + { + "nf": "4V7U5LkjykV/VF8SfOay/kj+mBQRWsxs+t2qude/DcM=" + } + ], + "outputs": [ + { + "cmu": "0rMmBKwO0tHCMb2Sxb4X7HgQnX7SbJ+ULeMGlYVmkEM=", + "epk": "tJbgVVk6ya5ZlancCG8ycsSm0JEw6mzzgwLHIhGv7sc=", + "ciphertext": "VsLOHi6X147kqq0EPsWd92+lzCcdEw0aD2cZ3ACqdEj/Q6H/be2Sjt2/ERqGNVvQfFezOQ==" + }, + { + "cmu": "8ihtYMK23I0B1kuwWDDQV2qoxKr8BvLe/rAXkRiJzGA=", + "epk": "cFs/OePadkrE+VBAHYlFjdQvKPFmcBPIJJSPhtylaOY=", + "ciphertext": "RsZca+ljzTLP35t/xHwPhF5erCHUjyVs2ofExzinuC/vdcJS7jIcDSL8FXVp6s6Wtn0BQw==" + }, + { + "cmu": "y9vaZc/qKuaZD2xc/JxoNLHsbBH+Ri6GIjmAGMrthkg=", + "epk": "0rdXxRsahpDMNz3Tc/u22uaL6PpgsMtDzLmvpWQzZJ0=", + "ciphertext": "ArD2rF/lRPgHVQ8FmmFmFX48tHpJ2rYRQU1U39jPzw0Oq3VHn0Pz0x92Z7vssBLUR9fwYA==" + }, + { + "cmu": "kYzbLDkm2VSWY1m44T/wQnySB8vzkRDKmS0BtbfNtxs=", + "epk": "41wNG9QX7g1vdguC78vgW67HfN0SL/m5KYj50iX8FJk=", + "ciphertext": "A3gfMl1Td9u6JSwTOIBTONSmV7O7G1cnEh848HzOcK3Npve+TCvNzg9JMSngMv1Lsp7iQg==" + }, + { + "cmu": "q760c+/6PPH8vymzi1BWpLxn0GM8XwkKesld/fZ76io=", + "epk": "fsOn/GRu4SjdY32RQ3ws5AM//iK4ILrqcwHGLcxC6UU=", + "ciphertext": "GW1H0f9PGUXx5A6jq2OvgfrEm/wQNBGrgqkrpQ09uBC5dRg+ij3+a8tGSuAYqPWJhkLpbg==" + }, + { + "cmu": "6gy0sg3RfqUIpI1j9ojj0VCrBMZgUGgpoDkXQ30C6UY=", + "epk": "cLodGx2I/vwrfct13zO7P1P7CMmJjj/5e6THpygPADg=", + "ciphertext": "ICR5joSlDIxRTCkJcQySi7iYBZh/4Rj/WvDSwldjWX5X0Jg5tDKjdFKHPvDCE7HhuJQ/vw==" + }, + { + "cmu": "iPeYv11B3fyhx2T6+WgpYgFuK0vHDucPSgWfWMs3uG8=", + "epk": "7u7NyJ0l8k5NZqw39ad0716TV9jUiThicWSpel9GyVw=", + "ciphertext": "YDsLFkMJpOCHVL2D8AkrP9vz4zx8XL8HaVyQeK2k8kaAZmlBTHqEXXZ0RGkSXu5yZ3y2PQ==" + }, + { + "cmu": "R8j9KN5b2f5yieTw2gABVlK83iLYEpKta8enAw5/ZT8=", + "epk": "vZyVH3lRnM22cg15vq83nkueCWmeIbV8HFBzfwdOPQM=", + "ciphertext": "7jarXpsvSPnRAkw3gJCSh1Ke9wDtnL9C8kD/xHSzWc91GjesTrTW0yGWdwX6RmaJkg0ppw==" + }, + { + "cmu": "qSIUZJDyQt0CjfhHigGcABbMlvlTZgHbRtTHLR+pTz0=", + "epk": "3ie629wX19kmJmooLo3H0gtaAqmj8iGkdDhXY6GL6xY=", + "ciphertext": "qHySsunkkVo4CtXbUKQMwghgJNhnEFG2YZnAPxNBGTf5J0HTI2WYEmbhPPHhIQiiNxvUsw==" + }, + { + "cmu": "RLTUdxhgqykiOEuz5OU0cOn/iyNX0GhiLzEsiOC/Dl8=", + "epk": "6C1yJ73g73e3ufn78gAv0nl67I7ijaEi8rhEodhHcI0=", + "ciphertext": "oNyzogDmsuLQtAZMlHeriQrVsFv6aESE6LIUok3aALnNy8Cr9kAnics47drJrqRq5g+DbQ==" + }, + { + "cmu": "Sz6bTLBv4X2NgeAaMtSIDaKAz5/I6D97ee/YUXMckQc=", + "epk": "eA2lUd8D5QcW63JDj3e0wjFYUpwH4awPH0mKApnitlY=", + "ciphertext": "CZZaBgXY8wEOqryP8VTEMib94aNFTqpY0PjnhiKRtxZx/DivmOGbOYuQyUGWaW9pAIw/aw==" + }, + { + "cmu": "7tmmSOC0JdDuTazXXjK92Tpfi0iWo84bLM3nl6gZRz8=", + "epk": "QPoD3hOhXzKgywxOx8j/21qFPe0d+q/5BXd0XtMkOYU=", + "ciphertext": "2xUlchxPMZTpgBdAP2E4ODHWunLLouqILQZF7W63BYGEhy6dDO0wJ8GtLebdwcCr9CkSUQ==" + }, + { + "cmu": "em82EBk17kJmqWFTulkUKUiNUxILGRLZxgX5y5pY8Tg=", + "epk": "Z8ESeDuuaBt+4uNTJ0tiGa+SW17I3wmRUaml2jL/fBc=", + "ciphertext": "uf3zq09+ndUsKazwer8aOTW2W3l9qp4xgzpicHWN4Mo1g1e2HoPLXw4giFN2zSQYzwoOxg==" + }, + { + "cmu": "PlfyEPpFmFS3t8bu/ycGHfTaJYqa5tGh2fdkLrp3cwo=", + "epk": "4hEDLFZu7524Wsd6tRdrLBnyPxNSQJyRliqhJtjshi4=", + "ciphertext": "enXu2JrIoibbXp7T3pDH/9B+mfjID9N3gmpCclXNp3aoW5rE6XbZYXfDc3qf9tVQ2CrF6w==" + }, + { + "cmu": "HSe8HYu4N37hQJpk5t9s7pTva9S2jEJ0pWhkO5Z5RhU=", + "epk": "c78QyvLyMIXFDzXpEicftoTJFzIwbMod3YH2nuA9qYc=", + "ciphertext": "6kc0t0U2KaCx8EkTmh5kxbzq+QSQ9mlIV0KJF+6uTVAenmAT3f5MG1sURXPNOy9q3yISYw==" + }, + { + "cmu": "ASTs5c6QOtdmsX511zOiwGv+oAJNnrVE9Kf4zTc0OAU=", + "epk": "Vi/7yBfuxgf+tj0FOFI54uU/9bDSSZePOV8Ha8f08EI=", + "ciphertext": "3qFmI0+UDLS0fnx52o4EPEVeEDmEZ/Hov9KEQSIGcjV248Xrn56d/n+6l54uVJMT4zIfvQ==" + }, + { + "cmu": "CH+8xmdro0gQCgrczrdhQsRnyKfoCbyXynfRFxwniQ8=", + "epk": "RtkE+9P53qZbBqflB4VplCdj6pH3lKHzzPdwiIcTqZI=", + "ciphertext": "3wEiCwx+18JBLGG7Yf5vzNT6qTK6M7PA7IePQs+N/nHKIPhqhmADLH6lzjnOEiaoGurxpw==" + }, + { + "cmu": "4ywp/ddVCpn7OBaQDZGH9kiVwv1Pgsq0u8aYHcms2w0=", + "epk": "81OQJLjzovbYTIPZhyaR+Q291I+m5qfuD15tSvyYPKw=", + "ciphertext": "qglNAQd5nXerOT42Cco3rBlZuGHim7aURY4Aq0MFnZajDYBjVCkWfoxB2gsz8y6H1WqUBg==" + }, + { + "cmu": "bpFy7+QFL5t4pAwLWV8t+z+cupzynH+ksRblYgZIsio=", + "epk": "jxnqL3FjfO2JcUulgAsDgLzE8tkZ0LaeaUhhZgymij8=", + "ciphertext": "vEJvAmveuypfpUs3pCAaLSSYHVGLVkd0zBIdNnjP7w7kR2MGNubR0fEppsccHESb7g8Ozw==" + }, + { + "cmu": "jj5yCMEg0Bo+A2dJxFNmkjrQ5bV3yZEX9lka1vObflw=", + "epk": "LSV45xmKh8Lrw56IbKNXDPBSYdcesJk1bewuBNT65DI=", + "ciphertext": "XNx/yy60ecIDVyHKHiGzrlAQ2MSPYNblVbwAEgO60oR+hmvW/KuAdojnZjyDdFYlUO9lMA==" + }, + { + "cmu": "ETjlMxs+WS2supiDzfv9esVei7tqI0en8rGjoTZtzg4=", + "epk": "Xdj+oESwcKRDRTNALjdPKNov2r1xY63w5itVUq3sVLU=", + "ciphertext": "KfnKPsRUeXvBdf/CoWwtV0JzxO+uAvw5TA+0o0uIfBt/qU+k6OAwxmyj7zr+8SBC1zimVQ==" + }, + { + "cmu": "nV3ZCTH7NjS4wD0uJMj71o2XDCvLQM96fo5AanWBfjk=", + "epk": "4aApmUDAA9Zsti0bee9QNNRexKdOYYaCTVoTNwYFN4o=", + "ciphertext": "14nEy/eg3As0DawXuKb/b1W3HV/8wyN+0iohZ2QkdEVcdWPg3NqgG824haN6h5PcbvEiLQ==" + }, + { + "cmu": "IoxiA8KDj2op3B0394tIH7Gc5lC07yhIqgHqTp3hWlc=", + "epk": "NitE9wvrrjzmGI1BuIHBLHiiSr7qLQG9YXXx6I9AZ4E=", + "ciphertext": "RjNvd8Rpn85W6G0Od0rh0wiXPjTAsGgyIhPWsGmCmbH3Xh7osxyes7ePVkUpi5myucGEXQ==" + }, + { + "cmu": "mvDAo6QgloqEUl6ackD36l0fDwCZGaHDr3O11//YOh8=", + "epk": "/3vg/EaW6TQ1GBTaYyfjQ/OobX3UkR074GBPj2gH3jE=", + "ciphertext": "2zhSL4js/Y7u7OFsFYzO2kQxWFJ8Da5ZUYM68GqjKqjmAx2Pw3D/cYYdK87ii6Dr4lz5bw==" + }, + { + "cmu": "/bEBfsh5tHjiUoRHNnQy71s1wHNUsWNCvndRQjteWkI=", + "epk": "v8Cx5+bM9GbzILoO+dKW4vib4MK8v/Ea38Xx9sJxDWs=", + "ciphertext": "O1RfTIONEk5d+BA78Wl3uUkHOnZMwJqzgIky2qMDihrl09HL1s/VkA7KS5ywArrXAd0kfw==" + }, + { + "cmu": "E2Ft9N/jdEOfvQ4YWH9x3wCZNKj62Oxry11tF+/rJUM=", + "epk": "SXoXZfwbkkr5n6af7ggXd9O28DsasYnGnIm/xuKPHuE=", + "ciphertext": "dykcc/FmwOR6yWzjXaL6iHNrLP9sqLPyVMUmMzSRPSxjrt+Y3Qrr8et9hWFwh+T4be5Sjg==" + }, + { + "cmu": "3ngzVDLkAwGRVLWnoF4gHA2OdvSu+Inqkkkmq/tPqwA=", + "epk": "ABk28zORJvqo/+UzQbszbgGoM8Qck3JX7Dmc/n55PRM=", + "ciphertext": "oLsGS22CeLVEwOXEvcrXiiCqcZqTusWqjAtS/6JI9y5vKsWelPNWQG4LHLzotawF318T5g==" + }, + { + "cmu": "XIQYUkANZe8cUyFqlAx/9cuYFEgO10Ing3+LXLVWSm8=", + "epk": "aAcjepTYKuKNtyTVx7l8MO0sT/1xwFmPf+uzTm8SSlQ=", + "ciphertext": "aI6vNFWKf0DYWZv0TtDRRJjm2/4Qs9gXbkq9hAeHJWL39e6WWa89aFI8du02t4FE8G4ZOw==" + }, + { + "cmu": "iJ6+bjVTfywXgydPoePqQlABsoWAauRBZj1FkiRR9Ww=", + "epk": "AkN77m4GW/Rfos5q0awJ3m4gzFuV4aPnB6tKDb5JTuI=", + "ciphertext": "ZJGMnGpY0b5N8IaTkDk43g43T+kN9Kux1gKup9MvLmuxZz0ZnaEW1anzTyhLe01LFWgSkA==" + }, + { + "cmu": "RloHBtkglNUSdetI+Snjt2A2o+V7XcALEW2ZLN20gSE=", + "epk": "Rmue2KkNDVNrS4RD8na0EaLxahXCN89dqQ+cqd92OVM=", + "ciphertext": "ePrJuZifWfImwbbn0bR2jMG6W2lwOePtXmyVkp23FlgRmUEItaAURNYozxiPtZBGvuCkCg==" + }, + { + "cmu": "D93higE5xxp9T+NVpILfr6mHlg/+XJ8q+aTAgHXacQw=", + "epk": "LRz9E3+wTa6bXiWzqzMSqNBYaVNQbY0E4XNHWUMCIBU=", + "ciphertext": "MmDkzGMI/AesOVhkWs+6q5EwpfR3rzRM6dmr1deUUvgGOoftPjOo+32F6VkyBOpBGK8hCg==" + }, + { + "cmu": "C1oDieUy/3tkw+xfsKXHmRo4Xnm3UjXiIitXtKhEigw=", + "epk": "NLekWivUlWgsGJXNu8gIAtqeBuYmJLI9oljlzbOKqdI=", + "ciphertext": "66OWsiDlMN+9RvzWfxyPSTtVUvpg4B6Bli0q1UzrMwGGdSMQoxK4SP9aYqoRDg/PlALEUw==" + }, + { + "cmu": "qDFSrgUQUiBrbXo4olzpbPD94g0Jmbs+J+ifxIZ55AA=", + "epk": "NiYVYvpELEX8ESUV6jYHbPMo4C+lAlgPZCEx6USs3sI=", + "ciphertext": "Nn6uwMKAz98aE+9wAF/60ES/w1EBjFfeIZZ+wmyuXVdlqHPe6bjfonG7kt7FFTHSS64yQg==" + }, + { + "cmu": "UAvcKFB8DRJwez6RbqbOEPJEXaJqVm9yfraP6ZWqvFA=", + "epk": "48ONonhB1eBK1A8u+9ysjDijqovaGRdCT/oyPHwXUW4=", + "ciphertext": "U7Kw1CGc6sLkLoQMSJhpSNLcVzjMCxZTVYxI/SD1YbheW2qaQlTjVoCfjcyqsytseis+LA==" + }, + { + "cmu": "k+I+QKHF17AtyPTk4mLldmO67+bb9qxv/voXDOKL1VQ=", + "epk": "D9aqcucaJSSaU1rmvWni9z7EfEXGBE0vhiGvAcoMFiE=", + "ciphertext": "35rfrFdCWLqs5nxJhUdPpQVlXqafRJCwKV7/0pslVPvsxP/2aUMjBDUbqN8o1lG+fwDB/g==" + }, + { + "cmu": "3C6sLgMM/j2RpL1sJGwzYH3ZYUGrPbXfIuxS6XT3QTY=", + "epk": "gJGsKLP5S/ZXQf1S45bOMAi/DJOed8EOP/1LnJBEhB8=", + "ciphertext": "t7mo4bn+6aaD8/dmElGjU70q6zQssLK5QvkrwG8KZm2JZFOmcHpzR2wl+o3Ar8s9guEpGA==" + }, + { + "cmu": "C1UqoLZyhsHwChTPidCoEVQaS9tBukJBYhpvhJPX5Rw=", + "epk": "rPzYgRejgDi7gHDDNq+pS9a+xUiQO/bfdQ/sGWOoixE=", + "ciphertext": "ez08vteU1/Wt52uHK53rVm43ZSA8QGFTkbQ6uK6cErVyqQO8LJ7SoLwA1BL2Swevv+XYAQ==" + }, + { + "cmu": "sIwQyskjf51nKSwjXrg4aLIqyNchqUZz6bF5oCLpOSw=", + "epk": "kI0FshLaNg6TPhvAqEH6ndcelpqChDtUk7gSK4Qabmc=", + "ciphertext": "FG+00jdf+KFWUNJVREymym8iZEMU2rl14Nks5/bqO2uXsqgVMUEcJiGrfMv8psEzY70EUg==" + }, + { + "cmu": "yKlbMf3gRZyBihm5ELf2VkDFKQ74LJZEEJrXsHqtdlA=", + "epk": "o3kYBzHaK+jW5GcwjjyIwypL89LIctQeLbXKvu5PiTw=", + "ciphertext": "wMrIz0OyyZe1sDrVVb0FdwsT5aXy5oQkdmTsV4UUUauDBVBVEmrD/rwJkAPj2BO4N6/OdQ==" + }, + { + "cmu": "u794WfBW3170HVR7daniilzV2lBcFIbjipE0TTRCghU=", + "epk": "ayYt0M6B/HJLj8htqiRdghHisT3eT7f8Iicb4MR2fSY=", + "ciphertext": "AIJ5pA+uwBu8mk2/xWhe2kx7AlqWenFgepDi2iO7ehEUVywQyrfQGgwNFSZ5bX4WkBSW1g==" + }, + { + "cmu": "J4Emj6e0NdiiRodUEGnO0ry6M0rfHnhiQrnnCgyIryM=", + "epk": "LtVhkZa66+h3GH/6hi7eXPjFNGZ6uS98aD8lfVdBfN0=", + "ciphertext": "H2IpoxG2uf3bh1Vm3XAiRbjwwJ5DwXb5cAkMiEvIOLplwl7cknGzNaOhWX/ebbp1r8Ioxg==" + }, + { + "cmu": "DTmXaLyxspLSwLNNkFzj55uipyrDCDIQVQ+Jh3XFgDg=", + "epk": "4BjuLhjnyhKJI4gKl0bDKGdNo2ijDPoTvZ5VP002S18=", + "ciphertext": "X5h9H6nCjiFeBDZ2RmgSTVQK+tHBeRToBM5f20mAprbExEvWig6aG01rjnm6joO/6n4e/A==" + }, + { + "cmu": "62GKYJXHpWh9OsyOkLScjFhkGDZuTaQGgsn7TMSdjSw=", + "epk": "OTKsF6Y8z5fvwr/YhBtO5tJfFCR130kY10sZD0p1nz8=", + "ciphertext": "sTCq85kLHjl9799oQJP03qf3vQX3wpVRW+nF7sUrLFqwNEMzqN3wZwhFTQdZGPuAxJxJrg==" + }, + { + "cmu": "OZW+UhFhUn3FZpW9r6sfX/dIB6MFASW4k26T2slSaD4=", + "epk": "z02spztBgkD6uLBYpwUwlco6UMygKJkGeVfRyI0DHDA=", + "ciphertext": "7I4rsuap1ErbB/+GVJ91QrbghS4Sm+Oy/Wyhm59x98/bnDYbd/28v82/yyB2A73TV3B5lQ==" + }, + { + "cmu": "h+o+5c8DJ3eI+dgVenT+PmL/BrQ/Rv/GnpGGeW4PByc=", + "epk": "rvlakKAheHJJJ0qxtDP9cUwtbr5xUNShBHqHRLXXKeo=", + "ciphertext": "TfnpU6XIX2lMUXl8roCMywERi78/ys62LVQjGwjyC645k8UXhs6rGk7/Ch2PKz1X24O/5Q==" + }, + { + "cmu": "Hfy8XpzO3NS/pe0hpx/WFNyCvsQaJmxSPDv3WzcxjFQ=", + "epk": "mRqZ7HwzFrEWLdg1EoTg10C5yWD6T1guoa8upAs0PZE=", + "ciphertext": "nCwirDz63CvLQJGRmwGfw2wrHlePK0SxeQuQtG5/Hqn7uo1/ZtD8ORv+LSUQPlHrhvwiMQ==" + }, + { + "cmu": "pFO74tCUhobwaz7A77sP6CEEgvkSiE02HqXfhKSzkSw=", + "epk": "YPRGg/F+DLxBOxkg8h2fItRciloylqRltzM9ogWXm18=", + "ciphertext": "R+4OhDJ2CkuRrQxBNVkgHdMHq/kYWLWMCoVAwpvWxLdiAR5dRNTEYcGNLWkaZ7io8jRT/A==" + }, + { + "cmu": "2R8O4Ha5EzI1QhYUfv5s4q3bmjEAM39yCopSsiKluFM=", + "epk": "v2hRJt9tt9ecsM6EvOKAMNaLcZbJXCxmiLPuNDYFplE=", + "ciphertext": "8UesO+iIfUQk3orDMC+TU93vD0L2uBfIl/Kamqr4Bqyy48Nc37r9DXlhqYR4bU0SjRsIDQ==" + }, + { + "cmu": "dawkPQr+WphXXCi4q0rbh+q/nE1IBx4uTFdyd5l6pl0=", + "epk": "ZkrD1esepLYY4MsI/Y/OqJf3aDcj0kj2UEi2fJKz/nA=", + "ciphertext": "iABRSTeSr9Isrb+G69cxhl1RVFMgtu6YjGM0X2J4WHKGVE4f6IKHWpTmm8UGJvoOoYjHVA==" + }, + { + "cmu": "OTI3CBege4IzRnpSDWQaEPiW7NEkxgIZVkcORnHSQQI=", + "epk": "g6oLgyQydbC0bSNB63E0zK/zHLgbQgTRXQH5jOD1DLg=", + "ciphertext": "tNjFmxp6tyr7i84I8EabBQvpyARVPR07/2zcUWFwH6DT+zNQtKr8LzL1zEVNEn72LtQkbA==" + }, + { + "cmu": "uKoOZu9czZ3svqVLftFTqy05VPyk5NnnKiDGenjN9ww=", + "epk": "d8/LQzl15ZZoIEpUP+BYdAnPt0eG9pVGmtdABYBvzr4=", + "ciphertext": "ETLd32PcGnyV/l6Y5moSmGmZXpqolYTCqGHE+rxULsuMFpfdNdlEmqy3c+Yl20VqEGlcbQ==" + }, + { + "cmu": "ZLFs5I9wWFQH3CVl9TABAWHknJSjiT9wd+hqHcmbBlk=", + "epk": "n4KkfIIVuUqvU2JAkV0FBshLHiki1QViHKJjrIpGAco=", + "ciphertext": "YcNzekzvcC22kIHiBum6hsndi/yri7KeRNNM8EW1M+Moy3yCNvhmbsiKCH7W/VkO4zwoXw==" + }, + { + "cmu": "34NrzKpIKESY1UPB+8mK0tLEDyByrFk1NKnmx9BfzAA=", + "epk": "mgeD0p32Qh0vEHAxj7NN6xZeaLnTEMhvhSBhNr6t1yY=", + "ciphertext": "9fUbjSLPseUUb2RbHq7BS4BaR6rd/Mmp0gt1ZNjNuIyM8KZjv03e7Te6Z9UaoeI49aTjPQ==" + }, + { + "cmu": "2NWS6v7x+e70DS3X3gv+LmQFhatQ+UmwFZkyCDJazXI=", + "epk": "6K/DUkJARDs48KhilEMAhV74pLCIBUGDcjvEiDFn5PI=", + "ciphertext": "SRrhgGDVzNnJ3/f9zibWs8JDOJVD+8tJDDD7FKeU7xATL6T4vZtHICz1HiNb5WPka9Wa9w==" + }, + { + "cmu": "+06GXVemy7iku4T2JJTwX/rEox2Z65c28Q7c3q6rbDI=", + "epk": "txK5Xut3gqYwwykNqvMWqsHErgnV9quLjErnretIs3M=", + "ciphertext": "vasZedt2+TJPN+quF71BzeOjR1uWP9Dycbjy0kPqG9Q7SvFMAJa74a2qQZHQr6YEotlwjw==" + }, + { + "cmu": "gmE4uR1Q/JMk7GJtTyfptt3kWGoStAhGadewmnPr0GQ=", + "epk": "Xi/bEv4xMXWwUrU0Rfdkt2fymOTHPGb5AIMcKOchkUs=", + "ciphertext": "8lCzSEzR4DikRHH0YC7tDahFhGm2qkMwe4YkADrsRHm3mJPS5tJZQr47Y0DdbIYeD30yqA==" + }, + { + "cmu": "jsMTJvi7nUHoyIm4D20eAeHRvq2jqM2PFNhWzHZ193A=", + "epk": "HTiwiMj5YKZ8rM6RBvJMBtA6sqBVlG/0qyL4v8xKJjo=", + "ciphertext": "0ZwNUUwVYIkENgatb09fjYsWJ0WNqiO8R4T5O1Kp7xfFO0jspcU56KKx+MPPwwdYpBlduw==" + }, + { + "cmu": "Cao+3FoPzwfdlWd6tL8OpGbj4sWD9EoDKWqI+erxS10=", + "epk": "G+np+revUYJFB/+nevffHKRDZG39yZJxmb+bOaxlmQI=", + "ciphertext": "PsEnbcIGUHHeE8dYmdEkrFInybDaLu4OcANM6mg/rkQC4RQgMwBKClMET+rKy4tqB6duhg==" + }, + { + "cmu": "lExghMS440ZjH+Htu+m9KrjV6xGI92IwTpNVwLpx/Bc=", + "epk": "qA38B3JijpcG2AsHaTVzDjhdNSajs+OwW3yV2luhcjo=", + "ciphertext": "0EbZZI+IzO+Abc1p1bg/3ajDAXCHHzGpKrlNJG7j/O3U8xpfND6RyGZf2iqPQ/hLgbPpVg==" + }, + { + "cmu": "CDEdOZy6W55PZg5ZxK8bCVXGP1NtrKlxUxD/iE8AxBQ=", + "epk": "4wX9kPs597/DkBUi6YmFkmLUjJOX6q7ErwR1O05mjFU=", + "ciphertext": "yluwDphuv6CSxqKluou7axCIl4X7Wi1PWH/CNcc5l+FiiS14JQDZHm5t++1zLNSe3d4fLA==" + }, + { + "cmu": "UTVexm0bGtYdpzD2xIqQAsMOr3hkoJZXptrqXXll/0k=", + "epk": "pFna69weNZRdWkNMco9I4kGWcYoA+TRPClVqP5tdlpU=", + "ciphertext": "Y7oOkNUR8N0zqZCOi9m/eu33O/4Avu6D1a6asPReQEQa0MFCP3nM/lCr8+xptrIH6zVH2Q==" + }, + { + "cmu": "jEey8xVVIhrHcKfuhWsFCQ5coa3DuCxSDxb+VCNJXlk=", + "epk": "eMBk8WpIbV/72ryq3vCJdZw+Au9ypXFL5G1G5SPKd50=", + "ciphertext": "yUpP2QbhxI9EPtfL1ygIy/Ob/+RdcgTJnjpu8BEV48iRg9Kg5tRuxvW2YtWWjD18Fuop5w==" + }, + { + "cmu": "cnZHdEwpRm/oYBFkSVdPBpvHvH5odEKwprH9X3oLvgc=", + "epk": "CCWpp04DpjBI0ABjOEXhZkhx2R0Hei18UIypAsFbo7M=", + "ciphertext": "lxNhvYk+kFZV7TMNYJVIlbpqdlYbYOEbaMEx/bSnxcQufqS8tLXlti2IrqVpXXFWWucu6g==" + }, + { + "cmu": "XWdJwmAMbIdw6/QlyTeTsPS94i1no+kg6T2Sy+wYCm0=", + "epk": "s/kvjqMRyNFLQXRx3e3dU2O1RvZv5f0FHW7cx+b+EyM=", + "ciphertext": "7yfCEWLYipU9nR+YZ04bw6F3XrCaixRNhaGTMu1UhGNxSgKmRnmqQymQ3f5DzXjdbVD8Fg==" + }, + { + "cmu": "TmR1v6OIKvfRqzmvWDDzDljUPrCENernylJWWo2oOyc=", + "epk": "OtkfqWhR3ZjZJToEiHE/iiNYE7oz2FoD35065Ugc/kk=", + "ciphertext": "q0k6SQDDnYVSQgeNIDaE/hTpqF/GUnh9Zkq0UTyaYpjmU9UzTJuhlMd33jNNzK0bEWy/TA==" + }, + { + "cmu": "wiHWu5jaMCQul63PojG+hjyKuMoGzZQgjsCOA5nYfFU=", + "epk": "9A0LBiXqEaSkB78K89FLQdNdflakPgj4v4GF/jlqeO8=", + "ciphertext": "ByPKYCjv4FLvOFY1mqwe+La9FoqQF/rZBwpUmYVBwa3UBgVa6LLgXjXdNlLtIm0EO5l4fQ==" + }, + { + "cmu": "wrsE3gBRJyHZywhP0Ey60G8NUNdN7OaGrotB96VVhlw=", + "epk": "7mumggSiWEJ5JK96yQznD9Qq2XD938mAUdHu8zW1MaM=", + "ciphertext": "Ji5fokqSUEaA8TM4sotnvnTNh9M+UBiNRW+ZchSfHF0q8YpEacpKYHcSO/JbkPUJlIV7NQ==" + }, + { + "cmu": "a0EdXh8oX1oHFUjp0KdPoJGq5QVdpbFUkePB9FSu9xY=", + "epk": "L8r5TcXb6M/PiO9SKLpJJDrrhgq2VtENb9GNfUqEJ80=", + "ciphertext": "/X1X7BKVYy+4tjKDmwC+WLOQ+GPYrq1dEkfGpRD9Sp4cN0MM7+i9fuByWPljuJiYhX+tcA==" + }, + { + "cmu": "clVlR5ld+lmqIXafJBCS3tNKUyeomtxp1GxrgLuW9Dw=", + "epk": "vlKwMI2lomaGEN4hZNSrv5d50LqvMw4ncovQq17qhxo=", + "ciphertext": "FzdE+IeHDFem9QRfMo1wy3ifnidTs1oEFx/wXrRzbTTSCNS7ztquOUNWskvpBcN5vM385g==" + }, + { + "cmu": "a9KZkw0MUmTUCvjoUpau9iqMWW5raTqeliRnl4UunEU=", + "epk": "xlLn1XUvxEQRsQ7uWnsYxK/zt7yu1RxDYnwmQkpNaFQ=", + "ciphertext": "ylRhwAeS1HDRp35Qd1pd3lGi3ZJmRI61aKwyUh5IXI8Z5+SE7WLu6f8nDeMwN8JOwxJQhA==" + }, + { + "cmu": "N6Hxdz+28rmG8FOZG5N5Mpy5rooyJZNmqbwCm1M8FBs=", + "epk": "NAU83CErUMNk6byS+9udJPVSZ1UUaAGQJLq88lKWGK8=", + "ciphertext": "jsLarXaefWNIGvtefeIHIbxq2nUQA1imIyxcBHJ2WnuE6Q0+u/kJYge5WjPhaHEDp/y+1w==" + }, + { + "cmu": "XzQdF1UatgFWIxGH0o/i8s9raAuCZB3DCufaEzDjnQw=", + "epk": "MMOtKcl9zScDKOh0M/uam3N+85gAy1nukcj0aS/qOIo=", + "ciphertext": "ld6rIg+GO3bcjr/QAgx0fng/UnBIuhMyEDLcMT1gduMbp4SpIzNJ2cNJ2OGHskViJVX7mg==" + }, + { + "cmu": "cZlUmYwwIpph5vqB9KRr5UdaDyTDbDC1RZxdy7EUU2Q=", + "epk": "ZHrjPaVaNSfz6J2fVBH1GLSm2zeO9N2UxzCS6BhrkLM=", + "ciphertext": "YZwyQEOweW/cRk70LA1lfZ/HzgQr3W5+qWqZGKPD8ezKz1u5LlBRzoP3N0wnflXFMSHIEw==" + }, + { + "cmu": "CQY2rbcQZMulbYQmZiXA5A4UJY+iKfWEN4C2TUluPDU=", + "epk": "ayLxHtsBpNFqGnVmzOUPEa5xH016NtVxJUfmXcRqNe4=", + "ciphertext": "3Dv9uGtM3RK+Dsw3uhnn8usEdhggmFPQRzzMX+dlpll/6/bqs4Skpwt3qj56vIQL0wrPiA==" + }, + { + "cmu": "YGzsWOfiehKqwc2fnwuZw40LT2yc03hAjgP1t4oiI28=", + "epk": "0evF9Vfm5FWGkLOQMmIjhWiWzgaBagk6cbpPg7H1lcI=", + "ciphertext": "AmFxnk8WQpJ7ERG9XqgArI5dyVqEHmIf0rRxLAbSFNIJO7zRd21PcbOUoxkb+MavUUMDGg==" + }, + { + "cmu": "ljIPebLbcJ3i8b1G/ZLXj08oz1uob6BwiQoo9LC8khs=", + "epk": "yJDHU51y9r8GrsBXunFY7a5NeitCFDI0HjhafqVXl+o=", + "ciphertext": "TPy38I4hJMjvYSnNPGwqKYzIcDX3CsO1Rk6w8idO/kaJKUkBsuwTJdNFNUej5LPEfdvvFg==" + }, + { + "cmu": "xtKJrGYu3ldOMTjgNWcEFPve9/iyzrp/CZexd8iAWxg=", + "epk": "7CY+xXYtIg4om1KndqkESiiJsZFsqWTmPP/Ik5UESVQ=", + "ciphertext": "9htA6oO/7XtovBPxKs8gAHVjhKn4tl5TplLjbHwjlbMpzNXVI+yumlU48Dw5gBQIMY+htQ==" + } + ] + }, + { + "index": "23", + "hash": "jlGq6Y1uYeVH/jTUSXIcEg42jh1Wl+bJ1hDv6YcJQRg=", + "spends": [ + { + "nf": "+VGIkPpWfYFQTMKhYFcEUl2qwlR3QqdZrPf00FqN0bY=" + } + ], + "outputs": [ + { + "cmu": "Rwp+vpV0Iwk0XjnlWsdcZ+FXM4w3H7TPv9LYjI+NB1I=", + "epk": "4M5DcSHGOIWXsvAOZxH93pmWr3P5sF61MptbDqV17Ko=", + "ciphertext": "rxsHNmpwSe6PlW+9Tvm5vJrwheuh7nFQEMLnRWoRR5m3QS0Fx2AXA3fop2Nmsg4RSwMoXA==" + }, + { + "cmu": "p/hh/vzar2BCGVLrqlVr27X0QORL8hb5Rkzal+AdFhA=", + "epk": "iw+QQRR215Rjeia3b0zAeTTIR1QD4S2rHN7IpN4xt40=", + "ciphertext": "fQWwf5EnncM/CQ/Ec0MX6PFsoMlHEYadjVJm093NM0zEboMzs0d6uitX8UOD9C3oU9VRJw==" + }, + { + "cmu": "CGM4A8b9gUuPPscNqyzznXoxRvti4vjOfHsgK+N5ljA=", + "epk": "l19oWAFoNHUTBtGtNSUw64ZPhMGhQXQADTa8H4uhuD8=", + "ciphertext": "Pe+ufDyVekJ5YYXUdGgU4HRmxUcN5oGJyRbKxlunVXlcso2F5xrOMnLBEWsbaJIOpPP7kw==" + }, + { + "cmu": "a1RNuPl4lSS38izscJWOd/u3Jr6cD5Qg2i23LQq+50w=", + "epk": "EbgH8dAVyPohNUE3J3iHoWa+lK/j2znqtnoZ9hEsVjw=", + "ciphertext": "O86PFauAvvKFBTkqpcfvhP2JC5Qv4x+rOvUVmqAB9hdCIIP3O0WGJ9hcJS9TO/N518Gh7Q==" + }, + { + "cmu": "SFSc8BuN4oawFnoakri6CdM28Q56lwmM8n7qW762QTo=", + "epk": "gwUFqNlDWxuxrPLdGERw9FC2qGBm1uS0Udx4YlezULM=", + "ciphertext": "MpADoPR9xiO/7eBw/rpuoOzTZ6TyReG45Nk7KfEL+vPWhGL18pKUt8cYkY8ITad5iYdgMQ==" + }, + { + "cmu": "eOUkIF2oB+qo1UnmLdcUOzq00MeEFCpBVQZum0cWVE4=", + "epk": "Y9YVwcuiXNUeDNjthRyxxl6VbRwr1kNsamiPpi6v9dQ=", + "ciphertext": "v2k69qhc0qpUG5hsUthUh9jf6GSy7vMlcy7bgxJkOW3gOzMpai0h06eh/LOnmHlzUDrJ8w==" + }, + { + "cmu": "n4APGfXnpCEuEQUDxAFxWBbOERh2v/1H4BA7DeZ4yyM=", + "epk": "5EsouAJLHDTg/ZBDLqQmTM51AM2o4vtUofv4H4OkMKM=", + "ciphertext": "QHMIr9VEbgKgO5H5uVHdGiDIpftQ5DVa+RdSdsgoPEYtpUo00WEjeC72Ii40LLkMJ3DKag==" + }, + { + "cmu": "A9Ezim2BSPSE/sXbCf41/SRsb46wv8gBKjFoYU/mLQs=", + "epk": "wEGti6nWdfkotBRFx8WOQc5tlFDhypEEA+a2uWyscCc=", + "ciphertext": "i+M8A5Ega4nRsAOlE/VcXmFtE1uO8wWm9Tt99jCKVfTRy5r2W8aE4qcXsqX67eILH3sW4Q==" + }, + { + "cmu": "FH7hc+1f3Vdmy3svBBblv0hGUwNEutFU+eFpQDmGKWc=", + "epk": "Vg/SoXksy6nbBhhlMIMweVcHPVQhrujD9e2I3sNh/RI=", + "ciphertext": "Cs6tI7acn3r2x7zai0QtVcSvBflzpXkFlv8NWZK2EVymO1A+oE21ctqndqWJjdOG5r5L2A==" + }, + { + "cmu": "vwCnK3fXXWLMVynBID3LNKiFm+LD3nOc3+DXfymGNkY=", + "epk": "WkqbOqqwkw9qARC57tFrv/MR/d+BKL+6qP0ymrgO+o0=", + "ciphertext": "MHSjGDWDB+rchYBWECp28aLR6tGkAu6abzOFqUEmhQMNNFlScGBSSGEqeSsvKp9nhEOwrg==" + }, + { + "cmu": "mSvHwRgFYreRPVlmejSL2rQmaiww8kebjTzbnZG/Kw4=", + "epk": "oI9MyA2KQtGHrGDdMtfyjr3dAUvlI/9Il3oTdcWbRco=", + "ciphertext": "tx6Mi41tOm++yrY5gmAgscuV7NaOryaRU4o8umYRoen30YThiTFeUndcsHlqDFu1Y9fO0Q==" + }, + { + "cmu": "R/CwgELsLlGrKZ+qHakQHzAWOYKgxsBD09jfyRQA5SY=", + "epk": "pbOZxk5A3qIITUq3CYotg4g/y+AOdcvPOmQF0MZFEuo=", + "ciphertext": "7TyidWbyviqsboxVLzE/sqUyY/FWfLjSJWSErlPdal1QbDMKwnWrd232/cwIccUgcWp2Tg==" + }, + { + "cmu": "Izfbqqi/LjOGW6SJPn/P0/8pzguwTdA0wQauz7DnbCQ=", + "epk": "ibQEp8VUUVJWOphCl0zoTpHSzWtC97oGAfyEqzDds2c=", + "ciphertext": "PfGFH0TzyRsk4q00hPzmQHrU8y1WGL2FkAxQGsJv/A+DfLMK02SqwLLig38Vsxo21uRYgA==" + }, + { + "cmu": "sGLcSXF1ojmivjwcJ6F86EmEfivn2VwzyXwcF71mbQ8=", + "epk": "lAfJc3/p3vd76Y2vuNVtGX5wlnt8p3cJAe9tRwobEgo=", + "ciphertext": "6i6jWCCIfuEzywVJTPBgkVrwLMah9r7G9oobJq7nHTMg2V+o4w92zEbutM/DAqnJ5VXz8w==" + }, + { + "cmu": "zEZ7iIA59OWCL+zbyZ4+g7LbcCt9GT/a09rO19BWewo=", + "epk": "UcVXaIbeWEK2fBpQl4XplkG9VH2Kj+BLsM3HLau5pWQ=", + "ciphertext": "b1FljRdMXEB/4J8w33xSJOCS/SVH6x6r7xwhkmrZxFIt6+E79xv0eQz73lQg1kipJDK+kg==" + }, + { + "cmu": "c2QIp2zqA059uVScAujmiVNOKJJQHRJFHmRJ+EGHAQo=", + "epk": "paNRBLpToIzg3V9n00nXq/NCDcs1FYB9IbVugvpjA9g=", + "ciphertext": "wKgh0waCJvv+b9SrsX/iE/F6i1D6rZjQVYsa+TcOWl6pNSgTI/K4RisfyW45M97QDrS8mQ==" + }, + { + "cmu": "/Y4fdEezO09fTFD7wNlBMvy6Jd6s6ggxsfpqPf7ueWQ=", + "epk": "8/Dk6raNGuUU35Qi0v7s2Cw3Qlft9KfOSAKeOf5KYsg=", + "ciphertext": "Yxp/euMK15+r6p47TREPQgypXh8dWr4+viZBIuCBGPQz5Ib6jFM8HHO/VFOWftSwezsYHg==" + }, + { + "cmu": "uKDeBIeT/WX1ywLGU3eJKi5OB/5tAVasr2MOxIierEw=", + "epk": "61olMBO976jW61VECMPXaUZEJD3yqASsDt4cIwUBLuk=", + "ciphertext": "D+CYPF2nWxBmS5wUtpaNl66Z91miGoK0VGYykWkvfubh4vlqH/7ULglYPn2prDpNiQwbWw==" + }, + { + "cmu": "6vOwleQC7t6WbcWAPI2YaZOtfpY5GGpde6L08Iwl6A8=", + "epk": "YWBDKcCPKT35Hy0YucBL8xQzyPd1lpv4GD5xbwnViRo=", + "ciphertext": "/zpbSNBPtg6i2opJMjxXNOrayYgW/jhiZ2kqtH/sBZnuHegVZO75M8GATkXj4eThzYcm+g==" + }, + { + "cmu": "Hc+YHX5seIcyN6qjTBlYC+c8ycFwJcMbHgtf7d2Nmhw=", + "epk": "cyCvtjzJ0wJKeF0hfSCuAGplD+G7bTFR3bDSqvKeltA=", + "ciphertext": "IzGM3ivgKx0f1IzLTq2FEwItOit6ic3LSBVfhbrgzLmHMwYbwef2fFE+5k6L72v70XP/pA==" + }, + { + "cmu": "+OvF2/z6EAy3qaeWgjR7LFC09awkUAJMq0I1F0FJgBk=", + "epk": "IS+Do5pUWUxFfzTFijs4pCCw87f2ft5FIdagCuY8qco=", + "ciphertext": "Im0PrQOkZstCd0VeEdISkz912jkv52w7cuqnCGCOkOBw0hpAHT9heJFgP9iZXGRhuLR9fg==" + }, + { + "cmu": "2f0lJa8DQFQitJr12qKOYfrABthsIyhxpoU+kvNkrCE=", + "epk": "a6VtN3TrReROMelP4+ZHbnsZE58h8XThl7evPMtepjg=", + "ciphertext": "fgJ/sOmauw+1LeHQMNVNOUkUNsUedOSIcT3eQdv7+qNjtuMtMAlYpELXwaCX8LCZJysHUw==" + }, + { + "cmu": "OU1r48+g1EoDI8xjuM6plIPCaG3uCCPz0Oxx/Vxn0Rc=", + "epk": "o3BCcDWDDsI4WfFAwlLRgGkzESYmSiby5c0Gpk6WkZE=", + "ciphertext": "bXCRSmawQHR2n/63x+WKT02GXMg/TRa0J+mk38g0uxUDCgjeLQQk7CAi/wURXmtZl2lZWg==" + }, + { + "cmu": "2QE0I8J+/jEyM8zEqbXdciGbLHIU28qY6GV0GasxLCA=", + "epk": "dqImy/idqOxilF8Hhzmz3Q7AnokesfGPsaf01qmmB4A=", + "ciphertext": "Myfyd07KmeVlZfAFdopqK5G5bDGB9zqlWhew6OdnUovFzOL7qQffHeTiL6XWzSFZueuzJg==" + }, + { + "cmu": "kEq4xGxq697aqtyd/V7WAszFQtzBBpLFMsdAA2h52yo=", + "epk": "WOExZcnItP694Ul1O5MrdNmBzrv7tkrSRO/wtTNUp5w=", + "ciphertext": "D5DKhTH9BwsFoNB6K7+TTCV5PcXlvBc+LlUVd+6jhBFJak/UcEjc09Hw11Oen4bJlZwbXw==" + }, + { + "cmu": "ziRBLNYbH+HhxxdRMy+TtOSHsOJ1vF0dCPt74A2wmRo=", + "epk": "Xj5fwqENsJTHssPVc6IFwLsgX8W4949g0guzeY6/SYg=", + "ciphertext": "8qhA8QOABxFpgIgt8ZewPavnzU8poZC0E3bETwDdHqv10hgMiOkgzNSWBY6zErxD+GU3uA==" + }, + { + "cmu": "nf96rBk/mnRWbIJ1yzKHNBI/dqbTwFy8xotGOFdm1nI=", + "epk": "0vbTg7E1Z3/b4y+1no5AvSPf42E2TrR/fCJhI9Lu+A8=", + "ciphertext": "cAnqLkryA0CFfCGx2Z8oi7lKADdwJm6D6FqguJ1UmL6XaoQJbYQymjrBvHtI5kyvK4n8wg==" + }, + { + "cmu": "75CbHRhgmwsRyT4SlRW2KsVjYnCiL8IAafkRddk6fhw=", + "epk": "yyn4fNNRsT5GrXbnJPqLdbQxUhqMmnKoGIr3MAKVhqI=", + "ciphertext": "HgXbCTC4UToCSuhlaFT9t24iyoXX9aDRS2qV63f78PcJOrjO45QTb1zLyBo3gKDlDjCyPA==" + }, + { + "cmu": "vi7eCEF5OddMRdEZ6FnYOYUX8iy4+Pyh/LEdZX8LfiM=", + "epk": "j7pEFv6hfW9TCoIPkvtjl5+Qd0O+pUax0INKsvJtRS4=", + "ciphertext": "mdoyLmAuFcuquaGXVLiQIoy2T9Kwvc1FaaOrY7YtmdqoGBSHy0dd9QymFJUFyfpN3bCtyQ==" + }, + { + "cmu": "iRfTxXfN4bzAv+Wh7ycF2Erja3PpbJ/kQ8A239WejAU=", + "epk": "cab/E6qR9wXDE160AGBJ55f0TKVGaQ/U5vd5EqkFq2k=", + "ciphertext": "RnuJIdZPehDoEh7RngSiuFBWiludqQMbGdwqfljklKCqrG9sWFRaa+5bWxYIpKWG5ttV5w==" + }, + { + "cmu": "ulQFFZhJgL2jNAO8yl4gTEOcDMqCnUSJoGCIbeCxtzA=", + "epk": "nI5W8FbG2xLF63/LKL3F2vQ5ThvZZPmq0H2GA+e84wE=", + "ciphertext": "3/2PZ+40ppOOoYembCgWCYQ+DHsV2o9uEq0XBbS2E5sQHq4XnEoblQsWWnBT6axhPZOT/g==" + }, + { + "cmu": "ZbmB50Hb2AdKZxDNlsGva2Ru9PHb6flOLO+cPMZwViw=", + "epk": "+UcAApXzGQ+mSusP3ifVDUbUr2vZ+2FXdtVArR1UVL0=", + "ciphertext": "a5bF041tp9xSebXR3NYCYCYdmI0eiU8oIoP4JhmAEakMwNTQ2WBg66qK9YcyhZgZ7HCkMQ==" + }, + { + "cmu": "0wxFo8CYHSoCKb/zQ85y9GgFWgCk7AN6JQOGmsbIEyA=", + "epk": "G0U2FS/gB+E0bitDYKwrsZguCC+AMHME4YCNMYrOGxo=", + "ciphertext": "Li0HFdx6KsK+vijeVW6vyARJ5PrtRK314xRHNTV0xvOpKHEDuEzMYbPog+1qsfs1ijr2+Q==" + }, + { + "cmu": "cIBjEGnqOimiCrrHz9xkpq+pR8HJEWqkrcFJNZxwK2M=", + "epk": "N1owLw2t35Pm0Jd2AtmqshUibJ30hYdZbp4pukcgYJo=", + "ciphertext": "au/c3byaE9DtRfNBVXKMPtYxDhuvDRr9NHEG8docbkfCMG6wEP65yaBxkteXnzJCbHl/8A==" + }, + { + "cmu": "v9U6k+NeOtvtnmAsgzH1AElgo6V+THBv11GevgWFmmA=", + "epk": "M+e8nhaf1KrJu2ucYukkwsMH1bm2fMEslmFU0RM3Hwc=", + "ciphertext": "z2ZUH9XW1r6iZRcY5ksORLBmKxLQ9gjOL5K1OpAN3prWW9ILhjJ2+XRbIm4G3k2S7PZ17A==" + }, + { + "cmu": "Z2/cdkKU3jwY26qbSfq8FXvWuHg+gFCOlm5U1TmL0A4=", + "epk": "61AL2FFHesEDs5KwKK6gBPFwo/F9dsOiQyG0jDrRdkc=", + "ciphertext": "xW+LYLrCiV1Unnd0cNCSbT46oRtzk2a/CbLiDgoKl4ffkM1Bn+Nj8HLwQXg1Caos9FT4dg==" + }, + { + "cmu": "u4K61m5dgViJV+oamjC+IE6cZzW8hOZPS8uX5uAF8Fg=", + "epk": "nK+BI4DEc15diOS1iIuhEM/Hv7o9KNMVacdizofcNQs=", + "ciphertext": "O7H9pdwIr6QsPZW0gFlFsYUy3BUF0MUFb8hgLIM1r7oAfh4TAu2OlKOsExxo6/B+82Z+KQ==" + }, + { + "cmu": "mS6juBRHc1xXDPh7L7RT5Z0YLcHDApKoJgHH05iaTFU=", + "epk": "8UUEc8B4el/5N+brMQz5ptxT9u1QZABn9+oF319ca+g=", + "ciphertext": "xwj5AO/PiSrx3sFYQVMKgjQmhSGOU151m8pjn3TB+s5CFAGNsC3EK4AyGXNC8ArrtOUEqQ==" + }, + { + "cmu": "/fZ0n2VykSgp56bhIf8C4MDRKOVOf+Gl+7eM2aU/CmE=", + "epk": "E1ceqhtlzVpfDDp7itF42u3C3ydGEuXEGvSVl/Ui4UU=", + "ciphertext": "FgQn9BbCxd6ulZIwzWE0pP1f0XXrRkqHW55ETLe5S7BTqfmBtFcgbBfhq8fH1Uk+OMUK/g==" + }, + { + "cmu": "2Z8ERsvwqHQgSxzvYZakKXdh7/UefmxfF3lDLJALd14=", + "epk": "eyBhC2zlSqEKUrbjNVncm07ppferwZCvczzoiAggj6M=", + "ciphertext": "h5+IeaBHbXqG9iKsxNWYscHNUj/qT7makB9alw99WApbOv8Mte9rnK3zG9B/OeKr2xiwYQ==" + }, + { + "cmu": "LRtqZHd2wXZKhwF2814/f4k0xr0FC6QFTjT8kVdRVUM=", + "epk": "E1/41I5+32xooYCMmulzzDHQ8YVI/w3yWi6cEWQ7hQs=", + "ciphertext": "pHZh4ZKLnWny9W1zfdzop5eELviApg0usYqGtVxWeqEoMZPVxgUULFKxrw3h4dQ/DC5zNw==" + }, + { + "cmu": "hOWAPnNgLE6IYRECMhOzuKg7U5r/IB6dHlxvlSrQ0Ak=", + "epk": "i669UC64Hs7wmUQ1DVHGh05E4tnERnm/DViSR0iXih0=", + "ciphertext": "SEpACiLz8iqPRKGzi4L29IA0AOVtk1ZN/BsmQ2imzp+LUPE6Xwf/ndfbLtOzoBKaEDZfDA==" + }, + { + "cmu": "s4RqzHYXo/4ZYw+mPBBi4E5csLFlZlD1kQCgXpUIO1A=", + "epk": "SoAILOo4lEw5vo81ns4WMLqKleKSKojrEGsRTR77Kdw=", + "ciphertext": "buF2XkoGeuxaJUQz4jmmn0sVBuY8rW6hltvKbm8fgGKJs/THKvQMgpfPiX7ASs48C5QEpQ==" + }, + { + "cmu": "6xwtLIPbVK67cUbXlTNoGgjk4L9zmofpbJK0ydlpDiw=", + "epk": "5IEZqcn8faI+OWh5/T+dWuSlZPxRb9AHEu2JMsjKgJU=", + "ciphertext": "IuBUf7xBckI6V9o0wqWbg5h/fEOGjCvKEVa6OKJOsK32KlGrS8wXt352L1+cyWTENWqJow==" + }, + { + "cmu": "xK2twfM+3/RKlqU4j1i/Q7pyAsrVsyPfhhuGw/5vbmU=", + "epk": "eqml9axEF8D1dahrGmNC2F10EioM/PP+6ZsLdB0epg0=", + "ciphertext": "GljuPHm9XEM/6eluE2wjsTWeth3rWpxmm/iet75g+Z1EKfV+yVBP6Yg5dbQjdSEsJ7haHQ==" + }, + { + "cmu": "ORJcRTnac6ahPXFRDHNZKdmFEU5BRcCC59/41fZFKk4=", + "epk": "7U6JHCRYBzpECxTI8nnvnoit9/ENYJbJxBFqjTqnAcA=", + "ciphertext": "byPTnRDWNkPpuNuNkRyF9Kc8GyIO0JTpZlxZ396jI6Fi2HuklEbBmbLp+cRdRzrSM6rb7Q==" + }, + { + "cmu": "aKimAIuaUnwWKe7RbCmGm+Dg44BKikCW7C7SNEOq+yI=", + "epk": "Usa/Etj+zhlJEh85/Zsql95P+Atdn1vIyZzMxxc73as=", + "ciphertext": "EOT+3rWyGiqKiv4gHMkRYclR3Z+mM0+wy9noOeXQbAfNKPQl6yc71+Bf6TGS9S/zj3QIPw==" + }, + { + "cmu": "zIqaXHFxcARR+QpOM8Pd3tzuaEumEC2dtefgDSy0JT0=", + "epk": "E6F/c4QaMXANnaaIQMqHiikbj9uiuhD+kuCEtUE5Z7U=", + "ciphertext": "vHq4MfJmBkslkphQvyuAkcHAn1OePVHwIJ/cD5jhVR7cFlgXGnJEjvUuK3Xae8eXCLhQ4w==" + }, + { + "cmu": "R3HawtrqzQeJfSfnRJKokONol99gBxdgf08JFt5RxUA=", + "epk": "9tqHrbosLuFLwmYwVMJ/KXlUvOH5J6th1K2Dkw57NE4=", + "ciphertext": "kTibADPs78D8WxjzULTiScTD2PwZaTTcjoHsZVmpPN8fUI1aUp9St/18/pZfis53sbDlfg==" + }, + { + "cmu": "ID2bMh0BG8/yXJQAkuMStVJt4Sl5J6b7V/POfimHKFg=", + "epk": "LeAm+0tYsqbNYoQgvXQtYpCpzCdxgOnMKDu01ehHs44=", + "ciphertext": "ektusOPlPO6BFjC17rlV16elCNcv5c3ONbmT6SsxwGPB+QbdctmZbddVOvrWr05zCxYHiA==" + }, + { + "cmu": "B7Vm7J/sCASQs519TSEckrPV2fMo7zl2WtvMvRkYHmM=", + "epk": "uIin4gc1DQSseon90RcbjodwUBzYItMDX0uJdbG2zgM=", + "ciphertext": "R63pZAj9fdQsHaWof9HnNsrKzBnT+AgXPCQILiviwwH3t35iEjnr+Nruo8Y/mBwMRvY9Hg==" + }, + { + "cmu": "AiOqPKr667bvmppla4c0nwjddcT681StZvf+UuxpsVQ=", + "epk": "2eQnpH0dtdRvX5eRXnfxj/2zl1ZTqRPYftcWK+IR/ts=", + "ciphertext": "AnpZeswMj6w84GkhhNYtslMTLXY7cs/77BhRwLkwLglxOQkKmDoXz4ZLnPzusMDq1rNA9A==" + }, + { + "cmu": "lnIdEc0zrl6x/tfmkD0Iw6RU15t2O22616vWwpzdVko=", + "epk": "XBU/0v8kQOs+hE4jnHZzK70v42fb3Wao2e2Q+5/fmqU=", + "ciphertext": "XRrMRhtLEs1F4fEnHkXFlqbXGqZq9PwOcJPOMA/raK3HRwSvXL2aKDW8zy83m7AbwtFlgQ==" + }, + { + "cmu": "ngJTnmtffkss3x6yFZRxqLqPe9X99xCT5XCYS7PwIRM=", + "epk": "YOXWfKUMokEAQZOtMiF9S8J/boQWbefFVWzrajJ4sW8=", + "ciphertext": "Dk0JQjiJo5dcMfVumzg5ZU9d2aLqzaupolvclxC3aDFkc8k6VkqlEEVLbjrDNJpkLj6SCQ==" + }, + { + "cmu": "mkxgZFjwqdYPEudtdBvKovcAasoV3V4PwegvIeSX+iQ=", + "epk": "VBzlumsoM8EstR8rZAUCYZrfAL+adTApBljvoia/rJA=", + "ciphertext": "InN2nhqMtle3+cQGqEHfNLoJLAiQcIHaZ+zA9z2CUK06fpWiist3sh+29YwDP1W0ISeAEg==" + }, + { + "cmu": "L+6nane3UbP25oEY8ciu6LbEQvsgOGUW303xSHmWs3I=", + "epk": "V+1chEpFdvj7NWY0lDTnKEdL96AOv6/k3spci0QWYTQ=", + "ciphertext": "sVxYyl0FO6hL0xCXnmiuZgj1tt6NuPtP2dHgqyTkSDIMSOz7EDGKYheBoU2OhjFC4NdXXw==" + }, + { + "cmu": "T02CHUgCBU/tDRTA2AcsUfM8UjSPQeWYq8Chm+NPTUE=", + "epk": "Lwqk4sVN0+Clp66tW2W+C66p0Lm8PcHXkdEuyaRLols=", + "ciphertext": "w5nel+o5+JPqHqzZDwF6qn6Vie6ngodbFnBzdiElb8xUYWvC6pLih3EmIyvglPjwr0R6iA==" + }, + { + "cmu": "DIs0DLq/wZXIrfNt/4AOm79z+L6/pz8gzP5lQz2hnEk=", + "epk": "ywe5ANxuVL05ks7WJPE5Rs51nL9zhkP9tnvv1iWhYJE=", + "ciphertext": "uwNfGgRM4ZnPMIbxhXFZm++wnopVepSOH5Ra9dYnXFJAr30BgA5Hvfg0G47QvEeDY2O3Fw==" + }, + { + "cmu": "DADKgKcltl83SqFaDZN2DCkyXb0T88SK1big2PdaznE=", + "epk": "gBqcSFB2nwx253rTuLNJtctQ0/0tuZJFdMzy9EKmTV4=", + "ciphertext": "EXjkENjBpOfJ22BW15H28mPf5wOCZaV3flR7EukbLwcT1qImwXJX1sZ94CxoPC6Mzq5M/g==" + }, + { + "cmu": "jtzuFMib5ATzhaah5dcm/8JgTkkoXsqN8u9eHY1OPyo=", + "epk": "VS7OrkqxcswZ/cg7dbfwChanjCuF48UdRHfeaarxj2I=", + "ciphertext": "Xue6CbT5xUMjqqegWE9DS9ubs4FPOf8/197QE4RRcL1rNZQcLnASSe09svDx8a9Icc0p1Q==" + }, + { + "cmu": "NbyzOy/hhaHR7SFRZ4qIlBYtA84Vsljs6BgMaP/fMiY=", + "epk": "netDwUeGfdumUFD5cnMEw1d5/KRNGXyFoZTCeN4+Hk4=", + "ciphertext": "oDEXudXbHHTUYi3H/QvCB2lSdLO7C4D0kP5Jy8UI/7Znq//e2Q84zBRbQpgJRguSzLeA5A==" + }, + { + "cmu": "68uZ73Dbqj4lHLOHqdLk3WHB2eL7/3gLgPYhTAZELCo=", + "epk": "GRc4vX46C/10Y9U071kn2TV6HtCXQrISdYc8tC/1xc0=", + "ciphertext": "6NnDunJGXpWEn7tAklWq4/XrPGnm9hrlnYjtN4b4O3NU8l7osIKmH+6pkdRTp1FO1KpMog==" + }, + { + "cmu": "cZo94xF5AHb7+09PjQmxqwDecJtLAfwJI2qwWNLGuVY=", + "epk": "ZFhZTD3GUI4qN6cf+QGc0CxjDbemdIefL+CKQCracQ0=", + "ciphertext": "1/UE6w8kXg6x7ITJggyDVEdF22O4TzCCbdcEQFCcRHkBWV22/y03nZYp1QYTMEQq3ii9Tw==" + }, + { + "cmu": "edVb5sSDS3qWMmL9Y8R6KqqS0uqKFrOTKuG4CCJQdzI=", + "epk": "ogeFaJImW0JyFL1aF/qyTERimgkP93PPWWV1AL6v1O4=", + "ciphertext": "MhcpsPPAPomAIOxrhUdqmGQDkwDFbCwMLyI1rph9Yzi4M3H4nTZk1gC6h18hDhHsQ5vkYA==" + }, + { + "cmu": "O6INudqu8DhOh3rDenuOgHJRHZGnj1mX7YHjB3geU1w=", + "epk": "X7+Ivn4OGJ/EpwplHswlxuQ7n6Zyhd4J4LZs2g4PoVA=", + "ciphertext": "4simGojp9x+UDMRi0XZLYFCNiRaGJb37N+jI+ayGQGFeB3qSebt2U/HednT8nPuoRtyRpQ==" + }, + { + "cmu": "3ioOFpWqY7R7aVAMiLrzZBD8ip045mNaJFCBUS5HcFQ=", + "epk": "nYDAnDOeS57UVbveFmEso5RA+ZUV/CrPVmEG0Qnw51g=", + "ciphertext": "kMjJreO+UeJAC732MYMBrssCU2ZzflCmsVEohZJsWanTXTnEXpXzA6hYuBXX/ACbMKhlaA==" + }, + { + "cmu": "ntYgmX01g9oySMeVIfieY5HqFHNHQyA2WT6wkQEuix8=", + "epk": "Chvb4v/XtTiYUC8KU4vvdKFdD9mOxbCefrtKeMdBDAw=", + "ciphertext": "RcrvyfxHa/8sxDwxdzHVan6n+WbMahYF2g3PBMtbwmSq2Du1GbxXvuaKCDmQ9h9nmXEr4Q==" + }, + { + "cmu": "HDby4FhBb/JTMGjtOxKfmpDNLwiW35iLGfGzTzx3h0I=", + "epk": "7DxBX5smLBko0tf8FPmdkhZmU9J/Nco8UaREkAmipJw=", + "ciphertext": "btjKu75F1kSKPpFoWTSkg1O5lCGQ3bGWbdrYZkh5rPaCH4cWbmkNv/L4xCGGm7Iys1L/nA==" + }, + { + "cmu": "TKz5Zk15vegJqBEH3R06XlBF4o7XiVX/UaNRKo0M7WA=", + "epk": "MBkfVDao+5Fq9KTkK8OagibN2j4kRZRXB6wlP4VqIC4=", + "ciphertext": "ouBWGBo0Rk0W2Zb2ollVOjnvfFUO1rJwPE2+XVg20szLFVwAUpwByjDZUyGNRbPUv2t68A==" + }, + { + "cmu": "3+dJS1W5z/Wpvw0z81rAlF/w9Afc7XMUwIsDWvAdIBU=", + "epk": "TBm5t1ufiyoYHx6uul+/3K/QgROINZijBvZNe1ofoAA=", + "ciphertext": "NcCUFczt+lzuyQY9OhmsVxrSOYu/4oh84bNm/aBO+dk//VB/2h11XhjvRy1zswWXElNaXw==" + }, + { + "cmu": "VI37Aw6I+ZFRc1JSfVOIqptrdP73tfMOCNclZ4Gg6y8=", + "epk": "9W5g+hPNVIn++1SeNOnTUcXOLyMYzO3bKojwp0ghQa4=", + "ciphertext": "o4AFlq3UA5a/JnXQRMJXFiavjCKBWiNY4RawgRPBjLXwG1KHI4PXR4RvpWgFNspe5/hbAw==" + }, + { + "cmu": "sde6JOyi8OQrubK2JallcFqjBZ0gEyEUo6SxCr0Wrjw=", + "epk": "aK0+PHT7cwM207A60Cmz5qh6bcmXEVvF4V72TV8b5mU=", + "ciphertext": "+/VjzzMAAPnN6O93gem+JUBuhhXiWkg44aCYmzMcITxxVwUkuXe73QDbbxk2w8Z7vm/EZQ==" + }, + { + "cmu": "/9xOumOzwQHNzcDMpxt5O0JjAxmkGHMdRImdez3zK2c=", + "epk": "cV7q7oytrGGchs4gU3w7f55fDZzSjhTM+j3Fbykcgaw=", + "ciphertext": "xU+Xqze4niLiAjnHrza1lBkDzNVH8SdHcj0EUIx6aT6IGRenYvXwf/od61h6ePLJg8o1oA==" + }, + { + "cmu": "yLpKecC8jw0JkbQKn2zcsiI885EnoKaxGA6EITY10XE=", + "epk": "gNjNPih8MJOhdc8dLpwKtBGs5i1XNl2dZUXkOaAvXK8=", + "ciphertext": "9mGqaArhN+jlbqI8V+CMJ7Jgz3YyQf0UjL8LCRi6QPDK52/22YqV02YdMxR8RXknkJBfjQ==" + }, + { + "cmu": "idV7QxIxdJ7IkzQMg4MUzzqal6MTERxvtjy/HNLDZjA=", + "epk": "DKfqFqvgncIqlbLYjbxXdZ3qlJw0zpOaIdwmxLLLRCo=", + "ciphertext": "SgGnNWWOR/Fy9p9qP2ECwBrZML4VLMW0KdI+5WI6YZSdFog5nnjWNBjL69nVuMLqHMUZAQ==" + }, + { + "cmu": "fLs/x5NPM6+XZPcWCaU+458UsIuwp2BKkfR2aEM76Ww=", + "epk": "c5lgOF/qr5SI7x6qIcYo5X50UzU92WLVPrBP1sJ9BwU=", + "ciphertext": "T4y1aBsnxMTaXuB+qyVNUeAnpySYcbXt3QhDjAC9D5wYyYoBqiwfVqwiDWRY+/PBTU2/ag==" + }, + { + "cmu": "/0j3WUbXCS8vuMqZARJdFcUyVbmMsyEsF6NBFLNZuz4=", + "epk": "CtaR2iyr2ePELKfGIZFJdX+zY2TOwh0HVjOmGMcM4U0=", + "ciphertext": "WoTuMArTCJghgGHhSZK0xzbxR+MDayCkzVA+Pie4WpbExWiaa/Y7gBhyNBWtZ3PQS86xjA==" + } + ] + }, + { + "index": "24", + "hash": "5ZsEEPDQH3DRxwNWXc2mFaVoW7MpsqgqnDYaCZdh2z8=", + "spends": [ + { + "nf": "pQAnO4t7dPZhagIPEI+AQEgZrCZmn1tZNA52uJoJVpo=" + } + ], + "outputs": [ + { + "cmu": "CSNY6dzX7rHrAv4OoSnk3n7Dm4Zwus0HmUJcdL30yTk=", + "epk": "liKcoBFwiUxdRL2IatzygDEHPSvC3fe5X9M/q2xEmao=", + "ciphertext": "v+FqqwqrOtMWWSsMDC2+D28FFL7SMdRbJT1ymyLtsZOcwp1APku3BD1NN/RDYAhQxiQZNQ==" + }, + { + "cmu": "MpLsZiVzmYkeTgvClma45NR5Mg57H1GT5KiPM73kUjg=", + "epk": "7RNNjRLW4ystY4k2Ad0hX++Z8Pxu+B5hY04/HJj9NQA=", + "ciphertext": "olcy5tR5Ws+1Izl7QGQE+zWrlhqa1SlBLNmCFEfcpXtW4kDe8iUhJIoHvS8Eo6Ad82UveA==" + }, + { + "cmu": "9raXG5Dw/Msnvqxj9bJFtkdAM7sYY7s38nKjV94jTw0=", + "epk": "VIqw95VAM1LgYSR80NIBpsNRtVL40FmIcVym7MQOA6I=", + "ciphertext": "zCxQTICK8SnijahmvpaaxZLp+WwgDByqstJadgfyxdFl4KyXC2z00qNBADzb53j+u8UseA==" + }, + { + "cmu": "9dWciM6k1pcw6ynGYao3oYj2oEKfZh6EIgm8a6jcuCc=", + "epk": "2QuhkHUXOyHvgWuj768sjYtg9JHTEjhbzMUx0oR8R+U=", + "ciphertext": "OdplyIQwdFkByeU6SXp61P1/+8qyiwoxyiiOXs13w0wnE6Qwy22qALsBFBANaz39XejTgg==" + }, + { + "cmu": "ToZKZDETxvNnO4VhIIGDlUWLCetQVkTTZg01k7UT0gs=", + "epk": "DBParoIEqo1/hV/vx4qk2Gir7FpjDL4PwNlGEg+//5U=", + "ciphertext": "nUcLj+mf3rO/Iic+hsMuexDz41y2RZFzwwkip9aJJjNnR7Bh1a8SHc9nF+TZpwRGpfjbyA==" + }, + { + "cmu": "BkJDnPdidjJyppuGth6030cnyYjDA2hNhRd4tJ6KjS8=", + "epk": "fZX3f6TAtOnQ3X0ZdqYyP3lRfo8LQUuCPZqBvAZeOtQ=", + "ciphertext": "02ksfsVHm3pu1VGhaGBMOlwK3V220xZKIDs7cM0XhTWdQ2gVViUQmYqyXvHLNsMsMAGKkQ==" + }, + { + "cmu": "LSyeXvvsesK4ZwmN4xF6k5DRVUXUVYuirVA9hP7fTVs=", + "epk": "Jk5uyN1Rp2bN0aNGd+3CEPFZK/iRIBZq2NiFv/Y3qT8=", + "ciphertext": "5OwD8EY1FuJE9DJLOO5NDSxNV/qraW8WTlOeG0qYgTK+MDWM1GUJwsGbpp/vTOM2DDzoag==" + }, + { + "cmu": "IuStk1Pj3sEdF5KOTuhxHOOrxTu2Vm/prhzERfG1mQw=", + "epk": "2cMJyBaSRQbvcXQ3tkv8Ic7UAcBa1XWBl0Jkug7wjjc=", + "ciphertext": "6AEZmjwsnFqNJoM4NXnUIrL5nzPyfjyCSJCgObYpaNJd1WjoSkz/ZZjdn59aw9wZEZ1UMA==" + }, + { + "cmu": "apemvhcKQaqI32n8CPpe3jD5mSI7/ShAA/ODsjeQJR4=", + "epk": "JtVd7dnXb8b/3I2H5jX3gmrvobHJT7KCmYq7kfgLiqE=", + "ciphertext": "qSDHDyincjDkYUZ8qcDs+AdRsDpeNJ1aNRGWXzB57wftgZU6sijtW0bLfWcRkwlW/etT7g==" + }, + { + "cmu": "ogTsbE36s/uFFszbyx5RyoBWGEl2AYOOriZs+dyzZgs=", + "epk": "SDUMrXc0ryZ3a6ZoWMHTdXULtaGQaUi2JUIgIMckh+U=", + "ciphertext": "icG0Hq2JS8E3Hk/ZdKeJBdBDDBnC4sIeZk4mRXiG94B0CXOlisrSsvDz3C4WztkzzfuE0Q==" + }, + { + "cmu": "Icz0i/4vb8vpGQWmrvhv0gt3J17fvKrFxrKStuGZX3A=", + "epk": "G+sA+mH/9KCmP1dmZagMDqOfQrrTGJCK4Q+dummjoqs=", + "ciphertext": "JsF4J5rOzODYRBarzFFnZiipPnn0sV+mUEiojsxAK0D8SmOskROFbtcZK8ch6tM9J/dELw==" + }, + { + "cmu": "qEpIpsW+USHfu0vM4WuETxjCJCvdhZaJkMDHYIlmkhU=", + "epk": "arIqzN1baz5URRysm/ChPwRYjCdrPtRI5jj9QyuCObY=", + "ciphertext": "1M0ueweYdu7fd0m2iDEI/eyH8ZVfpREsAExgxxOXcUCZjVBAQX0CYooq+fBIblSMeyKWmw==" + }, + { + "cmu": "2ObKFT9mT8Nw39fdrL90iT0B0iwSKxsEZcX7ifPXRl8=", + "epk": "7F4eGaxFbfnbT+FVUyr7F/9BozM+5XjUKIh1CNnrTgc=", + "ciphertext": "VC2Jb7Mg4u8qcReZLBSW0LVcTdI0nh78est3lXjHvz+r47iZhVTjx2+SCYaShnOh9LxFZg==" + }, + { + "cmu": "hViphNKI9xtpUjDJAPqrHP9lYQi4Ed0GCCPBrIxrdBY=", + "epk": "KOKdl3vs4qIthmkIidf6PNIyzvXhhRpyg4SczyxXHcE=", + "ciphertext": "P3fQkgTjl6V85R5jhupoAVNX6xGWVVUEG1giTVaMjbw/nO/rIZxkEmVmZRjDlsekvK0NmA==" + }, + { + "cmu": "zgHWh+HfEYTyFOtAetV7VHplADHypUVj7Wt5dqJHfVA=", + "epk": "jNkl90KrImECDNcxVW9HDawbRoJwVtvxZTsfqZXyKhE=", + "ciphertext": "nc9CymSqQVSN7o3NYk6Ggy20o2/qt31RhSAsV3ELVjts0NUjDsxw+jyswzgtWZiR5yNIhQ==" + }, + { + "cmu": "kStWSMsO8ZtayGXywwS0zaoyGofCR5fKRD6hm9mdrkE=", + "epk": "/sfZ8II+Rh9kmTjFRWLg8BFxVLsB+LT3ddW8LggC+LE=", + "ciphertext": "NH/6l797bpDzqDEi+hd2K0b+7jZeIBs+Da+SOlkzJmBv6lOO/+uf9zXlmzLHYZbgdqHP8A==" + }, + { + "cmu": "uvTXnHwbnkeGGNO7FlXQ3wofjCUP3IYPHcwPu5jw20o=", + "epk": "m/ajtjBHZZF4xySL2MboU7OBqTQ9vJ1gkWly27nofzc=", + "ciphertext": "bHqUmOgOzknvLcGMlCJkQwjrU6eHzHBLpuZbnGIIuSVkKk45/jl+nOpvZW8eGF8oUY1FKw==" + }, + { + "cmu": "LnmpAISXhusccd+iBU/dV10ym8+HWj/gOVcCQlfC2QA=", + "epk": "OmdZj5ldCkR64ymb6IbDJSDeb+F44ozVsCDMuiekrws=", + "ciphertext": "8FAgwLDPjVW8ByHQLi9yG21rBwmViN6iGDpiEDBO82ETjGFu86Lksg5FEZDLJ8Bpdje/sQ==" + }, + { + "cmu": "mESaW+WIUq/7Pc7iUOsmz3QzoTQCdhU6yWDqOeK4e1Q=", + "epk": "h3F4outtNa6VYSuiA3iCGZ3FcC7k1aWaI2vT2TRBWu8=", + "ciphertext": "9Ix9Ep2cv7Vo8yMZGVw7FHVzdxS0ecwkb0cGlza9lG9MakTFOHbecA5VfoTKpONEw+Zvew==" + }, + { + "cmu": "6rO9ybhQPUGsZ+F5dw6sMNdtIK6UEYWHRr21BnT/L1o=", + "epk": "+6tQ2nbTcoV2vYU1TYctXzl8t7w81va5yWTawzg70DA=", + "ciphertext": "9wc74BCH5txIbv8r8ipX8BC2TvQwRHtpYedV+5SkYQcF8bK/vgDU1IsqkEuVWKnWJ8dJPQ==" + }, + { + "cmu": "Kh0AcqFM7UcCHBQT09R5oY2Er0GBjMaHxO+pOYGAjxM=", + "epk": "iUyV+59vqtQ5c+UxDEasvcWPdrURJ5g4UUCKXJfYK70=", + "ciphertext": "GCByfwol4Tey/qVEkTuqhWKxD+PjbLUCoPkRxBBWU9Pd66Kv/VS8a1XJxTGZMAfH49hDpg==" + }, + { + "cmu": "4RSacZSSg8xMhpyDB8cdoqDM1vG3PgJ9N7mXqD7hi1E=", + "epk": "oUJzWRBPj8+C1XttvxsDjtIr5KINyKFPVtBW4PnX95M=", + "ciphertext": "wjlH2e5MiptOAuf4zYUD/VnFQv47CGi+QLUk2a7+CIAVznuRpA1QCDcfMUUNikid8yMlog==" + }, + { + "cmu": "YlddQHY3ylsKwXfbgs6Jp2iqpI8MgBj2jHH5OC5GnnI=", + "epk": "yNQdp7jwBQBWxAVEe2gKtS22M6H1TGfaqSgiZba/XGg=", + "ciphertext": "B3FxMaG52B1LrcHSaaOflsig/khTG3Ef72BZ7cgqAI/ZFG/9raBD6odakciP4TEEYcUK6g==" + }, + { + "cmu": "tW9g7p/IOyFWMpDpKccxyGdM5ECCPjPdASnXNtcwMT0=", + "epk": "sBcZVUTlv5oQVlRPJIjkSpCCVhUOG3SCUNPOiALAOSE=", + "ciphertext": "AZ6i+VHgFt/0HTFHVkhVXAD37GMBGPkEqKYF52JTciSN/tUYr8Mz7QGUvPLSJp5dxCK34A==" + }, + { + "cmu": "BtVWwhl+d+fYU1s3WsqHVVC922o6Bsu3i+9+coT+AQc=", + "epk": "/AOsz1Xrxeervi9blefrQuQ2Z90iIE0pPjjwFnS+E4U=", + "ciphertext": "RFmXOY7fC7/EpTKjahfdwrKUX8eFpG0bAfdOEencq2YZPfqH3qOlvDc64H9vfJenarllXw==" + }, + { + "cmu": "rejIFGh63vWThAdbE0L8womXCUkSWTqJxzILNM9remc=", + "epk": "s7yJJANeS1agSy+ZS04Ci7W2ij2NkDloTBfWIgsItV8=", + "ciphertext": "+mbkNZJKtLtQqz8frC7MckJe7JHALM3c1FHhNUtQp+a4dctneKse7XTySS8CSqVc/Ec23Q==" + }, + { + "cmu": "TqpSodBkOmS/6IcWKSHwJbfxLbOJxd9SdiczGKppBiA=", + "epk": "mDWHBYXv7rh4xjeWDIUjCtREBuRt7tvLaSsQRGFMA0o=", + "ciphertext": "sQy/OhH9Gi4B+4qUqUtnY/7qK+wZSUQbHO+qN2uRfgiDbdlf13XILf4mB4ipoC4txjGwtg==" + }, + { + "cmu": "pBCzKLgQY7+hbQ7DGmP3tmw5v4GKaV9oFiPqxukVaQY=", + "epk": "YGPbDKu9lvD+7veeYdFpPiOGL6AWSZ7+GZIbGBZRk0c=", + "ciphertext": "+FevFLUFDFLRwbhaxJJJhXLyr7R3SCf9ACNuC7ajQcltmM+UzWSkbSBHbU0uFi1uj9mb4g==" + }, + { + "cmu": "6+QuT4O1+osgv5b3qq3tSmD0uLAVFvMlA/5Dh8AbKEI=", + "epk": "th85qwDVubtfZyTCvZMINSHtaIr51+9pABNjZmi6qWI=", + "ciphertext": "yAMeLILC/GYlfHQxtzKJxzE3Mty7vgvGCexcFO/TNV8Swr54ofYNVKebq/vtBjnUpvyoEA==" + }, + { + "cmu": "yDJTlqpYW0lTEHo3sN8fjtc/dSbEFmR1vgaTXU+ZTA0=", + "epk": "L0LvS5fzWp9cWgzwbdEgivS2UxG1pXl4NUN/SdOGrLQ=", + "ciphertext": "K115wvYSZjO0W7RgIynyEWJAS2BnyPrykEoNaMl2isndVxQDTnhryWRSPHKDINZpem0oYw==" + }, + { + "cmu": "kCeWpKXdmKZYR6PNeq5o93LemMnic5OnwZcLvcybs14=", + "epk": "MSkIhDh6r19+rDDYTgsrYM1V+NgIUFFCgwIk5GuFhxc=", + "ciphertext": "CVE1LilyBChSQMp+KGc1q1f4Egajr7gB7qgR6VmeLbyQ1pnyi2Yo3QbGMHa5zx5TZRcqOw==" + }, + { + "cmu": "v/yDuLFeo/gugoyvl/i1WZEyy0+ExElTVy7z3aT9Pz4=", + "epk": "cNXh4WIuP2W0BXbUUa3ZlD5s/02lAlDrdT5XmQzJlYk=", + "ciphertext": "4dcGQjWQ4cU+0/Nu4ufBwsP01BV/JzZ01WX7m362msbd/LFoSolqJEf8YL4qekvXAEomQQ==" + }, + { + "cmu": "T6jvOBJFb4PZz3qBWZMfZmqOWBr2wnYs7VljXak2LBI=", + "epk": "7HmJXOkHcSlYq9LA2gtLUCGQPJA2HRmRgiCr9L8MQh4=", + "ciphertext": "NKrAjgXsPj/6hnsuu9OeSeVzF39W5K9k7kBd002i/ktfbr6KeW/hux7x2FlOw4PjM1FvHA==" + }, + { + "cmu": "CO2/H2+r/CTxAXqLHxP4uafmFecOsJmoYolIBq8YaRE=", + "epk": "vK+CJHjE6ovoPBMQm+vK0JhJvoBAEXRPaoJpFmaSSZI=", + "ciphertext": "Aj7Tf3JCsAxs4WEo0AwGdS6Y4Pvg/vt2Rycd53BkNR5Aev5KpofFcuPM0K7EC2/vPsPrRw==" + }, + { + "cmu": "Wuf6/ZsB2ei6WVKjJ0///4FMrQxzOAOFB9MPHnHbKwg=", + "epk": "uq+Bxq06Hyg1lnUSk/+d5FWx1FDgg0luCNPLdYbEFYg=", + "ciphertext": "rnY2Humac5C0TSmji8GmD8tPXBsUzCuYpQo5Yk14+htJg8XBSrwEpGS6IU3u1xA+ORp8RQ==" + }, + { + "cmu": "4L9Z0Vahv8nrZpK8Mz08vm/vTxJvWgCrU3ZrNLF9hzc=", + "epk": "ejejlNLBb3wBFTSfs+HLz/XI/sNCVsWGl1PWxMoTRmY=", + "ciphertext": "tzp/zpQjR3PZOgiy4VDajdswKQ8DGGPGSup/XryIccdGhmC3eC2q9XN3jc906Kwbkfs/rA==" + }, + { + "cmu": "84bIcNkXrFaPjqJz+GgSWiz/9YMY51V7MB4LQbfsCnM=", + "epk": "x1PhKurtCRVt10dtja+Wlx0nmFAtMl4Or7Uaxwt+FdM=", + "ciphertext": "5GQRqFcJLL7ZxaCG8+ZT+3MUON0bxKeTzKbmj0MFR8sQ8Q6lseXFFvVBZg8wyvmbLWcZSw==" + }, + { + "cmu": "8xLiVFJXuH0jwjKXqpMbtljKaM7+fSOIDMJqH4yXbw8=", + "epk": "GIOeqgd+31YdoLLLfStv01tvhWVf1D/SAI9venGNI9Y=", + "ciphertext": "aF7stKRPpPDb6YO7Fr0ZzrZJLBMFR9W83uvSi2zEhAYZyrRQE+eDCzlimxqnJwFN0b0bXw==" + }, + { + "cmu": "/4HnrkBG7ZLm+XgbkNWbfhYAv4hCUZymjbSTXkaJE20=", + "epk": "VLSmTmt0/OcpTdJ53o0u+BvU8NZ72EdidAxsdFdI/Fo=", + "ciphertext": "phcnWzFG0jipYZ9kppVndK3DsULTd8L6+7ietPpqb2M2RgCBHBzm00IfyevDHz+0PXqzQQ==" + }, + { + "cmu": "A+Tv3cgiuLVkDbUL7Qyw2V4m8Hx96BVoeVcyJoyrUkc=", + "epk": "vgXiELm1d1EhfgImFQeK18KlL69l4uBj23NuY2b33c4=", + "ciphertext": "3tdcL0y7LN37fLOcDgloC/yVFoKkKQQbImSP3frS5+WYaVWZ/7mZElazyt7mOjom1R6QDA==" + }, + { + "cmu": "IuezYLNeV0oqbYJ38BJm7MT6c06qUgcVli/TgNKp1AM=", + "epk": "sF4K3z2QMwamDBQqpJuxYwWgSZI0JKaRQaUS0lQHimo=", + "ciphertext": "PT+bF6fMSyMuKWDpK/7z9jeszvH7dbtfqtATkmfdlelon9USt60zk7Cif6IkadRGLusR9Q==" + }, + { + "cmu": "vSrfvEZEOpb+iqGd75tqYQuk/MV/UZ9WHFIS3dwHIBo=", + "epk": "NpYDXpJfite7k+wkIXe4zOi6WPp5mmrgJk5WFv4y+bM=", + "ciphertext": "ONnmvaSjc4yqW5xoJhhCMdSW9ZzsYD3dk6h1/xpLZFGcK2iE9HqWWfYgCbK1ODuITZCkfA==" + }, + { + "cmu": "XvZKRSSRTogqJ3ItqJzeanyuyxY0Wa/k+k8IKk1J3xE=", + "epk": "j3NxnFr8SHgWy8q8JQ8fYIwxWIzrRKsWpEAbl+UZGRI=", + "ciphertext": "iG7DyV3//7bmlZXUKfY3afqVHP8Wg/zdASh6nUAXavigModim2D66li5XBj+/eo9TyV4Yw==" + }, + { + "cmu": "WTyX+M1ScOxaexN/mrNbp5S2JPjb0mHe7y/qjFi0ixI=", + "epk": "9jrKn3aOryEcYbUaLpb4aW8CTqhruXXjxAMo0peDirY=", + "ciphertext": "50tr9423u47Npr2mIfx2KZkJy8dDLlgv+GTiNVVU1ibkhXNEYdyIeUK5YryKUHJvjn8fGQ==" + }, + { + "cmu": "BtBy0UgqnTUGBPWntIjv5fik9IewQ5YST9GYQzl53w8=", + "epk": "5PWaR9hiynGvfoopeBlkhduMi4YVSh1j4tAtK6U0EY4=", + "ciphertext": "jrFJLwOxRI8dv9xVv4GdHxFWeHmqVLyQZM6Nz/R/IFIISeOiwsDY6U/qZAC+J29LvpUu5Q==" + }, + { + "cmu": "Q5+enYgMLloouwklfuxPv1bFKZeph+NwSbo2jtfB0x4=", + "epk": "Cv5q/FTyNUM83e83EQmgm774hzBh2SRrKQSuI6Jtt5E=", + "ciphertext": "FyT21chulPV1b987pbFuTaJ8cmkXxFEst0y2f7YMMF1K3TxnDlrEiLTat4AHuX0zijr7kg==" + }, + { + "cmu": "uuhNseC/8GFB739Hmv8s1FoW6+yEfiP9fR78soHuJUw=", + "epk": "OIjlhxiiKJV8/iwGrAjgWOP5ga9BJLwCN16MAiexapQ=", + "ciphertext": "bvm9G25N4j3bdJTKO96y6YTk1L2rbK12GaSkZ3VEEoJDxWDz/6urtUxbxZqggU2KtW0eqw==" + }, + { + "cmu": "XRweLXof0bGyIHOeqX9MBz+3Dil1iiBlW1KjDVe2Hy4=", + "epk": "e9OkEvbqbSEGZwLe1ZV4eNYjjEA6mIXF8Mi8qLbZb0w=", + "ciphertext": "m96M//Ycr7LTL+B8jAzWjkV7odQXB7mRYgckODx0YhsegPfMkuLoZ3x/6LhgI65n8Pk3sg==" + }, + { + "cmu": "mEyxdik4ZPZ6QFAr+w56JJY2tdpSp4Cci8GzPaXpv28=", + "epk": "APLA1sBTZ8kdTsDZUJUBgnVdQH9ZE95/EwjoEmDZB60=", + "ciphertext": "/U4l8A92Ro03NkBaaHWFnpMIbr3ntK6up8PsWObEsn4kT8qzFWRFgtXWCM+rgT8/7D92mw==" + }, + { + "cmu": "0ndPIzfPb18f5YiCDNy68S4rYtk2ij0QLJbPMHGW/1s=", + "epk": "KNT7WeUPfpazuuXNkdgWGO3ro4CU4rsUI/xBtIg//BQ=", + "ciphertext": "1rEYR6JzedN3k+bBsmVumSUpEPxog7M6cysCjJcI/jCk/K0Z5YLnbsXujGoVaNeGCePvbA==" + }, + { + "cmu": "8sVVl8MAZZeI9jMsMt2OAlYH1gbo31kP+oEtye1RQAQ=", + "epk": "6H2hvXy8j5kSk852UkWlORO89Optsw3wAifvdPrF8Y4=", + "ciphertext": "QB5SylEN8iFZbLT3SfwHC+cjsO47coE/t4SdubVvGS/w7llfaVa85Et5GnquFoRoJlzpiQ==" + }, + { + "cmu": "tvWgM8vHuRDDB3Tag2w7pOX5qAUh2iN60FVz7m1OSwc=", + "epk": "4V3Q0ejXkBER9BK7pwQqRiwp+UcKMHuhUN7Dijv+IzI=", + "ciphertext": "DIvI7sB3rkvNdrmOHBKHniw1gEXNFEBDC8mlbGIFX5AGNZsbUbMdWU371pUv9kBfqJqOyQ==" + }, + { + "cmu": "LCyqDQJr7T/iszT2tu1dNUUaWnxuJnn65lWdMQnl11g=", + "epk": "4lELqYqZUpGlRD5IDgzXR/CaHa/0Wosf19LVTDJQ1fM=", + "ciphertext": "0pJiS/Z48K5yWcIcGftN2ueLgtAce003EETu2H/mruuIgLTyyccQthSed/1uMwPnz0wLxg==" + }, + { + "cmu": "GVDLPzU/o3ii0R7EfqGahihoMxmTG2csKyhTobnwjBg=", + "epk": "gu5gfrR/XG/jPouChP8l0OQbg6C0WcDAWItsUGNQaEc=", + "ciphertext": "odYhGkgm84Sz+wdPq1vCnAwt2LhBN2Spi+/En81pKuTlTiPGrWmSDsGdzfaKrT5iF1XemQ==" + }, + { + "cmu": "K95EO1tRLZTyOgsNQq8cY0ATLgemEtVSD4ieGa61plE=", + "epk": "RVgzY/rk1FHJQAL6Wmjf9FGsLtplWinIQ32+6C2O3D4=", + "ciphertext": "i/zJt2dlSUoRUk/+uG5oEO4gEsw807yjfX4wd1bCBjwxrawUMG0NWKNTsMfdq/reEMpp4w==" + }, + { + "cmu": "YhqV3crZ0TIJOcT8Mz2uvS72HmEwhWqOS7AKJwLQOwc=", + "epk": "Xao5c4XS7k1xqzRiR1jnVxVBc3IH1b+LGNjj5djFc8A=", + "ciphertext": "oxAo3A3jOeyP0hu8F1l3UnRIMkX7bOqwUbOIwfrO4K2s0raeNW8m2jcBROB5ckhLf5NVkQ==" + }, + { + "cmu": "Rx/QhnpJQF5vDH1ysAFZkD7EDIhTPCf+Yl6Mtf7DxCg=", + "epk": "rKYIxeRXAl1QnwBN1FhgqRWlJD6vUeOYld6h+FOA4s4=", + "ciphertext": "BeZMMLARq6vGF/Uo6sHR9HuccVKbBMeH8J3wiWKpA/tyoubsPtKHnqBupfk37OtGJHF4ig==" + }, + { + "cmu": "UUw6jKnMPx1+kSIyKND6HN0Xmga66NeiHRcMGhIjkxc=", + "epk": "0NajyGt/uMaXwUEs7gOJsgg+o4/JBq2+A6LVEt95aqY=", + "ciphertext": "aCvm48RVdOFNvl0Xbggmw7YcB0E4PJLhOM2dFOd3W+z5mQPoLV6YC+rIgIDu+HS8/oZs2g==" + }, + { + "cmu": "eyEDKSHPkXuPppylRp/EC8GJjNFObbvD04IuGtEZIyM=", + "epk": "mPf3eMSkTbhNueQrE4UgK6ezzlUqwI5IQQdJKj3hP2U=", + "ciphertext": "BQPTDDRc2ObPUg7g35/hFS5dIrtnUvNsOZpOPTYxoRUbj/R3Sr+MrQxQhpUUmyvtVeSTRw==" + }, + { + "cmu": "iR3TxIUeytyM7m2zBCd7V6A1Wi6QrJlgMYJ4SN7tOR8=", + "epk": "Hq7akZp+LENPs2SD8DtCD6Tef+0KCy77QolQdb1fGD8=", + "ciphertext": "HEd32wtxS/R6PqDcuPrVp1EcnsQDgZYfD0MDwfynwBt4iXpgXgR7z1FUcYCGsXql8JthuA==" + }, + { + "cmu": "pWQadIUbKuRFLVSnGh8vBq6O7skym0Ae4J/WmSBryR8=", + "epk": "0kUfcZQyCyC2GCpeZhpJiyiA++HGwtI+Yd60EHd/x5o=", + "ciphertext": "ANEn6jXWgZiISRehtf/ZD6j60zJncXhajfzadYUwKkko6XY1Bw+aCoWYr/XVYVQPZHwN0g==" + }, + { + "cmu": "8bM1NY7rFkBrMDGbQgjtRI2Y/sh2YrmiOJbeiM7ABRk=", + "epk": "4aCDwEYoZZb2EbfGOpn96TSf7KJwzKBoSF3QcDFBjqg=", + "ciphertext": "TV6hBQyVwSCif1gerZ9TjzA7YC82EJMZf3tLmpHEU/clYzo3t67spmUIrJ9T3RAI3Xcn3Q==" + }, + { + "cmu": "S64wFqr19fZ9VSuQ7v8Kzj4O8Yr+K7bV32evOOhVcB8=", + "epk": "vidb2G3Zr1YRldKDz4gt1goiS3/p3vEDav37Wc1eIT4=", + "ciphertext": "5T1NH3FOzPTwyO4+Z+fZs6kPr1d+d4BXSv/X7Ugaj8J61M8FwhfeBstpaSlV5fAxqHkTDA==" + }, + { + "cmu": "W9x1yUVK+YYeQ+Qb294bcA9Fd7QfySzpBvO4v0vTQ2g=", + "epk": "ri21HnH0/dXlUyclZ5q7oPR8F+SmExLJm+XjKhvZjok=", + "ciphertext": "PuS0MciXK9Q3HBgOQU1WuuLNPacPt4Px0GhKFvkTsu4cRXp3EOp+h2pHjOVzJGoRgt0eBw==" + }, + { + "cmu": "hMDq9+aDK2MOY8Yjz5nTMbn2rPVXUJ6LqDxdASSZ8wg=", + "epk": "H5Kh0k3ZXAuBY2U92VBb5r2MNFw6HiR15gAd+cQ+PvE=", + "ciphertext": "FmLetQAihwxKuG9acs6cEKKpLD1mpM3kVSr84yoskcq3LJIPcObVJrARx/tyEP/vDiveKg==" + }, + { + "cmu": "TQ+j0YrPRtgQn03yGtubgzvPwu8nbPMof7mfmlukTzg=", + "epk": "JOpIY98/7ma/jJgfNN6u8f/fQps6Tz0ViOHSB3Ycrrg=", + "ciphertext": "iKOAt30y8CkcBj7cN/wsIbesGx47/mcUm3XJiaj5mQbHC6T0jrk3gLOyCgGqNn4SSLkM0Q==" + }, + { + "cmu": "gA59lbaL8c8sCfPwFGR+vrgyOqDb4SpOPa77Vqp9CnM=", + "epk": "SqRz9zR3QCbXMWeNujU53tEn7AxlAZSn+SavgsrXFhM=", + "ciphertext": "Hn1eXFEczCY1/MubxVRKDfy86uLnc5JNwp/DVWwDZmoJ6EWwp6FSBuoNHOpZIg9Cd1rkrA==" + }, + { + "cmu": "RqocDIEhOu28tHn1UxjW6DPYIt8zs0BeVZRW8vzvCy0=", + "epk": "dP+GT9Re89S9ICMH9AxB0AQMYGv/DUSApYtIYwhPa1A=", + "ciphertext": "axLhykK7qYvKt55vESSDLpcULkI5qooHWSKsAKvdpUPFEgech3hMyHP5MKzTzQUel9rgng==" + }, + { + "cmu": "0d8W2m3Tbb9bBSsCSuBgt8EeyfSQBGoRuKSamiDoDzk=", + "epk": "+cjLijMiTyCdI/jumg2tzA2lMcuXvbOHORex6+jEbrE=", + "ciphertext": "0R7FWBJG96+D2EAOczUEby39hOnxdXRLcCyLQufbGUSINSvHI/WQMLPYH3rklVAm33KGeQ==" + }, + { + "cmu": "0Rur5eo2iMgqaGerbrjwBlCb+ot/H6X5nXWwbtU8Hko=", + "epk": "yztFYqzBtLwQ25QIzdJJSgAn+f6GWq2A9oEFnlAiR88=", + "ciphertext": "B9VFjCXF6xygmwXjo1WLDuau4+QQP48vg147JwIQ6H3wTWTHtoaebu6AElc0UrjOHdCnhw==" + }, + { + "cmu": "qBixFijgEl6FdwwZGM7mRIoSx5fBNeJd0FcqgNvGpHA=", + "epk": "Tfney2MnYVIljTgBdu20OOlBsmJCuBRrsE/EICW/8xI=", + "ciphertext": "s7ryq2jD6kwTXjMsu7PwMHkp2W9S2NPnUw5UJBbqPi6n8B6f3FNZu08XwB49o7nNWhH93g==" + }, + { + "cmu": "lpdMPqbOrZg1MsEUcbu/ksVZG9gQo9ikCcX3VMeJ1Wg=", + "epk": "xBfgWYNkRB2oGNrU74hFco9XPxVhRL4cb1vuws4SS7M=", + "ciphertext": "HCoz+JpmCSZvt9lCzVVkRWZ/QL2JUfNZuh8qr1DiDFOtKc3x5xLqQZ31OYg8+2JCuxjvcA==" + }, + { + "cmu": "rnyfoBLXILQ3TjiG688WMeT2V/wCthb+qgDYbFQ7rXM=", + "epk": "rAqmQ/inSL+H2O6+sQBrpj68K9iR5jWBfdi3F6UFypA=", + "ciphertext": "4yUdxEChuUtgyrhtsKMSc9YDbcjjHW45ouE2nv00ld9Z+sccrWrPB719j48yupUUebopqg==" + }, + { + "cmu": "0WmO3zc2F9nPNyyCnQ0mEX46rqHjn5C0VSgEGQXVt1s=", + "epk": "L41T/WQu2D3dxgxFC9rmXrrADRY8UJXS0OnyiU8HLxQ=", + "ciphertext": "v2XbFn6OfbxgRyarGXDQJDpfdLAT5Mi+CDL4QVx0hGBcly+yoMAWfBZpCRuB31GdQkXLgA==" + }, + { + "cmu": "Zl6+7L/Jfcn9uanJ1FE4wXUehFXVT3VvdhhPsTU9jBc=", + "epk": "CSZEgIEMVUbvOtplgrLDXm4KlFkgXvETsYjgjBlO/U8=", + "ciphertext": "bRJdWv+5Ymb2eNgzeqCdqGZhdQzbx3aYxkdt7ICcPt6L/vmZx1Is+AGSFOm4L5Tkw6GmAQ==" + } + ] + }, + { + "index": "25", + "hash": "ZvnGG16VyjM3LW79xfCGZf/bBumvVo+fLYrzh7mFK24=", + "spends": [ + { + "nf": "OfW/04oQl0O4wKNXprWgP4DxFJmuKOCNBYzFB/G7YoA=" + } + ], + "outputs": [ + { + "cmu": "dvbrpdgcGUip7JetJlPi4AbBOrwWJmqAZhtETk9T9U0=", + "epk": "78q/+tMtm4JBGq9s4LUI3CYMLBigmCT45Z1O25vlUg0=", + "ciphertext": "u0kj6qe+6jsBIEgZ9LC9PJo24N+vo+20fyYcLghnaADLfek2vcAuSNvkA2Zfn0xLl77oyA==" + }, + { + "cmu": "jPCNwfKOHK5uO8D8+Efu6eexGTdGACtD+/U2UbnoFmQ=", + "epk": "TEd4kVjcX3twQWOcLOvhnIFoouuDIEnGUu5sDpCujfI=", + "ciphertext": "xY+XaJjm8uSIzq8RXg4286kb6vSF/HiSiFRDVuwYsOjevloZiyqGeSpsXoE8gJ1sN9Rjug==" + }, + { + "cmu": "7rQdXyVbg6er0qRRe2eebcFNask6fvOTwQYf39riXGY=", + "epk": "Auw8RyqUSgmxM4KcEGVWMNajknppARhG10apg/n4DQs=", + "ciphertext": "yVoH7s5P8yYpv2qbZP9aNEKrjGj60XSXIgDNpV3vZpqpPPJhshO8BdOOQ9xncJHvb4UVow==" + }, + { + "cmu": "tD/CCVnbNcITRCzVtqusKxJCKcjQnJt0HFEwGRQWqlA=", + "epk": "O8Q5WQp2IilXJRYwpkwIB5r59jpt+KgVi7nDftVBhmg=", + "ciphertext": "fRBBTX0T6o2Y8QV77VbEpu3uRUHLqRLfISVDJqdD16m2U6EWagF6LM19YTlCMZKx0bz1dA==" + }, + { + "cmu": "c+nQeOHxfRWbECJQQsySQb+PoVQhzQQq04CJWZSZOUg=", + "epk": "ebV2F1yVxg24QaYkTMfNHVxmi/h3zfFkp2viPZvmx8M=", + "ciphertext": "U0qZA04UBHEp/RJynCfH2gZ0ZluT0pf6jRvX5oF3anUxYmOeL+elIdiVTK1IRL+9yk3GyA==" + }, + { + "cmu": "WJU30LMOWeeDgsjzR/vjcYox1VZTTwUSzOTbuntHJy4=", + "epk": "TRQtCRQxMWRamyjfOaTEXEzRa9TruYaFvJrhcBWrWwM=", + "ciphertext": "fjmUvrvGQJJDqJHoqUUUa9C3euXlitm0alJKNmBur+C0OkS/Q9Z9U7ShNeHvxijAalvsCQ==" + }, + { + "cmu": "IeX5f06NCv0IkPwZIBUXyF/R3QgdBunYlQcCb7ReZB0=", + "epk": "LYDGa7AOT4y9NFszNZtqLDqZfuaNADFnSGt1c6n8BZY=", + "ciphertext": "spAilwkfEMhzChgXVbXn2fTk9o+aSrG0S3d6Gx+dc4bjzEoBKDnugqGTFhIwcFUwhwWLIA==" + }, + { + "cmu": "3W5AlaKOxghTV3vzzLlrJ2vUdWTfdKumOhaoyFInH1g=", + "epk": "ptdFn1xTA905SfYowXg3tplGSJ1jgXodb/yfuYof6V8=", + "ciphertext": "uK5+nKbSG+t0uuoyK9tTyfE1RLdPcCVjJ9eQQyjWtAd5GvDkVBerSIvwgWCIDjlDBDIICQ==" + }, + { + "cmu": "AlKqxQdotG/CYjgjf5PUZEtfdbS+gabXTgmfpIRvLAM=", + "epk": "6tOs5OS0rH2gEWm1DeW130jAsLzTV3t0zO8yWy2XGLM=", + "ciphertext": "URAA+csliVvSV3n+mDgEjDPQSpmFriV4/Y+QrJjCjkwFDoeHN//f1FgRK+J7U1Rj7X8nQA==" + }, + { + "cmu": "n5zmZYIzCMLkkhOw0S6M7+d1iW0dvuTfU7zU2eK+pCY=", + "epk": "zw3hcd+dJvi9rnSKIlijCIHUBAQsBj2QYc5vF1aauIU=", + "ciphertext": "bsqHFB5ryyyrGdPo0u0nHVAlX0wrzjNuHTOX+r5jag3Mrvo6dv3MTLMrtlG5iylOPYcW2A==" + }, + { + "cmu": "jp5GzrRNIuOhl3yT30zGMrj30JmxqUWLJLRXaoQk1mw=", + "epk": "nDN+GBIFXbnkJ4IIoBI0G8QOZFvAJ8lkauS3l4lBF8U=", + "ciphertext": "ttgWFF+qiVsMO/SjSLS/83SgulpG02QDiWgqvzfogErhfqlmISlDyvlEPYXkJujZnNTGUg==" + }, + { + "cmu": "5y/FyeIVKfW9JJemM0sGJXiyAMgbh2y1au05bF5LYSo=", + "epk": "bUTYRGBA64ZNC9Hg62rpkq3EoTykne8MVjORW+4zHUk=", + "ciphertext": "C9uo4M9JK5nzkTwtBO5MwXksFMZxc53JRC0lu+Xt6i+kyC0dwm4jnykrvfwKpQBnJFS4bw==" + }, + { + "cmu": "zMbnIHTlrS7cjuoNGciYvsEZyHOa6vGgKjt3GELygRA=", + "epk": "SfXVFoWCyM0nTA3RfXMyWxbed4Kc+uM4OnynefgRdpg=", + "ciphertext": "f9Emasev+ZJ56YB1F8Q1Y8FoN72TiXLPoTK/Nhcx4uUgsdxHXbLgLMp/qI9SIziKqVWVpA==" + }, + { + "cmu": "lyO1jR9LNiNyOijQimSRpD3xl7m6sgc9+PWBZdiIojo=", + "epk": "FR9fATSKWnko62DMUYxOUV4PG7dGissbZfN6vomUWjo=", + "ciphertext": "nMTp4jy9tMS/T3kWuR5DSEGTIopgAj01w2HUtm8C/uB/OrcrQmwUKypne4javzPmIpfxnQ==" + }, + { + "cmu": "ENN1ciqM1CYsikfuCi1SR3AMD8u71wVr/KrRGNO8HWU=", + "epk": "16XZGrP2hw/cxXubZkeTngVUCHr6AmZ9VggiXEqwdBg=", + "ciphertext": "UeD1J5Vbm47XUi7tCNJLDuzm5w3e7kCxNGgnxKU8GB7cH8ejBAGnnTiVoJPPNbArs9D5Ug==" + }, + { + "cmu": "+mu7hyoxaOxwpoIijUOMgRJtV5+RyhjmmePpkLDUPhA=", + "epk": "mMkDWg+GWeCtY1KsGv6J3+SByEJPYsfef7f63ZkfTm4=", + "ciphertext": "qezjBBDWsSqBpGGZ1gwDo5nxF8NSxbCDCYBg5H+qN3kytDaMTTa/z00qkNCMTcEB57VDrQ==" + }, + { + "cmu": "vB9PsSTYzfd7qib1Y/5kDB0E5rL008DsQaXmyaGfMVM=", + "epk": "6XA24NJVldTnaM3Mc4EbiTjz6hfbn8TUgtEKDOJ6puk=", + "ciphertext": "eim1j3jgkuqJxfnfeeyY6GDSEnXXW5gQcqq86Xmqsi5w+WHY9GEhH/GQ2klNHR9IuQchyw==" + }, + { + "cmu": "6OuA1v+1ty7cwYfP/hVoKyfj3PCM+7sk4uEZvfvD9Ak=", + "epk": "93UhTatvbt8f+REI2fuPfpr+U2UMuyUkImoDv41euCg=", + "ciphertext": "8rFeyet83/bKf6GI9tU4M/aydxUHRkvY5iwc2bry4mVRHSWxH7tS4LmPrJuWjUuXZth3jQ==" + }, + { + "cmu": "S0XXgX2B3wREPN/b+d1/ioqCfQithdu7edqfoJbUDlM=", + "epk": "YaG0QqSqKlcA830Sduc6zgZlAIKMsWNaSP84ufTnn98=", + "ciphertext": "QgkH71CjDd03pRkMmoA0FbRNdgEm7UlJHkwp6P66O3EMl4Gwgh7VcQB4+bz05n+32h3CCQ==" + }, + { + "cmu": "mtCoVoVokMrZQS9XEQMa5TR/gxQWvzNX6iRh76VcL28=", + "epk": "3Ic7yn+fLS1nJSUhjhArBWXwunJjkhUcrNDIQp+ZvAs=", + "ciphertext": "sInrHe4hfxHj2XWzEiZJqeEDzyyPVhQbZyWBT7HKIDblV9VLHKvF1maxOdBlqCWiqoP6Ng==" + }, + { + "cmu": "ka1oNeYzTIcO1RT1huAl0TQWbbYAUHkLkKIXcc7ix1s=", + "epk": "4pp4EFrSWNZK7muQ2HuzBLiTce4v66KOxEHzUonBOLM=", + "ciphertext": "pZZquBoERYEck9qMm0qPcFhdsiHexdZFS1Wv2jf5RSKrfsCKbRSH9k3ewkhCwTNCQz5bpQ==" + }, + { + "cmu": "H8r6tx9ojAFNYXADa1fT+zGIMOHfl3tG/WdIfXfuFVo=", + "epk": "Zc/pIDszuRfTxdhW+12DcXFDhWQAynz4uRjBYm8zXTE=", + "ciphertext": "Vq65H9n1bIvxoinwXCSF3qVagdeXNWT20vFzmulKKJ5m+xSf3qyh5AFR+f9nfJ+TxY+Rig==" + }, + { + "cmu": "mFTwwMW08zjiEc43bepr1U9wa4lnf/VmhN0RBjO97zQ=", + "epk": "Uc1RShM2jJbX8SiWoendFvFLRpuW484LTB5AvAqjC/I=", + "ciphertext": "HW3N5rN1z0iwrKk5c6v+FOHutb2/NrJyrsOjQk6MBWIqor8u/fIJwOMZXzZ41HzOya0zqA==" + }, + { + "cmu": "Sh19ha4S1aMw5mHrQE5dSjsyl90M9omxjqYF9HvD00w=", + "epk": "exSAySSgHc1HIa9rHpgMI8E3b7HSfWuCp8QfyowwDVw=", + "ciphertext": "D7Ws4xtV9z6Vet6N7DockXGQEj8rPNAgnNVv2lIkUCRFUS5KnveMTgJdDkHAQv8xrQ+9mA==" + }, + { + "cmu": "YXVSZQ/G3lUhq2ug4mY6dzV7gCthqYhrkN0iTk3xMmo=", + "epk": "ZpVUg60dHPtCuvnS6zdOSuMMTTpgoBxvEQLf9xixDFM=", + "ciphertext": "6LXECG0ZtNWBr/f0PGbKVyN/FoVDShA+wwsw1gbWhJxjmHFq1Tp3rcXE3T4+mHVIkBq3qw==" + }, + { + "cmu": "RE2D8YLqMYiBOLDakw65vXMpvX3v/9FyWFskCOV0txw=", + "epk": "+AXxkHxp6CUC9ue/710I2eguIxQwZLgflaOT7Beu4aw=", + "ciphertext": "6LIYU8vpXS+D/gstb49SGUXjO9+DYjah8l8EcTnABeiUL/ChinOy1S5gQ/CZA0EkcqEayQ==" + }, + { + "cmu": "SgP8uc35GptU6Ur8XV3ANZc+OKAuvxiy8U0wJ3tOEiA=", + "epk": "1uXKAd7mSZcAak/qE+QyzkuSEtAY+vm9XdGF5mRZiUQ=", + "ciphertext": "tu839DXs2COn0k+HgTkHrWKGJjAG/C92rH30phsFg9Sdf4JTKOdVf8s3UOXqpQBNNm3G7Q==" + }, + { + "cmu": "L8uWQz2EtIbB0ZMyCs12aSMiQ5bk6xu9uGLIsG19oxs=", + "epk": "iQV8JQ4cRh+3c5xw++WC+1oxuSS6eNLd0qUPHq4t1VY=", + "ciphertext": "r8t5XKWMK6Fy5fVczUGAqjsOzZrwg2lT5d/FJdRD4JI5jY0bgGp9H0FLW+dznXI45zeYkw==" + }, + { + "cmu": "a/wTMt1ug81O4UOETmlm8x+NWdihJzw5gPzNkDvj2jY=", + "epk": "SMX5nFjmf8qh6qL4bChDrMvZICjVU+lPCwL85DEJ9hg=", + "ciphertext": "iWnFkIV7FS8erq6pX6yi+4gZRX6dyv4AL9bB2vydJc2/Adl9rJShZk/5AuQqB3kCgC5UhQ==" + }, + { + "cmu": "K9KEwb0LL7Yc4ITCUH3lFdECZdom320uqIJ7hSbgCVc=", + "epk": "r6KlIXvfwpdCFHfZZNGM2fBfbAKNf/apPKDySWb/AZw=", + "ciphertext": "K9PV/3ZC3u+7l6drmnqY9c8X9+DYXKXVqNq43XWBB8cK2wcmONnLL/FTEERm3yB7PXihSQ==" + }, + { + "cmu": "+HJHv+caihMNXrNXClApmQ6rSLSGxRiHDYebxnhKdUk=", + "epk": "SpvHoY9lphK++NF5sP3sVG4VSZqpZvdGNL9nAYj4JKo=", + "ciphertext": "CGZISFWWwx55HrcGzB+ib864dU56B9BYtCMJaR9098PU8PfMbXYCNvaNesLWtWBtVXCacg==" + }, + { + "cmu": "OG901327FfUvEGlZ48l0Ghd3ORIEzk8F5zxB5vDt9XE=", + "epk": "BzP3erSDJncQI0w1lXGv7d6LpklaC9YpYGolaha1u7k=", + "ciphertext": "tUOUAzCw0vqbyucEr5vKJir3UPeAmSmjZ6tlXDA0rbCCEsXjgnvMS/HbzpeUatCwigMpfg==" + }, + { + "cmu": "VcifcJA7CKrhi+BtVqA8TWYGRZVeH2rQLIaZiuqU+XA=", + "epk": "fMhymlZW1E+Rfmp4zLmDQe/KH/NJaE3xZs4sz3bIJzQ=", + "ciphertext": "a7EmoX05TFDv4hTztQtZbRH3i2ZbeMFXS5sDqP0BqlV68dVRtDdr7nbwHZHUyB4U5/HkZg==" + }, + { + "cmu": "K1PrBobzVixk/brmWaV6qmZDMKGkorpUhwzRpWCgkQg=", + "epk": "rZNXbvsNBjmHlT3GcJEU4UljatI/EoGao6dfhUYwM+E=", + "ciphertext": "FwmjqSg8A4u+ZqM018cKx7jSr6VEf15zTmoNlTV2PIhUIu3h/jN8lDvZGlt+wRD/5ThNaA==" + }, + { + "cmu": "NoZnGNkL7y/G7Algt9rFt+KyQrgKk8/COg/wv75zOz0=", + "epk": "o9+utR9MM5/BUCMNQbiKCsjcXTN/dag3mclJYxXIDow=", + "ciphertext": "oGRt8xJ8PI85qhuBvp8t0Vu66xo5NxL72ciJo0RxCBX3i7JLYZNVprfH1yxp//zSa9rMDw==" + }, + { + "cmu": "n80GNftcLoEPWY3hxcQ22dBhU3ybzr+eK/vE8TSn1UY=", + "epk": "WvHr3NHhO7jyAb0h9yq+9zbGlvFeAZA6SvB/7A3TkSw=", + "ciphertext": "JItFqVldMKjrEWKpMtHaYFGFTb9Lw1KTEfvNWFroU65wY7OKHdHnH+rzH6KRpHu/v8+r2Q==" + }, + { + "cmu": "+4VXgp5HA6mJC0+1psktrGplybeCA9T7wJoIFfAuJBY=", + "epk": "9yOuJ+5cAjQc9/f5Io7UFnFxFGd2bYPvG58nPQSd0VM=", + "ciphertext": "0fXCRU3FjUDl7gbezrSgNCj3IzyEP9RCJyl7xF3B0jnni0ZfCABDvlC0QgavS9ZTE9kKMg==" + }, + { + "cmu": "ILIYkyTUWsaiUz3QqvGaj3Dl1TLqDx/kTZMFOdrVRkc=", + "epk": "LWqnk/45imBBV2V3SPK89+Y28Cb8wNAbjtZSD2bBlKw=", + "ciphertext": "hQ6Z9IluXgNB9ug7OFLaxH+lTPeI3WQVsFIeRqjdqiRiIScMb9nWLLg9lFyR4crH8yikoA==" + }, + { + "cmu": "4baSXM/Sf7paWDqxYIC/82sVcw73HKy1leWVB4JvwiI=", + "epk": "4CxWWHEDNk5L6hYqU+sq8OUlsj307TvvFUmP9aKz/5I=", + "ciphertext": "LT4DXDx29f8arR+aeBIqFX5zUVREWduuGvCk6q6hdem9UKs1D0o2rlVpdhaOoWVbNbFxOA==" + }, + { + "cmu": "hXX5sLOnjATnLyl4gTQuP6VeKHrMfvW6jrZtjVd5AAo=", + "epk": "R3CQazS75h6ELLz/CmwH4XCQ2PfJGKucEATOnb5CCbE=", + "ciphertext": "a8JdzPewttqrNbTG03Bg7a4njWsfIMsyJI18/5FdXxkteyO5PN767z7Idbm8LtRyLMXN5g==" + }, + { + "cmu": "gZsczpyz3/aSY3+8k10GaQfVBbNqx51wQ9yHLg2xviM=", + "epk": "VJAy+1fbq0kylT38biPzfkugJY/ny/BidZ/zF3uT9nI=", + "ciphertext": "y0DX4NF3LG7VA0UlIoNCYW0v/UdYtwXFlM9WJIMvxZdGSi8g5WkxBvE5yz/iJA48GzOK9g==" + }, + { + "cmu": "6UearvKMeozoWs/E6fOQLd/fjva+vT7Cyqe+HiWcOzU=", + "epk": "gKpaCtW3I734PhJX58bVuewk11bwoBnPg7r+9H7tKeo=", + "ciphertext": "dSiTK7KfRUj+/FtcOZkXtdU8CrALYMH3KB0dO0lSvAo2HWk1QCOg+rANtC+ZKsetXQcrSg==" + }, + { + "cmu": "09nuAR5oTB9ihIUEjOKni+kcA/WaHJMdXza5z1YI3hM=", + "epk": "91GkJSxK6FCDiw+cuYAi4UVnOzLn5HEZWN8VWTe/yhY=", + "ciphertext": "bM98vKLioClgqWbWJ+2crAbQD/gBhO+/dFdwLT29I30Vjb8FJaLIh08l2QGHiD/mKWZOBQ==" + }, + { + "cmu": "KAR15EflstS/pBR+8YSkaOwoT1ZKRu5cy1z/NJdQ9BQ=", + "epk": "vM+CF1Rta6Dnx/ZsSZDEVo27OKCJESUkpCprFcVaO5g=", + "ciphertext": "ylYpqiuNVgjyslZbONtps86d1R+kySOCcb5JpbORGVdFfI0DuJIVorgWKMMbBard9Su7fg==" + }, + { + "cmu": "AtJa8A2GIdb6huTm5c0qaxDqbQyrnyu1IcMoc+W0SXA=", + "epk": "ClkqLDsAynCG7A7mf9ffPeauxg1LNHUm4rYjApi9WOk=", + "ciphertext": "D3jF6kILi1KlRQA5TMCHWp2vwGiODXWvOVBKmYQ5ns9stZhczqFNxwYTshAlyXlxjgexGg==" + }, + { + "cmu": "hilIDvveEakF8wrNz1LO6NCdblfqmJNEtWfyrL+fYmA=", + "epk": "S8pohIW/i9TYGIeueq9pFlzh9DBFUkqVEZY+iL9KgTQ=", + "ciphertext": "IugAtAqmPixhxw+ZXu9u177bndfmph1CjTigHT/Rq43pRWesgmyVJL0sIcQ2Ako40F4+XA==" + }, + { + "cmu": "zcUVhVcOvO74n+rXcUPMZH8j5FPuq8Y9kBMCy4eZqUo=", + "epk": "uP6osde7uq7I6/fE9HC45cHoEpWCvbX8UrpE45WOt5k=", + "ciphertext": "xSOOVMaAHOLuATfFa6gxGIxtgN09qRa5G7jW+8vD6iodfrjFUrAG7AasxNCnTWO7vgKLyA==" + }, + { + "cmu": "vM5I90XL1rHWHeRUbb1wsrSDLLL64A+Cjqjt0srj7jc=", + "epk": "IucDcCL+AjuN5sO/IrAnn31isdmYt4e1dnRoWZzpfZU=", + "ciphertext": "nauVa9cnLLBBItuFUpTwbPOpA3imeRCifOjOcGav6XGdTPjbd4g8WvL9H/YoztKxJzQ60w==" + }, + { + "cmu": "XQCkQwbUUIvJhYi+gJRaKRCpB75zO6+G5N+F6yGmg1w=", + "epk": "KRQD0pzOeZEhmlCrJZqf8+xjOxtQBD4yMhA9epIhiao=", + "ciphertext": "bYw8WpIlgFwRDyHm0ILVOfjn53rDLkL8F5AYEQe9Eh32PgZ8hU82vfxAsaIoha7z4VGUhg==" + }, + { + "cmu": "lu5xtRy8ioLfW+e91/Y3gl3hT2d8EOGKuiOZ9nGIZFM=", + "epk": "AcvtSot33vbWobuJ4nR2FF/RdW8dUveOOlu571fD/mw=", + "ciphertext": "gbn9YNvTpM3uqEMId5v3FQWUe2eBDm+cYMW7pYccMaaB9DuKIZCrPteeWVdPavoDHpfb4A==" + }, + { + "cmu": "C2GYG4RKUtcYpl0zkGvtmlvotSn8M1MJoGBNOSlvdFg=", + "epk": "U9DLf7dccXfyg0wcL+mxE+WayRzK/xmGIR5L2N+53Fs=", + "ciphertext": "B1OXAHZvw+ItZ7OxGFtDfOM72ZaWGLncxEuelI9wIqF/y9RcVOVnkhvo/2SXgGqfSU3QYw==" + }, + { + "cmu": "+RnsYW9fDt6R6tHl+EHRwKtfBnTR97OWEMh7JA0fIEg=", + "epk": "mrRs0uSPxHMP2BvsG+zenY4D17IEL8eCRDK4nKF+72s=", + "ciphertext": "QTE7RIOcersme502bteIfx0syB2oSbOQbTDAs9tTTBdU0mEiaoJC4yThT7V+6O2t+nxK8w==" + }, + { + "cmu": "7YB1ocK49EjP1c5uihoaI6xfd4NGa1IB3iRmlhJLpD0=", + "epk": "lTUWZradF812lIFbbb1jBrpkOr9l6s94S2CY4U9m3Lg=", + "ciphertext": "fh15u/CNjF+XadPO3jJh0YP/4kpon6CEJfdQZtMi860c9nzWNPtVGhgYKOF0Q5Nynd08CA==" + }, + { + "cmu": "468EB6UiMTR2s+gQI27twdMTfNa6qd+r+x3kRGygimA=", + "epk": "d3d9HeE/I3cmiIwnGvCY8pRr1LmvoEc+YqBDc/ANgyU=", + "ciphertext": "RITJWevlPhC9JX17RGAtCWdyqz5k+QkGE595LkT+/SlIwfZl4qy0fXL2mqnATTcUya7fQQ==" + }, + { + "cmu": "2DX8LVNMKWq0tRSMR/vOgNSPGM4cQeVp3Zgs0bPsIyc=", + "epk": "pIyJ17ViHhn0GuXqxovJkGbAFAcjhMZatiaGhCZi4a0=", + "ciphertext": "9HjsIN1Wc6/xMfGTU5KWNZiaqq9sm44J1uiliK/Lqy9/fCJIv/V2O88f1/TUs8GQz0CZOg==" + }, + { + "cmu": "myPnQEhFtoIDNoa44XBTOI9lYcJ5T/YrHU8LrMatzTE=", + "epk": "ILtwPII5nvGpBgcEqEHxPyuPwdOZ1Hfimyt4g6CKCI4=", + "ciphertext": "u327jRh9aUYx/7pBz3d+Bx3+zrjUR2LDT3dtJ+G7TuqLCHo0JvPWRFslMSGzdjpdzWJE2A==" + }, + { + "cmu": "mLSme2eVKQk2Zd4Zk2gQi7FIO+Hr3t6+ZPT0euG4vWg=", + "epk": "UOsrb+yLbHdzuXTV8ktobzIOIsUqT1Dn4dDOJw8fatM=", + "ciphertext": "rFi/88hXW9tVk3ZmWj6DvJJ3JjCunpS9dt+UECgurmBRRi7YoHtJQHg02BpBnk0ywrnWKQ==" + }, + { + "cmu": "YmEDSDEo9gkAdoEjTekG65V4utSgVFQgo8BDxk5H1C0=", + "epk": "0aGGBek/yppVe6a2PWO8NUL241cpitJhWRJdmcYM7Zg=", + "ciphertext": "GMHzK72/hUMjjZxKxrno4OVW5zvoV1o1vQlzBdFmOfK0BRTlV3FWYSv4D2VqF91nGQ08Bw==" + }, + { + "cmu": "E3kzig/ern7zeWsxONH/anFgYnRbELge0MIraI4V3js=", + "epk": "Q7/cE0ISSOThHd1lKSX4BphURUk6IOA8gl/1CpvhBu4=", + "ciphertext": "6T4JQYhu377T/keSy6KRsCkUAf9W7X+YvJ+7xLEb87UL5ZOsu/KpGvIVo9EonxwXcU2cxg==" + }, + { + "cmu": "haRkUZlB+/RXsMzXkGxL5dMrr7v8h21rOMVyvmNGPxk=", + "epk": "EAlCrp9nVDqI7bmV2t9HjH4B2uXidOjtY0emuxHs+s4=", + "ciphertext": "qACtRXoTHmy8r22DlcKGYha23QYzvvMTckHv1F8Q49msBRaruFiR4es/NMxiKnUl2MP8dQ==" + }, + { + "cmu": "rVwAKi9PiLkInwpVH/tBOluXigIiGhrBHU983yM0CR4=", + "epk": "Dxsg37kmmGxdYwnYi/SUb0JJBIzE6fd3DlGNGx6aAPM=", + "ciphertext": "OBHN5Kna7Mcnro8ul0oQDF3QK28fiRqI1xaicomI1nF/+GtyAvcI2TP2qUNO2G2PHNHSgA==" + }, + { + "cmu": "7cuyDOXaTEZlvwCyMjdf9CpROYVMDfoXH1LLBOf6T1Q=", + "epk": "tKalIOlGQbfQMe+L1aAtNYxKevRCpQsGYaPymNjSyFs=", + "ciphertext": "uIdaBvPPr7Ohr7qk5wE7K7ryzGQdFC68xV47S0/ElKCSHUqhbKOJhypJSNN52uzSY57VEQ==" + }, + { + "cmu": "X7yZe2mlMKNoSk5JjQHrajyU2a5fnehHWbWsrDEvxwQ=", + "epk": "syGiM7IQNfC2h1BmgPg9pbe7k8aZgAMzdg1iXCpiD40=", + "ciphertext": "GbIvRXFLGVlFzvLc4BK0A/CxT6oXTdU5UFQOvgQi3uWI4vGJEM662DkK4sd0ggeis1sEQw==" + }, + { + "cmu": "bT9yCl9NTESjaqS9e0Hw8GAdAecyxypeAz+RZOT1f04=", + "epk": "Rxvup+ZXxClifp//jmwUx8BFBI6Bb5nH0GGMAkUeOTI=", + "ciphertext": "BIwpJcJs1/mtbY0Ljl2eWOPLdRiUKctHA0y5+5bGOO2aWhPCJuaS6K/oqn1zbJc28Lkz4g==" + }, + { + "cmu": "979s/AGLfhMsMAZ6XoNEnBgUD86HYBA5gape38CqXEM=", + "epk": "XobHEl6FFJTH1z0Kgji0f6FdXhwchoRalHxo6yGakaI=", + "ciphertext": "+K27aBB1zFL5crMdGDscmw/YMlF9DP+eYoIrenOSS2ulkfv6BkRHVsOQbjK3N1Pmn2DUew==" + }, + { + "cmu": "/82COKk/6XfrlH3Gv2abK8lTaKqMmcFoInkg1gypQF4=", + "epk": "fRXKEZbvLEGdv4B7aMnaIAOoN2jAm2oWrv2GNDxt4Nc=", + "ciphertext": "WzU7zLKSD3a2aQJ8q11Oa6aiKEl+z2jMWOr03Kpq8hLnqJil8/IeG8+2HCpJ5C5CDC4TQA==" + }, + { + "cmu": "//yqOenoLkBnykoZclT2Sjm1luJXoL+ns/zi9JQqsjs=", + "epk": "A52SS8cO3zKxGy+G2gX0wKLrKnGm5W/lEQL1QgY2YkI=", + "ciphertext": "b/GqOtjDXWfsO15lU76jAZa5sqsFWFbYkyOiWZNAne3ELo5uHpYpn+NewQg4pBSvGgYR+g==" + }, + { + "cmu": "UMKSfFE1MInVKYVBI1RfDJWbuf5V0VCbCmBy0azrSjY=", + "epk": "piEYbBFWEHeeeSgfL7+OQ7aAwB4UNMTVVrYsWVWIX5s=", + "ciphertext": "q6oRnSe4BlYTWyLlp8wNA5lKzWGIszNiagXAYEFX285WnHwdyTZmi402xv5M9E3bowNY6w==" + }, + { + "cmu": "N9owulagSIyaiIlNR+ZRfQqq7HhtJiBi9bujh/juVG8=", + "epk": "rSZhdOsjeeoUI6vSiyfjIoa9gOTf7Ews/9NZPX37woE=", + "ciphertext": "TDMgq95YaKNk8lKsTk7vnbE533T6SSpR7IItLPj1QaqE+HaXLaQYUTmKVK6jcITguMqTnQ==" + }, + { + "cmu": "KtN18IYTzr4/AsNQRw6NTWl4rSiQdZGbTdD22K0auSw=", + "epk": "UBr9Kh4iupmIi2jfCdw+/Q0pwz6hNsPgyZmRnI3O7O0=", + "ciphertext": "i38khkpdBTWSiXo8Py2Sz5mnajUMjhsnVaV20W0fyPrcVWicHFAcwNFqyZwICCpnhoKR9Q==" + }, + { + "cmu": "Az/4Gx37Ou+kZiEKXNMib5V+UE7sUcGscenH/kgAR0I=", + "epk": "B8ivC0ycaFnHWScYiw/8iZaGreCuE5F/VMGQJBq4hU0=", + "ciphertext": "dxGqPP6wZ7o0gLxWBd1oJCPg58CQfWK/bp0Zp5W+h8Jub9l/4ZWgoaJGwfd6o5e6lKgJGA==" + }, + { + "cmu": "3bRphwgdl7RBISH1afTRRMOBbPFI1StqXI8lq3tAoRY=", + "epk": "+wr8v+PE1BRnDd4LDqdEx2EISLWAwgmJOS4HSeOasWw=", + "ciphertext": "+2Nyy5rzbYI29zBZkUy9ODYfGwavGSD5qL2cEIFByPqRuo967fWiPQdNULtxmDLRQXI/LA==" + }, + { + "cmu": "1R9oYKhWL9cfdQlK5II1FqNMT4chauLraV50evU1lAU=", + "epk": "5smtrHcBHFkcjvT50ykEWiy8aKi/ue+vNcJ3FmCavRA=", + "ciphertext": "LAAzRB/wZiuY0EuU0mk++DyOc1VsneEKhn7ZIWzg7WsNLBuFZXgzqmEH1cxrGTFv0Y2BTA==" + }, + { + "cmu": "5QKu4T2QzXFzCQF0soAJQujTlBfaqUVKPKI0U3kUL1g=", + "epk": "s0flnF5qwVY5zWyrJkPAd+WVEdDHjLsgmv2haa3s0T8=", + "ciphertext": "2SextGKhIO1Wt5Ase39BNnGoJuI1443vmlKPnFtVxKC4Hn7WQtgT4vj9IT3JmlNRYwBaDA==" + }, + { + "cmu": "oxU/Msrqj7JGjjjElvk2h0mwxBPkBEMoOdmTct5SCxE=", + "epk": "/+CHM1zplIulUQh66LJNV01nsdvf5ouovo2E5KoC8hc=", + "ciphertext": "ZJZF5xw45ymc3o5uNiO3cGNbFNM+4h1jMvsVcXQA+AqT65raQFZMyX3iEp1bDXeVFpNkUg==" + }, + { + "cmu": "vIc87Bh4XXO7lZHZGmq76TCn+BRz8c+5AMLZ+CrrgGo=", + "epk": "/6T+xVYf5+BLqFF9KNN/mO6Wus+E4h0YCtDgIJowij4=", + "ciphertext": "93rM2UIlb1JkLJKbu1cBaVcGK5+/dNcUkgZwAn3YVY4+K8+5lNhzAwMcyP/xmj/kdTf5TA==" + }, + { + "cmu": "9H2QvkaBvczY8LPjiVbHd36FP+QyjkChFhzn0SzaawM=", + "epk": "uhkkiwrhzQM7j/3WVoUevyCtFtdVH28zfBEx1GYRFlA=", + "ciphertext": "+y2kmWg/daILllHh+A5Ep5wYC1l8j8DhGXjGFMKGiaX+2oFyxVhI6nUbCrjz/PSslAay+w==" + }, + { + "cmu": "234hM5OpJqbIGXZuQ7iDYV34qtM32cw9lUs38LvhKiM=", + "epk": "cMHDgJcq6m/ZBkuxK8+jWFqRcPMo/XnQNeiZzgGPDyQ=", + "ciphertext": "fLstHVhh6TcIGGLjD0V970wFMQtHfB3NdPPdEyvkkC+bHPyqeIYNrMmngx+s6pDM8ykUDg==" + } + ] + }, + { + "index": "26", + "hash": "C3SzEyIlAJErvrf5Il76OtTgWExBzqCedfIKNZt226g=", + "spends": [ + { + "nf": "sebfPonTOIk50IPTFszSZne2GF7lHCY2LhwHFSqvaEc=" + } + ], + "outputs": [ + { + "cmu": "EABxFLc16n151a5UR+9SwUDNv++kRraZRO8bBqI/vkU=", + "epk": "IP2KO6PlEGx98jldmbrvadJMIiqd0Wr8wdkhdwhID4M=", + "ciphertext": "3pPgDKsAI2k17eWuh1mdsxViqqt1UM2uugXuoCj4gTAgUQsdf/L7E+cKkepJ1dQOnLCbWg==" + }, + { + "cmu": "SPDMAIiUkpx4AWzkUexYY8Tu5QUsg21PmXNGmoHwWlc=", + "epk": "0XaOv8a8v9R0+Hl6kZYpXy28Nfp/Vy+hv28a4INO5EQ=", + "ciphertext": "MxwxohA6CMJmGUXgyEZZdOuxf4OMbyk6H2NL3q23zA/o5wTiDNHhyKpfVJ4XlQkghrYnKw==" + }, + { + "cmu": "U20ml1KIeMvsHIeihA6rhbqyd2GlfPTLX3LQytffhhs=", + "epk": "6X16x8JZSE+0UGyXdRWsh694m5zNEKtspy5V1N0taNg=", + "ciphertext": "+SCEaj2h184BToxQpDf5XN2/ly3X+J7jVdBFN9UpVXeweas2pYC3KKAE+97cIct0ii8Wpg==" + }, + { + "cmu": "0IDhg6oORfWZtqQDI31h3dDTVMNqAZL/L8kBVfbhl20=", + "epk": "QHRWWTmcgRo1S+ea6Kz6Ko2BzylunbOoyrYnglDgEVg=", + "ciphertext": "1XgpiiLEtaPkxJ1YViPg/H20wYISREJtcwMNkLqGCckcMe69MUtDSFZo4FwS0YyrO9ziGA==" + }, + { + "cmu": "/Odotclol8Ao1r5cNEwiTaEeBjqYCYhY/SKh43uz0CI=", + "epk": "VQ763R61HqKVAJFr7qtsIFG6XwdnbuNZ0TvhGetiuG8=", + "ciphertext": "4/CPoIL4SKnXPFmJ+C/M6Syt+UiKnP12vjetk9oDKUYIf19atiiNOv3FNXz9yubW4HXknQ==" + }, + { + "cmu": "nNZSYN+3vlsensUKQ4tMCcN81tsB5rvdwvvmnatNMUE=", + "epk": "hh2N+mvp7oJ8YMAAe2o3co5LvTXklbpYoiLw5Jy1i0I=", + "ciphertext": "2uqx272gse7axPhl7UqJ1zjKe9p7+1WZap2bYiAVvGROPsTKiSUUzHjAvzTm8aE3Kv1FfQ==" + }, + { + "cmu": "+5dv+FBTPGxIGRaM/32fQfKawIPJ4EX5m6Jd+3ZR2SM=", + "epk": "Bd2TCEDHM98yWcrErJXWSYeutaqOhHulG4Sd6wiKXTI=", + "ciphertext": "4xKzvDagL86nKbo46c3GlmdO7HM8Rs52XgreQnE3ml+6dpPHBliCoh9eEvmj2E0sVJU/vQ==" + }, + { + "cmu": "fl2r0M2gQq7PYIGXFRycPSYhb+LfCm8Ych+AMn0Uu1E=", + "epk": "qzpsPvCQZwSknlh+2Pj7E5qFZhtAChbS2Gep+jCiZq4=", + "ciphertext": "iVc2GV75zZq8oGpiM/DeToI8QEEMJVHaYSM7N36XyGSTUxDXSWYDMOXyGOhNMsSpgOGDoA==" + }, + { + "cmu": "EVWgvSJbxkadUxKdpxey+bp83vY/dsG13dFf2N2j6E0=", + "epk": "YggZaybFKuDxlg7iifKUKlsVTLpnmcicsnsbLdRB0YY=", + "ciphertext": "PwkwfG1gTTysjiY44EYuAgHymWWbzHxrsCamk+bURaHLH6Sl8K6qvXkjksJdnkxbaGpTfw==" + }, + { + "cmu": "vl+l03n+5K7wzaU6QuuCItibsbiDGn76AMwSaCotBig=", + "epk": "m7zfu+HouqfiOen1egDKVYOEXFlF9e95lCXbq8ntMVE=", + "ciphertext": "rt4autVPFQOHwFzSutrTxydmeA4TDwPOqTgtty8RXO5MpCBM6v6tEQJ7/qHEwP2Zy4b7yw==" + }, + { + "cmu": "k11V20mx88uHhcj10AQAxa0uyA4H5jW1ZJwWee5h4CM=", + "epk": "IXukqHvU2ETSGz0KhyhsiVk1YJMlQzT9ixoUK5b0LhA=", + "ciphertext": "Cs6KEbcclsvN/DDO8qktANWzQQNtBlO/o7OrmB+ZGi6e95meEGIoIsDyGdCHhfmSlo0VzQ==" + }, + { + "cmu": "yxHqcI/SjTn1iNxOJ48+C0K4ESS41Nr4nhCRgP7pUDc=", + "epk": "mGNMaPjcMM5FauEGGIZKa2FP89ABxDK9/7sP/DbV2go=", + "ciphertext": "QstYQryOSxjQ6zZI/AV+vg+606T7QFCP8VAkreSVDZivRtlN+G4dVnfM9nDbgxtSCvDVRw==" + }, + { + "cmu": "i1ErNAQzFqh2/1S2xUl3K70BSH1cRHefeEsXjY836Bs=", + "epk": "umPYlrkD38rh0zHCh3Ix6wtydlMZkQObsJnVxrBiZbw=", + "ciphertext": "HR+iaJGSwDQdCrcawxfkj3f4byVw7jtZ6AANjhRcVzUTNKCPj5qNOaGvToz2zdKLyLNm9Q==" + }, + { + "cmu": "5kO2SnUS/0H29Q8CU6BFdH/2DXxQeDNRuMWUR44K7Wc=", + "epk": "ld5nxrVVAK9QwzlInr+aXm+lmnQIpxxmJmiNblsA3Ks=", + "ciphertext": "hE1Ban8/GvS7mG6JkntBBLAbjThwLxIMbs0sDjmUXOGfp5WDsEW7VNZLRnYmZDsVP0tksA==" + }, + { + "cmu": "7Rvv8wcHUSbNefatWirIW8Sb64vy0jMqSjlelEP4Ki0=", + "epk": "7OPpj5PkdXrsc1Mq246BgFjxvAxXXk022/SAcVnyFF8=", + "ciphertext": "eP8J8FxjN5/LQ34pbZZWEZcbe+QiEIEAWkgbBOKggwW2Vht4H1Ym5MK4ZfI8UMyfko1WNQ==" + }, + { + "cmu": "r/Jol7XuhRB1aRbmh9N3WuGj4/KRXl6eo2jj61W6xTk=", + "epk": "OKoCqDTeNY8GlHYkvE+iqRzuU3Qf5fLXS5TSR4DVNBo=", + "ciphertext": "/A2JHyV3A7qg4LEXnN6344RlYW76joTO3fDyO5bWcH/6DoC9EZ08a3/rc8km3+RtPtlckw==" + }, + { + "cmu": "YR2l+jP8tWT+HUkY0bLD6sHCQP31wLB3TzEMHayNywQ=", + "epk": "5cpW7Il8jWuvw7JVu9Je4n0TPXhtqOdG91V3sSlK7Ng=", + "ciphertext": "JeB7PB3FerfXacdIwLxWr9BCBi6+57jFesEc6YElixsO//0QXCqVBICO950SMdcIfgPF3w==" + }, + { + "cmu": "8CERTpgRMUJMu/FVdvEsrn39qfBWI8PU2YF4cqb4ygs=", + "epk": "PATqOjCV50yu7Ny0vpNL6NBqPqmFwX6vUV6eRbs1GqQ=", + "ciphertext": "5uFOS9QstkvYPz9SrObcoBQRxDoxVi4y/CBvFCN29JTCTPgZF1bJh0h+wq3z5m2y/XbNCw==" + }, + { + "cmu": "j7BkUllFcDmnsEsn9dxakJzQS2AtvuXJ47nuXBFPvUI=", + "epk": "nzOheth5SEFHcWkQ1NPLF1AMemSU8pz7MgtlE5Cc5yU=", + "ciphertext": "osszz3L9oVm+NdWoHebsS+dtwuP5sTep0iJCPabRE3PSBEeghfeaFm8PfBpllgih1rEuKQ==" + }, + { + "cmu": "3e5u5kZN5IEnbUarPMHHr+syjHBDXuutCZOiu674hi4=", + "epk": "nTlpgMkkIpLZ8unVftfW5yjx+ARHxmPSjnAjvJVgpsU=", + "ciphertext": "AMfTVgAB/DDUhC0+eHlDY8Zxp3Eoh2IuLYo8ouY7oIRrZcLGSPYXCZGlL6VTmofBws68RQ==" + }, + { + "cmu": "n5pUwBBrwp3GNv42ruFaPMnzYnoBUGGToZjRH1vMMyU=", + "epk": "q6b/MJQXcXP2B2+/MrH6/eGGhau10JgeucC1hU+ER9U=", + "ciphertext": "7+ax4uO9uSNxZwcGMeeTVdfIy1o5HBdGBr8oV/tOD9dYEx0gipOr4bKphfbeI5WtKlV9rQ==" + }, + { + "cmu": "EYbNUhj1ke5+udJn78M2UVrND2oaWjyj7S0jLQ3f/UE=", + "epk": "cGoXHIjns5Wj9sfHGbKMAu4tcHgURqPah7zkXJcOoFo=", + "ciphertext": "eUXUZnJ1T3uVcCvYlTzcZIDCtY6GW/PzqT1RwT06iCyIyYQaCRkdqn7Z7bDC8Gg/fxt2gA==" + }, + { + "cmu": "v5yPIRzr2/dWR6Mel1sLLY/VN24WkMO34eIyG3mrmXI=", + "epk": "7EmLKdd3J2qto2zwd6aYepnh9U6KCfGBtuaEsdBp3Zk=", + "ciphertext": "P6Y26IY1toAqF2kzm0sVfkarFgmsLigHdlM1fqrp32Y6dgKm42TnzABlG/7SX5lyHKrqgQ==" + }, + { + "cmu": "CAOSVRQAmRCVSy73Xbq7NiUTU8H+qivR2BOrewDW7QU=", + "epk": "0dHXhiqHc/9XNsWHfK849vgouBoFbOwGlddlmZ6ShfM=", + "ciphertext": "RhLqGGuD3LkVwjwuErychyDTO2s6H5Fi0uL77ua+asEub3KikrIxsoIlVhkCgdJbksuVZg==" + }, + { + "cmu": "nmYoC+zuDx++adPrLOiAxXX/uzKcWR2gmsUvaNS47CA=", + "epk": "HpXI0mxWYXMTLVlDy912gn57MnWBmVDYl+3UEgdQ5DI=", + "ciphertext": "/em7mCL3cjDikhVybHqyHvh2iSHp7IiaF9SVgi0SVQEamUTMC1TxjnXexwyCeWczz8TBJA==" + }, + { + "cmu": "p9TVwdJVPM+wp3agfsjKEbhTiqnaFhAP9q/xtAJAhRs=", + "epk": "zzfFUvYy6Od6eteVN2xdafauzrwF5vf0JP04bC9Zncg=", + "ciphertext": "yO9iV4k8ecFXN55IPHCsZyoAhcwbbh3ddikFIK/tzmm1+g2gK60GlFQVJChjJOGXN2PlxA==" + }, + { + "cmu": "dkpzPmeS+Qv+xUehCs1aoA4ayFnGu3DeI2l3QjuOACA=", + "epk": "NEfcw2bbaLaor8LUCyq3y6XEy2G/Bjwn4fOUyXiZup0=", + "ciphertext": "qaThf4idvvf/WpES57H7og+CNhk/3BkXgTVOw/bedVriew4E6ZEFWH+A2zAPS2HPAGSbuQ==" + }, + { + "cmu": "w5+8eUrYlqlDwUPPt3iJddPIs8j60s4qyoP9XuAu5DE=", + "epk": "thog/mobQ+La8WA70Ivnkd4Ak7WtlzN8KlIofeRnN78=", + "ciphertext": "POoXg0vOdq2wxas2xPANsa0AKdE4vUBbbZZBfvkMvW0OBKL9kWscVUW53pLEqYAkSz19bQ==" + }, + { + "cmu": "Mlc/S/nJuUmdi+oZKQ0bg3v0ENgdPdsHHs+w96SGhGI=", + "epk": "sOXoy4OquBI+2H3DMRg3BggUoj9+Hq7WwL8ufX16UhI=", + "ciphertext": "uzYB6m0lrGzIj7o9IV3XN2FD8iAnYmncMsCIVEr19JMhbdrzrGL0qx0I1urlqtQcqDro5Q==" + }, + { + "cmu": "2p1Hv6+DW1GaQ7oXLAHXvCT8sWoM9ajvhcrPImQVNSQ=", + "epk": "bBSoL5Z9SPzeCurf7oSgXFVecZcF1vr9Wv6DX3yCqYI=", + "ciphertext": "Hjoe4nrzQBSrwmhwIkwu7FXdTq8wn77bsxBbjAjX/1Uzs4np/YS1zLMLbo4wdGTLgDqkTg==" + }, + { + "cmu": "lArY2R8csLOze89MDcK/MPpJbCaJ9MbMJSRZ7a8jwFI=", + "epk": "Gve9CZLrksGMrqSg2m8Luc959+9ViNhshi/PQzi9rVA=", + "ciphertext": "5Y9vaCGlEjzgSsY893kw4xQtj1yF0zrX7ZTy+l+hZw3A/9Cqe2jk4jSjrjriyTRvNLAVjw==" + }, + { + "cmu": "jzKICbFl+ZKA0Se4AVpjmhHIkvcJ7BWS4DK0kXcymDY=", + "epk": "Sw/Spo9rVY75MlZJY8Bj4sIDKcl62N3oVOy5VJHZcNI=", + "ciphertext": "No4hQg8AKuzPCedM9ysam3pxdtM+m9B7x9GzBwqxNqfbnhND50DrxSrO/C97uM828beNzw==" + }, + { + "cmu": "rNCEwNgBdsu1FWAj+JbXRpCz6s3BkKQFVXd9Vqvup1I=", + "epk": "d69BpU0m7ToP5wfvFSIVU8OJsoxZittBjSxYZlVHleo=", + "ciphertext": "MjF1Mjpvjgxa07YYCIfTPeIplyG/1rdeBTkMp5HKfjhdgdzldn1gU0wdPlHYU7C5TNGYjg==" + }, + { + "cmu": "tfiktw+bk5ItZhVUPUY7nxA9kPn3uunBpZvr+8oV7xQ=", + "epk": "YWrWLIpnxOZ0iuN7gYHd6OLH4XTatP2Kyj+hUHoAGQo=", + "ciphertext": "7R+3dzlyeoBFn/xeXsJUcw+9YcmXSU3gPPAkTYqRuaPtblXqbN0NJWjW8EwRZIl6qFWIPQ==" + }, + { + "cmu": "ikWu5bbx6TeEoeQ4BEN+Hrq227mKX+K5yIl+kuZKnFA=", + "epk": "Pdz7v1d+J4uc874ZL8vH53B/9gEPIa/M4KVYCCVVcFw=", + "ciphertext": "NPfGYU83iNzGbOS3ndUxZku4eRLqDgrAnXVUsfCkfwFSuruE9PtpVfqnY+zF6ynqJ1Edpg==" + }, + { + "cmu": "Kel68irH7OoOSI8W88p7oVDe6E/XVkNJOMB5e4G1FF8=", + "epk": "ZRCpb5qZbNAykZQv9XhEodruepTJXlvOfHUr7kOVfUo=", + "ciphertext": "ul4sFbymQHaq2Zt80TZdO/yO3RTMQRxX4lzJ6RqMGenB5m7hXgppt5f7+gIqZUwAioxD6A==" + }, + { + "cmu": "TqCXGqEV7HtspVwAZQpcuBekZH429o5qv58qrfQG6gE=", + "epk": "x+dZyzcj+wsGjoQaukf5Qr9cAQrUw8sb0T/TVIMFKyA=", + "ciphertext": "uKcsKCxJdtdKSV8u4hFccNs5pPH3/DTgu3CY40sIC4BnpsFO2Bu4lrUzqzCsdAPdbvQY0w==" + }, + { + "cmu": "/rsy8nP65GluJ5Ejnl9Zhk8TwcktuNKx/Zg6qeIcygQ=", + "epk": "wwuecH1q6VyzG0Y9hWxdHfja6SPUYhUc7cabNmVoG6Y=", + "ciphertext": "azeU2pzOijCkvLShdvjknps9+is1t+2LAY82zKt1fglq0tHGoRB4IcyASKnePCZEl71ydA==" + }, + { + "cmu": "Qq0DZhPEl9Z5mtg5LxFmpZCMM5vN18vY9QtgQYB5HAE=", + "epk": "P3E06GXoKBqwbLPFPjFBH34K32Il8dl3jLgKGp4n25k=", + "ciphertext": "S2gDHImezc2bX5uwpW4iuPcX2AXDe5/cz4sAU1/LkfyKlIA+xrGLspGvOYAfSfdU74rNCA==" + }, + { + "cmu": "NL6x6v3Plm6NkUOkrPv/wEYuluqsWMI2kzzsRkCnb1o=", + "epk": "KqJSROzJ7HOCgA1d9AIPYSOpRyAutjgRILn1huG8BGE=", + "ciphertext": "LMsq1F1JiLq7Tb/RqJRpEwpEdOfOTJsFbpKG7uOhA2EQuVYHtxTSmjVWtKA2Hdgn8ZpPpA==" + }, + { + "cmu": "eA3kX10jLZMwDooEh0fhOdyMi5PGF+6DGGCtbz3Fsh4=", + "epk": "Thv8yVptXpiP/4+sQ1jTR5c4nW3YeH8oC3RlNcGucOE=", + "ciphertext": "X47KXp7YiOuYxs94AcBP+Ta55AIrA+A7srEKZtZHm/k0KItpjDVsC6LbXWWYARzHfFmOGA==" + }, + { + "cmu": "UpuJH0WzTxVxcrXFMdtV32djS06RBA3fh3icLd+rLSQ=", + "epk": "OEJpWlTTrsghdFNj83coTLqylFe4tWQVV4Hu20ciaog=", + "ciphertext": "V0BaWdWHwHMDq4bzNSxoIzDeXwai5CgD0R2FuvfZNOdHuc0lZ9mNC6Ai7UitWE2iTBBCTw==" + }, + { + "cmu": "m1gbhNyy2SY+rY1ZzSPAOv69rk3mzPOqFCv0pawlUg8=", + "epk": "2M4z4+XUZaWsQxYiLOIXtCPxKqwHm1Tgo05TLyAWGkM=", + "ciphertext": "hpqwB7FHMgnKG53gTk2nZAlu7nCcMeIqG5HC1arER1l9RWe2+jWNJ9YciWEtXj5ybXu8Ww==" + }, + { + "cmu": "l1GegTtk9WqCkwtMdRU+n/7XPGf36x9xIKW+YXEHYxE=", + "epk": "bmt42iDERvg+xBxhkdXxRxU4qbK4tRDGGpR8HjxuZ8o=", + "ciphertext": "2/LuuQquVX5eZXNfIUZkpGXBjJgwx+DrtJTOs8fN+6c/lTMqM6KNbCw26sfUW2WNGLRdWg==" + }, + { + "cmu": "w9dcm2waAFzHiO044HdfCStwhjE/XFXRFXj9Y4DnLio=", + "epk": "wmb7vs6YDOH6d7qNXSaeqdav3CsYAQPqy9cPMJawrEE=", + "ciphertext": "YKO15xhxhwAcd8pXpIJH8mKB7d8OtkEWhJzDnH9S9v15Ubk8kJzm7y8bT6P23nZUicHoXA==" + }, + { + "cmu": "xcSbiObQokBpO9XLArYbbyOVNAfD/AyhgMRY8pZLhUo=", + "epk": "0B55fIkE+rA/ULL0yw/p5go2Auo6gObxzFmcrd2acqQ=", + "ciphertext": "u38P8OBUwkkJgY0ufp0ENndcFmN4dyZ4HktS4M3yM7K+aIYS1TFt8f9mTfa+GFPkQsCmVg==" + }, + { + "cmu": "H8JrM94fvQvyy+6aIbbJcvJdLDNL0ZLLmDXAjWn/pVs=", + "epk": "Wu8W60tvCJQnhdNxBcdyVobRiNQFsXFAq887gIbNjT8=", + "ciphertext": "FrM63Zt5BOOdf/REjqO8D3Y5D1LnxPe1KQY5QmAcknxxo9NRC4ljqtvS7nwVMNkL43v8Uw==" + }, + { + "cmu": "V/70o/zfX82uHLD00/pU6ONipRUKxQlQudPcNfmZ2Ac=", + "epk": "lh6DEjfa45Mkc2OcjlI+LC6cXWKiRgATt60zfBCsDxU=", + "ciphertext": "KqZVj8U9Pg1mdX3clhfbQEBX2s1FNNN7UWGrshGcyvkyDl/97zom7vp+bfYpbi2pZvkJIQ==" + }, + { + "cmu": "pK+YlZi+ezV4hf4S41k+wVey3wWk7ePXDEGn08JeUT4=", + "epk": "kvEJgg4Clf89vVGoeA9iSCn0Jh2qQhG2su8iiuLslUM=", + "ciphertext": "pQrOODP6VOsfUdMA8Vb2VXeD+p830g2PwveY8/iWEWjnBzhtigF6gXu1PLbMX+gMetQYGg==" + }, + { + "cmu": "/hkgXYfe/PMKL51JulwDVdredSVSLm/CMWqlF1VKhmI=", + "epk": "JZAkKkExcgHgi24aLDBpSpEf5o6GdLuwdYY/cm0hKtM=", + "ciphertext": "Fa1ohi5DkQasZkshnxBBrX5mzTV//vH8YRJgOZRGuxBcdjLiYKTmW71TxpMOItoTPtJ6Pg==" + }, + { + "cmu": "BqGDhfQTyCITtbpLLJ0N6oJhLj5c8SnVR30mai+LjVE=", + "epk": "BFyICXI7uV2MF168mUEE3rf3dGivarB4c7//wpmMg48=", + "ciphertext": "pDQf+eKUJIfnZQ58JXudBt0YU9BGQuZhWU/Q2kn5xPxL0yMIaq0L/M3VN+itncGKVEMygg==" + }, + { + "cmu": "wx0HfM3X8EdAyEpXT0+OKtitCvoHV9y66sNZ5Fnh3hI=", + "epk": "0vYJvR1F5YuggQ7ocUosyltqz2X3ujZxMXIuDy5YNeo=", + "ciphertext": "ZinaTZnZs2khnPuSIhJN6RDJn++7PxzY5WAjj0m3egY6103qrGU3ZcUu593WzjCh5eK9qA==" + }, + { + "cmu": "AKa1B0/py13i4YSRSiHKM3usd93cVzAyu2oNEKVryRo=", + "epk": "qN090OBK/qcc4QLt5UrNqEVctKA6J3BOU0bRR0uQYhk=", + "ciphertext": "xfWh1oRxPxIubk2ftMY3Kgq0RruBGCsN18zKPU6fOTGzrvlnx3lKFXjJ+ofsQflmq0eD1w==" + }, + { + "cmu": "WS9p9sJtRMDHj50EH3eHOsJWCy5FCffJSPrnfI4O3Sg=", + "epk": "D037miiL7F1Vt+lGZuSttQVAKf8mgQD/ZKkWb0h5cxE=", + "ciphertext": "kvqP4Z/bLpl1nBocihFyI+aKuPWoITxTWmfQ8pVe26Y9SF5vmQPjws75u0JtWZ9VTYqz7A==" + }, + { + "cmu": "wJWUsPNTeKICrDM2/PI4rbJvnkbwhxlLRD2AIrqdFBc=", + "epk": "wTzq3q9uEqiikjuKd8SkAJHYEetyLLXJXfWj86pmQV0=", + "ciphertext": "SvbubXxm1qpcKuBW4bHuKezQNVDbXbqb5vKQhf15OpjJjEtykfM+iMtGr7H/zmSkygUn9A==" + }, + { + "cmu": "Pz45877RhaAAPuMx9nA1ur3sGdYZse/ETjKhjL2HOF4=", + "epk": "KKIhAf38lJMzgTMCXOxQjXA4kwRGLqJsj6J66qOBLIg=", + "ciphertext": "HS+5Kwwd0klyamh9SnCuraJRvDI3Lo1wvHTvlQfC09LSoTFZwQldx4tv3gpAHBZ1cnEAUw==" + }, + { + "cmu": "i9m5OWQJU85ePiNgdOwmKWqOmb9uxRVwzEPWsVxChAc=", + "epk": "cME9QykKmehyTslJ3zY305mW14Y+Uw7k51BAx2U4KVM=", + "ciphertext": "PY+6jYY3NjlCDBRnMbk4O8VN9ZrFUtyAxxIQaIclECH7V72NGTr+Uzu/O/YWRoOpu/Fp8w==" + }, + { + "cmu": "PtF86APAUEG5jIfoznXi/LWE9oI20MSsgB8plo50zDk=", + "epk": "8JxNWK9a1Hy2EPRtN6EKXnyn1xVxBxYtWnq0gAjVhsk=", + "ciphertext": "TUIOXsaCWhGaWUSRD2yToXpSnuwp82GlqzW8DFb8nglSZTtbnBe9U6pJ2US9+R7mEj0SUg==" + }, + { + "cmu": "E/uTYV0HnsUMK4P9GVWQRmHl2XmYYY43ubtUev0mhlI=", + "epk": "VGMyQPMa3MRvTpa1zuGpjzUgGqkqT1l/zvrxKpNByzg=", + "ciphertext": "hQiWm8ry63EIHj8KCHfPZTLsbVKsRXlROyEZLva0ammUnhVsMGJZsg2JEqXpHcWoZBl4+w==" + }, + { + "cmu": "gj052anFwFsZtyVM0uekLiCi/HZUHE4/CcmwbBn4m0U=", + "epk": "uiFou78QYQjj5N1e/c5jLMVIq8p4xu+lJ02ZteWL4gs=", + "ciphertext": "9Z9zv9rquuuOJRWJ4ehDedt5AbYrA0qq65pI7YoNe6rpDP2/+df2os/Pq8iv6pel95mdLQ==" + }, + { + "cmu": "owoJ0jRIVPQIyVQtwV89Lm2zoyqc88LRCZSooGlVriY=", + "epk": "pMHkdswBbRetjTekj63TZeOXBXJelsVufNOTJUX92jE=", + "ciphertext": "gpDycBEusW+yi62EhkuBtQbdcV7fzRXB7HllzqB84eRjQQRMpbOkUxYDBGoG2av6waKvxg==" + }, + { + "cmu": "c2c0iFlyYO6ihBZc8tUIl6UT/ajFT56CYCfBAriiER4=", + "epk": "a/kf5zmVD1B6KymLCotqJ325zBAO92IP53L+fRQlQzQ=", + "ciphertext": "bOiVmvuTNu7klnOEIBFRdSQbW+ap71I6K+Jw9gGnUr/dSWOUV9ETeV7cKmDMtrnIRKEimA==" + }, + { + "cmu": "NrE5OTPlITzmnwBVykheS+MgbEDM9r6obVZoparKoh4=", + "epk": "wm2ajTNb32/aejZYLeJ0q9UnOP82NvCInqKNKq5GkQc=", + "ciphertext": "Q8g9O38AS1npCFvkBZocz3M4uDEUYiUHGOg0tMYRTsZQkYwJE9reOzHpniaVhkYezpUpZQ==" + }, + { + "cmu": "Byit8Ah6Q0+ns8Txi4znzF0hdGJKdpvQdjQ04R2HZhc=", + "epk": "m0HJG0g2UbwlTFLE+pIHYw8UA289qwVqAz0eWSgVIrM=", + "ciphertext": "8vznm5Cxdv/4r4jcKPVl35VRdLtTbgMjwSjENOXoFwTnNqxJ9cVltxWlD0Au8aBYwre2DA==" + }, + { + "cmu": "0yjOiCRsRWa3ALRADLXXKY8hx4/LgkSbJ3MpsyF+swo=", + "epk": "mJQWtcSJczABNG8ROA/F9gi44bjdHSZKU5X/eJdS/NY=", + "ciphertext": "NQxUN/YwMJfF5mSb7JoBG3mcXxGhUY3krLVDSUDLmLpAY8r7w95a6kWKHrYkrRR1ixbVzw==" + }, + { + "cmu": "/to8BT2yLcn2hYp2vxNyrHKNnS8/u482jAwwAG9VPWA=", + "epk": "2H+t7fnyGhLD2h5qZOu3IX0gpRd5PkRMsMm/bQCvpes=", + "ciphertext": "j993DkZDhi0DJ0rMCJoOcqGSiDJl5osBCCfk4qQr8C0JiKW2bt8OTMueuUhAEr9dCMXopA==" + }, + { + "cmu": "F7JO/wtcAHQhe004UoZrbUPd2ThbfHTVkxfi0MkXmks=", + "epk": "5M43PPf0yPA/A4mYoZ+8dUnaw3IuafmHifmifJpnOTE=", + "ciphertext": "POt3s7Z80hVmu8zPwqEcr7zWBeNODfQqYXh4QBKin6AfmUDZuaYI7oiHKHeWM4pllao2Ww==" + }, + { + "cmu": "xz5rvlkd70uHmIS7CP6aw8MctZD6xTKERNT0kt8pTyE=", + "epk": "nj5YIVkb130/dClMqs0NRYuPXx0bTw+aJ44gHqDOzdQ=", + "ciphertext": "Fd2J6qYyTMn1ROtKQse+84MZSEDq3yJ3SfqcMhUto30qRks/KMMXWHwm3aO5NnrYwvZ2IQ==" + }, + { + "cmu": "49VYiEz5DHSNWPBxolbsclPf3e+Kd4bbfajue7LA8S4=", + "epk": "RG2EnDf4xv7c7JuZlTsJlM0TFLMqVSq5QCo7mEl5xig=", + "ciphertext": "Sm5AL1h/IkA1fVGgYyVR/OI/pnE66SFHjEvZogjXklH6uiyO7/a30fRnsgq/nlvqrp0JeA==" + }, + { + "cmu": "+YrEW7lvwvHN9bDdk3PFKB2DuFsnel0No2duUB7iMQs=", + "epk": "6WbWTeKnH3xAd+5odmCMCUqQkJBzGdGNUYOlwiI7y0c=", + "ciphertext": "b7m+17oUjpARvxSlz8VNDAqz+FcYaj9foony5+f5agJkOdl0wkYUni88UKncsifkc6A6cA==" + }, + { + "cmu": "HGEf6po+ztNLbUF2a/fByiSkQg4TggTQBU4Z3Kp58DM=", + "epk": "JkQk2z9B97Nfzppg9qNV5X2w45MbkZ67kUZSJkWnsrs=", + "ciphertext": "k+QlZ5cxOa44TV4/CF9eM8qrkdkb93zOLCR0+tw9Dq6MpA3MKKelJNhRMGhRvEBwlsa83g==" + }, + { + "cmu": "7EKoIeNVmgcbWYoq7hLOZkwBezeEgH5BHxCS4nZfZTU=", + "epk": "S1Nd6OTzcdXuWwb/P3CqwlhvJT/Tz+p42HWuAokMsTE=", + "ciphertext": "63pYnigMlQG+B5zsp4ftDA4aK1IyqbxZLqyStIQMXg1eKXIjDoYC6ItTlFFJyKOrd/d6fQ==" + }, + { + "cmu": "GPNsd43Rt1XOU+imrg9MGBFrNDxBsFRrPk7Z/eYAykI=", + "epk": "2U5OtR7twA5lk0x87u81TSXRFW/vhIQc1cR3NVHcK64=", + "ciphertext": "xliafKyoCCrnScT5J7d0QjlaeCcIleKbl3dbAH7dMAfrNzRH+o8V9qFnmNTHH71Vu/AHVA==" + }, + { + "cmu": "E3KalgdnmejEPaZNP2F3ASOgdC2/sk6SOUfjSeXimFQ=", + "epk": "O8lVqgqsQ7uEIykZZGVgNqJfoF4x99grjAedQvl7yQY=", + "ciphertext": "lpkbCYZwKEY6+hdgEGWB2eVeYsi+7dsBtHi4HAGBccvAkwSuv7LpN6N21ixUXTB6X2D1Yg==" + }, + { + "cmu": "ZTNzAqMuX+055tnwJT6/Pevy2E/g7sLpeptcJDrhVxo=", + "epk": "V/A+E+y+uzEusPJxeVS0mxbwjwSeFpjXK7U2Vc3QUOo=", + "ciphertext": "yPK/6bbfwTp6dxR2QT/Tyu06S4GcKgdO+4w27QB7C77sPZfMraejpLkEuAg9gIH2AXGkfw==" + }, + { + "cmu": "YnkniF9JW0h0if/efxmBGfYHPVaxLHBXwU9LRAAVBFc=", + "epk": "4cOfvafYTUEMG9Zsvupse3Q65DoOBKD+0pSwbgX8nOE=", + "ciphertext": "GVxKLvrghtFFAbXFXiN3SJGp+CQnnIAmoI/plk7zOg27idjIwuZlG/4lQ1KHOQgL5djqcg==" + }, + { + "cmu": "oYDwhLvYhrr8bycxfWfIAmxhkELWQ6ljk489zT8dB08=", + "epk": "sYfYVAg3oTnV+7vf2iT2qYfiULAEBuZ8IRSnImLJZzA=", + "ciphertext": "7oXoz3dTQaA6lIUaHkWL0x0KMxgj0Mg1hT2Ro+mCIf9zOeX4sTIAeaGolrzxNEQfCbxSEQ==" + }, + { + "cmu": "CvwaJtMvCaJ8jEE2kCbD2YfLjouY5tibuuDzz1H5PUk=", + "epk": "lOwqCHd6Xe8ZUYReoxu3vFfB1htmDLBhkxdGP44dwxU=", + "ciphertext": "qeLz9msJV3Khzk9Nzpe7VYskzANDOxzmo3QiidnsfizQEutvKPHCubHn1F24qdqydojulg==" + }, + { + "cmu": "bAJCWJs5JQo2VfINvW3vxe6Gp9X9SyTMewmPVVbLPz0=", + "epk": "bGnCeoqRv6pvi+VYtR+keZ/ei0qFXb6Hw04fY9xi06c=", + "ciphertext": "xzQ5M3xt00eyGbMd2zkAPUNoJsesGll08j1ZeU1L7TgmfgxCVSdo/PfMGTXbAOT/9Rx4NQ==" + }, + { + "cmu": "bNnsOX4dX9ZMlzK/81lQ16i6WhOAvzqgz4FpmeUS010=", + "epk": "Y/rouCC1L8cWDN+bzDUTq4BulXGlvO9HBbUDuLefOOQ=", + "ciphertext": "OmPu8fF2mR3mD00TLkfOQNSKJaZ3DcD23/ashlUOtDGiMFHGu1cBRNeH6pzGim+t1F7eoA==" + }, + { + "cmu": "GS/7kqa3oKIJcgtBOQNXwFRPkBfOwaxRjyYQ1WaSdBA=", + "epk": "qBFQw/WfzPluX+VbAvb6V4exf6Zx4xA4zA1SNi56uSY=", + "ciphertext": "3GOa28OyRDS0b1EEyGxXfz34BmEjhC9Rpxx2HcIhVIhH6uIsk09Gy4dhFTcacoo3Any68g==" + }, + { + "cmu": "nq4rnONKYF24oSbl/GdRVl+4fZ0U1dOXx0+6zeyFgG0=", + "epk": "WZpotScbaKpjU2c6WKoM9aUebVQhHyHiLa+1R9TLIyM=", + "ciphertext": "y+OORhY1QflarZoftodsu/B5L59S1SCB1oe/b7Vd6GN9PKitKdqaWVmaj6fE+mwXzJzxgw==" + }, + { + "cmu": "tP3dcFsV9UVVVy7Z2qUzEp7mYMXsfYQNaKDtaNSuw0I=", + "epk": "HqxNpxXC1sg4mQb+ePh9dZDKs3+Lkh/5xP7FQZzQ6dQ=", + "ciphertext": "eBiWc6EAlO8oDeV37+VIV/to/D4x9mEQKq4NfW2Wrij3HGt+v/PTKMK2COJ2PUKlx2yatg==" + }, + { + "cmu": "xjJIjzkM2T9Ds1OV5WkT1Qv86jNMJNrPWTHIM/a8aAc=", + "epk": "4WBIsAD8CLWXRDnpoXwWp8V8NOQS8Qt9XX+vMhhhaOg=", + "ciphertext": "jhhP3YVhb30Qzy0O8Wx0op+dpK7Bdhfi0uUPo3mvW1XvG0TTccmS1fh1RoJAXMMaQv9KXw==" + }, + { + "cmu": "1tfcwGYHqMLtqXKUNIegsoCoI/8+EJqisoe6Acq0YEE=", + "epk": "tjLROe0b2cnM3xUHGO8p7VQg+51sr5DwvVh5BtWhpYE=", + "ciphertext": "OOLlOFcfbNYjNuKvaZINO1dr9akj8AW/kwSoN5B05nUY7LEQJCGUOsBBGRfzE5rVmMSzTQ==" + }, + { + "cmu": "0CSe5c57EYT1yEQrzdBT9c9n+HcPcx05guzH8V2D6wA=", + "epk": "93/V8hv8Oa2Tfa0HdAioh6pfTcO6sx4HcbCRZPlTRLg=", + "ciphertext": "9GqzsFwpjdVpnWil2i4NstoOArcgSJngtBU70oaU4SYz2h46787YqCsbA1gTO2S0JBPt6A==" + }, + { + "cmu": "tgf87pfAUKid2s7NBuxmtE+3TyzqwBgYL/q61wwfJjg=", + "epk": "dXxqNX0gr3tg4jVqhQslqs8ESDVs0hRU56ljyuXBFZI=", + "ciphertext": "vle03B+Z7RkJ4HokAysB1/auk5TE7hIQqkl4iCe69+NazPxPUzSTJ9Jm6+GEWut+WXD9ig==" + } + ] + }, + { + "index": "27", + "hash": "3JHfaOmcrkFRqcUt4KYu2lz+sh1Gs3O9sxQj8m+xBn4=", + "spends": [ + { + "nf": "zdR7qwUdDyyGiHkOCYWl6MZGdJqyPEf3lp2ILYlWii4=" + } + ], + "outputs": [ + { + "cmu": "un8qurH4PL3a8PlukFkRmWlZtKbR0fd2aocc1EOCER0=", + "epk": "t0+XrHg41svZDnYtSi43XwU/zFYI1GWR1mcqAqza+Zg=", + "ciphertext": "/SUkNKgQkivOEmwTrtAs3UqbjXUmy8ATTWTxJBTitpM2jdB3m1X9IlM10IUASK4j5OsH1A==" + }, + { + "cmu": "TmxZR3xozKBQkqGE8lBPtBo+g/RhgXYb5+44t3QiGRQ=", + "epk": "yxlJ1gCB8cQUkQA4hC4Q6zzdQUWJrROJHxPAuvA2FUg=", + "ciphertext": "s5gsp3RH5n6wQPl9JpO08qxXf4jnaFWvBB2cj+hO1fwW4l89o0K48Q2dcUVdroeuOSlsag==" + }, + { + "cmu": "ELoTIPtuyVnujBmg28HHnpmf9o4vP/zVvoEfEqKeKSo=", + "epk": "e3GvTcxEuQ+aT6imEsF2paDY1xzM+O6qrSOso1t490A=", + "ciphertext": "WD7p7Ou8y7AhGsUBkMpCYk+Dy1FiQwTyCWr01eBeoTjlpO4bA2JpmSOfrC2y37v40rZRxg==" + }, + { + "cmu": "H/2ATowK3IM3NGDaa3uSX+i9ieh+9sC4o1PhXUlOtxs=", + "epk": "3JPiwJy5XTsarwhBdevTnDFswbuz+KZDwAkEG2JW6AY=", + "ciphertext": "ylXDSDmqeupdbm3fKxBuC9aBroOHS/OxQKIO52zoVYL7eGFAMoMJ7pnKVHwN7vgJIDZBBg==" + }, + { + "cmu": "CTlEOskSufCWhJBQn2AWj4un3pb4nIj+5GLK2yX8Qz4=", + "epk": "05EBfxmJ+FuJkeX37fSoIwqvlVLpMlW3FRKOdZbNo2A=", + "ciphertext": "jSbLUA+o2u1ax3U4zXGEQeTnPDvd2MFq3OGrmVAPSIpU9cT9nxr99dkSnj5v1EON2ILxgw==" + }, + { + "cmu": "jHyrnFbVpUCqkpSry49JThVVfbkILLVzsIxR5MbdWDU=", + "epk": "SR/+B5YRqk8sm/tjtlEkpqlRMaT6Jt3zBQhoNOG5hMw=", + "ciphertext": "bvIH864vnro4Nr7k5LbJi4J0hPqmJF4Kl77am8c3B3avi+WXmyIXe+0wpIoieN3rgNkXIg==" + }, + { + "cmu": "X3zMUtQS2Of/UXofxuqb17Z2975Ni+nUqkWAoYPXQyI=", + "epk": "Mwxu3HHjSMafKZgAUj91AFuXDkzLStbn7rWY+LBT9lY=", + "ciphertext": "Z9xsePrGjJ19TltvOE2q2qXuvBFfzOMFKGoWPA4vd2QIwvuLp//xAfZlD1PDszfBr2zWGg==" + }, + { + "cmu": "xiFyyAff6vW8+UVFnxy6HqoCT8G5fsp7mERGA+UNlTU=", + "epk": "uJ3p4HLx5+JvUSCGxk5IL1JQG+l8OXQUKeos44ib0h8=", + "ciphertext": "Se1igY1eS93NtAubSg28T9ekpQkKzasvV8baWJtPg0Z54MOF+jyulMEIMUWtB/i6IwlVSw==" + }, + { + "cmu": "JOLXXg32OAuDpZcYkBPILU3TmW96RYzVMrhIsy4QqWU=", + "epk": "/SnJlgl9VAXfI9rO6ILItDbrPWL6X0yEAFmSyrHtiM4=", + "ciphertext": "Phe2HqKVbqg/WwcNiCi0/n1uBJrH8zWr4vcL3P6/vnJofMiaMdY8azArGMWtsM+zDz1qYw==" + }, + { + "cmu": "rSOVunUWxYTvVasce+N/ILzl9uaeHdQkB6+vArj0s0s=", + "epk": "Oh90hFIGab6RRtYYkcgoRRaFMueEikmxQD3dMVkW8ss=", + "ciphertext": "TCwU0K33dTDOF5hwJubJamyM76kP539/hQefq3IPIUka5fSix0Xe4l25HlwWESzgi9uX+Q==" + }, + { + "cmu": "CdmDLnrRDNP3ixLEkHsmJkaCyJpFk7trrmwlAbd7d28=", + "epk": "6P2uX+zFuH0/qNkWTlbyxORMUG6yco9DJiJ4jwF/lOs=", + "ciphertext": "LGsjHjWwtrdCfVMzmYJdCdF9BE5+gMt9aKpg7yXr3TFqFElNYgKSvsRus2hjawMq1jSBtA==" + }, + { + "cmu": "AmmdCS0Meq3kkgcFBVD+Y+fobr2Z6fIHKO3SzmNx8Es=", + "epk": "YI6iZIIm4gND99Im+D8EMkADXPQysC0xgZvjb7S6GKY=", + "ciphertext": "k4cw+jcOjnzXuph5kZZPzn+ORsJgz+4x1REDc+MCBtwYWkPYza3uknrCifoWPo/Zv+UTkQ==" + }, + { + "cmu": "zmEwkom6gKaLFLV/LPYgwLrbUJlOZRWxMtUgVrDe8F0=", + "epk": "GhLinwcPrZZhELujKW0rv5TVWBx4XsS/r0JbunXioFo=", + "ciphertext": "CLE7cInhkB7+PTlE/S1xS1avN/JzAMwrew/PgCDYCib1jdUYCX96voRGc6oW/gEv5F+4Nw==" + }, + { + "cmu": "adZDEj9WSLOzCj+wm/4A3/vz6DE0gezyoYLcTbHmAQw=", + "epk": "0Vv8t5GpuTir17/uAInCCHh9Lg8tTFNscIWI+/aPyKY=", + "ciphertext": "T+6xK8tTNEqdBk8Fpt+4+J16UK4KV9GsDVqk2fcOKGeuWtHLNIR1aOfD4KFFmshYvfJaZw==" + }, + { + "cmu": "+K7LviV7mEzjuw+fEhgawKIUY0KHuNaioCat62dhZWk=", + "epk": "tXiFVKvsOSP375zxMTFlZUC3mAax2KLNjWws3WXLhl8=", + "ciphertext": "HvkL5XD99VpkhyTm6vaqfDDeKdOtbzaxim+PuL9MiYqmmDHn8EFRCvG/EBaYzvPLz/vJUw==" + }, + { + "cmu": "AbIRKxZ63rMIrcSgLoJHcjBvg/pZPbMxmD8eSp1+7l4=", + "epk": "3Zpyjk/u8TTpQd5kKv7m8vrfprkelrQMve0sgWy6Y8k=", + "ciphertext": "a7jHq4SmbhIUsBc4Mi2nSFEtdVMbhfSPeC23nsGfb44wyBz7E8/qX1yw2RL0cmKWP4uTvg==" + }, + { + "cmu": "tAiqo7nZS9NxOxt5bGt168SstputxoT08Iet3tg0OjM=", + "epk": "yow1WSftCFJiCIfRO3simYYsnqjsSKWI4CE+GqUqbsk=", + "ciphertext": "cq4jn0067/mGWEIUU2NsJmC1V0p8NHqQufOLAKx3y8STFC+9LjqJuo7BwPP57gAnmNEqxA==" + }, + { + "cmu": "SmTZK4aSeusCN+maGKZWkYbVaB39AGbewTHJW/+MNW8=", + "epk": "LgUMtrZ1ELohYnme5H51Gt4MmOKp50RVxg1+EmTyRcY=", + "ciphertext": "6aUueg4OcoTUol46ogGiAberYEDzg2T9NtgQHCTbrTKH5ONGX66ZhBWlswgakO1gp+wdpQ==" + }, + { + "cmu": "lKPtyNwG0pKmt3juQb8CCAmsVVDmM8DRNkGJDJK1QSE=", + "epk": "xIKxzbEJKMIQ9euS94BDgNAH8leKFuFdXpoMmPzbts4=", + "ciphertext": "Art2/CMl3ExWJDeyk6HQPkTrA7103mIXjD7gJgZJA5tn5HzG9lmYT9ktmmE6HZsjgvKxvQ==" + }, + { + "cmu": "cn9n66Ct0IrNQwnmy2XjEzZVgomJZgJC00/p9nzRn0E=", + "epk": "f9yQ/4yNdWsxljLGOXrG/TS8R9aqd0yUwGc/X4vpWFY=", + "ciphertext": "AHqrs+YZ+Og8KqiisUeqZYWgD6IZZ7YCGDjnAw8TvQ3xGW7GrxumQFwQKHlP84AVCP+PSQ==" + }, + { + "cmu": "fSM9ezurloGJE7UVDk/xQ7RGgV09b0i8SFNJwbjR1lQ=", + "epk": "xMU8qW+xr/YPEgvqu/8GaoGHIEpUgKZL3pzNSz2qEpg=", + "ciphertext": "yxLNQp/ZRLktMxPSEBUOXx9khXBBk6hfHkSvBeONwJnYc0+cTrOm+e7l1+VZLJd1pnWYNw==" + }, + { + "cmu": "SNEJXTXIjqzlX7PF4apOPPe6GPUCEl3kbATXOa423mA=", + "epk": "V+PAXaT2XC7dzwbmL7HnaDHiDo4gGeI3St6DgR5vvfI=", + "ciphertext": "DNkAw57xc3aOhqVEwBSsuDfhrgJ2ZtuYxowrFm7EJKexw4mmqDyN9UNmhzeX+7Dyw+Z5sA==" + }, + { + "cmu": "Q8kzCNEXJYdZcesJudASr8AN39UwQwTM1w5/7jSTOFI=", + "epk": "SjGFIFHC5CLR7CqaA5TSaTWtiVA6mDyy7BtjG8GGed0=", + "ciphertext": "D+7vcHv0XwQLgTpQKeNRPDJCUUVpAnCIqSUphosrtWAtwgdEvEiDVBDFGbPZSd/LfuxMGw==" + }, + { + "cmu": "gMDlgGokemJO4cWkokRPncacOV4VpemZ2XDqMvnmBk4=", + "epk": "NPs8fsqNTNeV0oNdThYHTCPLVjQC/Se6Bvhy4y58QOg=", + "ciphertext": "PipN3opqEx7xpCbj+KaRlfuj0GJzGgCMDoM39ym7bqVZi5fu1+9daYHw+HMRXt1e6VY4mA==" + }, + { + "cmu": "GUmPZGMbflS7YZGXHYggVzLneXj20iVj1aotJSNY/2A=", + "epk": "fWdPpRwJpBtyzHjy+djf+qVIqe7yKffheBxcDJSp+l0=", + "ciphertext": "J3wDssGV2eQHanKOszU53e+/jXMnsP454wMkxuSmU0Yw6pl2FdLS2uj9aSFeIpnw8sdbgg==" + }, + { + "cmu": "WCQ/t6EV6zdgipRrx9sHeAaIZYCAU4xHHRi2ruOTUg4=", + "epk": "+syJZ7Yr/L2ZbShAMIU6DhMpUjqBdlSOF/HUhDiOXt8=", + "ciphertext": "5yrDLkYN0WgiEjDEPSipfP933neYwKKQrlp1ttMDEpJA80l5usb7X0+nIxDmeJva+XvAyw==" + }, + { + "cmu": "hCyWGzBhxKwG6n0ZLx5/qrzHLgrLXzItI8uZghkH3Vk=", + "epk": "Ij2OsLRiilEOlXEgZGWlvY72NsGg25FtUd4xdtQBGZg=", + "ciphertext": "LzOl7BxPgCzKmitRzX0x7NaNIJ9NVaY3N9ixI8G2W/vxfiB77N3rIt1nChgMQlh1bjuqww==" + }, + { + "cmu": "NdPim2XqxTMwzF/qNKOId2+U9BLsfHwG2Zn5y4MZjVI=", + "epk": "lxNOJ9ZNmHutOW8CXi4h+xOMEz5E/ey8+FUKrXHi/DI=", + "ciphertext": "CNUMyskoDMzjcun6uiZnRy+u8WITkQEkUKs7/fOFk9Q6ZYZZaIdLKe9GYN3sHBrUnQ/ulg==" + }, + { + "cmu": "Vk24CSLh8mVEsp0WEjHnJy+KLBYoKX9VMwZZmIvK42I=", + "epk": "PrnU/Q3J8UdU/TFIdvc2iwJp/7RKPu98lEGeo5/D9k8=", + "ciphertext": "DB57Re6fJi2tWEOcIsNr4rbIy1Z4CK+xsQ08opzJs72xstkX6cct01U7j4wglEef+Faohg==" + }, + { + "cmu": "PVLPTX9XR+wakidSsNsRc+HYbm4cO9MsFk6WFthHYAE=", + "epk": "U6Ys9MQbeH0x1A7wrexLiXLFpf2XYLbRWwJCdKoppaw=", + "ciphertext": "T4HSapJeopuQAiOh5ftZrLQu5ougqXsitZmTLjkpd+Fb8yoCgzLM88CC2q6r+vIe7XQe5A==" + }, + { + "cmu": "y5W0NHfqhHBhCFuutsRAw4NzOZxf1j8C+Zhfh/Jh/iY=", + "epk": "NMAF6hVtcA/D6FeKDmvFwQgHJo+/X+OyYv4saqZfXY8=", + "ciphertext": "jPQl6xKJsIoEL2oJzgxKxwsYSOrJokyPyPo//HfGLwKw2dcRbKaQ6tVzABImFzzbay/MiA==" + }, + { + "cmu": "bncDK9F4b8/Z5QwwKv9A4OnHv9SVbAW5i6yl3v/Rxlw=", + "epk": "wMtW+OH2xZkZUcpDHYF/De/OfbeKauvoSEX9AuZHbbw=", + "ciphertext": "LAI4bLUbSHC4GWCRE7+AkbSBry+xjw4cxJHyQeUec+U6/SYs1u+9wo9fhVmdbJbv4XeZHw==" + }, + { + "cmu": "1fhbisyzTpanK+rtbCqlRsvPnOp7An2G/9le2uIQJCw=", + "epk": "VwUig/W4zTzV2ifiiAoM2sqxKhytiTv9TKQAJRKf5LY=", + "ciphertext": "fAVzbY9AbpxlXYzDDzZEZ0ziWriNLeheR7lglxOZga1uOquwiz+jNIEeNrqAWm5IZejmug==" + }, + { + "cmu": "M9VvPaUA8RbASlTmblPvqm4YGOvuH4VKlPZ9Y9Jl7gs=", + "epk": "jNtJBllnpNzZ07AVSHxa/g1gUze6T54WLp19z+mPWTo=", + "ciphertext": "G4Xc/vQxj5CZwQ5mKWslUZM2rCwF2AuB5wyhpVUsQxBdYIZm+MIPnYK+99H037FA2f9S3A==" + }, + { + "cmu": "nKdWalArHy4T63k1LXfPRdTXkHxzuJhRTpEHWUSsSkI=", + "epk": "1uTEuYomVbkhnbnnJNnMGfdel2nSGAC5+W0Cd66IZow=", + "ciphertext": "skB6ycGsYCHiITFWYuuW36S+Cvvv+51hWMJm2LI+/lmY2twqGVLMDq48WqHYRVp6q9yFoA==" + }, + { + "cmu": "ZCiELhqbLBgP1vPkH0OihNMsL68qZqa5pqZIkK06IRA=", + "epk": "xA93bBVAsHWgfelyR3rOTbGKrtPIkaJXvb2jr0QJLMI=", + "ciphertext": "O3OV+/MmMU5qSG2N3Co/BpXsZMdSm5g76Y0avGXPUTPm276XrTKwND/wvjmaZu6ufMDAiA==" + }, + { + "cmu": "Q1msXkl5en3u73Sda6wg1iQ+LjU7GMEP2YJLKmDhu0U=", + "epk": "SP2BPhlZ91XFbF/ikOQQAL3ZO3Rr/yEI1B5wbhVv+NM=", + "ciphertext": "JWEJDxKydVG92IkpJOO654cHKHOlXdjTqgexQ/ZZuNf/F6UhC8AMLb5QqzzYccYKy74vaw==" + }, + { + "cmu": "bm11vpY8Fbb+VJygeruz6Y2/5/b2gQVh98sI4lYmJgg=", + "epk": "+bvEesOv2CYtR41t4+Ychg0s6lA41s4txLgQsqUrx2o=", + "ciphertext": "gd3G8f+mXbB9nJxW1v+cAtoTHQlxQAMepzrxAlyJikygWBfIrvXcqtWQFLKDm30kzEsWqQ==" + }, + { + "cmu": "3KdAiVTtSkCC1rZjBAQU4gNBGxowU60cJkPbBhlpCRc=", + "epk": "AHm6FvLLSaDYPJ1MlgwfvAlZqKCJTwDLpk0IxThMPQA=", + "ciphertext": "vyKvS4tj1CG/8xHkPtdSX1X3KlXRdxHEmSGTLy2tA3UGZh9dkNsgYXS0i+bOPq4jtn9BcA==" + }, + { + "cmu": "9TvdTBn6sGCOrV+ydH+BXUQEEl/kdIBK3/4dICxZ/1k=", + "epk": "ZUGBMxHZVGseyl5ZjPJ5AiXQSEEKBM8cBBUkibPJlWE=", + "ciphertext": "CTNBJ3xeCBEFh2g+VBz9I3/6pCa9eR2AbvlvRUJ1FYjZZKtfERPDHU7cBGPhoHa9Ul5Fkg==" + }, + { + "cmu": "Qtq1kglmS5chf8goSuOa4Uoc0//9RcELK5nkf1Js8go=", + "epk": "9zuGNvAQvlENxfqPYUd8So77CmbaRhg72PSFY3rLfas=", + "ciphertext": "ShqVbwWyDYHwMKk04MlfbqcA0iCO5cuEVeWEuOxhz3Oi6g5bGejEA0dziZ6lHUtOO6AlwQ==" + }, + { + "cmu": "Y0cFB3i6uOa2eKKaF3xD4BeHKHu4xdiTudIMHGarXWg=", + "epk": "G55CH6dJYiIjcQNiyGT/RN4Zws83pLpxN1jFNOLP3hM=", + "ciphertext": "eZi/Fy8I/2p9Smkr0AnaTP11XMAopcAYsHeWvJFhYiXU99+J7uI8v3ok5nliiYWrWEmUtg==" + }, + { + "cmu": "IntB0y2HT2UvcTdWXgPFfNplcZJeo42n+itKpTuuQwc=", + "epk": "APgN8iD8bWuIHaCyK4XXAiZywlHNgBIR12CWW7SmZuw=", + "ciphertext": "lsXLsdLO056G+r2fdzJ8Ds1xMz2XPpIY9q59la8sc6p9lxbsq5Iw8mrF+tPMl9+m8ZxBBw==" + }, + { + "cmu": "AKUBHRUlqcQ2ogxeDqhaRGyDUXNYr/P08Di7o40w9Ew=", + "epk": "FKfNwL+gMyj/0Q03PyA+ILIpC7Lw78TdOHmJIIXxDoM=", + "ciphertext": "QHl7SQwuSsXfdPPrQkgZ89AiIbFVJnEVu4mEFSEpPaauiLg0TrrJMP+J0VwodsRTY+C7xA==" + }, + { + "cmu": "tbb8rcg2BPlXywS37QOAvx05tofrZWk+EHOduWmUw1w=", + "epk": "rHkXuSPvkKvEruQW0S6lSmZo+B1dIzMDBVhPaFnBqw4=", + "ciphertext": "bUlnuo6jeQIyG6g1oKCyqjxKSzLwuhzzOPij2d+558u0PWHrP/p/JzItFKjux+VkyD//Mw==" + }, + { + "cmu": "+zjvULI09p/QW6Aj6C69XbFnN0X5YKFcf/nFF4lMrTc=", + "epk": "qEebSLKdm8d+6pGcx2L4h7Gzw9FPLNua1qTqnsM0MFI=", + "ciphertext": "ROzwIZfQs8DhBtBwED2rZ+AI+oiegF1XRb+Z2M6TLG5S2jz9ekQcchoHWCn5ruB64CZIgg==" + }, + { + "cmu": "0w04yH/Wx3corRxaHY3rFwyTywh4BX/gLJr8Sz1cd1A=", + "epk": "FWxjT/qElXSLZWrmDT3dJzpGX+Fu7yQQ9cEh0GuEFqU=", + "ciphertext": "LFqjjuhVuE7g5Z/1fW1C1X56UuKlkzfAkX6OrHraoC5+VrYTHzKU9cBzcGzVqXz167rgQA==" + }, + { + "cmu": "dbBpyl87M7hnHFHZTpykbxmfJCov/UQgUfNW30bHnEk=", + "epk": "SIoiJ8y6aqy/HvAd5hK6hvbMS9SBdchwran0GNT5b8I=", + "ciphertext": "YDArfqQ9cPFzqENnOnPJWDEBBM5CD5tO6/fZvXkx8Fb7v46s4TjgfagK8gR1hDPgBgb/6w==" + }, + { + "cmu": "xKmW5i1mbx7GeOn5rFuasq+e9p+ikfMpb/0KOCAeGB4=", + "epk": "Fs9+1RGjy7yNm6MeQcyS7JSwm2jMMSuFueFq+nZe/LU=", + "ciphertext": "GoqoU24nsaolUAhK+cFHcVmgrCXko7wV+LzGZi6KV4Rp60RIKdymd5d/3MoMrhm0RP8lhw==" + }, + { + "cmu": "SxmPjpLkyjvXHm6JzfPTNjrbiIz/2KyGRr6B89FTq0g=", + "epk": "s9hsy8JIYO4udpAtEOTtn90/zj18VfgKAvoaGyq4neU=", + "ciphertext": "U2iKxhj1sXJrnongW43Pi4NDteo+zEXenVkpkgh5tkImyqOLBTfj1LgV/Z36sCgSvafJfw==" + }, + { + "cmu": "++It7fxJpagI0CLclIUoFlFOVvMIN2VB9gwLc8LSxwY=", + "epk": "VVWbas1IAGuMdhRXVpTtA2Bl1LyU2wxhBfxOMU1Oi5M=", + "ciphertext": "MIhrx6bf8OEQjfyg95oaI9YMcgY3ZBtw0/AbQIgJlCGbdrVG6ZyYU+gfJiy6ZwUQvztQtg==" + }, + { + "cmu": "uLfjRBotsRthU5R6wbuL3t8UhsGLBNMUPG2pRrt942g=", + "epk": "gPirymIsGU7d1sE3ECgKv8ehECoDPqshPqSL+bPeyk0=", + "ciphertext": "9HVH0hB2jhsNFuk8hcv5cjQRLk4KGbP4ri1H5K8zEA88XY/MDCjHsrLMjGbkmxnD5RdC7A==" + }, + { + "cmu": "xidQb8ptddXu/tsnJq4419BcpZWoxbeXIsR2D03o7Uw=", + "epk": "ZJrMWYZ6RLxTpiqRGudRgflXDP75ox6UDiW4Jrxqhhg=", + "ciphertext": "mWAZFHHU6DaMxTiDNkGAw3XOHkzv5wCtHd/GxD0pLDdFOpSIqBNqwKsymRuHb6n1+DJumQ==" + }, + { + "cmu": "O3S9wt6AUV6wxT71uz+gU9h0PpW2crCYw4xzxWWZYyU=", + "epk": "Di6G3OVH/AsMQSoSUsb/xdMU6BOP/F1CygsochjwI6Y=", + "ciphertext": "kZlDxoThgYRGrJYuOwCeExCka9fO788ljYNCY62yM+gSe1LVdMIeu6Z707IkKmE8vtKx9Q==" + }, + { + "cmu": "75Kw8aDcuiZNJjJPYXZ7ldY6HnGMp7zHZam6l8dY3jE=", + "epk": "H6Zebv3gO3NwkiDHnU8/LH9eDoD9ng7cUOW1ZSks+GY=", + "ciphertext": "I/k1ImS1UI1QDYXmjKsE4sL3mcChQ8wnhtR8+YIf0rwpjkCD0kOYdE/Z80ex8wMULGmfLg==" + }, + { + "cmu": "8bvGyfQtOI7MQrtbvE+EVNIT7iN7JJv2UYuLXfZ1e3M=", + "epk": "Cpv+R5Tc9UPdxv2bTET1h46jnEFq2AGrtpa6tbahjfM=", + "ciphertext": "YTDw+NXLUdiXmLHbe+XL/FZdwqE9dCAxtjdFRx8YRkl/NOcgQmXHhCsw+fYuTIZN2qJ9Aw==" + }, + { + "cmu": "vhQpGNoE/SVpxAxVzar6lVv4ClQtbh+sfoP5MXCQsWk=", + "epk": "1eHxO6KRFjqyzmviSEDo+MoeC8/7xsW/F6mmQ4yP7yk=", + "ciphertext": "161+276mCX2/5bZ3mYbPFAl5nJgQxyLPnUn1H1KywzlekvilGjMQeRwgVGpcDw05n5idIw==" + }, + { + "cmu": "T5npYsFbcdrOPCaDqTq0WGSCqBG31N7IVVrsnp0UgTM=", + "epk": "FkFHDM8nQf3JruSzh2Jaqbl70nnJsD/HD80Yc3a/K+0=", + "ciphertext": "9qmDVrWc920b27Z1h/71+GHPjMb3Ie0L9QvvegWFl2GR3AS18GCqZpMh2YGJrMFO7xFkug==" + }, + { + "cmu": "EE9dKeOVarVg9wpBwAHcTC6dfsZZ7WEtzlVuMIzhLgE=", + "epk": "8vfcz9c+EJzMaflAz5Zpwztcw2q9TS+KlImcwjF9myM=", + "ciphertext": "fNIAfvv2AmZ7hCXPbV+oz4m6FZXYuK7hSrqLDcZk/1qN3/tq96SFJBMedVCVly1uGjHCvg==" + }, + { + "cmu": "xRqKFBhsPjbXjv0na/jRVKN3bTfwuGfqNM8AmkNOET0=", + "epk": "Llqi9f7Zd0iiCGUfJbshT+e5JkEfGJs3bMNBTWDWIKw=", + "ciphertext": "aZh5uPQo1ujD6Dt7hNqQaZtAEJn3TL37eQUs/p4yCzXM2WgNJ30Et5GoRHxVJYsor+afcA==" + }, + { + "cmu": "y/ZxEHWOWRjOI9ViyWps8Ub15Ghh4HMCgVNi2/GKv0k=", + "epk": "ApNlr11hjZ1ss4+v0sT99DjSqt7yq6JZu2Ne+0ljPjY=", + "ciphertext": "SAmN75q7Nly3EqLsZ1ZfhwPkRC01Bw93Y/EcZnukiO2Ibv4i9xy8DGLQ+r1k1CcTWdLFmQ==" + }, + { + "cmu": "W9f3oedXFbsE4hiSKH4ZxviJVbc/3Xdk0rkcUOgf9hM=", + "epk": "0o33B8mN7Dza+ULfqp7Vu0AdyinLxdJDO1qQMvctXd0=", + "ciphertext": "SZRFCSW7iPHmBEr29FtEF4YeUwt7AHAKaY7t2K51fnILb7W4e5hQD1+2QdSwTlaTcegWYg==" + }, + { + "cmu": "Kmt80fD3+cyLcCLaV7PFuOv42KfLLD4s1EqW/1oqxhw=", + "epk": "Ln4+JaxciwPpenXObvIf8TDsHmHObcNOWZNqrGMNNIw=", + "ciphertext": "HM0akpa0MAOZ2JliJvimHT/cjszs3EHnNL5gw6jajxMrcfAMBaoepFI1zolK7MH248PDxg==" + }, + { + "cmu": "mLlLH2ltWRsAEAfzszR9YnEptqzT+x+Yf7FObzjiME0=", + "epk": "nY+HipUaNtaL8BVw8H1midIvB4WTyLyF3XRRI06hT6Q=", + "ciphertext": "MVgOC40Wg82ommqVcT+MvPWXcHDYsdqz0p4vuxyp9tZc9BsMbcnGq1sscbvEOR+c+eDFHg==" + }, + { + "cmu": "IPlUq5J2FmP1GEKtepc0bUVCrUS2wxb2pq8Op1DpvyM=", + "epk": "rMbf9nUp1VsPAcrzyiJJs4abtI225tRO0aDzT8+iWdA=", + "ciphertext": "lFrh7TDVpJFBaacbmpI1/oeBsbPTkps2TeR3CY4HQFgkBo2ht0Jiu3xOy7oqG1NzS9w1UA==" + }, + { + "cmu": "/eOq78DsZVpa80xFPQX9I/aG77OGouq7ujJ5xGnj9EY=", + "epk": "//w98X7mVRNVNIZRn+0gFlLvzukKMFOygycUcSYLN7s=", + "ciphertext": "lnpqvNSK6hy8M0kc6vWzgMl418uyyHBYNsx6z8SYctYnFcVF6/wmohJoAAft/0gyk9Vqfw==" + }, + { + "cmu": "1iQZwjcJAtvGnZFBbZUwDIZR98uM2q6+W3g6B5+MyF0=", + "epk": "12rX3b3SkMENybAaWXZGemwLhsZ2mWtUFqQAFgnAMsY=", + "ciphertext": "zeIjbqxDuQi2E4UzStyGn6YOyZhiDDDtwhop90wUciVdsPH5I8gXgegRqRkxvA09cvNTqQ==" + }, + { + "cmu": "qv8/4D1Cki0lPIgBzw/OvTo7MYod7ZOblnyy64+8YwU=", + "epk": "SwRGbLIMR2dtWdnPCbEklU5Xu1S+gQInLhDdjrFOVqw=", + "ciphertext": "QUDQUt/dp/13q7Xb3OX1px9CVK9gQbezcexXSpZ4UKSla65dxwKYCaFGNmSDAGxivoU9vw==" + }, + { + "cmu": "4Xvm2D6qiDY88vbjmHFtvQ9vNl219slEIkfeAE+rrg4=", + "epk": "4jEA2G9jLa093wf1lDSrV9MNUXLNx3KFghZIzZ6BLD4=", + "ciphertext": "HCNxcJ8E0/GcuwXTh9PFkhYQREwh9jIjP1GXfRLAkW5fQDISWszY4TzDk6tTt4ptk+P+qA==" + }, + { + "cmu": "++ILLWaGAMMZc8O9iJIH09Ewf0Gc+8kHnfOfJsCohS8=", + "epk": "R1LXIRJbszAKc90/YckQHRYpt5GMflVRUgt2NoO9pic=", + "ciphertext": "r4Cjyj+C0YzbJmovc6CMYnGQYGDGr2mtF+FiiujPnog02X01RaA31hpU8qSL6Q2EhFfAvA==" + }, + { + "cmu": "chu9222+YcLMspeoQY/W4qwf3fFxJenJuUZvx8lQ/hI=", + "epk": "wyCQIPRa+0tftSB+Q/IioTV1X6YDJiTE32DcTikbfB4=", + "ciphertext": "SLMwBkHHnvnY1Irc3v2z3jNJ7+xBdrbxqvv/zL70hHjEMI6rzVFsTV3hkI+m5bRJa8+ang==" + }, + { + "cmu": "9MuGKQpz/lKOtlKnffxqcbG9K6mP1vWvpxu6DCGoc10=", + "epk": "uaXxLwb19kosA5mJm/fu4KqB9PQecG6+p2y8UCVRk+Q=", + "ciphertext": "i/U2J/1TtuiBPoaPcXraWBqUqzAycuWCgsNa0AGboJAA0K4WNkj/3HJaTY2Xon944yI2SQ==" + }, + { + "cmu": "4mwcboz/fPQXeCGCr1fK/WaWgXe8oABlUPdSen0HcVM=", + "epk": "/KJdnuM3xPRrEeLILOWkg/HDreNSuYSWiVZEdwkKS6A=", + "ciphertext": "sT/V6stHjxLwl24pnvV2jjAgfi04879L6RNgUrAigBwVt4gueLNcsdq5ah40JI3E9PImRw==" + }, + { + "cmu": "0/VYdueS3vhmP1uRyTOLgJu2QCwSFsJDT7xXOp5m4FQ=", + "epk": "VEzTi1GShrfk4+DVkY9yexrHj+xJdxqN7/bKYX+oCY0=", + "ciphertext": "gTDKEXKl+E3BIYZXVz2l8c+5ROGvbiZh5VtsuMWdkrxSfJc1wm67/8CAvQB278GhVXruxg==" + }, + { + "cmu": "xIKHvafnFssHbHYW3WMweoZhw6DKXti2itu++scNm0Y=", + "epk": "Fug37Qdn2A8na/WsyPckkjX6FGejx+qn8e5xRMp71ro=", + "ciphertext": "u0OILXJWbmIF6qyIVv/S+7yRIDUXm5mNzr3XSmcHczXvbETTmnzq28zrse6OrbCfqjz51g==" + }, + { + "cmu": "yvRDBq5CgLBx7sPkeBh7Y45fD2nJ+5BVZ1cX0w2TFgY=", + "epk": "fKv2KcnnppSm4nLhG5dt5ynLj8W+jR2ipKo+6DF099s=", + "ciphertext": "abTSswH9jaPfwxrUtM0MvaHznwEEvA1SxF0DsmUkkXmvE7ZKV9/N+rs5JMz9CgUNzW/JZQ==" + }, + { + "cmu": "hMwuPsZTseFiEdyomsYzafid8+Jk9HL3QIac4tooJxM=", + "epk": "Lv0kgz/Fgv/EPIJoiY2of9rR4Iumh6mgoicL29vriGI=", + "ciphertext": "M12tahaUjiw/M5TXGfV+z9nuSa4iVXH2icLfzT7nSGBPSWXjEvyk0dXErVRjOW7XDWADyg==" + }, + { + "cmu": "encl0r6bOuN0khJ62eRxUs7HeUQk3cKCmsQKjF2g9k0=", + "epk": "xGp154dqHa5I4/9FdyPwlh2OiVEygeT+cp6QugR32go=", + "ciphertext": "fmGiyq9MGRiS7/rguskKoeG0IrHFIN+s5atkvDceH4kdX5KwbGiGXzKGQeUl0d3lY4OxaQ==" + }, + { + "cmu": "d6CWj9vOazll2z7XHI27Cy7ZMZ9AFpzzSQv2zdhsGxs=", + "epk": "mbw5h95Wwjij2HQO7rd8l41gILJWDrlnL79rruBgSxA=", + "ciphertext": "EZtjazvXYr+TTPg1GaUKk9q2LRAccJwpEnjE3eizsr+kHs5j2wdlMcE65RtNGW9AxRedLw==" + }, + { + "cmu": "WBn0r3pLSWavG4k6SGmVVaxNxj+XvDmkz9S2iypoARY=", + "epk": "+Pwd9lvO1/jvzsY9Zrv950gfQ+akbZJdegi6NvGX54g=", + "ciphertext": "lbhdm6MhWnOWnLorXPIvGJeaXLVHtDBNTaE2T922mCNRp9SD6uniprYukTBTl74gjbqIgg==" + }, + { + "cmu": "907qRk7h/DANOo5w1zEFKaS+dwvraFKx5BEw2mBxdys=", + "epk": "I0CI7UkFC2TLbfhxNLo+N3aMVwnCmBnoj2MXHJfoEjw=", + "ciphertext": "QY8g6wzW6DdRCE3Alt+mboAy+WyKZSQFoteNhStgQMfVPVDoyIW4nuX5QYJ8sDLaXidpaA==" + }, + { + "cmu": "UXLRrqtuv8WXULx60QpMSZ8DlOd61epbEEHg8nNbol0=", + "epk": "j7KiwFWWJ6W/zUhrUt18nbSWjZP8kiCL/PU11CKvMVQ=", + "ciphertext": "61ZevymLG5RIfMApzW1SZtwJ4rddAbAx3uYRZpKSeR9ZxK1SepPokSdND/md0p17mh1SFw==" + }, + { + "cmu": "2YV5fiB+B8zSzm9NpG/JiTxjhENocrPVkfwTZs95TwA=", + "epk": "LeVdRDS1SK6QGAIc97aM9MPA0NtMvQye9CpE0mwd3zI=", + "ciphertext": "wfMV11UU3zOH5Ls/oFpnRc7pXG0UzRHwu/q6BaSSMljFzp2RdwWBKPWr8Tv9hOKZX7ZeyQ==" + }, + { + "cmu": "rxt0pqMF++Hvuu93VAruScHYb7l82vJFE2lzy85oiHA=", + "epk": "eyMcEPzqhTCSnKpvjJyjvI0JaBvNf4CHep9i/61WUtA=", + "ciphertext": "+Jy8LOdKdxpcuaGlJbtRUj9lAfEOFgGm+wMjV3v674hjxbX++FCt1+NLlXspDthr2foMhQ==" + } + ] + }, + { + "index": "28", + "hash": "45Et1qj+NhB+4qKQ+jA4iw1dPXr3rrenCjsMVJ0w1zA=", + "spends": [ + { + "nf": "pxfdTuoT88EqQkT6zWrRi0cS9DQ6D6QVWDw4gdPFH0s=" + } + ], + "outputs": [ + { + "cmu": "N/EFJz7tXc+shoVWhbacr+Cs3l/aaXPAZCunccusCVs=", + "epk": "SjCpFWEA6SctaCkbclzs1T5raxmUJDOHnR9rz0wxKYI=", + "ciphertext": "p7GQphnsbixARFJYJfvaysqIQ7KI42g5XIUam/bJ7n+SyfZlZAVT3GIPIKm4hBCxe9wL8w==" + }, + { + "cmu": "e1gyE4w3doFZVBcoa9Ak2qBbtvhIlGQvg6kHnl5ReUk=", + "epk": "e+3iDirKuu6zMMRiYlvYBo55Kr9F30B0ZFofQbf0CYc=", + "ciphertext": "M7+VYxUBNQ0uL/olCyW+R1UpSuNF1aMINLw7HZ5TGYjTcZVHoyTMve2BDrTqa8yC2atC1g==" + }, + { + "cmu": "ChrtHT/JJf1LCC1RHE5hUw4ZAzKyP+jj2tkQQT7e/U8=", + "epk": "jtRPMa5TzxBRel6UOXEZL05esgdkBgf/CAHUqUBuocs=", + "ciphertext": "cHU9Q7cxf467xFhkYBhLD0WoxKAC7xcRxG70MtRsuC+3wiTnxvD0h25D4KHqQdNveIITNg==" + }, + { + "cmu": "78plfR7ubSUt09DbXQFN0qVPcz3z3mMGYM1iciMcoAc=", + "epk": "o/x0SK0ETcj4EHzCl+QTYYtokLqBILPInwnG2T5b8SY=", + "ciphertext": "8berHDxTMRLCXmeTbIu1v3VSyrBvMV/cWUVkgHHg7oR6D5I63bjbf5jQo2ZQ1nVm7BVanw==" + }, + { + "cmu": "h8qA8lJhgUNQQzpJWDLRSqdm77kqGFAMDyJcmJkFZDU=", + "epk": "zGUmDi0E8sKJjSfxlBNDe6ShRGPu260/8h7F2wYr1D8=", + "ciphertext": "QGNmPv3Adb2VQM6+mstkWEX9uelAIrcqclZqFGNgSjZS8PAfl8wb5EnczvgLL+4DhaPADw==" + }, + { + "cmu": "t8aB3YD75Lwd86hx+6rxhJDlRXfWi6rZqXehMfAbWiA=", + "epk": "KKB39bJqA15wIv+Gf3pBqPz3e8g9HrrBwZ7pkat600A=", + "ciphertext": "iRaFh4VjaCUalpYkGUHu1ph1OQTvEbOkqq3741xkvvDRFXdL29i5TgewWzo+oHRFHHkUbA==" + }, + { + "cmu": "S7yC5taSosUIUto5yUqnKVTdWYwCQ5bMvi7UO45YflE=", + "epk": "vB7JROTqJNfG41aserMUpWfDD84upeUAcUtsGhMMbJ8=", + "ciphertext": "G/oP44vJIPY6mtXy/Zn3yfAYqb1NjSotwafVKtsKvI2RPb9SDShj0fOl7COLyHD3uZOzjg==" + }, + { + "cmu": "WcBSLyTm85LUC0G9dDnQtI5fAgVkduVR7nZUcTkrbRk=", + "epk": "rc/XNsL57cQFM/TAGdkHJe/lL9SeYyIVvxtiWaEYCZ0=", + "ciphertext": "W7fssa7GtIpCQbLjbwIXWWKqoTLCNkNHIh/eEAggcOQgQeWgdCbW3HaVBPTXdJXTnare+w==" + }, + { + "cmu": "2c3OR6egOyJtTb2O8YAXcuI2dupMam8ozkEnSubGqQs=", + "epk": "8VsATjHpd2fqRn/S8RS/X87NX97jdXAok55N3D7alcs=", + "ciphertext": "fz+DLvsUVOgEELp3saASXCF6RAC9rOJfbuonnW0a+L3aQqih+gRpDUxYspEdTftbrddRGQ==" + }, + { + "cmu": "kPa/hiKOTV6dxhZ/1Odp46GrN+TV3W7dT2vPRF1r9VY=", + "epk": "cUo5Tck3zM2cWmruCfLJS8794FiYG9fXeYaEcjXIr2I=", + "ciphertext": "GOLcjGc2Wsjoj02QKNbjGZ0WcjzY76S9mlQDLV6zcC484LLTY0+wLJGBRuQnQEJ2dCrSVQ==" + }, + { + "cmu": "iUPj9E8Rh2oub6Xqff7/vkKHABkykbUqTWCN9ihGzzA=", + "epk": "BvP1CaEDkRN9o3gW7+UZeLTd8G0SYxxQcI0vePThCCI=", + "ciphertext": "ZR3wIeqomPq1uHeSodQHvQ1i3zeuXuC+BfXyk0fJtrDlsqb+zgdzeD0sCRvSsUM6cZAhVQ==" + }, + { + "cmu": "5qMDZCjdDsW3LwgEieKXJReqSUp2Wzwm/7Xm6uBo7Eo=", + "epk": "L1hcCm5OBzvp7eNSEKb0fOIsilfP8p4865RUtrDHLgY=", + "ciphertext": "+a22w3Tqb1JOU1gjGw8ooxY5x5o5MPkNWD1WqTECt1nnZoKLdknoe/LbtAFUY98lXVgu/Q==" + }, + { + "cmu": "ujXqbKcVWg9eFZOUDc5EQLCcxyAhkAS9ql7dHIiBD0M=", + "epk": "2INmLfzfAQCRvJAUzQPjn/W2CkkPcnTpGRV9wakW09s=", + "ciphertext": "NzZQcG4a0Uj6eb3xSJCFJUUBL2MW8ZtC5DwhEDpS9bvGUK5dYDa0kP5BFQUX039KJAJWdw==" + }, + { + "cmu": "y705F9GqOyFn0dQQxExSoN6+TMDk07uQx66YfRqtzUM=", + "epk": "M04E9k6t5/hlSl0ASOzyBvkAv0O0wijlXfyX1YGqwds=", + "ciphertext": "lBeD7DW8a3K9KPMNopigm/mAn5EVpoTh7jLBVuitOa009C4XoyzCSmXqXrvPBXKD5xFjdg==" + }, + { + "cmu": "VeTeFCBMX8kgl84DMHKLMBhmkKJH98dbE5CFz1lApCA=", + "epk": "CxlZ2G6BnvKAjmAPAvR4Baq0EV3leAKzqmRbJ3xJ+5c=", + "ciphertext": "VvL3KH+CDODYPaxjC60L/XZeCDd6kc1p5rmqUN5yvbiJ/KRnnJmrwRD51PBex7Y6z8nsSg==" + }, + { + "cmu": "W4Ff1g5jCpmcxnB9NkHeitSN8G0+SAgO0SMKUsWttTE=", + "epk": "wmdoKqeOZk81pL7raNA8Oq6bRTu5DlbQ0zvd03gjXKQ=", + "ciphertext": "KxWAZ5ygXQlZ9iQiBWp8ubcuoNxKbpCNlvlhE4YU2H9qdLqz++DjHB3hqM58ONF2Hfq/6A==" + }, + { + "cmu": "l8CvjX1tMLz1Z+mlURlC5ooz9lklkeq6RRYeMYWdQnM=", + "epk": "8W8Pvf/ockMu2/7ifQ3c/FzcmK92HOFDBF0dCJLJNT4=", + "ciphertext": "CRFtNy0Mw6Y6933EVVRE4WT7okzb0R5kh42hE2SwFm9BAJdSEXDoyo8KNpLGQbv1myefaQ==" + }, + { + "cmu": "ySJdiHdv0FJAhB1hgjshQmQH2abMwL4WVhcv9DjYKl0=", + "epk": "0g/MKRcoIZnxOPtH9+GfJrirKGYj5lMVxWC+cVQFtkU=", + "ciphertext": "dp6thXChwXU+Va3DasIqJAXaEesZ8Nm+Rk8m61646ZRX8Jf/I8wbIaVDfeq2WKFPNGYMzw==" + }, + { + "cmu": "YN+Iu8JYxOnoOIO/rey243D0a8e4YKyFDokQCDv3BwQ=", + "epk": "9WXujZehnbKBRxTAbXE5ONn80YVXCunUk9Y96ow4ItM=", + "ciphertext": "P+4JKGkTnacuGC9Y1iXoWMbEw4f6lDEWQMA6rWMFR1+QaKkKSEPt7MH+bG6gNGvDt3ofUw==" + }, + { + "cmu": "QotLfUqBNy7n60KunmCW/pnKUmaxhtKI/eZFKn6g4Sc=", + "epk": "dJXoygxMcHbnboaZOB2idRSI9vH7sLV9/COMdgagrhY=", + "ciphertext": "zuAs0/TXaHwZhU+DlBrofK74vRTVJYzY0ROaLhLkiVmLTZmKcGyeKVO0mTWYltKvCBNckw==" + }, + { + "cmu": "Wgw10ll0QWBO4cUxktpnd6SciMAEgQE2i6tGSz6SICk=", + "epk": "EfNv9dx7Z7qfIggV9FASfo5tx7tCjSbaMMSNATzVGbo=", + "ciphertext": "f1ubrUR2TExnX5dXRJ6ZX3VNZta3pCmrSVqwAF58+nb7qU4km+eso+U1DmP46DQyVp0rDw==" + }, + { + "cmu": "vN/yNcwKSLL68s7hZogDm9zn+8ijy/dzXRjnPcp6ByY=", + "epk": "WZNKdPWxNMAV++PfhTPzkTHEWqNcMowfqzjzVg/kslc=", + "ciphertext": "EpT20wWsj/i3lsjGx5tosSQgm7yj86l65Fll01rfRgZzQPxlq4TqVi6v2YEShQRkMXINIA==" + }, + { + "cmu": "UbW2TV/o8Ic1md3B/4MFjCDlOjTVpYrgsV2UijzrsR4=", + "epk": "SNd9J+O9sGILljRwH0r0f8cF0aQKKMQX2J4mE4SaK7k=", + "ciphertext": "1V8kwxLGh0ntmIN2sk54u8LeJKiaTIGT2KzwYhFVNOsKqeOP2TsDAlJU8pifudZfoxHpQw==" + }, + { + "cmu": "cP0dUrq0Z6c8csqsn/D6u0Sm0FnZPg/LouSSXtLVbWc=", + "epk": "Or3zyPexRtOIyFXGRcXGZiOrToxdzFoJUhyRMclzR00=", + "ciphertext": "fbZIE1YBhcE7hp2trROmKHdV5Dw9EKjJIaBrHJ9ax7iIo+Dzfn4nbpN1wLIvkVD3GFlGUA==" + }, + { + "cmu": "/2yL9VsuXSiN6Wu25trI/1WG1QDMqerTf/oI3FXAogc=", + "epk": "At/lPIK5q9KfFQ4ByH37FWXyqCbSV4dD/+KZ0Du6dZI=", + "ciphertext": "FkL0K7NnGXXhEW/28SZKcU/LEJ+DTw79GfqKvSmRezA2Tq/srItTJLQJ9+LwKRU5wDnz5Q==" + }, + { + "cmu": "od+AmG0aXt0JV/9ElXvNgPYnUU9u2zCNS7wxZzL2GDE=", + "epk": "wjQhnlEx4kgL7StGfKjLM7ODKrkjM45RIASuWapOwjU=", + "ciphertext": "g+wz/J9WS45WlpAR984CnJS14o1vulf1VoTV0P5kKwTKQBjq4/m26tDv/s7Kzh0LfA8D2w==" + }, + { + "cmu": "2GZg7OoIRRkmBDTdjF96RsKcc6L+6/avSvxOHNDC9Qo=", + "epk": "DfBk/+yglemYZe25GAPmwfOH0gEDL6CzKnw0YuZ75Es=", + "ciphertext": "uXUl4Y6IWSBopnxvFil8FmPn7fHKnyfe4mW0CLWnp0tkYFh728AJH4lUmMxuzed74mV+eA==" + }, + { + "cmu": "3Wb++xUFb50w1nbFPMJzWkjY+BIMjDNdOUJne/miEh8=", + "epk": "LPODsafgcjvYKdTNqzZTaRt0Psck5lPtNgo32vMXoRc=", + "ciphertext": "hT9pLWb/82q6IKPXfhn5qGgJXUpSBQtWFpaV35pIKTeohxe8mgWBMfK/lZl5sQKU+ul5Fg==" + }, + { + "cmu": "7zVB2fEIhukFszvJZn7yubdfa+Cxt8froEpuCywFEVI=", + "epk": "9E2QoPr6ifUC7kYTdhi7IVHLlvVvz7t9g7kwgBROOMY=", + "ciphertext": "nohntNa6vEh7Rk4d20iZPS5u9sCHNVQkmGCz7O2VFYA6qyK1wnWCogInMuWg9o1e1n68Jw==" + }, + { + "cmu": "Fmua1fkHgOLI5GEsEcq8w/0JY8HhEo6zs9QPkz4H4lg=", + "epk": "k4IkiwEhcC4WemIuNtVdPBRvlTZDsHvqac7GFqVwarY=", + "ciphertext": "+nDcv9VYSX0Zya1dWMxIbBvc6q/4QpDsiRyI0ri29Z44BcGiZViWKM98RAlF4gW9gHlEvA==" + }, + { + "cmu": "cKASY0RwlkXvmOQb/t4+h2xxW/0bmWIf4trKG2FLKF4=", + "epk": "qtjFS/ZW1Kx40V9a9BQ5LIzqgjL0SsOdrG2FEUNUXqY=", + "ciphertext": "fkqzYXNBIAWJm1ttp46lL3N/XS6LaJCPQud1L/R9wIHwHlPDXQMZWOGXWY8tvXAg6tCBjA==" + }, + { + "cmu": "w7kJAxC8OGZqWnsGdYXxHgROSb4A7nEa1fxZ88ywI3E=", + "epk": "Pp4Vyr3R9fCnYQU0J1b9Ir8nrnfxqTUIEZTvjlH6kTs=", + "ciphertext": "1l4NCUm05t4QKzrh+pk4/U1UubMwTSpCkdWo1V3qQaIkEZPHjQoBO3Cnbx1IiCO0Dzm8Ow==" + }, + { + "cmu": "zRksegyE8N7ndFbZcqSrAuupLc9rvYMfMO6CQ6SZAg8=", + "epk": "Ww24ZWFUIs+evuT2uOWzEim+mvSockXf9fOiqQLhZKs=", + "ciphertext": "ZC2aPHoa1sPfcEP4S019/HwtoDlUGXplLKk9RoBG1S1IoUZeo15B4CGc7HLpbORFZ+Os2A==" + }, + { + "cmu": "TGFBlq7AudYr3PBy5n4wPYK4z2cksBaqvI7yGlh3nhs=", + "epk": "ZWasBGGnxew128JgGu7l3upMmY7rpA9Cpg/Db0VnLQk=", + "ciphertext": "SacT4Gac/q/5k5jYeszq1IQlpcwrWSMEp7CDcw9t1FQVnh3Z1MBMBftsa5szOchSs7Y1pg==" + }, + { + "cmu": "44frVll60u0cGjcGKFqLMhkFZDH/8xt9bY67Vn9JsUw=", + "epk": "K4Vz28E0rGNhAtoch9K08x0r9AeW4wGIwdQQAvsxVRw=", + "ciphertext": "D5Fu5IvfWTZaJq+GHjCj2QR+LaHmKejh5IxoEvCTMyGAAbFGC0jfA/avIOcOBEo/9XuCPg==" + }, + { + "cmu": "N7QoHdSueROHbI6WjNfjV2WMS/fKE1Jse11b7d9iUG0=", + "epk": "3ZWvhHWOaXyz0sw3CUtMCwtJBjU0d2QMlEsR6bTfzlA=", + "ciphertext": "JjVT9yzGtkDn0f+2uUJlxkiC1Gyk5SZV4IbRUn1BPp0PrYcPjXE+R2Atr4LNGTIW1b8Obw==" + }, + { + "cmu": "SMAql+5DxbP/q7gSv02UnTIXntjEPOv3JXli/ASlyQQ=", + "epk": "9cPX2hwWXu3tphOA8WXPp0gmG3aGduGPFczc6/lDxHI=", + "ciphertext": "V4eMIuotRAItrKsgobEUdqKy/WVM2YPHq+EOmqyjwvWMntcNSnFrda2YGr9Kr8eKAg3olw==" + }, + { + "cmu": "uz41zYLKLfo3GrgdAqJg2wQ4lYsU3M7ZbdU50rSwQQs=", + "epk": "kjAJWVluhQLHBg8tGLAe77SHhp6GtQERE7+vczASJFc=", + "ciphertext": "wRzNxfCg/fVDRGOO/3ZlwmDzwAQbP5kl56ULh7gmvXTyRgs1FbsC2qtitn97ZWLSzwKBgQ==" + }, + { + "cmu": "bhKhOxPR87M4Z+1ySQKrLEXmVTjzA1GLKTBVFbjDGVM=", + "epk": "XavFPPUcppcW6kWeZBxagXDWyRU/h6HKUjQZfZGYzes=", + "ciphertext": "g5tCMcl6jxBNMjzYIZCyzKizd+QXJCx1pZnSd8f1ka17Jrfx92dSKDZSPNouPnfqZ0cFCw==" + }, + { + "cmu": "ncAoyqZh8GCYZe/QaAkGmrVFk1G/jqrjb3h8GJZsti8=", + "epk": "a2efMYbCW0sbHlnZ58kXxj1Hnohd+e0lFYgnU4wF/bo=", + "ciphertext": "sZ4E9Sz3xE7QU9cSPEAZNG3NLwwRSxq54C8Z/pduC5m4HChqyvp6HTcTwLIcPSFlT4XDzg==" + }, + { + "cmu": "XR8u94qfvJK2896+ttsKnCdU62MhcsmtaUupbD7TnT0=", + "epk": "VtQwn5N/kBtEecJTC7EIZ+khgpf/dibKrmzkxKO1p9M=", + "ciphertext": "SrmMQ9hLwuT69PkJkTQ5HGonCTW00gcDMTTqWyDwbHdfl7qbqr541F6vwfL/oSZAa25lkg==" + }, + { + "cmu": "KkdYyKrT3aONWqOqR7Ri1+F47QTejtDwDJKZ+HlOB0M=", + "epk": "Co5ls/efWXUbgmMLXJhDXgX129fu5gzLpQSTbynHmgM=", + "ciphertext": "nPSdHmNNfdBKjLOjfip+/Z0HbdFL1QcyqaghBbuBFnf/nkHbVAY0uax+/qWLXCHrM0lZYA==" + }, + { + "cmu": "nhV3fYn4ktzz7c3+hKzexdj0krzmp4TlY3aLJ2kVnls=", + "epk": "gpUnoZFy6X8vPm4UXH68cTeB31SAmZGOWc028Z1AuZk=", + "ciphertext": "pGw/ZczhFMVDq6pyRPbrrk61qJ1/DC0ap0ZZX4aRxOXtHhVrupcBDmfJva0UL0UAV5Wrhw==" + }, + { + "cmu": "0SAr/aVyX0DaX8PRSrUfJ0sTQfiiLdiMjefe23f/onM=", + "epk": "wIj4KlyBj7kUYKd7yDNLbF5CwCZrcor+5UnhJg/GR74=", + "ciphertext": "KibDHWC6AQQOrITsozEaiaXoCEG23qpDcHpgdJoFbUjnn8JNhvFF44reLKAp/55o2Mg1+A==" + }, + { + "cmu": "bEnmUIBJS5BBo6mjVI32OJHxirAJqggzHjSPUU5c1B8=", + "epk": "VnlaREcuTS9+TaoiCSi81mG5ixe0/9obss/KEj5+7Mk=", + "ciphertext": "8XNnvBnyVzpSzpzF0TvWCRoauOV05B8IP2a2TxyXSxwokGn0AYuhXFWNlmr6hY80KVQZ8w==" + }, + { + "cmu": "6sWJOAfrlJlUymCjgLHJM7pbYIg9ZtQYgLJnw7krCWs=", + "epk": "RyjieUDkiO46nqj7ZLyy0MnZhJHKXe739E7SN33Cdeg=", + "ciphertext": "B4+hRHhtIc5gyvSxlfnGsieyTcfM8v06LCUYZsU3wQdZImjYvkIZzZOD5gG8WhFbyhigxg==" + }, + { + "cmu": "CP49z6bT+hiQev+yD2Z14DZVzNBYwyQHkkRpu465kWE=", + "epk": "LgdYZieYkTBUw4l0qUOsLesmk1lxWRYRuBpo/b2Wstc=", + "ciphertext": "peI/WbSqn8HQ3nXmB4xplGxo9MLbpHoFbE6D+mryqaoJysUVUi97QDes220xKBefYsVxXw==" + }, + { + "cmu": "b0fS7C1sK7fN3UU6yCAtucx93/7cU0ueQ/cJlbSw/U4=", + "epk": "FEBwsc4JC2tlvitgNS22Wg31Ol/Z7ZKUvsdWl6Yjuq4=", + "ciphertext": "XzUvzevzqdJtObLwKthsSBippAF15iLoZD4TNcszZx1L2ExbwWkT+cDVuwL6eGBsb+TMCQ==" + }, + { + "cmu": "F/w+73KgOUfk3O3qyuCfU+kr1bRPHOWeU2oiVhrYBD4=", + "epk": "P9EN7RJP1hF6jO/0mrYBDG5WmuN1P6Pwd7w2V0/gKD8=", + "ciphertext": "c8ObPGZJn9LpF97JuUbLyrSc1cn20BnyO7edr/Hgh/8J8M2+bZr1VClSfJ6Tv8cg6G2CfA==" + }, + { + "cmu": "qwP5OPSlR/sdfRcruZY/yyJfydfGwXX76anPOgeGzQQ=", + "epk": "c4oDLKn3e0/X6jti/4XsXefi90Hbj7/JxLFHWb6kEcI=", + "ciphertext": "GRI9WSWXlwYLeSgxC6gXuBxmOeg+nsi5yD+xzsN5Z8nAE+dNRy7uSDbf8t4QHq1gyZtL9A==" + }, + { + "cmu": "8u5HfITaSdGOSZTK9kEIK70NAI7guclk7hbZhSxYojc=", + "epk": "SvGOSgCeAtk8c4K5ztc4Px3p+CQwchqCuwZQF6lRESw=", + "ciphertext": "BOioCnaC8l9l6RJEdyCdKcxVpkfpgVwN4YSxPSGtVoERqzkewoDbkfUNJNp3aEwVl8+IMQ==" + }, + { + "cmu": "p2Q7FnwlKYY6wvl+/+C6FLv0jGoj5h9E4dGHj2L51Qg=", + "epk": "/sdjnMEN4q16JyMgMxyDh1FTecY2LwZq6B0c+I9dHPA=", + "ciphertext": "XV2UE6kltuLPjmrYeNhVYdSe/+Cy1xtn8A5N6xZzZzZD3fLMQHIO28lmoSgPyCDcW2ZFaA==" + }, + { + "cmu": "Iqzo4Q+QR0CWtPV1QIxNmqttCNQBrmXlGPyfP7XkySI=", + "epk": "IzDASoYI1sfG+wkEr/3i/sPiL6jagJ4FAErnS90DdaU=", + "ciphertext": "tfRZBOmt+9JCkTlStj4YoxTW5i4/ImWfRpojYMzoAs6xqqTr6l/3BxH2qWg9/D4g5YncaA==" + }, + { + "cmu": "YwJJFrk7Rl1xBPgXia+JtirNs1jd1GNiYhKeKT/KLUA=", + "epk": "XI2xwT+iUfbxOoXJ9VzDAY7oZoZlLrBDWcml1j6AKTw=", + "ciphertext": "Pw3uvm1aUC8sFIHBgAmN2Rd+MTWlMnhXADAQa5B9IjEiM01tzySQO7YKiCRJVCXUttFx/Q==" + }, + { + "cmu": "so+BIEUuXjJiHu3tivcFxsWLEt0vYQUZHm5yUomRuhE=", + "epk": "mgoOv0/QaiaRZEpN5X94kTUvq+T1Qb1tSjSHy2kXgd8=", + "ciphertext": "Gp9pjBtAvQT5idhBdotL0E+r65rd++Mjf4Kq3v9NoysrSDSNY1MqU3ZMxA9/IuJKX3Sb2w==" + }, + { + "cmu": "3OcLYNvpI7hNgc/byfo48LZ+nteqYHITk+4RksfKd1c=", + "epk": "zK//k307mv4K6epSEubGm5Y7m2XLAtMk+TXhF60UBbE=", + "ciphertext": "IafkYBqLim0R58XAtxjLKRq8cE7uPAYlrU2YbQMDHKvphrkwB8VqseC2LHHofvcK1btCPg==" + }, + { + "cmu": "lZrHBZRui0CIXLcKvzlulQfU6KIIF/m6Jbn6YK/ClFU=", + "epk": "99quWIl0ArmTOwvyA6p6y19FMUPiGojjNDoQqTuAapk=", + "ciphertext": "8oAqe26e/a1xR+bHC8Cswq+MXv7cwiOwcqy+F6AHCxv+POAZh9h8GUgc4gThv5RyMfdo7g==" + }, + { + "cmu": "nY/I/o9XmO9cIxJxKw47+MndLIXyBOAM7Bhd0F17c2A=", + "epk": "R4PRLVS4ab9UrT4VgRtWTC3fNEJ29zANm2iq1ibq37g=", + "ciphertext": "FrxYOtRZx87R0arSVLh6M4fZK9t+Uvmm3U8QO1P6egDZaRzL1lEQAxUo3Xd70vidiPTu5Q==" + }, + { + "cmu": "2JmrNe/ERr6IyyTB0o7Z/m46JttG6JvjNF6MSQDpqAw=", + "epk": "7iJBRIl/HoS5G0pwkFsgoD5CKQRHQzKrHCFGz8NyBl0=", + "ciphertext": "hpaH6K+UV7XByf6YBwPCIFr4SWtlsH5CS8pfEKUwik3JiY37k82yLlbCUB8JYAsHeDsMcA==" + }, + { + "cmu": "UCXcpjFOGQA1IwVoTzhiUXNxenJFcTNVPREQNbhgxR8=", + "epk": "mGDjF5J+X7mn+FWhe1SXmHtXbHvXTs1D64r5Lq5vDIw=", + "ciphertext": "cqBwjZPYOBFp48Ul0OmaitwJ2NLBgnd5rEL5U2WyDzlogsRRWiVQ7FYNSAzsElXowlq87A==" + }, + { + "cmu": "EUwVdQATHNcRuX/uLdk/BM0TQwUoVgdV5IWQTselfmc=", + "epk": "xT+ppQ9D8DpACH44nUEJhTvln9jdd1D7UoWHM0zLycM=", + "ciphertext": "Af8kOdu1YAZB/dK78NvDbG7s1Mk1d6RFEHrMoJ3rynfOhupufuQhHDtuH8HntkJzpSZrTA==" + }, + { + "cmu": "HhUF3u5353ThkFZhmKWnHyQkB1ts7V3+RiEgP5ZEEmM=", + "epk": "aJDIGh0gMDkKiC1f6fROXuOXJlclD86f+S1HtJ93bGo=", + "ciphertext": "1wLqZLkzljef/cyz02RUnVDOmJ85zkrJ1wmL4k+ZoqTSf975Kbwmz8cqh5qXX+kWaUc3EA==" + }, + { + "cmu": "WrMk+xJp08bajRI9D/jUd3rR4IL1MZiGds9Kg5s5NxI=", + "epk": "jPvC95SIuqWBcYdagOarU5GaEBJ5AQejyPMG7VMV5is=", + "ciphertext": "13+Viw4IQgaTjIv9Sy7QW/jATEoJLI64YyBt6HB2j/PoyvbyT+jaiWTst+4j1FtnqtIhbA==" + }, + { + "cmu": "g4qk9Zj00DakGixNH2IuCp1TNhT+KLn7aNHNe1u7ij4=", + "epk": "X+Kh/P5ZOeV5mj+YX9fSAVN7d9eDOVYvWdESNhqTOy4=", + "ciphertext": "KrpHSG4pRNjteTvnXrg+ypiBHpGUVn1VR6AtvKByBYOA7DFj9Mo8d5ivaqPe3RugEYR0wA==" + }, + { + "cmu": "wKeIU11mCEUomR6A39V7WNs3s430aQMBIUyVaDMRuSU=", + "epk": "Kx+JU760Llf75QK8V6LVPS2igAOePI3P9cpYwk+deEE=", + "ciphertext": "f9zwAKJ26V4V7jkq3nh/Lc4xMeN0lH4aMTGlOPFqwQ0y9L+E/TNe+EL7Eb/uebtBxTUTIQ==" + }, + { + "cmu": "/IJDk88CTpETqhX0WT9PuI/es6S5wYwYF3GCYSeFaW8=", + "epk": "MDmoqTBQYUqH9s6ySBZeMUsBwChW4kUaj3kMhRpe4yc=", + "ciphertext": "mfi5Hn2owG6WhR4A4tCsm9NaspfUjNnU+w7bndEFzBN9X/Eb9GZzV+OVJtmr2W4nw4cgBg==" + }, + { + "cmu": "khlzGD9LfsOH5J8FWBHA9K5PC5z8II1SE3VehdSTHE8=", + "epk": "Wn4d3MQho8K2CT+2XSMMRqgt33xPaSOCYhAaw0C9bU8=", + "ciphertext": "/+ZOniL2iT79rtmmKjSLf8jx/pNQ6Ekn5+c2D18KrA/U5LoLB4CK5+hdOt/xTEJl78OibQ==" + }, + { + "cmu": "7Ha1E4LZtYVZwXkcp9ujxfhR5Gvxrzlst2zbSxvJERg=", + "epk": "+3z7eHEbDDBVWexcRNC0l1J2nJn1wlw8ASuWT3+GNjM=", + "ciphertext": "TkfOB9MMRYWMpzr+qXXYc2gF3HAkdaAAMt0kWtWi7tnvy3w9mcKf4mtxoXZ4cxdIfmRPbQ==" + }, + { + "cmu": "tSpiAKXQ7MPjkFVvYtYRXf3Fq50Ye8h0hVWzDypZDTQ=", + "epk": "ooKBB3I9NIAdNC9WM9F3KVFoQyrqiJT2QRSPN+pqFsE=", + "ciphertext": "RUC70tsxbEpQCDZbvMEkTi8iRxVv45JcIsx5oka6pru45UOf9gPbyuew7mGgNZOt6FrU8Q==" + }, + { + "cmu": "3WqnP7TKlE2iZJ2GBObMFtPLC+s7i6XbTD2zWakbP3I=", + "epk": "+NKrByJiQeEl1JE5P6Vx3Cf62JUSEZOUuZI/lwPNi2s=", + "ciphertext": "ib2k/dW/g5iT+5EP3gY6y0CRNXjSICfqD/ZAhsQJlmO5GQujqorvs+5dcnBgdGlpw2eOcA==" + }, + { + "cmu": "odwhszYySU5Xwm1avt6kvAzQQea9w93DA2opj99OLTk=", + "epk": "jfjtsg2SKPssgD2MnKowskO8HJW+uiEl7lyWAD8Hvtw=", + "ciphertext": "1vgPzGpwBrujNSJJ8D9RfQtCjt6MtVDFyvhmFuQ2KlDccqTNYqKYwePB3U7qnNKKZ7vR1w==" + }, + { + "cmu": "Jaojgrctoq9Ep/VoJ818iAAg1y0iFz23NeOnmKXVWAo=", + "epk": "0Itk8Er47QuEfS93k0omCaAHNhCcPzENSmRHJMvllLU=", + "ciphertext": "VpIpgBGQzkGasQ3TYGcS1lyeCi/HFIT/FrVMnsdM4ma1Lfb4I0ljIqIfptOOv1NDnQnpjQ==" + }, + { + "cmu": "Nw0xZ2aSEo6rL9I3vnVyiNxMjROE1ukfrw+bD02ZYB0=", + "epk": "ER/R3GQ0qCpV0ZPngsQU8WTfkIFsKkQXL++gPhJ91bU=", + "ciphertext": "NUkJtSmWXyZ570WRmtc3jz+J3szccEXmNMdpoVGjmzciaKGAZS7qJPOfiSSTnJH0nkdN4g==" + }, + { + "cmu": "i3jiCtQwlAuy15aIrCDh4/FqEtt6QZEc4jKqBTLpPEo=", + "epk": "zyey1sY3tx4QEoP0f1Wk2yVTm2rty0cORB07ck/+uDs=", + "ciphertext": "dQGimv1RAn5IITyL3yoxcINmlTRSMz3IX9zgiizLAsvlN7Hgk+wnS0fW8/k+nVi1krc1aw==" + }, + { + "cmu": "LLe3nV/Vz2q2pqwKrRzkvC3tYjjRRbz1E8HlnCmzXkE=", + "epk": "jMFOjNFy0Y6iGvak7Q+z373Bm8Uw7IDd79OAa3AI6ew=", + "ciphertext": "2jx6y0lZofrf33sftyzyNO3LMAMgtJB9eHy0C61u9NGaIxWxDvbD8Z3/IAlQlPsV7cZuRw==" + }, + { + "cmu": "mtqCSY4c8wpgG0ghQHCJwYfGAb1cP/xiNXR5Hz+uHwM=", + "epk": "KtFJ1lkUmgPybg01IrKBW2748/M2rQkuWjMiQciGbRU=", + "ciphertext": "5Yrn1Xu2YJb9/KBKtawvzT6LKkEhUGtDZakT+58k9PI8NcbRXeJk1p/Oca8qz+yRiryJcQ==" + }, + { + "cmu": "J37LFKZvXRlQkBTVlxR/TrHA2C0LQtoK6EnkI8fZD1o=", + "epk": "hJ7ftjkHw4sb7s7tey4FcNDge/I8yLww70hnYUkzxTg=", + "ciphertext": "JkYwMZFGzl6F4d4x+ptee8Cal49+0yGgIbV8c/Hpt4RzMqVALKCeOUtR3UTez5Zzz0K3Jw==" + }, + { + "cmu": "aoQqPClx7yJ4DHiEsYPiy0aRk/bsmk44Wh9u62nV9j8=", + "epk": "UTRpetGjBEv/si2M/v7xEAUx0Jq5RwpKKmhW5qLcTjk=", + "ciphertext": "LIfIi9v18dq2LLkrqQ2qySNO1jW9oljewPWFI9K6aNisSTpCaWcH5BSFF4ZAQHDwsHF2JA==" + }, + { + "cmu": "+OMcwJeXgUAm6uVglhovzJLBtJI7+c5CvkvIHFlDDx8=", + "epk": "ygufZMWrLLBDr3/q1KXiJK72IOtKZSFPrVt8HtB2Hqs=", + "ciphertext": "Fih17O3gm+asCtx26Xy6nCQrZMDz/31JHkxwbuXJZgP9VoqgL9LG9RSDFMsFurFDubK5ng==" + }, + { + "cmu": "fW0LiojaNwXxFkmn3KQ4Ot54gnVsAmduFWHvJGdtODE=", + "epk": "BmtRs2UjVTfcVDVTE6JfkXgUD0NVBIk3s+N9+1F+1TU=", + "ciphertext": "e17Pa1k8ijATIq8f2ZL+rJ09h/k8awJIIGG18fS2XeL2hk0o1wdIFcatqhZNxv6NG3McUQ==" + }, + { + "cmu": "XGdCOnPJik9B8v++eduauasW/JFBrlxpKSDKodA84Bo=", + "epk": "kGUrGJ5ZmuReoCBUZNqMnR+ooX+zZijx0Mt2o2uYjzk=", + "ciphertext": "4+80aLuzDasvskohJtlXV3TH1s83HI/KRODHgb4/ZM8OtimI9zH/TPQEzwAHQnXYek1nkQ==" + } + ] + }, + { + "index": "29", + "hash": "4L05LqQq+YHCgR6J6VhFLulKegHfoRaiNxVYusd5mws=", + "spends": [ + { + "nf": "2zndSpjWqGam0OIusRjNOj1rxNhYQP9ixPBK+yXCpk4=" + } + ], + "outputs": [ + { + "cmu": "mL/j3wUqzn4amUrOPkG8uuqaNagHo8Bt2f6CqTsfRHI=", + "epk": "e4p493zF6x7NeHrMgp8Z8UF8K0YykEJtTDPOeQC/ubg=", + "ciphertext": "i9uGjPHJXB2wj6ZDFv9OjO6zI9FfVrLDI6rYTtKfwWCKzD80SN8DiqJ+oDijlyzEe6tNnw==" + }, + { + "cmu": "YV5DU2JywKIfrtrYIdQTAdP329BADwOgQh5LFlhT91Q=", + "epk": "a173je8kied2kg/8O8MTU5VQxuL5cdiX0M/+EMfXA2o=", + "ciphertext": "qnzAU3R6ORxTnzJqRHp5C+czfmY+g4wVN7Ci2ADtTzcASaU568LZjcWZqM2qSiBRTLx3RQ==" + }, + { + "cmu": "a9YGldu1K7lPP5rG7fk3jLoce2oeY7Ou7NZtY2ssDV8=", + "epk": "SZ0cMHrPk8Vt8jBld2BBV1kF3sg9aSV2Cr4cvAJPjYY=", + "ciphertext": "59tYeLgIsg4d7P9rNG0H4zX6HsyJ7ZQIj4L1YNNrMUsjIv3XuQVpAInkhb6Ykxvb5YYf1Q==" + }, + { + "cmu": "xLYxjr2bwRXwKC8tKAbXtRorfAjnjd+bO95hkzB262g=", + "epk": "vkTPVDU8rKfznlamPB6e96I8a3kUKMRceqLBtGMkPmc=", + "ciphertext": "8l9RH9+ISeMdmomhWprQm91rBsEvHF13oAXBP0cE7E4vEcVkLu7CNn1hgwepJ5uSGj5+3g==" + }, + { + "cmu": "o40WHMuL402W62jpTNTMWzfulLh9lP0oV6LKw4SjPgo=", + "epk": "K6gvPPFdWpdC35aNWaAycxY4dtUkjUuKVwbrRx3SUp8=", + "ciphertext": "CXwqlv4ftZxCqWKJJszR+MCZ56B7Bjt/oO2QqsZi5H9kxLpZAVg+u2DRXIN9tvUa/VLnOw==" + }, + { + "cmu": "MIvgohZaNAokODLaFcyzZEYzJsDmfZNby7XkM11T8QA=", + "epk": "9GAV78oTYE/lZYiPEwVzxzEarHT4JCK0+aFraDk3hLw=", + "ciphertext": "AMGFqCnaSTMj4236WdoJP4uQQcRHWlLxozWwNUaTDiD5hp2Ic2sdpJKf52hYn5oADtO2nA==" + }, + { + "cmu": "Dnq5CBoadHCEEaoq++B6ktO0GcoD6Xi8rp4kRCu/tS4=", + "epk": "45ytFpzbSO0qiBoH+b06CIngR/CoGucrwIg8oH7Gp9s=", + "ciphertext": "YVifG43e6rf3676iXXxrZnfbXjmnzQAK0glezKeQtUP/sNp/vpBErvIOOnMjSOrZg82UAg==" + }, + { + "cmu": "55SKETfd9zhooCXpjSeT8rZWdPduJ5P0tPCLu9Z+5gA=", + "epk": "TpD1xT0pWn4wC+jYOBXrCUzZIQWPb8sOMdQrh7GlhQQ=", + "ciphertext": "zyzJar7Y3Sp/eFugkGObMp7XvWvGx0KCVbJQAR1Jkp+HwZHc/ZvyRdXU4fIpkpaM0HwUSA==" + }, + { + "cmu": "3N4mZHPudhPQJUge2X9VpEty8Q0Rt/5VJZD2Z2mKFjo=", + "epk": "Yul6DcLFXqPPUKQCr6Xozz2sZwjW0v/Usdx36fmn1Ac=", + "ciphertext": "lC2vXIZt1pgbbO1mj8ZtN3ENihZC6e+T2FaWiGKnQeIjAXqAuNq7oZ9Z8BgfwxbmeYFM0w==" + }, + { + "cmu": "eoa0AVi+gzGydxOFjYqVz73qi0JvDSL39V+qQ/Ejjzk=", + "epk": "nLU7fjEHtkBPtCNifPfBpQAamePlgUxw2lh46VZIJ0I=", + "ciphertext": "d0/r+RSwgbVGp80Ne+JeIirxcHSSbrxbHqQL+sgKsJr+DFTSvNwMm4r/+ueB3/LbXcODXg==" + }, + { + "cmu": "GN2yQzaaj6eVr5/WKqrzkMCTbiNrwhGTDggdllPEBSk=", + "epk": "mt6BRMlMGYP50DpX2oJx10CH2R0nvchdToGI7aFItcE=", + "ciphertext": "3AoYaN56KfQ5YFnzZzbL26KaBoi8Uhpaqz9CQKfky+DjYwgOG5GZbbwUt0xoW9zwTySw6A==" + }, + { + "cmu": "WhDbJGFJdP993No3Kvr5jQ4N/NVkp05OtfnJMyY3SRo=", + "epk": "Y5DlkThji+5T34iaomEWlx3FF5qTpubShm1AdINveNA=", + "ciphertext": "PunOhMdv7QPyD1jvQ5J3tNAzp8tGob3U51YvkpYjgXDI/0gcWxaNasmCdlTcv0RFlogS6g==" + }, + { + "cmu": "cpXc2o0UyW4g7/dXd7Ba284aFR3zScikgNeGyFbNMD8=", + "epk": "zp9KcfimoIAqNH9Y5bro+9AVTneYveFg4E94l89fqAc=", + "ciphertext": "iP8bB3u87BcJ12AF5jg7EUaoJ1ZtRMqsFo0fx6wzQHEhcv0goHsWs/eqcYcf7SLtXOQDkA==" + }, + { + "cmu": "h4wK8bk2iIzfczWlVt12V+Ua4Bti4B88QYnyNiIPaGM=", + "epk": "Ahxjhi/QlE5SUOX7IW8l1mrSw4CBVTsE2490f3niXEc=", + "ciphertext": "1hdIf29T1t0rZg1owNFIIJRPinOICS4F89oRAyT2khzoBX9Ly0fetcjvlRJQ0CBCtX6NJw==" + }, + { + "cmu": "E2YWT8ceFG/0q/3wcYCeLNLpJPFTgsAJDLEgxp09ziY=", + "epk": "MyWG9lmua9TtHs9cMhNO9Nc2ie/Q4ZDhjXbPgXvv0q0=", + "ciphertext": "jaw4lsR79EyaVQfuiWoXZL6uPa25fgll9ncZkwXOmKq7h2Ls7Z+f7qMzssMA6dyckyW8gw==" + }, + { + "cmu": "FTjgIiv2mEELF0Tb2XM3Ss1+gk4Gd8CEuva2fhnE1V8=", + "epk": "X4PWGOBPLwAhZSUwD4LZEFw2OZNLvFwcGOyisozNls4=", + "ciphertext": "IdQMG/u9/Hjbh93eW1pH8Tsen23ITcMDY8U67IB+JXed7hoEawKmrNSG5JTgT04e0cIe/w==" + }, + { + "cmu": "Ur/KVv9YFpOsttCQqVEUkfF1bnGg6SZK8v0VeSvkqyM=", + "epk": "yiKsoMVAyDWu4vIrn9I3FzsZacXM/GlFq2pLnRLrILU=", + "ciphertext": "CCBFFLIY1OJ+E1Qa5W4ygV/fBgo7wXA+gHq1h1HoeA/rZCLrbeHIOrWm9ORTEfYIKGnPhg==" + }, + { + "cmu": "8GV8ikYtXRh2T91Ojb9z5PZU8g3JjDuO0b7jI4xZ1gs=", + "epk": "7RxpymdouDbbeUQA1PYc6e85vfAN0eay+z0TDmU9ZMo=", + "ciphertext": "LQ7G/TnqsTfHuj7uHA/nDIp0NxBEMBFxgQ5PLcAzv2lvD7jnipI7yi+zevlQheK07jZxVw==" + }, + { + "cmu": "jzLT/jYvC5x1Soe22wXDvKl+nC2/8H9xBrYByA0ho1w=", + "epk": "3Uq91hHGDT9zS+J4oPniFLalWolEgscsxxZxBuGSLqM=", + "ciphertext": "7yrI+KQK0+tYyGK0PBTEE/tYPEuLUmP1Lbj29QghfObFYXytQGLjxAw9KtEdr8L80oInKg==" + }, + { + "cmu": "iWqufgvBbzZWljsKah31DuXvfayL8eO5+8KtoYtYEUQ=", + "epk": "om1vnDf2lK/XLSsIFkJSkGNJ0H+bg1jG33Y34xpmruE=", + "ciphertext": "X6fbxO3DlseaZ2tcjqHQLkV5rAZfUbQidMvGZ0gNmhA9lxQ2I/ocKb3UgmGRazEh13j6sw==" + }, + { + "cmu": "3RS6yAhiQ7Lspc4NDFX+pWWNMhKWnnWN7PwHuqQEFhQ=", + "epk": "V1Yt+ceAEPfbZ04tA1G/YNpW3icgvuDYpwnNzqlHvkQ=", + "ciphertext": "DUwsrsrRUVZAb9GJRer4hCGFm5q3wQScWngPff6jqjGLh0WnkUarWDt45JAlFrhwmIU90A==" + }, + { + "cmu": "fBgDFHo0hkKKzEVDBxqjJlkQQfuGQKBVzxAlBxQw5Dg=", + "epk": "Q/9oVa34aeV2l0ACiiGNfTZFkUVhtZe7nOxqPvSlmKQ=", + "ciphertext": "jzolUJTcZx37DvuVHsuttsAWu77WP9LJdz6eTuieqkj+QnJaWRHTvQYZu1f8KY2CSlKPlw==" + }, + { + "cmu": "1+WB/Y3h4fjwo0wVbdrmPG86CO00CVd0ZdsXuAjxOjA=", + "epk": "K5JHZo9wlKzt6k4nra/nj94d1JBaOaf4ajv4c0r7Ork=", + "ciphertext": "r+wAIDigMgxR2F8/iZ9e2V3gL8V2K/JAm0BS5UlL1qukyIAFFFCPazgj5mFOjawU2D9dsQ==" + }, + { + "cmu": "hlBxFq7Le+jo/Zes1NUtN61NR5JZWkx9v9D62VMiO0U=", + "epk": "YBKZyo67jql9S6gjAtO9b0cQjHAIg2YTtfLoFWAw8qo=", + "ciphertext": "kHZ5LNrz0+iIjfBVIDwy8r8xcCZMHjJgnaERWzEsaKczZFmrSvvbEMCEKK8P8yfPDr3vQw==" + }, + { + "cmu": "pZMjCw0z1Kidh0ANQcIgvOmHH0WeNWrROIynItE0SUw=", + "epk": "8zG55bMnPFuR2eno6MrP2yJCE4/p5AEICBeyVXZyAak=", + "ciphertext": "dDm71ZsgxkwOxsTrbS0jRRzf1UtCmaG/ajQCHxiC0RKXomYoDtA4rFPEo93d8TXNTK9Jmw==" + }, + { + "cmu": "eI/Q3kBcT1q9fbXpI7JrP4ErcJ2K3iSCfacN9xRCWRo=", + "epk": "HDXHIOAmfZJJKkuEEQgvPZHWpTXOGbaHwdP/K9McpbM=", + "ciphertext": "7c0XNfE8wgD+X8PfQuvW8V0BTLNPqjUONMVW7DLgccK0jfMgwimx67n15Aw60W6eVPUm4A==" + }, + { + "cmu": "rDMBDyNu1W1FdFGPTua1lXWB0XI2PrD0RdS8OjH0Hg0=", + "epk": "FCcPDaSGWlGiVL2oMvo2+QSk0fam5z65TeLLtUIVGmI=", + "ciphertext": "8vgQFsI/KYLrV6EfLgGzv5xTc1S9jksg0sE5Z7UFFiI5qYu8v8umzp+OnBSGX+llLd5fpA==" + }, + { + "cmu": "p0PIqx+8s3oFMfYK3oQeJIfXblkIIOY/DRPwIaYrcgQ=", + "epk": "3/nRyyHtst/tBaAQFDycOXxBRGUO2JpQya83VqqBtps=", + "ciphertext": "QBE/v8R3gwvAPpLbklmogw4v106S0JvT9DUss9IcpMeCeCV1wYyDCjye68UB8a+gEB2isg==" + }, + { + "cmu": "4lw4OCvmTICcVDIK8HgJvC5GKeV/BlSsOKaiyWmcRCQ=", + "epk": "LfTm+TnRnRXmE+VlsjrepPxVo3xbIseDBOyLPnXGDQE=", + "ciphertext": "iOy2/M1iPVnVvFNOWj+5riTIhGE0/y7JhRw4/sfngDwrKctnmjc5I53T6OG2Wu+lWlZ6KA==" + }, + { + "cmu": "1eXyQbOaCsuttPBd8rXVTMAxj1Jgow+6ZJCtu30USAk=", + "epk": "DE0rxTdKGwqdadhAXodCoYFsWa+GAUrwdxTWO45MHhg=", + "ciphertext": "BRnR21Q5pPeQYa5IRNm1Cdnh/e+qUbEFF0545wI3Otvw0OBPubpjegr0R14DdPMilFWQug==" + }, + { + "cmu": "dpW+mve53KpBt/UbWIudLiL8/JbR3rdU+028wutJsTY=", + "epk": "UaROXZKks4gLaPs6oT++KloS01X3sgdTFQwN4KFOo8s=", + "ciphertext": "4jFBfTM3jx95HXXjA5UNhTb9KKc+/P1RNceYgYe9cuEBXPcVtydpQnazSqTMwUfQO9qK7Q==" + }, + { + "cmu": "+z8Sc7xg+4HTRFXHGHgV0zp2UXKgPWHwvx0KQdYSAkE=", + "epk": "5OJItOpQ5NHbPArqNgy02IzNCuM7vkPWUvS4RSAdNsQ=", + "ciphertext": "r3tQkKFRkvpcNsGrJpGKimUNOFw7CTmFcDsykTK+vAQa3GNH1h/SdEdXrx/n47zlqtbBjQ==" + }, + { + "cmu": "UlYWsU4mrPn4oxi4Bjol89htPeo/Fd9ClNISCcXOnFY=", + "epk": "tSg7IZaZ7s9nqYGh2or5dDKYGPiKTn+I4dvHf3h4Mmw=", + "ciphertext": "MwW8kiqNnhN+xOReGGBZrO+4LSqozqKn1pNpGaIw/J+Z7YjdEd+NmMSs7vQnsSqDVJCsMw==" + }, + { + "cmu": "kBY7i18dxVs/UNlOgx1dCabvvF+8Ub8VbPMq5/XqryM=", + "epk": "twjjDNos+TU5JQeAF5qCGILIeRUOa5GQ3pKrF96Buec=", + "ciphertext": "1CkX8j20EDBO/eibuATP0V/V02yNNP/CswHAuOLS9AWkz+inuv0jAKGADujwvpmatMSHMg==" + }, + { + "cmu": "Kj8pVGFcqE76diWITasUX9lJFZd9a6jQZqHa+hq8czU=", + "epk": "zZ33934yAPoYLeoqWA0LWT2g/jAD3k1riUNKlAqYzyA=", + "ciphertext": "Wth0nnzi4rLoObUNZDPHdLRwnXu685VoANlan/g3euI9YeV9kMFjfPbIHqG2Tu4Woqfg9Q==" + }, + { + "cmu": "qwEVxL1PbA4vWEDEowZWTWTn837R36BXGhtKCvSgDTo=", + "epk": "RAjHO+CY2QVnCGQmZ/Ksug3g4GwUeo0vvUWGwC1Rb0A=", + "ciphertext": "CrXS8M4m8xxU4DjKAmgV4MG9EeKgusOAcwhZkguh8PsaYYpuTclWPDhsV4igfJh3aeDznQ==" + }, + { + "cmu": "7URNnRCkkbaP8a8pL877OE5XDsUDugrSlaaJjzOwmyg=", + "epk": "QzsNxaj8QUkMpiXnadHdgqO/wJXyr9zj78LFzAwxfLY=", + "ciphertext": "vWrCi8/vLy9UUE/xegMK2b0Wkelcm6G42sFJg5YIpI2bqPM8CtJ7cfLsNjVQtZJ7sikk5A==" + }, + { + "cmu": "KRt3Vt/SvD4w7xgZlA4pkGNtAAcM+4NjHczv2GTlwF4=", + "epk": "l4Nz8x/FI7y0avA1lY6Ah+kqSXDGLc0V/4UcKHXzy5E=", + "ciphertext": "qif0XIXDpy9KxnjnuErGPH9sGCzjwPWStTJevVVcWMpHu7Qp+BbVR69H6TzIq46ajK/6Gw==" + }, + { + "cmu": "i7wwoYl9MjnWcMelRuap2W26CuBwxEz3AOU+v9HKGQk=", + "epk": "c9VArtWYAVpf8dsJNmcBy08XXuXuM9MEvFH6w3S00EI=", + "ciphertext": "PMTiYZDjMQz0//Np1kTl8DBu7yV4o+b5cUGc4JUvPSoi4ffQygT5QM69M4icWdg/YIwvnA==" + }, + { + "cmu": "LxDSTo2Pu+r+xn9WGSYBJ5ljd3VLy/sToLdfPE6Sfys=", + "epk": "H/pXjmMbHMeocVRwzWuMfe1gaUawQU5r5AKn6fv2xCU=", + "ciphertext": "NUfqwr/GnWx6PAwZe5SUtV9U2TBQSbaUUnd9DxM1cgSx8jChzT0L/BKCEySpKvQeTNApxw==" + }, + { + "cmu": "qOfds4K/h4ztxQ2M6wJEuxQoZRzsMrXNfG2mXyfKByI=", + "epk": "3DvneeXvQRyJASCdFhTfhShMl9HgC+NkNCmmMOPz7Ro=", + "ciphertext": "6k9/smJ01Yq1QeSJYGcCGVNJRX4tI+LTMnOCDvSyEnx95JnaD7P+MBSvoOqYWfnb6V9Ydw==" + }, + { + "cmu": "a1wW8NSEC59ahlSx6ehCjpuU0RkMwxiYLlD/puR7t1I=", + "epk": "j7+ryHFbkE0hr4IdlEcXg1u8mOtSMbygB7FEZaO4O9k=", + "ciphertext": "bETdJyveQBYy//XndA6FaSrABbrDYuEkxPAGRELZ584aBPKWsvgLV5tVdRqOf4dg6/VTYQ==" + }, + { + "cmu": "HdCVBwgVf/jMkfPzdIC3l5mmczPDUHvvEHW33oYGtxo=", + "epk": "o2SvtXXAK5Y/kDNPLgBsVD4DElAaVVr+ygPG0rLmUhY=", + "ciphertext": "zcEOtFmkxXJraFIfKk5CUpXIEH1FTXx/A2I8Tm9C0QtbRfIFGmsCS+nmv7FbLz6GGTerbQ==" + }, + { + "cmu": "T/BTKZk/vfCOJb4IbTOw/JUqNLoxb6Qo/QY0QsKtr1w=", + "epk": "b2KqVUxZBn7pmtI2mspwFrGu9PW+3zCw9lrYOgejsVg=", + "ciphertext": "7hPejYGtQzYeyHBIdtpQZWDnAsyZYAW3IpAf7EkyC8mA9XTJJvJx9pl70gwOTEGkbyPW7Q==" + }, + { + "cmu": "Kph7T/dwHtHYq9mgr5H5Ju0NzohzmbaEIew6ZZ4aTkM=", + "epk": "Yjo0BgjYJGRO7SZLw8UqDKc8zRy6T7l6TLR8cudoMlU=", + "ciphertext": "4bybCWHWoUP8tlYKx45ZuVlXPRU3Z364iViTZIzipzznFk7+T6vFwzBi8SdbyV57djjhuQ==" + }, + { + "cmu": "Kuc4NPm+UlKAoO0wBPGZAVpAIp8ePtsB8ota5rY6hTs=", + "epk": "95KZ+TKlzhUWRrOEuVTjOkGl5hGM35NHPzjRfRhPFvE=", + "ciphertext": "G+yRpKT4VE+13+YyrcS2SIsIo1EkQeasqT7AnLghIB8QJAlfu1Zp27rx5Z0URjUxfrmnVw==" + }, + { + "cmu": "rfS8OGt/qTLoDUqmhoNQl1FJuljVOtZWZk74CULq+Ws=", + "epk": "4owgyqfTtUlFrqMMRqEvJHYC0SmlnlETkXdxBgPCmA4=", + "ciphertext": "RVccWgxA2aSiqp/BLIHGT9QaCiixTnsubJPkazhfhN3+wPJ3b1yTnI49pIf2MP0w1yi0PA==" + }, + { + "cmu": "Bdwld1nT8lFNlmYy8nXS3b9/eldb2kbupSCxvlEiaWk=", + "epk": "FNncP/lGQEa5IrKenvUO2FebBH19QGbeG/hP+qTEOK0=", + "ciphertext": "ZiL4F7QyJ5edEPQ+eFzukMsENxIwfsTgJhjq/9cDMR+Wy/X6DlevKsDKwTR2fQl4m7dINg==" + }, + { + "cmu": "F7gIofPAYunN1L0H2J8CiMXHvUSHaKUWkqKyAWa5BGU=", + "epk": "KCGM/xnJCF1Atwyx/nvRma69JF9LoOwCH9++bu/vU00=", + "ciphertext": "kGdtUNO2RPfCWbVmdv8c+BxTBBFoby8cPMvV09GUzSaM8PIZNEh1Bi4wtbxyUYMs9yB36w==" + }, + { + "cmu": "so7DebnWTASRtnaJY2GqBrPyXA0VTzrPw3vcpnJ9ny4=", + "epk": "r7jvVSVX7D34WCYG38akIJlmlmTAi5DK7fudEVZe4xQ=", + "ciphertext": "/GKCRq/aecUcvHA0iszLUMne987TrHUpgz1M2W3cw9oq33ZqS/nBoTHeCzrPI2Y1vEtomQ==" + }, + { + "cmu": "3kPjmodYYNzdkSIUuCPUFbn4A+Bg+Va/DEU6CrJzMhw=", + "epk": "biDXKJWlkLtsnjJKxNB+M2dAtOQf//0bq9YZ3I8z9Uc=", + "ciphertext": "tUYZUMO7RdxgtkXt3h+DWaAzZ1L7hzDFLN7RD3BnRTObZy1Cmfd4ugf7KR5hQvsAsiGvjA==" + }, + { + "cmu": "D7bNP2ytqzD+aXFLAnsxInL70sTnd1dpqzOsSzEdwxo=", + "epk": "Hh8h/yww01H1ofwqt5g7a9CS6r4Wdjtisu1B/aeyEIw=", + "ciphertext": "r0jcZ2fCAS87OlELgLZkhYAWJxTI+Fmzzs2GTLJhP7p+sQRY+/hTffA1gYsxVWtq4YIygg==" + }, + { + "cmu": "uQkp5id71kP8hB2nxiKx54X14sqb5L3T0nWvAKgWvjY=", + "epk": "+E5m7b1z3+9UmTgU6FGbRSiJkB5Y0X1P3OuPJAsMVrA=", + "ciphertext": "RidG+feW8lgmbQB4WoagkU8vx6kXtVwrr5neclg+/B1dYS8ka3xkXvs76QGioN32/UhSNA==" + }, + { + "cmu": "VKNF/ArP2EgHW8ESVnngjR3ljK+v/nnANN4UuMMk0FA=", + "epk": "38vq+34vcnMhakDNo3FGciqJx7v4saNzVp5DqA7E2Lw=", + "ciphertext": "HFH0scnVD6vbWU/P4YIlTOLfmYYUNEMI6nx8Xl87VlQv7lUDdvSe7HGpDQbwl1oJ4mi6xQ==" + }, + { + "cmu": "yTtAA6tuKhSffN/W7QvT8gqz/B4npfLButjJ/dbMmyk=", + "epk": "90LZ9OcwdAYygM3P1zNaZ8SGFV3pAqljR8xZ4bjOY0A=", + "ciphertext": "OzmbgqxeGwmjxN2d3Vx1yzDwC0zFEbsWmTnkvDQdR3UnZoaOCk5yxGrGSTe9SvWb6x58Ew==" + }, + { + "cmu": "9YnPdngC+n7kkpIksqsEnblNfL6UnqKQTYIJXHBhxT0=", + "epk": "TJoM79LuOCXayC5y9iiKKe93DVMAU+0nfTy6h7ofTrY=", + "ciphertext": "oopOVxPZAsGxqkrdcUZNyOGnyG0Jl5YD7LnO4hge1nvkMOAI3LKhTPEnCT63KxkzTJW3Hw==" + }, + { + "cmu": "dudaxtOpwI8sKJw4H7D3ApvB+z/CY5jk4wxPUHKrtQg=", + "epk": "P40r0TZGcv/FuPmoOcroOv/3l7DC7weljYEqe9ZPBZc=", + "ciphertext": "GbRh5o7NJtTqbga2wbA9XvD7TKe8fN0GqgSIDm4ND3HcDx0I04QUpwQPOR6tvgaG0ABKHQ==" + }, + { + "cmu": "pzOUdla1k7N62yTcxnc9A4MHpICjFvtp0MCa1vdFkUs=", + "epk": "9J/0m2MmHamfPZy0t/Oozmiq70D46haNVMTbIDwAgBQ=", + "ciphertext": "iqBl4Wfb2TgMeKpfmDfERh5602f/pAxwk/kvxG+kUVBRFt2aydkwn0BSc1BWPabFvFVX1g==" + }, + { + "cmu": "iu+8NtX7ZeFZ2szLU+MdkCnTPZWUvJHdZcjto0iHdVE=", + "epk": "Js+8vldXI/TvGieomqk0bI0SMpMrFF6sYzWBkt/Mk7I=", + "ciphertext": "h8OUdY9Zr3ENtCGGSarYy5WKm6TPqezsnNMYmS+Lc3K0B0LGFUhywHAEShNY1MQWFHsXwg==" + }, + { + "cmu": "CLiueBp/IXzovnIatgiFJOyfXdLG68E3fomibAevqhc=", + "epk": "Uk3vmn/XBaqd3AlPfHYHPYgvWIpgdMViYDqzopeU3UA=", + "ciphertext": "WWBo/lHtU4g+LxZPLCEkB3WwybOHQlomnzcP0QYSZvgqEBFsZdp0vm/U4b9RufwL1UVBXw==" + }, + { + "cmu": "cVr7aGvfq5IpAXfDi/Y0t/LGhgKwLZFZczzFAnrDUGo=", + "epk": "bvL0d6TE4x6LUKewiYExZtgJ/bqK6tDeQlLcvoXVA3I=", + "ciphertext": "gnsQYrd3VN+L7r8Sv52iD6Qshl5rPzQdor+ikaVvA31snkDCNdnLVygYLweQ5+tOK+oIRg==" + }, + { + "cmu": "IF2dTXm2P2AG+Mz92Fal0mRmA1k04TxffVM6id99thM=", + "epk": "L4AI0Pgznr3WnHDVUmJi+l9zLvtDfhzr1pbwdTdsGbs=", + "ciphertext": "T6JG0J3yMCChoGPa00v6jaISPh6g9Bw+Jx42itNZVy7EPbhx3clh8GeuauNAP2ZOvQxyNQ==" + }, + { + "cmu": "IFym8w4qlivgGxgnxjnSvOVJonMzpz32sIepXxFUHTQ=", + "epk": "XOS2hSN9vQ8Y4wwZdABB/dhhblLR5YJh1nw6xGHsuO0=", + "ciphertext": "Gq/Mxy2W+BVkNrD2D6HxBGLYeQXBoNZnmW82fJGJhgQ/y+a2KxxEXT6kxT/+VU0KtmZWcg==" + }, + { + "cmu": "EC7qY5tiImhUq7H4bzBAEhakhIabyykuWi6vvGp/4zk=", + "epk": "oMhtSTxGpjQSHzFi/ToVTLiAHO8TNkhT0n+N1/ULcuQ=", + "ciphertext": "0E4X7B+bErxnCWEWTzq2eDK43pfsCad4gLfjs3+Dn0HF4Bo9nrHmdmiWxv6oBGnywKN0Sw==" + }, + { + "cmu": "L74UEEBszPR4mojTYrCuNTgSaWXgzHzgh8Mo2r1C+F4=", + "epk": "BNtSGeFRLLZu+T3v0+QJPJiWbdC2JxrwL+IQgf9HRwM=", + "ciphertext": "Uaxl3npHY8wDpNZRBNziYZYm5uyYFQ34wvQnX0+QW1Ji71AqFHAUrxwJ2VEv8SawZstD2w==" + }, + { + "cmu": "5SV2J+QePAI7Jza4BFF4p/K+8PQ699VtjLgD9abxAyk=", + "epk": "Lvk9tmqHPjhgnY2SOwNlRttaHCeiOq8MCXc8XVSwnuY=", + "ciphertext": "L0/P8rqn7V7MZ9aVGBeaGxMyEH2BxtU4aV76sp2XN/GxsGHzjj14rRCywD665BZFKjN84A==" + }, + { + "cmu": "iJpJVfihpBWl7T6XXt8SfeVrPRA87qvSvEGomnse/Ac=", + "epk": "9wTT6ZC1oOI3xMnxNJQ2MNWD2p4vOTBo5pvPn02khQs=", + "ciphertext": "EMmHCaWm+UeiTESjdrUKaKh2NLNaOj/o840IoRIESzPE0dV+J1J23qSWu1Vw+cBR989wdQ==" + }, + { + "cmu": "qqVrP/yRyfUFj2rI3FI2yw2Z4h0P8jbO1jdNX7DTE3I=", + "epk": "zBM2ra0BDJDo3VzguIFV7IolOJY+Y///GcLbyfjE/Ew=", + "ciphertext": "8SDwpxNuHPJEI30zAFqozlspswyBxIEuoL08ic2voLJoq6+SJ46dXjK9yQD+Wcaeq77/Bw==" + }, + { + "cmu": "Q13ruHfZsvWL86pEChXz0WJKs49YC1Y/k/gmfxJsUSs=", + "epk": "IsrqXaPwl05sn/yhFGWkiKHKwU69JHHUIXvX5jmZWO8=", + "ciphertext": "0LnWV6LHceLaDngcFlxpGRf8AGWVBwUje3AfP9lb9scTlXqvAWn5W1qc/R8z/l8wF2PrXA==" + }, + { + "cmu": "f6h1/lwTsczZxy2g3Vb6MflS9rDk1D1WcRiZeDp4FDU=", + "epk": "BlXFLIkiQ+/B8/gQbPq3ptFe7S9IbM6u/9gz2dKl7hI=", + "ciphertext": "nN6wowKd2+pXiWAAzIFV8ZMgrR5zVMClTm9LycZJTWIq+RyqQymOVrsdkxLwv0zC1wjUAw==" + }, + { + "cmu": "RxoQhpGOyKAjTKK9159raxorW/U1vvGrNS1SDK3dVm0=", + "epk": "WH2MPY/df/okUBjOcNAMQA1N3g+o77lSzgqNTRfmSWw=", + "ciphertext": "5/9NXbV5mUmdVBNfogZLMO4quGCX/yA23pdbvsujffpDV166WSS7FNBxtL6RRycUmbZlKw==" + }, + { + "cmu": "pldXOWLXtPomaG9gec2R2ZrhwkbbbtxpQd87yKccijQ=", + "epk": "0gAHJ6qi7ykMWN8RxiUy9NXcFtGsIVgUO4VCKrjfngk=", + "ciphertext": "3UYYgMwSNISkAHBHbyWu07tX7BxHrjd5H5yv50UPdpJ1mzj/FUTJI/IQlsvun8LAQAarRQ==" + }, + { + "cmu": "2N1qMwLX4IgxGv3MsfhLSevW9EKCoQkiqmJiZbc4VG0=", + "epk": "HX4goMyTYO/jlCMUwrFJtcmEfChEQabD5xeLbwc9wmo=", + "ciphertext": "nSvKWOa3hv5aW30BXZ5k08A5qDmAdJmBezHq0P1HV1ItaBwUNRKpYF7n92w9NoOoxZFnmQ==" + }, + { + "cmu": "TwIvpnJXtbQEAm69ONOHjpadNygNA1gFCiSRcUWNWj4=", + "epk": "pVQo6hEK3hCGk9PNn1FstOtGq4fMGt6w+ne7XcWt0tU=", + "ciphertext": "aej5tzBy8bhcHBlAav8KUwBsnGUlvN5GEwUMT2OKm0ou9zi5LV3eYs7f2ijxDRMVBug1mA==" + }, + { + "cmu": "IRP1JyogNKAU4GSKVFmjS17IbkpJodufIgRtIhsfW2s=", + "epk": "W5q0ANaSzVqlfKmU9FNI7BOsHEGL4d7TS53OB3kLq08=", + "ciphertext": "cMMtpHala3JzwJXiBBTdXh7CJZlQ4PlybL8B6nKwE44o8dIDhCnSYd4dzmn98I3JHxHWyg==" + }, + { + "cmu": "AvcWxwz1tpXdESaj6F2JJ3nAscRFTwSLk7MAATYWkiY=", + "epk": "S0lGOYksvLTsYWObTKMOsCT+3p6kMljUCyhjBv9wXMU=", + "ciphertext": "9ug0+bYpu6uiUJuI/cwnC8soGa2q2L070LtNyhlBTpAekNROYLV6Ad9JxhXL7mYhBkBtjw==" + }, + { + "cmu": "eJXZqrT3CgLtPFBwBvPl/TDa56Jdy1TEdgl1HW784UI=", + "epk": "II8usybHik2WdhepWNsYG+7z+41vbtP6KV4TMu6UTQw=", + "ciphertext": "V7brC/sXrZ4R1xGU/jjWbeMmZES9HsLOSceJeVRUMTJsvewK2HfXBUhMfLFMvodec3s+BA==" + }, + { + "cmu": "EBEoYEoNMglwXqKZrN2+h91vae9WEO6EPmeAGY3p/lI=", + "epk": "7yZQ+2XNUxg9K9828Ma/qRJ6B63QN/pdS3EaClKUWLs=", + "ciphertext": "jXNItX6ROjN+MA/eEokD02eOitYx3KCP60zUYzpb6m29RUqoprEh15ce26VnNIMOlMI4ag==" + }, + { + "cmu": "UqDRIwetYBWo471I4bJuF5eu/r0W+/vLzT00xyZeui4=", + "epk": "7jlI9W9FuK1xGOkEZiSzASS9Qe5kqA4fhRRncx1VhbM=", + "ciphertext": "kAUc8jXNQa08A0KCBxbL0BvVvz+8b8g0cWWH6z+z1iQZCCbPGrIspx8uIxsx1gmhz2Iebg==" + }, + { + "cmu": "CFOS5wRZd78odqi1ZQJXjQwLDxt1KS8dcX0gIE/E/T8=", + "epk": "fvdwwhw1C1w/EH6GvINacKX0zN6aBIUGedMpuesmaBg=", + "ciphertext": "V6EmNRELmm3nWcYZZOTA8G73hRQ7XIaS7oNwKU8cs1DqpF9lOqXCddSqkMciqcceWCmqZQ==" + }, + { + "cmu": "fqtrexBLPld8MV/ctMGj4vEUn+ubtapFp+ke8xEKP1w=", + "epk": "/c8NnrtmAz92PbNp7D+g9UujC0Xc3DF7E08x0/Kqi2Y=", + "ciphertext": "Lr4ImWkAdAQuelNcnaZ8eUKRuFnkoVyi33oqSf3bl9mhBXnRiTJ4QYEVMOLxrY5SLx+gxQ==" + }, + { + "cmu": "AmtQoKIa/yQsVOnxApjNUaVRGIIFDtIr5B4rr+UIyB8=", + "epk": "NKPxqEnrZeWkSHDV/EifoGAWKjIFtfIqH6qVl0aYiS0=", + "ciphertext": "5OYx3AN1JVtAgnLyCA4Ozoii/YPHxj4r2P+I6aSiePZM27NV9R07FH8TR3w54KhO3PCPLw==" + }, + { + "cmu": "rawsQQ3I94rmgmr3JAqj4xLTnIbHJt5d09qYTIWVRCA=", + "epk": "khowzQCu+Im8HIp1svOpQgNpjBrpvwfOKPlGHq3DC40=", + "ciphertext": "VqF3PyO1piQLiHnyM/fnT/nNqOKaSW39W4eWDYyFD7szfq61iZGNjMVqlMaAongEehBzZw==" + }, + { + "cmu": "mYGzMmhxVJXXU/ZcOJuJsfyODTmqJbxg0sD6pgCb7HE=", + "epk": "Jv3xRVvvhGpZk2ARs8lKJXQ3MAXSzOIiODvci/QiQxs=", + "ciphertext": "dvPwVmF/73xTvJUAKqQS38YKPP8P3rHVzaJDeOVDNBVaeGokXLbxtMwizJnQJD6GxovKsg==" + }, + { + "cmu": "7qfGldHUTZi7BjGx2ZCDAY6oh9uvPE84ibPDxsigA1g=", + "epk": "Npso5fXH9Imd3+S1xjcUtADUaytXoOhFTwoYXqCWPdg=", + "ciphertext": "z7OvL7U05YUcESSm+p+OBeFfs9D4IMQIUJ6CsWIJo0XUZE/9i1Yubky5HVdZj8Fnf2korw==" + }, + { + "cmu": "mWc/rg6Hcz64430/xwEc1KWx0b130jGzpL4wmNSHLiE=", + "epk": "kFD/hwRfjLATaXsiCXv4hPt7RFz01ddtkpbvUs1pNGQ=", + "ciphertext": "hApVbitV7BHqjN/3EuD1PWG7CmqMP7sof844rtSdJ2FbPQd2cS37jDDb8Hm2zp2CCUcr6g==" + }, + { + "cmu": "WETsMNYkmjL0QSwDa7bVLNPNFV/VcqHzUIH/TWUTeTc=", + "epk": "MoM3ElGt7DyE4gnvWT1io2Gqf+a4gyplP4yO59ODsO8=", + "ciphertext": "ED42Jsz/wooBWJNgr/6l5PL7ttb0iCry4U3+zvw9IdrkZoJW2r6SlvV6QzsV/eDWAIUlyw==" + } + ] + }, + { + "index": "30", + "hash": "UjI6O1fn89GsSAW27S5gj6hapN9EJXq2a6xQFSoMBpc=", + "spends": [ + { + "nf": "okKowfKF/QLmZEIkZ6xGwpNynhmuVMr7yUFAP6SC6XQ=" + } + ], + "outputs": [ + { + "cmu": "mFDdHuOmY6rW1hE3vOyCEGXxmhBYZnVRFHur0j+ICg0=", + "epk": "2xM94QWlkymoKs6emIusjerFbubUHc0bPgpHuGnY3cE=", + "ciphertext": "zuyD/w+D+8h54cqOv1js3VPUhZU9JYvafPqDuc3mqN1TxKdWVQ7nnVQA8seBYQDIx2gCjg==" + }, + { + "cmu": "FGxusmRzk6pDuShm2BADOoC69ra58VPKeGb41zwayGE=", + "epk": "DladyeXVPr95O2JTmVO4lGd7boPebPa1wDsN+zxQaoM=", + "ciphertext": "erXYEC0unOHjRaHysFxJ55KQ/Xw46X8Oq6ADsgE8WCZ81N6ZRiHo44yDJbO+RoBAgHYZmg==" + }, + { + "cmu": "gLAwe6fXn2zLJpGqJyNEMFCR1nGDtRdvJXr12xGNyzI=", + "epk": "GXn0/UsyOYL2qyD2TjznyFm3fr8h8EcLoBKTCK5Z1QQ=", + "ciphertext": "FDAb37AhJKDxSlikmITx1KPY4iAZHZciju7aHGGxDanuPPQ2huAMQK5VzsPESMielpt3CA==" + }, + { + "cmu": "ilIn4lKkim3NGfBcCXYbTAIod109VYj81hEUpBGmnAA=", + "epk": "qQp6J7AEVwlUUs8n7f3noPXp26JFgCIjfA1rritdbDs=", + "ciphertext": "4nP0IIbnRViZszNG7Ina7uNLnlr+VT8wLpF5d+MIzdXFJ6tm18NMbXNnHKhakBN1XOsjLg==" + }, + { + "cmu": "n3PWSgOGumgukbwRs+e3pZisr88d78l2zesPZePVrXE=", + "epk": "p3V9siR0eG1PuhBJQoiqPywIb+LyS+aq0gGOqn3Sc9k=", + "ciphertext": "3n/9OnrbUHDMeMPaDGBoJjidx5MQ1O9tzAj74yXcMmyw3IwORDH0F60jWFS4je0rdRA4LQ==" + }, + { + "cmu": "8UwZXgHJPEMwEZUy/qpmGRz9F1Tm6ZY5TpT1XBWsLho=", + "epk": "3X7N3zaxPCvpyvR1rkWyzIKy4Ny+AKQaipuhamXRzCE=", + "ciphertext": "Vhp9jvAQSCSFmNWs8yPzh/OrnXGYCLISJWnxY4gN1G0ou7xbb7BmiFm8kh7P2t7+jAxNJQ==" + }, + { + "cmu": "tHxmo9r8HfvjYr2iKb+VM2UuQ5dL6tpakbG5ly66cgA=", + "epk": "Nf5hvkiH3QtKlQ+29wm1FTu0Oi4VeQV7vj22WCXjwfI=", + "ciphertext": "fDx/snSNtU8WzwNR86WmiBfVqQbk9MM5GplzfCuvv4BpZ8YSgjEjYkFUP8pWeBu/NF1Dxg==" + }, + { + "cmu": "DG5Bqoo/ekORTMiLBGykssEAHmlUy67IqD0ukMQedVQ=", + "epk": "+C9CW58Ps6FCadcxlu2sUWey5b3OTQj5aZGYwqFWefA=", + "ciphertext": "bRlN2RUFYhIqYlcq+IUOfeqU+KOp4lCKS00mDxk/m7mlGPuR1zdwYB5q/73EjNOmSMqk+Q==" + }, + { + "cmu": "aCJMtVaVB3nFd70/o4ZzQkFPknTjC1ay0tU09z2axiM=", + "epk": "qUoSe35ocRmpO+GU8zVZh4YJP59MOEbkwBe0GBUTMlk=", + "ciphertext": "PVMsbEXqGsKm2mFay94yPx/u49GUrm93UAg7DfUQueUJ4i7XD4sOBY4JMtok86GMIu14Ig==" + }, + { + "cmu": "eApuk5lglopgJg5m8//a7nxkkSJQsOxnYYSu0RDM5Ck=", + "epk": "/BvFpfemFxLzO8eOiHEkVnhY+LZWCP/Gh5pRAte1fcQ=", + "ciphertext": "xwTAqoBuXRK7ZGb+d4TbJE650MX6d4VIN33iIfkRV59mejw4YXDa5p4ljRFBpDVDRi+iGQ==" + }, + { + "cmu": "XHXhRYEftIIRP8MUdTbOwIFEIZjHoQB0mrDoK5ugLQ0=", + "epk": "t6IHWtCInv9Zl8e8aYbi5DHcvDp7/P9ZpR9KK+hugz8=", + "ciphertext": "qGx2XNgNi2tdJQA/UCFHnBE9zvlbINazOnodwa/1fxxpbv1KBm2x7JnXyJvGkiA02rsz0Q==" + }, + { + "cmu": "WKP4xCYlDZShfonzgoRMeUVQ+pvkwSTDiOKrw+i8D1s=", + "epk": "Ic8CJkdlQ44RxLaVSJ8pVA/FaC6Vk/zdlmhMJx3ymLE=", + "ciphertext": "z0esYV1LS8YqRcH2PvgRUxby035g63zgREebZdiMGR4kEKTPcG0eO/+t//ilExFVw/rc6A==" + }, + { + "cmu": "5IVXibGvHxeDS2Ayw3RMk3XfXUYgE3g9vjmmRMtFSgw=", + "epk": "ATao2uxzZnnih5TstdR0h+ljtDNeO4yLV0PjvWalkgI=", + "ciphertext": "aGI2wtsMhLkUy1NipQcqm5MWRKAnpt3QS0j6zBVq/10VYUd1+fkk/K2F1yTdqs03Hf1uSQ==" + }, + { + "cmu": "uOtvkfW0ky6P9SPs/4vNCdUOUamGIT0hR3FMCCzlJGc=", + "epk": "wg2eggy5x4I7Bns/vnR3GnOkS5HzQKhqn7Aqt+yXVq4=", + "ciphertext": "zuXatKwgKTXpBhqB08zNqZig9+9t/sRKT+M2Csqo9vP6h64FOsUE7ojWXTQA16sqNH+GGw==" + }, + { + "cmu": "RwQ63K8zGzQPKeOFQHf1wv3v/uxqIh5IoZaJoGS3tlk=", + "epk": "k3AG2L+894S2vDj65FuS9dmU0IYGHBrNydqvLHgn6SI=", + "ciphertext": "6fxGx7SoTjazNIXpNfSNOhB4CF8jF175qgievsw+4c/1eI4Xs90nNAgMEd8lWQaMEODFsg==" + }, + { + "cmu": "p3zLMmG4SHdi9GbsWpVjSXnB9ElLsNtHN0nKI/GqLi0=", + "epk": "sGOE63HMkz8AM1614aohRX+asCM4U0t2Nwz3MP9cv/E=", + "ciphertext": "E72AbcFqoXSUH+QKFDPoWzq8M/ot6Mj+8qmZNjmDFAFmKPrb4ncwwYbKENRiid4HrmHx0A==" + }, + { + "cmu": "DX0GqArOXlY/pGmEjc1Ca2wpIDpHYffYivDxKtqhfGo=", + "epk": "FUhiSqLgUc3/QzJHYZtz3DKhUYoglWMgiVKrG01kfC8=", + "ciphertext": "C0Z9mQRxxEiuLCuvs1+kSJy77LkFuDPmCPgZV45pVa6pCWWqk13dS253TEGyKz4/p3VAcg==" + }, + { + "cmu": "evUbAVYFiX/iVTYQ6CEtMcsX91i9PlbbeSmYDBoTrE0=", + "epk": "8IOvkw+qfLK/iREgbMqns2Ag9SbEz0wGFFiozRGdyLo=", + "ciphertext": "mwM2JtWG4bxMwgcGIIiFMBn8ldhZqi2JGfeDiD2mlTUFrTuKV9to2lN3ZfAbzp8MfuWHAA==" + }, + { + "cmu": "UtTr0Pv9LThljUS51Eo4w7rXP6d6D0n5sB6sREXaUCs=", + "epk": "wRs37fhWrpIOtYsTu7sG29vjO9Sj4VfV/WQfi4N6S08=", + "ciphertext": "tg7hpSCz9b6PLjJYjfSlrrY61jqTsLHvt7NUOxM8Humis18u+WUJ4erMX1qFeS2uBcv9yQ==" + }, + { + "cmu": "616XQZQE3G8nZBGGe7H4E4wWvS98yVLXD2o3pKJqx18=", + "epk": "moR7c3GuTUuOe/7+FnmVVszWSSWs7Lzo7EcecTTdYkA=", + "ciphertext": "lQGUFj7dQa5dnAsVayuGvscFsDghb+RP9mJWjUkx7DIR9d5FkFc2vATNh++3QWxodgAhWg==" + }, + { + "cmu": "VofDRI6ohOCcK7emuKqgYFTOV59JDEYCoTy0V/SXoWk=", + "epk": "+eB6C1MlfQSfY/evVUZ5aKLKxnxeP3N4Kc7EM1wEscw=", + "ciphertext": "mPKaiiHN5FkceDihICrrV2FMXZ7fzy6PqIWsSbl/X3ZSD81SjBNu6SzNaU2Tr7leiNTyNg==" + }, + { + "cmu": "qHkW0kvd9iDH/EeVIjzps2LZi4EZW1o8OjtwVHMGmVQ=", + "epk": "cnEpBH4rtrqwhpAWADX5PjbnUTdFR/xqftcXr47igY4=", + "ciphertext": "oD0zBLbpKWI9fQJHe6uZrr+TdJhVmoHo+CPy04WdJbVcjI11IVEoxrJ05z/l8yye0wm95Q==" + }, + { + "cmu": "3gs5ANO3QvB1XoB4bNvDnQ5siZGc+z/91OyLDRNe2VA=", + "epk": "cCypTtdbbBWqmTg3pwmCWXzlcSScJGidqngsuieLMCk=", + "ciphertext": "VnCSgkdpILmg3sCMt0V/5ceBmecmTfsxeIgMSLTF8XuhYAbop3SKnDACioMimnUn6fMGCA==" + }, + { + "cmu": "9YbI5ZBToi7waRSD7RWqzN6hrHBRFutqqvnLr7MCujI=", + "epk": "6AKlxGf44CAGr9HVl5K4LOBSQEsV4QxbtMtweukKAwE=", + "ciphertext": "BqZuVk0sTFUiw3KLq+9057mgQEIkqZvTdMkUK74jnLvCYkz7qz2iZmdjvTFhrG2Hd/vdLw==" + }, + { + "cmu": "0Snh8/l+S1FkhApcPGbXb5eK4xcyUYTbhwJHvdyP8FM=", + "epk": "Y3AXqBPQv95QpZ9kkP8+8FGlJfFkwsIRIWoXPM/9WAo=", + "ciphertext": "9dTD5nIMRNEGShJEiFUXxTvQWAyFL0Ib39vi7ymIF38fmOUn3mVikUPHnuPBnWHaD4kNTw==" + }, + { + "cmu": "CsGjjUrX292ViXuWWkhNY6XZG8fnB/hkuQOlm10riWc=", + "epk": "ul66Oykh1fQKETIjFqc7XDFvxKJ3ySmOnT3SQphWwqU=", + "ciphertext": "gdO5Ddbf+J1nDHQJNA5uGMLFR8rIugsgx8fmYkm6aq5SJTvmbCWciNb37Pf853rv1ZedYQ==" + }, + { + "cmu": "nacOvgZRzR5vGs8/mTHvyeuoNbaAiWEZccZ0KA4nVk8=", + "epk": "F5GSp2LiRoQVUr5Ooa9Bta4DQEipThiJ9LG4mpTKN4o=", + "ciphertext": "elLQkxedqIN7XS77SJX0vYRMJR5iQjP1AEtJ5JEWOtOgSHPI9D1VRPu3AJq4TOlIAmglnw==" + }, + { + "cmu": "lQsGi3zDFINizo94vIpaQQ9Wb81znYFAtZ3JrqB9kkg=", + "epk": "hR52PjstYU/gEZ3gGSJQ68WwpQalXBYjPCNQuL4NgBY=", + "ciphertext": "p6CmWZud+LDWUpdo9IBXgKYN7JnWzMqpUFJ355/xCRkgROIDE1bRlDx2DahmvcdD0S+DeQ==" + }, + { + "cmu": "m/mXpVw+RkidW6hTssbU1pbg4vcKzT2q2jwqonOEhXI=", + "epk": "z5gnbjSD8yWqcqqNW8V483cxklOzklSqWiiUuoHwRtc=", + "ciphertext": "OnHh5BcOKeaEDP7qMTk060fejvGfWumLI65P5fRidVADcal7zQZO/AKfyc3vz776g4Astg==" + }, + { + "cmu": "Ok7beqk4LWKTZFagn+rHFY7ytgKUuwmcpHIdwu10Yjw=", + "epk": "oPTb4VTqHHpFlncY5exBcZvPyDNGTq6kJAS2roEo94Y=", + "ciphertext": "x6MePX2doMW3MR6u4urJkRNqOCh/Rif+UNNm7Q8FpmzIs9iS32hNWnk+xzcMR5R2gucKBA==" + }, + { + "cmu": "8DO3QBm+cCmphhjOFAPSUHF/BrrGw6JI3M0FTFzmfzs=", + "epk": "7600AEk4dTN0CaBbM9LJyIsF3vfhoTC87IWkC95YLis=", + "ciphertext": "KMBNawTlI3lTcAkVkIXQpkl1W9943EaeOI4/GDIaJBBcwyItp7HIXqgC8q8s2heCyaCwoQ==" + }, + { + "cmu": "DM8mV8t6qdxnbM3nnYfJE5zekk2Hxh5e2fxI7DCCJlw=", + "epk": "8dPcMiQxgmoAatLRRJoDYcoeEi/7PbHOB1yP1UNptjA=", + "ciphertext": "18kA8EoNck7RpEWtLQ1wuwCkSjWErRVChduCWJitGnnRP49oCJ0MKqyOu9pR/nXSNg4CJw==" + }, + { + "cmu": "pwmQsQpuT3mJhRlkAnjt/RlOTe7w1XNiIZxKTf/BpTc=", + "epk": "FiN39KZhb0U25WY0Estjuu+Wf9Vkl9EBeHLgBH7S/+w=", + "ciphertext": "15mIQC3qn8htULncYEX1PNqPVWLxt6LhU8RNXiAjbidt5v2OVKI9CULUtl6N92yAIy+fdg==" + }, + { + "cmu": "BUJM7NSlQ5jaCHgIvcP9Kzro6vyMoK7PC6qt4fojwyw=", + "epk": "bz5kzPG1n55VvrV3o/PcdwxyktB3dLtPVc7RYY4E92E=", + "ciphertext": "8SrxG0JbreAIKpunFKj7FVtLM9IwzIL8nUH/qURmYHxtpO1KKzsGahpk6wgHb387tRqGnw==" + }, + { + "cmu": "NNMK6JLoM5bHFLDS7GO1n+mibxt2f2rKkjinrh4jKzA=", + "epk": "a2GU3JroaGqYxYGwiDc6z8rQKzhrs+dsxeGiMIis9BA=", + "ciphertext": "XWG4glTJOfXq7R8+mr1D8aanINgfN9ftTs6SnmFpMf89oNrwmS4qNH3OKk7SXHNdSYyAnA==" + }, + { + "cmu": "2vigPcCuDUGTkcN1fzRQR+ZdD0Y8+6Atllzuk9RuzwY=", + "epk": "jWsJqNRxF3pb2aJPOaRYheAaOYbj4x4kp7RfcswjkMk=", + "ciphertext": "/hog7GWDaLP2uryqhZWNH5a/XwUTJ7MwnX8edKY8jgjfGJUYhP99EkxTqi91l8BXo3AKww==" + }, + { + "cmu": "DyCJNTRNC8SETz2/Wt+Z/98/B5lF6fsIvWBHwyG40T4=", + "epk": "gF+zIGTzjb3M8LNtlszHyEdSXmhwWe7kR+o0W+HE0FA=", + "ciphertext": "h4lVJh0hrV2/zyUaxxxa+9XXS0cuV9TchCHEmCbnQmHMTMM9SVFEUu39wH2u8XhsB+i0+g==" + }, + { + "cmu": "R2Cvef62EtR61FKgCaWkqg07N3EqAthtX3F/H1gMaUU=", + "epk": "5VEJBcmSQOT3Kxv0SFylL6pDbcYJpLUHV1hmmdWwMSc=", + "ciphertext": "T5OfGYOc10U2f6/XKUWYrsP14bSv3le95bK0nk9aK/VB7dswYKlqezyoB9vUIXp4iQ0NHg==" + }, + { + "cmu": "+PDvRn0Kxno1tqABm88+/MMHxT/NoKgNdntfP6Vf+zg=", + "epk": "BJzXdEkMPwSmUD8onHDEEQcHW3NxwJG5TI04H9IiKwA=", + "ciphertext": "YDHBPHk8/k9nXQJ5kyK3kVUyqJoNmvaLrPsGAeQOE9XNdQufJk3Oq8yjboEduqqiZMit2Q==" + }, + { + "cmu": "IY9xEPvTIxY1uChl1fJdPCdnqY8zoP2h5PJUQGgNOCI=", + "epk": "GtnvQGOCOy588q1zAwAlS/BJCR+q/GCcACsoDD3l5Qw=", + "ciphertext": "14WzGFOwDH7e+mYUTq1JRqCCe8nqsKHySDPNwrE8q250K7xusKXeCQVxxuNy4rpazS2Hnw==" + }, + { + "cmu": "0orUbkvw1LFnTeqraCZWOD8JvivPpkhwhgYyg1h/uDQ=", + "epk": "UvbvyIRmlNzwgzwl14+OlNdEH72JDqhUNpwYYDoof3A=", + "ciphertext": "0uJfoaVK8bZWjDvl8Q6uWhY9hm3KrNQ0WcoS2zaPAMXEdF4cY/i5U1wuPWqhyU62TqecKw==" + }, + { + "cmu": "eayExcCaSuHubNbOxNUpANyGCzBy6n7azGF+PyiXQw0=", + "epk": "xotFepCFGkKft98gPWK3WclXY/vjcVP+b6A0eI2Adaw=", + "ciphertext": "fxm9DectxVUZa2+SYADRiH3FH6uHat3qKfcgK5ju6AH5zYRYVcV+7TNersBkT1TkUmMXFg==" + }, + { + "cmu": "meC/eiZ4qDqKF3OIanFzcd1Gd1nIKWMvdHbFRIGCUls=", + "epk": "NK5zhcnWnmAG7NYAf5yfO3JrWhSgMhcw3TwRlJpcRTI=", + "ciphertext": "jBmrnaDr79McWV4JjvPoV77GlBOziEuon3PzegXJNWmYyzuv0IIcKZwki2c4g2QQc/aYvA==" + }, + { + "cmu": "e3O2pAtRfV5/XWEMMVLJvdC7ePCnHvgfl8LXPPLgpkQ=", + "epk": "ZCs++EodnHl2xhGjCMaIPpJm6LRWx8Y8QHzSh/EPiKY=", + "ciphertext": "fRXwySaGGOixTH6p3ewzyXFcSUC+bUbXKoDn594/8Co8DG8PEpnopQTOMtuilHfxoWR6Kg==" + }, + { + "cmu": "PIviDbWefomLbfHuCw/RBEkt1qMl704cB+WqaFt8V3E=", + "epk": "HQvMLzdFBfMDxX1Kd2sE5TjHocE37Il0JP3eOKi1wNM=", + "ciphertext": "PhQDwSYGRrPZKkefHzoqLaFBS7TU8UcZTuBdNoK2MFuIQG44W6VokDM2wQps3n9kvqzaTQ==" + }, + { + "cmu": "hYc2XXtySfD0NrxCP19+eDWdnjwjWNJxz8jRyfiN0FQ=", + "epk": "DffEDHr+UfDy7dNnWOT9X2u/KJuNfbfBZtMQLm8DU4M=", + "ciphertext": "PBbobSYXNYQryByr2cUTeL5ecUbf63qpl9G6pbfxHv+JvF/0+iY8045nZMY35BoYxvPrnA==" + }, + { + "cmu": "klmu3OKEinHAtWXbMPhSC45uoaNpf+axyBTfaZmHVBo=", + "epk": "PIn2HaID62VWglj+SklDWiHWiKeUNSHaejSwJhtjHEM=", + "ciphertext": "DQcGj0bNcKMtF+8WNIN6DIj2d214HMulasX6pNtDVdpa9P97h+hUpNk6G0hneAmnCa7Mfg==" + }, + { + "cmu": "2+9XfLkC5cnNhA2zD2YoFAxnKpc6OXvOxRYf+fJmthc=", + "epk": "ygm+wgYSmUXJocbUyBoS1FbwMh+TnjJhs89Mv0NA6Bo=", + "ciphertext": "4sEllH1zxfYjKFRRTua/ul2fJ2saqFmmmS8LFIX3TfIGvl+oKmkGUvdkLVrG3aYbBAnugg==" + }, + { + "cmu": "K1mTn47HlVcMoJabZaPrVDRkAFFcg30NpOe4tEfV9Fw=", + "epk": "ZwqN70urDL832+q6BEbaHlR6GJwt6jSrm4MVjgfhoGw=", + "ciphertext": "6TA7i7r+6Agb9dBRVyqXhWPAoRkC5I1YQQgfa3TYeaYxHMF8qqDK/MoOM7jygeGo7VySZw==" + }, + { + "cmu": "bdbwghR08dNxAtdrb1H/IP3h+BAFMYNYEgktzmMUGm8=", + "epk": "JU5aXBR7J3T7f2q2v8qC7pVGF1oLf6oWunY8eZjiOSk=", + "ciphertext": "rNoW7x2NgayL6hsmKwet/pYCwU3sGiOm2v3jRO6fqI7/tfnPIPjY+AeIUwdPczhNthM81w==" + }, + { + "cmu": "K/hgRPEO0Lxh02yAYkNdWawNfd37TwPImdpUej+9tEQ=", + "epk": "N/kjSaGZJbSUMuLeR2dWW9mPZfExL7MzzXCCLsaFckA=", + "ciphertext": "3brvwnoJ2+tEYIx45RyiKUjb++FqGL48xVz/DAud3/ul/nIq8xsX+gz+98qt3C4ltS9R0w==" + }, + { + "cmu": "aU59qRHreKoPySMoDsQnumk9FG0QdINaJ6Zu/1V1FhU=", + "epk": "3Xzvi1qgC91rrKQkY/QYK3+kndAb4NwGw45zhCki2qk=", + "ciphertext": "8CQ3BEG+uNiLrEYDeBp0AVN97hSmqPTb9wP3/JuebaVisYFLxVp1TEZyHD7dZBWLsXb2Tw==" + }, + { + "cmu": "qDKi8FKH0EtQM1tVLAXh6U/VGnuASb6JMmO+A+9cWm0=", + "epk": "Nv3hXIzZ+0E0bGiGh5yGrZXtPoy1O6Q+zKMrnedRQNc=", + "ciphertext": "gIcfMZRp4LY6QQk9ERQ7LD2FQrXEKieA3CxGcggDe05hn9bGuutBdBzBYbZFq6ZLiNFD9Q==" + }, + { + "cmu": "fVLOrxbA+dXjcIDz4btn6G/Tt5KEzoo1vLcI+FqWxFI=", + "epk": "vZCRQca3R8mnAiIRy05ejTwoAscidWysGqWXYYGLlzc=", + "ciphertext": "S9xNAgMXLNtrUlEgbW8SVaLdasiO+G7i/Vl5kvbYH91BJxkk1DTGmiVxVf7xZ8CxKRIDHQ==" + }, + { + "cmu": "QAgHHM5b/Rh/ngQ91q+MecuXjHSX8Qv60crIhnhXQ0I=", + "epk": "QFtZhwXxAHZQCs+xjdUuofGwC8v/T7UgyKuDxQC67D8=", + "ciphertext": "C6OZs7nGLgErzYAz4JHQKin/35b3qqYCkIlr6Vg+R4vPemnFJ+WdW1T1GcbC5JxF02At0A==" + }, + { + "cmu": "BfP+I5ez+o8mdX5j5ZsaLPdLWb+PRavYfpHqs0cJGAI=", + "epk": "rXK3PWoLKi4QdwBW6lfI/tb6jVY320TgjRcgSBSspd4=", + "ciphertext": "8g1eJXUkUikzs2MMeVQkqwNdu6rbEon1/WxukkCnzg2ub28gTGCvXyHIaPLmelJ7DbOxgg==" + }, + { + "cmu": "sGPgchOh3o6pQIzSeRCsyeD0zsJypnSa0RWxsHdga0M=", + "epk": "glYKbPfmHa/i2ZObUYPm0FJDQ3DI1CyLeoqO6r2NlZ0=", + "ciphertext": "cedD2IcruauwwaMX6vmMyLssgHmNJ0fiMA3V3n1H+2TYtVIAz4ZT02DgSXZbTYm7PiPCGw==" + }, + { + "cmu": "9Ih9agEp8gXnIwhNArYvdGbmrSJec+xlMhhCuzYyNB8=", + "epk": "hLueLtUSKmp+tj0VJfAa+PYNJXmjitjSJ8VEfi79CuE=", + "ciphertext": "8pxKM6jXTYBSXVBFoSlne3zVhn/8JP0dnwr2WGCwL5jAnhv9okjkgObuBB5eVajxGqfJaA==" + }, + { + "cmu": "25hWhWnM2CBXeipw75eGLPT4gcGrYZIx+GV7uEFJnWU=", + "epk": "XBMexBIK5zTB3rLG7UiuRUJwGo9L0w6IuQGVU4Oir60=", + "ciphertext": "3FCiG+SznYXNxJFZpufD8qe4odErFP2ARXFWvMmGs9kbRJKPM3jux1AR6k+IE+nvEkoU3w==" + }, + { + "cmu": "vZa8pW9JuILs3vpPqfvW3zIsJLLXikYrNEF6bHUeiBo=", + "epk": "Xy4d2DGyVy/eAeuQmmSHeVxLNmnvA2AT8g9LK10V0aw=", + "ciphertext": "LUM96UYN+6IPojVdA1wxyAp150quH5iPnT4cOcds6HfbchI6o7OFFrhf+vV01n39cpdc6w==" + }, + { + "cmu": "PPoSg67pKqqiCiH9wl5xRrp9aHEmQHJLGi22g+izjCA=", + "epk": "gKqiJ9KnSX1DfI7glSI9B22Am1U9fP/m3JBcyenzLtQ=", + "ciphertext": "vOBcAkfl4lK2y5X7y3xbUp0wVsOPsaENQqeEmKhA+kLrSPClhfnTHdbQk8q5LLjv4BMswA==" + }, + { + "cmu": "whrG34HcbjsnDTjtr7MnZL0rlR2Rsjc3xNDOjVLKQhM=", + "epk": "48X0z+W0zirymRVRXEN31WRZQUH6r9cetKmg4ff44tQ=", + "ciphertext": "gyEnhot6hGccuuijDTmZYIQhRRdHB3+7KnWc1J5Z/gpUJRxgMhhjKrc7B0PoJI83oRnSLQ==" + }, + { + "cmu": "7cRAAQudq5Mnep5pTP9MtLaQnFKY+vZfZM907ttHOhg=", + "epk": "sqOhHBLHAfI4sMWUZRlpOwWJ1G+k6XkFUg95G9sjcks=", + "ciphertext": "NVQ4cQnkHF1cxhZR4GrsKdDnTvheNK+yeXJivhpd1tvLCHN27SjWZ9Nlt6nTNaK1ypuJSg==" + }, + { + "cmu": "DCRuGmLvCeHIKS9k10CkIjXhy+hP9lk29F+4vmkxYQI=", + "epk": "1YZXmK21P758LgvHWNt/tV+SdssSZ15HcTPJ3Cj+uak=", + "ciphertext": "BoLux/QLZHlo66Y8ZuJCy+33ptzCYqnCAb6IIk23AUV6BGfoDIbxMJ20u7crV5TLNS+7Dw==" + }, + { + "cmu": "mM+ueJyr+uzKBETJyN/EW5X5oA3CUtM70MAz5izIuls=", + "epk": "Z/4yjPniGFViGYWk1THaF2XclZOWQPjWY2ok5P2y1NE=", + "ciphertext": "Ond1pl6CurVmLEk7MUt4F7gGmkiYukOpK62xeveQGuNtUHnmzs0RF9ATHu65oUAmZkEnQA==" + }, + { + "cmu": "4LylzvJJUer5MHtMM+iVs3IzejTb1YGdUoQlmwUfpFs=", + "epk": "yV5zrMDjhbG5l98k54eF8xqgWmBpuYuPIwBYlVi8Txg=", + "ciphertext": "mk4A8BynAkrOYAUw4nfEJjCiBLjuRHsK43h6GZ36uLcmgg2E27Z1+8eU+UObnEkEDnjcJg==" + }, + { + "cmu": "eaygNef3ABIf3OrLTuL3ZzHVMWPt/VtXbO4ZtlefbiA=", + "epk": "R8NHQ/823qMDE4KjyIVsqH1MI1tl8YTG/n4ImBYnKyE=", + "ciphertext": "I0h+n0UT3/Z7i9HfBw6fqckdsuIVM6LSGHW9GL3Bk03V2238epbkid4J1XYRoEmZiq8AAA==" + }, + { + "cmu": "wJtDPRIKBg8/ycjYic56iYi2s5OGLqKRgSlj7FXj5zg=", + "epk": "FdiWddUX0I1NXHyekkg+xUI3rVULt0LN7dqT3fApFbw=", + "ciphertext": "HLQmbx5NdizdnK/v1owvnS4os98ZrfZGxozjec+TQXmbupelMIVF/bEoFE2XgDMmQyeDUw==" + }, + { + "cmu": "zTWSXMIPbWbEiX0my8OgaaBoQlIpqePNBWV3eDFUsl4=", + "epk": "QhKda14zOMfkCjGKy2sNtPgsCi5tE/kAUV/RWKHHZeA=", + "ciphertext": "cxJQUqndHDxaeDl/YkW3jbKwYVQHMC6zV/FUleh3LZqFZn0Wmjof04ap1FPRCBLitflWTg==" + }, + { + "cmu": "tbT6vaRu1buboOL8CtGVc4QJ9VkVs+VwdztKGQTjcVs=", + "epk": "g7BKAbjRhuGpzxr6IB6CbfH44SxCBFhMlXPwbvE7ghU=", + "ciphertext": "zmjbZMQt1e5CMj7z2Gdbv95ONuc7wEIRcHNkIG+o2gdHNdSeNd9VhKFtzt6h1TKfrlQfgw==" + }, + { + "cmu": "mSTad+q0pRtbsX81RhXiGOU826t4tc1dTko5TB2NWT4=", + "epk": "9GUnYr/snKZzk7+Fm+7vw9juqRVeaFyI/bEbNAIxwQc=", + "ciphertext": "a+YLKYfK/JSJRxD47cLUtOZO43KrMTk5cGejmZaOJr4gHFxWCeP/PNRKdst6ERKMvy9mtA==" + }, + { + "cmu": "cSKvKuKmaTcR5zV7HbCY1N8K0uBhuVoWDuhoHOEOVT4=", + "epk": "gleQsnQJEo/r3KVyrsfgrwEte6yhviyhNKzuVrELKU0=", + "ciphertext": "wAIqOi0BU+8H/1FhRDqPXMLA9ZOIv+U9GwraPpGBBians9FQiQOEt3ghWaiPCjSZ2GLwIQ==" + }, + { + "cmu": "zVSlibg6PdKGTmPuvvbl50+I/fNMrMIpo22YL04kJ24=", + "epk": "gZ6uCJVO8nyUTH3xpt8Qy/LufHWa40kZ40cFzz41+BI=", + "ciphertext": "LA2fDwOhrX2SPXkN6RSQW5OQtIIysED1/18EKINmwWYjeNTTpkmN7bbZp/qcpBO3ABdM4w==" + }, + { + "cmu": "g5LEe6IEZlj54FaRiRU80PTEVTndCPn4Ghm+97v1+Sk=", + "epk": "wkVCj49MUe905OLWT4tsE9s8L0IGv/bKBxPu1uDnbY0=", + "ciphertext": "4MAanCNqXDFH791rduDM+brs7hvOZO9Sc4T9wdMhwB0sC+njUDU3t/Y1adMOIIM+vQcIsQ==" + }, + { + "cmu": "VNekdKLRv2ruk5wjOsvJMJ8RcEkC75XuevrFjruHOmU=", + "epk": "CCuayvivdXUEYDS91Ro6816nF6885+6MzWUZr0QY7RI=", + "ciphertext": "M1G+DrAlItcOjE6kXYOV3sAVT+ugUuU77wpDJTf6r8fcac/VZOsfobNT/1e2QF8tWbzsng==" + }, + { + "cmu": "2NP2yakAJdN1QsKQE6jZwOvNWObVkUCPvZrn9hlgQ18=", + "epk": "HcPn9yNyK/LREt2LbzfVulitsoKZyBKznAZ7lU4uSpQ=", + "ciphertext": "NB9KJgARlayONPt2M7cBqtK9P0fmXNKbBg+aH4VhA6/JXqVKEMUB3UUcmVw+i1nz4pqdUw==" + }, + { + "cmu": "/nlhC4aPHUkAKMsBmUbXtCfVd9HOMZReuArJTESeWUY=", + "epk": "48GX6nKNaqRuGJTQ5G7n1lkXZGXd67oCRXLBNe05Upg=", + "ciphertext": "jfDYxP47TJGYOL75MFwvFPeTnRg/54USbYtwsnKYvRTo84G5folksBECOBkBB3Zs2YgR6g==" + }, + { + "cmu": "yNu1VfjscKgbE5ndJqSdkaFUvpZ602A0S9eyaqyLPyQ=", + "epk": "9UB/LlmDyhgBYfYvykFLJw6HRlubwgcfQojr1ExKATM=", + "ciphertext": "8V8mFylHXSCyDBIwGKftC6pVw2Jt6b0lRzGXlaeoXjBRer2C4a0xwUlgRnbSmx6XJEfjVg==" + }, + { + "cmu": "/pDmEmNCzmJX5Fia62LkjiBpL5zhuL7yJPxue244CWA=", + "epk": "pR7QYEU1ZcApT4TBoZnHhUUg/jwrkdwMjd7ozXpPDIM=", + "ciphertext": "t2Mecz/kLIpo5ZnGEV4xOB+sHd2+ZOrbDUsYdjLDRwe8dL0bIH/dJAn4mfUKiQkSzycwlw==" + }, + { + "cmu": "3DOPNqr8VI80+SQ5ZMnhGrTxvAEOhHEJChNfT6WPh2c=", + "epk": "NBolhDR9UnKVvRUskZYBq2L21pgY1spWAkbGZuewCoE=", + "ciphertext": "BNsbMjVKg/bmIHBhPSfEgczxZSF5L2Yo804T8X294VfhyFTatbp90hkZQ79MMNRy4Duqag==" + }, + { + "cmu": "Ek3x+ADwSUmey/Fb04RJxxKzwPQFl1dTCjMXqyD27TU=", + "epk": "zjur4LMl+GpWYIhbXihWfVCE4kJE1fh6UOXuPvtGbbw=", + "ciphertext": "bU+FTBV83cf6MWjNVcbRSp37StmWB2Xhf3Ema3pT8eRh4zeENSvRPDPIP/afesWBFjeotQ==" + }, + { + "cmu": "fhlQIftF7nEVwl2vALBW6A6GqquGE8n4MOM7xgMqiR4=", + "epk": "9YWTi530DYHjdDIr14sNXOwLY4YS7JaMTumpAI5uJ8s=", + "ciphertext": "4Q6KdQMqoraECdTFmQe0p0WqH+iLaETBEKL1UIeUoEbO95X4QnTBY8YBd7f48P34FtXQoQ==" + }, + { + "cmu": "P4LrptQi4NF6Phdoy9DrliQS+gTJT1CiRoatN+rgoy4=", + "epk": "fGZyG+GSAaMb4gdEDWbEAr/cEV1oXpAKuSKr8XnNr7A=", + "ciphertext": "NzC8Qjg6OYQM17X88g5N/ZBiglEx/EHr1qbYFWY7BkXfVVnaLPTWUNDsiO7dq1ftw/bEfw==" + }, + { + "cmu": "XkX43gumsF7tRJ3Qe/IWnhmqexUfuUUTlhS8oyDpmio=", + "epk": "7NiC6dUVnlzhqcdSQegpeeNvKc7jCkz1j3VtAPgS3mM=", + "ciphertext": "nPGJkf3R57oVzsB3BXjGcLMNYTW74MwntukSCqfvmRfWZf7P4Kjb9EdlMY2G0PXvbQk5FQ==" + }, + { + "cmu": "/JH155PFB8VytJa6DoufuGxRQHAS4KgzNxBY2MhjoE8=", + "epk": "3VWLDvWup83xa8MGzwGWZ2rLsj48ptaAv4Pqh3hL/9M=", + "ciphertext": "pFYq43H2xuiy9m/3GJqjDwIJYQrXCFf6/SlpK/u55X5Cp7TObbzDsT2CPmfLBFyJQ7S+lQ==" + }, + { + "cmu": "rWIgaFXyYP2Xsrl8LYbW1w+s3FYYd01OI1LsaNGDl24=", + "epk": "QNSGnRNxPiyHG/AsBlWpUX0u265xvVyG59lPF4Bgm8M=", + "ciphertext": "m5ygCZsGHUko9w6w/7aHPeDhvPZGOXIRRRPG1PbI40zx1bsVUkTySbu/e1YsP7C7m/k6Bg==" + } + ] + }, + { + "index": "31", + "hash": "tVMvbaugkGMbKCPdTu8FZHVbf1p22EiDRLXvcnPiGs4=", + "spends": [ + { + "nf": "DW+I3tAd/msLJUOivshtnbalQy89oSZyEqni1vZt9Lc=" + } + ], + "outputs": [ + { + "cmu": "6HY5mvQCWYIR8QOwj4GOkDY8f0PqvtIf3IZwxmyO1mc=", + "epk": "kO6N23eteGmGwc+cCUA0W00T4byLTve4rgTYPO/eDLU=", + "ciphertext": "LxjX/NP/BVrfcNgkFdnEkQbyQsRIHorOxqR64hyUvuCWsZrFelLBj604S5OetsYm3Qgm9w==" + }, + { + "cmu": "MykV8v20fgAnHv2PQEZoDPJENisKDtSHJHrHASu02Qg=", + "epk": "83bWwyf+sSIRK9dmOXHSA/7c3M/gp+bvB3QBMV9JpMo=", + "ciphertext": "EGSylB19yN1ED5cm84VqpmZlvbXcjqEa9l6DvimmcX3Dex+Y5mmNYVLHkUIbHTRTaNZeow==" + }, + { + "cmu": "7O08Wsll+oGcY+aLyhRb/nq94wyWCpJQwOii3MuVNS4=", + "epk": "Wx/tNnFFh2Auq4EP2k65QxDSksRxUWY6wARfKtOFTew=", + "ciphertext": "28xC52c3MNsAGPjEv3FwT0Zws4wMb+uLqn0TDlNodcuVS5+aMkpmghMJVmPwW9yCycuAEw==" + }, + { + "cmu": "7VENYMCjYkaVHbPRUExNs2iEVB+lmZnZh+9B2xc2Xwc=", + "epk": "HKuV0j76UlzbN+qGQ7IljmdVZdk9ys9lk0ylty7mbqA=", + "ciphertext": "7UQb59t0OhRhfrvZZdS9iMNZrWfp4qc6Ctz/FYUafztmH2cJeN0wY+7/xHmHhCdqYzAL8A==" + }, + { + "cmu": "BHmnhkeehcggUOZjV6riFSS2uKzPeQNwbdCte8Jbbyw=", + "epk": "YNuxd8q5q+9b0QE7aYFC4Y63fwD+51/URPNDO7Tu4Jo=", + "ciphertext": "/xT3lTMIEMXpNORYKQ0n9NhSMbLB2alFZUOj6wE2qfBKJyV/7Ey6F2lGmnMWiMqDBG88SA==" + }, + { + "cmu": "PLzEpMPD1FTCg+V59k/DdJLqse1AcYktRzotediVxV4=", + "epk": "EZwNGvvGg/51MbRLHh+LIIdBDCVaRnb0iA2SacsbxOg=", + "ciphertext": "AemnsNGyNEpC3o1/dMgun6csmFmyNn4CSMDsHyDc98CrF9ROLgREmYO+EfH9cVj8Vr6HPg==" + }, + { + "cmu": "V4+P2r50Jh8S7W3OMxeNEwmIr0w5ISXxQ2WzDsLvwXM=", + "epk": "lrGFE9W5aLBf1cdpHfdb8rmXMsw1wbyRKcrg4+plP+I=", + "ciphertext": "FFSETn8bIDimL42biuNZFYh2vg4Dns2bmK3e23Gvvqkn66pkQh4lYMZ2u9YKE1//bI9Ldw==" + }, + { + "cmu": "Ns2DB0KdM4bObLFEe4L4I0N9UrjCYZASMNPmBUQOtRA=", + "epk": "/zQB7Y6GROcqU2GsX5mp++781zH15wegyWc9nQEhkDw=", + "ciphertext": "yYPdNwcYTenKve1bZ5b5DD7HSuUSVvVs3kxHbpK4fxusPpRTZFU0KckqQhhlvs0/WfmDAA==" + }, + { + "cmu": "Uz6pBQ22uGKY2imlIkMSfpHuXpimFMmsA/LWHiUm210=", + "epk": "BE8kPISvg/YKWFf5MPoN9kAh1v2D4AM3PzNmmJuPZE0=", + "ciphertext": "/568Y2c/WCKOko2j9eENa6FPoNYPwYcUgHsiTJsK9jV2VUinXQaE5DW7/AjcUeB8BEHlxQ==" + }, + { + "cmu": "cFU1a3tASDM2PqjdOsDFieB6C/y4i4Y+NqWn8ticuzA=", + "epk": "Nq38v22J1ZN3DtemSFCHyaJfJ5mPr1rzLwYD1msGqww=", + "ciphertext": "np9fU+pr0ugjkONMEsLNlSxhT/0u096XcPD5bQ1oibDmet+7FXZ5Vtb2sVMz2o5Fw0qGrg==" + }, + { + "cmu": "gOZwalCvGdItou3YHNoQVuPbwd1JqhHhZV2B9oRv+Fs=", + "epk": "icpZ74v+09s/BNTKKQQlK3maowhrnG9kdeUDgG6q32A=", + "ciphertext": "5XlmGVMPISTy2GUauUoOB/JAqGUJnat13gh+nygBux9a5wUkhz6KXaddog43w4zTZjsjlw==" + }, + { + "cmu": "J7/1CvIiHroBqYwXRWYzk9vaypzRLRmNM1nv+dG8+Qo=", + "epk": "L7faaRQWGX4pbb6QrmrK1mToJ0QpLdRtGCwp4mQUTbs=", + "ciphertext": "2H4ocr1rmLMZqwn+a2S9jVYO62bphfxuZPRzuucvVPf5o9finlCpY859iokCd9+g7mboag==" + }, + { + "cmu": "XO8L3eMrYY4OJUH65AmqJguKC0/dxSM7SuCojlc+Yw0=", + "epk": "arRzpw4tbtsowM98duv5Ych3mGg8Oi+B2GuJl7Ilwlg=", + "ciphertext": "0VxL6Swe57LKVxB/CycseYPaqZQt2dkwRsP1v6+1ePXj/NM/5fkaIlNhz9EMI1aYYbDhbw==" + }, + { + "cmu": "yLfrXDpUHbD01dbDwnhjo8ICPN6v4pRAndYQt1NnOVE=", + "epk": "8fkb0tCE9fDYwxcILmbUxUbuO2+yDOoNDkcPjbJjiQs=", + "ciphertext": "qTAMxrVR+M6Vqg/hUgqAhZlGMFaHZIHMdkQTM8HVur9c58lQxLGaTZY88B40c90UqUX5Hg==" + }, + { + "cmu": "pJ2GC6Q5QjJjzf0DndES9CdnLEBArgyiPIsw+0QysQ4=", + "epk": "0xbrtJ3zoeFGzcjlYIz2S9Ul8HMt1K5BloYRH7NbqE4=", + "ciphertext": "aoYCR3xFUWwSfuhDpthh51jG3RzrqShg24ffzFY638Qo1ojegG9poR1ilOXXEnexf8Jjiw==" + }, + { + "cmu": "lRbtxRg8/YRJ0+Hfr7EAQRiy/5jv0YR5InhwGlJzADE=", + "epk": "LMP3zV2jy26YAmS5rYZqHQCPk0I201o5ooqQG4TaWl0=", + "ciphertext": "QiNH7YEWvLizWDpQWBfIMxWNIQnF+5S6boyAH379jg6HXhLDwzvveNQho+XKcPiISIND0A==" + }, + { + "cmu": "MPWDegnwHFIvmP5MeCAcciXrD2lm8z3fsnT1y9b5lEk=", + "epk": "IQCdMB+4LvCovQjiTbPXsSUkpJxMbypFEA4voWdU0T0=", + "ciphertext": "l2i1cWkHeG5RkRalI8RrhwBS3jA4GuxtiuWZk4xMS3fFfL1KeRS3hCG1t6K9fQMr3KzE5g==" + }, + { + "cmu": "h2/sR0p11G/2FfSvArs9HHG4UgwsO6pGnfQWHqGhL24=", + "epk": "1ekzufJVOP068TN4uDfVsLz5rA0IzW88euSEfb0xmjU=", + "ciphertext": "Hz6u0+ImhaCoTgof7Z22roGALjpwUuwo4lS/9NE7//UpL6t6MW4PZEYPgC10ecGvTgPmUQ==" + }, + { + "cmu": "gV80g4YVvybZnzPr6aqTKTcYx0zTAbB3ZdtJf8BTVjw=", + "epk": "2mqn53ZCHoVZYrkfd3BV+URBteXLR8O3PVhAfwQW0lc=", + "ciphertext": "hNp1t4HgxiV2Wi7C78GhGGvD3Xiy0IIR6NvdmbvZK3AplTZbNJScnSb9ivNJE7F6NGf0fA==" + }, + { + "cmu": "vXu+pdIkhm0+7YaN9Q61BjUB79AdCNtTW6NtpPgzWVE=", + "epk": "CESd8/jvrtyTsg2ruae+OfuGlAKswiaSFZQkjy7Ei9Y=", + "ciphertext": "l+tsaoDdPKnZI4GGv/PA+DHJC/LTQL/sQyvJJj18ohwFNS3AN31mz0PApPc0LQg4cGb1zA==" + }, + { + "cmu": "BW4/Pel7kEbFlcCfUdc8V0eJA7UE5V7lSQeow3nFlw8=", + "epk": "C8XGIFi9jp3VeUt+IptHnfXyi4n8nrlzan6YJg1fKoE=", + "ciphertext": "UgMLT+LNkZBs9iu+bnrp5F2M5dhc8OR+Gt3mwDjMBUfRIK3aw+zf/RY3T6UGtP9X0TJBUQ==" + }, + { + "cmu": "Oc7S+c7HNXtE1Zd9CL/mz/5UmcFlTBYu9IEEgmoBgwM=", + "epk": "SpjbOt3PFZD7GP+4GRmIbf0JUg0RPCN6fxBJPx0gfF4=", + "ciphertext": "PHSYdhH8wsK8GYvsFycQDts1Y9byBVUgKv7WIQERU8KrqfSTkK+WdUB8yglxKULTYiIAng==" + }, + { + "cmu": "+yVNBVOjZDknljqskdCAkJTiXkE4q1o8oG4RpxZnOkM=", + "epk": "NdOnaMRnYm8ZdgSdxpcsGqCUWdFkcaB2zZFRQiEkDR0=", + "ciphertext": "61Rjh5vVv5kAv5kvFrJ4b/xi8DXKAXA/P1cMOaHs9sJ9QjT4kG/LC36Hmr4JSfhxnAYfJw==" + }, + { + "cmu": "W9Odx9oXt32nN8atOaegXcdPXAjhfoxUp90rEly9Uww=", + "epk": "P4a2S9TZR17KSIlTTXQbnLLAZv7f1vNIii5WGMaQnwg=", + "ciphertext": "+hrpDTYHEXH5phMNIuw9zd+GMn7Y7aXS245EwFm886FUKStbdvAyShUUTc6Y8TIMZHTgAg==" + }, + { + "cmu": "lWzg0bZSmh4L9GGNfFgSBHQTmDguZTR8vjhgtWjwXic=", + "epk": "DWqfyYf3FZP1Co0/g89B+iHPcqiJCw0X6XCiuUpIBwc=", + "ciphertext": "/pBc8wNNHKwkyK8MwpDi6fkHPoe6/qsIYsQ2j4vW5uxUKeDeyrzc3O6bYYdMLcka08vDJg==" + }, + { + "cmu": "pSapcKEvM/EESArwckd4g0QU58bS8arQe2LzBi7j/TM=", + "epk": "GJErV82h6MxCTKGHNvtaiqxV8isH2tqFF84FX9mevoQ=", + "ciphertext": "z6R5W8Dzd99DpKudUx4IVq0j4/q4hdtRMPTlY4J6voDgo7/wUB/BOs7Uv0VfM72a6WU5Aw==" + }, + { + "cmu": "BQrxblHhlnlDNyaDXSSuEDtKtr+rII0hX0aa5su4O3A=", + "epk": "0gYDYH7r/NCRGzu2UZj285iVvniMQ3QOe/5mwlGBCi8=", + "ciphertext": "3xIVLsUnpWhjTILjIYhQLCAYDOy1bDv1zeFvaUfcopLBbhg8ZhxHwLCpCWadoq2k+VH2bQ==" + }, + { + "cmu": "I3R0FqcFP9L5Jq+ACWqAadKWetxOAV+ttvwBiHgAS1E=", + "epk": "F6Wq83D/sBMAUznHuGtKyyfGjVJuJ0NPYBTmcIaZaqc=", + "ciphertext": "EDuxc/mwrs8fpbl+WJLK//Rtmhxdwa3iB1iVuxccCSkIAyfoQK0RNcK0nv1fJ4s3Wo0JjA==" + }, + { + "cmu": "CKOjEWRLVgSbUgQe5AG5jojDjo0A8vQGVF/ywIcX1Rg=", + "epk": "YYfnu7rHhOQSqFtbMtiKfX4mmrkayQmYkCTsPsEfGJk=", + "ciphertext": "cCVGWS3dEDimhSf0K2e7UgbP+yle0xpvwt+afRBYaH6TsNW7byEdJYTY32jCF5rSO98oMw==" + }, + { + "cmu": "gzl4BrrOesa5bo032VP4yqYt7b8YdcBAuAHWgTD2fAU=", + "epk": "o9P+tNqO/74mFGUUJ5cG4dNBsqvkTS/zqe8HmGxDgCc=", + "ciphertext": "6Z5XqgoC/h+6uT7HXWyXuCUzJ9cd2Y8KjOhQvC9DbNYgCi8EYDyooWWMG5Qmj+IAHdGL0Q==" + }, + { + "cmu": "tbEZBWz9H9VM1uj2uO1aa/k9QjUIOXG0KIkV8eSw/jk=", + "epk": "DB6MC/jbt3KCEOlCRhAtCiIXWEWaboXBOaDfG7ZsZ+Q=", + "ciphertext": "ioAQUqWUJjWe4wGig4mgC04CieQRlw/6qivY6VESFFK0ToWI7YhVzbujk0JH2Yfa5JHesw==" + }, + { + "cmu": "RqDU2aHXid64wuCihokAUMlD6FY0Yft8EYFNxR89ZXA=", + "epk": "CcfAdNtJRjr7Kocp6KVviJe4Tog2gtrOGd0nnNEAfbo=", + "ciphertext": "MU/v0cwSeDZfvn3Mk1hj4bWWG6xFForLWp17jju5ZcFTTXwhBAgSQnJQu8NugQsQyI/qPA==" + }, + { + "cmu": "JO+ElenAXBJelFM5tGsVtWOCvR5T6wjjdvxDqOhJcQs=", + "epk": "55iIa2CfaL3SW5R4ugy2t/CJDSKE9QN9H6IL+fxyW4A=", + "ciphertext": "oTPW+pWUsNnWyGS/iaCNY8AhKlI1oRRO32QlcqeXXMVozObuLtc4/qzYX9Rz1HvfVZhJlg==" + }, + { + "cmu": "L5rCBoBIP0MVkiaFyf0HVmgpf9TDXClpqCMFmcDFQT4=", + "epk": "dR9EH7mGXe4r1cMbVjUq4XEOHZu4M03C5sck05UCk64=", + "ciphertext": "niMV9cCu8oElPBpcua7W2OsyEWWAHIydlO63EDMw3p1dGlGntIVYOD/Dp0Z9jSY6DiFokA==" + }, + { + "cmu": "A/zoHUyq1xAi+ws8BbPf6UjeyU61mgwBREQxCfNSFAM=", + "epk": "8eRD1PbZFwmvZ297S4BnPu8EYezJuwZBgLustpz/r3E=", + "ciphertext": "ZmgQuhYGyOso5gkWIr3KJKyQOSoMOxFggP11qLiIyGUnRchSMnByFGAtJg4dXQwjnptAVA==" + }, + { + "cmu": "+85VrE6fKNGhqqfYxmJljKiRCgK8YSobR+PlBfrlSxU=", + "epk": "diIzoXl8GStT/Buosde7tJKic604ZHYYAyqDKe9i7D4=", + "ciphertext": "S2d3Ud6UCtNXbgAJj693i77okB65b8gmkzxd0tvSQmHF7rIZX+SqxRL3rAPwP6pdWkn4PA==" + }, + { + "cmu": "wW0iZB33lcP7M6C5awdcXS8JEkpZy/CugbHfsdx2CD4=", + "epk": "rE61Jts7njDU6fcramWSPOWEDpzuHlkBcYQXjgkOSBM=", + "ciphertext": "74x71wA61/xMV6jgC/KOb1G1c4kQNxE5nY5W7jTQNTShKQcUF3ytf/TXdFRkddXlTaBeDA==" + }, + { + "cmu": "EIBOfNPa/JTyN6st1aoFypx0fGAUJQV+rHzBCUh0tCE=", + "epk": "aw9bogQjuwf5y/XL3jX1NpiBHJ/vRdG1hVnHt/b9myU=", + "ciphertext": "P78iwNnss2VcjWOkgI/SIkkvlPHZNCXsaoP4jDLHU/+N0rdNLJ0KB8VYaZfzxphlZghEHg==" + }, + { + "cmu": "IXy9hAlDGvHstJIl86crny9gn8tIwzZ89tWoFuPbfDg=", + "epk": "cjqkRIzW2uPzj5trK99hULaxvgSY39wwM8Xvh7vJsyk=", + "ciphertext": "n0X8oUJruRo7HZw9TY/V9qcjSWMuARrNk4liK4UYAYQuXWcrhnf9bS/99C8vKsIGPsZs0Q==" + }, + { + "cmu": "1qGfFu7OJsEhDGw7xyaRysHgzVIrXPdb5BTUoIy+rDA=", + "epk": "kCxjPnhSOIrHmdVsQwEcrWzhToBz2xzjVNs0tqB2eh8=", + "ciphertext": "NQvl5MK16PzcRZGuUCnLZV0E3/I2LFY9wkqi2GuEUdCxW2Fu0OlnAnqehfAL1wu/izvaNQ==" + }, + { + "cmu": "Yhgth0lvoIFWFJlzRWFG1IZLqkHYuCLIiCVtP49MdhM=", + "epk": "QTX3symMOaErGEm3nAOhBnqk20AiL/0azLBhgjWKHUE=", + "ciphertext": "mE0Vn/+CczC1Luru1razKRuA+kxG6wHnUW8foFf+l5kuvoZzBNMUOwBQzGJnUiy0Dmkuwg==" + }, + { + "cmu": "EZkZH/TO73DzFkXF/11GMOLTUseBT74cJY2mKBFwwhk=", + "epk": "cPPHFA0GcJglqAAbvWXB1nwp19mBjxdcMyUleNSDNT8=", + "ciphertext": "ib0EsBUeKIDi15Hd/eAEprN8YndUOIYQTmWLz+8nUlM7u6FXn1vHMATHRcu+zhFDgkqzCw==" + }, + { + "cmu": "w7i2YaQkoTc9//lb75YDt0CFKTIUiP5eIb0ilhe0chk=", + "epk": "tUNQAnPe1eBCczo3s7sZ5DTqu2qAQjTCNI2sBMTC8sg=", + "ciphertext": "JB/shN1JDL531luGGV1PXgwoA5UYK5JFssGGm+QgEPzo+kuQoqLu4yaNilbRFZlX9gvEDg==" + }, + { + "cmu": "i3pCBBGgl5kPn1IMUhYfbtnCV0RRY3XgHxaGtW3NKBU=", + "epk": "RMRFtUI3Jr/E0SfdR4ONits4Ndoc6ao6XAtvNQMgvZE=", + "ciphertext": "Q4yJOow9joJsWmbf+qY4XamACMc3XJM+Mzcifje0ozLfrWBn35TJZQyhwTUXOaH1Qvm0rQ==" + }, + { + "cmu": "fhwC8XjFpRpj5vYkpURfggKBX7cID8PssMW+pSPodV8=", + "epk": "XL7LNl9NBoZePB0eZ+FKl4pLa359iK2uO1WFG88HWMs=", + "ciphertext": "RQQKfbix25rDQMe2Q+2+Yv7rt5yqpJ8DvPudG2qvAkJHTZSd8CIYpsnkCEZCz7NMLQlKCw==" + }, + { + "cmu": "lrouF0r+pHQoJquxjG2bnv2LNOKL33pu82ebo1sjIzM=", + "epk": "NGsCgN3udAO4OHsq3fW8BmeZSsZBAXam2cjv0ge4yVU=", + "ciphertext": "oZbocpjKyXwNJserEqT03+fvCLSi4aljPyChxOovosJ/MbxYp92SLp5g0jrscYYqcWnRfA==" + }, + { + "cmu": "+OO8Z+HmpucQxFA/8wv5OaHProk1UsTj7qHRP2SKbE4=", + "epk": "MuguNtHeug/hJTuzLP692QLGA9r2l5u700+luM8hm/E=", + "ciphertext": "o174+Cbe+u+QhBCwBNSCzEcb1DDvpAseEIR/W2341TiX5ACsb+vrsmAYWIPk71TdmCAkTg==" + }, + { + "cmu": "Wbavru6ODNc6gViJCVPh99XimCWko/ZLw+BvdFUuXUg=", + "epk": "c98YHuiLqHvzftGlrDQ5kt7f0QtqVH2cuFDhgQiBEtY=", + "ciphertext": "/uOeq34atFLOgsoJiWf8RncVwtYfdzbY8Z59fQcRcCSwO9ntyTcQeLDVqJeVR3G4kR8gog==" + }, + { + "cmu": "k4/mjvSL8aS/Zk18SRKeLRWtbXDGasvHTIJ4LE+KUR4=", + "epk": "Jzl9fWB+1SuNFCO5DQF9jAJ4/pP3oHfBaFFYnaZJhfE=", + "ciphertext": "wCzLzumxj5vBThI5JYxshnNEJf80JrMw0XRo5yjmLixkUw/WgsQ07ZlOH2o7zm5yMYvi3g==" + }, + { + "cmu": "ZWFXuF2frSjdW5NqeJEyCaPGBOoKRv7Hh9I9mmbcvWs=", + "epk": "KFTeIzaZGz51JvI05QGCmapDoeoiUhLkfSFWmpBqh/E=", + "ciphertext": "yfeMQvDzG3MObZ/HkkeeABClW4NbsVX5Al1Nr1lmxNWZMcS6L5Q+8eoCSh/jwttA5mp1iw==" + }, + { + "cmu": "8qEznLaNiUyanSlXlqTSNyQZz9K/heOnaKS10rgp8BE=", + "epk": "A5/k1ZXSXCm2ZLGxdFg2t2mF5CE8fDr1afkEF2Pi1iY=", + "ciphertext": "UHvbNDU2iQB94gk6JQMN4RYZO1PmYSPzZZadNDgqYGcbcDC0ATEgQVE8W2d0ZLCyuv2QNA==" + }, + { + "cmu": "3zYmxnsYwMLzAk5RVIa5LM9Jkk1UFR2OvdyAnxmSzWI=", + "epk": "/Dae7MtA3QXnoWVlasI/bg1CMJCqVZv7ILF7v7CnXWM=", + "ciphertext": "aWTAsoSFvmsROfw03LKU+0MgTfUSmR1Q8fosfaoAmJVOaeUL2Sz1ybvshsMPJ7wkD/JFpA==" + }, + { + "cmu": "6U+fr7TOGxmx8EvhaOpmzjjlIxFj+1m/x4PNHMQwjho=", + "epk": "PMt9JJTYr0n8hIwya6Ij0U7Cm79QJT2lv/vPwmG/tMg=", + "ciphertext": "SAliLubUTYxE+B56Kt05JJ9MlW6ViWxhJ+ENzHkyqjSAOace8G3YBSbV00KWcpXXYd4LQg==" + }, + { + "cmu": "lhpSv79+6xSzUb/rTlN/xb/ombwFP8vrBLZlZI0AQjo=", + "epk": "q0wq9MHpj/InMtsgngrgKGqkLpcMybPmUkyURoTE7E8=", + "ciphertext": "Bn4y+xieusV6uEoAdrfsnUEOXRNLi6eAZY3pm6kMAVU8mQ8F6KFLjhrQqJuCfaWQTe90nA==" + }, + { + "cmu": "yVeft96itKU1FQvhM8OljxJAW5hPtUb9P9KIDbwZ23E=", + "epk": "QXlS+peb/Gv7AR9c7DI0So8w6b54tyjHVwhfwVtAfzE=", + "ciphertext": "CsrlT4BEtOr5LnOr5g7y0kWL/g2K131/4sYJRyACEaOAU8Mmf2fHLT0SQ2RGWFnAM23JxQ==" + }, + { + "cmu": "U1ngEa3kRqxXTX1VSPTPN37w2zNtiWoNAmfB7mxfhgE=", + "epk": "gZMo/SW36YKNTvbZY17bQpfor5pnkAxlj9eC8fUtK7M=", + "ciphertext": "25cgjGJR+kJEIwVaeztFqRLMVUU19ahBuxsqmFvCPRiMqgFc6ZPTkyeUvJIe+OxTIqal0Q==" + }, + { + "cmu": "z+DAgPDteFuSt/bFiv/zBR2YcAherkqhL6aCl9cZXDw=", + "epk": "9ObkQIByMYGPYmoJvBPQvvuT5m1jeZNudmzQnbLSRis=", + "ciphertext": "V1/t6HcqGUI8jkjMngTw30I6xLS14mp4pltaWEX9U3XLkI4r9V8TAI1h17C0rVAC4+Nyrg==" + }, + { + "cmu": "k0CssoKv9jabgNSdvVrIPcGKivPV/fgICIArs8yEKjo=", + "epk": "yfLhdTgDInb3rOWF58TEW5Y/XIoa9m36+0M85v/xh6s=", + "ciphertext": "VlXto48vm91k01KjbojSsPFx/LBEY2k20b1Vey3+48Gpw5EDLZV6qqESM08YDrN0uxyzoQ==" + }, + { + "cmu": "wnRF4qwR6Hac40IgFop+6Iye9ORU9ltpy/CHiktFET4=", + "epk": "7xzcVCIwindOniGI4NmRXlzgjoOjoLnvhiaPbpJWJaw=", + "ciphertext": "zR0cqvUgryvyVCITlVPohzpxW6jzS/3QLmBsMuVynfjIl0O9+/kxvQl/wJ0+/I6R7z3iPg==" + }, + { + "cmu": "COxuJpluM9dTJJ6FnYaPxOdKuKAKJqkdrKh9JYreA2I=", + "epk": "TpMUxDliKpOYOp1ZmOoeBiCCjr5X/ltbcB8q2hzGqBY=", + "ciphertext": "eY2IZzT32xTxOcnMIJjX8nqwxDxwRQovjh0sTxwydkwkb9nzAAbrg5yaIi9C3RVFuZivJg==" + }, + { + "cmu": "tgDHcj4q1AHEm+Fu/NeAytAMUCnluQBEsUQaVH+Cz2o=", + "epk": "LQaj9w3FSjzmja8z++02KH7n6RHWmZ2vyzzmzXnpjh8=", + "ciphertext": "yC4cD1V3hzITM+qY+Zd2dYAVh9UCn+pD8ktdryO8RPOGj8kVN51mBNdy7tOkXKyPoms+lw==" + }, + { + "cmu": "Be0ue8rjq+XiL1e7sXkBPs+K/pX4v7bvyZximOaq0DI=", + "epk": "Xo5nUcJO5WciYv+iRIFnihWMo3PctLLdJTwuBLTUpVU=", + "ciphertext": "4YlaNcx3ZNkF4CBAIgivHQi23gLClt+Kr1rf7ZOvVHDWxE9FYUX3K29+31WJwlRJg2UJjw==" + }, + { + "cmu": "pI0h7N0gAfqqNeGa2kKmRQ84sftemYwdadXFp9p+qVk=", + "epk": "mJXfPK7ZLqtBukf13kGKB1cVSe83zajgh9MY+zmsGps=", + "ciphertext": "hVWX2aEPQ0Z+fqs1gwDvExMe6D9vp8k2tN64JD9ciSU2CND+wflFUhC92tjMS0ayLLtBkg==" + }, + { + "cmu": "/HQzI3gnMd2wz6t1gQ5YwS+0wT9mRoDh1PV8B0NQY1U=", + "epk": "bDMuwGoodBXVbBqJaBEOvq3zN2Up2JDOSCz4HiFwb0s=", + "ciphertext": "Mtv2Ahw8qEq6lBqIgprFGkw877gubWzzcPTtjZrwetKuRmyP6pBJzI5UdtwkWdyeFKT/iA==" + }, + { + "cmu": "4SCrCGk6DlGuL31bU+TpVTazjFrVd32B6SKOHn3q5zQ=", + "epk": "hOJ4acUGCuF//ZtQLh5TcrwQp8CyHflZGapYsthLwmw=", + "ciphertext": "4bNmiNzsRBBlHQoMNpvRI6VMuIilPZ8RZmMEDHE4JnKjn2ceNtxYYiwyY7hNFrmL0R3Q+Q==" + }, + { + "cmu": "KIaocr2N3KDhwYRM08UiDjElbCIv8kJ5LIGUTCtgfzQ=", + "epk": "klEi3IV9tuCPq7vfV0hWYZxcye3Y1X3NpUqjSYRYPhM=", + "ciphertext": "sV6tSg7YfRBUy+YX1mGvlK+YLYD5vxef9Uf2Ku/tx/oxz8HMf+iFxCb1zpsYIYXXYNa7hQ==" + }, + { + "cmu": "wujXE9NoAq9+iSQ4XgswmyGsHX4rr47jOPIKLvrTcWo=", + "epk": "Ys6Famv+m2C/QMQD2dxVw71lxRZIhRrHGdOLSK+XUgY=", + "ciphertext": "2wTdzFfvDpj4C9neaDGQ/olB2DogUjMegoo7gKzRKcSD+9kmqqDukfFaGoGwFG5gi8eleA==" + }, + { + "cmu": "bjo0sef7E6Hdl+hYgBk9yfSA4jLfnlDsQI3hqC1u6Uw=", + "epk": "wnMl7vxDOu2IGnyxlTmbNBXZyrwLcsf5uzhfRnFqmbs=", + "ciphertext": "v9wwukMcv4BzFZp2LnfNXRzoQtB1pN25eT/QyV+0P3JkUTD8nuns4IKAKMJ0u8ktB17v5A==" + }, + { + "cmu": "uNewhWEicyiSzN7cN8wExnC7O4WOlbErCul6rIozaEE=", + "epk": "r8RE8pY0U+Onpba6xHCx31gu6zVR3RpVuLqPDOpBG1s=", + "ciphertext": "TlGD1cOuo3Nj8/G92ONNaifaw+YZJJCzjuwxf6ofZnI9UHepkvFzxbfILP04pWRLVR6Q1Q==" + }, + { + "cmu": "wbQXm6mh7MYkc61X5Jt2T7xt5riaAIdjFkUCnIelrA0=", + "epk": "yaSdgCyMgOhpktIqLizFVaoagvRARgRDMce8tLe8DbY=", + "ciphertext": "jtacfHQvvKol+3iJlEiU3C24xREl2j66S+chRlWiCDgFCNxBmdTjKwJk1TgP8fpYT4sHLQ==" + }, + { + "cmu": "BieeVle8Vn4QZSvwJcgOy+FyUO6s1A11rDfighgA4Ac=", + "epk": "t3G8cMJuSmkhaMVGcEzODU0YqiQpvN0jn1qIVlq9LCU=", + "ciphertext": "hJFXx0swcySdBl/H6vmN/naHUSHMq4sPIyZ6z20bRNxoUOSA/jbbAoDrn91nBdcY4omqwA==" + }, + { + "cmu": "g/2s1WV4v9aftobTehy4UcT7X0Mf0MiwTQFxUyLHkF8=", + "epk": "gj0RYotHTeXQVchQuoPtmq9lq5WynWwAMrx/9UW1rVA=", + "ciphertext": "AlJ+ii2B6MHimayOlva3YHaoB+9VwIltlAc5cBLcLQX9CI2k1Hcdz2O1BrH7OmMGO4Ixlw==" + }, + { + "cmu": "aMDTjXDTfGF8rpagN9pAeIfUELAA3XaaRPPqfhCf6U0=", + "epk": "983UjX3kM/YBdZnMviQGuxws8rll5/UzEXb3Be9VwlU=", + "ciphertext": "pd3wnCZ6UkY33t/+tMoHB9MqOkHxOt4ZJz55UPFFs1TrPt3GYp2MaNHKqPOUmRvvfJc/Gg==" + }, + { + "cmu": "l1b4AZuNxY19Lwb8zlQuYESVLqC2bzWQlzmuJODjshs=", + "epk": "2IQAkLmZlklP12c9gR2WpKJlUWw5gmUJzr93AF9qz08=", + "ciphertext": "5OXvaxsXknH/WIBQ97xLxoRGtPpNWLFAsnYm2YEtMqQB3DMm/bqWYRNGgeyMNzyvOzkI6w==" + }, + { + "cmu": "TGchwRRefHWet6v3QWIHgV2OJ0z24faTjxe+xJqA2Bg=", + "epk": "zGvmPH1E+rpNpzkKGRDy3ZzuSUYgMgtqRllukt1L444=", + "ciphertext": "GpkI6mrLzlwwYnnyVv1uPPiPZL/xEbtgx7QlsR6DIUSRoyGjfXqF3GWIUDvu432W7LLlJQ==" + }, + { + "cmu": "7ECJyAxoxxkvrma1YZx20SSL0haviiwxNFc8wkUWXCo=", + "epk": "cUe2chiYw+KR7rqMiHA9yCq2qUPzU+nCy8Ds+s3x2oI=", + "ciphertext": "WQSYoNB9nhvXXHW2TvbRVsFcNIKbD57Ln4Qs2yg6qpPmLDJ6ycIbMqoCuitnjYz2z6Y4Hg==" + }, + { + "cmu": "0PW5qyF08Ie/uMFBfti6LvgRz8h2gfB3unFVm4bha0Y=", + "epk": "OlqpeChN4A562qM0kcI7loDPQIQJ2wJo7L6GOvPMB2w=", + "ciphertext": "hU/D5n9CNe6aFzD8CXo9IfDYJPLLWp3qYsZ3dSFxLdYflNsYoUOdf532V1JGROUZNdIA8Q==" + }, + { + "cmu": "l3PNv0BaWQHIHxbLiC3TLfhq3+QlRDK8dTkXgijDfmA=", + "epk": "vKwxTvjwD2X3ssD4z1hapwbNFG88QHnKZjV4dc1CKJs=", + "ciphertext": "EQVMMb4Hg6LErwVv74YIoB/FzK9Ru3YZX3u+1ofKEylTtC+HCfdEAkf3tXlqNu9efrD0GQ==" + }, + { + "cmu": "nKioZxK5xIgFB6JYKIylvHG8AAduzGjnpA0yWFV7/j8=", + "epk": "vEp85aAJ2WnoxNBypJKBj5+o7bdbre1D0kIOP8a7i5k=", + "ciphertext": "xjnOOMNmyzpkiQlb/jA5o+mbWWX4ssRkAfT2Wp5XEQbXdxngeT8k3yOMMcgNqxWVHzd7Ug==" + }, + { + "cmu": "T8pGdJYGeDsGMvm1MqL0dUOKdWOeolMFV+guMWrAaGw=", + "epk": "tdqLHqJWgg9O7AiFhV99DAOhBZR5VAL4IByxp52ExkE=", + "ciphertext": "o40LvBVtQfNIR+4k3lP4JqAWIw3zijeHOmMpw5Np+JsbK1aO5cLD0Paib2SC0o7PozgoZw==" + }, + { + "cmu": "SWS6L6z/yM2cWSYBfClbvmCxMboW1sOAnFYUqRs3nBE=", + "epk": "5TGHMAfy2ScWEEjhL/h8wAXjKNesK0AnvRMu51zXOI0=", + "ciphertext": "+WzGhOzdrnj6izDOa+TjYlknzLHaE095t3NOztHTHdM6G8yEbXvtQErH1ZS1e91uORFC3g==" + }, + { + "cmu": "Eqh3qJTPfgjiL9nJE4u5X1G53yd+gaEuHD53mGJSZz8=", + "epk": "ZTfORP1Nk6EApxo9YVXKdYCRcuX7igFAH5tnI8xquPM=", + "ciphertext": "R8L0MxL0rGD+c0DxI2MC1sjyK3BE6ry/Qx/WadhhhLxbuqF7icAFMs9R17AwtTyKspuCBQ==" + }, + { + "cmu": "geEWIcBjS8/UgSJI4Db/rlxidpaDIryCsz/tMgtnwzk=", + "epk": "RH19sJfSdAi9hvIjxIkN1oHsRQs45fH8y+qCa6tk3CI=", + "ciphertext": "sNCTKJYC6Cx3NwuvD7BXOyjPObQRExlpDG7eSo23ytfRzgTDARcHt5kPfG5t5/vzMwoFNQ==" + }, + { + "cmu": "QiPsiR4LF0jd1XGYdyRIf5bfQ5aHixCz6ZPjFz88GBc=", + "epk": "T07lF+CLIK/JuEurjUb5H7AUnilVyW60Gsxw173yzaA=", + "ciphertext": "aFqTbwPf2RYmhPo4VQ3C0zWPBQc0VzbwjSZXrxKuK3EjtESK7FrT2ruCfe8P3osn33ysAQ==" + }, + { + "cmu": "D9ljjDDRbdpFnT228qNpe/fiUKs7BopiK1qc3e1DdEk=", + "epk": "7A2TwZwEu4BGs/ayK7pyCXglQMX2/KqGLJNovzzwCW0=", + "ciphertext": "kai3ySahvzRd898I/9BfcMAP3idwibGM5xUI9cqTupxwOL3OavLkAfODIKJJxWZNojtJzg==" + }, + { + "cmu": "0+M4ZX8Unf/4kHGlWYDAE8SKfxq6f9gMTpDednHfEyk=", + "epk": "93YRrlr3GKOmql3bCRhaniTekgyZTh+/tnG2hp9qAwY=", + "ciphertext": "yn+1rZMYWAS4+87WP1uMW31Zh+O7dh4emsXUBAuZ7dDZ7bkAjDw2ZgFhbLZkKcQbYIHWWQ==" + }, + { + "cmu": "0Aox85exPzcHZSVTlQf3736M3OoTZ4x71OG8giAun0k=", + "epk": "CowxF7G8wXdredlD2REf0vlw2qfJamXi+Op0jEcT82E=", + "ciphertext": "c5FgzwJ/umqTB+Pe+w5C5cjMnLaZqheHtx8cAz8meEabP0QNdgUj8WOpknazrIlCrIdt0A==" + }, + { + "cmu": "YKXn2eIFDJnTTQJBB12EiLgjJG3t/I48fmur+VsVrmg=", + "epk": "7U8lQ8or2Ednz5BQsAHHvMVXp0IvNI1SqW86zOzDFbY=", + "ciphertext": "wsrOhpCJXqCSlbZWA68ECEwlMxuWkLk6IF1kXR1lPFs0j0K1ZTNVBbkdyupSY3Z3xFUacw==" + }, + { + "cmu": "ydnfhpUJ2Xt9TkOBFIL/fmsoOGAUtMJECW5HcuNKHk0=", + "epk": "ZiJv95yFJd+09WbFy3kEaQJcLxjhWi/QkXKXDPUzEyY=", + "ciphertext": "NppNlw3f+DLqJ/QuZoB3Fbj6cD6VlndgidQSO0p0OcAbTNyVl8GVi5h2dkMx2E0Jl/mIew==" + }, + { + "cmu": "gDK42H3LHHLX230KHUmZOAF4C96YQ9Xvgq8dpmlzyGg=", + "epk": "6OBvJY6fJn4LP/5pTokN9Bj8cufQN8yRxlWGZoYKJ6I=", + "ciphertext": "2fzypL89Ees7RFwNy/smDcc5Gdtx1HrpRaje1KJ0bPIWETcNxs6ItSQO3ZPyLaqXEDxi/Q==" + }, + { + "cmu": "49JH9eeA/rJGJaJ8IoXG162VugveQzoFWAkUXE11PnE=", + "epk": "ReDsKHni8yRqWeL24zc3CdJfWF5523QeJx8vUNICF8Y=", + "ciphertext": "3NhuNcKdUb5T7Hb+ekW5WpaWFVFxoYFjPIBj8QBxIbdZ94m8peKyanwN6IKNdh6ih4WSiQ==" + } + ] + }, + { + "index": "32", + "hash": "Ir7p1Ab9QMxccrEOsTDPLNo1UxHy2tkfps4CxIfMH1I=", + "spends": [ + { + "nf": "qQ8k4n3gVlSzNtCqdyRYlmlQB50J3OUjBpWT9t8ihNE=" + } + ], + "outputs": [ + { + "cmu": "i2m/JnRFjdQbL5CZXwseLy5TeFiNl0tcJPtDOWXPaQ0=", + "epk": "tltQXRXIDKCqlZzsaXpvMTzlh3LMGCcNfkoRJZKZpu8=", + "ciphertext": "G+cvNSQr/GRDz4Efn5l8n4xUZT6feZzA/s7/KY1oc7LHWOgugJaz8NIOHAsXGVinSl64rQ==" + }, + { + "cmu": "mq5X92uJn8ZFI47la4zwKFweFfujtSSxW6lQo0mFsjc=", + "epk": "XgHqmG7/Tkfa/JXDUfg1wwnIOSulMD0Xa/VHjJfKkI8=", + "ciphertext": "DmzX4vOwIHiYTDXBw+K4criHk9EWsPnVQNTMqMM3d7hue+UK6zi/P8/IhpESo5DtSVHQSg==" + }, + { + "cmu": "ToDNjQuEzxDIZo5+yOh0SIQjT+6CWzVOyi8z4qrccC8=", + "epk": "eZ4dy8GerZhgeiH7T6E01zb/94Q/kdmZgBr5TuNynSM=", + "ciphertext": "zXpFVX1MFhNrsmebe9wWTzhQP6kSva0dl61C1OhHnXs8lneN29/pn6k4JIAaSB5VMNjSUQ==" + }, + { + "cmu": "9UViy/mLMoBs6OsptlJzOE9qIadtT2nsuQCpND85QW4=", + "epk": "O5kPp64LVTZz5YcqZ7jG9vJzobPLNVdcbhrWDSEF95k=", + "ciphertext": "ZJKbS8rDR47vvrKzeeT2FtjrzQk5zJ4Ffd2jj9VimlP+Y/51MQ5H5SXIsQmfaJwrkJlsQg==" + }, + { + "cmu": "fGPQWbybuGqggK3V2jc8JJHuclltixtHuD51ASzxuVw=", + "epk": "PIt9/yLxua354emPLK7o8XS/1MF/hSDTo4HcmXFLMKQ=", + "ciphertext": "WfTrp1UoQcZ1GTKBc4s1uS1z3f9rqYECH09HcHQHbYoad8lhUwRbrvOMvteXGW4H7AsjRQ==" + }, + { + "cmu": "dCHsBQdlPDmAQqMThnUIKkTMcZDebzoYc6fynShFy2s=", + "epk": "waX9d1fqB6m7CCQoMpcT29812iCX2xq+dhIp56kgcGo=", + "ciphertext": "x6WzjFgH6fHBA5DFLb2Ue4zCrTduCSU1cOSql06j/dIjFYmprim7BoG4TPXxG5R620uzqA==" + }, + { + "cmu": "x2bp/eBj4Ax86jZ5exXjB681Z6PBo5GymLM7rZ3kgVo=", + "epk": "lXRt/Y72J3hkVyDDHljjQ77H8qntpPpeW141mQMfbW8=", + "ciphertext": "kPOgvbWcY8oux201nb+NgXYfozbt9c4KzaS5XTD+eSIHDFlHuGuIkDtGMh84unjv3lmJuA==" + }, + { + "cmu": "KZEah7k7wJC3ODyUFrLdPj1NU5+Nb262y6jn2lG2iz0=", + "epk": "OQQWjZwS/zuOGEt1snGIgSAiuP/Mp8AIk7PqrVeM5rU=", + "ciphertext": "P0c1Lx0liidGyqv+WwGHqrkBQNrhRFOZdkTf5NHwnfOCgfC1hp/Q4CND8Fw0SHpDNheMLg==" + }, + { + "cmu": "R80+s4srU386/4Oc6GaNabG9tRliBRUmnv2MNa/YsmM=", + "epk": "sORp4hdPILUwspy8YhdNc8iOkZExszaIoD/Cv7IR4ao=", + "ciphertext": "NEdhUgJwuD51srKqvoSE2xcy93XFVHqStBCVObHbl4Rr0PcQ8J12MLdk0N+bPNgi0m+6QA==" + }, + { + "cmu": "Bhghcg+PsKfHASRUTaRkGXIjk0kVgke4u51PHH8qtTY=", + "epk": "15zLkPNKk8ZK2QHhmf4IumdDaLSYnjn+MRQeTgu9zqc=", + "ciphertext": "VUnz/tHuUtZIwFbMhetlw17Kq+2yF+CqMY0kcuUnzD50ubMZox4c962U4C2Pk2nqikKwxg==" + }, + { + "cmu": "pnqLt9/XQTgalaQ1C0Me9DPAMgzQeAEbeEe+MHjnyCo=", + "epk": "EiH/6l1hcm8liCeZ24oLweMOP2UVDw/77ESiABo/164=", + "ciphertext": "ShSHElSdgSjtAwsRYQ8k/Ktq4iV002QbTIS92wRjsbPg5euEIRWqoyhvHpfObOxVCnYP5w==" + }, + { + "cmu": "OsPWejGZe6gCSL9fUSGnC2QuanxoNK9DHz8PMXrMXS8=", + "epk": "Wlr41HbW8B5xp7Q+bFOIbyIvuOSB+hAJqn+DohMiy9w=", + "ciphertext": "xmwnWeWhhbvU93m3+qUwOZVsJ0KvXS1I9q4iz4ifxR1hcTCHOwTGkmoLZMaHAnVazN611g==" + }, + { + "cmu": "qJ50Acs4rii7Ihv+UKE3Kfy0il66nOSZLB0JINbLJTU=", + "epk": "Bc3HSKDJMguYQfRLAhwKXyK7N4IT8/EU0FzzovgjdIU=", + "ciphertext": "RyshLnmOnCdhiGcRmtPal6qjsXobK06tp5DGhfi0f32Zfyy2pQ6C3dTQBWHVoP/Im8URvA==" + }, + { + "cmu": "2hihO0RmfuzZ9lgOCrqGWd1kvWpDkiOvanTMxGONi1w=", + "epk": "PZaJRhHl89lzjVotbZzpIYTAQsFJIAANDnm5bi+EDek=", + "ciphertext": "/za4w62bG4vdTWYX/9V6xFpvbxfw7Ay9zPEhcghOGAfDzeLI/lgL8ONU+np8tTunuCqG2A==" + }, + { + "cmu": "ANj3M1Uqi/mTLDpAmP2FBAYzkeQbhzdUUBdK8Oj9/xE=", + "epk": "hSR+uXj+30Vx7OML0Ls/igiNHGu8uMBo72ekmaEJMCk=", + "ciphertext": "4uYJ16WIueqG4IfaZMyMOqBmHWfWkQ89odE9JrRV1d6JR4ZlhTIqSzigyIWaLoMm29SJpQ==" + }, + { + "cmu": "VfchJ11CtX5eFg52QI9D3L/3sTSDvQiFWA7PMimrwTY=", + "epk": "KZSPuH55PHOOxmUQjIyCUpv11IQUQo5Ge+N18xX4Kp4=", + "ciphertext": "bshA5RzPJNSLmo3DTKCijWXuCmNHWBeV2l6me36Ch5XugRkWTfPCQvPmSQ4Bx5088/5/MA==" + }, + { + "cmu": "Z9ypOkGr9z/c28J+1fH52e661nQISLmf25oRokoP2WM=", + "epk": "9wVa/CDWoYqS0ftEF1fRTaPhlIFmfmZkMyvQLppr5Zs=", + "ciphertext": "z0tZlM/Ax6hn7/aWvEqBlUnNYtJYtGAdE9xONKqQZJsRI18MdR5zhFUUViWaaTZWnPW5/g==" + }, + { + "cmu": "io24Y//qWGK5XDC3pl9Nd5uDnCz5xyDcPOm4cM3k7xA=", + "epk": "Gy+TgO/qtGv682XpSOharEjWQwtXrYS81xbzXuVbnYw=", + "ciphertext": "2Q5FNhVGCERWYZikB3ZF3vMiCdv1GahxRNpXqMkPnC2Ee7WLH63bso6oyhJ+HHP4FZJUUg==" + }, + { + "cmu": "kh1VUaYFTKB8v6vGEpc2e3DFKORmisPRKYL3G1eEXFs=", + "epk": "xItJQNGwo1nef7SHGjnGskkF7QBySi2eyWgmvFefoyE=", + "ciphertext": "L7t3q/UO4uUdXGubUMu5gpTxNJANsQb93CADb/tFK3mNTdNiLe6Mpe2cYs4qJD0maHJGSg==" + }, + { + "cmu": "bwpxhlI5I5yjEAECLssW5GDhzwwaYRsQhcNagAFJQAo=", + "epk": "d6Quv9gBZM9r8cslLJJ2/T07VIpbdJxmFWz8XZL3wAs=", + "ciphertext": "fB3WUTR4W6asagq5Cp4uZhRV9DhBAyNEG82MUqUAjTeut5mwKEvxSR9zOeg0I/Ie4obX2w==" + }, + { + "cmu": "fqNlV5B/i4qxQ4NnY3M/HLYZKay233EJR09SpVT1GSU=", + "epk": "PIRVQcykUmf9crkZT90RjHwp1zfIkyaIgbfIK98Dv4s=", + "ciphertext": "VlaStnwteA9uQ4iapXL6G0DOxvYVDD04qmKG3ClPpvEDlmcaBdlJVPB4KvPWlYOYjap/2Q==" + }, + { + "cmu": "1eUf7fK+A3eHf0ntTUkyDgwbjU3/rp8PIEPKDcqFQ2s=", + "epk": "eSBcErJnsz4+adU844foeLt2RheDwiWlipYOvB3pZSk=", + "ciphertext": "tbRH0ILEYe2VvJuPv6/4fC2HFLDmbhMlET2A9i39EmcUZ2OkQu7FBqkwrC7AAbmyW3EQTg==" + }, + { + "cmu": "8BUwpp7fTQhPnIRV5TgQ0fhrYSb+HYKfHSqxLo8qlhE=", + "epk": "b09ztMt2jjFWmF5Z7+mDHO529X4c/1kV1o9tTNI1xzs=", + "ciphertext": "2Cd4g0DGgtNa6dfSpbaaF3caFX5k6xmdM/4sgSVJDN+Rv68yMpxEX0mFeK/OQ/SWOj9fJQ==" + }, + { + "cmu": "QWJbjj2+PCVfp0ghevWxhFmqwKiUub1HgAloXgPwkyM=", + "epk": "Jn0HbKWWC/GiegkQBkXTNdseCshGrRBbEozaley7iUg=", + "ciphertext": "mYlv3S18m0obg0AYPZ7sO++iABO36XVEHX7rfZhG/U/YCffyyT7f+3F2B8GJuLSjCYrfSQ==" + }, + { + "cmu": "c09puALfoiShA9kf5LpcY+k6wnFm7yYoPTcB1wdhCwk=", + "epk": "qdl/2Q+2Ru/WGfhfx4FtmBcX+XuxoaGA6pyJDsYARuQ=", + "ciphertext": "k+5ukBnOalQilK70HYVl3dDqvdh469qCAWSZZ2rOHiT0r6qMY3hGZAeB9yrGY1DJn4UnkA==" + }, + { + "cmu": "nNwN4ZduIvOnSMu90TjGedPoEOpbJiK5v88BUQwZIUw=", + "epk": "9szF+Dwr/Jyp2ISELxKpYnF6BTWbSsK8pgrUKEh0R1E=", + "ciphertext": "iMZqZEjP15BG72hCtmdaBcuAh04aCo7FkrtiKR6rSs9DzYzvIPy5eWZgrRHmy7jB30ZGFw==" + }, + { + "cmu": "kBLBexjoznS1wyRoo1pTKrKp28oGuYRw6wR+XwwsuzQ=", + "epk": "+fkzTEiIHMfLHRHy2a68Qrf47WjIKMKA9ZvEzZ+MFlM=", + "ciphertext": "H9KIsCsurAX4ob5D6ApAs3dAIY1gfQ1fsHkXqHli9G8RIslYhIXX9Dt/Ao9xqrpWnuHjxw==" + }, + { + "cmu": "xSMshDPa2WqXerqH6a6lYItIAjbF9TpOz+KY7B49Ai0=", + "epk": "fxqcNGyH5XlXj2MKtysJ5dTBKPgOQiOZewxxVeBu1L4=", + "ciphertext": "FRsZVT/sbCXm1cQIsnbPkvSBzOz2SwATbref6nS/HwEjiBPDUja7LaksF2FJHYpueYPmJA==" + }, + { + "cmu": "VFBBl+cFq2T0yPao9arYij3GDz3siivfKVXPxamWgBM=", + "epk": "oK0yTLvGEedU6aAPoHi5yphGqBrqxGsthM8ZMNk01Js=", + "ciphertext": "8XgSppz3Rl+v4o1L/6SMlt0OanKqTr3/lNMjDnZjkRfoqPdtunG7UVCRJLJN47Ih8niZFQ==" + }, + { + "cmu": "jjEw7vAQuKtrkevB797kN3rSvwSxxWLQKC4aQfmH6DA=", + "epk": "gqRTo7BsvWVdssNA8qaNIs9FhBy9lXTkHGj5SvstJXA=", + "ciphertext": "+U1YKsx/ShxNHon4Ztdlc3jY/sqmMpIP/rYErI1+AjN1Ombn2spobCHAGDqO+VY6FwnUrw==" + }, + { + "cmu": "k8wBRP2GKH99iMGhfdrWB/s2lkGhXvOF6P8p2/EqFWA=", + "epk": "FcVe54acXt8egVhGMuz72bzOC1J4v+P/nxFbQKoUFx8=", + "ciphertext": "DnCBgtfMvyaXPtX35SN4Sywp1WduMt6lpLo2XuLQXUgYnhDzoXpJpJU8YpV7jAqg9EiKtg==" + }, + { + "cmu": "GpbahlxQ87GltSxzJ5pA91kCKnm2nB0enYYMFSPvMSQ=", + "epk": "zSW226NXHfwectWM5UftDVTCDIRZBNRjlZnssPxGQaI=", + "ciphertext": "QSc+SdUPo4+7574mWVe7J+vGj1HFgvAMuXnYxwNS1wJ40kraig7nc2kU/PQ63ogvHokJ1A==" + }, + { + "cmu": "2760xG9t6Et6SLYkAWgH30/VT+YNC34Y1HTwlGlUi2k=", + "epk": "xouhItanVv+/LDdpInXXgQWhnx05cO5Zcw3oz9l+pGo=", + "ciphertext": "bg7vV0VkxgYNvm9mb9oqX12XimwJk+I65RDdwd/JPFvP8dgneqJQ89TTYhx70BNvpDl6AQ==" + }, + { + "cmu": "sUDz0PDu9i4GyfZFM3t2b5MGHD5QjUWVm9Fcq1pkInE=", + "epk": "sBtHHX2Y9IqDlSeIEtokpr+hiFJA81dT3i7IPko1Z4s=", + "ciphertext": "RTBxUpA91hK8qX1RR3BeZaa0J/VSSeLwLdD+WeUj3J84Pn2pr4fYswFJ9Ug0SFqmPjKc2w==" + }, + { + "cmu": "iuyDBbItMrMIfTVgiNovkJgx8ICf8Z/emCHyB4d56mA=", + "epk": "dC6szcePTmQuu6YoYuRgICQ8Yoof0jvKKmg8qyGwayY=", + "ciphertext": "Wf7wrkemg9hScSV6vETio2SBs7j/JClc0c6tf874uiXs9E6UYZI5gP/7bZ30NAwLVPeaDQ==" + }, + { + "cmu": "O2RjbPri/BOQemK+0jPXjqpKFAWM0T0F9P5P5JaANHI=", + "epk": "IewfWQa+9Inx1rZAEhFVaW5m5GjOgiPx9rkoI6HZR/I=", + "ciphertext": "1iYy3DeCBMhb58P7v83SsmDDIyjXY0dvGn+ar7cOYuK40EfLM5Wj2s++YvQqd+Gsm7/z1w==" + }, + { + "cmu": "Wp4qnr43IBfvogeJF5geWuZN6RsTE5NUOGf8L2d7CBs=", + "epk": "NyBsUjFZLpHtWMMJpNCliRm4wRJcsoHOqgpGenEWVhk=", + "ciphertext": "C2PW0wZrQUnKYsdlxzUal4haNd4qCakaNw/ZJ3wL9F5kTd3ev1zehAq2hCbJVz4qbdoO7g==" + }, + { + "cmu": "VjaqmZX9XfB3Qbtdl+xsse4Wt1dRgYU81F2wWQTBUyE=", + "epk": "P02wRou9+ROcSv9lLv98lCxC8lbvBRXboG4K5NVlihY=", + "ciphertext": "meYKy+IQrkewvRkMASj3gzUGbVYud/9UXR9uITwqMIgFhjdkrjCkQZwtl5t2LwL4KbsXWA==" + }, + { + "cmu": "qCamc8Lg6/NVC5aA5ZWvhHU3zB/2eu2yjq6wkTV92DY=", + "epk": "v8vsYIqkeB20dnOS2wkFSIjE8ozFOMgr+HDJNLDjBpw=", + "ciphertext": "bB+BFtD+t580OWYjsTKQLk4pp4XF2mHH+YW4b+7w03UdhYDNrhrgXcGPzbVygKDg9nXwCg==" + }, + { + "cmu": "4U9gg1zQ8sPK1lBvhAiRtO6+ND8k9hJeC28Te3GH2Gw=", + "epk": "FdpIj01G2AHoKVDD44TAk0phF2gZtT1hrI3UKQun528=", + "ciphertext": "MSykLVjsLvzS+3RjKiWfc+Up+Lj2dtrTxEQo1an51VD38ZqKrsd/xETYIWyGnUzkY99WKA==" + }, + { + "cmu": "9DJP7RwzWbWyNe+yKgOs42mW4TU2rx2FiRe9ApkA5mw=", + "epk": "SbBVlT/GDM0FCfjvXzDkVGd5bQyQwk2XF00SC6C5y+U=", + "ciphertext": "3BvV8cXnFzarsJrvSRWI0AZOe6nfUKYU9B1pmzxTtLjmj0tPH8SBpDmmQdGKF7NBRvRvnw==" + }, + { + "cmu": "gxjCZIJhy8xWy3bOsYmMeaOr7wCVaYcssbCwhY3EOA0=", + "epk": "bX7ks8pR6J3tqufBuFf2mDckFY7c2t35Y7PtqoYqPUo=", + "ciphertext": "k+7x0CE2fCZLaX0t5m3qhNpMcMlhhgQ0+QgAKpk6hj16HL6kFvrRKLpPxm/Mqy2FjERj7Q==" + }, + { + "cmu": "wEaxz1fciuIcZbvkw5Nw93ni1qrEMepTZkRPjLuTqmA=", + "epk": "FUt2eFDkLfcAyrloJUbi8wApgu9etDg674/5q/VMv2g=", + "ciphertext": "8/Yo+cldg5h0i0kUZ81DXiVnIG2juihTurs7B7CX3RfjzN0yuXLxZyVB0ELEOdR7w/s0gQ==" + }, + { + "cmu": "B4LMrKNTNsLIjsle73N8xV2PSPp4SEN4+GQN2HQ681s=", + "epk": "q6qvoOee05uALcp2GTaw8Mq6SrwGLc/AWoBh+y+q5LA=", + "ciphertext": "SrN7X+IC2+xZ/dYrYAxkJYXHS9YfsPUhmixqzLRYrD4rjJrRH/q27hdFbGYlwHkMzuydPg==" + }, + { + "cmu": "3w7MDdkEzsjGk3RFPNZT5GCF2C9148P/pZEEp8aS1BQ=", + "epk": "47f4gLA977YmC7u3ZuKS1qp7R4zzfev6wWWgDlqRRhE=", + "ciphertext": "kBHoNptRK91zXxul2tXDlgwv8whgw0TjlSwTzVVoLnla+GMMqZOP5ZDwkOQY7UJ8S1RzOQ==" + }, + { + "cmu": "xe4ZQE7F2hIFJJPqck5mGHcMxYtsLDw99qE3nV+Qy1c=", + "epk": "MHf45wk8rJjTt3ZWtIHWK1Euf8qY3cMLvU+Op629ERw=", + "ciphertext": "DdBww2nW8vOlGGyfjVf1EjDna+gUrRgKfoqHIqqtjbP59bx6gDUHE2ewLe9XbmQ1aSKLXg==" + }, + { + "cmu": "u7Ortl6TskTPO6NUz9zm0+IEpKE2AJmr2Am0vSCp00M=", + "epk": "U9qOZYTkkovLY2ASOSQqp9ZAr9Tz1NUL9lHyhlizRYQ=", + "ciphertext": "rHA9UE45h0Z0MXH5gn4TNPMv3UUkDf5yMgNN5uvsg1/p5FrBxUYGLIsx+Rdg6hdU8hBtnQ==" + }, + { + "cmu": "8xORyhER5bZY2kfPE7u0TeIc/nx7TG//v1VzLn/v5W4=", + "epk": "3CXhfUrXb4GdHa38ILuie5dqy9meqFbZZPo9tSaYJ7Y=", + "ciphertext": "Hu43J7VNsQZGQRf1dCXvE3H9u6yrQfkfuzV2RrPI/suY5MT3+tiyRNemSs3e8HFDcB7Ujg==" + }, + { + "cmu": "+sKKqFj5/w+qA9e7812Mi/TQZ6WJKNUeKuPhPmo1tQI=", + "epk": "4+xJHbT1EdJw1aS4vEdiqT8R/sijDjFMFaS0cI/25Jo=", + "ciphertext": "H1zr0yG+rihsCF1w/A73ruqq6HzC09BX6fNJ83uj1kLc8wuwMfx9JPte77AIX6SwS1nEPQ==" + }, + { + "cmu": "9h4QSXD8xFHq75Wttqsr0QV892N8M76DaI2W8CWZjxY=", + "epk": "kEPkNQzVa/U+5vUjlHMw8UAG7q2L5JL4pCTEP7djqyg=", + "ciphertext": "MRiQ6vCIhhHmTySO7p7gmFBGW9zVpg6kB2+ey4dtRqjZxPpMlS8o4WtfcNcfpMxeYvR47g==" + }, + { + "cmu": "1holXIZZ6j/hgNw8AsSvgEyWeKIhcAn+CvFAvl8KpCw=", + "epk": "cCSORJt1f0NcTRGB8SyT6FCnCInH9uwzQfuB8OHHOak=", + "ciphertext": "mwmfc1ZRA+Ua02eW+Gx3S+y3eyliOr7LCbNp24w5zH/w6xnDVRhz/A+Y5aE2RK5FL0O3yQ==" + }, + { + "cmu": "zU3sTy/Yw6QOYg9RoHy1KEjsjEjYKEE6S7fkTXy4P2g=", + "epk": "B+Tm3xTHxTd8gh1eKybzvJbGS2ZATWsRC+/zNZDzwrw=", + "ciphertext": "cstwT0+Kb/C/YMIxbpoWAEKi719Oo8AGFTp5XK4vp++mpVLIzqqafC+Xbas+6obIVYfflA==" + }, + { + "cmu": "xs5O+NA12P10c6UQapfu/alrKXJ20NLEn0t2ROIdNAc=", + "epk": "8AXQ2i2jWPTNyE245s9SaEbTcbuFqlrsCrQJnUnXpBQ=", + "ciphertext": "su4Zge0r1AsB+6ropPj0DG37u+zFvM/PJsefCNHKTzXuxTU6ChL8oeNGlZG3+otsyKdjBQ==" + }, + { + "cmu": "wmb9US1BRtA9YyowrW4mOEjSHzF23P6jrOM9DVP8oFA=", + "epk": "lHQ0rDBOUvTJhfy6vxpdESzZ4NpuPFZW+dbpgfQW6F4=", + "ciphertext": "FJNk89RknfPL/oFG5w+3IM8bGvZ0MCkted8pkv4L6en2TzxJ+JpLri0CugUTf+GR5mXIzg==" + }, + { + "cmu": "GBSg1cqms4+xglvZJkLSrWo/HGzNEcHb/0+Zk0fesXE=", + "epk": "rhpA7cmfzeyFh38WSbOsBhYh2BpJu7yU2scsHiF0cco=", + "ciphertext": "mOhlSwfGMgkXpiZsweil8nRHug111XN0YAXzXfJ20qXwTQdW4lZGvtv/xb+OOzG6nOdFVA==" + }, + { + "cmu": "FGEHrmOdp8qtK9gaTxy3Cqp853528SRX8YeT+J0UFAA=", + "epk": "TLr1gIPK6ZizrSDhYtVFDelB+QUno97zQZ4r7LMgL1Q=", + "ciphertext": "lzmHU4Aynx4Ys9BKoA01csvMBRuIhrnkv5OvEFbz5wImxwrV5QUBmhSkGLpiL2IqBO8SRQ==" + }, + { + "cmu": "ZA+wXLG/ywmSq7Tt9MJdephBmbw/0W5xgvLJsG/J/1k=", + "epk": "o+ZHm6cnjvNaVeqM4XKslo5k2w8D2Wh6rsJ3jJKx3Ro=", + "ciphertext": "M5IkhaCA5isH1NY5ShHrAFiTD8aoaoubuw2AZrlFQ/EQ3x1d/HRtC8T7VnENvXxTbCWE2w==" + }, + { + "cmu": "ivSWJhPI+obfjJRNRRB3E+Qgv4PwsVsYOYulzA+neEQ=", + "epk": "yJrHqvMo3QOf87rGDgscApOUlOuN95dQTAY7QT5+eIk=", + "ciphertext": "wmvM1AI1kXvs5lTjXSAht13xWuLQFEjxEKxEsiJlF2YTQCnt2g/syQ4NkB9fyePuVMXuSw==" + }, + { + "cmu": "XAwsuTQL3dt5MOx9EYtpU6r3wi7fF0GHRY144UISsQo=", + "epk": "DNuP42dqXe+9fd9kHTO8owyJza1G3NUVf88LDDrUVVs=", + "ciphertext": "H0Jg68Sn/Vf69za3QreKXA6gHxO+fhyBCd/g3HbIGRMEzbqpaTHfO9J7icPvcGolLEBdDg==" + }, + { + "cmu": "r2Qd1j6inxrhG2DkF9bKFqNUEoXLOYmTUKMZq0icKjo=", + "epk": "eit9eWjjaaIcZjdaXgOw9PcePvm1ByjF4HPZ48T9GM0=", + "ciphertext": "5XQFNEgO8iAqkDrU0fA9puHVxle5MLMk8OO0zIbQkcXQtekFaSb0z8xvzeqoKd2mjWI6tA==" + }, + { + "cmu": "sbiE+uky5Wy3BRHMZUVBeP500zEAvDyWAvFU3MvuHTg=", + "epk": "/5Xqhtn++gq51CXCnBq14j27EFd5dXY4s0fL0woMJmk=", + "ciphertext": "xosLgrTU1tZZUGH1KBCLTv8uBxepK0baUeGHeg7ZCOZJKRyzne9xl2uWje6Qce6RGKocVw==" + }, + { + "cmu": "kjOpwajft1QUjCzsTnBfn+X4400ZfupuYuw+Zni/RDY=", + "epk": "KNBzHFxuo2Km7vkf1ZOf6SWI96JtP1pVT1vV9OrHrgA=", + "ciphertext": "F4ku+CQ8CHHk1um9ItnRdn/8HJuEFhc5Mp9ooLPXUXwEcRIXPlMe/ibNHw+9a005gl7nyQ==" + }, + { + "cmu": "GVp0Lvhjje9NmbPBT/GuZDqVmOXYLDBEZkm7piD1FmU=", + "epk": "ZAI68Iy0yHcMf1+ctrG82f9SDrT1lTaPFvRObxouc/E=", + "ciphertext": "T269621RogkI2gUVwGWokgwp4ApvpdYUPQebaktMBvjfPjn2iAiyoUS+LHATl3MQsr4T2Q==" + }, + { + "cmu": "6q7U/rYBQwnZLkJdLV1P0Qa2M9vv+5SQYm/o5MxxWz0=", + "epk": "btcUEIN+dA5bn2rYSm0J1OUwu56kIQW2p/TM8Q4EEus=", + "ciphertext": "QR3XfRFysLy1bNopV8dtI7+elNsa7H6URiY11PPbj1KFm1qxe5piAkn/Z0vxv+XDCGkEEg==" + }, + { + "cmu": "x2ytf66t6CvsEosXj27ccDUqXTtz99DEp89QnJ1lAE0=", + "epk": "kEktbYi+Uaxn+d8BC61PZT4Bv5/mGi3fhvNYIwkOj1o=", + "ciphertext": "S2biy3dHZAWA5JK4ocw9K3DV6Yka3Mq8PKStex7itaDadfKHH/8MZiMDE5SAip1cFMsCVw==" + }, + { + "cmu": "g0Dhn4+aQvWJ2giw1pnjftfrEFQOTMWuzoUJYj/btF0=", + "epk": "f3lQBWTy9PKdYk74M/fAEMz36CxY8bwrNmlF3qUaMmE=", + "ciphertext": "iG1A2PpQITlT8dcJW5uMzv8e9RUNXYSV05r9/L4P2sBdjcaFwfMbiJtg5Bed+gGxuqSQLA==" + }, + { + "cmu": "TNZgJhoX+KPy5BKtsvIMDy1rm+JYzYC05O1rcLGkFTw=", + "epk": "SvprEOYk3xMpubDidTEEyqw+8uDyNTh4yOM2gafhQfM=", + "ciphertext": "SrVXNjYPOIj2cOt/iEYTWSPAS8ud34h4wRg8ZyYO9UKIwGCgz1+k0fdjJT2v2ofboNTQZg==" + }, + { + "cmu": "dLZdb2mTnp7itBcufrteYJsfT8tHmXaiMVQImlk70zo=", + "epk": "smkeJA1MaVt2KNOuYgfaP7pd+aGI+HPpFtLxT1hm3Mw=", + "ciphertext": "dB2HUNRkNIyDz2udaTJ3w+DtKptRo4Zsod1/7gqPzu+y2PaUaaXN5YSys7PEGS4s1pCpEA==" + }, + { + "cmu": "mXz4yQp1CvMaGzw5Qjb4TFOHT09Gb9SQA/TgxfZh7FE=", + "epk": "wiGtQ9EaRSRagDESC144P53FzCGchbBaKKn/sZFsH0E=", + "ciphertext": "5/rRqrGd33RV5jk8V9VEFWJrz182Jg2Cqex77+A1AN9O5iylwvZiQ8CwySDCZC/iWKm0BA==" + }, + { + "cmu": "7mCpnDp8oa1hHZtptaOszS4b5C9V3/aY3kRxxufD62s=", + "epk": "kCVUQz1vI5/unvpsbVKah0xQ3BM0N0W6HdRD5czNcoI=", + "ciphertext": "znOx8ivrcgh60IwN3uvBoWqxwR9QE8gkiBT6GD7RXYzaqisTuOPqYdFifPEYse0iZqBcKw==" + }, + { + "cmu": "qYTBcJTBwbKPyLNBQfV5oIF4Xs2fQCsqqWqOcA2DFFI=", + "epk": "4JxzuZYGQrK7qV3Lxh1egeUhYV1y1+BWdAYytmcLVDo=", + "ciphertext": "G4cVpSigpnCzkuYwE5X8DKXzbQ3N9+NNdJWz/yXYpUHArdp8fF0pNsW20InOp5IH8AxBKg==" + }, + { + "cmu": "tH8xGo9h8aWGANCiV1i4WZ9CI8xCJ95qT/7P9I9Mhh0=", + "epk": "K5cEjcauzI0fze+qH3vCXzqFgM5QKrcLekO1jN0FVus=", + "ciphertext": "sLzEGHP4mv/cVKXPJQv4vX1X2intgYXeJOf0aR7qH7Eeael6544erZ4i36jV+ZNq6MrquA==" + }, + { + "cmu": "0oIrZA5Ic6Nc8JWi8ZeU759TVRATAsFLS3Mwg7kXRgE=", + "epk": "ioe4QcHJpxSHsjYfzCFSGsCyVT1+Ejafxj+Nx4CeJgc=", + "ciphertext": "OkFb/RDBdpbUv4Gvo5CvXn8ePyzSF9+hyjpei6UG6oJcEBc4R90fUNjZ20IVTcFuUp/XSg==" + }, + { + "cmu": "rEutLuldx8tHbh7GmKCPXkBItZErsmHgtUaWa0gGIiI=", + "epk": "g2wWolDOiltWen6+yjCy1G0GGJI+tsD60OubzZ1l6JU=", + "ciphertext": "ieCdJUncIrKApn8yYDNtMDGgOV8/j8F1mmhoeTEx/swUEPfoVwgLomfj646/70p3b9uGdw==" + }, + { + "cmu": "Rvv/bGGN52ymC+eCQoFFTrK3kU067adCvMOucCDjom4=", + "epk": "+HI4xGIsCHnHSfD9ezMj6Z9z4E5AzE347j2LZ6rWW+g=", + "ciphertext": "xQ8yaHufGg1vhrody9IPirEvjvSJDSjle7TYGdAtsMLCfYbwnRSW8Ojg6um/8v4TSfNWdA==" + }, + { + "cmu": "+nL/3TSOL4/H1GL3VKJzPms9z/D+9+WVPJS+6GkBxhs=", + "epk": "AjAe7vJl0G3QOgpXywdMG148IlCOBth4o8YlsK2rg5U=", + "ciphertext": "voptZaQKn2LrafGibbIfDMwjWTf/BeBBQc3CVk4DTxNu+Rjcw1sNuNpIv1DsnjUwk4Y41Q==" + }, + { + "cmu": "rSl+4Xtbk3pkzoFIGSNVLz+EednQ5v4NuqZTN9uSOgw=", + "epk": "NsfiVLNeh4xfNiByDaR9/CuA2bIoQtbOArsFCL3dzr4=", + "ciphertext": "lmpR80Ed0hPL3gHSgTdPFFs983BTw6HXAFTITCVwu6SsfjIiP9WKrEYNMSMwZQizuvLLiQ==" + }, + { + "cmu": "d9KFTwBDsAKq06uNlMgVpAvAo+OOBojxVqHKdakLJSo=", + "epk": "t/SuNngF3uhstJjvF/Pjh+IEg6LvlvuEDjyvCICQNfI=", + "ciphertext": "w39rpjNVnDCGsscLtHnrewxcXHH1cATfpg5+94a9S8yy1RHlUN4RTVbd75Su+PctNiT3VQ==" + }, + { + "cmu": "oRF1NHo/vaRL8FzGi/mnhMPLfnwbBvqFCX27TDtuDWk=", + "epk": "QcbipvH45enaXrRHUNiJ3OY7/G/SDA+kOlVFDv7fUJk=", + "ciphertext": "1y0gJjQza7QSIV0zFQwfdn3rdtGeyrmynqPaBjk85NvLKaPVFpmVRMA4pLTAhIOvu1ERhg==" + }, + { + "cmu": "NnEInyqhk0WlCEN59pIykB8W3zTfv0RmjvlJ3eUEBgw=", + "epk": "7R+habCF6kofgDHNNO0df2AKEi3F1ASv2ZVGa8XDHdo=", + "ciphertext": "PXWcT5yczIzvBmWNje+J8++rkOn3uzbOeIE2DrNrELoz5Wv1rdAMq5Bv5VmdFHAi4R3u6w==" + }, + { + "cmu": "jTla7kTyGeqkyC6d+Y/Tp7unk79g2R+jxrIkzvevMQI=", + "epk": "DNKq5vrOdy4Dvscf41ug/tjr2ixTjrwEmK0jKrnWtUc=", + "ciphertext": "pLozqsDh/cxGTR7t8TgNZ3/AodnjnPOvDYIth/wPaiO39O+oOMJ8fPA7VbrYB8mcKMR8qg==" + }, + { + "cmu": "EEULYZpe++cld5jZIy8EtxG441Jhoi3/9FFO+sqCww0=", + "epk": "TNGncRUxjS/kM9ca8MaKQar8V1SvUOwcNON+O443UQE=", + "ciphertext": "gSUroB1RYR5oAe1X//LFXlxd2AiWpgI2EmDgNvymh4ZYZ87ipXnVJxhHuMcTanmomlZUXw==" + }, + { + "cmu": "cCmHWuZZTkEgquBeThdddWSaMIWouyHw5df639yO0U0=", + "epk": "ZtITdJ/mrz7Sh3SISiZU3Gk8IYwIWO8mwabh/wE5NbQ=", + "ciphertext": "LfCr14rHt8LZ2NmiHSy+tdDYiIXsj/IV/lYA1e6w0dLFm5Apn3GST3Ctapx/o/d1yJreAw==" + }, + { + "cmu": "Twp8Xdiw3Xj1aVa4wB3+5QDtwDUTXbZU10M11kDtv1Q=", + "epk": "PWAZeJUJ3HrqQtpm5x1diE7xld17YRC6XnuALoW4eDE=", + "ciphertext": "FjELNUPqQvS6PEaRoe2CBI0M+Pn3evHWZYddj1WVCswempcWiWj6q8czZ5QNNilAlreg+Q==" + }, + { + "cmu": "53vFDwIny5BrC0MKwB2+dKvyqQ46mJ47vAbKmHeGeUA=", + "epk": "ZR7PL+ZrmteYOMmwZXxjclXgVXTC72r/Bzjm50Ng4Uo=", + "ciphertext": "BGrN+f83QQAltO7LpUJX5S1mX8izOg1z/lCoARHZFnB1cQkiErXGTtZ9sV1Ai2eKmGFfwQ==" + }, + { + "cmu": "97o9X0uL+Rt6saoaZnhaUUEQBeSopaGan8VMuly+/l0=", + "epk": "Zf92IxKZIkXrY7a95xq9vgxMmX5EWMYtAdFWKpFmYp0=", + "ciphertext": "AR9cIgqEiIJVeDj/Lz5EmA/dWAyjIBGMSyRs7juFnqJzxsZspXFhQV/bcqHKOprqVyYPvQ==" + }, + { + "cmu": "i58vEOplq2Vv4+pGwbSkTImx6O/dTM+grLIC850HEwM=", + "epk": "nuLiGA7VA1sUrxonVpVYN8i88r6Tke1aesBLb9A7Dbk=", + "ciphertext": "u8d0sFyNhbSYofTjx6Ds+xPhkKL9x6iLi+/+2SerBcOL0wq277743PNpNIP55Y3iEXykzg==" + }, + { + "cmu": "aY0zUONzb0QK5ilNSkWeLyMbUrd2WMs/AUuzSKV9glM=", + "epk": "g9VQeZnS4CilHKyl1FcDhYnGyuz+uEPizxaWDD0LG9w=", + "ciphertext": "Ok+czi0Q0/RWgC601pwdtbHJctpyF80BjaJbQ6+K0BPuZ4HxT12GdAdrpvdYYFkb/3AA8Q==" + }, + { + "cmu": "A6/ZYV4D5cbJ7jNF9LZhDHmZ6gpChH5y6UavHe3fcSw=", + "epk": "cFzH1MpVhvma2L6P+OCzMLjFHY5cRlq4RkG3c+EE7dY=", + "ciphertext": "rUwLcfqAc55nKiCxfNLVEydFzu0N+r/pP+bUJUpIFPZ0upq0lsf4XfzdctkeRUrM/jYN+w==" + }, + { + "cmu": "74ljk3cHS7GVjFIx311Nh7Skm9MyE0rrHiYr3PvysFk=", + "epk": "QwkMEXVqYtC0Nb/ZNSIjpitXU0cMMpJYznEM+8yKJNg=", + "ciphertext": "uOb0mg/zOGk/p4ukCrWUg5oYKsWOeMCzuOfcKLhFUcuxpif9ddvcrJP+FdASodKsddA2/g==" + } + ] + }, + { + "index": "33", + "hash": "o3xDMOse6kl+u/X+qDlRcD344NfRv1n1oc5UMKC6P0I=", + "spends": [ + { + "nf": "qzSdTh2AyJhR5tlWVyjP7h7j0cPpCzToHryxP1d/LNg=" + } + ], + "outputs": [ + { + "cmu": "v/q9uQPeAQ69/cY5hGJuwlDddE5gFp4Kf1Yx7X9e2W8=", + "epk": "HTbEWNOp+zME9LHrDNpS+bpvqp4pXfkNdKZNrVe6gfI=", + "ciphertext": "CCslYkcT1KYXrdHJ0j/G91xMiqDAd7SbFncYqzMUMoVgX/jWYVaLEoAFtfUo4gk3+jFDHA==" + }, + { + "cmu": "aNe2wW1PwWeIX+f0M8EHoRWO7NScIfa0aHiegsUTgTA=", + "epk": "FohYT39E82YIPOivdBVeMBWp46e3JCAfIDOdfpzuFQI=", + "ciphertext": "F0zkJYF3s5nQ16a7TxTsFJ2YbGBUBV0lfK4ozgQ1cDaDGMK0jRFSuVd25KyQqkNdBhWHyg==" + }, + { + "cmu": "clAIBbfBJ0Hf0ar+hUp8Csb6/HhBjc/2WfmfwNWmKVo=", + "epk": "ghPwtGdJTq4pZ6stZGSI5wSA7IBITa0j1XHW+4sIypc=", + "ciphertext": "ADl/sFTnDGpgDsBILzu2R4twHSGxML9QifmvBWoDEjXWIN9tViujXbbF5x9+NyRgguwNSQ==" + }, + { + "cmu": "AkB6OuG+8p7q4ahA7Ku1VeBeDVA+y6zKAFtbltmMAyc=", + "epk": "kdpn8ZyzLqVmW1gL59wx4Xg7KElXYta3mFd69nBIeDc=", + "ciphertext": "gxuFx19vU1IWxF3NoxEvmXVuu/9gweQkLiMWWGsLWSWSG8CYbCyYY2Qm7w4R4iJpwWuAUg==" + }, + { + "cmu": "ZhfKloW+cwZUUfp9RkKdp/GACNEBZMiBueM2dlmTGAs=", + "epk": "Xs5Vh7X9ebu5l0jIPAF+6N56YuGECorv1JEyFSlH2YM=", + "ciphertext": "XTnbgz8bezC6i2zBC87bgFrItD9wcX9vDIYUhbHZNwhf31DBFLu6kPq/HTAlkYYPolJezQ==" + }, + { + "cmu": "1HEol6jXT8MOz5jVBV780O9WknqQphftf4rP9FBLiRA=", + "epk": "lN6zTWEAu4lbc5La11A5Tb4GV9fahIbvlmVmI6CyD8U=", + "ciphertext": "A6gLtbx+d++lSH4zv78v+8VzzZ8I7wRw1iJnoo+BRy5CvOBAD4XFK5xrcimzbFI4+7dGiQ==" + }, + { + "cmu": "OulbFU3kvhv23Anmy5/3mFhrfC1cWeLd0gKiyA1wCQI=", + "epk": "Pc07IDYLp1vk/+euJaIFtdk2pyc2pdCBT83SqMSxyAk=", + "ciphertext": "FJ+li5pAIMT2wqwcRhJs0QoG3Q/MgmekxmlEDJ0KZpeYAf46fccV9HAJpvAS9UA0hzZuxA==" + }, + { + "cmu": "L4Wq8rJirqOdKY5Z7q5rhK7ORXhM9zgO1MLnoAYkZD8=", + "epk": "R/00m+Acj80Ua/tEEtMRNFmoJvsUfW5a3rrPECnPUWc=", + "ciphertext": "Km91Kolp1NOmYYOCSkGyzKQBcORJuc36rojmsMTfxKq58aidEXfn1JRduYPTnbjNPKGEwA==" + }, + { + "cmu": "qZlTfo2piwCEDJYLLpLfdhoI47LM7xgfC/amXFE9Sl4=", + "epk": "91pjblfd85LDrVQYD0Qv8fACDMcQzB7fJilv3tCL/mw=", + "ciphertext": "yr9dvqhV8XDyA3QvON45rQeje0qCNBDRSS6dTiV6iiGrJNEi9tOY4mB0mc+scej6/YhGbw==" + }, + { + "cmu": "NhKwlvV5xsX4sg0YKncCvZELBcbGjhiH6QxiSRIapgQ=", + "epk": "saE+NQ+zfFAPg3DyPkVMEl8xhmYQIwfuExi0lir9kRI=", + "ciphertext": "++s7PGe3EsPEJazcCRYGQkK6lS0o6tsqrUIGiTAVkLUQFt2K4mWbuO3UevJey1u2mCVvfA==" + }, + { + "cmu": "YRl6KeQKuGrlGsW7fYlkfiRjFf/27zTqV71OjdqkLSM=", + "epk": "erSwcEgwinZGXYBY7dpEIvSciYnLLGDF4U04h4VUmII=", + "ciphertext": "1+zUaneYdXXpzaAkGj0f6WjGDWZLJtj8pPOgKRj0vA27ir9Xxna3uglvYgVz2IOZa1s05g==" + }, + { + "cmu": "wRqYPHxpOUixEUdbK4GjS3o8bHGBWOGrbmkf4tXxQlI=", + "epk": "yvromDW3NF1pUELbcCRFJWAO7z/BcWSiyUVV43KMF4k=", + "ciphertext": "a/RAS186HHUx8yJAFhCIXjje7RZgGHe57X1pYrxPKT+KacEGAC+VEW2xoTnEjqvGzbBZqA==" + }, + { + "cmu": "Pdifun0vfJlvCMh9/sJ2ncrz2WYxJ6BF4U4c8t46Z0g=", + "epk": "U7BvfR0qk12LI59kzE/is2cE9z8xwj4qp83PmrW1QAE=", + "ciphertext": "aF34wC8gNCi8+eUqlujUMccn/VDvdvuTDEbK+Dg4ADJc8LBei3hJPdkiO425q1FVADVqTw==" + }, + { + "cmu": "kZhne5xMaJzZTTJLa6eRKRt4npcuOjTRhvVTfpZItlc=", + "epk": "dOIrado5NKuadsGP6MnvgFCCZ1q4yY38L9QQgEsy5eE=", + "ciphertext": "3n5pAOM4iV88TpoXT7kRdt8y1/4YKWug4DAuzMbWx7Jci/WnDguuyblA0YGo225ei8GxBg==" + }, + { + "cmu": "SOMMivcUw4r5vvhcGULSMcyc48frfG1Lk5uZ4YcrcUE=", + "epk": "F0WXAwJAo1Ckj5FKdy5iBKO59enFr1LqJQjVxxu4ZSo=", + "ciphertext": "yH+aXunwWbu6S9v5CFp5SF4TR1bkHlxKx20Qj6tonGT8Pfn+yceYVyB4axvxAgk3TKwFoQ==" + }, + { + "cmu": "05p+9p1kXb3OD/DwHgwG3ivZgJzdH6MIcPHWkkHWhwM=", + "epk": "jl3wwfl82nB0yDj8OET4C/eaIVT1XVCqZMtdwq1dnWI=", + "ciphertext": "4oelrnRG4Qnf5W1XuOcqx5r7E+oUhRnDWeDiboKj5S7gudy0WlYMNlH8XcQlipJEqgtXiQ==" + }, + { + "cmu": "UU/0s5IbLoyxOjDafE4Kmg90UmyR3IlewoFsZHjSoWY=", + "epk": "2coZWvYdPbz5PJGG2CKU1q9dyWsLU3RL51nVR6kDmSs=", + "ciphertext": "2dFvUxZGEV2FPMW8FHcDxji+TzkeWkx8ApAYDTDal6OGLco8fDh6TMbRBpLjQX1nWrOhfQ==" + }, + { + "cmu": "YLSxuf0MnxhNf8KVINoWxdXEJO84vJpqV/OLtAbpEA0=", + "epk": "9MO1Xw4eD6lQXsy93Rn844r9zBdBuBJlzUo+Z6Z1Suo=", + "ciphertext": "vIuX0xf2lOchgUa5pS8Y6QE63r+MsZlBKZo7SCEzr0WMqF6LkFPqZqVuwYLqxRpEoL0yKQ==" + }, + { + "cmu": "rbQdJKYYZIlxkfsQTii1WSZ0HvC846FULT8l89zdFyg=", + "epk": "D+NXRxo5i+vrTYAK/qkpZ9qUZBo5NzIQBXFEyX08dxk=", + "ciphertext": "NRuiZdOO+xSWcH1BE1oxn0tZnEZBe5T93VJTbwaYXHpf1kEz8G+E8zjnP2Y/kKRv5/rQWQ==" + }, + { + "cmu": "a4j0osaKgyQpC1Jf81+vJTzgtHiEbj3rPKnvH4O3iw8=", + "epk": "+BiBL7v9j+G7wSoiDY/Nwn6kDsnWxO2cmP8dWesxXyk=", + "ciphertext": "Jc+kzn0Q2bhygfqf0R1wkxZ6ykhZK2ZouFI5nxqEFPQy9E6gGPYqsFwwawe0VkDB511wkg==" + }, + { + "cmu": "YNV5FgjOYwLzPBg3zT2X68l9YqsrvEZ95RCFID2Y/Gw=", + "epk": "EH325SyyofJySZJ1PqnW8ChqVTS3Mi8IwWr+E/ydyWU=", + "ciphertext": "rjNEeQhTcGUSKRyJIYJE1+28lUkCd6iQbY9VWuUX9RTmyfiWYHCS7IbaoKFMeryESweTXw==" + }, + { + "cmu": "SG0j9rtaX8NA/hY2oadKxVbqV0oEWcdaHD2V7/3wZ1g=", + "epk": "ozwSXCpnsRtpFwLkXgmXsI+LIFXNsm8F4F44k3P9LLc=", + "ciphertext": "j5a/nD3vx99UlsJYr1cpIGtcg9CXITZAIADpk4PNgmE67j4BJ1kiLQGwIt9cuPgQWyEGVA==" + }, + { + "cmu": "1LuSTs9Vo56hIexDR1P2quBiD+ynnvRYXMWX/d0qhCE=", + "epk": "ZSh1hkZ/XnWsEpITHdEH49eK0qAp22sYXZeZCkEJn6s=", + "ciphertext": "fag5De4zHYPA9EVTv3DxmspzQMhqWAAxzF3TPEmYWTGBr7dHkpkcP021npGiqIAHFwnISA==" + }, + { + "cmu": "YUrEmKtnn8wEEdGA+4IaRLvA6jUYSubj6XKBcvT1sw4=", + "epk": "MijIFmofsvSrzTtw2Uu+Xjnq9aLe3y8qRe06zqP9gR0=", + "ciphertext": "WxSQ4FvDrBk60ehbjYu3tOhREY6JW3Wd3kRntfy7KpCEjOCk+qrBLX9Qx2Y8H+ZGcRVA/A==" + }, + { + "cmu": "gPuKR1clrr9fwuwLpV50w9ZAGjdP8dKrw6pU0pzpeAE=", + "epk": "rVWOJnwA9EhWLXddv4L8az746nAbe5TeYto9u4Fmzl8=", + "ciphertext": "Pc9SsL8vJ85GJGUCQqRF2GXpbCT4pxJMCdqBoaN1hZS3YyDByAAsCs7tAX+sUcf+rI8y8Q==" + }, + { + "cmu": "3Vml42xhtXLkZBS+rUsWufejdI3YsvQN47z/++eDF2o=", + "epk": "4y3CK17ubzFb8ATkNsrjL1rrtL0oefvvSIbhYk5zqa4=", + "ciphertext": "RUo5Ak4LCX3QoUQi9UpbysW23MM4ZSc/AettdP7ELzGQcqv5PkFQSNeH7GnG/ZktGaXFLg==" + }, + { + "cmu": "/ItCFlP+WWPdTEv3bs0dkJ3YeLp2wnpPnihIY7Buhgo=", + "epk": "32zz5AZg2PhmgCan9UNPcLk4j2GYPdtKe0glWI+YNHA=", + "ciphertext": "XP5LgSbkHwdko7VjxP9QyRHt36sx27pXOb+xgsXXCP5lKx5uetd+OKlj3t5xBTKB1OjmlQ==" + }, + { + "cmu": "HDY+pmgeZgQ3D34XCRNrI5yFTdikGGiuFraNQjHpKlc=", + "epk": "dI30uF+RR28L8Tc13k6d9IgEHl3i0vbSCAiAph3JtcY=", + "ciphertext": "63JRMa0Cn4qId6UcfKggWo1q80a4pZOqWLzEADFYX/x4u3VjpoixwnTbP8bF/fwDirpOMg==" + }, + { + "cmu": "rbZFYXDDVzi9e5KILI2/hcSTdOxm+/bVVIR8lryD20o=", + "epk": "Hi8yqXnKHssgu/KTDAakcbGryDsIZKgmdZ3pR/QzYTw=", + "ciphertext": "K2bzP2hcLr8FprxND/02g3cobvGq6er2t0jV8Zt1171KTT2Gy3Pnrkept9VMasXhvTPoeQ==" + }, + { + "cmu": "TNRDsLnlPeU9J/tiKHAZnoXyESaHf/zRlABB2nwFhCo=", + "epk": "n+rv9SQsHFNpBLWD+bGSrU292uD+dir8ihSznvOXZWk=", + "ciphertext": "V6KlR2NnPu123r4A2zQLjvPLiiTBV0GtiI4e0rsHOF4H8Ao2SbJnpc28yg0u0AYmrr6zxg==" + }, + { + "cmu": "k0+NdGmVWkvjj8zTfdu05AfRULTyHaxhB22qWScMhTI=", + "epk": "n1JYAB6JEJk/xEDsJjI4T0/cwrQhikKnNn8pTLceKTQ=", + "ciphertext": "3+w/zRPzw2ze66cF4HVQvVH0SSa+YO4c7ewX4mEzyp3L3wy6KUHJcyZCQWD8AcWEp2cs7A==" + }, + { + "cmu": "4BLGpkr3r71xeEo6bJwkD8LxLtrhGH7NPjhIbmdpghs=", + "epk": "jc+NtybT/jrDpcIO1fIfqt3aSHruJLlJLaEMXu5w374=", + "ciphertext": "bOpMbrxdiFTL/OiZLl6y1I6brAf+IaqQU09g1iTahs//kqgB6BM1lauUAUbmq2W99HLecA==" + }, + { + "cmu": "ZvChI4fioSmV9TMVZRU53Zu1TTSaWsg1syzTyuY2Jh8=", + "epk": "q6L/MVatgSDnYDr7NSpp92PGP1U/Z0fztTYGIqW6j2I=", + "ciphertext": "LaCZSJ1z8pjTfXzPX/iCMjklkATB/KIaNe/rqj71EC+S5ldsSHVN8XdQVxvGRDHA4rq0dA==" + }, + { + "cmu": "+XXagx5h/QT4fmouQ804OlRDWMVezVquyH7E9DepxFQ=", + "epk": "UV4ZNuFURPZVFPe5moPxgKagUuNI0+6EpS+kKS4eKbE=", + "ciphertext": "c2hKLUXTLOJmKnX/wgw/lhDL0b/yPmCkbkzTwvGGApy4uIckr1g9zSpmptfSPFFcEbryjg==" + }, + { + "cmu": "tkwuyJc32F0QHfArEqiG4NXv/AeV6NGhX6NYgFQylSI=", + "epk": "ilCLUquUFQt4/3aBAXr3oVjaOmavyQF8/02ld4GCqFM=", + "ciphertext": "FiFVLAK4SCL84TajvZtXr4S31cQSZ7aX7vOdiqjNxlGytVlvuL3uCNxppVcus+p368owpA==" + }, + { + "cmu": "J5PvXy7pwaVxubxvv5fzO+U5jMo/l8cuEXe6GntRaBs=", + "epk": "39t5uYtkJQlOlqdiHWT/Hs9P/+GWKfTO3GGasMqWEmg=", + "ciphertext": "XtPLrWwJ/HIITBKQsZYnvmmh3tX1jk8ebPCMiir4C0vVVIIcJVnZx2f7LsnYRLlwSmUwLQ==" + }, + { + "cmu": "F1w7vkEnN0gCyhiywGukzvAoVqi1F7Bb6uuAPEfi2U8=", + "epk": "766ZfWM85AXHX4tIVCN6fB1ydttZCnDT3ImFj2wD9eA=", + "ciphertext": "Yju4VsSjaNqmP0jMbV+nviYakkOSVoIWmeHpmPMe5rIbWHDn7B7Bent7eiEkmPHcvWBEOA==" + }, + { + "cmu": "EKJ64b5cCTzhel2FHxhSD0ORar3QWvt729vmdYhdUWY=", + "epk": "azfcro8WIGT4Ifl1G9rwjEMX+i3ggoGF9VdNADNRXzM=", + "ciphertext": "Eo/Z7IwJUkPf1OjSQkfKZUpF0gtLVcjW31IrFH+/+8SklBvm01RPNcIcLX9VOW4mFNCNcA==" + }, + { + "cmu": "apq8pBgaEDku4qk27cYWTiDbA/EAhrrt+eNjOlRpN0I=", + "epk": "6mqxA0zdpxn3T0kjyPicBHNZAIss0MPWZfmTTJmUTEE=", + "ciphertext": "7D8ATuuvZpc3BY9DlY/RwHHGd8JEVqE6qpNM0BSii84V0LwmTQekpWQL7FaYvlkT5qkYjw==" + }, + { + "cmu": "QAuk6H+vjGdRjmZ6btbDN2N5Hk0WslNIaxwl/N8kjyA=", + "epk": "JdPzy6FMc2ncpFSguN7Ot9OFMmLE9HY9IkcNoI1Xopo=", + "ciphertext": "ghyKaNw0WnuOQ8g28w/NDgiqVJWkuyIKWUbtBnAzPFfP8f+6SL7acg2wOuOuiaIE62ZfCA==" + }, + { + "cmu": "XNlLpyGtcGltT4K3qWmhxNGcEa0WT+r4Tv/3bYr6Two=", + "epk": "pYvpyjxIdu724c5GDTzC7qzoC29KTld1n9Svr9b9Jig=", + "ciphertext": "OMio6DWzgCpEBarWfbC1z4FF+c9cJu9B84AeyC6lMKElLxoE7nNXEiGqVg6vNJoXcgDl9Q==" + }, + { + "cmu": "GxHGQmcxEKXuIwdb7MYUyoghszwDVFcs4u7PtZyaw0Y=", + "epk": "RrBidFzz338FFIVJ8e6ieZc4kEevSFwA6GKoySVqJVs=", + "ciphertext": "O3QJYixzkyOtxQDX0a0ff+m/YGlA3wA1GDSl2GNnc5KF32/U6IvCUMYjg/+NijbHb0FnQA==" + }, + { + "cmu": "Y+JOlNvjbnimizSVIIwF/1TZHLt95k9ey3/lJ7hJeEQ=", + "epk": "uDM7W91HQakuQccmDQmaCPzm+ZH1/oHNwAj1w5CkC+U=", + "ciphertext": "1Fe5lMT7g5gPaEHlt88m89VxTzhO4aX3uUlYyJ2/ReSuj3Ej/WZ+BWumeeP0825gKJwZ5w==" + }, + { + "cmu": "kdM7PELPgJJuhwpzePgL5+OlfTYuUfWEP5eA93KjZR8=", + "epk": "ry98HbPhmszx3Rf6IJu5DvGipMivLRHlU8luQYlCK84=", + "ciphertext": "xlNX1f+7DD5wr4nbe6PHbB7lAkMc1DfKMMsVsPZ90j63nfZ0rrRAovKgtsvOVae+FFaLhQ==" + }, + { + "cmu": "O1RMVQYpsnMNTqVqzBNsfWcVJik+NqzRnhOeckRMmA8=", + "epk": "gzCFmGrY/J6oWfa3tltR4g+DrZnrvHQ17a1cdvDJWGg=", + "ciphertext": "edydw93NeOa7wp+gxda2MqWKI3gqT+gR6qkCKthftUAN03ng4v/+bZ4W7HFIX8LU6WNNSw==" + }, + { + "cmu": "NkJvynPktT5PVBXhTUTK1ySEKerXsQk2tCveZ+VMWWo=", + "epk": "9CjKuU16d8gQPGCgKRtmbcUViETNTIeGM8i5mGwsH6Y=", + "ciphertext": "BsC4OUqrhvh3vdr6Un3wcFePJxLvuGLafGlsIdAD0LkGpJvaZZ70mHPTpvPN5EZbAKDJpQ==" + }, + { + "cmu": "85vwkt3k0d7LBZHJa7v2gVU28ZTZJIt6r+xdRE54MA0=", + "epk": "oD5FdDPq7VHKD/rzW8AZ1xKIbxL7Fg7+L2+9i3TbGCM=", + "ciphertext": "gfuNDSnKhSbuLtsvEi4nuAvJRW4nvyMZEFJfMF42muDLYglOORYnUraYxYnt4T7pEYzxgQ==" + }, + { + "cmu": "TmAAutWZLTUUOSwJUQYmcZlP8PjpGXK+JxOsvmS6KXE=", + "epk": "mwDSqATtJVXtx5jJSh8gEajd2AV+ZzCLcfPs1j4IY1c=", + "ciphertext": "4+FwujLCOzW258PDpoNa3rbM+j+ahf1lkNZamFU2/jNgjpHPkNQCR2+Iihh/DHvnCumpvA==" + }, + { + "cmu": "BmVx/rrHelH0gXODqbxwZgD4zSrPE4J9gzDLYXyplRk=", + "epk": "SAImgHt3Um7bOAb2YPmABT5mLT2JPMGrNsaPKAqzGTE=", + "ciphertext": "O27DjZDpKe1MZALuj0J5ZStD+rQGSvkhxFhtu6bpf+E0Zu0SgZBUk0iAcnkROPOGRlz6EA==" + }, + { + "cmu": "PWbnc04RkVqeTWRepjKkSv+GJmaj0pVW76WC7fmJdDU=", + "epk": "cnrYJzYwJqAhd+ub3niKFaTwrk+dbr7cXS9TIqjbpEU=", + "ciphertext": "JbFXuaQvxaem7w+7T4ps1HMX6oRPvL3r3UJQZ2L9X+/lNl0A9zFebgay2I2rN2pIL8PXJg==" + }, + { + "cmu": "YFcPzGz76y73EHEh9MavJHCRlmytDm1qw4PbXDtYp2I=", + "epk": "Zqm7LPdHmnGlWyVi7teUK6se9lylQ0ut83lPxXgAq1Y=", + "ciphertext": "DQgPvspTRPMdggISHGVXl7kwSK8ks7N7ibBjj8bkLEpXrOu1MQwuBb3Yyrg76pBL7mZEkg==" + }, + { + "cmu": "3GmrUbyb1Awu5eNFvkmDbMcIRzx3XXWFhNyjvS++5WQ=", + "epk": "WYWuXjwOE+D4ng6bZCNBUdHJkv4Y8QND/M+CY48TcLE=", + "ciphertext": "SqNMcqAgwILj7jjyzthuJJ7Lm16pQ4nOOIOjhk4b+R8Ia5Sy68XgmSmA1BUpZC0SjLuWSg==" + }, + { + "cmu": "8zUU5NEBZ6R+CoZAXRX0c4WffXeZM2i7Ta7Mmja/DW4=", + "epk": "WA4h6usmGAbqdy+sc6NldBR9dZ2h4orJ+GLcecIFBpk=", + "ciphertext": "n3LR/qTeiuJ7WDLg0ywC9Yab1Z2t3cTD95Hl3s2TArvbYnUAFxpLBSBOFZe7EUo0brnS4w==" + }, + { + "cmu": "a3sHsrnmQHAry6u2H6H+OvqQB1It+9gELKcsMJpPimY=", + "epk": "9y3n1qguntsCBp+NRxcn5f6+ucLjR52S21g3eVzytZo=", + "ciphertext": "TLmXNnBGrngpw35megaXExaQV/3QWe+Rq9GFj9lohhLaeHWDFeXLsTrTlMk7B2V+TwEnLQ==" + }, + { + "cmu": "em8P6+sozB8e9OojeUBe3lQp5CEcdylo4jxyIxMplkE=", + "epk": "GXIFek9gksLlNu2jRwhf86xf7B6XQx+FhJZgxayDEAI=", + "ciphertext": "gnWkobghxRSoZHIjB5VEhIXhmLi/M46JMFE21gHZv4ILJicIht9BuQHeBDOOkRWlmz8SEw==" + }, + { + "cmu": "TB794hUMp/icYyKE35WLtxUXMlxxmsWaFXu18xIAWHI=", + "epk": "gcAufolqconl+jdRzJihXpz60Tvibn7gB3qh6q8HG4o=", + "ciphertext": "hfvtKGSKVWIeQ64475xv8Yy37/N32e+xzrquO+yiNkEovqYwgnXBVB+sSa1AdLaDi41B3Q==" + }, + { + "cmu": "mF3vTWbqBPd7ZDdaeqmBHUL4aso0BliYBbHqdVE3608=", + "epk": "UseoGlT2AJitbNZPk5FmbnogDquOc93+6TvGQcm8VDw=", + "ciphertext": "51Xh26413tB2HLPt3ZDDv9jLr5co76+qoOki+kv/kTL5+ZHF3aAUTEdAa5pVWvkpMjIMVw==" + }, + { + "cmu": "uHWspaR87qHaplBazTiBjweb2DCk2QWUT1SOlBzxXAs=", + "epk": "xprgbaSyc/XdkpmjfUUZkvcr4pEF/zsJt0jvIzMXZ5o=", + "ciphertext": "x2pQ+MGrYOHiOvkkO2XOarNnk27aiB1D7u+OsStU3T2+zXAEJZg4QpYLW4mAP0OJ3n3Y7A==" + }, + { + "cmu": "eEM1LQ0lVYhmDGw1QPt0bcOzK/KfdgeUg3UFpW/QCyU=", + "epk": "RQau8ZG6gS/T1/1hj7j36dHnSsffTJCE1EXAyegdaho=", + "ciphertext": "DLuygU+jFDonmE1ODXPnA6rQMQulrcE+aAFunQtbZGPujmtpg8P5BwOsjqV6ml8asDCvKQ==" + }, + { + "cmu": "XflKBV6qOHP9bFzFQ79mMk+Rh7JyrKX2YlqwwQpXV0E=", + "epk": "gAu3y8+WSQaa6danwZg2MKtdDbo92axfdJEhYMRnMTM=", + "ciphertext": "L6992OaFTwtEjYX2o0H/aVI3x0jXEsyuq10XXLmyK6ZNuw8hM0Tf+uAmDHmsf+CkIWld4Q==" + }, + { + "cmu": "M7QMVw2w8V4WC1njwtGn7MvxF3c1bCJnl5R9diYyWEE=", + "epk": "4ASGMVvgp7Hfj+ILZQ4yXllIJfqQqJ8Z/mQx/CVkVJs=", + "ciphertext": "7hMx3n/9QIa14HBEHrb/a/fIywEVEOaMVcapr7XYtIsxqigze49adnlMHoPPYX/uJqFh6g==" + }, + { + "cmu": "3YFTZnIIrfD/Bk+GBcbkR/233uPgD02N3uD09kysCCk=", + "epk": "li4paWyXnpmKxkado++Z6PrOyry21I9mhE7iBmXe4s4=", + "ciphertext": "/kNH4MFF3EneOCM3wsTADlUYGK+MO3XZ7JXRjyweeunDzQCxNy0fTsl9IYgZkRh5iAe4eg==" + }, + { + "cmu": "0j8ipAouk3GkBtpSMFkpNj3JBpC/hV6EuFFU3B9sqBI=", + "epk": "xNSvXwjXG8O8i+5oA6xTvxqn3XZjH+ox+XIT76eeFQ8=", + "ciphertext": "OdV6jWiXPnvijxyC4GMyn/HXV/PPICh8+gkbQLrePJ+aqdXvelyoPP8PQiJOD2dnJzJW6g==" + }, + { + "cmu": "IeNooxwt5QfMlU3vzy05kj+oE4nGWQTfO/m8Km+6bAA=", + "epk": "aa3t0Gep6X7owNXaZG97HC0bxpoCmkSNWpSZx5bsS7g=", + "ciphertext": "sBE4C40NnjIZWyuOlB6l0A1PJsWmc1PZXvK6B9CAaj3eR+AuXXTBO+VgTHMrHvPyHEO3HA==" + }, + { + "cmu": "QPQA5wL5bkOdkX4YdJiCRg7mQ7m8SZ0wPygGsMdG9wY=", + "epk": "ZG33jwLkUt/nfYckWPgeYw0vQhjf2+7xk1tSzCVhi0g=", + "ciphertext": "tiATqiU/nOn4Ye+uZLHq2G1WfHA/cEaPj/S4HmDzXGp06ikltMOt9nxRIkNdy87uTSdg+Q==" + }, + { + "cmu": "eGv06qrJihIbWpvanUzzY7F71vQ4LfVJjz0tH+Jwcws=", + "epk": "3XemZHci2i4PX8z6D+CEnT7TLUsDAjCrz+5smni5TYQ=", + "ciphertext": "A0ucgf7AIuD+GOMxdoNjzF03fkwD3tI1egPLW8hsHaovooxzcPaselireGTDYe+aRK8D7w==" + }, + { + "cmu": "vMb0JBaZaFS0AaEganXLEWdcIsQCHJeB7FflR8Nrb3E=", + "epk": "nhWtLTic+3rPJeqvnfHk4PO1c7472RJpHOR0jQ2pJ90=", + "ciphertext": "DI7I151Gpe7WI88MSLFK01SldlVb2DL5HKCA2sukT+czzhiFyX6a+c0GTJH09Ll6Wfjsbw==" + }, + { + "cmu": "TFv0QNDCWGgMttAvTcNeF9nT1qpUOKnHgNNqW/Ja3XM=", + "epk": "LoftyE0Pb7oO0NqBTmtsI2ZfZL9+G7K4WoQS9UsI0E4=", + "ciphertext": "NzY38FLPmsZkQ1mLnRedyKXdIoVzLtvHoEgm9PpdH1ZfPU54L/1TrypNKPoi75XoZmwJig==" + }, + { + "cmu": "addIPKQAVlqofFQUdIFgsKlMhsWb/o1P8ZduOK00Jis=", + "epk": "/GmF4g6f7RTry9yV9nhN767S0Q52G2H6eLJXG8ei5ss=", + "ciphertext": "KYITZAkfdn9ZeXazjTTL0rLZoRKdyOGsdbQqWvk98Naam9CEMbFQBkw4M5zUNHgR7+JnLw==" + }, + { + "cmu": "qHbCEIE9VgpuVemwDxlk3HRPMZZvP5G0/XtpGGs19WM=", + "epk": "mA4wECzBeCFRNcp8QJLKPWxc7nGx2KP3ktMj+MkICZY=", + "ciphertext": "E7gSNBObaly0BtZbbLOoqiF7zWdtfXh6Ic5/AZCrK3RBTlM0v5x5GL7W8RYaPeDvJaKoCg==" + }, + { + "cmu": "3K/J04fJWkE5UmwoXC1J54fiN7fI4O/qkAUgp0Nh1j4=", + "epk": "B1yeYms5g/GjBmYhzXijIJ9WZqU7FYVYl7QFb+iZqh8=", + "ciphertext": "r/9NILSWNtIST84tdKnLbX6iHFoejJ1WxIVvscoiMs+2S2tfzfilei4vxoTimG/V1Wr/AA==" + }, + { + "cmu": "jYM99DO/0TaDm9hX9nLW54W5cceY0dZwEzwD1+2nuis=", + "epk": "87GZgVnDAZ97yBbVkkWBore3I8sBXFwedvt0bahaeiY=", + "ciphertext": "TMp6/OnK48psy3LFBHZYP89AqPPn2JZ/eP6o82A+V4xCjmjnT5LC6ClGwCf9CE2VQPQaMg==" + }, + { + "cmu": "UcFsn9EEcXKpi1POj14jn3u4+VMEL3MPa1EuoC18HBQ=", + "epk": "4TcDL2sCkoyozwxkWSLzmiHrPtIWUDx6dCr4fZGFZ1E=", + "ciphertext": "4h16BBPn2NJ1VKUyxRy7W2NVdrXO2pGan6yCWKRTaelikJ6Kf1ucaWAVaWAsyK2yrCqZXQ==" + }, + { + "cmu": "rLxbNgGp9/R/BdDUcOVtqutiIqECyn31aQyhYeKvrj8=", + "epk": "5NG7xzHLS9ceIDSA2SQPw4NfoUXP3ZZDmDy/IlQ/GdU=", + "ciphertext": "Asjw+luMcNTzPabCWvDSGCHT4zNwqkMersQG6nv6poUTC09L4wdawC/1HIUnklk4rOtWwg==" + }, + { + "cmu": "Iq0epufmcbPY+IQq3/wRfd152KLumt429yCLwqVky2Y=", + "epk": "T3AAzcXzqMSBafVMM3OC70SSzduarmU3zghtgY5WWbU=", + "ciphertext": "KBkHu9DSaeHKpheBUvlsitVnbfd97oSUQ3SC0m9XwrJUz2/vCLMypzIJ17nFmfMwY0OrfA==" + }, + { + "cmu": "H3TQqFsvPv+wqoxa76IAyC/z6Ulpm2pOeBiP18xpXmA=", + "epk": "2GWGXUHVd4o6MSAOqA0QAxIaHthbXzQlT67EVTDPfQc=", + "ciphertext": "ZS1Ad7zJRsxcbcmklHLZ9oIRZWlwM/p9Pk2Fg6A8wNnN/JbkDj7jWFT3qp8uoVkxZwAVrw==" + }, + { + "cmu": "mmuG192HdQZXsngkHxHaDttqFzHQq/+8ezuefHk7ozk=", + "epk": "IUlk3GZLFloo/4U5k6+Lj7Cgia0ioXnYTbGzaZk85Ks=", + "ciphertext": "6SNTIPLm2sILJ1lGIbnj/nc9qrfdA7f2lRyWedB7vhjLll7r0k+to8d3yxazHpuLclmLlA==" + }, + { + "cmu": "IbrYB6/sRzYDp0XWIzwbZBNChevWmLnVH6FPz3i1l0A=", + "epk": "J3b+d/ffv/bwhK+TBM0kHOPAzo661U3tnrEUx+//OW0=", + "ciphertext": "j0g7W1U5LxL1WQKdFw6DsMeuEODfX0x8Sr83Jo2Bv3T0h/IwZWfJ75ppe/YaoVgsRQxs1A==" + }, + { + "cmu": "uP9y7lJ0yfsiqevfRLpjp+xUyD6BuaGUZJSd5ajq9UY=", + "epk": "3c9YQ2YfqrzrEp5lBsMsTE9J2+l3uRtqoNQwSK0DH4w=", + "ciphertext": "idXI82DIx+JAiVPg0heV3d7au7+LLqDBIt7LT3ATbKqtXL4bY8kwe99fm7P//WL1WeJGsw==" + }, + { + "cmu": "EWXvk/sZXuldBSDS9+gcj5azUfLSWcSJdhWwmVD8olQ=", + "epk": "hrgE1qOyN9+5HWehoVkqCPAUzHrM2dU92OLRHdIIN94=", + "ciphertext": "QM51pzHCz05AwoAjSndyGIn6SmHMvfHLhwgUGLzcC3RxXGGAaSwpeo98YBielZQZzBxs0Q==" + }, + { + "cmu": "TbLUL68/NJzRL6LTZEeDHlwgwhgMmxtCMOG+YQL+lgU=", + "epk": "r7hPOqPsQT1tDFl7utJHK3C4nTP+DLEDd6EhVoaNBTA=", + "ciphertext": "STfUTDItwlkzj71ELO+xhF55C0QOSwvgwzJO9RfrkAKzkhmEUS2oZxA7ZsfSmqzsMtZNng==" + }, + { + "cmu": "qAs7MJoLwzMebLdYTRPwOE6FlBidTbsVlb8uMAwnJj4=", + "epk": "lD382c44jpBi0cfmo6DizY7E6cMtaOitdTeDuKb4ni0=", + "ciphertext": "evyYnh1nF0MKSUB94zsogHA2eLQeJhLWY2hb6YUhKRfzmgAi1Gn3I3JQHsAVYNwgV4c/eQ==" + }, + { + "cmu": "fE159oaiHBOFH1267BmxzyR59avnZ7H9D5PCm1RbhFI=", + "epk": "hqyub6LfW1kEd+uY11GG/lO2huVJma8mDANKBJVEGJg=", + "ciphertext": "9RgsihNHBm6XXT+lXFxWOZmU+8lPZPz9XSLiNLX0AuKoHOYQnTgFZ+QEUlIoC3M8PenL2g==" + }, + { + "cmu": "wB0XTlEZZPjBB0QYGU+DB2853RjbHHgAmjpUZ384kAg=", + "epk": "tov1TeaekkIEJ/9rWs/sN1UlP1F36Y7py6TtD/vrwNI=", + "ciphertext": "UuptxEA3Y4x7zmTyjZHPCwM6wCtfLI7CiaASl8B7wi5y5ZGvi4Ac3CXqRXqpYWzjSSTADg==" + }, + { + "cmu": "3cDcydnaPqFXCrFGaneDdRqWlyZWbDrm8pq2BBBnUyg=", + "epk": "8I1SH8EpeLNus3uMMTBhQuCzeQZVnLoXqcBsKqm3A0k=", + "ciphertext": "biknjy8qNEY5wc3ptDlEscPO9aV40fCO0wqVNoKsw+k8dQMILxPbs0/odgizg/UrU4n6WQ==" + }, + { + "cmu": "iMK7VfDlKbYEe31BZC+rWuIgFcCX43ubOpMV9DTX0kc=", + "epk": "iZPiNdHlmATAxHuyNuUS6oLzApjtqhgWQFfVIrmk0mY=", + "ciphertext": "2freD2oKAEZZUtwisvGRn6Z1bXfEIz0YtQlzCg2QdJ6XG1OtmdDFi3TRQu1pz9TGlw1BeQ==" + }, + { + "cmu": "G/sinp3aBHobCxKR1BLdSD+d0ceyyxo278rQvSzTMW8=", + "epk": "4Ed7hps7C4XxqI/7r+y6jPF81nZ93pgoeQJ0w+3khr8=", + "ciphertext": "57YjRpGqeqv0piZ6Sao8RK4EeR+6t1wMcNgZSYVuSWZG2CjNUVJOxQFFTZ617a6FcGK9/g==" + }, + { + "cmu": "fwXFhNI3+VdwH/LNjdUByLJaunkcAf3rQCwVBk9PEGA=", + "epk": "hHJaKNITWhR+unlZC92+4H/fONLhU3kg/fMH0zQZeSE=", + "ciphertext": "LzQuQksuR9EIFf3wvdsQsXfdz3vZaltiNglp4ww9ASsegvoJ9BNOP2v3xbNm0K6WhOh1dQ==" + }, + { + "cmu": "k3pRkNQNE7APnA5uB7cIetNHBbtVA8YC4oDCnfl9A3A=", + "epk": "mWqQRtlIzedW4wv8qzx1K05Dyirdy01g03qg7ROCjRc=", + "ciphertext": "YH1U1kCl2yqLPTnWISrea3Nwep4r0P010CHQ0OlYRVU3pAvzna3dICFTWBbpfHlMZYUT/g==" + }, + { + "cmu": "k9REV6cP/syQ18ly6j0gPo2HFsqcWvyEb2fXQxFWtDs=", + "epk": "cF92FgZB7oaSdF7Ld9vihGiLOhhJmb64rar+ZyxOKAg=", + "ciphertext": "DWlS6A5ojzmEyDZWp9MK3/gvGhj3zzRJhlI1YiZDmrO+6IboUugDGt1GzwazZH2SVTcpsA==" + }, + { + "cmu": "+sECAnwP0hlXVTg0RG9D14C0EZY8ISTnP5HlUG5gn0k=", + "epk": "9LDcH6XbMNHcMbXUNp85ngQuXtDexL9TNS0sYnKNP4M=", + "ciphertext": "uvERm445oC0M6PceVJSPS94m4LTvb0+ZbtzWVQA7YprLbC+3wtnZ1pVyJOdapMaFY8kS0g==" + }, + { + "cmu": "RgR1rUEFFmpkcRTtbUv8Ertx+CQzKj+SBENQhIb/mDQ=", + "epk": "QNBb/UViORV8aPj9LBtNTc0/jRImgYsuCk6pU2w7/h4=", + "ciphertext": "qWM3Sv0RlWmLX8UWChKxuxgNdC8zWTdoltnPJNeaZVlakOE6G6t4ChiD4Z4eWiVNKjYryQ==" + } + ] + }, + { + "index": "34", + "hash": "+xyASIMqiQsJ6IRydhFW2gsVfPUO63hDz72ff+UfPxU=", + "spends": [ + { + "nf": "VenLhbTuUtb51qEjUoos0iy3dz8dqpZM/ZcKeIRLytk=" + } + ], + "outputs": [ + { + "cmu": "q2Y+VXqah1/XzSShWwSUUI4QKSKm+Ah5+lihohj89HA=", + "epk": "2ELWAGxdmRYLmr3vOwZenlbZknL2B3s7nFy+NYRpZNo=", + "ciphertext": "sS+UqO1i2+4wHaXez0RkDHh+8Jeq1sDT5mXsU88cn2LGayQHCyX38mS8kUr68GFc0ywJ9Q==" + }, + { + "cmu": "v7o6btpKHQ3PZN7Nu4Bxoy2XG00bkMf/XZ4yonHqKV8=", + "epk": "vchAj6QG/kj4mrAsxKxX0Z4uJmNJVhTIpCbUxGv3zNE=", + "ciphertext": "ARCVltBWGVWxoQ1OdFLd3nSVoVZClZzRSme9bJtL/GRnA+c9f8RUWlVWbHrf4AzHzZgsJg==" + }, + { + "cmu": "KMAvChwaaLjBK/aQh05y6C1o87z+ct6TApmbnr30y3E=", + "epk": "7V1FQzur2bB4kEBt02ekYuwL2Q+RDUGLVJNYu8YyI+M=", + "ciphertext": "Aq0QLfba+1SW4loFZs9qNuJnZ0s6WbXXFi4x4f9NFxVYUiRMA9J6sg3by/HRmtLd0R35Og==" + }, + { + "cmu": "dTfQ/rGRty/Z0OCGpMeb0cBuWRySm4oelizi6m9Kex4=", + "epk": "atrvZhnqN2yalsQfznHCylJhtOixAFm0WFIt2bQ99iQ=", + "ciphertext": "8H+jV/uZhvYFJ3L6uTkRX3kM/y/8El0ZsJh234TUDecITb50EWBupNqEjpogleBuKehrRQ==" + }, + { + "cmu": "WWcKUbyKxCr6lMlg8rSiIbiCxUqoJPgrA/o9fs/e9VM=", + "epk": "sGfW8SDnfD9/h157oqyRf94ZLS0gg+miz2xWULuGyGQ=", + "ciphertext": "lzx8YuRRec6GDAlXgu0FxKLSZWb1fdu8GdCUk31xQb04P4PLd1v0TKHa+sMaf7zB22jhcA==" + }, + { + "cmu": "0g6ZRFjhePjNcsw5BMhirx8UOBoS6/3ev2HFoQuPOTI=", + "epk": "vrT9hw+nZQFfGYPDdx0aaxgZOBsnyEg3YOj325YUJ2Y=", + "ciphertext": "5hjV1SgFzeBM57hm/M5n0DuC6QOUk1w1ZVHTrdZ1d8nl0TY/4nTjx7uX0BWlxCabLkC6yQ==" + }, + { + "cmu": "+yITp7Lo9gibciM+qaDpwrxS9Zh+dDRgoSFi2xnFPmw=", + "epk": "NCfP2ixQnz0qRw8ZkHiUF+nnbcIPuFm+j/HdJ9E4QOY=", + "ciphertext": "6FTp7gMNv3BDWVKnK2JL1OhHqQnVTcosSukcmjtOW6E8KZGeCQkiuBCkeUkl/3simdDFhw==" + }, + { + "cmu": "d1HaWR9cSvkG7H5Z5Vj+ya062+GlShl8bA/K9yY/0RI=", + "epk": "IzLhLlA2C8ygxDDur8AfS7wif45JGByHfrJO9T50N8U=", + "ciphertext": "Imcrm0xaFaLdY6RhS58cH8nAN7E8DblRy397pWDLsidPZJMX7QRBblfQNEfQgOvaAroc4A==" + }, + { + "cmu": "PIPJExCHgh7n52j5nBSHH/9MSFKE9/v15Ys0UhgzSVo=", + "epk": "8K3qO//6E/ALHHwWl1LlWiJDQk9a8GAbN4BuSCBTI2c=", + "ciphertext": "kdVP+OTut7uP9IiS/vXqSC18QpWyZ6cAkEOm/a0TcwZgvYQN1iaI5ICtnTuFrodd883Tsg==" + }, + { + "cmu": "jL723WdZ/yQCY2ltVZ9NHiHgexYMN2B1DfLOS+W48go=", + "epk": "S8cHwamJRnwt7oFGsKNQv4r6ZMIO2KThR2mxS9A5BWU=", + "ciphertext": "NGf9drV5N/DdtMEl0aGrQKDUJBBn6P2x51I9vTYhZ5pvQJ5iQsWYS5ofnRoiFiIvKkucMA==" + }, + { + "cmu": "UeoV9a2VHNXCXiR51XDW4o3xRsOcYJMNyVUYMLfx2lA=", + "epk": "arFR1FO5BUBBAjdxSqxkqkO/k82Qt7PjDejmlSuIb2k=", + "ciphertext": "k4+EBe3XRlqIl/DcJl3e4rTx3eu6WdMn+h6GUQaNHFSDdqbihkzE78FKpSVHcnyJt0VoLg==" + }, + { + "cmu": "3/ZXrXvecB+CPxFjw5zHlzcrqquIhiSxGM8Vy4/sKHE=", + "epk": "NwlPRxNXy+2udlyduXkTodlrxtaAByNSstQUv5neaxA=", + "ciphertext": "00qGyPs+3WDVzdWJStpDh8oBR2PsSseA0l/hpFMaoHrj+VyRwdLB4eqTNQ7KTOo9AK5g9A==" + }, + { + "cmu": "v1gZHmgXBhRAnwykQVBlbxreIV5ocbEhgJVdjbLawz0=", + "epk": "Jgs/p9nkJBe0nOLowzdPmoD7TOibp+VPhITjF56n1o8=", + "ciphertext": "zcaE78Rnknv5qAhna7Ym/YYaKbL6XwbAHpSfqG6AEXUrtSWO340O4qsk4WMPEoeWTu7dAw==" + }, + { + "cmu": "Tn36SjM6FyO5FvpO0q34x/kFytftnFMGLUOUQ+v7pVo=", + "epk": "mfobpENgVA1XFe3/H4HwwTVsAx3YwJjMcJuRf4+/QLI=", + "ciphertext": "AKPEbj8XOVCo3w7/omdPiyr97zKvtWCtbkH8PC2ZcheCVY0IgfpwztPh+AaMfcBKS+kHIw==" + }, + { + "cmu": "zYdMuz+c7jj9lrLH6kyHTnCckH7mlgMNVMa3CTFAl2c=", + "epk": "G03dUuiYCKYTksZvmw4od0FdTm7ctaO1CJJ1WJe8SjI=", + "ciphertext": "3jH2Z4Aq2PLA8EKnQ+tSpfOcHVv7Ts1URtM92jYmyt2rpxaGMaGB8GG0mWQH8OXXxd8iWg==" + }, + { + "cmu": "kwu2DfFPfpMeCnZF89FlzwrawQtyNs8jKwVZlQ5K6Wo=", + "epk": "NnMv+dpW9YvWzfYCB6jasxJY5KQkgXykxPcS7ePkyls=", + "ciphertext": "BIPUnWzS8oPsBfWQV4jlHYOYbBvpF+wyswwi4qM+cDKAOQcFtbQXQk9ww+RCZeS9YRD5UA==" + }, + { + "cmu": "gauRui/yf2eiGssAbfWVE70t/4Jfn/EYJXxk40Hz1wI=", + "epk": "+W9bpOYVIqJ1nWg1xTsQYKlqEpyHbuM0yJr+FsU4pwg=", + "ciphertext": "tZIQz1qSbmXF3BYQ4CXyLUI4sKGkb+waPt28YJDIlNCnbKWovFvY4GNwMV27ATNUSZA7Ug==" + }, + { + "cmu": "veS2aejmCO4YxaD1wogdJ9Gl8jNUHLRgVG+/MFKImDU=", + "epk": "FucfPZ91waMYjK2AMXsFavz7DeOjFIgwP8x4o4RwcMU=", + "ciphertext": "3f9/n5JotSPD9A++rnQo4Sg2UVmZZFHrO2FQVQjoMRMzsiCNixhrSQ3C6cr6pV71v8FiOQ==" + }, + { + "cmu": "Jhi/9wRvu2J5qnZmWwprdoxy3+NQCk2LFjBggsUJyzo=", + "epk": "lbJql9YwV9hP2rx3Mfp6MS3n4OKTRHCKFLYEpJPUj+Y=", + "ciphertext": "yOhJnDMmDPHiFShS7WmECbizwoVfihvR+rv7StDJuXgCCXzF1onVu6VD8dn17dCCEUNygw==" + }, + { + "cmu": "fU4zKF1PXGhbUsvLVjCJrCykxEQzb8CopIwBnvvA6Rg=", + "epk": "G3TUl0DY+iQytcDr5s/Dc7q5n/yv5/Zm0V9aQnzwva0=", + "ciphertext": "IQ1csO4sb/MOdTST6XNc3cNZfpYLxvN6PbEXoge2lqzkA3wphcWfRuHIIeyhsufiN/194g==" + }, + { + "cmu": "GlmXadLZtxjxS8WXOFnu4sEH59jP0RAHjHSxblAm4nM=", + "epk": "xHmABx5LiQD9OuY2VWpFfvrSiOokPfWwBcfCuf6W4tM=", + "ciphertext": "WqVh0e8vEKGZ28AaXPEiSEwhDL4RdC9tzeFeaTRobPuSIjOPVsFhbvY6tcZ5BFxyHUPpkA==" + }, + { + "cmu": "7QmQE0KpGuYaacLFXpQvcwpPoYisq6w4ApLWkf+3zTk=", + "epk": "s5sFV2SkieslTiC6jB90Adf18O6Kwl5KBMhqJjoGIMM=", + "ciphertext": "lyEitdn6gI8XOiAIfQUxdCD4uMi9j0ugH85jAJ+fpuf1PznEuReL4yFRuDD+QnpNB62mVw==" + }, + { + "cmu": "e6wmE7UZlhUVlSFiFTajgL9YgAd2Ro1gwa56Lgh1100=", + "epk": "kEYV1psDz3VL2iir5m6ys2JiQH7Mh9yZKV846PBFCO4=", + "ciphertext": "cVDlKPItowpxSf93Boi+rTIYqTeFyn+3n+DqBc+DuNIPoQd8b3i24veiVY7kC7TvdKpJpg==" + }, + { + "cmu": "spfZW4WJmKf5qMfofY5D4t8sDu8arqbZpYuoGtAn8AE=", + "epk": "3xz26iWV8YkKMi6ZQ/NzXHMv0C/W2v130mKW9UhB9UU=", + "ciphertext": "5Hv1UC6ntmlxIYKv73dbXw8X8Z9wczrwD02gmjjxJsFuk+H56hme7yS5XXXcvI0wr+81zg==" + }, + { + "cmu": "W2tq0vl2fXmFgpozkMj+j8Uh1dQdnAQMeYEymhhH8Ew=", + "epk": "xee8jFLuE1VvB7xnlriIsXGChcGyU2T9h5De28DFYhc=", + "ciphertext": "LzllbBj+6sJ0DJD9eLBFdf3luLQZcLyd+E9McAY6vTwaxuLf1qk1blhq8L88yODZP2B79g==" + }, + { + "cmu": "PzTX0p/hV3ZV2Q0FpW6ntIHGHlmBzgq1Gp85U1ctWBw=", + "epk": "U6NU48RuLwoP5ev9H7L6qJfLnytKHYpmhEhD6YS0nmQ=", + "ciphertext": "Uglrvh3PwGWZknfnHUvT2IxhzbiDsukrGKEsEO/VBovHz5Jm11mFZjwEgr6fVIXcZriW9Q==" + }, + { + "cmu": "WHSrKM6c+zSR+qE/g9PBNPg0/vGLZDB6ceYwNBfMP2E=", + "epk": "mG30utXQTtv1VW6DgAEfcKgqXBFNt83nSlBHI9i3EiQ=", + "ciphertext": "RHipetLyH7Rj3GeOJa+EpMUx7AKS4hMKK9XoAy/JIz/CQ0/CHOtHlkYG1vyDFag4U75Ghw==" + }, + { + "cmu": "InN5CJY1SarsIqI/feekhuUEcH+sO2hjFt3MYqrYwT0=", + "epk": "fpSSGtyeJVQcYCOgWvLVLdEEDLiid8t0o9Rz+pHsJbE=", + "ciphertext": "4V2gZpmeQcczChV0bmztcOHSxotHFAM2g/2qpAGiDU4Rq5VaQYrUCAFRvHgWqf2PMVK/rg==" + }, + { + "cmu": "mGwtuGjVE3z9XhVaMMG9oXxE3abBYjuKbuXUbN3omhU=", + "epk": "VrBdqPLJu7egrZMcVYX95Cid0qmfrXQI8gdPnl02ymM=", + "ciphertext": "Qn4MNLpQdefw3+aqHDGQt4Pq7LhpaGTub6AMNNTSHHZNC1lSvYX7bLQDB2VAmoo47QH+ig==" + }, + { + "cmu": "L7cdtUNbkHxy/aWAA+kYFNuafYTceW96jjWw9bXPcEc=", + "epk": "gbhfS4NNBMzUKHPFXF7sZUss7gcDvFIPSZV3V9u1wOw=", + "ciphertext": "Co1G4sAkl5Po4Wln9l/b/enjSuuMXUIjXteCH0v2HisWSo1bH7Aztut5NNf8a4g3myikeg==" + }, + { + "cmu": "GSBU3DfqO+mAfJQZwvqzCJ+N37kORyEzMWA2s6/veV8=", + "epk": "YkqttK1ZkBFDtYQDJFP4/BEu2RU4HL1AOtUWEMOHj5I=", + "ciphertext": "So9VWlNTTENFjOtdCaQJJWPycJ5tQQs+JIK0AQGHBd3H/JsYfIfBcMMO4U/AEabnqoAr9Q==" + }, + { + "cmu": "M9YlV26B61yg6y0A1j9s3f8FaakkrOJ7dPd1YQMIOQs=", + "epk": "8MuzccpUzJzkA+3uox5yRCVsE/ALCOMjlQjb3xOeAWA=", + "ciphertext": "fCJQO7Q3qHXN5tsSmldz+fM6hNkziMZMlSlgWoYuOJs2PRT3sOMrZvSAHrDDTWlfbVk29g==" + }, + { + "cmu": "Y7TtBHwby3SanPxt0b6FVR58APo/SSRjDXkve82uIic=", + "epk": "r6eW3YDKD42EmDZafbSt9BfGqHSIBLP2Pf3ptgBEPuI=", + "ciphertext": "0UjZ0lJW/lxyLsyrHtfd9FFMDhabhpd6t3efdkxiu6+Ia8YxFRm6pEyAMt0r4mIy0z0qeg==" + }, + { + "cmu": "/biJrE8mtBrT64/sWspMUAY1h6AiveM8FKhq2QtmFRo=", + "epk": "2FEdr5Zfq0vcQLPC7w2ssIT3NEbC+VxjOFfN9tOXbpo=", + "ciphertext": "RmnWqSsOFbLiGo8eV9D8U3wP7eJW6hjP5Gd7ORMbBkrd2IByD+f3eQ+wmWIgCDNzJWVQ9w==" + }, + { + "cmu": "OT2sQIv+szr66/wlaGoHzSRjPtepWlic5GjroZOzWVA=", + "epk": "jratmVKIWg9RdSXTLLzL3LF3oyfC+ncp0cb+WVTv5SA=", + "ciphertext": "Yu40WK1k0t1JNLvICHRlkUbotMu2ZC+Y9Ul+1mbZe/pi2fkt/VfOWSwWpzD21cU12mWPUQ==" + }, + { + "cmu": "GtzRUr8yBBWlIGRxdqZcswVQVB7FcWX9ei4y/Lo9njo=", + "epk": "MK61MuQVoFDIx7ZWFG/lAKevsN7SqK8b2PJyEzSlOFM=", + "ciphertext": "4BY9IhszZYBkjO7lsdDJG1wXS+rn0wplqjGBZuSjKT1h8QTZEn9ijHwmf3VU3pI6D5TUwA==" + }, + { + "cmu": "32hmDhBWO+qsE07f662pCts3hglJ5Q4hWb6s8bYF51k=", + "epk": "IQjlGbiB2D5X6CifeDGYXtsbmmZl8uJJwg/Qw0Oh208=", + "ciphertext": "sPLiEptEgPY38fLvAsaWOjgtd7PTI8a6tL/w4eZOj6f0TPuh0xDFxQFx04Zm5UKjxlkqDw==" + }, + { + "cmu": "Uw7clkI+sbS0yj4ItNzleDLug6OGSs4efKFlGN5WiTo=", + "epk": "z9LgmcBGXn7gAmGTyn3tOd12D+QJS/xRQZ1t70aJzA8=", + "ciphertext": "+JYYd8NxJWpkpTorUWqA0LoaEqM7vWIvId68o/Uk8w6gEq7qt5zILojK7q+6AHC/nWmw1w==" + }, + { + "cmu": "sUcG3gUp9F1fOCufArwEdESDI54AmfQAsEocpTVy7xk=", + "epk": "9BF82mLHyKwiAt20zoesSt7ysEvt3wFq6gmCHwrZVcY=", + "ciphertext": "+6U7bTbGDlU33G4OItncQp+bgg6d96oQ2vkImijXIbHbONEB7o6XcZdeeS4ENSnDrDGhVA==" + }, + { + "cmu": "vs4dkgL2QSc3dwB3aj3mrqLn6QirtHbg8a+DPrHLGzY=", + "epk": "kqTbRVBUCDp3f5Vb1PFsHpg7dd9RaR/ESe7uke3tEgc=", + "ciphertext": "pO1kpRkawRYkHvMROK2O3YAje1tJOkr3rvqgjyOrAkTG6m4NF/9C3Mlv7TzhKrATbJvZUA==" + }, + { + "cmu": "8bbvELfS3hkHRQBb+L+WGWOGgYe4u9YE29wDCx3sWQU=", + "epk": "OrYbgqht++PpwJSV3Q0PDyxZJopKP/wsGuNkwtrOh48=", + "ciphertext": "bQbismBhj8LjuVUR76P0ud/xtZAXQzuZnyuqVKZNnlWGDhwv2BFY7m6N5rNUbrVQHJWswA==" + }, + { + "cmu": "y39FmAJ8+ouBdXDeFqbKRCe81Lkp/jIeqdSbEHf/CUI=", + "epk": "0i29kuGM4fG5lkXhUpenCIVla0J/4pAvZIS5LVPis4I=", + "ciphertext": "S9Bi/9dYqlFTR8xjZxYOsQ6UfdoLtHCKSdE+LM/WSMNgvZr+TzFlgPvZXkp27sAXZUo30Q==" + }, + { + "cmu": "de38uYge25Ep3kih3Z4rlu5aY2wTNWAFsBNwjlpZEQI=", + "epk": "T4Qy3LJIz2vS2sX9870vlCwVbprbH6PD9Z5LgBtE7tM=", + "ciphertext": "KhK6Rd3mB5kLUG+b76kukRrz14WEHKl6NxnKxznV5Bi5HdC/i8u7lYsopQoVlHD/KmBl1A==" + }, + { + "cmu": "Z9HmYQwazimL3DbvsejoNSjw1U6BlBziHb/+l9FuliU=", + "epk": "g8km6q39wYVJEHY6T6I+MIPiAI+ebQ162IKwidNL9ms=", + "ciphertext": "+ShVWYLaLRAAayqhxUDfwRk6Giai94CWvEzOILyfYjbcazdhsA+ptBP4GK3DPgra33SO+Q==" + }, + { + "cmu": "jlATdu2SqsYQtsLZmG2X/IEJWMD+BrjiKjK9d9Qf/A4=", + "epk": "GJdkrvjgNHP4lhtyjwuSt9r+ciyqt+dCu/LAfzZvvsI=", + "ciphertext": "iGsu+RyS7wKR776k6NFdVJmF127dcgvoXHG/h/0m9LtA6c6Prs/PBg+JdZHLRXrPB9IMcw==" + }, + { + "cmu": "ytLpZ0JsHuG6A95uVge0QgNtnIe71UlaNNNd3xuzMmo=", + "epk": "tlYTjsvOhdbh1O8tM+FdiW5yKfztAEhGFKV9D9J1Qmg=", + "ciphertext": "vbZsznnx7qfJn/8r9GmZeGA2TY/dl+MpPNHX6AqDKaztT+p/2QvvAf8brBNGlVjv0i/EVg==" + }, + { + "cmu": "xG4nsmyFyDNrll1Iytq4f9LdvPiuo5kco//x/njMXjE=", + "epk": "mvTMF7wkpDZ7Z7IsAG0H69UPEcj7VsP9XtAN/h+EGk4=", + "ciphertext": "9pYnmWY/tYqsdYGocutm7iRlx1rM1xPAEtZ9xbwee5k5amBAMkJkySTdGWTtTM4uqlLqnw==" + }, + { + "cmu": "W9G3d11GEp47B/g5B/N1ZriCRJXou4juvne73IwtTEc=", + "epk": "wLcFOBb7xiNXUGV0nsgVkP0gFo6TVZcXOYM6Jg0RKj4=", + "ciphertext": "HpW624dtWlZLdMdl3ia5wSA95GvHxsQevVYvGcD7ptAOEVQ6lXsgRF2c8/VpCt647Psnsw==" + }, + { + "cmu": "Errwfap5K+EjNn5GOlq/ydJ4eodH8Dp4jWYtXkgxe0A=", + "epk": "bR9UsTteRsI4uS/DGftKPA90Hc/02bVOBSpIo0qI/io=", + "ciphertext": "GD/cemjabpsgZ1sUQxl1kzAVtanTA3vCq1Z6LgMxG2J8EuPL/BNfh6MWZfixtu7KX15zPg==" + }, + { + "cmu": "PCT7Mu6mCSwHL+B8gBdZ8zfjQdDOJbTrgV2GeoJjIDE=", + "epk": "OlNmVrDO55xGbN/B4gBAyfN68/WIoaubLFLN03JYXm0=", + "ciphertext": "DC7AaBxRVW9T/gxx7eNs8XnA4XH10Jg3SP2aV9ZMM5NYt+SzwhPRec8XpPIWPDLejUDqYg==" + }, + { + "cmu": "Zg7lAw2KMXI6p4PeaQcUds96zR2Igdx4Au5Y9WacqWQ=", + "epk": "GvQydpwxMjailnCIsamHGlXvmAMsXlkHWa1QzTPkjbs=", + "ciphertext": "+HvNMSzac5yBYGwQKzbBO5MH8uK9dxChyzH0TLxCjKJn7zs//5s00cKu3sgWeJqamhLkyQ==" + }, + { + "cmu": "vdTusuLIWLYWj5ZQ17seFEQiS0HkpwCGZ1CoPBgAADQ=", + "epk": "lduSdiN6ysD/BC+Q+9EhzP5OBzcIMuupMacsrCbcQdg=", + "ciphertext": "tN/pgK1p2qZQn3PUQRmX3VE9OZepe/SBUYbfd18PjDR+vOVEZj6QCOvBWlV1amzC9CGY3Q==" + }, + { + "cmu": "zQF3MHZm4RXcUOcBJQbRDdem7lvQxVlJMH8TuDkcuQw=", + "epk": "Vb1Nt/zRyP/NrSMYbdPF8goTf5Kc2ANump2+8Cqklys=", + "ciphertext": "9rSpSQ5FqTYN5AS1NQo8swSen4/7iHsBpmCVzbhlk0zQClm4XsU+B/9pexoTlLmqC0Q3JA==" + }, + { + "cmu": "4gWJyMa1KDRZxyYjoLnBTxE9NbTZaQYuSWN7IiwyvSY=", + "epk": "r1lZzHNqqHGwoM/bwDy9jsRa+JVl1hies5IGCIO2gNU=", + "ciphertext": "qP2kk9XfPeSPgboJC5dyJgN8ZpHDzP5DUK8P6iFMec2fi9CjEaniNolfaNKMcXTkpYHrQA==" + }, + { + "cmu": "VJCmhCJiX4RQyKgJOSe88fIRtMHv+umgkpqeRJYb6Uk=", + "epk": "DFkIDrLvMQe2bNjBl6na5dEl6xXix7X4zVbA02lNoyg=", + "ciphertext": "Vki5dZsIwLpOxSTQhCxS5gOX8nqe3L8QuAer22GfuhHYhwNfXeNWXFVjnJxkrbjQC912Jw==" + }, + { + "cmu": "+7ecnMXa9/o8alRv2IeBSXUo2iJIrxG8JtZjy1W/OnI=", + "epk": "0g4d4tIlyWmm1XghYa+zh+J3wKyKrrAfX4+klED5Z84=", + "ciphertext": "SRbJaLT7aORUg28F8oVbWYt0U05DxZ3eWwIZ+KflRgtOYNleVLFZAIX6QWKdMVqaEAvfVg==" + }, + { + "cmu": "rWbS1610qyIJY9vviwDQfCIVB32S29CHdEzMMQRdLlo=", + "epk": "6WSeFoXHdODg7W/DoFpN0xhjENfgEVl2NGI0ON48Fso=", + "ciphertext": "js+S7W8ze1FYNmYT7pPB1aFaELDUB6zBu9Wh5eBwEtHBnyysOjtD+c+liufR+ohEtcWTlA==" + }, + { + "cmu": "37mqScaI106M+5wItJPFWGR1n5M6eds8la8gKln1UE8=", + "epk": "f3Z/+qud+Vjapw3wtiOKtKz9X5m6x8Gvzn8y8tNgztw=", + "ciphertext": "UK8xmkSZya58PLrunDzonQgqkpBFB04tkrmZPcAXgjzn/S7mBKzSIZeU9Jbx9zzgK/78kg==" + }, + { + "cmu": "n8/b0QGL0qneqcYuoyodyI0cHPBtR+sFWE59S53rCDE=", + "epk": "XwyOvyeQeBddE8sHd05MgC+czxB4DPxerL6SXHkYE10=", + "ciphertext": "i+PPa26eEdZRNf8ZCK+XjTagCrr1q+3MWkW7devQEF3HJpiTzi13kvpbKCHih6O9jqbxPA==" + }, + { + "cmu": "5XnFXHrJZFUZFXVIDAMxC0DbRyWiA0BPGETNRAnHnDA=", + "epk": "4pmMj2IH58ZxL2+WI1vYJsU5ojb933w29S3UGFCSqLE=", + "ciphertext": "fDmWL8gFblpFRJw945sju5OqKWBSlDJApbKARpBgMKHC5lpF35PhOAsCbe/70SmXnFsppg==" + }, + { + "cmu": "mW7sHmj/YRcKbuK8CPrbQmO9rVmq1LEvnK33czWP7Ww=", + "epk": "HQZC0HJ5KAYm+34EeJE48PEGib2BtP1Me2plxupis/A=", + "ciphertext": "B/qc6jxNsMyT0kw0zcY0uqp4ZYr/SVxG7Xiqnp8uSQWbDfUC46EAoEXrLLPkt18lSUNvDw==" + }, + { + "cmu": "PUb7Sthm08ETp5FcbQL1AVkBZ6ryZ8lJSB5nzEyL6Tc=", + "epk": "MlXEIk9tGkm2loQG2Xk/6S92j5bA8Rvq5qKPt1VtO9w=", + "ciphertext": "wgMqYJL/OUUOpTB0RA6PFupIRiR4Gnj/ajX0G0bAOOjQLroVFiIq6iqdEV5p86ywQ8r7Qg==" + }, + { + "cmu": "Xg6DP9oG0SJ2nrB+apjnEHnIsxiCAjrM8P52/gEJJEs=", + "epk": "o5CE3XV5YKxwm4inHntqrWYawAZUeLw3SLnX3bUhVCI=", + "ciphertext": "WCpXJtU7q++OKmgUdaI19ADSyr3PMrx3daRLNDE89t9wTLBoatfod03W5Axzdo1+pHT6kg==" + }, + { + "cmu": "B52EVQM9nT4ZEoHmx/jiePfRsl2GE/VEE7Eo2nR/CVc=", + "epk": "jgwqj67CIr2Qx4xDGg72tKoVJq87mbxLcB4OKl81HbY=", + "ciphertext": "tKqOumq/zTfbZhl/21KZ5jss4YFmchbsG8aA3jK/MNyvfuOEItZef0lY3ldWL5mW8V9H0Q==" + }, + { + "cmu": "k2khXCOZN1Z6PkT/KAc6fAqdAJLgeU9Lew5547+Cdx8=", + "epk": "V4Z+JXK36H3MJP6COLOETvNdXYdsYcpGoT+y7pOrGic=", + "ciphertext": "hkemcKN3KaLsqxW8TGBlTZQb8DniQ3ILqiQeN5uUWCylKPY4wV4BDh7NG7QOvx+1LycwMg==" + }, + { + "cmu": "UCVsCUpuE+R/T/rAr+uBlf2Qhk+uRlxNhp4QIhF0EGk=", + "epk": "gjInG9dzphwTDaf1kEQ4ASWUGph8ZwsvvZ/7CNDw3uM=", + "ciphertext": "LzvE1hAD1bGnWX+dlIDbxCC7GdWbxg92KJWUaKbsnAo2/AO8wZd28bwzcOclBSM7YChTNw==" + }, + { + "cmu": "LNIvED1OU8dt2lMWH26l23nDSgpvuQTYK7sj6hjDoRo=", + "epk": "iGSd0asqVQGKWC4L0nwnhupd1anWFFGZTPhrmBG1s7k=", + "ciphertext": "HgGbcmKUBUO6ZIL13fv5G9mfRHjegveMsmVHdCTr/dem7vIUWe1d+OYGF1G/dnebknmGMA==" + }, + { + "cmu": "GLJReg2F8jqL11bxeuZjVVtUW0bPVye3kdJLP1QGn3A=", + "epk": "B4SsSItzeyVr4GZRHZ/XQKwRXZndPF+OjPQowqy7PYQ=", + "ciphertext": "/05c+6HGlt8RyHrxQySFjmi0ildGUw/w9V5KEXmCTuDRMGZMOp86UQKoDDiok3c47n3vFA==" + }, + { + "cmu": "IZg1hZbbgIndRRjLnZNVms8vym2aslZ1e4p0lSFJyxo=", + "epk": "Z6B8RpB6THRIUGlGT0WoR20wMT+8D0X5mrm0jCrK85k=", + "ciphertext": "EFEavVsgjODF1vypgm90UpU7vHWkOJG1UIpesYDHDQOhk9Du0etL6dAwv3FRhvMjeYy4Fw==" + }, + { + "cmu": "sCbM9JHWROH5h2ExgXg3f4YpFMFuGJmhyO+KTdiesGw=", + "epk": "TvopKYhBVLS7ef0oTyFOZoSzkKY7HrmFMlj6qldWmEY=", + "ciphertext": "R846PGztVk1y3zg7tyOCIsLHglcKqA1dQXIuLf/Lttw1mVWfhXo1eoMZDF5jx8fsuyWOZw==" + }, + { + "cmu": "aax5znPTXbefLR7cGaiBXhMvNvVq2atkkh7++qGHmlc=", + "epk": "iInqbscUqFohnZhjV/lL7yC70s2curCOqtWTJOFo9sU=", + "ciphertext": "KyXU80ddfU+6zG1ralqQcJgeC87pabF7MdmUCO+qmZg/yTTW1/u0ysXn627LgyLVM+RSjg==" + }, + { + "cmu": "ntruzz7b4fw82Q29OExRKMyfBRXmbvYh5ZlE10XU+EY=", + "epk": "xP8W3t3ZUOieaCNPGwywFQi4o37mW4Sx4QRK8TSpAl0=", + "ciphertext": "we8VmMoOugkyf/w1PNJubTBodKKqyUupV0Y2UymWrEOHa9vyucpA3PeVgki8YSZ5n0RZ3A==" + }, + { + "cmu": "euK9XFG4bjrhW91i3khexzJGUxFqrIllEYFlSarasyw=", + "epk": "h9ROsS3QtzVDfZgxA1CMNDtn2ad21aYgT6OnfV0oCcY=", + "ciphertext": "3dfcxjeXaRsMoQylXJlyfs65qo7ymx9CYI6liTsvc1jmZ9ts1LxhgzIEJMeJz+8zp9RhwQ==" + }, + { + "cmu": "0+xGLVR/VknDNX888nVsl8RmjRw9jr7bXh0Nj6yBRUs=", + "epk": "DmwQoim9dWn+UZmkoRy5UiGX5zzFTXi5GcJi0zmBIF0=", + "ciphertext": "cVyWW/lm+RE8Jy1rUoMsfHDla3BfByts6abtsG/wtmkFJntiIMXzhpa1P57YoLE+wjssgw==" + }, + { + "cmu": "IOUT69GcZ2dd7afwPzk3Lu+tJ1XerRlkmZKHl5M91T4=", + "epk": "NxGU15axA25XvdMFwoeXxlCrsxewA2fN1tu6w6Awskw=", + "ciphertext": "XKzZYNS4eaz2XscxlNlgz1+BNsSBnKb4dnKxdESrXQV78Ow/07EIvvjm0mGh27uedrzs9Q==" + }, + { + "cmu": "DZQsDkc3MXyzwTqEPtffw4Xi/kqC7VtXJFv4HNZYcAs=", + "epk": "yzHNoZYwO9sCIGBNjs/HmtZjMiHbUbLTflENEcOkSQg=", + "ciphertext": "P1jX2remGpi2rYrzZuAQWMXEX00xmC7dvnMszFhhgzs7ZCh2AWRFr3H7KfOlwaHlNtbccA==" + }, + { + "cmu": "TRUN5DPcQpRz+dF2l6EE5pu8w5zKzg//rkMwXL6hPVw=", + "epk": "UkpHC5+8tdUA77cm3RCEm7oihFo4b8XnREXLHeO0BuA=", + "ciphertext": "k+bNAS04g6WTY5gTGTowq+R9xX7kr1YdJHC6bntbre9pSE8D+TglerQrcd9jRBbE2b7vCA==" + }, + { + "cmu": "+uhIGYf0RB358EvVnBOa4XH6MUaJJ8bIP9C1vl7/O1c=", + "epk": "8iK4mNl1pE/wW5ZbPVazcmFnxrCAWUDMv1U1JhkJr8I=", + "ciphertext": "cKGMrLXkRVc7s9OaU5JQobLkKp2cO8AE5vrtI5709X46RMEyYp2IHdBVZfwZkkdANzBF0w==" + }, + { + "cmu": "7/vPgjaXprJ4u+HMllv/oLQAjradIJd3v9mhon34JU0=", + "epk": "fd2FWVBVhHrTNCWVVYPKUwGZXQvdEtgb2PObtPT82jc=", + "ciphertext": "0MS9pifaUN00GGebtVWLKClY4nVfasBHqcTItHciOyNPBD316F3DrhBcDmGCtetTUzn1uQ==" + }, + { + "cmu": "j3OrxV1APuCtb3QfJecFg/TmbU5AvYfp4msBk0dqlR4=", + "epk": "le1rXZcFDuKlq2QlHRz9YlU5wSf1Ur7lqbiBHt8/LoI=", + "ciphertext": "ta3RInpiBcWQ60BLxlRHWjKjohpb3eOoMWdJv1qKnO6A32JEdcQZEgQ05UkwQPV2kSewJw==" + }, + { + "cmu": "sBSbTZxWKVnbyLwupJOWwwn7jDuFXTGifw3ygDslBko=", + "epk": "yeYxKm95Sr+htWX6Pq0pOVWBD/L4nJyOqXTA439Iji8=", + "ciphertext": "XJ1YcPlt8yKwehnYoKeQx12whjUMEjDDlg2PsfUM9O52LQ+olWly8FhetnhVB3/MCdQkBw==" + }, + { + "cmu": "wRDnt+Nu2GZeIii2tVip7UbQh/JHU5+ORZyOIPqpxgw=", + "epk": "4Cp8eLg12bqCf3uzIErG3sZIZeYpAUMQ5Dp/OW+Cb+k=", + "ciphertext": "zCpz+5wILIeun0sSqlhDrDLzHM3nPs/b4Eb/3mZXI7R0sdDydCd6G5QpH5cTwxWwhSs5HA==" + }, + { + "cmu": "D7nbEy/yRbUCko7g1obqMFO0gIydSpbAg3/pNmhjVAY=", + "epk": "BHNtEcp7sqX0p8gQzFP5It/CMMvr3qfCXMBOp3YV/QQ=", + "ciphertext": "5mYYyVY8hd9F/C+RXLRzAs7hSR6f/sChJkZlGKs/a5OyKuv7QKowQOexxXoY/ZN2sBgyDA==" + }, + { + "cmu": "GSRwUgr8IP7ZAN+Mlcn8KJxBm1bg+uLDaLPIqBVlL0Y=", + "epk": "fZfeoncGVTYQ6GYbBWV4+f20jipWRa5VeWoz6XZQRwE=", + "ciphertext": "SDY2/8IAfeYH3rgFJXY4xktr9HTV303SZas/GszELXo8+dIemRi1fQTxnRvz43wOQCNV9w==" + }, + { + "cmu": "7oIEsqdcFh0qBogNDcD8fNNhGte8JNXBqwJ1rpDwnHE=", + "epk": "dpZJA2XJGtAhMGA6Sr5woE4omyR5yCVKUNMDrVV8KJ8=", + "ciphertext": "125XWyeXZcQumkkbYSZtz2UyFVDin+OfN3RmM2CmngA/GjpvoX6byUguPgEa/MZbjhflNQ==" + }, + { + "cmu": "NuIlZyACOvalFcRtQYtNqVfeOVrfCz21rg4OXtLOngY=", + "epk": "8JAWoCWbhbz1OqYLEiN6nfuJ9nWH4dtPNmB1WKqx8I8=", + "ciphertext": "hi0pGybylLuDRiSXHlYv8G8qJ6U2I55F5XqYTf3e/LX8A8JFi2+SKqgKOG8ttxyqF3d7WA==" + }, + { + "cmu": "O2PK1ZeMSB4unMedXydDhmPzRVGa7XUj+gBNIqfJUUU=", + "epk": "Dr4zpsC5L0OPbIgAlGiC/nc5CfVukqGcoiuXyOyXV/A=", + "ciphertext": "2HpvUKz1gjtL9mkr8uydtL0aurVqibAmpUbkvjW9yxM3Im6DDN8qp1QdACEcRmmkn/WChA==" + }, + { + "cmu": "wwik91jdEQvPze/8c0eoBUh7dfR9sexpuimPGBWo+FQ=", + "epk": "Uz8mUcUUckRY1S8hJfmVva6r3qwc6uuIdQ0uOTH64jg=", + "ciphertext": "seS6n0kP0tqDmmKtbsJAsBM63KX1XefPghdbPNKQge1OvuYyZCmkronaQuBYm3u31RDTlA==" + }, + { + "cmu": "W/biRHvzLv1VLummpRYqMMnUz1eiHP8byaEkOOcjGSg=", + "epk": "RMFbCRLOboQPvWEpxieHaue6ocHaImahNE/igBRKIM0=", + "ciphertext": "6X5VW9/1Iv2KjrwjG7BhKfTI31rR5XQFXjZ61AVgwBiYK6YyY58aB4ZFZ38dHlIGahKSxg==" + }, + { + "cmu": "4CiJOFg6YMwyxvJ5GoAwfR3mP/wCwtHNxNZ9cqBMNGU=", + "epk": "wNn4DZiJp07CFtWYO41OzPeytbozaYEVq9uOm/RkCW0=", + "ciphertext": "uKY9OiVyiDYiMZxmN0PTXDxQQzXuST/zo9fxV41ZXy7Qft/YRRHG86Ttd6vYhc0xwQn8Pw==" + }, + { + "cmu": "lnvtt9f+HvgXlJWC6whlfsqrOEWHUwcVJMdJVLpVpWQ=", + "epk": "1wdq4wQUIoKnC1r86O4WtVbmNdwwvuVMDM2Sk3g/sYQ=", + "ciphertext": "eJxLv6MJK320NGO/MBSiTYApKe/HvN6Ez4F2kMA/GveQdW8XkRnbnOwHNe0nDTKqhTkDGQ==" + } + ] + }, + { + "index": "35", + "hash": "5zq0xeaTBiwIqBW8F3jRcUGACsnQPCGGdd3umCBNzx8=", + "spends": [ + { + "nf": "WFt4y4sMmfLDMnmMhVs/N9BYVIixYNkcs5z4j2qHvxU=" + } + ], + "outputs": [ + { + "cmu": "LJ/5HzBk5sZBsmjtWpR500PMv/lmIGZ8vT3dyAs2FjI=", + "epk": "xkuB6+Pj8ONST93dniRBjYmpwWYrv3nFSs3awsU8tG4=", + "ciphertext": "RcJ8E4fkl46aJ2cIo7/t1UsMifXAddL8y9fVLLPTZGjjGBMeyts6Mz1pazGN2J+8pkQeFQ==" + }, + { + "cmu": "ZIZ0lcv9THtd41M/Th0HllDi8qtDTbT4tQb6bmk0XEY=", + "epk": "S+gA2fo7rPaJcDKqi1095TO0ZIM7lyguGqyH7AE5pWg=", + "ciphertext": "d2zE6M10bHDcrRMpGIcpk7rSfvBZvqISK2Aqf+4WIV2h9iw0jfgTQI3MdUvcNxarCwb6tA==" + }, + { + "cmu": "1xN4yO5igYa1aJ3zNRiIXADypQTJFeKGkaRSoQItqS0=", + "epk": "GQFXy8B1B0aS1NPI55C/gaOdmmXCNGiTnW0P0ARpL7c=", + "ciphertext": "GjJ3of/WEBQT8MVqyD7XF2jz9NTKd1qqh2YabH8HiVY9dg9F8iJzMYeaGv62dqqSvQb9oQ==" + }, + { + "cmu": "1FI1/COk7abmWBs/ErWVsE1UuWFXmPbIJMpPICO8ZF0=", + "epk": "njMgZJEeBU+QAQkc7BFhiDX66v6BWa/Zz1NOOSphB0w=", + "ciphertext": "g+zAGJ8Es+xYQr6Q1vNg3e6KMK6/fIXkP2rn9RcXZy19xF3Pl4d1fBfavAKu7i/MtRyROQ==" + }, + { + "cmu": "Y5sgD/XIaDJ/lQLVBU3ginywoaFxnFAaLbPIGQZt8gE=", + "epk": "fUHlOP7Ds1R8Wsjq7MpnkGXnP74w/YXScgnjHkI+DpU=", + "ciphertext": "s7zgeGus3/HavL0V0wItbTeelRKUFeg1NnzvxGGoz7nPCuItMGqT2Uk2UF/Rl8wdR3/agw==" + }, + { + "cmu": "ru60W6XpHQbKmXbqD+7yzttiHhL7/EuToC992skkDRo=", + "epk": "LUK02ekC244j5oXRZPo5nxMS2heI3acfhSbTl4UtaEY=", + "ciphertext": "cXloNpovvqVcq4YEuAryxWVkpbEMnUQiDFZNue3AmWy1wnmku4xlk8cZAdwifn4GIIbgzg==" + }, + { + "cmu": "pkhdU2EOYZfE5FlaffGFQ7XKiR6NtFpr1DeTwwhHA14=", + "epk": "MHAX82JL0k5ljPveZ7Cii0T+7EUtQO3FjMf+90o57cU=", + "ciphertext": "cj9ITzlLjhHMVsEtlEpGIgbxMlwa8TuOuhl78ZVoF9FH7vFECIhVqdEn6U5rDWydtWyjmQ==" + }, + { + "cmu": "Jk5WM80xSpBiTxqDuhcRTCTUwp/rXWadcKM76FGiIxg=", + "epk": "a2KLEygAqvixbmNoNSTvvZKR7HFMI2lp6DGskA0FB8I=", + "ciphertext": "2ue0XAJz116zUuAocbLPOXfdtwVql0dHCOqyr0BUd4jnmiUhlvRYbcUvC7hz79+4OzLLMw==" + }, + { + "cmu": "eszLmjSDMxxGxUFQyuGV7BODRx3IvCaAM6AyBhDJtFI=", + "epk": "aa8E2swb7NPJ1k4PKdSdLYrlG1HOc9N5jr22hyjaOYk=", + "ciphertext": "Ja2mj5ZQFMpuxarjDbUR0RIEWxmLKsbjUY37TkI3vySn0/nOf64OjceKGFbO8vE9PNhEyg==" + }, + { + "cmu": "5gpXntlcukPYyeSsJPYRtHF+GPOXC0FOyi1IM2VbxzA=", + "epk": "QDCVhHILSepICmrUqp00//iDi71drFewrVEhEG3GYmo=", + "ciphertext": "Xs6mW0f8pYA77wZ0Rof4w1HsJlhptiKbG5zd3/47gncXCp8PQh/Q8q+IxOEgUlXoLT4dLw==" + }, + { + "cmu": "AnJa+NHK7DnDGd+5x57uJYEVc7PXqssn8HVWLf8iCDY=", + "epk": "bL/QsUNfvFXuWgj2IfV3VVOMqDbrVPwlq0R8XBc9Lsg=", + "ciphertext": "FCKJv+zW2as07p5wABZmtkRIOqihriGhnDp8KRLXNqdIXMYNrheo66eM1JOm+cjGGXjtyw==" + }, + { + "cmu": "8gaiKJ9SZZ3oUoFX1x9aYgRClDmZP4+3BpT9dF6VOjg=", + "epk": "ny8e8URwt2Ry+pzbKyZGJwzUi0AtvNf9YRtIrzpOcM0=", + "ciphertext": "o5kyxpW0ZBTo/uZ9Mv8gAhwP4ctjADm98PS0Cu+vOzmfA8oRP465P6Cd+ajEF5TYzILEcA==" + }, + { + "cmu": "xx2b5mi2dD2IKOX0z2bcOPNP1O7H2cGZAVe076VxeU0=", + "epk": "2mjWG0ZLfSYUAW8/sKNIbThoUxu/3SFNoo4Lr09EREA=", + "ciphertext": "MKlhG0TtfSyveh4QLlALxqKAVmfdnXClBVmscLjGBrGvcalYMNLPeDHtZeQevIgia4/aXw==" + }, + { + "cmu": "JP5giQTSjVYGdw9hUhJFSTgQBFoP7pVkqstmiXaZiEg=", + "epk": "ZwS+JMAU/JzhQ/6HP1leDnvsQr/PebWL3NRD24CFK20=", + "ciphertext": "9o2/GSmWYwoL3LG5/Sosyx0ZyouIZEI0Kb7Koo9xSIxRh4ubeNnh/EtqL+2ksHTnUwXCTA==" + }, + { + "cmu": "euJGEH5ChG9KY0V4YHobOcdcfoBpbHrpPvtiyaBju0o=", + "epk": "KXKzVl5Y7Yv5MWQ/SlPDQVCe+rka/s/fryjb7Hk3T2M=", + "ciphertext": "h3Uc7H5j8tHDAy84k5/fnmn+NTmjX+HTv7kCOk99+nxBvJZR6uJMTftaPj5KtnOMmZFG7w==" + }, + { + "cmu": "uIxcUm8+wgr1NT+9NZIjV4XWemfM7XzDJrQ9aQucDAQ=", + "epk": "ntP0wJ3gGtG9H+9sQMWJMp5LQsif/GILc1l3Rui/wJk=", + "ciphertext": "Vz207jdUKIXo6gVy73hx/V36yGPGQvUHmEbyAhLtjZsxg+DR7AKyWB7X1aOLb4GZ8V0L3Q==" + }, + { + "cmu": "V0zG/JtTdsDN3++1BWOyY9+Z7nWAggwfxCsiJ1rYDms=", + "epk": "ilCNor5M3zzrd6/foBlKfipK90J1EzfUZ2a9PRBRyIc=", + "ciphertext": "AbeKK21MXVM7ohVPHuyFvGHSHT0AVUlm0ZwXAoNY4Uqvt2p2ndxkJcihDl4OvXV0clacpw==" + }, + { + "cmu": "zRLyHbsA/GZTE0xjYTJoJNyz6KplqI+B+ftkarIRwwU=", + "epk": "N4Xn0oPAeY+T6VBjFYW2ER99AShkmaGNT6zghUrdTLQ=", + "ciphertext": "U6Gl8gk5Bd/9OYR8cyeRAS0z5diTEt7gC+LtwHbeiAACaqsazkEvU+SBGn32/i3k53oGRg==" + }, + { + "cmu": "UQ7J1m2taWBAML8tKNQ+Tdez6SAg9WYNlKrf+W0ZdS8=", + "epk": "rtNQWbKh13+hMaqmVA0M3uylvnPcjGEYHxO0rJ7XUVM=", + "ciphertext": "O/5eLKf41Yajm5HySqi5xm4muwokZozf+/PJCghkePOJ1V9ng0XTEOqDgiAky6Sd/hnf4Q==" + }, + { + "cmu": "cSrg7WX0+flyZs1Z/9r1FFPsonjCfpsq490Xu1/x+yQ=", + "epk": "uhDvFUVe02al8TL5FIGF0sUcBBeJGkJR1O+TFpxYlq8=", + "ciphertext": "7XyFgyHN9iOVknxOGmXNP3AYbynKjvlnDqTXGppFT257PFVDmZPYg3XDKrwXbm0UH71gdw==" + }, + { + "cmu": "CfNtuMPZ2pEMEYdRT83AuhMDE9n20LwbslXHS19s9xM=", + "epk": "56jiIl0Js+fCK310tkWH4ku8K70koe0XAWmPIwfpA8E=", + "ciphertext": "dm5WIl7O+AtosQqPB2xH/XMZqGvYgPGUZAuDj7BOtfaLaXQJtO+E4QG9pT85rf6a3KITMQ==" + }, + { + "cmu": "y4xVmp/nTmnPtVFzikE+UaATm372YI1n8RZceEpjwg8=", + "epk": "MRHWQE8jllyzXcQMMLckCsck9okzhW4KC+cTLQMGauM=", + "ciphertext": "hVl7Hove2dGkZ+vlGVhIwas1vHY0Fu2wl/bvJry7Mg8YhiSc34IxgBHl8d40GGqQpfstRA==" + }, + { + "cmu": "nqX2tgwj+LRR833x9YUkdjyDIU0fCZaD8WHbCjwIO24=", + "epk": "VqmTbUXLj2wRbkRQd9pF+urYOVK6hkRMyObia9dE/+4=", + "ciphertext": "B37w281SyVbemGXaaimwHoXKUBtK/41SqlI4a3O0jFBoYy/Oag8tliP9zKNKFU0CGYZANQ==" + }, + { + "cmu": "ciDVzw437dWtJ5e0ULReiwTCiiJs0ZbePNps0FZwNxk=", + "epk": "lEsTiTr0Oogyr5Znsi2vXCIxVn0ZASTR9jRsPRiXP0o=", + "ciphertext": "yYEEUEXRgeoDHS+q8jm7AsSEhFq52zS3oxU/QUqHHbhIR7mmz7WB/AzesC0PCgCefu6JFQ==" + }, + { + "cmu": "+ICeTfC9k9ZgYkH68Ogsa1bD+/B+ka5y0a6AE4lEOBQ=", + "epk": "sMWDHo+7qX+58KsqjtaLC7WotrryCFx9x3Mm3V0qBHA=", + "ciphertext": "mh7vI/uFRJBrmbIJEu7P6PpC7h0DM0waqFUSM7QycSyNWrGDSy0ds12kdwl7r+V/sGfL4A==" + }, + { + "cmu": "/NIG+LPWzz6UJBncIgmT83lImbMk3syBxS09j7CSlk8=", + "epk": "AfP9AZUayLZUkuP9mr5FJBfl9Z8EhpmmgOeG8BoT7do=", + "ciphertext": "+2FXH9zTU8CwMkSdWxnnxF9q/q+uNIM+MbHNgzIQtM9HrNgLp81fDcwZon/EYF5fweJ0UA==" + }, + { + "cmu": "nenr4IiOPGEucuEopElNXfcJ4musEVichzIPGuS+tBM=", + "epk": "u4h9T8cs+Uq6cUR/LMQh3llKWYEYLgRV7IDOhXNTzTU=", + "ciphertext": "q3J+JOluaLb+RkRSTeX277x/9FvJqciiMgMP8Jtioa7yuBehaCgquEe2RAn2mhpBl10QSw==" + }, + { + "cmu": "mGsSx85k/8+PnkEyQQ1FIOlO+JJIUHlYMI7LFVjcRTg=", + "epk": "iINfJcwcHGjvoTJFCTodOaWsb3J3/Pvo7BZ3nKfTnNc=", + "ciphertext": "ioGmUR98KhBuzmocMh51t6XLCWMpXwZRWLKgeF91Q/KddBaGWCeY5/slep0x5EcbXkdyRA==" + }, + { + "cmu": "pKfREd/cIEe2e+XvwmnawvvekCXaizX6wirCvKijeHE=", + "epk": "dKGoPbB4tbTKGuRsqp4+fIXJ69OjsSfckQ8vAzlK7IA=", + "ciphertext": "ucvO4LBW+1NspKzgTnk3/65yXKW1aEgJnNRfLvZkheyZAUxqWtw41GUk18t5dMxkyybD+w==" + }, + { + "cmu": "mdwmyOiAd26a4rWo2pbyippGtr7RWOjcErN/Mh2pPzY=", + "epk": "VvL7CjnpGUsaN6dBsdqek7ckoO6BXeh6EycvlkoJWOM=", + "ciphertext": "S4l1cN5BpKTC/xtsPwtyIfV2suIuZXYJB5HSFslxA2CS02JJvlU0z8mXBa4sG+k9FbeVYQ==" + }, + { + "cmu": "ybO9VAtNQ0fMMLYUZ0NRHUM5Gac6z599ZM2Ua26ElUU=", + "epk": "WK2HGqToPzhV99VFh27AHckDY2iterI3wZHxVoF07Vs=", + "ciphertext": "7JNy+1zb+Es8TtkzSFrqVGDw9UV5FdODR1IJg6uR/wr2hbznsYX0a4Ww/uwDMqK3srtJlw==" + }, + { + "cmu": "tgpEV3tfzVv5Nh1VnlRuSSstnm60O4YZcAo1EClZ20I=", + "epk": "e5TBcjPjHb/p5P+61B+Df8U1K5/YiQ7H2JKr3VpABec=", + "ciphertext": "yc5poZ98MQKBnXb+sxjuoh94VnstOZvEMP7aG07l2mlkj5PXKhLk/YVWcJWDFOxOFu11zg==" + }, + { + "cmu": "qobTfM85NXOME4lmyZOVAq7q1JmGXzFLOPjRBLw+u2U=", + "epk": "j93igjmURbMkyJtBG7r+ZhsmAziB3Rkq7qQtZkEHfBs=", + "ciphertext": "zxzboPZKOcje5UFfts+rO+GncXTL1y2vCD87EYhz6z+5YKrxmdaanfYAaz9hjSlCs3dLAQ==" + }, + { + "cmu": "m+cNzx5h9GtPyTPwQNQzQhYMkXwHZktYV76GjwsgCjw=", + "epk": "kjQavP0eJK3Z2cuBHLaeJR5wnmGYTzxcNc8qk7y7LlA=", + "ciphertext": "reVWloacfqH+hH00sFDFz1FJstkSmE2KxHrROUUWAqApbVUGovghKKReqf9mx9haxz+wTQ==" + }, + { + "cmu": "Yc21n6jmJ0WRv5dF4LejrUZe47P/82ZOu427y4zl4zM=", + "epk": "sUWWYCncxOqXqjI1/UP8AMIqp3NKItTlYTj0+3kgS+A=", + "ciphertext": "OFdRC6nTj2973NjkfMAK/0NLf95AhfBGCond3DcOxurFWLwESFHSia0/OES2vQEbkYN0mA==" + }, + { + "cmu": "08AuAd8Fx/KOi+6LVRJtN079J7PF9NvY54AkIx2E9Vs=", + "epk": "/ws59g01eZHDYg6ua7cNtE8MgwuIpYgSICWJzv4A1lQ=", + "ciphertext": "tZ1di4adhTnx3196RpN7TYm0kZx7P8wE/qg0bi6Sg6/luj3wQdGhvhnVVdI57AJFTSgnHw==" + }, + { + "cmu": "lWdiW5HON1Qh3ZgEx/l+H6qKG7iJPpF4snYvd/CDZw0=", + "epk": "fEI3fUtICJIHJp49B1VHrLRTf1HPW79m9Mpk9VwEmvA=", + "ciphertext": "/I+isDRhRALIlKG7UCn5tjMNFuFvJDK2t1+ehV1LLd0r1nhDRN3zLDsY7OKbm9zT7c7Q+w==" + }, + { + "cmu": "zYhv6bdqrYTnRU1kNWHgLePfVSHqTzvhbZa0KHZ0Nk0=", + "epk": "2Fdq0RWwt8NLugUKJWoD4gQ04p46yniYyPH3x75CDTI=", + "ciphertext": "uhO7/1PFOOerwyk4gD6SksdCk7ZkFfQ0CdKRv9iTM1D2bT//2HcxYFRabGpBNk1J9zUHWQ==" + }, + { + "cmu": "WfYkYKne8y2deFBsOkxPRyf6O+yf3+h9tZPpXkwQilw=", + "epk": "h+0/bjcyBo/YxfJ5g7LM1Ay3Di95eqS4rAjMHmdj6kw=", + "ciphertext": "KaNO8jNBFKGBEUj0g3N4Vjfs7lQUIG/ePmxeQZE+rh63n0JHXoQE/oR35lrBR0PfBVv20g==" + }, + { + "cmu": "LID3EYRD3jBMmnbYyzSOPxJOpUzPWdYNtY5FhxtiJUs=", + "epk": "fd8ohgie1NHD88tszV45c63w4v7vEcJlYQPl9+9Wc5Q=", + "ciphertext": "By+ISsdIX7/mPEfJVWzxoNHltv78dgjbxhd3vS44IXEv28UNTrvaoRvOaeOCf4t4KriUXQ==" + }, + { + "cmu": "dTo4DSQxONQ1cXpnVUBMJLzruT7hLm/nGlpO0QRXV18=", + "epk": "K0AAO+YhmRjUj0ZPPaXsXT0Mj+koQMPL91m5VU1WPGg=", + "ciphertext": "FSoUWa5mPBYaXHMtWEaNcNOHiz8C+cVvn54FTijAiePk/UtbvawA9VceETb1gG309/aCyg==" + }, + { + "cmu": "NcuFQk5MfPiLYCQ2+h8c1ZMM0/Yx4Ds0Q+lRUFK9X0g=", + "epk": "sdUuwCUyZ9Vjr3ZVYQT4cOZA9yyc3zuDHF41xHwptLo=", + "ciphertext": "iBGTWW9QsymmYcugxl9IAocHteM7hnrTy/eTZ5A1dTh2wNOp+wUHqBQ/RZjsCuHMUSgU0g==" + }, + { + "cmu": "DCxwpC2J/VeOmyWpJzHGtVlJp5q/3vm+Lyv7hMFnE2U=", + "epk": "r7T66nAQdPnRLf+qFWfNdQglrILkrq588mj5j9RM6x4=", + "ciphertext": "40x/WEnfyM04xUlLFLicJmzQ2KzZwfk03WWEhDpz/U/KUG8sOW8lGTiL7s4t8q9NLr8NBQ==" + }, + { + "cmu": "EHvDKrFeTMTJ12Au1JAVGxwUd/VdqInYqFzL2qaj3CU=", + "epk": "dge2XJSeg3Pt6jv50jD4OylqwJAqZ8qWLGWYhJ3qSbw=", + "ciphertext": "2t+cXOClQg6TvBRHxb9l+K0PBmOfEH5Yj3EQyPN6hTy/7t5h63opteRNhobXWwdF3vke6g==" + }, + { + "cmu": "Agp4nAE7Mg9/ezQr2iKjYmQAbLouKG/jvd3rYRePe0s=", + "epk": "8pmWiabq3UT2RcQ++eXQ6mx5Q1LCpUiufiKHiF8j4sw=", + "ciphertext": "4Xixchd1Phh+IBx3xvNkkX87C0spCc9rKUtWzdVk/nbH1KFuTYXS6XPIU/1+fI07GnaMbg==" + }, + { + "cmu": "aJYATL2j4Ju0dYCILIUNuOUQQiruMK7eH5J9pQizcg8=", + "epk": "zhnh0S+WAWAoi86i3xS/UdrmBv9zBr3gur/CmRR5szU=", + "ciphertext": "en2oNCrGO3F/hSOg5iioOxkfmt8TKRmkdgclRPaB8mJS8hPq2B4PU59HzVaZrmHSbngxlg==" + }, + { + "cmu": "bcoLBEjUceI3Cm+bFaer1Hw5107BOCg/ymJUJLVJQWY=", + "epk": "i8/5nrhniXpWJ6TNhPm1amyc+StoMyXxaKdRmnNYOMI=", + "ciphertext": "eJdrRE0tW4oWhjTC1cS5siSVb/FIDYF9OL87CKu0gVCbzPKeYfoiPQrqmbOoengHCht0bQ==" + }, + { + "cmu": "a8zBdz4GMNBy4NVk55HMhnDpEUAiTYbyNzVHBOieMwg=", + "epk": "RWKGA5wkJrDmFou+JkBlqe++1K6BEf94JstoGG0/mRc=", + "ciphertext": "iRjoTrXefQB5vEy4rGSUi9zhO9hYOZR7P5WVShTh1WaRGdtrujc7MpblG8gFpMxDxbn5vQ==" + }, + { + "cmu": "sKONbtyc+Atnjid0QVB8vWmkV4T3ICu2WSqGgL3Rajw=", + "epk": "juh0DFL7bWSaYIwEGwvQGLquj/u9RPBxRsPPsL7x8lg=", + "ciphertext": "mGOPMPE2xrOnmIBFUht3d/heHOfbPsIppj3opS14VgaR47gVk4IbqWALLO3HXU1/gYHl2g==" + }, + { + "cmu": "zmN3ILuwqTb2srOCszW4KIJnSpOzbJsv/j2piUGj7B4=", + "epk": "wGEtobse5EnriHiCq0DkJQxJCN8cAfJW0HHCYTB32mI=", + "ciphertext": "Xdk/xGTzrJ4umxH9abaTmQtxHst/52/9ShbwIt+oUJf/WkMZT1h+yHTefsTADv6k66AKZQ==" + }, + { + "cmu": "O7GP+rG4y/OXbXiYKcXGg5z0d8QYl/BBFddKkLxta1U=", + "epk": "wB4COr8bnxZjj2MngyVzeifWdxyGBDrS7NwOhnvw9Ss=", + "ciphertext": "0+IYJZRlFjhMJ5by6rgC6RmWKD9qheocRPlkuHMI6sC/ygpy2Ypvrpvrz9DPLrxOlTvOlw==" + }, + { + "cmu": "2Hhih4aNMQvfk0VO/UBCs61g9l2CrnSoBU7TxYNRQkQ=", + "epk": "5KXq/IjDCvCCx8RGcDwo52clIdtkvs1nie2rMC5ScGA=", + "ciphertext": "uacBroSfYCBB4r4f4wf5/1RgvJ9aL/F9DQXThya0WTCQFbTnH4ep+zbUNXkj7G/ZeSUagA==" + }, + { + "cmu": "bppcD3dNPj9a097hokwsNTv16QVH6nwdi2KPYtdQEQg=", + "epk": "oBpQMdAyIP9uCZwT3SBl9HzQLkk796k8Dyq9dYn1+WA=", + "ciphertext": "2nNpbgZOb8zZ7I8ECNnLVeV67SU0HHHXgrPDx5c0HwXk97fUn3YfvDXuoQvXtq02te3+ug==" + }, + { + "cmu": "+1Mzr+OeTI8FZJ+7CqvtpMpv6X91WZKG8Jg5rixjPhk=", + "epk": "UU7OpORAmHUQ5rPzb3GC8qGlozFn3yyhFz7iX5IIyLU=", + "ciphertext": "EdfJ+KpqbQ5yLbaTh9NE6O3HLAfFzEziwiA1i7PLIKplzPnoE16XM8DLnqMat9p1UObN6w==" + }, + { + "cmu": "k9F0hWvehpqopnSe/s37JqhmoUWr2KnKAMkPoa1kYkg=", + "epk": "czr89a95nYgBr8MeNuLsh1NHNBADnNUaxeYJnF3XzEQ=", + "ciphertext": "iQyNss36DvAlhpIa6FhNAUWKtQZmqAZN6BmGJUaSBqtXiU5QP3WDMdkgbXcDxWy5H74MKw==" + }, + { + "cmu": "dr7MKy8iEC3fY7rrw6RUNgNxRzDWeUb8R1d+8PtFekE=", + "epk": "50OwKMDFN2ISRMCY9oI4MtWGaZGzsAdz0osUgcsAdNo=", + "ciphertext": "FYeiPJTTWdslHd0Y8ie4kOP+rqxjTJtRAJ60g7GpNrxlZcVELm73nShA+5RX4DUAaHfVgg==" + }, + { + "cmu": "LPye0pf7nWU2PKgntsrlWVC22jK9Ta+G4qOetvo7mEU=", + "epk": "xZ/ZWUP9IDtXOA9LqcuKP/5AHpKkhg3wko2PzW9MhNg=", + "ciphertext": "H7L4kBd9V3IjWc4xHyqj7mQkZAzR4LTeXS42BCm6sIXxsMEfrn4BAVAaB/M2My9o0+GWkQ==" + }, + { + "cmu": "WKBik6UEs+4cjAxXdPFCQ02ohOMDsjlgHjCRIbWANSE=", + "epk": "V2xWV9raU2DwLwKpQEUlzSxSkCZq+LzSdxk28LfZNUw=", + "ciphertext": "TF2CwtFc5DdUKWQI4DXyppYUkRbVtO8ZWHT0ETc17UTiwWd43SLMxZ3cfIMYdcTIkYdjLg==" + }, + { + "cmu": "0J0aa8cWGQkXNLTZtHIoKuX2TTYmnabSTxJOpUNz1DM=", + "epk": "GWGqCPpCvq4qurxbX4TPvzwVG5GtYc0jjhJODpBOU+g=", + "ciphertext": "Xvabxm7FJm1s3wqOuAggasO2muETLOHEG7YqhdTn3gjwbxEPBpvlL8OccLkkSF2NEP3LRg==" + }, + { + "cmu": "X4Sl3mqrEySA9+Oqo2s72/ydXJLq+5HnMICkuFiOMXM=", + "epk": "r7ySTxp9hkFwWYs8yCFqEow84eaJr0U+kt8x/M7ghiQ=", + "ciphertext": "tk6gDDoM6dOOgZxH02SL5PxUikTLW7e9u7J3+35qcckwypN+NcBii9Luog/sERSTTtf52g==" + }, + { + "cmu": "fi/BSAfWow0yrO6BcnGTcmQkVa6FEnYS/p+dLvq9lhs=", + "epk": "S6Ll3GaRYf4UEJhTmfo2zhBhwprTN+p0iLDcP1bETbI=", + "ciphertext": "5yvlvJzzAoEpvL0sLq+t7xEQwPYasgHP8hvGus1Dgi6gN4xSiJ9QyqnbQ8tSdpN1B+6Lpg==" + }, + { + "cmu": "iD6EdWH8c86QvjHpzwO1WF4E5Tmis7k7i+LvA8hUyUo=", + "epk": "uwlzC+VbFZjuNbkjW/iPJi14lkl7dj3+VkDoSUmjYI4=", + "ciphertext": "nqh7o6CaPceIxTT03v0zc5tbh7KQnwDVZvOKYwAkFNoVH37k/m1ZA3rGV41BE52hS/fwZg==" + }, + { + "cmu": "kzrtzL1rCHX+7R2fYQL9mm3TR6D26WTUYvVUKG52W0U=", + "epk": "3i2QyTupDiCzSYHmgvZ5mk39pW57JRQnXNqQllveYt0=", + "ciphertext": "MifcPyFiQJPG5/TrzE6oqLPY4iyBegxxp+QU9OPcJCDik9k9wD+VFf2rBCnSPQwLF24FRA==" + }, + { + "cmu": "hAJGq5jcq3ay0WMLrFdFcrEZkH3G6BH8QiR0c6enCyo=", + "epk": "tsiZEP58TanIpSm6i+mzosiTNWiGdEhKt0qcUYgQut8=", + "ciphertext": "Gi6GMIZClFHqGas3TrAaNtJBxh7OBkykYYAKAk/aYhKkUhggoQd49kcgqfpCeK3APFcFgA==" + }, + { + "cmu": "aoR3ialVPTT2lE65QCho1vVCa3IVQZW+0HAFfNyoHDs=", + "epk": "OyAH4195MpnpUC6ecPgcUAGzubkTR4Q2jZAiCKYspVo=", + "ciphertext": "5weKfqB6wWwdUP7r6geGcIKGxHzfZbjXP1IaHNgYnZqFY7DVxnPcAR1RGlDTxxQwFF92zg==" + }, + { + "cmu": "iybknxb4GI/CmvSSgAXR6S5/BD0d4LhrTn2DUyGTRQg=", + "epk": "UCxERqczUYG1mep1+oZYphLNnm7rBLfeh4d0cGHRnqs=", + "ciphertext": "1HQPIyzrXPf3PzyxgOZtH2im5Iy0VavoIP9SqZ/1A+cUKY+HGglus676RRGH/c1CQKcZWw==" + }, + { + "cmu": "WRTispaA8oqrYfiNQEHFLF93dwpRpT1PgBmY5+tSgyg=", + "epk": "QxP4ReMuGTrjU0BjGVk4iqZTDhHzo8WnA4ADlSSwAms=", + "ciphertext": "/yglGFlXBDdJNS6VFc/TQP4O1uCjkAnITKxlkPVM8WI4omUYhOg1n71p/EMBZ9xOZ+VCiA==" + }, + { + "cmu": "Yj/7gYPbl7CHThSYol6k86jVuve3Kzszi3xCdZP+onM=", + "epk": "XC+6pJd5Tcd0mXN9q6+xsXPHKgVOe5wgX9+KeUKV7zA=", + "ciphertext": "90KZkHateyEdY65su8QKT3PqWoSYK63Q2xVOXDgF8QPKrHAlJB40Kr6nrODDUryjMxab8w==" + }, + { + "cmu": "Z+ZRT+ZYmfJKtAyy/5BinbDEZs3E4SmX6sDjemQ0URA=", + "epk": "NtrERRagKUxyPGVxxdxYKaKbO6r8RwJgqCzjK15fPcU=", + "ciphertext": "yx6/XZ/HCqECKV4CABio2i/C0HU6/RZdzI+AHBYj093mnP78UwfeFwqwXKHpVyO+yAwt5w==" + }, + { + "cmu": "Xs/CQ9ICFOQYI4o5Z9Au6hupiBFpgPpap8+kLOBd4FM=", + "epk": "EigklgcWAnb05PnnEFsvwtSVgH2rM58WlQeVi5TgqFI=", + "ciphertext": "/ANSn2zbmFGbzcp3qfOK6mb+LtEz4PSgspohwNgbnaVlNJn2DpXCehHS0Ey1uuJMnbhk+Q==" + }, + { + "cmu": "DhqIfFBQLV5XGPtlOGFwmL1J9rUKFYVNPAVMl6y0yyk=", + "epk": "f0w8Z5GLH6rwXdM9tMJvlf62jc6MjpkdKCOqdOVq8Rs=", + "ciphertext": "nA1WIH9i2EkQYMsvE7E64kIW9kKP1A2Ympsq70PRdD8sD7XKYt40LM6r2xbw7Mr+uSso4A==" + }, + { + "cmu": "veT59GDPSwe8Inxm5qFhidTlq9FSjkHNaQqUAyx1sHE=", + "epk": "T4h1KYMsmVY52hmqnE6dgUPY9x5xH54TBLaqbRkNrWo=", + "ciphertext": "5dbRHX05/XEBkYOkaMmfZzCmSPvd45aKbGc+YWkIrxdbM2ym/NSQfKgbcglmiO+8jVEV7g==" + }, + { + "cmu": "Ce10NVoZYB7rquCjkETgPEGvfdh7kWF7WHuBX8/SEBo=", + "epk": "7azPvfWmI6weYdaatlqYWxNlm/IT40VwVna/EFhAZdA=", + "ciphertext": "HCcnHYlZY65aqEJlJYz6yvFiYX5eau+K1usTauflcU0jekqwql3Wte98erv9DVJ5ReuVhQ==" + }, + { + "cmu": "47cJjD69jz/8f8t+5d423AJs0i+T3ku0/1fyj14QxDg=", + "epk": "UctkY6zHBORn4dROZzKC5zhC7rJpDG6aRyjK13GRVeA=", + "ciphertext": "stb1zYVetPn54LxtVMVBL7QRWazPbYq8dfN2Q4+KsX8xA3W9gG7Ja6X1oAv+TRkBauqMxA==" + }, + { + "cmu": "Q6G0JepExM7L5kfQ4ErWJdQ4h667ObPU4nzhd/WYvFQ=", + "epk": "lr9827KsEfJWRipzTNPCBMr3H+1Rucy2+Dz27O8njOo=", + "ciphertext": "TrGlHNtiPaCrXyM5Q9RHpbud84tIdw6QkqRsntnQQJn/umFNEUJ3cPzYWgjpO06g4FD7Rg==" + }, + { + "cmu": "YCebZQXYJSUUOKaQ1F4e3KgvIJrCwrtGP5uRf0d8HlI=", + "epk": "5aRj8ahnbCR69cKlBCW5k/GUsM386t5C6Ch8/5q3iKg=", + "ciphertext": "r+5nJIrG8j85ebzYV14+FXW/72IM053ror9IcoqnnnqX3nW5odUlW21PobvjF2Hc23RDSQ==" + }, + { + "cmu": "TVaCUq+tTa/WATw1u5Rd0kRGIsKy0xoLK7X7LaUH1Us=", + "epk": "dBd5WWu7MTcDuaCsUTXbdP9Nf6oSt16RL0UiJHbPCZw=", + "ciphertext": "W3nT4BJlfQYl9z7TsWs7kfulNlovL05EtXYgWa2xTHONGMAIKr/54t4EEfhlT3T4wrAjbA==" + }, + { + "cmu": "wTnXl3ydNulH/fTupRqz3ibJfxlEPhfa5mtfd3IgOQA=", + "epk": "Q+/fVmXWL4VYCQ4/9DLGO7uAWjEzPbGugGYMvgkPyVg=", + "ciphertext": "HB2HoudkChl/u1iJVrqtiKEtqGV3Iq48NMDNWei38GLU0NDA9VT4mZ/wBRs55yuuh90oGA==" + }, + { + "cmu": "lgE2UcYB3cyzD0I6F+7y5weLTVsjYHPm99AgiI/jjAk=", + "epk": "b1J4choZjSb7t4vC65utVZH1Gh2srVL9IT8vZBUJmhI=", + "ciphertext": "fMLARCzgqz1thCKOXq5cHWVFlv/6wxiWj5K9FAmhd+FNPvG4oBwhaRVqryLwC5TmQWOJRg==" + }, + { + "cmu": "NXdwLatAw52zDpg3EiZtotPBIxjRrbMRwEgQ9uakNFk=", + "epk": "Shv0KNYfwY+62I4DwwzFuZ3IDIt8EZdMpF/ESLZoMtI=", + "ciphertext": "HIOZrilRhxNIQsUVQvXg0lNBXGggWN1F2JQWB8wWUQcwBWVP3lgwMBIzj8SOjPsoV797wA==" + }, + { + "cmu": "5AripzkeLIyHUeMAK323TBP9PGiqc40FP3gXsnaDuQM=", + "epk": "i/IZB3y4f61fBDUe1uWfFGJ3lcRPbfKe6rA/8MG1MBE=", + "ciphertext": "XUCtpRPD58d0p8lSdW1teCT8/ByqQOqKo1jDzRdz4f8bR8K+ZKoO/x8A0TPX0k5eZXs0bQ==" + }, + { + "cmu": "SKiKZKkexE2SsEFG/XeOCed/WApHpcTHEX/IIojbtFg=", + "epk": "bfoLBUxa5jhfXxplau1GUXirDQtE6eWaFczuMW9k8c0=", + "ciphertext": "JtH4nNgyaWj6Og/Z/vP9mgPYUhurzUz0rb2iId7SaLbH+l+l6UZreRsdQWZj48mf/ubr2g==" + }, + { + "cmu": "feBqUc1cmNDJ7607Nwz0oRSAXf6/Bt42eneL7RU6iWs=", + "epk": "5joexaZ2ehY1AccIo9EdOYLLKYMC5s/6y8I9p/+Xnpc=", + "ciphertext": "IOwQZm/EC2XTUxtFslK8OkiMTC0Xc77piCWlSG0Vr3E1/+6zZeBQmeVY8PoAemv+UQgX8w==" + }, + { + "cmu": "QLHBWeJXmXMK6PdVogp8gEnTDEp9CDBIaWnmHyZQPFo=", + "epk": "R5nxjFNjutGzKCYi/l/SAhqFe84Pf3TxKx5g16BRb5c=", + "ciphertext": "YbQTCmoLigmF/TBW90EXHVp+coB80Ri8laaSAkj+zpWOC/P5Wij3l3ya0jlPKKCUM6d1Xg==" + }, + { + "cmu": "JEpkCHl6vE+qDUPTa7/W+9pxhc+pUjrzz8sALFSF4GM=", + "epk": "GCp7E7hViSXjIF+m3mJMrkN3m6iMewY+K+ziRTkBYnE=", + "ciphertext": "3r4To6pzOdqK1XNCDSrTCFAGLrgtKO6cucSPtRzpzl2dkF4/hpdQBKUsCCr82LwXNhPwyw==" + }, + { + "cmu": "zEEdWGelsWQjAkia4pzBUFVDO+ljA+esD37EJowVqAw=", + "epk": "BRkgo68E2twpX97y7MlSTFKtGvI2IXExGviBAV9Skeg=", + "ciphertext": "n25VnI38BzdUsk1OQNBIIfTouH18vw+ip5EI9P4JSIVgpgF7++PzHA+ITJEVk13VwGfQGg==" + }, + { + "cmu": "GvzSh/a+oi1E1KK402GZkFs+qS+OHxzc4oTpANn2cGs=", + "epk": "9MvpMQhya1RBuZ7GpYmxB2DUfy5Rp8sO/aZbD18ULk8=", + "ciphertext": "2tUYtgqguHFxBzXtiiEqNcx92l887iyzmK0ug3wE883fczjKROTY6i8schp//wtYNjLZPQ==" + }, + { + "cmu": "EXonLJpoM6c3u0JQbVmNE7cD4i9AwYljSLUpSOxNlTI=", + "epk": "trsAif02JzSjzGuKNzhnEdaQKU4tNlsXFsUk/V9/wNM=", + "ciphertext": "2856Fy3lLshdSIToLdKz75z3Ghv7nZozGzKXWy0Z+9EKwChzyEKunj9n234US9bY+hbvoQ==" + }, + { + "cmu": "o4Vpx2MgoKepu+TJ77B3xWWKScwnzvRMWAUtEBLZlg0=", + "epk": "LuUruzKvjJPZr2CsPZMaQ+rehfF56AoqmmKVYdox6Qs=", + "ciphertext": "WxbqVUcCw8GuZm0Mt1nI9PV2qhL11IneV0IQmG2ZPn/50GuqJkastqaUMAl80bi8DOxSrg==" + } + ] + }, + { + "index": "36", + "hash": "A8pMO7ViauRe6A1tVKsoZyPUzTRQI6jLRO51SGjDvXs=", + "spends": [ + { + "nf": "pO76g5zFUl7YvFgsH/HRQ87oN+9zyVYvMLK1vn7BgNg=" + } + ], + "outputs": [ + { + "cmu": "R3kL+w3I6XkqmOSPI1+NjgBF9fwBQoYK5w1jp14mt2I=", + "epk": "WSYzhlD+gYBKW8MnJC1OmvZnkqrjS+28qy8M/5WEjVA=", + "ciphertext": "8W4y9CRkPQZx0SonSpEFQlH2wGNgO+ba9jthJlRX9GqUoZEnrfKaS1DuwZYLIzv7ODnJBA==" + }, + { + "cmu": "EzYq4qRceFoHkwK+0R4Abgk31lDZGrZqISkiPmJCnTU=", + "epk": "ZYd2D0aJFniCJ1Ebw5gXmtRhEAoSHWgIXOJF68NRT2U=", + "ciphertext": "J+Vt5wvRmcnm1XAamaA8Pqld4nHUPvqzO7BtF9zIfqY8sBjGPaobP4Sc0ipFcVWDNa5mhw==" + }, + { + "cmu": "mhmwYYp3V1ERQ/xWGmVsKzdh9MZk/TfkLT5rU5Jp41o=", + "epk": "fISMQgOJUyGl927IRzFLjhnLkHiIvPxT2KX/hk2rBKE=", + "ciphertext": "Kj9tIttrTxk+HkbsU/iBfgd5EP73KUsgP5BwMEvoiEgoEUVb/2EpvHlDLomUWodiEv+9AA==" + }, + { + "cmu": "IVMT2mEkGea9fgo2vnSs1obKU77Q9a3sdz7abX8Vkgg=", + "epk": "kjCiKbvZi1QcW0y8qmtJCH/BMBbIwTyxBynHY0ocDak=", + "ciphertext": "REEpUpZfZeMKh+hvqdITxcr2yfdQ62yToHH7NdeInBnbqzDbb9h9FDtBfAF44i7+4lEUeg==" + }, + { + "cmu": "ToCzZX3EAvcOD6tQUVUGq37xfgG2HBmhjRO/aM2LVWY=", + "epk": "rwVwknS1+6r/kMggSk/BXFoNYOs8AjLLELlIoxexdTQ=", + "ciphertext": "8arC3HgLhmS7dwA97ZVgyiWoWaZJLfZCC33Xr/N2a2Du2c4039FePMwvMf/iCvkK7EUjIQ==" + }, + { + "cmu": "PWwg5z99XTMEe3yoxZovd7+ifIzoyouoX//oVnognyQ=", + "epk": "ZgGrWihcZhiVRekXYPAit0GK3NcdEByozdsy2MWU+oA=", + "ciphertext": "0ad1ApFshTleGt2rkNzqIpjBxs6FK+t6FEm3l/Zq0ilmmeGaJ+0wKS+B3/9aTwXmy+ttQQ==" + }, + { + "cmu": "rL02Dh9WC357s6wUq65Lpeyj7am2ZxXMxTwnxqVAilY=", + "epk": "oJIVNzxydwnIQUMCZgmalswRo9BpHKczGwaXNRommAI=", + "ciphertext": "EJ6+XhL0aH31wyxxb1k9T7auLv4OD8eu10+Dd8Qi82Kcg5wf2CeeNuyW/iwrSULjUNFLYw==" + }, + { + "cmu": "ghcBYzcMmjk/+hznPCLhM8se36E5laoAcuXVTPw4vmQ=", + "epk": "CQaKD/E48amMp6X+p9VqwvvO/3j97lZvXt34EE1B9bg=", + "ciphertext": "pjfBvlAori2YE/qkQXsDifgpkM1/IKcBUfuaa8yOVHo4geeydFRiuLd2Svs3GqCJ/HfNIg==" + }, + { + "cmu": "wTOjmbXLTVelPZjXG/9PDG7sBbtdylkFu6aU+Pu+Gz8=", + "epk": "0Uhe6r337QQR7qnBP3UTdRL9j5sljg2m52jLKqZI4eI=", + "ciphertext": "gF7+DaPbJrzEZBgXho9LWRYr1zlVQE52nNQ5P2nilfKQk92Okq1eOpBskLahZ2iI4T7wiQ==" + }, + { + "cmu": "bpGBvuPSl3xTrxC8fgnv5MzpjfvJGvhC8KLSXcd7WUY=", + "epk": "1aMdxk2zfYt/NWIpE9Msvx50FleJCNGmnliZMKVVfwM=", + "ciphertext": "5jM/ZZU0yfdhyKqn6bgpUrkdyA0tGcEBghsCKu9YX3ocUipywUpIg9JQu0ucnYubU6tgrQ==" + }, + { + "cmu": "B3W8F1B5mSLaOWrZ8QrIO1khqkRZuCEAkX0VHTeXjWQ=", + "epk": "JW/7usNTSubHaan8YkKjl/wV4WxrUhcErMAmA5/hXRU=", + "ciphertext": "sr7wApjc4eQVK8oA0k3faiD53aW7xF/hCl/xkjYCpX6RARE2LHF93QLdHXPBgxryEpS16w==" + }, + { + "cmu": "UR+qAFs3wzvJ4/O4tIEt3QNzgfsZycAo3A1CgwYwkxQ=", + "epk": "cZyRzMQeWESSAaY4LFx/QFhQmWaqAU8xHfJi4zVPK1U=", + "ciphertext": "+6TE9kNkpxIiYduzxx8K5qJX73X55WTZj3H+6icvHQy79NkPAFAywNLC2YY2GixdIVCrMw==" + }, + { + "cmu": "qyDtZb+R2SLP9Xa2BQTQzbuirkZ0uPSYVFGDsyRH/2g=", + "epk": "SsNRnb4t0A7ldI4sSC5dj/qTqr2i+lSg/FFacKv/wSo=", + "ciphertext": "skecafF8mvOq/D4vgZfOXyR3vtly5NM96OKks2d1iditcXChzdXQ8CDBQ1wwV0D4F9jBxw==" + }, + { + "cmu": "sCZ+iKXx4Mt6EGquEgZ2eQTNyCLnctgDpPJFQd5/O0U=", + "epk": "4c+1p/Aq06v9wyQHz3yRzzdlPcguVklwB89YS5KaOjc=", + "ciphertext": "a5tWPEOyOfvWOaHd2eStXWcI+SDW8VIBG/YFQfqVfEe6KxDeTWco1/ggQ4vu/jOpT3gMBQ==" + }, + { + "cmu": "WAu+pV8sRQ4x6/2dL6o/tN9OOlBAcOxBtJC8lX05R3I=", + "epk": "XJzZWVE/8cZ7HfbT+zYINiJHINaIef4+urEHS4466+w=", + "ciphertext": "8qdtUSA1x6AEaCXYubyhdONu6qEO0BPxN3sBllvVIeMaEBcaFh0n3oyaktjuu8S0h7dTrA==" + }, + { + "cmu": "kpganTgcm6K0Ai0mCJ5CAz9UBn09+pL6WFmzJor/RmQ=", + "epk": "Quyfg+TaUR88EFuk8uQaL9ZQvNRmiDkx/6ZZaFDWX5Y=", + "ciphertext": "7OSZyQKph52qTlGROYn1NT6eCfCVoepxJJfO5TfS3eE8t/r9o0ZbjL22xCz3pctSgnSbxw==" + }, + { + "cmu": "34sfO+QM6xxKESsEokd6xBmbL6ilf/DUY5TTLmJh1HM=", + "epk": "vNhr7EKPgwycJhp7JPoQKNuElg7XN3TAJYsRzMA/oQg=", + "ciphertext": "oY+vxe8TXknYjAxsyJ7NI5sKsSE6MsiejEu0hgxbaby01JPewqMWaGQaxX6UA6Sas9oQgA==" + }, + { + "cmu": "k8tVA+Ipwpnbz41k+nNfwOLlU7QwNOk926w9uTfMbwc=", + "epk": "zRSOiulaXpuseTEP0Z/8hRzkIdrJEZd4OSOoXBWW9ME=", + "ciphertext": "scDG5sOXXTpG4IigywW7/yPki9twbqF5Aqmicug/QL1gDnV42KwfFKBR7wIBo9TaqdOPJg==" + }, + { + "cmu": "ZwB1rxVs44d+bfdrABl1RiKoEUgn3/WyyertVS4Ummg=", + "epk": "oMnLh14VGRNiVd0hLdhZ+JQ7o6QowuxJ/0QLOsNZU1c=", + "ciphertext": "rigEwIvHqbZJnpT5TJWEgkUmc+oY7yQMw9jjWla9t2mhBjM/XQ4RLh/snkSGJqsh6kMijw==" + }, + { + "cmu": "FjG2T2I1cCCTn+F3QL7HZNxdCaL4UNpi4ZpGD9+b72A=", + "epk": "zwbSZRNDBrpbdnwjVKUq4CXZB31ZVu9pCp6lvlJsRWE=", + "ciphertext": "wE6qv8/prTTLxxdNaj/8J7rAJPsrS3t86EZ2GwR4pOkN9EO1NvydnD0gSbtpEEcVOpepIw==" + }, + { + "cmu": "GofwtUTUzIK1JQbp+N7+AyzkE8T3L1H2tVwnv+y3fF4=", + "epk": "CvpilnqvjW8pQtGk+sTGmv7tRqhqxZnM73tmFbrqwUA=", + "ciphertext": "n8UeSrhBZGIYcnX/uxK8ljCgXJw9sP6E6X+9rbQVoStyi/CRaUaTVoYjMR7lw1fJ0whJBA==" + }, + { + "cmu": "h9UrTxLzhuX+2Wpye+wF+Pw9Ox6UHmRpIIG1vcaAKzM=", + "epk": "byBUiDzZ3+2QgxRffQcTeYRnHTdOYsw7k+hwcHTxbgc=", + "ciphertext": "t5KSBe5zHZko63B/LGi6bkZy/uks29fJnsfrck4G0H+DEtq4fQzQR2FQ3MBL9vUS920yTw==" + }, + { + "cmu": "Kd52yhRZKzjAQ+Ps2+K7ONztAtLqSxZvTUnWy70iFGA=", + "epk": "wRMAGWCGrj/lQDpf529r2IwOmpAjhgCpTJISgjdTNwY=", + "ciphertext": "hdprFyr9DjWNMt+UzSIgoj+a1RIf/WlQ81kKhycJbaACVkuEZe/s7OO8276FNQkNnDCrow==" + }, + { + "cmu": "PuTdgQuCh/7RR1Nt+W8s/VvZu7a8bP+wK94RY3IILV0=", + "epk": "vft8z5Q8hyzKEQa6fmrrP6EYCzJRrYA6nVtKLgjbVxg=", + "ciphertext": "adX4nRacdQDiQPi7QLaC5eZoX1HDLf1Bb+hKhmpqjuD2YEMHjhPmMAOwNu6bP4Krqk6jEg==" + }, + { + "cmu": "2XRy3z1ELmU7bPEwn8L5EA1CyDgIRCskvbQSb76Lnis=", + "epk": "0LUJ8wODmuyJEPk86cCk+a0Znu/ihdzeX4C9fc6TLVc=", + "ciphertext": "bMudmh71UxOvNjGj/jFx6xgnw8kiHH+7/F7QHrR0iaa8yGfODCxo+4pyouJCgTeWzZHv3Q==" + }, + { + "cmu": "cMb9Yz5/4Gf2c4SRw0rRhsHPN8orIH+8FRFZ/GACKi0=", + "epk": "ew4aeeeZIhHJ5qlw3+sHERWdtuTZ4gPzVzdEesqM0a4=", + "ciphertext": "iv2iZJd54HuazAmz9Jkad3LXkrBT/b7eTyv8ay4WrrmgpX9kDlLMJzb7L1KuAxtV0gny7A==" + }, + { + "cmu": "bR6nnClPGV/HiQdS2E0ET06YpMllBC87YKSnJS3dWRI=", + "epk": "f+houVE4Qbncrf9W50TDG0RN1ZOzESZ/aBTXM5q5zJo=", + "ciphertext": "V7DSeGIzSQU0Uw8lWMWMlPfgz/lGZkLszwyMEs/WAoVwOIdew5vu/6IkY8h7/Q6PzHeOoQ==" + }, + { + "cmu": "hXz3cdr3Wg5bMQPBWxJ46nxyit9sVBunfaynLyaZtwc=", + "epk": "P37WB8DNo7L1we9HU7pgPnuNB+7p4vwZJs5uzROc2t4=", + "ciphertext": "pQz5b6kWEiehKPn0edsgs3HZyLObsbVp2U/4If/Ts8eLCRyr6Chre/nixEesVmD+FNqcnw==" + }, + { + "cmu": "XisbsDjnjLuOiLdTdRY12rMXI0fnPRGICiHHi+bnwWE=", + "epk": "dAH1ZP22bk4m0+aSyCPys5aQxgOu99mmW5n4Qt6fTC4=", + "ciphertext": "jP3KNQlLBRdEidixJ17oqh7i2bxEai+Wq8a0p/3NyxPEapVM7LiyWr8b1M4OrDkPN5MKfQ==" + }, + { + "cmu": "j5IZfPHqELVMF8ast8QsRGPga+Pr0eFTIutlv7X8bQ0=", + "epk": "dED/6p4K/+Ix3FVfXfQSamXHno79mxxiEt+8J31IHIA=", + "ciphertext": "lB1dTaaWP1ZHiBJS0QqEIZ25OlsNBX+ewNsCcrWh7HlNgsAjz4WCW5mAI5WZrOuLadBg9g==" + }, + { + "cmu": "xf0EYBqhYecIzzwAql4WFF5pnno3SndV0iz7I9pmbBc=", + "epk": "/7Yyuli0Kl80hgb2u7eIZ2WvPANmPoQFibWjoMo0SkY=", + "ciphertext": "Ry+YpJozcyaPwCCZ5022B0YJtF48fb4bphxMA2yORRaggHPhJVbcTsb85Can+cHLzavzuQ==" + }, + { + "cmu": "WDgXaVZS7Jhtehgr+D5LVJcnE3Rjx8/B1RFbnxercAM=", + "epk": "EU2yHPxEE7crD7pAUS3NUsN1ZDZO4HDjnueTOn/F9Ag=", + "ciphertext": "/5VvzvhGwOhVL++QjLVicuI71Zw4EvrJlO+179TkHaTrrDXrFVSVP4I8klBFazyeFP5t+Q==" + }, + { + "cmu": "3Vj2vSLC+zmVDlhpvEqga/Bnjy8cv6R4u5i53Y9g7h0=", + "epk": "uQPE2D/m6SvCMlPOpFDy7vcXBG7dwpZoWgNRpXR+DhE=", + "ciphertext": "OP5PRW63pkuVV4qHvevJpTzIBHFzDxSDblyHOwuFdBQvMREjEBXmQXWbCWIQV8EbKBWtbg==" + }, + { + "cmu": "fQ/8dFH/LhDUrMZeRkMPazQWOGCNYQJJ5/SMyNeNmzE=", + "epk": "lN9269q3aGiDAE3MYkuYKaay2Ov2sCVj5F7URk/LAog=", + "ciphertext": "wfzUESH0i1cFbpdQJF6pd7268d8Ic3JZN6A8QQKxUWgAtps+dITONFIbdD5ian/bnNWEEw==" + }, + { + "cmu": "jBSgXQ9H/OGWsyIe0MdQpztQeOZ3vQIVjH+Z24Tafmw=", + "epk": "8DJy5YPlBMAZEtdGwbY6qWl8usmDu5/pdXIpSIvuIrk=", + "ciphertext": "tygnxtC3J/CQraxiMQPHwItW52Z+lty//woYwW/bvxktrk84irM9vZjiB53pwuLsR5LM5A==" + }, + { + "cmu": "GciBcYFB5lFAd7+QCQmpi9DiUZCBV+urQvtDYI6IS0M=", + "epk": "/3fjfWlRiczvMWxi3LkM2mOd0TaUkFkAsb0uhfj9g8E=", + "ciphertext": "xnOyQ1Gq7DzBv6a12b+qerrAbP2UV3r47borJo0KR8AbeTtKHJ/GR5gby0ozCPX5++r+8Q==" + }, + { + "cmu": "nS+fOvyFafCgRlItoAMKq7rLuRY0awH5ua1DkPtUjFA=", + "epk": "fV19JlrjGT5UZsstFK4WyVxyR6tKZmX+7pi8kn6AfB0=", + "ciphertext": "XjFF2HmYDHT0vobOCLYNL//ACM1GFVCiI+pPZo6e9t8DdngUjgSV0uA9o/VTP04ruM1smA==" + }, + { + "cmu": "UJcTDXnCxd/XGplv17NJXccOPOfvV6j/YydS5PaBoAI=", + "epk": "84tGNDmbFkpFUu8ElMPeAEibFCkjhDHjlyAayuPBzC8=", + "ciphertext": "qmyDKQ0GLXW/x3lccQ62WakrIq4DKWKJ/a+qnfb0G9JyZBSt2fvckYzAmoPZnfXx1wGGrA==" + }, + { + "cmu": "dxZrrDZtBuuXYuoI0YxcQ0qXA4yAuOJPWDpIE05RwBQ=", + "epk": "0DZe0GOC0D9AaNhydOT0LOaTzQMZ1ZH8B5tN/5DiZug=", + "ciphertext": "phVk4vBqQozBSdtTBe+h1gwAwi3OtfzWj0lZYq+TG9N7lPn/ppJgrO9JvuZ17EmgfGQ+FA==" + }, + { + "cmu": "oH1kUO4mndCO0RgZ//TZkARzxQf35IoREdMFvsKUjSw=", + "epk": "ylaZzglPxwhiqh77mP7w0fbCSsnftTI0CXYp7T6o7j8=", + "ciphertext": "R9z9oALfvFvsWzRwhYCkZrLGqrb6iF1FDjQUrIPV0qMmr+a1rM+xJo+8TNGk6fqWEGY0fA==" + }, + { + "cmu": "QqqbrDc8/v6demJoG21cG1Gs/ry/aLKyZxI+4DYxcFs=", + "epk": "j+Xq3DluT0s1ToVE2u9i3PdnfxmD4k2KjqobCXPCizY=", + "ciphertext": "khhJxEscFzQ52AqiXeoaXJdGpqmcmPEN00b/8u0hYctwkkvqBSNI+EMbuiH5MnkR2sc2Hg==" + }, + { + "cmu": "ZLw1GLuSHKidfnFB/cZdQN63Y0ivmc3/IAAfPIFy2Wo=", + "epk": "oQjV/y28F6FQ+hIEGknQj8eStyB8DmDVs8S4UYCdYhc=", + "ciphertext": "kjGT4XVLblfi4tMJcaiVeYUsugBbxeserd2B+k9soAZmr1CJe3cZO+tTsNc0tPKOhxRqLw==" + }, + { + "cmu": "utH4jMDhUHJQoryNsl75Q1qL4vImkgDYx9aDpAUV2R8=", + "epk": "J6paoUqraEGeRa1mmdiGcitMJjQH/ZiYwTQZumWtjr8=", + "ciphertext": "NA9FUcqZqvFA/mtDANQVxm9Y7jqk2ZiTfCV4CpFx3u2LduRug4SiSntxwTNEIRNsixyZ0Q==" + }, + { + "cmu": "4OsdEaqF/fDGUnezYHo3eZ/zxxIqQeEmUdlKnx0vkB8=", + "epk": "qnf0ni4gvQZr4yiDnz6VgsHxuYq1E4PypITOsDx755s=", + "ciphertext": "OVC1+iGP9mxdbm8AHJbxA51ScEQripfBvC1hh+JZvsHvOInqzEXtuT/yFFvjoFiERqksEQ==" + }, + { + "cmu": "DI4zCTsZNWaCEZBo5ERcCXyZy69wLBSvulV4zzeLIlc=", + "epk": "Zlbqs64rDn4L+TNn5Qb+15KcrCiGAq1eKV0qreBwcIM=", + "ciphertext": "yw3NuPeccCyNi1zsaPytdR70GyFP0+602ch2UFHcHkEXxl4/jXAudQ2zehV64oGIUZO+KQ==" + }, + { + "cmu": "JhSsinq40WsuMkRjBcFjL996D83hvwH8nZyPjp33/QU=", + "epk": "RgUUlTBIWGdSZN66wMsWS+fK9B8nEivjzpoAdjAkcSU=", + "ciphertext": "80e+Six/JZcn841a4WG1wHuw8y1CuFaT3p8CgRJuR/O0L/LGd91mCnSh1aG4hsqovR3gVg==" + }, + { + "cmu": "i9IDx8/Ljdww/PqfRnXMqY6+F7JI1xmUHmVJvajOo3M=", + "epk": "TWreKiX7zwxWhEU06HnSDuj+jdqlCoIeRAWa5i1tZ+0=", + "ciphertext": "vMT0x+vro9VuDoQ2Hs7gA+VggENlJHTnGCIHbMNYaT/b0Mn0wK/iRxKgsN81BQhqhJ+bSw==" + }, + { + "cmu": "yLN2PC/ETp/5ksWsiZ+1gtcHG/2LfhDunpoUWpT4Mw0=", + "epk": "GTu/d3ZPfxBevhUv0Qf5Tf7UZv99gloB6Q9+ZOynk44=", + "ciphertext": "jLXhbLqbQ3LXb/BKisMpPF7M49gUyfoXqv4s2L6lKOhVL1fT0N8cr8vLAJ5qRIPeMw7FJw==" + }, + { + "cmu": "TxC/rPI7iaq9LAQl30UjcQMuUXQ2s0kT6eYj7NAMZVA=", + "epk": "BraSCsT3TXXVi2E5XuV+x28cIM9I7gFeYOVS/rEzdCQ=", + "ciphertext": "sBydbxlA9N4B6c7AE6JT0BHptA3imDSrQqa4nyafj4P/yEJcGpDSW5LDKErZkM3w8j/FWw==" + }, + { + "cmu": "PSLeB5xz1tbFgVzX12x6oXJ+nJOlES4bRLnPinyi+G0=", + "epk": "tbjgnHx/41NvqAs99M9NaLShdzDYgbGpVXknamgFwwY=", + "ciphertext": "cXyxjQT9oN3iiTJCRmBxyJHiSMS4W/3eAqi3WU81vlhusIewka3wbtV6uAVaQTtNKlrMzw==" + }, + { + "cmu": "Jofr2ZfH6lqcuZOIK+eKl7FxMmnXbADuZaXKAaCVLF4=", + "epk": "eHCRW5O+cr+/U4yrrxlwy+VcEQhkXTH2adKxHfd14J0=", + "ciphertext": "Eutqg7LV5hf5+ph+htl1H0J31R6Sq8g2ZBN6a1rMNJGGCgBi2V6homrMyZGFmVt3APdfLA==" + }, + { + "cmu": "5/tIgBXs+FO2DF1lXyF8aRyddSp8/YzpR85pOHi6sEs=", + "epk": "LmxJuUbcawPQh8Z5YK9qC2izYDl8+GsNLNGYHQZzwlU=", + "ciphertext": "kXBdCl7PyQYrRaZTU6IvOQrWggkLMXSJdxm53PD/8HhInXWmWOZnDX2zI3ErXiKjofbfYA==" + }, + { + "cmu": "18HqG5nMCC5asc18arYACZ67B5Cc21++D6t4ERoSegw=", + "epk": "7tq27wJhp6PUZE/j7hiVxN6MKT4xZWtEsUGm1t9ZCK4=", + "ciphertext": "N8ZzZCE/rOzBaW6SbpeIB3f26EBGoJuygmNFm6hoNSkO0KFiYetIDKwgUXnzxAFPlYdLFA==" + }, + { + "cmu": "od4aiLV3L05FlH4ss+nz/sDUoIKswncpQ99H/Kiwnmw=", + "epk": "tJolxfqYDyhq1pzsHgGOm2aZd0TWc1ldpvY4T44Ja6w=", + "ciphertext": "2QIYJRPnEfv59T0IdAY0gD9htD9sEio1wnmlECUHJ15xgiC5IgTQvO2ySORKhkGEWlMuLQ==" + }, + { + "cmu": "bUczXm0G45qW9MSpxIY9hphKGtY7muZb1KJYQeBonjk=", + "epk": "5MxJmeb8GNXx9ICasSZMcUWEV7kPvrrmCM/lOwJuGV0=", + "ciphertext": "Xa6Txx2F/YCFtpjdxyTPUAr3/dTAiVj1QvWR3r4HVs2l0l+t4DXyOZlJGZ1v9phwgx93jQ==" + }, + { + "cmu": "M6ypUY4RicOnPj+UHR7kB2tUmIoG6U9IaFUyC3ZIfx0=", + "epk": "EPO6DVKk3aBZC5b6KY6LpWPn5YeSI4yMo7gEhctHk8w=", + "ciphertext": "ukN9e9Cu1EruBcNatIFE9kGH4kT9S9JLHPLl6MNTX/uzxavii3/ip+jeToGz8hZT4f4KhQ==" + }, + { + "cmu": "k3ZUgTbrhpokeoQ2cAjLNBBGL0JxJ0OYtQLeTdVV9lU=", + "epk": "9tUAvTS3QXQZUaVPwVW1mDaf9B788qKMdUdoC7sdpMQ=", + "ciphertext": "trsLnHwpBDN9EwjZJyQS1bZMd/2WOG3+Q5Z4FJq+aYnLzkkpINnwyZ9t/Z38tuEJUNzElA==" + }, + { + "cmu": "U83175//CDjXSCfOLO3M1oNT/eRQbF8rK4LKhvkPNGk=", + "epk": "ShtwMn2RqkUI8wjHAVxlz092NDfMmZCWgns8QVQFFsA=", + "ciphertext": "6nOUfvW4qXUx04d6V7W4Gr8WeX7CF3Pj6d8lTamU5C9wySeUpt3kMmYIBpyX2FDBxPTNYQ==" + }, + { + "cmu": "p0q4VyEWrHi4KT3fqfY0ppu9Rx+ZHvxmZJfAsitmGSg=", + "epk": "7/KaVjnBJRUnsi7jYr5Lc8q6PyUVQ4kjuMwJRJPsKXM=", + "ciphertext": "kB+LGyXh9EfW9IkFuwb1GTZLbpODzBRUhsYoXftc9OP0pimrXYxNkOEC9sqz5xOrlv0xcQ==" + }, + { + "cmu": "fagwkVu4CHdZPhKz5RSpSqyhH29pW12hMd9SGK9f8jo=", + "epk": "ss20MylpwNM4t7vDfzcVTLytNOiZLX+BETh1LL4Hgtc=", + "ciphertext": "lrtoFMImW8l1gkSH7+RZjRq3LLddaM4GTbxRPzTDWZf6cCOVOAAC3pWurXE9Go3Ol7qA1w==" + }, + { + "cmu": "QSfesG0SSExK1ujPw2iFim23Odzu80osZu1WuRdUPAs=", + "epk": "euEaQ11Fah6hQu+SaM+h0VPmNgcOXbDSCZRzgdRiNI4=", + "ciphertext": "RzKvmqOfi/gURvzbp6Bt7mguQBOc30CATzkbpQrXMksL/R/AgKlvn6gsoyXp4uwiSNd/JQ==" + }, + { + "cmu": "lEM/a06+x9IVACJJ9iqmBv0FPnhsQoZun6yb9ThQ018=", + "epk": "aGKPY+RENIFc0kv+tgj+6DC4DZ8ooyRcU0sg4vOetbM=", + "ciphertext": "veppopXRyoaLBE1jrw3p05HLLQvo1hue6jitcb6h8f1d/tA5VFwdQ8KppPTPaGSTkRTlgQ==" + }, + { + "cmu": "/xqC53qcWUVCgIaHGVGfFGwKcmRJGOgxLgU1+ftxbUI=", + "epk": "RxQBt3L+9o4/w/adw/rfpt7AmCWGninrr/xrW6PrPpM=", + "ciphertext": "CpPvc6D5TXqG/jOLCXO142cIdSctJ7BHPQ1kuawGT8uXqKkF5USWk/E7EItr7ry2XblAMA==" + }, + { + "cmu": "5h4n3PRk0qe+1JLaUxPqjKzZ0SC4x7NXo7rVGh3m0AA=", + "epk": "ePJgXf/xIOIc/5RDB7z7DzH3AcZBIHKtBx2JRmWz4ik=", + "ciphertext": "hN99pDspCOacaUCiGnG71USYd4RRVs+hWtxGTpLQyHnPV3q3Xezx26Oay2820g0sDIYIKQ==" + }, + { + "cmu": "5RfKa8Rk5D4OnnnheJrhOcerJkbAeWNmev4KIhfWMlE=", + "epk": "dsR9zUSdXknvYnfBFW6+dEJg25ILr9Fnjmakfz3inos=", + "ciphertext": "ClfiAufo5SQDUMv5tebhOjpqXxL9N3m2yOoIV6zk4r022R5ND6G+JMihVfnfLtgVtUItvA==" + }, + { + "cmu": "5TpnHFMNEG5HZK+D4NpYnITB4Jr/u+FDrqWKVV1j3D4=", + "epk": "GLnpOi+CSeW79XDHwEKAz7dC5c0QaaVANE6N2ZRDyKs=", + "ciphertext": "bA6qH2z+QZSQgVwDzPD6LdP7FiFwpj5zw7eksdVNANj6aAnaY6s8xDI7XCYU/YYaJ0C6AQ==" + }, + { + "cmu": "+Rya4X97Y8Is4ukalN4yaiyWRGuIeXdUlYathrLLkVA=", + "epk": "y+2uX/YCrM+tQUFM+e7qTmRPPTfu/gxk9yhZZ0a+FdA=", + "ciphertext": "nsT9J8yvAwbui8C789fb/P0r5scv342n8GPevKdlu+SloI2oDTJkOSMWDpCMNzpOghGzCg==" + }, + { + "cmu": "U+4kmTpVOYzBeGc1tKLELx18n8cN85i2zRIkbb6SF1I=", + "epk": "k4mSgYabu74UqRJoAVvKu5ZQjGh5o/SzXzjfKHDhDTw=", + "ciphertext": "aiWoRIJRhIgqtckqDCfJ8xUtVgd8UramyE4j2OZ9YTR5gSrPE5cnFTOJnXFO9mnZehpl7g==" + }, + { + "cmu": "LwoD0Xd0UUazySFPV1SNOfEVmWAT5hIqif22Bl8j5xU=", + "epk": "mMIaTAchWaX03aiA82fcdH7DkAx9ry61Rby6286K4co=", + "ciphertext": "bNR9hBYXdpJXdJxmOhU4e3lK9dnCjRS96bKdhmRTry93r5dV7PI+l0UZyKyEG6/sDHSn2Q==" + }, + { + "cmu": "lvE1U16QKtYFQnI1YvAmc0qSKkqm7LqSqiTolGUBqQA=", + "epk": "LEeZTm/5FtYZPI4dJSHLHUTsUx5t8+dyZ1GWEe3CJIc=", + "ciphertext": "LaKb8if4fvYmNs3uyC4P1x/cvebMhhvKrvWFjgxy1BjfSmVf9pJNuXJejFkH5ee0PN6wxg==" + }, + { + "cmu": "slLWoUrNYhkBYvpPIqAWwlB6+J+PP6wDGCwcBYEcsBc=", + "epk": "kSnUrd48PUS9HOpkhvCJx5K3CFks8ldMvgDAFtpoBKc=", + "ciphertext": "jw0JbFk04mx2+EcG2VevWH8IyVc6f86HtxXLq8IMQlDZKFn9NNoXl9cvk7S5Rnye0ULRrg==" + }, + { + "cmu": "DjChmO+sm5B/HCiXxHtKzZZR3S7zv5SEyh40Lk416mU=", + "epk": "v5ST8GAaRQOY//wO2hNH+yiAZRDMuf4YUTKlrccs+GA=", + "ciphertext": "J8VQ/x+yLKtv87+mX2OmXC42evbytiT+cMVwG+SfSEaiz7W5Q4+NPl/IT3m/Go6Wv1/VcA==" + }, + { + "cmu": "ENxF0lagbilKXhHlGS8fFBgk0qL4ltDT5hTdLrlDzxI=", + "epk": "wA4QWH+8R+qMciQxPy/OH/wa8441LkINUU6p1NV5aDc=", + "ciphertext": "jZ2keJ810NPi6lqw+vZNMz7+V6Xx8u+b/NIbbN2alMiMf6jNmDdv5XzwcDZKvlUSaMTlnQ==" + }, + { + "cmu": "pWE1pkMOWUHhz4F2u7b1AZZSyaWr1oaMxoYxH2YzSj0=", + "epk": "nqdGrmTV17mnqWypIL4Nf2y/xzVzdE/OqOwsarZA16Q=", + "ciphertext": "xwelVoRNZ97odhWUahDqqaafm/OOjd0ShaZcKwr8BoHadRVKUczmG6buS8jpEDi87aA0BQ==" + }, + { + "cmu": "rxb7MuvMJwNeM4G67fsfJM7UkwCDtfUThP52+96gzxo=", + "epk": "Y+aboK8ucZ0H5+lbo2Rwtpcjdd5IhzyKauOC3CQkDzc=", + "ciphertext": "Bubp8VME+U2l2U6yoQssruCfcpb6scNPBSoFxb7L6ADnRPHZw5JI8nXHVMYSh52k43DFcg==" + }, + { + "cmu": "82QW1DlaqZoPTURx0cKd2UlTjnMqrVK6Hy+/2DnxARc=", + "epk": "8tFHrCYR8lHz3OefSStjYsLNIVYec7N1Blg3kv/YajA=", + "ciphertext": "thxk/MfTg6dA3sPMDOTcHNS79nS6whn51ZvswTxMJLhkltB/Uu66BqL83oD2aDRECVCcEw==" + }, + { + "cmu": "p7hzdj8Pl+nCYdoQQqLs/hSxBY4ddXLffs689Qmq3mo=", + "epk": "DbzvCIXAPCvtxppfsFH9ZIA5fVQctcW8zx5EqrxMmZE=", + "ciphertext": "b4YTEtaKKZmxsezwr3gzIBUyiosNI21Pxo0MupavDoIqNoVx6diQRLWwgqIkVOi7eFIa1Q==" + }, + { + "cmu": "Wee/vXVsDby6iuBYnhuqE/l7PHev0zcTSv6goeWeODU=", + "epk": "gua6Mi9ffwTbL0DkVoxFH50j10/z0xcO2DQHVcECaFs=", + "ciphertext": "Wv/MUR/ya2x1gqb4BVr1bfNXydA3Q188FVAWPcYEeNeQkoFf1hIjDDCOwy27ZXDTCuU8GA==" + }, + { + "cmu": "hsL0hEnuEwFD6wRJI6nLbkyqKKQMcQh3AOPlXAB8BFA=", + "epk": "jdhaX/+T3XN/8QeFKUkg2eVuqTrN8gzPPPEx/u8GBBg=", + "ciphertext": "HxsA/byKRCoWzfFynj6JKAF2xiby+L7zmqbthvHFHQOfN1LAylyhLLiX6iGhIW01qdmusQ==" + }, + { + "cmu": "kfqEGOPgNE6SLSnAGoYsKjuyVxjE83H5Uw9f/imR4Vc=", + "epk": "XgkhdjPNBv0ow46pKMn4ZeTkxLpKk7U7maXHg0xuR00=", + "ciphertext": "SAdjYLFeT0tOoDHVIQ/wswVOoFiNBOL+lOBt9ImQ17CpzgVV/Bxa+ciYmAmF13NeYXgTVg==" + }, + { + "cmu": "PdA5vvAKB406uJHbx7sOvE5lANUWLYoLizV23TzNpl4=", + "epk": "/7qaCi+ohVjbzGC+FrIXMqxEiBwTZWGzwEJWWVSe8LE=", + "ciphertext": "PeH7XsJYMEIxhwyoQp+XnPPnhkTjdCxbB10p+tdHeYmV4ZeyPcVu8Sj/IbNXFoG20dvFSg==" + }, + { + "cmu": "3c5EzCStmJe92gG8SZ96U/0/DEOPRTmID4ZXEexPFQY=", + "epk": "V9Qj1I/k34+TvX/tDOG5ib1p3saoEAK3Cp2H7XSgMsg=", + "ciphertext": "BRmu8sDfxxJkoCmasM7L0bRDPA+R7Ts+IAixv2OqKqjxz9msAovLUy/GUwpGoma4oLULKw==" + }, + { + "cmu": "h8V+yEEn/v5TgKLByYDQpNBi9LNTc8ghru6AYIB7+FE=", + "epk": "lkvGxEMGRd7EnXfjSKi3KhYNOy8AMPEadI5AFYyawr8=", + "ciphertext": "0Ng8bIOA03aQruCWRt2o8oXR05dypS3WMVInJzTbdxldoCX/IBDU3bH9aXiZ7KqNytQxcg==" + }, + { + "cmu": "1t/1uOa3/vQBdmPdQpvOLNC/cC6KBSBEFUVWEzmclz0=", + "epk": "+h4fzMhIEEAUeh7baDoX64ibqAMsG/m+DJtqwKhu1Qo=", + "ciphertext": "PvC32ixQvR9etsAwvQgdsRyn//U3B077aJeLWR6FumpD9lUtisIP76tg0/xacXvVfIQYPA==" + }, + { + "cmu": "S5sqgzToGrIBXtkXtkO5RBeeGjMVPhL38JNH2ZvKhks=", + "epk": "9wrqXew/GJ51GAEtcHFEeisF5QfdfOmhHnbId377QD8=", + "ciphertext": "5al3qSTo6IcKgcyCrYOjs/TakDcjAIE+GUPZlQwlH7+VSZSRsFqNchENXlJ9ySNMYZvPJw==" + }, + { + "cmu": "77AsX2m5zkJTh8EWSFFrseB7Gzi/Mhdb7rCvtCSpME8=", + "epk": "u1SAf/w5lSAg/+hPo2gZJPOQDqGD587J8BmUFHyrXgc=", + "ciphertext": "YXzyePC4hhNm2gX8Byu2FsyG5OSQewf7Fe3U8TozLSe7TvIpgoXRtiGmhBwq85XwoMLDJw==" + }, + { + "cmu": "wSPmZCHS2MS1j5FcI7weMXK3Kod99Ucxv5kY8/YTtTY=", + "epk": "68ZiNG9yGpYNf4DgLFfaYtReBAL7u9fraadqz7+R3ho=", + "ciphertext": "eLQNCtY644pw1Nsel2muJCOHz1wSTTQBDKXuj2aGXDOI7M46C8+AXfdE3Q/MWKp+FXbgNw==" + }, + { + "cmu": "KWTlcNYAcctdWyoCUuG2h9gTS20OMbEshtaBY370ry0=", + "epk": "y9ep0uGq4zHWhnC1ehrbcyukjpOyW+VWE+CwAEXL+4o=", + "ciphertext": "Ipmm2obmT4jHfMtrIsBW0UZze45CPdYlsEY/gnYQ3mPyTz5bc078J2xvBZ607PYltjY1Hw==" + }, + { + "cmu": "j5EUvnoK0QsUcJy755Lh6Ag9aw3iPSLv7Ueg2F07YA4=", + "epk": "Tmi+yDFEOiPqdVEfYBz/GzCDxkTJU8KjGXJMjmFLDqI=", + "ciphertext": "bWscMpEoy56bXH+G03DooJ2P4XYv4Byn0Mr9pEVG4zKPvbFfpf4YyKhIxastn4G138Jlhg==" + }, + { + "cmu": "T/EzQsXuv7l5Awip5dBVjDGXduiyEUNOYMsX6bMwW2c=", + "epk": "/SqHaGiiZaGMXXjKtZOrGSG4f7/MPzt8lfpMwkZpKpE=", + "ciphertext": "hFu0BJIDBapUQxHeCwxCMzRF7LPkcW86PpTl4r/akAc5aIb6erE/WDg4e9A5yrclqpnUUw==" + }, + { + "cmu": "4TMdCOaWrr6mr3o3jlBCifmp3tcepO3wU646XzjnZzg=", + "epk": "iZfjhFKvMQths+dNzVYwjddDNsoMsc2h/cOoj5J9kHM=", + "ciphertext": "WhcRMX9+Ztepk0j8PpKMLy7LH/i3k+5eihCcKa0FmPiiTNP3xZJW0YITNqsyB6UNHIrlTw==" + }, + { + "cmu": "MlBlC3ESuBSkYqf7keWFNohbBLN6vbkvTIwt3nBfWk4=", + "epk": "PMooWrt3B9jGKwfDxTN6fT2uvm68/3rN6OxXjBzNyZ0=", + "ciphertext": "/wIVNuzcCouIuMZs0VxzfJtYCgXhpqJ48/wpgh4OiNwJmTbheVl8bnrxoLkelB711FC/4w==" + } + ] + }, + { + "index": "37", + "hash": "HZdbyVqNgpv4+OdbeT5pPkK+1zNvrWGSAt+ZxTAOmoE=", + "spends": [ + { + "nf": "SpE4MqaegboB8kpbYhh+eXOSft97YGPhAmHvcHKHPko=" + } + ], + "outputs": [ + { + "cmu": "saXSNWzyJrDoYLyejrsnOHfO0elQM/5muzV5fDAdUAA=", + "epk": "cs/ytfZB5QJH5OMNSxxTmwJ85dba+r//zRo/mZtPzJo=", + "ciphertext": "izqGxnZj/G9mYaU6slykQcXDEE/NCWVWoMAWT6UxQar+f29ot+CLUKS1G1HzwwKocNC/Vg==" + }, + { + "cmu": "gDmHK6yXjSrp/nxohWuIC9s1M2zjJ6beoMYCHthmVUE=", + "epk": "qkq7FDKlqqGwKjd8YFsAVr36q3c7MW06rzBFXK6lE6g=", + "ciphertext": "N5aMfoMrS+Axa/u+T/aJRPeVmB/5V/wi6psFuaIeDqYzQbYYZPHmn+wVYk43LtpVudNeCQ==" + }, + { + "cmu": "DBZx7Ez70zsJ8oK2XK2Dy1eWJd8zz5ADA85T+lB9dj4=", + "epk": "/4oX1OUJYIfA7aIT8xfjIoiXjU8jvb3H+ccbZLKwzrk=", + "ciphertext": "SHo8Jb2Q0/fRghkETsMTl4610AywoTQchtNnKtBr1j5/dScQx2udAL3k1NVHcApz7iIq/Q==" + }, + { + "cmu": "R1nMZcLin1ao6RbvRFrBR2KN/+dKhlZkfyrIBLyCXTk=", + "epk": "C6Sp214IHtsCEefzhj+Hpd3kkZqpnNsjK2viYGaNYiA=", + "ciphertext": "6dn5Ts5OAx1X9dHKK94mgnJlNc7lbOB+WFrBU7OIl16M51y8/e0d+9JHDrSBkhljihYJvg==" + }, + { + "cmu": "uU9lCfqXyVwItbC1zsnN0+a3g/alVoRIZLF2MBUTVyU=", + "epk": "3809nKxJe7351bUhe+6QyDLZnSu02ycrNc+4sr6ISiU=", + "ciphertext": "1q/HvLCrQCpLk9vHkQMKlYBMNCq+D9Krjc3U/v3nUXo5ZPqVXupPlBOsVpuM4ZoPj6m3Sg==" + }, + { + "cmu": "2sahChHyd16SbWJ5WpB90xJfyS9xqaqbTaI/VshQ9jU=", + "epk": "jyfrJxXYFBp4DZ9D6vemvSMGRlJlzRd+Rm5wyU13U8Q=", + "ciphertext": "YiS3IPUzvAz7TV+8HMEDt0fA1wG5Cx3v/ssftFKOysgsLLFswSqfHdFQOTuD67dT9LFurg==" + }, + { + "cmu": "AXd/O5pBMEPqcj03iRTPNgu1AJAqPcui25i3P8u/CFY=", + "epk": "k9I1fp2cvQPlVEgTwvFiduAHYLHNVKtsIjQkrmjL7Tc=", + "ciphertext": "tJ3nOmIhn1bnEBtQeLzqfYKfwyBRWu27OTATvoWSkJZj27huFWUoL0rVYYHD5CzTLiY4QQ==" + }, + { + "cmu": "08NfetPmpOyuLykBTEAZkv/sxrkW43Pwzcl51Jqxrk8=", + "epk": "lvjnOThFjcCJ6CLQ+QFbC7jVL3NkIHZBGVmWP1X3/cg=", + "ciphertext": "K9sJm9cDGWMTZ0VGGk1/ofYw2GRXZsq5O1R7IguKXe9gsmzVbvRqyyYPUXD4LhQq1waSLw==" + }, + { + "cmu": "jFbCQ4KDQ/7Bm/qfSrQjKjP62H3k7H3dlMjErKwGrnA=", + "epk": "JEG/Mv+uMZk0mzAx0EBf5Nz0xQWB6X0ZgGdnSYBdn7M=", + "ciphertext": "iv/kn7XwY5vfcVKPs0I7L4DGh6gnzpOwl8TBCA9vwLd/qoWLQf/xChIWUePKmp15B5WwrA==" + }, + { + "cmu": "RpRy/0tzS2gvEe5c4Q4IS/YEedA4dQTn2Gg33ihoGjA=", + "epk": "0eV7y+2icKVWtkzFchajusa7L5sfQPhioszeEjVpvDI=", + "ciphertext": "DcSOKBDAG5iYun13HegoSNBcGs0IlJMrawBx8AZyW2wty1Gc6MM20/pimwPvXuFJAgrttw==" + }, + { + "cmu": "qYsfETQEFLxElrg2KmtOKpEG57+TEkKRKM3XuzI4Ci4=", + "epk": "PsmxxFZgvjOz1UB9nxyQrVh17HynKAbeVG8+DhVVvr4=", + "ciphertext": "LDMBuvMPLMK8n8vS+IYDdNPuk9f0ZreFwNBcRecqXgxvFGxyG7Ew7qIydlmPs5ReBzFspQ==" + }, + { + "cmu": "bFPwLeMmpV3DbZcaAgtNv8o2AHTwpxzTTveKa2lYfB8=", + "epk": "RwjJbLJjld+YNn2G5C1t6VizobBlxZz+544H1XTEdxs=", + "ciphertext": "3KMhxTKOXGhSx2lsJQV7uBy9x0B/CBWJs9oWG1YN/JZOr/B2Xcq6QE78EYP2hYdjD6Q5jw==" + }, + { + "cmu": "Y9nve38BxgsvITFrCy6X06h/wrPmEgD5qzgkmXzGJCg=", + "epk": "yR7wVndHDeOaD9qEgJ63n/s3s9HKlyU03uEYQLZPpsw=", + "ciphertext": "dGcWLmw2GFjN25bRR1AjcvDaKGGC7+enAsxWI66RIucXXhAkgIrHIMURQZ1Dzf3GazRFBg==" + }, + { + "cmu": "AjbSDVlR/wzeN1coHeZO0OEW4Qt/4aep0kTbogmjRTw=", + "epk": "sP8hIyu0y/f9aJS0tmbuTcfDp+v1Lo12bdgGV3Gd9ro=", + "ciphertext": "ThT6erpbehhCcR3Fsqt9sH7Z/XJCHAW/boszL6rcYeQyPOAN5oVUgSrKCwEikdFfcYJ7DA==" + }, + { + "cmu": "Jd/Q6oEdPy8ZaTAXD4gXITF9B/o1Qp0KxRiG27O5DAw=", + "epk": "y+eLDy4PqnbhkE5LpB10Xaor+FYyQ6DY0RA5IJfpxig=", + "ciphertext": "Q767lKt1vJ/b13VM/+DJaRd9Xf82QfX8ITaside6a93wrlODVrqzj4zzzCbDI1APknofjg==" + }, + { + "cmu": "Boi4g52munegTG0VyRBtUUey1PD9cqZP6UPFHYt4wzo=", + "epk": "XqoPZNXrGkbkikm94jETuQf8Q6hYJBhvFisusXJH9WA=", + "ciphertext": "zZx1iKvAmnqIJ6mJK/aqB0OgfRS3Xy+svZ/Jg5+frTotZxnC0JfljHs1emIOUKjKhWPyBQ==" + }, + { + "cmu": "PSThHFY3CnyDh8GybqqCDye0I5olKp+MbkHDLZfhImk=", + "epk": "gEyyOoBXmRccge4rd03hz0HyptGsuVOTx6t1ooRkVdI=", + "ciphertext": "H1y05/mheFYJFx/pgzYjcWItVBfoOerjcQZCrGvS+BL+tpfH3EXEs7KTYvv/2hFyv+/eUA==" + }, + { + "cmu": "JuyL3lQXeCJ+nQpY06/+kk7TJtSwfhsspI7e0/JCVUs=", + "epk": "mP1hbDb1QbSHatEBFcCGTk0uEVFSZnnClZIy5+wq8xs=", + "ciphertext": "T1h1E4iWi9E2Ipwnn0v3SrWRhULI3pCgkJvJS6nKxuE9DRXix3EhL3eFoqEEwHTfK0EeVA==" + }, + { + "cmu": "4qu4ClhFT0hk8U9ABai19G95x4zS8xVYSMqg1PTarW4=", + "epk": "Miu1fLV296L57PGRMRxmzfVRyFBEY+vVPA8JhstIJ0g=", + "ciphertext": "ESsDltLXei0vYGNUqm4hhCD8wjJy+TvavcUIerXKELWAzKtWsnYdVYXYwRFD4+2q9DDpYg==" + }, + { + "cmu": "eFnT+NXNPvJXkZwtAa9yq7S7eP3TiAOk71frhnUW124=", + "epk": "HWx6PQ5EPg8Yr9hF2zKOftyWf/GpJV/LOguYFFAxNR4=", + "ciphertext": "9jHxIm1ZrcEWLPRh/9TfPRlDzCuYuOw6IDl9+cejE+noWsHtJTGeOVnaqFzt3Fcjk/TLjg==" + }, + { + "cmu": "CZfV/T5X8SrJHlFJZrbHHdTAb0YQSzSq99/SHUARvBo=", + "epk": "j49MG+zmF3AM8zvs3QaeK917G8sfDyrwgGL+sCpu4Zw=", + "ciphertext": "MKngX1DCkYZ8lNvs7uV2wmqFupUaXr0Sv8KAjcZVlMw70dHZ/qfn0lG0uWEZwjqpcszpxg==" + }, + { + "cmu": "XpPS3A8bWvBDkiTxmLhysK29RtQCvk/B1gFe/ISeSgQ=", + "epk": "wVbzciwlyLC3ZVDXFx3N+9wTbjJs99RHdeMNv30I+Zc=", + "ciphertext": "apI5huc0SuvK2lOzORNJckG86SxeVqFcHxVEYO6SMQOEpGc+cy+lS5X/qsKR0d0yFw6IUg==" + }, + { + "cmu": "4h6NRkJdDBhbALu0IjFFjdUSNY8FX1GeKJOEx5Yaog0=", + "epk": "WfAF7xBthbqVtDLxg6HxOtJHCQyP/UbVJKJYPZXdQ+M=", + "ciphertext": "ziaJzkzNNvrJBY+0JAvygXMJQpZ8YjIaPaPMFFdA7c4N+8R7Z1/IWkTBgXvKCk2xRIv23Q==" + }, + { + "cmu": "1Kdr3E0WB5tZVBcEfY62dXHuRaRUepnPrYyLxK6QbzQ=", + "epk": "d4thkE7ad3qpS2ruwdYUap+x0UjCApEkqsWLDoOEU5c=", + "ciphertext": "AiuLby2qfP5NjpcdWtAQNnsoqGMqF7dB9AkO+ekMow79nL1EG1adaO9hl6xUl2+fjW1i9A==" + }, + { + "cmu": "CgKAjO6ewxXMD568mNddIvWq7J6uzY7xFEnl6qbZOkk=", + "epk": "ZPM9jDlN9wnIIsra9kv2wkfiGYexAgDIVYdMkb73zuw=", + "ciphertext": "68j/lkfM2Z0AiuALfUKiVo9hP2aIhHEok2EeivHRKiKCKlj6h+w/ceKY1vEJ9iCnK6XdqQ==" + }, + { + "cmu": "vN5FfMj5QElpFpZU6MY2b7AWza5Mv6Vnk9ozH4bgkxg=", + "epk": "qqt9jcAP/dgmSuqCBfpyYTC1v7ReurtQB3YYgMiutvE=", + "ciphertext": "MiOsliEJs+lQ8aPy0ktO+F/KGSkQBnMcEtM90N+ewhs5WJA591/tBGdErl7qed3NsIyWUQ==" + }, + { + "cmu": "fd206IArDZILt9ryVLi5hKnm2sKkkp68nlMNBHXjBQI=", + "epk": "9hDSQbkYs9zgirLipEnKXbSf3rgkBt7JR8UJQeHa4S0=", + "ciphertext": "l4jCa7be4LNgxUTk6ynOIEFR6lVlJtuAlJMN43SCOs7MxLEc21rpqYOe6Bh//plFTHwvOg==" + }, + { + "cmu": "vih/33VZgVrTdmFe2ubFjzNPhGl60uRjOXQ4qlurPws=", + "epk": "9EzrJ9duLaZe5Mw0gVGr+3cd2j0qezZcrcU9qCLnWbk=", + "ciphertext": "/FW3x3DVPDPYRsk3iVX1f2SNE5RSXOaMUPzNnEcm5IXlx/rpJmSvzWuaQBmobNMk9PPm+A==" + }, + { + "cmu": "AOwoE1K5vntJ4de0KRsHCwJdxH4wrSeXtvSJpRB9mz8=", + "epk": "XE134kyL99JnEb+xyLQ5OPKWVwiniytStfbyg4nPGr4=", + "ciphertext": "E6wlihd98gQaehavMqdt7X7wWT9vsM04HTkHIbM0eQ5NRn0QzHgGLPUFLHfaH2xF/fgdoA==" + }, + { + "cmu": "Wv6Dd+UQr9pGyKNLNPiVsstOixMH2GL4dCPy7jwK1WQ=", + "epk": "REKQGvN5ZZyfV6qrk5c1xU4+TzHs/DQS5Xm2Oa5eyMc=", + "ciphertext": "AYpR+nO7Rv5GD+Jwv5sNXhS8zja3nG46wycJ951KK+dniHv5/oPJsESbu4bUonOOgnxf/Q==" + }, + { + "cmu": "z4P0jSR7jYKEY+t2ohxZJKe/UEPiN6QbkKYKwflZgXA=", + "epk": "CdN2+meyAjXq2iv7D+8BsIsKQEyEposN2VGYHJP/Nhg=", + "ciphertext": "jhKvSX5H/AsSNCpuexhRPFNIR3USg+fWzlZ7NdPGgwqDGRhNHez4+l+Xazb9ATriKkNKxA==" + }, + { + "cmu": "iaAAEGLLBXfKQtI/oRFw6UHAG1b2gCXHwinXUQRysiM=", + "epk": "NQGwGI41epNIlnICfopc1EvgwZXqQFvsOgs5A4A/BqE=", + "ciphertext": "MMYGDfQC8x+YrIzDnm4yONMY7V+lUw3dOtazCzVy9L0o2MXpqFyRV5LCrxSUPUHkp1K59A==" + }, + { + "cmu": "Y/62v31jVHLN8i2T5giDPwM6yjDp+AopP3qELwaFOy4=", + "epk": "CCO8aYzHHTKOZrgjp/vXiRK79SWBOuLuHw5FGZSXx+Q=", + "ciphertext": "zKuTpUjiH/kmCrG48m/oOggl4gWf8JnVU5QoQ0FuLw1ybFWWoio6FBIq28+uWC9sYhLdWw==" + }, + { + "cmu": "PFlCN4PbRbH0vrLpZGQxNUd0N6uLcelGrji8s16S4Eg=", + "epk": "tFNQOTn/Gqrd49fNxLJo2vE9oUlpx9BvDKlBnv4431M=", + "ciphertext": "msqmrhYCbgSplariimvmrhy51UZKPlPufEmswBxh8KNYoqqloQ8JMG6LpcUeaacpG61SEA==" + }, + { + "cmu": "VrGPLXVj4sZS6G2tqCBX60PXmr23/N9trwJUFXdbpFI=", + "epk": "C5MkLJsbqG2v6OhyfKeL+ifLcT8lq9HgcU9DF/d5enM=", + "ciphertext": "ZIsy6oCvbQ1MTSe0BLA0Vh/ABQGGLfw1wuwu98D6to16BGqDu0B/hDHk+X7vQjt+Xoo0Bw==" + }, + { + "cmu": "Wjx5MXoijtDtcFpQhHunBKR24M8YEtAj1jN9h1AqaWg=", + "epk": "ms38o5k/UigVnlsW4lEr09Cjb4gH2RyrJn7kE/JInMQ=", + "ciphertext": "ZJAAwKlTjvPt2FR5SY+j2cVjUcAIVvGBynTkuMAzVfFV8tvslQkMS7Sgb6sFyIUJlQQl1w==" + }, + { + "cmu": "OH2IVfU8Z/ovd2K0abDPhqqqywajXWnalRXJ1Y18ryI=", + "epk": "uHMS1CYkfJo2gu5Tq+41jlr4ISBB9E2jzHLSXOXmhvA=", + "ciphertext": "jppS6gxvpMfnu5ycc3THKtp7qBb3AwKDv226rJQPc+LsEKxq40S9RRQ95AnUbk6iqi9Ezg==" + }, + { + "cmu": "4ZZjDlGfDufJcYjK6RFp6HO1Ay/2EbAOc2GVOwH4qC8=", + "epk": "VtvXKbvb8d0yrsnKBBWear+xaBWltL9GyD+yQ7Byoto=", + "ciphertext": "0OJbBLs2Cs/teCi/TQifNX4/0WYiX7i86UhTJB64HbZE5zx+bIrnYQrvj2gqvxf6BBNovQ==" + }, + { + "cmu": "UaKkH2Uy4Ev7cg70uRmuGN9M+YDR1d+FPQnHsiaNrDc=", + "epk": "zaHUB2BNXYE/+4BV7C2SIRTIQ/pqER6O9HVVOnjAuQ0=", + "ciphertext": "kVcZ3PXCDd2+EZgt8esjRD+umWfI/ER5mjUIYpiw8puSjUfUbjRQiKRbw1uwUHe75qvINA==" + }, + { + "cmu": "7voa0cHHpo/BIwYEpy55Mq+C6ZJdLYJGEauo4ytvRFE=", + "epk": "Fj5F9PfWJifrWSyPLjxSox9o4CW4YrwFu93qp9x0Vw0=", + "ciphertext": "So1oQ97kpghS5JFHnKD/rIY+GSyEf4w9uzFxYhoNnFkN4EoTTgK7SO2doYPBIxqR3aDtlQ==" + }, + { + "cmu": "f05gINJhEykl3KstMsQizZdzDwta7Cg2a3LVTaK9By8=", + "epk": "oI/Flwy9iGYKfRT+2h8iIzQDUROMJvYJLmPD0hLi3ps=", + "ciphertext": "W9vE1DKvMWhMysfJbeZeQoGXi+pgPGGo2GuwuKDFvjPMERtVvQkenaCLM0zuwQomxoavgg==" + }, + { + "cmu": "NhRR9Tn8sfrM4QI+qQFXBPdRhaT+KYo1Ma3kUTP20Fo=", + "epk": "qpL7GpsJZBWPv1YsJM0RehmgaJui6VS20HD82SeAcSQ=", + "ciphertext": "Z5k9KqiEM8xGEWrl7gGm6pbAfIs1XuV0Vhp6Cmm4djQNVsHza1Qzh1ADxfxaxC51qYqnFw==" + }, + { + "cmu": "TZ+Ka6Nyqt6v2WPLsItlv4ujofSeCgfABG/DRBWbIGI=", + "epk": "s583EDvRxM4p/Ek5iPEmrnu4sZBwjTlfeugN45MsYak=", + "ciphertext": "16wwlFGjtPR/mCU03va0QRgFkvV3GmRewd6u1cd5COCgLEitbqspOYpBHZE96CJn6jD9DA==" + }, + { + "cmu": "+H2yqCnBW2Q21hdZ7AqtTb/3toGYySZiLsRIZ+TUmgQ=", + "epk": "oRJtLCU+3vEAk8LIJie/hUFhA8AY+wykY1TN2nJL9fE=", + "ciphertext": "NLBnjSUzvIcrXp7UiRnA6UabwOed6NJMVRhnnOW/dGDtr074zFW4BLqSgBcby6kW0W5lyw==" + }, + { + "cmu": "Zhr+VC96Ap6ADI73IgaFQeMtRbM/jRjw75oiykA2yx8=", + "epk": "a61X09WfAH6bl7/WljgdqIU5b8hXUoFl2tFU71gJQx8=", + "ciphertext": "nIVP+2bmPKuEuK7htxzPv6bUVRWayraCpK1GP8QnVaLI4q7dvOJKzjPNJGcEgG5PdjvpFg==" + }, + { + "cmu": "G62OaHUZGifC4du6f5TrXyoTmIBPBDzt+H7+DZTfsV8=", + "epk": "uQ2ero814w0gSHvY2qThCcK5pL38mgowdVNnuttzvFk=", + "ciphertext": "j4EXVhC4Rf+k575WxISKqv1RtvFSLE+OL3DmrwlsijuqzC3DxBSpKgGogNcx3QwMncVoUA==" + }, + { + "cmu": "EUJDziQxvZEb5N9YEFceZEBlIB3Vko6hFEaRVCIgZ1k=", + "epk": "owMY70pht67tssN6mQrOdAivxMCz4bdDXEKe5MWB4Jg=", + "ciphertext": "XXFcq/wrVOPOO7Ute/KNJ7EFzJvYDLq6mciiSpCi0Vh0zdo+B2rkTdNIfoAm3y+N/oq6jA==" + }, + { + "cmu": "XCMFQREWVuDdBfoZBrwmUe2/+lqkmkMEQTtPfQNg6hg=", + "epk": "yJrIAUlaBIN8SKvBvDA05GBrcNNHrOAcXlr68xTZqwc=", + "ciphertext": "Fo5BgmlObQjbXaUVXKuDkY9D+uPkYb9d3VBpk/F7miD8a3+Uo++MbNB75dwLaq7b6Q3xxA==" + }, + { + "cmu": "F935AamSJiVtYDOoaxf6SXofagqQCeMQGXnNL4l9FmA=", + "epk": "gCEQI4aMBWT6m7cO8x6cneU5Mp+CnICd7EFk5B7+VFc=", + "ciphertext": "C69WuO4mMPt1LVJkziZoC9ohoRVhwJXvujpxbFhzcEOfv43NbTfClnbZ8+itwNhnBHcVog==" + }, + { + "cmu": "c7dbxC3/GJcJRq3euR+giumqxCqLH7C6DYScI8xMS0A=", + "epk": "MvEhoyyevWNC4aZgFp8d019G+wXld+P54mU+qK7sn40=", + "ciphertext": "2X3QTrvMEuMsnp1t5vdAhOBwew3ni7ol0Oyltzps0XuWt9ul2//J0lizzDYfTa1wNcMEUg==" + }, + { + "cmu": "rtQj0fp9lTUoVnhHA6vDry+1d6U5WRTIUM+1RQROnBU=", + "epk": "IGWOoi90dDQucsJmoSkoh7zjqhMQb264adANP1CddS0=", + "ciphertext": "uLmIVrQ4o1da5SYUm9cjqN76vG3cXYVSE2HIcpQln8FzTD+WXYhnLcaAZFKnjmwabB5JZA==" + }, + { + "cmu": "XhRfN9wQhnWD2K7xB6/AV50TMhT6ggc81sn/l3y3Ml4=", + "epk": "tEK4YOT5cIWloz+Yjo40x9Pv27SULYkhmPbFpl4ztQY=", + "ciphertext": "6WylrJ9nzMxuv1jnzJsmBcBit7H8I4Cm8F1UqvUCRGtJrDQjYF2OLiIFxKQGzuVDQfTIHQ==" + }, + { + "cmu": "9umbgQGdVdXTlma3SpRnEbUdTLuuwBz+qgGJaHYuqRw=", + "epk": "0Tdhq4Z5l1VG0/L1U3f1RlVBAMgd98CRk/rig470hUo=", + "ciphertext": "jkAPme2diYIhHq4qxd4X5az6AxCkrUo4W4pw4nHgrOVObHo5rBB12zyNbBE85+Fgy2tn3Q==" + }, + { + "cmu": "wD3+2T8qB9IaW7iQ8OCApsAAf918VLtbDWOnA4V3pUg=", + "epk": "BR2W1l8fkYdTw1I5JFDPhXU28C7jf9C1iPACR5y7JRE=", + "ciphertext": "OD18DSnDmSr6L2NSTPje5HlMzMB7/g2IKMfJdb3A1apk8KmGuPdllZZ9AJqK0UGbSAIEew==" + }, + { + "cmu": "F3Hz6f1MxjGtvKOwhxbVtUDQg6WnkYF4286hgoav0hE=", + "epk": "FWsJCkNnqaNsTphvBLdfU7LBdOUDv7EQZoRBzxouZQ8=", + "ciphertext": "I/bZC6Sh/kWqrrXT0e3cTb1XkZDzUud5fXxxs3bGjqUE02rbxXf8AOhxUg4k6h8tJiXW3Q==" + }, + { + "cmu": "9DId3cBgYbQi8aMEYbdIQ0DS0LF+sxRAhxBZqvnLnFQ=", + "epk": "+ndxGaskza6WLNpB0qTtNaKRWL8jbUsXJ+wOltiGBVQ=", + "ciphertext": "wb3Tm1/Ut3h8ATiZXz1JC/K+C8djtSMCHfkdKzsLV9iIqIaGIDaOq1uPx82xa2jDkgftNA==" + }, + { + "cmu": "y/qrpBmbJ9Yb1xpLgmjnAW+mVrEglGHRn/ulQelCXT0=", + "epk": "Xl4SGyrFMZWJMCDuGAWtlMYT1++1NjVZOYt+aNa41Lo=", + "ciphertext": "PhHnHpFVZeZdXN07bdesYWmUn/gHA5hsbsZFNToaNju2fJ6tl9Fh84noo9vkDy3iNRzZQg==" + }, + { + "cmu": "HKzgnnMB+lSwalF46yAkPfsSSpwurPqlQ5f8E2NldkU=", + "epk": "bIU880fu73Iolb8jW8Ea+T7NPJ4COUqtBS95qgJIqw8=", + "ciphertext": "7bIamsxQuwPotwdIOdonufM3aeARoswVc465pMQbcNN4BrZ7ctDrRgw6A5caFWj2+OnaSA==" + }, + { + "cmu": "vtW0gtRL26QFcGD16+j2oI75n4tCZat5bJINWtuFXQo=", + "epk": "njDajemH/okASukx9bQKfJV9/0EFEkn1DgeCHzPzecw=", + "ciphertext": "S129l7SrnC7bRwamIn3fHDcxCmU2h09FTMFv0i44cQ6niIwRV8hfIbxV0HTUcnHSX0PgwQ==" + }, + { + "cmu": "6NlrEEI33kvNxNUmYw5NgI4y3azqeNmpxdhmRQaS9SA=", + "epk": "rb6shUbaU/VLOs/KzEn2b/xdEtCiRMBfuIhJiRWKZI8=", + "ciphertext": "g03u8TTJ6ezZEqJn3J55syyi8Xxo4OPqO7JSr4GKJ8nQhEWyq2/B94GxUQ/xFkdD4dhzPg==" + }, + { + "cmu": "+y1jhn9nryKUoX1ycYgXQf1TZWqZNvQ9ZcmbBLaBAE0=", + "epk": "SqRr/8zpQfFomnSJ8V5VNw/1Z2HfnfraE0NaMBgLUs8=", + "ciphertext": "7xf+J8B1rBvTCgpr9G39wIHOrX9hlfMaVolKcf8hzpvNe5qqaXuDpwzLjFSiYhn9POEtFw==" + }, + { + "cmu": "XBH3XYbTeM/KGFIFCO1+xC801Jzgh1+oDYiWd7jXBGQ=", + "epk": "wnnX802EGsLpSYNdlBd2jA5PbEta+0xF+A9MjeC00Tk=", + "ciphertext": "GbpvOozSbyQ80ll5KeMdOvk3MkNxpPZvPuytLjuf0VYuBufhC7JmmOaM8RoiVBfRiZrkaA==" + }, + { + "cmu": "xXtqzGOPNF2/WU5nwED9sT+jTv4BQdb/aIJWTXx4B0c=", + "epk": "MMezSyQWNsTrerTiGE72hIC9ZRg/x4X0uuCweTVSY9M=", + "ciphertext": "ZyNaZ28GIiz3P60jxTLhCfCmfLGhhIajHpTttSKkly23BsDh56Jd/BnDyMhCtFwuKs7AJQ==" + }, + { + "cmu": "pzuJP9GDKDKnyoYTD0WMCiZLiLGR8JqDxDDVzIN6Hww=", + "epk": "RtTr8PeZsysZwshfQ4WaeGc/FCxaefi3+c/wL7hjz+Q=", + "ciphertext": "klxHplxuru3lj20G9EsdiaTzGGhblCzljXT1Rf/uG6s9UhNkSniLaP92ZswQiu3DmT5LJA==" + }, + { + "cmu": "mUeCkhGaPx3CE1BmyxOxe4VXzgfMXv3KUViPDeOfSl0=", + "epk": "B5gSbsXfKrCaHP1yaZn/c7HqIcY/sYr3h9kLtlpn84E=", + "ciphertext": "zQinDEPDBZuuER6vLyz/Zesl/XZPf9GD9XHkhJTduAANPYARFA2SWZC6QSwxExira27gNA==" + }, + { + "cmu": "YY6WXZ/1jYKg8Zx4ESE4ACpx9OM4H2DZsoLNwY7Oqgc=", + "epk": "MLb/VcNEp/LuiJJ97pmRGXgB08J8cPwhz3YusFDzKck=", + "ciphertext": "I87fcKnpqIYRzEqsoK77ODftOM6axlJ4jUV/rKxmi0IPvtI67ddZV7GvKJfMJUKWPBDoJg==" + }, + { + "cmu": "xH/JZgJJylzBilWFtEDd+HBAaw77B/RGv9nHEJ4/lFQ=", + "epk": "Kb77r3AaCblHEJyMcxRK05VJgb86IfYJLkR9Wg4nhok=", + "ciphertext": "RYgVDqnxWkYN/zIDrWNLgzdBc9/LjEqx06dJecpDBITAmeiRXuL0Uplrn2Ttxeqalv9R1g==" + }, + { + "cmu": "L1Plinb2510+L8AUHPABRiEbwMnSYze5Ufnge+4Pimg=", + "epk": "L+VKPvPQqRXRLxcTNlm7aRQ1yFlSBmeQrqZj+QCRVGU=", + "ciphertext": "s+qA/aWLlbtSsqPQpQysbQz+Suwnra9eLpJF1bJcWBn1xbPLNRByT+z1ncdn06pCHj7eJA==" + }, + { + "cmu": "npLzMFgYOTAslBHrkwEofAwvkNZ80RWWBSMrpWPB5D0=", + "epk": "GNpX8XJWgbbcrbV0x9naGIkHJfOhuGBuo5OlWxT62wQ=", + "ciphertext": "1w6sDrGWy27RAB81z70MCb2G3YWjEgGOQYWeH216q4sKem84tWH4dIEafukQcqpGX93Ktg==" + }, + { + "cmu": "CHz9V1wjfR8LCo3gaPXuyxIhh3eA8z/cucJtQxgf5D4=", + "epk": "O1Ukp6Gv5xd0bXLsX/aCIVNv3fkmIEqpUg07w67whYA=", + "ciphertext": "k2ebMJIMA8WhUdD1rVufZ1ehgIyIUjGA8HmN7EAjfAp8KU9MfLKN404RZaQC+FcY8NkDtw==" + }, + { + "cmu": "MQG8MNa7fXcC/WF4MeTyMfIsRc3E8gPDe/CWZo8xnU4=", + "epk": "l9QrAN7lyINAJxc8uMf9wX+0oVG5ruknFsjtjmDOrT4=", + "ciphertext": "EBi7d8Q33+4Nz34ZeyE+7izGI21Ba0U+AugeDDI8r9Vf2cPYvxl5/CsCyFW91A/sHi9t7A==" + }, + { + "cmu": "PxITydpG/pMAsgrxRXM8ylMRtGMy0MPJhKALDxJJFwY=", + "epk": "ry0fhSAlFQqOB91kLP6XEqbX447ct/S6o2aiPGcbeVg=", + "ciphertext": "hZk+4VaUaMDQz6g36ppvVKMVTq9zG2GnIIKZDMbvMf5WQvQpQDm1dUPt+WsIgYGuQmnDgg==" + }, + { + "cmu": "muM0yJrqWZT1b3+9piM/i66CBzCPOr+PGJzrRGZpglo=", + "epk": "wsGCqOfgOdPP9GR2EqO1aJmA/KB5tcy+PI8vwFAXsqE=", + "ciphertext": "TM2Z6Vt/MQQEpydgMbvIXG7Nqkg8DLuiU/zISQt8baltJFVTMqiydanDCR/+J5jEsC5VPQ==" + }, + { + "cmu": "xMRO3QgRQO6k3wg1PuGxheNEmPkAp0cBMuDLk/PcrDw=", + "epk": "vQfDmbE1JFKNxbh8A0iV+PKTJtyO7xubXhg/I6zpdGo=", + "ciphertext": "4nbbsemy8YN4Law1Ooe77bIhg6+TDjXAwgH+bdiwoKVSzXZ2+FVwM3g5sFWhNcHaO0sDoQ==" + }, + { + "cmu": "fOVVMnjTN3W2TOTvHX4RYcu4HwiCVukOeJXXDAokby4=", + "epk": "gdPjy0EiwrD0qTIYUUntiS6Z0ZUktRieH497uaNjsl4=", + "ciphertext": "mg/iwK35oWhAeMRp42RHrBKBJurVgvmlIDcqRu+MvRqbNK9FqYqHq+pEPgw6qQuhdF6M5Q==" + }, + { + "cmu": "ajEncXhf9smStzVw2NXAydh1N46J57lK0bUMNJakfFo=", + "epk": "fjpRLcm/PqYATl0hNj34rR2FtH1HAFqLxKy+7x64V0k=", + "ciphertext": "AXdpeP7BuWf6SItRZcqPWN8cfoB3CkoHm+Oms9toUdTudqt9ghV5dpWlQBRsj4g9iKIMDQ==" + }, + { + "cmu": "j61KniLmCQm2vPRA0Q6UAySRQcHUMt25caEnYGSV5EY=", + "epk": "LOGRN+Z09n6JTs4yAsNAKUPihz1pT/tFvZo0KZeE9XI=", + "ciphertext": "Hf6WjiF2Fb09fhE2p0NlrryKZ/bqo7x/3FOLVnkHbZdumwgBzZGkIWWtyP8VWZC9ZP4DIw==" + }, + { + "cmu": "5nvWU5AFkgyV1W5+sMC4DtI+1aXjr7JKZa1tsUJNfWo=", + "epk": "9JyoTabNgT4ubm41JKfNfXqdXclMA9XkkSfAhFgJ0fM=", + "ciphertext": "m/UQN0NF1rNaHFuVtnlozMObortVe0ifOLemspYPa6yV7U3JDS1S1qpR24tB5FNNe53Bgg==" + }, + { + "cmu": "2Ma+4scQHnBND1L9E8cqjdxHM74MW0h/JW6rlLdkoQg=", + "epk": "tWBmy9nrsAFnwdF8yxncTFExijVKLK8q8me3U5SQC5Y=", + "ciphertext": "a3uRmEnzjawHd9nYSm5pnUwSZSsorO/wGDo7UEhLyPp/kzyi6YoaGidTJSIl1/4bxzIfUQ==" + }, + { + "cmu": "zPaZobHdFVI4TfaT+TmcMsFig/W51rhT2tz6H0ZRgQg=", + "epk": "LpY8MyiDDy2jPMOSbOv194xfDZ5Z3Xr93EQekwQgaBM=", + "ciphertext": "pt4m9/OZ8xT8+Uicq+8u3FUC1g0uHanvSnVwe/4v+Q9G4t+EpvRaTzabJnhnTrjderK1Dw==" + }, + { + "cmu": "SqoG3Ed0vMa7E+PDGmcqk4WfzLWg+QAi+SVu056fXAw=", + "epk": "WUb8Ph8L1azOj4whylR5tslzFgLCaOvh0jLEVWpXfKw=", + "ciphertext": "dlyUSRq3s5FKnJSxH6isifa5c/uNUSBGB10wIa/gVg6Su5fwQTNX8+itWi4DXVfOBsDlkQ==" + }, + { + "cmu": "6ziiozJWC3w8tDNRT8yMPVwxz+O4BMCHx9fkGZneZkQ=", + "epk": "AIrr5M9ZttQo/qYBUZXXb2wQsi3QlK3yHjCtJKuKq1E=", + "ciphertext": "X8+UciR7erWeVGBpCbVndiik70u64lwF957uoaYPeFczwJn8CnIsei9UR/1rOX8snV2WaA==" + }, + { + "cmu": "Fr2ouG4ALnC+MXULWHvCCPmhyqkZvwhKeTjkobWFyUc=", + "epk": "2PfOVHfqa119Ev6AHqKxY6qOlnCG1hH7uc+5UhZuLa8=", + "ciphertext": "cQY8ERO4Im5DBoR8S3xv+G7jMb32B3/diAqTrmonuCZ+sZ8WysoZH5lmKUUR/6q89KGTbQ==" + }, + { + "cmu": "+fceksbSp432bMi7DfQ+EzmVFMgIpNEvARGe1uP75FI=", + "epk": "sMPliTLCDKC6IJMtxph2BPTK8ARBnu6waNTnFb9cOro=", + "ciphertext": "5hFHnprHLNOEMKfUuE5dQXaGZVnU6xGkghKrMpPgT0MoH7SDV7IqElrdkrvvGcA4dv49hw==" + }, + { + "cmu": "LWaeR1duyMLIJEhIRDyd5G43QSLk+cDfC2Ms302QFWY=", + "epk": "UTBjSuTBW0RVXBtUWAycJHK7E0safekjUc3gmPQl/DY=", + "ciphertext": "r2R1MutBzm0Tlcy5OcRi6m5GLoU37QmPo7qcK5WYXKi71akwN+haZwywqWfQniuXsZejFw==" + }, + { + "cmu": "v0DIELPm61QWfpA2yMjhzB3lfsuv5pwrURYUA4ZRnlc=", + "epk": "38GO3ICoCwDfHB5X0aG1X5kf3qUmL9rFvAwmKhzyp4U=", + "ciphertext": "3c/aBLqBIQ7SRbPeuzsQmmVa0MPMVfpJvA3APA9jcO/lq05kE1+lWpjQ6Azm3QhkThQgmA==" + }, + { + "cmu": "dueYI5RTJSLWtPXvDbceNumMiQMLv/CL+tGxYIkfLSE=", + "epk": "H22FHObuc8OScdI7DzfWXh0aDQs8tp8Q3jkFvIKVkTk=", + "ciphertext": "1wAC+JPocn6ozHT3z8nBVAgFy6Vp66ABhkdKwRHzmZaPKFdcmkPr2RWq+JBWSy3+JsO+Yg==" + }, + { + "cmu": "2VNHa9subwzI7JzxcE8hen5NNtxZSlT2bzTaWO415EQ=", + "epk": "uAHdMx0ruE7PdpemTgzeuuNAtS50wap1Goci7RUK3A4=", + "ciphertext": "AEDClLtf1ktD7q5cKHdjHSXcMmxOv25WQodw71qLs5SC5+tDJSzld8mzO8Hy74WxFa2iYA==" + }, + { + "cmu": "J9rf9X+ZQQw7taB5xb6t+AOKfZUlTmAS7tvMn1AB8Qs=", + "epk": "MFJ1Ub001MFHizD/N9+iDUeK/PD/sN1E2l+dQnwuuMg=", + "ciphertext": "EuRFeMZFgDKRtr47LgJFZbPdvnsMWjuHkIJuJCERI1+jAPqh6khVT02MbH++Lhksn5pL7Q==" + }, + { + "cmu": "nElUteBtFCOw4B3UsymyEshO7Q08Ue5IGnlwmr9dSxg=", + "epk": "JhhEwo7HRy4sOzL2A0TMuU6A8y8n7M7eFLi++Ylpo58=", + "ciphertext": "BKQgmsMt1MQ2QI1Rh3nxr8y5nAuyEM+AuJ0sltPaut3TINEgteiewFmb7lqYLCTbyZ5vPw==" + }, + { + "cmu": "6vZcIu5uEbhg4hh5qHyhPQAdMhgplRqxBfsiZEKt0E0=", + "epk": "ShtuX8idXED/5WVBtlBM1zw6iGgkh7FnnConOFOKi2E=", + "ciphertext": "A285d0QxfVkBkwnvwPe52eOFOTVLAjZbzZXsd9DvHl5t4ZZecuvwbgbsgp0eve1b8vhoFg==" + }, + { + "cmu": "cOd0ukq/z4X4gb7fzux2Bof47/gao5O7JtJ28Vu3fyk=", + "epk": "uJsGwdHcQMnv1DTurcZ/7J+PDbYQvEYLthUuX8/eyoY=", + "ciphertext": "3L5u5MnqKqM/7g7eBiwKU3mDbVP939iSSmf3XD7u7bezTWIUuRh2RLnw4rZ+mvJGTP1EAA==" + }, + { + "cmu": "9+esE4hGGso/3AEmbnRVWx1m4OWsSVoi885Fr3hn1Tw=", + "epk": "S8yq9FyDYfJpWW6/QFQveoO3YU4q9umhyoRljMEzJTs=", + "ciphertext": "+yxpsKMMITmmNI250gH2k9vrH5TGLcQcIucF7lzBWOu6oxwbxWCMd79TInVEZhUHOmH0IA==" + }, + { + "cmu": "tXNJTSYqLWLmr6jcE1U8rOeChSHnKWfv4VK5LrUCAhw=", + "epk": "68O8M83PzasWuXaChW20h0gEAKUR2Op6yoT/pUSKykM=", + "ciphertext": "6dIocQ2QL73+nGCbE2thQ7zMo6nmNmzXVLHtm7ukF9+XDIcov1Svorydg3KD/I7PMmSR+w==" + }, + { + "cmu": "fkLqxd4sA+TQeEkmdwXG5sPjQZIXE1lPJr4NEhFAaj4=", + "epk": "yRBDNZuQ5TJJsw8fGz4SF/tPev9MWJ1NxoHforlp/DE=", + "ciphertext": "GKBY7y2/7v8k9wYde82MkqtEJHi5mtjVDwlmbNNy4R1O7CcvhTbnyhPCDe7uGHKFuIUOOA==" + }, + { + "cmu": "c9sDBpofH8y69NNnRa6aVgimXHKvGaoT+Kyzr2SqjlI=", + "epk": "RCUC1uJfpkBphbrV/QsC/PIs/WiMa2f/NFHi+WLPnsM=", + "ciphertext": "EyN4dji+W3rt50d4qwFGPJEfpIi5rm1EU7f6cq+kco12THqeuOTNBm5+8odka9VBzIWFVA==" + }, + { + "cmu": "sL1IqSzMeZR1sPCB+C2pWwDMOTg4J1czNs/emZeu2Uw=", + "epk": "rBFwAdROGhwrOhm2tTDjDuVMsLtWAfQP/u/vIlVU5XE=", + "ciphertext": "sM3Btuq9o+thqiETaKA7viF54EwNvDKppjcbMa4gdlP89lbdCv2MRD3T9Ob9n9G2dmt8wA==" + } + ] + } + ] +} diff --git a/Tests/TestUtils/Stubs.swift b/Tests/TestUtils/Stubs.swift index 9c6f99cc2..7fb7be1e1 100644 --- a/Tests/TestUtils/Stubs.swift +++ b/Tests/TestUtils/Stubs.swift @@ -11,7 +11,7 @@ import GRPC import SwiftProtobuf @testable import ZcashLightClientKit -// swiftlint:disable function_parameter_count identifier_name +// swiftlint:disable function_parameter_count identifier_name type_body_length class AwfulLightWalletService: MockLightWalletService { override func latestBlockHeight() throws -> BlockHeight { throw LightWalletServiceError.criticalError @@ -56,13 +56,58 @@ extension LightWalletServiceMockResponse { // swiftlint:disable:next type_body_length class MockRustBackend: ZcashRustBackendWelding { + static var networkType = NetworkType.testnet + static var mockDataDb = false + static var mockAcounts = false + static var mockError: RustWeldingError? + static var mockLastError: String? + static var mockAccounts: [SaplingExtendedSpendingKey]? + static var mockAddresses: [String]? + static var mockBalance: Int64? + static var mockVerifiedBalance: Int64? + static var mockMemo: String? + static var mockSentMemo: String? + static var mockValidateCombinedChainSuccessRate: Float? + static var mockValidateCombinedChainFailAfterAttempts: Int? + static var mockValidateCombinedChainKeepFailing = false + static var mockValidateCombinedChainFailureHeight: BlockHeight = 0 + static var mockScanblocksSuccessRate: Float? + static var mockCreateToAddress: Int64? + static var rustBackend = ZcashRustBackend.self + static var consensusBranchID: Int32? + static var writeBlocksMetadataResult: () throws -> Bool = { true } + static var rewindCacheToHeightResult: () -> Bool = { true } + static func latestCachedBlockHeight(fsBlockDbRoot: URL) -> ZcashLightClientKit.BlockHeight { + .empty() + } + + static func rewindCacheToHeight(fsBlockDbRoot: URL, height: Int32) -> Bool { + rewindCacheToHeightResult() + } + + static func initBlockMetadataDb(fsBlockDbRoot: URL) throws -> Bool { + true + } + + static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashLightClientKit.ZcashCompactBlock]) throws -> Bool { + try writeBlocksMetadataResult() + } + static func initAccountsTable(dbData: URL, ufvks: [ZcashLightClientKit.UnifiedFullViewingKey], networkType: ZcashLightClientKit.NetworkType) throws { } static func createToAddress(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, to address: String, value: Int64, memo: ZcashLightClientKit.MemoBytes?, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 { -1 } - static func shieldFunds(dbCache: URL, dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, memo: ZcashLightClientKit.MemoBytes?, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 { + static func shieldFunds( + dbData: URL, + usk: ZcashLightClientKit.UnifiedSpendingKey, + memo: ZcashLightClientKit.MemoBytes?, + shieldingThreshold: Zatoshi, + spendParamsPath: String, + outputParamsPath: String, + networkType: ZcashLightClientKit.NetworkType + ) -> Int64 { -1 } @@ -106,7 +151,7 @@ class MockRustBackend: ZcashRustBackendWelding { throw KeyDerivationErrors.unableToDerive } - static func shieldFunds(dbCache: URL, dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, memo: ZcashLightClientKit.MemoBytes, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 { + static func shieldFunds(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, memo: ZcashLightClientKit.MemoBytes, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 { -1 } @@ -206,27 +251,7 @@ class MockRustBackend: ZcashRustBackendWelding { } return consensus } - - static var networkType = NetworkType.testnet - static var mockDataDb = false - static var mockAcounts = false - static var mockError: RustWeldingError? - static var mockLastError: String? - static var mockAccounts: [SaplingExtendedSpendingKey]? - static var mockAddresses: [String]? - static var mockBalance: Int64? - static var mockVerifiedBalance: Int64? - static var mockMemo: String? - static var mockSentMemo: String? - static var mockValidateCombinedChainSuccessRate: Float? - static var mockValidateCombinedChainFailAfterAttempts: Int? - static var mockValidateCombinedChainKeepFailing = false - static var mockValidateCombinedChainFailureHeight: BlockHeight = 0 - static var mockScanblocksSuccessRate: Float? - static var mockCreateToAddress: Int64? - static var rustBackend = ZcashRustBackend.self - static var consensusBranchID: Int32? - + static func lastError() -> RustWeldingError? { mockError ?? rustBackend.lastError() } @@ -292,35 +317,35 @@ class MockRustBackend: ZcashRustBackendWelding { mockSentMemo ?? getSentMemoAsUTF8(dbData: dbData, idNote: idNote, networkType: networkType) } - static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 { + static func validateCombinedChain(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType, limit: UInt32 = 0) -> Int32 { if let rate = self.mockValidateCombinedChainSuccessRate { if shouldSucceed(successRate: rate) { - return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType) + return validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType) } else { return Int32(mockValidateCombinedChainFailureHeight) } } else if let attempts = self.mockValidateCombinedChainFailAfterAttempts { self.mockValidateCombinedChainFailAfterAttempts = attempts - 1 if attempts > 0 { - return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType) + return validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType) } else { if attempts == 0 { return Int32(mockValidateCombinedChainFailureHeight) } else if attempts < 0 && mockValidateCombinedChainKeepFailing { return Int32(mockValidateCombinedChainFailureHeight) } else { - return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType) + return validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType) } } } - return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData, networkType: networkType) + return rustBackend.validateCombinedChain(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType) } - private static func validationResult(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 { + private static func validationResult(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType) -> Int32 { if mockDataDb { return -1 } else { - return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData, networkType: networkType) + return rustBackend.validateCombinedChain(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType) } } @@ -328,15 +353,15 @@ class MockRustBackend: ZcashRustBackendWelding { mockDataDb ? true : rustBackend.rewindToHeight(dbData: dbData, height: height, networkType: networkType) } - static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool { + static func scanBlocks(fsBlockDbRoot: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool { if let rate = mockScanblocksSuccessRate { if shouldSucceed(successRate: rate) { - return mockDataDb ? true : rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData, networkType: networkType) + return mockDataDb ? true : rustBackend.scanBlocks(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType) } else { return false } } - return rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData, networkType: Self.networkType) + return rustBackend.scanBlocks(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: Self.networkType) } static func createToAddress( diff --git a/Tests/TestUtils/TestCoordinator.swift b/Tests/TestUtils/TestCoordinator.swift index be3cd2e21..4f1801bdf 100644 --- a/Tests/TestUtils/TestCoordinator.swift +++ b/Tests/TestUtils/TestCoordinator.swift @@ -9,13 +9,12 @@ import Foundation import XCTest @testable import ZcashLightClientKit -/** -This is the TestCoordinator -What does it do? quite a lot. -Is it a nice "SOLID" "Clean Code" piece of source code? -Hell no. It's your testing overlord and you will be grateful it is. -*/ // swiftlint:disable force_try function_parameter_count + +/// This is the TestCoordinator +/// What does it do? quite a lot. +/// Is it a nice "SOLID" "Clean Code" piece of source code? +/// Hell no. It's your testing overlord and you will be grateful it is. class TestCoordinator { enum CoordinatorError: Error { case notDarksideWallet @@ -93,13 +92,23 @@ class TestCoordinator { streamingCallTimeout: 1000000 ) ) - let storage = CompactBlockStorage(url: databases.cacheDB, readonly: false) - try storage.createTable() - + + let realRustBackend = ZcashRustBackend.self + + let storage = FSCompactBlockRepository( + cacheDirectory: self.databases.fsCacheDbRoot, + metadataStore: .live( + fsBlockDbRoot: self.databases.fsCacheDbRoot, + rustBackend: ZcashRustBackend.self + ), + blockDescriptor: .live, + contentProvider: DirectoryListingProviders.defaultSorted + ) + let buildResult = try TestSynchronizerBuilder.build( - rustBackend: ZcashRustBackend.self, + rustBackend: realRustBackend, lowerBoundHeight: self.birthday, - cacheDbURL: databases.cacheDB, + fsBlockDbRoot: databases.fsCacheDbRoot, dataDbURL: databases.dataDB, pendingDbURL: databases.pendingDB, endpoint: LightWalletEndpointBuilder.default, @@ -152,9 +161,8 @@ class TestCoordinator { try synchronizer.start(retry: true) } - /** - Notifications - */ + // MARK: notifications + func subscribeToNotifications(synchronizer: Synchronizer) { NotificationCenter.default.addObserver(self, selector: #selector(synchronizerFailed(_:)), name: .synchronizerFailed, object: synchronizer) NotificationCenter.default.addObserver(self, selector: #selector(synchronizerSynced(_:)), name: .synchronizerSynced, object: synchronizer) @@ -233,7 +241,7 @@ extension TestCoordinator { let config = await self.synchronizer.blockProcessor.config let newConfig = CompactBlockProcessor.Configuration( - cacheDb: config.cacheDb, + fsBlockCacheRoot: config.fsBlockCacheRoot, dataDb: config.dataDb, spendParamsURL: config.spendParamsURL, outputParamsURL: config.outputParamsURL, @@ -258,7 +266,7 @@ extension TestCoordinator { } struct TemporaryTestDatabases { - var cacheDB: URL + var fsCacheDbRoot: URL var dataDB: URL var pendingDB: URL } @@ -269,7 +277,7 @@ enum TemporaryDbBuilder { let timestamp = String(Int(Date().timeIntervalSince1970)) return TemporaryTestDatabases( - cacheDB: tempUrl.appendingPathComponent("cache_db_\(timestamp).db"), + fsCacheDbRoot: tempUrl.appendingPathComponent("fs_cache_\(timestamp)"), dataDB: tempUrl.appendingPathComponent("data_db_\(timestamp).db"), pendingDB: tempUrl.appendingPathComponent("pending_db_\(timestamp).db") ) @@ -280,14 +288,14 @@ enum TestSynchronizerBuilder { static func build( rustBackend: ZcashRustBackendWelding.Type, lowerBoundHeight: BlockHeight, - cacheDbURL: URL, + fsBlockDbRoot: URL, dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, service: LightWalletService, repository: TransactionRepository, accountRepository: AccountRepository, - storage: CompactBlockStorage, + storage: CompactBlockRepository, spendParamsURL: URL, outputParamsURL: URL, spendingKey: UnifiedSpendingKey, @@ -298,7 +306,7 @@ enum TestSynchronizerBuilder { loggerProxy: Logger? = nil ) throws -> (spendingKeys: [UnifiedSpendingKey]?, synchronizer: SDKSynchronizer) { let initializer = Initializer( - cacheDbURL: cacheDbURL, + fsBlockDbRoot: fsBlockDbRoot, dataDbURL: dataDbURL, pendingDbURL: pendingDbURL, endpoint: endpoint, @@ -322,14 +330,14 @@ enum TestSynchronizerBuilder { static func build( rustBackend: ZcashRustBackendWelding.Type, lowerBoundHeight: BlockHeight, - cacheDbURL: URL, + fsBlockDbRoot: URL, dataDbURL: URL, pendingDbURL: URL, endpoint: LightWalletEndpoint, service: LightWalletService, repository: TransactionRepository, accountRepository: AccountRepository, - storage: CompactBlockStorage, + storage: CompactBlockRepository, spendParamsURL: URL, outputParamsURL: URL, seedBytes: [UInt8], @@ -346,7 +354,7 @@ enum TestSynchronizerBuilder { return try build( rustBackend: rustBackend, lowerBoundHeight: lowerBoundHeight, - cacheDbURL: cacheDbURL, + fsBlockDbRoot: fsBlockDbRoot, dataDbURL: dataDbURL, pendingDbURL: pendingDbURL, endpoint: endpoint, diff --git a/Tests/TestUtils/TestDbBuilder.swift b/Tests/TestUtils/TestDbBuilder.swift index c6aab99aa..1ed085561 100644 --- a/Tests/TestUtils/TestDbBuilder.swift +++ b/Tests/TestUtils/TestDbBuilder.swift @@ -43,27 +43,9 @@ class TestDbBuilder { case generalError } - static func inMemoryCompactBlockStorage() throws -> CompactBlockStorage { - let compactBlockDao = CompactBlockStorage(connectionProvider: try InMemoryDbProvider()) - try compactBlockDao.createTable() - - return compactBlockDao - } - - static func diskCompactBlockStorage(at url: URL) throws -> CompactBlockStorage { - let compactBlockDao = CompactBlockStorage(connectionProvider: SimpleConnectionProvider(path: url.absoluteString)) - try compactBlockDao.createTable() - - return compactBlockDao - } - static func pendingTransactionsDbURL() throws -> URL { try __documentsDirectory().appendingPathComponent("pending.db") } - - static func prePopulatedCacheDbURL() -> URL? { - Bundle.module.url(forResource: "cache", withExtension: "db") - } static func prePopulatedDataDbURL() -> URL? { Bundle.module.url(forResource: "test_data", withExtension: "db") @@ -73,6 +55,10 @@ class TestDbBuilder { Bundle.module.url(forResource: "darkside_data", withExtension: "db") } + static func prePopulatedDarksideCacheDb() -> URL? { + Bundle.module.url(forResource: "darkside_caches", withExtension: "db") + } + static func prepopulatedDataDbProvider() throws -> ConnectionProvider? { guard let url = prePopulatedMainnetDataDbURL() else { return nil } @@ -87,7 +73,7 @@ class TestDbBuilder { switch initResult { case .success: return provider case .seedRequired: - throw StorageError.migrationFailedWithMessage(message: "Seed value required to initialize the wallet database") + throw DatabaseStorageError.migrationFailedWithMessage(message: "Seed value required to initialize the wallet database") } } @@ -139,12 +125,22 @@ class InMemoryDbProvider: ConnectionProvider { } enum StubBlockCreator { + static func createRandomBlockMeta() -> ZcashCompactBlock.Meta { + ZcashCompactBlock.Meta( + // swiftlint:disable:next force_unwrapping + hash: randomData(ofLength: 32)!, + time: UInt32(Date().timeIntervalSince1970), + saplingOutputs: UInt32.random(in: 0 ... 32), + orchardOutputs: UInt32.random(in: 0 ... 32) + ) + } + static func createRandomDataBlock(with height: BlockHeight) -> ZcashCompactBlock? { guard let data = randomData(ofLength: 100) else { LoggerProxy.debug("error creating stub block") return nil } - return ZcashCompactBlock(height: height, data: data) + return ZcashCompactBlock(height: height, data: data, meta: createRandomBlockMeta()) } static func createBlockRange(_ range: CompactBlockRange) -> [ZcashCompactBlock]? { diff --git a/Tests/TestUtils/Tests+Utils.swift b/Tests/TestUtils/Tests+Utils.swift index 40f6924d9..e480b66f5 100644 --- a/Tests/TestUtils/Tests+Utils.swift +++ b/Tests/TestUtils/Tests+Utils.swift @@ -86,10 +86,6 @@ func __documentsDirectory() throws -> URL { try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) } -func __cacheDbURL() throws -> URL { - try __documentsDirectory().appendingPathComponent("cache.db", isDirectory: false) -} - func __dataDbURL() throws -> URL { try __documentsDirectory().appendingPathComponent("data.db", isDirectory: false) }