Browse Source

Corrected bug #76

Corrected miner block payload on UPoolMining.pas and some minor code
changes
PascalCoin 7 years ago
parent
commit
a744e8644f
3 changed files with 62 additions and 55 deletions
  1. 20 13
      src/core/UAccounts.pas
  2. 40 38
      src/core/UBlockChain.pas
  3. 2 4
      src/core/UPoolMining.pas

+ 20 - 13
src/core/UAccounts.pas

@@ -66,6 +66,7 @@ Type
     Class Procedure CalcProofOfWork_Part1(const operationBlock : TOperationBlock; var Part1 : TRawBytes);
     Class Procedure CalcProofOfWork_Part3(const operationBlock : TOperationBlock; var Part3 : TRawBytes);
     Class Procedure CalcProofOfWork(const operationBlock : TOperationBlock; var PoW : TRawBytes);
+    Class Function IsValidMinerBlockPayload(const newBlockPayload : TRawBytes) : Boolean;
   end;
 
   { TAccountComp }
@@ -373,10 +374,9 @@ uses
 
 { TPascalCoinProtocol }
 
-class function TPascalCoinProtocol.GetNewTarget(vteorical, vreal: Cardinal; Const actualTarget: TRawBytes): TRawBytes;
+class function TPascalCoinProtocol.GetNewTarget(vteorical, vreal: Cardinal; const actualTarget: TRawBytes): TRawBytes;
 Var
-  bnact, bnaux, bnmindiff, bnremainder, bn: TBigNum;
-  ts1, ts2: Cardinal;
+  bnact, bnaux, bn: TBigNum;
   tsTeorical, tsReal, factor1000, factor1000Min, factor1000Max: Int64;
 begin
   { Given a teorical time in seconds (vteorical>0) and a real time in seconds (vreal>0)
@@ -496,6 +496,20 @@ begin
   end;
 end;
 
+class function TPascalCoinProtocol.IsValidMinerBlockPayload(const newBlockPayload: TRawBytes): Boolean;
+var i : Integer;
+begin
+  Result := False;
+  if Length(newBlockPayload)>CT_MaxPayloadSize then Exit;
+  // Checking Miner Payload valid chars
+  for i := 1 to length(newBlockPayload) do begin
+    if Not (newBlockPayload[i] in [#32..#254]) then begin
+      exit;
+    end;
+  end;
+  Result := True;
+end;
+
 class function TPascalCoinProtocol.GetRewardForNewLine(line_index: Cardinal): UInt64;
 Var n, i : Cardinal;
 begin
@@ -2361,18 +2375,11 @@ begin
       end;
     end;
   end;
-  // 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));
+  // Checking Miner Payload valid chars/length
+  If Not TPascalCoinProtocol.IsValidMinerBlockPayload(newOperationBlock.block_payload) then begin
+    errors := 'Invalid Miner Payload value. Length: '+inttostr(Length(newOperationBlock.block_payload));
     exit;
   end;
-  // Checking Miner Payload valid chars
-  for i := 1 to length(newOperationBlock.block_payload) do begin
-    if Not (newOperationBlock.block_payload[i] in [#32..#254]) then begin
-      errors := 'Invalid Miner Payload character at pos '+inttostr(i)+' value:'+inttostr(ord(newOperationBlock.block_payload[i]));
-      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));

+ 40 - 38
src/core/UBlockChain.pas

@@ -284,6 +284,7 @@ Type
     Property nonce: Cardinal read GetnOnce write SetnOnce;
     Property timestamp: Cardinal read Gettimestamp write Settimestamp;
     Property BlockPayload : TRawBytes read GetBlockPayload write SetBlockPayload;
+    function Update_And_RecalcPOW(newNOnce, newTimestamp : Cardinal; newBlockPayload : TRawBytes) : Boolean;
     procedure UpdateTimestamp;
     function SaveBlockToStorage(Stream: TStream): Boolean;
     function SaveBlockToStream(save_only_OperationBlock : Boolean; Stream: TStream): Boolean;
@@ -1088,8 +1089,11 @@ begin
     Clear(true);
     Result := False;
     //
-    errors := 'Invalid protocol structure. Check application version!';
-    if (Stream.Size - Stream.Position < 5) then exit;
+    errors := '';
+    if (Stream.Size - Stream.Position < 5) then begin
+      errors := 'Invalid protocol structure. Check application version!';
+      exit;
+    end;
     Stream.Read(soob,1);
     // About soob var:
     // In build prior to 1.0.4 soob only can have 2 values: 0 or 1
@@ -1347,6 +1351,27 @@ begin
   Result := true;
 end;
 
+function TPCOperationsComp.Update_And_RecalcPOW(newNOnce, newTimestamp: Cardinal; newBlockPayload: TRawBytes) : Boolean;
+Var i : Integer;
+  _changedPayload : Boolean;
+begin
+  Lock;
+  Try
+    If newBlockPayload<>FOperationBlock.block_payload then begin
+      _changedPayload := TPascalCoinProtocol.IsValidMinerBlockPayload(newBlockPayload);
+    end else _changedPayload:=False;
+    If (_changedPayload) Or (newNOnce<>FOperationBlock.nonce) Or (newTimestamp<>FOperationBlock.timestamp) then begin
+      If _changedPayload then FOperationBlock.block_payload:=newBlockPayload;
+      FOperationBlock.nonce:=newNOnce;
+      FOperationBlock.timestamp:=newTimestamp;
+      CalcProofOfWork(_changedPayload,FOperationBlock.proof_of_work);
+      Result := True;
+    end else Result := False;
+  finally
+    Unlock;
+  end;
+end;
+
 procedure TPCOperationsComp.SetAccountKey(const value: TAccountKey);
 begin
   Lock;
@@ -1374,23 +1399,8 @@ begin
 end;
 
 procedure TPCOperationsComp.SetBlockPayload(const Value: TRawBytes);
-Var i : Integer;
 begin
-  Lock;
-  Try
-    if Value=FOperationBlock.block_payload then exit;
-    if Length(Value)>CT_MaxPayloadSize then Exit;
-    // Checking Miner Payload valid chars
-    for i := 1 to length(Value) do begin
-      if Not (Value[i] in [#32..#254]) then begin
-        exit;
-      end;
-    end;
-    FOperationBlock.block_payload := Value;
-    CalcProofOfWork(true,FOperationBlock.proof_of_work);
-  finally
-    Unlock;
-  end;
+  Update_And_RecalcPOW(FOperationBlock.nonce,FOperationBlock.timestamp,Value);
 end;
 
 procedure TPCOperationsComp.OnOperationsHashTreeChanged(Sender: TObject);
@@ -1401,25 +1411,12 @@ end;
 
 procedure TPCOperationsComp.SetnOnce(const value: Cardinal);
 begin
-  Lock;
-  Try
-    FOperationBlock.nonce := value;
-    CalcProofOfWork(false,FOperationBlock.proof_of_work);
-  finally
-    Unlock;
-  end;
+  Update_And_RecalcPOW(value,FOperationBlock.timestamp,FOperationBlock.block_payload);
 end;
 
 procedure TPCOperationsComp.Settimestamp(const value: Cardinal);
 begin
-  Lock;
-  Try
-    if FOperationBlock.timestamp=Value then exit; // No change, nothing to do
-    FOperationBlock.timestamp := value;
-    CalcProofOfWork(false,FOperationBlock.proof_of_work);
-  finally
-    Unlock;
-  end;
+  Update_And_RecalcPOW(FOperationBlock.nonce,value,FOperationBlock.block_payload);
 end;
 
 procedure TPCOperationsComp.UpdateTimestamp;
@@ -1945,8 +1942,10 @@ begin
   try
     // c = operations count
     for i := 1 to c do begin
-      errors := 'Invalid operation structure ' + inttostr(i) + '/' + inttostr(c);
-      if Stream.Size - Stream.Position < 4 then exit;
+      if Stream.Size - Stream.Position < 4 then begin
+        errors := 'Invalid operation structure ' + inttostr(i) + '/' + inttostr(c);
+        exit;
+      end;
       Stream.Read(OpType, 4);
       j := TPCOperationsComp.IndexOfOperationClassByOpType(OpType);
       if j >= 0 then
@@ -1954,15 +1953,18 @@ begin
       else
         OpClass := Nil;
       if Not Assigned(OpClass) then begin
-        errors := errors + ' optype not valid:' + InttoHex(OpType, 4);
+        errors := 'Invalid operation structure ' + inttostr(i) + '/' + inttostr(c) + ' optype not valid:' + InttoHex(OpType, 4);
         exit;
       end;
-      errors := 'Invalid operation load from stream ' + inttostr(i) + '/' + inttostr(c)+' Class:'+OpClass.ClassName;
       bcop := OpClass.Create;
       Try
         if LoadingFromStorage then begin
-          If not bcop.LoadFromStorage(Stream,LoadProtocolV2) then exit;
+          If not bcop.LoadFromStorage(Stream,LoadProtocolV2) then begin
+            errors := 'Invalid operation load from storage ' + inttostr(i) + '/' + inttostr(c)+' Class:'+OpClass.ClassName;
+            exit;
+          end;
         end else if not bcop.LoadFromNettransfer(Stream) then begin
+          errors := 'Invalid operation load from stream ' + inttostr(i) + '/' + inttostr(c)+' Class:'+OpClass.ClassName;
           exit;
         end;
         AddOperationToHashTree(bcop);

+ 2 - 4
src/core/UPoolMining.pas

@@ -820,10 +820,8 @@ begin
         // Best practices: Only will accept a solution if timestamp >= sent timestamp for this job (1.5.3)
         If (P^.SentMinTimestamp<=_timestamp) then begin
           _targetPoW := FNodeNotifyEvents.Node.Bank.SafeBox.GetActualTargetHash(P^.OperationsComp.OperationBlock.protocol_version=CT_PROTOCOL_2);
+          P^.OperationsComp.Update_And_RecalcPOW(_nOnce,_timestamp,_payload);
           if (P^.OperationsComp.OperationBlock.proof_of_work<=_targetPoW) then begin
-            P^.OperationsComp.BlockPayload := _payload;
-            P^.OperationsComp.timestamp := _timestamp;
-            P^.OperationsComp.nonce := _nOnce;
             // Candidate!
             nbOperations := TPCOperationsComp.Create(Nil);
             nbOperations.bank := FNodeNotifyEvents.Node.Bank;
@@ -1093,7 +1091,7 @@ begin
               FPoolFinalMinerName := raws;
               for i:=1 to length(raws) do begin
                 if Not (raws[i] in [#32..#254]) then begin
-                  TLog.NewLog(ltError,ClassName,'Invalid proposed miner name. Value at pos '+inttostr(i)+' is not #24..#254: '+IntToStr(integer(raws[i])));
+                  TLog.NewLog(ltError,ClassName,'Invalid proposed miner name. Value at pos '+inttostr(i)+' is not #32..#254: '+IntToStr(integer(raws[i])));
                   FPoolFinalMinerName:='';
                   break;
                 end;