Browse Source

check operations block

Main changes are the separation of IsValidNewOperationsBlock adding a
IsValidOperationBlock in order to easily check basic info of
TOperationBlock
Also added changes to don't use UCommon unit
PascalCoin 7 years ago
parent
commit
aa32a36e2c
1 changed files with 64 additions and 42 deletions
  1. 64 42
      src/core/UAccounts.pas

+ 64 - 42
src/core/UAccounts.pas

@@ -20,7 +20,7 @@ unit UAccounts;
 interface
 
 uses
-  Classes, UConst, UCrypto, SyncObjs, UThread, UBaseTypes, UCommon;
+  Classes, UConst, UCrypto, SyncObjs, UThread, UBaseTypes;
 {$I config.inc}
 
 Type
@@ -189,6 +189,7 @@ Type
     FAutoAddAll : Boolean;
     FAccountList : TPCSafeBox;
     FOrderedAccountKeysList : TList; // An ordered list of pointers to quickly find account keys in account list
+    Function Find(Const AccountKey: TAccountKey; var Index: Integer): Boolean;
     function GetAccountKeyList(index: Integer): TOrderedCardinalList;
     function GetAccountKey(index: Integer): TAccountKey;
   protected
@@ -200,7 +201,6 @@ Type
     Procedure RemoveAccountKey(Const AccountKey : TAccountKey);
     Procedure AddAccounts(Const AccountKey : TAccountKey; const accounts : Array of Cardinal);
     Procedure RemoveAccounts(Const AccountKey : TAccountKey; const accounts : Array of Cardinal);
-    Function Find(Const AccountKey: TAccountKey; var Index: Integer): Boolean;
     Function IndexOfAccountKey(Const AccountKey : TAccountKey) : Integer;
     Property AccountKeyList[index : Integer] : TOrderedCardinalList read GetAccountKeyList;
     Property AccountKey[index : Integer] : TAccountKey read GetAccountKey;
@@ -271,6 +271,7 @@ Type
     class function ValidAccountName(const new_name : TRawBytes; var errors : AnsiString) : Boolean;
 
     Function IsValidNewOperationsBlock(Const newOperationBlock : TOperationBlock; checkSafeBoxHash : Boolean; var errors : AnsiString) : Boolean;
+    class Function IsValidOperationBlock(Const newOperationBlock : TOperationBlock; var errors : AnsiString) : Boolean;
     Function GetActualTargetHash(UseProtocolV2 : Boolean): TRawBytes;
     Function GetActualCompactTargetHash(UseProtocolV2 : Boolean): Cardinal;
     Function FindAccountByName(aName : AnsiString) : Integer;
@@ -368,7 +369,7 @@ Const
 implementation
 
 uses
-  SysUtils, ULog, UOpenSSLdef, UOpenSSL, UAccountKeyStorage, Math;
+  SysUtils, ULog, UOpenSSLdef, UOpenSSL, UAccountKeyStorage, math;
 
 { TPascalCoinProtocol }
 
@@ -922,7 +923,7 @@ end;
 
 class function TAccountComp.FormatMoney(Money: Int64): AnsiString;
 begin
-  Result := FormatFloat('#,###0.0000', (Money/10000));
+  Result := FormatFloat('#,###0.0000',(Money/10000));
 end;
 
 class function TAccountComp.FormatMoneyDecimal(Money : Int64) : Single;
@@ -1578,13 +1579,13 @@ procedure TPCSafeBox.CheckMemory;
     in order to free memory not used. Tested with FPC 3.0 }
 {$IFDEF FPC}
 Var sb : TPCSafeBox;
-  tc : QWord;
+  tc : TTickCount;
 {$ENDIF}
 begin
   {$IFDEF FPC}
   StartThreadSafe;
   try
-    tc := GetTickCount64;
+    tc := TPlatform.GetTickCount;
     sb := TPCSafeBox.Create;
     try
       sb.CopyFrom(Self);
@@ -1593,8 +1594,7 @@ begin
     finally
       sb.Free;
     end;
-    tc := GetTickCount64 - tc;
-    TLog.NewLog(ltDebug,Classname,'Checked memory '+IntToStr(tc)+' miliseonds');
+    TLog.NewLog(ltDebug,Classname,'Checked memory '+IntToStr(TPlatform.GetElapsedMilliseconds(tc))+' milliseconds');
   finally
     EndThreadSave;
   end;
@@ -2272,15 +2272,7 @@ begin
     errors := 'block ('+inttostr(newOperationBlock.block)+') is not new position ('+inttostr(BlocksCount)+')';
     exit;
   end;
-  // Check Account key
-  if Not TAccountComp.IsValidAccountKey(newOperationBlock.account_key,errors) then begin
-    exit;
-  end;
-  // reward
-  if (newOperationBlock.reward<>TPascalCoinProtocol.GetRewardForNewLine(newOperationBlock.block)) then begin
-    errors := 'Invalid reward';
-    exit;
-  end;
+
   // fee: Cannot be checked only with the safebox
   // protocol available is not checked
   if (newOperationBlock.block > 0) then begin
@@ -2300,15 +2292,66 @@ begin
         errors := 'Invalid protocol version change to '+IntToStr(newOperationBlock.protocol_version);
         exit;
       end;
-    end else if (Not (newOperationBlock.protocol_version in [CT_PROTOCOL_1,CT_PROTOCOL_2])) then begin
-      errors := 'Invalid protocol version '+IntToStr(newOperationBlock.protocol_version);
-      exit;
     end;
     // timestamp
     if ((newOperationBlock.timestamp) < (lastBlock.timestamp)) then begin
       errors := 'Invalid timestamp (Back timestamp: New timestamp:'+inttostr(newOperationBlock.timestamp)+' < last timestamp ('+Inttostr(BlocksCount-1)+'):'+Inttostr(lastBlock.timestamp)+')';
       exit;
     end;
+  end;
+  // compact_target
+  target_hash:=GetActualTargetHash(newOperationBlock.protocol_version=CT_PROTOCOL_2);
+  if (newOperationBlock.compact_target <> TPascalCoinProtocol.TargetToCompact(target_hash)) then begin
+    errors := 'Invalid target found:'+IntToHex(newOperationBlock.compact_target,8)+' actual:'+IntToHex(TPascalCoinProtocol.TargetToCompact(target_hash),8);
+    exit;
+  end;
+  // initial_safe_box_hash: Only can be checked when adding new blocks, not when restoring a safebox
+  If checkSafeBoxHash then begin
+    // TODO: Can use FSafeBoxHash instead of CalcSafeBoxHash ???? Quick speed if possible
+    if (newOperationBlock.initial_safe_box_hash <> CalcSafeBoxHash) then begin
+      errors := 'BlockChain Safe box hash invalid: '+TCrypto.ToHexaString(newOperationBlock.initial_safe_box_hash)+' var: '+
+        TCrypto.ToHexaString(FSafeBoxHash)+
+        ' Calculated:'+TCrypto.ToHexaString(CalcSafeBoxHash);
+      exit;
+    end;
+  end;
+  if (newOperationBlock.proof_of_work > target_hash) then begin
+    errors := 'Proof of work is higher than target '+TCrypto.ToHexaString(newOperationBlock.proof_of_work)+' > '+TCrypto.ToHexaString(target_hash);
+    exit;
+  end;
+  Result := IsValidOperationBlock(newOperationBlock,errors);
+end;
+
+class function TPCSafeBox.IsValidOperationBlock(Const newOperationBlock : TOperationBlock; var errors : AnsiString) : Boolean;
+  { This class function will check a OperationBlock basic info as a valid info
+
+    Creted at Build 2.1.7 as a division of IsValidNewOperationsBlock for easily basic check TOperationBlock
+
+    TOperationBlock contains the info of the new block, but cannot be checked with current Safebox state
+    (Use IsValidNewOperationsBlock instead) and also cannot check operations, operations_hash, fees...
+  }
+var pow : TRawBytes;
+  i : Integer;
+begin
+  Result := False;
+  errors := '';
+  // Check Account key
+  if Not TAccountComp.IsValidAccountKey(newOperationBlock.account_key,errors) then begin
+    exit;
+  end;
+  // reward
+  if (newOperationBlock.reward<>TPascalCoinProtocol.GetRewardForNewLine(newOperationBlock.block)) then begin
+    errors := 'Invalid reward';
+    exit;
+  end;
+  // Valid protocol version
+  if (Not (newOperationBlock.protocol_version in [CT_PROTOCOL_1,CT_PROTOCOL_2])) then begin
+    errors := 'Invalid protocol version '+IntToStr(newOperationBlock.protocol_version);
+    exit;
+  end;
+  // fee: Cannot be checked only with the safebox
+  // protocol available is not checked
+  if (newOperationBlock.block > 0) then begin
   end else begin
     if (CT_Zero_Block_Proof_of_work_in_Hexa<>'') then begin
       // Check if valid Zero block
@@ -2318,13 +2361,6 @@ begin
       end;
     end;
   end;
-  // compact_target
-  target_hash:=GetActualTargetHash(newOperationBlock.protocol_version=CT_PROTOCOL_2);
-  if (newOperationBlock.compact_target <> TPascalCoinProtocol.TargetToCompact(target_hash)) then begin
-    errors := 'Invalid target found:'+IntToHex(newOperationBlock.compact_target,8)+' actual:'+IntToHex(TPascalCoinProtocol.TargetToCompact(target_hash),8);
-    exit;
-  end;
-  // nonce: Not checked
   // block_payload: Checking Miner payload size
   if length(newOperationBlock.block_payload)>CT_MaxPayloadSize then begin
     errors := 'Invalid Miner Payload length: '+inttostr(Length(newOperationBlock.block_payload));
@@ -2337,16 +2373,6 @@ begin
       exit;
     end;
   end;
-  // initial_safe_box_hash: Only can be checked when adding new blocks, not when restoring a safebox
-  If checkSafeBoxHash then begin
-    // TODO: Can use FSafeBoxHash instead of CalcSafeBoxHash ???? Quick speed if possible
-    if (newOperationBlock.initial_safe_box_hash <> CalcSafeBoxHash) then begin
-      errors := 'BlockChain Safe box hash invalid: '+TCrypto.ToHexaString(newOperationBlock.initial_safe_box_hash)+' var: '+
-        TCrypto.ToHexaString(FSafeBoxHash)+
-        ' Calculated:'+TCrypto.ToHexaString(CalcSafeBoxHash);
-      exit;
-    end;
-  end;
   // operations_hash: NOT CHECKED WITH OPERATIONS!
   If (length(newOperationBlock.operations_hash)<>32) then begin
     errors := 'Invalid Operations hash value: '+TCrypto.ToHexaString(newOperationBlock.operations_hash)+' length='+IntToStr(Length(newOperationBlock.operations_hash));
@@ -2358,10 +2384,6 @@ begin
     errors := 'Proof of work is bad calculated '+TCrypto.ToHexaString(newOperationBlock.proof_of_work)+' <> Good: '+TCrypto.ToHexaString(pow);
     exit;
   end;
-  if (newOperationBlock.proof_of_work > target_hash) then begin
-    errors := 'Proof of work is higher than target '+TCrypto.ToHexaString(newOperationBlock.proof_of_work)+' > '+TCrypto.ToHexaString(target_hash);
-    exit;
-  end;
   Result := true;
 end;
 
@@ -3341,7 +3363,7 @@ begin
   while L <= H do
   begin
     I := (L + H) shr 1;
-    c := BinStrComp(PRawListData(FList[i])^.RawData,RawData);
+    c := TBaseType.BinStrComp(PRawListData(FList[i])^.RawData,RawData);
     if C < 0 then L := I + 1 else
     begin
       H := I - 1;