Przeglądaj źródła

Merge pull request #30 from PascalCoinDev/master

Improvements on 5.4
Pascal Coin 4 lat temu
rodzic
commit
04d7088fc1

+ 4 - 1
CHANGELOG.md

@@ -1,10 +1,13 @@
 # Changelog
 
 ## Build 5.4 - (PENDING RELEASE)
+- Added "DATAFOLDER" configuration option at pascalcoin_daemon.ini file (daemon/service) in order to allow customize data folder
 - Added usage of AbstractMem library to allow build a PascalCoin version using virtual memory and efficient caching mechanism
   - Must activate {$DEFINE USE_ABSTRACTMEM} at config.inc file
 - Improved performance when downloading Safebox (Fresh installation)
-- Fixed minor bugs
+- Fixed bugs:
+  - Fixed bugs on "pascalcoin_daemon" (daemon on Linux / Service on Windows) that produced crash on windows and some invalid finalization on Linux
+  - Fixed minor bugs
 
 ## Build 5.3.0 - 2020-03-12
 - Fixed "out of memory" error when downloading Safebox

+ 9 - 9
src/core/UConst.pas

@@ -41,9 +41,9 @@ Const
     {$IFDEF PRODUCTION}'00000003A29C32E84A539ADE24397D41D30116A6FAFEC17B7D9CED68A4238C92'{$ELSE}{$IFDEF TESTNET}''{$ELSE}{$ENDIF}{$ENDIF};
 
 
-  CT_NetServer_Port = {$IFDEF PRODUCTION}4004{$ELSE}{$IFDEF TESTNET}4604{$ELSE}{$ENDIF}{$ENDIF};
-  CT_JSONRPCMinerServer_Port = {$IFDEF PRODUCTION}4009{$ELSE}{$IFDEF TESTNET}4609{$ELSE}{$ENDIF}{$ENDIF};
-  CT_JSONRPC_Port = {$IFDEF PRODUCTION}4003{$ELSE}{$IFDEF TESTNET}4603{$ELSE}{$ENDIF}{$ENDIF};
+  CT_NetServer_Port = {$IFDEF PRODUCTION}4004{$ELSE}{$IFDEF TESTNET}4204{$ELSE}{$ENDIF}{$ENDIF};
+  CT_JSONRPCMinerServer_Port = {$IFDEF PRODUCTION}4009{$ELSE}{$IFDEF TESTNET}4209{$ELSE}{$ENDIF}{$ENDIF};
+  CT_JSONRPC_Port = {$IFDEF PRODUCTION}4003{$ELSE}{$IFDEF TESTNET}4203{$ELSE}{$ENDIF}{$ENDIF};
   CT_AccountsPerBlock = 5;
 
   CT_NewLineSecondsAvg: Cardinal = {$IFDEF PRODUCTION}300{$ELSE}{$IFDEF TESTNET}30{$ELSE}{$ENDIF}{$ENDIF};
@@ -76,7 +76,7 @@ Const
     {$IFDEF PRODUCTION}$16000000{$ELSE}$08000000{$ENDIF};
   {$ENDIF}
   CT_MinCompactTarget_v5: Cardinal = // Minimum compact target of block if using Protocol 5 or higher
-    {$IFDEF PRODUCTION}$12000000{$ELSE}{$IFDEF TESTNET}$0D000000{$ELSE}{$ENDIF}{$ENDIF};
+    {$IFDEF PRODUCTION}$12000000{$ELSE}{$IFDEF TESTNET}$10000000{$ELSE}{$ENDIF}{$ENDIF};
 
 
   CT_CalcNewTargetBlocksAverage: Cardinal = 100;
@@ -127,10 +127,10 @@ Const
   CT_Protocol_Upgrade_v3_MinBlock = {$IFDEF PRODUCTION}210000{$ELSE}250{$ENDIF};
   CT_Protocol_Upgrade_v4_MinBlock = {$IFDEF PRODUCTION}260000{$ELSE}400{$ENDIF};
   CT_Protocol_Upgrade_v5_MinBlock = {$IFDEF PRODUCTION}378000{$ELSE}500{$ENDIF};
-  CT_Protocol_Upgrade_v6_MinBlock = {$IFDEF PRODUCTION}999999999{$ELSE}600{$ENDIF}; // TODO: ALLOW V6 activate setting a valid "min block" value
+  CT_Protocol_Upgrade_v6_MinBlock = {$IFDEF PRODUCTION}999999999{$ELSE}999999999{$ENDIF}; // TODO: ALLOW V6 activate setting a valid "min block" value
 
 
-  CT_MagicNetIdentification = {$IFDEF PRODUCTION}$0A043580{$ELSE}$06000000{$ENDIF};
+  CT_MagicNetIdentification = {$IFDEF PRODUCTION}$0A043580{$ELSE}$05000004{$ENDIF};
 
   CT_NetProtocol_Version: Word = 10;
   // IMPORTANT NOTE!!!
@@ -141,9 +141,9 @@ Const
 
   CT_SafeBoxBankVersion : Word = 3; // Protocol 2 upgraded safebox version from 2 to 3
 
-  CT_MagicIdentificator: String = {$IFDEF PRODUCTION}'PascalCoin'{$ELSE}'PascalCoin_TESTNET_6'{$ENDIF}; //
+  CT_MagicIdentificator: String = {$IFDEF PRODUCTION}'PascalCoin'{$ELSE}'PascalCoinTESTNET_5.Beta.4'{$ENDIF}; //
 
-  CT_PascalCoin_Data_Folder : String = {$IFDEF PRODUCTION}'PascalCoin'{$ELSE}'PascalCoin_TESTNET_6'{$ENDIF}; //
+  CT_PascalCoin_Data_Folder : String = {$IFDEF PRODUCTION}'PascalCoin'{$ELSE}'PascalCoin_TESTNET_5.Beta.4'{$ENDIF}; //
 
   CT_PseudoOp_Reward = $0;
   // Value of Operations type in Protocol 1
@@ -198,7 +198,7 @@ Const
   CT_OpSubtype_Data_Signer                = 103;
   CT_OpSubtype_Data_Receiver              = 104;
 
-  CT_ClientAppVersion : String = {$IFDEF PRODUCTION}'5.4.Beta'{$ELSE}{$IFDEF TESTNET}'TESTNET 6 pre 1'{$ELSE}{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : String = {$IFDEF PRODUCTION}'5.4.Beta'{$ELSE}{$IFDEF TESTNET}'TESTNET 5.4.beta'{$ELSE}{$ENDIF}{$ENDIF};
 
   CT_Discover_IPs = {$IFDEF PRODUCTION}'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin1.dynamic-dns.net;pascalcoin2.dynamic-dns.net;pascalcoin1.dns1.us;pascalcoin2.dns1.us;pascalcoin1.dns2.us;pascalcoin2.dns2.us'
                     {$ELSE}'pascaltestnet1.dynamic-dns.net;pascaltestnet2.dynamic-dns.net;pascaltestnet1.dns1.us;pascaltestnet2.dns1.us'{$ENDIF};

+ 16 - 4
src/core/UNode.pas

@@ -124,6 +124,7 @@ Type
     procedure MarkVerifiedECDSASignaturesFromMemPool(newOperationsToValidate : TPCOperationsComp);
     class function NodeVersion : String;
     class function GetPascalCoinDataFolder : String;
+    class procedure SetPascalCoinDataFolder(const ANewDataFolder : String);
   End;
 
   TThreadSafeNodeNotifyEvent = Class(TPCThread)
@@ -207,6 +208,7 @@ implementation
 Uses UOpTransaction, UConst, UTime, UCommon, UPCOperationsSignatureValidator, UFolderHelper;
 
 var _Node : TNode;
+  _PascalCoinDataFolder : String;
 
 { TNode }
 
@@ -652,8 +654,8 @@ begin
   if Not Assigned(_Node) then _Node := Self;
 end;
 
-class procedure TNode.DecodeIpStringToNodeServerAddressArray(
-  const Ips: String; Var NodeServerAddressArray: TNodeServerAddressArray);
+class procedure TNode.DecodeIpStringToNodeServerAddressArray(const Ips: String;
+  var NodeServerAddressArray: TNodeServerAddressArray);
   Function GetIp(var ips_string : String; var nsa : TNodeServerAddress) : Boolean;
   Const CT_IP_CHARS = ['a'..'z','A'..'Z','0'..'9','.','-','_'];
   var i : Integer;
@@ -829,7 +831,7 @@ begin
   Result := true;
 end;
 
-function TNode.IsReady(Var CurrentProcess: String): Boolean;
+function TNode.IsReady(var CurrentProcess: String): Boolean;
 var LLockedMempool : TPCOperationsComp;
 begin
   Result := false;
@@ -1293,7 +1295,16 @@ end;
 
 class function TNode.GetPascalCoinDataFolder: String;
 begin
-  Result := TFolderHelper.GetDataFolder(CT_PascalCoin_Data_Folder);
+  if (_PascalCoinDataFolder.Trim.Length>0) then begin
+    Result := _PascalCoinDataFolder;
+  end else begin
+    Result := TFolderHelper.GetDataFolder(CT_PascalCoin_Data_Folder);
+  end;
+end;
+
+class procedure TNode.SetPascalCoinDataFolder(const ANewDataFolder: String);
+begin
+  _PascalCoinDataFolder := ANewDataFolder;
 end;
 
 function TNode.LockMempoolRead: TPCOperationsComp;
@@ -1600,6 +1611,7 @@ end;
 
 initialization
   _Node := Nil;
+  _PascalCoinDataFolder := '';
 finalization
   FreeAndNil(_Node);
 end.

+ 2 - 2
src/core/UOpTransaction.pas

@@ -1458,7 +1458,7 @@ begin
     Exit;
   end;
   if (account_signer.balance<FData.fee) then begin
-    errors := 'Insuficient founds';
+    errors := 'Insuficient funds';
     exit;
   end;
   if (length(FData.payload.payload_raw)>CT_MaxPayloadSize) then begin
@@ -2060,7 +2060,7 @@ begin
     Exit;
   end;
   if (account_signer.balance<FData.fee) then begin
-    errors := 'Insuficient founds';
+    errors := 'Insuficient funds';
     exit;
   end;
   if (length(FData.payload.payload_raw)>CT_MaxPayloadSize) then begin

+ 1 - 0
src/core/URPC.pas

@@ -3558,6 +3558,7 @@ begin
       jso.GetAsVariant('lastcon').Value := nsaarr[i].last_connection;
       jso.GetAsVariant('attempts').Value := nsaarr[i].total_failed_attemps_to_connect;
     end;
+    GetResultObject.GetAsVariant('datafolder').Value:=FNode.GetPascalCoinDataFolder;
     Result := True;
   end else if (method='encodepubkey') then begin
     // Creates a encoded public key based on params

+ 30 - 34
src/core/upcdaemon.pas

@@ -46,6 +46,7 @@ Const
   CT_INI_IDENT_LOWMEMORY = 'LOWMEMORY';
   CT_INI_IDENT_MINPENDINGBLOCKSTODOWNLOADCHECKPOINT = 'MINPENDINGBLOCKSTODOWNLOADCHECKPOINT';
   CT_INI_IDENT_PEERCACHE = 'PEERCACHE';
+  CT_INI_IDENT_DATA_FOLDER = 'DATAFOLDER';
 
 Type
   { TPCDaemonThread }
@@ -55,6 +56,7 @@ Type
     FIniFile : TIniFile;
     FMaxBlockToRead: Int64;
     FLastNodesCacheUpdatedTS : TTickCount;
+    function GetDataFolder : String;
     procedure OnNetDataReceivedHelloMessage(Sender : TObject);
     procedure OnInitSafeboxProgressNotify(sender : TObject; const message : String; curPos, totalCount : Int64);
   protected
@@ -70,7 +72,6 @@ Type
   TPCDaemon = Class(TCustomDaemon)
   Private
     FThread : TPCDaemonThread;
-    Procedure ThreadStopped (Sender : TObject);
   public
     Function Start : Boolean; override;
     Function Stop : Boolean; override;
@@ -87,7 +88,6 @@ Type
   TPCDaemonMapper = Class(TCustomDaemonMapper)
   private
     FLog : TLog;
-    procedure OnPascalCoinInThreadLog(logtype : TLogType; Time : TDateTime; AThreadID : TThreadID; Const sender, logtext : String);
   protected
     Procedure DoOnCreate; override;
     Procedure DoOnDestroy; override;
@@ -105,6 +105,19 @@ Var _FLog : TLog;
 
 { TPCDaemonThread }
 
+function TPCDaemonThread.GetDataFolder: String;
+Var LIniDataFolder : String;
+begin
+  LIniDataFolder := FIniFile.ReadString(CT_INI_SECTION_GLOBAL,CT_INI_IDENT_DATA_FOLDER,'').Trim;
+  if (LIniDataFolder.Length=0) then begin
+    LIniDataFolder:=TNode.GetPascalCoinDataFolder;
+  end else begin
+    TNode.SetPascalCoinDataFolder(LIniDataFolder);
+  end;
+  ForceDirectories(LIniDataFolder);
+  Result := LIniDataFolder;
+end;
+
 procedure TPCDaemonThread.OnNetDataReceivedHelloMessage(Sender: TObject);
 Var LNsarr : TNodeServerAddressArray;
   i : Integer;
@@ -154,7 +167,7 @@ var
     TLog.NewLog(ltInfo,ClassName,'RPC server is active on port '+IntToStr(port));
     If FIniFile.ReadBool(CT_INI_SECTION_GLOBAL,CT_INI_IDENT_RPC_SAVELOGS,true) then begin
       FIniFile.WriteBool(CT_INI_SECTION_GLOBAL,CT_INI_IDENT_RPC_SAVELOGS,true);
-      FRPC.LogFileName:= TNode.GetPascalCoinDataFolder+PathDelim+'pascalcoin_rpc.log';
+      FRPC.LogFileName:= GetDataFolder+PathDelim+'pascalcoin_rpc.log';
       TLog.NewLog(ltInfo,ClassName,'Activating RPC logs on file '+FRPC.LogFileName);
     end else begin
       FIniFile.WriteBool(CT_INI_SECTION_GLOBAL,CT_INI_IDENT_RPC_SAVELOGS,false);
@@ -233,12 +246,10 @@ begin
       // Load Node
       // Check OpenSSL dll
       if Not LoadSSLCrypt then begin
-        WriteLn('Cannot load '+SSL_C_LIB);
-        WriteLn('To use this software make sure this file is available on you system or reinstall the application');
         raise Exception.Create('Cannot load '+SSL_C_LIB+#10+'To use this software make sure this file is available on you system or reinstall the application');
       end;
       TCrypto.InitCrypto;
-      FWalletKeys.WalletFileName := TNode.GetPascalCoinDataFolder+PathDelim+'WalletKeys.dat';
+      FWalletKeys.WalletFileName := GetDataFolder+PathDelim+'WalletKeys.dat';
       // Creating Node:
       FNode := TNode.Node;
       {$IFDEF TESTNET}
@@ -249,7 +260,7 @@ begin
       Try
         // Check Database
         FNode.Bank.StorageClass := TFileStorage;
-        TFileStorage(FNode.Bank.Storage).DatabaseFolder := TNode.GetPascalCoinDataFolder+PathDelim+'Data';
+        TFileStorage(FNode.Bank.Storage).DatabaseFolder := GetDataFolder+PathDelim+'Data';
         TFileStorage(FNode.Bank.Storage).LowMemoryUsage := FIniFile.ReadBool(CT_INI_SECTION_GLOBAL,CT_INI_IDENT_LOWMEMORY,False);
         // By default daemon will not download checkpoint except if specified on INI file
         TNetData.NetData.MinFutureBlocksToDownloadNewSafebox := FIniFile.ReadInteger(CT_INI_SECTION_GLOBAL,CT_INI_IDENT_MINPENDINGBLOCKSTODOWNLOADCHECKPOINT,0);
@@ -268,7 +279,7 @@ begin
         Try
           Repeat
             Sleep(100);
-          Until Terminated;
+          Until (Terminated) or (Application.Terminated);
         finally
           FreeAndNil(FMinerServer);
         end;
@@ -313,30 +324,26 @@ end;
 
 { TPCDaemon }
 
-procedure TPCDaemon.ThreadStopped(Sender: TObject);
-begin
-  FreeAndNil(FThread);
-end;
-
 function TPCDaemon.Start: Boolean;
 begin
   Result:=inherited Start;
   TLog.NewLog(ltinfo,ClassName,'Daemon Start '+BoolToStr(Result));
   FThread:=TPCDaemonThread.Create;
-  FThread.OnTerminate:=@ThreadStopped;
-  FThread.FreeOnTerminate:=False;
+  FThread.FreeOnTerminate:=True;
   if (Application.HasOption('b','block')) then begin
     FThread.MaxBlockToRead:=StrToInt64Def(Application.GetOptionValue('b','block'),$FFFFFFFF);
     TLog.NewLog(ltinfo,ClassName,'Max block to read: '+IntToStr(FThread.MaxBlockToRead));
   end;
-  FThread.Resume;
+  FThread.Start;
 end;
 
 function TPCDaemon.Stop: Boolean;
 begin
   Result:=inherited Stop;
-  TLog.NewLog(ltinfo,ClassName,'Daemon Stop: '+BoolToStr(Result));
+  TLog.NewLog(ltinfo,ClassName,'Daemon Stop Start');
   FThread.Terminate;
+  FThread.WaitFor;
+  TLog.NewLog(ltinfo,ClassName,'Daemon Stop Finished');
 end;
 
 function TPCDaemon.Pause: Boolean;
@@ -362,8 +369,10 @@ end;
 function TPCDaemon.ShutDown: Boolean;
 begin
   Result:=inherited ShutDown;
-  TLog.NewLog(ltinfo,ClassName,'Daemon Shutdown: '+BoolToStr(Result));
+  TLog.NewLog(ltinfo,ClassName,'Daemon Shutdown Start');
   FThread.Terminate;
+  FThread.WaitFor;
+  TLog.NewLog(ltinfo,ClassName,'Daemon Shutdown Finished');
 end;
 
 function TPCDaemon.Install: Boolean;
@@ -380,40 +389,27 @@ end;
 
 { TPCDaemonMapper }
 
-procedure TPCDaemonMapper.OnPascalCoinInThreadLog(logtype: TLogType;
-  Time: TDateTime; AThreadID: TThreadID; const sender, logtext: String);
-Var s : AnsiString;
-begin
-//  If Not SameText(sender,TPCDaemonThread.ClassName) then exit;
-  If logtype in [lterror,ltinfo] then begin
-    if AThreadID=MainThreadID then s := ' MAIN:' else s:=' TID:';
-    WriteLn(formatDateTime('dd/mm/yyyy hh:nn:ss.zzz',Time)+s+IntToHex(PtrInt(AThreadID),8)+' ['+CT_LogType[Logtype]+'] <'+sender+'> '+logtext);
-  end;
-end;
-
 procedure TPCDaemonMapper.DoOnCreate;
 Var D : TDaemonDef;
 begin
   inherited DoOnCreate;
-  WriteLn('');
-  WriteLn(formatDateTime('dd/mm/yyyy hh:nn:ss.zzz',now)+' Starting PascalCoin server');
   FLog := TLog.Create(Nil);
-  FLog.OnInThreadNewLog:=@OnPascalCoinInThreadLog;
   _FLog := FLog;
   D:=DaemonDefs.Add as TDaemonDef;
-  D.DisplayName:='Pascal Coin Daemon';
+  D.DisplayName:='PascalCoin Daemon';
   D.Name:='PascalCoinDaemon';
   D.DaemonClassName:='TPCDaemon';
+  D.Options:=[doAllowStop];
   D.WinBindings.ServiceType:=stWin32;
 end;
 
 procedure TPCDaemonMapper.DoOnDestroy;
 begin
+  inherited DoOnDestroy;
   If Assigned(FLog) then begin
     FLog.OnInThreadNewLog:=Nil;
     FreeAndNil(FLog);
   end;
-  inherited DoOnDestroy;
 end;
 
 end.

+ 6 - 2
src/pascalcoin_daemon.ini

@@ -40,8 +40,12 @@ RPC_SERVERMINER_B58_PUBKEY=
 RPC_SERVERMINER_MAX_CONNECTIONS=1000
 ;RPC_SERVERMINER_MAX_OPERATIONS_PER_BLOCK : Integer
 ;Max operations included per block
-RPC_SERVERMINER_MAX_OPERATIONS_PER_BLOCK=10000
+RPC_SERVERMINER_MAX_OPERATIONS_PER_BLOCK=
 ;RPC_SERVERMINER_MAX_ZERO_FEE_OPERATIONS : Integer
 ;Max operations without fee that can be included in a block
 ;Note: Operations with fee>0 are processed first (have more priority)
-RPC_SERVERMINER_MAX_ZERO_FEE_OPERATIONS=4000
+RPC_SERVERMINER_MAX_ZERO_FEE_OPERATIONS=
+;DATAFOLDER : String
+;Allow define folder to store data of PascalCoin (Blockchain, Safebox, WalletKeys file, Temporal files ...)
+;If empty will use default folder $HOME/PascalCoin (Each OS will assigna a different $HOME folder, AppData for Windows...)
+DATAFOLDER=

+ 10 - 2
src/pascalcoin_daemon.lpi

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
   <ProjectOptions>
-    <Version Value="10"/>
+    <Version Value="11"/>
     <PathDelim Value="\"/>
     <General>
       <Flags>
@@ -25,10 +25,18 @@
     </PublishOptions>
     <RunParams>
       <local>
-        <FormatVersion Value="1"/>
         <CommandLineParams Value="-r"/>
         <Display Use="True" Value=""/>
       </local>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default">
+          <local>
+            <CommandLineParams Value="-r"/>
+            <Display Use="True" Value=""/>
+          </local>
+        </Mode0>
+      </Modes>
     </RunParams>
     <Units Count="1">
       <Unit0>

+ 19 - 0
src/pascalcoin_daemon.pp

@@ -11,11 +11,30 @@ uses
   Classes, daemonapp,
   UCrypto, upcdaemon;
 
+Type
+
+  { TDaemonMainLoop }
+
+  TDaemonMainLoop = Class
+  public
+    Class procedure DaemonMainLoop;
+  end;
+
+{ TDaemonMainLoop }
+
+class procedure TDaemonMainLoop.DaemonMainLoop;
+begin
+  while not Application.Terminated do begin
+    CheckSynchronize(10);
+  end;
+end;
 
 begin
   Application.Title:='PascalCoin Daemon application';
+  IsConsole:=False;
   RegisterDaemonClass(TPCDaemon);
   RegisterDaemonMapper(TPCDaemonMapper);
+  Application.GUIMainLoop:[email protected];
   TCrypto.InitCrypto;
   Application.Run;
 end.