react-native-zcash 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (427) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +22 -0
  3. package/README.md +44 -44
  4. package/android/build.gradle +1 -1
  5. package/ios/RNZcash.m +0 -1
  6. package/ios/RNZcash.swift +14 -15
  7. package/ios/ZCashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift +123 -0
  8. package/ios/ZCashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift +222 -0
  9. package/ios/ZCashLightClientKit/Block/DatabaseStorage/StorageError.swift +22 -0
  10. package/ios/ZCashLightClientKit/Block/DatabaseStorage/StorageManager.swift +73 -0
  11. package/ios/ZCashLightClientKit/Block/Downloader/BlockDownloader.swift +240 -0
  12. package/ios/ZCashLightClientKit/Block/Downloader/CompactBlockDownloaderBuilder.swift +26 -0
  13. package/ios/ZCashLightClientKit/Block/Processor/CompactBlockDownloadOperation.swift +258 -0
  14. package/ios/ZCashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift +157 -0
  15. package/ios/ZCashLightClientKit/Block/Processor/CompactBlockProcessor.swift +1454 -0
  16. package/ios/ZCashLightClientKit/Block/Processor/CompactBlockScanningOperation.swift +238 -0
  17. package/ios/ZCashLightClientKit/Block/Processor/CompactBlockValidationInformation.swift +66 -0
  18. package/ios/ZCashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift +103 -0
  19. package/ios/ZCashLightClientKit/Block/Processor/FigureNextBatchOperation.swift +58 -0
  20. package/ios/ZCashLightClientKit/Block/Processor/ZcashOperation.swift +68 -0
  21. package/ios/ZCashLightClientKit/Constants/WalletBirthday+Constants.swift +58 -0
  22. package/ios/ZCashLightClientKit/Constants/WalletBirthday+mainnet.swift +20 -0
  23. package/ios/ZCashLightClientKit/Constants/WalletBirthday+testnet.swift +20 -0
  24. package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +245 -0
  25. package/ios/ZCashLightClientKit/DAO/BlockDao.swift +67 -0
  26. package/ios/ZCashLightClientKit/DAO/CompactBlockDAO.swift +24 -0
  27. package/ios/ZCashLightClientKit/DAO/NotesDao.swift +142 -0
  28. package/ios/ZCashLightClientKit/DAO/PagedTransactionDao.swift +62 -0
  29. package/ios/ZCashLightClientKit/DAO/PendingTransactionDao.swift +213 -0
  30. package/ios/ZCashLightClientKit/DAO/TransactionBuilder.swift +169 -0
  31. package/ios/ZCashLightClientKit/DAO/TransactionDao.swift +393 -0
  32. package/ios/ZCashLightClientKit/DAO/UnspentTransactionOutputDao.swift +188 -0
  33. package/ios/ZCashLightClientKit/Entity/AccountEntity.swift +201 -0
  34. package/ios/ZCashLightClientKit/Entity/CompactBlockEntity.swift +13 -0
  35. package/ios/ZCashLightClientKit/Entity/EncodedTransactionEntity.swift +26 -0
  36. package/ios/ZCashLightClientKit/Entity/PendingTransactionEntity.swift +205 -0
  37. package/ios/ZCashLightClientKit/Entity/ReceivedNoteEntity.swift +22 -0
  38. package/ios/ZCashLightClientKit/Entity/SentNoteEntity.swift +45 -0
  39. package/ios/ZCashLightClientKit/Entity/TransactionEntity.swift +161 -0
  40. package/ios/ZCashLightClientKit/Entity/UnspentTransactionOutputEntity.swift +17 -0
  41. package/ios/ZCashLightClientKit/Extensions/Data+Zcash.swift +17 -0
  42. package/ios/ZCashLightClientKit/Extensions/Data+internal.swift +35 -0
  43. package/ios/ZCashLightClientKit/Extensions/HexEncode.swift +41 -0
  44. package/ios/ZCashLightClientKit/Extensions/ZcashRust+Utils.swift +26 -0
  45. package/ios/ZCashLightClientKit/Extensions/ZcashSDK+extensions.swift +34 -0
  46. package/ios/ZCashLightClientKit/Initializer.swift +357 -0
  47. package/ios/ZCashLightClientKit/Model/WalletTypes.swift +108 -0
  48. package/ios/ZCashLightClientKit/Providers/ResourceProvider.swift +47 -0
  49. package/ios/ZCashLightClientKit/Repository/BlockRepository.swift +13 -0
  50. package/ios/ZCashLightClientKit/Repository/CompactBlockRepository.swift +75 -0
  51. package/ios/ZCashLightClientKit/Repository/NotesRepository.swift +16 -0
  52. package/ios/ZCashLightClientKit/Repository/PaginatedTransactionRepository.swift +35 -0
  53. package/ios/ZCashLightClientKit/Repository/PendingTransactionRepository.swift +19 -0
  54. package/ios/ZCashLightClientKit/Repository/TransactionRepository.swift +30 -0
  55. package/ios/ZCashLightClientKit/Repository/TransactionRepositoryBuilder.swift +24 -0
  56. package/ios/ZCashLightClientKit/Repository/UnspentTransactionOutputRepository.swift +18 -0
  57. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1000000.json +7 -0
  58. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1010000.json +7 -0
  59. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1020000.json +7 -0
  60. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1030000.json +7 -0
  61. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1040000.json +7 -0
  62. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1050000.json +7 -0
  63. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1060000.json +7 -0
  64. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1070000.json +7 -0
  65. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1080000.json +7 -0
  66. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1090000.json +7 -0
  67. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1100000.json +7 -0
  68. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1110000.json +7 -0
  69. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1120000.json +7 -0
  70. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1130000.json +7 -0
  71. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1140000.json +7 -0
  72. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1150000.json +7 -0
  73. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1160000.json +7 -0
  74. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1170000.json +7 -0
  75. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1180000.json +7 -0
  76. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1190000.json +7 -0
  77. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1200000.json +7 -0
  78. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1210000.json +7 -0
  79. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1220000.json +7 -0
  80. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1230000.json +7 -0
  81. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1240000.json +7 -0
  82. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1250000.json +7 -0
  83. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1260000.json +7 -0
  84. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1270000.json +7 -0
  85. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1280000.json +7 -0
  86. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1290000.json +7 -0
  87. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1300000.json +7 -0
  88. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1310000.json +7 -0
  89. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1320000.json +7 -0
  90. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1330000.json +7 -0
  91. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1340000.json +7 -0
  92. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1350000.json +7 -0
  93. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1360000.json +7 -0
  94. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1370000.json +7 -0
  95. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1380000.json +7 -0
  96. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1390000.json +7 -0
  97. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1400000.json +7 -0
  98. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1410000.json +7 -0
  99. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1420000.json +7 -0
  100. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1430000.json +7 -0
  101. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1440000.json +7 -0
  102. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1450000.json +7 -0
  103. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1460000.json +7 -0
  104. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1470000.json +7 -0
  105. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1480000.json +7 -0
  106. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1490000.json +7 -0
  107. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1500000.json +7 -0
  108. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1510000.json +7 -0
  109. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1520000.json +7 -0
  110. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1530000.json +7 -0
  111. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1540000.json +7 -0
  112. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1550000.json +7 -0
  113. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1560000.json +7 -0
  114. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1570000.json +7 -0
  115. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1580000.json +7 -0
  116. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1590000.json +7 -0
  117. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1600000.json +7 -0
  118. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1610000.json +7 -0
  119. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1620000.json +7 -0
  120. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1630000.json +7 -0
  121. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1640000.json +7 -0
  122. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1650000.json +7 -0
  123. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1660000.json +7 -0
  124. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1670000.json +7 -0
  125. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1680000.json +7 -0
  126. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1690000.json +7 -0
  127. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1700000.json +7 -0
  128. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1710000.json +7 -0
  129. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1720000.json +7 -0
  130. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1730000.json +7 -0
  131. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1740000.json +7 -0
  132. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1750000.json +7 -0
  133. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1760000.json +7 -0
  134. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1770000.json +7 -0
  135. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1780000.json +7 -0
  136. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1790000.json +7 -0
  137. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1800000.json +7 -0
  138. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1810000.json +7 -0
  139. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1820000.json +7 -0
  140. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1830000.json +7 -0
  141. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1840000.json +7 -0
  142. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1850000.json +7 -0
  143. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1860000.json +7 -0
  144. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1870000.json +7 -0
  145. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1880000.json +7 -0
  146. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1890000.json +7 -0
  147. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1900000.json +7 -0
  148. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1910000.json +7 -0
  149. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1920000.json +7 -0
  150. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1930000.json +7 -0
  151. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1940000.json +7 -0
  152. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1950000.json +7 -0
  153. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1960000.json +7 -0
  154. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1970000.json +7 -0
  155. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1980000.json +7 -0
  156. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/1990000.json +7 -0
  157. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2000000.json +7 -0
  158. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2010000.json +7 -0
  159. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2020000.json +7 -0
  160. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2030000.json +7 -0
  161. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2040000.json +7 -0
  162. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2050000.json +7 -0
  163. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2060000.json +7 -0
  164. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2070000.json +7 -0
  165. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2080000.json +7 -0
  166. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2090000.json +7 -0
  167. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2100000.json +7 -0
  168. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2110000.json +7 -0
  169. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2120000.json +7 -0
  170. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2130000.json +7 -0
  171. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2140000.json +7 -0
  172. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2150000.json +7 -0
  173. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2160000.json +7 -0
  174. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/2170000.json +7 -0
  175. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/419200.json +7 -0
  176. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/500000.json +7 -0
  177. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/510000.json +7 -0
  178. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/520000.json +7 -0
  179. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/530000.json +7 -0
  180. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/540000.json +7 -0
  181. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/550000.json +7 -0
  182. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/560000.json +7 -0
  183. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/570000.json +7 -0
  184. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/580000.json +7 -0
  185. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/590000.json +7 -0
  186. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/600000.json +7 -0
  187. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/610000.json +7 -0
  188. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/620000.json +7 -0
  189. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/630000.json +7 -0
  190. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/640000.json +7 -0
  191. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/650000.json +7 -0
  192. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/660000.json +7 -0
  193. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/663150.json +8 -0
  194. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/670000.json +7 -0
  195. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/680000.json +7 -0
  196. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/690000.json +7 -0
  197. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/700000.json +7 -0
  198. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/710000.json +7 -0
  199. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/720000.json +7 -0
  200. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/730000.json +7 -0
  201. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/740000.json +7 -0
  202. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/750000.json +7 -0
  203. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/760000.json +7 -0
  204. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/770000.json +7 -0
  205. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/780000.json +7 -0
  206. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/790000.json +7 -0
  207. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/800000.json +7 -0
  208. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/810000.json +7 -0
  209. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/820000.json +7 -0
  210. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/830000.json +7 -0
  211. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/840000.json +7 -0
  212. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/850000.json +7 -0
  213. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/860000.json +7 -0
  214. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/870000.json +7 -0
  215. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/880000.json +7 -0
  216. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/890000.json +7 -0
  217. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/900000.json +7 -0
  218. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/910000.json +7 -0
  219. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/920000.json +7 -0
  220. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/930000.json +7 -0
  221. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/940000.json +7 -0
  222. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/950000.json +7 -0
  223. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/960000.json +7 -0
  224. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/970000.json +7 -0
  225. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/980000.json +7 -0
  226. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/mainnet/990000.json +7 -0
  227. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1000000.json +7 -0
  228. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1010000.json +7 -0
  229. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1020000.json +7 -0
  230. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1030000.json +7 -0
  231. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1040000.json +7 -0
  232. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1050000.json +7 -0
  233. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1060000.json +7 -0
  234. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1070000.json +7 -0
  235. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1080000.json +7 -0
  236. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1090000.json +7 -0
  237. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1100000.json +7 -0
  238. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1110000.json +7 -0
  239. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1120000.json +7 -0
  240. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1130000.json +7 -0
  241. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1140000.json +7 -0
  242. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1150000.json +7 -0
  243. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1160000.json +7 -0
  244. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1170000.json +7 -0
  245. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1180000.json +7 -0
  246. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1190000.json +7 -0
  247. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1200000.json +7 -0
  248. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1210000.json +7 -0
  249. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1220000.json +7 -0
  250. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1230000.json +7 -0
  251. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1240000.json +7 -0
  252. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1250000.json +7 -0
  253. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1260000.json +7 -0
  254. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1270000.json +7 -0
  255. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1280000.json +7 -0
  256. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1290000.json +7 -0
  257. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1300000.json +7 -0
  258. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1310000.json +7 -0
  259. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1320000.json +7 -0
  260. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1330000.json +7 -0
  261. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1340000.json +7 -0
  262. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1350000.json +7 -0
  263. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1360000.json +7 -0
  264. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1370000.json +7 -0
  265. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1380000.json +7 -0
  266. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1390000.json +7 -0
  267. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1400000.json +7 -0
  268. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1410000.json +7 -0
  269. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1420000.json +7 -0
  270. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1430000.json +7 -0
  271. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1440000.json +7 -0
  272. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1450000.json +7 -0
  273. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1460000.json +7 -0
  274. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1470000.json +7 -0
  275. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1480000.json +7 -0
  276. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1490000.json +7 -0
  277. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1500000.json +7 -0
  278. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1510000.json +7 -0
  279. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1520000.json +7 -0
  280. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1530000.json +7 -0
  281. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1540000.json +7 -0
  282. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1550000.json +7 -0
  283. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1560000.json +7 -0
  284. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1570000.json +7 -0
  285. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1580000.json +7 -0
  286. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1590000.json +7 -0
  287. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1600000.json +7 -0
  288. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1610000.json +7 -0
  289. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1620000.json +7 -0
  290. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1630000.json +7 -0
  291. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1640000.json +7 -0
  292. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1650000.json +7 -0
  293. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1660000.json +7 -0
  294. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1670000.json +7 -0
  295. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1680000.json +7 -0
  296. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1690000.json +7 -0
  297. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1700000.json +7 -0
  298. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1710000.json +7 -0
  299. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1720000.json +7 -0
  300. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1730000.json +7 -0
  301. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1740000.json +7 -0
  302. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1750000.json +7 -0
  303. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1760000.json +7 -0
  304. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1770000.json +7 -0
  305. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1780000.json +7 -0
  306. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1790000.json +7 -0
  307. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1800000.json +7 -0
  308. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1810000.json +7 -0
  309. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1820000.json +7 -0
  310. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1830000.json +7 -0
  311. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1840000.json +7 -0
  312. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1850000.json +7 -0
  313. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/1860000.json +7 -0
  314. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/280000.json +7 -0
  315. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/290000.json +7 -0
  316. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/300000.json +7 -0
  317. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/310000.json +7 -0
  318. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/320000.json +7 -0
  319. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/330000.json +7 -0
  320. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/340000.json +7 -0
  321. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/350000.json +7 -0
  322. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/360000.json +7 -0
  323. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/370000.json +7 -0
  324. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/380000.json +7 -0
  325. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/390000.json +7 -0
  326. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/400000.json +7 -0
  327. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/410000.json +7 -0
  328. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/420000.json +7 -0
  329. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/430000.json +7 -0
  330. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/440000.json +7 -0
  331. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/450000.json +7 -0
  332. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/460000.json +7 -0
  333. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/470000.json +7 -0
  334. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/480000.json +7 -0
  335. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/490000.json +7 -0
  336. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/500000.json +7 -0
  337. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/510000.json +7 -0
  338. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/520000.json +7 -0
  339. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/530000.json +7 -0
  340. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/540000.json +7 -0
  341. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/550000.json +7 -0
  342. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/560000.json +7 -0
  343. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/570000.json +7 -0
  344. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/580000.json +7 -0
  345. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/590000.json +7 -0
  346. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/600000.json +7 -0
  347. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/610000.json +7 -0
  348. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/620000.json +7 -0
  349. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/630000.json +7 -0
  350. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/640000.json +7 -0
  351. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/650000.json +7 -0
  352. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/660000.json +7 -0
  353. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/670000.json +7 -0
  354. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/680000.json +7 -0
  355. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/690000.json +7 -0
  356. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/700000.json +7 -0
  357. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/710000.json +7 -0
  358. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/720000.json +7 -0
  359. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/730000.json +7 -0
  360. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/740000.json +7 -0
  361. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/750000.json +7 -0
  362. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/760000.json +7 -0
  363. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/770000.json +7 -0
  364. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/780000.json +7 -0
  365. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/790000.json +7 -0
  366. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/800000.json +7 -0
  367. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/810000.json +7 -0
  368. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/820000.json +7 -0
  369. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/830000.json +7 -0
  370. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/840000.json +7 -0
  371. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/850000.json +7 -0
  372. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/860000.json +7 -0
  373. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/870000.json +7 -0
  374. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/880000.json +7 -0
  375. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/890000.json +7 -0
  376. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/900000.json +7 -0
  377. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/910000.json +7 -0
  378. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/920000.json +7 -0
  379. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/930000.json +7 -0
  380. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/940000.json +7 -0
  381. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/950000.json +7 -0
  382. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/960000.json +7 -0
  383. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/970000.json +7 -0
  384. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/980000.json +7 -0
  385. package/ios/ZCashLightClientKit/Resources/saplingtree-checkpoints/testnet/990000.json +7 -0
  386. package/ios/ZCashLightClientKit/Rust/ZcashRustBackend.swift +718 -0
  387. package/ios/ZCashLightClientKit/Rust/ZcashRustBackendWelding.swift +389 -0
  388. package/ios/ZCashLightClientKit/Rust/zcashlc.h +385 -0
  389. package/ios/ZCashLightClientKit/Service/LightWalletGRPCService.swift +551 -0
  390. package/ios/ZCashLightClientKit/Service/LightWalletService.swift +214 -0
  391. package/ios/ZCashLightClientKit/Service/Model/ZcashCompactBlock.swift +46 -0
  392. package/ios/ZCashLightClientKit/Service/ProtoBuf/Extensions/Protocolbuffer+Extensions.swift +50 -0
  393. package/ios/ZCashLightClientKit/Service/ProtoBuf/compact_formats.pb.swift +332 -0
  394. package/ios/ZCashLightClientKit/Service/ProtoBuf/proto/compact_formats.proto +56 -0
  395. package/ios/ZCashLightClientKit/Service/ProtoBuf/proto/service.proto +180 -0
  396. package/ios/ZCashLightClientKit/Service/ProtoBuf/service.grpc.swift +383 -0
  397. package/ios/ZCashLightClientKit/Service/ProtoBuf/service.pb.swift +1173 -0
  398. package/ios/ZCashLightClientKit/Synchronizer/SDKSynchronizer.swift +929 -0
  399. package/ios/ZCashLightClientKit/Synchronizer.swift +430 -0
  400. package/ios/ZCashLightClientKit/Tool/DerivationTool.swift +344 -0
  401. package/ios/ZCashLightClientKit/Transaction/PersistentTransactionManager.swift +339 -0
  402. package/ios/ZCashLightClientKit/Transaction/TransactionEncoder.swift +116 -0
  403. package/ios/ZCashLightClientKit/Transaction/TransactionManager.swift +42 -0
  404. package/ios/ZCashLightClientKit/Transaction/WalletTransactionEncoder.swift +216 -0
  405. package/ios/ZCashLightClientKit/Utils/Bundle+module.swift +30 -0
  406. package/ios/ZCashLightClientKit/Utils/LoggingProxy.swift +47 -0
  407. package/ios/ZCashLightClientKit/Utils/SaplingParameterDownloader.swift +124 -0
  408. package/ios/libzcashlc.xcframework/Info.plist +40 -0
  409. package/ios/libzcashlc.xcframework/ios-arm64/libzcashlc.a +0 -0
  410. package/ios/libzcashlc.xcframework/ios-arm64_x86_64-simulator/libzcashlc.a +0 -0
  411. package/ios/react-native-zcash-Bridging-Header.h +2 -0
  412. package/ios/react-native-zcash.xcodeproj/project.pbxproj +1 -0
  413. package/lib/scripts/copyCheckpoints.d.ts +5 -0
  414. package/lib/scripts/updateSources.d.ts +1 -0
  415. package/package.json +20 -37
  416. package/react-native-zcash.podspec +17 -7
  417. package/ios/RNZcash-Bridging-Header.h +0 -6
  418. package/ios/RNZcash.xcodeproj/project.pbxproj +0 -271
  419. package/ios/RNZcash.xcworkspace/contents.xcworkspacedata +0 -7
  420. package/ios/RNZcash.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  421. package/lib/src/browser.d.ts +0 -0
  422. package/lib/src/index.d.ts +0 -0
  423. package/lib/test/test.test.d.ts +0 -0
  424. package/scripts/copyCheckpoints.js +0 -12
  425. package/src/browser.ts +0 -36
  426. package/src/index.flow.js +0 -168
  427. package/src/index.ts +0 -1
@@ -0,0 +1,1454 @@
1
+ //
2
+ // CompactBlockProcessor.swift
3
+ // ZcashLightClientKit
4
+ //
5
+ // Created by Francisco Gindre on 18/09/2019.
6
+ // Copyright © 2019 Electric Coin Company. All rights reserved.
7
+ //
8
+ // swiftlint:disable file_length type_body_length
9
+
10
+ import Foundation
11
+ import GRPC
12
+
13
+ public typealias RefreshedUTXOs = (inserted: [UnspentTransactionOutputEntity], skipped: [UnspentTransactionOutputEntity])
14
+
15
+ /**
16
+ Errors thrown by CompactBlock Processor
17
+ */
18
+ public enum CompactBlockProcessorError: Error {
19
+ case invalidConfiguration
20
+ case missingDbPath(path: String)
21
+ case dataDbInitFailed(path: String)
22
+ case connectionError(underlyingError: Error)
23
+ case grpcError(statusCode: Int, message: String)
24
+ case connectionTimeout
25
+ case generalError(message: String)
26
+ case maxAttemptsReached(attempts: Int)
27
+ case unspecifiedError(underlyingError: Error)
28
+ case criticalError
29
+ case invalidAccount
30
+ case wrongConsensusBranchId(expectedLocally: ConsensusBranchID, found: ConsensusBranchID)
31
+ case networkMismatch(expected: NetworkType, found: NetworkType)
32
+ case saplingActivationMismatch(expected: BlockHeight, found: BlockHeight)
33
+ }
34
+
35
+ /**
36
+ CompactBlockProcessor notification userInfo object keys.
37
+ check Notification.Name extensions for more details.
38
+ */
39
+ public enum CompactBlockProcessorNotificationKey {
40
+ public static let progress = "CompactBlockProcessorNotificationKey.progress"
41
+ // public static let progressStartHeight = "CompactBlockProcessorNotificationKey.progressStartHeight"
42
+ // public static let progressTargetHeight = "CompactBlockProcessorNotificationKey.progressTargetHeight"
43
+ public static let progressBlockTime = "CompactBlockProcessorNotificationKey.progressBlockTime"
44
+ public static let reorgHeight = "CompactBlockProcessorNotificationKey.reorgHeight"
45
+ public static let latestScannedBlockHeight = "CompactBlockProcessorNotificationKey.latestScannedBlockHeight"
46
+ public static let rewindHeight = "CompactBlockProcessorNotificationKey.rewindHeight"
47
+ public static let foundTransactions = "CompactBlockProcessorNotificationKey.foundTransactions"
48
+ public static let foundBlocks = "CompactBlockProcessorNotificationKey.foundBlocks"
49
+ public static let foundTransactionsRange = "CompactBlockProcessorNotificationKey.foundTransactionsRange"
50
+ public static let error = "error"
51
+ public static let refreshedUTXOs = "CompactBlockProcessorNotificationKey.refreshedUTXOs"
52
+ public static let enhancementProgress = "CompactBlockProcessorNotificationKey.enhancementProgress"
53
+ public static let previousStatus = "CompactBlockProcessorNotificationKey.previousStatus"
54
+ public static let newStatus = "CompactBlockProcessorNotificationKey.newStatus"
55
+ public static let currentConnectivityStatus = "CompactBlockProcessorNotificationKey.currentConnectivityStatus"
56
+ public static let previousConnectivityStatus = "CompactBlockProcessorNotificationKey.previousConnectivityStatus"
57
+ }
58
+
59
+ public enum CompactBlockProgress {
60
+ case download(_ progress: BlockProgress)
61
+ case validate
62
+ case scan(_ progress: BlockProgress)
63
+ case enhance(_ progress: EnhancementStreamProgress)
64
+ case fetch
65
+
66
+ public var progress: Float {
67
+ switch self {
68
+ case .download(let blockProgress), .scan(let blockProgress):
69
+ return blockProgress.progress
70
+ case .enhance(let enhancementProgress):
71
+ return enhancementProgress.progress
72
+ default:
73
+ return 0
74
+ }
75
+ }
76
+
77
+ public var progressHeight: BlockHeight? {
78
+ switch self {
79
+ case .download(let blockProgress), .scan(let blockProgress):
80
+ return blockProgress.progressHeight
81
+ case .enhance(let enhancementProgress):
82
+ return enhancementProgress.lastFoundTransaction?.minedHeight
83
+ default:
84
+ return 0
85
+ }
86
+ }
87
+
88
+ public var blockDate: Date? {
89
+ if case .enhance(let enhancementProgress) = self, let time = enhancementProgress.lastFoundTransaction?.blockTimeInSeconds {
90
+ return Date(timeIntervalSince1970: time)
91
+ }
92
+
93
+ return nil
94
+ }
95
+
96
+ public var targetHeight: BlockHeight? {
97
+ switch self {
98
+ case .download(let blockProgress), .scan(let blockProgress):
99
+ return blockProgress.targetHeight
100
+ default:
101
+ return nil
102
+ }
103
+ }
104
+ }
105
+
106
+ protocol EnhancementStreamDelegate: AnyObject {
107
+ func transactionEnhancementProgressUpdated(_ progress: EnhancementProgress)
108
+ }
109
+
110
+ public protocol EnhancementProgress {
111
+ var totalTransactions: Int { get }
112
+ var enhancedTransactions: Int { get }
113
+ var lastFoundTransaction: ConfirmedTransactionEntity? { get }
114
+ var range: CompactBlockRange { get }
115
+ }
116
+
117
+ public struct EnhancementStreamProgress: EnhancementProgress {
118
+ public var totalTransactions: Int
119
+ public var enhancedTransactions: Int
120
+ public var lastFoundTransaction: ConfirmedTransactionEntity?
121
+ public var range: CompactBlockRange
122
+
123
+ public var progress: Float {
124
+ totalTransactions > 0 ? Float(enhancedTransactions) / Float(totalTransactions) : 0
125
+ }
126
+ }
127
+
128
+ public extension Notification.Name {
129
+ /**
130
+ Processing progress update
131
+
132
+ Query the userInfo object for the key CompactBlockProcessorNotificationKey.progress for a CompactBlockProgress struct
133
+ */
134
+ static let blockProcessorUpdated = Notification.Name(rawValue: "CompactBlockProcessorUpdated")
135
+
136
+ /**
137
+ notification sent when processor status changed
138
+ */
139
+ static let blockProcessorStatusChanged = Notification.Name(rawValue: "CompactBlockProcessorStatusChanged")
140
+
141
+ /**
142
+ Notification sent when a compact block processor starts downloading
143
+ */
144
+
145
+ static let blockProcessorStartedDownloading = Notification.Name(rawValue: "CompactBlockProcessorStartedDownloading")
146
+ /**
147
+ Notification sent when the compact block processor starts validating the chain state
148
+ */
149
+
150
+ static let blockProcessorStartedValidating = Notification.Name(rawValue: "CompactBlockProcessorStartedValidating")
151
+ /**
152
+ Notification sent when the compact block processor starts scanning blocks from the cache
153
+ */
154
+ static let blockProcessorStartedScanning = Notification.Name(rawValue: "CompactBlockProcessorStartedScanning")
155
+
156
+ /**
157
+ Notification sent when the compact block processor stop() method is called
158
+ */
159
+ static let blockProcessorStopped = Notification.Name(rawValue: "CompactBlockProcessorStopped")
160
+
161
+ /**
162
+ Notification sent when the compact block processor presented an error.
163
+
164
+ Query userInfo object on the key CompactBlockProcessorNotificationKey.error
165
+ */
166
+ static let blockProcessorFailed = Notification.Name(rawValue: "CompactBlockProcessorFailed")
167
+
168
+ /**
169
+ Notification sent when the compact block processor has finished syncing the blockchain to latest height
170
+ */
171
+ static let blockProcessorFinished = Notification.Name(rawValue: "CompactBlockProcessorFinished")
172
+
173
+ /**
174
+ Notification sent when the compact block processor is doing nothing
175
+ */
176
+ static let blockProcessorIdle = Notification.Name(rawValue: "CompactBlockProcessorIdle")
177
+
178
+ /**
179
+ Notification sent when something odd happened. probably going from a state to another state that shouldn't be the next state.
180
+ */
181
+ static let blockProcessorUnknownTransition = Notification.Name(rawValue: "CompactBlockProcessorTransitionUnknown")
182
+
183
+ /**
184
+ Notification sent when the compact block processor handled a ReOrg.
185
+
186
+ 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
187
+ */
188
+ static let blockProcessorHandledReOrg = Notification.Name(rawValue: "CompactBlockProcessorHandledReOrg")
189
+
190
+ /**
191
+ Notification sent when the compact block processor enhanced a bunch of transactions
192
+ Query the user info object for CompactBlockProcessorNotificationKey.foundTransactions which will contain an [ConfirmedTransactionEntity] Array with the found transactions and CompactBlockProcessorNotificationKey.foundTransactionsrange
193
+ */
194
+ static let blockProcessorFoundTransactions = Notification.Name(rawValue: "CompactBlockProcessorFoundTransactions")
195
+
196
+ /**
197
+ Notification sent when the compact block processor fetched utxos from lightwalletd attempted to store them
198
+ Query the user info object for CompactBlockProcessorNotificationKey.blockProcessorStoredUTXOs which will contain a RefreshedUTXOs tuple with the collection of UTXOs stored or skipped
199
+ */
200
+ static let blockProcessorStoredUTXOs = Notification.Name(rawValue: "CompactBlockProcessorStoredUTXOs")
201
+
202
+ static let blockProcessorStartedEnhancing = Notification.Name(rawValue: "CompactBlockProcessorStartedEnhancing")
203
+
204
+ static let blockProcessorEnhancementProgress = Notification.Name("CompactBlockProcessorEnhancementProgress")
205
+
206
+ static let blockProcessorStartedFetching = Notification.Name(rawValue: "CompactBlockProcessorStartedFetching")
207
+
208
+ /**
209
+ 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`
210
+ */
211
+ static let blockProcessorConnectivityStateChanged = Notification.Name("CompactBlockProcessorConnectivityStateChanged")
212
+ }
213
+
214
+ /**
215
+ The compact block processor is in charge of orchestrating the download and caching of compact blocks from a LightWalletEndpoint
216
+ when started the processor downloads does a download - validate - scan cycle until it reaches latest height on the blockchain.
217
+ */
218
+ public class CompactBlockProcessor {
219
+ /**
220
+ Compact Block Processor configuration
221
+
222
+ Property: cacheDbPath absolute file path of the DB where raw, unprocessed compact blocks are stored.
223
+ Property: dataDbPath absolute file path of the DB where all information derived from the cache DB is stored.
224
+ */
225
+ public struct Configuration {
226
+ public var cacheDb: URL
227
+ public var dataDb: URL
228
+ public var downloadBatchSize = ZcashSDK.DefaultBatchSize
229
+ public var retries = ZcashSDK.defaultRetries
230
+ public var maxBackoffInterval = ZcashSDK.defaultMaxBackOffInterval
231
+ public var rewindDistance = ZcashSDK.defaultRewindDistance
232
+ public var walletBirthday: BlockHeight
233
+
234
+ private(set) var network: ZcashNetwork
235
+ private(set) var saplingActivation: BlockHeight
236
+
237
+ public var blockPollInterval: TimeInterval {
238
+ TimeInterval.random(in: ZcashSDK.defaultPollInterval / 2 ... ZcashSDK.defaultPollInterval * 1.5)
239
+ }
240
+
241
+ init (
242
+ cacheDb: URL,
243
+ dataDb: URL,
244
+ downloadBatchSize: Int,
245
+ retries: Int,
246
+ maxBackoffInterval: TimeInterval,
247
+ rewindDistance: Int,
248
+ walletBirthday: BlockHeight,
249
+ saplingActivation: BlockHeight,
250
+ network: ZcashNetwork
251
+ ) {
252
+ self.cacheDb = cacheDb
253
+ self.dataDb = dataDb
254
+ self.network = network
255
+ self.downloadBatchSize = downloadBatchSize
256
+ self.retries = retries
257
+ self.maxBackoffInterval = maxBackoffInterval
258
+ self.rewindDistance = rewindDistance
259
+ self.walletBirthday = walletBirthday
260
+ self.saplingActivation = saplingActivation
261
+ }
262
+
263
+ public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight, network: ZcashNetwork) {
264
+ self.cacheDb = cacheDb
265
+ self.dataDb = dataDb
266
+ self.walletBirthday = walletBirthday
267
+ self.saplingActivation = network.constants.saplingActivationHeight
268
+ self.network = network
269
+ }
270
+ }
271
+
272
+ /**
273
+ Represents the possible states of a CompactBlockProcessor
274
+ */
275
+ public enum State {
276
+ /**
277
+ connected and downloading blocks
278
+ */
279
+ case downloading
280
+
281
+ /**
282
+ was doing something but was paused
283
+ */
284
+ case stopped
285
+
286
+ /**
287
+ processor is validating
288
+ */
289
+ case validating
290
+
291
+ /**
292
+ processor is scanning
293
+ */
294
+ case scanning
295
+
296
+ /**
297
+ Processor is Enhancing transactions
298
+ */
299
+ case enhancing
300
+
301
+ /**
302
+ fetching utxos
303
+ */
304
+ case fetching
305
+
306
+ /**
307
+ was processing but erred
308
+ */
309
+ case error(_ e: Error)
310
+
311
+ /**
312
+ Processor is up to date with the blockchain and you can now make transactions.
313
+ */
314
+ case synced
315
+ }
316
+
317
+ public private(set) var state: State = .stopped {
318
+ didSet {
319
+ transitionState(from: oldValue, to: self.state)
320
+ }
321
+ }
322
+
323
+ var config: Configuration {
324
+ willSet {
325
+ self.stop()
326
+ }
327
+ }
328
+ var maxAttemptsReached: Bool {
329
+ self.retryAttempts >= self.config.retries
330
+ }
331
+ var shouldStart: Bool {
332
+ switch self.state {
333
+ case .stopped, .synced, .error:
334
+ return !maxAttemptsReached
335
+ default:
336
+ return false
337
+ }
338
+ }
339
+
340
+ private var service: LightWalletService
341
+ private var downloader: CompactBlockDownloading
342
+ private var storage: CompactBlockStorage
343
+ private var transactionRepository: TransactionRepository
344
+ private var accountRepository: AccountRepository
345
+ private var rustBackend: ZcashRustBackendWelding.Type
346
+ private var retryAttempts: Int = 0
347
+ private var backoffTimer: Timer?
348
+ private var lowerBoundHeight: BlockHeight?
349
+ private var latestBlockHeight: BlockHeight
350
+ private var lastChainValidationFailure: BlockHeight?
351
+ private var consecutiveChainValidationErrors: Int = 0
352
+ private var processingError: Error?
353
+ private var foundBlocks = false
354
+ private var maxAttempts: Int {
355
+ config.retries
356
+ }
357
+
358
+ private var batchSize: BlockHeight {
359
+ BlockHeight(self.config.downloadBatchSize)
360
+ }
361
+
362
+ private var operationQueue: OperationQueue = {
363
+ let queue = OperationQueue()
364
+ queue.name = "CompactBlockProcessorQueue"
365
+ queue.maxConcurrentOperationCount = 1
366
+ return queue
367
+ }()
368
+
369
+ /**
370
+ Initializes a CompactBlockProcessor instance
371
+ - Parameters:
372
+ - downloader: an instance that complies to CompactBlockDownloading protocol
373
+ - backend: a class that complies to ZcashRustBackendWelding
374
+ */
375
+ convenience init(
376
+ service: LightWalletService,
377
+ storage: CompactBlockStorage,
378
+ backend: ZcashRustBackendWelding.Type,
379
+ config: Configuration
380
+ ) {
381
+ self.init(
382
+ service: service,
383
+ storage: storage,
384
+ backend: backend,
385
+ config: config,
386
+ repository: TransactionRepositoryBuilder.build(
387
+ dataDbURL: config.dataDb
388
+ ),
389
+ accountRepository: AccountRepositoryBuilder.build(dataDbURL: config.dataDb, readOnly: true)
390
+ )
391
+ }
392
+
393
+ /**
394
+ Initializes a CompactBlockProcessor instance from an Initialized object
395
+ - Parameters:
396
+ - initializer: an instance that complies to CompactBlockDownloading protocol
397
+ */
398
+ public convenience init(initializer: Initializer) {
399
+ self.init(
400
+ service: initializer.lightWalletService,
401
+ storage: initializer.storage,
402
+ backend: initializer.rustBackend,
403
+ config: Configuration(
404
+ cacheDb: initializer.cacheDbURL,
405
+ dataDb: initializer.dataDbURL,
406
+ walletBirthday: initializer.walletBirthday.height,
407
+ network: initializer.network
408
+ ),
409
+ repository: initializer.transactionRepository,
410
+ accountRepository: initializer.accountRepository
411
+ )
412
+ }
413
+
414
+ internal init(
415
+ service: LightWalletService,
416
+ storage: CompactBlockStorage,
417
+ backend: ZcashRustBackendWelding.Type,
418
+ config: Configuration,
419
+ repository: TransactionRepository,
420
+ accountRepository: AccountRepository
421
+ ) {
422
+ self.service = service
423
+ self.downloader = CompactBlockDownloader(service: service, storage: storage)
424
+ self.rustBackend = backend
425
+ self.storage = storage
426
+ self.config = config
427
+ self.transactionRepository = repository
428
+ self.latestBlockHeight = config.walletBirthday
429
+ self.accountRepository = accountRepository
430
+ }
431
+
432
+ deinit {
433
+ self.operationQueue.cancelAllOperations()
434
+ }
435
+
436
+ static func validateServerInfo(
437
+ _ info: LightWalletdInfo,
438
+ saplingActivation: BlockHeight,
439
+ localNetwork: ZcashNetwork,
440
+ rustBackend: ZcashRustBackendWelding.Type
441
+ ) throws {
442
+ // check network types
443
+ guard let remoteNetworkType = NetworkType.forChainName(info.chainName) else {
444
+ throw CompactBlockProcessorError.generalError(
445
+ message: "Chain name does not match. Expected either 'test' or 'main' but received '\(info.chainName)'." +
446
+ "this is probably an API or programming error"
447
+ )
448
+ }
449
+
450
+ guard remoteNetworkType == localNetwork.networkType else {
451
+ throw CompactBlockProcessorError.networkMismatch(expected: localNetwork.networkType, found: remoteNetworkType)
452
+ }
453
+
454
+ guard saplingActivation == info.saplingActivationHeight else {
455
+ throw CompactBlockProcessorError.saplingActivationMismatch(expected: saplingActivation, found: BlockHeight(info.saplingActivationHeight))
456
+ }
457
+
458
+ // check branch id
459
+ let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight), networkType: localNetwork.networkType)
460
+
461
+ guard let remoteBranchID = ConsensusBranchID.fromString(info.consensusBranchID) else {
462
+ throw CompactBlockProcessorError.generalError(message: "Consensus BranchIDs don't match this is probably an API or programming error")
463
+ }
464
+
465
+ guard remoteBranchID == localBranch else {
466
+ throw CompactBlockProcessorError.wrongConsensusBranchId(expectedLocally: localBranch, found: remoteBranchID)
467
+ }
468
+ }
469
+
470
+ static func nextBatchBlockRange(latestHeight: BlockHeight, latestDownloadedHeight: BlockHeight, walletBirthday: BlockHeight) -> CompactBlockRange {
471
+ let lowerBound = latestDownloadedHeight <= walletBirthday ? walletBirthday : latestDownloadedHeight + 1
472
+
473
+ let upperBound = latestHeight
474
+ return lowerBound ... upperBound
475
+ }
476
+
477
+ /**
478
+ Starts the CompactBlockProcessor instance and starts downloading and processing blocks
479
+
480
+ triggers the blockProcessorStartedDownloading notification
481
+
482
+ - Important: subscribe to the notifications before calling this method
483
+
484
+ */
485
+ public func start(retry: Bool = false) throws {
486
+ // TODO: check if this validation makes sense at all
487
+ // try validateConfiguration()
488
+ if retry {
489
+ self.retryAttempts = 0
490
+ self.processingError = nil
491
+ self.backoffTimer?.invalidate()
492
+ self.backoffTimer = nil
493
+ }
494
+ guard !operationQueue.isSuspended else {
495
+ LoggerProxy.debug("restarting suspended queue")
496
+ operationQueue.isSuspended = false
497
+ return
498
+ }
499
+
500
+ guard shouldStart else {
501
+ switch self.state {
502
+ case .error(let e):
503
+ // max attempts have been reached
504
+ LoggerProxy.info("max retry attempts reached with error: \(e)")
505
+ notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.maxAttempts))
506
+ self.state = .stopped
507
+ case .stopped:
508
+ // max attempts have been reached
509
+ LoggerProxy.info("max retry attempts reached")
510
+ notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.maxAttempts))
511
+ case .synced:
512
+ // max attempts have been reached
513
+ LoggerProxy.warn("max retry attempts reached on synced state, this indicates malfunction")
514
+ notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.maxAttempts))
515
+ default:
516
+ LoggerProxy.debug("Warning: compact block processor was started while busy!!!!")
517
+ }
518
+ return
519
+ }
520
+
521
+ self.nextBatch()
522
+ }
523
+
524
+ /**
525
+ Stops the CompactBlockProcessor
526
+
527
+ Note: retry count is reset
528
+ - Parameter cancelTasks: cancel the pending tasks. Defaults to true
529
+ */
530
+ public func stop(cancelTasks: Bool = true) {
531
+ self.backoffTimer?.invalidate()
532
+ self.backoffTimer = nil
533
+
534
+ if cancelTasks {
535
+ operationQueue.cancelAllOperations()
536
+ } else {
537
+ self.operationQueue.isSuspended = true
538
+ }
539
+
540
+ self.retryAttempts = 0
541
+ self.state = .stopped
542
+ }
543
+
544
+ /**
545
+ Rewinds to provided height.
546
+ If nil is provided, it will rescan to nearest height (quick rescan)
547
+ */
548
+ public func rewindTo(_ height: BlockHeight?) throws -> BlockHeight {
549
+ self.stop()
550
+
551
+ let lastDownloaded = try downloader.lastDownloadedBlockHeight()
552
+ let height = Int32(height ?? lastDownloaded)
553
+ let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height, networkType: self.config.network.networkType)
554
+
555
+ guard nearestHeight > 0 else {
556
+ let error = rustBackend.lastError() ?? RustWeldingError.genericError(
557
+ message: "unknown error getting nearest rewind height for height: \(height)"
558
+ )
559
+ fail(error)
560
+ throw error
561
+ }
562
+
563
+ // FIXME: this should be done on the rust layer
564
+ let rewindHeight = max(Int32(nearestHeight - 1), Int32(config.walletBirthday))
565
+ guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network.networkType) else {
566
+ let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)")
567
+ fail(error)
568
+ throw error
569
+ }
570
+
571
+ // clear cache
572
+ try downloader.rewind(to: BlockHeight(rewindHeight))
573
+ self.lastChainValidationFailure = nil
574
+ self.lowerBoundHeight = try? downloader.lastDownloadedBlockHeight()
575
+ return BlockHeight(rewindHeight)
576
+ }
577
+ /**
578
+ changes the wallet birthday in configuration. Use this method when wallet birthday is not available and the processor can't be lazy initialized.
579
+ - Note: this does not rewind your chain state
580
+ - Parameter startHeight: the wallet birthday for this compact block processor
581
+ - Throws CompactBlockProcessorError.invalidConfiguration if block height is invalid or if processor is already started
582
+ */
583
+ func setStartHeight(_ startHeight: BlockHeight) throws {
584
+ guard self.state == .stopped, startHeight >= config.network.constants.saplingActivationHeight else {
585
+ throw CompactBlockProcessorError.invalidConfiguration
586
+ }
587
+
588
+ var config = self.config
589
+ config.walletBirthday = startHeight
590
+ self.config = config
591
+ }
592
+
593
+ func validateServer(completionBlock: @escaping (() -> Void)) {
594
+ self.service.getInfo(result: { [weak self] result in
595
+ guard let self = self else { return }
596
+
597
+ switch result {
598
+ case .success(let info):
599
+ DispatchQueue.main.async { [weak self] in
600
+ guard let self = self else { return }
601
+ do {
602
+ try Self.validateServerInfo(
603
+ info,
604
+ saplingActivation: self.config.saplingActivation,
605
+ localNetwork: self.config.network,
606
+ rustBackend: self.rustBackend
607
+ )
608
+ completionBlock()
609
+ } catch {
610
+ self.severeFailure(error)
611
+ }
612
+ }
613
+ case .failure(let error):
614
+ self.severeFailure(error.mapToProcessorError())
615
+ }
616
+ })
617
+ }
618
+
619
+ /**
620
+ processes new blocks on the given range based on the configuration set for this instance
621
+ the way operations are queued is implemented based on the following good practice https://forums.developer.apple.com/thread/25761
622
+
623
+ */
624
+ // swiftlint:disable cyclomatic_complexity
625
+ func processNewBlocks(range: CompactBlockRange) {
626
+ self.foundBlocks = true
627
+ self.backoffTimer?.invalidate()
628
+ self.backoffTimer = nil
629
+
630
+ let cfg = self.config
631
+
632
+ let downloadBlockOperation = CompactBlockBatchDownloadOperation(
633
+ service: self.service,
634
+ storage: self.storage,
635
+ startHeight: range.lowerBound,
636
+ targetHeight: range.upperBound,
637
+ progressDelegate: self
638
+ )
639
+
640
+ downloadBlockOperation.startedHandler = { [weak self] in
641
+ DispatchQueue.main.async {
642
+ self?.state = .downloading
643
+ }
644
+ }
645
+
646
+ downloadBlockOperation.errorHandler = { [weak self] error in
647
+ DispatchQueue.main.async {
648
+ guard let self = self else { return }
649
+ self.processingError = error
650
+ self.fail(error)
651
+ }
652
+ }
653
+
654
+ let validateChainOperation = CompactBlockValidationOperation(
655
+ rustWelding: self.rustBackend,
656
+ cacheDb: cfg.cacheDb,
657
+ dataDb: cfg.dataDb,
658
+ networkType: self.config.network.networkType
659
+ )
660
+
661
+ let downloadValidateAdapterOperation = BlockOperation { [weak validateChainOperation, weak downloadBlockOperation] in
662
+ validateChainOperation?.error = downloadBlockOperation?.error
663
+ }
664
+
665
+ validateChainOperation.completionHandler = { [weak self] _, cancelled in
666
+ guard !cancelled else {
667
+ DispatchQueue.main.async {
668
+ self?.state = .stopped
669
+ LoggerProxy.debug("Warning: validateChainOperation operation cancelled")
670
+ }
671
+ return
672
+ }
673
+
674
+ LoggerProxy.debug("validateChainFinished")
675
+ }
676
+
677
+ validateChainOperation.errorHandler = { [weak self] error in
678
+ DispatchQueue.main.async { [weak self] in
679
+ guard let self = self else { return }
680
+
681
+ guard let validationError = error as? CompactBlockValidationError else {
682
+ LoggerProxy.error("Warning: validateChain operation returning generic error: \(error)")
683
+ return
684
+ }
685
+
686
+ switch validationError {
687
+ case .validationFailed(let height):
688
+ LoggerProxy.debug("chain validation at height: \(height)")
689
+ self.validationFailed(at: height)
690
+ case .failedWithError(let e):
691
+ guard let validationFailure = e else {
692
+ LoggerProxy.error("validation failed without a specific error")
693
+ self.fail(CompactBlockProcessorError.generalError(message: "validation failed without a specific error"))
694
+ return
695
+ }
696
+
697
+ self.fail(validationFailure)
698
+ }
699
+ }
700
+ }
701
+
702
+ validateChainOperation.startedHandler = { [weak self] in
703
+ DispatchQueue.main.async { [weak self] in
704
+ self?.state = .validating
705
+ }
706
+ }
707
+
708
+ let scanBlocksOperation = CompactBlockBatchScanningOperation(
709
+ rustWelding: rustBackend,
710
+ cacheDb: config.cacheDb,
711
+ dataDb: config.dataDb,
712
+ transactionRepository: transactionRepository,
713
+ range: range,
714
+ networkType: self.config.network.networkType,
715
+ progressDelegate: self
716
+ )
717
+
718
+ let validateScanningAdapterOperation = BlockOperation { [weak scanBlocksOperation, weak validateChainOperation] in
719
+ scanBlocksOperation?.error = validateChainOperation?.error
720
+ }
721
+
722
+ scanBlocksOperation.startedHandler = { [weak self] in
723
+ DispatchQueue.main.async { [weak self] in
724
+ self?.state = .scanning
725
+ }
726
+ }
727
+
728
+ scanBlocksOperation.completionHandler = { [weak self] _, cancelled in
729
+ guard !cancelled else {
730
+ DispatchQueue.main.async { [weak self] in
731
+ self?.state = .stopped
732
+ LoggerProxy.debug("Warning: scanBlocksOperation operation cancelled")
733
+ }
734
+ return
735
+ }
736
+ }
737
+
738
+ scanBlocksOperation.errorHandler = { [weak self] error in
739
+ DispatchQueue.main.async { [weak self] in
740
+ guard let self = self else { return }
741
+ self.processingError = error
742
+ self.fail(error)
743
+ }
744
+ }
745
+
746
+ let enhanceOperation = CompactBlockEnhancementOperation(
747
+ rustWelding: rustBackend,
748
+ dataDb: config.dataDb,
749
+ downloader: downloader,
750
+ repository: transactionRepository,
751
+ range: range.blockRange(),
752
+ networkType: self.config.network.networkType
753
+ )
754
+
755
+ enhanceOperation.startedHandler = {
756
+ LoggerProxy.debug("Started Enhancing range: \(range)")
757
+ DispatchQueue.main.async { [weak self] in
758
+ self?.state = .enhancing
759
+ }
760
+ }
761
+
762
+ enhanceOperation.txFoundHandler = { [weak self] txs, range in
763
+ self?.notifyTransactions(txs, in: range)
764
+ }
765
+
766
+ enhanceOperation.completionHandler = { _, cancelled in
767
+ guard !cancelled else {
768
+ LoggerProxy.debug("Warning: enhance operation on range \(range) cancelled")
769
+ return
770
+ }
771
+ }
772
+
773
+ enhanceOperation.errorHandler = { [weak self] error in
774
+ DispatchQueue.main.async { [weak self] in
775
+ guard let self = self else { return }
776
+
777
+ self.processingError = error
778
+ self.fail(error)
779
+ }
780
+ }
781
+
782
+ let scanEnhanceAdapterOperation = BlockOperation { [weak enhanceOperation, weak scanBlocksOperation] in
783
+ enhanceOperation?.error = scanBlocksOperation?.error
784
+ }
785
+
786
+ let fetchOperation = FetchUnspentTxOutputsOperation(
787
+ accountRepository: accountRepository,
788
+ downloader: self.downloader,
789
+ rustbackend: rustBackend,
790
+ dataDb: config.dataDb,
791
+ startHeight: config.walletBirthday,
792
+ networkType: self.config.network.networkType
793
+ )
794
+
795
+ fetchOperation.startedHandler = { [weak self] in
796
+ DispatchQueue.main.async { [weak self] in
797
+ self?.state = .fetching
798
+ }
799
+ }
800
+
801
+ fetchOperation.completionHandler = { [weak self] _, cancelled in
802
+ guard !cancelled else {
803
+ LoggerProxy.debug("Warning: fetch operation on range \(range) cancelled")
804
+ return
805
+ }
806
+ DispatchQueue.main.async { [weak self] in
807
+ self?.processBatchFinished(range: range)
808
+ }
809
+ }
810
+
811
+ fetchOperation.errorHandler = { [weak self] error in
812
+ DispatchQueue.main.async { [weak self] in
813
+ guard let self = self else { return }
814
+
815
+ self.processingError = error
816
+ self.fail(error)
817
+ }
818
+ }
819
+
820
+ fetchOperation.fetchedUTXOsHandler = { result in
821
+ NotificationCenter.default.post(
822
+ name: .blockProcessorStoredUTXOs,
823
+ object: self,
824
+ userInfo: [CompactBlockProcessorNotificationKey.refreshedUTXOs: result]
825
+ )
826
+ }
827
+
828
+ let enhanceFetchAdapterOperation = BlockOperation { [weak fetchOperation, weak enhanceOperation] in
829
+ fetchOperation?.error = enhanceOperation?.error
830
+ }
831
+
832
+ downloadValidateAdapterOperation.addDependency(downloadBlockOperation)
833
+ validateChainOperation.addDependency(downloadValidateAdapterOperation)
834
+ validateScanningAdapterOperation.addDependency(validateChainOperation)
835
+ scanBlocksOperation.addDependency(validateScanningAdapterOperation)
836
+ scanEnhanceAdapterOperation.addDependency(scanBlocksOperation)
837
+ enhanceOperation.addDependency(scanEnhanceAdapterOperation)
838
+ enhanceFetchAdapterOperation.addDependency(enhanceOperation)
839
+ fetchOperation.addDependency(enhanceFetchAdapterOperation)
840
+
841
+ operationQueue.addOperations(
842
+ [
843
+ downloadBlockOperation,
844
+ downloadValidateAdapterOperation,
845
+ validateChainOperation,
846
+ validateScanningAdapterOperation,
847
+ scanBlocksOperation,
848
+ scanEnhanceAdapterOperation,
849
+ enhanceOperation,
850
+ enhanceFetchAdapterOperation,
851
+ fetchOperation
852
+ ],
853
+ waitUntilFinished: false
854
+ )
855
+ }
856
+
857
+ func calculateProgress(start: BlockHeight, current: BlockHeight, latest: BlockHeight) -> Float {
858
+ let totalBlocks = Float(abs(latest - start))
859
+ let completed = Float(abs(current - start))
860
+ let progress = completed / totalBlocks
861
+ return progress
862
+ }
863
+
864
+ func notifyProgress(_ progress: CompactBlockProgress) {
865
+ var userInfo: [AnyHashable: Any] = [:]
866
+ userInfo[CompactBlockProcessorNotificationKey.progress] = progress
867
+
868
+ LoggerProxy.debug("progress: \(progress)")
869
+
870
+ NotificationCenter.default.post(
871
+ name: Notification.Name.blockProcessorUpdated,
872
+ object: self,
873
+ userInfo: userInfo
874
+ )
875
+ }
876
+
877
+ func notifyTransactions(_ txs: [ConfirmedTransactionEntity], in range: BlockRange) {
878
+ NotificationCenter.default.post(
879
+ name: .blockProcessorFoundTransactions,
880
+ object: self,
881
+ userInfo: [
882
+ CompactBlockProcessorNotificationKey.foundTransactions: txs,
883
+ CompactBlockProcessorNotificationKey.foundTransactionsRange: ClosedRange(uncheckedBounds: (range.start.height, range.end.height))
884
+ ]
885
+ )
886
+ }
887
+
888
+ func determineLowerBound(
889
+ errorHeight: Int,
890
+ consecutiveErrors: Int,
891
+ walletBirthday: BlockHeight
892
+ ) -> BlockHeight {
893
+ let offset = min(ZcashSDK.maxReorgSize, ZcashSDK.defaultRewindDistance * (consecutiveErrors + 1))
894
+ return max(errorHeight - offset, walletBirthday - ZcashSDK.maxReorgSize)
895
+ }
896
+
897
+ func severeFailure(_ error: Error) {
898
+ operationQueue.cancelAllOperations()
899
+ LoggerProxy.error("show stoppper failure: \(error)")
900
+ self.backoffTimer?.invalidate()
901
+ self.retryAttempts = config.retries
902
+ self.processingError = error
903
+ self.state = .error(error)
904
+ self.notifyError(error)
905
+ }
906
+
907
+ func fail(_ error: Error) {
908
+ // todo specify: failure
909
+ LoggerProxy.error("\(error)")
910
+ operationQueue.cancelAllOperations()
911
+ self.retryAttempts += 1
912
+ self.processingError = error
913
+ switch self.state {
914
+ case .error:
915
+ notifyError(error)
916
+ default:
917
+ break
918
+ }
919
+ self.state = .error(error)
920
+ guard self.maxAttemptsReached else { return }
921
+ // don't set a new timer if there are no more attempts.
922
+ self.setTimer()
923
+ }
924
+
925
+ func retryProcessing(range: CompactBlockRange) {
926
+ operationQueue.cancelAllOperations()
927
+ // update retries
928
+ self.retryAttempts += 1
929
+ self.processingError = nil
930
+ guard self.retryAttempts < config.retries else {
931
+ self.notifyError(CompactBlockProcessorError.maxAttemptsReached(attempts: self.retryAttempts))
932
+ self.stop()
933
+ return
934
+ }
935
+
936
+ do {
937
+ try downloader.rewind(to: max(range.lowerBound, self.config.walletBirthday))
938
+
939
+ // process next batch
940
+ // processNewBlocks(range: Self.nextBatchBlockRange(latestHeight: latestBlockHeight, latestDownloadedHeight: try downloader.lastDownloadedBlockHeight(), walletBirthday: config.walletBirthday))
941
+ nextBatch()
942
+ } catch {
943
+ self.fail(error)
944
+ }
945
+ }
946
+
947
+ func mapError(_ error: Error) -> CompactBlockProcessorError {
948
+ if let processorError = error as? CompactBlockProcessorError {
949
+ return processorError
950
+ }
951
+ if let lwdError = error as? LightWalletServiceError {
952
+ return lwdError.mapToProcessorError()
953
+ } else if let rpcError = error as? GRPC.GRPCStatus {
954
+ switch rpcError {
955
+ case .ok:
956
+ LoggerProxy.warn("Error Raised when status is OK")
957
+ return CompactBlockProcessorError.grpcError(
958
+ statusCode: rpcError.code.rawValue,
959
+ message: rpcError.message ?? "Error Raised when status is OK"
960
+ )
961
+ default:
962
+ return CompactBlockProcessorError.grpcError(statusCode: rpcError.code.rawValue, message: rpcError.message ?? "No message")
963
+ }
964
+ }
965
+ return .unspecifiedError(underlyingError: error)
966
+ }
967
+
968
+ private func validateConfiguration() throws {
969
+ guard FileManager.default.isReadableFile(atPath: config.cacheDb.absoluteString) else {
970
+ throw CompactBlockProcessorError.missingDbPath(path: config.cacheDb.absoluteString)
971
+ }
972
+
973
+ guard FileManager.default.isReadableFile(atPath: config.dataDb.absoluteString) else {
974
+ throw CompactBlockProcessorError.missingDbPath(path: config.dataDb.absoluteString)
975
+ }
976
+ }
977
+
978
+ private func nextBatch() {
979
+ self.state = .downloading
980
+ NextStateHelper.nextState(
981
+ service: self.service,
982
+ downloader: self.downloader,
983
+ config: self.config,
984
+ rustBackend: self.rustBackend,
985
+ queue: nil
986
+ ) { result in
987
+ DispatchQueue.main.async { [weak self] in
988
+ guard let self = self else { return }
989
+ switch result {
990
+ case .success(let nextState):
991
+ switch nextState {
992
+ case .finishProcessing(let height):
993
+ self.latestBlockHeight = height
994
+ self.processingFinished(height: height)
995
+ case .processNewBlocks(let range):
996
+ self.latestBlockHeight = range.upperBound
997
+ self.lowerBoundHeight = range.lowerBound
998
+ self.processNewBlocks(range: range)
999
+ case let .wait(latestHeight, latestDownloadHeight):
1000
+ // Lightwalletd might be syncing
1001
+ self.lowerBoundHeight = latestDownloadHeight
1002
+ self.latestBlockHeight = latestHeight
1003
+ LoggerProxy.info(
1004
+ "Lightwalletd might be syncing: latest downloaded block height is: \(latestDownloadHeight)" +
1005
+ "while latest blockheight is reported at: \(latestHeight)"
1006
+ )
1007
+ self.processingFinished(height: latestDownloadHeight)
1008
+ }
1009
+ case .failure(let error):
1010
+ self.severeFailure(error)
1011
+ }
1012
+ }
1013
+ }
1014
+ }
1015
+
1016
+ private func validationFailed(at height: BlockHeight) {
1017
+ // cancel all Tasks
1018
+ operationQueue.cancelAllOperations()
1019
+
1020
+ // register latest failure
1021
+ self.lastChainValidationFailure = height
1022
+ self.consecutiveChainValidationErrors += 1
1023
+
1024
+ // rewind
1025
+ let rewindHeight = determineLowerBound(
1026
+ errorHeight: height,
1027
+ consecutiveErrors: consecutiveChainValidationErrors,
1028
+ walletBirthday: self.config.walletBirthday
1029
+ )
1030
+
1031
+ guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network.networkType) else {
1032
+ fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)"))
1033
+ return
1034
+ }
1035
+
1036
+ do {
1037
+ try downloader.rewind(to: rewindHeight)
1038
+
1039
+ // notify reorg
1040
+ NotificationCenter.default.post(
1041
+ name: Notification.Name.blockProcessorHandledReOrg,
1042
+ object: self,
1043
+ userInfo: [
1044
+ CompactBlockProcessorNotificationKey.reorgHeight: height, CompactBlockProcessorNotificationKey.rewindHeight: rewindHeight
1045
+ ]
1046
+ )
1047
+
1048
+ // process next batch
1049
+ self.nextBatch()
1050
+ } catch {
1051
+ self.fail(error)
1052
+ }
1053
+ }
1054
+
1055
+ private func processBatchFinished(range: CompactBlockRange) {
1056
+ guard processingError == nil else {
1057
+ retryProcessing(range: range)
1058
+ return
1059
+ }
1060
+
1061
+ retryAttempts = 0
1062
+ consecutiveChainValidationErrors = 0
1063
+
1064
+ guard !range.isEmpty else {
1065
+ processingFinished(height: range.upperBound)
1066
+ return
1067
+ }
1068
+
1069
+ nextBatch()
1070
+ }
1071
+
1072
+ private func processingFinished(height: BlockHeight) {
1073
+ NotificationCenter.default.post(
1074
+ name: Notification.Name.blockProcessorFinished,
1075
+ object: self,
1076
+ userInfo: [
1077
+ CompactBlockProcessorNotificationKey.latestScannedBlockHeight: height,
1078
+ CompactBlockProcessorNotificationKey.foundBlocks: self.foundBlocks
1079
+ ]
1080
+ )
1081
+ self.state = .synced
1082
+ setTimer()
1083
+ }
1084
+
1085
+ private func setTimer() {
1086
+ let interval = self.config.blockPollInterval
1087
+ self.backoffTimer?.invalidate()
1088
+ let timer = Timer(
1089
+ timeInterval: interval,
1090
+ repeats: true,
1091
+ block: { [weak self] _ in
1092
+ guard let self = self else { return }
1093
+ do {
1094
+ if self.shouldStart {
1095
+ LoggerProxy.debug(
1096
+ """
1097
+ Timer triggered: Starting compact Block processor!.
1098
+ Processor State: \(self.state)
1099
+ latestHeight: \(self.latestBlockHeight)
1100
+ attempts: \(self.retryAttempts)
1101
+ lowerbound: \(String(describing: self.lowerBoundHeight))
1102
+ """
1103
+ )
1104
+ try self.start()
1105
+ } else if self.maxAttemptsReached {
1106
+ self.fail(CompactBlockProcessorError.maxAttemptsReached(attempts: self.config.retries))
1107
+ }
1108
+ } catch {
1109
+ self.fail(error)
1110
+ }
1111
+ }
1112
+ )
1113
+ RunLoop.main.add(timer, forMode: .default)
1114
+
1115
+ self.backoffTimer = timer
1116
+ }
1117
+
1118
+ private func transitionState(from oldValue: State, to newValue: State) {
1119
+ guard oldValue != newValue else {
1120
+ return
1121
+ }
1122
+
1123
+ NotificationCenter.default.post(
1124
+ name: .blockProcessorStatusChanged,
1125
+ object: self,
1126
+ userInfo: [
1127
+ CompactBlockProcessorNotificationKey.previousStatus: oldValue,
1128
+ CompactBlockProcessorNotificationKey.newStatus: newValue
1129
+ ]
1130
+ )
1131
+
1132
+ switch newValue {
1133
+ case .downloading:
1134
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorStartedDownloading, object: self)
1135
+ case .synced:
1136
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorFinished, object: self)
1137
+ case .error(let err):
1138
+ notifyError(err)
1139
+ case .scanning:
1140
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorStartedScanning, object: self)
1141
+ case .stopped:
1142
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorStopped, object: self)
1143
+ case .validating:
1144
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorStartedValidating, object: self)
1145
+ case .enhancing:
1146
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorStartedEnhancing, object: self)
1147
+ case .fetching:
1148
+ NotificationCenter.default.post(name: Notification.Name.blockProcessorStartedFetching, object: self)
1149
+ }
1150
+ }
1151
+
1152
+ private func notifyError(_ err: Error) {
1153
+ NotificationCenter.default.post(
1154
+ name: Notification.Name.blockProcessorFailed,
1155
+ object: self,
1156
+ userInfo: [CompactBlockProcessorNotificationKey.error: mapError(err)]
1157
+ )
1158
+ }
1159
+ // TODO: encapsulate service errors better
1160
+ }
1161
+
1162
+ public extension CompactBlockProcessor.Configuration {
1163
+ /**
1164
+ Standard configuration for most compact block processors
1165
+ */
1166
+ static func standard(for network: ZcashNetwork, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration {
1167
+ let pathProvider = DefaultResourceProvider(network: network)
1168
+ return CompactBlockProcessor.Configuration(
1169
+ cacheDb: pathProvider.cacheDbURL,
1170
+ dataDb: pathProvider.dataDbURL,
1171
+ walletBirthday: walletBirthday,
1172
+ network: network
1173
+ )
1174
+ }
1175
+ }
1176
+
1177
+ extension LightWalletServiceError {
1178
+ func mapToProcessorError() -> CompactBlockProcessorError {
1179
+ switch self {
1180
+ case let .failed(statusCode, message):
1181
+ return CompactBlockProcessorError.grpcError(statusCode: statusCode, message: message)
1182
+ case .invalidBlock:
1183
+ return CompactBlockProcessorError.generalError(message: "\(self)")
1184
+ case .generalError(let message):
1185
+ return CompactBlockProcessorError.generalError(message: message)
1186
+ case .sentFailed(let error):
1187
+ return CompactBlockProcessorError.connectionError(underlyingError: error)
1188
+ case .genericError(let error):
1189
+ return CompactBlockProcessorError.unspecifiedError(underlyingError: error)
1190
+ case .timeOut:
1191
+ return CompactBlockProcessorError.connectionTimeout
1192
+ case .criticalError:
1193
+ return CompactBlockProcessorError.criticalError
1194
+ case .userCancelled:
1195
+ return CompactBlockProcessorError.connectionTimeout
1196
+ case .unknown:
1197
+ return CompactBlockProcessorError.unspecifiedError(underlyingError: self)
1198
+ }
1199
+ }
1200
+ }
1201
+ extension CompactBlockProcessor.State: Equatable {
1202
+ public static func == (lhs: CompactBlockProcessor.State, rhs: CompactBlockProcessor.State) -> Bool {
1203
+ switch (lhs, rhs) {
1204
+ case
1205
+ (.downloading, .downloading),
1206
+ (.scanning, .scanning),
1207
+ (.validating, .validating),
1208
+ (.stopped, .stopped),
1209
+ (.error, .error),
1210
+ (.synced, .synced),
1211
+ (.enhancing, enhancing),
1212
+ (.fetching, .fetching):
1213
+ return true
1214
+ default:
1215
+ return false
1216
+ }
1217
+ }
1218
+ }
1219
+
1220
+ // Transparent stuff
1221
+
1222
+ extension CompactBlockProcessor {
1223
+ public func utxoCacheBalance(tAddress: String) throws -> WalletBalance {
1224
+ try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress, networkType: config.network.networkType)
1225
+ }
1226
+ }
1227
+
1228
+ extension CompactBlockProcessor {
1229
+ public func getUnifiedAddres(accountIndex: Int) -> UnifiedAddress? {
1230
+ guard let account = try? accountRepository.findBy(account: accountIndex) else {
1231
+ return nil
1232
+ }
1233
+ return UnifiedAddressShim(account: account)
1234
+ }
1235
+
1236
+ public func getShieldedAddress(accountIndex: Int) -> SaplingShieldedAddress? {
1237
+ try? accountRepository.findBy(account: accountIndex)?.address
1238
+ }
1239
+
1240
+ public func getTransparentAddress(accountIndex: Int) -> TransparentAddress? {
1241
+ try? accountRepository.findBy(account: accountIndex)?.transparentAddress
1242
+ }
1243
+
1244
+ public func getTransparentBalance(accountIndex: Int) throws -> WalletBalance {
1245
+ guard let tAddress = try? accountRepository.findBy(account: accountIndex)?.transparentAddress else {
1246
+ throw CompactBlockProcessorError.invalidAccount
1247
+ }
1248
+ return try utxoCacheBalance(tAddress: tAddress)
1249
+ }
1250
+ }
1251
+
1252
+ private struct UnifiedAddressShim {
1253
+ let account: AccountEntity
1254
+ }
1255
+
1256
+ extension UnifiedAddressShim: UnifiedAddress {
1257
+ var tAddress: TransparentAddress {
1258
+ account.transparentAddress
1259
+ }
1260
+
1261
+ var zAddress: SaplingShieldedAddress {
1262
+ account.address
1263
+ }
1264
+ }
1265
+
1266
+ extension CompactBlockProcessor {
1267
+ func refreshUTXOs(tAddress: String, startHeight: BlockHeight, result: @escaping (Result<RefreshedUTXOs, Error>) -> Void) {
1268
+ let dataDb = self.config.dataDb
1269
+ self.downloader.fetchUnspentTransactionOutputs(tAddress: tAddress, startHeight: startHeight) { [weak self] fetchResult in
1270
+ switch fetchResult {
1271
+ case .success(let utxos):
1272
+ DispatchQueue.main.async {
1273
+ self?.operationQueue.addOperation { [self] in
1274
+ guard let self = self else { return }
1275
+ do {
1276
+ guard try self.rustBackend.clearUtxos(
1277
+ dbData: dataDb,
1278
+ address: tAddress,
1279
+ sinceHeight: startHeight - 1,
1280
+ networkType: self.config.network.networkType
1281
+ ) >= 0 else {
1282
+ result(.failure(CompactBlockProcessorError.generalError(message: "attempted to clear utxos but -1 was returned")))
1283
+ return
1284
+ }
1285
+ } catch {
1286
+ result(.failure(self.mapError(error)))
1287
+ }
1288
+ result(.success(self.storeUTXOs(utxos, in: dataDb)))
1289
+ }
1290
+ }
1291
+ case .failure(let error):
1292
+ result(.failure(self?.mapError(error) ?? error))
1293
+ }
1294
+ }
1295
+ }
1296
+
1297
+ private func storeUTXOs(_ utxos: [UnspentTransactionOutputEntity], in dataDb: URL) -> RefreshedUTXOs {
1298
+ var refreshed: [UnspentTransactionOutputEntity] = []
1299
+ var skipped: [UnspentTransactionOutputEntity] = []
1300
+ for utxo in utxos {
1301
+ do {
1302
+ try self.rustBackend.putUnspentTransparentOutput(
1303
+ dbData: dataDb,
1304
+ address: utxo.address,
1305
+ txid: utxo.txid.bytes,
1306
+ index: utxo.index,
1307
+ script: utxo.script.bytes,
1308
+ value: Int64(utxo.valueZat),
1309
+ height: utxo.height,
1310
+ networkType: self.config.network.networkType
1311
+ ) ? refreshed.append(utxo) : skipped.append(utxo)
1312
+ } catch {
1313
+ LoggerProxy.info("failed to put utxo - error: \(error)")
1314
+ skipped.append(utxo)
1315
+ }
1316
+ }
1317
+ return (inserted: refreshed, skipped: skipped)
1318
+ }
1319
+ }
1320
+
1321
+ extension CompactBlockProcessorError: LocalizedError {
1322
+ /// A localized message describing what error occurred.
1323
+ public var errorDescription: String? {
1324
+ switch self {
1325
+ case .dataDbInitFailed(let path):
1326
+ return "Data Db file couldn't be initialized at path: \(path)"
1327
+ case .connectionError(let underlyingError):
1328
+ return "There's a problem with the Network Connection. Underlying error: \(underlyingError.localizedDescription)"
1329
+ case .connectionTimeout:
1330
+ return "Network connection timeout"
1331
+ case .criticalError:
1332
+ return "Critical Error"
1333
+ case .generalError(let message):
1334
+ return "Error Processing Blocks - \(message)"
1335
+ case let .grpcError(statusCode, message):
1336
+ return "Error on gRPC - Status Code: \(statusCode) - Message: \(message)"
1337
+ case .invalidAccount:
1338
+ return "Invalid Account"
1339
+ case .invalidConfiguration:
1340
+ return "CompactBlockProcessor was started with an Invalid Configuration"
1341
+ case .maxAttemptsReached(let attempts):
1342
+ return "Compact Block failed \(attempts) times and reached the maximum amount of retries it was set up to do"
1343
+ case .missingDbPath(let path):
1344
+ return "CompactBlockProcessor was set up with path \(path) but thath location couldn't be reached"
1345
+ case let .networkMismatch(expected, found):
1346
+ // swiftlint:disable:next line_length
1347
+ 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"
1348
+ case let .saplingActivationMismatch(expected, found):
1349
+ // swiftlint:disable:next line_length
1350
+ 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?"
1351
+ case .unspecifiedError(let underlyingError):
1352
+ return "Unspecified error caused by this underlying error: \(underlyingError)"
1353
+ case let .wrongConsensusBranchId(expectedLocally, found):
1354
+ // swiftlint:disable:next line_length
1355
+ 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."
1356
+ }
1357
+ }
1358
+
1359
+ /// A localized message describing the reason for the failure.
1360
+ public var failureReason: String? {
1361
+ self.localizedDescription
1362
+ }
1363
+
1364
+ /// A localized message describing how one might recover from the failure.
1365
+ public var recoverySuggestion: String? {
1366
+ self.localizedDescription
1367
+ }
1368
+
1369
+ /// A localized message providing "help" text if the user requests help.
1370
+ public var helpAnchor: String? {
1371
+ self.localizedDescription
1372
+ }
1373
+ }
1374
+
1375
+ extension CompactBlockProcessor: CompactBlockProgressDelegate {
1376
+ func progressUpdated(_ progress: CompactBlockProgress) {
1377
+ notifyProgress(progress)
1378
+ }
1379
+ }
1380
+
1381
+ extension CompactBlockProcessor: EnhancementStreamDelegate {
1382
+ func transactionEnhancementProgressUpdated(_ progress: EnhancementProgress) {
1383
+ NotificationCenter.default.post(
1384
+ name: .blockProcessorEnhancementProgress,
1385
+ object: self,
1386
+ userInfo: [CompactBlockProcessorNotificationKey.enhancementProgress: progress]
1387
+ )
1388
+ }
1389
+ }
1390
+
1391
+ extension CompactBlockProcessor {
1392
+ enum NextStateHelper {
1393
+ // swiftlint:disable:next function_parameter_count
1394
+ static func nextState(
1395
+ service: LightWalletService,
1396
+ downloader: CompactBlockDownloading,
1397
+ config: Configuration,
1398
+ rustBackend: ZcashRustBackendWelding.Type,
1399
+ queue: DispatchQueue?,
1400
+ result: @escaping (Result<FigureNextBatchOperation.NextState, Error>) -> Void
1401
+ ) {
1402
+ let dispatchQueue = queue ?? DispatchQueue.global(qos: .userInitiated)
1403
+
1404
+ dispatchQueue.async {
1405
+ do {
1406
+ let nextResult = try self.nextState(
1407
+ service: service,
1408
+ downloader: downloader,
1409
+ config: config,
1410
+ rustBackend: rustBackend
1411
+ )
1412
+ result(.success(nextResult))
1413
+ } catch {
1414
+ result(.failure(error))
1415
+ }
1416
+ }
1417
+ }
1418
+
1419
+ static func nextState(
1420
+ service: LightWalletService,
1421
+ downloader: CompactBlockDownloading,
1422
+ config: Configuration,
1423
+ rustBackend: ZcashRustBackendWelding.Type
1424
+ ) throws -> FigureNextBatchOperation.NextState {
1425
+ let info = try service.getInfo()
1426
+
1427
+ try CompactBlockProcessor.validateServerInfo(
1428
+ info,
1429
+ saplingActivation: config.saplingActivation,
1430
+ localNetwork: config.network,
1431
+ rustBackend: rustBackend
1432
+ )
1433
+
1434
+ // get latest block height
1435
+ let latestDownloadedBlockHeight: BlockHeight = max(config.walletBirthday, try downloader.lastDownloadedBlockHeight())
1436
+
1437
+ let latestBlockheight = try service.latestBlockHeight()
1438
+
1439
+ if latestDownloadedBlockHeight < latestBlockheight {
1440
+ return .processNewBlocks(
1441
+ range: CompactBlockProcessor.nextBatchBlockRange(
1442
+ latestHeight: latestBlockheight,
1443
+ latestDownloadedHeight: latestDownloadedBlockHeight,
1444
+ walletBirthday: config.walletBirthday
1445
+ )
1446
+ )
1447
+ } else if latestBlockheight == latestDownloadedBlockHeight {
1448
+ return .finishProcessing(height: latestBlockheight)
1449
+ }
1450
+
1451
+ return .wait(latestHeight: latestBlockheight, latestDownloadHeight: latestBlockheight)
1452
+ }
1453
+ }
1454
+ }