PascalCoin 8 lat temu
rodzic
commit
b7a72b6a49

+ 2 - 2
PascalCoinMiner.lpi

@@ -29,7 +29,7 @@
     <RunParams>
       <local>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="-p 0 -d 1 -s -n a"/>
+        <CommandLineParams Value="-c 1 -s -n TEST"/>
       </local>
     </RunParams>
     <Units Count="1">
@@ -52,7 +52,7 @@
     </SearchPaths>
     <CodeGeneration>
       <Optimizations>
-        <OptimizationLevel Value="2"/>
+        <OptimizationLevel Value="3"/>
       </Optimizations>
     </CodeGeneration>
     <Linking>

+ 43 - 28
PascalCoinMiner.pp

@@ -55,7 +55,7 @@ type
   end;
 
 Const
-  CT_MINER_VERSION = '0.2';
+  CT_MINER_VERSION = 'BETA 0.3 FOR SUPRNOVA TESTING ONLY';
   CT_Line_DeviceStatus = 3;
   CT_Line_ConnectionStatus = 4;
   CT_Line_MinerValues = 7;
@@ -100,9 +100,12 @@ end;
 procedure TPascalMinerApp.OnConnectionStateChanged(Sender: TObject);
 Const CT_state : Array[boolean] of String = ('Disconnected','Connected');
 var i : Integer;
+  s : String;
 begin
+  If FPoolMinerThread.PoolMinerClient.PoolType=ptNone then s:='SOLO MINING'
+  else s:='POOL MINING USER "'+FPoolMinerThread.PoolMinerClient.UserName+'"';
   If FPoolMinerThread.PoolMinerClient.Connected then begin
-    WriteLine(CT_Line_ConnectionStatus,'Connected to '+FPoolMinerThread.PoolMinerClient.ClientRemoteAddr);
+    WriteLine(CT_Line_ConnectionStatus,s + ' server: '+FPoolMinerThread.PoolMinerClient.ClientRemoteAddr);
     For i:=0 to FDeviceThreads.Count-1 do begin
       TCustomMinerDeviceThread(FDeviceThreads[i]).Paused:=false;
     end;
@@ -110,7 +113,7 @@ begin
     For i:=0 to FDeviceThreads.Count-1 do begin
       TCustomMinerDeviceThread(FDeviceThreads[i]).Paused:=true;
     end;
-    WriteLine(CT_Line_ConnectionStatus,'** NO CONNECTED... Connecting to '+FPoolMinerThread.PoolMinerClient.ClientRemoteAddr);
+    WriteLine(CT_Line_ConnectionStatus,'** NOT CONNECTED '+s + ' Connecting to '+FPoolMinerThread.PoolMinerClient.ClientRemoteAddr);
   end;
 end;
 
@@ -201,7 +204,7 @@ var
     devt : TCustomMinerDeviceThread;
   begin
     Result := false;
-    if (Not HasOption('p','platform')) And (Not HasOption('d','device')) And (Not HasOption('c','cpu:')) then begin
+    if (Not HasOption('p','platform')) And (Not HasOption('d','device')) And (Not HasOption('c','cpu')) then begin
       Writeln('Need to specify -p X and -d Y for GPU mining or -c N for CPU mining. See -h for more info');
       ShowGPUDrivers;
       Terminate;
@@ -302,21 +305,6 @@ var
               WriteLine(CT_Line_MiningStatus+i,s);
             end;
           end;
-          {
-          gs := FPoolMinerThread.GlobalMinerStats;
-          if ms.WorkingMillisecondsHashing>0 then hrHashing := (((ms.RoundsCount DIV Int64(ms.WorkingMillisecondsHashing)))/(1000))
-          else hrHashing := 0;
-          if ms.WorkingMillisecondsTotal>0 then hrReal := (((ms.RoundsCount DIV Int64(ms.WorkingMillisecondsTotal)))/(1000))
-          else hrReal := 0;
-          if gs.WorkingMillisecondsHashing>0 then glhrHashing := (((gs.RoundsCount DIV Int64(gs.WorkingMillisecondsHashing)))/(1000))
-          else glhrHashing := 0;
-          if gs.WorkingMillisecondsTotal>0 then glhrReal := (((gs.RoundsCount DIV Int64(gs.WorkingMillisecondsTotal)))/(1000))
-          else glhrReal := 0;
-          If gs.RoundsCount>0 then begin
-            WriteLog(Format('Mining at %0.2f MHash/s %0.2f %0.2f %0.2f - Total Rounds: %0.2f G ',[hrHashing,glhrHashing, hrReal, glhrReal, gs.RoundsCount/1073741824]));
-          end else begin
-            WriteLog('Not mining... check connection or paused state...');
-          end; }
           WriteLine(CT_Line_LastFound+FDeviceThreads.Count-1,'MY VALID BLOCKS FOUND: '+IntToStr(gs.WinsCount) +' Working time: '+IntToStr(Trunc(now - FAppStartTime))+'d '+FormatDateTime('hh:nn:ss',Now-FAppStartTime) );
         end;
         If KeyPressed then begin
@@ -329,7 +317,7 @@ var
     until Terminated;
   end;
 
-  Procedure DoVisualprocess(minerName : String);
+  Procedure DoVisualprocess(minerName, UserName, Password : String);
   Var sc : tcrtcoord;
     Flog : TLog;
     devt : TCustomMinerDeviceThread;
@@ -337,6 +325,11 @@ var
   Begin
     FPoolMinerThread := TPoolMinerThread.Create(nsarr[0].ip,nsarr[0].port,FPrivateKey.PublicKey);
     try
+      If (UserName<>'') then begin
+        FPoolMinerThread.PoolMinerClient.PoolType:=ptIdentify;
+        FPoolMinerThread.PoolMinerClient.UserName:=UserName;
+        FPoolMinerThread.PoolMinerClient.Password:=Password;
+      end;
       If Not AddMiners then exit;
       if HasOption('t','testmode') then begin
         i := StrToIntDef(GetOptionValue('t','testmode'),-1);
@@ -348,6 +341,7 @@ var
           exit;
         end;
       end;
+      //
       cursoroff;
       try
         clrscr;
@@ -389,12 +383,13 @@ var
     end;
   end;
 
+Var username,password : String;
 begin
   FLastLogs := TStringList.Create;
   FLock := TCriticalSection.Create;
   Try
     // quick check parameters
-    ErrorMsg:=CheckOptions('hp:d:s::c:n::t:', 'help platform device server cpu minername testmode');
+    ErrorMsg:=CheckOptions('hp:d:s::c:n::t:u::x::', 'help platform device server cpu minername testmode user pwd');
     if ErrorMsg<>'' then begin
       //ShowException(Exception.Create(ErrorMsg));
       WriteLn(ErrorMsg);
@@ -456,10 +451,25 @@ begin
         Exit;
       end;
     end;
+    username:='';
+    password:='';
+    If (HasOption('u','user')) Or (HasOption('x','pwd')) then begin
+      username:=trim(GetOptionValue('u','user'));
+      password:=trim(GetOptionValue('x','pwd'));
+      if (username='') then begin
+        WriteLn('Input Pool username (or empty for non pool connection):');
+        Readln(username);
+      end;
+      if (password='') And (username<>'') then begin
+        WriteLn('Input Pool password for user ',username,':');
+        Readln(password);
+      end;
+    end;
+
     FPrivateKey := TECPrivateKey.Create;
     Try
       FPrivateKey.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
-      DoVisualprocess(s);
+      DoVisualprocess(s,username,password);
     finally
       FreeAndNil(FPrivateKey);
     end;
@@ -472,11 +482,15 @@ begin
 end;
 
 constructor TPascalMinerApp.Create(TheOwner: TComponent);
+Var FLog : TLog;
 begin
   inherited Create(TheOwner);
   FDeviceThreads := TList.Create;
   StopOnException:=True;
   FAppStartTime := Now;
+  FLog := TLog.Create(self);
+  FLog.SaveTypes:=CT_TLogTypes_DEFAULT;
+  FLog.FileName:=ExtractFileDir(ExeName)+PathDelim+'PascalCoinMiner.log';
 end;
 
 destructor TPascalMinerApp.Destroy;
@@ -497,13 +511,14 @@ begin
   writeln('    Y can be multiple devices. Example -d 0,2,3  Will use devices 0, 2 and 3');
   writeln('  -c N  (For CPU mining, where N is CPU''s to use. Activating this disable GPU mining)');
   writeln('  -n MYNAME  (Will add MYNAME value to miner name assigned by server)');
+  writeln('  ** POOL IDENTIFICATION PROTOCOL **');
+  writeln('  (Not needed for PascalCoin core, only some third party pools)');
+  writeln('  -u USERNAME');
+  writeln('  -x PASSWORD');
   writeln('');
-  writeln('Basic example CPU mining: ');
-  writeln('  ',ExtractFileName(ExeName),' -s 192.168.1.77:4009 -c 2 -n USER_1');
-  writeln('  (2 CPU''s to server 192.168.1.77 port 4009 and miner name USER_1)');
-  writeln('Basic example GPU mining: ');
-  writeln('  ',ExtractFileName(ExeName),' -p 0 -d 0 -s -n ABC');
-  writeln('  (p 0 d 0 at server localhost:',CT_JSONRPCMinerServer_Port,' miner name ABC)');
+  writeln('Basic example GPU mining over multiple devices: ');
+  writeln('  ',ExtractFileName(ExeName),' -p 0 -d 0,1,2,3 -s -n ABC');
+  writeln('  (Devices 0,1,2,3 at server localhost:',CT_JSONRPCMinerServer_Port,' miner name ABC)');
   writeln('');
   ShowGPUDrivers;
 end;

BIN
PascalCoinWallet.res


+ 5 - 0
README.md

@@ -34,6 +34,11 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 ## History:  
 
+### Build 1.4.3.0 - 2017-02-02
+
+- Adding "maturation" param to "JSON Operation object", return null when operation is not included on a blockchain yet, 0 means that is included in highest block and so on...
+- Fixing miner timestamp value to prevent invalid time
+
 ### Build 1.4.2.0 - 2017-01-23
 
 - Max JSON-RPC miner connections is now 1000 (before, 10)

+ 5 - 0
README.txt

@@ -34,6 +34,11 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 ## History:  
 
+### Build 1.4.3.0 - 2017-02-02
+
+- Adding "maturation" param to "JSON Operation object", return null when operation is not included on a blockchain yet, 0 means that is included in highest block and so on...
+- Fixing miner timestamp value to prevent invalid time
+
 ### Build 1.4.2.0 - 2017-01-23
 
 - Max JSON-RPC miner connections is now 1000 (before, 10)

+ 1 - 37
Units/Forms/UFRMWallet.dfm

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

+ 96 - 93
Units/Forms/UFRMWallet.lfm

@@ -4,7 +4,7 @@ object FRMWallet: TFRMWallet
   Top = 201
   Width = 865
   Caption = 'Pascal Coin Wallet, JSON-RPC Miner & Explorer'
-  ClientHeight = 600
+  ClientHeight = 580
   ClientWidth = 865
   Color = clBtnFace
   Constraints.MinHeight = 600
@@ -162,7 +162,7 @@ object FRMWallet: TFRMWallet
       Left = 90
       Height = 13
       Top = 11
-      Width = 70
+      Width = 60
       Caption = 'Total Blocks:'
       ParentColor = False
     end
@@ -170,7 +170,7 @@ object FRMWallet: TFRMWallet
       Left = 166
       Height = 13
       Top = 11
-      Width = 21
+      Width = 18
       Caption = '000'
       ParentColor = False
     end
@@ -178,7 +178,7 @@ object FRMWallet: TFRMWallet
       Left = 90
       Height = 13
       Top = 26
-      Width = 106
+      Width = 89
       Caption = 'Current Block age:'
       ParentColor = False
     end
@@ -186,7 +186,7 @@ object FRMWallet: TFRMWallet
       Left = 198
       Height = 13
       Top = 26
-      Width = 96
+      Width = 81
       Caption = '000 seconds ago'
       ParentColor = False
     end
@@ -194,7 +194,7 @@ object FRMWallet: TFRMWallet
       Left = 90
       Height = 13
       Top = 41
-      Width = 115
+      Width = 98
       Caption = 'Pending Operations:'
       ParentColor = False
     end
@@ -202,7 +202,7 @@ object FRMWallet: TFRMWallet
       Left = 207
       Height = 13
       Top = 41
-      Width = 21
+      Width = 18
       Caption = '000'
       ParentColor = False
     end
@@ -210,7 +210,7 @@ object FRMWallet: TFRMWallet
       Left = 90
       Height = 13
       Top = 56
-      Width = 81
+      Width = 68
       Caption = 'Miners clients:'
       ParentColor = False
     end
@@ -218,7 +218,7 @@ object FRMWallet: TFRMWallet
       Left = 177
       Height = 13
       Top = 56
-      Width = 21
+      Width = 18
       Caption = '000'
       ParentColor = False
     end
@@ -226,7 +226,7 @@ object FRMWallet: TFRMWallet
       Left = 429
       Height = 13
       Top = 11
-      Width = 86
+      Width = 76
       Caption = 'Current Target:'
       ParentColor = False
     end
@@ -234,7 +234,7 @@ object FRMWallet: TFRMWallet
       Left = 518
       Height = 13
       Top = 11
-      Width = 21
+      Width = 18
       Caption = '000'
       ParentColor = False
     end
@@ -242,7 +242,7 @@ object FRMWallet: TFRMWallet
       Left = 370
       Height = 13
       Top = 26
-      Width = 21
+      Width = 18
       Caption = '000'
       ParentColor = False
     end
@@ -250,7 +250,7 @@ object FRMWallet: TFRMWallet
       Left = 285
       Height = 13
       Top = 26
-      Width = 83
+      Width = 69
       Caption = 'Time average:'
       ParentColor = False
     end
@@ -258,7 +258,7 @@ object FRMWallet: TFRMWallet
       Left = 90
       Height = 13
       Top = 70
-      Width = 72
+      Width = 63
       Caption = 'Node Status:'
       ParentColor = False
     end
@@ -266,7 +266,7 @@ object FRMWallet: TFRMWallet
       Left = 168
       Height = 13
       Top = 70
-      Width = 18
+      Width = 15
       Caption = '???'
       ParentColor = False
     end
@@ -274,7 +274,7 @@ object FRMWallet: TFRMWallet
       Left = 285
       Height = 13
       Top = 11
-      Width = 55
+      Width = 48
       Caption = 'Accounts:'
       ParentColor = False
     end
@@ -282,7 +282,7 @@ object FRMWallet: TFRMWallet
       Left = 344
       Height = 13
       Top = 11
-      Width = 21
+      Width = 18
       Caption = '000'
       ParentColor = False
     end
@@ -290,7 +290,7 @@ object FRMWallet: TFRMWallet
       Left = 370
       Height = 13
       Top = 41
-      Width = 21
+      Width = 18
       Caption = '000'
       Font.Color = clGray
       Font.Height = -11
@@ -302,7 +302,7 @@ object FRMWallet: TFRMWallet
       Left = 360
       Height = 13
       Top = 56
-      Width = 86
+      Width = 74
       Caption = 'Blocks found:'
       Font.Color = clWindowText
       Font.Height = -11
@@ -316,7 +316,7 @@ object FRMWallet: TFRMWallet
       Height = 13
       Hint = 'Blocks found while Miner is running...'
       Top = 56
-      Width = 24
+      Width = 21
       Caption = '000'
       Font.Color = clWindowText
       Font.Height = -11
@@ -330,9 +330,9 @@ object FRMWallet: TFRMWallet
     object lblReceivedMessages: TLabel
       Cursor = crHandPoint
       Left = 360
-      Height = 22
+      Height = 23
       Top = 66
-      Width = 211
+      Width = 185
       Caption = 'Received messages'
       Font.Color = clRed
       Font.Height = -19
@@ -344,9 +344,9 @@ object FRMWallet: TFRMWallet
     end
     object lblBuild: TLabel
       Left = 586
-      Height = 22
+      Height = 23
       Top = 3
-      Width = 56
+      Width = 49
       Caption = 'Build'
       Font.Color = clWindowText
       Font.Height = -19
@@ -358,8 +358,8 @@ object FRMWallet: TFRMWallet
   end
   object StatusBar: TStatusBar
     Left = 0
-    Height = 21
-    Top = 579
+    Height = 23
+    Top = 557
     Width = 865
     Panels = <    
       item
@@ -379,21 +379,21 @@ object FRMWallet: TFRMWallet
   end
   object PageControl: TPageControl
     Left = 0
-    Height = 488
+    Height = 466
     Top = 91
     Width = 865
-    ActivePage = tsMyAccounts
+    ActivePage = tsLogs
     Align = alClient
-    TabIndex = 0
+    TabIndex = 4
     TabOrder = 2
     OnChange = PageControlChange
     object tsMyAccounts: TTabSheet
       Caption = 'Accounts Explorer'
-      ClientHeight = 461
-      ClientWidth = 861
+      ClientHeight = 440
+      ClientWidth = 857
       object Splitter1: TSplitter
         Left = 380
-        Height = 395
+        Height = 374
         Top = 66
         Width = 5
       end
@@ -401,41 +401,41 @@ object FRMWallet: TFRMWallet
         Left = 0
         Height = 66
         Top = 0
-        Width = 861
+        Width = 857
         Align = alTop
         ClientHeight = 66
-        ClientWidth = 861
+        ClientWidth = 857
         TabOrder = 0
         object Label18: TLabel
           Left = 11
           Height = 13
           Top = 35
-          Width = 70
+          Width = 61
           Caption = 'Find account'
           ParentColor = False
         end
         object cbMyPrivateKeys: TComboBox
           Left = 260
-          Height = 31
+          Height = 21
           Top = 7
           Width = 411
-          ItemHeight = 0
+          ItemHeight = 13
           OnChange = cbMyPrivateKeysChange
           Style = csDropDownList
           TabOrder = 0
         end
         object cbExploreMyAccounts: TCheckBox
           Left = 11
-          Height = 24
+          Height = 19
           Top = 10
-          Width = 329
+          Width = 235
           Caption = 'Explore accounts with one of my Wallet Keys'
           OnClick = cbExploreMyAccountsClick
           TabOrder = 1
         end
         object ebFindAccountNumber: TEdit
           Left = 87
-          Height = 23
+          Height = 21
           Top = 33
           Width = 83
           OnChange = ebFindAccountNumberChange
@@ -453,16 +453,16 @@ object FRMWallet: TFRMWallet
         end
         object cbFilterAccounts: TCheckBox
           Left = 260
-          Height = 24
+          Height = 19
           Top = 35
-          Width = 202
+          Width = 145
           Caption = 'Filter accounts by balance'
           OnClick = cbFilterAccountsClick
           TabOrder = 4
         end
         object ebFilterAccountByBalanceMin: TEdit
           Left = 412
-          Height = 23
+          Height = 21
           Hint = 'Min balance'
           Top = 33
           Width = 83
@@ -472,7 +472,7 @@ object FRMWallet: TFRMWallet
         end
         object ebFilterAccountByBalanceMax: TEdit
           Left = 503
-          Height = 23
+          Height = 21
           Hint = 'Max balance'
           Top = 33
           Width = 83
@@ -483,17 +483,17 @@ object FRMWallet: TFRMWallet
       end
       object pnlAccounts: TPanel
         Left = 0
-        Height = 395
+        Height = 374
         Top = 66
         Width = 380
         Align = alLeft
         BevelOuter = bvNone
-        ClientHeight = 395
+        ClientHeight = 374
         ClientWidth = 380
         TabOrder = 1
         object dgAccounts: TDrawGrid
           Left = 0
-          Height = 361
+          Height = 340
           Top = 0
           Width = 380
           Align = alLeft
@@ -507,7 +507,7 @@ object FRMWallet: TFRMWallet
         object pnlAccountsInfo: TPanel
           Left = 0
           Height = 34
-          Top = 361
+          Top = 340
           Width = 380
           Align = alBottom
           BevelOuter = bvNone
@@ -518,7 +518,7 @@ object FRMWallet: TFRMWallet
             Left = 5
             Height = 13
             Top = 10
-            Width = 55
+            Width = 48
             Caption = 'Accounts:'
             ParentColor = False
           end
@@ -526,7 +526,7 @@ object FRMWallet: TFRMWallet
             Left = 136
             Height = 13
             Top = 10
-            Width = 49
+            Width = 41
             Caption = 'Balance:'
             ParentColor = False
           end
@@ -534,7 +534,7 @@ object FRMWallet: TFRMWallet
             Left = 60
             Height = 13
             Top = 10
-            Width = 21
+            Width = 18
             Caption = '000'
             ParentColor = False
           end
@@ -542,7 +542,7 @@ object FRMWallet: TFRMWallet
             Left = 200
             Height = 13
             Top = 10
-            Width = 21
+            Width = 18
             Caption = '000'
             ParentColor = False
           end
@@ -588,22 +588,22 @@ object FRMWallet: TFRMWallet
       end
       object pcAccountsOptions: TPageControl
         Left = 385
-        Height = 395
+        Height = 374
         Top = 66
-        Width = 476
+        Width = 472
         ActivePage = tsAccountOperations
         Align = alClient
         TabIndex = 0
         TabOrder = 2
         object tsAccountOperations: TTabSheet
           Caption = 'Operations of selected Account'
-          ClientHeight = 368
-          ClientWidth = 472
+          ClientHeight = 348
+          ClientWidth = 464
           object dgAccountOperations: TDrawGrid
             Left = 0
-            Height = 368
+            Height = 348
             Top = 0
-            Width = 472
+            Width = 464
             Align = alClient
             ExtendedSelect = False
             TabOrder = 0
@@ -859,17 +859,17 @@ object FRMWallet: TFRMWallet
     end
     object tsBlockChain: TTabSheet
       Caption = 'BlockChain Explorer'
-      ClientHeight = 461
-      ClientWidth = 861
+      ClientHeight = 440
+      ClientWidth = 857
       ImageIndex = 1
       object Panel2: TPanel
         Left = 0
         Height = 41
         Top = 0
-        Width = 841
+        Width = 857
         Align = alTop
         ClientHeight = 41
-        ClientWidth = 841
+        ClientWidth = 857
         TabOrder = 0
         object Label9: TLabel
           Left = 11
@@ -900,9 +900,9 @@ object FRMWallet: TFRMWallet
       end
       object dgBlockChainExplorer: TDrawGrid
         Left = 0
-        Height = 363
+        Height = 399
         Top = 41
-        Width = 841
+        Width = 857
         Align = alClient
         ExtendedSelect = False
         TabOrder = 1
@@ -913,17 +913,17 @@ object FRMWallet: TFRMWallet
     end
     object tsOperations: TTabSheet
       Caption = 'Operations Explorer'
-      ClientHeight = 461
-      ClientWidth = 861
+      ClientHeight = 440
+      ClientWidth = 857
       ImageIndex = 1
       object Panel1: TPanel
         Left = 0
         Height = 41
         Top = 0
-        Width = 841
+        Width = 857
         Align = alTop
         ClientHeight = 41
-        ClientWidth = 841
+        ClientWidth = 857
         TabOrder = 0
         object Label2: TLabel
           Left = 11
@@ -954,9 +954,9 @@ object FRMWallet: TFRMWallet
       end
       object dgOperationsExplorer: TDrawGrid
         Left = 0
-        Height = 363
+        Height = 399
         Top = 41
-        Width = 841
+        Width = 857
         Align = alClient
         ExtendedSelect = False
         TabOrder = 1
@@ -967,55 +967,56 @@ object FRMWallet: TFRMWallet
     end
     object tsLogs: TTabSheet
       Caption = 'Logs'
-      ClientHeight = 461
-      ClientWidth = 861
+      ClientHeight = 440
+      ClientWidth = 857
       ImageIndex = 2
       object pnlTopLogs: TPanel
         Left = 0
         Height = 41
         Top = 0
-        Width = 841
+        Width = 857
         Align = alTop
         ClientHeight = 41
-        ClientWidth = 841
+        ClientWidth = 857
         TabOrder = 0
         object cbShowDebugLogs: TCheckBox
           Left = 15
-          Height = 17
+          Height = 19
           Top = 10
-          Width = 97
+          Width = 102
           Caption = 'Show Debug logs'
           TabOrder = 0
         end
       end
       object memoLogs: TMemo
         Left = 0
-        Height = 363
+        Height = 399
         Top = 41
-        Width = 841
+        Width = 857
         Align = alClient
         ScrollBars = ssBoth
         TabOrder = 1
+        WordWrap = False
       end
     end
     object tsNodeStats: TTabSheet
       Caption = 'Node Stats'
-      ClientHeight = 461
-      ClientWidth = 861
+      ClientHeight = 440
+      ClientWidth = 857
       ImageIndex = 3
       object Label3: TLabel
         Left = 15
         Height = 13
         Top = 15
-        Width = 207
+        Width = 177
         Caption = 'Active Net Connections of this Node:'
         ParentColor = False
       end
       object Label6: TLabel
         Left = 15
         Height = 13
-        Top = 312
-        Width = 202
+        Top = 291
+        Width = 198
         Anchors = [akLeft, akRight, akBottom]
         Caption = 'Available or possible Node Servers:'
         ParentColor = False
@@ -1023,41 +1024,44 @@ object FRMWallet: TFRMWallet
       object Label7: TLabel
         Left = 15
         Height = 13
-        Top = 208
-        Width = 103
+        Top = 187
+        Width = 99
         Anchors = [akLeft, akRight, akBottom]
         Caption = 'BlackList of Nodes'
         ParentColor = False
       end
       object memoNetConnections: TMemo
         Left = 15
-        Height = 166
+        Height = 145
         Top = 34
-        Width = 834
+        Width = 830
         Anchors = [akTop, akLeft, akRight, akBottom]
         ReadOnly = True
         ScrollBars = ssVertical
         TabOrder = 0
+        WordWrap = False
       end
       object memoNetServers: TMemo
         Left = 15
         Height = 116
-        Top = 331
-        Width = 834
+        Top = 310
+        Width = 830
         Anchors = [akLeft, akRight, akBottom]
         ReadOnly = True
         ScrollBars = ssVertical
         TabOrder = 1
+        WordWrap = False
       end
       object memoNetBlackLists: TMemo
-        Left = 15
+        Left = 16
         Height = 79
-        Top = 227
-        Width = 833
+        Top = 206
+        Width = 829
         Anchors = [akLeft, akRight, akBottom]
         ReadOnly = True
         ScrollBars = ssVertical
         TabOrder = 2
+        WordWrap = False
       end
     end
     object tsMessages: TTabSheet
@@ -1110,7 +1114,6 @@ object FRMWallet: TFRMWallet
         MultiSelect = True
         ScrollWidth = 273
         TabOrder = 0
-        TopIndex = -1
       end
       object bbSendAMessage: TButton
         Left = 315

+ 3 - 0
Units/Forms/UFRMWallet.pas

@@ -361,6 +361,7 @@ begin
     TNetData.NetData.OnNodeServersUpdated := OnNetNodeServersUpdated;
     TNetData.NetData.OnBlackListUpdated := OnNetBlackListUpdated;
     //
+    TimerUpdateStatus.Interval := 5000;
     TimerUpdateStatus.Enabled := true;
     UpdateConfigChanged;
   Except
@@ -384,6 +385,7 @@ begin
   {$IFnDEF FPC}
   Hide();
   WindowState := wsMinimized;
+  TimerUpdateStatus.Enabled := false;
   { Show the animated tray icon and also a hint balloon. }
   TrayIcon.Visible := True;
   TrayIcon.ShowBalloonHint;
@@ -1500,6 +1502,7 @@ end;
 procedure TFRMWallet.TrayIconDblClick(Sender: TObject);
 begin
   TrayIcon.Visible := False;
+  TimerUpdateStatus.Enabled := true;
   Show();
   WindowState := wsNormal;
   Application.BringToFront();

+ 3 - 3
Units/PascalCoin/UConst.pas

@@ -62,7 +62,7 @@ Const
   CT_MaxTransactionFee = 100000000;
   CT_MaxWalletAmount = 10000000000000;
   //
-  CT_MinCompactTarget: Cardinal = {$IFDEF PRODUCTION}$19000000{$ELSE}{$IFDEF TESTNET}$17000000{$ELSE}{$ENDIF}{$ENDIF}; // First compact target of block 0
+  CT_MinCompactTarget: Cardinal = {$IFDEF PRODUCTION}$19000000{$ELSE}{$IFDEF TESTNET}$19000000{$ELSE}{$ENDIF}{$ENDIF}; // First compact target of block 0
 
   CT_CalcNewTargetBlocksAverage: Cardinal = 100;
   CT_MaxAccount : Cardinal = $FFFFFFFF;
@@ -74,7 +74,7 @@ Const
   CT_MinServersConnected = 3;
   CT_MaxServersConnected = 5;
 
-  CT_MaxClientsConnected = 100;
+  CT_MaxClientsConnected = 500;
 
   CT_BankToDiskEveryNBlocks = 500; // Build 1.3.0 Changed from 1000 to 500
 
@@ -100,7 +100,7 @@ Const
   CT_Op_Changekey = $02;
   CT_Op_Recover = $03;
 
-  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.4.2'{$ELSE}{$IFDEF TESTNET}'TESTNET'{$ELSE}{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.4.3'{$ELSE}{$IFDEF TESTNET}'TESTNET'{$ELSE}{$ENDIF}{$ENDIF};
 
   CT_Discover_IPs =  'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us';
 

+ 9 - 4
Units/PascalCoin/UPoolMinerThreads.pas

@@ -219,6 +219,11 @@ begin
   FPoolMinerClient.OnMinerMustChangeValues := OnPoolMinerMustChangeValues;
   FPoolMinerClient.OnConnect := OnPoolMinerClientConnectionChanged;
   FPoolMinerClient.OnDisconnect := OnPoolMinerClientConnectionChanged;
+{ XXXXXXXXXXXXXXXXX
+  FPoolMinerClient.PoolType:=ptSuprnova;
+  FPoolMinerClient.UserName:='suprnova.1';
+  FPoolMinerClient.Password:='password';
+}
   FOnConnectionStateChanged := Nil;
   FDevicesList := TPCThreadList.Create;
   FMinerThreads := 0;
@@ -330,7 +335,7 @@ begin
   try
     mvfw := sender.FMinerValuesForWork;
     TLog.NewLog(ltinfo,ClassName,'FOUND VALID NONCE!!! Timestamp:'+Inttostr(Timestamp)+ ' Nonce:'+Inttostr(NOnce));
-    FPoolMinerClient.SubmitBlockFound(mvfw.payload_start,Timestamp,NOnce);
+    FPoolMinerClient.SubmitBlockFound(mvfw,mvfw.payload_start,Timestamp,NOnce);
   finally
     FDevicesList.UnlockList;
   end;
@@ -362,8 +367,8 @@ Var l : TList;
   auxXXXXX : TMinerValuesForWork;
 begin
   FGlobalMinerValuesForWork := FPoolMinerClient.MinerValuesForWork;
-  TLog.NewLog(ltupdate,ClassName,Format('New miner values. Block %d Payload %s',[FPoolMinerClient.MinerValuesForWork.block,
-    FPoolMinerClient.MinerValuesForWork.payload_start]));
+  TLog.NewLog(ltupdate,ClassName,Format('New miner values. Block %d Target %s Payload %s',[FPoolMinerClient.MinerValuesForWork.block,
+    IntToHex(FPoolMinerClient.MinerValuesForWork.target,8), FPoolMinerClient.MinerValuesForWork.payload_start]));
   l := FDevicesList.LockList;
   Try
     for i := 0 to l.Count - 1 do begin
@@ -506,7 +511,7 @@ begin
     canWork := CanBeModifiedOnLastChunk(i,aux);
     If Not canWork then FMinerValuesForWork.payload_start:=FMinerValuesForWork.payload_start+' ';
   until (canWork);
-  TLog.NewLog(ltinfo,classname,Format('Updated MinerValuesForWork: Payload:%s',[FMinerValuesForWork.payload_start]));
+  TLog.NewLog(ltinfo,classname,Format('Updated MinerValuesForWork: Target:%s Payload:%s',[IntToHex(FMinerValuesForWork.target,8),FMinerValuesForWork.payload_start]));
   If Assigned(FOnMinerValuesChanged) then FOnMinerValuesChanged(Self);
 end;
 

+ 175 - 53
Units/PascalCoin/UPoolMining.pas

@@ -33,6 +33,9 @@ Const
   CT_PoolMining_Method_MINER_NOTIFY = 'miner-notify'; // Server message to clients to update miners PoW data
   CT_PoolMining_Method_MINER_SUBMIT = 'miner-submit'; // Client message to server to notify a PoW found
 
+  CT_PoolMining_Method_STRATUM_MINING_AUTHORIZE = 'mining-authorize';
+  CT_PoolMining_Method_STRATUM_MINING_SUBSCRIBE = 'mining-subscribe';
+
 Type
   TMinerValuesForWork = Record
      block : Cardinal;
@@ -43,10 +46,14 @@ Type
      target : Cardinal;
      timestamp : Cardinal;
      target_pow : TRawBytes;
+     // Stratum jobid
+     jobid : String;
   End;
 
   TProcessJSONObjectEvent = Procedure (json : TPCJSONObject; method : String) of object;
 
+  { TJSONRPCTcpIpClient }
+
   TJSONRPCTcpIpClient = Class(TBufferedNetTcpIpClient)
   private
     FLastId : Cardinal;
@@ -60,24 +67,39 @@ Type
     Destructor Destroy; override;
     Procedure SendJSONRPCErrorResponse(const id : Variant; const error : String);
     Procedure SendJSONRPCResponse(result : TPCJSONObject; const id : Variant);
-    Procedure SendJSONRPCMethod(const method : String; params : TPCJSONObject; const id : Variant);
-    Function SendJSONRPCMethodAndWait(const method : String; params : TPCJSONObject; MaxWaitMiliseconds : Cardinal; resultObject : TPCJSONObject; processEventOnInvalid : TProcessJSONObjectEvent = Nil) : Boolean;
+    Procedure SendJSONRPCMethod(const method : String; params : TPCJSONList; const id : Variant);
+    Function SendJSONRPCMethodAndWait(const method : String; params : TPCJSONList; MaxWaitMiliseconds : Cardinal; resultObject : TPCJSONObject; processEventOnInvalid : TProcessJSONObjectEvent = Nil) : Boolean;
     Function DoProcessBuffer(SenderThread : TPCThread; MaxWaitMiliseconds : Cardinal; DeleteBufferOnExit : Boolean; var ResponseMethod : String; var jsonObject : TPCJSONObject) : Boolean;
     Function GetNewId : Cardinal;
   End;
 
+  TPoolType = (ptNone,ptIdentify);
+
+  { TPoolMinerClient }
+
   TPoolMinerClient = Class(TJSONRPCTcpIpClient)
   private
     FMinerValuesForWork: TMinerValuesForWork;
     FOnMinerMustChangeValues: TNotifyEvent;
+    FPassword: String;
+    FPoolFinalMinerName: String;
+    FPoolType: TPoolType;
+    FStratum_Target_PoW: TRawBytes;
+    FUserName: String;
     procedure SetMinerValuesForWork(const Value: TMinerValuesForWork);
   protected
+    Procedure DoOnConnect; Override;
   public
     Constructor Create(AOwner : TComponent); override;
     Property OnMinerMustChangeValues : TNotifyEvent read FOnMinerMustChangeValues write FOnMinerMustChangeValues;
     Property MinerValuesForWork : TMinerValuesForWork read FMinerValuesForWork write SetMinerValuesForWork;
-    Procedure SubmitBlockFound(Const Payload : TRawBytes; Timestamp, NOnce : Cardinal);
+    Procedure SubmitBlockFound(Const MinerValuesToGenerateBlock : TMinerValuesForWork; const Payload: TRawBytes; Timestamp, NOnce: Cardinal);
     Procedure DoProcessJSONObject(json : TPCJSONObject; ResponseMethod : String);
+    Property PoolType : TPoolType read FPoolType write FPoolType;
+    Property UserName : String read FUserName write FUserName;
+    Property Password : String read FPassword write FPassword;
+    Property PoolFinalMinerName : String read FPoolFinalMinerName;
+    Property Stratum_Target_PoW : TRawBytes read FStratum_Target_PoW;
   End;
 
   TPoolMiningServer = Class(TNetTcpIpServer)
@@ -114,7 +136,7 @@ Type
 Function TBytesToString(Const bytes : TBytes):AnsiString;
 
 Const
-  CT_TMinerValuesForWork_NULL : TMinerValuesForWork = (block:0;version:0;part1:'';payload_start:'';part3:'';target:0;timestamp:0;target_pow:'');
+  CT_TMinerValuesForWork_NULL : TMinerValuesForWork = (block:0;version:0;part1:'';payload_start:'';part3:'';target:0;timestamp:0;target_pow:'';jobid:'');
 
 implementation
 
@@ -268,7 +290,7 @@ begin
         if Assigned(jsonData) then begin
           if jsonData is TPCJSONObject then begin
             jsonObject.Assign(jsonData);
-            If (jsonObject.IndexOfName('id')>=0) And (jsonObject.IndexOfName('method')<0) then begin
+            If (Not jsonObject.IsNull('id')) And (jsonObject.IndexOfName('method')<0) then begin
               // Is a Response!
               FlushBufferPendingMessages(true,jsonObject.AsInteger('id',0));
             end;
@@ -337,7 +359,7 @@ begin
   End;
 end;
 
-procedure TJSONRPCTcpIpClient.SendJSONRPCMethod(const method: String; params: TPCJSONObject; const id: Variant);
+procedure TJSONRPCTcpIpClient.SendJSONRPCMethod(const method: String; params: TPCJSONList; const id: Variant);
 Var json : TPCJSONObject;
   stream : TMemoryStream;
   b : Byte;
@@ -346,11 +368,15 @@ Var json : TPCJSONObject;
 begin
   json := TPCJSONObject.Create;
   Try
+    json.GetAsVariant('id').Value := id;
     json.GetAsVariant('method').Value := method;
     if Assigned(params) then begin
-      json.GetAsArray('params').GetAsObject(0).Assign(params);
+      If params is TPCJSONObject then begin
+        json.GetAsArray('params').GetAsObject(0).Assign(params);
+      end else if params is TPCJSONArray then begin
+        json.GetAsArray('params').Assign(params);
+      end;
     end;
-    json.GetAsVariant('id').Value := id;
     if (Not VarIsNull(id)) then begin
       new(P);
       P^.id:=id;
@@ -367,8 +393,6 @@ begin
       stream.Write(b,1);
       b := 10;
       stream.Write(b,1);
-      b := 0;
-      stream.Write(b,1);
       stream.Position := 0;
       WriteBufferToSend(stream);
     finally
@@ -379,7 +403,7 @@ begin
   End;
 end;
 
-function TJSONRPCTcpIpClient.SendJSONRPCMethodAndWait(const method: String; params: TPCJSONObject; MaxWaitMiliseconds: Cardinal; resultObject : TPCJSONObject; processEventOnInvalid : TProcessJSONObjectEvent = Nil) : Boolean;
+function TJSONRPCTcpIpClient.SendJSONRPCMethodAndWait(const method: String; params: TPCJSONList; MaxWaitMiliseconds: Cardinal; resultObject : TPCJSONObject; processEventOnInvalid : TProcessJSONObjectEvent = Nil) : Boolean;
 Var nId : Cardinal;
   tc,maxw : Cardinal;
   json : TPCJSONObject;
@@ -428,7 +452,8 @@ Var response : TPCJSONObject;
 begin
   response := TPCJSONObject.Create;
   Try
-    response.GetAsObject('result').Assign(result);
+    If Assigned(Result) then response.GetAsObject('result').Assign(result)
+    else response.GetAsVariant('result').Value:=null;
     response.GetAsVariant('error').Value := Null;
     response.GetAsVariant('id').Value := id;
     stream := TMemoryStream.Create;
@@ -438,8 +463,6 @@ begin
       stream.Write(b,1);
       b := 10;
       stream.Write(b,1);
-      b := 0;
-      stream.Write(b,1);
       stream.Position := 0;
       WriteBufferToSend(stream);
     finally
@@ -539,6 +562,7 @@ end;
 
 procedure TPoolMiningServer.FillMineValue(mine_values: TPCJSONObject; Client : TJSONRPCTcpIpClient);
 Var Op : TPCOperationsComp;
+  ts : Cardinal;
 begin
   mine_values.GetAsVariant('block').Value := FNodeNotifyEvents.Node.Bank.LastBlockFound.OperationBlock.block+1;
   mine_values.GetAsVariant('version').Value := FNodeNotifyEvents.Node.Operations.OperationBlock.protocol_version;
@@ -555,7 +579,12 @@ begin
   finally
     Op.Free;
   end;
-  mine_values.GetAsVariant('timestamp').Value := UnivDateTimeToUnix(DateTime2UnivDateTime(now));
+  // Build 1.4.3 Prevent past time mining
+  ts := UnivDateTimeToUnix(DateTime2UnivDateTime(now));
+  if (ts<FNodeNotifyEvents.Node.Bank.LastBlockFound.OperationBlock.timestamp) then begin
+    ts := FNodeNotifyEvents.Node.Bank.LastBlockFound.OperationBlock.timestamp;
+  end;
+  mine_values.GetAsVariant('timestamp').Value := ts;
 end;
 
 function TPoolMiningServer.MinerSubmit(Client: TJSONRPCTcpIpClient; params: TPCJSONObject; const id : Variant): Boolean;
@@ -729,24 +758,101 @@ end;
 constructor TPoolMinerClient.Create(AOwner: TComponent);
 begin
   FMinerValuesForWork := CT_TMinerValuesForWork_NULL;
+  FPoolType:=ptNone;
+  FUserName:='';
+  FPassword:='';
+  FPoolFinalMinerName:='';
+  FStratum_Target_PoW:='';
   inherited;
 end;
 
+procedure TPoolMinerClient.DoOnConnect;
+Var params : TPCJSONArray;
+  resultObject : TPCJSONObject;
+  s : String;
+  raws : TRawBytes;
+  i : Integer;
+begin
+  inherited DoOnConnect;
+  If FPoolType=ptIdentify then begin
+    // Pool initialization
+    params := TPCJSONArray.Create;
+    resultObject := TPCJSONObject.Create;
+    try
+      params.GetAsVariant(0).Value:=UserName;
+      params.GetAsVariant(1).Value:=Password;
+      If SendJSONRPCMethodAndWait(CT_PoolMining_Method_STRATUM_MINING_AUTHORIZE,params,1000,resultObject,nil) then begin
+        TLog.NewLog(ltInfo,Classname,CT_PoolMining_Method_STRATUM_MINING_AUTHORIZE+' response: '+resultObject.ToJSON(false));
+        // Now subscribe
+        params.Clear;
+        resultObject.Clear;
+        If SendJSONRPCMethodAndWait(CT_PoolMining_Method_STRATUM_MINING_SUBSCRIBE,params,1000,resultObject,nil) then begin
+          //
+          TLog.NewLog(ltInfo,Classname,CT_PoolMining_Method_STRATUM_MINING_SUBSCRIBE+' response: '+resultObject.ToJSON(false));
+          // Decode response
+          If (resultObject.IsNull('error')) then begin
+            s := resultObject.GetAsArray('result').GetAsArray(0).GetAsArray(0).GetAsVariant(0).AsString('');
+            if (s<>'mining.nonce') then Raise Exception.Create('Not a mining.nonce');
+            s := resultObject.GetAsArray('result').GetAsVariant(1).AsString('');
+            raws := TCrypto.HexaToRaw(s);
+            If (length(s)>0) And (length(raws)=0) then begin
+              TLog.NewLog(lterror,ClassName,'Invalid value to assign as a Miner name. Not hexadecimal '+s);
+              FPoolFinalMinerName:='';
+            end else begin
+              FPoolFinalMinerName := raws;
+              for i:=1 to length(raws) do begin
+                if Not (raws[i] in [#32..#254]) then begin
+                  TLog.NewLog(ltError,ClassName,'Invalid proposed miner name. Value at pos '+inttostr(i)+' is not #24..#254: '+IntToStr(integer(raws[i])));
+                  FPoolFinalMinerName:='';
+                  break;
+                end;
+              end;
+            end;
+            TLog.NewLog(ltInfo,Classname,'Final miner name: "'+FPoolFinalMinerName+'" (Length '+IntToStr(length(FPoolFinalMinerName)));
+          end;
+        end else raise Exception.Create('Not response to "'+CT_PoolMining_Method_STRATUM_MINING_SUBSCRIBE+'" method for user "'+UserName+'"');
+      end else raise Exception.Create('Not response to "'+CT_PoolMining_Method_STRATUM_MINING_AUTHORIZE+'" method for user "'+UserName+'"');
+    finally
+      resultObject.free;
+      params.free;
+    end;
+  end;
+end;
+
 procedure TPoolMinerClient.DoProcessJSONObject(json: TPCJSONObject; ResponseMethod : String);
 Var method : String;
     id_value : Variant;
     i : Integer;
-  params_object : TPCJSONObject;
+  params_as_object,pobject : TPCJSONObject;
+  params_as_array : TPCJSONArray;
+  params : TPCJSONData;
   mvfw : TMinerValuesForWork;
+  prev_pow,proposed_pow : TRawBytes;
 begin
   TLog.NewLog(ltdebug,ClassName,'Received JSON: '+json.ToJSON(false));
+  params := Nil;
+  params_as_object := Nil;
+  params_as_array := Nil;
   if (ResponseMethod<>'') then begin
     method := ResponseMethod;
-    params_object := json.GetAsObject('result');
+    i := json.IndexOfName('result');
+    if (i>=0) then begin
+      params := json.Items[i];
+    end;
+    //params_object := json.GetAsObject('result');
     TLog.NewLog(ltinfo,classname,'Received response method:'+ResponseMethod+' JSON:'+json.ToJSON(false));
   end else begin
     method := json.AsString('method','');
-    params_object := json.GetAsArray('params').GetAsObject(0);
+    i := json.IndexOfName('params');
+    if (i>=0) then begin
+      params := json.Items[i];
+    end;
+  end;
+  If Assigned(params) then begin
+    if (params is TPCJSONNameValue) then begin
+      if (TPCJSONNameValue(params).Value is TPCJSONObject) then params_as_object := TPCJSONObject(TPCJSONNameValue(params).Value)
+      else if (TPCJSONNameValue(params).Value is TPCJSONArray) then params_as_array := TPCJSONArray(TPCJSONNameValue(params).Value);
+    end;
   end;
   i := json.IndexOfName('id');
   if i<0 then begin
@@ -755,20 +861,27 @@ begin
     id_value := json.GetAsVariant('id').Value;
   end;
   if method=CT_PoolMining_Method_MINER_NOTIFY then begin
-    mvfw := CT_TMinerValuesForWork_NULL;
-    mvfw.block := params_object.AsInteger('block',0);
-    mvfw.version := params_object.AsInteger('version',0);
-    mvfw.part1 := TCrypto.HexaToRaw(params_object.AsString('part1',''));
-    mvfw.payload_start := TCrypto.HexaToRaw(params_object.AsString('payload_start',''));
-    mvfw.part3 := TCrypto.HexaToRaw(params_object.AsString('part3',''));
-    mvfw.target := params_object.AsInteger('target',0);
-    mvfw.timestamp := params_object.AsInteger('timestamp',0);
-    mvfw.part1 := TCrypto.HexaToRaw(params_object.AsString('part1',''));
-    mvfw.target_pow := TCrypto.HexaToRaw(params_object.AsString('target_pow',''));
-    if (Not VarIsNull(id_value)) And (ResponseMethod='') then begin
-      SendJSONRPCResponse(params_object,id_value);
-    end;
-    MinerValuesForWork := mvfw;
+    If assigned(params_as_array) then pobject := params_as_array.GetAsObject(0)
+    else pobject := Nil;
+    if assigned(pobject) then begin
+      mvfw := CT_TMinerValuesForWork_NULL;
+      mvfw.block := pobject.AsInteger('block',0);
+      mvfw.version := pobject.AsInteger('version',0);
+      mvfw.part1 := TCrypto.HexaToRaw(pobject.AsString('part1',''));
+      mvfw.payload_start := TCrypto.HexaToRaw(pobject.AsString('payload_start',''));
+      mvfw.part3 := TCrypto.HexaToRaw(pobject.AsString('part3',''));
+      mvfw.target := pobject.AsInteger('target',0);
+      mvfw.timestamp := pobject.AsInteger('timestamp',0);
+      mvfw.part1 := TCrypto.HexaToRaw(pobject.AsString('part1',''));
+      mvfw.target_pow := TCrypto.HexaToRaw(pobject.AsString('target_pow',''));
+      If FPoolType=ptIdentify then begin
+        mvfw.jobid:=pobject.AsString('jobid','');
+      end;
+      if (Not VarIsNull(id_value)) And (ResponseMethod='') then begin
+        SendJSONRPCResponse(pobject,id_value);
+      end;
+      MinerValuesForWork := mvfw;
+    end else TLog.NewLog(ltError,ClassName,'method '+method+' without JSON object '+params.ToJSON(false));
   end;
 end;
 
@@ -777,41 +890,50 @@ Var _t : Cardinal;
   _t_pow : TRawBytes;
 begin
   FMinerValuesForWork := Value;
-  // Check that target and target_pow are equal!
-  _t_pow := TPCBank.TargetFromCompact(FMinerValuesForWork.target);
-  if (length(FMinerValuesForWork.target_pow)=32) then begin
-    _t := TPCBank.TargetToCompact(FMinerValuesForWork.target_pow);
-    if (FMinerValuesForWork.target<CT_MinCompactTarget) then begin
-      // target has no valid value... assigning compact_target!
-      FMinerValuesForWork.target:=TPCBank.TargetToCompact(_t_pow);
-    end else if (_t_pow<>FMinerValuesForWork.target_pow) Or (_t<>FMinerValuesForWork.target) then begin
-      TLog.NewLog(ltError,Classname,'Received bad values for target and target_pow!');
-      If (FMinerValuesForWork.target<CT_MinCompactTarget) then begin
-        FMinerValuesForWork.target_pow:=TPCBank.TargetFromCompact(FMinerValuesForWork.target);
-      end else begin
+  If FStratum_Target_PoW<>'' then begin
+    FMinerValuesForWork.target:=TPCBank.TargetToCompact(FStratum_Target_PoW);
+    FMinerValuesForWork.target_pow:=TPCBank.TargetFromCompact(FMinerValuesForWork.target);
+  end else begin
+    // Check that target and target_pow are equal!
+    _t_pow := TPCBank.TargetFromCompact(FMinerValuesForWork.target);
+    if (length(FMinerValuesForWork.target_pow)=32) then begin
+      _t := TPCBank.TargetToCompact(FMinerValuesForWork.target_pow);
+      if (FMinerValuesForWork.target<CT_MinCompactTarget) then begin
+        // target has no valid value... assigning compact_target!
         FMinerValuesForWork.target:=TPCBank.TargetToCompact(_t_pow);
+      end else if (_t_pow<>FMinerValuesForWork.target_pow) Or (_t<>FMinerValuesForWork.target) then begin
+        TLog.NewLog(ltError,Classname,'Received bad values for target and target_pow!');
+        If (FMinerValuesForWork.target<CT_MinCompactTarget) then begin
+          FMinerValuesForWork.target_pow:=TPCBank.TargetFromCompact(FMinerValuesForWork.target);
+        end else begin
+          FMinerValuesForWork.target:=TPCBank.TargetToCompact(_t_pow);
+        end;
       end;
-    end;
-  end else begin
-    if (FMinerValuesForWork.target<CT_MinCompactTarget) then begin
-      // target_pow has no value... assigning target!
-      FMinerValuesForWork.target_pow:=TPCBank.TargetFromCompact(FMinerValuesForWork.target);
     end else begin
-      // Invalid target and compact_target
-      FMinerValuesForWork.target := CT_TMinerValuesForWork_NULL.target;
-      FMinerValuesForWork.target_pow := CT_TMinerValuesForWork_NULL.target_pow;
+      if (FMinerValuesForWork.target<CT_MinCompactTarget) then begin
+        // target_pow has no value... assigning target!
+        FMinerValuesForWork.target_pow:=TPCBank.TargetFromCompact(FMinerValuesForWork.target);
+      end else begin
+        // Invalid target and compact_target
+        FMinerValuesForWork.target := CT_TMinerValuesForWork_NULL.target;
+        FMinerValuesForWork.target_pow := CT_TMinerValuesForWork_NULL.target_pow;
+      end;
     end;
   end;
+  If (FPoolType=ptIdentify) And (FPoolFinalMinerName<>'') then FMinerValuesForWork.payload_start:=FPoolFinalMinerName;
   if Assigned(FOnMinerMustChangeValues) then FOnMinerMustChangeValues(Self);
 end;
 
-procedure TPoolMinerClient.SubmitBlockFound(const Payload: TRawBytes; Timestamp, NOnce: Cardinal);
+procedure TPoolMinerClient.SubmitBlockFound(Const MinerValuesToGenerateBlock : TMinerValuesForWork; const Payload: TRawBytes; Timestamp, NOnce: Cardinal);
 Var json, resultJSON : TPCJSONObject;
   nOnceAsSignedInt : Int32;
 begin
   json := TPCJSONObject.Create;
   Try
     nOnceAsSignedInt := NOnce;
+    If FPoolType=ptIdentify then begin
+      json.GetAsVariant('jobid').Value := MinerValuesToGenerateBlock.jobid;
+    end;
     json.GetAsVariant('payload').Value := TCrypto.ToHexaString(Payload);
     json.GetAsVariant('timestamp').Value := Timestamp;
     json.GetAsVariant('nonce').Value := nOnceAsSignedInt;

+ 59 - 54
Units/PascalCoin/URPC.pas

@@ -21,7 +21,7 @@ interface
 
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
   UNetProtocol, UOpTransaction, UWalletKeys, UTime, UAES, UECIES,
-  UJSONFunctions, classes, blcksock, synsock, IniFiles;
+  UJSONFunctions, classes, blcksock, synsock, IniFiles, Variants;
 
 Const
   CT_RPC_ErrNum_InternalError = 100;
@@ -88,6 +88,7 @@ Type
   TRPCProcess = class(TPCThread)
   private
     FSock:TTCPBlockSocket;
+    FNode : TNode;
   public
     Constructor Create (hsock:tSocket);
     Destructor Destroy; override;
@@ -198,6 +199,7 @@ begin
   FSock:=TTCPBlockSocket.create;
   FSock.socket:=HSock;
   FreeOnTerminate:=true;
+  FNode := TNode.Node;
   //Priority:=tpNormal;
   inherited create(false);
   FreeOnTerminate:=true;
@@ -450,7 +452,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
   begin
     pcops := TPCOperationsComp.Create(Nil);
     try
-      If Not TNode.Node.Bank.LoadOperations(pcops,nBlock) then begin
+      If Not FNode.Bank.LoadOperations(pcops,nBlock) then begin
         ErrorNum := CT_RPC_ErrNum_InternalError;
         ErrorDesc := 'Cannot load Block: '+IntToStr(nBlock);
         Result := False;
@@ -470,8 +472,8 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
       jsonObject.GetAsVariant('oph').Value:=TCrypto.ToHexaString(pcops.OperationBlock.operations_hash);
       jsonObject.GetAsVariant('pow').Value:=TCrypto.ToHexaString(pcops.OperationBlock.proof_of_work);
       jsonObject.GetAsVariant('operations').Value:=pcops.Count;
-      jsonObject.GetAsVariant('hashratekhs').Value := TNode.Node.Bank.SafeBox.CalcBlockHashRateInKhs(pcops.OperationBlock.Block,50);
-      jsonObject.GetAsVariant('maturation').Value := TNode.Node.Bank.BlocksCount - pcops.OperationBlock.block - 1;
+      jsonObject.GetAsVariant('hashratekhs').Value := FNode.Bank.SafeBox.CalcBlockHashRateInKhs(pcops.OperationBlock.Block,50);
+      jsonObject.GetAsVariant('maturation').Value := FNode.Bank.BlocksCount - pcops.OperationBlock.block - 1;
       Result := True;
     finally
       pcops.Free;
@@ -490,6 +492,9 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
       jsonObject.GetAsVariant('block').Value:=OPR.Block;
       jsonObject.GetAsVariant('time').Value:=OPR.time;
       jsonObject.GetAsVariant('opblock').Value:=OPR.NOpInsideBlock;
+      if (OPR.Block>0) And (OPR.Block<FNode.Bank.BlocksCount) then
+        jsonObject.GetAsVariant('maturation').Value := FNode.Bank.BlocksCount - OPR.Block - 1
+      else jsonObject.GetAsVariant('maturation').Value := null;
     end;
     jsonObject.GetAsVariant('optype').Value:=OPR.OpType;
     jsonObject.GetAsVariant('account').Value:=OPR.AffectedAccount;
@@ -532,13 +537,13 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     try
       list := TList.Create;
       Try
-        TNode.Node.Operations.OperationsHashTree.GetOperationsAffectingAccount(AccountNumber,list);
+        FNode.Operations.OperationsHashTree.GetOperationsAffectingAccount(AccountNumber,list);
         for i := list.Count - 1 downto 0 do begin
-          Op := TNode.Node.Operations.OperationsHashTree.GetOperation(PtrInt(list[i]));
+          Op := FNode.Operations.OperationsHashTree.GetOperation(PtrInt(list[i]));
           If TPCOperation.OperationToOperationResume(0,Op,AccountNumber,OPR) then begin
             OPR.NOpInsideBlock := i;
-            OPR.Block := TNode.Node.Operations.OperationBlock.block;
-            OPR.Balance := TNode.Node.Operations.SafeBoxTransaction.Account(AccountNumber).balance;
+            OPR.Block := FNode.Operations.OperationBlock.block;
+            OPR.Balance := FNode.Operations.SafeBoxTransaction.Account(AccountNumber).balance;
             OperationsResume.Add(OPR);
           end;
         end;
@@ -546,7 +551,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
         list.Free;
       End;
       if ((max<=0) Or (OperationsResume.Count<(max+start))) then begin
-        TNode.Node.GetStoredOperationsFromAccount(OperationsResume,AccountNumber,MaxBlocksDepht,max+start);
+        FNode.GetStoredOperationsFromAccount(OperationsResume,AccountNumber,MaxBlocksDepht,max+start);
       end;
       //
       for i:=0 to OperationsResume.Count-1 do begin
@@ -647,25 +652,25 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     opr : TOperationResume;
   begin
     Result := false;
-    if (sender<0) or (sender>=TNode.Node.Bank.AccountsCount) then begin
+    if (sender<0) or (sender>=FNode.Bank.AccountsCount) then begin
       If (sender=CT_MaxAccount) then ErrorDesc := 'Need sender'
       else ErrorDesc:='Invalid sender account '+Inttostr(sender);
       ErrorNum:=CT_RPC_ErrNum_InvalidAccount;
       Exit;
     end;
-    if (target<0) or (target>=TNode.Node.Bank.AccountsCount) then begin
+    if (target<0) or (target>=FNode.Bank.AccountsCount) then begin
       If (target=CT_MaxAccount) then ErrorDesc := 'Need target'
       else ErrorDesc:='Invalid target account '+Inttostr(target);
       ErrorNum:=CT_RPC_ErrNum_InvalidAccount;
       Exit;
     end;
-    sacc := TNode.Node.Operations.SafeBoxTransaction.Account(sender);
-    tacc := TNode.Node.Operations.SafeBoxTransaction.Account(target);
+    sacc := FNode.Operations.SafeBoxTransaction.Account(sender);
+    tacc := FNode.Operations.SafeBoxTransaction.Account(target);
 
     opt := CreateOperationTransaction(sender,target,sacc.n_operation,amount,fee,sacc.accountkey,tacc.accountkey,RawPayload,Payload_method,EncodePwd);
     if opt=nil then exit;
     try
-      If not TNode.Node.AddOperation(Nil,opt,errors) then begin
+      If not FNode.AddOperation(Nil,opt,errors) then begin
         ErrorDesc := 'Error adding operation: '+errors;
         ErrorNum := CT_RPC_ErrNum_InvalidOperation;
         Exit;
@@ -765,17 +770,17 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     opr : TOperationResume;
   begin
     Result := false;
-    if (account_number<0) or (account_number>=TNode.Node.Bank.AccountsCount) then begin
+    if (account_number<0) or (account_number>=FNode.Bank.AccountsCount) then begin
       ErrorDesc:='Invalid account '+Inttostr(account_number);
       ErrorNum:=CT_RPC_ErrNum_InvalidAccount;
       Exit;
     end;
-    acc := TNode.Node.Operations.SafeBoxTransaction.Account(account_number);
+    acc := FNode.Operations.SafeBoxTransaction.Account(account_number);
 
     opck := CreateOperationChangeKey(account_number,acc.n_operation,acc.accountkey,new_pub_key,fee,RawPayload,Payload_method,EncodePwd);
     if not assigned(opck) then exit;
     try
-      If not TNode.Node.AddOperation(Nil,opck,errors) then begin
+      If not FNode.AddOperation(Nil,opck,errors) then begin
         ErrorDesc := 'Error adding operation: '+errors;
         ErrorNum := CT_RPC_ErrNum_InvalidOperation;
         Exit;
@@ -856,12 +861,12 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
       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
+          if (accountsnumber.Get(ian)<0) or (accountsnumber.Get(ian)>=FNode.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));
+          acc := FNode.Operations.SafeBoxTransaction.Account(accountsnumber.Get(ian));
           opck := CreateOperationChangeKey(acc.account,acc.n_operation,acc.accountkey,new_pub_key,fee,RawPayload,Payload_method,EncodePwd);
           if not assigned(opck) then exit;
           try
@@ -873,7 +878,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
         // Ready to execute...
         OperationsResumeList := TOperationsResumeList.Create;
         Try
-          i := TNode.Node.AddOperations(Nil,operationsht,OperationsResumeList, errors);
+          i := FNode.AddOperations(Nil,operationsht,OperationsResumeList, errors);
           if (i<0) then begin
             ErrorNum:=CT_RPC_ErrNum_InternalError;
             ErrorDesc:=errors;
@@ -970,7 +975,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
       errors := '';
       OperationsResumeList := TOperationsResumeList.Create;
       Try
-        i := TNode.Node.AddOperations(Nil,OperationsHashTree,OperationsResumeList,errors);
+        i := FNode.AddOperations(Nil,OperationsHashTree,OperationsResumeList,errors);
         if (i<0) then begin
           ErrorNum:=CT_RPC_ErrNum_InternalError;
           ErrorDesc:=errors;
@@ -1137,8 +1142,8 @@ begin
     // Param "account" contains account number
     // Returns JSON Object with account information based on BlockChain + Pending operations
     c := params.GetAsVariant('account').AsCardinal(CT_MaxAccount);
-    if (c>=0) And (c<TNode.Node.Bank.AccountsCount) then begin
-      account := TNode.Node.Operations.SafeBoxTransaction.Account(c);
+    if (c>=0) And (c<FNode.Bank.AccountsCount) then begin
+      account := FNode.Operations.SafeBoxTransaction.Account(c);
       FillAccountObject(account,GetResultObject);
       Result := True;
     end else begin
@@ -1165,7 +1170,7 @@ begin
       l := params.AsInteger('start',0);
       for j := 0 to ocl.Count - 1 do begin
         if (j>=l) then begin
-          account := TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j));
+          account := FNode.Operations.SafeBoxTransaction.Account(ocl.Get(j));
           FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
         end;
         if (k>0) And ((j+1)>=(k+l)) then break;
@@ -1179,7 +1184,7 @@ begin
         ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         for j := 0 to ocl.Count - 1 do begin
           if (c>=l) then begin
-            account := TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j));
+            account := FNode.Operations.SafeBoxTransaction.Account(ocl.Get(j));
             FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
           end;
           inc(c);
@@ -1231,7 +1236,7 @@ begin
       ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
       account.balance := 0;
       for j := 0 to ocl.Count - 1 do begin
-        inc(account.balance, TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j)).balance );
+        inc(account.balance, FNode.Operations.SafeBoxTransaction.Account(ocl.Get(j)).balance );
       end;
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       Result := true;
@@ -1242,7 +1247,7 @@ begin
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
         ocl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         for j := 0 to ocl.Count - 1 do begin
-          inc(account.balance, TNode.Node.Operations.SafeBoxTransaction.Account(ocl.Get(j)).balance );
+          inc(account.balance, FNode.Operations.SafeBoxTransaction.Account(ocl.Get(j)).balance );
         end;
       end;
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
@@ -1280,7 +1285,7 @@ begin
     // Param "block" contains block number (0..getblockcount-1)
     // Returns JSON object with block information
     c := params.GetAsVariant('block').AsCardinal(CT_MaxBlock);
-    if (c>=0) And (c<TNode.Node.Bank.BlocksCount) then begin
+    if (c>=0) And (c<FNode.Bank.BlocksCount) then begin
       Result := GetBlock(c,GetResultObject);
     end else begin
       ErrorNum := CT_RPC_ErrNum_InvalidBlock;
@@ -1294,20 +1299,20 @@ begin
     i := params.AsCardinal('last',0);
     if (i>0) then begin
       if (i>1000) then i := 1000;
-      c2 := TNode.Node.Bank.BlocksCount-1;
-      if (TNode.Node.Bank.BlocksCount>=i) then
-        c := (TNode.Node.Bank.BlocksCount) - i
+      c2 := FNode.Bank.BlocksCount-1;
+      if (FNode.Bank.BlocksCount>=i) then
+        c := (FNode.Bank.BlocksCount) - i
       else c := 0;
     end else begin
       c := params.GetAsVariant('start').AsCardinal(CT_MaxBlock);
       c2 := params.GetAsVariant('end').AsCardinal(CT_MaxBlock);
       i := params.AsInteger('max',0);
-      if (c<TNode.Node.Bank.BlocksCount) And (i>0) And (i<=1000) then begin
-        if (c+i<TNode.Node.Bank.BlocksCount) then c2 := c+i
-        else c2 := TNode.Node.Bank.BlocksCount-1;
+      if (c<FNode.Bank.BlocksCount) And (i>0) And (i<=1000) then begin
+        if (c+i<FNode.Bank.BlocksCount) then c2 := c+i
+        else c2 := FNode.Bank.BlocksCount-1;
       end;
     end;
-    if ((c>=0) And (c<TNode.Node.Bank.BlocksCount)) And (c2>=c) And (c2<TNode.Node.Bank.BlocksCount) then begin
+    if ((c>=0) And (c<FNode.Bank.BlocksCount)) And (c2>=c) And (c2<FNode.Bank.BlocksCount) then begin
       i := 0; Result := true;
       while (c<=c2) And (Result) And (i<1000) do begin
         Result := GetBlock(c2,jsonresponse.GetAsArray('result').GetAsObject(i));
@@ -1317,22 +1322,22 @@ begin
       ErrorNum := CT_RPC_ErrNum_InvalidBlock;
       if (c>c2) then ErrorDesc := 'Block start > block end'
       else if (c=CT_MaxBlock) Or (c2=CT_MaxBlock) then ErrorDesc:='Need param "last" or "start" and "end"/"max"'
-      else if (c2>=TNode.Node.Bank.BlocksCount) then ErrorDesc := 'Block higher or equal to getblockccount: '+IntToStr(c2)
+      else if (c2>=FNode.Bank.BlocksCount) then ErrorDesc := 'Block higher or equal to getblockccount: '+IntToStr(c2)
       else  ErrorDesc := 'Block not found: '+IntToStr(c);
     end;
   end else if (method='getblockcount') then begin
     // Returns a number with Node blocks count
-    jsonresponse.GetAsVariant('result').Value:=TNode.Node.Bank.BlocksCount;
+    jsonresponse.GetAsVariant('result').Value:=FNode.Bank.BlocksCount;
     Result := True;
   end else if (method='getblockoperation') then begin
     // Param "block" contains block. Null = Pending operation
     // Param "opblock" contains operation inside a block: (0..getblock.operations-1)
     // Returns a JSON object with operation values as "Operation resume format"
     c := params.GetAsVariant('block').AsCardinal(CT_MaxBlock);
-    if (c>=0) And (c<TNode.Node.Bank.BlocksCount) then begin
+    if (c>=0) And (c<FNode.Bank.BlocksCount) then begin
       pcops := TPCOperationsComp.Create(Nil);
       try
-        If Not TNode.Node.Bank.LoadOperations(pcops,c) then begin
+        If Not FNode.Bank.LoadOperations(pcops,c) then begin
           ErrorNum := CT_RPC_ErrNum_InternalError;
           ErrorDesc := 'Cannot load Block: '+IntToStr(c);
           Exit;
@@ -1362,10 +1367,10 @@ begin
     // Param "block" contains block
     // Returns a JSON array with items as "Operation resume format"
     c := params.GetAsVariant('block').AsCardinal(CT_MaxBlock);
-    if (c>=0) And (c<TNode.Node.Bank.BlocksCount) then begin
+    if (c>=0) And (c<FNode.Bank.BlocksCount) then begin
       pcops := TPCOperationsComp.Create(Nil);
       try
-        If Not TNode.Node.Bank.LoadOperations(pcops,c) then begin
+        If Not FNode.Bank.LoadOperations(pcops,c) then begin
           ErrorNum := CT_RPC_ErrNum_InternalError;
           ErrorDesc := 'Cannot load Block: '+IntToStr(c);
           Exit;
@@ -1399,7 +1404,7 @@ begin
     // Param "depht" (optional or "deep") 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);
-    if ((c>=0) And (c<TNode.Node.Bank.AccountsCount)) then begin
+    if ((c>=0) And (c<FNode.Bank.AccountsCount)) then begin
       if (params.IndexOfName('depth')>=0) then i := params.AsInteger('depth',100) else i:=params.AsInteger('deep',100);
       Result := GetAccountOperations(c,GetResultArray,i,params.AsInteger('start',0),params.AsInteger('max',100));
     end else begin
@@ -1411,15 +1416,15 @@ begin
     // Returns all the operations pending to be included in a block in "Operation resume format" as an array
     // Create result
     GetResultArray;
-    for i:=TNode.Node.Operations.Count-1 downto 0 do begin
-      if not TPCOperation.OperationToOperationResume(0,TNode.Node.Operations.Operation[i],TNode.Node.Operations.Operation[i].SenderAccount,opr) then begin
+    for i:=FNode.Operations.Count-1 downto 0 do begin
+      if not TPCOperation.OperationToOperationResume(0,FNode.Operations.Operation[i],FNode.Operations.Operation[i].SenderAccount,opr) then begin
         ErrorNum := CT_RPC_ErrNum_InternalError;
         ErrorDesc := 'Error converting data';
         exit;
       end;
       opr.NOpInsideBlock:=i;
-      opr.Balance := TNode.Node.Operations.SafeBoxTransaction.Account(TNode.Node.Operations.Operation[i].SenderAccount).balance;
-      FillOperationResumeToJSONObject(opr,GetResultArray.GetAsObject( TNode.Node.Operations.Count-1-i ));
+      opr.Balance := FNode.Operations.SafeBoxTransaction.Account(FNode.Operations.Operation[i].SenderAccount).balance;
+      FillOperationResumeToJSONObject(opr,GetResultArray.GetAsObject( FNode.Operations.Count-1-i ));
     end;
     Result := true;
   end else if (method='findoperation') then begin
@@ -1432,7 +1437,7 @@ begin
     end;
     pcops := TPCOperationsComp.Create(Nil);
     try
-      If not TNode.Node.FindOperation(pcops,r,c,i) then begin
+      If not FNode.FindOperation(pcops,r,c,i) then begin
         ErrorNum:=CT_RPC_ErrNum_NotFound;
         ErrorDesc:='ophash not found: "'+params.AsString('ophash','')+'"';
         exit;
@@ -1590,7 +1595,7 @@ begin
   end else if (method='nodestatus') then begin
     // Returns a JSON Object with Node status
     GetResultObject.GetAsVariant('ready').Value := False;
-    If TNode.Node.IsReady(ansistr) then begin
+    If FNode.IsReady(ansistr) then begin
       GetResultObject.GetAsVariant('ready_s').Value := ansistr;
       if TNetData.NetData.NetStatistics.ActiveConnections>0 then begin
         GetResultObject.GetAsVariant('ready').Value := True;
@@ -1607,15 +1612,15 @@ begin
     end else begin
       GetResultObject.GetAsVariant('ready_s').Value := ansistr;
     end;
-    GetResultObject.GetAsVariant('port').Value:=TNode.Node.NetServer.Port;
+    GetResultObject.GetAsVariant('port').Value:=FNode.NetServer.Port;
     GetResultObject.GetAsVariant('locked').Value:=Not _RPCServer.WalletKeys.IsValidPassword;
     GetResultObject.GetAsVariant('timestamp').Value:=UnivDateTimeToUnix(DateTime2UnivDateTime(now));
     GetResultObject.GetAsVariant('version').Value:=CT_ClientAppVersion;
     GetResultObject.GetAsObject('netprotocol').GetAsVariant('ver').Value := CT_NetProtocol_Version;
     GetResultObject.GetAsObject('netprotocol').GetAsVariant('ver_a').Value := CT_NetProtocol_Available;
-    GetResultObject.GetAsVariant('blocks').Value:=TNode.Node.Bank.BlocksCount;
-    GetResultObject.GetAsVariant('sbh').Value:=TCrypto.ToHexaString(TNode.Node.Bank.LastOperationBlock.initial_safe_box_hash);
-    GetResultObject.GetAsVariant('pow').Value:=TCrypto.ToHexaString(TNode.Node.Bank.LastOperationBlock.proof_of_work);
+    GetResultObject.GetAsVariant('blocks').Value:=FNode.Bank.BlocksCount;
+    GetResultObject.GetAsVariant('sbh').Value:=TCrypto.ToHexaString(FNode.Bank.LastOperationBlock.initial_safe_box_hash);
+    GetResultObject.GetAsVariant('pow').Value:=TCrypto.ToHexaString(FNode.Bank.LastOperationBlock.proof_of_work);
     GetResultObject.GetAsObject('netstats').GetAsVariant('active').Value:=TNetData.NetData.NetStatistics.ActiveConnections;
     GetResultObject.GetAsObject('netstats').GetAsVariant('clients').Value:=TNetData.NetData.NetStatistics.ClientsConnections;
     GetResultObject.GetAsObject('netstats').GetAsVariant('servers').Value:=TNetData.NetData.NetStatistics.ServersConnectionsWithResponse;
@@ -1763,13 +1768,13 @@ begin
     Result := true;
   end else if (method='stopnode') then begin
     // Stops communications to other nodes
-    TNode.Node.NetServer.Active := false;
+    FNode.NetServer.Active := false;
     TNetData.NetData.NetConnectionsActive:=false;
     jsonresponse.GetAsVariant('result').Value := true;
     Result := true;
   end else if (method='startnode') then begin
     // Stops communications to other nodes
-    TNode.Node.NetServer.Active := true;
+    FNode.NetServer.Active := true;
     TNetData.NetData.NetConnectionsActive:=true;
     jsonresponse.GetAsVariant('result').Value := true;
     Result := true;

+ 9 - 1
Units/PascalCoin/UTCPIP.pas

@@ -45,6 +45,8 @@ type
   TTCPBlockSocket = TCustomIpClient;
   {$ENDIF}
 
+  { TNetTcpIpClient }
+
   TNetTcpIpClient = Class(TComponent)
   private
     FTcpBlockSocket : TTCPBlockSocket;
@@ -70,6 +72,7 @@ type
     procedure TCustomIpClient_OnError(Sender: TObject; ASocketError: Integer);
     {$ENDIF}
   protected
+    Procedure DoOnConnect; Virtual;
     function ReceiveBuf(var Buf; BufSize: Integer): Integer;
     Function SendStream(Stream : TStream) : Int64;
     Procedure DoWaitForData(WaitMilliseconds : Integer; var HasData : Boolean); virtual;
@@ -241,7 +244,7 @@ begin
   Try
     FTcpBlockSocket.Connect(FRemoteHost,IntToStr(FRemotePort));
     FConnected := FTcpBlockSocket.LastError=0;
-    if (FConnected) And (Assigned(FOnConnect)) then FOnConnect(Self)
+    if (FConnected) then DoOnConnect
     else TLog.NewLog(ltdebug,Classname,'Cannot connect to a server at: '+ClientRemoteAddr+' Reason: '+FTcpBlockSocket.GetErrorDescEx);
   Except
     On E:Exception do begin
@@ -305,6 +308,11 @@ begin
   {$ENDIF}
 end;
 
+procedure TNetTcpIpClient.DoOnConnect;
+begin
+  If (Assigned(FOnConnect)) then FOnConnect(Self);
+end;
+
 procedure TNetTcpIpClient.DoWaitForData(WaitMilliseconds: Integer; var HasData: Boolean);
 Begin
   {$IFDEF DelphiSockets}

+ 25 - 1
Units/Utils/UJSONFunctions.pas

@@ -72,6 +72,7 @@ Type
     Function AsDateTime(DefValue : TDateTime) : TDateTime;
     Function AsCurrency(DefValue : Currency) : Currency;
     Function AsCardinal(DefValue : Cardinal) : Cardinal;
+    Function IsNull : Boolean;
   End;
 
   TPCJSONNameValue = Class(TPCJSONData)
@@ -127,6 +128,8 @@ Type
     Function GetAsArray(index : Integer) : TPCJSONArray;
   end;
 
+  { TPCJSONObject }
+
   TPCJSONObject = Class(TPCJSONList)
   private
     Function GetIndexOrCreateName(Name : String) : Integer;
@@ -156,6 +159,7 @@ Type
     Function SaveAsStream(ParamName : String; Stream : TStream) : Integer;
     Function LoadAsStream(ParamName : String; Stream : TStream) : Integer;
     Function GetNameValue(index : Integer) : TPCJSONNameValue;
+    Function IsNull(ParamName : String) : Boolean;
     Procedure SetAs(Name : String; Value : TPCJSONData);
   End;
 
@@ -510,6 +514,11 @@ begin
   {$ENDIF}
 end;
 
+function TPCJSONVariantValue.IsNull: Boolean;
+begin
+  Result := VarIsNull(FValue) or VarIsEmpty(FValue);
+end;
+
 procedure TPCJSONVariantValue.SetValue(const Value: Variant);
 begin
   FOldValue := FValue;
@@ -657,7 +666,7 @@ begin
   end;
 end;
 
-function TPCJSONObject.AsString(ParamName, DefValue: String): String;
+function TPCJSONObject.AsString(ParamName: String; DefValue: String): String;
 Var v : Variant;
   VV : TPCJSONVariantValue;
 begin
@@ -825,6 +834,21 @@ begin
   Result := Items[index] as TPCJSONNameValue;
 end;
 
+function TPCJSONObject.IsNull(ParamName: String): Boolean;
+Var i : Integer;
+  NV : TPCJSONNameValue;
+begin
+  i := IndexOfName(ParamName);
+  if i<0 then result := true
+  else begin
+    Result := false;
+    NV := TPCJSONNameValue( FList.Items[i] );
+    If (Assigned(NV.Value)) AND (NV.Value is TPCJSONVariantValue) then begin
+      Result := TPCJSONVariantValue(NV.Value).IsNull;
+    end;
+  end;
+end;
+
 function TPCJSONObject.IndexOfName(Name: String): Integer;
 begin
   for Result := 0 to FList.Count - 1 do begin

+ 0 - 104
pascalcoin_daemon.lps

@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<CONFIG>
-  <ProjectSession>
-    <PathDelim Value="\"/>
-    <Version Value="9"/>
-    <BuildModes Active="Default"/>
-    <Units Count="13">
-      <Unit0>
-        <Filename Value="pascalcoin_daemon.pp"/>
-        <IsPartOfProject Value="True"/>
-        <EditorIndex Value="-1"/>
-        <CursorPos X="14" Y="13"/>
-        <UsageCount Value="20"/>
-      </Unit0>
-      <Unit1>
-        <Filename Value="C:\lazarus\fpc\3.0.0\source\packages\fcl-extra\src\daemonapp.pp"/>
-        <EditorIndex Value="-1"/>
-        <UsageCount Value="10"/>
-      </Unit1>
-      <Unit2>
-        <Filename Value="Units\PascalCoin\upcdaemon.pas"/>
-        <IsVisibleTab Value="True"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="198"/>
-        <CursorPos X="95" Y="233"/>
-        <UsageCount Value="10"/>
-      </Unit2>
-      <Unit3>
-        <Filename Value="Units\PascalCoin\UNetProtocol.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="1363"/>
-        <CursorPos X="11" Y="1384"/>
-        <UsageCount Value="10"/>
-      </Unit3>
-      <Unit4>
-        <Filename Value="Units\PascalCoin\UPoolMining.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="74"/>
-        <CursorPos X="3" Y="83"/>
-        <UsageCount Value="10"/>
-      </Unit4>
-      <Unit5>
-        <Filename Value="Units\PascalCoin\UAccounts.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="266"/>
-        <CursorPos X="47" Y="280"/>
-        <UsageCount Value="10"/>
-      </Unit5>
-      <Unit6>
-        <Filename Value="Units\PascalCoin\UThread.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="12"/>
-        <CursorPos X="3" Y="33"/>
-        <UsageCount Value="10"/>
-      </Unit6>
-      <Unit7>
-        <Filename Value="C:\lazarus\fpc\3.0.0\source\rtl\objpas\classes\classesh.inc"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="1632"/>
-        <CursorPos Y="1646"/>
-        <UsageCount Value="10"/>
-      </Unit7>
-      <Unit8>
-        <Filename Value="Units\PascalCoin\UConst.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="42"/>
-        <CursorPos X="22" Y="77"/>
-        <UsageCount Value="10"/>
-      </Unit8>
-      <Unit9>
-        <Filename Value="Units\PascalCoin\UWalletKeys.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="91"/>
-        <CursorPos X="35" Y="102"/>
-        <UsageCount Value="10"/>
-      </Unit9>
-      <Unit10>
-        <Filename Value="Units\PascalCoin\ULog.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="8"/>
-        <CursorPos X="133" Y="29"/>
-        <UsageCount Value="10"/>
-      </Unit10>
-      <Unit11>
-        <Filename Value="Units\PascalCoin\UOpenSSL.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="191"/>
-        <CursorPos X="22" Y="214"/>
-        <UsageCount Value="10"/>
-      </Unit11>
-      <Unit12>
-        <Filename Value="Units\PascalCoin\UTCPIP.pas"/>
-        <EditorIndex Value="-1"/>
-        <TopLine Value="145"/>
-        <CursorPos X="15" Y="161"/>
-        <UsageCount Value="10"/>
-      </Unit12>
-    </Units>
-    <General>
-      <ActiveWindowIndexAtStart Value="-1"/>
-    </General>
-    <JumpHistory HistoryIndex="-1"/>
-  </ProjectSession>
-</CONFIG>