Skip to content

Commit

Permalink
Merge pull request #23 from PascalCoinDev/master
Browse files Browse the repository at this point in the history
Version 5.3
  • Loading branch information
PascalCoinDev committed Mar 13, 2020
2 parents d6edf45 + 5616943 commit f33df61
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 18 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog

## Build 5.3.0 - 2020-03-12
- Fixed "out of memory" error when downloading Safebox
- Fixed freeze bug on GUI when updating accounts grid
- Minor improvements for testing

## Build 5.2.0 - 2020-02-11
- Mandatory upgrade due fixes some important security bugs
- Fixed CryptoLib4Pascal multithreading bug
Expand Down
7 changes: 6 additions & 1 deletion src/config.inc
Expand Up @@ -57,6 +57,11 @@

// This will allow check safebox names list. Warning: This will slow app
{.$DEFINE Check_Safebox_Names_Consistency}

// This will assume that PoW on old protocols are true and will not check, usefull after enough time to increase validation speed.
// Warning: Use only on versions after enough time since last protocol upgrade and non main-node versions
{.$DEFINE ASSUME_VALID_POW_OLD_PROTOCOLS}


{ ********************************************************************
Don't touch more code, it will addapt based on your preferences
Expand All @@ -66,7 +71,7 @@
ERROR: You must select ONLY ONE option: PRODUCTION or TESTNET
{$ENDIF}{$ELSE}{$DEFINE PRODUCTION}{$ENDIF}

{$IF (not Defined(Use_OpenSSL)) or (not Defined(Use_CryptoLib4Pascal))}
{$IF (not Defined(Use_OpenSSL)) and (not Defined(Use_CryptoLib4Pascal))}
{$DEFINE Use_OpenSSL}
{$UNDEF Use_CryptoLib4Pascal}
{$ENDIF}
Expand Down
15 changes: 15 additions & 0 deletions src/core/UAccounts.pas
Expand Up @@ -828,6 +828,10 @@ class function TPascalCoinProtocol.AllowUseHardcodedRandomHashTable(
LInternalHardcodedSha256 : TRawBytes;
begin
Result := False;
{$IFDEF ASSUME_VALID_POW_OLD_PROTOCOLS}
// In this case will not use Hardcoded RandomHash Table
Exit;
{$ENDIF}
If Not FileExists(AHardcodedFileName) then begin
TLog.NewLog(ltdebug,ClassName,Format('Hardcoded RandomHash from file not found:%s',
[AHardcodedFileName] ));
Expand Down Expand Up @@ -3383,7 +3387,11 @@ function TPCSafeBox.LoadSafeBoxFromStream(Stream : TStream; checkAll : Boolean;
// For TESTNET increase speed purposes, will only check latests blocks
if ((iblock + (CT_BankToDiskEveryNBlocks * 10)) >= sbHeader.blockscount) then begin
{$ENDIF}
{$IFDEF ASSUME_VALID_POW_OLD_PROTOCOLS}
LAddToMultiThreadOperationsBlockValidator := (LUseMultiThreadOperationsBlockValidator) and (LBlock.blockchainInfo.protocol_version>=CT_PROTOCOL_5) and (Assigned(LPCOperationsBlockValidator));
{$ELSE}
LAddToMultiThreadOperationsBlockValidator := (LUseMultiThreadOperationsBlockValidator) and (LBlock.blockchainInfo.protocol_version>=CT_PROTOCOL_4) and (Assigned(LPCOperationsBlockValidator));
{$ENDIF}
If not IsValidNewOperationsBlock(LBlock.blockchainInfo,False,Not LAddToMultiThreadOperationsBlockValidator,aux_errors) then begin
errors := errors + ' > ' + aux_errors;
exit;
Expand Down Expand Up @@ -4121,11 +4129,18 @@ class function TPCSafeBox.IsValidOperationBlock(const newOperationBlock: TOperat
end;
// proof_of_work:
{$IFnDEF TESTING_NO_POW_CHECK}
{$IFDEF ASSUME_VALID_POW_OLD_PROTOCOLS}
if (newOperationBlock.protocol_version>=CT_PROTOCOL_5) then begin
{$ENDIF}
TPascalCoinProtocol.CalcProofOfWork(newOperationBlock,pow);
if (Not TBaseType.Equals(pow,newOperationBlock.proof_of_work)) then begin
errors := 'Proof of work is bad calculated '+TCrypto.ToHexaString(newOperationBlock.proof_of_work)+' <> Good: '+TCrypto.ToHexaString(pow);
exit;
end;
{$IFDEF ASSUME_VALID_POW_OLD_PROTOCOLS}
end;
{$ENDIF}

{$ENDIF}
Result := true;
end;
Expand Down
2 changes: 1 addition & 1 deletion src/core/UConst.pas
Expand Up @@ -195,7 +195,7 @@ interface
CT_OpSubtype_Data_Signer = 103;
CT_OpSubtype_Data_Receiver = 104;

CT_ClientAppVersion : String = {$IFDEF PRODUCTION}'5.2'{$ELSE}{$IFDEF TESTNET}'TESTNET 5.2'{$ELSE}{$ENDIF}{$ENDIF};
CT_ClientAppVersion : String = {$IFDEF PRODUCTION}'5.3'{$ELSE}{$IFDEF TESTNET}'TESTNET 5.3'{$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};
Expand Down
26 changes: 19 additions & 7 deletions src/core/UNetProtocol.pas
Expand Up @@ -509,7 +509,8 @@ implementation

uses
UConst, ULog, UNode, UTime, UPCEncryption, UChunk,
UPCOperationsBlockValidator, UPCOperationsSignatureValidator;
UPCOperationsBlockValidator, UPCOperationsSignatureValidator,
UPCTemporalFileStream;

Const
CT_NetTransferType : Array[TNetTransferType] of String = ('Unknown','Request','Response','Autosend');
Expand Down Expand Up @@ -1855,8 +1856,10 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
safeBoxHeader : TPCSafeBoxHeader;
errors : String;
i : Integer;
LFirstSafebox : Boolean;
Begin
Result := False;
LFirstSafebox := TNode.Node.Bank.SafeBox.BlocksCount = 0;
safeboxStream.Size:=0;
safeboxStream.Position:=0;
// Will try to download penultimate saved safebox
Expand All @@ -1876,7 +1879,8 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
for i:=0 to ((_blockcount-1) DIV 10000) do begin // Bug v3.0.1 and minors
FNewBlockChainFromClientStatus := Format('Receiving new safebox with %d blocks (step %d/%d) from %s',
[_blockcount,i+1,((_blockcount-1) DIV 10000)+1,Connection.ClientRemoteAddr]);
receiveChunk := TMemoryStream.Create;
if LFirstSafebox then receiveChunk := TMemoryStream.Create
else receiveChunk := TPCTemporalFileStream.Create('CHUNK_'+IntToStr(i)+'_');
if (Not DownloadSafeBoxChunk(_blockcount,safebox_last_operation_block.initial_safe_box_hash,(i*10000),((i+1)*10000)-1,receiveChunk,safeBoxHeader,errors)) then begin
receiveChunk.Free;
TLog.NewLog(ltError,CT_LogSender,errors);
Expand All @@ -1886,16 +1890,21 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
chunks[High(chunks)].safeBoxHeader := safeBoxHeader;
chunks[High(chunks)].chunkStream := receiveChunk;
end;
TLog.NewLog(ltDebug,CT_LogSender,Format('Concatening %d chunks',[Length(chunks)]));
// Will concat safeboxs:
chunk1 := TMemoryStream.Create;
chunk1 := TPCTemporalFileStream.Create('CONCAT_CHUNKS_');
try
if (length(chunks)=1) then begin
safeboxStream.CopyFrom(chunks[0].chunkStream,0);
end else begin
chunk1.CopyFrom(chunks[0].chunkStream,0);
end;
for i:=1 to high(chunks) do begin
FNewBlockChainFromClientStatus := Format('Concatening downloaded safebox (step %d/%d) from %s',
[i,High(chunks),Connection.ClientRemoteAddr]);
TLog.NewLog(ltDebug,CT_LogSender,Format('Concatening chunk %d/%d',[i,High(chunks)]));
safeboxStream.Size:=0;
safeboxStream.Position := 0; // Added caused by FPC 3.0.4 bug that does not update position auto when setting size=0 at a TFileStream
chunk1.Position:=0;
chunks[i].chunkStream.Position:=0;
If Not TPCSafeBox.ConcatSafeBoxStream(chunk1,chunks[i].chunkStream,safeboxStream,errors) then begin
Expand All @@ -1905,6 +1914,7 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
chunk1.Size := 0;
chunk1.CopyFrom(safeboxStream,0);
end;
FNewBlockChainFromClientStatus := Format('Downloaded safebox with %d chunks from %s',[High(chunks),Connection.ClientRemoteAddr]);
finally
chunk1.Free;
end;
Expand All @@ -1924,7 +1934,7 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
request_id : Cardinal;
Begin
Result := False;
receiveData := TMemoryStream.Create;
receiveData := TPCTemporalFileStream.Create('SAFEBOX_');
try
if Not DownloadSafeboxStream(receiveData,op) then Exit;
// Now receiveData is the ALL safebox
Expand Down Expand Up @@ -1953,7 +1963,7 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
end;

procedure DownloadNewBlockchain(start_block : Int64; IsMyBlockChainOk : Boolean);
var safeboxStream : TMemoryStream;
var safeboxStream : TStream;
newTmpBank : TPCBank;
safebox_last_operation_block : TOperationBlock;
opComp : TPCOperationsComp;
Expand All @@ -1971,7 +1981,7 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
if (download_new_safebox) then begin
TLog.NewLog(ltinfo,ClassName,Format('Will download new safebox. My blocks:%d Remote blocks:%d Equal Block:%d (MaxFutureBlocksToDownloadNewSafebox:%d)',[TNode.Node.Bank.BlocksCount,Connection.RemoteOperationBlock.block+1,start_block-1,MinFutureBlocksToDownloadNewSafebox]));
// Will try to download safebox
safeboxStream := TMemoryStream.Create;
safeboxStream := TPCTemporalFileStream.Create('NEW_SAFEBOX_');
Try
if Not DownloadSafeboxStream(safeboxStream,safebox_last_operation_block) then Exit;
safeboxStream.Position := 0;
Expand Down Expand Up @@ -2046,6 +2056,7 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
var rid : Cardinal;
my_op, client_op : TOperationBlock;
errors : String;
LTickCount : TTickCount;
begin
// Protection against discovering servers...
if FIsDiscoveringServers then begin
Expand All @@ -2056,6 +2067,7 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;

if (Not Assigned(TNode.Node.Bank.StorageClass)) then Exit;
//
LTickCount := TPlatform.GetTickCount;
if Not FLockGettingNewBlockChainFromClient.TryEnter then begin
TLog.NewLog(ltdebug,CT_LogSender,'Is getting new blockchain from client...');
exit;
Expand Down Expand Up @@ -2116,8 +2128,8 @@ procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection;
DownloadNewBlockchain(my_op.block+1,True);
end;
Finally
TLog.NewLog(ltdebug,CT_LogSender,'Finalizing');
FLockGettingNewBlockChainFromClient.Release;
TLog.NewLog(ltdebug,CT_LogSender,Format('Finalizing process in %d milis',[TPlatform.GetElapsedMilliseconds(LTickCount)]));
end;
end;

Expand Down
81 changes: 81 additions & 0 deletions src/core/UPCTemporalFileStream.pas
@@ -0,0 +1,81 @@
unit UPCTemporalFileStream;

{ Copyright (c) 2020 by Albert Molina
Distributed under the MIT software license, see the accompanying file LICENSE
or visit http://www.opensource.org/licenses/mit-license.php.
This unit is a part of the PascalCoin Project, an infinitely scalable
cryptocurrency. Find us here:
Web: https://www.pascalcoin.org
Source: https://github.com/PascalCoin/PascalCoin
If you like it, consider a donation using Bitcoin:
16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
THIS LICENSE HEADER MUST NOT BE REMOVED.
}

{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}

interface

uses
Classes, {$IFnDEF FPC}Windows,{$ENDIF} SysUtils;
{$I ./../config.inc}

Type
{ TPCTemporalFileStream }

TPCTemporalFileStream = Class(TFileStream)
private
FTemporalFileName : String;
protected
public
Constructor Create(const AInitialName : String); reintroduce;
Destructor Destroy; override;
End;

implementation

Uses ULog, UNode;

{ TPCTemporalFileStream }

constructor TPCTemporalFileStream.Create(const AInitialName : String);
var LFolder, LTime, LFileName : String;
i : Integer;
begin
FTemporalFileName:= '';
LFolder := TNode.GetPascalCoinDataFolder+PathDelim+'Temp';
ForceDirectories(LFolder);
i := 0;
repeat
LTime := FormatDateTime('yyyymmddhhnnsszzz',Now);
if i>0 then begin
Sleep(1);
LFileName := LFolder + PathDelim + AInitialName + LTime +'_'+ IntToStr(i) + '.tmp';
end else begin
LFileName := LFolder + PathDelim + AInitialName + LTime + '.tmp';
end;
inc(i);
until (Not (FileExists(LFileName)) or (i>5000));
TLog.NewLog(ltdebug,ClassName,Format('Creating a new Temporal file Stream: %s',[LFileName]));
inherited Create(LFileName,fmCreate+fmShareDenyWrite);
FTemporalFileName:=LFileName;
end;

destructor TPCTemporalFileStream.Destroy;
var LSize : Integer;
begin
LSize := Size;
inherited Destroy;
if FTemporalFileName<>'' then begin
TLog.NewLog(ltdebug,ClassName,Format('Deleting a Temporal file Stream (%d bytes): %s',[LSize, FTemporalFileName]));
DeleteFile(FTemporalFileName);
end;
end;

end.
25 changes: 16 additions & 9 deletions src/gui-classic/UGridUtils.pas
Expand Up @@ -97,7 +97,7 @@ interface
procedure SetNode(const Value: TNode);
function GetNode: TNode;
procedure SetAllowMultiSelect(const Value: Boolean);
procedure TerminateAccountGridUpdateThread;
procedure TerminateAccountGridUpdateThread(AWaitUntilTerminated : Boolean);
procedure SetAccountsGridFilter(const Value: TAccountsGridFilter);
function GetAccountsCount: Integer;
procedure SetAccountsGridDatasource(const Value: TAccountsGridDatasource);
Expand Down Expand Up @@ -343,8 +343,9 @@ procedure TAccountsGridUpdateThread.BCExecute;
end;
Finally
FisProcessing := False;
if Not Terminated then
if Not Terminated then begin
Synchronize(SynchronizedOnTerminated);
end;
End;
end;

Expand Down Expand Up @@ -447,7 +448,7 @@ constructor TAccountsGrid.Create(AOwner: TComponent);

destructor TAccountsGrid.Destroy;
begin
TerminateAccountGridUpdateThread;
TerminateAccountGridUpdateThread(True);
FNodeNotifyEvents.Free;
FAccountsList.Free;
inherited;
Expand Down Expand Up @@ -853,12 +854,18 @@ procedure TAccountsGrid.SetNode(const Value: TNode);
UpdateData;
end;

procedure TAccountsGrid.TerminateAccountGridUpdateThread;
procedure TAccountsGrid.TerminateAccountGridUpdateThread(AWaitUntilTerminated : Boolean);
var LTmp : TAccountsGridUpdateThread;
begin
if Assigned(FAccountsGridUpdateThread) then begin
FAccountsGridUpdateThread.Terminate;
FAccountsGridUpdateThread.WaitFor;
FreeAndNil(FAccountsGridUpdateThread);
LTmp := FAccountsGridUpdateThread;
FAccountsGridUpdateThread := Nil;
if Assigned(Ltmp) then begin
if Not AWaitUntilTerminated then LTmp.FreeOnTerminate := True;
LTmp.Terminate;
if AWaitUntilTerminated then begin
LTmp.WaitFor;
FreeAndNil(LTmp);
end;
end;
end;

Expand Down Expand Up @@ -892,7 +899,7 @@ procedure TAccountsGrid.UpdateData;
if Assigned(Node) then begin
case FAccountsGridDatasource of
acds_NodeFiltered: begin
TerminateAccountGridUpdateThread;
TerminateAccountGridUpdateThread(False);
FAccountsBalance := 0;
FAccountsGridUpdateThread := TAccountsGridUpdateThread.Create(Self,AccountsGridFilter);
end;
Expand Down

0 comments on commit f33df61

Please sign in to comment.