Jelajahi Sumber

limit 0-fee improvements

PascalCoin 6 tahun lalu
induk
melakukan
7a7fccfb2b
1 mengubah file dengan 63 tambahan dan 32 penghapusan
  1. 63 32
      src/core/UBlockChain.pas

+ 63 - 32
src/core/UBlockChain.pas

@@ -269,6 +269,7 @@ Type
     FTotalAmount : Int64;
     FTotalFee : Int64;
     FMax0feeOperationsBySigner : Integer;
+    function InternalCanAddOperationToHashTree(lockedThreadList : TList; op : TPCOperation) : Boolean;
     function InternalAddOperationToHashTree(list : TList; op : TPCOperation; CalcNewHashTree : Boolean) : Boolean;
     Function FindOrderedByOpReference(lockedThreadList : TList; const Value: TOpReference; var Index: Integer): Boolean;
     Function FindOrderedBySha(lockedThreadList : TList; const Value: TRawBytes; var Index: Integer): Boolean;
@@ -278,6 +279,7 @@ Type
   public
     Constructor Create;
     Destructor Destroy; Override;
+    function CanAddOperationToHashTree(op : TPCOperation) : Boolean;
     function AddOperationToHashTree(op : TPCOperation) : Boolean;
     Procedure ClearHastThree;
     Property HashTree : TRawBytes read GetHashTree;
@@ -906,7 +908,12 @@ Begin
         exit;
       end;
       // Only process when in current address, prevent do it when reading operations from file
-      Result := op.DoOperation(FPreviousUpdatedBlocks, FSafeBoxTransaction, errors);
+      if FOperationsHashTree.CanAddOperationToHashTree(op) then begin
+        Result := op.DoOperation(FPreviousUpdatedBlocks, FSafeBoxTransaction, errors);
+      end else begin
+        errors := 'Cannot add operation. Limits reached';
+        Exit;
+      end;
     end else Result := true;
     if Result then begin
       if FOperationsHashTree.AddOperationToHashTree(op) then begin
@@ -1431,16 +1438,18 @@ begin
       lastn := FOperationsHashTree.OperationsCount;
       for i:=0 to lastn-1 do begin
         op := FOperationsHashTree.GetOperation(i);
-        if (op.DoOperation(FPreviousUpdatedBlocks, SafeBoxTransaction,errors)) then begin
-          if aux.AddOperationToHashTree(op) then begin
-            inc(n);
-            inc(FOperationBlock.fee,op.OperationFee);
-            {$IFDEF HIGHLOG}TLog.NewLog(ltdebug,Classname,'Sanitizing (pos:'+inttostr(i+1)+'/'+inttostr(lastn)+'): '+op.ToString){$ENDIF};
-          end else begin
-            TLog.NewLog(lterror,ClassName,Format('Undo operation.DoExecute at Sanitize due limits reached. Executing %d operations',[FOperationsHashTree.OperationsCount]));
-            FPreviousUpdatedBlocks.Clear;
-            FSafeBoxTransaction.Rollback;
-            for iUndo := 0 to FOperationsHashTree.OperationsCount-1 do FOperationsHashTree.GetOperation(iUndo).DoOperation(FPreviousUpdatedBlocks, FSafeBoxTransaction, auxs);
+        if (aux.CanAddOperationToHashTree(op)) then begin
+          if (op.DoOperation(FPreviousUpdatedBlocks, SafeBoxTransaction,errors)) then begin
+            if aux.AddOperationToHashTree(op) then begin
+              inc(n);
+              inc(FOperationBlock.fee,op.OperationFee);
+              {$IFDEF HIGHLOG}TLog.NewLog(ltdebug,Classname,'Sanitizing (pos:'+inttostr(i+1)+'/'+inttostr(lastn)+'): '+op.ToString){$ENDIF};
+            end else begin
+              TLog.NewLog(lterror,ClassName,Format('Undo operation.DoExecute at Sanitize due limits reached. Executing %d operations',[aux.OperationsCount]));
+              FPreviousUpdatedBlocks.Clear;
+              FSafeBoxTransaction.Rollback;
+              for iUndo := 0 to aux.OperationsCount-1 do aux.GetOperation(iUndo).DoOperation(FPreviousUpdatedBlocks, FSafeBoxTransaction, auxs);
+            end;
           end;
         end;
       end;
@@ -1780,6 +1789,17 @@ begin
   end;
 end;
 
+function TOperationsHashTree.CanAddOperationToHashTree(op: TPCOperation): Boolean;
+Var lockedList : TList;
+begin
+  lockedList := FHashTreeOperations.LockList;
+  Try
+    Result := InternalCanAddOperationToHashTree(lockedList,op);
+  Finally
+    FHashTreeOperations.UnlockList;
+  End;
+end;
+
 procedure TOperationsHashTree.ClearHastThree;
 var l : TList;
   i : Integer;
@@ -2064,27 +2084,10 @@ Var msCopy : TMemoryStream;
   i,npos,iListSigners : Integer;
   listSigners : TList;
 begin
-  Result := False;
-  // Protections:
-  // Protect 0-fee operations
-  if (op.OperationFee=0) And (FMax0feeOperationsBySigner>=0) then begin
-    if (FMax0feeOperationsBySigner=0) then Exit // Not allowed 0-fee operations!
-    else if (FMax0feeOperationsBySigner>0) then begin
-      listSigners := TList.Create;
-      try
-        op.SignerAccounts(listSigners);
-        for iListSigners:=0 to listSigners.Count-1 do begin
-          If FindOrderedByAccountData(list,PtrInt(listSigners[iListSigners]),i) then begin
-            PaccData := FListOrderedByAccountsData[i];
-            if (PaccData^.account_without_fee>=FMax0feeOperationsBySigner) then Exit; // Limit 0-fee reached
-          end;
-        end;
-      finally
-        listSigners.Free;
-      end;
-    end;
-  end;
-  Result := True; // Will add:
+  if Not InternalCanAddOperationToHashTree(list,op) then begin
+    Result := False;
+    Exit;
+  end else Result := True; // Will add:
   msCopy := TMemoryStream.Create;
   try
     New(P);
@@ -2145,6 +2148,34 @@ begin
   If Assigned(FOnChanged) then FOnChanged(Self);
 end;
 
+function TOperationsHashTree.InternalCanAddOperationToHashTree(lockedThreadList : TList; op: TPCOperation): Boolean;
+Var PaccData : POperationsHashAccountsData;
+  iListSigners,iFound : Integer;
+  listSigners : TList;
+begin
+  Result := False;
+  // Protections:
+  // Protect 0-fee operations
+  if (op.OperationFee=0) And (FMax0feeOperationsBySigner>=0) then begin
+    if (FMax0feeOperationsBySigner=0) then Exit // Not allowed 0-fee operations!
+    else if (FMax0feeOperationsBySigner>0) then begin
+      listSigners := TList.Create;
+      try
+        op.SignerAccounts(listSigners);
+        for iListSigners:=0 to listSigners.Count-1 do begin
+          If FindOrderedByAccountData(lockedThreadList,PtrInt(listSigners[iListSigners]),iFound) then begin
+            PaccData := FListOrderedByAccountsData[iFound];
+            if (PaccData^.account_without_fee>=FMax0feeOperationsBySigner) then Exit; // Limit 0-fee reached
+          end;
+        end;
+      finally
+        listSigners.Free;
+      end;
+    end;
+  end;
+  Result := True;
+end;
+
 function TOperationsHashTree.FindOrderedBySha(lockedThreadList : TList; const Value: TRawBytes; var Index: Integer): Boolean;
 var L, H, I : Integer;
   iLockedThreadListPos : PtrInt;