Browse Source

Build 2.1.2

PascalCoin 8 years ago
parent
commit
68ac8ba519

+ 10 - 0
README.md

@@ -34,6 +34,16 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 ## History:  
 
+### Build 2.1.2.0 - 2017-07-27
+- No more blockchain in installer = TRUE DELETABLE BLOCKCHAIN (Safebox will be automatically downloaded by client from network)
+- Fixed storage bug when downloading a new safebox
+- Safebox will be downloaded in small chunks (aprox 2mb per chunk)
+- Read safebox file improvements (quick start)
+
+### Build 2.1.1.0 - 2017-07-16
+- Fixed installer bug: In last Windows installer a malformed safebox file was included. This build is only to provide a good safebox file with the installer
+- No important changes in exe/binary file 
+
 ### Build 2.1.0.0 - 2017-07-14
 - Fixed bug of slow mass transactions from a single account due to incorrect sending order
 - Fixed memory leak on GetSafeBox request call

+ 10 - 0
README.txt

@@ -34,6 +34,16 @@ Also, consider a donation at PascalCoin development account: "0-10"
 
 ## History:  
 
+### Build 2.1.2.0 - 2017-07-27
+- No more blockchain in installer = TRUE DELETABLE BLOCKCHAIN (Safebox will be automatically downloaded by client from network)
+- Fixed storage bug when downloading a new safebox
+- Safebox will be downloaded in small chunks (aprox 2mb per chunk)
+- Read safebox file improvements (quick start)
+
+### Build 2.1.1.0 - 2017-07-16
+- Fixed installer bug: In last Windows installer a malformed safebox file was included. This build is only to provide a good safebox file with the installer
+- No important changes in exe/binary file 
+
 ### Build 2.1.0.0 - 2017-07-14
 - Fixed bug of slow mass transactions from a single account due to incorrect sending order
 - Fixed memory leak on GetSafeBox request call

+ 2 - 14
Units/Forms/UFRMWallet.dfm

@@ -368,16 +368,12 @@ object FRMWallet: TFRMWallet
     Top = 91
     Width = 849
     Height = 432
-    ActivePage = tsMyAccounts
+    ActivePage = tsNodeStats
     Align = alClient
     TabOrder = 2
     OnChange = PageControlChange
     object tsMyAccounts: TTabSheet
       Caption = 'Accounts Explorer'
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
       object Splitter1: TSplitter
         Left = 380
         Top = 66
@@ -614,10 +610,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
@@ -1012,10 +1004,6 @@ object FRMWallet: TFRMWallet
     object tsNodeStats: TTabSheet
       Caption = 'Node Stats'
       ImageIndex = 3
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
       DesignSize = (
         841
         404)
@@ -1324,7 +1312,7 @@ object FRMWallet: TFRMWallet
     Left = 105
     Top = 180
     Bitmap = {
-      494C010102000800100210003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      494C010102000800140210003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
       0000000000003600000028000000400000003000000001002000000000000030
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000002A292929D60B0B0BF4111111EE0000006B000000000000

+ 4 - 4
Units/Forms/UFRMWallet.pas

@@ -556,14 +556,14 @@ begin
               sLastConnTime := '';
             end;
             if NC is TNetServerClient then begin
-              sNSC.Add(Format('Client: IP:%s Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
-                [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
+              sNSC.Add(Format('Client: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
+                [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
             end else begin
               if NC.IsMyselfServer then sNSC.Add(Format('MySelf IP:%s Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
                 [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]))
               else begin
-                sRS.Add(Format('Remote Server: IP:%s Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
-                [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
+                sRS.Add(Format('Remote Server: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
+                [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
               end;
             end;
           end else begin

+ 8 - 6
Units/PascalCoin/UAccounts.pas

@@ -1614,18 +1614,21 @@ end;
 
 function TPCSafeBox.DoUpgradeToProtocol2: Boolean;
 var block_number : Cardinal;
+  aux : TRawBytes;
 begin
   // Upgrade process to protocol 2
   Result := false;
   If Not CanUpgradeToProtocol2 then exit;
   // Recalc all BlockAccounts block_hash value
-  TLog.NewLog(ltInfo,ClassName,'Start Upgrade to protocol 2 - Old Safeboxhash:'+TCrypto.ToHexaString(FSafeBoxHash));
+  aux := CalcSafeBoxHash;
+  TLog.NewLog(ltInfo,ClassName,'Start Upgrade to protocol 2 - Old Safeboxhash:'+TCrypto.ToHexaString(FSafeBoxHash)+' calculated: '+TCrypto.ToHexaString(aux)+' Blocks: '+IntToStr(BlocksCount));
   FBufferBlocksHash:='';
   for block_number := 0 to BlocksCount - 1 do begin
     {$IFDEF uselowmem}
     TBaseType.To32Bytes(CalcBlockHash( Block(block_number), True),PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash);
     FBufferBlocksHash := FBufferBlocksHash+TBaseType.ToRawBytes(PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash);
     {$ELSE}
+    PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash := CalcBlockHash( Block(block_number), True);
     FBufferBlocksHash := FBufferBlocksHash+PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash;
     {$ENDIF}
   end;
@@ -2076,7 +2079,6 @@ Var destStartBlock, destEndBlock, nBlock : Cardinal;
   c : Cardinal;
   destOffsets : TCardinalsArray;
   i : Integer;
-  source1SBH, source2SBH : TRawBytes;
   s1Header,s2Header : TPCSafeBoxHeader;
 begin
   Result := False; errors := '';
@@ -2092,10 +2094,10 @@ begin
       exit;
     end;
     // Check SBH and blockcount
-    if (source1SBH<>source2SBH) or (s1Header.blocksCount<>s2Header.blocksCount) Or (s1Header.protocol<>s2Header.protocol) then begin
+    if (s1Header.safeBoxHash<>s2Header.safeBoxHash) or (s1Header.blocksCount<>s2Header.blocksCount) Or (s1Header.protocol<>s2Header.protocol) then begin
       errors := Format('Source1 and Source2 have diff safebox. Source 1 %d %s (protocol %d) Source 2 %d %s (protocol %d)',
-       [s1Header.blocksCount,TCrypto.ToHexaString(source1SBH),s1Header.protocol,
-        s2Header.blocksCount,TCrypto.ToHexaString(source2SBH),s2Header.protocol]);
+       [s1Header.blocksCount,TCrypto.ToHexaString(s1Header.safeBoxHash),s1Header.protocol,
+        s2Header.blocksCount,TCrypto.ToHexaString(s2Header.safeBoxHash),s2Header.protocol]);
       exit;
     end;
     // Save dest heaer
@@ -2129,7 +2131,7 @@ begin
     end;
     // Save SafeBoxHash at the end
     Dest.Seek(0,soFromEnd);
-    TStreamOp.WriteAnsiString(Dest,source1SBH);
+    TStreamOp.WriteAnsiString(Dest,s1Header.safeBoxHash);
     Result := true;
   Finally
     Source1.Position:=source1InitialPos;

+ 1 - 1
Units/PascalCoin/UBlockChain.pas

@@ -703,7 +703,7 @@ begin
       If Assigned(auxSB) then begin
         SafeBox.CopyFrom(auxSB);
       end else begin
-        Result := SafeBox.LoadSafeBoxFromStream(Stream,true,LastReadBlock,errors);
+        Result := SafeBox.LoadSafeBoxFromStream(Stream,false,LastReadBlock,errors);
       end;
       If Not Result then exit;
       If SafeBox.BlocksCount>0 then FLastOperationBlock := SafeBox.Block(SafeBox.BlocksCount-1).blockchainInfo

+ 2 - 2
Units/PascalCoin/UConst.pas

@@ -97,7 +97,7 @@ Const
 
   CT_MagicNetIdentification = {$IFDEF PRODUCTION}$0A043580{$ELSE}$0A04FFFF{$ENDIF}; // Unix timestamp 168048000 ... It's Albert birthdate!
 
-  CT_NetProtocol_Version: Word = $0005; // Version 1.5.4 only allows net protocol version 5  (introduced on 1.5.0)
+  CT_NetProtocol_Version: Word = $0006; // Version 2.1.2 only allows net protocol 6 (Introduced on 2.0.0)
   // IMPORTANT NOTE!!!
   // NetProtocol_Available MUST BE always >= NetProtocol_version
   CT_NetProtocol_Available: Word = $0006;  // Remember, >= NetProtocol_version !!!
@@ -135,7 +135,7 @@ Const
   CT_OpSubtype_ChangeKeySigned            = 71;
   CT_OpSubtype_ChangeAccountInfo          = 81;
 
-  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'2.1.0'{$ELSE}{$IFDEF TESTNET}'TESTNET 2.1.0'{$ELSE}{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'2.1.2'{$ELSE}{$IFDEF TESTNET}'TESTNET 2.1.2'{$ELSE}{$ENDIF}{$ENDIF};
 
   CT_Discover_IPs =  'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us';
 

+ 1 - 1
Units/PascalCoin/UFileStorage.pas

@@ -829,7 +829,7 @@ begin
     if not Result then begin
       raise Exception.Create('Cannot found header of previous block '+inttostr(Operations.OperationBlock.block));
     end;
-    If ((_Header.BlockNumber-BlockHeaderFirstBlock) MOD CT_GroupBlockSize)=0 then begin  //XXXXXXXXXX
+    If ((_Header.BlockNumber-BlockHeaderFirstBlock) MOD CT_GroupBlockSize)=0 then begin
       _Header.StreamBlockRelStartPos := 0;
     end else begin
       _Header.StreamBlockRelStartPos := _HeaderPrevious.StreamBlockRelStartPos + _HeaderPrevious.BlockSize;

+ 116 - 47
Units/PascalCoin/UNetProtocol.pas

@@ -335,6 +335,7 @@ Type
     Property Client : TNetTcpIpClient read GetClient;
     Function ClientRemoteAddr : AnsiString;
     property TimestampDiff : Integer read FTimestampDiff;
+    property RemoteOperationBlock : TOperationBlock read FRemoteOperationBlock;
     //
     Property NetProtocolVersion : TNetProtocolVersion read FNetProtocolVersion;
     //
@@ -1200,75 +1201,143 @@ Const CT_LogSender = 'GetNewBlockChainFromClient';
     end;
   End;
 
-  Function DownloadSafeBox(IsMyBlockchainValid : Boolean) : Boolean;
-  Var c,_blockcount,request_id : Cardinal;
-    SendData, ReceiveData : TStream;
-    op : TOperationBlock;
+  Function DownloadSafeBoxChunk(safebox_blockscount : Cardinal; Const sbh : TRawBytes; from_block, to_block : Cardinal; receivedDataUnzipped : TStream;
+    var safeBoxHeader : TPCSafeBoxHeader; var errors : AnsiString) : Boolean;
+  Var sendData,receiveData : TStream;
     headerdata : TNetHeaderData;
-    safeBoxHeader : TPCSafeBoxHeader;
-    errors : AnsiString;
+    request_id : Cardinal;
+    c : Cardinal;
   Begin
     Result := False;
-    // Will try to download penultimate saved safebox
-    _blockcount := ((Connection.FRemoteOperationBlock.block DIV CT_BankToDiskEveryNBlocks)-1) * CT_BankToDiskEveryNBlocks;
-    SendData := TMemoryStream.Create;
-    ReceiveData := TMemoryStream.Create;
+    sendData := TMemoryStream.Create;
+    receiveData := TMemoryStream.Create;
     try
-      If not Do_GetOperationBlock(_blockcount,5000,op) then begin
-        Connection.DisconnectInvalidClient(false,Format('Cannot obtain operation block %d for downloading safebox',[_blockcount]));
-        exit;
+      sendData.Write(safebox_blockscount,SizeOf(safebox_blockscount)); // 4 bytes for blockcount
+      TStreamOp.WriteAnsiString(SendData,sbh);
+      sendData.Write(from_block,SizeOf(from_block));
+      c := to_block;
+      if (c>=safebox_blockscount) then c := safebox_blockscount-1;
+      sendData.Write(c,SizeOf(c));
+      if (from_block>c) or (c>=safebox_blockscount) then begin
+        errors := 'ERROR DEV 20170727-1';
+        Exit;
       end;
-      // Obtain safebox
-      SendData.Write(_blockcount,SizeOf(_blockcount)); // 4 bytes for blockcount
-      TStreamOp.WriteAnsiString(SendData,op.initial_safe_box_hash);
-      c := 0;
-      SendData.Write(c,SizeOf(c));
-      c := _blockcount-1;
-      SendData.Write(c,SizeOf(c));
-      TLog.NewLog(ltdebug,CT_LogSender,Format('Sending %s from block %d to %d (Total: %d)',
-        [TNetData.OperationToText(CT_NetOp_GetSafeBox),0,_blockcount-1,_blockcount]));
+      TLog.NewLog(ltDebug,CT_LogSender,Format('Call to GetSafeBox from blocks %d to %d of %d',[from_block,c,safebox_blockscount]));
       request_id := TNetData.NetData.NewRequestId;
-      if Connection.DoSendAndWaitForResponse(CT_NetOp_GetSafeBox,request_id,SendData,ReceiveData,60000,headerdata) then begin
+      if Connection.DoSendAndWaitForResponse(CT_NetOp_GetSafeBox,request_id,sendData,receiveData,30000,headerdata) then begin
         if HeaderData.is_error then exit;
-        SendData.Size:=0;
-        If Not TPCChunk.LoadSafeBoxFromChunk(ReceiveData,SendData,safeBoxHeader,errors) then begin
+        receivedDataUnzipped.Size:=0;
+        If Not TPCChunk.LoadSafeBoxFromChunk(receiveData,receivedDataUnzipped,safeBoxHeader,errors) then begin
+          Connection.DisconnectInvalidClient(false,'Invalid received chunk: '+errors);
+          exit;
+        end;
+        If (safeBoxHeader.safeBoxHash<>sbh) or (safeBoxHeader.startBlock<>from_block) or (safeBoxHeader.endBlock<>c) or
+          (safeBoxHeader.blocksCount<>safebox_blockscount) or (safeBoxHeader.protocol<CT_PROTOCOL_2) or
+          (safeBoxHeader.protocol>CT_BlockChain_Protocol_Available) then begin
+          errors := Format('Invalid received chunk based on call: Blockscount:%d %d - from:%d %d to %d %d - SafeboxHash:%s %s',
+              [safeBoxHeader.blocksCount,safebox_blockscount,safeBoxHeader.startBlock,from_block,safeBoxHeader.endBlock,c,
+               TCrypto.ToHexaString(safeBoxHeader.safeBoxHash),TCrypto.ToHexaString(sbh)]);
           Connection.DisconnectInvalidClient(false,'Invalid received chunk: '+errors);
           exit;
         end;
-        TNode.Node.DisableNewBlocks;
+        Result := True;
+      end else errors := 'No response on DownloadSafeBoxChunk';
+    finally
+      receiveData.Free;
+      SendData.Free;
+    end;
+  end;
+
+  Type TSafeBoxChunkData = Record
+    safeBoxHeader : TPCSafeBoxHeader;
+    chunkStream : TStream;
+  end;
+
+  Function DownloadSafeBox(IsMyBlockchainValid : Boolean) : Boolean;
+  Var _blockcount,request_id : Cardinal;
+    receiveData, receiveChunk, chunk1 : TStream;
+    op : TOperationBlock;
+    safeBoxHeader : TPCSafeBoxHeader;
+    errors : AnsiString;
+    chunks : Array of TSafeBoxChunkData;
+    i : Integer;
+  Begin
+    Result := False;
+    // Will try to download penultimate saved safebox
+    _blockcount := ((Connection.FRemoteOperationBlock.block DIV CT_BankToDiskEveryNBlocks)-1) * CT_BankToDiskEveryNBlocks;
+    If not Do_GetOperationBlock(_blockcount,5000,op) then begin
+      Connection.DisconnectInvalidClient(false,Format('Cannot obtain operation block %d for downloading safebox',[_blockcount]));
+      exit;
+    end;
+    receiveData := TMemoryStream.Create;
+    try
+      SetLength(chunks,0);
+      try
+        // Will obtain chunks of 10000 blocks each
+        for i:=0 to _blockcount DIV 10000 do begin
+          receiveChunk := TMemoryStream.Create;
+          if (Not DownloadSafeBoxChunk(_blockcount,op.initial_safe_box_hash,(i*10000),((i+1)*10000)-1,receiveChunk,safeBoxHeader,errors)) then begin
+            receiveChunk.Free;
+            TLog.NewLog(ltError,CT_LogSender,errors);
+            Exit;
+          end;
+          SetLength(chunks,length(chunks)+1);
+          chunks[High(chunks)].safeBoxHeader := safeBoxHeader;
+          chunks[High(chunks)].chunkStream := receiveChunk;
+        end;
+        // Will concat safeboxs:
+        chunk1 := TMemoryStream.Create;
         try
-          TNode.Node.Bank.SafeBox.StartThreadSafe;
-          try
-            SendData.Position:=0;
-            If TNode.Node.Bank.LoadBankFromStream(SendData,True,errors) then begin
-              TLog.NewLog(ltInfo,ClassName,'Received new safebox!');
-              If Not IsMyBlockchainValid then begin
-                TNode.Node.Bank.Storage.EraseStorage;
-              end;
-              Connection.Send_GetBlocks(TNode.Node.Bank.BlocksCount,100,request_id);
-              Result := true;
-            end else begin
-              Connection.DisconnectInvalidClient(false,'Cannot load from stream! '+errors);
+          chunk1.CopyFrom(chunks[0].chunkStream,0);
+          for i:=1 to high(chunks) do begin
+            receiveData.Size:=0;
+            chunk1.Position:=0;
+            chunks[i].chunkStream.Position:=0;
+            If Not TPCSafeBox.ConcatSafeBoxStream(chunk1,chunks[i].chunkStream,receiveData,errors) then begin
+              TLog.NewLog(ltError,CT_LogSender,errors);
               exit;
             end;
-          finally
-            TNode.Node.Bank.SafeBox.EndThreadSave;
+            chunk1.Size := 0;
+            chunk1.CopyFrom(receiveData,0);
           end;
         finally
-          TNode.Node.EnableNewBlocks;
+          chunk1.Free;
         end;
-      end else begin
-        TLog.NewLog(lterror,CT_LogSender,Format('No received response for %s',[TNetData.OperationToText(CT_NetOp_GetSafeBox)]));
+      finally
+        for i:=0 to high(chunks) do begin
+          chunks[i].chunkStream.Free;
+        end;
+        SetLength(chunks,0);
+      end;
+      // Now receiveData is the ALL safebox
+      TNode.Node.DisableNewBlocks;
+      try
+        TNode.Node.Bank.SafeBox.StartThreadSafe;
+        try
+          receiveData.Position:=0;
+          If TNode.Node.Bank.LoadBankFromStream(receiveData,True,errors) then begin
+            TLog.NewLog(ltInfo,ClassName,'Received new safebox!');
+            If Not IsMyBlockchainValid then begin
+              TNode.Node.Bank.Storage.EraseStorage;
+            end;
+            Connection.Send_GetBlocks(TNode.Node.Bank.BlocksCount,100,request_id);
+            Result := true;
+          end else begin
+            Connection.DisconnectInvalidClient(false,'Cannot load from stream! '+errors);
+            exit;
+          end;
+        finally
+          TNode.Node.Bank.SafeBox.EndThreadSave;
+        end;
+      finally
+        TNode.Node.EnableNewBlocks;
       end;
     finally
-      SendData.Free;
-      ReceiveData.free;
+      receiveData.Free;
     end;
   end;
 
 var rid : Cardinal;
-  bufferdata : TMemoryStream;
-  headerdata : TNetHeaderData;
   my_op, client_op : TOperationBlock;
 begin
   // Protection against discovering servers...