Kaynağa Gözat

Build 1.5.1

PascalCoin 8 yıl önce
ebeveyn
işleme
1c3a250487

+ 2 - 1
PascalCoinMiner.pp

@@ -2,6 +2,7 @@ program PascalCoinMiner;
 
 {$mode objfpc}{$H+}
 {$DEFINE UseCThreads}
+{$I ./Units/PascalCoin/config.inc}
 
 { Copyright (c) 2017 by Albert Molina
 
@@ -55,7 +56,7 @@ type
   end;
 
 Const
-  CT_MINER_VERSION = '0.4';
+  CT_MINER_VERSION = {$IFDEF PRODUCTION}'0.5'{$ELSE}{$IFDEF TESTNET}'0.5 TESTNET'{$ELSE}ERROR{$ENDIF}{$ENDIF};
   CT_Line_DeviceStatus = 3;
   CT_Line_ConnectionStatus = 4;
   CT_Line_MinerValues = 7;

BIN
PascalCoinWallet.res


+ 9 - 1
README.md

@@ -34,6 +34,13 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 ## History:  
 
+### Build 1.5.1.0 - 2017-02-20
+
+- Memory leak fixed on RPC-JSON commands
+- Memory leak fixed on node connections
+- Improved network speed processing new blocks/operations
+- Some minor bugs
+
 ### Build 1.5.0.0 - 2017-02-15
 
 - Net protocol upgrade to 4-5
@@ -42,6 +49,7 @@ Also, consider a donation at PascalCoin development account: "0-10"
 - Improved network connection
 - Added JSON-RPC port 4003 protection Whitelist (only allowed IP's can use JSON-RPC)
 
+
 ### 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...
@@ -197,4 +205,4 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 - First stable version.
 - Created with Genesis block hardcoded
-- Published at same time than Genesis block. NO PREMINE
+- Published at same time than Genesis block. NO PREMINE

+ 9 - 1
README.txt

@@ -34,6 +34,13 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 ## History:  
 
+### Build 1.5.1.0 - 2017-02-20
+
+- Memory leak fixed on RPC-JSON commands
+- Memory leak fixed on node connections
+- Improved network speed processing new blocks/operations
+- Some minor bugs
+
 ### Build 1.5.0.0 - 2017-02-15
 
 - Net protocol upgrade to 4-5
@@ -42,6 +49,7 @@ Also, consider a donation at PascalCoin development account: "0-10"
 - Improved network connection
 - Added JSON-RPC port 4003 protection Whitelist (only allowed IP's can use JSON-RPC)
 
+
 ### 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...
@@ -197,4 +205,4 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 - First stable version.
 - Created with Genesis block hardcoded
-- Published at same time than Genesis block. NO PREMINE
+- Published at same time than Genesis block. NO PREMINE

+ 1 - 1
Units/Forms/UFRMWallet.dfm

@@ -1284,7 +1284,7 @@ object FRMWallet: TFRMWallet
     Left = 105
     Top = 180
     Bitmap = {
-      494C010102000800C00110003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      494C010102000800CC0110003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
       0000000000003600000028000000400000003000000001002000000000000030
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000002A292929D60B0B0BF4111111EE0000006B000000000000

+ 1 - 1
Units/PascalCoin/UBlockChain.pas

@@ -591,7 +591,7 @@ var step : String;
 begin
   Try
     step := 'Deleting critical section';
-    FBankLock.Free;
+    FreeAndNil(FBankLock);
     step := 'Clear';
     Clear;
     step := 'Destroying LastBlockCache';

+ 1 - 1
Units/PascalCoin/UConst.pas

@@ -100,7 +100,7 @@ Const
   CT_Op_Changekey = $02;
   CT_Op_Recover = $03;
 
-  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.5.0'{$ELSE}{$IFDEF TESTNET}'TESTNET'{$ELSE}{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.5.1'{$ELSE}{$IFDEF TESTNET}'TESTNET 1.5.1'{$ELSE}{$ENDIF}{$ENDIF};
 
   CT_Discover_IPs =  'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us';
 

+ 211 - 166
Units/PascalCoin/UNetProtocol.pas

@@ -213,13 +213,15 @@ Type
     //
     Procedure DiscoverFixedServersOnly(const FixedServers : TNodeServerAddressArray);
     //
+    Function ConnectionsCountAll : Integer;
+    Function ConnectionsCountServerClients : Integer;
+    Function ConnectionsCountClients : Integer;
+    Function GetConnection(index : Integer; var NetConnection : TNetConnection) : Boolean;
     Function ConnectionsCount(CountOnlyNetClients : Boolean) : Integer;
     Function Connection(index : Integer) : TNetConnection;
     Function ConnectionExistsAndActive(ObjectPointer : TObject) : Boolean;
     Function ConnectionExists(ObjectPointer : TObject) : Boolean;
-    Function ConnectionsLock : TList;
-    Procedure ConnectionsUnlock;
-    Function ConnectionLock(Sender : TObject; ObjectPointer : TObject) : Boolean;
+    Function ConnectionLock(Sender : TObject; ObjectPointer : TObject; MaxWaitMiliseconds : Cardinal) : Boolean;
     Procedure ConnectionUnlock(ObjectPointer : TObject);
     Function FindConnectionByClientRandomValue(Sender : TNetConnection) : TNetConnection;
     Procedure DiscoverServers;
@@ -484,7 +486,7 @@ begin
   end;
 end;
 
-function TNetData.ConnectionLock(Sender : TObject; ObjectPointer: TObject): Boolean;
+function TNetData.ConnectionLock(Sender : TObject; ObjectPointer: TObject; MaxWaitMiliseconds : Cardinal) : Boolean;
 var i : Integer;
   l : TList;
 begin
@@ -493,7 +495,7 @@ begin
   try
     for i := 0 to l.Count - 1 do begin
       if TObject(l[i])=ObjectPointer then begin
-        Result := TPCThread.TryProtectEnterCriticalSection(Sender,500,TNetConnection(l[i]).FNetLock);
+        Result := TPCThread.TryProtectEnterCriticalSection(Sender,MaxWaitMiliseconds,TNetConnection(l[i]).FNetLock);
         exit;
       end;
     end;
@@ -519,14 +521,43 @@ begin
   end;
 end;
 
-function TNetData.ConnectionsLock: TList;
+function TNetData.ConnectionsCountAll: Integer;
+Var l : TList;
+begin
+  l := FNetConnections.LockList;
+  try
+    Result := l.Count;
+  finally
+    FNetConnections.UnlockList;
+  end;
+end;
+
+function TNetData.ConnectionsCountClients: Integer;
+Var l : TList; i : Integer;
 begin
-  Result := FNetConnections.LockList;
+  Result := 0;
+  l := FNetConnections.LockList;
+  try
+    for i := 0 to l.Count - 1 do begin
+      if TObject(l[i]) is TNetClient then inc(Result);
+    end;
+  finally
+    FNetConnections.UnlockList;
+  end;
 end;
 
-procedure TNetData.ConnectionsUnlock;
+function TNetData.ConnectionsCountServerClients: Integer;
+Var l : TList; i : Integer;
 begin
-  FNetConnections.UnlockList;
+  Result := 0;
+  l := FNetConnections.LockList;
+  try
+    for i := 0 to l.Count - 1 do begin
+      if TObject(l[i]) is TNetServerClient then inc(Result);
+    end;
+  finally
+    FNetConnections.UnlockList;
+  end;
 end;
 
 procedure TNetData.ConnectionUnlock(ObjectPointer: TObject);
@@ -839,6 +870,22 @@ begin
   Result := Nil;
 end;
 
+function TNetData.GetConnection(index: Integer; var NetConnection : TNetConnection) : Boolean;
+Var l : TList;
+begin
+  Result := false; NetConnection := Nil;
+  l := FNetConnections.LockList;
+  try
+    if (index>=0) And (index<l.Count) then begin
+      NetConnection := TNetConnection( l[index] );
+      Result := true;
+      exit;
+    end;
+  finally
+    FNetConnections.UnlockList;
+  end;
+end;
+
 procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection; const Why : String);
 Const CT_LogSender = 'GetNewBlockChainFromClient';
 
@@ -1623,56 +1670,34 @@ Procedure TNetConnection.DoProcessBuffer;
 Var HeaderData : TNetHeaderData;
   ms : TMemoryStream;
   ops : AnsiString;
-  DebugStep : String;
 begin
-  DebugStep := '';
+  if FDoFinalizeConnection then begin
+    TLog.NewLog(ltdebug,Classname,'Executing DoFinalizeConnection at client '+ClientRemoteAddr);
+    Connected := false;
+  end;
+  if Not Connected then exit;
+  ms := TMemoryStream.Create;
   try
-    if FDoFinalizeConnection then begin
-      DebugStep := 'Executing DoFinalizeConnection';
-      TLog.NewLog(ltdebug,Classname,'Executing DoFinalizeConnection at client '+ClientRemoteAddr);
-      Connected := false;
+    if Not FIsWaitingForResponse then begin
+      DoSendAndWaitForResponse(0,0,Nil,ms,0,HeaderData);
     end;
-    if Not Connected then exit;
-    ms := TMemoryStream.Create;
-    try
-      TPCThread.ProtectEnterCriticalSection(Self,FNetLock);
-      Try
-        if Not FIsWaitingForResponse then begin
-          DebugStep := 'is not waiting for response, do send';
-          DoSendAndWaitForResponse(0,0,Nil,ms,0,HeaderData);
-        end else begin
-          DebugStep := 'Is waiting for response, nothing';
-        end;
-      Finally
-        FNetLock.Release;
-      End;
-    finally
-      ms.Free;
-    end;
-    If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
-       AND ((FLastDataReceivedTS+(1000*FRandomWaitSecondsSendHello)<GetTickCount) AND (FLastDataSendedTS+(1000*FRandomWaitSecondsSendHello)<GetTickCount)) then begin
-       // Build 1.4 -> Changing wait time from 120 secs to a random seconds value
-      DebugStep := 'LastSend time old';
-      If TNetData.NetData.PendingRequest(Self,ops)>=2 then begin
-        TLog.NewLog(ltDebug,Classname,'Pending requests without response... closing connection to '+ClientRemoteAddr+' > '+ops);
-        DebugStep := 'Setting connected to false';
-        Connected := false;
-      end else begin
-        TLog.NewLog(ltDebug,Classname,'Sending Hello to check connection to '+ClientRemoteAddr+' > '+ops);
-        DebugStep := 'Sending Hello';
-        Send_Hello(ntp_request,TNetData.NetData.NewRequestId);
-      end;
-    end else if (Self is TNetServerClient) AND (FLastDataReceivedTS=0) And (FCreatedTime+EncodeTime(0,1,0,0)<Now) then begin
-      // Disconnecting client without data...
-      TLog.NewLog(ltDebug,Classname,'Disconnecting client without data '+ClientRemoteAddr);
+  finally
+    ms.Free;
+  end;
+  If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
+     AND ((FLastDataReceivedTS+(1000*FRandomWaitSecondsSendHello)<GetTickCount) AND (FLastDataSendedTS+(1000*FRandomWaitSecondsSendHello)<GetTickCount)) then begin
+     // Build 1.4 -> Changing wait time from 120 secs to a random seconds value
+    If TNetData.NetData.PendingRequest(Self,ops)>=2 then begin
+      TLog.NewLog(ltDebug,Classname,'Pending requests without response... closing connection to '+ClientRemoteAddr+' > '+ops);
       Connected := false;
+    end else begin
+      TLog.NewLog(ltDebug,Classname,'Sending Hello to check connection to '+ClientRemoteAddr+' > '+ops);
+      Send_Hello(ntp_request,TNetData.NetData.NewRequestId);
     end;
-  Except
-    On E:Exception do begin
-      E.Message := E.Message+' Step.TNetConnection.DoProcessBuffer: '+DebugStep;
-      TLog.NewLog(lterror,Classname,E.Message);
-      Raise;
-    end;
+  end else if (Self is TNetServerClient) AND (FLastDataReceivedTS=0) And (FCreatedTime+EncodeTime(0,1,0,0)<Now) then begin
+    // Disconnecting client without data...
+    TLog.NewLog(ltDebug,Classname,'Disconnecting client without data '+ClientRemoteAddr);
+    Connected := false;
   end;
 end;
 
@@ -1959,25 +1984,26 @@ procedure TNetConnection.DoProcess_Hello(HeaderData: TNetHeaderData; DataBuffer:
       Result := false;
       showmessage := true;
       // This message only appears if there is no other valid connections
-      l := TNetData.NetData.NetConnections.LockList;
-      try
-        for i := 0 to l.Count - 1 do begin
-          nc :=(TNetConnection(l[i]));
-          if (nc<>self) and (nc.FHasReceivedData) and (nc.Connected)
-            and (nc.FLastKnownTimestampDiff>=((-1)*CT_MaxSecondsDifferenceOfNetworkNodes))
-            and (nc.FLastKnownTimestampDiff<=(CT_MaxSecondsDifferenceOfNetworkNodes))
-            then begin
-            showmessage := false;
-            break;
+      if TNetData.NetData.NetConnections.TryLockList(5000,l) then begin
+        try
+          for i := 0 to l.Count - 1 do begin
+            nc :=(TNetConnection(l[i]));
+            if (nc<>self) and (nc.FHasReceivedData) and (nc.Connected)
+              and (nc.FLastKnownTimestampDiff>=((-1)*CT_MaxSecondsDifferenceOfNetworkNodes))
+              and (nc.FLastKnownTimestampDiff<=(CT_MaxSecondsDifferenceOfNetworkNodes))
+              then begin
+              showmessage := false;
+              break;
+            end;
           end;
+        finally
+          TNetData.NetData.NetConnections.UnlockList;
+        end;
+        if showmessage then begin
+          TNode.Node.NotifyNetClientMessage(Nil,'Detected a different time in an other node... check that your PC time and timezone is correct or you will be Blacklisted! '+
+            'Your time: '+TimeToStr(now)+' - '+Client.ClientRemoteAddr+' time: '+TimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(connection_ts)))+' Difference: '+inttostr(FLastKnownTimestampDiff)+' seconds. '+
+            '(If this message appears on each connection, then you have a bad configured time, if not, do nothing)' );
         end;
-      finally
-        TNetData.NetData.NetConnections.UnlockList;
-      end;
-      if showmessage then begin
-        TNode.Node.NotifyNetClientMessage(Nil,'Detected a different time in an other node... check that your PC time and timezone is correct or you will be Blacklisted! '+
-          'Your time: '+TimeToStr(now)+' - '+Client.ClientRemoteAddr+' time: '+TimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(connection_ts)))+' Difference: '+inttostr(FLastKnownTimestampDiff)+' seconds. '+
-          '(If this message appears on each connection, then you have a bad configured time, if not, do nothing)' );
       end;
     end else begin
       Result := true;
@@ -2048,7 +2074,7 @@ Begin
           ClientAppVersion := other_version;
           if (DataBuffer.Size-DataBuffer.Position>=SizeOf(FRemoteAccumulatedWork)) then begin
             DataBuffer.Read(FRemoteAccumulatedWork,SizeOf(FRemoteAccumulatedWork));
-            TLog.NewLog(ltdebug,ClassName,'Received HELLO with Accumulated work '+IntToStr(FRemoteAccumulatedWork));
+            TLog.NewLog(ltdebug,ClassName,'Received HELLO with height: '+inttostr(op.OperationBlock.block)+' Accumulated work '+IntToStr(FRemoteAccumulatedWork));
           end;
         end;
         //
@@ -2152,7 +2178,7 @@ begin
         DoDisconnect := false;
         if DataBuffer.Size - DataBuffer.Position >= SizeOf(FRemoteAccumulatedWork) then begin
           DataBuffer.Read(FRemoteAccumulatedWork,SizeOf(FRemoteAccumulatedWork));
-          TLog.NewLog(ltdebug,ClassName,'Received NEW BLOCK with Accumulated work '+IntToStr(FRemoteAccumulatedWork));
+          TLog.NewLog(ltdebug,ClassName,'Received NEW BLOCK with height: '+inttostr(op.OperationBlock.block)+' Accumulated work '+IntToStr(FRemoteAccumulatedWork));
         end else FRemoteAccumulatedWork := 0;
         FRemoteOperationBlock := op.OperationBlock;
         //
@@ -2199,77 +2225,99 @@ var tc : Cardinal;
   was_waiting_for_response : Boolean;
   l : TList;
   i : Integer;
+  iDebugStep : Integer;
 begin
-  Result := false;
-  HeaderData := CT_NetHeaderData;
-  If FIsWaitingForResponse then begin
-    TLog.NewLog(ltdebug,Classname,'Is waiting for response ...');
-    exit;
-  end;
-  If Not Assigned(FTcpIpClient) then exit;
-  if Not Client.Connected then exit;
-  TPCThread.ProtectEnterCriticalSection(Self,FNetLock);
+  iDebugStep := 0;
   Try
-    was_waiting_for_response := RequestId>0;
-    try
-      if was_waiting_for_response then begin
-        FIsWaitingForResponse := true;
-        Send(ntp_request,operation,0,RequestId,SendDataBuffer);
-      end;
-      tc := GetTickCount;
-      Repeat
-        if (ReadTcpClientBuffer(MaxWaitTime,HeaderData,ReceiveDataBuffer)) then begin
-          l := TNetData.NetData.NodeServersAddresses.LockList;
-          try
-            for i := 0 to l.Count - 1 do begin
-              If PNodeServerAddress( l[i] )^.netConnection=Self then begin
-                PNodeServerAddress( l[i] )^.last_connection := (UnivDateTimeToUnix(DateTime2UnivDateTime(now)));
-                PNodeServerAddress( l[i] )^.total_failed_attemps_to_connect := 0;
+    Result := false;
+    HeaderData := CT_NetHeaderData;
+    If FIsWaitingForResponse then begin
+      TLog.NewLog(ltdebug,Classname,'Is waiting for response ...');
+      exit;
+    end;
+    iDebugStep := 100;
+    If Not Assigned(FTcpIpClient) then exit;
+    if Not Client.Connected then exit;
+    iDebugStep := 110;
+    TPCThread.ProtectEnterCriticalSection(Self,FNetLock);
+    Try
+      iDebugStep := 120;
+      was_waiting_for_response := RequestId>0;
+      try
+        if was_waiting_for_response then begin
+          iDebugStep := 200;
+          FIsWaitingForResponse := true;
+          Send(ntp_request,operation,0,RequestId,SendDataBuffer);
+        end;
+        iDebugStep := 300;
+        tc := GetTickCount;
+        Repeat
+          iDebugStep := 400;
+          if (ReadTcpClientBuffer(MaxWaitTime,HeaderData,ReceiveDataBuffer)) then begin
+            iDebugStep := 500;
+            l := TNetData.NetData.NodeServersAddresses.LockList;
+            try
+              iDebugStep := 600;
+              for i := 0 to l.Count - 1 do begin
+                If PNodeServerAddress( l[i] )^.netConnection=Self then begin
+                  PNodeServerAddress( l[i] )^.last_connection := (UnivDateTimeToUnix(DateTime2UnivDateTime(now)));
+                  PNodeServerAddress( l[i] )^.total_failed_attemps_to_connect := 0;
+                end;
               end;
+            finally
+              iDebugStep := 700;
+              TNetData.netData.NodeServersAddresses.UnlockList;
             end;
-          finally
-            TNetData.netData.NodeServersAddresses.UnlockList;
-          end;
-          TLog.NewLog(ltDebug,Classname,'Received '+CT_NetTransferType[HeaderData.header_type]+' operation:'+TNetData.OperationToText(HeaderData.operation)+' id:'+Inttostr(HeaderData.request_id)+' Buffer size:'+Inttostr(HeaderData.buffer_data_length) );
-          if (RequestId=HeaderData.request_id) And (HeaderData.header_type=ntp_response) then begin
-            Result := true;
-          end else begin
-            case HeaderData.operation of
-              CT_NetOp_Hello : Begin
-                DoProcess_Hello(HeaderData,ReceiveDataBuffer);
-              End;
-              CT_NetOp_Message : Begin
-                DoProcess_Message(HeaderData,ReceiveDataBuffer);
-              End;
-              CT_NetOp_GetBlocks : Begin
-                if HeaderData.header_type=ntp_request then
-                  DoProcess_GetBlocks_Request(HeaderData,ReceiveDataBuffer)
-                else if HeaderData.header_type=ntp_response then
-                  DoProcess_GetBlocks_Response(HeaderData,ReceiveDataBuffer)
-                else DisconnectInvalidClient(false,'Not resquest or response: '+TNetData.HeaderDataToText(HeaderData));
-              End;
-              CT_NetOp_GetOperationsBlock : Begin
-                if HeaderData.header_type=ntp_request then
-                  DoProcess_GetOperationsBlock_Request(HeaderData,ReceiveDataBuffer)
-                else TLog.NewLog(ltdebug,Classname,'Received old response of: '+TNetData.HeaderDataToText(HeaderData));
-              End;
-              CT_NetOp_NewBlock : Begin
-                DoProcess_NewBlock(HeaderData,ReceiveDataBuffer);
-              End;
-              CT_NetOp_AddOperations : Begin
-                DoProcess_AddOperations(HeaderData,ReceiveDataBuffer);
-              End;
-            else
-              DisconnectInvalidClient(false,'Invalid operation: '+TNetData.HeaderDataToText(HeaderData));
+            iDebugStep := 800;
+            TLog.NewLog(ltDebug,Classname,'Received '+CT_NetTransferType[HeaderData.header_type]+' operation:'+TNetData.OperationToText(HeaderData.operation)+' id:'+Inttostr(HeaderData.request_id)+' Buffer size:'+Inttostr(HeaderData.buffer_data_length) );
+            if (RequestId=HeaderData.request_id) And (HeaderData.header_type=ntp_response) then begin
+              Result := true;
+            end else begin
+              iDebugStep := 1000;
+              case HeaderData.operation of
+                CT_NetOp_Hello : Begin
+                  DoProcess_Hello(HeaderData,ReceiveDataBuffer);
+                End;
+                CT_NetOp_Message : Begin
+                  DoProcess_Message(HeaderData,ReceiveDataBuffer);
+                End;
+                CT_NetOp_GetBlocks : Begin
+                  if HeaderData.header_type=ntp_request then
+                    DoProcess_GetBlocks_Request(HeaderData,ReceiveDataBuffer)
+                  else if HeaderData.header_type=ntp_response then
+                    DoProcess_GetBlocks_Response(HeaderData,ReceiveDataBuffer)
+                  else DisconnectInvalidClient(false,'Not resquest or response: '+TNetData.HeaderDataToText(HeaderData));
+                End;
+                CT_NetOp_GetOperationsBlock : Begin
+                  if HeaderData.header_type=ntp_request then
+                    DoProcess_GetOperationsBlock_Request(HeaderData,ReceiveDataBuffer)
+                  else TLog.NewLog(ltdebug,Classname,'Received old response of: '+TNetData.HeaderDataToText(HeaderData));
+                End;
+                CT_NetOp_NewBlock : Begin
+                  DoProcess_NewBlock(HeaderData,ReceiveDataBuffer);
+                End;
+                CT_NetOp_AddOperations : Begin
+                  DoProcess_AddOperations(HeaderData,ReceiveDataBuffer);
+                End;
+              else
+                DisconnectInvalidClient(false,'Invalid operation: '+TNetData.HeaderDataToText(HeaderData));
+              end;
             end;
-          end;
-        end else sleep(1);
-      Until (Result) Or (GetTickCount>(MaxWaitTime+tc));
-    finally
-      if was_waiting_for_response then FIsWaitingForResponse := false;
+          end else sleep(1);
+          iDebugStep := 900;
+        Until (Result) Or (GetTickCount>(MaxWaitTime+tc));
+      finally
+        if was_waiting_for_response then FIsWaitingForResponse := false;
+      end;
+      iDebugStep := 990;
+    Finally
+      FNetLock.Release;
+    End;
+  Except
+    On E:Exception do begin
+      E.Message := E.Message+' DoSendAndWaitForResponse step '+Inttostr(iDebugStep);
+      Raise;
     end;
-  Finally
-    FNetLock.Release;
   End;
 end;
 
@@ -2757,7 +2805,6 @@ end;
 destructor TNetClient.Destroy;
 begin
   TLog.NewLog(ltdebug,Classname,'Starting TNetClient.Destroy');
-  TNetData.NetData.FNetConnections.Remove(Self);
   FNetClientThread.OnTerminate := Nil;
   if Not FNetClientThread.Terminated then begin
     FNetClientThread.Terminate;
@@ -2933,64 +2980,62 @@ end;
 { TThreadGetNewBlockChainFromClient }
 
 procedure TThreadGetNewBlockChainFromClient.BCExecute;
-Var i, iMax : Integer;
+Var i,j, iMax : Integer;
   maxWork : UInt64;
   nsa : TNodeServerAddress;
   candidates : TList;
   lop : TOperationBlock;
-  netConnectionsList : TList;
   nc : TNetConnection;
 begin
   // Search better candidates:
   candidates := TList.Create;
   try
     lop := CT_OperationBlock_NUL;
-    netConnectionsList := TNetData.NetData.ConnectionsLock;
-    Try
-      TNetData.NetData.FMaxRemoteOperationBlock := CT_OperationBlock_NUL;
-      // First round: Find by most work
-      iMax := 0;
-      maxWork := 0;
-      for i := 0 to netConnectionsList.Count - 1 do begin
-        nc := TNetConnection(netConnectionsList[i]);
+    TNetData.NetData.FMaxRemoteOperationBlock := CT_OperationBlock_NUL;
+    // First round: Find by most work
+    iMax := 0;
+    maxWork := 0;
+    j := TNetData.NetData.ConnectionsCountAll;
+    for i := 0 to j - 1 do begin
+      if TNetData.NetData.GetConnection(i,nc) then begin
         if (nc.FRemoteAccumulatedWork>maxWork) And (nc.FRemoteAccumulatedWork>TNode.Node.Bank.SafeBox.WorkSum) then begin
           maxWork := nc.FRemoteAccumulatedWork;
           iMax := i;
         end;
         // Preventing downloading
         if nc.FIsDownloadingBlocks then exit;
-        //
       end;
-      if (maxWork>0) then begin
-        for i := 0 to netConnectionsList.Count - 1 do begin
-          nc := TNetConnection(netConnectionsList[i]);
+    end;
+    if (maxWork>0) then begin
+      for i := 0 to j - 1 do begin
+        If TNetData.NetData.GetConnection(i,nc) then begin
           if (nc.FRemoteAccumulatedWork>=maxWork) then begin
             candidates.Add(nc);
             lop := nc.FRemoteOperationBlock;
           end;
         end;
       end;
-      // Second round: Find by most height
-      if candidates.Count=0 then begin
-        for i := 0 to netConnectionsList.Count - 1 do begin
-          nc := TNetConnection(netConnectionsList[i]);
+    end;
+    // Second round: Find by most height
+    if candidates.Count=0 then begin
+      for i := 0 to j - 1 do begin
+        if (TNetData.NetData.GetConnection(i,nc)) then begin
           if (nc.FRemoteOperationBlock.block>=TNode.Node.Bank.BlocksCount) And
              (nc.FRemoteOperationBlock.block>=lop.block) then begin
              lop := nc.FRemoteOperationBlock;
           end;
         end;
-        if (lop.block>0) then begin
-          for i := 0 to netConnectionsList.Count - 1 do begin
-            nc := TNetConnection(netConnectionsList[i]);
+      end;
+      if (lop.block>0) then begin
+        for i := 0 to j - 1 do begin
+          If (TNetData.NetData.GetConnection(i,nc)) then begin
             if (nc.FRemoteOperationBlock.block>=lop.block) then begin
                candidates.Add(nc);
             end;
           end;
         end;
       end;
-    Finally
-      TNetData.NetData.ConnectionsUnlock;
-    End;
+    end;
     TNetData.NetData.FMaxRemoteOperationBlock := lop;
     if (candidates.Count>0) then begin
       // Random a candidate
@@ -3068,7 +3113,7 @@ begin
   Try
     while not Terminated do begin
       l_to_del.Clear;
-      l := FNetData.ConnectionsLock;
+      l := FNetData.NetConnections.LockList;
       try
         FTerminatedAllConnections := l.Count=0;
         for i := 0 to l.Count-1 do begin
@@ -3077,11 +3122,11 @@ begin
           end;
         end;
       finally
-        FNetData.ConnectionsUnlock;
+        FNetData.NetConnections.UnlockList;
       end;
 
       for i := 0 to l_to_del.Count - 1 do begin
-        If FNetData.ConnectionLock(Self,TNetConnection(l_to_del[i])) then begin
+        If FNetData.ConnectionLock(Self,TNetConnection(l_to_del[i]),500) then begin
           try
             DebugStep := 'Destroying NetClient '+TNetConnection(l_to_del[i]).ClientRemoteAddr;
             TNetConnection(l_to_del[i]).Free;

+ 40 - 48
Units/PascalCoin/UNode.pas

@@ -145,13 +145,12 @@ var _Node : TNode;
 
 function TNode.AddNewBlockChain(SenderConnection: TNetConnection; NewBlockOperations: TPCOperationsComp;
   var newBlockAccount: TBlockAccount; var errors: AnsiString): Boolean;
-Var i : Integer;
-  operationscomp : TPCOperationsComp;
+Var i,j : Integer;
   nc : TNetConnection;
   ms : TMemoryStream;
-  netConnectionsList : TList;
   s : String;
   errors2 : AnsiString;
+  OpBlock : TOperationBlock;
 begin
   Result := false;
   if FDisabledsNewBlocksCount>0 then begin
@@ -160,8 +159,9 @@ begin
     exit;
   end;
   If NewBlockOperations.OperationBlock.block<>Bank.BlocksCount then exit;
+  OpBlock := NewBlockOperations.OperationBlock;
   TLog.NewLog(ltdebug,Classname,Format('AddNewBlockChain Connection:%s NewBlock:%s',[
-    Inttohex(PtrInt(SenderConnection),8),TPCOperationsComp.OperationBlockToText(NewBlockOperations.OperationBlock)]));
+    Inttohex(PtrInt(SenderConnection),8),TPCOperationsComp.OperationBlockToText(OpBlock)]));
   If Not TPCThread.TryProtectEnterCriticalSection(Self,2000,FLockNodeOperations) then begin
     If NewBlockOperations.OperationBlock.block<>Bank.BlocksCount then exit;
     s := 'Cannot AddNewBlockChain due blocking lock operations node';
@@ -175,9 +175,15 @@ begin
       Result := Bank.AddNewBlockChainBlock(NewBlockOperations,newBlockAccount,errors);
       if Result then begin
         if Assigned(SenderConnection) then begin
-          FNodeLog.NotifyNewLog(ltupdate,SenderConnection.ClassName,Format(';%d;%s;%s',[NewBlockOperations.OperationBlock.block,SenderConnection.ClientRemoteAddr,NewBlockOperations.OperationBlock.block_payload]));
+          FNodeLog.NotifyNewLog(ltupdate,SenderConnection.ClassName,Format(';%d;%s;%s',[OpBlock.block,SenderConnection.ClientRemoteAddr,OpBlock.block_payload]));
+        end else begin
+          FNodeLog.NotifyNewLog(ltupdate,ClassName,Format(';%d;%s;%s',[OpBlock.block,'NIL',OpBlock.block_payload]));
+        end;
+      end else begin
+        if Assigned(SenderConnection) then begin
+          FNodeLog.NotifyNewLog(lterror,SenderConnection.ClassName,Format(';%d;%s;%s;%s',[OpBlock.block,SenderConnection.ClientRemoteAddr,OpBlock.block_payload,errors]));
         end else begin
-          FNodeLog.NotifyNewLog(ltupdate,ClassName,Format(';%d;%s;%s',[NewBlockOperations.OperationBlock.block,'NIL',NewBlockOperations.OperationBlock.block_payload]));
+          FNodeLog.NotifyNewLog(lterror,ClassName,Format(';%d;%s;%s;%s',[OpBlock.block,'NIL',OpBlock.block_payload,errors]));
         end;
       end;
       FOperations.Clear(true);
@@ -190,30 +196,20 @@ begin
     finally
       ms.Free;
     end;
-    if Result then begin
-      FOperations.SanitizeOperations;
-      // Notify to clients
-      netConnectionsList := TNetData.NetData.ConnectionsLock;
-      Try
-        for i:=0 to netConnectionsList.Count-1 do begin
-          nc := netConnectionsList[i];
-          if (SenderConnection<>nc) then begin
-            TThreadNodeNotifyNewBlock.Create(nc);
-          end;
-        end;
-      Finally
-        TNetData.NetData.ConnectionsUnlock;
-      End;
-    end else begin
-      // If error is on a SenderMiner its a hole
-      FOperations.SanitizeOperations;
-    end;
+    FOperations.SanitizeOperations;
   finally
     FLockNodeOperations.Release;
     TLog.NewLog(ltdebug,Classname,Format('Finalizing AddNewBlockChain Connection:%s NewBlock:%s',[
-      Inttohex(PtrInt(SenderConnection),8),TPCOperationsComp.OperationBlockToText(NewBlockOperations.OperationBlock) ]));
+      Inttohex(PtrInt(SenderConnection),8),TPCOperationsComp.OperationBlockToText(OpBlock) ]));
   End;
   if Result then begin
+    // Notify to clients
+    j := TNetData.NetData.ConnectionsCountAll;
+    for i:=0 to j-1 do begin
+      if (TNetData.NetData.GetConnection(i,nc)) then begin
+        if (nc<>SenderConnection) then TThreadNodeNotifyNewBlock.Create(nc);
+      end;
+    end;
     // Notify it!
     NotifyBlocksChanged;
   end;
@@ -239,7 +235,6 @@ Var
   nc : TNetConnection;
   e : AnsiString;
   mtl : TList;
-  netConnectionsList : TList;
   s : String;
   OPR : TOperationResume;
   ActOp : TPCOperation;
@@ -304,17 +299,12 @@ begin
     end;
     if Result=0 then exit;
     // Send to other nodes
-    netConnectionsList := TNetData.NetData.ConnectionsLock;
-    Try
-      for i:=0 to netConnectionsList.Count-1 do begin
-        nc := netConnectionsList[i];
-        if (nc<>SenderConnection) then begin
-          TThreadNodeNotifyOperations.Create(nc,valids_operations);
-        end;
+    j := TNetData.NetData.ConnectionsCountAll;
+    for i:=0 to j-1 do begin
+      If TNetData.NetData.GetConnection(i,nc) then begin
+        if (nc<>SenderConnection) then TThreadNodeNotifyOperations.Create(nc,valids_operations);
       end;
-    Finally
-      TNetData.NetData.ConnectionsUnlock;
-    End;
+    end;
   finally
     valids_operations.Free;
   end;
@@ -691,9 +681,8 @@ begin
 end;
 
 function TNode.SendNodeMessage(Target: TNetConnection; TheMessage: AnsiString; var errors: AnsiString): Boolean;
-Var i : Integer;
+Var i,j : Integer;
   nc : TNetConnection;
-  netConnectionsList : TList;
   s : String;
 begin
   Result := false;
@@ -707,15 +696,18 @@ begin
     if assigned(Target) then begin
       Target.Send_Message(TheMessage);
     end else begin
-      netConnectionsList := TNetData.NetData.ConnectionsLock;
-      Try
-        for i:=0 to netConnectionsList.Count-1 do begin
-          nc := netConnectionsList[i];
-          nc.Send_Message(TheMessage);
+      j := TNetData.NetData.ConnectionsCountAll;
+      for i:=0 to j-1 do begin
+        if TNetData.NetData.GetConnection(i,nc) then begin
+          If TNetData.NetData.ConnectionLock(Self,nc,500) then begin
+            try
+              nc.Send_Message(TheMessage);
+            finally
+              TNetData.NetData.ConnectionUnlock(nc)
+            end;
+          end;
         end;
-      Finally
-        TNetData.NetData.ConnectionsUnlock;
-      End;
+      end;
     end;
     result := true;
   finally
@@ -839,7 +831,7 @@ end;
 
 procedure TThreadNodeNotifyNewBlock.BCExecute;
 begin
-  if TNetData.NetData.ConnectionLock(Self,FNetConnection) then begin
+  if TNetData.NetData.ConnectionLock(Self,FNetConnection,500) then begin
     try
       TLog.NewLog(ltdebug,ClassName,'Sending new block found to '+FNetConnection.Client.ClientRemoteAddr);
       FNetConnection.Send_NewBlockFound;
@@ -864,7 +856,7 @@ end;
 
 procedure TThreadNodeNotifyOperations.BCExecute;
 begin
-  if TNetData.NetData.ConnectionLock(Self, FNetConnection) then begin
+  if TNetData.NetData.ConnectionLock(Self, FNetConnection, 500) then begin
     try
       if FOperationsHashTree.OperationsCount<=0 then exit;
       TLog.NewLog(ltdebug,ClassName,'Sending '+inttostr(FOperationsHashTree.OperationsCount)+' Operations to '+FNetConnection.ClientRemoteAddr);

+ 5 - 9
Units/PascalCoin/UPoolMinerThreads.pas

@@ -17,6 +17,8 @@ unit UPoolMinerThreads;
 
 interface
 
+{$I config.inc}
+
 uses
   Classes, SysUtils, syncobjs, UThread, UPoolMining, UAccounts, UCrypto, ULog, UBlockChain, USha256;
 
@@ -219,13 +221,8 @@ 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;
+  FDevicesList := TPCThreadList.Create('TPoolMinerThread_DevicesList');
   FMinerThreads := 0;
   FMinerAddName:='';
   FTestingPoWLeftBits := 0;
@@ -354,7 +351,6 @@ begin
   finally
     FDevicesList.UnlockList;
   end;
-  // XXXXXXXXXXXX Synchronize(NotifyPoolMinerConnectionChanged);
   NotifyPoolMinerConnectionChanged;
 end;
 
@@ -410,7 +406,7 @@ begin
   FMinerValuesForWork := CT_TMinerValuesForWork_NULL;
   FPartialDeviceStats := CT_TMinerStats_NULL;
   FGlobaDeviceStats := CT_TMinerStats_NULL;
-  FLastStats := TPCThreadList.Create;
+  FLastStats := TPCThreadList.Create('TCustomMinerDeviceThread_LastStats');
   FOnFoundNOnce:=Nil;
   FOnMinerValuesChanged:=Nil;
   FOnStateChanged:=Nil;
@@ -617,7 +613,7 @@ end;
 
 constructor TCPUDeviceThread.Create(PoolMinerThread: TPoolMinerThread; InitialMinerValuesForWork: TMinerValuesForWork);
 begin
-  FCPUsThreads := TPCThreadList.Create;
+  FCPUsThreads := TPCThreadList.Create('TCPUDeviceThread_CPUsThreads');
   FCPUs:=0;
   FUseOpenSSLFunctions := true;
   inherited Create(PoolMinerThread, InitialMinerValuesForWork);

+ 15 - 12
Units/PascalCoin/UPoolMining.pas

@@ -288,18 +288,21 @@ begin
         // Decode
         jsonData := TPCJSONData.ParseJSONValue(PartialBuffer);
         if Assigned(jsonData) then begin
-          if jsonData is TPCJSONObject then begin
-            jsonObject.Assign(jsonData);
-            If (Not jsonObject.IsNull('id')) And (jsonObject.IndexOfName('method')<0) then begin
-              // Is a Response!
-              FlushBufferPendingMessages(true,jsonObject.AsInteger('id',0));
-            end;
-            Result := true;
-            exit;
-          end else begin
-            TLog.NewLog(lterror,ClassName,'Invalid JSON class: '+jsonData.ClassName+' json: '+TBytesToString(PartialBuffer));
-            jsonData.Free;
-          End;
+          Try
+            if jsonData is TPCJSONObject then begin
+              jsonObject.Assign(jsonData);
+              If (Not jsonObject.IsNull('id')) And (jsonObject.IndexOfName('method')<0) then begin
+                // Is a Response!
+                FlushBufferPendingMessages(true,jsonObject.AsInteger('id',0));
+              end;
+              Result := true;
+              exit;
+            end else begin
+              TLog.NewLog(lterror,ClassName,'Invalid JSON class: '+jsonData.ClassName+' json: '+TBytesToString(PartialBuffer));
+            End;
+          Finally
+            jsonData.Free; // Memory leak on 1.5.0
+          end;
         end else begin
           TLog.NewLog(lterror,ClassName,Format('Read %d bytes but no valid JSON inside: %s',[last_bytes_read,TBytesToString(PartialBuffer)]));
         end;

+ 2 - 2
Units/PascalCoin/URPC.pas

@@ -586,7 +586,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     nc : TNetConnection;
     obj: TPCJSONObject;
   Begin
-    l := TNetData.NetData.ConnectionsLock;
+    l := TNetData.NetData.NetConnections.LockList;
     try
       for i:=0 to l.Count-1 do begin
         nc := TNetData.NetData.Connection(i);
@@ -602,7 +602,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
         obj.GetAsVariant('netver_a').Value:=nc.NetProtocolVersion.protocol_available;
       end;
     finally
-      TNetData.NetData.ConnectionsUnlock;
+      TNetData.NetData.NetConnections.UnlockList;
     end;
   end;
 

+ 5 - 4
Units/PascalCoin/UTCPIP.pas

@@ -21,8 +21,6 @@ interface
 
 {$I config.inc}
 
-{.$DEFINE DelphiSockets}
-{$DEFINE Synapse}
 {$IFDEF DelphiSockets}{$IFDEF Synapse}DelphiSockets and Synapse are defined! Choose one!{$ENDIF}{$ENDIF}
 {$IFNDEF DelphiSockets}{$IFNDEF Synapse}Nor DelphiSockets nor Synapse are defined! Choose one!{$ENDIF}{$ENDIF}
 
@@ -281,7 +279,8 @@ begin
   FLock := TPCCriticalSection.Create('TNetTcpIpClient_Lock');
   FTcpBlockSocket := TTCPBlockSocket.Create;
   FTcpBlockSocket.OnAfterConnect := OnConnect;
-  FTcpBlockSocket.SocksTimeout := 10000;
+  FTcpBlockSocket.SocksTimeout := 5000; //Build 1.5.0 was 10000;
+  FTcpBlockSocket.ConnectionTimeout := 5000; // Build 1.5.0 was default
   FRemoteHost := '';
   FRemotePort  := 0;
   FBytesReceived := 0;
@@ -293,7 +292,7 @@ end;
 destructor TNetTcpIpClient.Destroy;
 begin
   Disconnect;
-  {$IFDEF DelphiSockets}
+  {$IFDEF Synapse}  // Memory leak on 1.5.0
   FreeAndNil(FLock);
   {$ENDIF}
   inherited;
@@ -737,6 +736,8 @@ begin
       n.FConnected := True;
       n.RemoteHost := ClientSocket.GetRemoteSinIP;
       n.RemotePort := ClientSocket.GetRemoteSinPort;
+      ClientSocket.SocksTimeout := 5000; //New 1.5.1
+      ClientSocket.ConnectionTimeout := 5000; // New 1.5.1
       {$ENDIF}
     {$IFDEF Synapse}
     finally

+ 1 - 0
Units/PascalCoin/UThread.pas

@@ -180,6 +180,7 @@ end;
 
 class procedure TPCThread.ProtectEnterCriticalSection(Const Sender : TObject; var Lock: TPCCriticalSection);
 begin
+
   if Not Lock.TryEnter then begin
 //    TLog.NewLog(ltdebug,Sender.Classname,Format('Locked critical section (WAIT): LockCount:%d RecursionCount:%d Semaphore:%d LockOwnerThread:%s',[
 //      Lock.LockCount,Lock.RecursionCount,Lock.LockSemaphore,IntToHex(Lock.OwningThread,8) ]));

+ 1 - 1
pascalcoin_daemon.ini

@@ -6,7 +6,7 @@ SAVELOGS=0
 ;Port to use by TCP/IP JSON-RPC commands
 RPC_PORT=4003
 ;RPC_WHITELIST : String containing allowed IP's that can use port 4003. Empty=ALL
-RPC_WHITELIST=127.0.0.1 
+RPC_WHITELIST=127.0.0.1;
 ;RPC_SAVELOGS : Boolean
 ;Save RPC commands log file $HOME/PascalCoin
 RPC_SAVELOGS=1