浏览代码

Build 1.3

PascalCoin 8 年之前
父节点
当前提交
3117ef0463

二进制
PascalCoinWallet.res


+ 9 - 0
PascalCoinWalletLazarus.lpi

@@ -14,6 +14,7 @@
       <Title Value="PascalCoinWalletLazarus"/>
       <Title Value="PascalCoinWalletLazarus"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
+      <Icon Value="0"/>
     </General>
     </General>
     <i18n>
     <i18n>
       <EnableI18N LFM="False"/>
       <EnableI18N LFM="False"/>
@@ -212,7 +213,15 @@
         <SyntaxMode Value="Delphi"/>
         <SyntaxMode Value="Delphi"/>
       </SyntaxOptions>
       </SyntaxOptions>
     </Parsing>
     </Parsing>
+    <CodeGeneration>
+      <Optimizations>
+        <OptimizationLevel Value="2"/>
+      </Optimizations>
+    </CodeGeneration>
     <Linking>
     <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="False"/>
+      </Debugging>
       <Options>
       <Options>
         <Win32>
         <Win32>
           <GraphicApplication Value="True"/>
           <GraphicApplication Value="True"/>

+ 27 - 0
README.md

@@ -34,6 +34,33 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 
 ## History:  
 ## History:  
 
 
+### Build 1.3.0.0 - 2016-11-24
+
+- JSON-RPC modifications:
+  - New param "b58_pubkey", can be used instead of "enc_pubkey": b58_pubkey is a Base58 encoded public key with checksum, is the value that Wallet exports/imports public key
+  - New JSON object type Public Key: "name","can_use","enc_pubkey","b58_pubkey","ec_nid","x" and "y" for each public key
+  - Added params "start" and "max" to "getaccountoperations". By default deep=100, max=100 and start=0, so will return last 100 operations made to an account
+  - Added params "start" and "max" to "getblockoperations". By default max=100 and start=0, so will return last 100 operations made to a block
+  - Added params "start" and "max" to "getwalletaccounts". By default max=100 and start=0, so will return first 100 accounts of the wallet
+  - Added params "start" and "max" to "getwalletpubkeys". By default max=100 and start=0, so will return first 100 public keys of the wallet
+    - Will return a Public key JSON object
+  - Method "decodepubkey" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)
+    - Will return a Public key JSON object
+  - Method "changekey" allows params "new_enc_pubkey" or "new_b58_pubkey" (if used together, returns error if not match)
+  - Method "getwalletaccounts" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)
+  - Method "getwalletaccountscount" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)
+  - Method "getwalletcoins" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)  
+  - Method "payloadencrypt"  allows params "enc_pubkey" or "b58_pubkey" when payload_method="pubkey" (if used together, returns error if not match)  
+  - Method "addnewkey" changed. Does not return an HEXASTRING with enc_pubkey, now returns a public key JSON object
+  - New methods:
+    - Method "changekeys". Similar to "changekey" but for multiple accounts at param "accounts" as a coma separated string (ex: "accounts"="1248,1753,85056"). Returns a JSON object with result information
+    - Method "lock" to lock wallet. Returns true if locked, returns false if wallet has no password (an empty string, must put a new password prior to lock)
+    - New method "getwalletpubkey". Search for "enc_pubkey" or "b58_pubkey" and returns a Public key JSON object
+- Corrected a issue saving last 5 .bank files
+- Improved protections for .bank corruption files
+- Added "open data folder" button on options form
+- Other minor changes
+
 ### Build 1.2.0.0 - 2016-11-16
 ### Build 1.2.0.0 - 2016-11-16
 
 
 - Account checksum values modified to be more easy and more distributed: Checksum = ((N * 101) MOD 89)+10
 - Account checksum values modified to be more easy and more distributed: Checksum = ((N * 101) MOD 89)+10

+ 27 - 0
README.txt

@@ -34,6 +34,33 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 
 ## History:  
 ## History:  
 
 
+### Build 1.3.0.0 - 2016-11-24
+
+- JSON-RPC modifications:
+  - New param "b58_pubkey", can be used instead of "enc_pubkey": b58_pubkey is a Base58 encoded public key with checksum, is the value that Wallet exports/imports public key
+  - New JSON object type Public Key: "name","can_use","enc_pubkey","b58_pubkey","ec_nid","x" and "y" for each public key
+  - Added params "start" and "max" to "getaccountoperations". By default deep=100, max=100 and start=0, so will return last 100 operations made to an account
+  - Added params "start" and "max" to "getblockoperations". By default max=100 and start=0, so will return last 100 operations made to a block
+  - Added params "start" and "max" to "getwalletaccounts". By default max=100 and start=0, so will return first 100 accounts of the wallet
+  - Added params "start" and "max" to "getwalletpubkeys". By default max=100 and start=0, so will return first 100 public keys of the wallet
+    - Will return a Public key JSON object
+  - Method "decodepubkey" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)
+    - Will return a Public key JSON object
+  - Method "changekey" allows params "new_enc_pubkey" or "new_b58_pubkey" (if used together, returns error if not match)
+  - Method "getwalletaccounts" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)
+  - Method "getwalletaccountscount" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)
+  - Method "getwalletcoins" allows params "enc_pubkey" or "b58_pubkey" (if used together, returns error if not match)  
+  - Method "payloadencrypt"  allows params "enc_pubkey" or "b58_pubkey" when payload_method="pubkey" (if used together, returns error if not match)  
+  - Method "addnewkey" changed. Does not return an HEXASTRING with enc_pubkey, now returns a public key JSON object
+  - New methods:
+    - Method "changekeys". Similar to "changekey" but for multiple accounts at param "accounts" as a coma separated string (ex: "accounts"="1248,1753,85056"). Returns a JSON object with result information
+    - Method "lock" to lock wallet. Returns true if locked, returns false if wallet has no password (an empty string, must put a new password prior to lock)
+    - New method "getwalletpubkey". Search for "enc_pubkey" or "b58_pubkey" and returns a Public key JSON object
+- Corrected a issue saving last 5 .bank files
+- Improved protections for .bank corruption files
+- Added "open data folder" button on options form
+- Other minor changes
+
 ### Build 1.2.0.0 - 2016-11-16
 ### Build 1.2.0.0 - 2016-11-16
 
 
 - Account checksum values modified to be more easy and more distributed: Checksum = ((N * 101) MOD 89)+10
 - Account checksum values modified to be more easy and more distributed: Checksum = ((N * 101) MOD 89)+10

+ 1 - 1
Units/Forms/UFRMAbout.pas

@@ -96,7 +96,7 @@ end;
 procedure TFRMAbout.OpenURL(Url: String);
 procedure TFRMAbout.OpenURL(Url: String);
 begin
 begin
   {$IFDEF FPC}
   {$IFDEF FPC}
-   OpenDocument(pchar(URL)) { *Convertido desde ShellExecute* }
+  OpenDocument(pchar(URL))
   {$ELSE}
   {$ELSE}
   shellexecute(0, 'open', pchar(URL), nil, nil, SW_SHOW)
   shellexecute(0, 'open', pchar(URL), nil, nil, SW_SHOW)
   {$ENDIF}
   {$ENDIF}

+ 56 - 23
Units/Forms/UFRMOperation.pas

@@ -29,6 +29,9 @@ uses
   Dialogs, StdCtrls, UNode, UWalletKeys, UCrypto, Buttons, UBlockChain,
   Dialogs, StdCtrls, UNode, UWalletKeys, UCrypto, Buttons, UBlockChain,
   UAccounts, ActnList, ComCtrls, Types;
   UAccounts, ActnList, ComCtrls, Types;
 
 
+Const
+  CM_PC_WalletKeysChanged = WM_USER + 1;
+
 type
 type
 
 
   { TFRMOperation }
   { TFRMOperation }
@@ -107,13 +110,17 @@ type
     FTxAmount : Int64;
     FTxAmount : Int64;
     FNewAccountPublicKey : TAccountKey;
     FNewAccountPublicKey : TAccountKey;
     FSenderAccounts: TOrderedCardinalList;
     FSenderAccounts: TOrderedCardinalList;
+    FOldOnChanged : TNotifyEvent;
     procedure SetWalletKeys(const Value: TWalletKeys);
     procedure SetWalletKeys(const Value: TWalletKeys);
+    Procedure UpdateWalletKeys;
     { Private declarations }
     { Private declarations }
     Procedure UpdateAccountsInfo;
     Procedure UpdateAccountsInfo;
     Function UpdateOperationOptions(var errors : AnsiString) : Boolean;
     Function UpdateOperationOptions(var errors : AnsiString) : Boolean;
     Function UpdatePayload(Const SenderAccount : TAccount; var errors : AnsiString) : Boolean;
     Function UpdatePayload(Const SenderAccount : TAccount; var errors : AnsiString) : Boolean;
     procedure SetFee(const Value: Int64);
     procedure SetFee(const Value: Int64);
     Procedure OnSenderAccountsChanged(Sender : TObject);
     Procedure OnSenderAccountsChanged(Sender : TObject);
+    procedure OnWalletKeysChanged(Sender : TObject);
+    procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
   public
   public
     { Public declarations }
     { Public declarations }
     Property SenderAccounts : TOrderedCardinalList read FSenderAccounts;
     Property SenderAccounts : TOrderedCardinalList read FSenderAccounts;
@@ -288,6 +295,11 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TFRMOperation.CM_WalletChanged(var Msg: TMessage);
+begin
+   UpdateWalletKeys;
+end;
+
 procedure TFRMOperation.ebDestAccountChange(Sender: TObject);
 procedure TFRMOperation.ebDestAccountChange(Sender: TObject);
 begin
 begin
   if FDisabled then exit;
   if FDisabled then exit;
@@ -370,6 +382,7 @@ end;
 
 
 procedure TFRMOperation.FormCreate(Sender: TObject);
 procedure TFRMOperation.FormCreate(Sender: TObject);
 begin
 begin
+  FWalletKeys := Nil;
   FSenderAccounts := TOrderedCardinalList.Create;
   FSenderAccounts := TOrderedCardinalList.Create;
   FSenderAccounts.OnListChanged := OnSenderAccountsChanged;
   FSenderAccounts.OnListChanged := OnSenderAccountsChanged;
   FDisabled := true;
   FDisabled := true;
@@ -420,6 +433,7 @@ end;
 
 
 procedure TFRMOperation.FormDestroy(Sender: TObject);
 procedure TFRMOperation.FormDestroy(Sender: TObject);
 begin
 begin
+  if Assigned(FWalletKeys) then FWalletKeys.OnChanged := FOldOnChanged;
   FreeAndNil(FSenderAccounts);
   FreeAndNil(FSenderAccounts);
 end;
 end;
 
 
@@ -447,6 +461,12 @@ begin
   UpdateOperationOptions(errors);
   UpdateOperationOptions(errors);
 end;
 end;
 
 
+procedure TFRMOperation.OnWalletKeysChanged(Sender: TObject);
+begin
+  PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
+  if Assigned(FOldOnChanged) then FOldOnChanged(Sender);
+end;
+
 procedure TFRMOperation.rbTransactionClick(Sender: TObject);
 procedure TFRMOperation.rbTransactionClick(Sender: TObject);
 Var errors : AnsiString;
 Var errors : AnsiString;
 begin
 begin
@@ -468,30 +488,15 @@ begin
 end;
 end;
 
 
 procedure TFRMOperation.SetWalletKeys(const Value: TWalletKeys);
 procedure TFRMOperation.SetWalletKeys(const Value: TWalletKeys);
-Var i : Integer;
-  wk : TWalletKey;
-  s : String;
 begin
 begin
+  if FWalletKeys=Value then exit;
+  if Assigned(FWalletKeys) then FWalletKeys.OnChanged := FOldOnChanged;
   FWalletKeys := Value;
   FWalletKeys := Value;
-  cbNewPrivateKey.items.BeginUpdate;
-  Try
-    cbNewPrivateKey.Items.Clear;
-    //cbNewPrivateKey.Items.AddObject('Generate a new Private Key',TObject(-1));
-    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 Not Assigned(wk.PrivateKey) then s := s + '(*)';
-      cbNewPrivateKey.Items.AddObject(s,TObject(i));
-    end;
-  Finally
-    cbNewPrivateKey.Items.EndUpdate;
-  End;
-  rbTransactionClick(Nil);
-  memoPayloadClick(Nil);
+  if Assigned(FWalletKeys) then begin
+    FOldOnChanged := FWalletKeys.OnChanged;
+    FWalletKeys.OnChanged := OnWalletKeysChanged;
+  end;
+  UpdateWalletKeys;
 end;
 end;
 
 
 procedure TFRMOperation.UpdateAccountsInfo;
 procedure TFRMOperation.UpdateAccountsInfo;
@@ -598,7 +603,9 @@ begin
         tsGlobalError.tabvisible := {$IFDEF LINUX}true{$ELSE}false{$ENDIF};
         tsGlobalError.tabvisible := {$IFDEF LINUX}true{$ELSE}false{$ENDIF};
         tsOperation.TabVisible := false;
         tsOperation.TabVisible := false;
         PageControl.ActivePage := tsGlobalError;
         PageControl.ActivePage := tsGlobalError;
-        ActiveControl := bbPassword;
+        if bbPassword.CanFocus then begin
+          ActiveControl := bbPassword;
+        end;
       end else begin
       end else begin
         tsOperation.visible := true;
         tsOperation.visible := true;
         tsOperation.tabvisible := {$IFDEF LINUX}true{$ELSE}false{$ENDIF};
         tsOperation.tabvisible := {$IFDEF LINUX}true{$ELSE}false{$ENDIF};
@@ -805,4 +812,30 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TFRMOperation.UpdateWalletKeys;
+Var i : Integer;
+  wk : TWalletKey;
+  s : String;
+begin
+  cbNewPrivateKey.items.BeginUpdate;
+  Try
+    cbNewPrivateKey.Items.Clear;
+    //cbNewPrivateKey.Items.AddObject('Generate a new Private Key',TObject(-1));
+    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 Not Assigned(wk.PrivateKey) then s := s + '(*)';
+      cbNewPrivateKey.Items.AddObject(s,TObject(i));
+    end;
+  Finally
+    cbNewPrivateKey.Items.EndUpdate;
+  End;
+  rbTransactionClick(Nil);
+  memoPayloadClick(Nil);
+end;
+
 end.
 end.

+ 51 - 13
Units/Forms/UFRMPascalCoinWalletConfig.dfm

@@ -4,7 +4,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   BorderStyle = bsSingle
   BorderStyle = bsSingle
   Caption = 'Options'
   Caption = 'Options'
-  ClientHeight = 460
+  ClientHeight = 476
   ClientWidth = 374
   ClientWidth = 374
   Color = clBtnFace
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Charset = DEFAULT_CHARSET
@@ -86,7 +86,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 56
     Width = 56
     Height = 21
     Height = 21
     Alignment = taRightJustify
     Alignment = taRightJustify
-    TabOrder = 7
+    TabOrder = 8
     Text = '0'
     Text = '0'
   end
   end
   object cbSaveLogFiles: TCheckBox
   object cbSaveLogFiles: TCheckBox
@@ -95,7 +95,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 97
     Width = 97
     Height = 17
     Height = 17
     Caption = 'Save log file'
     Caption = 'Save log file'
-    TabOrder = 8
+    TabOrder = 9
     OnClick = cbSaveLogFilesClick
     OnClick = cbSaveLogFilesClick
   end
   end
   object cbShowLogs: TCheckBox
   object cbShowLogs: TCheckBox
@@ -104,28 +104,28 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 97
     Width = 97
     Height = 17
     Height = 17
     Caption = 'Show logs'
     Caption = 'Show logs'
-    TabOrder = 10
+    TabOrder = 11
   end
   end
   object bbOk: TBitBtn
   object bbOk: TBitBtn
-    Left = 171
-    Top = 410
+    Left = 176
+    Top = 420
     Width = 75
     Width = 75
     Height = 25
     Height = 25
     DoubleBuffered = True
     DoubleBuffered = True
     Kind = bkOK
     Kind = bkOK
     ParentDoubleBuffered = False
     ParentDoubleBuffered = False
-    TabOrder = 11
+    TabOrder = 14
     OnClick = bbOkClick
     OnClick = bbOkClick
   end
   end
   object bbCancel: TBitBtn
   object bbCancel: TBitBtn
-    Left = 261
-    Top = 410
+    Left = 266
+    Top = 420
     Width = 75
     Width = 75
     Height = 25
     Height = 25
     DoubleBuffered = True
     DoubleBuffered = True
     Kind = bkCancel
     Kind = bkCancel
     ParentDoubleBuffered = False
     ParentDoubleBuffered = False
-    TabOrder = 12
+    TabOrder = 15
   end
   end
   object udInternetServerPort: TUpDown
   object udInternetServerPort: TUpDown
     Left = 226
     Left = 226
@@ -232,7 +232,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 171
     Width = 171
     Height = 17
     Height = 17
     Caption = 'Show modal messages'
     Caption = 'Show modal messages'
-    TabOrder = 13
+    TabOrder = 12
   end
   end
   object udJSONRPCMinerServerPort: TUpDown
   object udJSONRPCMinerServerPort: TUpDown
     Left = 226
     Left = 226
@@ -261,7 +261,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 334
     Width = 334
     Height = 121
     Height = 121
     Caption = ' Miner Server Private Key: '
     Caption = ' Miner Server Private Key: '
-    TabOrder = 14
+    TabOrder = 7
     object rbGenerateANewPrivateKeyEachBlock: TRadioButton
     object rbGenerateANewPrivateKeyEachBlock: TRadioButton
       Left = 20
       Left = 20
       Top = 20
       Top = 20
@@ -301,6 +301,44 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 97
     Width = 97
     Height = 17
     Height = 17
     Caption = 'Save debug logs too'
     Caption = 'Save debug logs too'
-    TabOrder = 9
+    TabOrder = 10
+  end
+  object bbOpenDataFolder: TBitBtn
+    Left = 15
+    Top = 420
+    Width = 120
+    Height = 25
+    Caption = 'Open Data folder'
+    DoubleBuffered = True
+    Glyph.Data = {
+      36030000424D3603000000000000360000002800000010000000100000000100
+      18000000000000030000120B0000120B00000000000000000000FF00FF078DBE
+      078DBE078DBE078DBE078DBE078DBE078DBE078DBE078DBE078DBE078DBE078D
+      BEFF00FFFF00FFFF00FF078DBE25A1D171C6E884D7FA66CDF965CDF965CDF965
+      CDF965CDF865CDF965CDF866CEF93AADD81999C9FF00FFFF00FF078DBE4CBCE7
+      39A8D1A0E2FB6FD4FA6FD4F96ED4FA6FD4F96FD4FA6FD4FA6FD4FA6ED4F93EB1
+      D9C9F0F3078DBEFF00FF078DBE72D6FA078DBEAEE9FC79DCFB79DCFB79DCFB79
+      DCFB79DCFB7ADCFB79DCFA79DCFA44B5D9C9F0F3078DBEFF00FF078DBE79DDFB
+      1899C79ADFF392E7FC84E4FB83E4FC83E4FC84E4FC83E4FC83E4FB84E5FC48B9
+      DAC9F0F31496C4FF00FF078DBE82E3FC43B7DC65C2E0ABF0FC8DEBFC8DEBFC8D
+      EBFD8DEBFD8DEBFC8DEBFD8DEBFC4CBBDAC9F0F3C9F0F3078DBE078DBE8AEAFC
+      77DCF3219CC7FEFFFFC8F7FDC9F7FDC9F7FDC9F7FEC8F7FEC9F7FDC8F7FE9BD5
+      E6EAFEFED2F3F8078DBE078DBE93F0FE93F0FD1697C5078DBE078DBE078DBE07
+      8DBE078DBE078DBE078DBE078DBE078DBE078DBE078DBE078DBE078DBE9BF5FE
+      9AF6FE9AF6FE9BF5FD9BF6FE9AF6FE9BF5FE9AF6FD9BF5FE9AF6FE9AF6FE0989
+      BAFF00FFFF00FFFF00FF078DBEFEFEFEA0FBFFA0FBFEA0FBFEA1FAFEA1FBFEA0
+      FAFEA1FBFEA1FBFFA0FBFFA1FBFF0989BAFF00FFFF00FFFF00FFFF00FF078DBE
+      FEFEFEA5FEFFA5FEFFA5FEFF078DBE078DBE078DBE078DBE078DBE078DBEFF00
+      FFFF00FFFF00FFFF00FFFF00FFFF00FF078DBE078DBE078DBE078DBEFF00FFFF
+      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+      FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+      FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+      00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF}
+    ParentDoubleBuffered = False
+    TabOrder = 13
+    OnClick = bbOpenDataFolderClick
   end
   end
 end
 end

+ 61 - 16
Units/Forms/UFRMPascalCoinWalletConfig.lfm

@@ -1,12 +1,12 @@
 object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
 object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
   Left = 462
   Left = 462
-  Height = 460
+  Height = 479
   Top = 234
   Top = 234
   Width = 374
   Width = 374
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   BorderStyle = bsSingle
   BorderStyle = bsSingle
   Caption = 'Options'
   Caption = 'Options'
-  ClientHeight = 460
+  ClientHeight = 479
   ClientWidth = 374
   ClientWidth = 374
   Color = clBtnFace
   Color = clBtnFace
   Font.Color = clWindowText
   Font.Color = clWindowText
@@ -89,7 +89,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Top = 332
     Top = 332
     Width = 56
     Width = 56
     Alignment = taRightJustify
     Alignment = taRightJustify
-    TabOrder = 7
+    TabOrder = 8
     Text = '0'
     Text = '0'
   end
   end
   object cbSaveLogFiles: TCheckBox
   object cbSaveLogFiles: TCheckBox
@@ -99,7 +99,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Width = 78
     Width = 78
     Caption = 'Save log file'
     Caption = 'Save log file'
     OnClick = cbSaveLogFilesClick
     OnClick = cbSaveLogFilesClick
-    TabOrder = 8
+    TabOrder = 9
   end
   end
   object cbShowLogs: TCheckBox
   object cbShowLogs: TCheckBox
     Left = 15
     Left = 15
@@ -107,26 +107,26 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Top = 397
     Top = 397
     Width = 68
     Width = 68
     Caption = 'Show logs'
     Caption = 'Show logs'
-    TabOrder = 10
+    TabOrder = 11
   end
   end
   object bbOk: TBitBtn
   object bbOk: TBitBtn
-    Left = 171
-    Height = 25
-    Top = 410
+    Left = 184
+    Height = 30
+    Top = 432
     Width = 75
     Width = 75
     Kind = bkOK
     Kind = bkOK
     OnClick = bbOkClick
     OnClick = bbOkClick
-    TabOrder = 11
+    TabOrder = 14
   end
   end
   object bbCancel: TBitBtn
   object bbCancel: TBitBtn
-    Left = 261
-    Height = 25
-    Top = 410
+    Left = 274
+    Height = 30
+    Top = 432
     Width = 75
     Width = 75
     Cancel = True
     Cancel = True
     Kind = bkCancel
     Kind = bkCancel
     ModalResult = 2
     ModalResult = 2
-    TabOrder = 12
+    TabOrder = 15
   end
   end
   object udInternetServerPort: TUpDown
   object udInternetServerPort: TUpDown
     Left = 226
     Left = 226
@@ -232,7 +232,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Top = 359
     Top = 359
     Width = 127
     Width = 127
     Caption = 'Show modal messages'
     Caption = 'Show modal messages'
-    TabOrder = 13
+    TabOrder = 12
   end
   end
   object udJSONRPCMinerServerPort: TUpDown
   object udJSONRPCMinerServerPort: TUpDown
     Left = 226
     Left = 226
@@ -264,7 +264,7 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Caption = ' Miner Server Private Key: '
     Caption = ' Miner Server Private Key: '
     ClientHeight = 103
     ClientHeight = 103
     ClientWidth = 330
     ClientWidth = 330
-    TabOrder = 14
+    TabOrder = 7
     object rbGenerateANewPrivateKeyEachBlock: TRadioButton
     object rbGenerateANewPrivateKeyEachBlock: TRadioButton
       Left = 18
       Left = 18
       Height = 19
       Height = 19
@@ -305,6 +305,51 @@ object FRMPascalCoinWalletConfig: TFRMPascalCoinWalletConfig
     Top = 377
     Top = 377
     Width = 118
     Width = 118
     Caption = 'Save debug logs too'
     Caption = 'Save debug logs too'
-    TabOrder = 9
+    TabOrder = 10
+  end
+  object bbOpenDataFolder: TBitBtn
+    Left = 16
+    Height = 30
+    Top = 432
+    Width = 131
+    Caption = 'Open Data Folder'
+    Glyph.Data = {
+      36040000424D3604000000000000360000002800000010000000100000000100
+      2000000000000004000064000000640000000000000000000000078DBE4D078D
+      BEFF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF078D
+      BEFF078DBEFF078DBEFF078DBEFF078DBEFFFFFFFF00FFFFFF00078DBEFF25A1
+      D1FF70C6E7FF6BCFF9FF66CDF9FF65CDF9FF65CDF9FF65CDF9FF65CDF8FF65CD
+      F9FF65CDF8FF66CEF9FF39ADD8FF078DBEFF078DBE4DFFFFFF00078DBEFF4CBC
+      E7FF5EB8DAFF94DFFBFF6FD4FAFF6FD4F9FF6ED4FAFF6FD4F9FF6FD4FAFF6FD4
+      FAFF6FD4FAFF6ED4F9FF3EB1D9FF84D7EBFF078DBEFFFFFFFF00078DBEFF72D6
+      FAFF1593C2FFB6ECFDFF7DDDFBFF79DCFBFF79DCFBFF79DCFBFF79DCFBFF7ADC
+      FBFF79DCFAFF79DCFAFF44B5D9FFAEF1F9FF078DBEFFFFFFFF00078DBEFF79DD
+      FBFF1899C7FF94DDF3FFA2EBFCFF84E4FBFF83E4FCFF83E4FCFF84E4FCFF83E4
+      FCFF83E4FBFF84E5FCFF48B9DAFFB3F4F9FF078DBEFF078DBE4D078DBEFF82E3
+      FCFF43B7DCFF4BB9DBFFBFF4FDFF8EEBFCFF8DEBFCFF8DEBFDFF8DEBFDFF8DEB
+      FCFF8DEBFDFF8DEBFCFF4CBBDAFFB6F7F9FF6DCAE0FF078DBEFF078DBEFF8AEA
+      FCFF77DCF3FF1496C3FFFFFFFFFFC9F8FEFFC9F8FEFFC9F8FEFFC9F8FFFFC9F7
+      FFFFC9F8FEFFC9F8FFFF9CD6E7FFDFFAFBFFDBF7FAFF078DBEFF078DBEFF93F0
+      FEFF93F0FDFF1697C5FF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF078D
+      BEFF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF078DBEFF9BF5
+      FEFF9AF6FEFF9AF6FEFF9BF5FDFF9BF6FEFF9AF6FEFF9BF5FEFF9AF6FDFF9BF5
+      FEFF9AF6FEFF9AF6FEFF0989BAFFFFFFFF00FFFFFF00FFFFFF00078DBEFFFEFE
+      FEFFA0FBFFFFA0FBFEFFA0FBFEFFA1FAFEFFA1FBFEFFA0FAFEFFA1FBFEFFA1FB
+      FFFFA0FBFFFFA1FBFFFF0989BAFFFFFFFF00FFFFFF00FFFFFF00078DBE4D078D
+      BEFFFEFEFEFFA5FEFFFFA5FEFFFFA5FEFFFF078DBEFF078DBEFF078DBEFF078D
+      BEFF078DBEFF078DBEFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00078D
+      BE4D078DBEFF078DBEFF078DBEFF078DBEFF078DBE4DFFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+    }
+    OnClick = bbOpenDataFolderClick
+    TabOrder = 13
   end
   end
 end
 end

+ 16 - 1
Units/Forms/UFRMPascalCoinWalletConfig.pas

@@ -22,6 +22,7 @@ interface
 uses
 uses
 {$IFnDEF FPC}
 {$IFnDEF FPC}
   Windows,
   Windows,
+  ShellApi,
 {$ELSE}
 {$ELSE}
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
 {$ENDIF}
 {$ENDIF}
@@ -29,6 +30,9 @@ uses
   Dialogs, StdCtrls, Buttons, ComCtrls, UAppParams, UWalletKeys;
   Dialogs, StdCtrls, Buttons, ComCtrls, UAppParams, UWalletKeys;
 
 
 type
 type
+
+  { TFRMPascalCoinWalletConfig }
+
   TFRMPascalCoinWalletConfig = class(TForm)
   TFRMPascalCoinWalletConfig = class(TForm)
     cbJSONRPCMinerServerActive: TCheckBox;
     cbJSONRPCMinerServerActive: TCheckBox;
     ebDefaultFee: TEdit;
     ebDefaultFee: TEdit;
@@ -56,10 +60,12 @@ type
     rbMineAllwaysWithThisKey: TRadioButton;
     rbMineAllwaysWithThisKey: TRadioButton;
     cbPrivateKeyToMine: TComboBox;
     cbPrivateKeyToMine: TComboBox;
     cbSaveDebugLogs: TCheckBox;
     cbSaveDebugLogs: TCheckBox;
+    bbOpenDataFolder: TBitBtn;
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure bbOkClick(Sender: TObject);
     procedure bbOkClick(Sender: TObject);
     procedure bbUpdatePasswordClick(Sender: TObject);
     procedure bbUpdatePasswordClick(Sender: TObject);
     procedure cbSaveLogFilesClick(Sender: TObject);
     procedure cbSaveLogFilesClick(Sender: TObject);
+    procedure bbOpenDataFolderClick(Sender: TObject);
   private
   private
     FAppParams: TAppParams;
     FAppParams: TAppParams;
     FWalletKeys: TWalletKeys;
     FWalletKeys: TWalletKeys;
@@ -75,7 +81,7 @@ type
 
 
 implementation
 implementation
 
 
-uses UConst, UAccounts, ULog, UCrypto, UMiner;
+uses UConst, UAccounts, ULog, UCrypto, UMiner, UFolderHelper;
 
 
 {$IFnDEF FPC}
 {$IFnDEF FPC}
   {$R *.dfm}
   {$R *.dfm}
@@ -118,6 +124,15 @@ begin
   ModalResult := MrOk;
   ModalResult := MrOk;
 end;
 end;
 
 
+procedure TFRMPascalCoinWalletConfig.bbOpenDataFolderClick(Sender: TObject);
+begin
+  {$IFDEF FPC}
+  OpenDocument(pchar(TFolderHelper.GetPascalCoinDataFolder))
+  {$ELSE}
+  shellexecute(0, 'open', pchar(TFolderHelper.GetPascalCoinDataFolder), nil, nil, SW_SHOW)
+  {$ENDIF}
+end;
+
 procedure TFRMPascalCoinWalletConfig.bbUpdatePasswordClick(Sender: TObject);
 procedure TFRMPascalCoinWalletConfig.bbUpdatePasswordClick(Sender: TObject);
 Var s,s2 : String;
 Var s,s2 : String;
 begin
 begin

+ 87 - 69
Units/Forms/UFRMPayloadDecoder.lfm

@@ -1,6 +1,8 @@
 object FRMPayloadDecoder: TFRMPayloadDecoder
 object FRMPayloadDecoder: TFRMPayloadDecoder
-  Left = 0
-  Top = 0
+  Left = 344
+  Height = 406
+  Top = 184
+  Width = 674
   ActiveControl = ebOphash
   ActiveControl = ebOphash
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   BorderStyle = bsSingle
   BorderStyle = bsSingle
@@ -8,303 +10,317 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
   ClientHeight = 406
   ClientHeight = 406
   ClientWidth = 674
   ClientWidth = 674
   Color = clBtnFace
   Color = clBtnFace
-  Font.Charset = DEFAULT_CHARSET
   Font.Color = clWindowText
   Font.Color = clWindowText
   Font.Height = -11
   Font.Height = -11
   Font.Name = 'Tahoma'
   Font.Name = 'Tahoma'
-  Font.Style = []
-  Position = poOwnerFormCenter
   OnCreate = FormCreate
   OnCreate = FormCreate
-  PixelsPerInch = 96
+  Position = poOwnerFormCenter
+  LCLVersion = '1.6.0.4'
   object Label1: TLabel
   object Label1: TLabel
     Left = 20
     Left = 20
+    Height = 13
     Top = 56
     Top = 56
     Width = 46
     Width = 46
-    Height = 13
     Caption = 'Block/Op:'
     Caption = 'Block/Op:'
+    ParentColor = False
   end
   end
   object lblBlock: TLabel
   object lblBlock: TLabel
     Left = 72
     Left = 72
+    Height = 19
     Top = 51
     Top = 51
     Width = 109
     Width = 109
-    Height = 19
     Caption = '000000/0000'
     Caption = '000000/0000'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object lblDateTime: TLabel
   object lblDateTime: TLabel
     Left = 255
     Left = 255
+    Height = 19
     Top = 51
     Top = 51
     Width = 30
     Width = 30
-    Height = 19
     Caption = '000'
     Caption = '000'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object Label6: TLabel
   object Label6: TLabel
     Left = 195
     Left = 195
+    Height = 13
     Top = 56
     Top = 56
     Width = 52
     Width = 52
-    Height = 13
     Caption = 'Date Time:'
     Caption = 'Date Time:'
+    ParentColor = False
   end
   end
   object Label2: TLabel
   object Label2: TLabel
     Left = 20
     Left = 20
+    Height = 13
     Top = 106
     Top = 106
     Width = 52
     Width = 52
-    Height = 13
     Caption = 'Operation:'
     Caption = 'Operation:'
+    ParentColor = False
   end
   end
   object lblOperationTxt: TLabel
   object lblOperationTxt: TLabel
     Left = 90
     Left = 90
+    Height = 22
     Top = 101
     Top = 101
     Width = 561
     Width = 561
-    Height = 22
     AutoSize = False
     AutoSize = False
     Caption = '000'
     Caption = '000'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
     WordWrap = True
     WordWrap = True
   end
   end
   object lblAmountCaption: TLabel
   object lblAmountCaption: TLabel
     Left = 220
     Left = 220
+    Height = 13
     Top = 81
     Top = 81
     Width = 41
     Width = 41
-    Height = 13
     Caption = 'Amount:'
     Caption = 'Amount:'
+    ParentColor = False
   end
   end
   object lblAmount: TLabel
   object lblAmount: TLabel
     Left = 270
     Left = 270
+    Height = 19
     Top = 76
     Top = 76
     Width = 30
     Width = 30
-    Height = 19
     Caption = '000'
     Caption = '000'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object lblFeeCaption: TLabel
   object lblFeeCaption: TLabel
     Left = 517
     Left = 517
+    Height = 13
     Top = 56
     Top = 56
     Width = 22
     Width = 22
-    Height = 13
     Caption = 'Fee:'
     Caption = 'Fee:'
+    ParentColor = False
   end
   end
   object lblFee: TLabel
   object lblFee: TLabel
     Left = 547
     Left = 547
+    Height = 19
     Top = 51
     Top = 51
     Width = 30
     Width = 30
-    Height = 19
     Caption = '000'
     Caption = '000'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object Label4: TLabel
   object Label4: TLabel
     Left = 20
     Left = 20
+    Height = 13
     Top = 24
     Top = 24
     Width = 38
     Width = 38
-    Height = 13
     Caption = 'OpHash'
     Caption = 'OpHash'
+    ParentColor = False
   end
   end
   object lblSenderCaption: TLabel
   object lblSenderCaption: TLabel
     Left = 20
     Left = 20
+    Height = 13
     Top = 81
     Top = 81
     Width = 38
     Width = 38
-    Height = 13
     Caption = 'Sender:'
     Caption = 'Sender:'
+    ParentColor = False
   end
   end
   object lblSender: TLabel
   object lblSender: TLabel
     Left = 64
     Left = 64
+    Height = 19
     Top = 76
     Top = 76
     Width = 97
     Width = 97
-    Height = 19
     Caption = '9999999-99'
     Caption = '9999999-99'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object lblReceiverCaption: TLabel
   object lblReceiverCaption: TLabel
     Left = 411
     Left = 411
+    Height = 13
     Top = 81
     Top = 81
     Width = 46
     Width = 46
-    Height = 13
     Caption = 'Receiver:'
     Caption = 'Receiver:'
+    ParentColor = False
   end
   end
   object lblReceiver: TLabel
   object lblReceiver: TLabel
     Left = 463
     Left = 463
+    Height = 19
     Top = 76
     Top = 76
     Width = 30
     Width = 30
-    Height = 19
     Caption = '000'
     Caption = '000'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object lblReceiverInfo: TLabel
   object lblReceiverInfo: TLabel
     Left = 481
     Left = 481
+    Height = 19
     Top = 50
     Top = 50
     Width = 121
     Width = 121
-    Height = 19
     Caption = '(Receiver info)'
     Caption = '(Receiver info)'
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clRed
     Font.Color = clRed
     Font.Height = -16
     Font.Height = -16
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    ParentColor = False
     ParentFont = False
     ParentFont = False
   end
   end
   object PageControl: TPageControl
   object PageControl: TPageControl
     Left = 20
     Left = 20
+    Height = 206
     Top = 140
     Top = 140
     Width = 631
     Width = 631
-    Height = 206
     ActivePage = tsDecoded
     ActivePage = tsDecoded
+    TabIndex = 0
     TabOrder = 2
     TabOrder = 2
     OnChanging = PageControlChanging
     OnChanging = PageControlChanging
     object tsDecoded: TTabSheet
     object tsDecoded: TTabSheet
       Caption = 'Payload'
       Caption = 'Payload'
+      ClientHeight = 180
+      ClientWidth = 623
       object Label7: TLabel
       object Label7: TLabel
         Left = 15
         Left = 15
+        Height = 13
         Top = 94
         Top = 94
         Width = 87
         Width = 87
-        Height = 13
         Caption = 'Decoded Payload:'
         Caption = 'Decoded Payload:'
+        ParentColor = False
       end
       end
       object lblDecodedMethod: TLabel
       object lblDecodedMethod: TLabel
-        Left = 562
-        Top = 94
-        Width = 44
+        Left = 192
         Height = 13
         Height = 13
+        Top = 94
+        Width = 414
         Alignment = taRightJustify
         Alignment = taRightJustify
+        AutoSize = False
         Caption = '(Method)'
         Caption = '(Method)'
-        Font.Charset = DEFAULT_CHARSET
         Font.Color = clGray
         Font.Color = clGray
         Font.Height = -11
         Font.Height = -11
         Font.Name = 'Tahoma'
         Font.Name = 'Tahoma'
-        Font.Style = []
+        ParentColor = False
         ParentFont = False
         ParentFont = False
       end
       end
       object Label3: TLabel
       object Label3: TLabel
         Left = 15
         Left = 15
+        Height = 13
         Top = 9
         Top = 9
         Width = 155
         Width = 155
-        Height = 13
         Caption = 'Original Payload in Hexadecimal:'
         Caption = 'Original Payload in Hexadecimal:'
+        ParentColor = False
       end
       end
       object memoDecoded: TMemo
       object memoDecoded: TMemo
         Left = 15
         Left = 15
+        Height = 55
         Top = 111
         Top = 111
         Width = 591
         Width = 591
-        Height = 55
-        TabStop = False
-        Font.Charset = DEFAULT_CHARSET
         Font.Color = clBlack
         Font.Color = clBlack
         Font.Height = -13
         Font.Height = -13
         Font.Name = 'Tahoma'
         Font.Name = 'Tahoma'
         Font.Style = [fsBold]
         Font.Style = [fsBold]
         Lines.Strings = (
         Lines.Strings = (
-          'memoDecoded')
+          'memoDecoded'
+        )
+        OnKeyDown = memoDecodedKeyDown
         ParentFont = False
         ParentFont = False
         ReadOnly = True
         ReadOnly = True
         TabOrder = 0
         TabOrder = 0
-        OnKeyDown = memoDecodedKeyDown
+        TabStop = False
       end
       end
       object memoOriginalPayloadInHexa: TMemo
       object memoOriginalPayloadInHexa: TMemo
         Left = 15
         Left = 15
+        Height = 55
         Top = 28
         Top = 28
         Width = 591
         Width = 591
-        Height = 55
-        TabStop = False
         Color = clBtnFace
         Color = clBtnFace
-        Font.Charset = DEFAULT_CHARSET
         Font.Color = clBlack
         Font.Color = clBlack
         Font.Height = -13
         Font.Height = -13
         Font.Name = 'Tahoma'
         Font.Name = 'Tahoma'
         Font.Style = [fsBold]
         Font.Style = [fsBold]
         Lines.Strings = (
         Lines.Strings = (
-          'memoDecoded')
+          'memoDecoded'
+        )
+        OnKeyDown = memoDecodedKeyDown
         ParentFont = False
         ParentFont = False
         ReadOnly = True
         ReadOnly = True
         TabOrder = 1
         TabOrder = 1
-        OnKeyDown = memoDecodedKeyDown
+        TabStop = False
       end
       end
     end
     end
     object tsDecodeMethods: TTabSheet
     object tsDecodeMethods: TTabSheet
       Caption = 'Decode methods'
       Caption = 'Decode methods'
+      ClientHeight = 0
+      ClientWidth = 0
       ImageIndex = 1
       ImageIndex = 1
       object lblPasswordsInfo: TLabel
       object lblPasswordsInfo: TLabel
         Left = 235
         Left = 235
+        Height = 13
         Top = 162
         Top = 162
         Width = 81
         Width = 81
-        Height = 13
         Caption = 'lblPasswordsInfo'
         Caption = 'lblPasswordsInfo'
+        ParentColor = False
       end
       end
       object cbMethodPublicPayload: TCheckBox
       object cbMethodPublicPayload: TCheckBox
         Left = 16
         Left = 16
+        Height = 17
         Top = 15
         Top = 15
         Width = 225
         Width = 225
-        Height = 17
         Caption = 'Not encrypted (Public payload)'
         Caption = 'Not encrypted (Public payload)'
-        TabOrder = 0
         OnClick = cbMethodPublicPayloadClick
         OnClick = cbMethodPublicPayloadClick
+        TabOrder = 0
       end
       end
       object cbUsingPrivateKeys: TCheckBox
       object cbUsingPrivateKeys: TCheckBox
         Left = 16
         Left = 16
+        Height = 17
         Top = 38
         Top = 38
         Width = 225
         Width = 225
-        Height = 17
         Caption = 'Using Private keys of my Wallet'
         Caption = 'Using Private keys of my Wallet'
-        TabOrder = 1
         OnClick = cbMethodPublicPayloadClick
         OnClick = cbMethodPublicPayloadClick
+        TabOrder = 1
       end
       end
       object cbUsingPasswords: TCheckBox
       object cbUsingPasswords: TCheckBox
         Left = 16
         Left = 16
+        Height = 17
         Top = 61
         Top = 61
         Width = 225
         Width = 225
-        Height = 17
         Caption = 'Using Passwords of the list'
         Caption = 'Using Passwords of the list'
-        TabOrder = 2
         OnClick = cbMethodPublicPayloadClick
         OnClick = cbMethodPublicPayloadClick
+        TabOrder = 2
       end
       end
       object memoPasswords: TMemo
       object memoPasswords: TMemo
         Left = 235
         Left = 235
+        Height = 146
         Top = 10
         Top = 10
         Width = 371
         Width = 371
-        Height = 146
+        OnChange = cbMethodPublicPayloadClick
         ScrollBars = ssBoth
         ScrollBars = ssBoth
         TabOrder = 3
         TabOrder = 3
-        OnChange = cbMethodPublicPayloadClick
       end
       end
       object bbSaveMethods: TBitBtn
       object bbSaveMethods: TBitBtn
         Left = 60
         Left = 60
+        Height = 25
         Top = 110
         Top = 110
         Width = 75
         Width = 75
-        Height = 25
         Caption = 'Save'
         Caption = 'Save'
         Glyph.Data = {
         Glyph.Data = {
           DE010000424DDE01000000000000760000002800000024000000120000000100
           DE010000424DDE01000000000000760000002800000024000000120000000100
@@ -322,18 +338,19 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
           33333333A222433333333333338F338F00003333333333333A22433333333333
           33333333A222433333333333338F338F00003333333333333A22433333333333
           3338F38F000033333333333333A223333333333333338F830000333333333333
           3338F38F000033333333333333A223333333333333338F830000333333333333
           333A333333333333333338330000333333333333333333333333333333333333
           333A333333333333333338330000333333333333333333333333333333333333
-          0000}
+          0000
+        }
         NumGlyphs = 2
         NumGlyphs = 2
-        TabOrder = 4
         OnClick = bbSaveMethodsClick
         OnClick = bbSaveMethodsClick
+        TabOrder = 4
       end
       end
     end
     end
   end
   end
   object bbClose: TBitBtn
   object bbClose: TBitBtn
     Left = 572
     Left = 572
+    Height = 25
     Top = 362
     Top = 362
     Width = 79
     Width = 79
-    Height = 25
     Cancel = True
     Cancel = True
     Caption = 'Close'
     Caption = 'Close'
     Glyph.Data = {
     Glyph.Data = {
@@ -348,16 +365,17 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
       55557775555777FF5555555555599905555555555557777F5555555555559905
       55557775555777FF5555555555599905555555555557777F5555555555559905
       555555555555777FF5555555555559905555555555555777FF55555555555579
       555555555555777FF5555555555559905555555555555777FF55555555555579
       05555555555555777FF5555555555557905555555555555777FF555555555555
       05555555555555777FF5555555555557905555555555555777FF555555555555
-      5990555555555555577755555555555555555555555555555555}
+      5990555555555555577755555555555555555555555555555555
+    }
     ModalResult = 2
     ModalResult = 2
     NumGlyphs = 2
     NumGlyphs = 2
     TabOrder = 3
     TabOrder = 3
   end
   end
   object bbFind: TBitBtn
   object bbFind: TBitBtn
     Left = 599
     Left = 599
+    Height = 25
     Top = 19
     Top = 19
     Width = 52
     Width = 52
-    Height = 25
     Caption = '&Find'
     Caption = '&Find'
     Glyph.Data = {
     Glyph.Data = {
       36030000424D3603000000000000360000002800000010000000100000000100
       36030000424D3603000000000000360000002800000010000000100000000100
@@ -385,25 +403,25 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
       DEDDFFFEF2F9D8A3F4C48CF9D49FFDEAB8D0B49FB89086FF00FFFF00FFFF00FF
       DEDDFFFEF2F9D8A3F4C48CF9D49FFDEAB8D0B49FB89086FF00FFFF00FFFF00FF
       FF00FFFF00FFFF00FFFF00FFFF00FFAD827FC9AA9EEFE0B7EFDFB2E7CEACB890
       FF00FFFF00FFFF00FFFF00FFFF00FFAD827FC9AA9EEFE0B7EFDFB2E7CEACB890
       86B89086FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
       86B89086FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-      00FFFF00FFBA968ABB988CB79188FF00FFFF00FFFF00FFFF00FF}
+      00FFFF00FFBA968ABB988CB79188FF00FFFF00FFFF00FFFF00FF
+    }
+    OnClick = bbFindClick
     TabOrder = 1
     TabOrder = 1
     TabStop = False
     TabStop = False
-    OnClick = bbFindClick
   end
   end
   object ebOphash: TEdit
   object ebOphash: TEdit
     Left = 64
     Left = 64
+    Height = 22
     Top = 20
     Top = 20
     Width = 529
     Width = 529
-    Height = 22
-    Font.Charset = DEFAULT_CHARSET
     Font.Color = clWindowText
     Font.Color = clWindowText
     Font.Height = -12
     Font.Height = -12
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
+    OnExit = ebOphashExit
+    OnKeyPress = ebOphashKeyPress
     ParentFont = False
     ParentFont = False
     TabOrder = 0
     TabOrder = 0
     Text = '12345678901234567890123456789012345678901234567890123456789012'
     Text = '12345678901234567890123456789012345678901234567890123456789012'
-    OnExit = ebOphashExit
-    OnKeyPress = ebOphashKeyPress
   end
   end
 end
 end

+ 38 - 2
Units/Forms/UFRMWallet.dfm

@@ -368,12 +368,16 @@ object FRMWallet: TFRMWallet
     Top = 91
     Top = 91
     Width = 849
     Width = 849
     Height = 432
     Height = 432
-    ActivePage = tsMyAccounts
+    ActivePage = tsNodeStats
     Align = alClient
     Align = alClient
     TabOrder = 2
     TabOrder = 2
     OnChange = PageControlChange
     OnChange = PageControlChange
     object tsMyAccounts: TTabSheet
     object tsMyAccounts: TTabSheet
       Caption = 'Accounts Explorer'
       Caption = 'Accounts Explorer'
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object Splitter1: TSplitter
       object Splitter1: TSplitter
         Left = 380
         Left = 380
         Top = 66
         Top = 66
@@ -579,6 +583,10 @@ object FRMWallet: TFRMWallet
         TabOrder = 2
         TabOrder = 2
         object tsAccountOperations: TTabSheet
         object tsAccountOperations: TTabSheet
           Caption = 'Operations of selected Account'
           Caption = 'Operations of selected Account'
+          ExplicitLeft = 0
+          ExplicitTop = 0
+          ExplicitWidth = 0
+          ExplicitHeight = 0
           object dgAccountOperations: TDrawGrid
           object dgAccountOperations: TDrawGrid
             Left = 0
             Left = 0
             Top = 0
             Top = 0
@@ -598,6 +606,10 @@ object FRMWallet: TFRMWallet
         object tsMultiSelectAccounts: TTabSheet
         object tsMultiSelectAccounts: TTabSheet
           Caption = 'Selected accounts for massive operations'
           Caption = 'Selected accounts for massive operations'
           ImageIndex = 1
           ImageIndex = 1
+          ExplicitLeft = 0
+          ExplicitTop = 0
+          ExplicitWidth = 0
+          ExplicitHeight = 0
           object dgSelectedAccounts: TDrawGrid
           object dgSelectedAccounts: TDrawGrid
             Left = 41
             Left = 41
             Top = 31
             Top = 31
@@ -787,6 +799,10 @@ object FRMWallet: TFRMWallet
     object tsPendingOperations: TTabSheet
     object tsPendingOperations: TTabSheet
       Caption = 'Pending Operations'
       Caption = 'Pending Operations'
       ImageIndex = 5
       ImageIndex = 5
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object dgPendingOperations: TDrawGrid
       object dgPendingOperations: TDrawGrid
         Left = 0
         Left = 0
         Top = 86
         Top = 86
@@ -834,6 +850,10 @@ object FRMWallet: TFRMWallet
     object tsBlockChain: TTabSheet
     object tsBlockChain: TTabSheet
       Caption = 'BlockChain Explorer'
       Caption = 'BlockChain Explorer'
       ImageIndex = 1
       ImageIndex = 1
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object Panel2: TPanel
       object Panel2: TPanel
         Left = 0
         Left = 0
         Top = 0
         Top = 0
@@ -879,6 +899,10 @@ object FRMWallet: TFRMWallet
     object tsOperations: TTabSheet
     object tsOperations: TTabSheet
       Caption = 'Operations Explorer'
       Caption = 'Operations Explorer'
       ImageIndex = 1
       ImageIndex = 1
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object Panel1: TPanel
       object Panel1: TPanel
         Left = 0
         Left = 0
         Top = 0
         Top = 0
@@ -924,6 +948,10 @@ object FRMWallet: TFRMWallet
     object tsLogs: TTabSheet
     object tsLogs: TTabSheet
       Caption = 'Logs'
       Caption = 'Logs'
       ImageIndex = 2
       ImageIndex = 2
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object pnlTopLogs: TPanel
       object pnlTopLogs: TPanel
         Left = 0
         Left = 0
         Top = 0
         Top = 0
@@ -953,6 +981,10 @@ object FRMWallet: TFRMWallet
     object tsNodeStats: TTabSheet
     object tsNodeStats: TTabSheet
       Caption = 'Node Stats'
       Caption = 'Node Stats'
       ImageIndex = 3
       ImageIndex = 3
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       DesignSize = (
       DesignSize = (
         841
         841
         404)
         404)
@@ -1015,6 +1047,10 @@ object FRMWallet: TFRMWallet
     object tsMessages: TTabSheet
     object tsMessages: TTabSheet
       Caption = 'Messages'
       Caption = 'Messages'
       ImageIndex = 6
       ImageIndex = 6
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       DesignSize = (
       DesignSize = (
         841
         841
         404)
         404)
@@ -1248,7 +1284,7 @@ object FRMWallet: TFRMWallet
     Left = 105
     Left = 105
     Top = 180
     Top = 180
     Bitmap = {
     Bitmap = {
-      494C010102000800840110003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      494C010102000800940110003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
       0000000000003600000028000000400000003000000001002000000000000030
       0000000000003600000028000000400000003000000001002000000000000030
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000002A292929D60B0B0BF4111111EE0000006B000000000000
       0000000000000000002A292929D60B0B0BF4111111EE0000006B000000000000

+ 110 - 122
Units/Forms/UFRMWallet.lfm

@@ -4,7 +4,7 @@ object FRMWallet: TFRMWallet
   Top = 328
   Top = 328
   Width = 865
   Width = 865
   Caption = 'Pascal Coin Wallet, JSON-RPC Miner & Explorer'
   Caption = 'Pascal Coin Wallet, JSON-RPC Miner & Explorer'
-  ClientHeight = 580
+  ClientHeight = 600
   ClientWidth = 865
   ClientWidth = 865
   Color = clBtnFace
   Color = clBtnFace
   Constraints.MinHeight = 600
   Constraints.MinHeight = 600
@@ -162,15 +162,15 @@ object FRMWallet: TFRMWallet
       Left = 90
       Left = 90
       Height = 13
       Height = 13
       Top = 11
       Top = 11
-      Width = 60
+      Width = 70
       Caption = 'Total Blocks:'
       Caption = 'Total Blocks:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblCurrentBlock: TLabel
     object lblCurrentBlock: TLabel
-      Left = 156
+      Left = 166
       Height = 13
       Height = 13
       Top = 11
       Top = 11
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -178,15 +178,15 @@ object FRMWallet: TFRMWallet
       Left = 90
       Left = 90
       Height = 13
       Height = 13
       Top = 26
       Top = 26
-      Width = 89
+      Width = 106
       Caption = 'Current Block age:'
       Caption = 'Current Block age:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblCurrentBlockTime: TLabel
     object lblCurrentBlockTime: TLabel
-      Left = 188
+      Left = 198
       Height = 13
       Height = 13
       Top = 26
       Top = 26
-      Width = 81
+      Width = 96
       Caption = '000 seconds ago'
       Caption = '000 seconds ago'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -194,15 +194,15 @@ object FRMWallet: TFRMWallet
       Left = 90
       Left = 90
       Height = 13
       Height = 13
       Top = 41
       Top = 41
-      Width = 98
+      Width = 115
       Caption = 'Pending Operations:'
       Caption = 'Pending Operations:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblOperationsPending: TLabel
     object lblOperationsPending: TLabel
-      Left = 194
+      Left = 207
       Height = 13
       Height = 13
       Top = 41
       Top = 41
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -210,15 +210,15 @@ object FRMWallet: TFRMWallet
       Left = 90
       Left = 90
       Height = 13
       Height = 13
       Top = 56
       Top = 56
-      Width = 68
+      Width = 81
       Caption = 'Miners clients:'
       Caption = 'Miners clients:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblMinersClients: TLabel
     object lblMinersClients: TLabel
-      Left = 163
+      Left = 177
       Height = 13
       Height = 13
       Top = 56
       Top = 56
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -226,23 +226,23 @@ object FRMWallet: TFRMWallet
       Left = 429
       Left = 429
       Height = 13
       Height = 13
       Top = 11
       Top = 11
-      Width = 76
+      Width = 86
       Caption = 'Current Target:'
       Caption = 'Current Target:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblCurrentDifficulty: TLabel
     object lblCurrentDifficulty: TLabel
-      Left = 511
+      Left = 518
       Height = 13
       Height = 13
       Top = 11
       Top = 11
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblTimeAverage: TLabel
     object lblTimeAverage: TLabel
-      Left = 360
+      Left = 370
       Height = 13
       Height = 13
       Top = 26
       Top = 26
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -250,7 +250,7 @@ object FRMWallet: TFRMWallet
       Left = 285
       Left = 285
       Height = 13
       Height = 13
       Top = 26
       Top = 26
-      Width = 69
+      Width = 83
       Caption = 'Time average:'
       Caption = 'Time average:'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -258,15 +258,15 @@ object FRMWallet: TFRMWallet
       Left = 90
       Left = 90
       Height = 13
       Height = 13
       Top = 70
       Top = 70
-      Width = 63
+      Width = 72
       Caption = 'Node Status:'
       Caption = 'Node Status:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblNodeStatus: TLabel
     object lblNodeStatus: TLabel
-      Left = 163
+      Left = 168
       Height = 13
       Height = 13
       Top = 70
       Top = 70
-      Width = 15
+      Width = 18
       Caption = '???'
       Caption = '???'
       ParentColor = False
       ParentColor = False
     end
     end
@@ -274,23 +274,23 @@ object FRMWallet: TFRMWallet
       Left = 285
       Left = 285
       Height = 13
       Height = 13
       Top = 11
       Top = 11
-      Width = 48
+      Width = 55
       Caption = 'Accounts:'
       Caption = 'Accounts:'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblCurrentAccounts: TLabel
     object lblCurrentAccounts: TLabel
-      Left = 337
+      Left = 344
       Height = 13
       Height = 13
       Top = 11
       Top = 11
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       ParentColor = False
       ParentColor = False
     end
     end
     object lblTimeAverageAux: TLabel
     object lblTimeAverageAux: TLabel
-      Left = 360
+      Left = 370
       Height = 13
       Height = 13
       Top = 41
       Top = 41
-      Width = 18
+      Width = 21
       Caption = '000'
       Caption = '000'
       Font.Color = clGray
       Font.Color = clGray
       Font.Height = -11
       Font.Height = -11
@@ -302,7 +302,7 @@ object FRMWallet: TFRMWallet
       Left = 360
       Left = 360
       Height = 13
       Height = 13
       Top = 56
       Top = 56
-      Width = 74
+      Width = 86
       Caption = 'Blocks found:'
       Caption = 'Blocks found:'
       Font.Color = clWindowText
       Font.Color = clWindowText
       Font.Height = -11
       Font.Height = -11
@@ -312,11 +312,11 @@ object FRMWallet: TFRMWallet
       ParentFont = False
       ParentFont = False
     end
     end
     object lblBlocksFound: TLabel
     object lblBlocksFound: TLabel
-      Left = 440
+      Left = 450
       Height = 13
       Height = 13
       Hint = 'Blocks found while Miner is running...'
       Hint = 'Blocks found while Miner is running...'
       Top = 56
       Top = 56
-      Width = 21
+      Width = 24
       Caption = '000'
       Caption = '000'
       Font.Color = clWindowText
       Font.Color = clWindowText
       Font.Height = -11
       Font.Height = -11
@@ -330,9 +330,9 @@ object FRMWallet: TFRMWallet
     object lblReceivedMessages: TLabel
     object lblReceivedMessages: TLabel
       Cursor = crHandPoint
       Cursor = crHandPoint
       Left = 360
       Left = 360
-      Height = 23
+      Height = 22
       Top = 66
       Top = 66
-      Width = 185
+      Width = 211
       Caption = 'Received messages'
       Caption = 'Received messages'
       Font.Color = clRed
       Font.Color = clRed
       Font.Height = -19
       Font.Height = -19
@@ -344,9 +344,9 @@ object FRMWallet: TFRMWallet
     end
     end
     object lblBuild: TLabel
     object lblBuild: TLabel
       Left = 586
       Left = 586
-      Height = 23
+      Height = 22
       Top = 3
       Top = 3
-      Width = 49
+      Width = 56
       Caption = 'Build'
       Caption = 'Build'
       Font.Color = clWindowText
       Font.Color = clWindowText
       Font.Height = -19
       Font.Height = -19
@@ -358,8 +358,8 @@ object FRMWallet: TFRMWallet
   end
   end
   object StatusBar: TStatusBar
   object StatusBar: TStatusBar
     Left = 0
     Left = 0
-    Height = 23
-    Top = 557
+    Height = 21
+    Top = 579
     Width = 865
     Width = 865
     Panels = <    
     Panels = <    
       item
       item
@@ -379,21 +379,21 @@ object FRMWallet: TFRMWallet
   end
   end
   object PageControl: TPageControl
   object PageControl: TPageControl
     Left = 0
     Left = 0
-    Height = 466
+    Height = 488
     Top = 91
     Top = 91
     Width = 865
     Width = 865
-    ActivePage = tsMyAccounts
+    ActivePage = tsMessages
     Align = alClient
     Align = alClient
-    TabIndex = 0
+    TabIndex = 6
     TabOrder = 2
     TabOrder = 2
     OnChange = PageControlChange
     OnChange = PageControlChange
     object tsMyAccounts: TTabSheet
     object tsMyAccounts: TTabSheet
       Caption = 'Accounts Explorer'
       Caption = 'Accounts Explorer'
-      ClientHeight = 440
-      ClientWidth = 857
+      ClientHeight = 461
+      ClientWidth = 861
       object Splitter1: TSplitter
       object Splitter1: TSplitter
         Left = 380
         Left = 380
-        Height = 374
+        Height = 395
         Top = 66
         Top = 66
         Width = 5
         Width = 5
       end
       end
@@ -401,41 +401,41 @@ object FRMWallet: TFRMWallet
         Left = 0
         Left = 0
         Height = 66
         Height = 66
         Top = 0
         Top = 0
-        Width = 857
+        Width = 861
         Align = alTop
         Align = alTop
         ClientHeight = 66
         ClientHeight = 66
-        ClientWidth = 857
+        ClientWidth = 861
         TabOrder = 0
         TabOrder = 0
         object Label18: TLabel
         object Label18: TLabel
           Left = 11
           Left = 11
           Height = 13
           Height = 13
           Top = 35
           Top = 35
-          Width = 61
+          Width = 70
           Caption = 'Find account'
           Caption = 'Find account'
           ParentColor = False
           ParentColor = False
         end
         end
         object cbMyPrivateKeys: TComboBox
         object cbMyPrivateKeys: TComboBox
           Left = 260
           Left = 260
-          Height = 21
+          Height = 31
           Top = 7
           Top = 7
           Width = 411
           Width = 411
-          ItemHeight = 13
+          ItemHeight = 0
           OnChange = cbMyPrivateKeysChange
           OnChange = cbMyPrivateKeysChange
           Style = csDropDownList
           Style = csDropDownList
           TabOrder = 0
           TabOrder = 0
         end
         end
         object cbExploreMyAccounts: TCheckBox
         object cbExploreMyAccounts: TCheckBox
           Left = 11
           Left = 11
-          Height = 19
+          Height = 24
           Top = 10
           Top = 10
-          Width = 235
+          Width = 329
           Caption = 'Explore accounts with one of my Wallet Keys'
           Caption = 'Explore accounts with one of my Wallet Keys'
           OnClick = cbExploreMyAccountsClick
           OnClick = cbExploreMyAccountsClick
           TabOrder = 1
           TabOrder = 1
         end
         end
         object ebFindAccountNumber: TEdit
         object ebFindAccountNumber: TEdit
           Left = 87
           Left = 87
-          Height = 21
+          Height = 23
           Top = 33
           Top = 33
           Width = 83
           Width = 83
           OnChange = ebFindAccountNumberChange
           OnChange = ebFindAccountNumberChange
@@ -453,16 +453,16 @@ object FRMWallet: TFRMWallet
         end
         end
         object cbFilterAccounts: TCheckBox
         object cbFilterAccounts: TCheckBox
           Left = 260
           Left = 260
-          Height = 19
+          Height = 24
           Top = 35
           Top = 35
-          Width = 145
+          Width = 202
           Caption = 'Filter accounts by balance'
           Caption = 'Filter accounts by balance'
           OnClick = cbFilterAccountsClick
           OnClick = cbFilterAccountsClick
           TabOrder = 4
           TabOrder = 4
         end
         end
         object ebFilterAccountByBalanceMin: TEdit
         object ebFilterAccountByBalanceMin: TEdit
           Left = 412
           Left = 412
-          Height = 21
+          Height = 23
           Hint = 'Min balance'
           Hint = 'Min balance'
           Top = 33
           Top = 33
           Width = 83
           Width = 83
@@ -472,7 +472,7 @@ object FRMWallet: TFRMWallet
         end
         end
         object ebFilterAccountByBalanceMax: TEdit
         object ebFilterAccountByBalanceMax: TEdit
           Left = 503
           Left = 503
-          Height = 21
+          Height = 23
           Hint = 'Max balance'
           Hint = 'Max balance'
           Top = 33
           Top = 33
           Width = 83
           Width = 83
@@ -483,17 +483,17 @@ object FRMWallet: TFRMWallet
       end
       end
       object pnlAccounts: TPanel
       object pnlAccounts: TPanel
         Left = 0
         Left = 0
-        Height = 374
+        Height = 395
         Top = 66
         Top = 66
         Width = 380
         Width = 380
         Align = alLeft
         Align = alLeft
         BevelOuter = bvNone
         BevelOuter = bvNone
-        ClientHeight = 374
+        ClientHeight = 395
         ClientWidth = 380
         ClientWidth = 380
         TabOrder = 1
         TabOrder = 1
         object dgAccounts: TDrawGrid
         object dgAccounts: TDrawGrid
           Left = 0
           Left = 0
-          Height = 340
+          Height = 361
           Top = 0
           Top = 0
           Width = 380
           Width = 380
           Align = alLeft
           Align = alLeft
@@ -507,7 +507,7 @@ object FRMWallet: TFRMWallet
         object pnlAccountsInfo: TPanel
         object pnlAccountsInfo: TPanel
           Left = 0
           Left = 0
           Height = 34
           Height = 34
-          Top = 340
+          Top = 361
           Width = 380
           Width = 380
           Align = alBottom
           Align = alBottom
           BevelOuter = bvNone
           BevelOuter = bvNone
@@ -518,7 +518,7 @@ object FRMWallet: TFRMWallet
             Left = 5
             Left = 5
             Height = 13
             Height = 13
             Top = 10
             Top = 10
-            Width = 48
+            Width = 55
             Caption = 'Accounts:'
             Caption = 'Accounts:'
             ParentColor = False
             ParentColor = False
           end
           end
@@ -526,7 +526,7 @@ object FRMWallet: TFRMWallet
             Left = 120
             Left = 120
             Height = 13
             Height = 13
             Top = 10
             Top = 10
-            Width = 88
+            Width = 104
             Caption = 'Accounts Balance:'
             Caption = 'Accounts Balance:'
             ParentColor = False
             ParentColor = False
           end
           end
@@ -534,7 +534,7 @@ object FRMWallet: TFRMWallet
             Left = 60
             Left = 60
             Height = 13
             Height = 13
             Top = 10
             Top = 10
-            Width = 18
+            Width = 21
             Caption = '000'
             Caption = '000'
             ParentColor = False
             ParentColor = False
           end
           end
@@ -542,7 +542,7 @@ object FRMWallet: TFRMWallet
             Left = 214
             Left = 214
             Height = 13
             Height = 13
             Top = 10
             Top = 10
-            Width = 18
+            Width = 21
             Caption = '000'
             Caption = '000'
             ParentColor = False
             ParentColor = False
           end
           end
@@ -588,22 +588,22 @@ object FRMWallet: TFRMWallet
       end
       end
       object pcAccountsOptions: TPageControl
       object pcAccountsOptions: TPageControl
         Left = 385
         Left = 385
-        Height = 374
+        Height = 395
         Top = 66
         Top = 66
-        Width = 472
+        Width = 476
         ActivePage = tsAccountOperations
         ActivePage = tsAccountOperations
         Align = alClient
         Align = alClient
         TabIndex = 0
         TabIndex = 0
         TabOrder = 2
         TabOrder = 2
         object tsAccountOperations: TTabSheet
         object tsAccountOperations: TTabSheet
           Caption = 'Operations of selected Account'
           Caption = 'Operations of selected Account'
-          ClientHeight = 348
-          ClientWidth = 464
+          ClientHeight = 368
+          ClientWidth = 472
           object dgAccountOperations: TDrawGrid
           object dgAccountOperations: TDrawGrid
             Left = 0
             Left = 0
-            Height = 348
+            Height = 368
             Top = 0
             Top = 0
-            Width = 464
+            Width = 472
             Align = alClient
             Align = alClient
             ExtendedSelect = False
             ExtendedSelect = False
             TabOrder = 0
             TabOrder = 0
@@ -611,19 +611,12 @@ object FRMWallet: TFRMWallet
             TitleFont.Height = -11
             TitleFont.Height = -11
             TitleFont.Name = 'Tahoma'
             TitleFont.Name = 'Tahoma'
             OnDblClick = MiDecodePayloadClick
             OnDblClick = MiDecodePayloadClick
-            RowHeights = (
-              24
-              24
-              24
-              24
-              24
-            )
           end
           end
         end
         end
         object tsMultiSelectAccounts: TTabSheet
         object tsMultiSelectAccounts: TTabSheet
           Caption = 'Selected accounts for massive operations'
           Caption = 'Selected accounts for massive operations'
-          ClientHeight = 0
-          ClientWidth = 0
+          ClientHeight = 368
+          ClientWidth = 472
           ImageIndex = 1
           ImageIndex = 1
           object dgSelectedAccounts: TDrawGrid
           object dgSelectedAccounts: TDrawGrid
             Left = 41
             Left = 41
@@ -636,13 +629,6 @@ object FRMWallet: TFRMWallet
             TitleFont.Color = clWindowText
             TitleFont.Color = clWindowText
             TitleFont.Height = -11
             TitleFont.Height = -11
             TitleFont.Name = 'Tahoma'
             TitleFont.Name = 'Tahoma'
-            RowHeights = (
-              24
-              24
-              24
-              24
-              24
-            )
           end
           end
           object pnlSelectedAccountsTop: TPanel
           object pnlSelectedAccountsTop: TPanel
             Left = 0
             Left = 0
@@ -827,14 +813,14 @@ object FRMWallet: TFRMWallet
     end
     end
     object tsPendingOperations: TTabSheet
     object tsPendingOperations: TTabSheet
       Caption = 'Pending Operations'
       Caption = 'Pending Operations'
-      ClientHeight = 0
-      ClientWidth = 0
+      ClientHeight = 461
+      ClientWidth = 861
       ImageIndex = 5
       ImageIndex = 5
       object dgPendingOperations: TDrawGrid
       object dgPendingOperations: TDrawGrid
         Left = 0
         Left = 0
-        Height = 318
+        Height = 375
         Top = 86
         Top = 86
-        Width = 841
+        Width = 861
         Align = alClient
         Align = alClient
         ExtendedSelect = False
         ExtendedSelect = False
         TabOrder = 0
         TabOrder = 0
@@ -847,18 +833,18 @@ object FRMWallet: TFRMWallet
         Left = 0
         Left = 0
         Height = 86
         Height = 86
         Top = 0
         Top = 0
-        Width = 841
+        Width = 861
         Align = alTop
         Align = alTop
         BevelOuter = bvNone
         BevelOuter = bvNone
         BorderWidth = 10
         BorderWidth = 10
         ClientHeight = 86
         ClientHeight = 86
-        ClientWidth = 841
+        ClientWidth = 861
         TabOrder = 1
         TabOrder = 1
         object Label10: TLabel
         object Label10: TLabel
           Left = 10
           Left = 10
           Height = 66
           Height = 66
           Top = 10
           Top = 10
-          Width = 821
+          Width = 841
           Align = alClient
           Align = alClient
           AutoSize = False
           AutoSize = False
           Caption = 'Here you can see Operations transmited/received from other nodes that will be included in next block. There is no guarantee that other nodes will include them when mining, so it''s important that you mine too to help include Operations to the main BlockChain'
           Caption = 'Here you can see Operations transmited/received from other nodes that will be included in next block. There is no guarantee that other nodes will include them when mining, so it''s important that you mine too to help include Operations to the main BlockChain'
@@ -873,8 +859,8 @@ object FRMWallet: TFRMWallet
     end
     end
     object tsBlockChain: TTabSheet
     object tsBlockChain: TTabSheet
       Caption = 'BlockChain Explorer'
       Caption = 'BlockChain Explorer'
-      ClientHeight = 0
-      ClientWidth = 0
+      ClientHeight = 461
+      ClientWidth = 861
       ImageIndex = 1
       ImageIndex = 1
       object Panel2: TPanel
       object Panel2: TPanel
         Left = 0
         Left = 0
@@ -927,8 +913,8 @@ object FRMWallet: TFRMWallet
     end
     end
     object tsOperations: TTabSheet
     object tsOperations: TTabSheet
       Caption = 'Operations Explorer'
       Caption = 'Operations Explorer'
-      ClientHeight = 0
-      ClientWidth = 0
+      ClientHeight = 461
+      ClientWidth = 861
       ImageIndex = 1
       ImageIndex = 1
       object Panel1: TPanel
       object Panel1: TPanel
         Left = 0
         Left = 0
@@ -981,8 +967,8 @@ object FRMWallet: TFRMWallet
     end
     end
     object tsLogs: TTabSheet
     object tsLogs: TTabSheet
       Caption = 'Logs'
       Caption = 'Logs'
-      ClientHeight = 0
-      ClientWidth = 0
+      ClientHeight = 461
+      ClientWidth = 861
       ImageIndex = 2
       ImageIndex = 2
       object pnlTopLogs: TPanel
       object pnlTopLogs: TPanel
         Left = 0
         Left = 0
@@ -1014,40 +1000,40 @@ object FRMWallet: TFRMWallet
     end
     end
     object tsNodeStats: TTabSheet
     object tsNodeStats: TTabSheet
       Caption = 'Node Stats'
       Caption = 'Node Stats'
-      ClientHeight = 0
-      ClientWidth = 0
+      ClientHeight = 461
+      ClientWidth = 861
       ImageIndex = 3
       ImageIndex = 3
       object Label3: TLabel
       object Label3: TLabel
         Left = 15
         Left = 15
         Height = 13
         Height = 13
         Top = 15
         Top = 15
-        Width = 177
+        Width = 207
         Caption = 'Active Net Connections of this Node:'
         Caption = 'Active Net Connections of this Node:'
         ParentColor = False
         ParentColor = False
       end
       end
       object Label6: TLabel
       object Label6: TLabel
         Left = 15
         Left = 15
         Height = 13
         Height = 13
-        Top = 250
-        Width = 169
-        Anchors = [akLeft, akBottom]
+        Top = 312
+        Width = 202
+        Anchors = [akLeft, akRight, akBottom]
         Caption = 'Available or possible Node Servers:'
         Caption = 'Available or possible Node Servers:'
         ParentColor = False
         ParentColor = False
       end
       end
       object Label7: TLabel
       object Label7: TLabel
         Left = 15
         Left = 15
         Height = 13
         Height = 13
-        Top = 146
-        Width = 86
-        Anchors = [akLeft, akBottom]
+        Top = 208
+        Width = 103
+        Anchors = [akLeft, akRight, akBottom]
         Caption = 'BlackList of Nodes'
         Caption = 'BlackList of Nodes'
         ParentColor = False
         ParentColor = False
       end
       end
       object memoNetConnections: TMemo
       object memoNetConnections: TMemo
         Left = 15
         Left = 15
-        Height = 106
+        Height = 166
         Top = 34
         Top = 34
-        Width = 810
+        Width = 834
         Anchors = [akTop, akLeft, akRight, akBottom]
         Anchors = [akTop, akLeft, akRight, akBottom]
         ReadOnly = True
         ReadOnly = True
         ScrollBars = ssVertical
         ScrollBars = ssVertical
@@ -1056,8 +1042,8 @@ object FRMWallet: TFRMWallet
       object memoNetServers: TMemo
       object memoNetServers: TMemo
         Left = 15
         Left = 15
         Height = 116
         Height = 116
-        Top = 269
-        Width = 810
+        Top = 331
+        Width = 834
         Anchors = [akLeft, akRight, akBottom]
         Anchors = [akLeft, akRight, akBottom]
         ReadOnly = True
         ReadOnly = True
         ScrollBars = ssVertical
         ScrollBars = ssVertical
@@ -1066,8 +1052,8 @@ object FRMWallet: TFRMWallet
       object memoNetBlackLists: TMemo
       object memoNetBlackLists: TMemo
         Left = 15
         Left = 15
         Height = 79
         Height = 79
-        Top = 165
-        Width = 810
+        Top = 227
+        Width = 833
         Anchors = [akLeft, akRight, akBottom]
         Anchors = [akLeft, akRight, akBottom]
         ReadOnly = True
         ReadOnly = True
         ScrollBars = ssVertical
         ScrollBars = ssVertical
@@ -1076,14 +1062,14 @@ object FRMWallet: TFRMWallet
     end
     end
     object tsMessages: TTabSheet
     object tsMessages: TTabSheet
       Caption = 'Messages'
       Caption = 'Messages'
-      ClientHeight = 0
-      ClientWidth = 0
+      ClientHeight = 461
+      ClientWidth = 861
       ImageIndex = 6
       ImageIndex = 6
       object Label11: TLabel
       object Label11: TLabel
         Left = 15
         Left = 15
         Height = 13
         Height = 13
         Top = 151
         Top = 151
-        Width = 51
+        Width = 59
         Caption = 'Messages:'
         Caption = 'Messages:'
         ParentColor = False
         ParentColor = False
       end
       end
@@ -1091,7 +1077,7 @@ object FRMWallet: TFRMWallet
         Left = 315
         Left = 315
         Height = 13
         Height = 13
         Top = 11
         Top = 11
-        Width = 85
+        Width = 99
         Caption = 'Message to send:'
         Caption = 'Message to send:'
         ParentColor = False
         ParentColor = False
       end
       end
@@ -1099,7 +1085,7 @@ object FRMWallet: TFRMWallet
         Left = 15
         Left = 15
         Height = 13
         Height = 13
         Top = 11
         Top = 11
-        Width = 107
+        Width = 126
         Caption = 'Available connections:'
         Caption = 'Available connections:'
         ParentColor = False
         ParentColor = False
       end
       end
@@ -1107,7 +1093,7 @@ object FRMWallet: TFRMWallet
         Left = 410
         Left = 410
         Height = 13
         Height = 13
         Top = 11
         Top = 11
-        Width = 361
+        Width = 430
         Caption = '(Messages will be encrypted, so only dest connection will be able to read it)'
         Caption = '(Messages will be encrypted, so only dest connection will be able to read it)'
         Font.Color = clGrayText
         Font.Color = clGrayText
         Font.Height = -11
         Font.Height = -11
@@ -1122,22 +1108,24 @@ object FRMWallet: TFRMWallet
         Width = 275
         Width = 275
         ItemHeight = 0
         ItemHeight = 0
         MultiSelect = True
         MultiSelect = True
+        ScrollWidth = 273
         TabOrder = 0
         TabOrder = 0
+        TopIndex = -1
       end
       end
       object bbSendAMessage: TButton
       object bbSendAMessage: TButton
         Left = 315
         Left = 315
         Height = 25
         Height = 25
         Top = 101
         Top = 101
-        Width = 456
+        Width = 525
         Caption = 'Send a Message'
         Caption = 'Send a Message'
         OnClick = bbSendAMessageClick
         OnClick = bbSendAMessageClick
         TabOrder = 1
         TabOrder = 1
       end
       end
       object memoMessages: TMemo
       object memoMessages: TMemo
         Left = 15
         Left = 15
-        Height = 215
+        Height = 270
         Top = 170
         Top = 170
-        Width = 810
+        Width = 825
         Anchors = [akTop, akLeft, akRight, akBottom]
         Anchors = [akTop, akLeft, akRight, akBottom]
         Font.Color = clWindowText
         Font.Color = clWindowText
         Font.Height = -16
         Font.Height = -16
@@ -1155,7 +1143,7 @@ object FRMWallet: TFRMWallet
         Left = 315
         Left = 315
         Height = 61
         Height = 61
         Top = 30
         Top = 30
-        Width = 456
+        Width = 525
         Lines.Strings = (
         Lines.Strings = (
           'memoMessageToSend'
           'memoMessageToSend'
         )
         )

+ 97 - 67
Units/Forms/UFRMWallet.pas

@@ -27,10 +27,14 @@ uses
 {$ENDIF}
 {$ENDIF}
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, ExtCtrls, ComCtrls, UWalletKeys, StdCtrls,
   Dialogs, ExtCtrls, ComCtrls, UWalletKeys, StdCtrls,
-  ULog, DB, Grids, DBGrids, UAppParams,
-  UBlockChain, UNode, DBCtrls, UGridUtils, UMiner, UAccounts, Menus, ImgList,
+  ULog, Grids, UAppParams,
+  UBlockChain, UNode, UGridUtils, UMiner, UAccounts, Menus, ImgList,
   UNetProtocol, UCrypto, Buttons, UPoolMining, URPC;
   UNetProtocol, UCrypto, Buttons, UPoolMining, URPC;
 
 
+Const
+  CM_PC_WalletKeysChanged = WM_USER + 1;
+  CM_PC_NetConnectionUpdated = WM_USER + 2;
+
 type
 type
   TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
   TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
 
 
@@ -233,6 +237,8 @@ type
     FMaxAccountBalance : Int64;
     FMaxAccountBalance : Int64;
     FPoolMiningServer : TPoolMiningServer;
     FPoolMiningServer : TPoolMiningServer;
     FRPCServer : TRPCServer;
     FRPCServer : TRPCServer;
+    FMustProcessWalletChanged : Boolean;
+    FMustProcessNetConnectionUpdated : Boolean;
     //Procedure CheckMining;
     //Procedure CheckMining;
     Procedure OnNewAccount(Sender : TObject);
     Procedure OnNewAccount(Sender : TObject);
     Procedure OnReceivedHelloMessage(Sender : TObject);
     Procedure OnReceivedHelloMessage(Sender : TObject);
@@ -260,6 +266,8 @@ type
     Function GetAccountKeyForMiner : TAccountKey;
     Function GetAccountKeyForMiner : TAccountKey;
     Procedure DoUpdateAccounts;
     Procedure DoUpdateAccounts;
     Function DoUpdateAccountsFilter : Boolean;
     Function DoUpdateAccountsFilter : Boolean;
+    procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
+    procedure CM_NetConnectionUpdated(var Msg: TMessage); message CM_PC_NetConnectionUpdated;
   public
   public
     { Public declarations }
     { Public declarations }
     Property WalletKeys : TWalletKeysExt read FWalletKeys;
     Property WalletKeys : TWalletKeysExt read FWalletKeys;
@@ -498,6 +506,83 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TFRMWallet.CM_NetConnectionUpdated(var Msg: TMessage);
+Const CT_BooleanToString : Array[Boolean] of String = ('False','True');
+Var i : integer;
+ NC : TNetConnection;
+ l : TList;
+ sClientApp : String;
+ strings, sNSC, sRS, sDisc : TStrings;
+begin
+  Try
+    if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
+    try
+      strings := memoNetConnections.Lines;
+      sNSC := TStringList.Create;
+      sRS := TStringList.Create;
+      sDisc := TStringList.Create;
+      strings.BeginUpdate;
+      Try
+        for i := 0 to l.Count - 1 do begin
+          NC := l[i];
+          If NC.Client.BytesReceived>0 then begin
+            sClientApp := '['+IntToStr(NC.NetProtocolVersion.protocol_version)+'-'+IntToStr(NC.NetProtocolVersion.protocol_available)+'] '+NC.ClientAppVersion;
+          end else begin
+            sClientApp := '(no data)';
+          end;
+
+          if NC.Connected then begin
+            if NC is TNetServerClient then begin
+              sNSC.Add(Format('Client: IP:%s Sent/Received:%d/%d Bytes - %s - Active since %s',
+                [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,DateTimeElapsedTime(NC.CreatedTime)]));
+            end else begin
+              if NC.IsMyselfServer then sNSC.Add(Format('MySelf IP:%s Sent/Received:%d/%d Bytes - %s - Active since %s',
+                [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,DateTimeElapsedTime(NC.CreatedTime)]))
+              else begin
+                sRS.Add(Format('Remote Server: IP:%s Sent/Received:%d/%d Bytes - %s - Active since %s',
+                [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,DateTimeElapsedTime(NC.CreatedTime)]));
+              end;
+            end;
+          end else begin
+            if NC is TNetServerClient then begin
+              sDisc.Add(Format('Disconnected client: IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
+            end else if NC.IsMyselfServer then begin
+              sDisc.Add(Format('Disconnected MySelf IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
+            end else begin
+              sDisc.Add(Format('Disconnected Remote Server: IP:%s %s - %s',[NC.ClientRemoteAddr,CT_BooleanToString[NC.Connected],sClientApp]));
+            end;
+          end;
+        end;
+        strings.Clear;
+        strings.Add(Format('Connections Updated %s Clients:%d Servers:%d (valid servers:%d)',[DateTimeToStr(now),sNSC.Count,sRS.Count,TNetData.NetData.NetStatistics.ServersConnectionsWithResponse]));
+        strings.AddStrings(sRS);
+        strings.AddStrings(sNSC);
+        if sDisc.Count>0 then begin
+          strings.Add('');
+          strings.Add('Disconnected connections: '+Inttostr(sDisc.Count));
+          strings.AddStrings(sDisc);
+        end;
+      Finally
+        strings.EndUpdate;
+        sNSC.Free;
+        sRS.Free;
+        sDisc.Free;
+      End;
+      //CheckMining;
+    finally
+      TNetData.NetData.NetConnections.UnlockList;
+    end;
+  Finally
+    FMustProcessNetConnectionUpdated := false;
+  End;
+end;
+
+procedure TFRMWallet.CM_WalletChanged(var Msg: TMessage);
+begin
+  UpdatePrivateKeys;
+  FMustProcessWalletChanged := false;
+end;
+
 {
 {
 procedure TFRMWallet.CheckMining;
 procedure TFRMWallet.CheckMining;
   Procedure Stop;
   Procedure Stop;
@@ -714,6 +799,8 @@ end;
 procedure TFRMWallet.FormCreate(Sender: TObject);
 procedure TFRMWallet.FormCreate(Sender: TObject);
 Var i : Integer;
 Var i : Integer;
 begin
 begin
+  FMustProcessWalletChanged := false;
+  FMustProcessNetConnectionUpdated := false;
   FRPCServer := Nil;
   FRPCServer := Nil;
   FMinAccountBalance := 0;
   FMinAccountBalance := 0;
   FMaxAccountBalance := CT_MaxWalletAmount;
   FMaxAccountBalance := CT_MaxWalletAmount;
@@ -749,6 +836,7 @@ begin
   FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
   FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
   FOperationsAccountGrid := TOperationsGrid.Create(Self);
   FOperationsAccountGrid := TOperationsGrid.Create(Self);
   FOperationsAccountGrid.DrawGrid := dgAccountOperations;
   FOperationsAccountGrid.DrawGrid := dgAccountOperations;
+  FOperationsAccountGrid.MustShowAlwaysAnAccount := true;
   FPendingOperationsGrid := TOperationsGrid.Create(Self);
   FPendingOperationsGrid := TOperationsGrid.Create(Self);
   FPendingOperationsGrid.DrawGrid := dgPendingOperations;
   FPendingOperationsGrid.DrawGrid := dgPendingOperations;
   FPendingOperationsGrid.AccountNumber := -1; // all
   FPendingOperationsGrid.AccountNumber := -1; // all
@@ -1135,70 +1223,10 @@ begin
 end;
 end;
 
 
 procedure TFRMWallet.OnNetConnectionsUpdated(Sender: TObject);
 procedure TFRMWallet.OnNetConnectionsUpdated(Sender: TObject);
-Const CT_BooleanToString : Array[Boolean] of String = ('False','True');
-Var i : integer;
- NC : TNetConnection;
- l : TList;
- sClientApp : String;
- strings, sNSC, sRS, sDisc : TStrings;
 begin
 begin
-  l := TNetData.NetData.NetConnections.LockList;
-  try
-    strings := memoNetConnections.Lines;
-    sNSC := TStringList.Create;
-    sRS := TStringList.Create;
-    sDisc := TStringList.Create;
-    strings.BeginUpdate;
-    Try
-      for i := 0 to l.Count - 1 do begin
-        NC := l[i];
-        If NC.Client.BytesReceived>0 then begin
-          sClientApp := '['+IntToStr(NC.NetProtocolVersion.protocol_version)+'-'+IntToStr(NC.NetProtocolVersion.protocol_available)+'] '+NC.ClientAppVersion;
-        end else begin
-          sClientApp := '(no data)';
-        end;
-
-        if NC.Connected then begin
-          if NC is TNetServerClient then begin
-            sNSC.Add(Format('Client: IP:%s Sent/Received:%d/%d Bytes - %s - Active since %s',
-              [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,DateTimeElapsedTime(NC.CreatedTime)]));
-          end else begin
-            if NC.IsMyselfServer then sNSC.Add(Format('MySelf IP:%s Sent/Received:%d/%d Bytes - %s - Active since %s',
-              [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,DateTimeElapsedTime(NC.CreatedTime)]))
-            else begin
-              sRS.Add(Format('Remote Server: IP:%s Sent/Received:%d/%d Bytes - %s - Active since %s',
-              [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,DateTimeElapsedTime(NC.CreatedTime)]));
-            end;
-          end;
-        end else begin
-          if NC is TNetServerClient then begin
-            sDisc.Add(Format('Disconnected client: IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
-          end else if NC.IsMyselfServer then begin
-            sDisc.Add(Format('Disconnected MySelf IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
-          end else begin
-            sDisc.Add(Format('Disconnected Remote Server: IP:%s %s - %s',[NC.ClientRemoteAddr,CT_BooleanToString[NC.Connected],sClientApp]));
-          end;
-        end;
-      end;
-      strings.Clear;
-      strings.Add(Format('Connections Updated %s Clients:%d Servers:%d (valid servers:%d)',[DateTimeToStr(now),sNSC.Count,sRS.Count,TNetData.NetData.NetStatistics.ServersConnectionsWithResponse]));
-      strings.AddStrings(sRS);
-      strings.AddStrings(sNSC);
-      if sDisc.Count>0 then begin
-        strings.Add('');
-        strings.Add('Disconnected connections: '+Inttostr(sDisc.Count));
-        strings.AddStrings(sDisc);
-      end;
-    Finally
-      strings.EndUpdate;
-      sNSC.Free;
-      sRS.Free;
-      sDisc.Free;
-    End;
-    //CheckMining;
-  finally
-    TNetData.NetData.NetConnections.UnlockList;
-  end;
+  if FMustProcessNetConnectionUpdated then exit;
+  FMustProcessNetConnectionUpdated := true;
+  PostMessage(Self.Handle,CM_PC_NetConnectionUpdated,0,0);
 end;
 end;
 
 
 procedure TFRMWallet.OnNetNodeServersUpdated(Sender: TObject);
 procedure TFRMWallet.OnNetNodeServersUpdated(Sender: TObject);
@@ -1348,7 +1376,9 @@ end;
 
 
 procedure TFRMWallet.OnWalletChanged(Sender: TObject);
 procedure TFRMWallet.OnWalletChanged(Sender: TObject);
 begin
 begin
-  UpdatePrivateKeys;
+  if FMustProcessWalletChanged then exit;
+  FMustProcessWalletChanged := true;
+  PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
 end;
 end;
 
 
 procedure TFRMWallet.PageControlChange(Sender: TObject);
 procedure TFRMWallet.PageControlChange(Sender: TObject);
@@ -1564,7 +1594,7 @@ Var i : integer;
  NC : TNetConnection;
  NC : TNetConnection;
  l : TList;
  l : TList;
 begin
 begin
-  l := TNetData.NetData.NetConnections.LockList;
+  if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
   try
   try
     lbNetConnections.Items.BeginUpdate;
     lbNetConnections.Items.BeginUpdate;
     Try
     Try

+ 35 - 3
Units/Forms/UFRMWalletKeys.pas

@@ -21,7 +21,12 @@ interface
 
 
 uses
 uses
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-  Dialogs, StdCtrls, UWalletKeys, Buttons, clipbrd;
+  Dialogs, StdCtrls, UWalletKeys, Buttons,
+  {$IFDEF FPC}LMessages,{$ENDIF}
+  clipbrd;
+
+Const
+  CM_PC_WalletKeysChanged = {$IFDEF FPC}LM_USER{$ELSE}WM_USER{$ENDIF} + 1;
 
 
 type
 type
   TFRMWalletKeys = class(TForm)
   TFRMWalletKeys = class(TForm)
@@ -59,17 +64,21 @@ type
     procedure bbExportAllWalletKeysClick(Sender: TObject);
     procedure bbExportAllWalletKeysClick(Sender: TObject);
     procedure bbImportKeysFileClick(Sender: TObject);
     procedure bbImportKeysFileClick(Sender: TObject);
   private
   private
+    FOldOnChanged : TNotifyEvent;
     FWalletKeys: TWalletKeys;
     FWalletKeys: TWalletKeys;
     procedure SetWalletKeys(const Value: TWalletKeys);
     procedure SetWalletKeys(const Value: TWalletKeys);
+    procedure OnWalletKeysChanged(Sender : TObject);
     { Private declarations }
     { Private declarations }
     Procedure UpdateWalletKeys;
     Procedure UpdateWalletKeys;
     Procedure UpdateSelectedWalletKey;
     Procedure UpdateSelectedWalletKey;
     Function GetSelectedWalletKey(var WalletKey : TWalletKey) : Boolean;
     Function GetSelectedWalletKey(var WalletKey : TWalletKey) : Boolean;
     Function GetSelectedWalletKeyAndIndex(var WalletKey : TWalletKey; var index : Integer) : Boolean;
     Function GetSelectedWalletKeyAndIndex(var WalletKey : TWalletKey; var index : Integer) : Boolean;
     Procedure CheckIsWalletKeyValidPassword;
     Procedure CheckIsWalletKeyValidPassword;
+    procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
   public
   public
     { Public declarations }
     { Public declarations }
     Property WalletKeys : TWalletKeys read FWalletKeys write SetWalletKeys;
     Property WalletKeys : TWalletKeys read FWalletKeys write SetWalletKeys;
+    Destructor Destroy; override;
   end;
   end;
 
 
 implementation
 implementation
@@ -78,7 +87,7 @@ uses
 {$IFnDEF FPC}
 {$IFnDEF FPC}
   Windows,
   Windows,
 {$ELSE}
 {$ELSE}
-  LCLIntf, LCLType, LMessages,
+  LCLIntf, LCLType,
 {$ENDIF}
 {$ENDIF}
   UCrypto, UAccounts, UFRMNewPrivateKeyType, UAES;
   UCrypto, UAccounts, UFRMNewPrivateKeyType, UAES;
 
 
@@ -371,6 +380,17 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TFRMWalletKeys.CM_WalletChanged(var Msg: TMessage);
+begin
+  UpdateWalletKeys;
+end;
+
+destructor TFRMWalletKeys.Destroy;
+begin
+  if Assigned(FWalletKeys) then FWalletKeys.OnChanged := FOldOnChanged;
+  inherited;
+end;
+
 procedure TFRMWalletKeys.FormCreate(Sender: TObject);
 procedure TFRMWalletKeys.FormCreate(Sender: TObject);
 begin
 begin
   lbWalletKeys.Sorted := true;
   lbWalletKeys.Sorted := true;
@@ -402,9 +422,21 @@ begin
   UpdateSelectedWalletKey;
   UpdateSelectedWalletKey;
 end;
 end;
 
 
+procedure TFRMWalletKeys.OnWalletKeysChanged(Sender : TObject);
+begin
+  PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
+  if Assigned(FOldOnChanged) then FOldOnChanged(Sender);
+end;
+
 procedure TFRMWalletKeys.SetWalletKeys(const Value: TWalletKeys);
 procedure TFRMWalletKeys.SetWalletKeys(const Value: TWalletKeys);
 begin
 begin
+  if FWalletKeys=Value then exit;
+  if Assigned(FWalletKeys) then FWalletKeys.OnChanged := FOldOnChanged;
   FWalletKeys := Value;
   FWalletKeys := Value;
+  if Assigned(FWalletKeys) then begin
+    FOldOnChanged := FWalletKeys.OnChanged;
+    FWalletKeys.OnChanged := OnWalletKeysChanged;
+  end;
   UpdateWalletKeys;
   UpdateWalletKeys;
 end;
 end;
 
 
@@ -451,7 +483,7 @@ end;
 
 
 procedure TFRMWalletKeys.UpdateWalletKeys;
 procedure TFRMWalletKeys.UpdateWalletKeys;
 Var lasti,i : Integer;
 Var lasti,i : Integer;
-  wk : TWalletKey;
+  selected_wk,wk : TWalletKey;
   s : AnsiString;
   s : AnsiString;
 begin
 begin
   GetSelectedWalletKeyAndIndex(wk,lasti);
   GetSelectedWalletKeyAndIndex(wk,lasti);

+ 144 - 115
Units/PascalCoin/UAccounts.pas

@@ -136,12 +136,12 @@ Type
   private
   private
     FBlockAccountsList : TList;
     FBlockAccountsList : TList;
     FListOfOrderedAccountKeysList : TList;
     FListOfOrderedAccountKeysList : TList;
-    FBufferBlocksHash: AnsiString;
+    FBufferBlocksHash: TRawBytes;
     FTotalBalance: Int64;
     FTotalBalance: Int64;
     FTotalFee: Int64;
     FTotalFee: Int64;
     FSafeBoxHash : TRawBytes;
     FSafeBoxHash : TRawBytes;
     FLock: TCriticalSection; // Thread safe
     FLock: TCriticalSection; // Thread safe
-    FIsLocked : Boolean;
+    FPreviousBlockSafeBoxHash : TRawBytes;
     Procedure SetAccount(account_number : Cardinal; newAccountkey: TAccountKey; newBalance: UInt64; newN_operation: Cardinal);
     Procedure SetAccount(account_number : Cardinal; newAccountkey: TAccountKey; newBalance: UInt64; newN_operation: Cardinal);
     Procedure AccountKeyListAddAccounts(Const AccountKey : TAccountKey; accounts : Array of Cardinal);
     Procedure AccountKeyListAddAccounts(Const AccountKey : TAccountKey; accounts : Array of Cardinal);
     Procedure AccountKeyListRemoveAccount(Const AccountKey : TAccountKey; accounts : Array of Cardinal);
     Procedure AccountKeyListRemoveAccount(Const AccountKey : TAccountKey; accounts : Array of Cardinal);
@@ -166,7 +166,8 @@ Type
     Property TotalBalance : Int64 read FTotalBalance;
     Property TotalBalance : Int64 read FTotalBalance;
     Procedure StartThreadSafe;
     Procedure StartThreadSafe;
     Procedure EndThreadSave;
     Procedure EndThreadSave;
-    Property IsLocked : Boolean read FIsLocked;
+    Property SafeBoxHash : TRawBytes read FSafeBoxHash;
+    Property PreviousBlockSafeBoxHash : TRawBytes read FPreviousBlockSafeBoxHash;
   End;
   End;
 
 
 
 
@@ -650,6 +651,7 @@ begin
   Dec(FTotalFee,FTotalFee);
   Dec(FTotalFee,FTotalFee);
   AccountKeyListAddAccounts(accountkey,accs);
   AccountKeyListAddAccounts(accountkey,accs);
   // Calculating new value of safebox
   // Calculating new value of safebox
+  FPreviousBlockSafeBoxHash := FSafeBoxHash;
   FSafeBoxHash := CalcSafeBoxHash;
   FSafeBoxHash := CalcSafeBoxHash;
 end;
 end;
 
 
@@ -771,18 +773,24 @@ procedure TPCSafeBox.Clear;
 Var i : Integer;
 Var i : Integer;
   P : PBlockAccount;
   P : PBlockAccount;
 begin
 begin
-  for i := 0 to FBlockAccountsList.Count - 1 do begin
-    P := FBlockAccountsList.Items[i];
-    Dispose(P);
-  end;
-  FBlockAccountsList.Clear;
-  For i:=0 to FListOfOrderedAccountKeysList.count-1 do begin
-    TOrderedAccountKeysList( FListOfOrderedAccountKeysList[i] ).ClearAccounts(False);
+  StartThreadSafe;
+  Try
+    for i := 0 to FBlockAccountsList.Count - 1 do begin
+      P := FBlockAccountsList.Items[i];
+      Dispose(P);
+    end;
+    FBlockAccountsList.Clear;
+    For i:=0 to FListOfOrderedAccountKeysList.count-1 do begin
+      TOrderedAccountKeysList( FListOfOrderedAccountKeysList[i] ).ClearAccounts(False);
+    end;
+    FBufferBlocksHash := '';
+    FTotalBalance := 0;
+    FTotalFee := 0;
+    FSafeBoxHash := CalcSafeBoxHash;
+    FPreviousBlockSafeBoxHash := '';
+  Finally
+    EndThreadSave;
   end;
   end;
-  FBufferBlocksHash := '';
-  FTotalBalance := 0;
-  FTotalFee := 0;
-  FSafeBoxHash := CalcSafeBoxHash;
 end;
 end;
 
 
 procedure TPCSafeBox.CopyFrom(accounts: TPCSafeBox);
 procedure TPCSafeBox.CopyFrom(accounts: TPCSafeBox);
@@ -790,30 +798,40 @@ Var i,j : Cardinal;
   P : PBlockAccount;
   P : PBlockAccount;
   BA : TBlockAccount;
   BA : TBlockAccount;
 begin
 begin
-  if accounts=Self then exit;
-  Clear;
-  if accounts.BlocksCount>0 then begin
-    for i := 0 to accounts.BlocksCount - 1 do begin
-      BA := accounts.Block(i);
-      New(P);
-      P^ := BA;
-      FBlockAccountsList.Add(P);
-      for j := Low(BA.accounts) to High(BA.accounts) do begin
-        AccountKeyListAddAccounts(BA.accounts[j].accountkey,[BA.accounts[j].account]);
+  StartThreadSafe;
+  Try
+    accounts.StartThreadSafe;
+    try
+      if accounts=Self then exit;
+      Clear;
+      if accounts.BlocksCount>0 then begin
+        for i := 0 to accounts.BlocksCount - 1 do begin
+          BA := accounts.Block(i);
+          New(P);
+          P^ := BA;
+          FBlockAccountsList.Add(P);
+          for j := Low(BA.accounts) to High(BA.accounts) do begin
+            AccountKeyListAddAccounts(BA.accounts[j].accountkey,[BA.accounts[j].account]);
+          end;
+        end;
       end;
       end;
+
+      FTotalBalance := accounts.TotalBalance;
+      FTotalFee := accounts.FTotalFee;
+      FBufferBlocksHash := accounts.FBufferBlocksHash;
+      FSafeBoxHash := accounts.FSafeBoxHash;
+      FPreviousBlockSafeBoxHash := accounts.FPreviousBlockSafeBoxHash;
+    finally
+      accounts.EndThreadSave;
     end;
     end;
+  finally
+    EndThreadSave;
   end;
   end;
-
-  FTotalBalance := accounts.TotalBalance;
-  FTotalFee := accounts.FTotalFee;
-  FBufferBlocksHash := accounts.FBufferBlocksHash;
-  FSafeBoxHash := accounts.FSafeBoxHash;
 end;
 end;
 
 
 constructor TPCSafeBox.Create;
 constructor TPCSafeBox.Create;
 begin
 begin
   FLock := TCriticalSection.Create;
   FLock := TCriticalSection.Create;
-  FIsLocked := false;
   FBlockAccountsList := TList.Create;
   FBlockAccountsList := TList.Create;
   FListOfOrderedAccountKeysList := TList.Create;
   FListOfOrderedAccountKeysList := TList.Create;
   Clear;
   Clear;
@@ -828,14 +846,12 @@ begin
   end;
   end;
   FreeAndNil(FBlockAccountsList);
   FreeAndNil(FBlockAccountsList);
   FreeAndNil(FListOfOrderedAccountKeysList);
   FreeAndNil(FListOfOrderedAccountKeysList);
-  FLock.Free;
+  FreeAndNil(FLock);
   inherited;
   inherited;
 end;
 end;
 
 
 procedure TPCSafeBox.EndThreadSave;
 procedure TPCSafeBox.EndThreadSave;
 begin
 begin
-  if Not FIsLocked then raise Exception.Create('Is not locked');
-  FIsLocked := False;
   FLock.Release;
   FLock.Release;
 end;
 end;
 
 
@@ -848,70 +864,81 @@ Var w : Word;
   j : Integer;
   j : Integer;
   safeBoxBankVersion : Word;
   safeBoxBankVersion : Word;
 begin
 begin
-  Clear;
-  Result := false;
-  Try
-    errors := 'Invalid stream';
-    TStreamOp.ReadAnsiString(Stream,s);
-    if (s<>CT_MagicIdentificator) then exit;
-    errors := 'Invalid version or corrupted stream';
-    if Stream.Size<8 then exit;
-    Stream.Read(w,2);
-    if w<>CT_BlockChain_Protocol_Version then exit;
-    Stream.Read(safeBoxBankVersion,2);
-    if safeBoxBankVersion<>CT_SafeBoxBankVersion then begin
-      errors := 'Invalid SafeBoxBank version: '+InttostR(safeBoxBankVersion);
-      exit;
-    end;
-    Stream.Read(blockscount,4);
-    if blockscount>(CT_NewLineSecondsAvg*2000000) then exit; // Protection for corrupted data...
-    errors := 'Corrupted stream';
-    for iblock := 0 to blockscount-1 do begin
-      errors := 'Corrupted stream reading block '+inttostr(iblock+1)+'/'+inttostr(blockscount);
-      block := CT_BlockAccount_NUL;
-      if Stream.Read(block.blockaccount,4)<4 then exit;
-      if (block.blockaccount<>iblock) then exit; // Invalid value
-      for iacc := Low(block.accounts) to High(block.accounts) do begin
-        errors := 'Corrupted stream reading account '+inttostr(iacc+1)+'/'+inttostr(length(block.accounts))+' of block '+inttostr(iblock+1)+'/'+inttostr(blockscount);
-        if Stream.Read(block.accounts[iacc].account,4)<4 then exit;
+  StartThreadSafe;
+  try
+    Clear;
+    Result := false;
+    Try
+      errors := 'Invalid stream';
+      TStreamOp.ReadAnsiString(Stream,s);
+      if (s<>CT_MagicIdentificator) then exit;
+      errors := 'Invalid version or corrupted stream';
+      if Stream.Size<8 then exit;
+      Stream.Read(w,2);
+      if w<>CT_BlockChain_Protocol_Version then exit;
+      Stream.Read(safeBoxBankVersion,2);
+      if safeBoxBankVersion<>CT_SafeBoxBankVersion then begin
+        errors := 'Invalid SafeBoxBank version: '+InttostR(safeBoxBankVersion);
+        exit;
+      end;
+      Stream.Read(blockscount,4);
+      if blockscount>(CT_NewLineSecondsAvg*2000000) then exit; // Protection for corrupted data...
+      // Build 1.3.0 to increase reading speed:
+      FBlockAccountsList.Capacity := blockscount;
+      errors := 'Corrupted stream';
+      for iblock := 0 to blockscount-1 do begin
+        errors := 'Corrupted stream reading block '+inttostr(iblock+1)+'/'+inttostr(blockscount);
+        block := CT_BlockAccount_NUL;
+        if Stream.Read(block.blockaccount,4)<4 then exit;
+        if (block.blockaccount<>iblock) then exit; // Invalid value
+        for iacc := Low(block.accounts) to High(block.accounts) do begin
+          errors := 'Corrupted stream reading account '+inttostr(iacc+1)+'/'+inttostr(length(block.accounts))+' of block '+inttostr(iblock+1)+'/'+inttostr(blockscount);
+          if Stream.Read(block.accounts[iacc].account,4)<4 then exit;
+          if TStreamOp.ReadAnsiString(Stream,s)<0 then exit;
+          block.accounts[iacc].accountkey := TAccountComp.RawString2Accountkey(s);
+          if Stream.Read(block.accounts[iacc].balance,SizeOf(UInt64))<SizeOf(UInt64) then exit;
+          if Stream.Read(block.accounts[iacc].updated_block,4)<4 then exit;
+          if Stream.Read(block.accounts[iacc].n_operation,4)<4 then exit;
+          if safeBoxBankVersion>=1 then begin
+            if Stream.Read(block.accounts[iacc].previous_updated_block,4)<4 then exit;
+          end;
+          // check valid
+          if not TAccountComp.IsValidAccountKey(block.accounts[iacc].accountkey,s) then begin
+            errors := errors + ' > '+s;
+            exit;
+          end;
+          inc(FTotalBalance,block.accounts[iacc].balance);
+        end;
+        errors := 'Corrupted stream reading block hash '+inttostr(iblock+1)+'/'+inttostr(blockscount);
+        if Stream.Read(block.timestamp,4)<4 then exit;
         if TStreamOp.ReadAnsiString(Stream,s)<0 then exit;
         if TStreamOp.ReadAnsiString(Stream,s)<0 then exit;
-        block.accounts[iacc].accountkey := TAccountComp.RawString2Accountkey(s);
-        if Stream.Read(block.accounts[iacc].balance,SizeOf(UInt64))<SizeOf(UInt64) then exit;
-        if Stream.Read(block.accounts[iacc].updated_block,4)<4 then exit;
-        if Stream.Read(block.accounts[iacc].n_operation,4)<4 then exit;
-        if safeBoxBankVersion>=1 then begin
-          if Stream.Read(block.accounts[iacc].previous_updated_block,4)<4 then exit;
+        block.block_hash := s;
+        // Check is valid:
+        if CalcBlockHash(block)<>block.block_hash then exit;
+        if safeBoxBankVersion>=2 then begin
+          if Stream.Read(block.target,4)<4 then exit;
         end;
         end;
-        // check valid
-        if not TAccountComp.IsValidAccountKey(block.accounts[iacc].accountkey,s) then begin
-          errors := errors + ' > '+s;
-          exit;
+        // Add
+        New(P);
+        P^ := block;
+        FBlockAccountsList.Add(P);
+        for j := low(block.accounts) to High(block.accounts) do begin
+          AccountKeyListAddAccounts(block.accounts[j].accountkey,[block.accounts[j].account]);
         end;
         end;
-        inc(FTotalBalance,block.accounts[iacc].balance);
-      end;
-      errors := 'Corrupted stream reading block hash '+inttostr(iblock+1)+'/'+inttostr(blockscount);
-      if Stream.Read(block.timestamp,4)<4 then exit;
-      if TStreamOp.ReadAnsiString(Stream,s)<0 then exit;
-      block.block_hash := s;
-      // Check is valid:
-      if CalcBlockHash(block)<>block.block_hash then exit;
-      if safeBoxBankVersion>=2 then begin
-        if Stream.Read(block.target,4)<4 then exit;
-      end;
-      // Add
-      New(P);
-      P^ := block;
-      FBlockAccountsList.Add(P);
-      for j := low(block.accounts) to High(block.accounts) do begin
-        AccountKeyListAddAccounts(block.accounts[j].accountkey,[block.accounts[j].account]);
+        FBufferBlocksHash := FBufferBlocksHash+block.block_hash;
+        LastReadBlock := block;
       end;
       end;
-      FBufferBlocksHash := FBufferBlocksHash+block.block_hash;
-      LastReadBlock := block;
-    end;
-    Result := true;
+      // Build 1.3.0 adding previous block hash information
+      TStreamOp.ReadAnsiString(Stream,FPreviousBlockSafeBoxHash);
+      // Build 1.3.0 adding calculation
+      FSafeBoxHash := CalcSafeBoxHash;
+      Result := true;
+    Finally
+      if Not Result then Clear;
+    End;
   Finally
   Finally
-    if Not Result then Clear;
-  End;
+    EndThreadSave;
+  end;
 end;
 end;
 
 
 class function TPCSafeBox.LoadSafeBoxStreamHeader(Stream: TStream; var BlocksCount: Cardinal): Boolean;
 class function TPCSafeBox.LoadSafeBoxStreamHeader(Stream: TStream; var BlocksCount: Cardinal): Boolean;
@@ -937,25 +964,32 @@ Var
   c,iblock,iacc : Cardinal;
   c,iblock,iacc : Cardinal;
   b : TBlockAccount;
   b : TBlockAccount;
 begin
 begin
-  TStreamOp.WriteAnsiString(Stream,CT_MagicIdentificator);
-  Stream.Write(CT_BlockChain_Protocol_Version,SizeOf(CT_BlockChain_Protocol_Version));
-  Stream.Write(CT_SafeBoxBankVersion,SizeOf(CT_SafeBoxBankVersion));
-  c := BlocksCount;
-  Stream.Write(c,Sizeof(c));
-  for iblock := 0 to c-1 do begin
-    b := Block(iblock);
-    Stream.Write(b.blockaccount,SizeOf(b.blockaccount)); // Little endian
-    for iacc := Low(b.accounts) to High(b.accounts) do begin
-      Stream.Write(b.accounts[iacc].account,Sizeof(b.accounts[iacc].account));
-      TStreamOp.WriteAnsiString(Stream,TAccountComp.AccountKey2RawString(b.accounts[iacc].accountkey));
-      Stream.Write(b.accounts[iacc].balance,Sizeof(b.accounts[iacc].balance));
-      Stream.Write(b.accounts[iacc].updated_block,Sizeof(b.accounts[iacc].updated_block));
-      Stream.Write(b.accounts[iacc].n_operation,Sizeof(b.accounts[iacc].n_operation));
-      Stream.Write(b.accounts[iacc].previous_updated_block,Sizeof(b.accounts[iacc].previous_updated_block));
+  StartThreadSafe;
+  Try
+    TStreamOp.WriteAnsiString(Stream,CT_MagicIdentificator);
+    Stream.Write(CT_BlockChain_Protocol_Version,SizeOf(CT_BlockChain_Protocol_Version));
+    Stream.Write(CT_SafeBoxBankVersion,SizeOf(CT_SafeBoxBankVersion));
+    c := BlocksCount;
+    Stream.Write(c,Sizeof(c));
+    for iblock := 0 to c-1 do begin
+      b := Block(iblock);
+      Stream.Write(b.blockaccount,SizeOf(b.blockaccount)); // Little endian
+      for iacc := Low(b.accounts) to High(b.accounts) do begin
+        Stream.Write(b.accounts[iacc].account,Sizeof(b.accounts[iacc].account));
+        TStreamOp.WriteAnsiString(Stream,TAccountComp.AccountKey2RawString(b.accounts[iacc].accountkey));
+        Stream.Write(b.accounts[iacc].balance,Sizeof(b.accounts[iacc].balance));
+        Stream.Write(b.accounts[iacc].updated_block,Sizeof(b.accounts[iacc].updated_block));
+        Stream.Write(b.accounts[iacc].n_operation,Sizeof(b.accounts[iacc].n_operation));
+        Stream.Write(b.accounts[iacc].previous_updated_block,Sizeof(b.accounts[iacc].previous_updated_block));
+      end;
+      Stream.Write(b.timestamp,Sizeof(b.timestamp));
+      TStreamOp.WriteAnsiString(Stream,b.block_hash);
+      Stream.Write(b.target,Sizeof(b.target));
     end;
     end;
-    Stream.Write(b.timestamp,Sizeof(b.timestamp));
-    TStreamOp.WriteAnsiString(Stream,b.block_hash);
-    Stream.Write(b.target,Sizeof(b.target));
+    // New Build 1.3.0
+    TStreamOp.WriteAnsiString(Stream,FPreviousBlockSafeBoxHash);
+  Finally
+    EndThreadSave;
   end;
   end;
 end;
 end;
 
 
@@ -991,12 +1025,7 @@ end;
 
 
 procedure TPCSafeBox.StartThreadSafe;
 procedure TPCSafeBox.StartThreadSafe;
 begin
 begin
-  if FIsLocked then Begin
-    TLog.NewLog(lterror,Classname,'IS LOCKED !!!');
-    raise Exception.Create('IS LOCKED !!!');
-  end;
   TPCThread.ProtectEnterCriticalSection(Self,FLock);
   TPCThread.ProtectEnterCriticalSection(Self,FLock);
-  FIsLocked := true;
 end;
 end;
 
 
 { TPCSafeBoxTransaction }
 { TPCSafeBoxTransaction }

+ 31 - 18
Units/PascalCoin/UBlockChain.pas

@@ -620,7 +620,7 @@ begin
           Clear;
           Clear;
         end;
         end;
       end;
       end;
-      NewLog(Nil, ltinfo,'Start restoring from disk operations (Max '+inttostr(max_block)+') Orphan: ' +Storage.Orphan);
+      NewLog(Nil, ltinfo,'Start restoring from disk operations (Max '+inttostr(max_block)+') BlockCount: '+inttostr(BlocksCount)+' Orphan: ' +Storage.Orphan);
       Operations := TPCOperationsComp.Create(Self);
       Operations := TPCOperationsComp.Create(Self);
       try
       try
         while ((BlocksCount<=max_block)) do begin
         while ((BlocksCount<=max_block)) do begin
@@ -804,6 +804,16 @@ begin
       finally
       finally
         op.Free;
         op.Free;
       end;
       end;
+      if (SafeBox.PreviousBlockSafeBoxHash<>'') then begin
+        if FLastOperationBlock.initial_safe_box_hash<>SafeBox.PreviousBlockSafeBoxHash then begin
+          errors := 'SafeBox Previous block safeboxhash <> operation safeboxhash. Invalid bank!';
+          TLog.NewLog(lterror,ClassName,'Previous SafeBoxHash <> Last operation block safebox hash on block '+
+            IntToStr(BlocksCount-1)+' '+TCrypto.ToHexaString(SafeBox.PreviousBlockSafeBoxHash)+'<>'+TCrypto.ToHexaString(FLastOperationBlock.initial_safe_box_hash));
+          Result := false;
+          Clear;
+          exit;
+        end;
+      end;
       FInitialSafeBoxHash := SafeBox.CalcSafeBoxHash;
       FInitialSafeBoxHash := SafeBox.CalcSafeBoxHash;
       if (BlocksCount>0) then FActualTargetHash := TargetFromCompact( FLastOperationBlock.compact_target );
       if (BlocksCount>0) then FActualTargetHash := TargetFromCompact( FLastOperationBlock.compact_target );
       // Initialize new target hash:
       // Initialize new target hash:
@@ -1782,8 +1792,6 @@ begin
   l := FHashTreeOperations.LockList;
   l := FHashTreeOperations.LockList;
   try
   try
     InternalAddOperationToHashTree(l,op);
     InternalAddOperationToHashTree(l,op);
-    inc(FTotalAmount,op.OperationAmount);
-    inc(FTotalFee,op.OperationFee);
   finally
   finally
     FHashTreeOperations.UnlockList;
     FHashTreeOperations.UnlockList;
   end;
   end;
@@ -1822,15 +1830,18 @@ begin
   end;
   end;
   ClearHastThree;
   ClearHastThree;
   lme := FHashTreeOperations.LockList;
   lme := FHashTreeOperations.LockList;
-  lsender := Sender.FHashTreeOperations.LockList;
   try
   try
-    for i := 0 to lsender.Count - 1 do begin
-      opsender := lsender[i];
-      InternalAddOperationToHashTree(lme,opsender);
+    lsender := Sender.FHashTreeOperations.LockList;
+    try
+      for i := 0 to lsender.Count - 1 do begin
+        opsender := lsender[i];
+        InternalAddOperationToHashTree(lme,opsender);
+      end;
+    finally
+      Sender.FHashTreeOperations.UnlockList;
     end;
     end;
   finally
   finally
     FHashTreeOperations.UnlockList;
     FHashTreeOperations.UnlockList;
-    Sender.FHashTreeOperations.UnlockList;
   end;
   end;
 end;
 end;
 
 
@@ -1892,20 +1903,22 @@ Var ms : TMemoryStream;
 begin
 begin
   ms := TMemoryStream.Create;
   ms := TMemoryStream.Create;
   try
   try
-      newOp := TPCOperation( op.NewInstance );
-      op.SaveToStream(ms);
-      ms.Position := 0;
-      newOp.LoadFromStream(ms);
-      newOp.FPrevious_Sender_updated_block := op.Previous_Sender_updated_block;
-      newOp.FPrevious_Destination_updated_block := op.FPrevious_Destination_updated_block;
-      h := TCrypto.DoSha256(ms.Memory,ms.Size);
-      newOp.tag := list.Count;
-      list.Add(newOp);
+    newOp := TPCOperation( op.NewInstance );
+    op.SaveToStream(ms);
+    ms.Position := 0;
+    newOp.LoadFromStream(ms);
+    newOp.FPrevious_Sender_updated_block := op.Previous_Sender_updated_block;
+    newOp.FPrevious_Destination_updated_block := op.FPrevious_Destination_updated_block;
+    h := TCrypto.DoSha256(ms.Memory,ms.Size);
+    newOp.tag := list.Count;
+    list.Add(newOp);
   finally
   finally
-      ms.Free;
+    ms.Free;
   end;
   end;
   // Include to hash tree
   // Include to hash tree
   FHashTree := TCrypto.DoSha256(FHashTree+h);
   FHashTree := TCrypto.DoSha256(FHashTree+h);
+  inc(FTotalAmount,op.OperationAmount);
+  inc(FTotalFee,op.OperationFee);
 end;
 end;
 
 
 function TOperationsHashTree.OperationsCount: Integer;
 function TOperationsHashTree.OperationsCount: Integer;

+ 2 - 2
Units/PascalCoin/UConst.pas

@@ -80,7 +80,7 @@ Const
 
 
   CT_MaxClientsConnected = 100;
   CT_MaxClientsConnected = 100;
 
 
-  CT_BankToDiskEveryNBlocks = 1000;
+  CT_BankToDiskEveryNBlocks = 500; // Build 1.3.0 Changed from 1000 to 500
 
 
   CT_Default_EC_OpenSSL_NID = NID_secp256k1;
   CT_Default_EC_OpenSSL_NID = NID_secp256k1;
 
 
@@ -104,7 +104,7 @@ Const
   CT_Op_Changekey = $02;
   CT_Op_Changekey = $02;
   CT_Op_Recover = $03;
   CT_Op_Recover = $03;
 
 
-  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.2.0'{$ELSE}{$IFDEF TESTNET}'TESTNET'{$ELSE}{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.3.0'{$ELSE}{$IFDEF TESTNET}'TESTNET'{$ELSE}{$ENDIF}{$ENDIF};
 
 
   CT_Discover_IPs =  'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin1.ddns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us';
   CT_Discover_IPs =  'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin1.ddns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us';
 
 

+ 25 - 7
Units/PascalCoin/UFileStorage.pas

@@ -69,7 +69,7 @@ Type
 
 
 implementation
 implementation
 
 
-Uses ULog, SysUtils, UThread;
+Uses ULog, SysUtils, UThread, UConst;
 
 
 { TFileStorage }
 { TFileStorage }
 
 
@@ -255,6 +255,7 @@ var
     folder : AnsiString;
     folder : AnsiString;
     filename,auxfn : AnsiString;
     filename,auxfn : AnsiString;
     fs : TFileStream;
     fs : TFileStream;
+    ms : TMemoryStream;
     errors : AnsiString;
     errors : AnsiString;
     blockscount, c : Cardinal;
     blockscount, c : Cardinal;
 begin
 begin
@@ -281,9 +282,17 @@ begin
     if (filename<>'') then begin
     if (filename<>'') then begin
       fs := TFileStream.Create(filename,fmOpenRead);
       fs := TFileStream.Create(filename,fmOpenRead);
       try
       try
-        if not Bank.LoadBankFromStream(fs,errors) then begin
-          TLog.NewLog(lterror,ClassName,'Error reading bank from file: '+filename+ ' Error: '+errors);
-        end;
+        ms := TMemoryStream.Create;
+        Try
+          ms.CopyFrom(fs,0);
+          fs.Position := 0;
+          ms.Position := 0;
+          if not Bank.LoadBankFromStream(ms,errors) then begin
+            TLog.NewLog(lterror,ClassName,'Error reading bank from file: '+filename+ ' Error: '+errors);
+          end;
+        Finally
+          ms.Free;
+        End;
       finally
       finally
         fs.Free;
         fs.Free;
       end;
       end;
@@ -296,6 +305,7 @@ end;
 function TFileStorage.DoSaveBank: Boolean;
 function TFileStorage.DoSaveBank: Boolean;
 var fs: TFileStream;
 var fs: TFileStream;
     bankfilename: AnsiString;
     bankfilename: AnsiString;
+    ms : TMemoryStream;
 begin
 begin
   Result := true;
   Result := true;
   bankfilename := GetBankFileName(GetFolder(Orphan),Bank.BlocksCount);
   bankfilename := GetBankFileName(GetFolder(Orphan),Bank.BlocksCount);
@@ -303,7 +313,15 @@ begin
     fs := TFileStream.Create(bankfilename,fmCreate);
     fs := TFileStream.Create(bankfilename,fmCreate);
     try
     try
       fs.Size := 0;
       fs.Size := 0;
-      Bank.SaveBankToStream(fs);
+      ms := TMemoryStream.Create;
+      try
+        Bank.SaveBankToStream(ms);
+        ms.Position := 0;
+        fs.Position := 0;
+        fs.CopyFrom(ms,0);
+      finally
+        ms.Free;
+      end;
     finally
     finally
       fs.Free;
       fs.Free;
     end;
     end;
@@ -341,7 +359,7 @@ begin
   Result := '';
   Result := '';
   If not ForceDirectories(BaseDataFolder) then exit;
   If not ForceDirectories(BaseDataFolder) then exit;
   // We will store last 5 banks
   // We will store last 5 banks
-  Result := BaseDataFolder + PathDelim+'bank'+ inttostr(block MOD 5)+'.bank';
+  Result := BaseDataFolder + PathDelim+'bank'+ inttostr((block DIV CT_BankToDiskEveryNBlocks) MOD 5)+'.bank';
 end;
 end;
 
 
 function TFileStorage.GetBlockHeaderFirstBytePosition(Stream : TStream; Block: Cardinal; var StreamBlockHeaderStartPos: Int64; var BlockHeaderFirstBlock: Cardinal): Boolean;
 function TFileStorage.GetBlockHeaderFirstBytePosition(Stream : TStream; Block: Cardinal; var StreamBlockHeaderStartPos: Int64; var BlockHeaderFirstBlock: Cardinal): Boolean;
@@ -579,7 +597,7 @@ begin
   if (BlockHeaderFirstBlock>Block) then raise Exception.Create('Dev error 20160917-1');
   if (BlockHeaderFirstBlock>Block) then raise Exception.Create('Dev error 20160917-1');
   if (BlockHeaderFirstBlock+CT_GroupBlockSize)<Block then raise Exception.Create('Dev error 20160917-2');
   if (BlockHeaderFirstBlock+CT_GroupBlockSize)<Block then raise Exception.Create('Dev error 20160917-2');
   if Stream.Size< (StreamBlockHeaderStartPos + (GetBlockHeaderFixedSize)) then begin
   if Stream.Size< (StreamBlockHeaderStartPos + (GetBlockHeaderFixedSize)) then begin
-    TLog.NewLog(ltError,Classname,'Invalid stream size');
+    // Not log... it's normal when finding block   TLog.NewLog(ltError,Classname,Format('Invalid stream size %d < (%d + %d) Reading block %d',[Stream.Size,StreamBlockHeaderStartPos,GetBlockHeaderFixedSize,Block]));
     exit;
     exit;
   end;
   end;
   Stream.Position := StreamBlockHeaderStartPos + (CT_SizeOfBlockHeader*(Block-BlockHeaderFirstBlock));
   Stream.Position := StreamBlockHeaderStartPos + (CT_SizeOfBlockHeader*(Block-BlockHeaderFirstBlock));

+ 51 - 49
Units/PascalCoin/UNetProtocol.pas

@@ -1634,7 +1634,8 @@ begin
       ms.Free;
       ms.Free;
     end;
     end;
     If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
     If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
-       AND ((FLastDataReceivedTS+(1000*60)<GetTickCount) AND (FLastDataSendedTS+(1000*60)<GetTickCount)) then begin
+       AND ((FLastDataReceivedTS+(1000*120)<GetTickCount) AND (FLastDataSendedTS+(1000*120)<GetTickCount)) then begin
+       // Build 1.3 -> Changing wait time from 60 to 120 secs.
       DebugStep := 'LastSend time old';
       DebugStep := 'LastSend time old';
       If TNetData.NetData.PendingRequest(Self,ops)>=2 then begin
       If TNetData.NetData.PendingRequest(Self,ops)>=2 then begin
         TLog.NewLog(ltDebug,Classname,'Pending requests without response... closing connection to '+ClientRemoteAddr+' > '+ops);
         TLog.NewLog(ltDebug,Classname,'Pending requests without response... closing connection to '+ClientRemoteAddr+' > '+ops);
@@ -2801,61 +2802,62 @@ begin
       netserverclientstop := Nil;
       netserverclientstop := Nil;
       needother := true;
       needother := true;
       FLastCheckTS := GetTickCount;
       FLastCheckTS := GetTickCount;
-      l := FNetData.FNetConnections.LockList;
-      try
-        ntotal := l.Count;
-        newstats := CT_TNetStatistics_NUL;
-        for i := l.Count-1 downto 0 do begin
-          netconn := TNetConnection(l.Items[i]);
-          if (netconn is TNetClient) then begin
-            if (netconn.Connected) then begin
-              inc(newstats.ServersConnections);
-              if (netconn.FHasReceivedData) then inc(newstats.ServersConnectionsWithResponse);
-            end;
-            if (Not TNetClient(netconn).Connected) And (netconn.CreatedTime+EncodeTime(0,0,5,0)<now) then begin
-              // Free this!
-              TNetClient(netconn).FinalizeConnection;
-              inc(ndeleted);
-            end else inc(nactive);
-          end else if (netconn is TNetServerClient) then begin
-            if (netconn.Connected) then begin
-              inc(newstats.ClientsConnections);
-            end;
-            inc(nserverclients);
-            if (Not netconn.FDoFinalizeConnection) then begin
-              // Build 1.0.9 BUG-101 Only disconnect old versions prior to 1.0.9
-              if not assigned(netserverclientstop) then begin
-                netserverclientstop := TNetServerClient(netconn);
-                aux := Copy(netconn.FClientAppVersion,1,5);
-                needother := Not ((aux='1.0.6') or (aux='1.0.7') or (aux='1.0.8'));
-              end else begin
-                aux := Copy(netconn.FClientAppVersion,1,5);
-                if ((aux='1.0.6') or (aux='1.0.7') or (aux='1.0.8'))
-                  And ((needother) Or (netconn.CreatedTime<netserverclientstop.CreatedTime)) then begin
-                  needother := false;
+      If (FNetData.FNetConnections.TryLockList(100,l)) then begin
+        try
+          ntotal := l.Count;
+          newstats := CT_TNetStatistics_NUL;
+          for i := l.Count-1 downto 0 do begin
+            netconn := TNetConnection(l.Items[i]);
+            if (netconn is TNetClient) then begin
+              if (netconn.Connected) then begin
+                inc(newstats.ServersConnections);
+                if (netconn.FHasReceivedData) then inc(newstats.ServersConnectionsWithResponse);
+              end;
+              if (Not TNetClient(netconn).Connected) And (netconn.CreatedTime+EncodeTime(0,0,5,0)<now) then begin
+                // Free this!
+                TNetClient(netconn).FinalizeConnection;
+                inc(ndeleted);
+              end else inc(nactive);
+            end else if (netconn is TNetServerClient) then begin
+              if (netconn.Connected) then begin
+                inc(newstats.ClientsConnections);
+              end;
+              inc(nserverclients);
+              if (Not netconn.FDoFinalizeConnection) then begin
+                // Build 1.0.9 BUG-101 Only disconnect old versions prior to 1.0.9
+                if not assigned(netserverclientstop) then begin
                   netserverclientstop := TNetServerClient(netconn);
                   netserverclientstop := TNetServerClient(netconn);
+                  aux := Copy(netconn.FClientAppVersion,1,5);
+                  needother := Not ((aux='1.0.6') or (aux='1.0.7') or (aux='1.0.8'));
+                end else begin
+                  aux := Copy(netconn.FClientAppVersion,1,5);
+                  if ((aux='1.0.6') or (aux='1.0.7') or (aux='1.0.8'))
+                    And ((needother) Or (netconn.CreatedTime<netserverclientstop.CreatedTime)) then begin
+                    needother := false;
+                    netserverclientstop := TNetServerClient(netconn);
+                  end;
                 end;
                 end;
               end;
               end;
             end;
             end;
           end;
           end;
+          // Update stats:
+          FNetData.FNetStatistics.ActiveConnections := newstats.ClientsConnections + newstats.ServersConnections;
+          FNetData.FNetStatistics.ClientsConnections := newstats.ClientsConnections;
+          FNetData.FNetStatistics.ServersConnections := newstats.ServersConnections;
+          FNetData.FNetStatistics.ServersConnectionsWithResponse := newstats.ServersConnectionsWithResponse;
+          // Must stop clients?
+          if (nserverclients>CT_MaxServersConnected) And // This is to ensure there are more serverclients than clients
+             ((nserverclients + nactive + ndeleted)>=CT_MaxClientsConnected) And (Assigned(netserverclientstop)) then begin
+            TLog.NewLog(ltinfo,Classname,Format('Sending FinalizeConnection NetServerClients:%d Servers_active:%d Servers_deleted:%d',[nserverclients,nactive,ndeleted]));
+            netserverclientstop.FinalizeConnection;
+          end;
+        finally
+          FNetData.FNetConnections.UnlockList;
         end;
         end;
-        // Update stats:
-        FNetData.FNetStatistics.ActiveConnections := newstats.ClientsConnections + newstats.ServersConnections;
-        FNetData.FNetStatistics.ClientsConnections := newstats.ClientsConnections;
-        FNetData.FNetStatistics.ServersConnections := newstats.ServersConnections;
-        FNetData.FNetStatistics.ServersConnectionsWithResponse := newstats.ServersConnectionsWithResponse;
-        // Must stop clients?
-        if (nserverclients>CT_MaxServersConnected) And // This is to ensure there are more serverclients than clients
-           ((nserverclients + nactive + ndeleted)>=CT_MaxClientsConnected) And (Assigned(netserverclientstop)) then begin
-          TLog.NewLog(ltinfo,Classname,Format('Sending FinalizeConnection NetServerClients:%d Servers_active:%d Servers_deleted:%d',[nserverclients,nactive,ndeleted]));
-          netserverclientstop.FinalizeConnection;
+        if (nactive<=CT_MaxServersConnected) And (Not Terminated) then begin
+          // Discover
+          FNetData.DiscoverServers;
         end;
         end;
-      finally
-        FNetData.FNetConnections.UnlockList;
-      end;
-      if (nactive<=CT_MaxServersConnected) And (Not Terminated) then begin
-        // Discover
-        FNetData.DiscoverServers;
       end;
       end;
     end;
     end;
     sleep(100);
     sleep(100);

+ 5 - 3
Units/PascalCoin/UNode.pas

@@ -78,7 +78,7 @@ Type
     //
     //
     Procedure NotifyBlocksChanged;
     Procedure NotifyBlocksChanged;
     //
     //
-    procedure GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDeep : Integer);
+    procedure GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDeep, MaxOperations : Integer);
     Function FindOperation(Const OperationComp : TPCOperationsComp; Const OperationHash : TRawBytes; var block : Cardinal; var operation_block_index : Integer) : Boolean;
     Function FindOperation(Const OperationComp : TPCOperationsComp; Const OperationHash : TRawBytes; var block : Cardinal; var operation_block_index : Integer) : Boolean;
     //
     //
     Procedure AutoDiscoverNodes(Const ips : AnsiString);
     Procedure AutoDiscoverNodes(Const ips : AnsiString);
@@ -631,7 +631,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TNode.GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDeep: Integer);
+procedure TNode.GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDeep, MaxOperations: Integer);
   Procedure DoGetFromBlock(block_number : Cardinal; last_balance : Int64; act_deep : Integer);
   Procedure DoGetFromBlock(block_number : Cardinal; last_balance : Int64; act_deep : Integer);
   var opc : TPCOperationsComp;
   var opc : TPCOperationsComp;
     op : TPCOperation;
     op : TPCOperation;
@@ -683,7 +683,9 @@ procedure TNode.GetStoredOperationsFromAccount(const OperationsResume: TOperatio
         //
         //
         opc.Clear(true);
         opc.Clear(true);
         if (next_block_number>=0) And (next_block_number<block_number) And (act_deep>0)
         if (next_block_number>=0) And (next_block_number<block_number) And (act_deep>0)
-           And (next_block_number >= (account_number DIV CT_AccountsPerBlock)) then DoGetFromBlock(next_block_number,last_balance,act_deep-1);
+           And (next_block_number >= (account_number DIV CT_AccountsPerBlock))
+           And ((OperationsResume.Count<MaxOperations) Or (MaxOperations<=0))
+           then DoGetFromBlock(next_block_number,last_balance,act_deep-1);
       finally
       finally
         l.Free;
         l.Free;
       end;
       end;

+ 303 - 52
Units/PascalCoin/URPC.pas

@@ -405,7 +405,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     jsonObject.GetAsVariant('ophash').Value := TCrypto.ToHexaString(OPR.OperationHash);
     jsonObject.GetAsVariant('ophash').Value := TCrypto.ToHexaString(OPR.OperationHash);
   end;
   end;
 
 
-  Function GetAccountOperations(AccountNumber : Cardinal; jsonArray : TPCJSONArray; MaxBlocksDeep : Integer) : Boolean;
+  Function GetAccountOperations(AccountNumber : Cardinal; jsonArray : TPCJSONArray; MaxBlocksDeep,start,max : Integer) : Boolean;
   var list : TList;
   var list : TList;
     Op : TPCOperation;
     Op : TPCOperation;
     OPR : TOperationResume;
     OPR : TOperationResume;
@@ -430,12 +430,17 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
       Finally
       Finally
         list.Free;
         list.Free;
       End;
       End;
-      TNode.Node.GetStoredOperationsFromAccount(OperationsResume,AccountNumber,MaxBlocksDeep);
+      if ((max<=0) Or (OperationsResume.Count<(max+start))) then begin
+        TNode.Node.GetStoredOperationsFromAccount(OperationsResume,AccountNumber,MaxBlocksDeep,max+start);
+      end;
       //
       //
       for i:=0 to OperationsResume.Count-1 do begin
       for i:=0 to OperationsResume.Count-1 do begin
-        Obj := jsonArray.GetAsObject(i);
-        OPR := OperationsResume[i];
-        FillOperationResumeToJSONObject(OPR,Obj);
+        if (i>=start) then begin
+          Obj := jsonArray.GetAsObject(jsonArray.Count);
+          OPR := OperationsResume[i];
+          FillOperationResumeToJSONObject(OPR,Obj);
+          if ((max>0) And (jsonArray.Count>=max)) then break; // stop
+        end;
       end;
       end;
       Result := True;
       Result := True;
     finally
     finally
@@ -602,6 +607,139 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     end;
     end;
   end;
   end;
 
 
+  Function GetCardinalsValues(ordinals_coma_separated : String; cardinals : TOrderedCardinalList; var errors : AnsiString) : Boolean;
+  Var i,istart : Integer;
+    ctxt : String;
+    an : Cardinal;
+  begin
+    result := false;
+    cardinals.Clear;
+    errors := '';
+    ctxt := '';
+    istart := 1;
+    for i := 1 to length(ordinals_coma_separated) do begin
+      case ordinals_coma_separated[i] of
+        '0'..'9','-' : ctxt := ctxt + ordinals_coma_separated[i];
+        ',',';' : begin
+          if trim(ctxt)<>'' then begin
+            if Not TAccountComp.AccountTxtNumberToAccountNumber(trim(ctxt),an) then begin
+              errors := 'Invalid account number at pos '+IntToStr(istart)+': '+ctxt;
+              exit;
+            end;
+            cardinals.Add(an);
+          end;
+          ctxt := '';
+          istart := i+1;
+        end;
+        ' ' : ; // Continue...
+      else
+        errors := 'Invalid char at pos '+inttostr(i)+': "'+ordinals_coma_separated[i]+'"';
+        exit;
+      end;
+    end;
+    //
+    if (trim(ctxt)<>'') then begin
+      if Not TAccountComp.AccountTxtNumberToAccountNumber(trim(ctxt),an) then begin
+        errors := 'Invalid account number at pos '+IntToStr(istart)+': '+ctxt;
+        exit;
+      end;
+      cardinals.Add(an);
+    end;
+    if cardinals.Count=0 then begin
+      errors := 'No valid value';
+      exit;
+    end;
+    Result := true;
+  end;
+
+  Function ChangeAccountsKey(accounts_txt : String; new_pub_key : TAccountKey; fee : UInt64; RawPayload : TRawBytes; Const Payload_method, EncodePwd : AnsiString) : Boolean;
+  // "payload_method" types: "none","dest"(default),"sender","aes"(must provide "pwd" param)
+  Var opck : TOpChangeKey;
+    acc : TAccount;
+    i,ian : Integer;
+    errors : AnsiString;
+    opr : TOperationResume;
+    f_raw : TRawBytes;
+    accountsnumber : TOrderedCardinalList;
+    operationsht : TOperationsHashTree;
+  begin
+    Result := false;
+    accountsnumber := TOrderedCardinalList.Create;
+    try
+      if not GetCardinalsValues(accounts_txt,accountsnumber,errors) then begin
+        ErrorDesc := 'Error in accounts: '+errors;
+        ErrorNum := CT_RPC_ErrNum_InvalidAccount;
+        Exit;
+      end;
+      operationsht := TOperationsHashTree.Create;
+      try
+        for ian := 0 to accountsnumber.Count - 1 do begin
+
+          if (accountsnumber.Get(ian)<0) or (accountsnumber.Get(ian)>=TNode.Node.Bank.AccountsCount) then begin
+            ErrorDesc:='Invalid account '+Inttostr(accountsnumber.Get(ian));
+            ErrorNum:=CT_RPC_ErrNum_InvalidAccount;
+            Exit;
+          end;
+          acc := TNode.Node.Operations.SafeBoxTransaction.Account(accountsnumber.Get(ian));
+          _RPCServer.FWalletKeys.AccountsKeyList.IndexOfAccountKey(acc.accountkey);
+          i := _RPCServer.FWalletKeys.IndexOfAccountKey(acc.accountkey);
+          if (i<0) then begin
+            ErrorDesc:='Private key of account '+Inttostr(acc.account)+' not found in wallet';
+            ErrorNum:=CT_RPC_ErrNum_InvalidAccount;
+            Exit;
+          end;
+          if (Not assigned(_RPCServer.FWalletKeys.Key[i].PrivateKey)) then begin
+            if _RPCServer.FWalletKeys.Key[i].CryptedKey<>'' then begin
+              // Wallet is password protected
+              ErrorDesc := 'Wallet is password protected for account '+IntToStr(acc.account);
+              ErrorNum := CT_RPC_ErrNum_WalletPasswordProtected;
+            end else begin
+              ErrorDesc := 'Wallet private key not found in Wallet for account '+IntToStr(acc.account);
+              ErrorNum := CT_RPC_ErrNum_InvalidAccount;
+            end;
+            exit;
+          end;
+          if (length(RawPayload)>0) then begin
+            if (Payload_method='none') then f_raw:=RawPayload
+            else if (Payload_method='dest') then begin
+              f_raw := ECIESEncrypt(new_pub_key,RawPayload);
+            end else if (Payload_method='sender') then begin
+              f_raw := ECIESEncrypt(acc.accountkey,RawPayload);
+            end else if (Payload_method='aes') then begin
+              f_raw := TAESComp.EVP_Encrypt_AES256(RawPayload,EncodePwd);
+            end else begin
+              ErrorNum:=CT_RPC_ErrNum_InvalidOperation;
+              ErrorDesc:='Invalid encode payload method: '+Payload_method;
+              exit;
+            end;
+          end else f_raw := '';
+          opck := TOpChangeKey.Create(acc.account,acc.n_operation+1,_RPCServer.FWalletKeys.Key[i].PrivateKey,new_pub_key,fee,f_raw);
+          try
+            operationsht.AddOperationToHashTree(opck);
+          finally
+            opck.free;
+          end;
+        end; // For
+        // Ready to execute...
+        i := TNode.Node.AddOperations(Nil,operationsht,errors);
+        if (i<0) then begin
+          ErrorNum:=CT_RPC_ErrNum_InternalError;
+          ErrorDesc:=errors;
+          exit;
+        end;
+        GetResultObject.GetAsVariant('accounts_total').Value := operationsht.OperationsCount;
+        GetResultObject.GetAsVariant('accounts_ok').Value := i;
+        GetResultObject.GetAsVariant('accounts_error').Value := operationsht.OperationsCount - i;
+        GetResultObject.GetAsVariant('errors').Value := errors;
+        Result := true;
+      finally
+        operationsht.Free;
+      end;
+    finally
+      accountsnumber.Free;
+    end;
+  end;
+
   Procedure FillAccountObject(Const account : TAccount; jsonObj : TPCJSONObject);
   Procedure FillAccountObject(Const account : TAccount; jsonObj : TPCJSONObject);
   Begin
   Begin
     jsonObj.GetAsVariant('account').Value:=account.account;
     jsonObj.GetAsVariant('account').Value:=account.account;
@@ -611,6 +749,15 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     jsonObj.GetAsVariant('updated_b').Value:=account.updated_block;
     jsonObj.GetAsVariant('updated_b').Value:=account.updated_block;
   end;
   end;
 
 
+  Procedure FillPublicKeyObject(const PubKey : TAccountKey; jsonObj : TPCJSONObject);
+  Begin
+    jsonObj.GetAsVariant('ec_nid').Value := PubKey.EC_OpenSSL_NID;
+    jsonObj.GetAsVariant('x').Value := TCrypto.ToHexaString(PubKey.x);
+    jsonObj.GetAsVariant('y').Value := TCrypto.ToHexaString(PubKey.y);
+    jsonObj.GetAsVariant('enc_pubkey').Value := TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(PubKey));
+    jsonObj.GetAsVariant('b58_pubkey').Value := TAccountComp.AccountPublicKeyExport(PubKey);
+  End;
+
   Function DoEncrypt(RawPayload : TRawBytes; pub_key : TAccountKey; Const Payload_method, EncodePwd : AnsiString) : Boolean;
   Function DoEncrypt(RawPayload : TRawBytes; pub_key : TAccountKey; Const Payload_method, EncodePwd : AnsiString) : Boolean;
   Var f_raw : TRawBytes;
   Var f_raw : TRawBytes;
   begin
   begin
@@ -677,8 +824,39 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     Result := true;
     Result := true;
   End;
   End;
 
 
+  Function CapturePubKey(const prefix : String; var pubkey : TAccountKey; var errortxt : String) : Boolean;
+  var ansistr : AnsiString;
+    auxpubkey : TAccountKey;
+  begin
+    pubkey := CT_Account_NUL.accountkey;
+    errortxt := '';
+    Result := false;
+    if (params.IndexOfName(prefix+'b58_pubkey')>=0) then begin
+      If Not TAccountComp.AccountPublicKeyImport(params.AsString(prefix+'b58_pubkey',''),pubkey,ansistr) then begin
+        errortxt:= 'Invalid value of param "'+prefix+'b58_pubkey": '+ansistr;
+        exit;
+      end;
+      if (params.IndexOfName(prefix+'enc_pubkey')>=0) then begin
+        auxpubkey := TAccountComp.RawString2Accountkey(TCrypto.HexaToRaw(params.AsString(prefix+'enc_pubkey','')));
+        if (Not TAccountComp.Equal(auxpubkey,pubkey)) then begin
+          errortxt := 'Params "'+prefix+'b58_pubkey" and "'+prefix+'enc_pubkey" public keys are not the same public key';
+          exit;
+        end;
+      end;
+    end else begin
+      if (params.IndexOfName(prefix+'enc_pubkey')<0) then begin
+        errortxt := 'Need param "'+prefix+'enc_pubkey" or "'+prefix+'b58_pubkey"';
+        exit;
+      end;
+      pubkey := TAccountComp.RawString2Accountkey(TCrypto.HexaToRaw(params.AsString(prefix+'enc_pubkey','')));
+    end;
+    If Not TAccountComp.IsValidAccountKey(pubkey,ansistr) then begin
+      errortxt := 'Invalid public key: '+ansistr;
+    end else Result := true;
+  end;
+
 Var c,c2 : Cardinal;
 Var c,c2 : Cardinal;
-  i,j : Integer;
+  i,j,k,l : Integer;
   account : TAccount;
   account : TAccount;
   ansistr : AnsiString;
   ansistr : AnsiString;
   nsaarr : TNodeServerAddressArray;
   nsaarr : TNodeServerAddressArray;
@@ -720,12 +898,9 @@ begin
   end else if (method='getwalletaccounts') then begin
   end else if (method='getwalletaccounts') then begin
     // Returns JSON array with accounts in Wallet
     // Returns JSON array with accounts in Wallet
     jsonarr := jsonresponse.GetAsArray('result');
     jsonarr := jsonresponse.GetAsArray('result');
-    if (params.IndexOfName('enc_pubkey')>=0) then begin
-      r := TCrypto.HexaToRaw(params.AsString('enc_pubkey',''));
-      opr.newKey := TAccountComp.RawString2Accountkey(r);
-      if Not TAccountComp.IsValidAccountKey(opr.newKey,ansistr) then begin
+    if (params.IndexOfName('enc_pubkey')>=0) Or (params.IndexOfName('b58_pubkey')>=0) then begin
+      if Not (CapturePubKey('',opr.newKey,ErrorDesc)) then begin
         ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
         ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
-        ErrorDesc := 'Invalid public key in param enc_pubkey: '+ansistr;
         exit;
         exit;
       end;
       end;
       i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
       i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
@@ -735,30 +910,40 @@ begin
         exit;
         exit;
       end;
       end;
       ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
       ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
+      k := params.AsInteger('max',100);
+      l := params.AsInteger('start',0);
       for j := 0 to ocl.Count - 1 do begin
       for j := 0 to ocl.Count - 1 do begin
-        account := TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j));
-        FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+        if (j>=l) then begin
+          account := TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j));
+          FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+        end;
+        if (k>0) And ((j+1)>=(k+l)) then break;
       end;
       end;
       Result := true;
       Result := true;
     end else begin
     end else begin
+      k := params.AsInteger('max',100);
+      l := params.AsInteger('start',0);
+      c := 0;
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
         ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         for j := 0 to ocl.Count - 1 do begin
         for j := 0 to ocl.Count - 1 do begin
-          account := TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j));
-          FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+          if (c>=l) then begin
+            account := TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j));
+            FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+          end;
+          inc(c);
+          if (k>0) And (c>=(k+l)) then break;
         end;
         end;
+        if (k>0) And (c>=(k+l)) then break;
       end;
       end;
       Result := true;
       Result := true;
     end;
     end;
   end else if (method='getwalletaccountscount') then begin
   end else if (method='getwalletaccountscount') then begin
     // New Build 1.1.1
     // New Build 1.1.1
     // Returns a number with count value
     // Returns a number with count value
-    if (params.IndexOfName('enc_pubkey')>=0) then begin
-      r := TCrypto.HexaToRaw(params.AsString('enc_pubkey',''));
-      opr.newKey := TAccountComp.RawString2Accountkey(r);
-      if Not TAccountComp.IsValidAccountKey(opr.newKey,ansistr) then begin
+    if (params.IndexOfName('enc_pubkey')>=0) Or (params.IndexOfName('b58_pubkey')>=0) then begin
+      if Not (CapturePubKey('',opr.newKey,ErrorDesc)) then begin
         ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
         ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
-        ErrorDesc := 'Invalid public key in param enc_pubkey: '+ansistr;
         exit;
         exit;
       end;
       end;
       i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
       i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
@@ -771,6 +956,7 @@ begin
       jsonresponse.GetAsVariant('result').value := ocl.count;
       jsonresponse.GetAsVariant('result').value := ocl.count;
       Result := true;
       Result := true;
     end else begin
     end else begin
+      ErrorDesc := '';
       c :=0;
       c :=0;
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
         ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
@@ -780,12 +966,9 @@ begin
       Result := true;
       Result := true;
     end;
     end;
   end else if (method='getwalletcoins') then begin
   end else if (method='getwalletcoins') then begin
-    if (params.IndexOfName('enc_pubkey')>=0) then begin
-      r := TCrypto.HexaToRaw(params.AsString('enc_pubkey',''));
-      opr.newKey := TAccountComp.RawString2Accountkey(r);
-      if Not TAccountComp.IsValidAccountKey(opr.newKey,ansistr) then begin
+    if (params.IndexOfName('enc_pubkey')>=0) Or (params.IndexOfName('b58_pubkey')>=0) then begin
+      if Not (CapturePubKey('',opr.newKey,ErrorDesc)) then begin
         ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
         ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
-        ErrorDesc := 'Invalid public key in param enc_pubkey: '+ansistr;
         exit;
         exit;
       end;
       end;
       i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
       i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
@@ -802,6 +985,7 @@ begin
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       Result := true;
       Result := true;
     end else begin
     end else begin
+      ErrorDesc := '';
       c :=0;
       c :=0;
       account.balance := 0;
       account.balance := 0;
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
@@ -815,13 +999,32 @@ begin
     end;
     end;
   end else if (method='getwalletpubkeys') then begin
   end else if (method='getwalletpubkeys') then begin
     // Returns JSON array with pubkeys in wallet
     // Returns JSON array with pubkeys in wallet
+    k := params.AsInteger('max',100);
+    j := params.AsInteger('start',0);
     jsonarr := jsonresponse.GetAsArray('result');
     jsonarr := jsonresponse.GetAsArray('result');
     for i:=0 to _RPCServer.WalletKeys.Count-1 do begin
     for i:=0 to _RPCServer.WalletKeys.Count-1 do begin
-      jsonarr.GetAsObject(i).GetAsVariant('name').Value := _RPCServer.WalletKeys.Key[i].Name;
-      jsonarr.GetAsObject(i).GetAsVariant('enc_pubkey').Value := TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(_RPCServer.WalletKeys.Key[i].AccountKey));
-      jsonarr.GetAsObject(i).GetAsVariant('can_use').Value := (_RPCServer.WalletKeys.Key[i].CryptedKey<>'');
+      if (i>=j) then begin
+        jso := jsonarr.GetAsObject(jsonarr.count);
+        jso.GetAsVariant('name').Value := _RPCServer.WalletKeys.Key[i].Name;
+        jso.GetAsVariant('can_use').Value := (_RPCServer.WalletKeys.Key[i].CryptedKey<>'');
+        FillPublicKeyObject(_RPCServer.WalletKeys.Key[i].AccountKey,jso);
+      end;
+      if (k>0) And ((i+1)>=(j+k)) then break;
     end;
     end;
     Result := true;
     Result := true;
+  end else if (method='getwalletpubkey') then begin
+    if Not (CapturePubKey('',opr.newKey,ErrorDesc)) then begin
+      ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
+      exit;
+    end;
+    i := _RPCServer.WalletKeys.AccountsKeyList.IndexOfAccountKey(opr.newKey);
+    if (i<0) then begin
+      ErrorNum := CT_RPC_ErrNum_NotFound;
+      ErrorDesc := 'Public key not found in wallet';
+      exit;
+    end;
+    FillPublicKeyObject(_RPCServer.WalletKeys.AccountsKeyList.AccountKey[i],GetResultObject);
+    Result := true;
   end else if (method='getblock') then begin
   end else if (method='getblock') then begin
     // Param "block" contains block number (0..getblockcount-1)
     // Param "block" contains block number (0..getblockcount-1)
     // Returns JSON object with block information
     // Returns JSON object with block information
@@ -911,14 +1114,19 @@ begin
           ErrorDesc := 'Cannot load Block: '+IntToStr(c);
           ErrorDesc := 'Cannot load Block: '+IntToStr(c);
           Exit;
           Exit;
         end;
         end;
-        GetResultArray;
-        for i := pcops.Count - 1 downto 0 do begin
-          If TPCOperation.OperationToOperationResume(c,pcops.Operation[i],pcops.Operation[i].SenderAccount,opr) then begin
-            opr.NOpInsideBlock:=i;
-            opr.time:=pcops.OperationBlock.timestamp;
-            opr.Balance := -1; // Don't include!
-            FillOperationResumeToJSONObject(opr,GetResultArray.GetAsObject(pcops.Count - 1 - i));
+        jsonarr := GetResultArray;
+        k := params.AsInteger('max',100);
+        j := params.AsInteger('start',0);
+        for i := 0 to pcops.Count - 1 do begin
+          if (i>=j) then begin
+            If TPCOperation.OperationToOperationResume(c,pcops.Operation[i],pcops.Operation[i].SenderAccount,opr) then begin
+              opr.NOpInsideBlock:=i;
+              opr.time:=pcops.OperationBlock.timestamp;
+              opr.Balance := -1; // Don't include!
+              FillOperationResumeToJSONObject(opr,jsonarr.GetAsObject(jsonarr.Count));
+            end;
           end;
           end;
+          if (k>0) And ((i+1)>=(j+k)) then break;
         end;
         end;
         Result := True;
         Result := True;
       finally
       finally
@@ -933,9 +1141,10 @@ begin
     // Returns all the operations affecting an account in "Operation resume format" as an array
     // Returns all the operations affecting an account in "Operation resume format" as an array
     // Param "account" contains account number
     // Param "account" contains account number
     // Param "deep" (optional) contains max blocks deep to search (Default: 100)
     // Param "deep" (optional) contains max blocks deep to search (Default: 100)
+    // Param "start" and "max" contains starting index and max operations respectively
     c := params.GetAsVariant('account').AsCardinal(CT_MaxAccount);
     c := params.GetAsVariant('account').AsCardinal(CT_MaxAccount);
     if ((c>=0) And (c<TNode.Node.Bank.AccountsCount)) then begin
     if ((c>=0) And (c<TNode.Node.Bank.AccountsCount)) then begin
-      Result := GetAccountOperations(c,GetResultArray,params.AsInteger('deep',100));
+      Result := GetAccountOperations(c,GetResultArray,params.AsInteger('deep',100),params.AsInteger('start',0),params.AsInteger('max',100));
     end else begin
     end else begin
       ErrorNum := CT_RPC_ErrNum_InvalidAccount;
       ErrorNum := CT_RPC_ErrNum_InvalidAccount;
       If (c=CT_MaxAccount) then ErrorDesc := 'Need account param'
       If (c=CT_MaxAccount) then ErrorDesc := 'Need account param'
@@ -1000,7 +1209,7 @@ begin
        TCrypto.HexaToRaw(params.AsString('payload','')),
        TCrypto.HexaToRaw(params.AsString('payload','')),
        params.AsString('payload_method','dest'),params.AsString('pwd',''));
        params.AsString('payload_method','dest'),params.AsString('pwd',''));
   end else if (method='changekey') then begin
   end else if (method='changekey') then begin
-    // Change key of "account" to "new_enc_pubkey" (encoded public key format) with "fee"
+    // Change key of "account" to "new_enc_pubkey" or "new_b58_pubkey" (encoded public key format) with "fee"
     // If "payload" is present, it will be encoded using "payload_method"
     // If "payload" is present, it will be encoded using "payload_method"
     // "payload_method" types: "none","dest"(default),"sender","aes"(must provide "pwd" param)
     // "payload_method" types: "none","dest"(default),"sender","aes"(must provide "pwd" param)
     // Returns a JSON "Operation Resume format" object when successfull
     // Returns a JSON "Operation Resume format" object when successfull
@@ -1010,8 +1219,42 @@ begin
       ErrorDesc := 'Wallet is password protected. Unlock first';
       ErrorDesc := 'Wallet is password protected. Unlock first';
       exit;
       exit;
     end;
     end;
+    if params.IndexOfName('account')<0 then begin
+      ErrorNum := CT_RPC_ErrNum_InvalidAccount;
+      ErrorDesc := 'Need "account" param';
+      exit;
+    end;
+    If Not CapturePubKey('new_',account.accountkey,ErrorDesc) then begin
+      ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
+      exit;
+    end;
     Result := ChangeAccountKey(params.AsCardinal('account',CT_MaxAccount),
     Result := ChangeAccountKey(params.AsCardinal('account',CT_MaxAccount),
-       TAccountComp.RawString2Accountkey(TCrypto.HexaToRaw(params.AsString('new_enc_pubkey',''))),
+       account.accountkey,
+       ToPascalCoins(params.AsDouble('fee',0)),
+       TCrypto.HexaToRaw(params.AsString('payload','')),
+       params.AsString('payload_method','dest'),params.AsString('pwd',''));
+  end else if (method='changekeys') then begin
+    // Allows a massive change key operation
+    // Change key of "accounts" to "new_enc_pubkey" or "new_b58_pubkey" (encoded public key format) with "fee"
+    // If "payload" is present, it will be encoded using "payload_method"
+    // "payload_method" types: "none","dest"(default),"sender","aes"(must provide "pwd" param)
+    // Returns a JSON object with result information
+    If Not _RPCServer.WalletKeys.IsValidPassword then begin
+      ErrorNum := CT_RPC_ErrNum_WalletPasswordProtected;
+      ErrorDesc := 'Wallet is password protected. Unlock first';
+      exit;
+    end;
+    if params.IndexOfName('accounts')<0 then begin
+      ErrorNum := CT_RPC_ErrNum_InvalidAccount;
+      ErrorDesc := 'Need "accounts" param';
+      exit;
+    end;
+    If Not CapturePubKey('new_',account.accountkey,ErrorDesc) then begin
+      ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
+      exit;
+    end;
+    Result := ChangeAccountsKey(params.AsString('accounts',''),
+       account.accountkey,
        ToPascalCoins(params.AsDouble('fee',0)),
        ToPascalCoins(params.AsDouble('fee',0)),
        TCrypto.HexaToRaw(params.AsString('payload','')),
        TCrypto.HexaToRaw(params.AsString('payload','')),
        params.AsString('payload_method','dest'),params.AsString('pwd',''));
        params.AsString('payload_method','dest'),params.AsString('pwd',''));
@@ -1084,18 +1327,16 @@ begin
     end;
     end;
   end else if (method='decodepubkey') then begin
   end else if (method='decodepubkey') then begin
     // Returns "ec_nid", "x" and "y" of an encoded public key (x and y in hexadecimal)
     // Returns "ec_nid", "x" and "y" of an encoded public key (x and y in hexadecimal)
-    // Param "enc_pubkey" is an hexadecimal encoded address (see 'encodepubkey')
-    if (params.AsString('enc_pubkey','')='') then begin
-      ErrorDesc:= 'Need param "enc_pubkey"';
-      ErrorNum:= CT_RPC_ErrNum_InvalidPubKey;
+    // Must provide:
+    // - Param "enc_pubkey" is an hexadecimal encoded public key (see 'encodepubkey')
+    // or
+    // - Param "b58_pubkey" is a Base58 encoded public key
+    If Not CapturePubKey('',account.accountkey,ErrorDesc) then begin
+      ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
       exit;
       exit;
     end;
     end;
-    account.accountkey := CT_Account_NUL.accountkey;
-    account.accountkey := TAccountComp.RawString2Accountkey(TCrypto.HexaToRaw(params.AsString('enc_pubkey','')));
     if (TAccountComp.IsValidAccountKey(account.accountkey,ansistr)) then begin
     if (TAccountComp.IsValidAccountKey(account.accountkey,ansistr)) then begin
-      GetResultObject.GetAsVariant('ec_nid').Value := account.accountkey.EC_OpenSSL_NID;
-      GetResultObject.GetAsVariant('x').Value := TCrypto.ToHexaString(account.accountkey.x);
-      GetResultObject.GetAsVariant('y').Value := TCrypto.ToHexaString(account.accountkey.y);
+      FillPublicKeyObject(account.accountkey,GetResultObject);
       Result := True;
       Result := True;
     end else begin
     end else begin
       ErrorDesc:= ansistr;
       ErrorDesc:= ansistr;
@@ -1103,7 +1344,7 @@ begin
     end;
     end;
   end else if (method='payloadencrypt') then begin
   end else if (method='payloadencrypt') then begin
     // Encrypts a "payload" using "payload_method"
     // Encrypts a "payload" using "payload_method"
-    // "payload_method" types: "none","pubkey"(must provide "enc_pubkey"),"aes"(must provide "pwd" param)
+    // "payload_method" types: "none","pubkey"(must provide "enc_pubkey" or "b58_pubkey"),"aes"(must provide "pwd" param)
     // If payload is "pubkey"
     // If payload is "pubkey"
     // Returns an hexa string with encrypted payload
     // Returns an hexa string with encrypted payload
     if (params.AsString('payload','')='') then begin
     if (params.AsString('payload','')='') then begin
@@ -1111,8 +1352,15 @@ begin
       ErrorDesc := 'Need param "payload"';
       ErrorDesc := 'Need param "payload"';
       exit;
       exit;
     end;
     end;
+    opr.newKey := CT_TWalletKey_NUL.AccountKey;
+    if (params.IndexOfName('enc_pubkey')>=0) Or (params.IndexOfName('b58_pubkey')>=0) then begin
+      if Not (CapturePubKey('',opr.newKey,ErrorDesc)) then begin
+        ErrorNum := CT_RPC_ErrNum_InvalidPubKey;
+        exit;
+      end;
+    end;
     Result := DoEncrypt(TCrypto.HexaToRaw(params.AsString('payload','')),
     Result := DoEncrypt(TCrypto.HexaToRaw(params.AsString('payload','')),
-       TAccountComp.RawString2Accountkey(TCrypto.HexaToRaw(params.AsString('enc_pubkey',''))),
+       opr.newKey,
        params.AsString('payload_method',''),params.AsString('pwd',''));
        params.AsString('payload_method',''),params.AsString('pwd',''));
   end else if (method='payloaddecrypt') then begin
   end else if (method='payloaddecrypt') then begin
     // Decrypts a "payload" searching for wallet private keys and for array of strings in "pwds" param
     // Decrypts a "payload" searching for wallet private keys and for array of strings in "pwds" param
@@ -1133,7 +1381,7 @@ begin
     GetConnections;
     GetConnections;
     Result := true;
     Result := true;
   end else if (method='addnewkey') then begin
   end else if (method='addnewkey') then begin
-    // Creates a new private key and stores it on the wallet, returning encoded value
+    // Creates a new private key and stores it on the wallet, returning Public key JSON object
     // Param "ec_nid" can be 714=secp256k1 715=secp384r1 729=secp283k1 716=secp521r1. (Default = CT_Default_EC_OpenSSL_NID)
     // Param "ec_nid" can be 714=secp256k1 715=secp384r1 729=secp283k1 716=secp521r1. (Default = CT_Default_EC_OpenSSL_NID)
     // Param "name" is name for this address
     // Param "name" is name for this address
     If Not _RPCServer.WalletKeys.IsValidPassword then begin
     If Not _RPCServer.WalletKeys.IsValidPassword then begin
@@ -1145,15 +1393,18 @@ begin
     try
     try
       ecpkey.GenerateRandomPrivateKey(params.AsInteger('ec_nid',CT_Default_EC_OpenSSL_NID));
       ecpkey.GenerateRandomPrivateKey(params.AsInteger('ec_nid',CT_Default_EC_OpenSSL_NID));
       _RPCServer.FWalletKeys.AddPrivateKey(params.AsString('name',DateTimeToStr(now)),ecpkey);
       _RPCServer.FWalletKeys.AddPrivateKey(params.AsString('name',DateTimeToStr(now)),ecpkey);
-      jsonresponse.GetAsVariant('result').Value:=TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(ecpkey.PublicKey));
+      FillPublicKeyObject(ecpkey.PublicKey,GetResultObject);
       Result := true;
       Result := true;
     finally
     finally
       ecpkey.Free;
       ecpkey.Free;
     end;
     end;
+  end else if (method='lock') then begin
+    jsonresponse.GetAsVariant('result').Value := _RPCServer.WalletKeys.LockWallet;
+    Result := true;
   end else if (method='unlock') then begin
   end else if (method='unlock') then begin
     // Unlocks the Wallet with "pwd" password
     // Unlocks the Wallet with "pwd" password
     // Returns Boolean if wallet is unlocked
     // Returns Boolean if wallet is unlocked
-    if (params.AsString('pwd','')='') then begin
+    if (params.IndexOfName('pwd')<0) then begin
       ErrorNum:= CT_RPC_ErrNum_InvalidData;
       ErrorNum:= CT_RPC_ErrNum_InvalidData;
       ErrorDesc := 'Need param "pwd"';
       ErrorDesc := 'Need param "pwd"';
       exit;
       exit;

+ 8 - 0
Units/PascalCoin/UThread.pas

@@ -62,6 +62,7 @@ Type
     procedure Clear;
     procedure Clear;
     procedure Remove(Item: Pointer); inline;
     procedure Remove(Item: Pointer); inline;
     function LockList: TList;
     function LockList: TList;
+    function TryLockList(MaxWaitMilliseconds : Cardinal; var lockedList : TList) : Boolean;
     procedure UnlockList; inline;
     procedure UnlockList; inline;
   end;
   end;
 
 
@@ -287,6 +288,13 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TPCThreadList.TryLockList(MaxWaitMilliseconds: Cardinal;
+  var lockedList: TList): Boolean;
+begin
+  lockedList := FList;
+  Result := TPCThread.TryProtectEnterCriticalSection(Self,MaxWaitMilliseconds,FLock);
+end;
+
 procedure TPCThreadList.UnlockList;
 procedure TPCThreadList.UnlockList;
 begin
 begin
   FLock.Release;
   FLock.Release;

+ 11 - 0
Units/PascalCoin/UWalletKeys.pas

@@ -63,6 +63,7 @@ Type
     Property WalletFileName : AnsiString read FWalletFileName write SetWalletFileName;
     Property WalletFileName : AnsiString read FWalletFileName write SetWalletFileName;
     Property OnChanged : TNotifyEvent read FOnChanged write FOnChanged;
     Property OnChanged : TNotifyEvent read FOnChanged write FOnChanged;
     Procedure SetName(index : Integer; Const newName : AnsiString);
     Procedure SetName(index : Integer; Const newName : AnsiString);
+    Function LockWallet : Boolean;
   End;
   End;
 
 
   TWalletKeysExt = Class(TWalletKeys)
   TWalletKeysExt = Class(TWalletKeys)
@@ -301,6 +302,15 @@ begin
   if Assigned(FOnChanged) then FOnChanged(Self);
   if Assigned(FOnChanged) then FOnChanged(Self);
 end;
 end;
 
 
+function TWalletKeys.LockWallet: Boolean;
+begin
+  // Return true when wallet has a password, locking it. False if there password is empty string
+  FWalletPassword := '';
+  GeneratePrivateKeysFromPassword;
+  Result := Not IsValidPassword;
+  if Assigned(FOnChanged) then FOnChanged(Self);
+end;
+
 procedure TWalletKeys.SaveToStream(Stream: TStream);
 procedure TWalletKeys.SaveToStream(Stream: TStream);
 var i : Integer;
 var i : Integer;
   P : PWalletKey;
   P : PWalletKey;
@@ -368,6 +378,7 @@ begin
   // Try if password is Ok
   // Try if password is Ok
   GeneratePrivateKeysFromPassword;
   GeneratePrivateKeysFromPassword;
   if FIsValidPassword then SaveToStream(FWalletFileStream);
   if FIsValidPassword then SaveToStream(FWalletFileStream);
+  if Assigned(FOnChanged) then FOnChanged(Self);
 end;
 end;
 
 
 { TWalletKeysExt }
 { TWalletKeysExt }

+ 9 - 5
Units/PascalCoin/upcdaemon.pas

@@ -191,9 +191,11 @@ constructor TPCDaemonMapper.Create(AOwner: TComponent);
 Var D : TDaemonDef;
 Var D : TDaemonDef;
 begin
 begin
   inherited Create(AOwner);
   inherited Create(AOwner);
-  FLog := TLog.Create(Nil);
-  FLog.SaveTypes:=CT_TLogTypes_ALL;
-  FLog.FileName:=TFolderHelper.GetPascalCoinDataFolder+PathDelim+'pascalcoin_'+FormatDateTime('yyyymmddhhnn',Now)+'.log';
+  if (Application.HasOption('l','log')) then begin
+    FLog := TLog.Create(Nil);
+    FLog.SaveTypes:=CT_TLogTypes_ALL;
+    FLog.FileName:=TFolderHelper.GetPascalCoinDataFolder+PathDelim+'pascalcoin_'+FormatDateTime('yyyymmddhhnn',Now)+'.log';
+  end;
   D:=DaemonDefs.Add as TDaemonDef;
   D:=DaemonDefs.Add as TDaemonDef;
   D.DisplayName:='Pascal Coin Daemon';
   D.DisplayName:='Pascal Coin Daemon';
   D.Name:='PascalCoinDaemon';
   D.Name:='PascalCoinDaemon';
@@ -203,8 +205,10 @@ end;
 
 
 destructor TPCDaemonMapper.Destroy;
 destructor TPCDaemonMapper.Destroy;
 begin
 begin
-  FLog.OnInThreadNewLog:=Nil;
-  FreeAndNil(FLog);
+  If Assigned(FLog) then begin
+    FLog.OnInThreadNewLog:=Nil;
+    FreeAndNil(FLog);
+  end;
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 

+ 0 - 2
Units/Utils/UFolderHelper.pas

@@ -91,8 +91,6 @@ var
   FolderPath: array[0 .. MAX_PATH] of Char;
   FolderPath: array[0 .. MAX_PATH] of Char;
 begin
 begin
   Result := '';
   Result := '';
-  //SetLastError(ERROR_SUCCESS);
-
   if SHGetFolderPath(0, aCSIDL, 0, 0, @FolderPath) = S_OK then
   if SHGetFolderPath(0, aCSIDL, 0, 0, @FolderPath) = S_OK then
     Result := FolderPath;
     Result := FolderPath;
 end;
 end;

+ 15 - 2
Units/Utils/UGridUtils.pas

@@ -82,6 +82,7 @@ Type
     FPendingOperations: Boolean;
     FPendingOperations: Boolean;
     FBlockStart: Int64;
     FBlockStart: Int64;
     FBlockEnd: Int64;
     FBlockEnd: Int64;
+    FMustShowAlwaysAnAccount: Boolean;
     Procedure OnNodeNewOperation(Sender : TObject);
     Procedure OnNodeNewOperation(Sender : TObject);
     Procedure OnNodeNewAccount(Sender : TObject);
     Procedure OnNodeNewAccount(Sender : TObject);
     Procedure InitGrid;
     Procedure InitGrid;
@@ -93,7 +94,8 @@ Type
     procedure SetPendingOperations(const Value: Boolean);
     procedure SetPendingOperations(const Value: Boolean);
 
 
     procedure SetBlockEnd(const Value: Int64);
     procedure SetBlockEnd(const Value: Int64);
-    procedure SetBlockStart(const Value: Int64);protected
+    procedure SetBlockStart(const Value: Int64);
+    procedure SetMustShowAlwaysAnAccount(const Value: Boolean);
   protected
   protected
     procedure Notification(AComponent: TComponent; Operation: TOperation); Override;
     procedure Notification(AComponent: TComponent; Operation: TOperation); Override;
   public
   public
@@ -102,6 +104,7 @@ Type
     Property DrawGrid : TDrawGrid read FDrawGrid write SetDrawGrid;
     Property DrawGrid : TDrawGrid read FDrawGrid write SetDrawGrid;
     Property PendingOperations : Boolean read FPendingOperations write SetPendingOperations;
     Property PendingOperations : Boolean read FPendingOperations write SetPendingOperations;
     Property AccountNumber : Int64 read FAccountNumber write SetAccountNumber;
     Property AccountNumber : Int64 read FAccountNumber write SetAccountNumber;
+    Property MustShowAlwaysAnAccount : Boolean read FMustShowAlwaysAnAccount write SetMustShowAlwaysAnAccount;
     Property Node : TNode read GetNode write SetNode;
     Property Node : TNode read GetNode write SetNode;
     Procedure UpdateAccountOperations; virtual;
     Procedure UpdateAccountOperations; virtual;
     Procedure ShowModalDecoder(WalletKeys: TWalletKeys; AppParams : TAppParams);
     Procedure ShowModalDecoder(WalletKeys: TWalletKeys; AppParams : TAppParams);
@@ -532,6 +535,7 @@ constructor TOperationsGrid.Create(AOwner: TComponent);
 begin
 begin
   FAccountNumber := 0;
   FAccountNumber := 0;
   FDrawGrid := Nil;
   FDrawGrid := Nil;
+  MustShowAlwaysAnAccount := false;
   FOperationsResume := TOperationsResumeList.Create;
   FOperationsResume := TOperationsResumeList.Create;
   FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
   FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
   FNodeNotifyEvents.OnBlocksChanged := OnNodeNewAccount;
   FNodeNotifyEvents.OnBlocksChanged := OnNodeNewAccount;
@@ -745,6 +749,13 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TOperationsGrid.SetMustShowAlwaysAnAccount(const Value: Boolean);
+begin
+  if FMustShowAlwaysAnAccount=Value then exit;
+  FMustShowAlwaysAnAccount := Value;
+  UpdateAccountOperations;
+end;
+
 procedure TOperationsGrid.SetNode(const Value: TNode);
 procedure TOperationsGrid.SetNode(const Value: TNode);
 begin
 begin
   if GetNode=Value then exit;
   if GetNode=Value then exit;
@@ -787,6 +798,8 @@ begin
   FOperationsResume.Clear;
   FOperationsResume.Clear;
   Try
   Try
     if Not Assigned(Node) then exit;
     if Not Assigned(Node) then exit;
+    if (MustShowAlwaysAnAccount) And (AccountNumber<0) then exit;
+
     if FPendingOperations then begin
     if FPendingOperations then begin
       for i := Node.Operations.Count - 1 downto 0 do begin
       for i := Node.Operations.Count - 1 downto 0 do begin
         Op := Node.Operations.OperationsHashTree.GetOperation(i);
         Op := Node.Operations.OperationsHashTree.GetOperation(i);
@@ -858,7 +871,7 @@ begin
         Finally
         Finally
           list.Free;
           list.Free;
         End;
         End;
-        Node.GetStoredOperationsFromAccount(FOperationsResume,AccountNumber,100);
+        Node.GetStoredOperationsFromAccount(FOperationsResume,AccountNumber,100,5000);
       end;
       end;
     end;
     end;
   Finally
   Finally