Browse Source

Rewrite: key management GUI, added wizards for key import

Herman Schoenfeld 7 years ago
parent
commit
23583ed918
52 changed files with 3712 additions and 1933 deletions
  1. 127 89
      PascalCoinWallet.lpi
  2. BIN
      Resources/WalletImages/clipboard-24x24.png
  3. BIN
      Resources/WalletImages/lock-16x16.png
  4. BIN
      Resources/WalletImages/minus-16x16.png
  5. BIN
      Resources/WalletImages/plus-16x16.png
  6. BIN
      Resources/WalletImages/success-64x64.png
  7. BIN
      Resources/WalletImages/unlock-64x64.png
  8. BIN
      Resources/WalletImages/unlock-red-64x64.png
  9. 27 35
      Units/Forms/UFRMAbout.lfm
  10. 2 2
      Units/Forms/UFRMAbout.pas
  11. 19 19
      Units/Forms/UFRMAccountExplorer.pas
  12. 1 1
      Units/Forms/UFRMAccountSelect.lfm
  13. 1 1
      Units/Forms/UFRMAccountSelect.pas
  14. 3 3
      Units/Forms/UFRMMainForm.lfm
  15. 11 10
      Units/Forms/UFRMMainForm.pas
  16. 2 2
      Units/Forms/UFRMMessages.pas
  17. 0 96
      Units/Forms/UFRMNewPrivateKeyType.lfm
  18. 0 98
      Units/Forms/UFRMNewPrivateKeyType.pas
  19. 7 7
      Units/Forms/UFRMNodesIp.pas
  20. 2 4
      Units/Forms/UFRMOperation.pas
  21. 4 3
      Units/Forms/UFRMPascalCoinWalletConfig.lfm
  22. 82 109
      Units/Forms/UFRMPascalCoinWalletConfig.pas
  23. 45 65
      Units/Forms/UFRMPayloadDecoder.pas
  24. 1 1
      Units/Forms/UFRMPendingOperations.pas
  25. 1319 591
      Units/Forms/UFRMWalletKeys.lfm
  26. 351 415
      Units/Forms/UFRMWalletKeys.pas
  27. 0 35
      Units/Forms/UFRMWalletKeys2.pas
  28. 132 221
      Units/Forms/UUserInterface.pas
  29. 92 0
      Units/Forms/Wizards/UWIZAddKey.pas
  30. 28 0
      Units/Forms/Wizards/UWIZAddKey_EnterName.lfm
  31. 55 0
      Units/Forms/Wizards/UWIZAddKey_EnterName.pas
  32. 65 0
      Units/Forms/Wizards/UWIZAddKey_GenerateOrImport.lfm
  33. 49 0
      Units/Forms/Wizards/UWIZAddKey_GenerateOrImport.pas
  34. 51 0
      Units/Forms/Wizards/UWIZAddKey_ImportPrivKey.lfm
  35. 66 0
      Units/Forms/Wizards/UWIZAddKey_ImportPrivKey.pas
  36. 29 0
      Units/Forms/Wizards/UWIZAddKey_ImportPubKey.lfm
  37. 59 0
      Units/Forms/Wizards/UWIZAddKey_ImportPubKey.pas
  38. 33 0
      Units/Forms/Wizards/UWIZAddKey_SelectEncryption.lfm
  39. 62 0
      Units/Forms/Wizards/UWIZAddKey_SelectEncryption.pas
  40. 65 0
      Units/Forms/Wizards/UWIZAddKey_Start.lfm
  41. 55 0
      Units/Forms/Wizards/UWIZAddKey_Start.pas
  42. 0 23
      Units/PascalCoin/UConst.pas
  43. 43 17
      Units/PascalCoin/UCrypto.pas
  44. 1 1
      Units/PascalCoin/URPC.pas
  45. 1 1
      Units/PascalCoin/UServerApp.pas
  46. 339 0
      Units/PascalCoin/USettings.pas
  47. 350 4
      Units/PascalCoin/UWallet.pas
  48. 1 1
      Units/PascalCoin/upcdaemon.pas
  49. 6 6
      Units/Utils/UAutoScope.pas
  50. 1 1
      Units/Utils/UGridUtils.pas
  51. 2 2
      Units/Utils/UWizard.lfm
  52. 123 70
      Units/Utils/UWizard.pas

+ 127 - 89
PascalCoinWallet.lpi

@@ -38,7 +38,7 @@
         <PackageName Value="LCL"/>
         <PackageName Value="LCL"/>
       </Item1>
       </Item1>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="69">
+    <Units Count="75">
       <Unit0>
       <Unit0>
         <Filename Value="PascalCoinWallet.dpr"/>
         <Filename Value="PascalCoinWallet.dpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -56,7 +56,7 @@
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit3>
       </Unit3>
       <Unit4>
       <Unit4>
-        <Filename Value="Units\PascalCoin\UWalletKeys.pas"/>
+        <Filename Value="Units\PascalCoin\UWallet.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit4>
       </Unit4>
       <Unit5>
       <Unit5>
@@ -125,259 +125,297 @@
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit18>
       </Unit18>
       <Unit19>
       <Unit19>
-        <Filename Value="Units\Forms\UFRMWalletKeys.pas"/>
+        <Filename Value="Units\Forms\UFRMPayloadDecoder.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="FRMWalletKeys"/>
+        <ComponentName Value="FRMPayloadDecoder"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit19>
       </Unit19>
       <Unit20>
       <Unit20>
-        <Filename Value="Units\Forms\UFRMNewPrivateKeyType.pas"/>
+        <Filename Value="Units\Forms\UFRMNodesIp.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="FRMNewPrivateKeyType"/>
+        <ComponentName Value="FRMNodesIp"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit20>
       </Unit20>
       <Unit21>
       <Unit21>
-        <Filename Value="Units\Forms\UFRMPayloadDecoder.pas"/>
+        <Filename Value="Units\PascalCoin\UTCPIP.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="FRMPayloadDecoder"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit21>
       </Unit21>
       <Unit22>
       <Unit22>
-        <Filename Value="Units\Forms\UFRMNodesIp.pas"/>
+        <Filename Value="Units\Utils\UJSONFunctions.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="FRMNodesIp"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit22>
       </Unit22>
       <Unit23>
       <Unit23>
-        <Filename Value="Units\PascalCoin\UTCPIP.pas"/>
+        <Filename Value="Units\PascalCoin\URPC.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit23>
       </Unit23>
       <Unit24>
       <Unit24>
-        <Filename Value="Units\Utils\UJSONFunctions.pas"/>
+        <Filename Value="Units\PascalCoin\UPoolMining.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit24>
       </Unit24>
       <Unit25>
       <Unit25>
-        <Filename Value="Units\PascalCoin\URPC.pas"/>
+        <Filename Value="Units\PascalCoin\UOpenSSL.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit25>
       </Unit25>
       <Unit26>
       <Unit26>
-        <Filename Value="Units\PascalCoin\UPoolMining.pas"/>
+        <Filename Value="Units\PascalCoin\UOpenSSLdef.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit26>
       </Unit26>
       <Unit27>
       <Unit27>
-        <Filename Value="Units\PascalCoin\UOpenSSL.pas"/>
+        <Filename Value="Units\PascalCoin\UFileStorage.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit27>
       </Unit27>
       <Unit28>
       <Unit28>
-        <Filename Value="Units\PascalCoin\UOpenSSLdef.pas"/>
+        <Filename Value="Units\PascalCoin\config.inc"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit28>
       </Unit28>
       <Unit29>
       <Unit29>
-        <Filename Value="Units\PascalCoin\UFileStorage.pas"/>
+        <Filename Value="Units\PascalCoin\UAES.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit29>
       </Unit29>
       <Unit30>
       <Unit30>
-        <Filename Value="Units\PascalCoin\config.inc"/>
+        <Filename Value="Units\PascalCoin\UChunk.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit30>
       </Unit30>
       <Unit31>
       <Unit31>
-        <Filename Value="Units\PascalCoin\UAES.pas"/>
-        <IsPartOfProject Value="True"/>
-      </Unit31>
-      <Unit32>
-        <Filename Value="Units\PascalCoin\UChunk.pas"/>
-        <IsPartOfProject Value="True"/>
-      </Unit32>
-      <Unit33>
         <Filename Value="Units\Forms\UFRMAccountSelect.pas"/>
         <Filename Value="Units\Forms\UFRMAccountSelect.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMAccountSelect"/>
         <ComponentName Value="FRMAccountSelect"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit33>
-      <Unit34>
+      </Unit31>
+      <Unit32>
         <Filename Value="Units\PascalCoin\UBaseTypes.pas"/>
         <Filename Value="Units\PascalCoin\UBaseTypes.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-      </Unit34>
-      <Unit35>
+      </Unit32>
+      <Unit33>
         <Filename Value="Units\Utils\UWizard.pas"/>
         <Filename Value="Units\Utils\UWizard.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="WizardHostForm"/>
         <ComponentName Value="WizardHostForm"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit35>
-      <Unit36>
+      </Unit33>
+      <Unit34>
         <Filename Value="Units\Utils\generics.collections.pas"/>
         <Filename Value="Units\Utils\generics.collections.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="Generics.Collections"/>
         <UnitName Value="Generics.Collections"/>
-      </Unit36>
-      <Unit37>
+      </Unit34>
+      <Unit35>
         <Filename Value="Units\Utils\generics.defaults.pas"/>
         <Filename Value="Units\Utils\generics.defaults.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="Generics.Defaults"/>
         <UnitName Value="Generics.Defaults"/>
-      </Unit37>
-      <Unit38>
+      </Unit35>
+      <Unit36>
         <Filename Value="Units\Utils\generics.hashes.pas"/>
         <Filename Value="Units\Utils\generics.hashes.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="Generics.Hashes"/>
         <UnitName Value="Generics.Hashes"/>
-      </Unit38>
-      <Unit39>
+      </Unit36>
+      <Unit37>
         <Filename Value="Units\Utils\generics.helpers.pas"/>
         <Filename Value="Units\Utils\generics.helpers.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="Generics.Helpers"/>
         <UnitName Value="Generics.Helpers"/>
-      </Unit39>
-      <Unit40>
+      </Unit37>
+      <Unit38>
         <Filename Value="Units\Utils\generics.memoryexpanders.pas"/>
         <Filename Value="Units\Utils\generics.memoryexpanders.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="Generics.MemoryExpanders"/>
         <UnitName Value="Generics.MemoryExpanders"/>
-      </Unit40>
-      <Unit41>
+      </Unit38>
+      <Unit39>
         <Filename Value="Units\Utils\generics.strings.pas"/>
         <Filename Value="Units\Utils\generics.strings.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="Generics.Strings"/>
         <UnitName Value="Generics.Strings"/>
-      </Unit41>
-      <Unit42>
+      </Unit39>
+      <Unit40>
         <Filename Value="Units\Forms\UFRMMessages.pas"/>
         <Filename Value="Units\Forms\UFRMMessages.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMMessages"/>
         <ComponentName Value="FRMMessages"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit42>
-      <Unit43>
+      </Unit40>
+      <Unit41>
         <Filename Value="Units\Forms\UFRMNodes.pas"/>
         <Filename Value="Units\Forms\UFRMNodes.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMNodes"/>
         <ComponentName Value="FRMNodes"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit43>
-      <Unit44>
+      </Unit41>
+      <Unit42>
         <Filename Value="Units\Forms\UFRMLogs.pas"/>
         <Filename Value="Units\Forms\UFRMLogs.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMLogs"/>
         <ComponentName Value="FRMLogs"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit44>
-      <Unit45>
+      </Unit42>
+      <Unit43>
         <Filename Value="Units\Forms\UFRMOperationExplorer.pas"/>
         <Filename Value="Units\Forms\UFRMOperationExplorer.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMOperationExplorer"/>
         <ComponentName Value="FRMOperationExplorer"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit45>
-      <Unit46>
+      </Unit43>
+      <Unit44>
         <Filename Value="Units\Forms\UFRMBlockExplorer.pas"/>
         <Filename Value="Units\Forms\UFRMBlockExplorer.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMBlockExplorer"/>
         <ComponentName Value="FRMBlockExplorer"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit46>
-      <Unit47>
+      </Unit44>
+      <Unit45>
         <Filename Value="Units\Forms\UFRMPendingOperations.pas"/>
         <Filename Value="Units\Forms\UFRMPendingOperations.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMPendingOperations"/>
         <ComponentName Value="FRMPendingOperations"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
-      </Unit47>
-      <Unit48>
+      </Unit45>
+      <Unit46>
         <Filename Value="Units\Forms\UFRMAccountExplorer.pas"/>
         <Filename Value="Units\Forms\UFRMAccountExplorer.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="FRMAccountExplorer"/>
         <ComponentName Value="FRMAccountExplorer"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
+      </Unit46>
+      <Unit47>
+        <Filename Value="Units\Forms\UUserInterface.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit47>
+      <Unit48>
+        <Filename Value="Units\Utils\UCommonUI.pas"/>
+        <IsPartOfProject Value="True"/>
       </Unit48>
       </Unit48>
       <Unit49>
       <Unit49>
-        <Filename Value="Units\Forms\UUserInterface.pas"/>
+        <Filename Value="Units\Utils\UCommon.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit49>
       </Unit49>
       <Unit50>
       <Unit50>
-        <Filename Value="Units\Utils\UCommonUI.pas"/>
+        <Filename Value="Units\PascalCoin\UGPUMining.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit50>
       </Unit50>
       <Unit51>
       <Unit51>
-        <Filename Value="Units\Utils\UCommon.pas"/>
+        <Filename Value="Units\PascalCoin\upcdaemon.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit51>
       </Unit51>
       <Unit52>
       <Unit52>
-        <Filename Value="Units\PascalCoin\UGPUMining.pas"/>
+        <Filename Value="Units\PascalCoin\UPoolMinerThreads.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit52>
       </Unit52>
       <Unit53>
       <Unit53>
-        <Filename Value="Units\PascalCoin\upcdaemon.pas"/>
+        <Filename Value="Units\PascalCoin\UServerApp.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit53>
       </Unit53>
       <Unit54>
       <Unit54>
-        <Filename Value="Units\PascalCoin\UPoolMinerThreads.pas"/>
+        <Filename Value="Units\PascalCoin\USha256.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit54>
       </Unit54>
       <Unit55>
       <Unit55>
-        <Filename Value="Units\PascalCoin\UServerApp.pas"/>
+        <Filename Value="Units\Utils\generics.dictionaries.inc"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit55>
       </Unit55>
       <Unit56>
       <Unit56>
-        <Filename Value="Units\PascalCoin\USha256.pas"/>
+        <Filename Value="Units\Utils\generics.dictionariesh.inc"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit56>
       </Unit56>
       <Unit57>
       <Unit57>
-        <Filename Value="Units\Utils\generics.dictionaries.inc"/>
+        <Filename Value="Units\Forms\UFRMAccountInfo.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit57>
       </Unit57>
       <Unit58>
       <Unit58>
-        <Filename Value="Units\Utils\generics.dictionariesh.inc"/>
+        <Filename Value="Units\Forms\UFRMMemoText.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit58>
       </Unit58>
       <Unit59>
       <Unit59>
-        <Filename Value="Units\Forms\UFRMAccountInfo.pas"/>
+        <Filename Value="Units\Forms\UFRMSaleAccounts.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <HasResources Value="True"/>
       </Unit59>
       </Unit59>
       <Unit60>
       <Unit60>
-        <Filename Value="Units\Forms\UFRMMemoText.pas"/>
+        <Filename Value="Units\Forms\UCTRLBanner.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <ComponentName Value="CTRLBanner"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
       </Unit60>
       </Unit60>
       <Unit61>
       <Unit61>
-        <Filename Value="Units\Forms\UFRMSaleAccounts.pas"/>
+        <Filename Value="Units\Forms\UFRMMainForm.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <ComponentName Value="FRMMainForm"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
       </Unit61>
       </Unit61>
       <Unit62>
       <Unit62>
-        <Filename Value="Units\Forms\UFRMWalletKeys2.pas"/>
+        <Filename Value="Units\Forms\UFRMSyncronizationForm.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit62>
       </Unit62>
       <Unit63>
       <Unit63>
-        <Filename Value="Units\Forms\UCTRLBanner.pas"/>
+        <Filename Value="Units\Utils\UAutoScope.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="CTRLBanner"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit63>
       </Unit63>
       <Unit64>
       <Unit64>
-        <Filename Value="Units\Forms\UFRMMainForm.pas"/>
+        <Filename Value="Units\Utils\UVisualGrid.inc"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="FRMMainForm"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit64>
       </Unit64>
       <Unit65>
       <Unit65>
-        <Filename Value="Units\Forms\UFRMSyncronizationForm.pas"/>
+        <Filename Value="Units\Utils\UVisualGrid.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <HasResources Value="True"/>
       </Unit65>
       </Unit65>
       <Unit66>
       <Unit66>
-        <Filename Value="Units\Utils\UAutoScope.pas"/>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey_Start.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZAddKey_Start"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
       </Unit66>
       </Unit66>
       <Unit67>
       <Unit67>
-        <Filename Value="Units\Utils\UVisualGrid.inc"/>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey_GenerateOrImport.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZAddKey_GenerateOrImport"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
       </Unit67>
       </Unit67>
       <Unit68>
       <Unit68>
-        <Filename Value="Units\Utils\UVisualGrid.pas"/>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey_ImportPubKey.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZAddKey_ImportPubKey"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
       </Unit68>
       </Unit68>
+      <Unit69>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey_ImportPrivKey.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZAddKey_ImportPrivKey"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit69>
+      <Unit70>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey_EnterName.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZAddKey_EnterName"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit70>
+      <Unit71>
+        <Filename Value="Units\Forms\UFRMWalletKeys.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="FRMWalletKeys"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit71>
+      <Unit72>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit72>
+      <Unit73>
+        <Filename Value="Units\PascalCoin\USettings.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit73>
+      <Unit74>
+        <Filename Value="Units\Forms\Wizards\UWIZAddKey_SelectEncryption.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZAddKey_SelectEncryption"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit74>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>
@@ -388,7 +426,7 @@
     </Target>
     </Target>
     <SearchPaths>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir);Units\PascalCoin;Units\Utils"/>
       <IncludeFiles Value="$(ProjOutDir);Units\PascalCoin;Units\Utils"/>
-      <OtherUnitFiles Value="Synapse\lib;Units\Forms;Units\PascalCoin;Units\Utils;Units\SQLite3"/>
+      <OtherUnitFiles Value="Synapse\lib;Units\Forms;Units\PascalCoin;Units\Utils;Units\SQLite3;Units\Forms\Wizards"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     </SearchPaths>
     <Parsing>
     <Parsing>

BIN
Resources/WalletImages/clipboard-24x24.png


BIN
Resources/WalletImages/lock-16x16.png


BIN
Resources/WalletImages/minus-16x16.png


BIN
Resources/WalletImages/plus-16x16.png


BIN
Resources/WalletImages/success-64x64.png


BIN
Resources/WalletImages/unlock-64x64.png


BIN
Resources/WalletImages/unlock-red-64x64.png


+ 27 - 35
Units/Forms/UFRMAbout.lfm

@@ -1,7 +1,7 @@
 object FRMAbout: TFRMAbout
 object FRMAbout: TFRMAbout
-  Left = 764
+  Left = -3141
   Height = 405
   Height = 405
-  Top = 516
+  Top = 507
   Width = 585
   Width = 585
   ActiveControl = bbClose
   ActiveControl = bbClose
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
@@ -194,19 +194,6 @@ object FRMAbout: TFRMAbout
     Caption = 'Source Code:'
     Caption = 'Source Code:'
     ParentColor = False
     ParentColor = False
   end
   end
-  object Label3: TLabel
-    Left = 90
-    Height = 13
-    Top = 339
-    Width = 135
-    Caption = 'Check For New Versions:'
-    Font.Color = clWindowText
-    Font.Height = -11
-    Font.Name = 'Tahoma'
-    Font.Style = [fsBold]
-    ParentColor = False
-    ParentFont = False
-  end
   object Label4: TLabel
   object Label4: TLabel
     Cursor = crHandPoint
     Cursor = crHandPoint
     Left = 170
     Left = 170
@@ -222,29 +209,14 @@ object FRMAbout: TFRMAbout
     ParentFont = False
     ParentFont = False
     OnClick = Label4Click
     OnClick = Label4Click
   end
   end
-  object Label5: TLabel
-    Cursor = crHandPoint
-    Left = 237
-    Height = 13
-    Top = 339
-    Width = 253
-    Caption = 'https://sourceforge.net/projects/pascalcoin'
-    Font.Color = clBlue
-    Font.Height = -11
-    Font.Name = 'Tahoma'
-    Font.Style = [fsBold]
-    ParentColor = False
-    ParentFont = False
-    OnClick = Label5Click
-  end
   object Memo1: TMemo
   object Memo1: TMemo
     Left = 90
     Left = 90
-    Height = 266
+    Height = 250
     Top = 46
     Top = 46
     Width = 478
     Width = 478
     BorderStyle = bsNone
     BorderStyle = bsNone
     Lines.Strings = (
     Lines.Strings = (
-      'Copyright (c) 2016 - 2017 Albert Molina'
+      'Copyright (c) 2018 PascalCoin Project'
       ''
       ''
       'Pascal Coin is P2P cryptocurrency without the need for historical operations. This software '
       'Pascal Coin is P2P cryptocurrency without the need for historical operations. This software '
       'comprises a node within the Pascal Coin network and can be used to Mine and Explore blocks and '
       'comprises a node within the Pascal Coin network and can be used to Mine and Explore blocks and '
@@ -261,9 +233,6 @@ object FRMAbout: TFRMAbout
       'Gebauer.'
       'Gebauer.'
       'Original source code is written in Pascal Language and is available at '
       'Original source code is written in Pascal Language and is available at '
       'https://github.com/PascalCoin/PascalCoin'
       'https://github.com/PascalCoin/PascalCoin'
-      ''
-      'If you like it, consider a donation using BitCoin:'
-      '16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk'
     )
     )
     ParentColor = True
     ParentColor = True
     ReadOnly = True
     ReadOnly = True
@@ -281,4 +250,27 @@ object FRMAbout: TFRMAbout
     ModalResult = 1
     ModalResult = 1
     TabOrder = 1
     TabOrder = 1
   end
   end
+  object Label6: TLabel
+    Left = 112
+    Height = 13
+    Top = 296
+    Width = 43
+    Caption = 'Website:'
+    ParentColor = False
+  end
+  object Label7: TLabel
+    Cursor = crHandPoint
+    Left = 170
+    Height = 13
+    Top = 296
+    Width = 150
+    Caption = 'http://www.pascalcoin.org'
+    Font.Color = clBlue
+    Font.Height = -11
+    Font.Name = 'Tahoma'
+    Font.Style = [fsBold]
+    ParentColor = False
+    ParentFont = False
+    OnClick = Label4Click
+  end
 end
 end

+ 2 - 2
Units/Forms/UFRMAbout.pas

@@ -31,14 +31,14 @@ type
   TFRMAbout = class(TApplicationForm)
   TFRMAbout = class(TApplicationForm)
     Image1: TImage;
     Image1: TImage;
     Label1: TLabel;
     Label1: TLabel;
+    Label6: TLabel;
+    Label7: TLabel;
     Memo1: TMemo;
     Memo1: TMemo;
     bbClose: TBitBtn;
     bbClose: TBitBtn;
     lblBuild: TLabel;
     lblBuild: TLabel;
     lblProtocolVersion: TLabel;
     lblProtocolVersion: TLabel;
     Label2: TLabel;
     Label2: TLabel;
-    Label3: TLabel;
     Label4: TLabel;
     Label4: TLabel;
-    Label5: TLabel;
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure Label4Click(Sender: TObject);
     procedure Label4Click(Sender: TObject);
     procedure Label5Click(Sender: TObject);
     procedure Label5Click(Sender: TObject);

+ 19 - 19
Units/Forms/UFRMAccountExplorer.pas

@@ -203,8 +203,8 @@ implementation
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
-uses UFRMAccountSelect, UConst, UFRMOperation,
-     UWalletKeys, UCrypto, UFRMMemoText, UUserInterface, UCommon;
+uses UFRMAccountSelect, UConst, USettings, UFRMOperation,
+     UWallet, UCrypto, UFRMMemoText, UUserInterface, UCommon;
 
 
 { TFRMAccountExplorer }
 { TFRMAccountExplorer }
 
 
@@ -233,14 +233,14 @@ begin
   FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(TUserInterface.Node.Bank.SafeBox,false);
   FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(TUserInterface.Node.Bank.SafeBox,false);
 
 
   // Subscribe to wallet events
   // Subscribe to wallet events
-  TUserInterface.WalletKeys.OnChanged.Add(OnPrivateKeysChanged);
+  TWallet.Keys.OnChanged.Add(OnPrivateKeysChanged);
   Refresh;
   Refresh;
 end;
 end;
 
 
 procedure TFRMAccountExplorer.FormDestroy(Sender: TObject);
 procedure TFRMAccountExplorer.FormDestroy(Sender: TObject);
 begin
 begin
   // Unsubscribe from wallet events
   // Unsubscribe from wallet events
-  TUserInterface.WalletKeys.OnChanged.Remove(OnPrivateKeysChanged);
+  TWallet.Keys.OnChanged.Remove(OnPrivateKeysChanged);
 
 
   // Nullify fields
   // Nullify fields
   FAccountOperationsGrid.Node := Nil;
   FAccountOperationsGrid.Node := Nil;
@@ -351,8 +351,8 @@ begin
         if cbMyPrivateKeys.ItemIndex<0 then exit;
         if cbMyPrivateKeys.ItemIndex<0 then exit;
         if cbMyPrivateKeys.ItemIndex=0 then begin
         if cbMyPrivateKeys.ItemIndex=0 then begin
           // All keys in the wallet
           // All keys in the wallet
-          for i := 0 to TUserInterface.WalletKeys.Count - 1 do begin
-            j := FOrderedAccountsKeyList.IndexOfAccountKey(TUserInterface.WalletKeys[i].AccountKey);
+          for i := 0 to TWallet.Keys.Count - 1 do begin
+            j := FOrderedAccountsKeyList.IndexOfAccountKey(TWallet.Keys[i].AccountKey);
             if (j>=0) then begin
             if (j>=0) then begin
               l := FOrderedAccountsKeyList.AccountKeyList[j];
               l := FOrderedAccountsKeyList.AccountKeyList[j];
               for k := 0 to l.Count - 1 do begin
               for k := 0 to l.Count - 1 do begin
@@ -365,8 +365,8 @@ begin
           end;
           end;
         end else begin
         end else begin
           i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
           i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
-          if (i>=0) And (i<TUserInterface.WalletKeys.Count) then begin
-            j := FOrderedAccountsKeyList.IndexOfAccountKey(TUserInterface.WalletKeys[i].AccountKey);
+          if (i>=0) And (i<TWallet.Keys.Count) then begin
+            j := FOrderedAccountsKeyList.IndexOfAccountKey(TWallet.Keys[i].AccountKey);
             if (j>=0) then begin
             if (j>=0) then begin
               l := FOrderedAccountsKeyList.AccountKeyList[j];
               l := FOrderedAccountsKeyList.AccountKeyList[j];
               for k := 0 to l.Count - 1 do begin
               for k := 0 to l.Count - 1 do begin
@@ -411,8 +411,8 @@ begin
   cbMyPrivateKeys.items.BeginUpdate;
   cbMyPrivateKeys.items.BeginUpdate;
   Try
   Try
     cbMyPrivateKeys.Items.Clear;
     cbMyPrivateKeys.Items.Clear;
-    For i:=0 to TUserInterface.WalletKeys.Count-1 do begin
-      wk := TUserInterface.WalletKeys.Key[i];
+    For i:=0 to TWallet.Keys.Count-1 do begin
+      wk := TWallet.Keys.Key[i];
       if assigned(FOrderedAccountsKeyList) then begin
       if assigned(FOrderedAccountsKeyList) then begin
         FOrderedAccountsKeyList.AddAccountKey(wk.AccountKey);
         FOrderedAccountsKeyList.AddAccountKey(wk.AccountKey);
       end;
       end;
@@ -512,10 +512,10 @@ var i : Integer;
 begin
 begin
   if (cbMyPrivateKeys.ItemIndex<0) then  exit;
   if (cbMyPrivateKeys.ItemIndex<0) then  exit;
   i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
   i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
-  if (i<0) Or (i>=TUserInterface.WalletKeys.Count) then raise Exception.Create('Must select a Key');
-  name := TUserInterface.WalletKeys.Key[i].Name;
+  if (i<0) Or (i>=TWallet.Keys.Count) then raise Exception.Create('Must select a Key');
+  name := TWallet.Keys.Key[i].Name;
   if InputQuery('Change Key name','Input new name',nameString) then begin
   if InputQuery('Change Key name','Input new name',nameString) then begin
-    TUserInterface.WalletKeys.SetName(i,name);
+    TWallet.Keys.SetName(i,name);
   end;
   end;
 end;
 end;
 
 
@@ -535,7 +535,7 @@ begin
     ltarget := FAccountsSelectedGrid.LockAccountsList;
     ltarget := FAccountsSelectedGrid.LockAccountsList;
     Try
     Try
       for i := 0 to lsource.Count-1 do begin
       for i := 0 to lsource.Count-1 do begin
-        if TUserInterface.WalletKeys.IndexOfAccountKey(TUserInterface.Node.Bank.SafeBox.Account(lsource.Get(i)).accountInfo.accountKey)<0 then raise Exception.Create(Format('You cannot operate with account %d because private key not found in your wallet',[lsource.Get(i)]));
+        if TWallet.Keys.IndexOfAccountKey(TUserInterface.Node.Bank.SafeBox.Account(lsource.Get(i)).accountInfo.accountKey)<0 then raise Exception.Create(Format('You cannot operate with account %d because private key not found in your wallet',[lsource.Get(i)]));
         ltarget.Add(lsource.Get(i));
         ltarget.Add(lsource.Get(i));
       end;
       end;
     Finally
     Finally
@@ -555,7 +555,7 @@ Var l, selected : TOrderedCardinalList;
 begin
 begin
   an := FAccountsGrid.AccountNumber(dgAccounts.Row);
   an := FAccountsGrid.AccountNumber(dgAccounts.Row);
   if (an<0) then raise Exception.Create('No account selected');
   if (an<0) then raise Exception.Create('No account selected');
-  if TUserInterface.WalletKeys.IndexOfAccountKey(TUserInterface.Node.Bank.SafeBox.Account(an).accountInfo.accountkey)<0 then
+  if TWallet.Keys.IndexOfAccountKey(TUserInterface.Node.Bank.SafeBox.Account(an).accountInfo.accountkey)<0 then
     raise Exception.Create(Format('You cannot add %s account because private key not found in your wallet.'#10+#10+'You''re not the owner!',
     raise Exception.Create(Format('You cannot add %s account because private key not found in your wallet.'#10+#10+'You''re not the owner!',
       [TAccountComp.AccountNumberToAccountTxtNumber(an)]));
       [TAccountComp.AccountNumberToAccountTxtNumber(an)]));
   // Add
   // Add
@@ -609,8 +609,8 @@ begin
     finally
     finally
       FAccountsSelectedGrid.UnlockAccountsList;
       FAccountsSelectedGrid.UnlockAccountsList;
     end;
     end;
-    DefaultFee := TUserInterface.AppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
-    WalletKeys := TUserInterface.WalletKeys;
+    DefaultFee := TSettings.DefaultFee;
+    WalletKeys := TWallet.Keys;
     ShowModal;
     ShowModal;
   Finally
   Finally
     Free;
     Free;
@@ -623,7 +623,7 @@ begin
   F := TFRMAccountSelect.Create(Self);
   F := TFRMAccountSelect.Create(Self);
   try
   try
     F.Node := TUserInterface.Node;
     F.Node := TUserInterface.Node;
-    F.WalletKeys := TUserInterface.WalletKeys;
+    F.WalletKeys := TWallet.Keys;
     F.ShowModal;
     F.ShowModal;
   finally
   finally
     F.Free;
     F.Free;
@@ -701,7 +701,7 @@ begin
     If FAccountsGrid.SelectedAccounts(targetAccounts) = 0
     If FAccountsGrid.SelectedAccounts(targetAccounts) = 0
       then raise Exception.Create('No row selected');
       then raise Exception.Create('No row selected');
 
 
-    TUserInterface.ShowNewOperationDialog(Self, targetAccounts, TUserInterface.AppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0));
+    TUserInterface.ShowNewOperationDialog(Self, targetAccounts, TSettings.DefaultFee);
   finally
   finally
      targetAccounts.Free;
      targetAccounts.Free;
   end;
   end;

+ 1 - 1
Units/Forms/UFRMAccountSelect.lfm

@@ -14,7 +14,7 @@ object FRMAccountSelect: TFRMAccountSelect
   OnCreate = FormCreate
   OnCreate = FormCreate
   OnDestroy = FormDestroy
   OnDestroy = FormDestroy
   Position = poOwnerFormCenter
   Position = poOwnerFormCenter
-  LCLVersion = '1.6.0.4'
+  LCLVersion = '1.6.4.0'
   object pnlAccountsTop: TPanel
   object pnlAccountsTop: TPanel
     Left = 395
     Left = 395
     Height = 282
     Height = 282

+ 1 - 1
Units/Forms/UFRMAccountSelect.pas

@@ -23,7 +23,7 @@ uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, UAccounts, Grids, StdCtrls, Buttons, ExtCtrls, UCommonUI,
   Dialogs, UAccounts, Grids, StdCtrls, Buttons, ExtCtrls, UCommonUI,
-  UWalletKeys, UNode, UGridUtils, UConst, UThread;
+  UWallet, UNode, UGridUtils, UConst, UThread;
 
 
 const
 const
   CT_AS_MyAccounts = $0001;
   CT_AS_MyAccounts = $0001;

+ 3 - 3
Units/Forms/UFRMMainForm.lfm

@@ -1,7 +1,7 @@
 object FRMMainForm: TFRMMainForm
 object FRMMainForm: TFRMMainForm
-  Left = 125
+  Left = 52
   Height = 600
   Height = 600
-  Top = 58
+  Top = 55
   Width = 865
   Width = 865
   Caption = 'Pascal Coin Wallet, JSON-RPC Miner & Explorer'
   Caption = 'Pascal Coin Wallet, JSON-RPC Miner & Explorer'
   ClientHeight = 580
   ClientHeight = 580
@@ -19,7 +19,7 @@ object FRMMainForm: TFRMMainForm
   OnCreate = FormCreate
   OnCreate = FormCreate
   OnDestroy = FormDestroy
   OnDestroy = FormDestroy
   OnResize = FormResize
   OnResize = FormResize
-  Position = poOwnerFormCenter
+  Position = poDefault
   ShowHint = True
   ShowHint = True
   LCLVersion = '1.6.4.0'
   LCLVersion = '1.6.4.0'
   object paLogoPanel: TPanel
   object paLogoPanel: TPanel

+ 11 - 10
Units/Forms/UFRMMainForm.pas

@@ -17,7 +17,7 @@ interface
 
 
 uses
 uses
   Messages, SysUtils, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Classes, Graphics, Controls, Forms,
-  Dialogs, ExtCtrls, ComCtrls, UWalletKeys,
+  Dialogs, ExtCtrls, ComCtrls, UWallet,
   ULog,
   ULog,
   UBlockChain, UNode, UGridUtils, UAccounts, Menus,
   UBlockChain, UNode, UGridUtils, UAccounts, Menus,
   UNetProtocol, UCrypto, Buttons, ActnList, UPoolMining,
   UNetProtocol, UCrypto, Buttons, ActnList, UPoolMining,
@@ -141,7 +141,8 @@ end;
 
 
 procedure TFRMMainForm.FormCloseQuery(Sender: TObject; var CanClose: boolean);
 procedure TFRMMainForm.FormCloseQuery(Sender: TObject; var CanClose: boolean);
 begin
 begin
-  case TUserInterface.AskQuestion(Self, 'Quit PascalCoin', 'Are you sure you want to quit? Select ''No'' to run in background.', [mbCancel, mbNo, mbYes]) of
+  case TUserInterface.AskQuestion(Self, mtConfirmation, 'Quit PascalCoin',
+  'Are you sure you want to quit? Select ''No'' to run in background.', [mbCancel, mbNo, mbYes]) of
     mbYes: begin
     mbYes: begin
       CanClose := false;
       CanClose := false;
       PostMessage(Self.Handle, CM_PC_Terminate, 0, 0);
       PostMessage(Self.Handle, CM_PC_Terminate, 0, 0);
@@ -165,7 +166,7 @@ end;
 
 
 procedure TFRMMainForm.ActivateFirstTime;
 procedure TFRMMainForm.ActivateFirstTime;
 begin
 begin
-  TUserInterface.WalletKeys.OnChanged.Add(OnWalletChanged);
+  TWallet.Keys.OnChanged.Add(OnWalletChanged);
   TNetData.NetData.OnConnectivityChanged.Add(OnConnectivityChanged);
   TNetData.NetData.OnConnectivityChanged.Add(OnConnectivityChanged);
   RefreshWalletLockIcon;
   RefreshWalletLockIcon;
   RefreshConnectivityIcon;
   RefreshConnectivityIcon;
@@ -173,7 +174,7 @@ end;
 
 
 procedure TFRMMainForm.FormDestroy(Sender: TObject);
 procedure TFRMMainForm.FormDestroy(Sender: TObject);
 begin
 begin
-  TUserInterface.WalletKeys.OnChanged.Remove(OnWalletChanged);
+  TWallet.Keys.OnChanged.Remove(OnWalletChanged);
   TNetData.NetData.OnConnectivityChanged.Remove(OnConnectivityChanged);
   TNetData.NetData.OnConnectivityChanged.Remove(OnConnectivityChanged);
 end;
 end;
 
 
@@ -188,12 +189,12 @@ end;
 
 
 procedure TFRMMainForm.RefreshWalletLockIcon;
 procedure TFRMMainForm.RefreshWalletLockIcon;
 begin
 begin
-  if NOT TUserInterface.WalletKeys.HasPassword then begin
+  if NOT TWallet.Keys.HasPassword then begin
     { No password has been set }
     { No password has been set }
     tbtnWalletLock.Enabled := false;
     tbtnWalletLock.Enabled := false;
     tbtnWalletLock.ImageIndex := 3;
     tbtnWalletLock.ImageIndex := 3;
     tbtnWalletLock.Hint := 'Your wallet does not have a password.';
     tbtnWalletLock.Hint := 'Your wallet does not have a password.';
-  end else if TUserInterface.WalletKeys.IsValidPassword then begin
+  end else if TWallet.Keys.IsValidPassword then begin
     { Password has been input, allow user to lock }
     { Password has been input, allow user to lock }
     tbtnWalletLock.Enabled := true;
     tbtnWalletLock.Enabled := true;
     tbtnWalletLock.ImageIndex := 3;
     tbtnWalletLock.ImageIndex := 3;
@@ -360,15 +361,15 @@ end;
 
 
 procedure TFRMMainForm.tbtnWalletLockClick(Sender:TObject);
 procedure TFRMMainForm.tbtnWalletLockClick(Sender:TObject);
 begin
 begin
-  if NOT TUserInterface.WalletKeys.HasPassword then begin
+  if NOT TWallet.Keys.HasPassword then begin
      { no password has been set }
      { no password has been set }
      ShowMessage('Your wallet has no password and is unsafe. Please set a password using ''Key Manager'' in Wallet menu.');
      ShowMessage('Your wallet has no password and is unsafe. Please set a password using ''Key Manager'' in Wallet menu.');
-   end else if TUserInterface.WalletKeys.IsValidPassword then begin
+   end else if TWallet.Keys.IsValidPassword then begin
      { wallet is unlocked, lock it }
      { wallet is unlocked, lock it }
-     TUserInterface.WalletKeys.LockWallet;
+     TWallet.Keys.LockWallet;
    end else begin
    end else begin
      { wallet is locked, try to unlock it}
      { wallet is locked, try to unlock it}
-     TUserInterface.UnlockWallet(Self, TUserInterface.WalletKeys);
+     TUserInterface.UnlockWallet(Self);
    end;
    end;
 end;
 end;
 
 

+ 2 - 2
Units/Forms/UFRMMessages.pas

@@ -48,7 +48,7 @@ type
 
 
 implementation
 implementation
 
 
-uses UUserInterface;
+uses UUserInterface, USettings;
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
@@ -69,7 +69,7 @@ begin
     s := DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr;
     s := DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr;
     memoMessages.Lines.Add(DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr+' Length '+inttostr(Length(MessageData))+' bytes');
     memoMessages.Lines.Add(DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr+' Length '+inttostr(Length(MessageData))+' bytes');
     memoMessages.Lines.Add('RECEIVED> '+MessageData);
     memoMessages.Lines.Add('RECEIVED> '+MessageData);
-    if TUserInterface.AppParams.ParamByName[CT_PARAM_ShowModalMessages].GetAsBoolean(false) then begin
+    if TSettings.ShowModalMessages then begin
       s := DateTimeToStr(now)+' Message from '+NetConnection.ClientRemoteAddr+#10+
       s := DateTimeToStr(now)+' Message from '+NetConnection.ClientRemoteAddr+#10+
          'Length '+inttostr(length(MessageData))+' bytes'+#10+#10;
          'Length '+inttostr(length(MessageData))+' bytes'+#10+#10;
       if TCrypto.IsHumanReadable(MessageData) then begin
       if TCrypto.IsHumanReadable(MessageData) then begin

+ 0 - 96
Units/Forms/UFRMNewPrivateKeyType.lfm

@@ -1,96 +0,0 @@
-object FRMNewPrivateKeyType: TFRMNewPrivateKeyType
-  Left = 763
-  Height = 229
-  Top = 434
-  Width = 311
-  BorderIcons = [biSystemMenu]
-  BorderStyle = bsDialog
-  Caption = 'New Private Key'
-  ClientHeight = 229
-  ClientWidth = 311
-  Color = clBtnFace
-  Font.Color = clWindowText
-  Font.Height = -11
-  Font.Name = 'Tahoma'
-  OnCreate = FormCreate
-  OnDestroy = FormDestroy
-  Position = poOwnerFormCenter
-  LCLVersion = '1.6.0.4'
-  object Label1: TLabel
-    Left = 30
-    Height = 13
-    Top = 25
-    Width = 27
-    Caption = 'Name'
-    ParentColor = False
-  end
-  object ebName: TEdit
-    Left = 70
-    Height = 21
-    Top = 22
-    Width = 206
-    TabOrder = 0
-    Text = 'ebName'
-  end
-  object rgKeyType: TRadioGroup
-    Left = 30
-    Height = 105
-    Top = 60
-    Width = 246
-    AutoFill = True
-    Caption = ' Key Type: '
-    ChildSizing.LeftRightSpacing = 6
-    ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
-    ChildSizing.EnlargeVertical = crsHomogenousChildResize
-    ChildSizing.ShrinkHorizontal = crsScaleChilds
-    ChildSizing.ShrinkVertical = crsScaleChilds
-    ChildSizing.Layout = cclLeftToRightThenTopToBottom
-    ChildSizing.ControlsPerLine = 1
-    ClientHeight = 87
-    ClientWidth = 242
-    Items.Strings = (
-      'asdf'
-    )
-    TabOrder = 1
-  end
-  object bbOk: TBitBtn
-    Left = 112
-    Height = 25
-    Top = 181
-    Width = 75
-    Caption = 'OK'
-    Default = True
-    Glyph.Data = {
-      DE010000424DDE01000000000000760000002800000024000000120000000100
-      0400000000006801000000000000000000001000000000000000000000000000
-      80000080000000808000800000008000800080800000C0C0C000808080000000
-      FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
-      3333333333333333333333330000333333333333333333333333F33333333333
-      00003333344333333333333333388F3333333333000033334224333333333333
-      338338F3333333330000333422224333333333333833338F3333333300003342
-      222224333333333383333338F3333333000034222A22224333333338F338F333
-      8F33333300003222A3A2224333333338F3838F338F33333300003A2A333A2224
-      33333338F83338F338F33333000033A33333A222433333338333338F338F3333
-      0000333333333A222433333333333338F338F33300003333333333A222433333
-      333333338F338F33000033333333333A222433333333333338F338F300003333
-      33333333A222433333333333338F338F00003333333333333A22433333333333
-      3338F38F000033333333333333A223333333333333338F830000333333333333
-      333A333333333333333338330000333333333333333333333333333333333333
-      0000
-    }
-    NumGlyphs = 2
-    OnClick = bbOkClick
-    TabOrder = 2
-  end
-  object bbCancel: TBitBtn
-    Left = 201
-    Height = 25
-    Top = 181
-    Width = 75
-    Cancel = True
-    Caption = 'Cancel'
-    Kind = bkCancel
-    ModalResult = 2
-    TabOrder = 3
-  end
-end

+ 0 - 98
Units/Forms/UFRMNewPrivateKeyType.pas

@@ -1,98 +0,0 @@
-unit UFRMNewPrivateKeyType;
-
-{$MODE Delphi}
-
-{ Copyright (c) 2016 by Albert Molina
-
-  Distributed under the MIT software license, see the accompanying file LICENSE
-  or visit http://www.opensource.org/licenses/mit-license.php.
-
-  This unit is a part of Pascal Coin, a P2P crypto currency without need of
-  historical operations.
-
-  If you like it, consider a donation using BitCoin:
-  16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
-
-  }
-
-interface
-
-{$I ./../PascalCoin/config.inc}
-
-uses
-  LCLIntf, LCLType, LMessages,
-  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-  Dialogs, StdCtrls, Buttons, ExtCtrls, UCommonUI, UWalletKeys,UCrypto;
-
-type
-  TFRMNewPrivateKeyType = class(TApplicationForm)
-    Label1: TLabel;
-    ebName: TEdit;
-    rgKeyType: TRadioGroup;
-    bbOk: TBitBtn;
-    bbCancel: TBitBtn;
-    procedure FormCreate(Sender: TObject);
-    procedure bbOkClick(Sender: TObject);
-    procedure FormDestroy(Sender: TObject);
-  private
-    FWalletKeys: TWalletKeys;
-    FGeneratedPrivateKey: TECPrivateKey;
-    procedure SetWalletKeys(const Value: TWalletKeys);
-    { Private declarations }
-  public
-    { Public declarations }
-    Property WalletKeys : TWalletKeys read FWalletKeys write SetWalletKeys;
-    Property GeneratedPrivateKey : TECPrivateKey read FGeneratedPrivateKey write FGeneratedPrivateKey;
-  end;
-
-
-implementation
-
-uses
-  UAccounts, UConst ;
-
-{$R *.lfm}
-
-procedure TFRMNewPrivateKeyType.bbOkClick(Sender: TObject);
-begin
-  if Not Assigned(WalletKeys) then exit;
-  if rgKeyType.ItemIndex<0 then raise Exception.Create('Select a key type');
-
-  if Assigned(FGeneratedPrivateKey) then FGeneratedPrivateKey.Free;
-
-  FGeneratedPrivateKey := TECPrivateKey.Create;
-  FGeneratedPrivateKey.GenerateRandomPrivateKey( PtrInt(rgKeyType.Items.Objects[rgKeyType.ItemIndex]) );
-  WalletKeys.AddPrivateKey(ebName.Text,FGeneratedPrivateKey);
-  ModalResult := MrOk;
-end;
-
-procedure TFRMNewPrivateKeyType.FormCreate(Sender: TObject);
-Var l : TList;
-  i : Integer;
-begin
-  FGeneratedPrivateKey := Nil;
-  FWalletKeys := Nil;
-  ebName.Text := DateTimeToStr(now);
-  rgKeyType.Items.Clear;
-  l := TList.Create;
-  Try
-    TAccountComp.ValidsEC_OpenSSL_NID(l);
-    for i := 0 to l.Count - 1 do begin
-      rgKeyType.Items.AddObject(TAccountComp.GetECInfoTxt(PtrInt(l[i])),l[i]);
-    end;
-  Finally
-    l.free;
-  End;
-end;
-
-procedure TFRMNewPrivateKeyType.FormDestroy(Sender: TObject);
-begin
-  FreeAndNil(FGeneratedPrivateKey);
-end;
-
-procedure TFRMNewPrivateKeyType.SetWalletKeys(const Value: TWalletKeys);
-begin
-  FWalletKeys := Value;
-end;
-
-end.

+ 7 - 7
Units/Forms/UFRMNodesIp.pas

@@ -10,7 +10,7 @@ uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, Buttons,
   Dialogs, StdCtrls, Buttons,
-  UCommonUI, UAppParams;
+  UCommonUI;
 
 
 type
 type
   TFRMNodesIp = class(TApplicationForm)
   TFRMNodesIp = class(TApplicationForm)
@@ -33,7 +33,7 @@ type
 implementation
 implementation
 
 
 uses
 uses
-  UUserInterface, UNetProtocol, UNode, UConst;
+  UUserInterface, USettings, UNetProtocol, UNode, UConst;
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
@@ -53,8 +53,8 @@ Var
 begin
 begin
   memoNodesIp.Clear;
   memoNodesIp.Clear;
   setlength(nsarr,0);
   setlength(nsarr,0);
-  ips := TUserInterface.AppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].GetAsString('');
-  if trim(ips)<>'' then begin
+  ips := TSettings.TryConnectOnlyWithThisFixedServers;
+  if ips <> '' then begin
     cbTryOnlyWithThisServers.Checked := true;
     cbTryOnlyWithThisServers.Checked := true;
     TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
     TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
   end else begin
   end else begin
@@ -85,13 +85,13 @@ begin
   end;
   end;
   // Encode
   // Encode
   ips := TNode.EncodeNodeServerAddressArrayToIpString(nsarr);
   ips := TNode.EncodeNodeServerAddressArrayToIpString(nsarr);
-  TUserInterface.AppParams.ParamByName[CT_PARAM_PeerCache].SetAsString(ips);
+  TSettings.PeerCache := ips;
   if cbTryOnlyWithThisServers.Checked then Begin
   if cbTryOnlyWithThisServers.Checked then Begin
-    TUserInterface.AppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].SetAsString(ips);
+    TSettings.TryConnectOnlyWithThisFixedServers := ips;
     TNetData.NetData.DiscoverFixedServersOnly(nsarr);
     TNetData.NetData.DiscoverFixedServersOnly(nsarr);
     Application.MessageBox(PChar('Restart application to take effect'),PChar(Application.Title),MB_OK);
     Application.MessageBox(PChar('Restart application to take effect'),PChar(Application.Title),MB_OK);
   end else begin
   end else begin
-    TUserInterface.AppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].SetAsString('');
+    TSettings.TryConnectOnlyWithThisFixedServers := '';
     setlength(nsarr,0);
     setlength(nsarr,0);
     TNetData.NetData.DiscoverFixedServersOnly(nsarr);
     TNetData.NetData.DiscoverFixedServersOnly(nsarr);
   end;
   end;

+ 2 - 4
Units/Forms/UFRMOperation.pas

@@ -23,7 +23,7 @@ uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, UCommonUI,
   Dialogs, StdCtrls, UCommonUI,
-  UNode, UWalletKeys, UCrypto, Buttons, UBlockChain,
+  UNode, UWallet, UCrypto, Buttons, UBlockChain,
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UCommon;
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UCommon;
 
 
 Const
 Const
@@ -174,7 +174,7 @@ type
 implementation
 implementation
 
 
 uses
 uses
-  UECIES, UConst, UOpTransaction, UFRMNewPrivateKeyType, UAES, UFRMWalletKeys;
+  UECIES, UConst, UOpTransaction, UAES, UFRMWalletKeys;
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
@@ -358,7 +358,6 @@ Var FRM : TFRMWalletKeys;
 begin
 begin
   FRM := TFRMWalletKeys.Create(Self);
   FRM := TFRMWalletKeys.Create(Self);
   Try
   Try
-    FRM.WalletKeys := WalletKeys;
     FRM.ShowModal;
     FRM.ShowModal;
     cbBuyNewKey.SetFocus;
     cbBuyNewKey.SetFocus;
     UpdateWalletKeys;
     UpdateWalletKeys;
@@ -372,7 +371,6 @@ Var FRM : TFRMWalletKeys;
 begin
 begin
   FRM := TFRMWalletKeys.Create(Self);
   FRM := TFRMWalletKeys.Create(Self);
   Try
   Try
-    FRM.WalletKeys := WalletKeys;
     FRM.ShowModal;
     FRM.ShowModal;
     rbChangeKeyWithAnother.Checked := true;
     rbChangeKeyWithAnother.Checked := true;
     cbNewPrivateKey.SetFocus;
     cbNewPrivateKey.SetFocus;

+ 4 - 3
Units/Forms/UFRMPascalCoinWalletConfig.lfm

@@ -1,7 +1,7 @@
 object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
 object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
-  Left = 462
+  Left = -1385
   Height = 524
   Height = 524
-  Top = 234
+  Top = 29
   Width = 374
   Width = 374
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   BorderStyle = bsSingle
   BorderStyle = bsSingle
@@ -13,8 +13,9 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
   Font.Height = -11
   Font.Height = -11
   Font.Name = 'Tahoma'
   Font.Name = 'Tahoma'
   OnCreate = FormCreate
   OnCreate = FormCreate
+  OnDestroy = FormDestroy
   Position = poOwnerFormCenter
   Position = poOwnerFormCenter
-  LCLVersion = '1.6.0.4'
+  LCLVersion = '1.6.4.0'
   object Label1: TLabel
   object Label1: TLabel
     Left = 30
     Left = 30
     Height = 13
     Height = 13

+ 82 - 109
Units/Forms/UFRMPascalCoinWalletConfig.pas

@@ -20,11 +20,12 @@ interface
 uses
 uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-  Dialogs, StdCtrls, Buttons, ComCtrls, UCommonUI, UAppParams, UWalletKeys;
+  Dialogs, StdCtrls, Buttons, ComCtrls, UCommonUI;
 
 
-type
+const
+    CM_PC_WalletKeysChanged = WM_USER + 1;
 
 
-  TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
+type
 
 
   { TFRMPascalCoinWalletConfig }
   { TFRMPascalCoinWalletConfig }
 
 
@@ -66,60 +67,57 @@ type
     procedure cbSaveLogFilesClick(Sender: TObject);
     procedure cbSaveLogFilesClick(Sender: TObject);
     procedure bbOpenDataFolderClick(Sender: TObject);
     procedure bbOpenDataFolderClick(Sender: TObject);
     procedure cbJSONRPCPortEnabledClick(Sender: TObject);
     procedure cbJSONRPCPortEnabledClick(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
   private
   private
-    FAppParams: TAppParams;
-    FWalletKeys: TWalletKeys;
-    procedure SetAppParams(const Value: TAppParams);
-    procedure SetWalletKeys(const Value: TWalletKeys);
-    Procedure UpdateWalletConfig;
-    { Private declarations }
+    procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
+    procedure OnWalletChanged(Sender: TObject);
+    procedure RefreshUI;
+    procedure RefreshUI_WalletAspect;
   public
   public
-    { Public declarations }
-    Property AppParams : TAppParams read FAppParams write SetAppParams;
-    Property WalletKeys : TWalletKeys read FWalletKeys write SetWalletKeys;
   end;
   end;
 
 
 implementation
 implementation
 
 
-uses UConst, UAccounts, ULog, UCrypto, UFolderHelper;
+uses UConst, USettings, UAccounts, ULog, UCrypto, UFolderHelper, UWallet, UUserInterface, UCommon;
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
 procedure TFRMPascalCoinWalletConfig.bbOkClick(Sender: TObject);
 procedure TFRMPascalCoinWalletConfig.bbOkClick(Sender: TObject);
 Var df : Int64;
 Var df : Int64;
-  mpk : TMinerPrivateKey;
+  mpk : TMinerPrivateKeyType;
   i : Integer;
   i : Integer;
 begin
 begin
   if udInternetServerPort.Position = udJSONRPCMinerServerPort.Position then raise Exception.Create('Server port and JSON-RPC Server miner port are equal!');
   if udInternetServerPort.Position = udJSONRPCMinerServerPort.Position then raise Exception.Create('Server port and JSON-RPC Server miner port are equal!');
 
 
   if TAccountComp.TxtToMoney(ebDefaultFee.Text,df) then begin
   if TAccountComp.TxtToMoney(ebDefaultFee.Text,df) then begin
-    AppParams.ParamByName[CT_PARAM_DefaultFee].SetAsInt64(df);
+    TSettings.DefaultFee := df;
   end else begin
   end else begin
-    ebDefaultFee.Text := TAccountComp.FormatMoney(AppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInteger(0));
+    ebDefaultFee.Text := TAccountComp.FormatMoney(TSettings.DefaultFee);
     raise Exception.Create('Invalid Fee value');
     raise Exception.Create('Invalid Fee value');
   end;
   end;
-  AppParams.ParamByName[CT_PARAM_InternetServerPort].SetAsInteger(udInternetServerPort.Position );
+  TSettings.InternetServerPort := udInternetServerPort.Position;
   if rbGenerateANewPrivateKeyEachBlock.Checked then mpk := mpk_NewEachTime
   if rbGenerateANewPrivateKeyEachBlock.Checked then mpk := mpk_NewEachTime
   else if rbUseARandomKey.Checked then mpk := mpk_Random
   else if rbUseARandomKey.Checked then mpk := mpk_Random
   else if rbMineAllwaysWithThisKey.Checked then begin
   else if rbMineAllwaysWithThisKey.Checked then begin
     mpk := mpk_Selected;
     mpk := mpk_Selected;
     if cbPrivateKeyToMine.ItemIndex<0 then raise Exception.Create('Must select a private key');
     if cbPrivateKeyToMine.ItemIndex<0 then raise Exception.Create('Must select a private key');
     i := PtrInt(cbPrivateKeyToMine.Items.Objects[cbPrivateKeyToMine.ItemIndex]);
     i := PtrInt(cbPrivateKeyToMine.Items.Objects[cbPrivateKeyToMine.ItemIndex]);
-    if (i<0) Or (i>=FWalletKeys.Count) then raise Exception.Create('Invalid private key');
-    AppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].SetAsString( TAccountComp.AccountKey2RawString( FWalletKeys.Key[i].AccountKey ) );
+    if (i<0) Or (i>=TWallet.Keys.Count) then raise Exception.Create('Invalid private key');
+    if NOT TWallet.Keys.Key[i].HasPrivateKey then raise Exception.Create('Cannot use key "' + TWallet.Keys.Key[i].Name + '" for mining since it is watch-only');
+    TSettings.MinerSelectedPrivateKey := TAccountComp.AccountKey2RawString(TWallet.Keys.Key[i].AccountKey);
   end else mpk := mpk_Random;
   end else mpk := mpk_Random;
 
 
-  AppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].SetAsInteger(integer(mpk));
-  AppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].SetAsBoolean(cbJSONRPCMinerServerActive.Checked );
-  AppParams.ParamByName[CT_PARAM_SaveLogFiles].SetAsBoolean(cbSaveLogFiles.Checked );
-  AppParams.ParamByName[CT_PARAM_ShowLogs].SetAsBoolean(cbShowLogs.Checked );
-  AppParams.ParamByName[CT_PARAM_SaveDebugLogs].SetAsBoolean(cbSaveDebugLogs.Checked);
-  AppParams.ParamByName[CT_PARAM_MinerName].SetAsString(ebMinerName.Text);
-  AppParams.ParamByName[CT_PARAM_ShowModalMessages].SetAsBoolean(cbShowModalMessages.Checked);
-  AppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].SetAsInteger(udJSONRPCMinerServerPort.Position);
-  AppParams.ParamByName[CT_PARAM_JSONRPCEnabled].SetAsBoolean(cbJSONRPCPortEnabled.Checked);
-  AppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].SetAsString(ebJSONRPCAllowedIPs.Text);
-
+  TSettings.MinerPrivateKeyType := mpk;
+  TSettings.MinerServerRpcActive := cbJSONRPCMinerServerActive.Checked;
+  TSettings.MinerServerRpcPort := udJSONRPCMinerServerPort.Position;
+  TSettings.SaveLogFiles := cbSaveLogFiles.Checked;
+  TSettings.ShowLogs := cbShowLogs.Checked;
+  TSettings.SaveDebugLogs := cbSaveDebugLogs.Checked;
+  TSettings.MinerName := ebMinerName.Text;
+  TSettings.ShowModalMessages := cbShowModalMessages.Checked;
+  TSettings.RpcPortEnabled := cbJSONRPCPortEnabled.Checked;
+  TSettings.RpcAllowedIPs := ebJSONRPCAllowedIPs.Text;
+  TSettings.Save;
   ModalResult := MrOk;
   ModalResult := MrOk;
 end;
 end;
 
 
@@ -131,29 +129,7 @@ end;
 procedure TFRMPascalCoinWalletConfig.bbUpdatePasswordClick(Sender: TObject);
 procedure TFRMPascalCoinWalletConfig.bbUpdatePasswordClick(Sender: TObject);
 Var s,s2 : String;
 Var s,s2 : String;
 begin
 begin
-  if Not Assigned(FWalletKeys) then exit;
-  if Not FWalletKeys.IsValidPassword then begin
-    s := '';
-    Repeat
-      if Not InputQuery('Wallet Password','Insert Wallet Password',s) then exit;
-      FWalletKeys.WalletPassword := s;
-      if Not FWalletKeys.IsValidPassword then Application.MessageBox(PChar('Invalid password'),PChar(Application.Title),MB_ICONERROR+MB_OK);
-    Until FWalletKeys.IsValidPassword;
-  end;
-  if FWalletKeys.IsValidPassword then begin
-    s := ''; s2 := '';
-    if Not InputQuery('Change password','Type new password',s) then exit;
-    if trim(s)<>s then raise Exception.Create('Password cannot start or end with a space character');
-    if Not InputQuery('Change password','Type new password again',s2) then exit;
-    if s<>s2 then raise Exception.Create('Two passwords are different!');
-
-    FWalletKeys.WalletPassword := s;
-    Application.MessageBox(PChar('Password changed!'+#10+#10+
-      'Please note that your new password is "'+s+'"'+#10+#10+
-      '(If you lose this password, you will lose your Wallet forever !)'),
-      PChar(Application.Title),MB_ICONWARNING+MB_OK);
-  end;
-  UpdateWalletConfig;
+  TUserInterface.ChangeWalletPassword(Self)
 end;
 end;
 
 
 procedure TFRMPascalCoinWalletConfig.cbJSONRPCPortEnabledClick(Sender: TObject);
 procedure TFRMPascalCoinWalletConfig.cbJSONRPCPortEnabledClick(Sender: TObject);
@@ -173,34 +149,49 @@ begin
   ebDefaultFee.Text := TAccountComp.FormatMoney(0);
   ebDefaultFee.Text := TAccountComp.FormatMoney(0);
   ebMinerName.Text := '';
   ebMinerName.Text := '';
   bbUpdatePassword.Enabled := false;
   bbUpdatePassword.Enabled := false;
-  UpdateWalletConfig;
   lblDefaultJSONRPCMinerServerPort.Caption := Format('(Default %d)',[CT_JSONRPCMinerServer_Port]);
   lblDefaultJSONRPCMinerServerPort.Caption := Format('(Default %d)',[CT_JSONRPCMinerServer_Port]);
+  RefreshUI;
+  TWallet.Keys.OnChanged.Add(OnWalletChanged);
+end;
+
+procedure TFRMPascalCoinWalletConfig.FormDestroy(Sender: TObject);
+begin
+  TWallet.Keys.OnChanged.Remove(OnWalletChanged);
+end;
+
+procedure TFRMPascalCoinWalletConfig.CM_WalletChanged(var Msg: TMessage);
+begin
+  RefreshUI_WalletAspect;
 end;
 end;
 
 
-procedure TFRMPascalCoinWalletConfig.SetAppParams(const Value: TAppParams);
+procedure TFRMPascalCoinWalletConfig.OnWalletChanged(Sender: TObject);
+begin
+  // Ensure handled in UI thread
+  PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
+end;
+
+procedure TFRMPascalCoinWalletConfig.RefreshUI;
 Var i : Integer;
 Var i : Integer;
 begin
 begin
-  FAppParams := Value;
-  if Not Assigned(Value) then exit;
   Try
   Try
-    udInternetServerPort.Position := AppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
-    ebDefaultFee.Text := TAccountComp.FormatMoney(AppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0));
-    cbJSONRPCMinerServerActive.Checked := AppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
-    case TMinerPrivateKey(AppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].GetAsInteger(Integer(mpk_Random))) of
+    udInternetServerPort.Position := TSettings.InternetServerPort;
+    ebDefaultFee.Text := TAccountComp.FormatMoney(TSettings.DefaultFee);
+    cbJSONRPCMinerServerActive.Checked := TSettings.MinerServerRpcActive;
+    case TSettings.MinerPrivateKeyType of
       mpk_NewEachTime : rbGenerateANewPrivateKeyEachBlock.Checked := true;
       mpk_NewEachTime : rbGenerateANewPrivateKeyEachBlock.Checked := true;
       mpk_Random : rbUseARandomKey.Checked := true;
       mpk_Random : rbUseARandomKey.Checked := true;
       mpk_Selected : rbMineAllwaysWithThisKey.Checked := true;
       mpk_Selected : rbMineAllwaysWithThisKey.Checked := true;
     else rbUseARandomKey.Checked := true;
     else rbUseARandomKey.Checked := true;
     end;
     end;
-    UpdateWalletConfig;
-    cbSaveLogFiles.Checked := AppParams.ParamByName[CT_PARAM_SaveLogFiles].GetAsBoolean(false);
-    cbShowLogs.Checked := AppParams.ParamByName[CT_PARAM_ShowLogs].GetAsBoolean(false);
-    cbSaveDebugLogs.Checked := AppParams.ParamByName[CT_PARAM_SaveDebugLogs].GetAsBoolean(false);
-    ebMinerName.Text := AppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
-    cbShowModalMessages.Checked := AppParams.ParamByName[CT_PARAM_ShowModalMessages].GetAsBoolean(false);
-    udJSONRPCMinerServerPort.Position := AppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
-    cbJSONRPCPortEnabled.Checked := AppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
-    ebJSONRPCAllowedIPs.Text := AppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1;');
+    RefreshUI_WalletAspect;
+    cbSaveLogFiles.Checked := TSettings.SaveLogFiles;
+    cbShowLogs.Checked := TSettings.ShowLogs;
+    cbSaveDebugLogs.Checked := TSettings.SaveDebugLogs;
+    ebMinerName.Text := TSettings.MinerName;
+    cbShowModalMessages.Checked := TSettings.ShowModalMessages;
+    udJSONRPCMinerServerPort.Position := TSettings.MinerServerRpcPort;
+    cbJSONRPCPortEnabled.Checked := TSettings.RpcPortEnabled;
+    ebJSONRPCAllowedIPs.Text := TSettings.RpcAllowedIPs;
   Except
   Except
     On E:Exception do begin
     On E:Exception do begin
       TLog.NewLog(lterror,ClassName,'Exception at SetAppParams: '+E.Message);
       TLog.NewLog(lterror,ClassName,'Exception at SetAppParams: '+E.Message);
@@ -210,52 +201,34 @@ begin
   cbJSONRPCPortEnabledClick(nil);
   cbJSONRPCPortEnabledClick(nil);
 end;
 end;
 
 
-procedure TFRMPascalCoinWalletConfig.SetWalletKeys(const Value: TWalletKeys);
-begin
-  FWalletKeys := Value;
-  UpdateWalletConfig;
-end;
-
-procedure TFRMPascalCoinWalletConfig.UpdateWalletConfig;
+procedure TFRMPascalCoinWalletConfig.RefreshUI_WalletAspect;
 Var i, iselected : Integer;
 Var i, iselected : Integer;
   s : String;
   s : String;
   wk : TWalletKey;
   wk : TWalletKey;
 begin
 begin
-  if Assigned(FWalletKeys) then begin
-    if FWalletKeys.IsValidPassword then begin
-      if FWalletKeys.WalletPassword='' then begin
-        bbUpdatePassword.Caption := 'Wallet without password, protect it!';
-      end else begin
-        bbUpdatePassword.Caption := 'Change Wallet password';
-      end;
+  if TWallet.Keys.HasPassword then
+    bbUpdatePassword.Caption := 'Change Wallet password'
+  else
+    bbUpdatePassword.Caption := 'Wallet without password, protect it!';
+  cbPrivateKeyToMine.Items.Clear;
+  for i := 0 to TWallet.Keys.Count - 1 do begin
+    wk := TWallet.Keys.Key[i];
+    if (wk.Name='') then begin
+      s := TCrypto.ToHexaString( TAccountComp.AccountKey2RawString(wk.AccountKey));
     end else begin
     end else begin
-        bbUpdatePassword.Caption := 'Wallet with password, change it!';
+      s := wk.Name;
     end;
     end;
-    cbPrivateKeyToMine.Items.Clear;
-    for i := 0 to FWalletKeys.Count - 1 do begin
-      wk := FWalletKeys.Key[i];
-      if (wk.Name='') then begin
-        s := TCrypto.ToHexaString( TAccountComp.AccountKey2RawString(wk.AccountKey));
-      end else begin
-        s := wk.Name;
-      end;
-      if wk.CryptedKey<>'' then begin
-        cbPrivateKeyToMine.Items.AddObject(s,TObject(i));
-      end;
+    if wk.CryptedKey<>'' then begin
+      cbPrivateKeyToMine.Items.AddObject(s,TObject(i));
     end;
     end;
-    cbPrivateKeyToMine.Sorted := true;
-    if Assigned(FAppParams) then begin
-      s := FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].GetAsString('');
-      iselected := FWalletKeys.IndexOfAccountKey(TAccountComp.RawString2Accountkey(s));
-      if iselected>=0 then begin
-        iselected :=  cbPrivateKeyToMine.Items.IndexOfObject(TObject(iselected));
-        cbPrivateKeyToMine.ItemIndex := iselected;
-      end;
-
-    end;
-
-  end else bbUpdatePassword.Caption := '(Wallet password)';
-  bbUpdatePassword.Enabled := Assigned(FWAlletKeys);
+  end;
+  cbPrivateKeyToMine.Sorted := true;
+  s := TSettings.MinerSelectedPrivateKey;
+  iselected := TWallet.Keys.IndexOfAccountKey(TAccountComp.RawString2Accountkey(s));
+  if iselected >= 0 then begin
+    iselected :=  cbPrivateKeyToMine.Items.IndexOfObject(TObject(iselected));
+    cbPrivateKeyToMine.ItemIndex := iselected;
+  end;
 end;
 end;
 
 
 end.
 end.

+ 45 - 65
Units/Forms/UFRMPayloadDecoder.pas

@@ -23,7 +23,7 @@ uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, UCommonUI,
   Dialogs, StdCtrls, UCommonUI,
-  UBlockChain, UCrypto, UWalletKeys, Buttons, ComCtrls,UAppParams;
+  UBlockChain, UCrypto, UWallet, Buttons, ComCtrls,UAppParams;
 
 
 type
 type
 
 
@@ -68,17 +68,14 @@ type
     procedure PageControlChanging(Sender: TObject; var AllowChange: Boolean);
     procedure PageControlChanging(Sender: TObject; var AllowChange: Boolean);
     procedure cbMethodPublicPayloadClick(Sender: TObject);
     procedure cbMethodPublicPayloadClick(Sender: TObject);
     procedure bbSaveMethodsClick(Sender: TObject);
     procedure bbSaveMethodsClick(Sender: TObject);
-    procedure memoDecodedKeyDown(Sender: TObject; var Key: Word;
-      Shift: TShiftState);
+    procedure memoDecodedKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure bbFindClick(Sender: TObject);
     procedure bbFindClick(Sender: TObject);
     procedure ebOphashExit(Sender: TObject);
     procedure ebOphashExit(Sender: TObject);
     procedure ebOphashKeyPress(Sender: TObject; var Key: Char);
     procedure ebOphashKeyPress(Sender: TObject; var Key: Char);
     procedure cbShowAsHexadecimalClick(Sender: TObject);
     procedure cbShowAsHexadecimalClick(Sender: TObject);
   private
   private
     FOpResume : TOperationResume;
     FOpResume : TOperationResume;
-    FWalletKeys : TWalletKeys;
     FSavedDecodeMethods : boolean;
     FSavedDecodeMethods : boolean;
-    FAppParams : TAppParams;
     FSemaphor : Boolean;
     FSemaphor : Boolean;
     { Private declarations }
     { Private declarations }
     Procedure TryToDecode;
     Procedure TryToDecode;
@@ -86,7 +83,7 @@ type
     procedure SetOpResume(const Value: TOperationResume);
     procedure SetOpResume(const Value: TOperationResume);
   public
   public
     { Public declarations }
     { Public declarations }
-    Procedure Init(Const AOperationResume : TOperationResume; WalletKeys : TWalletKeys; AppParams : TAppParams);
+    Procedure Init(Const AOperationResume : TOperationResume);
     Property OpResume : TOperationResume read FOpResume write SetOpResume;
     Property OpResume : TOperationResume read FOpResume write SetOpResume;
     Procedure DoFind(Const OpHash : String);
     Procedure DoFind(Const OpHash : String);
   end;
   end;
@@ -95,7 +92,7 @@ implementation
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
-Uses UNode, UTime, UECIES, UAES, UAccounts;
+Uses UNode, UTime, UECIES, UAES, UAccounts, USettings;
 
 
 { TFRMPayloadDecoder }
 { TFRMPayloadDecoder }
 
 
@@ -183,8 +180,6 @@ procedure TFRMPayloadDecoder.FormCreate(Sender: TObject);
 begin
 begin
   FSemaphor := true;
   FSemaphor := true;
   try
   try
-    FWalletKeys := Nil;
-    FAppParams := Nil;
     memoDecoded.Lines.Clear;
     memoDecoded.Lines.Clear;
     memoOriginalPayloadInHexa.Lines.Clear;
     memoOriginalPayloadInHexa.Lines.Clear;
     lblPasswordsInfo.Caption := '';
     lblPasswordsInfo.Caption := '';
@@ -194,10 +189,8 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TFRMPayloadDecoder.Init(Const AOperationResume : TOperationResume; WalletKeys : TWalletKeys; AppParams : TAppParams);
+procedure TFRMPayloadDecoder.Init(Const AOperationResume : TOperationResume);
 begin
 begin
-  FWalletKeys := WalletKeys;
-  FAppParams := AppParams;
   OpResume := AOperationResume;
   OpResume := AOperationResume;
   FSavedDecodeMethods := true;
   FSavedDecodeMethods := true;
   PageControl.ActivePage := tsDecoded;
   PageControl.ActivePage := tsDecoded;
@@ -233,11 +226,12 @@ end;
 
 
 procedure TFRMPayloadDecoder.SaveMethods;
 procedure TFRMPayloadDecoder.SaveMethods;
 begin
 begin
-  FAppParams.ParamByName['PayloadDecoder.notencrypted'].SetAsBoolean(cbMethodPublicPayload.Checked);
-  FAppParams.ParamByName['PayloadDecoder.usingprivatekeys'].SetAsBoolean(cbUsingPrivateKeys.Checked);
-  FAppParams.ParamByName['PayloadDecoder.usingpasswords'].SetAsBoolean(cbUsingPasswords.Checked);
-  FAppParams.ParamByName['PayloadDecoder.passwords'].SetAsString(memoPasswords.Lines.Text);
-  FAppParams.ParamByName['PayloadDecoder.showashexadecimal'].SetAsBoolean(cbShowAsHexadecimal.Checked);
+  TSettings.AppParams.ParamByName['PayloadDecoder.notencrypted'].SetAsBoolean(cbMethodPublicPayload.Checked);
+  TSettings.AppParams.ParamByName['PayloadDecoder.usingprivatekeys'].SetAsBoolean(cbUsingPrivateKeys.Checked);
+  TSettings.AppParams.ParamByName['PayloadDecoder.usingpasswords'].SetAsBoolean(cbUsingPasswords.Checked);
+  TSettings.AppParams.ParamByName['PayloadDecoder.passwords'].SetAsString(memoPasswords.Lines.Text);
+  TSettings.AppParams.ParamByName['PayloadDecoder.showashexadecimal'].SetAsBoolean(cbShowAsHexadecimal.Checked);
+  TSettings.Save;
   FSavedDecodeMethods := true;
   FSavedDecodeMethods := true;
 end;
 end;
 
 
@@ -300,18 +294,11 @@ begin
     else lblFee.Font.Color := clRed;
     else lblFee.Font.Color := clRed;
     ebOpHash.text := TCrypto.ToHexaString(Value.OperationHash);
     ebOpHash.text := TCrypto.ToHexaString(Value.OperationHash);
     memoOriginalPayloadInHexa.Lines.Text := TCrypto.ToHexaString(Value.OriginalPayload);
     memoOriginalPayloadInHexa.Lines.Text := TCrypto.ToHexaString(Value.OriginalPayload);
-    if Assigned(FWalletKeys) then begin
-      cbMethodPublicPayload.Checked := FAppParams.ParamByName['PayloadDecoder.notencrypted'].GetAsBoolean(true);
-      cbUsingPrivateKeys.Checked := FAppParams.ParamByName['PayloadDecoder.usingprivatekeys'].GetAsBoolean(true);
-      cbUsingPasswords.Checked := FAppParams.ParamByName['PayloadDecoder.usingpasswords'].GetAsBoolean(true);
-      memoPasswords.Lines.Text := FAppParams.ParamByName['PayloadDecoder.passwords'].GetAsString('');
-      cbShowAsHexadecimal.Checked := FAppParams.ParamByName['PayloadDecoder.showashexadecimal'].GetAsBoolean(false);
-    end else begin
-      cbMethodPublicPayload.Checked := true;
-      cbUsingPrivateKeys.Checked := true;
-      cbUsingPasswords.Checked := true;
-      memoPasswords.Lines.Text := '';
-    end;
+    cbMethodPublicPayload.Checked := TSettings.AppParams.ParamByName['PayloadDecoder.notencrypted'].GetAsBoolean(true);
+    cbUsingPrivateKeys.Checked := TSettings.AppParams.ParamByName['PayloadDecoder.usingprivatekeys'].GetAsBoolean(true);
+    cbUsingPasswords.Checked := TSettings.AppParams.ParamByName['PayloadDecoder.usingpasswords'].GetAsBoolean(true);
+    memoPasswords.Lines.Text := TSettings.AppParams.ParamByName['PayloadDecoder.passwords'].GetAsString('');
+    cbShowAsHexadecimal.Checked := TSettings.AppParams.ParamByName['PayloadDecoder.showashexadecimal'].GetAsBoolean(false);
     FSavedDecodeMethods := true;
     FSavedDecodeMethods := true;
     PageControl.ActivePage := tsDecoded;
     PageControl.ActivePage := tsDecoded;
     TryToDecode;
     TryToDecode;
@@ -325,10 +312,8 @@ procedure TFRMPayloadDecoder.TryToDecode;
   Var i : Integer;
   Var i : Integer;
   begin
   begin
     Result := false;
     Result := false;
-    if Not assigned(FWalletKeys) then exit;
-
-    for i := 0 to FWalletKeys.Count - 1 do begin
-      WalletKey := FWalletKeys.Key[i];
+    for i := 0 to TWallet.Keys.Count - 1 do begin
+      WalletKey := TWallet.Keys.Key[i];
       If Assigned(WalletKey.PrivateKey) then begin
       If Assigned(WalletKey.PrivateKey) then begin
         If ECIESDecrypt(WalletKey.PrivateKey.EC_OpenSSL_NID,WalletKey.PrivateKey.PrivateKey,false,raw,Decrypted) then begin
         If ECIESDecrypt(WalletKey.PrivateKey.EC_OpenSSL_NID,WalletKey.PrivateKey.PrivateKey,false,raw,Decrypted) then begin
           Result := true;
           Result := true;
@@ -361,42 +346,37 @@ Var raw : TRawBytes;
   ok : boolean;
   ok : boolean;
 begin
 begin
   ok := true;
   ok := true;
-  if Assigned(FWalletKeys) And Assigned(FAppParams) then begin
-    raw := FOpResume.OriginalPayload;
-    if raw<>'' then begin
-      // First try to a human readable...
-      if (cbMethodPublicPayload.Checked) and (TCrypto.IsHumanReadable(raw)) then begin
-        if cbShowAsHexadecimal.Checked then memoDecoded.Lines.Text := TCrypto.ToHexaString(raw)
-        else memoDecoded.Lines.Text := raw;
-        lblDecodedMethod.Caption := 'Not encrypted payload';
-      end else if (cbUsingPrivateKeys.Checked) And (UseWallet(raw,Decrypted,WalletKey)) then begin
-        if cbShowAsHexadecimal.Checked then memoDecoded.Lines.Text := TCrypto.ToHexaString(Decrypted)
-        else memoDecoded.Lines.Text := Decrypted;
-        lblDecodedMethod.Caption := 'Encrypted with EC '+TAccountComp.GetECInfoTxt(WalletKey.PrivateKey.EC_OpenSSL_NID);
-      end else if (cbUsingPasswords.Checked) And (UsePassword(raw,Decrypted,PasswordUsed)) then begin
-        if cbShowAsHexadecimal.Checked then memoDecoded.Lines.Text := TCrypto.ToHexaString(Decrypted)
-        else memoDecoded.Lines.Text := Decrypted;
-        lblDecodedMethod.Caption := 'Encrypted with pwd:"'+PasswordUsed+'"';
-      end else begin
-        memoDecoded.Lines.Text := 'CANNOT DECRYPT';
-        lblDecodedMethod.Caption := '';
-        ok := false;
-      end;
-      if ok then begin
-        memoDecoded.Font.Color := clBlack;
-        memoDecoded.Color := clWhite;
-      end else begin
-        memoDecoded.Font.Color := clRed;
-        memoDecoded.Color := clBtnFace;
-      end;
+  raw := FOpResume.OriginalPayload;
+  if raw<>'' then begin
+    // First try to a human readable...
+    if (cbMethodPublicPayload.Checked) and (TCrypto.IsHumanReadable(raw)) then begin
+      if cbShowAsHexadecimal.Checked then memoDecoded.Lines.Text := TCrypto.ToHexaString(raw)
+      else memoDecoded.Lines.Text := raw;
+      lblDecodedMethod.Caption := 'Not encrypted payload';
+    end else if (cbUsingPrivateKeys.Checked) And (UseWallet(raw,Decrypted,WalletKey)) then begin
+      if cbShowAsHexadecimal.Checked then memoDecoded.Lines.Text := TCrypto.ToHexaString(Decrypted)
+      else memoDecoded.Lines.Text := Decrypted;
+      lblDecodedMethod.Caption := 'Encrypted with EC '+TAccountComp.GetECInfoTxt(WalletKey.PrivateKey.EC_OpenSSL_NID);
+    end else if (cbUsingPasswords.Checked) And (UsePassword(raw,Decrypted,PasswordUsed)) then begin
+      if cbShowAsHexadecimal.Checked then memoDecoded.Lines.Text := TCrypto.ToHexaString(Decrypted)
+      else memoDecoded.Lines.Text := Decrypted;
+      lblDecodedMethod.Caption := 'Encrypted with pwd:"'+PasswordUsed+'"';
     end else begin
     end else begin
-      memoDecoded.Lines.Text := '(No payload)';
-      memoDecoded.Font.Color := clDkGray;
-      memoDecoded.Color := clLtGray;
+      memoDecoded.Lines.Text := 'CANNOT DECRYPT';
       lblDecodedMethod.Caption := '';
       lblDecodedMethod.Caption := '';
+      ok := false;
+    end;
+    if ok then begin
+      memoDecoded.Font.Color := clBlack;
+      memoDecoded.Color := clWhite;
+    end else begin
+      memoDecoded.Font.Color := clRed;
+      memoDecoded.Color := clBtnFace;
     end;
     end;
   end else begin
   end else begin
-    memoDecoded.Lines.Text := '';
+    memoDecoded.Lines.Text := '(No payload)';
+    memoDecoded.Font.Color := clDkGray;
+    memoDecoded.Color := clLtGray;
     lblDecodedMethod.Caption := '';
     lblDecodedMethod.Caption := '';
   end;
   end;
 end;
 end;

+ 1 - 1
Units/Forms/UFRMPendingOperations.pas

@@ -78,7 +78,7 @@ end;
 procedure TFRMPendingOperations.miFindOperationbyOpHashClick(Sender: TObject);
 procedure TFRMPendingOperations.miFindOperationbyOpHashClick(Sender: TObject);
 var ophash:AnsiString;
 var ophash:AnsiString;
 begin
 begin
-  if Not TUserInterface.AskUserEnterString(Self, 'Search operation by OpHash','Insert Operation Hash value (OpHash)',ophash)
+  if Not TUserInterface.AskEnterString(Self, 'Search operation by OpHash','Insert Operation Hash value (OpHash)',ophash)
     then exit;
     then exit;
 
 
   TUserInterface.ShowOperationInfoDialog(Self, ophash);
   TUserInterface.ShowOperationInfoDialog(Self, ophash);

+ 1319 - 591
Units/Forms/UFRMWalletKeys.lfm

@@ -1,252 +1,99 @@
 object FRMWalletKeys: TFRMWalletKeys
 object FRMWalletKeys: TFRMWalletKeys
-  Left = 628
-  Height = 478
-  Top = 282
-  Width = 569
-  BorderIcons = [biSystemMenu]
-  BorderStyle = bsSingle
-  Caption = 'Wallet keys'
-  ClientHeight = 478
-  ClientWidth = 569
-  Color = clBtnFace
-  Font.Color = clWindowText
-  Font.Height = -11
-  Font.Name = 'Tahoma'
+  Left = 198
+  Height = 477
+  Top = 373
+  Width = 661
+  Caption = 'Wallet Keys'
+  ClientHeight = 477
+  ClientWidth = 661
   OnCreate = FormCreate
   OnCreate = FormCreate
+  OnDestroy = FormDestroy
   Position = poOwnerFormCenter
   Position = poOwnerFormCenter
   LCLVersion = '1.6.4.0'
   LCLVersion = '1.6.4.0'
+  object lbWalletKeys: TListBox
+    Left = 24
+    Height = 210
+    Top = 80
+    Width = 612
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    ItemHeight = 0
+    OnClick = lbWalletKeysClick
+    PopupMenu = pmKeyMenu
+    ScrollWidth = 344
+    TabOrder = 0
+  end
   object lblEncryptionTypeCaption: TLabel
   object lblEncryptionTypeCaption: TLabel
-    Left = 30
-    Height = 13
-    Top = 298
-    Width = 80
-    Caption = 'Encryption type:'
+    Left = 55
+    Height = 15
+    Top = 305
+    Width = 50
+    Anchors = [akLeft, akBottom]
+    Caption = 'Key Type:'
     ParentColor = False
     ParentColor = False
   end
   end
   object lblEncryptionType: TLabel
   object lblEncryptionType: TLabel
-    Left = 125
-    Height = 13
-    Top = 298
-    Width = 54
+    Left = 115
+    Height = 15
+    Top = 304
+    Width = 521
+    Anchors = [akLeft, akRight, akBottom]
+    AutoSize = False
     Caption = '000000000'
     Caption = '000000000'
     ParentColor = False
     ParentColor = False
   end
   end
   object lblKeyNameCaption: TLabel
   object lblKeyNameCaption: TLabel
-    Left = 30
-    Height = 13
-    Top = 317
-    Width = 51
-    Caption = 'Key name:'
+    Left = 48
+    Height = 15
+    Top = 328
+    Width = 57
+    Anchors = [akLeft, akBottom]
+    Caption = 'Key Name:'
     ParentColor = False
     ParentColor = False
   end
   end
   object lblKeyName: TLabel
   object lblKeyName: TLabel
-    Left = 125
-    Height = 13
-    Top = 317
-    Width = 313
+    Left = 115
+    Height = 15
+    Top = 328
+    Width = 521
+    Anchors = [akLeft, akRight, akBottom]
     AutoSize = False
     AutoSize = False
     Caption = '000000000'
     Caption = '000000000'
     ParentColor = False
     ParentColor = False
   end
   end
   object lblPrivateKeyCaption: TLabel
   object lblPrivateKeyCaption: TLabel
-    Left = 30
-    Height = 13
-    Top = 336
+    Left = 47
+    Height = 15
+    Top = 352
     Width = 58
     Width = 58
-    Caption = 'Private key:'
-    ParentColor = False
-  end
-  object lblPrivateKeyCaption2: TLabel
-    Left = 30
-    Height = 13
-    Top = 355
-    Width = 80
-    Caption = '(In hexa format)'
-    ParentColor = False
-  end
-  object lblKeysEncrypted: TLabel
-    Left = 30
-    Height = 39
-    Top = 15
-    Width = 259
-    AutoSize = False
-    Caption = 'lblKeysEncrypted'
-    Font.Color = clBlack
-    Font.Height = -16
-    Font.Name = 'Tahoma'
-    Font.Style = [fsBold]
+    Anchors = [akLeft, akBottom]
+    Caption = 'Public Key:'
     ParentColor = False
     ParentColor = False
-    ParentFont = False
-    WordWrap = True
-  end
-  object lbWalletKeys: TListBox
-    Left = 30
-    Height = 227
-    Top = 60
-    Width = 346
-    ItemHeight = 0
-    OnClick = lbWalletKeysClick
-    ScrollWidth = 344
-    TabOrder = 0
-  end
-  object bbExportPrivateKey: TBitBtn
-    Left = 382
-    Height = 36
-    Top = 136
-    Width = 159
-    Caption = 'Export Private key'
-    Glyph.Data = {
-      76060000424D7606000000000000360400002800000018000000180000000100
-      0800000000004002000000000000000000000001000000010000FF00FF005251
-      5100565758005A5958005B5D5D005D5E5E006361610066666600696969006C6B
-      6B0073706F0072707000747271000E80AA001788AF000B86B2000C85B000098A
-      B700078CBA00198EB7000E91BE001E94BC002898BA003E99BB000493C4000997
-      C7000A9ECF00229BC20035A0C30030AACA0032AACE003DAACC003FB0CB0036A9
-      D0003BB1D9003DBDDA0039B8DE0029BBE0004DBBD90068B0CA0019C7F1001BD4
-      FE002FC6E7003ECDE9002CD3F9002ED8FE003CE0FE0054C0D40059C4D70059C2
-      DD006FC2D6007CC0D50078C1D80049DDFE0054DFFE0061C6E5006CD4EE0064D9
-      E90076DFE9007DDFE90055E0FF0058E0FE006BE3F40063E6FE0060ECFE0075E2
-      FA0077E6FF007BE8FF0071F2FE0088828000928E8C0096908F00969291009794
-      94009E969400A09C9B00A19F9E00ACA09E00A6A2A100A6A4A400ADA5A300AAA5
-      A400ABA8A800ADAAA900B0A5A300B2A7A500B2ABAB00B4ABA900BBB1AE00BEB1
-      AF00BAB3B200BAB4B200BEB6B400C4B8B600C1BCBB0083DFE9008ADAEB0094DF
-      E90089DDF100A4DFEA009AE2F40095EBFD0095EDFE009EEDFF0084F3F90080F5
-      FC008FF6FB0083F8FE0093F2FE0097F9FE0094FDFE0099FFFE009EFFFE00AAEF
-      FD00B4EEF300A4FFFE00A8F9FE00ADFBFE00AAFFFE00B6F1FF00BCF2F800B3F9
-      FF00B3FFFE00B9FFFE00C7C2C100C7C6C600CCC4C200CAC7C600CFCCCC00D1C7
-      C500D4CBC900D1CDCD00D5CFCE00D8D0CE00D7D1D000D9D5D400DCD7D600DFD8
-      D600E3DEDD00C3DFEA00CCF6FF00C9FFFE00CFFFFF00D1F7FF00DBF8FE00DFFF
-      FF00E7E3E200E9E5E500ECE9E900EFEEED00F1EBEA00F1EFEE00E5FFFF00F3F1
-      F100F6F2F000F8F5F300F8F5F400F0F7FA00F5FFFF00FBF8F800FAFFFF00FFFE
-      FE00000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0007070707000000000000000000000000000000000000000746967E07000000
-      0000000000000000000000000000000D085E489A5E080D0D0000000000000000
-      00000000000D0D2626075E48A1071F130D0D000000000000000000000D163940
-      3F35075E4C93070707100D000000000000000000123A6B402E353D075E519580
-      4E0707070707000000000000123A6B402E293D42075E4EA19289858281550700
-      00000000123A6B402E292D4266075E4C9689865A475D4D0700000000123A6B40
-      2E292D3C6671077D928A7D0A0A58580700000000123A6B402E292D3C4371079A
-      958007035151550700000000123A6D6C6667778C8F90079A860701574C024A07
-      0000000012727860311E1B151C3407A17E0B534C000445070000000011322023
-      2A282C36426407539A8882040404570700000000103169402E292D3643716207
-      5393825A515A5A0700000000123A6B402E292D3C436662370707070708070700
-      00000000123A6B402E292D3C43663837222117000000000000000000123A6B40
-      2E292D3C436638231A180D000000000000000000123A6B402E292D3C43663822
-      1A180D000000000000000000123A6B402E292D3C436638231A180D0000000000
-      00000000123B757975756F6F6F6F6A3E25190D000000000000000000128BA190
-      8E79736F6F6F6F6D442B0D00000000000000000012279D9D908E796F6F6F6F6F
-      691E0D000000000000000000001214333363615F3B3A2F2F0E0D000000000000
-      0000000000000014121212121212121200000000000000000000
-    }
-    OnClick = bbExportPrivateKeyClick
-    TabOrder = 4
   end
   end
-  object memoPrivateKey: TMemo
-    Left = 125
-    Height = 80
-    Top = 336
-    Width = 416
+  object memoPublicKey: TMemo
+    Left = 115
+    Height = 61
+    Top = 352
+    Width = 522
+    Anchors = [akLeft, akRight, akBottom]
     Color = clBtnFace
     Color = clBtnFace
     Font.Color = clBlack
     Font.Color = clBlack
-    Font.Height = -16
+    Font.Height = -11
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Lines.Strings = (
     Lines.Strings = (
-      'memoPrivateKey'
+      'memoPublicKey'
     )
     )
     ParentFont = False
     ParentFont = False
     ReadOnly = True
     ReadOnly = True
-    TabOrder = 9
+    TabOrder = 1
     TabStop = False
     TabStop = False
   end
   end
-  object bbChangeName: TBitBtn
-    Left = 440
-    Height = 25
-    Top = 305
-    Width = 101
-    Caption = 'Change Name'
-    OnClick = bbChangeNameClick
-    TabOrder = 8
-  end
-  object bbImportPrivateKey: TBitBtn
-    Left = 382
-    Height = 36
-    Top = 98
-    Width = 159
-    Caption = 'Import Private key'
-    Glyph.Data = {
-      76060000424D7606000000000000360400002800000018000000180000000100
-      0800000000004002000000000000000000000001000000010000FF00FF000571
-      0A0008750D0024B53B0029B942002ABA44002EBD4A002FBF4C0033C1500034C2
-      520035C3540037C5570039C659003BC85C003CC95E003FCC630040CC650045D0
-      6B0046D16C0049D472004BD675004ED8790050D97B0051DA7E000E80AA001788
-      AF000B86B200098AB700078CBA00198EB700118EB9000E91BE001E94BC002898
-      BA0055DD810056DF850058E087000493C4000997C7000C9BCB000A9DCE00229B
-      C20015AFD90026A0C80021AACF0035A0C30030AACA0032AACE003DAACC003FB0
-      CB0031AED7003DBDDA0039B8DE0029BBE00056B1CE0052BDDB0068B0CA006BBD
-      D70019C7F1001BD4FE002FC6E70026C2E9003ECDE9002CD3F9002ED8FE003CE0
-      FE0054C0D40059C4D70059C2DD006FC2D60062C3DE007CC0D5007AC6DF0043C8
-      E90054DFFE0060CEEA0079CFE9006CD4EE0064D9E90076DFE9007DDFE90055E0
-      FF006BE3F40060ECFE0075E2FA007BE8FF0071F2FE008FD0E60083DFE9008ADA
-      EB0094DFE90081DBF100A4DFEA0095EBFD0095EEFE009EEDFF0084F3F90080F5
-      FC008FF6FB0083F8FE0093F2FE0097F9FE0094FDFE0099FFFE009EFFFE00AFE8
-      F600B4EEF300A4FFFE00A8F9FE00ADFBFE00AAFFFE00B6F1FF00BCF2F800B3F9
-      FF00B3FFFE00B9FFFE00C3DFEA00CCF6FF00C9FFFE00CFFFFF00D1F6FE00DFFF
-      FF00E5FFFF00F0F7FA00F5FFFF00FAFFFF000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000202020200000000000000000000000000000000000000
-      0002040302000000000000000000001818181818181818180002060402000000
-      000000000018182C2C2A3D494B46301D18020906020000000000000018214E53
-      413B4051555D4D3427020D0902000000000000001C4F6353413B405102020202
-      02020F0D02020202020200001C4F6353413B405102242317151311100D090906
-      040200001C4F6353413B40510224242323151311100F0D09060200001C4F6353
-      413B4051020101010102171302010101020100001C4F6353413B4051555D4D34
-      2702231702000000000000001C4F65645D5F6F757878694C3202242302000000
-      000000001C6A7059442F29202D3639485702242402000000000000001B453134
-      3C3A3F4A545B372B1E02242402000000000000001A436153413B4051555D4D34
-      2701020202000000000000001C4F6353413B4051555D4D342725180000000000
-      000000001C4F6353413B4051555D4D342725180000000000000000001C4F6353
-      413B4051555D4D342725180000000000000000001C4F6353413B4051555D4D34
-      2825180000000000000000001C4F6353413B4051555D4D342725180000000000
-      000000001C506D716D6D6767676762523527180000000000000000001C747D7A
-      77716B6767676765563E180000000000000000001C387B7C7977716767676767
-      612F18000000000000000000001C1F47475C5A58504F42421918000000000000
-      000000000000001C1C1C1C1C1C1C1C1C00000000000000000000
-    }
-    OnClick = bbImportPrivateKeyClick
-    TabOrder = 3
-  end
-  object bbExportPublicKey: TBitBtn
-    Left = 382
+  object btnBackupWallet: TBitBtn
+    Left = 24
     Height = 36
     Height = 36
-    Top = 212
-    Width = 159
-    Caption = 'Export Public key'
+    Top = 426
+    Width = 193
+    Anchors = [akBottom]
+    Caption = 'Backup Wallet'
     Glyph.Data = {
     Glyph.Data = {
       F6060000424DF606000000000000360000002800000018000000180000000100
       F6060000424DF606000000000000360000002800000018000000180000000100
       180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
       180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
@@ -305,15 +152,16 @@ object FRMWalletKeys: TFRMWalletKeys
       89B88989B88989B88989B88989B88989B88989B88989B88989FF00FFFF00FFFF
       89B88989B88989B88989B88989B88989B88989B88989B88989FF00FFFF00FFFF
       00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
       00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
     }
     }
-    OnClick = bbExportPublicKeyClick
-    TabOrder = 6
+    OnClick = btnBackupWalletClick
+    TabOrder = 2
   end
   end
-  object bbImportPublicKey: TBitBtn
-    Left = 382
+  object btnRestoreBackup: TBitBtn
+    Left = 432
     Height = 36
     Height = 36
-    Top = 174
-    Width = 159
-    Caption = 'Import Public key'
+    Top = 426
+    Width = 206
+    Anchors = [akRight, akBottom]
+    Caption = 'Restore Backup'
     Glyph.Data = {
     Glyph.Data = {
       F6060000424DF606000000000000360000002800000018000000180000000100
       F6060000424DF606000000000000360000002800000018000000180000000100
       180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
       180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
@@ -372,43 +220,80 @@ object FRMWalletKeys: TFRMWalletKeys
       FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C85180C85180C85180C85180C
       FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C85180C85180C85180C85180C
       8518FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
       8518FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
     }
     }
-    OnClick = bbImportPublicKeyClick
-    TabOrder = 5
+    OnClick = btnRestoreBackupClick
+    TabOrder = 3
   end
   end
-  object bbGenerateNewKey: TBitBtn
-    Left = 382
-    Height = 36
-    Top = 60
-    Width = 159
-    Caption = 'Generate a new Key'
+  object btnCopyClipboard: TSpeedButton
+    Left = 81
+    Height = 24
+    Top = 376
+    Width = 24
+    Anchors = [akLeft, akBottom]
     Glyph.Data = {
     Glyph.Data = {
-      76060000424D7606000000000000360400002800000018000000180000000100
-      0800000000004002000000000000000000000001000000010000FF00FF007D33
-      2F00993300000C35EB000335FB001342FB00224EFB00325BFC005274FC000E80
-      AA001788AF000B86B200098AB700078CBA00078EBD00118EB9000E91BE001E94
-      BC002898BA000493C4000997C7000A9DCE00229BC20015AFD90026A0C80021AA
-      CF0035A0C30030AACA0032AACE003FB0CB003DBDDA0039B8DE0029BBE00046A6
-      C90056B1CE0052BDDB0068B0CA006BBDD700718DFC0019C7F1001BD4FE002FC6
-      E70026C2E9003ECDE9002CD3F9002ED8FE003CE0FE0054C0D40059C4D70059C2
-      DD006FC2D6007CC0D50076C4DF007AC6DF0043C8E90054DFFE0060CEEA006CD4
-      EE0064D9E90076DFE9007DDFE90055E0FF006BE3F40060ECFE0075E2FA007BE8
-      FF0071F2FE008099FC00A0B2FD00AFBFFD008FD0E60083DFE9008ADAEB0094DF
-      E90081DBF100A4DFEA0095EBFD0095EEFE009EEDFF0084F3F90080F5FC008FF6
-      FB0083F8FE0093F2FE0097F9FE0094FDFE0099FFFE009EFFFE00B4EEF300A4FF
-      FE00A8F9FE00ADFBFE00AAFFFE00B6F1FF00BCF2F800B3F9FF00B3FFFE00B9FF
-      FE00C3DFEA00CFD8FD00DFE5FE00CCF6FF00C9FFFE00CFFFFF00D1F7FF00DFFF
-      FF00EEF1FE00E5FFFF00F0F7FA00F5FFFF00FAFFFF00FEFEFE00000000000000
+      36090000424D3609000000000000360000002800000018000000180000000100
+      2000000000000009000064000000640000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      0003000000080000000800000008000000080000000800000008000000080000
+      0008000000080000000800000003000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      006B000000CB000000CE000000CE000000CE000000CE000000CE000000CE0000
+      00CE000000CE000000CB0000007B000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      00C70000007D0000003C0000003C0000003C0000003C0000003C0000003C0000
+      003C0000003C00000099000000F8000000000000000000000000000000000000
+      0000000000000000002300000036000000360000003600000036000000360000
+      00DB000000550000000000000000000000000000000000000000000000000000
+      0000000000000000007A000000F9000000000000000000000000000000000000
+      000000000000000000E3000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000550000000000000000000000000000000000000000000000000000
+      0000000000000000007A000000F9000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000550000000000000000000000000000000000000000000000000000
+      0000000000000000007A000000F9000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000550000000000000000000000000000000000000000000000000000
+      0000000000000000007A000000F9000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000550000000000000000000000000000000000000000000000000000
+      0000000000000000007A000000F9000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000550000000000000000000000000000000E0000003B0000003D0000
+      003D0000003D0000009A000000E9000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF0000005500000000000000000000000000000085000000F0000000CC0000
+      00CC000000DA000000FF0000005C000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF00000055000000000000000000000000000000A8000000BF000000000000
+      000E0000009B0000007000000004000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF00000055000000000000000000000000000000A8000000BF0000002F0000
+      00B4000000800000000A00000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF00000056000000010000000100000001000000A9000000E3000000CB0000
+      005F000000050000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000930000005E0000005E0000005E000000D0000000EF0000005D0000
+      0004000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF000000C3000000040000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000E3000000D3000000D3000000D30000
+      00D3000000D3000000D3000000D8000000F7000000FF000000BF000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000530000000200000002000000020000
+      000200000002000000020000001B000000CC000000FF000000BF000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000EB000000F9000000EF000000EA000000EA000000EA0000
+      00EA000000EA000000EA000000EC000000F6000000F9000000AC000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000350000006E0000006E0000006E0000006E0000006E0000
+      006E0000006E0000006E0000006E0000006E0000006D0000001A000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
@@ -416,377 +301,1220 @@ object FRMWalletKeys: TFRMWalletKeys
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
-      000000020202020202020202020200000000000000000000000000026F6F6F6F
-      64076A6F6F0200000000000000090909090909026F6F6F450504446F6F020000
-      00000009091919172A3638026F6F26040404066F6F020000000009123A3F2E28
-      2D3D41026A070404260504456F02000000000D3B523F2E282D3D410206040545
-      6F4304066F02000000000D3B523F2E282D3D41024407636F6F6A050443020000
-      00000D3B523F2E282D3D41026F6F6F6F6F6F44040401000000000D3B523F2E28
-      2D3D41026F6F6F6F6F6F6F080403000000000D3B523F2E282D3D41026F6F6F6F
-      6F6F6F6A0704040000000D3B54534D4E5D656802020202020202020201030404
-      00000D585E48311C16111A2225354634090000000000040404000C321D1E2927
-      2C37404A23180F21090000000000000404040B30503F2E282D3D414D391E150D
-      090000000000000000000D3B523F2E282D3D414D391E15130900000000000000
-      00000D3B523F2E282D3D414D391F1513090000000000000000000D3B523F2E28
-      2D3D414D391F1513090000000000000000000D3B523F2E282D3D414D391E1513
-      090000000000000000000D3B523F2E282D3D414D391F15130900000000000000
-      00000D3C5B5F5B5B56565656513E2014090000000000000000000D626F69675F
-      595656565654422B090000000000000000000D246C6D69675F5656565656501C
-      09000000000000000000000D1033334B49473C3B2F2F0A090000000000000000
-      00000000000D0D0D0D0D0D0D0D0D000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000
     }
     }
-    OnClick = bbGenerateNewKeyClick
-    TabOrder = 2
+    OnClick = btnCopyClipboardClick
   end
   end
-  object bbDelete: TBitBtn
-    Left = 382
-    Height = 36
-    Top = 251
-    Width = 159
-    Caption = 'Delete'
+  object btnAddKey: TSpeedButton
+    Left = 604
+    Height = 32
+    Top = 40
+    Width = 32
+    Anchors = [akTop, akRight]
     Glyph.Data = {
     Glyph.Data = {
-      F6060000424DF606000000000000360000002800000018000000180000000100
-      180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF00009A00009A00039D020DA4020D
-      A400039D00009A00009AFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF00009A020DA4041FB3072FC0
-      0732C20732C20732C20732C2072FC0041FB3020DA400009AFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF00009A01079F0526B807
-      32C20732C20732C20732C20732C20732C20732C20732C20732C20732C20526B8
-      01079F00009AFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF00009A0210
-      A7062FC50732C50732C20732C20732C20732C20732C20732C20732C20732C207
-      32C20732C20732C2072FC00210A700009AFF00FFFF00FFFF00FFFF00FFFF00FF
-      00009A0210A80633D00633CF0632CA0732C60732C20732C20732C20732C20732
-      C20732C20732C20732C20732C20732C20732C20732C20210A700009AFF00FFFF
-      00FFFF00FFFF00FF01079F0530D70533DA0633D50633D00632CB0732C70732C3
-      0732C20732C20732C20732C20732C20732C20732C20732C20732C20732C2072F
-      C001079FFF00FFFF00FFFF00FF00009A0427CC0534E40533DF0533DB022FD512
-      3DD44868DA042FC70430C30732C20732C20631C2002BC03E5FD01F46C8012CC0
-      0732C20732C20732C20526B800009AFF00FFFF00FF010DA90434EC0434EA0534
-      E50533E1113ADDB3C1F3FEFEFF7F95E50029C7042FC40631C20026BE5F7BD7F9
-      FAFDCED6F32146C80732C20732C20732C20732C2020DA4FF00FF00009A0321CB
-      0335F50434F00434EB0534E6224AE5EFF2FDFFFFFFFFFFFF7E95E60029C80024
-      C25F7AD7F9FAFEFFFFFFFFFFFF4464D10732C20732C20732C20732C2041FB300
-      009A00009A0431E90335FA0335F60434F10434EC002DE64164EAEBEEFCFFFFFF
-      FFFFFF718AE35875DCF9FAFEFFFFFFFCFCFE6781D9022CC00732C20732C20732
-      C20732C2072FC000009A00039E0737F30839FB0537FB0335F70434F20434ED00
-      28E64063EAEAEEFDFFFFFFFDFDFFFCFCFFFFFFFFFBFBFE6781DA0027BE0531C2
-      0732C20732C20732C20732C20732C200039D010DAC1241FB1E4AFB0C3CFB0335
-      FB0335F80435F30434EE0027E7385EEBE9EDFDFFFFFFFFFFFFF8F9FE5F7CDF00
-      25C50631C30732C20732C20732C20732C20732C20732C2020DA4020EAD224EFB
-      456AFC204CFB0335FB0335FB0335F90333F50029EF5272F1ECF0FDFFFFFFFFFF
-      FFF8F9FE718BE5002ACD0430CA0732C50732C20732C20732C20732C20732C202
-      0DA400039F2852F86785FD3E65FC0738FB0335FB0234FB002AFA5D7CF9F9FAFF
-      FFFFFFF4F6FEEEF1FDFFFFFFFFFFFF7E96E8002ACE0430CB0732C60732C30732
-      C20732C20732C200039D00009A2048F37792FD6B88FD1946FB0335FB0130FB5D
-      7DFDF9FAFFFFFFFFFCFCFF5978F3395DEDEBEEFDFFFFFFFFFFFF7F96E90631D1
-      0632CC0732C80732C30732C2072FC000009A00009A112ED76B88FD9AAEFD466B
-      FC093AFB214CFBFAFBFFFFFFFFFCFCFF6482FB002AF20027EC4063EEEBEEFDFF
-      FFFFFFFFFF4466E00633D20633CD0732C90732C4041FB300009AFF00FF0511B2
-      456AFCA8B9FE8FA5FD2E58FC0835FB92A7FDF1F4FF6583FD002AFB0234F90435
-      F40028ED4064EFE6EBFCABBAF5113ADE0633D80633D30633CF0632C9020DA4FF
-      00FFFF00FF00009A1B3DE57A94FDBFCCFE89A1FD2A54FC0637FB2652FC0030FB
-      0234FB0335FB0335FA0335F6002DF01F4AEE0A39E70130E20533DE0533D90633
-      D40526BF00009AFF00FFFF00FFFF00FF0108A72F56F792A8FDCDD7FE97ACFD45
-      6AFC1745FB0637FB0335FB0335FB0335FB0335FA0335F70434F20535ED0535E8
-      0534E40533DF0530D301079FFF00FFFF00FFFF00FFFF00FF00009A0717BA3A61
-      FC95AAFDCFD8FEB6C4FE7A94FD456AFC2752FC1745FB103FFB103FFB1543FB1B
-      48F91A46F40D3BEF0434E90533DF0210A900009AFF00FFFF00FFFF00FFFF00FF
-      FF00FF00009A0717BA3158F7839CFDC0CCFECDD7FEB8C6FE99ADFD7E97FD6C89
-      FD6583FD607FFC5073FC2E58FA0F3DF40431E60210AB00009AFF00FFFF00FFFF
-      00FFFF00FFFF00FFFF00FFFF00FF00009A0209A81F40E65073FC819AFDA1B4FE
-      AEBEFEA9BAFE9AAEFD839CFD6281FD3860FC1644F90529D90107A200009AFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF00009A07
-      13B41733DA2C53F73A61FB4066FC3961FC2A54F81741F00826D2010DAD00009A
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FF00009A00009A0105A0020EB1010DB00003A000009A00
-      009AFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+      36040000424D3604000000000000360000002800000010000000100000000100
+      2000000000000004000064000000640000000000000000000000000000000000
+      0000000000000000000000000000503E2C03503E2CD3503E2CFF503E2CFF503E
+      2C8B000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000503E2C03503E
+      2C14503E2C14503E2C14503E2C14503E2C3B503E2CFF503E2CFF503E2CFF503E
+      2CFF503E2C14503E2C14503E2C14503E2C14503E2C1200000000503E2CD3503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2C64503E2CFF503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2C85503E2CFF503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2C83503E2C8B503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E
+      2CFF503E2CFF503E2CFF503E2CFF503E2CFF503E2CF9503E2C38000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C14503E2CFF503E2CFF503E2CFF503E
+      2CFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000503E2C12503E2CFF503E2CFF503E2CFF503E
+      2CF9000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000503E2C64503E2C85503E2C83503E
+      2C38000000000000000000000000000000000000000000000000
     }
     }
-    OnClick = bbDeleteClick
-    TabOrder = 7
+    OnClick = btnAddKeyClick
+  end
+  object lblKeysEncrypted: TLabel
+    Left = 97
+    Height = 32
+    Top = 40
+    Width = 496
+    Alignment = taCenter
+    AutoSize = False
+    Caption = 'lblKeysEncrypted'
+    Font.Color = clBlack
+    Font.Height = -16
+    Font.Name = 'Tahoma'
+    Font.Style = [fsBold]
+    ParentColor = False
+    ParentFont = False
+    WordWrap = True
   end
   end
-  object bbUpdatePassword: TBitBtn
-    Left = 382
-    Height = 38
+  object btnLock: TSpeedButton
+    Left = 25
+    Height = 64
     Top = 8
     Top = 8
-    Width = 159
-    Caption = 'Password'
+    Width = 64
     Font.Color = clWindowText
     Font.Color = clWindowText
     Font.Height = -13
     Font.Height = -13
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
-    Glyph.Data = {
-      76060000424D7606000000000000360400002800000018000000180000000100
-      0800000000004002000000000000000000000001000000010000000000000101
-      0100020202000303030004040400050505000606060007070700080808000909
-      09000A0A0A000B0B0B000C0C0C000D0D0D000E0E0E000F0F0F00101010001111
-      1100121212001313130014141400151515001616160017171700181818001919
-      19001A1A1A001B1B1B001C1C1C001D1D1D001E1E1E001F1F1F00202020002121
-      2100222222002323230024242400252525002626260027272700282828002929
-      29002A2A2A002B2B2B002C2C2C002D2D2D002E2E2E002F2F2F00303030003131
-      3100323232003333330034343400353535003636360037373700383838003939
-      39003A3A3A003B3B3B003C3C3C003D3D3D003E3E3E003F3F3F00404040004141
-      4100424242004343430044444400454545004646460047474700484848004949
-      49004A4A4A004B4B4B004C4C4C004D4D4D004E4E4E004F4F4F00505050005151
-      5100525252005353530054545400555555005656560057575700585858005959
-      59005A5A5A005B5B5B005C5C5C005D5D5D005E5E5E00685968007C4F7C009441
-      9400B72CB700DD15DD00F506F500FD01FD00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00F008F900D517F000BD24E800A830E1007B4B
-      D0005065C1003774B7002B7DB100237FAC001F82AD001C83AD001785AE001687
-      AF001489B100128AB300108CB6000F8EB9000D91BB000C94BF000A97C3000A99
-      C5000A9AC7000B9BC8000B9CCA000C9ECC000C9FCD000DA0CE000DA1CE000EA2
-      CF0011A3CF0015A4CF0018A5CF001CA7D10021A9D1002AAAD00035AACD0035AD
-      D00035AFD30035B1D60037B5D8003AB8DB003EB9DC0040BBDD0045BEDE004CC1
-      E00055C6E3005BC8E40061CAE40066CBE3006BCCE30072D3E60078D8EB0080D8
-      EE0083D9F10085DCF40088DBF5008BDBF6008EDAF70091DAF70095DCF70097E0
-      F7009EE3F800A4E7F900A9E9F900AEE9F900B5EBF900B2EBF800919191919191
-      919191919191919191919191919191919191919191919191D5E7E8E7E3DED591
-      919191919191919191919191919191D6DDF7F8F8F7F6F4EEE6D5919191919191
-      919191919191D7DADEF8F8F6F7F6EDF1F8F1E69191919191919191919191DADE
-      DFFAFAF8F7F7E9EDF7F7F8EB91919191919191919191DDE5E3FCFCFAFAEEE0E9
-      F3F7F7F7DC919191919191919191DEE7E4FEFEFCFCEDC5E0EFF7F6F6DC919191
-      919191919191DEEAE7FEFEFEFDFBC4C4F5F7F6F6DC919191919191919191E3EC
-      E9FEFEFEFEFEE0C3F9F7F6F6DC919191919191919191E3E9E3F8F8F1F1F8FBFB
-      FCFAF7F6DC919191919191919191DCEAEAE0E1E9E5E3DEE4EBF2FAF9DC919191
-      919191919191DBF3EEC5C5EFF3EBE5DDD9D6E6F5DC91919191919191919191D5
-      E8EDF1FAF6F0EAE4DAD1D2DBDC919191919191919191919191DBE8F0F3F3F3E4
-      D0CFE4D8DC919191919191919191919191919191D5DEE4DED2CFD4D491919191
-      91919191919191919191919191919191D2CE9191919191919191919191919191
-      91C8C89191919191D2CE919191919191919191919191919191D9D09191919191
-      D2CE919191919191919191919191919191E6E39191919191D2CE919191919191
-      919191919191919191E0F3CE91919191D2CE9191919191919191919191919191
-      9191EFF6E1C9C8CDD9CC91919191919191919191919191919191C9EDF9F3F3EB
-      DC91919191919191919191919191919191919191CBE0E1CF9191919191919191
-      9191919191919191919191919191919191919191919191919191
-    }
-    OnClick = bbUpdatePasswordClick
+    OnClick = btnLockClick
     ParentFont = False
     ParentFont = False
-    TabOrder = 1
   end
   end
-  object bbExportAllWalletKeys: TBitBtn
-    Left = 30
+  object btnChangePassword: TBitBtn
+    Left = 228
     Height = 36
     Height = 36
-    Top = 425
-    Width = 225
-    Caption = 'Export all Wallet Keys to a file'
+    Top = 426
+    Width = 193
+    Anchors = [akLeft, akBottom]
+    Caption = 'Change Password'
     Glyph.Data = {
     Glyph.Data = {
-      F6060000424DF606000000000000360000002800000018000000180000000100
-      180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FFFF00FF019ACF019ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C8518FF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FF0D9FD18BD4EE6BD3F845C0ED28B0E0019ACF01
-      9ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C85180C8518
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF069CD076C8E5A9E9FE6DD8
-      FF75DBFF77DCFF77DBFF63D1F930B3E3029BD0019ACF019ACF019ACF019ACFFF
-      00FF0C85181399220C8518FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF019ACF
-      34AFD9BCE9F86ED8FF6FD8FE70D8FE70D8FE71D8FF0C85180C85180C85180C85
-      180C85180C85180C85180C85181DAC31139A220C8518FF00FFFF00FFFF00FFFF
-      00FFFF00FF019ACF1FA9D68FD3EB97E4FF6FD9FE71D9FE71D9FE71D9FE0C8518
-      57E38851DD7E4AD77443D0693BC95E34C1522BBA4725B33C1EAE33149B230C85
-      18FF00FFFF00FFFF00FFFF00FF019ACF31B1DC49B7DEBDEEFB71DDFE77DEFE77
-      DEFE77DEFE0C85185EE89059E48953DE804CD87645D16C3DCA6035C2542DBB49
-      26B53F1FAF35149B250C8518FF00FFFF00FFFF00FF019ACF52C2E71DA7D5ADE2
-      F38FE8FF7CE2FE7CE3FE7CE3FE0C851861EB955FE9925AE58B54DF824DD97846
-      D26D3ECB6237C4562FBD4C27B64021B037159B250C8518FF00FFFF00FF019ACF
-      60CAEF1FA8D85EC1E1C2E6ED8ACEE08FCFE18ECFE10C851861EB9561EB955FEA
-      935CE58D56E0844FDB7A48D47040CD6538C65931BF4D1DA3320C8518FF00FFFF
-      00FFFF00FF019ACF65CFF53EB7E52CA9D4C5EFF8ACF3FEA5F2FFA5F2FF0C8518
-      61EB9561EB9561EB9561EB945CE68E57E18650DC7C49D57242CE6727AD410C85
-      18FF00FFFF00FFFF00FFFF00FF019ACF69D1F855C4F32A9CC673CBE7D6FEFDB1
-      FBFDB2FBFD0C85180C85180C85180C85180C85180C85180C85180C851852DD7F
-      32B6500C851898FAFF019ACFFF00FFFF00FFFF00FF019ACF77D5FC5CC8FB748E
-      A224A8D5B9E7F3D5F5F9D5F6F9D6F6FADCFAFBCDFDFCB9FCFCAFFAFCB0FAFCB1
-      FAFC0C85183ABE5C0C85189FFCFFA4FFFF43C1E2019ACFFF00FFFF00FF019ACF
-      8BDBFF5FCDFFB7898973C3DD18A2D218A2D216A2D215A1D21AA4D391D7EBEBFE
-      FDDBFDFCC5FBFBC2FBFB0C85180C851883E4F3B6FDFFBAFFFFB5FCFD019ACFFF
-      00FFFF00FF019ACF99E2FF67D3FFB88989FEF5ECFDF3EBF0EFEAE5EBE8D6E5E6
-      A4D2E025A6D34DB9DDE5F8FBF5FDFCEBFCFB0C8518C4FBFF9CE4F2DAFEFFD9FE
-      FFE3FFFFADE9F5019ACFFF00FF019ACF9FE9FF70DCFFB88989FEF3E9FFF2E6FE
-      F3E9FEF3E9FEF3E9FEF3E9D4E4E439ADD422A5D49DD8ECF1F9FBEEEFEFE9FDFF
-      CEEEF7F8FFFFF7FFFFFEFFFFE9F9FD019ACFFF00FF019ACFA7EFFF76E5FFB889
-      89FFF2E5FFF0E2FFF2E5FFF2E5FFF2E5FFF2E5FFF2E5EAEBE38EC9DA44B0D501
-      9ACF019ACF019ACF019ACF019ACF019ACF019ACF019ACF019ACFFF00FF019ACF
-      ABF6FF7EEDFFB88989FFF0E2FFEFDFFFF0E2FFF0E2FFF0E2FFF0E2FFF0E2FEEE
-      E0FBECDEFAEBDEF6E6D9B8898993F7FF019ACFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FF019ACFC7FFFF82F5FFB88989FFEEDFFFECDBFFEEDFFFEEDFFFEEDF
-      FFEEDFF9E8D9DECCC1D9CABDCFBDB4C8B3ACB88989B5FFFF019ACFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FF019ACFA4E0F0A0FDFFB88989FFECDBFFEBD8FF
-      ECDBFFECDBFFECDBFFECDBF5E2D2C4ABA7C2A8A5BBA39FC2AFA9B88989019ACF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF019ACFECFFFFB889
-      89FFEBD8FFEAD5FFEBD8FFEBD8FFEBD8FFEBD8FFEBD8D9C8C5FEFEFDFEF6EFDE
-      C9C0B88989FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-      FF00FF019ACFB88989FFE9D5FFE8D3FFE9D5FFE9D5FFE9D5FFE9D5FFE9D5C6AD
-      A9FEF8F2E8D4CACD9999FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FFFF00FFFF00FFFF00FFB88989FFE7D1FFE7D0FFE7D1FFE7D1FFE7D1
-      FFE7D1E7CEBFD3BFB9E8D5CCCD9999FF00FFFF00FFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB88989FFE6CFFFE6CFFF
-      E6CFFFE6CFFFE6CFFFE6CFD5BBB2E0CCC5CD9999FF00FFFF00FFFF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB889
-      89B88989B88989B88989B88989B88989B88989B88989B88989FF00FFFF00FFFF
-      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+      76060000424D7606000000000000360400002800000018000000180000000100
+      0800000000004002000000000000000000000001000000010000FF00FF005251
+      5100565758005A5958005B5D5D005D5E5E006361610066666600696969006C6B
+      6B0073706F0072707000747271000E80AA001788AF000B86B2000C85B000098A
+      B700078CBA00198EB7000E91BE001E94BC002898BA003E99BB000493C4000997
+      C7000A9ECF00229BC20035A0C30030AACA0032AACE003DAACC003FB0CB0036A9
+      D0003BB1D9003DBDDA0039B8DE0029BBE0004DBBD90068B0CA0019C7F1001BD4
+      FE002FC6E7003ECDE9002CD3F9002ED8FE003CE0FE0054C0D40059C4D70059C2
+      DD006FC2D6007CC0D50078C1D80049DDFE0054DFFE0061C6E5006CD4EE0064D9
+      E90076DFE9007DDFE90055E0FF0058E0FE006BE3F40063E6FE0060ECFE0075E2
+      FA0077E6FF007BE8FF0071F2FE0088828000928E8C0096908F00969291009794
+      94009E969400A09C9B00A19F9E00ACA09E00A6A2A100A6A4A400ADA5A300AAA5
+      A400ABA8A800ADAAA900B0A5A300B2A7A500B2ABAB00B4ABA900BBB1AE00BEB1
+      AF00BAB3B200BAB4B200BEB6B400C4B8B600C1BCBB0083DFE9008ADAEB0094DF
+      E90089DDF100A4DFEA009AE2F40095EBFD0095EDFE009EEDFF0084F3F90080F5
+      FC008FF6FB0083F8FE0093F2FE0097F9FE0094FDFE0099FFFE009EFFFE00AAEF
+      FD00B4EEF300A4FFFE00A8F9FE00ADFBFE00AAFFFE00B6F1FF00BCF2F800B3F9
+      FF00B3FFFE00B9FFFE00C7C2C100C7C6C600CCC4C200CAC7C600CFCCCC00D1C7
+      C500D4CBC900D1CDCD00D5CFCE00D8D0CE00D7D1D000D9D5D400DCD7D600DFD8
+      D600E3DEDD00C3DFEA00CCF6FF00C9FFFE00CFFFFF00D1F7FF00DBF8FE00DFFF
+      FF00E7E3E200E9E5E500ECE9E900EFEEED00F1EBEA00F1EFEE00E5FFFF00F3F1
+      F100F6F2F000F8F5F300F8F5F400F0F7FA00F5FFFF00FBF8F800FAFFFF00FFFE
+      FE00000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0007070707000000000000000000000000000000000000000746967E07000000
+      0000000000000000000000000000000D085E489A5E080D0D0000000000000000
+      00000000000D0D2626075E48A1071F130D0D000000000000000000000D163940
+      3F35075E4C93070707100D000000000000000000123A6B402E353D075E519580
+      4E0707070707000000000000123A6B402E293D42075E4EA19289858281550700
+      00000000123A6B402E292D4266075E4C9689865A475D4D0700000000123A6B40
+      2E292D3C6671077D928A7D0A0A58580700000000123A6B402E292D3C4371079A
+      958007035151550700000000123A6D6C6667778C8F90079A860701574C024A07
+      0000000012727860311E1B151C3407A17E0B534C000445070000000011322023
+      2A282C36426407539A8882040404570700000000103169402E292D3643716207
+      5393825A515A5A0700000000123A6B402E292D3C436662370707070708070700
+      00000000123A6B402E292D3C43663837222117000000000000000000123A6B40
+      2E292D3C436638231A180D000000000000000000123A6B402E292D3C43663822
+      1A180D000000000000000000123A6B402E292D3C436638231A180D0000000000
+      00000000123B757975756F6F6F6F6A3E25190D000000000000000000128BA190
+      8E79736F6F6F6F6D442B0D00000000000000000012279D9D908E796F6F6F6F6F
+      691E0D000000000000000000001214333363615F3B3A2F2F0E0D000000000000
+      0000000000000014121212121212121200000000000000000000
     }
     }
-    OnClick = bbExportAllWalletKeysClick
-    TabOrder = 10
+    OnClick = btnChangePasswordClick
+    TabOrder = 4
   end
   end
-  object bbImportKeysFile: TBitBtn
-    Left = 264
-    Height = 36
-    Top = 424
-    Width = 209
-    Caption = 'Import a Wallet Keys File'
-    Glyph.Data = {
-      F6060000424DF606000000000000360000002800000018000000180000000100
-      180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FFFF00FF019ACF019ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FF0D9FD18BD4EE6BD3F845C0ED28B0E0019ACF01
-      9ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF069CD076C8E5A9E9FE6DD8
-      FF75DBFF77DCFF77DBFF63D1F930B3E3029BD0019ACF019ACF019ACF019ACFFF
-      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF019ACF
-      34AFD9BCE9F86ED8FF6FD8FE70D8FE70D8FE71D8FF74DBFF7ADEFF79DDFF73D9
-      FF5CCCF522ACDD019ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FF019ACF1FA9D68FD3EB97E4FF6FD9FE71D9FE71D9FE71D9FE71D9FE
-      71D9FE71D9FE73DAFE76DCFF7BDFFF7ADEFF78DCFF77DCFF019ACFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FF019ACF31B1DC49B7DEBDEEFB71DDFE77DEFE77
-      DEFE77DEFE77DEFE77DEFE77DEFE77DEFE76DEFE76DEFE76DEFE78DFFF7CE1FF
-      65D2F8019ACFFF00FFFF00FFFF00FFFF00FFFF00FF019ACF52C2E71DA7D5ADE2
-      F38FE8FF7CE2FE7CE3FE7CE3FE7CE3FE7CE3FE7CE3FE7CE3FE7CE3FE7CE3FE7C
-      E3FE7DE4FE7DE3FE5ED1F3019ACFFF00FFFF00FFFF00FFFF00FFFF00FF019ACF
-      60CAEF1FA8D85EC1E2BBF4FE7DE7FE82E8FE81E8FE81E8FE81E8FE81E8FE81E8
-      FE81E8FE81E8FE81E8FE82E8FE84E9FE5ED3F18DEEFF019ACFFF00FFFF00FFFF
-      00FFFF00FF019ACF65CFF53EB7E529ACD8BFEEF88DEFFF85EDFF85EDFF85EDFF
-      85EDFF86EDFF86EDFF86EDFF86EDFF86EDFF87EDFF89EEFF65D9F396F5FF019A
-      CFFF00FFFF00FFFF00FFFF00FF019ACF69D1F855C4F31FA7D773CBE7C5FCFF93
-      F7FF93F7FF92F6FF8DF4FF89F3FF89F2FF8BF2FF8BF2FF8BF2FF8BF2FF8EF3FF
-      6ADEF395F8FF98FAFF019ACFFF00FFFF00FFFF00FF019ACF77D5FC5CC8FB3EB8
-      E920A7D5B6E6F3D0F4FAD1F5FAD2F6FAD5F9FCB9FBFE9BF8FF8FF6FF91F6FF92
-      F6FF93F7FF6BD0B70C85188BEAE0A4FFFF43C1E2019ACFFF00FFFF00FF019ACF
-      8BDBFF5FCDFF64CDFE2CAFE30D9FD30FA0D310A0D310A0D317A3D38ED7ECE2FD
-      FEC3FAFFA5F8FFA3F8FF84DDCF0C851838B5570C8518ABF3EBB5FCFD019ACFFF
-      00FFFF00FF019ACF99E2FF67D3FF6DD4FE6CD4FE69D1FE64CEFB61CDF95BC9F5
-      48BEEB17A3D54BB8DDDFF7FBE8FCFFB1E7DD0C85184ACE7361EB9541C1640C85
-      18D6F6F0ADE9F5019ACFFF00FF019ACF9FE9FF70DCFF76DDFE76DDFE76DDFE75
-      DCFE74DCFE73DCFE73DBFE61CEF61CA8D91CA5D58CCED70C851842C5665BE68C
-      59E1895DE78F3EBD600C8518DBF1EF019ACFFF00FF019ACFA7EFFF76E5FF7CE5
-      FF7CE5FF7CE5FF7CE5FF7DE5FF7DE5FF7DE5FF7DE3FF72DDFB40B8D20C85182D
-      AD474AD47250D97B55DE8359E1885AE38B33AF510C85180197C3FF00FF019ACF
-      ABF6FF7EEDFF85ECFF85ECFF85ECFF85ECFF84ECFF80ECFF7CECFF7DECFF7EEC
-      FF0C85180C85180C85180C851840C7634FDA7A55DF830C85180C85180C85180C
-      8518FF00FF019ACFC7FFFF82F5FF8FF5FF8FF5FF8FF5FF8EF5FF8DF4FFA0FDFF
-      B7FFFFAFFFFFAEFFFFA6F9F4A5FBF8A3FCFA4CB07732B74F48D6704AD3720C85
-      18FF00FFFF00FFFF00FFFF00FF019ACFA4E0F0A0FDFF8AFCFF90FCFF90FCFF90
-      FCFF99FDFF86E8F5019ACF019ACF019ACF019ACF019ACF019ACF0486642CB347
-      41D16636BC540C8518FF00FFFF00FFFF00FFFF00FFFF00FF019ACFECFFFFBCFF
-      FFBCFFFFBCFFFFC0FFFF9DF5FB019ACFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FF0C85182BB74538C9580C8518FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-      FF00FF019ACF019ACF019ACF019ACF019ACF019ACFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FF0C851828BB4126B13E0C8518FF00FFFF00FFFF00FFFF
-      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-      FF00FFFF00FFFF00FFFF00FFFF00FF0C851814A4241CAE310C8518FF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C85180C85180C96170D991A0C8518
-      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C85180C85180C85180C85180C
-      8518FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+  object ilIcons: TImageList
+    Height = 64
+    Width = 64
+    left = 489
+    top = 136
+    Bitmap = {
+      4C69020000004000000040000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C6A909CDCDAE29CEC9AF73CDCBAFC0CDC9ADE4CEC9
+      ADFACDC9ADFECDC9ADFEC6C0A2FEBEB797FEBEB797FEBEB797FEBEB797FEC1B9
+      9AFAC1BB9BEAC2BB9B97C3B99B33C8C8A30EFFFFFF0100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007F7F7F02D1CAB027CDC8AD8CCDC9ADEFCECAAEFFCECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCECAAEFFC6C0A2FFBFB897FFBFB897FFBFB897FFBFB897FFBFB8
+      97FFBFB897FFBFB897FFC0B998F9C2BA9BB0C0BA9A56BFBF9F08000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000FFFF
+      FF01CFC9AE56CECAAEC1CDC9ADF8CECAAEFFCECAAEFFCECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCECAAEFFC6C0A2FFBFB897FFBFB897FFBFB897FFBFB897FFBFB8
+      97FFBFB897FFBFB897FFBFB897FFBFB897FFC0B999F3C1BC9A96C9BFAA180000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000CFCC
+      B155CEC9AEE6CDC9ADFECECAAEFFCECAAEFFCECAAEFFCECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCECAAEFFC6C0A2FFBFB897FFBFB897FFBFB897FFBFB897FFBFB8
+      97FFBFB897FFBFB897FFBFB897FFBFB897FFBFB897FFBFB897FAC1BC9A99BFBF
+      BF04000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000CBCBAE23CDC9
+      AEE3CECAAEFFCECAAEFFCECAAEFFCECAAEFFCECAAEFFCECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCECAAEFFC6C0A2FFBFB897FFBFB897FFBFB897FFBFB897FFBFB8
+      97FFBFB897FFBFB897FFBFB897FFBFB897FFBFB897FFBFB897FFC0B999ECC6C0
+      A356000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000C6C6A909CDCAADB3CDC9
+      ADFDCECAAEFFCECAAEFFCECAAEFFCECAAEFFCDCAADF8CDCAADBFCDC9AD6DD2C9
+      AE39CFC9AF30CFC9AF30CDC9AF43C6BD9F55C6BD9F55C5BFA15DC6C0A383C5BF
+      A0BAC1BB9AE5BFB897FABFB897FFBFB897FFBFB897FFBFB897FFBFB897FFC1BB
+      99A9C1C1A3190000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000AAAAAA03CEC9AC73CECAADF1CECA
+      AEFFCECAAEFFCECAAEFFCDC9ADFECEC9ADD1CECBAD5EFFFF7F02000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000B2B2990AC4BE9D7EBFB898E5BFB897FFBFB897FFBFB897FFBFB897FFBFB9
+      98F9C0BA9B52AAAAAA0300000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000D3CAAF1DCECAAEC1CECAAEFFCECA
+      AEFFCECAAEFFCECAAEFFCDCAAED0CDC9AE39FFFF7F0200000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000BFBF7F04C2BB9A6DBFB898EEBFB897FFBFB897FFBFB897FFBFB8
+      97FFC1BB9CABC3B4961100000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000CECAAE49CEC9AEE1CECAAEFFCECA
+      AEFFCECAAEFFCDCAADF2CECBAE69B6B6B6070000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C3C3A511C0BB9BC0BFB897FDBFB897FFBFB897FFBFB8
+      97FFC1BB9BE9BCBC971B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000CEC9AE5FCDC9ADF2CECAAEFFCECA
+      AEFFCECAAEFFCEC9ADD8CECAAF3A000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C4BE9F93BFB897F9BFB897FFBFB897FFBFB8
+      97FFC1B99AFAC1B89E1D00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000CFCBAE6CCECAAEFBCECAAEFFCECA
+      AEFFCECAAEFFCECAAEC1C8C8A921000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C8C0A162BFB897F4BFB897FFBFB897FFBFB8
+      97FFBFB897FFC3BB991E00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01CCC8AC75CECAAEFFCECAAEFFCECA
+      AEFFCECAAEFFCDCAADB3CFCFAF10000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C5C19E3ABFB796F0BFB897FFBFB897FFBFB8
+      97FFBFB897FFBDB79A2B00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFF01C1C6B075AFC0B6FF9CB9BCFF90B5
+      BFFF90B5BFFF80AFC3CD2B92D8631A8DDF581A8DDF581A8DDF581A8DDF581A8D
+      DF581A8DDF581A8DDF581A8DDF581A8DDF581A8DDF581A8DDF581A8DDF581A8D
+      DF581A8DDF581A8DDF581A8DDF584C9DCC7E84A7B0F586A8AFFF86A8AFFF8BAA
+      AEFF98AEA8FF93ADA83200000001000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000198DE1801E88D7EB2289D5FF2088D6FF1F88
+      D6FF1F88D6FF1C87D7FB1684D8F41684D8F31684D8F31684D8F31684D8F31684
+      D8F31684D8F31684D8F31684D8F31684D8F31684D8F31684D8F31684D8F31684
+      D8F31684D8F31684D8F31684D8F31784D7F61D86D5FE1E87D5FF1E87D5FF1E87
+      D5FF2087D4FF1886D8ED178ADCC22AAAD4060000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000001A8ADE9C1684D8FD1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FE188ADCB10000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000099FF051785DAF21684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1686D9D72A7FD40600000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000001F94E918198ADEF81684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8DF1B88DA1C00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1D95E7F8198BDEFF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F81E94E6FF1889DDFF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F81F96E8FF1D93E5FF1888DBFF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F81F96E8FF2298EAFF1D92E4FF1787DAFF1684
+      D8FF1684D8FF1684D8FF1684D8FF1683D7FF1681D3FF1681D3FF1681D3FF1681
+      D3FF1681D3FF1681D3FF1681D3FF167FD0FF0F5286FF104975FF167BC8FF145E
+      97FF092E4BFF1776C0FF1683D7FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F82499EBFF37A5F6FF279BEDFF1D91E4FF1888
+      DCFF1684D8FF1684D8FF1682D5FF1262A0FF0E4B79FF0E4977FF0E4977FF0E49
+      77FF0E4977FF0E4977FF0E4977FF0E4773FF092B47FF0A2B46FF0E4672FF092B
+      46FF051C2DFF0E456FFF115B94FF1574BCFF1683D6FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1D93
+      E5FF1888DCFF1684D7FF1465A4FF092A43FF041928FF041827FF041827FF0418
+      27FF041827FF041827FF041827FF041827FF041827FF041827FF041827FF0418
+      27FF041827FF041928FF061F32FF092F4DFF146AACFF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1D93E5FF177CC7FF0E3C61FF082135FF082137FF082035FF082137FF0821
+      37FF082137FF082137FF082137FF082137FF082137FF082137FF082137FF0820
+      35FF082034FF061B2CFF041827FF041827FF0B3454FF1683D6FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1D8FDFFF1A7FCCFF197DC9FF197DC9FF197DC9FF177DCCFF177D
+      CCFF167ECDFF177DCCFF197DC9FF197DC9FF197DC9FF197DC9FF197DC9FF197D
+      C9FF1679C4FF104D7DFF041827FF041827FF07253CFF1683D6FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1B8FE1FF1786D9FF1684D8FF1683D6FF186BACFF1962
+      9BFF19629BFF1779C5FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1683D6FF10568CFF041827FF041827FF07253BFF1683D6FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1B8FE1FF1786DAFF167CCAFF072338FF0418
+      27FF051A2AFF156DB0FF1684D7FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1683D6FF10558AFF041827FF041827FF07253BFF1683D6FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1C91E3FF1772BAFF041928FF0418
+      27FF071F32FF1569AAFF1777C1FF1777C2FF1678C3FF187AC7FF187BC8FF187B
+      C8FF1670B6FF0D3A5EFF041827FF041827FF07253BFF1683D6FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1D6CA7FF041828FF0417
+      25FF051929FF082740FF082A44FF082A44FF082A45FF082B46FF092C47FF092C
+      47FF082841FF051C2DFF041827FF041827FF0A3150FF1683D6FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1C5C89FF051A29FF0418
+      27FF041624FF041826FF041827FF041827FF041827FF041827FF041827FF0418
+      27FF041827FF041827FF041827FF062237FF1668A8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF0F3B5DFF051B2AFF051A
+      29FF092B46FF0B3759FF071F33FF061D30FF0D3759FF072238FF071F33FF0C39
+      5EFF0B385BFF0D3A5FFF124E7FFF1573BBFF1683D6FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF2291DEFE082437FF051B2AFF0822
+      36FF176FB1FF187FCDFF0D3555FF0D3F66FF1880D0FF0D446EFF135081FF1681
+      D3FF1683D7FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF257FC1FF051C2CFF051B2AFF0D34
+      50FF1C81C8FF1C8CDDFF1873B8FF167AC6FF1683D7FF1575BFFF177DCBFF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1C6397FF051C2BFF051B2AFF1244
+      68FF1F8AD5FF1E94E6FF1B8DDFFF1782D4FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1E95E7FF124366FF051B2BFF051B2AFF1350
+      7BFF1F90DEFF1F96E8FF1E94E7FF1B8CDEFF1682D4FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF2091DFFF092840FF051B2AFF061D2DFF155B
+      8DFF1F94E5FF1F96E8FF1F96E8FF1E95E7FF1A89DAFF1683D5FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF2283C6FF082538FF051D2DFF092539FF186B
+      A6FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1D92E4FF1888DBFF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F85CDFF145B8CFF125889FF155F92FF1D85
+      CEFF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1D92E5FF1889DDFF1684
+      D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1D93E5FF1A8C
+      DFFF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1E95
+      E7FF198BDEFF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000249AEC1C1E96E8F8259AECFF3DA8F9FF299CEEFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1E95E7FF1889DDFF1684D8FF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0178BE02100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000001D93EB1A1E96E7F82599EBFF3CA7F8FF299CEDFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1D93E5FF1888DCFF1684D8FF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1584D8E0188BDE1F00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000003399CC052095E6E42197E9FF2C9EF0FF2399EBFF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1D92E4FF1888DCFF1684D8FF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1685D9D81F9FFF0800000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000001D93E5951F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1D93E5FF1889DCFF1684D8FF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1787DAC60000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000001E98EA191F96E7D21F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1E94E6FF1888DBFF1684D8FF1684
+      D8FF1684D8FF1684D8FF1684D8FF1989DB500000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000001E92E93B1F96E8D51F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96
+      E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1F96E8FF1D93E6FF1787DBFF1684
+      D8FF1684D8FF1684D8FF1989DEA3007FFF040000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000FF011E92E7211D94E7811F95E8C31E95
+      E7F01E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95
+      E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95
+      E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21E95E7F21C91E3F21788
+      DAEE1789DCD61A8BE258007FFF04000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000FFFFFF01CECEA915D1CBAD32CBCBAC4ACECBAD54CDCAAD58CDCAAD58CAC5
+      A858C2B99C58BFB99658BFB99658BFB99658BFB99958C0B99751C4C09C39CDCD
+      BA1AE2E2C6090000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000D4D4
+      AA06CDCDAF43CFC9AE95CEC9ADC9CECAADEBCECAAEF7CECAAEFCCECAAFFCCAC5
+      A7FCC1BA9AFCBEB796FDBEB796FDBFB896FCBFB897FCBFB797F4C2BA9AD2C5BF
+      A0A4C6C2A471C8C1A22100000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000CCCCA528CECC
+      AC78CECAACC7CEC9AEF5CEC9AEFCCECAAEFFCECAAEFFCECAAEFFCFCBAFFFCAC5
+      A8FFC1BA9BFFBFB796FFBFB897FFBFB897FFBFB897FFBFB897FFBFB897FCBEB7
+      96F8BEB896EAC1BB9AA2C7BEA237BFBFBF040000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000FFFFFF02D4CFB930CFC9B0A8CECA
+      ADF1CECAAEFCCECAAEFFCECAAEFFCECAAEFFCECAAEFFCECAAEFFCFCBAFFFCAC5
+      A8FFC1BA9BFFBFB796FFBFB897FFBFB897FFBFB897FFBFB897FFBFB897FFBFB8
+      97FFBFB897FFBFB896F8C2BA9AB4C5C09E35FFFFFF0200000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000CCC3AA1ECFCAAE9BCEC9ADF5CECA
+      AEFFCECAAEFFCECAAEFFCCC8ABFECBC7ABFCCECAAEFBCECAAEF7CECAAEF7CAC5
+      A7F9C1B99BFBBEB696FBBEB797FBBFB896FCBFB897FDBFB797FEBFB796FFBFB8
+      97FFBFB897FFBFB897FFC0B897FCC3BC9DA2C8C8A22100000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000C6C6A909CECCAD6ACBC8ABE6CECAADFFCECA
+      AEFFCECAAEFFCECAADFBCECCB0DFCECBAEAFCECAAE88CDC9AD77CDCBAF76CBC4
+      A77BC4BC9E87C3BA9B8AC3BA9B8AC2BB9D97C3BC9BB3C2BB9BCDC0B999EFBFB8
+      97FCBFB897FFBFB897FFBFB796FFC1B898EFC4BE9D7EBFBF9F08000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000D6D1B232CFCBAEC8CECAAEFCCECAAEFFCECA
+      AEFFCDC9ADFBCCC8ABC0D3D0B75DD7D7B720C6C6A9090000000000000000FFFF
+      7F02BFBF9F08E2E2A909E2E2A909D2C3A511C4C4A023C4BC9E3DC6C0A07AC2BA
+      9BCDBFB897FFBFB897FFBFB897FFBFB897FFC1BA99CCC5BDA03E000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000BFBFBF04CECAAF74CECAADECCECAAEFFCECAAEFFCECA
+      AEFFCBC9ADD7D1CAB249E2C6C609000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000FFFFFF01D2C3B411C7C2
+      A258C0BA99E2BFB897FFBFB897FFBFB796FFBFB997F5C2BD9C8F000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C6A912CFCBACB1CECAAEFCCECAAEFFCDC9ADFFCBC7
+      ABFEE0DECC7ED2D2A51100000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000C9C9
+      9F18C3BD9D9BBFB897FDBFB897FFBFB897FFBFB998FFC1BB9AC4000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000D2D2B422CDCAADD5CDC9ADFFCECAAEFFCDC9ADFFCCC8
+      A9E2E5E1D03CFFFF7F0200000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000C6C6
+      A909C4BC9F68BFB898F6BFB897FFBFB897FFBFB998FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000D7D1B52DCECBAFDECECAAEFFCECAAEFFCECAAEF8CCC9
+      ACC0D6CBB7190000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000FFFF
+      FF02C3C09E45C1B998E0BFB796FFBFB897FFBFB796FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000CBC6AD32CDCBAEDFCECAAEFFCECAAEFFCECAAEF8CDCA
+      ADB3C8C8A30E0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000C5BB9C31C0B997D4BEB796FDBFB897FFBFB796FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332CCCAADE0CFCBAFFFCECAAEFFCECAAEF8CDCA
+      ADB3C8C8A30E0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000C5BB9C31C0B997D4BEB795FDBFB897FFBFB897FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332CCCAADE0CFCBAFFFCECAAEFFCECAAEF8CDCA
+      ADB3C8C8A30E0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000C5BB9C31C0B997D4BEB795FDBFB897FFBFB897FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332CCCAADE0CFCBAFFFCECAAEFFCECAAEF8CDCA
+      ADB3C8C8A30E0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000C5BB9C31C0B997D4BEB795FDBFB897FFBFB897FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332CCCAADE0CFCBAFFFCECAAEFFCECAAEF8CECB
+      ADB2CCCCB20A0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000C5BB9C31C0BA98D4BFB796FDBFB897FFBFB897FFC0B897CF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332CCCAADE0D0CBAEFFD0CBAEFFD0CBADF8D0CB
+      ACAEB6B691070000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000C5BB9C31C2B997D6C1B795FDC1B896FFC1B896FFC0B998D0000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332CCCAADE0CDCAB0FFCCCAAFFFD0CBADFBCBCA
+      ACAE3F7FBF080000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000FFFF
+      FF01B6B6A023C3BA969FBEB597CEBCB797E0BEB797F4BDB899CE000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000C6C1A332BCC3B0DBA6BDBAFC9BB8BBF99DB9BBF88DB5
+      BFB2389BD4120000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF017F7F
+      FF02A2B9B90BA8B3A22C9FAFA3439BAEA65F99AFA7A1A0B1A4AC000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000CFA68000BF4DA000BEDEA000B
+      EDEA000BEDEA000BEDEA000BEDEA000BEDEA000BEDEA000BEDEA000BEDEA000B
+      EDEA000BEDEA000BEDEA000BEDEA000BEDEA000BEDEA000BEDEA000BEDEA000B
+      EDEA000BEDEA000BEDEA030EECEE0D19E9FC0D1AEAFF0C19EAFE0C19EAFE0715
+      EBF9000CEDEC000BEDEA000CEFE9000DF4C90016F31700000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000017F7F7F02AAAAAA0399CCCC057FAAAA0C9CB0B00D000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000EF67F000CEEF6000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000EF5D50000FF03000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000FF04000CF0C6000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000BEFFE0013FE0D000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000001EFF11000EF7CF000CEFFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000FF533000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130617FED00010FBFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED00719FFFF000FFAFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF0719FFFF000FF8FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF0D1FFFFF0A1BFEFF010F
+      F5FF000CEEFF000CEEFF000CEEFF000CEEFF000CEDFF010DE9FF010CE8FF010C
+      E8FF010CE8FF010CE8FF010CE8FF010CE8FF010CE8FF030ECBFF030A5FFF030E
+      C5FF0510B4FF02074FFF030FC2FF000CEBFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF2F3BFFFF2533FFFF0617
+      FDFF010FF5FF000CEFFF000CEEFF000CEDFF030FCAFF030B8CFF020982FF0209
+      82FF020982FF020982FF020982FF020983FF020983FF030A66FF010438FF0309
+      70FF020859FF00032FFF02086CFF020A94FF020DC1FF010DE7FF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF0617FEFF010EF5FF000CEEFF020DDDFF050C6AFF010330FF00022BFF0002
+      2BFF00022BFF00022BFF00022BFF00022BFF00022BFF00022BFF00022BFF0002
+      2BFF00022BFF00022BFF00022BFF010331FF02064AFF030DA2FF010DE7FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF0718FEFF000EF6FF0A179AFF03073CFF03073AFF03073AFF0307
+      3CFF03073CFF03073CFF03073CFF03073CFF03073CFF03073CFF03073CFF0307
+      3BFF03073AFF030639FF030535FF00022BFF00022BFF02084DFF000CD7FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF0819FFFF0516E5FF0512DCFF0512DCFF0512DCFF010D
+      E1FF010DE1FF010DE1FF0410DFFF0512DDFF0612DEFF0612DEFF0512DCFF0512
+      DCFF0512DCFF0411DAFF0714C1FF00022BFF00022BFF01053BFF000BD3FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF0718FDFF000DF2FF000CEEFF000CEEFF0916
+      C2FF0915AAFF0915AAFF0613C9FF010DEAFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF0313D7FF00022BFF00022BFF01053BFF000BD2FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF0515FCFF010EF3FF010EE9FF0208
+      4BFF00022BFF00022CFF030C91FF010DE8FF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF0515D3FF00022CFF00022BFF01053BFF000BD2FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0515FCFF0715DAFF0104
+      35FF00022AFF010431FF050E91FF0513D2FF0413D4FF0515D6FF0515D7FF0717
+      DAFF0718DBFF0717D0FF061389FF00022BFF00022BFF01053BFF000BD2FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF1022C8FF0104
+      33FF00022AFF000229FF02053FFF02064AFF01064BFF02074CFF02074CFF0208
+      4DFF02084EFF03084AFF010535FF00022BFF00022BFF02074CFF010CD6FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0F1FA8FF0205
+      33FF00022BFF00022AFF00022AFF00022BFF00022BFF00022BFF00022BFF0002
+      2BFF00022BFF00022BFF00022BFF00022BFF000435FF020C99FF000CE7FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFEFF0A167CFF0105
+      31FF01042EFF01053BFF030C5CFF030740FF00022DFF040E60FF030B52FF0104
+      33FF030A5CFF060F64FF040E61FF061077FF0410B9FF010DE7FF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0E22F4FF050C56FF0104
+      2FFF010531FF050F83FF0311E7FF050D75FF050C59FF010DE8FF0411B5FF0712
+      74FF0310D7FF000DEDFF000DEDFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF1023DCFF040A47FF0104
+      2EFF020636FF0B1AABFF0313FAFF0513D2FF0614D4FF000CEDFF0310E0FF0513
+      D5FF010EEBFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF1020B9FF04093FFF0104
+      2EFF03073CFF0F21CCFF0618FFFF0111FBFF010DECFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081596FF020636FF0104
+      2EFF02073FFF0B1DE3FF081AFFFF0618FFFF0111FDFF000DE7FF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF0A1CF9FF070F75FF010530FF0104
+      2EFF050A4FFF0B1DF5FF081AFFFF081AFFFF081AFFFF0011FDFF000DE8FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF0D20E9FF071064FF010431FF0105
+      31FF081275FF081AFEFF081AFFFF081AFFFF081AFFFF0819FFFF010FF6FF000C
+      EFFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF0B1DEEFF0915ABFF040F96FF0610
+      94FF0918C8FF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0618FEFF0111
+      F8FF000CEFFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0617
+      FEFF0110F9FF000CEFFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF0719FFFF0110F9FF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000D1AFE130819FED0081AFFFF3640FFFF2B37FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF0010FAFF000CEEFF000CEEFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0011F63B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000E1CFE120819FECF081AFFFF343FFFFF2936FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF0110F8FF000CEFFF000CEEFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFF0012F538000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000FF03081AFEB9081AFEFD1A29FFFF1525FFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF0719FEFF0210F7FF000CEFFF000CEEFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CEEFE000FFF11000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000819FF780819FEF6081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF0718FEFF0210F6FF000CEFFF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000CF2ED0000FF03000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000C18FE15081BFEBC081AFEFE081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0718FEFF010FF6FF000C
+      EEFF000CEEFF000CEEFF000CEEFF000CEEFF000EF36C0000FF01000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000016FF22071AFEB6081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081A
+      FFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF081AFFFF0618FEFF000D
+      F4FF000CEEFF000CEEFF000CEEFF000EF5B4000EF01200000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000FF060815FC5E0819
+      FEB50719FEE4081AFEF1081AFEF2081AFEF2081AFEF2081AFEF2081AFEF2081A
+      FEF2081AFEF2081AFEF2081AFEF2081AFEF2081AFEF2081AFEF2081AFEF2081A
+      FEF2081AFEF2081AFEF2081AFEF2081AFEF2081AFEF2081AFEF2081AFEF20618
+      FDF2000CF3F1000CF3E0020EF87D000FF0110000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000
     }
     }
-    OnClick = bbImportKeysFileClick
-    TabOrder = 11
   end
   end
-  object bbLock: TBitBtn
-    Left = 296
-    Height = 38
-    Top = 8
-    Width = 79
-    Caption = 'Lock'
-    Font.Color = clWindowText
-    Font.Height = -13
-    Font.Name = 'Tahoma'
-    Font.Style = [fsBold]
-    Glyph.Data = {
-      76060000424D7606000000000000360400002800000018000000180000000100
-      0800000000004002000000000000000000000001000000010000000000000101
-      0100020202000303030004040400050505000606060007070700080808000909
-      09000A0A0A000B0B0B000C0C0C000D0D0D000E0E0E000F0F0F00101010001111
-      1100121212001313130014141400151515001616160017171700181818001919
-      19001A1A1A001B1B1B001C1C1C001D1D1D001E1E1E001F1F1F00202020002121
-      2100222222002323230024242400252525002626260027272700282828002929
-      29002A2A2A002B2B2B002C2C2C002D2D2D002E2E2E002F2F2F00303030003131
-      3100323232003333330034343400353535003636360037373700383838003939
-      39003A3A3A003B3B3B003C3C3C003D3D3D003E3E3E003F3F3F00404040004141
-      4100424242004343430044444400454545004646460047474700484848004949
-      49004A4A4A004B4B4B004C4C4C004D4D4D004E4E4E004F4F4F00505050005151
-      5100525252005353530054545400555555005656560057575700585858005959
-      59005A5A5A005B5B5B005C5C5C005D5D5D005E5E5E00685968007C4F7C009441
-      9400B72CB700DD15DD00F506F500FD01FD00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00
-      FE00FE00FE00FE00FE00FE00FE00F008F900D517F000BD24E800A830E1007B4B
-      D0005065C1003774B7002B7DB100237FAC001F82AD001C83AD001785AE001687
-      AF001489B100128AB300108CB6000F8EB9000D91BB000C94BF000A97C3000A99
-      C5000A9AC7000B9BC8000B9CCA000C9ECC000C9FCD000DA0CE000DA1CE000EA2
-      CF0011A3CF0015A4CF0018A5CF001CA7D10021A9D1002AAAD00035AACD0035AD
-      D00035AFD30035B1D60037B5D8003AB8DB003EB9DC0040BBDD0045BEDE004CC1
-      E00055C6E3005BC8E40061CAE40066CBE3006BCCE30072D3E60078D8EB0080D8
-      EE0083D9F10085DCF40088DBF5008BDBF6008EDAF70091DAF70095DCF70097E0
-      F7009EE3F800A4E7F900A9E9F900AEE9F900B5EBF900B2EBF800919191919191
-      919191919191919191919191919191919191919191919191D5E7E8E7E3DED591
-      919191919191919191919191919191D6DDF7F8F8F7F6F4EEE6D5919191919191
-      919191919191D7DADEF8F8F6F7F6EDF1F8F1E69191919191919191919191DADE
-      DFFAFAF8F7F7E9EDF7F7F8EB91919191919191919191DDE5E3FCFCFAFAEEE0E9
-      F3F7F7F7DC919191919191919191DEE7E4FEFEFCFCEDC5E0EFF7F6F6DC919191
-      919191919191DEEAE7FEFEFEFDFBC4C4F5F7F6F6DC919191919191919191E3EC
-      E9FEFEFEFEFEE0C3F9F7F6F6DC919191919191919191E3E9E3F8F8F1F1F8FBFB
-      FCFAF7F6DC919191919191919191DCEAEAE0E1E9E5E3DEE4EBF2FAF9DC919191
-      919191919191DBF3EEC5C5EFF3EBE5DDD9D6E6F5DC91919191919191919191D5
-      E8EDF1FAF6F0EAE4DAD1D2DBDC919191919191919191919191DBE8F0F3F3F3E4
-      D0CFE4D8DC919191919191919191919191919191D5DEE4DED2CFD4D491919191
-      91919191919191919191919191919191D2CE9191919191919191919191919191
-      91C8C89191919191D2CE919191919191919191919191919191D9D09191919191
-      D2CE919191919191919191919191919191E6E39191919191D2CE919191919191
-      919191919191919191E0F3CE91919191D2CE9191919191919191919191919191
-      9191EFF6E1C9C8CDD9CC91919191919191919191919191919191C9EDF9F3F3EB
-      DC91919191919191919191919191919191919191CBE0E1CF9191919191919191
-      9191919191919191919191919191919191919191919191919191
-    }
-    OnClick = bbLockClick
-    ParentFont = False
-    TabOrder = 12
+  object pmKeyMenu: TPopupMenu
+    left = 393
+    top = 168
+    object miChangeName: TMenuItem
+      Caption = 'Change Name'
+      OnClick = miChangeNameClick
+    end
+    object miExportPublicKey: TMenuItem
+      Caption = 'Export Public Key '
+      OnClick = miExportPublicKeyClick
+    end
+    object miExportPrivateKey: TMenuItem
+      Caption = 'Export Private Key'
+      OnClick = miExportPrivateKeyClick
+    end
+    object miSep1: TMenuItem
+      Caption = '-'
+    end
+    object miDeleteKey: TMenuItem
+      Caption = 'Delete'
+      OnClick = miDeleteKeyClick
+    end
   end
   end
   object SaveDialog: TSaveDialog
   object SaveDialog: TSaveDialog
+    Width = 28
+    Height = 28
     DefaultExt = '.dat'
     DefaultExt = '.dat'
     Filter = 'Wallet keys file|*.dat|All files|*.*'
     Filter = 'Wallet keys file|*.dat|All files|*.*'
     FilterIndex = 0
     FilterIndex = 0
-    left = 150
-    top = 150
+    left = 145
+    top = 168
   end
   end
   object OpenDialog: TOpenDialog
   object OpenDialog: TOpenDialog
+    Width = 28
+    Height = 28
     DefaultExt = '.dat'
     DefaultExt = '.dat'
     Filter = 'Wallet keys file (*.dat)|*.dat|All files (*.*)|*.*'
     Filter = 'Wallet keys file (*.dat)|*.dat|All files (*.*)|*.*'
     FilterIndex = 0
     FilterIndex = 0
-    left = 205
-    top = 155
+    left = 234
+    top = 183
   end
   end
 end
 end

+ 351 - 415
Units/Forms/UFRMWalletKeys.pas

@@ -2,442 +2,456 @@ unit UFRMWalletKeys;
 
 
 {$mode delphi}
 {$mode delphi}
 
 
-{ Copyright (c) 2016 by Albert Molina
+{ Copyright (c) 2018 by Herman Schoenfeld
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
 
 
-  This unit is a part of Pascal Coin, a P2P crypto currency without need of
-  historical operations.
-
-  If you like it, consider a donation using BitCoin:
-  16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
-
-  }
+  Acknowledgements:
+  - Albert Molina: portions of code copied from https://github.com/PascalCoin/PascalCoin/blob/master/Units/Forms/UFRMWallet.pas
+}
 
 
 interface
 interface
 
 
-{$I ./../PascalCoin/config.inc}
-
 uses
 uses
-  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-  Dialogs, StdCtrls, UCommonUI, UWalletKeys, Buttons,
-  LMessages, clipbrd, UConst, UCommon;
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Messages,
+  Buttons, Menus, UCommonUI, UWallet;
 
 
-Const
-  CM_PC_WalletKeysChanged = LM_USER + 1;
+const
+  CM_PC_WalletChanged = WM_USER + 1;
 
 
 type
 type
+
+  { TFRMWalletKeys }
+
   TFRMWalletKeys = class(TApplicationForm)
   TFRMWalletKeys = class(TApplicationForm)
-    lbWalletKeys: TListBox;
-    bbExportPrivateKey: TBitBtn;
-    lblEncryptionTypeCaption: TLabel;
+    btnChangePassword: TBitBtn;
+    btnBackupWallet: TBitBtn;
+    btnAddKey: TSpeedButton;
+    btnLock: TSpeedButton;
+    btnRestoreBackup: TBitBtn;
+    ilIcons: TImageList;
     lblEncryptionType: TLabel;
     lblEncryptionType: TLabel;
-    lblKeyNameCaption: TLabel;
+    lblEncryptionTypeCaption: TLabel;
     lblKeyName: TLabel;
     lblKeyName: TLabel;
-    lblPrivateKeyCaption: TLabel;
-    memoPrivateKey: TMemo;
-    bbChangeName: TBitBtn;
-    bbImportPrivateKey: TBitBtn;
-    bbExportPublicKey: TBitBtn;
-    bbImportPublicKey: TBitBtn;
-    bbGenerateNewKey: TBitBtn;
-    lblPrivateKeyCaption2: TLabel;
-    bbDelete: TBitBtn;
+    lblKeyNameCaption: TLabel;
     lblKeysEncrypted: TLabel;
     lblKeysEncrypted: TLabel;
-    bbUpdatePassword: TBitBtn;
-    bbExportAllWalletKeys: TBitBtn;
-    SaveDialog: TSaveDialog;
-    bbImportKeysFile: TBitBtn;
+    lblPrivateKeyCaption: TLabel;
+    lbWalletKeys: TListBox;
+    memoPublicKey: TMemo;
+    btnCopyClipboard: TSpeedButton;
+    miDeleteKey: TMenuItem;
+    miExportPublicKey: TMenuItem;
+    miExportPrivateKey: TMenuItem;
+    miChangeName: TMenuItem;
+    miSep1: TMenuItem;
     OpenDialog: TOpenDialog;
     OpenDialog: TOpenDialog;
-    bbLock: TBitBtn;
+    pmKeyMenu: TPopupMenu;
+    SaveDialog: TSaveDialog;
+    procedure btnAddKeyClick(Sender: TObject);
+    procedure btnBackupWalletClick(Sender: TObject);
+    procedure btnChangePasswordClick(Sender: TObject);
+    procedure btnCopyClipboardClick(Sender: TObject);
+    procedure btnDeleteKeyClick(Sender: TObject);
+    procedure btnLockClick(Sender: TObject);
+    procedure btnRestoreBackupClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
-    procedure bbChangeNameClick(Sender: TObject);
-    procedure bbExportPrivateKeyClick(Sender: TObject);
-    procedure bbImportPrivateKeyClick(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
     procedure lbWalletKeysClick(Sender: TObject);
     procedure lbWalletKeysClick(Sender: TObject);
-    procedure bbGenerateNewKeyClick(Sender: TObject);
-    procedure bbExportPublicKeyClick(Sender: TObject);
-    procedure bbDeleteClick(Sender: TObject);
-    procedure bbImportPublicKeyClick(Sender: TObject);
-    procedure bbUpdatePasswordClick(Sender: TObject);
-    procedure bbExportAllWalletKeysClick(Sender: TObject);
-    procedure bbImportKeysFileClick(Sender: TObject);
-    procedure bbLockClick(Sender: TObject);
+    procedure miChangeNameClick(Sender: TObject);
+    procedure miDeleteKeyClick(Sender: TObject);
+    procedure miExportPrivateKeyClick(Sender: TObject);
+    procedure miExportPublicKeyClick(Sender: TObject);
   private
   private
-    //FOldOnChanged : TNotifyEvent;
-    FWalletKeys: TWalletKeys;
-    procedure SetWalletKeys(const Value: TWalletKeys);
-    procedure OnWalletKeysChanged(Sender : TObject);
-    { Private declarations }
-    Procedure UpdateWalletKeys;
-    Procedure UpdateSelectedWalletKey;
-    Function GetSelectedWalletKey(var WalletKey : TWalletKey) : Boolean;
-    Function GetSelectedWalletKeyAndIndex(var WalletKey : TWalletKey; var index : Integer) : Boolean;
-    Procedure CheckIsWalletKeyValidPassword;
-    procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
+    { private declarations }
+    procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletChanged;
+    procedure OnWalletChanged(Sender: TObject);
+    procedure RefreshUI;
+    function GetSelectedWalletKey(var WalletKey: TWalletKey): Boolean;
+    function GetSelectedWalletKeyAndIndex(var WalletKey: TWalletKey; var index: Integer): Boolean;
+  protected
+    function CheckIsWalletKeyValidPassword : boolean;
+    procedure ToggleWalletLock;
+    procedure AddNewKey;
+    procedure DeleteSelectedKey;
+    procedure UpdateSelectedWalletKey;
+    procedure ChangeSelectedKeyName;
+    procedure ExportSelectedPrivateKey;
+    procedure ExportSelectedPublicKey(notify:boolean);
+    procedure ChangeWalletPassword;
+    procedure BackupWallet;
+    procedure RestoreWallet;
   public
   public
-    { Public declarations }
-    Property WalletKeys : TWalletKeys read FWalletKeys write SetWalletKeys;
-    Destructor Destroy; override;
+    { public declarations }
   end;
   end;
 
 
-implementation
 
 
-uses
-  LCLIntf, LCLType, UCrypto, UAccounts, UUserInterface, UFRMNewPrivateKeyType, UAES;
+implementation
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
-{ TFRMWalletKeys }
+uses  LCLIntf, Clipbrd, UUserInterface, USettings, UCommon, UAccounts, UWIZAddKey, UAutoScope;
 
 
-procedure TFRMWalletKeys.bbChangeNameClick(Sender: TObject);
-Var wk : TWalletKey;
-  s : String;
-  index : integer;
+{%region Form life-cycle}
+
+procedure TFRMWalletKeys.FormCreate(Sender: TObject);
 begin
 begin
-  if not GetSelectedWalletKeyAndIndex(wk,index) then exit;
-  s := wk.Name;
-  if InputQuery('Change name','Input new key name:',s) then begin
-    WalletKeys.SetName(index,s);
-    UpdateWalletKeys;
+  TWallet.Keys.OnChanged.Add(OnWalletChanged);
+  RefreshUI;
+end;
+
+procedure TFRMWalletKeys.FormDestroy(Sender: TObject);
+begin
+  TWallet.Keys.OnChanged.Remove(OnWalletChanged);
+end;
+
+{%endregion}
+
+{%region Methods}
+
+procedure TFRMWalletKeys.ToggleWalletLock;
+begin
+  if NOT TWallet.Keys.HasPassword then exit;
+  if TWallet.Keys.IsValidPassword then begin
+    TWallet.Keys.LockWallet;
+  end else begin
+    TUserInterface.UnlockWallet(Self);
   end;
   end;
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbDeleteClick(Sender: TObject);
-Var wk : TWalletKey;
+procedure TFRMWalletKeys.AddNewKey;
+var
+  Scoped : TScoped;
+  wiz : TWIZAddKeyWizard;
+  model : TWizAddKeyModel;
+begin
+  wiz := Scoped.AddObject(TWIZAddKeyWizard.Create(nil)) as TWIZAddKeyWizard;
+  model := Scoped.AddObject(TWIZAddKeyModel.Create(nil)) as TWizAddKeyModel;
+  wiz.Start(model);
+end;
+
+procedure TFRMWalletKeys.DeleteSelectedKey;
+Var
+  wk : TWalletKey;
   index : Integer;
   index : Integer;
-  s : String;
+  prompt : String;
 begin
 begin
   if Not GetSelectedWalletKeyAndIndex(wk,index) then exit;
   if Not GetSelectedWalletKeyAndIndex(wk,index) then exit;
-  s := 'Are you sure you want to delete the selected private key?'+#10+wk.Name+#10+#10+
+
+  if (TSettings.MinerPrivateKeyType = mpk_Selected) AND (TSettings.MinerSelectedPrivateKey = TAccountComp.AccountKey2RawString(wk.AccountKey)) then begin
+    TUserInterface.ShowError(Self, 'Delete Key Faied',
+    'This key is used for mining and cannot be deleted.' + #10 + #10 +
+    'De-select this key from options and try again.');
+    exit;
+  end;
+
+  prompt := 'Are you sure you want to delete the selected private key?'+#10+wk.Name+#10+#10+
     'Please note that this will forever remove access to accounts using this key...';
     'Please note that this will forever remove access to accounts using this key...';
-  if Application.MessageBox(Pchar(s),PChar('Delete key'),
-    MB_YESNO+MB_DEFBUTTON2+MB_ICONWARNING)<>Idyes then exit;
-  if Application.MessageBox(PChar('Are you sure you want to delete?'),PChar('Delete key'),
-    MB_YESNO+MB_DEFBUTTON2+MB_ICONWARNING)<>Idyes then exit;
-  WalletKeys.Delete(index);
-  UpdateWalletKeys;
+  if TUserInterface.AskQuestion(Self, mtWarning, 'Confirm Delete', prompt, mbYesNo) = mbYes then
+    if TUserInterface.AskQuestion(Self, mtWarning, 'Confirm Delete', 'ARE YOU ABSOLUTELY SURE?', mbYesNo) = mbYes then
+      TWallet.DeleteKey(wk);
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbExportAllWalletKeysClick(Sender: TObject);
-Var efn : String;
-  fs : TFileStream;
+procedure TFRMWalletKeys.UpdateSelectedWalletKey;
+Var
+  wk : TWalletKey;
+  ok : Boolean;
 begin
 begin
-  if WalletKeys.Count<=0 then raise Exception.Create('Your wallet is empty. No keys!');
-  if ((WalletKeys.IsValidPassword) And (WalletKeys.WalletPassword='')) then begin
-    if Application.MessageBox(PChar('Your wallet has NO PASSWORD'+#10+#10+
-      'It is recommend to protect your wallet with a password prior to exporting it!'+#10+#10+
-      'Continue without password protection?'),PChar(Application.Title),MB_YESNO+MB_ICONWARNING+MB_DEFBUTTON2)<>IdYes then exit;
-  end;
-
-  if Not SaveDialog.Execute then exit;
-  efn := SaveDialog.FileName;
-  if FileExists(efn) then begin
-    if Application.MessageBox(PChar('This file exists:'+#10+efn+#10#10+'Overwrite?'),PChar(Application.Title),MB_YESNO+MB_ICONQUESTION+MB_DEFBUTTON2)<>IdYes then exit;
-  end;
-  fs := TFileStream.Create(efn,fmCreate);
+  ok := false;
+  wk := CT_TWalletKey_NUL;
   try
   try
-    fs.Size := 0;
-    WalletKeys.SaveToStream(fs);
+    if Not GetSelectedWalletKey(wk) then exit;
+    ok := true;
+    lblEncryptionType.Caption := TAccountComp.GetECInfoTxt( wk.AccountKey.EC_OpenSSL_NID );
+    if wk.Name='' then lblKeyName.Caption := '(No Name)'
+    else lblKeyName.Caption := wk.Name;
+    memoPublicKey.Lines.Text := TAccountComp.AccountPublicKeyExport(wk.AccountKey);
+    memoPublicKey.Font.Color := clBlack;
   finally
   finally
-    fs.Free;
+    lblEncryptionTypeCaption.Enabled := ok;
+    lblEncryptionType.Enabled := ok;
+    lblKeyNameCaption.Enabled := ok;
+    lblKeyName.Enabled := (ok) And (wk.Name<>'');
+    lblPrivateKeyCaption.Enabled := ok;
+    memoPublicKey.Enabled := ok;
+    btnCopyClipboard.Enabled := ok;
+    if not ok then begin
+      lblEncryptionType.Caption := '';
+      lblKeyName.Caption := '';
+      memoPublicKey.Lines.Clear;
+    end;
   end;
   end;
-  Application.MessageBox(PChar('Wallet key exported to a file:'+#10+efn),PChar(Application.Title),MB_OK+MB_ICONINFORMATION);
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbExportPrivateKeyClick(Sender: TObject);
+procedure TFRMWalletKeys.ChangeSelectedKeyName;
+Var wk : TWalletKey;
+  s : String;
+  index : integer;
+begin
+  if not GetSelectedWalletKeyAndIndex(wk,index) then exit;
+  s := wk.Name;
+  if TUserInterface.AskEnterString(Self, 'Change name','Input new key name:',s) then begin
+    TWallet.Keys.SetName(index,s);
+  end;
+end;
+
+procedure TFRMWalletKeys.ExportSelectedPrivateKey;
 Var wk : TWalletKey;
 Var wk : TWalletKey;
   pwd1,pwd2, enc : String;
   pwd1,pwd2, enc : String;
 begin
 begin
-  CheckIsWalletKeyValidPassword;
+  if not CheckIsWalletKeyValidPassword then exit;
   if Not GetSelectedWalletKey(wk) then exit;
   if Not GetSelectedWalletKey(wk) then exit;
   if Assigned(wk.PrivateKey) then begin
   if Assigned(wk.PrivateKey) then begin
-    if InputQuery('Export private key','Insert a password to export',pwd1) then begin
-      if InputQuery('Export private key','Repeat the password to export',pwd2) then begin
+    if TUserInterface.AskEnterProtectedString(Self, 'Export Private Key','Enter a password to encrypt private key',pwd1) then begin
+      if TUserInterface.AskEnterProtectedString(Self, 'Export Private Key','Re-enter the password',pwd2) then begin
         if pwd1<>pwd2 then raise Exception.Create('Passwords does not match!');
         if pwd1<>pwd2 then raise Exception.Create('Passwords does not match!');
-        enc := TCrypto.ToHexaString( TAESComp.EVP_Encrypt_AES256( wk.PrivateKey.ExportToRaw,pwd1) );
+        enc := TWallet.ExportPrivateKey(wk, pwd1);
         Clipboard.AsText := enc;
         Clipboard.AsText := enc;
-        Application.MessageBox(PChar('The password has been encrypted with your password and copied to the clipboard.'+
+        TUserInterface.ShowInfo(Self, 'Completed',
+         'The private key has been encrypted with your password and copied to the clipboard.'+
           #10+#10+
           #10+#10+
-          'Password: "'+pwd1+'"'+#10+
-          #10+
           'Encrypted key value (Copied to the clipboard):'+#10+
           'Encrypted key value (Copied to the clipboard):'+#10+
           enc+
           enc+
-          #10+#10+'Length='+Inttostr(length(enc))+' bytes'),
-          PChar(Application.Title),MB_OK+MB_ICONINFORMATION);
+          #10+#10+'Length='+Inttostr(length(enc))+' bytes');
       end else raise Exception.Create('Cancelled operation');
       end else raise Exception.Create('Cancelled operation');
     end;
     end;
   end;
   end;
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbExportPublicKeyClick(Sender: TObject);
+procedure TFRMWalletKeys.ExportSelectedPublicKey(notify:boolean);
 Var wk : TWalletKey;
 Var wk : TWalletKey;
   s : String;
   s : String;
 begin
 begin
-  CheckIsWalletKeyValidPassword;
   if Not GetSelectedWalletKey(wk) then exit;
   if Not GetSelectedWalletKey(wk) then exit;
-  s := TAccountComp.AccountPublicKeyExport(wk.AccountKey);
+  s := TWallet.ExportPublicKey(wk);
   Clipboard.AsText := s;
   Clipboard.AsText := s;
-  Application.MessageBox(PChar('The public key has been copied to the clipboard'+#10+#10+
-    'Public key value:'+#10+
-    s+#10+#10+
-    'Length='+Inttostr(length(s))+' bytes'),
-          PChar(Application.Title),MB_OK+MB_ICONINFORMATION);
+  if notify then
+    TUserInterface.ShowInfo(Self, 'Completed',
+      'The public key has been copied to the clipboard'+#10+#10+
+      'Public key value:'+#10+
+      s+#10+#10+
+      'Length='+Inttostr(length(s))+' bytes');
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbGenerateNewKeyClick(Sender: TObject);
-Var FRM : TFRMNewPrivateKeyType;
+procedure TFRMWalletKeys.ChangeWalletPassword;
 begin
 begin
-  CheckIsWalletKeyValidPassword;
-  FRM := TFRMNewPrivateKeyType.Create(Self);
-  try
-    FRM.WalletKeys := WalletKeys;
-    FRM.ShowModal;
-    UpdateWalletKeys;
-  finally
-    FRM.Free;
-  end;
+  if not CheckIsWalletKeyValidPassword
+    then exit;
+  TUserInterface.ChangeWalletPassword(Self);
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbImportKeysFileClick(Sender: TObject);
-Var wki : TWalletKeys;
-  ifn,pwd : String;
-  i : Integer;
-  cPrivatekeys, cPublicKeys : Integer;
+procedure TFRMWalletKeys.BackupWallet;
+var
+  filename : String;
 begin
 begin
-  if Not OpenDialog.Execute then exit;
-  ifn := OpenDialog.FileName;
-  if Not FileExists(ifn) then raise Exception.Create('Cannot find file '+ifn);
+  if TWallet.Keys.Count<=0 then begin
+    TUserInterface.ShowError(self, 'Error', 'Your wallet is empty. No keys!');
+    exit;
+  end;
+  if NOT TWallet.Keys.HasPassword then
+    if TUserInterface.AskQuestion(self, mtWarning,
+      'No Password', 'Your wallet has NO PASSWORD'+#10+#10+
+      'It is recommend to protect your wallet with a password prior to exporting it!'+#10+#10+
+      'Continue without password protection?', mbYesNo) <> mbYes then exit;
+  if Not SaveDialog.Execute
+    then exit;
+  filename := SaveDialog.FileName;
+  if FileExists(filename) then
+    if TUserInterface.AskQuestion(self, mtConfirmation, 'Overwrite', 'This file exists:'+#10+filename+#10#10+'Overwrite?', mbYesNo)<> mbYes then
+         exit;
+  TWallet.BackupWallet(filename);
+  TUserInterface.ShowInfo(self, 'Completed', 'Wallet key exported to a file:'+#10+filename);
+end;
 
 
-  wki := TWalletKeys.Create(Self);
-  try
-    wki.WalletFileName := ifn;
-    if wki.Count<=0 then raise Exception.Create('Wallet file has no valid data');
-    pwd := '';
-    While (Not wki.IsValidPassword) do begin
-      if Not InputQuery('Import','Enter the wallet file password:',pwd) then exit;
-      wki.WalletPassword := pwd;
-      if not wki.IsValidPassword then begin
-        If Application.MessageBox(PChar('Password entered is not valid, retry?'),PChar(Application.Title),MB_ICONERROR+MB_YESNO)<>Idyes then exit;
-      end;
-    end;
-    cPrivatekeys := 0;
-    cPublicKeys := 0;
-    if wki.IsValidPassword then begin
-      for i := 0 to wki.Count - 1 do begin
-        if WalletKeys.IndexOfAccountKey(wki.Key[i].AccountKey)<0 then begin
-          If Assigned(wki.Key[i].PrivateKey) then begin
-            WalletKeys.AddPrivateKey(wki.Key[i].Name,wki.Key[i].PrivateKey);
-            inc(cPrivatekeys);
-          end else begin
-            WalletKeys.AddPublicKey(wki.Key[i].Name,wki.Key[i].AccountKey);
-            inc(cPublicKeys);
-          end;
-        end;
-      end;
-    end;
-    if (cPrivatekeys>0) Or (cPublicKeys>0) then begin
-      Application.MessageBox(PChar('Wallet file imported successfully'+#10+#10+
-        'File:'+ifn+#10+#10+
-        'Total keys in wallet: '+inttostr(wki.Count)+#10+
-        'Imported private keys: '+IntToStr(cPrivatekeys)+#10+
-        'Imported public keys only: '+IntToStr(cPublicKeys)+#10+
-        'Duplicated (not imported): '+InttoStr(wki.Count - cPrivatekeys - cPublicKeys)),
-        PChar(Application.Title),MB_OK+MB_ICONINFORMATION);
+procedure TFRMWalletKeys.RestoreWallet;
+Var
+  filename,password : String;
+  restoreResult : TRestoreWalletResult;
+begin
+  if not CheckIsWalletKeyValidPassword then exit;
+  if not OpenDialog.Execute then exit;
+  filename := OpenDialog.FileName;
+  if Not FileExists(filename) then
+    raise Exception.Create('Cannot find file '+filename);
+  repeat
+    if NOT TUserInterface.AskEnterProtectedString(Self, 'Restore Wallet', 'Please enter password used to secure the imported wallet', password) then
+      exit;
+    restoreResult := TWallet.RestoreWallet(filename, password);
+    if (not restoreResult.Success) AND (TUserInterface.AskQuestion(self, mtError, 'Wrong Password', 'Password entered is not valid, retry?', mbYesNo) <> mbYes) then
+      exit;
+  until restoreResult.Success;
+  if restoreResult.Success then begin
+    if (restoreResult.ImportedPrivateKeys>0) Or (restoreResult.ImportedPublicKeys>0) then begin
+      TUserInterface.ShowInfo(self,
+      'Completed',
+      'Wallet file imported successfully'+#10+#10+
+        'File: '+filename+#10+#10+
+        'Total keys in wallet: '+inttostr(restoreResult.TotalKeysFound)+#10+
+        'Imported private keys: '+IntToStr(restoreResult.ImportedPrivateKeys)+#10+
+        'Imported watch-only keys: '+IntToStr(restoreResult.ImportedPublicKeys)+#10+
+        'Duplicates (discarded): '+InttoStr(restoreResult.Duplicates));
     end else begin
     end else begin
-      Application.MessageBox(PChar('Wallet file keys were already in your wallet. Nothing imported'+#10+#10+
-        'File:'+ifn+#10+#10+
-        'Total keys in wallet: '+inttostr(wki.Count)),
-        PChar(Application.Title),MB_OK+MB_ICONWARNING);
+      TUserInterface.ShowWarning(Self,
+      'No New Keys',
+      'Wallet file keys were already in your wallet. Nothing imported'+#10+#10+
+        'File: '+filename+#10+#10+
+        'Total keys in wallet: '+inttostr(restoreResult.TotalKeysFound));
     end;
     end;
-  finally
-    wki.Free;
   end;
   end;
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbImportPrivateKeyClick(Sender: TObject);
-var s : String;
- desenc, enc : AnsiString;
- EC : TECPrivateKey;
- i : Integer;
- wk : TWalletKey;
- parseResult : Boolean;
-
-  function ParseRawKey(EC_OpenSSL_NID : Word) : boolean;
-  begin
-    FreeAndNil(EC); ParseRawKey := False;
-    EC := TECPrivateKey.Create;
-    Try
-      EC.SetPrivateKeyFromHexa(EC_OpenSSL_NID, TCrypto.ToHexaString(enc));
-      ParseRawKey := True;
-    Except
-      On E:Exception do begin
-        FreeAndNil(EC);
-        Raise;
-      end;
-    end;
-  end;
+{%endregion}
 
 
-  function ParseEncryptedKey : boolean;
-  begin
-      Repeat
-        s := '';
-        desenc := '';
-        if InputQuery('Import private key','Enter the password:',s) then begin
-          If (TAESComp.EVP_Decrypt_AES256(enc,s,desenc)) then begin
-            if (desenc<>'') then begin
-              EC := TECPrivateKey.ImportFromRaw(desenc);
-              ParseEncryptedKey := True;
-              Exit;
-            end else begin
-              if Application.MessageBox(PChar('Invalid password!'),'',MB_RETRYCANCEL+MB_ICONERROR)<>IDRETRY then begin
-                ParseEncryptedKey := False;
-                Exit;
-              end;
-              desenc := '';
-            end;
-          end else begin
-            if Application.MessageBox(PChar('Invalid password or corrupted data!'),'',MB_RETRYCANCEL+MB_ICONERROR)<>IDRETRY then begin
-              ParseEncryptedKey := False;
-              Exit;
-            end;
-          end;
-        end else begin
-          ParseEncryptedKey := false;
-          Exit;
-        end;
-      Until (desenc<>'');
-  end;
+{%region Aux}
 
 
+procedure TFRMWalletKeys.RefreshUI;
+var
+  lasti,i : Integer;
+  selected_wk,wk : TWalletKey;
+  keyName : AnsiString;
 begin
 begin
-  EC := Nil;
-  CheckIsWalletKeyValidPassword;
-  if Not Assigned(WalletKeys) then exit;
-  if InputQuery('Import private key','Insert the password protected private key or raw private key',s) then begin
-    s := trim(s);
-    if (s='') then raise Exception.Create('No valid key');
-    enc := TCrypto.HexaToRaw(s);
-    if (enc='') then raise Exception.Create('Invalid text... You must enter an hexadecimal value ("0".."9" or "A".."F")');
-    case Length(enc) of
-         32: parseResult := ParseRawKey(CT_NID_secp256k1);
-         35,36: parseResult := ParseRawKey(CT_NID_sect283k1);
-         48: parseResult := ParseRawKey(CT_NID_secp384r1);
-         65,66: parseResult := ParseRawKey(CT_NID_secp521r1);
-         64, 80, 96: parseResult := ParseEncryptedKey;
-         else Exception.Create('Invalidly formatted private key string. Ensure it is an encrypted private key export or raw private key hexstring.');
+  GetSelectedWalletKeyAndIndex(wk,lasti);
+  lbWalletKeys.Items.BeginUpdate;
+  Try
+    lbWalletKeys.Items.Clear;
+    lblKeysEncrypted.Caption := '';
+
+    If NOT TWallet.Keys.HasPassword then begin
+      // NO PASSWORD
+      lblKeysEncrypted.Caption := 'Wallet has no password';
+      ilIcons.GetBitmap(1, btnLock.Glyph);
+      btnLock.Enabled := false;
+      btnChangePassword.Enabled := true;
+      btnAddKey.Visible := true;
+      btnChangePassword.Caption := 'Set Password';
+      btnChangePassword.Enabled := true;
+      btnRestoreBackup.Enabled := true;
+      miChangeName.Enabled := true;
+      miExportPrivateKey.Enabled := true;
+      miDeleteKey.Enabled := true;
+    end else if TWallet.Keys.IsValidPassword then begin
+      // UNLOCKED
+      lblKeysEncrypted.Caption := 'Wallet is unlocked';
+      ilIcons.GetBitmap(1, btnLock.Glyph);
+      btnLock.Enabled := true;
+      btnChangePassword.Enabled := true;
+      btnAddKey.Enabled := true;
+      btnAddKey.Visible := true;
+      btnChangePassword.Caption := 'Change Password';
+      btnChangePassword.Enabled := true;
+      btnRestoreBackup.Enabled := true;
+      miChangeName.Enabled := true;
+      miExportPrivateKey.Enabled := true;
+      miDeleteKey.Enabled := true;
+    end else begin
+      // LOCKED
+      lblKeysEncrypted.Caption := 'Wallet is locked';
+      ilIcons.GetBitmap(0, btnLock.Glyph);
+      btnLock.Enabled := true;
+      btnChangePassword.Enabled := false;
+      btnAddKey.Visible := false;
+      btnAddKey.Enabled := false;
+      btnChangePassword.Caption := 'Change Password';
+      btnChangePassword.Enabled := false;
+      btnRestoreBackup.Enabled := false;
+      miChangeName.Enabled := false;
+      miExportPrivateKey.Enabled := false;
+      miDeleteKey.Enabled := false;
     end;
     end;
-    if (parseResult = False) then
-       exit;
-    Try
-      // EC is assigned by ParseRawKey/ImportEncryptedKey
-      if Not Assigned(EC) then begin
-        Application.MessageBox(PChar('Invalid password and/or corrupted data!'),'', MB_OK);
-        exit;
-      end;
-      i := WalletKeys.IndexOfAccountKey(EC.PublicKey);
-      if (i>=0) then begin
-        wk := WalletKeys.Key[i];
-        if Assigned(wk.PrivateKey) And (Assigned(wk.PrivateKey.PrivateKey)) then raise Exception.Create('This key is already in your wallet!');
+    for i := 0 to TWallet.Keys.Count - 1 do begin
+      wk := TWallet.Keys.Key[i];
+      if (wk.Name='') then begin
+        keyName := '(No Name)';
+      end else begin
+        keyName := wk.Name;
       end;
       end;
-      s := 'Imported '+DateTimeToStr(now);
-      s := InputBox('Set a name','Name for this private key:',s);
-      i := WalletKeys.AddPrivateKey(s,EC);
-      Application.MessageBox(PChar('Imported private key'),PChar(Application.Title),MB_OK+MB_ICONINFORMATION);
-    Finally
-      EC.Free;
-    End;
-    UpdateWalletKeys;
-  end;
+      if Not wk.HasPrivateKey then
+        keyName:=keyName+' (watch-only)';
+      lbWalletKeys.Items.AddObject(keyName,TObject(i));
+    end;
+    i := lbWalletKeys.Items.IndexOfObject(TObject(lasti));
+    lbWalletKeys.ItemIndex := i;
+  Finally
+    lbWalletKeys.Items.EndUpdate;
+  End;
+  UpdateSelectedWalletKey;
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbImportPublicKeyClick(Sender: TObject);
-var s : String;
- raw : AnsiString;
- EC : TECPrivateKey;
- account : TAccountKey;
- errors : AnsiString;
+function TFRMWalletKeys.CheckIsWalletKeyValidPassword : boolean;
 begin
 begin
-  CheckIsWalletKeyValidPassword;
-  if Not Assigned(WalletKeys) then exit;
-  if Not InputQuery('Import publick key','Insert the public key in hexa format or imported format',s) then exit;
-  If not TAccountComp.AccountPublicKeyImport(s,account,errors) then begin
-    raw := TCrypto.HexaToRaw(s);
-    if trim(raw)='' then raise Exception.Create('Invalid public key value (Not hexa or not an imported format)'+#10+errors);
-    account := TAccountComp.RawString2Accountkey(raw);
-  end;
-  If not TAccountComp.IsValidAccountKey(account,errors) then raise Exception.Create('This data is not a valid public key'+#10+errors);
-  if WalletKeys.IndexOfAccountKey(account)>=0 then raise exception.Create('This key exists on your wallet');
-  s := 'Imported public key '+DateTimeToStr(now);
-  if InputQuery('Set a name','Name for this private key:',s) then begin
-    WalletKeys.AddPublicKey(s,account);
-    UpdateWalletKeys;
-    Application.MessageBox(PChar('Imported public key'),PChar(Application.Title),MB_OK+MB_ICONINFORMATION);
-  end;
+  if NOT TWallet.Keys.IsValidPassword then begin
+    TUserInterface.ShowError(Self, 'Unable to continue', 'Wallet is locked. Please unlock the wallet to perform this task.');
+    Result := false;
+  end else
+    Result := true;
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbLockClick(Sender: TObject);
+function TFRMWalletKeys.GetSelectedWalletKey(var WalletKey: TWalletKey): Boolean;
+Var i : Integer;
 begin
 begin
-  FWalletKeys.LockWallet;
+  Result := GetSelectedWalletKeyAndIndex(WalletKey,i);
 end;
 end;
 
 
-procedure TFRMWalletKeys.bbUpdatePasswordClick(Sender: TObject);
+function TFRMWalletKeys.GetSelectedWalletKeyAndIndex(var WalletKey: TWalletKey; var index: Integer): Boolean;
 begin
 begin
-  if FWalletKeys.IsValidPassword then begin
-    TUserInterface.ChangeWalletPassword(Self, FWalletKeys);
-  end else begin
-    TUserInterface.UnlockWallet(Self, FWalletKeys);
+  index := -1;
+  Result := false;
+  if lbWalletKeys.ItemIndex<0 then exit;
+  index := Integer(lbWalletKeys.Items.Objects[ lbWalletKeys.ItemIndex ]);
+  if (index>=0) And (index<TWallet.Keys.Count) then begin
+    WalletKey := TWallet.Keys.Key[index];
+    Result := true;
   end;
   end;
-  UpdateWalletKeys;
 end;
 end;
 
 
-procedure TFRMWalletKeys.CheckIsWalletKeyValidPassword;
-begin
-  if Not Assigned(FWalletKeys) then exit;
+{%endregion}
 
 
-  if Not FWalletKeys.IsValidPassword then begin
-    Application.MessageBox(PChar('Wallet key is encrypted!'+#10+#10+'You must enter password to continue...'),
-      PCHar(Application.Title),MB_OK+MB_ICONWARNING);
-    bbUpdatePasswordClick(Nil);
-    if Not FWalletKeys.IsValidPassword then raise Exception.Create('Cannot continue without valid password');
-  end;
+{%region Event Handlers}
+
+procedure TFRMWalletKeys.btnLockClick(Sender: TObject);
+begin
+  ToggleWalletLock;
 end;
 end;
 
 
 procedure TFRMWalletKeys.CM_WalletChanged(var Msg: TMessage);
 procedure TFRMWalletKeys.CM_WalletChanged(var Msg: TMessage);
 begin
 begin
-  UpdateWalletKeys;
+  RefreshUI;
 end;
 end;
 
 
-destructor TFRMWalletKeys.Destroy;
+procedure TFRMWalletKeys.OnWalletChanged(Sender: TObject);
 begin
 begin
-  if Assigned(FWalletKeys) then FWalletKeys.OnChanged.Remove(OnWalletKeysChanged);
-  inherited;
+  // Ensure handled in UI thread
+  PostMessage(Self.Handle,CM_PC_WalletChanged,0,0);
 end;
 end;
 
 
-procedure TFRMWalletKeys.FormCreate(Sender: TObject);
+procedure TFRMWalletKeys.btnAddKeyClick(Sender: TObject);
 begin
 begin
-  lbWalletKeys.Sorted := true;
-  FWalletKeys := Nil;
-  UpdateWalletKeys;
+  AddNewKey;
 end;
 end;
 
 
-function TFRMWalletKeys.GetSelectedWalletKey(var WalletKey: TWalletKey): Boolean;
-Var i : Integer;
+procedure TFRMWalletKeys.btnBackupWalletClick(Sender: TObject);
 begin
 begin
-  Result := GetSelectedWalletKeyAndIndex(WalletKey,i);
+ BackupWallet;
 end;
 end;
 
 
-function TFRMWalletKeys.GetSelectedWalletKeyAndIndex(var WalletKey: TWalletKey; var index: Integer): Boolean;
+procedure TFRMWalletKeys.btnChangePasswordClick(Sender: TObject);
 begin
 begin
-  index := -1;
-  Result := false;
-  if Not Assigned(WalletKeys) then exit;
-  if lbWalletKeys.ItemIndex<0 then exit;
-  index := Integer(lbWalletKeys.Items.Objects[ lbWalletKeys.ItemIndex ]);
-  if (index>=0) And (index<WalletKeys.Count) then begin
-    WalletKey := WalletKeys.Key[index];
-    Result := true;
-  end;
+  ChangeWalletPassword;
+end;
+
+procedure TFRMWalletKeys.btnCopyClipboardClick(Sender: TObject);
+begin
+  ExportSelectedPublicKey(false);
+end;
+
+procedure TFRMWalletKeys.btnDeleteKeyClick(Sender: TObject);
+begin
+  DeleteSelectedKey;
+end;
+
+procedure TFRMWalletKeys.btnRestoreBackupClick(Sender: TObject);
+begin
+ RestoreWallet;
 end;
 end;
 
 
 procedure TFRMWalletKeys.lbWalletKeysClick(Sender: TObject);
 procedure TFRMWalletKeys.lbWalletKeysClick(Sender: TObject);
@@ -445,105 +459,27 @@ begin
   UpdateSelectedWalletKey;
   UpdateSelectedWalletKey;
 end;
 end;
 
 
-procedure TFRMWalletKeys.OnWalletKeysChanged(Sender : TObject);
+procedure TFRMWalletKeys.miChangeNameClick(Sender: TObject);
 begin
 begin
-  PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
+  ChangeSelectedKeyName;
 end;
 end;
 
 
-procedure TFRMWalletKeys.SetWalletKeys(const Value: TWalletKeys);
+procedure TFRMWalletKeys.miDeleteKeyClick(Sender: TObject);
 begin
 begin
-  if FWalletKeys=Value then exit;
-  if Assigned(FWalletKeys) then FWalletKeys.OnChanged.Remove(OnWalletKeysChanged);
-  FWalletKeys := Value;
-  if Assigned(FWalletKeys) then begin
-    FWalletKeys.OnChanged.Add(OnWalletKeysChanged);
-  end;
-  UpdateWalletKeys;
+  DeleteSelectedKey;
 end;
 end;
 
 
-procedure TFRMWalletKeys.UpdateSelectedWalletKey;
-Var
-  wk : TWalletKey;
-  ok : Boolean;
+procedure TFRMWalletKeys.miExportPrivateKeyClick(Sender: TObject);
 begin
 begin
-  ok := false;
-  wk := CT_TWalletKey_NUL;
-  try
-    if Not GetSelectedWalletKey(wk) then exit;
-    ok := true;
-    lblEncryptionType.Caption := TAccountComp.GetECInfoTxt( wk.AccountKey.EC_OpenSSL_NID );
-    if wk.Name='' then lblKeyName.Caption := '(No name)'
-    else lblKeyName.Caption := wk.Name;
-    if Assigned(wk.PrivateKey) then begin
-      memoPrivateKey.Lines.Text :=  TCrypto.PrivateKey2Hexa(wk.PrivateKey.PrivateKey);
-      memoPrivateKey.Font.Color := clBlack;
-    end else begin
-      memoPrivateKey.Lines.Text := '(No private key)';
-      memoPrivateKey.Font.Color := clRed;
-    end;
-  finally
-    lblEncryptionTypeCaption.Enabled := ok;
-    lblEncryptionType.Enabled := ok;
-    lblKeyNameCaption.Enabled := ok;
-    lblKeyName.Enabled := (ok) And (wk.Name<>'');
-    lblPrivateKeyCaption.Enabled := ok;
-    memoPrivateKey.Enabled := ok;
-    bbExportPrivateKey.Enabled := ok;
-    bbExportPublicKey.Enabled := ok;
-    bbChangeName.Enabled := ok;
-    lblPrivateKeyCaption2.Enabled := ok;
-    bbDelete.Enabled := ok;
-    if not ok then begin
-      lblEncryptionType.Caption := '';
-      lblKeyName.Caption := '';
-      memoPrivateKey.Lines.Clear;
-    end;
-  end;
-
+  ExportSelectedPrivateKey;
 end;
 end;
 
 
-procedure TFRMWalletKeys.UpdateWalletKeys;
-Var lasti,i : Integer;
-  selected_wk,wk : TWalletKey;
-  s : AnsiString;
+procedure TFRMWalletKeys.miExportPublicKeyClick(Sender: TObject);
 begin
 begin
-  GetSelectedWalletKeyAndIndex(wk,lasti);
-  lbWalletKeys.Items.BeginUpdate;
-  Try
-    lbWalletKeys.Items.Clear;
-    lblKeysEncrypted.Caption := '';
-    if not assigned(FWalletKeys) then exit;
-    bbLock.Enabled := (FWalletKeys.IsValidPassword) And (FWalletKeys.WalletPassword<>'');
-    If FWalletKeys.IsValidPassword then begin
-      if FWalletKeys.WalletPassword='' then lblKeysEncrypted.Caption := 'Wallet without password'
-      else lblKeysEncrypted.Caption := 'Wallet is password protected';
-      lblKeysEncrypted.font.Color := clGreen;
-      bbUpdatePassword.Caption := 'Change password';
-    end else begin
-      lblKeysEncrypted.Caption := 'Wallet is encrypted... need password!';
-      lblKeysEncrypted.font.Color := clRed;
-      bbUpdatePassword.Caption := 'Input password';
-    end;
-    for i := 0 to WalletKeys.Count - 1 do begin
-      wk := WalletKeys.Key[i];
-      if (wk.Name='') then begin
-        s := 'Sha256='+TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString(wk.AccountKey) ) );
-      end else begin
-        s := wk.Name;
-      end;
-      if Not Assigned(wk.PrivateKey) then begin
-        if wk.CryptedKey<>'' then s:=s+' (Encrypted, need password)';
-        s:=s+' (* without key)';
-      end;
-      lbWalletKeys.Items.AddObject(s,TObject(i));
-    end;
-    i := lbWalletKeys.Items.IndexOfObject(TObject(lasti));
-    lbWalletKeys.ItemIndex := i;
-  Finally
-    lbWalletKeys.Items.EndUpdate;
-  End;
-  UpdateSelectedWalletKey;
+  ExportSelectedPublicKey(true);
 end;
 end;
 
 
+{%endregion}
+
 end.
 end.
 
 

+ 0 - 35
Units/Forms/UFRMWalletKeys2.pas

@@ -1,35 +0,0 @@
-unit UFRMWalletKeys2;
-
-{$mode delphi}
-
-{ Copyright (c) 2018 by Herman Schoenfeld
-
-  Distributed under the MIT software license, see the accompanying file LICENSE
-  or visit http://www.opensource.org/licenses/mit-license.php.
-}
-
-
-interface
-
-{$I ./../PascalCoin/config.inc}
-
-uses
-  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, UConst;
-
-type
-  TFRMWalletKeys2 = class(TApplicationForm)
-  private
-    { private declarations }
-  public
-    { public declarations }
-  end;
-
-var
-  FRMWalletKeys2: TFRMWalletKeys2;
-
-implementation
-
-{$R *.lfm}
-
-end.
-

+ 132 - 221
Units/Forms/UUserInterface.pas

@@ -17,7 +17,7 @@ interface
 
 
 uses
 uses
   SysUtils, Classes, Forms, Controls, Windows, ExtCtrls, Dialogs,
   SysUtils, Classes, Forms, Controls, Windows, ExtCtrls, Dialogs,
-  UCommonUI, UBlockChain, UAccounts, UNode, UWalletKeys, UAppParams, UConst, UFolderHelper, UGridUtils, URPC, UPoolMining,
+  UCommonUI, UBlockChain, UAccounts, UNode, UWallet, UConst, UFolderHelper, UGridUtils, URPC, UPoolMining,
   ULog, UThread, UNetProtocol, UCrypto,
   ULog, UThread, UNetProtocol, UCrypto,
   UFRMMainForm, UFRMSyncronizationForm, UFRMAccountExplorer, UFRMOperationExplorer, UFRMPendingOperations, UFRMOperation,
   UFRMMainForm, UFRMSyncronizationForm, UFRMAccountExplorer, UFRMOperationExplorer, UFRMPendingOperations, UFRMOperation,
   UFRMLogs, UFRMMessages, UFRMNodes, UFRMBlockExplorer, UFRMWalletKeys;
   UFRMLogs, UFRMMessages, UFRMNodes, UFRMBlockExplorer, UFRMWalletKeys;
@@ -27,10 +27,6 @@ type
 
 
   TLoadDatabaseThread = class;
   TLoadDatabaseThread = class;
 
 
-  { TMinerPrivateKey }
-
-  TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
-
   { TUserInterface }
   { TUserInterface }
 
 
   TUserInterface = class
   TUserInterface = class
@@ -50,12 +46,9 @@ type
       // Components
       // Components
       FRPCServer : TRPCServer; static;
       FRPCServer : TRPCServer; static;
       FPoolMiningServer : TPoolMiningServer; static;
       FPoolMiningServer : TPoolMiningServer; static;
-      FMinerPrivateKeyType : TMinerPrivateKey; static;
-      FWalletKeys : TWalletKeysExt; static;
 
 
       // Local fields
       // Local fields
       FStarted : boolean; static;
       FStarted : boolean; static;
-      FAppParams : TAppParams; static;
       FMainForm : TFRMMainForm; static;
       FMainForm : TFRMMainForm; static;
       FIsActivated : Boolean; static;
       FIsActivated : Boolean; static;
       FUpdating : Boolean; static;
       FUpdating : Boolean; static;
@@ -72,7 +65,6 @@ type
 
 
       // Methods
       // Methods
       class procedure RefreshConnectionStatusDisplay;
       class procedure RefreshConnectionStatusDisplay;
-      class function GetAccountKeyForMiner: TAccountKey;
 
 
       // Getters/Setters
       // Getters/Setters
       class procedure SetStatusBar0Text(const text : AnsiString); static;
       class procedure SetStatusBar0Text(const text : AnsiString); static;
@@ -84,17 +76,13 @@ type
 
 
       // Aux methods
       // Aux methods
       class procedure FinishedLoadingDatabase;
       class procedure FinishedLoadingDatabase;
-      class procedure LoadAppParams;
-      class procedure SaveAppParams;
-
-      // Notifiers
-      class procedure NotifyConfigChanged;
 
 
       // Handlers
       // Handlers
       class procedure OnTimerUpdateStatusTimer(Sender: TObject);
       class procedure OnTimerUpdateStatusTimer(Sender: TObject);
       class procedure OnSubFormDestroyed(Sender: TObject);
       class procedure OnSubFormDestroyed(Sender: TObject);
 
 
       // Backend Handlers (TODO: refactor this out with TNotifyManyEvents)
       // Backend Handlers (TODO: refactor this out with TNotifyManyEvents)
+      class procedure OnSettingsChanged(Sender: TObject);
       class procedure OnAccountsChanged(Sender: TObject);
       class procedure OnAccountsChanged(Sender: TObject);
       class procedure OnBlocksChanged(Sender: TObject);
       class procedure OnBlocksChanged(Sender: TObject);
       class procedure OnReceivedHelloMessage(Sender: TObject);
       class procedure OnReceivedHelloMessage(Sender: TObject);
@@ -110,9 +98,7 @@ type
       class property Started : boolean read FStarted;
       class property Started : boolean read FStarted;
       class property Node : TNode read FNode;
       class property Node : TNode read FNode;
       class property Log : TLog read FLog;
       class property Log : TLog read FLog;
-      class property AppParams : TAppParams read FAppParams;
       class property PoolMiningServer : TPoolMiningServer read FPoolMiningServer;
       class property PoolMiningServer : TPoolMiningServer read FPoolMiningServer;
-      class property WalletKeys : TWalletKeysExt read FWalletKeys;
       class property MainFormMode : TFRMMainFormMode read GetMainFormMode write SetMainFormMode;
       class property MainFormMode : TFRMMainFormMode read GetMainFormMode write SetMainFormMode;
       class property StatusBar0Text : AnsiString read FStatusBar0Text write SetStatusBar0Text;
       class property StatusBar0Text : AnsiString read FStatusBar0Text write SetStatusBar0Text;
       class property StatusBar1Text : AnsiString read FStatusBar1Text write SetStatusBar1Text;
       class property StatusBar1Text : AnsiString read FStatusBar1Text write SetStatusBar1Text;
@@ -132,14 +118,17 @@ type
       class procedure ShowOperationInfoDialog(parentForm: TForm; const ophash : AnsiString);
       class procedure ShowOperationInfoDialog(parentForm: TForm; const ophash : AnsiString);
       class procedure ShowOperationInfoDialog(parentForm: TForm; const operation : TOperationResume); overload;
       class procedure ShowOperationInfoDialog(parentForm: TForm; const operation : TOperationResume); overload;
       class procedure ShowNewOperationDialog(parentForm : TForm; accounts : TOrderedCardinalList; defaultFee : Cardinal);
       class procedure ShowNewOperationDialog(parentForm : TForm; accounts : TOrderedCardinalList; defaultFee : Cardinal);
-      class procedure ShowWalletKeysDialog(parentForm : TForm);
       class procedure ShowSeedNodesDialog(parentForm : TForm);
       class procedure ShowSeedNodesDialog(parentForm : TForm);
       class procedure ShowPrivateKeysDialog(parentForm: TForm);
       class procedure ShowPrivateKeysDialog(parentForm: TForm);
       class procedure ShowMemoText(parentForm: TForm; const ATitle : AnsiString; text : TStrings);
       class procedure ShowMemoText(parentForm: TForm; const ATitle : AnsiString; text : TStrings);
-      class procedure UnlockWallet(parentForm: TForm;  walletKeys : TWalletKeys);
-      class procedure ChangeWalletPassword(parentForm: TForm; walletKeys : TWalletKeys);
-      class function AskQuestion(parentForm: TForm; const ACaption, APrompt : String; buttons: TMsgDlgButtons) : TMsgDlgBtn;
-      class function AskUserEnterString(parentForm: TForm; const ACaption, APrompt : String; var Value : String) : Boolean;
+      class procedure UnlockWallet(parentForm: TForm);
+      class procedure ChangeWalletPassword(parentForm: TForm);
+      class procedure ShowInfo(parentForm : TForm; const ACaption, APrompt : String);
+      class procedure ShowWarning(parentForm : TForm; const ACaption, APrompt : String);
+      class procedure ShowError(parentForm : TForm; const ACaption, APrompt : String);
+      class function AskQuestion(parentForm: TForm; AType:TMsgDlgType; const ACaption, APrompt : String; buttons: TMsgDlgButtons) : TMsgDlgBtn;
+      class function AskEnterString(parentForm: TForm; const ACaption, APrompt : String; var Value : String) : Boolean;
+      class function AskEnterProtectedString(parentForm: TForm; const ACaption, APrompt : String; var Value : String) : Boolean;
 
 
       // Show sub-forms
       // Show sub-forms
       class procedure ShowAccountExplorer;
       class procedure ShowAccountExplorer;
@@ -164,7 +153,7 @@ implementation
 
 
 uses
 uses
   UFRMAbout, UFRMNodesIp, UFRMPascalCoinWalletConfig, UFRMPayloadDecoder, UFRMMemoText,
   UFRMAbout, UFRMNodesIp, UFRMPascalCoinWalletConfig, UFRMPayloadDecoder, UFRMMemoText,
-  UOpenSSL, UFileStorage, UTime, UCommon;
+  UOpenSSL, UFileStorage, UTime, UCommon, USettings;
 
 
 {%region UI Lifecyle}
 {%region UI Lifecyle}
 
 
@@ -218,31 +207,23 @@ begin
     If Not ForceDirectories(TFolderHelper.GetPascalCoinDataFolder) then
     If Not ForceDirectories(TFolderHelper.GetPascalCoinDataFolder) then
       raise Exception.Create('Cannot create dir: '+TFolderHelper.GetPascalCoinDataFolder);
       raise Exception.Create('Cannot create dir: '+TFolderHelper.GetPascalCoinDataFolder);
 
 
-    // Open AppParams
-    TUserInterface.FAppParams := TAppParams.Create(FMainForm);
-    TUserInterface.FAppParams.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'AppParams.prm';
+    // Load settings
+    TSettings.Load;
+    TSettings.OnChanged.Add(OnSettingsChanged);
 
 
     // Open Wallet
     // Open Wallet
-    Try
-      FWalletKeys := TWalletKeysExt.Create(FMainForm);  // On Activate, this will be populated
-      FWalletKeys.WalletFileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'WalletKeys.dat';
-    Except
-      On E:Exception do begin
-        E.Message := 'Cannot open your wallet... Perhaps another instance of Pascal Coin is active!'+#10+#10+E.Message;
-        Raise;
-      end;
-    End;
+    TWallet.Load;
 
 
     // Load peer list
     // Load peer list
-    ips := FAppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].GetAsString('');
+    ips := TSettings.TryConnectOnlyWithThisFixedServers;
     TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
     TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
     TNetData.NetData.DiscoverFixedServersOnly(nsarr);
     TNetData.NetData.DiscoverFixedServersOnly(nsarr);
     setlength(nsarr,0);
     setlength(nsarr,0);
 
 
     // Start Node
     // Start Node
     FNode := TNode.Node;
     FNode := TNode.Node;
-    FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
-    FNode.PeerCache := FAppParams.ParamByName[CT_PARAM_PeerCache].GetAsString('')+';'+CT_Discover_IPs;
+    FNode.NetServer.Port := TSettings.InternetServerPort;
+    FNode.PeerCache := TSettings.PeerCache+';'+CT_Discover_IPs;
 
 
     // Subscribe to Node events (TODO refactor with FNotifyEvents)
     // Subscribe to Node events (TODO refactor with FNotifyEvents)
     FNodeNotifyEvents := TNodeNotifyEvents.Create(FMainForm);
     FNodeNotifyEvents := TNodeNotifyEvents.Create(FMainForm);
@@ -251,10 +232,10 @@ begin
 
 
     // Start RPC server
     // Start RPC server
     FRPCServer := TRPCServer.Create;
     FRPCServer := TRPCServer.Create;
-    FRPCServer.WalletKeys := WalletKeys;
-    FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
-    FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
-    WalletKeys.SafeBox := FNode.Bank.SafeBox;
+    FRPCServer.WalletKeys := TWallet.Keys;
+    FRPCServer.Active := TSettings.RpcPortEnabled;
+    FRPCServer.ValidIPs := TSettings.RpcAllowedIPs;
+    TWallet.Keys.SafeBox := FNode.Bank.SafeBox;
 
 
     // Initialise Database
     // Initialise Database
     FNode.Bank.StorageClass := TFileStorage;
     FNode.Bank.StorageClass := TFileStorage;
@@ -276,9 +257,6 @@ begin
     FTimerUpdateStatus.Interval := 1000;
     FTimerUpdateStatus.Interval := 1000;
     FTimerUpdateStatus.Enabled := true;
     FTimerUpdateStatus.Enabled := true;
 
 
-    // Load app params
-    LoadAppParams;
-
     // open the sync dialog
     // open the sync dialog
     FMainForm.SyncControl.UpdateBlockChainState;   //TODO fix this work-flow
     FMainForm.SyncControl.UpdateBlockChainState;   //TODO fix this work-flow
     RefreshConnectionStatusDisplay;
     RefreshConnectionStatusDisplay;
@@ -309,11 +287,12 @@ begin
   // Show sync dialog
   // Show sync dialog
   ShowSyncDialog;
   ShowSyncDialog;
 
 
-  // Show about box if first time load
-  if FAppParams.ParamByName[CT_PARAM_FirstTime].GetAsBoolean(true) then begin
-    FAppParams.ParamByName[CT_PARAM_FirstTime].SetAsBoolean(false);
+  // Final loading sequence
+  TSettings.RunCount := TSettings.RunCount + 1;
+  if TSettings.RunCount = 1 then begin
     ShowAboutBox(nil);
     ShowAboutBox(nil);
   end;
   end;
+  TSettings.Save;
 end;
 end;
 
 
 class procedure TUserInterface.ExitApplication;
 class procedure TUserInterface.ExitApplication;
@@ -324,8 +303,9 @@ begin
   // Exit application
   // Exit application
   TLog.NewLog(ltinfo,Classname,'Quit Application - START');
   TLog.NewLog(ltinfo,Classname,'Quit Application - START');
   Try
   Try
-    step := 'Saving params';
-    SaveAppParams;
+    step := 'Saving Settings';
+    TSettings.OnChanged.Remove(OnSettingsChanged);
+    TSettings.Save;
 
 
     // Destroys root form, non-modal forms and all their attached components
     // Destroys root form, non-modal forms and all their attached components
     step := 'Destroying UI graph';
     step := 'Destroying UI graph';
@@ -339,8 +319,6 @@ begin
     FNodesForm := nil;  // destroyed by FWallet
     FNodesForm := nil;  // destroyed by FWallet
     FMessagesForm := nil;  // destroyed by FWallet
     FMessagesForm := nil;  // destroyed by FWallet
     FTrayIcon := nil; // destroyed by FWallet
     FTrayIcon := nil; // destroyed by FWallet
-    FAppParams := nil; // destroyed by FWallet
-    FWalletKeys := nil; // destroyed by FWallet
     FNodeNotifyEvents := nil; // destroyed by FWallet
     FNodeNotifyEvents := nil; // destroyed by FWallet
 
 
     step := 'Destroying components';
     step := 'Destroying components';
@@ -407,11 +385,11 @@ end;
 class procedure TUserInterface.FinishedLoadingDatabase;
 class procedure TUserInterface.FinishedLoadingDatabase;
 begin
 begin
   FPoolMiningServer := TPoolMiningServer.Create;
   FPoolMiningServer := TPoolMiningServer.Create;
-  FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
-  FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
-  FPoolMiningServer.MinerPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
-  FNode.Operations.AccountKey := GetAccountKeyForMiner;
-  FPoolMiningServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
+  FPoolMiningServer.Port := TSettings.MinerServerRpcPort;
+  FPoolMiningServer.MinerAccountKey := TWallet.MiningKey;
+  FPoolMiningServer.MinerPayload := TSettings.MinerName;
+  FNode.Operations.AccountKey := TWallet.MiningKey;
+  FPoolMiningServer.Active := TSettings.MinerServerRpcActive;
   FPoolMiningServer.OnMiningServerNewBlockFound := OnMiningServerNewBlockFound;
   FPoolMiningServer.OnMiningServerNewBlockFound := OnMiningServerNewBlockFound;
   FMainForm.SyncControl.OnFinishedLoadingDatabase;
   FMainForm.SyncControl.OnFinishedLoadingDatabase;
   FMainForm.OnFinishedLoadingDatabase;
   FMainForm.OnFinishedLoadingDatabase;
@@ -437,12 +415,7 @@ class procedure TUserInterface.ShowOptionsDialog(parentForm: TForm);
 begin
 begin
   With TFRMPascalCoinWalletConfig.Create(parentForm) do
   With TFRMPascalCoinWalletConfig.Create(parentForm) do
   try
   try
-    AppParams := FAppParams;
-    WalletKeys := FWalletKeys;
-    if ShowModal=MrOk then begin
-      SaveAppParams;
-      NotifyConfigChanged;
-    end;
+    ShowModal
   finally
   finally
     Free;
     Free;
   end;
   end;
@@ -452,7 +425,7 @@ class procedure TUserInterface.ShowOperationInfoDialog(parentForm: TForm; const
 begin
 begin
   with TFRMPayloadDecoder.Create(parentForm) do
   with TFRMPayloadDecoder.Create(parentForm) do
   try
   try
-    Init(CT_TOperationResume_NUL, TUserInterface.WalletKeys,TUserInterface.AppParams);
+    Init(CT_TOperationResume_NUL);
     if ophash <> '' then
     if ophash <> '' then
       DoFind(ophash);
       DoFind(ophash);
     ShowModal;
     ShowModal;
@@ -465,7 +438,7 @@ class procedure TUserInterface.ShowOperationInfoDialog(parentForm: TForm; const
 begin
 begin
   with TFRMPayloadDecoder.Create(parentForm) do
   with TFRMPayloadDecoder.Create(parentForm) do
   try
   try
-    Init(operation, TUserInterface.WalletKeys,TUserInterface.AppParams);
+    Init(operation);
     ShowModal;
     ShowModal;
   finally
   finally
     Free;
     Free;
@@ -481,25 +454,12 @@ begin
   Try
   Try
     SenderAccounts.CopyFrom(accounts);
     SenderAccounts.CopyFrom(accounts);
     DefaultFee := defaultFee;
     DefaultFee := defaultFee;
-    WalletKeys := FWalletKeys;
     ShowModal;
     ShowModal;
   Finally
   Finally
     Free;
     Free;
   End;
   End;
 end;
 end;
 
 
-class procedure TUserInterface.ShowWalletKeysDialog(parentForm : TForm);
-var FRM : TFRMWalletKeys;
-begin
-  FRM := TFRMWalletKeys.Create(parentForm);
-  Try
-    FRM.WalletKeys := FWalletKeys;
-    FRM.ShowModal;
-  Finally
-    FRM.Free;
-  End;
-end;
-
 class procedure TUserInterface.ShowSeedNodesDialog(parentForm : TForm);
 class procedure TUserInterface.ShowSeedNodesDialog(parentForm : TForm);
 Var FRM : TFRMNodesIp;
 Var FRM : TFRMNodesIp;
 begin
 begin
@@ -515,12 +475,12 @@ class procedure TUserInterface.ShowPrivateKeysDialog(parentForm: TForm);
 Var FRM : TFRMWalletKeys;
 Var FRM : TFRMWalletKeys;
 begin
 begin
   FRM := TFRMWalletKeys.Create(parentForm);
   FRM := TFRMWalletKeys.Create(parentForm);
-  Try
-    FRM.WalletKeys := FWalletKeys;
+  try
+    //FRM.WalletKeys := FWalletKeys;
     FRM.ShowModal;
     FRM.ShowModal;
-  Finally
+  finally
     FRM.Free;
     FRM.Free;
-  End;
+  end;
 end;
 end;
 
 
 class procedure TUserInterface.ShowMemoText(parentForm: TForm; const ATitle : AnsiString; text : TStrings);
 class procedure TUserInterface.ShowMemoText(parentForm: TForm; const ATitle : AnsiString; text : TStrings);
@@ -536,40 +496,63 @@ begin
   end;
   end;
 end;
 end;
 
 
-class procedure TUserInterface.ChangeWalletPassword(parentForm: TForm; walletKeys : TWalletKeys);
-Var s,s2 : String;
+class procedure TUserInterface.ChangeWalletPassword(parentForm: TForm);
+var
+  s,s2 : String;
+  locked : boolean;
 begin
 begin
-  if walletKeys = nil then walletKeys := FWalletKeys;
   s := ''; s2 := '';
   s := ''; s2 := '';
-  if Not InputQuery('Change password','Enter new password',s) then exit;
-  if trim(s)<>s then raise Exception.Create('Password cannot start or end with a space character');
-  if Not InputQuery('Change password','Enter new password again',s2) then exit;
-  if s<>s2 then raise Exception.Create('Two passwords are different!');
-
-  walletKeys.WalletPassword := s;
-  Application.MessageBox(PChar('Password changed!'+#10+#10+
-    'Please note that your new password is "'+s+'"'+#10+#10+
-    '(If you lose this password, you will lose your wallet forever!)'),
-    PChar(Application.Title),MB_ICONWARNING+MB_OK);
-end;
-
-class procedure TUserInterface.UnlockWallet(parentForm: TForm; walletKeys : TWalletKeys);
+  locked := (NOT TWallet.Keys.HasPassword) OR (NOT TWallet.Keys.IsValidPassword);
+  if Not AskEnterProtectedString(parentForm, 'Change password','Enter new password',s)
+    then exit;
+  if trim(s)<>s then
+    raise Exception.Create('Password cannot start or end with a space character');
+  if Not AskEnterProtectedString(parentForm, 'Change password', 'Enter new password again',s2)
+    then exit;
+  if s<>s2 then
+    raise Exception.Create('Two passwords are different!');
+  TWallet.Keys.WalletPassword := s;
+  if locked then
+    TWallet.Keys.LockWallet;
+
+  ShowWarning(parentform,
+  'Password Changed',
+  'Your password has been changed.' + #10+#10 +
+  'Please ensure you remember your password.'+#10+
+  'If you lose your password your accounts and funds will be lost forever.');
+end;
+
+class procedure TUserInterface.UnlockWallet(parentForm: TForm);
 Var s : String;
 Var s : String;
 begin
 begin
-  if walletKeys = nil then walletKeys := FWalletKeys;
   s := '';
   s := '';
   Repeat
   Repeat
-    if Not InputQuery('Wallet password','Enter wallet password',s) then exit;
-    walletKeys.WalletPassword := s;
-    if Not walletKeys.IsValidPassword then Application.MessageBox(PChar('Invalid password'),PChar(Application.Title),MB_ICONERROR+MB_OK);
-  Until walletKeys.IsValidPassword;
-  //UpdateWalletKeys;
+    if Not AskEnterProtectedString(parentForm, 'Wallet password','Enter wallet password',s) then exit;
+    TWallet.Keys.WalletPassword := s;
+    if Not TWallet.Keys.IsValidPassword then
+      ShowError(parentForm, 'Invalid Password', 'The password you have entered is incorrect.');
+  Until TWallet.Keys.IsValidPassword;
 end;
 end;
 
 
-class function TUserInterface.AskQuestion(parentForm: TForm; const ACaption, APrompt : String; buttons: TMsgDlgButtons) : TMsgDlgBtn;
+class procedure TUserInterface.ShowInfo(parentForm : TForm; const ACaption, APrompt : String);
+begin
+  MessageDlg(ACaption, APrompt, mtInformation, [mbOK], 0, mbOK);
+end;
+
+class procedure TUserInterface.ShowWarning(parentForm : TForm; const ACaption, APrompt : String);
+begin
+  MessageDlg(ACaption, APrompt, mtWarning, [mbOK], 0, mbOK);
+end;
+
+class procedure TUserInterface.ShowError(parentForm : TForm; const ACaption, APrompt : String);
+begin
+  MessageDlg(ACaption, APrompt, mtError, [mbOK], 0, mbOK);
+end;
+
+class function TUserInterface.AskQuestion(parentForm: TForm; AType:TMsgDlgType; const ACaption, APrompt : String; buttons: TMsgDlgButtons) : TMsgDlgBtn;
 var modalResult : TModalResult;
 var modalResult : TModalResult;
 begin
 begin
-  modalResult := MessageDlg(ACaption, APrompt, mtConfirmation, Buttons, 0, mbNo);
+  modalResult := MessageDlg(ACaption, APrompt, AType, Buttons, 0, mbNo);
   case modalResult of
   case modalResult of
     mrYes: Result := mbYes;
     mrYes: Result := mbYes;
     mrNo: Result := mbNo;
     mrNo: Result := mbNo;
@@ -586,11 +569,16 @@ begin
   end;
   end;
 end;
 end;
 
 
-class function TUserInterface.AskUserEnterString(parentForm: TForm; const ACaption, APrompt : String; var Value : String) : Boolean;
+class function TUserInterface.AskEnterString(parentForm: TForm; const ACaption, APrompt : String; var Value : String) : Boolean;
 begin
 begin
   Result := InputQuery(ACaption, APrompt, Value);
   Result := InputQuery(ACaption, APrompt, Value);
 end;
 end;
 
 
+class function TUserInterface.AskEnterProtectedString(parentForm: TForm; const ACaption, APrompt : String; var Value : String) : Boolean;
+begin
+  Result := InputQuery(ACaption, APrompt, true, Value);
+end;
+
 {%endregion}
 {%endregion}
 
 
 {%region Show Forms}
 {%region Show Forms}
@@ -732,41 +720,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-class function TUserInterface.GetAccountKeyForMiner: TAccountKey;
-Var PK : TECPrivateKey;
-  i : Integer;
-  PublicK : TECDSA_Public;
-begin
-  Result := CT_TECDSA_Public_Nul;
-  if Not Assigned(FWalletKeys) then exit;
-  if Not Assigned(FAppParams) then exit;
-  case FMinerPrivateKeyType of
-    mpk_NewEachTime: PublicK := CT_TECDSA_Public_Nul;
-    mpk_Selected: begin
-      PublicK := TAccountComp.RawString2Accountkey(FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].GetAsString(''));
-    end;
-  else
-    // Random
-    PublicK := CT_TECDSA_Public_Nul;
-    if FWalletKeys.Count>0 then PublicK := FWalletKeys.Key[Random(FWalletKeys.Count)].AccountKey;
-  end;
-  i := FWalletKeys.IndexOfAccountKey(PublicK);
-  if i>=0 then begin
-    if (FWalletKeys.Key[i].CryptedKey='') then i:=-1;
-  end;
-  if i<0 then begin
-    PK := TECPrivateKey.Create;
-    try
-      PK.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
-      FWalletKeys.AddPrivateKey('New for miner '+DateTimeToStr(Now), PK);
-      PublicK := PK.PublicKey;
-    finally
-      PK.Free;
-    end;
-  end;
-  Result := PublicK;
-end;
-
 class procedure TUserInterface.RefreshConnectionStatusDisplay;
 class procedure TUserInterface.RefreshConnectionStatusDisplay;
 var errors : AnsiString;
 var errors : AnsiString;
 begin
 begin
@@ -791,49 +744,8 @@ end;
 
 
 {%endregion}
 {%endregion}
 
 
-{%region Auxillary methods}
-
-class procedure TUserInterface.SaveAppParams;
-Var ms : TMemoryStream;
-  s : AnsiString;
-begin
-  // Disabled in V2 (Herman)
-  FAppParams.ParamByName[CT_PARAM_GridAccountsStream].SetAsString('');
-  //ms := TMemoryStream.Create;
-  //Try
-  //  AccountExplorer.AccountsGrid.SaveToStream(ms);
-  //  ms.Position := 0;
-  //  setlength(s,ms.Size);
-  //  ms.ReadBuffer(s[1],ms.Size);
-  //  FAppParams.ParamByName[CT_PARAM_GridAccountsStream].SetAsString(s);
-  //Finally
-  //  ms.Free;
-  //End;
-end;
 
 
-class procedure TUserInterface.LoadAppParams;
-Var
-  s : AnsiString;
-  fvi : TFileVersionInfo;
-begin
-  // Disabled in V2 (HS)
-  //ms := TMemoryStream.Create;
-  //Try
-  //  s := FAppParams.ParamByName[CT_PARAM_GridAccountsStream].GetAsString('');
-  //  ms.WriteBuffer(s[1],length(s));
-  //  ms.Position := 0;
-  //  // Disabled on V2: FAccountsGrid.LoadFromStream(ms);
-  //Finally
-  //  ms.Free;
-  //End;
-  If FAppParams.FindParam(CT_PARAM_MinerName)=Nil then begin
-    // New configuration... assigning a new random value
-    fvi := TFolderHelper.GetTFileVersionInfo(Application.ExeName);
-    FAppParams.ParamByName[CT_PARAM_MinerName].SetAsString('New Node '+DateTimeToStr(Now)+' - '+
-      fvi.InternalName+' Build:'+fvi.FileVersion);
-  end;
-  NotifyConfigChanged;
-end;
+{%region Auxillary methods}
 
 
 class procedure TUserInterface.SetMainFormMode(AMode: TFRMMainFormMode);
 class procedure TUserInterface.SetMainFormMode(AMode: TFRMMainFormMode);
 begin
 begin
@@ -850,42 +762,6 @@ begin
   Result := FMainForm.Mode;
   Result := FMainForm.Mode;
 end;
 end;
 
 
-class procedure TUserInterface.NotifyConfigChanged;
-Var wa : Boolean;
-  i : Integer;
-begin
-  if FAppParams.ParamByName[CT_PARAM_SaveLogFiles].GetAsBoolean(false) then begin
-    if FAppParams.ParamByName[CT_PARAM_SaveDebugLogs].GetAsBoolean(false) then FLog.SaveTypes := CT_TLogTypes_ALL
-    else FLog.SaveTypes := CT_TLogTypes_DEFAULT;
-    FLog.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'PascalCointWallet.log';
-  end else begin
-    FLog.SaveTypes := [];
-    FLog.FileName := '';
-  end;
-  if Assigned(FNode) then begin
-    wa := FNode.NetServer.Active;
-    FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
-    FNode.NetServer.Active := wa;
-    FNode.Operations.BlockPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
-    FNode.NodeLogFilename := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'blocks.log';
-  end;
-  if Assigned(FPoolMiningServer) then begin
-    if FPoolMiningServer.Port<>FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port) then begin
-      FPoolMiningServer.Active := false;
-      FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
-    end;
-    FPoolMiningServer.Active :=FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
-    FPoolMiningServer.UpdateAccountAndPayload(GetAccountKeyForMiner,FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString(''));
-  end;
-  if Assigned(FRPCServer) then begin
-    FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
-    FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
-  end;
-  i := FAppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].GetAsInteger(Integer(mpk_Random));
-  if (i>=Integer(Low(TMinerPrivatekey))) And (i<=Integer(High(TMinerPrivatekey))) then FMinerPrivateKeyType := TMinerPrivateKey(i)
-  else FMinerPrivateKeyType := mpk_Random;
-end;
-
 class procedure TUserInterface.SetStatusBar0Text(const text : AnsiString); static;
 class procedure TUserInterface.SetStatusBar0Text(const text : AnsiString); static;
 begin
 begin
   FStatusBar0Text := text;
   FStatusBar0Text := text;
@@ -921,6 +797,41 @@ end;
 
 
 {%region Handlers -- TODO: many need to be refactored out with TNotifyManyEvent}
 {%region Handlers -- TODO: many need to be refactored out with TNotifyManyEvent}
 
 
+class procedure TUserInterface.OnSettingsChanged(Sender: TObject);
+Var wa : Boolean;
+  i : Integer;
+begin
+  if TSettings.SaveLogFiles then begin
+    if TSettings.SaveDebugLogs then
+      FLog.SaveTypes := CT_TLogTypes_ALL
+    else
+      FLog.SaveTypes := CT_TLogTypes_DEFAULT;
+    FLog.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'PascalCointWallet.log';
+  end else begin
+    FLog.SaveTypes := [];
+    FLog.FileName := '';
+  end;
+  if Assigned(FNode) then begin
+    wa := FNode.NetServer.Active;
+    FNode.NetServer.Port := TSettings.InternetServerPort;
+    FNode.NetServer.Active := wa;
+    FNode.Operations.BlockPayload := TSettings.MinerName;
+    FNode.NodeLogFilename := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'blocks.log';
+  end;
+  if Assigned(FPoolMiningServer) then begin
+    if FPoolMiningServer.Port <> TSettings.MinerServerRpcPort then begin
+      FPoolMiningServer.Active := false;
+      FPoolMiningServer.Port := TSettings.MinerServerRpcPort;
+    end;
+    FPoolMiningServer.Active :=TSettings.MinerServerRpcActive;
+    FPoolMiningServer.UpdateAccountAndPayload(TWallet.MiningKey, TSettings.MinerName);
+  end;
+  if Assigned(FRPCServer) then begin
+    FRPCServer.Active := TSettings.RpcPortEnabled;
+    FRPCServer.ValidIPs := TSettings.RpcAllowedIPs;
+  end;
+end;
+
 class procedure TUserInterface.OnAccountsChanged(Sender: TObject);
 class procedure TUserInterface.OnAccountsChanged(Sender: TObject);
 begin
 begin
   FUILock.Acquire;
   FUILock.Acquire;
@@ -976,7 +887,7 @@ begin
     if (s<>'') then s := s+';';
     if (s<>'') then s := s+';';
     s := s + nsarr[i].ip+':'+IntToStr( nsarr[i].port );
     s := s + nsarr[i].ip+':'+IntToStr( nsarr[i].port );
   end;
   end;
-  FAppParams.ParamByName[CT_PARAM_PeerCache].SetAsString(s);
+  TSettings.PeerCache := s;
   TNode.Node.PeerCache := s;
   TNode.Node.PeerCache := s;
 end;
 end;
 
 
@@ -1038,7 +949,7 @@ end;
 class procedure TUserInterface.OnMiningServerNewBlockFound(Sender: TObject);
 class procedure TUserInterface.OnMiningServerNewBlockFound(Sender: TObject);
 begin
 begin
   // No lock required
   // No lock required
-  FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
+  FPoolMiningServer.MinerAccountKey := TWallet.MiningKey;
 end;
 end;
 
 
 class procedure TUserInterface.OnTimerUpdateStatusTimer(Sender: TObject);
 class procedure TUserInterface.OnTimerUpdateStatusTimer(Sender: TObject);

+ 92 - 0
Units/Forms/Wizards/UWIZAddKey.pas

@@ -0,0 +1,92 @@
+unit UWIZAddKey;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, UWizard;
+
+type
+
+  { TFRMAddKeyModel }
+  TWIZAddKeyAction = (akaGenerateKey, akaImportPrivateKey, akaImportPublicKey);
+  TWIZAddKeyModel = class(TComponent)
+    public
+      Name : String;
+      KeyText : String;
+      Password : String;
+      EncryptionTypeNID : word;
+      Action : TWIZAddKeyAction;
+  end;
+
+  { TWIZAddKeyWizard }
+
+  TWIZAddKeyWizard = class(TWizard<TWIZAddKeyModel>)
+    public
+      constructor Create(AOwner: TComponent); override;
+      function DetermineHasNext : boolean; override;
+      function DetermineHasPrevious : boolean;  override;
+      function FinishRequested(out message : AnsiString) : boolean; override;
+      function CancelRequested(out message : AnsiString) : boolean; override;
+  end;
+
+implementation
+
+uses
+  UCrypto,
+  UWallet,
+  UWIZAddKey_Start,
+  UWIZAddKey_GenerateOrImport,
+  UWIZAddKey_ImportPubKey,
+  UWIZAddKey_ImportPrivKey,
+  UWIZAddKey_EnterName;
+
+constructor TWIZAddKeyWizard.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner, [TWIZAddKey_Start, TWIZAddKey_EnterName]);
+  TitleText := 'Add Key';
+  FinishText := 'Add Key';
+end;
+
+function TWIZAddKeyWizard.DetermineHasNext : boolean;
+begin
+  Result := NOT (CurrentScreen is TWIZAddKey_EnterName);
+end;
+
+function TWIZAddKeyWizard.DetermineHasPrevious : boolean;
+begin
+  Result := inherited DetermineHasPrevious;
+end;
+
+function TWIZAddKeyWizard.FinishRequested(out message : AnsiString) : boolean;
+begin
+  // Execute the key addition here
+  try
+    Result := true;
+    case Model.Action of
+      akaGenerateKey: TWallet.GenerateNewKey(Model.Name, Model.EncryptionTypeNID);
+      akaImportPrivateKey: TWallet.ImportPrivateKey(Model.Name, Model.KeyText, Model.Password);
+      akaImportPublicKey: TWallet.ImportPublicKey(Model.Name, Model.KeyText);
+    end;
+  except
+      On E:Exception do begin
+        Result := false;
+        message := E.ToString;
+      end;
+  end;
+end;
+
+function TWIZAddKeyWizard.CancelRequested(out message : AnsiString) : boolean;
+begin
+  Result := true;
+end;
+
+end.
+

+ 28 - 0
Units/Forms/Wizards/UWIZAddKey_EnterName.lfm

@@ -0,0 +1,28 @@
+object WIZAddKey_EnterName: TWIZAddKey_EnterName
+  Left = -665
+  Height = 100
+  Top = 643
+  Width = 334
+  Caption = 'WIZAddKey_EnterName'
+  ClientHeight = 100
+  ClientWidth = 334
+  LCLVersion = '1.6.4.0'
+  object Label2: TLabel
+    Left = 17
+    Height = 15
+    Top = 16
+    Width = 130
+    Caption = 'Enter a name for this key'
+    ParentColor = False
+    WordWrap = True
+  end
+  object txtName: TEdit
+    Left = 17
+    Height = 23
+    Top = 40
+    Width = 299
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    TabOrder = 0
+  end
+end

+ 55 - 0
Units/Forms/Wizards/UWIZAddKey_EnterName.pas

@@ -0,0 +1,55 @@
+unit UWIZAddKey_EnterName;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, UWizard, UWIZAddKey;
+
+type
+
+  { TWIZAddKey_EnterName }
+
+  TWIZAddKey_EnterName = class(TWizardForm<TWIZAddKeyModel>)
+    txtName: TEdit;
+    Label2: TLabel;
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+    function Validate(out message : AnsiString) : boolean; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+{ TWIZAddKey_EnterName }
+
+procedure TWIZAddKey_EnterName.OnPresent;
+begin
+  txtName.Clear;
+  txtName.SetFocus;
+end;
+
+procedure TWIZAddKey_EnterName.OnNext;
+begin
+  Model.Name := Trim(txtName.Text);
+end;
+
+function TWIZAddKey_EnterName.Validate(out message : AnsiString) : boolean;
+begin
+  Result := Length(Trim(txtName.Text)) > 0;
+  if not result then
+    message := 'Name is empty or whitespace';
+end;
+
+end.
+

+ 65 - 0
Units/Forms/Wizards/UWIZAddKey_GenerateOrImport.lfm

@@ -0,0 +1,65 @@
+object WIZAddKey_GenerateOrImport: TWIZAddKey_GenerateOrImport
+  Left = 500
+  Height = 285
+  Top = 383
+  Width = 448
+  Caption = 'Add Key'
+  ClientHeight = 285
+  ClientWidth = 448
+  LCLVersion = '1.6.4.0'
+  object rbPrivateKey: TRadioButton
+    Left = 32
+    Height = 19
+    Top = 56
+    Width = 175
+    Caption = 'Generate a new private key'
+    Checked = True
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 0
+    TabStop = True
+  end
+  object rbPublicKey: TRadioButton
+    Left = 32
+    Height = 19
+    Top = 168
+    Width = 188
+    Caption = 'Import an existing private key'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 1
+  end
+  object Label1: TLabel
+    Left = 32
+    Height = 32
+    Top = 16
+    Width = 370
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'How will the private key be added into your wallet?'
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label2: TLabel
+    Left = 52
+    Height = 64
+    Top = 80
+    Width = 352
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Use this option to generate a brand new private key which will only exist on your machine. You will then be able to export this key and import it into other machines.'
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label3: TLabel
+    Left = 48
+    Height = 66
+    Top = 192
+    Width = 350
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Use this option to import a private key that you have exported from another wallet.'
+    ParentColor = False
+    WordWrap = True
+  end
+end

+ 49 - 0
Units/Forms/Wizards/UWIZAddKey_GenerateOrImport.pas

@@ -0,0 +1,49 @@
+unit UWIZAddKey_GenerateOrImport;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  UWizard, UWIZAddKey;
+
+type
+
+  { TWIZAddKey_GenerateOrImport }
+
+  TWIZAddKey_GenerateOrImport = class(TWizardForm<TWIZAddKeyModel>)
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    rbPrivateKey: TRadioButton;
+    rbPublicKey: TRadioButton;
+  public
+    procedure OnNext; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+uses UWIZAddKey_ImportPrivKey, UWIZAddKey_SelectEncryption, UWIZAddKey_EnterName;
+
+procedure TWIZAddKey_GenerateOrImport.OnNext;
+begin
+  if rbPrivateKey.Checked then begin
+    Model.Action := akaGenerateKey;
+    UpdatePath(ptReplaceAllNext, [TWIZAddKey_SelectEncryption, TWIZAddKey_EnterName])
+  end else begin
+    Model.Action := akaImportPrivateKey;
+    UpdatePath(ptReplaceAllNext, [TWIZAddKey_ImportPrivKey, TWIZAddKey_EnterName])
+  end;
+end;
+
+end.
+

+ 51 - 0
Units/Forms/Wizards/UWIZAddKey_ImportPrivKey.lfm

@@ -0,0 +1,51 @@
+object WIZAddKey_ImportPrivKey: TWIZAddKey_ImportPrivKey
+  Left = -679
+  Height = 225
+  Top = 316
+  Width = 438
+  Caption = 'WIZAddKey_ImportPrivKey'
+  ClientHeight = 225
+  ClientWidth = 438
+  LCLVersion = '1.6.4.0'
+  object Label1: TLabel
+    Left = 32
+    Height = 32
+    Top = 16
+    Width = 362
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Enter the encrypted private key that you have exported from another wallet. '
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label2: TLabel
+    Left = 25
+    Height = 24
+    Top = 160
+    Width = 362
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Enter the password used to encrypt the key when it was exported.'
+    ParentColor = False
+    WordWrap = True
+  end
+  object txtPassword: TEdit
+    Left = 24
+    Height = 23
+    Top = 184
+    Width = 386
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    EchoMode = emPassword
+    PasswordChar = '*'
+    TabOrder = 1
+  end
+  object txtPrivateKey: TMemo
+    Left = 24
+    Height = 88
+    Top = 56
+    Width = 385
+    Anchors = [akTop, akLeft, akRight]
+    TabOrder = 0
+  end
+end

+ 66 - 0
Units/Forms/Wizards/UWIZAddKey_ImportPrivKey.pas

@@ -0,0 +1,66 @@
+unit UWIZAddKey_ImportPrivKey;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  UWizard, UWIZAddKey;
+
+type
+
+  { TWIZAddKey_ImportPrivKey }
+
+  TWIZAddKey_ImportPrivKey = class(TWizardForm<TWIZAddKeyModel>)
+    txtPassword: TEdit;
+    Label1: TLabel;
+    Label2: TLabel;
+    txtPrivateKey: TMemo;
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+    function Validate(out message : AnsiString) : boolean; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+uses UCrypto, UWallet;
+
+{ TWIZAddKey_ImportPrivKey }
+
+procedure TWIZAddKey_ImportPrivKey.OnPresent;
+begin
+  txtPrivateKey.Clear;
+  txtPassword.Clear;
+  txtPrivateKey.SetFocus;
+end;
+
+procedure TWIZAddKey_ImportPrivKey.OnNext;
+begin
+  Model.KeyText := txtPrivateKey.Text;
+  Model.Password := txtPassword.Text;
+end;
+
+function TWIZAddKey_ImportPrivKey.Validate(out message : AnsiString) : boolean;
+var
+  privateKey : TECPrivateKey;
+begin
+  try
+    Result := TWallet.TryDecryptPrivateKey(txtPrivateKey.Text, txtPassword.Text, privateKey, message);
+  finally
+    if Assigned(privateKey) then
+      privateKey.Free;
+  end;
+end;
+
+end.
+

+ 29 - 0
Units/Forms/Wizards/UWIZAddKey_ImportPubKey.lfm

@@ -0,0 +1,29 @@
+object WIZAddKey_ImportPubKey: TWIZAddKey_ImportPubKey
+  Left = -722
+  Height = 253
+  Top = 31
+  Width = 429
+  Caption = 'WIZAddKey_ImportPubKey'
+  ClientHeight = 253
+  ClientWidth = 429
+  LCLVersion = '1.6.4.0'
+  object Label1: TLabel
+    Left = 32
+    Height = 32
+    Top = 16
+    Width = 370
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Enter the public key either in the PascalCoin encoding format or raw hex format.'
+    ParentColor = False
+    WordWrap = True
+  end
+  object txtPublicKey: TMemo
+    Left = 24
+    Height = 160
+    Top = 56
+    Width = 379
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    TabOrder = 0
+  end
+end

+ 59 - 0
Units/Forms/Wizards/UWIZAddKey_ImportPubKey.pas

@@ -0,0 +1,59 @@
+unit UWIZAddKey_ImportPubKey;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  UWizard, UWIZAddKey;
+
+type
+
+  { TWIZAddKey_ImportPubKey }
+
+  TWIZAddKey_ImportPubKey = class(TWizardForm<TWIZAddKeyModel>)
+    Label1: TLabel;
+    txtPublicKey: TMemo;
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+    function Validate(out message : AnsiString) : boolean; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts;
+
+{ TWIZAddKey_ImportPubKey }
+
+
+procedure TWIZAddKey_ImportPubKey.OnPresent;
+begin
+  txtPublicKey.Clear;
+  txtPublicKey.SetFocus;
+end;
+
+procedure TWIZAddKey_ImportPubKey.OnNext;
+begin
+  Model.KeyText := txtPublicKey.Text;
+end;
+
+function TWIZAddKey_ImportPubKey.Validate(out message : AnsiString) : boolean;
+var
+  accountKey : TAccountKey;
+begin
+   Result := TAccountComp.AccountPublicKeyImport(txtPublicKey.Text, accountKey, message);
+end;
+
+end.
+

+ 33 - 0
Units/Forms/Wizards/UWIZAddKey_SelectEncryption.lfm

@@ -0,0 +1,33 @@
+object WIZAddKey_SelectEncryption: TWIZAddKey_SelectEncryption
+  Left = -1207
+  Height = 240
+  Top = 90
+  Width = 320
+  Caption = 'WIZAddKey_SelectEncryption'
+  ClientHeight = 240
+  ClientWidth = 320
+  OnCreate = FormCreate
+  LCLVersion = '1.6.4.0'
+  object rgKeyType: TRadioGroup
+    Left = 24
+    Height = 209
+    Top = 16
+    Width = 278
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    AutoFill = True
+    Caption = 'Select the type of encryption:'
+    ChildSizing.LeftRightSpacing = 6
+    ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
+    ChildSizing.EnlargeVertical = crsHomogenousChildResize
+    ChildSizing.ShrinkHorizontal = crsScaleChilds
+    ChildSizing.ShrinkVertical = crsScaleChilds
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 1
+    ClientHeight = 189
+    ClientWidth = 274
+    Items.Strings = (
+      'asdf'
+    )
+    TabOrder = 0
+  end
+end

+ 62 - 0
Units/Forms/Wizards/UWIZAddKey_SelectEncryption.pas

@@ -0,0 +1,62 @@
+unit UWIZAddKey_SelectEncryption;
+
+{$mode delphi}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, UWizard, UWIZAddKey;
+
+type
+
+  { TWIZAddKey_SelectEncryption }
+
+  TWIZAddKey_SelectEncryption = class(TWizardForm<TWIZAddKeyModel>)
+    rgKeyType: TRadioGroup;
+    procedure FormCreate(Sender: TObject);
+  public
+    procedure OnNext; override;
+    function Validate(out message : AnsiString) : boolean; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts;
+
+{ TWIZAddKey_SelectEncryption }
+
+procedure TWIZAddKey_SelectEncryption.FormCreate(Sender: TObject);
+var
+  i : Integer;
+  availableEncryptionTypes : TList;
+begin
+  rgKeyType.Items.Clear;
+  availableEncryptionTypes := TList.Create;
+  try
+    TAccountComp.ValidsEC_OpenSSL_NID(availableEncryptionTypes);
+    for i := 0 to availableEncryptionTypes.Count - 1 do begin
+      rgKeyType.Items.AddObject(TAccountComp.GetECInfoTxt(PtrInt(availableEncryptionTypes[i])),availableEncryptionTypes[i]);
+    end;
+  finally
+    availableEncryptionTypes.free;
+  end;
+end;
+
+procedure TWIZAddKey_SelectEncryption.OnNext;
+begin
+  Self.Model.EncryptionTypeNID := PtrInt(rgKeyType.Items.Objects[rgKeyType.ItemIndex]);
+end;
+
+function TWIZAddKey_SelectEncryption.Validate(out message : AnsiString) : boolean;
+begin
+  Result := true;
+  if rgKeyType.ItemIndex < 0 then begin
+    message := 'A type of encryption must be selected';
+    Result := false;
+  end;
+end;
+
+end.
+

+ 65 - 0
Units/Forms/Wizards/UWIZAddKey_Start.lfm

@@ -0,0 +1,65 @@
+object WIZAddKey_Start: TWIZAddKey_Start
+  Left = 26
+  Height = 300
+  Top = 27
+  Width = 437
+  Caption = 'Add Key'
+  ClientHeight = 300
+  ClientWidth = 437
+  LCLVersion = '1.6.4.0'
+  object rbPrivateKey: TRadioButton
+    Left = 32
+    Height = 19
+    Top = 56
+    Width = 84
+    Caption = 'Private Key'
+    Checked = True
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 1
+    TabStop = True
+  end
+  object rbPublicKey: TRadioButton
+    Left = 32
+    Height = 19
+    Top = 168
+    Width = 144
+    Caption = 'Watch-only Public Key'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 0
+  end
+  object Label1: TLabel
+    Left = 32
+    Height = 32
+    Top = 16
+    Width = 370
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'What type of key would you like to add into your wallet?'
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label2: TLabel
+    Left = 52
+    Height = 64
+    Top = 80
+    Width = 352
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Adding a private key allows you to send operations from accounts bound to this key. Please ensure your wallet is adequately protected if using this option since sensitive information is stored on your machine.'
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label3: TLabel
+    Left = 48
+    Height = 66
+    Top = 192
+    Width = 350
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'A watch-only key allows you to track accounts that are bound to this key but without the ability to authorize new operations. There is no sensitive information kept on your machine when using this option.'
+    ParentColor = False
+    WordWrap = True
+  end
+end

+ 55 - 0
Units/Forms/Wizards/UWIZAddKey_Start.pas

@@ -0,0 +1,55 @@
+unit UWIZAddKey_Start;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  UWizard, UWIZAddKey;
+
+type
+
+  { TWIZAddKey_Start }
+
+  TWIZAddKey_Start = class(TWizardForm<TWIZAddKeyModel>)
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    rbPrivateKey: TRadioButton;
+    rbPublicKey: TRadioButton;
+  private
+    { private declarations }
+  public
+    { public declarations }
+    procedure OnNext; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+uses
+   UWIZAddKey_GenerateOrImport, UWIZAddKey_ImportPrivKey, UWIZAddKey_ImportPubKey, UWIZAddKey_EnterName;
+
+{ TWIZAddKey_Start }
+
+
+procedure TWIZAddKey_Start.OnNext;
+begin
+  if rbPublicKey.Checked = true then begin
+    Model.Action := akaImportPublicKey;
+    UpdatePath(ptReplaceAllNext, [TWIZAddKey_ImportPubKey, TWIZAddKey_EnterName]);
+  end else begin
+    UpdatePath(ptReplaceAllNext, [TWIZAddKey_GenerateOrImport, TWIZAddKey_ImportPrivKey]);//, TWIZAddKey_ImportPrivKey, TWIZAddKey_Finish]);
+  end;
+end;
+
+end.
+

+ 0 - 23
Units/PascalCoin/UConst.pas

@@ -141,29 +141,6 @@ Const
 
 
   CT_MAX_Operations_per_block_by_miner =  {$IFDEF PRODUCTION}10000{$ELSE}{$IFDEF TESTNET}50000{$ELSE}{$ENDIF}{$ENDIF};
   CT_MAX_Operations_per_block_by_miner =  {$IFDEF PRODUCTION}10000{$ELSE}{$IFDEF TESTNET}50000{$ELSE}{$ENDIF}{$ENDIF};
 
 
-  // App Params
-  CT_PARAM_GridAccountsStream = 'GridAccountsStreamV2';
-  CT_PARAM_GridAccountsPos = 'GridAccountsPos';
-  CT_PARAM_DefaultFee = 'DefaultFee';
-  CT_PARAM_InternetServerPort = 'InternetServerPort';
-  {$IFDEF TESTNET}CT_PARAM_AutomaticMineWhenConnectedToNodes = 'AutomaticMineWhenConnectedToNodes';{$ENDIF}
-  CT_PARAM_MinerPrivateKeyType = 'MinerPrivateKeyType';
-  CT_PARAM_MinerPrivateKeySelectedPublicKey = 'MinerPrivateKeySelectedPublicKey';
-  CT_PARAM_SaveLogFiles = 'SaveLogFiles';
-  CT_PARAM_SaveDebugLogs = 'SaveDebugLogs';
-  CT_PARAM_ShowLogs = 'ShowLogs';
-  CT_PARAM_MinerName = 'MinerName';
-  CT_PARAM_FirstTime = 'FirstTime';
-  CT_PARAM_ShowModalMessages = 'ShowModalMessages';
-  {$IFDEF TESTNET}CT_PARAM_MaxCPUs = 'MaxCPUs'; {$ENDIF} //deprecated
-  CT_PARAM_PeerCache = 'PeerCache';
-  CT_PARAM_TryToConnectOnlyWithThisFixedServers = 'TryToConnectOnlyWithFixedServers';
-  CT_PARAM_JSONRPCMinerServerPort = 'JSONRPCMinerServerPort';
-  CT_PARAM_JSONRPCMinerServerActive = 'JSONRPCMinerServerActive';
-  CT_PARAM_JSONRPCEnabled = 'JSONRPCEnabled';
-  CT_PARAM_JSONRPCAllowedIPs = 'JSONRPCAllowedIPs';
-
-
 
 
 implementation
 implementation
 
 

+ 43 - 17
Units/PascalCoin/UCrypto.pas

@@ -37,6 +37,7 @@ Type
      EC_OpenSSL_NID : Word;
      EC_OpenSSL_NID : Word;
      x: TRawBytes;
      x: TRawBytes;
      y: TRawBytes;
      y: TRawBytes;
+     class operator = (const a,b : TECDSA_Public) : boolean;
   end;
   end;
   PECDSA_Public = ^TECDSA_Public;
   PECDSA_Public = ^TECDSA_Public;
 
 
@@ -61,24 +62,25 @@ Type
     class Function ImportFromRaw(Const raw : TRawBytes) : TECPrivateKey; static;
     class Function ImportFromRaw(Const raw : TRawBytes) : TECPrivateKey; static;
   End;
   End;
 
 
-  TCrypto = Class
+  TCrypto = class
   private
   private
   public
   public
-    Class function ToHexaString(const raw : TRawBytes) : AnsiString;
-    Class function HexaToRaw(const HexaString : AnsiString) : TRawBytes;
-    Class function DoSha256(p : PAnsiChar; plength : Cardinal) : TRawBytes; overload;
-    Class function DoSha256(const TheMessage : AnsiString) : TRawBytes; overload;
-    Class procedure DoDoubleSha256(p : PAnsiChar; plength : Cardinal; Var ResultSha256 : TRawBytes); overload;
-    Class function DoRipeMD160_HEXASTRING(const TheMessage : AnsiString) : TRawBytes; overload;
-    Class function DoRipeMD160AsRaw(p : PAnsiChar; plength : Cardinal) : TRawBytes; overload;
-    Class function DoRipeMD160AsRaw(const TheMessage : AnsiString) : TRawBytes; overload;
-    Class function PrivateKey2Hexa(Key : PEC_KEY) : AnsiString;
-    Class function ECDSASign(Key : PEC_KEY; const digest : AnsiString) : TECDSA_SIG;
-    Class function ECDSAVerify(EC_OpenSSL_NID : Word; PubKey : EC_POINT; const digest : AnsiString; Signature : TECDSA_SIG) : Boolean; overload;
-    Class function ECDSAVerify(PubKey : TECDSA_Public; const digest : AnsiString; Signature : TECDSA_SIG) : Boolean; overload;
-    Class procedure InitCrypto;
-    Class function IsHumanReadable(Const ReadableText : TRawBytes) : Boolean;
-  End;
+    class function IsHexString(const AHexString: AnsiString) : boolean;
+    class function ToHexaString(const raw : TRawBytes) : AnsiString;
+    class function HexaToRaw(const HexaString : AnsiString) : TRawBytes;
+    class function DoSha256(p : PAnsiChar; plength : Cardinal) : TRawBytes; overload;
+    class function DoSha256(const TheMessage : AnsiString) : TRawBytes; overload;
+    class procedure DoDoubleSha256(p : PAnsiChar; plength : Cardinal; Var ResultSha256 : TRawBytes); overload;
+    class function DoRipeMD160_HEXASTRING(const TheMessage : AnsiString) : TRawBytes; overload;
+    class function DoRipeMD160AsRaw(p : PAnsiChar; plength : Cardinal) : TRawBytes; overload;
+    class function DoRipeMD160AsRaw(const TheMessage : AnsiString) : TRawBytes; overload;
+    class function PrivateKey2Hexa(Key : PEC_KEY) : AnsiString;
+    class function ECDSASign(Key : PEC_KEY; const digest : AnsiString) : TECDSA_SIG;
+    class function ECDSAVerify(EC_OpenSSL_NID : Word; PubKey : EC_POINT; const digest : AnsiString; Signature : TECDSA_SIG) : Boolean; overload;
+    class function ECDSAVerify(PubKey : TECDSA_Public; const digest : AnsiString; Signature : TECDSA_SIG) : Boolean; overload;
+    class procedure InitCrypto;
+    class function IsHumanReadable(const ReadableText : TRawBytes) : Boolean;
+  end;
 
 
   TBigNum = Class
   TBigNum = Class
   private
   private
@@ -126,7 +128,7 @@ Const
 implementation
 implementation
 
 
 uses
 uses
-  ULog, UConst, UAccounts;
+  UAES, ULog, UConst, UAccounts;
 
 
 Var _initialized : Boolean = false;
 Var _initialized : Boolean = false;
 
 
@@ -138,6 +140,16 @@ Begin
   end;
   end;
 End;
 End;
 
 
+{ TECDSA_Public }
+
+class operator TECDSA_Public.= (const a,b : TECDSA_Public) : boolean;
+begin
+  Result :=
+    (a.EC_OpenSSL_NID = b.EC_OpenSSL_NID) AND
+    (a.x = b.x) AND
+    (a.y = b.y);
+end;
+
 { TECPrivateKey }
 { TECPrivateKey }
 
 
 constructor TECPrivateKey.Create;
 constructor TECPrivateKey.Create;
@@ -534,6 +546,20 @@ begin
   end;
   end;
 end;
 end;
 
 
+class function TCrypto.IsHexString(const AHexString: AnsiString) : boolean;
+var
+  i : Integer;
+begin
+  Result := true;
+  for i := Low(AHexString) to High(AHexString) do
+    if (NOT (AHexString[i] in ['0'..'9'])) AND
+       (NOT (AHexString[i] in ['a'..'f'])) AND
+       (NOT (AHexString[i] in ['A'..'F'])) then begin
+       Result := false;
+       exit;
+    end;
+end;
+
 { TBigNum }
 { TBigNum }
 
 
 function TBigNum.Add(BN: TBigNum): TBigNum;
 function TBigNum.Add(BN: TBigNum): TBigNum;

+ 1 - 1
Units/PascalCoin/URPC.pas

@@ -18,7 +18,7 @@ unit URPC;
 interface
 interface
 
 
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
-  UNetProtocol, UOpTransaction, UWalletKeys, UTime, UAES, UECIES,
+  UNetProtocol, UOpTransaction, UWallet, UTime, UAES, UECIES,
   UJSONFunctions, classes, blcksock, synsock, IniFiles, Variants, math;
   UJSONFunctions, classes, blcksock, synsock, IniFiles, Variants, math;
 
 
 Const
 Const

+ 1 - 1
Units/PascalCoin/UServerApp.pas

@@ -17,7 +17,7 @@ uses
   Messages,
   Messages,
   {$ENDIF}
   {$ENDIF}
   SyncObjs,
   SyncObjs,
-  UOpenSSL, UCrypto, UNode, UFileStorage, UFolderHelper, UWalletKeys, UConst, ULog, UNetProtocol,
+  UOpenSSL, UCrypto, UNode, UFileStorage, UFolderHelper, UWallet, UConst, ULog, UNetProtocol,
   URPC;
   URPC;
 
 
 type
 type

+ 339 - 0
Units/PascalCoin/USettings.pas

@@ -0,0 +1,339 @@
+unit USettings;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+{$I ./../PascalCoin/config.inc}
+
+interface
+
+uses
+  UAppParams, UCommon;
+
+type
+
+  { TMinerPrivateKeyType }
+
+  TMinerPrivateKeyType = (mpk_NewEachTime, mpk_Random, mpk_Selected);
+
+  { TSettings }
+
+  TSettings = class
+    private
+      FOnChanged : TNotifyManyEvent; static;
+      FAppParams : TAppParams; static;
+      class function GetInternetServerPort : Integer; static;
+      class procedure SetInternetServerPort(AInt:Integer); static;
+      class function GetRpcPortEnabled : boolean; static;
+      class procedure SetRpcPortEnabled(ABool: boolean); static;
+      class function GetDefaultFee : Int64; static;
+      class procedure SetDefaultFee(AInt64: Int64); static;
+      class function GetMinerPrivateKeyType : TMinerPrivateKeyType; static;
+      class procedure SetMinerPrivateKeyType(AType: TMinerPrivateKeyType); static;
+      class function GetMinerSelectedPrivateKey : string; static;
+      class procedure SetMinerSelectedPrivateKey(AKey:string); static;
+      class function GetMinerServerRpcActive : boolean; static;
+      class procedure SetMinerServerRpcActive(ABool: Boolean); static;
+      class function GetMinerServerRpcPort : Integer; static;
+      class procedure SetMinerServerRpcPort(APort: Integer); static;
+      class function GetSaveLogFiles : boolean; static;
+      class procedure SetSaveLogFiles(ABool: boolean); static;
+      class function GetShowLogs : boolean; static;
+      class procedure SetShowLogs(ABool: boolean); static;
+      class function GetSaveDebugLogs : boolean; static;
+      class procedure SetSaveDebugLogs(ABool: boolean); static;
+      class function GetMinerName : string; static;
+      class procedure SetMinerName(AName: string); static;
+      class function GetRunCount : Integer; static;
+      class procedure SetRunCount(AInt: Integer); static;
+      class function GetShowModalMessages : boolean; static;
+      class procedure SetShowModalMessages(ABool: boolean); static;
+      class function GetRpcAllowedIPs : string; static;
+      class procedure SetRpcAllowedIPs(AString: string); static;
+      class function GetPeerCache : string; static;
+      class procedure SetPeerCache(AString: string); static;
+      class function GetTryConnectOnlyWithThisFixedServers : string; static;
+      class procedure SetTryConnectOnlyWithThisFixedServers(AString: string); static;
+      class procedure CheckLoaded;
+      class procedure NotifyOnChanged;
+    public
+      class procedure Load;
+      class procedure Save;
+      class property OnChanged : TNotifyManyEvent read FOnChanged write FOnChanged;
+      class property InternetServerPort : Integer read GetInternetServerPort write SetInternetServerPort;
+      class property RpcPortEnabled : boolean read GetRpcPortEnabled write SetRpcPortEnabled;
+      class property RpcAllowedIPs : string read GetRpcAllowedIPs write SetRpcAllowedIPs;
+      class property DefaultFee : Int64 read GetDefaultFee write SetDefaultFee;
+      class property MinerPrivateKeyType : TMinerPrivateKeyType read GetMinerPrivateKeyType write SetMinerPrivateKeyType;
+      class property MinerSelectedPrivateKey : string read GetMinerSelectedPrivateKey write SetMinerSelectedPrivateKey;
+      class property MinerServerRpcActive : boolean read GetMinerServerRpcActive write SetMinerServerRpcActive;
+      class property MinerServerRpcPort : Integer read GetMinerServerRpcPort write SetMinerServerRpcPort;
+      class property SaveLogFiles : boolean read GetSaveLogFiles write SetSaveLogFiles;
+      class property ShowLogs : boolean read GetShowLogs write SetShowLogs;
+      class property SaveDebugLogs : boolean read GetSaveDebugLogs write SetSaveDebugLogs;
+      class property MinerName : string read GetMinerName write SetMinerName;
+      class property RunCount : Integer read GetRunCount write SetRunCount;
+      class property ShowModalMessages : boolean read GetShowModalMessages write SetShowModalMessages;
+      class property PeerCache : string read GetPeerCache write SetPeerCache;
+      class property TryConnectOnlyWithThisFixedServers : string read GetTryConnectOnlyWithThisFixedServers write SetTryConnectOnlyWithThisFixedServers;
+      class property AppParams : TAppParams read FAppParams;
+  end;
+
+implementation
+
+uses
+  Classes, SysUtils, UConst, UFolderHelper;
+
+const
+  // App Params
+  CT_PARAM_DefaultFee = 'DefaultFee';
+  CT_PARAM_InternetServerPort = 'InternetServerPort';
+  {$IFDEF TESTNET}CT_PARAM_AutomaticMineWhenConnectedToNodes = 'AutomaticMineWhenConnectedToNodes';{$ENDIF}
+  CT_PARAM_MinerPrivateKeyType = 'MinerPrivateKeyType';
+  CT_PARAM_MinerPrivateKeySelectedPublicKey = 'MinerPrivateKeySelectedPublicKey';
+  CT_PARAM_SaveLogFiles = 'SaveLogFiles';
+  CT_PARAM_SaveDebugLogs = 'SaveDebugLogs';
+  CT_PARAM_ShowLogs = 'ShowLogs';
+  CT_PARAM_MinerName = 'MinerName';
+  CT_PARAM_RunCount = 'RunCount';
+  CT_PARAM_ShowModalMessages = 'ShowModalMessages';
+  {$IFDEF TESTNET}CT_PARAM_MaxCPUs = 'MaxCPUs'; {$ENDIF} //deprecated
+  CT_PARAM_PeerCache = 'PeerCache';
+  CT_PARAM_TryToConnectOnlyWithThisFixedServers = 'TryToConnectOnlyWithFixedServers';
+  CT_PARAM_JSONRPCMinerServerPort = 'JSONRPCMinerServerPort';
+  CT_PARAM_JSONRPCMinerServerActive = 'JSONRPCMinerServerActive';
+  CT_PARAM_JSONRPCEnabled = 'JSONRPCEnabled';
+  CT_PARAM_JSONRPCAllowedIPs = 'JSONRPCAllowedIPs';
+
+{ TSettings }
+
+class procedure TSettings.Load;
+begin
+  FAppParams := TAppParams.Create(nil);
+  FAppParams.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'AppParams.prm';
+end;
+
+class procedure TSettings.Save;
+begin
+  //TODO Update FAppParams to optionally save on set value, and make FApp.Save public and verify all AppParams updates in client code
+end;
+
+class function TSettings.GetInternetServerPort : Integer;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
+end;
+
+class procedure TSettings.SetInternetServerPort(AInt:Integer);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_InternetServerPort].SetAsInteger(AInt);
+end;
+
+class function TSettings.GetRpcPortEnabled : boolean;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
+end;
+
+class procedure TSettings.SetRpcPortEnabled(ABool: boolean);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].SetAsBoolean(ABool);
+end;
+
+class function TSettings.GetRpcAllowedIPs : string;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1;');
+end;
+
+class procedure TSettings.SetRpcAllowedIPs(AString: string);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].SetAsString(AString);
+end;
+
+class function TSettings.GetDefaultFee : Int64;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
+end;
+
+class procedure TSettings.SetDefaultFee(AInt64: Int64);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_DefaultFee].SetAsInt64(AInt64);
+end;
+
+class function TSettings.GetMinerServerRpcActive : boolean;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
+end;
+
+class procedure TSettings.SetMinerServerRpcActive(ABool: Boolean);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].SetAsBoolean(ABool);
+end;
+
+class function TSettings.GetMinerServerRpcPort : Integer;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
+end;
+
+class procedure TSettings.SetMinerServerRpcPort(APort: Integer);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].SetAsInteger(APort)
+end;
+
+class function TSettings.GetMinerPrivateKeyType : TMinerPrivateKeyType;
+begin
+  CheckLoaded;
+  Result := TMinerPrivateKeyType(FAppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].GetAsInteger(Integer(mpk_Random)))
+end;
+
+class procedure TSettings.SetMinerPrivateKeyType(AType: TMinerPrivateKeyType);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].SetAsInteger(Integer(AType));
+end;
+
+class function TSettings.GetMinerSelectedPrivateKey : string;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].GetAsString('');
+end;
+
+class procedure TSettings.SetMinerSelectedPrivateKey(AKey:string);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].SetAsString(AKey);
+end;
+
+class function TSettings.GetSaveLogFiles : boolean;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_SaveLogFiles].GetAsBoolean(false);
+end;
+
+class procedure TSettings.SetSaveLogFiles(ABool: boolean);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_SaveLogFiles].SetAsBoolean(ABool);
+end;
+
+class function TSettings.GetShowLogs : boolean;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_ShowLogs].GetAsBoolean(false);
+end;
+
+class procedure TSettings.SetShowLogs(ABool: boolean);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_ShowLogs].SetAsBoolean(ABool);
+end;
+
+class function TSettings.GetSaveDebugLogs : boolean;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_SaveDebugLogs].GetAsBoolean(false);
+end;
+
+class procedure TSettings.SetSaveDebugLogs(ABool: boolean);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_SaveDebugLogs].SetAsBoolean(ABool);
+end;
+
+class function TSettings.GetMinerName : string;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('Anonymous Miner')
+end;
+
+class procedure TSettings.SetMinerName(AName: string);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_MinerName].SetAsString(AName);
+end;
+
+class function TSettings.GetRunCount : Integer;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_RunCount].GetAsInteger(0)
+end;
+
+class procedure TSettings.SetRunCount(AInt: Integer);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_RunCount].SetAsInteger(AInt)
+end;
+
+class function TSettings.GetShowModalMessages : boolean;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_ShowModalMessages].GetAsBoolean(false);
+end;
+
+class procedure TSettings.SetShowModalMessages(ABool: boolean);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_ShowModalMessages].SetAsBoolean(ABool);
+end;
+
+class function TSettings.GetPeerCache : string;
+begin
+  CheckLoaded;
+  Result := FAppParams.ParamByName[CT_PARAM_PeerCache].GetAsString('');
+end;
+
+class procedure TSettings.SetPeerCache(AString: string);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_PeerCache].SetAsString(AString);
+end;
+
+class function TSettings.GetTryConnectOnlyWithThisFixedServers : string;
+begin
+  CheckLoaded;
+  Result := Trim(FAppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].GetAsString(''));
+end;
+
+class procedure TSettings.SetTryConnectOnlyWithThisFixedServers(AString: string);
+begin
+  CheckLoaded;
+  FAppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].SetAsString(Trim(AString));
+end;
+
+class procedure TSettings.CheckLoaded;
+begin
+  if not Assigned(FAppParams) then
+    raise Exception.Create('Application settings have not been loaded');
+end;
+
+class procedure TSettings.NotifyOnChanged;
+begin
+  FOnChanged.Invoke(nil);
+end;
+
+initialization
+  TSettings.FAppParams := nil;
+
+finalization
+  if Assigned(TSettings.FAppParams) then
+    FreeAndNil(TSettings.FAppParams);
+
+end.
+
+
+

+ 350 - 4
Units/PascalCoin/UWalletKeys.pas → Units/PascalCoin/UWallet.pas

@@ -1,4 +1,4 @@
-unit UWalletKeys;
+unit UWallet;
 
 
 {$mode delphi}
 {$mode delphi}
 
 
@@ -18,7 +18,7 @@ unit UWalletKeys;
 interface
 interface
 
 
 uses
 uses
-  Classes, UBlockChain, UAccounts, UCrypto, UCommon;
+  Classes, USettings, UBlockChain, UAccounts, UCrypto, UCommon;
 
 
 Type
 Type
   TWalletKey = Record
   TWalletKey = Record
@@ -27,6 +27,7 @@ Type
     CryptedKey : TRawBytes;
     CryptedKey : TRawBytes;
     PrivateKey : TECPrivateKey;
     PrivateKey : TECPrivateKey;
     SearchableAccountKey : TRawBytes;
     SearchableAccountKey : TRawBytes;
+    function HasPrivateKey : boolean;
   End;
   End;
 
 
   TWalletKeys = Class(TComponent)
   TWalletKeys = Class(TComponent)
@@ -78,23 +79,62 @@ Type
     Function AddPublicKey(Const Name : AnsiString; ECDSA_Public : TECDSA_Public) : Integer; override;
     Function AddPublicKey(Const Name : AnsiString; ECDSA_Public : TECDSA_Public) : Integer; override;
     Procedure Delete(index : Integer); override;
     Procedure Delete(index : Integer); override;
     Procedure Clear; override;
     Procedure Clear; override;
-    //
     Property AccountsKeyList : TOrderedAccountKeysList read FOrderedAccountKeysList;
     Property AccountsKeyList : TOrderedAccountKeysList read FOrderedAccountKeysList;
     Property SafeBox : TPCSafeBox read GetSafeBox write SetSafeBox;
     Property SafeBox : TPCSafeBox read GetSafeBox write SetSafeBox;
   End;
   End;
 
 
+  TRestoreWalletResult = record
+    TotalKeysFound : Integer;
+    ImportedPrivateKeys : Integer;
+    ImportedPublicKeys : Integer;
+    Duplicates : Integer;
+    Success : boolean;
+  end;
+
+  TWallet = class
+    private
+      FKeys : TWalletKeysExt; static;
+      class function GetKeys : TWalletKeysExt; static;
+      class function GetMiningKey : TAccountKey; static;
+      class procedure CheckLoaded;
+      class procedure CheckUnlocked;
+    public
+      class property Keys : TWalletKeysExt read GetKeys;
+      class property MiningKey : TAccountKey read GetMiningKey;
+      class procedure Load;
+      class function HasKey(const AKey: TWalletKey) : boolean;
+      class procedure DeleteKey(const AKey: TWalletKey);
+      class procedure GenerateNewKey(const AName: string; AEncryptionTypeNID : Word);
+      class function ExportPublicKey(const AKey: TWalletKey) : string;
+      class function ExportPrivateKey(const AKey: TWalletKey; const APassword: string) : string;
+      class procedure ImportPrivateKey(const AName, AKeyImportText, APassword: string);
+      class procedure ImportPublicKey(Const AName, AKeyImportText : string);
+      class function RestoreWallet(const AFileName, APassword: string) : TRestoreWalletResult;
+      class procedure BackupWallet(const AFileName: string);
+      class function TryDecryptPrivateKey(const AEncryptedKeyText, APassword:string; out APrivateKey : TECPrivateKey; out AMessage : string) : boolean;
+      class function TryParseEncryptedKey(const AKeyText, AKeyPassword : string; out AKey : TECPrivateKey) : boolean;
+      class function TryParseRawKey(const ARawBytes : TRawBytes; AEncryptionTypeNID : Word; out AKey : TECPrivateKey) : boolean;
+      class function TryParseHexKey(const AHexString : string; AEncryptionTypeNID : Word; out AKey : TECPrivateKey) : boolean;
+  end;
 
 
 Const CT_TWalletKey_NUL  : TWalletKey = (Name:'';AccountKey:(EC_OpenSSL_NID:0;x:'';y:'');CryptedKey:'';PrivateKey:Nil;SearchableAccountKey:'');
 Const CT_TWalletKey_NUL  : TWalletKey = (Name:'';AccountKey:(EC_OpenSSL_NID:0;x:'';y:'');CryptedKey:'';PrivateKey:Nil;SearchableAccountKey:'');
 
 
 implementation
 implementation
 
 
 uses
 uses
-  SysUtils, UConst, ULog, UAES;
+  SysUtils, UConst, ULog, UAES, UFolderHelper;
 
 
 Const
 Const
   CT_PrivateKeyFile_Magic = 'TWalletKeys';
   CT_PrivateKeyFile_Magic = 'TWalletKeys';
   CT_PrivateKeyFile_Version = 100;
   CT_PrivateKeyFile_Version = 100;
 
 
+{ TWalletKey }
+
+function TWalletKey.HasPrivateKey : boolean;
+begin
+  Result := Length(Self.CryptedKey) > 0;
+end;
+
 { TWalletKeys }
 { TWalletKeys }
 
 
 Type PWalletKey = ^TWalletKey;
 Type PWalletKey = ^TWalletKey;
@@ -122,6 +162,14 @@ begin
   end else begin
   end else begin
     P := FSearchableKeys[Result];
     P := FSearchableKeys[Result];
     P^.Name := Name;
     P^.Name := Name;
+    if NOT P^.HasPrivateKey then begin
+      // overriding watch-only public key with full private/public key data, so double-check private key matches
+      if P^.AccountKey <> ECPrivateKey.PublicKey then
+        raise Exception.Create('[UWallet.pas] TWalletKeys.AddPrivateKey - consistency check failed when overriding watch-only key');
+      P^.CryptedKey := TAESComp.EVP_Encrypt_AES256(TCrypto.PrivateKey2Hexa(ECPrivateKey.PrivateKey), WalletPassword);
+      P^.PrivateKey := TECPrivateKey.Create;
+      P^.PrivateKey.SetPrivateKeyFromHexa(ECPrivateKey.EC_OpenSSL_NID, TCrypto.PrivateKey2Hexa(ECPrivateKey.PrivateKey));
+    end;
   end;
   end;
   if Not FIsReadingStream then SaveToStream(FWalletFileStream);
   if Not FIsReadingStream then SaveToStream(FWalletFileStream);
   FOnChanged.Invoke(Self);
   FOnChanged.Invoke(Self);
@@ -136,6 +184,7 @@ begin
     P^ := CT_TWalletKey_NUL;
     P^ := CT_TWalletKey_NUL;
     P^.Name := Name;
     P^.Name := Name;
     P^.AccountKey := ECDSA_Public;
     P^.AccountKey := ECDSA_Public;
+    P^.CryptedKey := '';
     P^.PrivateKey := Nil;
     P^.PrivateKey := Nil;
     P^.SearchableAccountKey := TAccountComp.AccountKey2RawString(ECDSA_Public);
     P^.SearchableAccountKey := TAccountComp.AccountKey2RawString(ECDSA_Public);
     FSearchableKeys.Insert(Result,P);
     FSearchableKeys.Insert(Result,P);
@@ -458,4 +507,301 @@ begin
   end;
   end;
 end;
 end;
 
 
+{ TWallet }
+
+class function TWallet.GetMiningKey: TAccountKey;
+Var PK : TECPrivateKey;
+  i : Integer;
+  PublicK : TECDSA_Public;
+begin
+  CheckLoaded;
+  Result := CT_TECDSA_Public_Nul;
+  case TSettings.MinerPrivateKeyType of
+    mpk_NewEachTime: PublicK := CT_TECDSA_Public_Nul;
+    mpk_Selected: PublicK := TAccountComp.RawString2Accountkey(TSettings.MinerSelectedPrivateKey);
+    mpk_Random: begin
+      PublicK := CT_TECDSA_Public_Nul;
+      if FKeys.Count>0 then PublicK := FKeys.Key[Random(FKeys.Count)].AccountKey;
+    end;
+  end;
+  i := FKeys.IndexOfAccountKey(PublicK);
+  if i>=0 then begin
+    if (FKeys.Key[i].CryptedKey='') then i:=-1;
+  end else begin
+    // Generate a new key
+    PK := TECPrivateKey.Create;
+    try
+      PK.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
+      FKeys.AddPrivateKey('User Key '+FormatDateTime('YYYY-MM-DD hh:nn' ,Now), PK);
+      PublicK := PK.PublicKey;
+    finally
+      PK.Free;
+    end;
+  end;
+  Result := PublicK;
+end;
+
+class function TWallet.GetKeys : TWalletKeysExt; inline;
+begin
+  CheckLoaded;
+  Result := FKeys;
+end;
+
+class procedure TWallet.Load;
+begin
+  try
+    if not Assigned(FKeys) then
+      FKeys := TWalletKeysExt.Create(nil);
+    FKeys.WalletFileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'WalletKeys.dat';
+  except
+    on E:Exception do begin
+      E.Message := 'Cannot open your wallet... Perhaps another instance of Pascal Coin is active!'+#10+#10+E.Message;
+      Raise;
+    end;
+  end;
+end;
+
+class function TWallet.HasKey(const AKey: TWalletKey) : boolean;
+begin
+  Result := FKeys.IndexOfAccountKey(AKey.AccountKey) >= 0;
+end;
+
+class procedure TWallet.DeleteKey(const AKey: TWalletKey);
+var
+  i : Integer;
+begin
+  CheckLoaded;
+  i := FKeys.IndexOfAccountKey(AKey.AccountKey);
+  if i >= 0 then
+    FKeys.Delete(i)
+  else
+    raise Exception.Create('Key not found');
+end;
+
+class procedure TWallet.GenerateNewKey(const AName: string; AEncryptionTypeNID : Word);
+var
+  privateKey : TECPrivateKey;
+begin
+  privateKey := TECPrivateKey.Create;
+  try
+    privateKey.GenerateRandomPrivateKey(AEncryptionTypeNID);
+    FKeys.AddPrivateKey(AName, privateKey);
+  finally
+    privateKey.Free;
+  end;
+end;
+
+class function TWallet.ExportPublicKey(const AKey: TWalletKey) : string;
+begin
+  Result := TAccountComp.AccountPublicKeyExport(AKey.AccountKey);
+end;
+
+class function TWallet.ExportPrivateKey(const AKey: TWalletKey; const APassword: string) : string;
+begin
+  Result := TCrypto.ToHexaString(TAESComp.EVP_Encrypt_AES256(AKey.PrivateKey.ExportToRaw, APassword));
+end;
+
+class procedure TWallet.ImportPrivateKey(const AName, AKeyImportText, APassword: string);
+var
+ message : String;
+ EC : TECPrivateKey;
+ i : Integer;
+begin
+  CheckLoaded;
+  CheckUnlocked;
+  try
+    if NOT TryDecryptPrivateKey(AKeyImportText, APassword, EC, message) then
+      raise Exception.Create(message);
+    i := FKeys.IndexOfAccountKey(EC.PublicKey);
+    if  i>=0  then
+      if FKeys.Key[i].HasPrivateKey then
+        raise Exception.Create('This key is already in your wallet!');
+    i := FKeys.AddPrivateKey(AName,EC);
+  finally
+    if Assigned(EC) then
+      EC.Free;
+  end;
+end;
+
+class procedure TWallet.ImportPublicKey(Const AName, AKeyImportText : string);
+var
+  raw, errors : AnsiString;
+  accountKey : TAccountKey;
+begin
+  CheckLoaded;
+  CheckUnlocked;
+  If not TAccountComp.AccountPublicKeyImport(AKeyImportText, accountKey, errors) then begin
+    raw := TCrypto.HexaToRaw(AKeyImportText);
+    if trim(raw)='' then
+      raise Exception.Create('Invalid public key value (Not hexa or not an imported format)'+#10+errors);
+    accountKey := TAccountComp.RawString2Accountkey(raw);
+  end;
+  If not TAccountComp.IsValidAccountKey(accountKey,errors) then
+    raise Exception.Create('This data is not a valid public key'+#10+errors);
+  if FKeys.IndexOfAccountKey(accountKey)>=0 then
+    raise exception.Create('This key exists on your wallet');
+  FKeys.AddPublicKey(AName, accountKey);
+end;
+
+class function TWallet.RestoreWallet(const AFileName, APassword: string) : TRestoreWalletResult;
+var
+  wki : TWalletKeys;
+  i, j : Integer;
+begin
+  CheckLoaded;
+  if NOT FileExists(AFileName) then
+    raise Exception.Create('File not found: ' + AFilename);
+
+  wki := TWalletKeys.Create(nil);
+  try
+    wki.WalletFileName := AFileName;
+    if wki.Count<=0 then
+      raise Exception.Create('Wallet file has no valid data');
+    Result.ImportedPrivateKeys := 0;
+    Result.ImportedPublicKeys := 0;
+    Result.Success := false;
+
+    // If password required, set it
+    if NOT wki.IsValidPassword then begin
+      wki.WalletPassword := APassword;
+      if NOT wki.IsValidPassword then
+        exit;
+    end;
+
+    // Import the keys
+    Result.TotalKeysFound:= wki.Count;
+    for i := 0 to wki.Count - 1 do begin
+      if NOT HasKey(wki.Key[i]) then begin
+        if wki.Key[i].HasPrivateKey then begin
+          TWallet.Keys.AddPrivateKey(wki.Key[i].Name, wki.Key[i].PrivateKey);
+          inc(Result.ImportedPrivateKeys);
+        end else begin
+          TWallet.Keys.AddPublicKey(wki.Key[i].Name, wki.Key[i].AccountKey);
+          inc(Result.ImportedPublicKeys);
+        end;
+      end else begin
+        j := FKeys.IndexOfAccountKey(wki[i].AccountKey);
+        // case: existing wallet has public key but import has private key
+        if (NOT FKeys[j].HasPrivateKey) AND (wki.Key[i].HasPrivateKey) then begin
+          TWallet.Keys.AddPrivateKey(wki.Key[i].Name, wki.Key[i].PrivateKey);
+          inc(Result.ImportedPrivateKeys);
+        end else Inc(Result.Duplicates);
+      end;
+    end;
+    result.Success := true;
+  finally
+    wki.Free;
+  end;
+end;
+
+class procedure TWallet.BackupWallet(const AFileName : string);
+var
+  fs : TFileStream;
+begin
+  CheckLoaded;
+  fs := TFileStream.Create(AFileName, fmCreate);
+  try
+    fs.Size := 0;
+    TWallet.Keys.SaveToStream(fs);
+  finally
+    fs.Free;
+  end;
+end;
+
+class function TWallet.TryDecryptPrivateKey(const AEncryptedKeyText, APassword:string; out APrivateKey : TECPrivateKey; out AMessage : string) : boolean;
+var
+ parseResult : Boolean;
+begin
+  APrivateKey := nil;
+  AMessage := '';
+  if NOT TCrypto.IsHexString(AEncryptedKeyText) then begin
+    Result := false;
+    AMessage := 'Invalid key text. You must enter a hexadecimal value ("0".."9" or "A".."F").';
+    exit;
+  end;
+  case Length(AEncryptedKeyText) div 2 of
+    32: parseResult := TryParseRawKey(AEncryptedKeyText, CT_NID_secp256k1, APrivateKey);
+    35,36: parseResult := TryParseRawKey(AEncryptedKeyText, CT_NID_sect283k1, APrivateKey);
+    48: parseResult := TryParseRawKey(AEncryptedKeyText, CT_NID_secp384r1, APrivateKey);
+    65,66: parseResult := TryParseRawKey(AEncryptedKeyText, CT_NID_secp521r1, APrivateKey);
+    64, 80, 96: parseResult := TryParseEncryptedKey(AEncryptedKeyText, APassword, APrivateKey);
+    else begin
+      result := false;
+      AMessage := 'Invalidly formatted private key string. Ensure it is an encrypted private key export or raw private key hexstring.';
+      exit;
+    end;
+  end;
+  if NOT parseResult then begin
+    Result := false;
+    if Length(AEncryptedKeyText) div 2 in [64, 80, 96] then
+      AMessage := 'Incorrect password'
+    else
+      AMessage := 'Unencrypted key data is invalid or corrupted';
+    if Assigned(APrivateKey) then FreeAndNil(APrivateKey);
+    exit;
+  end;
+  if Not Assigned(APrivateKey) then begin
+    Result := false;
+    AMessage := '[UWallet.pas] TWallet.ImportPrivateKey - expected non-null private key';
+    exit;
+  end;
+  Result := true;
+end;
+
+class function TWallet.TryParseEncryptedKey(const AKeyText, AKeyPassword : string; out AKey : TECPrivateKey) : boolean;
+var
+ decrypt : string;
+begin
+  AKey := nil;
+  if NOT TCrypto.IsHexString(AKeyText) then begin
+    Result := false;
+    exit;
+  end;
+  decrypt := '';
+  If (TAESComp.EVP_Decrypt_AES256(TCrypto.HexaToRaw(AKeyText),AKeyPassword,decrypt)) AND (decrypt<>'') then begin
+    AKey := TECPrivateKey.ImportFromRaw(decrypt);
+    Result := true;
+  end else begin
+    Result := false;
+  end;
+end;
+
+class function TWallet.TryParseRawKey(const ARawBytes : TRawBytes; AEncryptionTypeNID : Word; out AKey : TECPrivateKey) : boolean;
+begin
+  Result := TryParseHexKey(TCrypto.ToHexaString(ARawBytes), AEncryptionTypeNID, AKey);
+end;
+
+class function TWallet.TryParseHexKey(const AHexString : string; AEncryptionTypeNID : Word; out AKey : TECPrivateKey) : boolean;
+begin
+  AKey := TECPrivateKey.Create;
+  Try
+    AKey.SetPrivateKeyFromHexa(AEncryptionTypeNID, AHexString);
+    Result := True;
+  Except
+    On E:Exception do begin
+      FreeAndNil(AKey);
+      Result := false;
+    end;
+  end;
+end;
+
+class procedure TWallet.CheckLoaded;
+begin
+  if not Assigned(FKeys) then
+    raise Exception.Create('Wallet has not been loaded');
+end;
+
+class procedure TWallet.CheckUnlocked;
+begin
+  if NOT FKeys.IsValidPassword then
+    raise Exception.Create('Wallet is locked.');
+end;
+
+initialization
+  TWallet.FKeys := nil;
+
+finalization
+  if Assigned(TWallet.FKeys) then
+    FreeAndNil(TWallet.FKeys);
+
 end.
 end.

+ 1 - 1
Units/PascalCoin/upcdaemon.pas

@@ -19,7 +19,7 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, daemonapp,
   Classes, SysUtils, daemonapp,
-  SyncObjs, UOpenSSL, UCrypto, UNode, UFileStorage, UFolderHelper, UWalletKeys, UConst, ULog, UNetProtocol,
+  SyncObjs, UOpenSSL, UCrypto, UNode, UFileStorage, UFolderHelper, UWallet, UConst, ULog, UNetProtocol,
   IniFiles,
   IniFiles,
   UThread, URPC, UPoolMining, UAccounts;
   UThread, URPC, UPoolMining, UAccounts;
 
 

+ 6 - 6
Units/Utils/UAutoScope.pas

@@ -18,7 +18,7 @@
     Ver 1.0.0
     Ver 1.0.0
     * Initial release.
     * Initial release.
  **********************************************************************}
  **********************************************************************}
-unit AutoScope;
+unit UAutoScope;
 {$IFDEF FPC}
 {$IFDEF FPC}
   {$CODEPAGE UTF8}
   {$CODEPAGE UTF8}
   {$MODE DELPHI}{$H+}
   {$MODE DELPHI}{$H+}
@@ -36,10 +36,10 @@ interface
     {$IFDEF VER2_4}{$ERROR Too old compiller.}{$ENDIF}
     {$IFDEF VER2_4}{$ERROR Too old compiller.}{$ENDIF}
   {$ENDIF}
   {$ENDIF}
   {$DEFINE USE_INTERFACE}
   {$DEFINE USE_INTERFACE}
-  {$IFNDEF VER_3_0}
-    {$IFDEF USE_INTERFACE}{$UNDEF USE_INTERFACE}{$ENDIF}
-    {$DEFINE USE_OPERATORS}
-  {$ENDIF}
+  //{$IFNDEF VER_3_0}
+  //  {$IFDEF USE_INTERFACE}{$UNDEF USE_INTERFACE}{$ENDIF}
+  //  {$DEFINE USE_OPERATORS}
+  //{$ENDIF}
 {$ELSE}
 {$ELSE}
   {$DEFINE USE_INTERFACE}
   {$DEFINE USE_INTERFACE}
 {$ENDIF}
 {$ENDIF}
@@ -395,4 +395,4 @@ begin
   UnregisterPointer(P);
   UnregisterPointer(P);
 end;
 end;
 
 
-end.
+end.

+ 1 - 1
Units/Utils/UGridUtils.pas

@@ -20,7 +20,7 @@ interface
 uses
 uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
   Classes, Grids, UNode, UAccounts, UBlockChain, UAppParams,
   Classes, Grids, UNode, UAccounts, UBlockChain, UAppParams,
-  UWalletKeys, UCrypto, UPoolMining, URPC;
+  UWallet, UCrypto, UPoolMining, URPC;
 
 
 Type
 Type
   // TAccountsGrid implements a visual integration of TDrawGrid
   // TAccountsGrid implements a visual integration of TDrawGrid

+ 2 - 2
Units/Utils/UWizard.lfm

@@ -1,7 +1,7 @@
 object WizardHostForm: TWizardHostForm
 object WizardHostForm: TWizardHostForm
-  Left = 187
+  Left = 993
   Height = 120
   Height = 120
-  Top = 35
+  Top = 640
   Width = 360
   Width = 360
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   Caption = 'Wizard'
   Caption = 'Wizard'

+ 123 - 70
Units/Utils/UWizard.pas

@@ -5,9 +5,6 @@
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
-
-  Additional Credits:
-    <contributors add yourselves here>
 }
 }
 
 
 unit UWizard;
 unit UWizard;
@@ -27,11 +24,14 @@ const
   CT_WIZARD_DEFAULT_FINISH : AnsiString = '&Finish';
   CT_WIZARD_DEFAULT_FINISH : AnsiString = '&Finish';
   CT_WIZARD_DEFAULT_TITLE : AnsiString = 'Wizard';
   CT_WIZARD_DEFAULT_TITLE : AnsiString = 'Wizard';
 
 
-
 type
 type
   { Forward Declarations }
   { Forward Declarations }
   TWizardForm<T> = class;
   TWizardForm<T> = class;
 
 
+  { Enums }
+
+  TPathUpdateType = (ptInject, ptReplaceAllNext, ptReplaceAll);
+
   { TWizardHostForm - the host form that contains the wizard screens. }
   { TWizardHostForm - the host form that contains the wizard screens. }
   TWizardHostForm = class(TForm)
   TWizardHostForm = class(TForm)
     FHorizonalLine: TPanel;
     FHorizonalLine: TPanel;
@@ -73,11 +73,11 @@ type
   { TWizardForm is the base class for wizard screens }
   { TWizardForm is the base class for wizard screens }
   TWizardForm<T> = class(TForm)
   TWizardForm<T> = class(TForm)
     private
     private
-      FBag : T;
+      FModel : T;
       //FWizard : TWizard<T>;  // FPG Bug: cyclic generic dependencies, via forward decls, don't work
       //FWizard : TWizard<T>;  // FPG Bug: cyclic generic dependencies, via forward decls, don't work
     protected
     protected
-      InjectScreen : procedure (screen : TWizardForm<T>) of object;    // FPC Bug workaround: calling this is equivalent to FWizard.InjectScreen
-      property Bag : T read FBag write FBag;
+      UpdatePath : procedure (APathUpdateType: TPathUpdateType; const screens : array of TComponentClass) of object;    // FPC Bug workaround: calling this is equivalent to FWizard.InjectScreen
+      property Model : T read FModel write FModel;
 
 
     public
     public
       procedure Initialize; virtual;
       procedure Initialize; virtual;
@@ -88,18 +88,19 @@ type
    end;
    end;
 
 
   { TWizard - Base class for wizards. Encapsulates the entire wizard flow. }
   { TWizard - Base class for wizards. Encapsulates the entire wizard flow. }
-  TWizard<T> = class
+  TWizard<T> = class(TComponent)
     type
     type
       __TScreenType = TWizardForm<T>; // FPC Bug: doesn't support nested generics
       __TScreenType = TWizardForm<T>; // FPC Bug: doesn't support nested generics
-      TWizardFormList = TList<__TScreenType>;
-
+      __TList_TComponentClass = TList<TComponentClass>;
     private
     private
         FHost : TWizardHostForm;
         FHost : TWizardHostForm;
         FStarted : Boolean;
         FStarted : Boolean;
         FFinished : Boolean;
         FFinished : Boolean;
         FCurrentScreen : TWizardForm<T>;
         FCurrentScreen : TWizardForm<T>;
-        FPropertyBag : T;
-        FScreens :  TWizardFormList;
+        FModel : T;
+        FScreenPath : TList<TComponentClass>;
+        FScreenPathBackup : TDictionary<SizeInt, __TList_TComponentClass>;
+        FScreenInstances : TDictionary<TComponentClass, __TScreenType>;
         FCurrentScreenIndex : Integer;
         FCurrentScreenIndex : Integer;
         FNextText : AnsiString;
         FNextText : AnsiString;
         FPreviousText : AnsiString;
         FPreviousText : AnsiString;
@@ -111,31 +112,32 @@ type
         procedure NextHandler(sender : TObject);
         procedure NextHandler(sender : TObject);
         procedure PreviousHandler(sender : TObject);
         procedure PreviousHandler(sender : TObject);
     protected
     protected
+        function CreateScreen(AType: TComponentClass) : TWizardForm<T>;
         function DetermineHasNext : boolean; virtual;
         function DetermineHasNext : boolean; virtual;
         function DetermineHasPrevious : boolean; virtual;
         function DetermineHasPrevious : boolean; virtual;
         procedure PresentScreen(screen : TWizardForm<T>); virtual;
         procedure PresentScreen(screen : TWizardForm<T>); virtual;
         function FinishRequested(out message : AnsiString) : boolean; virtual; abstract;
         function FinishRequested(out message : AnsiString) : boolean; virtual; abstract;
         function CancelRequested(out message : AnsiString) : boolean; virtual; abstract;
         function CancelRequested(out message : AnsiString) : boolean; virtual; abstract;
     public
     public
-        constructor Create(constref propertyBag : T; screens: array of TWizardForm<T>);
+        constructor Create(AOwner:TComponent; const screens: array of TComponentClass); overload;
         destructor Destroy; override;
         destructor Destroy; override;
-        property PropertyBag : T read FPropertyBag;
+        property CurrentScreen : TWizardForm<T> read FCurrentScreen;
+        property Model : T read FModel;
         property HasNext : boolean read DetermineHasNext;
         property HasNext : boolean read DetermineHasNext;
         property HasPrevious : boolean read DetermineHasPrevious;
         property HasPrevious : boolean read DetermineHasPrevious;
         property NextText : AnsiString read FNextText write FNextText;
         property NextText : AnsiString read FNextText write FNextText;
         property PreviousText : AnsiString read FPreviousText write FPreviousText;
         property PreviousText : AnsiString read FPreviousText write FPreviousText;
         property FinishText : AnsiString read FFinishText write FFinishText;
         property FinishText : AnsiString read FFinishText write FFinishText;
         property TitleText : AnsiString read FTitleText write FTitleText;
         property TitleText : AnsiString read FTitleText write FTitleText;
-        procedure Start(AOwner : TComponent); virtual;
+        procedure Start(constref model : T); virtual;
         procedure Next; virtual;
         procedure Next; virtual;
         procedure Previous; virtual;
         procedure Previous; virtual;
-        procedure InjectScreen(screen : TWizardForm<T>); virtual;
-        procedure RemoveScreen(screen : TWizardForm<T>); virtual;
+        procedure UpdatePath(APathUpdateType: TPathUpdateType; const screens : array of TComponentClass); virtual;
   end;
   end;
 
 
   { TActioWizard Delegate Declarations }
   { TActioWizard Delegate Declarations }
-  TActionWizardCancelFunc<T> = function(screenIndex : Integer; constref propertyBag : T; out message : AnsiString) : boolean of object;
-  TActionWizardFinishFunc<T> = function(constref  propertyBag : T; out message : AnsiString) : boolean of object;
+  TActionWizardCancelFunc<T> = function(screenIndex : Integer; constref model : T; out message : AnsiString) : boolean of object;
+  TActionWizardFinishFunc<T> = function(constref  model : T; out message : AnsiString) : boolean of object;
 
 
   { TActionWizard - a generic Wizard that can be used without subclassing }
   { TActionWizard - a generic Wizard that can be used without subclassing }
   TActionWizard<T> = class(specialize TWizard<T>)
   TActionWizard<T> = class(specialize TWizard<T>)
@@ -146,8 +148,8 @@ type
       function CancelRequested(out message : AnsiString) : boolean; override;
       function CancelRequested(out message : AnsiString) : boolean; override;
       function FinishRequested(out message : AnsiString) : boolean; override;
       function FinishRequested(out message : AnsiString) : boolean; override;
     public
     public
-      constructor Create(title, finish: AnsiString; constref bag : T; screens : array of TWizardForm<T>; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
-      class procedure Show(AOwner : TComponent; title, finish: AnsiString; constref bag : T; screens : array of TWizardForm<T>; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
+      constructor Create(AOwner:TComponent; title, finish: AnsiString; const screens : array of TComponentClass; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
+      class procedure Show(AParent: TForm; title, finish: AnsiString; constref bag : T; const screens : array of TComponentClass; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
       property FinishText : AnsiString read FTitleText;
       property FinishText : AnsiString read FTitleText;
       property TitleText : AnsiString read FFinishText;
       property TitleText : AnsiString read FFinishText;
   end;
   end;
@@ -294,11 +296,12 @@ end;
 
 
 {%region TWizard }
 {%region TWizard }
 
 
-constructor TWizard<T>.Create(constref propertyBag : T; screens: array of TWizardForm<T>);
+constructor TWizard<T>.Create(AOwner:TComponent; const screens: array of TComponentClass);
 var
 var
    i : integer;
    i : integer;
    screen : TWizardForm<T>;
    screen : TWizardForm<T>;
 begin
 begin
+  inherited Create(AOwner);
   if Length(screens) = 0 then
   if Length(screens) = 0 then
     raise Exception.Create('Wizard needs at least 1 screen');
     raise Exception.Create('Wizard needs at least 1 screen');
 
 
@@ -309,26 +312,47 @@ begin
   self.FTitleText := CT_WIZARD_DEFAULT_TITLE;
   self.FTitleText := CT_WIZARD_DEFAULT_TITLE;
   self.FStarted := false;
   self.FStarted := false;
   self.FFinished := false;
   self.FFinished := false;
-  self.FPropertyBag := propertyBag;
-  self.FScreens := TWizardFormList.Create;
-  for i := Low(screens) to High(screens) do begin
-    screen := screens[i];
-    screen.InjectScreen := InjectScreen;
-    FScreens.Add(screen);
-  end;
+  self.FScreenPath := TList<TComponentClass>.Create;
+  self.FScreenInstances := TDictionary<TComponentClass, __TScreenType>.Create;
+
+  // Create the screen path
+  UpdatePath(ptReplaceAll, screens);
+  FScreenPathBackup := TDictionary<SizeInt, __TList_TComponentClass>.Create;
 end;
 end;
 
 
 destructor TWizard<T>.Destroy;
 destructor TWizard<T>.Destroy;
 var
 var
   i : integer;
   i : integer;
+  screen : TWizardForm<T>;
+  key : TComponentClass;
+  backup : TList<TComponentClass>;
 begin
 begin
-  for i:= 0 to FScreens.Count - 1 do begin
-    FScreens[i].Destroy;
+  // screens destroyed as sub-components
+  for screen in FScreenInstances.Values do begin
+    if screen.Owner = nil then
+      screen.Free; // only destroy if dangling screen component
   end;
   end;
-  FScreens.Destroy;
+  FScreenInstances.Free;
+  FScreenPath.Free;
+  for backup in FScreenPathBackup.Values do
+    backup.Free;
+  FScreenPathBackup.Free;
+  inherited Destroy;
   // note: Property bag not destroyed, left for user to destroy
   // note: Property bag not destroyed, left for user to destroy
 end;
 end;
 
 
+function TWizard<T>.CreateScreen(AType: TComponentClass) : TWizardForm<T>;
+begin
+  if NOT FScreenInstances.ContainsKey(AType) then begin
+    Result := TWizardForm<T>(AType.Create(self));
+    if Result = nil then
+      raise Exception.Create('Supplied type was not correct TWizardForm<T> type');
+    Result.UpdatePath := UpdatePath;
+    FScreenInstances.Add(AType, Result);
+    Result.Initialize;
+  end else Result := FScreenInstances[AType];
+end;
+
 function TWizard<T>.CalculateFitSize : TPoint;
 function TWizard<T>.CalculateFitSize : TPoint;
 var
 var
   maxWidth, maxHeight, i : Integer;
   maxWidth, maxHeight, i : Integer;
@@ -336,8 +360,7 @@ var
 begin
 begin
   maxWidth := 0;
   maxWidth := 0;
   maxHeight := 0;
   maxHeight := 0;
-  for i := 0 to self.FScreens.Count - 1 do begin
-    screen := self.FScreens[i];
+  for screen in FScreenInstances.Values do begin
     if screen.Width > maxWidth then maxWidth := screen.Width;
     if screen.Width > maxWidth then maxWidth := screen.Width;
     if screen.Height > maxHeight then maxHeight := screen.Height;
     if screen.Height > maxHeight then maxHeight := screen.Height;
   end;
   end;
@@ -347,7 +370,7 @@ end;
 function TWizard<T>.DetermineHasNext : boolean;
 function TWizard<T>.DetermineHasNext : boolean;
 begin
 begin
    CheckStarted;
    CheckStarted;
-   DetermineHasNext := FCurrentScreenIndex < FScreens.Count - 1;
+   DetermineHasNext := FCurrentScreenIndex < FScreenPath.Count - 1;
 end;
 end;
 
 
 function TWizard<T>.DetermineHasPrevious : boolean;
 function TWizard<T>.DetermineHasPrevious : boolean;
@@ -356,12 +379,13 @@ begin
   DetermineHasPrevious := FCurrentScreenIndex > 0;
   DetermineHasPrevious := FCurrentScreenIndex > 0;
 end;
 end;
 
 
-procedure TWizard<T>.Start(AOwner : TComponent);
+procedure TWizard<T>.Start(constref model : T);
 var
 var
   i : integer;
   i : integer;
 begin
 begin
   CheckNotStarted;
   CheckNotStarted;
-  self.FHost := TWizardHostForm.Create(AOwner);
+  self.FModel := model;
+  self.FHost := TWizardHostForm.Create(Self.GetParentComponent);
   self.FHost.NextEvent.Add(NextHandler);
   self.FHost.NextEvent.Add(NextHandler);
   self.FHost.PreviousEvent.Add(PreviousHandler);
   self.FHost.PreviousEvent.Add(PreviousHandler);
   self.FHost.CloseQueryEvent := CancelRequested;
   self.FHost.CloseQueryEvent := CancelRequested;
@@ -371,14 +395,13 @@ begin
   self.FCurrentScreenIndex := 0;
   self.FCurrentScreenIndex := 0;
   self.FStarted := true;
   self.FStarted := true;
   self.FFinished := false;
   self.FFinished := false;
-  for i := 0 to self.FScreens.Count - 1 do begin
-    FScreens[i].Bag := self.PropertyBag;
-    FScreens[i].Initialize;
-  end;
   self.FHost.SetContentSize ( CalculateFitSize );
   self.FHost.SetContentSize ( CalculateFitSize );
-  self.PresentScreen(FScreens[FCurrentScreenIndex]);
+  self.FScreenPathBackup.Add(0, TList<TComponentClass>.Create(FScreenPath));
+  self.PresentScreen(FScreenInstances[FScreenPath[FCurrentScreenIndex]]);
+  //self.FHost.NextEvent.Remove(NextHandler);
+  //self.FHost.PreviousEvent.Remove(PreviousHandler);
   self.FHost.ShowModal;
   self.FHost.ShowModal;
-  self.FHost.Destroy;
+  self.FHost.Free;
   self.FHost := nil;
   self.FHost := nil;
 end;
 end;
 
 
@@ -391,10 +414,16 @@ begin
     ShowMessage (message);
     ShowMessage (message);
     exit;
     exit;
   end;
   end;
-  FCurrentScreen.Next;
+  FCurrentScreen.OnNext;
+  FModel := FCurrentScreen.Model; // Restore model in case it's a record
   if HasNext then begin
   if HasNext then begin
     inc(FCurrentScreenIndex);
     inc(FCurrentScreenIndex);
-    PresentScreen(FScreens[FCurrentScreenIndex]);
+    // Backup current path in case user goes back
+    if FScreenPathBackup.ContainsKey(FCurrentScreenIndex) then begin
+      FScreenPathBackup[FCurrentScreenIndex].Free;
+    end;
+    FScreenPathBackup.AddOrSetValue(FCurrentScreenIndex, TList<TComponentClass>.Create(FScreenPath));
+    PresentScreen(FScreenInstances[FScreenPath[FCurrentScreenIndex]]);
     exit;
     exit;
   end;
   end;
 
 
@@ -409,30 +438,56 @@ procedure TWizard<T>.Previous;
 begin
 begin
   CheckStarted;
   CheckStarted;
   if not HasPrevious then exit;
   if not HasPrevious then exit;
-  FCurrentScreen.Previous;
+  FCurrentScreen.OnPrevious;
+  FModel := FCurrentScreen.Model; // Restore model in case it's a record
   dec (FCurrentScreenIndex);
   dec (FCurrentScreenIndex);
-  PresentScreen(FScreens[FCurrentScreenIndex]);
-end;
 
 
-procedure TWizard<T>.InjectScreen(screen : TWizardForm<T>);
-begin
-  CheckStarted;
-  screen.Initialize;
-  FScreens.Insert(FCurrentScreenIndex + 1, screen );
-  self.FHost.SetContentSize ( CalculateFitSize );
-  FHost.NextText := IIF(NOT HasNext, FinishText, NextText);
+  // Restore backup path when this screen was first displayed
+  FScreenPath.Free;
+  FScreenPath := TList<TComponentClass>.Create(FScreenPathBackup[FCurrentScreenIndex]);
+  PresentScreen(FScreenInstances[FScreenPath[FCurrentScreenIndex]]);
 end;
 end;
 
 
-procedure TWizard<T>.RemoveScreen(screen : TWizardForm<T>);
-begin
-  CheckStarted;
-  FScreens.Remove(screen);
-  screen.Destroy;
+procedure TWizard<T>.UpdatePath(APathUpdateType: TPathUpdateType; const screens : array of TComponentClass);
+var
+  i, n : SizeInt;
+begin
+  case APathUpdateType of
+    ptInject: begin
+      for i := Low(screens) to High(screens) do begin
+        n := FCurrentScreenIndex + 1 + i - Low(screens);
+        if FScreenPath[n] <> screens[i] then begin
+          // only insert screen if not already there
+          FScreenPath.Insert(n, screens[i]);
+          CreateScreen(screens[i]);
+        end;
+      end;
+    end;
+    ptReplaceAllNext: begin
+      FScreenPath.DeleteRange(FCurrentScreenIndex + 1, FScreenPath.Count - FCurrentScreenIndex - 1);
+      for i := Low(screens) to High(screens) do begin
+        FScreenPath.Add(screens[i]);
+        CreateScreen(screens[i]);
+      end;
+    end;
+    ptReplaceAll: begin
+      FScreenPath.Clear;
+      for i := Low(screens)to High(screens) do begin
+        FScreenPath.Add(screens[i]);
+        CreateScreen(screens[i]);
+      end;
+    end;
+  end;
+  if Assigned(FHost) then begin
+    FHost.SetContentSize ( CalculateFitSize );
+    FHost.NextText := IIF(NOT HasNext, FinishText, NextText);
+  end;
 end;
 end;
 
 
 procedure TWizard<T>.PresentScreen(screen : TWizardForm<T>);
 procedure TWizard<T>.PresentScreen(screen : TWizardForm<T>);
 begin
 begin
   FCurrentScreen := screen;
   FCurrentScreen := screen;
+  FCurrentScreen.Model := Model;
   FHost.HidePrevious := NOT HasPrevious;
   FHost.HidePrevious := NOT HasPrevious;
   FHost.NextText := IIF( NOT HasNext, FinishText, NextText);
   FHost.NextText := IIF( NOT HasNext, FinishText, NextText);
   FHost.SetContent(screen);
   FHost.SetContent(screen);
@@ -459,45 +514,44 @@ begin
   Previous;
   Previous;
 end;
 end;
 
 
-
 {%endregion}
 {%endregion}
 
 
 {%region TActionWizard }
 {%region TActionWizard }
 
 
-constructor TActionWizard<T>.Create(title, finish: AnsiString; constref bag : T; screens : array of TWizardForm<T>; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
+constructor TActionWizard<T>.Create(AOwner: TComponent; title, finish: AnsiString; const screens : array of TComponentClass; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
 begin
 begin
-  inherited Create(bag, screens);
+  inherited Create(AOwner, screens);
   self.FTitleText := title;
   self.FTitleText := title;
   self.FFinishText := finishText;
   self.FFinishText := finishText;
   self.FCancelEvent := cancelFunc;
   self.FCancelEvent := cancelFunc;
   self.FFinishEvent := finishFunc;
   self.FFinishEvent := finishFunc;
 end;
 end;
 
 
-class procedure TActionWizard<T>.Show(AOwner : TComponent; title, finish: AnsiString; constref bag : T; screens : array of TWizardForm<T>; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
+class procedure TActionWizard<T>.Show(AParent: TForm; title, finish: AnsiString; constref bag : T; const screens : array of TComponentClass; cancelFunc: TActionWizardCancelFunc<T>; finishFunc : TActionWizardFinishFunc<T>);
 type
 type
   MyWizard = TActionWizard<T>;
   MyWizard = TActionWizard<T>;
 var
 var
   wizard : MyWizard;
   wizard : MyWizard;
 begin
 begin
-  wizard := MyWizard.Create(title, finish, bag, screens, cancelFunc, finishFunc);
+  wizard := MyWizard.Create(nil, title, finish, screens, cancelFunc, finishFunc);
   try
   try
-    wizard.Start(AOwner);
+    wizard.Start(bag);
   finally
   finally
-    wizard.Destroy;
+    wizard.Free;
   end;
   end;
 end;
 end;
 
 
 function TActionWizard<T>.CancelRequested(out message : AnsiString) : boolean;
 function TActionWizard<T>.CancelRequested(out message : AnsiString) : boolean;
 begin
 begin
   if Assigned(FCancelEvent) and NOT FFinished then
   if Assigned(FCancelEvent) and NOT FFinished then
-    Result := FCancelEvent(Self.FCurrentScreenIndex, self.PropertyBag, message)
+    Result := FCancelEvent(Self.FCurrentScreenIndex, self.Model, message)
   else Result := true;
   else Result := true;
 end;
 end;
 
 
 function TActionWizard<T>.FinishRequested(out message : AnsiString) : boolean;
 function TActionWizard<T>.FinishRequested(out message : AnsiString) : boolean;
 begin
 begin
   if Assigned(FFinishEvent) then
   if Assigned(FFinishEvent) then
-    Result := FFinishEvent(self.PropertyBag, message)
+    Result := FFinishEvent(self.Model, message)
   else Result := true;
   else Result := true;
   FFinished := true;
   FFinished := true;
 end;
 end;
@@ -505,4 +559,3 @@ end;
 {%endregion}
 {%endregion}
 
 
 end.
 end.
-