Browse Source

Revert "Multithread on loading blocks/operations on gui-classic"

This reverts commit e5b0f6619cf88cb9a9d38c5785654f83973c1049.
PascalCoin 6 years ago
parent
commit
a2d76abcba
2 changed files with 178 additions and 309 deletions
  1. 2 25
      src/core/UNode.pas
  2. 176 284
      src/gui-classic/UGridUtils.pas

+ 2 - 25
src/core/UNode.pas

@@ -91,8 +91,7 @@ Type
     //
     //
     Procedure NotifyBlocksChanged;
     Procedure NotifyBlocksChanged;
     //
     //
-    procedure GetStoredOperationsFromAccount(AOwnerThread : TPCThread; const OperationsResume: TList<TOperationResume>; account_number: Cardinal; MaxDepth, StartOperation, EndOperation : Integer; SearchBackwardsStartingAtBlock : Cardinal=0); overload;
-    procedure GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDepth, StartOperation, EndOperation : Integer; SearchBackwardsStartingAtBlock : Cardinal=0); overload;
+    procedure GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDepth, StartOperation, EndOperation : Integer; SearchBackwardsStartingAtBlock : Cardinal=0);
     Function FindOperation(Const OperationComp : TPCOperationsComp; Const OperationHash : TRawBytes; var block : Cardinal; var operation_block_index : Integer) : Boolean;
     Function FindOperation(Const OperationComp : TPCOperationsComp; Const OperationHash : TRawBytes; var block : Cardinal; var operation_block_index : Integer) : Boolean;
     Function FindOperationExt(Const OperationComp : TPCOperationsComp; Const OperationHash : TRawBytes; var block : Cardinal; var operation_block_index : Integer) : TSearchOperationResult;
     Function FindOperationExt(Const OperationComp : TPCOperationsComp; Const OperationHash : TRawBytes; var block : Cardinal; var operation_block_index : Integer) : TSearchOperationResult;
     Function FindNOperation(block, account, n_operation : Cardinal; var OpResume : TOperationResume) : TSearchOperationResult;
     Function FindNOperation(block, account, n_operation : Cardinal; var OpResume : TOperationResume) : TSearchOperationResult;
@@ -809,8 +808,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TNode.GetStoredOperationsFromAccount(AOwnerThread : TPCThread; const OperationsResume: TList<TOperationResume>; account_number: Cardinal;
-  MaxDepth, StartOperation, EndOperation: Integer; SearchBackwardsStartingAtBlock: Cardinal);
+procedure TNode.GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDepth, StartOperation, EndOperation: Integer; SearchBackwardsStartingAtBlock : Cardinal = 0);
   // Optimization:
   // Optimization:
   // For better performance, will only include at "OperationsResume" values betweeen "startOperation" and "endOperation"
   // For better performance, will only include at "OperationsResume" values betweeen "startOperation" and "endOperation"
 
 
@@ -826,9 +824,6 @@ procedure TNode.GetStoredOperationsFromAccount(AOwnerThread : TPCThread; const O
     acc_0_miner_reward, acc_4_dev_reward : Int64;
     acc_0_miner_reward, acc_4_dev_reward : Int64;
     acc_4_for_dev : Boolean;
     acc_4_for_dev : Boolean;
   begin
   begin
-    if Assigned(AOwnerThread) then begin
-      if AOwnerThread.terminated then Exit;
-    end;
     if (act_depth<=0) then exit;
     if (act_depth<=0) then exit;
     opc := TPCOperationsComp.Create(Nil);
     opc := TPCOperationsComp.Create(Nil);
     Try
     Try
@@ -838,9 +833,6 @@ procedure TNode.GetStoredOperationsFromAccount(AOwnerThread : TPCThread; const O
         while (last_block_number>block_number) And (act_depth>0)
         while (last_block_number>block_number) And (act_depth>0)
           And (block_number >= (account_number DIV CT_AccountsPerBlock))
           And (block_number >= (account_number DIV CT_AccountsPerBlock))
           And (nOpsCounter <= EndOperation) do begin
           And (nOpsCounter <= EndOperation) do begin
-          if Assigned(AOwnerThread) then begin
-            if AOwnerThread.terminated then Exit;
-          end;
           found_in_block := False;
           found_in_block := False;
           last_block_number := block_number;
           last_block_number := block_number;
           l.Clear;
           l.Clear;
@@ -934,21 +926,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TNode.GetStoredOperationsFromAccount(const OperationsResume: TOperationsResumeList; account_number: Cardinal; MaxDepth, StartOperation, EndOperation: Integer; SearchBackwardsStartingAtBlock : Cardinal = 0);
-var LOpList : TList<TOperationResume>;
-  i : Integer;
-begin
-  LOpList := TList<TOperationResume>.Create;
-  try
-    GetStoredOperationsFromAccount(Nil,LOpList,account_number,MaxDepth,StartOperation,EndOperation,SearchBackwardsStartingAtBlock);
-    for i := 0 to LOpList.Count-1 do begin
-      OperationsResume.Add(LOpList[i]);
-    end;
-  finally
-    LOpList.Free;
-  end;
-end;
-
 function TNode.FindNOperation(block, account, n_operation: Cardinal;
 function TNode.FindNOperation(block, account, n_operation: Cardinal;
   var OpResume: TOperationResume): TSearchOperationResult;
   var OpResume: TOperationResume): TSearchOperationResult;
   // Note: block = 0 search in all blocks. If Block>0 must match a valid block with operation with this account
   // Note: block = 0 search in all blocks. If Block>0 must match a valid block with operation with this account

+ 176 - 284
src/gui-classic/UGridUtils.pas

@@ -30,7 +30,7 @@ uses
 {$ELSE}
 {$ELSE}
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
 {$ENDIF}
 {$ENDIF}
-  Classes, Grids, UNode, UAccounts, UBlockChain, UAppParams, UThread,
+  Classes, Grids, UNode, UAccounts, UBlockChain, UAppParams,
   UWallet, UCrypto, UPoolMining, URPC, UBaseTypes, UPCOrderedLists,
   UWallet, UCrypto, UPoolMining, URPC, UBaseTypes, UPCOrderedLists,
   {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF};
   {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF};
 
 
@@ -83,17 +83,6 @@ Type
     Function SelectedAccounts(accounts : TOrderedCardinalList) : Integer;
     Function SelectedAccounts(accounts : TOrderedCardinalList) : Integer;
   End;
   End;
 
 
-  TOperationsGrid = Class;
-
-  TOperationsGridUpdateThread = Class(TPCThread)
-    FOperationsGrid : TOperationsGrid;
-    procedure DoUpdateOperationsGrid(ANode : TNode; var AList : TList<TOperationResume>);
-  protected
-    procedure BCExecute; override;
-  public
-    constructor Create(AOperationsGrid : TOperationsGrid);
-  End;
-
   TOperationsGrid = Class(TComponent)
   TOperationsGrid = Class(TComponent)
   private
   private
     FDrawGrid: TDrawGrid;
     FDrawGrid: TDrawGrid;
@@ -104,7 +93,6 @@ Type
     FBlockStart: Int64;
     FBlockStart: Int64;
     FBlockEnd: Int64;
     FBlockEnd: Int64;
     FMustShowAlwaysAnAccount: Boolean;
     FMustShowAlwaysAnAccount: Boolean;
-    FOperationsGridUpdateThread : TOperationsGridUpdateThread;
     Procedure OnNodeNewOperation(Sender : TObject);
     Procedure OnNodeNewOperation(Sender : TObject);
     Procedure OnNodeNewAccount(Sender : TObject);
     Procedure OnNodeNewAccount(Sender : TObject);
     Procedure InitGrid;
     Procedure InitGrid;
@@ -165,19 +153,6 @@ Type
   End;
   End;
   TBlockChainDataArray = Array of TBlockChainData;
   TBlockChainDataArray = Array of TBlockChainData;
 
 
-  TBlockChainGrid = Class;
-
-  TBlockChainGridUpdateThread = Class(TPCThread)
-    FBlockChainGrid : TBlockChainGrid;
-    FBlockStart, FBlockEnd : Int64;
-    procedure DoUpdateBlockChainGrid(ANode : TNode; var AList : TList<TBlockChainData>; ABlockStart, ABlockEnd : Int64);
-  protected
-    procedure BCExecute; override;
-  public
-    constructor Create(ABlockChainGrid : TBlockChainGrid);
-  End;
-
-
   { TBlockChainGrid }
   { TBlockChainGrid }
 
 
   TShowHashRateAs = (hr_Unit, hr_Kilo, hr_Mega, hr_Giga, hr_Tera, hr_Peta, hr_Exa);
   TShowHashRateAs = (hr_Unit, hr_Kilo, hr_Mega, hr_Giga, hr_Tera, hr_Peta, hr_Exa);
@@ -193,7 +168,6 @@ Type
     FNodeNotifyEvents : TNodeNotifyEvents;
     FNodeNotifyEvents : TNodeNotifyEvents;
     FHashRateAverageBlocksCount: Integer;
     FHashRateAverageBlocksCount: Integer;
     FShowTimeAverageColumns: Boolean;
     FShowTimeAverageColumns: Boolean;
-    FBlockChainGridUpdateThread : TBlockChainGridUpdateThread;
     Procedure OnNodeNewAccount(Sender : TObject);
     Procedure OnNodeNewAccount(Sender : TObject);
     Procedure InitGrid;
     Procedure InitGrid;
     procedure OnGridDrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
     procedure OnGridDrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
@@ -474,7 +448,9 @@ begin
     C.ColumnType := act_account_number;
     C.ColumnType := act_account_number;
     C.width := -1;
     C.width := -1;
   end;
   end;
+  {.$IFDEF FPC}
   DrawGrid.Canvas.Font.Color:=clBlack;
   DrawGrid.Canvas.Font.Color:=clBlack;
+  {.$ENDIF}
   if (ARow=0) then begin
   if (ARow=0) then begin
     // Header
     // Header
     s := CT_ColumnHeader[C.ColumnType];
     s := CT_ColumnHeader[C.ColumnType];
@@ -645,127 +621,6 @@ begin
   InitGrid;
   InitGrid;
 end;
 end;
 
 
-{ TOperationsGridUpdateThread }
-
-procedure TOperationsGridUpdateThread.BCExecute;
-var list : TList<TOperationResume>;
-  i : Integer;
-begin
-  list := TList<TOperationResume>.Create;
-  try
-    DoUpdateOperationsGrid(FOperationsGrid.Node,list);
-    if (Not Terminated) then begin
-      FOperationsGrid.FOperationsResume.Clear;
-      for i := 0 to list.Count-1 do begin
-        FOperationsGrid.FOperationsResume.Add(list[i]);
-      end;
-      FOperationsGrid.InitGrid;
-    end;
-  finally
-    list.Free;
-  end;
-end;
-
-constructor TOperationsGridUpdateThread.Create(AOperationsGrid: TOperationsGrid);
-begin
-  FOperationsGrid := AOperationsGrid;
-  inherited Create(True);
-  FreeOnTerminate := False;
-  Suspended := False;
-end;
-
-procedure TOperationsGridUpdateThread.DoUpdateOperationsGrid(ANode: TNode; var AList: TList<TOperationResume>);
-Var list : TList<Cardinal>;
-  i,j : Integer;
-  OPR : TOperationResume;
-  Op : TPCOperation;
-  opc : TPCOperationsComp;
-  bstart,bend : int64;
-  LOperationsResume : TOperationsResumeList;
-begin
-  if Not Assigned(ANode) then exit;
-  AList.Clear;
-  Try
-    if (FOperationsGrid.MustShowAlwaysAnAccount) And (FOperationsGrid.AccountNumber<0) then exit;
-
-    if FOperationsGrid.FPendingOperations then begin
-      for i := ANode.Operations.Count - 1 downto 0 do begin
-        Op := ANode.Operations.OperationsHashTree.GetOperation(i);
-        If TPCOperation.OperationToOperationResume(0,Op,True,Op.SignerAccount,OPR) then begin
-          OPR.NOpInsideBlock := i;
-          OPR.Block := ANode.Bank.BlocksCount;
-          OPR.Balance := ANode.Operations.SafeBoxTransaction.Account(Op.SignerAccount).balance;
-          AList.Add(OPR);
-        end;
-      end;
-    end else begin
-      if FOperationsGrid.AccountNumber<0 then begin
-        opc := TPCOperationsComp.Create(Nil);
-        try
-          opc.bank := ANode.Bank;
-          If FOperationsGrid.FBlockEnd<0 then begin
-            If ANode.Bank.BlocksCount>0 then bend := ANode.Bank.BlocksCount-1
-            else bend := 0;
-          end else bend := FOperationsGrid.FBlockEnd;
-          if FOperationsGrid.FBlockStart<0 then begin
-            if (bend > 300) then bstart := bend - 300
-            else bstart := 0;
-          end else bstart:= FOperationsGrid.FBlockStart;
-          If bstart<0 then bstart := 0;
-          if bend>=ANode.Bank.BlocksCount then bend:=ANode.Bank.BlocksCount;
-          while (bstart<=bend) and (Not Terminated) do begin
-            opr := CT_TOperationResume_NUL;
-            if (ANode.Bank.Storage.LoadBlockChainBlock(opc,bend)) then begin
-              // Reward operation
-              OPR := CT_TOperationResume_NUL;
-              OPR.valid := true;
-              OPR.Block := bend;
-              OPR.time := opc.OperationBlock.timestamp;
-              OPR.AffectedAccount := bend * CT_AccountsPerBlock;
-              OPR.Amount := opc.OperationBlock.reward;
-              OPR.Fee := opc.OperationBlock.fee;
-              OPR.Balance := OPR.Amount+OPR.Fee;
-              OPR.OperationTxt := 'Blockchain reward';
-              AList.Add(OPR);
-              // Reverse operations inside a block
-              for i := opc.Count - 1 downto 0 do begin
-                if TPCOperation.OperationToOperationResume(bend,opc.Operation[i],True,opc.Operation[i].SignerAccount,opr) then begin
-                  opr.NOpInsideBlock := i;
-                  opr.Block := bend;
-                  opr.time := opc.OperationBlock.timestamp;
-                  AList.Add(opr);
-                end;
-              end;
-            end else break;
-            dec(bend);
-          end;
-        finally
-          opc.Free;
-        end;
-
-      end else begin
-        list := TList<Cardinal>.Create;
-        Try
-          ANode.Operations.OperationsHashTree.GetOperationsAffectingAccount(FOperationsGrid.AccountNumber,list);
-          for i := list.Count - 1 downto 0 do begin
-            Op := ANode.Operations.OperationsHashTree.GetOperation((list[i]));
-            If TPCOperation.OperationToOperationResume(0,Op,False,FOperationsGrid.AccountNumber,OPR) then begin
-              OPR.NOpInsideBlock := i;
-              OPR.Block := ANode.Operations.OperationBlock.block;
-              OPR.Balance := ANode.Operations.SafeBoxTransaction.Account(FOperationsGrid.AccountNumber).balance;
-              AList.Add(OPR);
-            end;
-          end;
-        Finally
-          list.Free;
-        End;
-        ANode.GetStoredOperationsFromAccount(Self,AList,FOperationsGrid.AccountNumber,100,0,5000);
-      end;
-    end;
-  Finally
-  End;
-end;
-
 { TOperationsGrid }
 { TOperationsGrid }
 
 
 constructor TOperationsGrid.Create(AOwner: TComponent);
 constructor TOperationsGrid.Create(AOwner: TComponent);
@@ -780,17 +635,11 @@ begin
   FBlockStart := -1;
   FBlockStart := -1;
   FBlockEnd := -1;
   FBlockEnd := -1;
   FPendingOperations := false;
   FPendingOperations := false;
-  FOperationsGridUpdateThread := Nil;
   inherited;
   inherited;
 end;
 end;
 
 
 destructor TOperationsGrid.Destroy;
 destructor TOperationsGrid.Destroy;
 begin
 begin
-  If Assigned(FOperationsGridUpdateThread) then begin
-    FOperationsGridUpdateThread.Terminate;
-    FOperationsGridUpdateThread.WaitFor;
-    FreeAndNil(FOperationsGridUpdateThread);
-  end;
   FOperationsResume.Free;
   FOperationsResume.Free;
   FNodeNotifyEvents.Free;
   FNodeNotifyEvents.Free;
   inherited;
   inherited;
@@ -840,7 +689,9 @@ procedure TOperationsGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Integer; R
 Var s : String;
 Var s : String;
   opr : TOperationResume;
   opr : TOperationResume;
 begin
 begin
+  {.$IFDEF FPC}
   DrawGrid.Canvas.Font.Color:=clBlack;
   DrawGrid.Canvas.Font.Color:=clBlack;
+  {.$ENDIF}
   opr := CT_TOperationResume_NUL;
   opr := CT_TOperationResume_NUL;
   Try
   Try
   if (ARow=0) then begin
   if (ARow=0) then begin
@@ -1004,11 +855,6 @@ end;
 procedure TOperationsGrid.SetNode(const Value: TNode);
 procedure TOperationsGrid.SetNode(const Value: TNode);
 begin
 begin
   if GetNode=Value then exit;
   if GetNode=Value then exit;
-  If Assigned(FOperationsGridUpdateThread) then begin
-    FOperationsGridUpdateThread.Terminate;
-    FOperationsGridUpdateThread.WaitFor;
-    FreeAndNil(FOperationsGridUpdateThread);
-  end;
   FNodeNotifyEvents.Node := Value;
   FNodeNotifyEvents.Node := Value;
   UpdateAccountOperations; // New Build 1.0.3
   UpdateAccountOperations; // New Build 1.0.3
 end;
 end;
@@ -1051,126 +897,95 @@ begin
 end;
 end;
 
 
 procedure TOperationsGrid.UpdateAccountOperations;
 procedure TOperationsGrid.UpdateAccountOperations;
+Var list : TList<Cardinal>;
+  i,j : Integer;
+  OPR : TOperationResume;
+  Op : TPCOperation;
+  opc : TPCOperationsComp;
+  bstart,bend : int64;
 begin
 begin
-  if Not Assigned(Node) then exit;
-  If Assigned(FOperationsGridUpdateThread) then begin
-    FOperationsGridUpdateThread.Terminate;
-    FOperationsGridUpdateThread.WaitFor;
-    FreeAndNil(FOperationsGridUpdateThread);
-  end;
-  FOperationsGridUpdateThread := TOperationsGridUpdateThread.Create(Self);
-end;
-
-{ TBlockChainGridUpdateThread }
-
-procedure TBlockChainGridUpdateThread.BCExecute;
-var Llist : TList<TBlockChainData>;
-  i : Integer;
-  LBlockStart, LBlockEnd : Integer;
-begin
-  if (Not Assigned(FBlockChainGrid.Node)) Or (Terminated) then Exit;
-
-  if (FBlockChainGrid.FBlockStart>FBlockChainGrid.FBlockEnd) And (FBlockChainGrid.FBlockStart>=0) then FBlockChainGrid.FBlockEnd := -1;
-  if (FBlockChainGrid.FBlockEnd>=0) And (FBlockChainGrid.FBlockEnd<FBlockChainGrid.FBlockStart) then FBlockChainGrid.FBlockStart:=-1;
-
-  if FBlockChainGrid.FBlockStart>(FBlockChainGrid.FNodeNotifyEvents.Node.Bank.BlocksCount-1) then FBlockChainGrid.FBlockStart := -1;
-  if (FBlockChainGrid.FBlockEnd>=0) And (FBlockChainGrid.FBlockEnd<FBlockChainGrid.Node.Bank.BlocksCount) then begin
-    LBlockEnd := FBlockChainGrid.FBlockEnd
-  end else begin
-    if (FBlockChainGrid.FBlockStart>=0) And (FBlockChainGrid.FBlockStart+FBlockChainGrid.MaxBlocks<=FBlockChainGrid.Node.Bank.BlocksCount) then LBlockEnd := FBlockChainGrid.FBlockStart + FBlockChainGrid.MaxBlocks - 1
-    else LBlockEnd := FBlockChainGrid.Node.Bank.BlocksCount-1;
-  end;
-
-  if (FBlockChainGrid.FBlockStart>=0) And (FBlockChainGrid.FBlockStart<FBlockChainGrid.Node.Bank.BlocksCount) then LBlockStart := FBlockChainGrid.FBlockStart
-  else begin
-    if LBlockEnd>FBlockChainGrid.MaxBlocks then LBlockStart := LBlockEnd - FBlockChainGrid.MaxBlocks + 1
-    else LBlockStart := 0;
-  end;
-
-
-  Llist := TList<TBlockChainData>.Create;
-  try
-    DoUpdateBlockChainGrid(FBlockChainGrid.Node,Llist,LBlockStart,LBlockEnd);
-    if (Not Terminated) then begin
-      SetLength(FBlockChainGrid.FBlockChainDataArray,Llist.Count);
-      for i := 0 to Llist.Count-1 do begin
-        FBlockChainGrid.FBlockChainDataArray[i] := Llist[i];
-      end;
-      if Assigned(FBlockChainGrid.DrawGrid) then begin
-        if Llist.Count>0 then FBlockChainGrid.DrawGrid.RowCount := Llist.Count+1
-        else FBlockChainGrid.DrawGrid.RowCount := 2;
-        FBlockChainGrid.FDrawGrid.Invalidate;
-      end;
-    end;
-  finally
-    Llist.Free;
-  end;
-end;
-
-constructor TBlockChainGridUpdateThread.Create(ABlockChainGrid : TBlockChainGrid);
-begin
-  FBlockChainGrid := ABlockChainGrid;
-  inherited Create(True);
-  FreeOnTerminate := False;
-  Suspended := False;
-end;
+  FOperationsResume.Clear;
+  Try
+    if Not Assigned(Node) then exit;
+    if (MustShowAlwaysAnAccount) And (AccountNumber<0) then exit;
 
 
-procedure TBlockChainGridUpdateThread.DoUpdateBlockChainGrid(ANode: TNode; var AList: TList<TBlockChainData>; ABlockStart, ABlockEnd : Int64);
-Var opc : TPCOperationsComp;
-  bcd : TBlockChainData;
-  opb : TOperationBlock;
-  bn : TBigNum;
-begin
-  opc := TPCOperationsComp.Create(Nil);
-  try
-    opc.bank := ANode.Bank;
-    while (ABlockStart<=ABlockEnd) and (Not Terminated) do begin
-      bcd := CT_TBlockChainData_NUL;
-      opb := ANode.Bank.SafeBox.Block(ABlockEnd).blockchainInfo;
-      bcd.Block:=opb.block;
-      bcd.Timestamp := opb.timestamp;
-      bcd.BlockProtocolVersion := opb.protocol_version;
-      bcd.BlockProtocolAvailable := opb.protocol_available;
-      bcd.Reward := opb.reward;
-      bcd.Fee := opb.fee;
-      bcd.Target := opb.compact_target;
-      bn := ANode.Bank.SafeBox.CalcBlockHashRateInHs(bcd.Block,FBlockChainGrid.HashRateAverageBlocksCount);
-      try
-        bcd.HashRateHs := bn.Value;
-        bcd.HashRateKhs := bn.Divide(1000).Value;
-      finally
-        bn.Free;
-      end;
-      bn := TBigNum.TargetToHashRate(opb.compact_target);
-      Try
-        bcd.HashRateTargetHs := bn.Value / (CT_NewLineSecondsAvg);
-        bcd.HashRateTargetKhs := bn.Divide(1000).Divide(CT_NewLineSecondsAvg).Value;
-      finally
-        bn.Free;
+    if FPendingOperations then begin
+      for i := Node.Operations.Count - 1 downto 0 do begin
+        Op := Node.Operations.OperationsHashTree.GetOperation(i);
+        If TPCOperation.OperationToOperationResume(0,Op,True,Op.SignerAccount,OPR) then begin
+          OPR.NOpInsideBlock := i;
+          OPR.Block := Node.Bank.BlocksCount;
+          OPR.Balance := Node.Operations.SafeBoxTransaction.Account(Op.SignerAccount).balance;
+          FOperationsResume.Add(OPR);
+        end;
       end;
       end;
-      bcd.MinerPayload := opb.block_payload;
-      bcd.PoW := opb.proof_of_work;
-      bcd.SafeBoxHash := opb.initial_safe_box_hash;
-      bcd.AccumulatedWork := ANode.Bank.SafeBox.Block(bcd.Block).AccumulatedWork;
-      if (Not Terminated) then begin
-        If (ANode.Bank.LoadOperations(opc,ABlockEnd)) then begin
-          bcd.OperationsCount := opc.Count;
-          bcd.Volume := opc.OperationsHashTree.TotalAmount + opc.OperationsHashTree.TotalFee;
+    end else begin
+      if AccountNumber<0 then begin
+        opc := TPCOperationsComp.Create(Nil);
+        try
+          opc.bank := Node.Bank;
+          If FBlockEnd<0 then begin
+            If Node.Bank.BlocksCount>0 then bend := Node.Bank.BlocksCount-1
+            else bend := 0;
+          end else bend := FBlockEnd;
+          if FBlockStart<0 then begin
+            if (bend > 300) then bstart := bend - 300
+            else bstart := 0;
+          end else bstart:= FBlockStart;
+          If bstart<0 then bstart := 0;
+          if bend>=Node.Bank.BlocksCount then bend:=Node.Bank.BlocksCount;
+          while (bstart<=bend) do begin
+            opr := CT_TOperationResume_NUL;
+            if (Node.Bank.Storage.LoadBlockChainBlock(opc,bend)) then begin
+              // Reward operation
+              OPR := CT_TOperationResume_NUL;
+              OPR.valid := true;
+              OPR.Block := bend;
+              OPR.time := opc.OperationBlock.timestamp;
+              OPR.AffectedAccount := bend * CT_AccountsPerBlock;
+              OPR.Amount := opc.OperationBlock.reward;
+              OPR.Fee := opc.OperationBlock.fee;
+              OPR.Balance := OPR.Amount+OPR.Fee;
+              OPR.OperationTxt := 'Blockchain reward';
+              FOperationsResume.Add(OPR);
+              // Reverse operations inside a block
+              for i := opc.Count - 1 downto 0 do begin
+                if TPCOperation.OperationToOperationResume(bend,opc.Operation[i],True,opc.Operation[i].SignerAccount,opr) then begin
+                  opr.NOpInsideBlock := i;
+                  opr.Block := bend;
+                  opr.time := opc.OperationBlock.timestamp;
+                  FOperationsResume.Add(opr);
+                end;
+              end;
+            end else break;
+            dec(bend);
+          end;
+        finally
+          opc.Free;
         end;
         end;
-        bcd.TimeAverage200:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,200);
-        bcd.TimeAverage150:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,150);
-        bcd.TimeAverage100:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,100);
-        bcd.TimeAverage75:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,75);
-        bcd.TimeAverage50:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,50);
-        bcd.TimeAverage25:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,25);
-        bcd.TimeAverage10:=ANode.Bank.GetTargetSecondsAverage(bcd.Block,10);
-        AList.Add(bcd);
-        if (ABlockEnd>0) then dec(ABlockEnd) else Break;
+
+      end else begin
+        list := TList<Cardinal>.Create;
+        Try
+          Node.Operations.OperationsHashTree.GetOperationsAffectingAccount(AccountNumber,list);
+          for i := list.Count - 1 downto 0 do begin
+            Op := Node.Operations.OperationsHashTree.GetOperation((list[i]));
+            If TPCOperation.OperationToOperationResume(0,Op,False,AccountNumber,OPR) then begin
+              OPR.NOpInsideBlock := i;
+              OPR.Block := Node.Operations.OperationBlock.block;
+              OPR.Balance := Node.Operations.SafeBoxTransaction.Account(AccountNumber).balance;
+              FOperationsResume.Add(OPR);
+            end;
+          end;
+        Finally
+          list.Free;
+        End;
+        Node.GetStoredOperationsFromAccount(FOperationsResume,AccountNumber,100,0,5000);
       end;
       end;
     end;
     end;
-  finally
-    opc.Free;
-  end;
+  Finally
+    InitGrid;
+  End;
 end;
 end;
 
 
 { TBlockChainGrid }
 { TBlockChainGrid }
@@ -1188,16 +1003,10 @@ begin
   SetLength(FBlockChainDataArray,0);
   SetLength(FBlockChainDataArray,0);
   FShowTimeAverageColumns:=False;
   FShowTimeAverageColumns:=False;
   FHashRateAs:={$IFDEF PRODUCTION}hr_Giga{$ELSE}hr_Mega{$ENDIF};
   FHashRateAs:={$IFDEF PRODUCTION}hr_Giga{$ELSE}hr_Mega{$ENDIF};
-  FBlockChainGridUpdateThread := Nil;
 end;
 end;
 
 
 destructor TBlockChainGrid.Destroy;
 destructor TBlockChainGrid.Destroy;
 begin
 begin
-  If Assigned(FBlockChainGridUpdateThread) then begin
-    FBlockChainGridUpdateThread.Terminate;
-    FBlockChainGridUpdateThread.WaitFor;
-    FreeAndNil(FBlockChainGridUpdateThread);
-  end;
   FNodeNotifyEvents.OnBlocksChanged := Nil;
   FNodeNotifyEvents.OnBlocksChanged := Nil;
   FNodeNotifyEvents.Node := Nil;
   FNodeNotifyEvents.Node := Nil;
   FreeAndNil(FNodeNotifyEvents);
   FreeAndNil(FNodeNotifyEvents);
@@ -1263,7 +1072,9 @@ Var s : String;
   deviation : Real;
   deviation : Real;
   hr_base : Int64;
   hr_base : Int64;
 begin
 begin
+  {.$IFDEF FPC}
   DrawGrid.Canvas.Font.Color:=clBlack;
   DrawGrid.Canvas.Font.Color:=clBlack;
+  {.$ENDIF}
   if (ARow=0) then begin
   if (ARow=0) then begin
     // Header
     // Header
     case ACol of
     case ACol of
@@ -1474,13 +1285,94 @@ end;
 
 
 
 
 procedure TBlockChainGrid.UpdateBlockChainGrid;
 procedure TBlockChainGrid.UpdateBlockChainGrid;
+Var nstart,nend : Cardinal;
+  opc : TPCOperationsComp;
+  bcd : TBlockChainData;
+  i : Integer;
+  opb : TOperationBlock;
+  bn : TBigNum;
 begin
 begin
-  If Assigned(FBlockChainGridUpdateThread) then begin
-    FBlockChainGridUpdateThread.Terminate;
-    FBlockChainGridUpdateThread.WaitFor;
-    FreeAndNil(FBlockChainGridUpdateThread);
+  if (FBlockStart>FBlockEnd) And (FBlockStart>=0) then FBlockEnd := -1;
+  if (FBlockEnd>=0) And (FBlockEnd<FBlockStart) then FBlockStart:=-1;
+
+  if Not Assigned(FNodeNotifyEvents.Node) then exit;
+
+  if FBlockStart>(FNodeNotifyEvents.Node.Bank.BlocksCount-1) then FBlockStart := -1;
+
+  try
+    if Node.Bank.BlocksCount<=0 then begin
+      SetLength(FBlockChainDataArray,0);
+      exit;
+    end;
+    if (FBlockEnd>=0) And (FBlockEnd<Node.Bank.BlocksCount) then begin
+      nend := FBlockEnd
+    end else begin
+      if (FBlockStart>=0) And (FBlockStart+MaxBlocks<=Node.Bank.BlocksCount) then nend := FBlockStart + MaxBlocks - 1
+      else nend := Node.Bank.BlocksCount-1;
+    end;
+
+    if (FBlockStart>=0) And (FBlockStart<Node.Bank.BlocksCount) then nstart := FBlockStart
+    else begin
+      if nend>MaxBlocks then nstart := nend - MaxBlocks + 1
+      else nstart := 0;
+    end;
+    SetLength(FBlockChainDataArray,nend - nstart +1);
+    opc := TPCOperationsComp.Create(Nil);
+    try
+      opc.bank := Node.Bank;
+      while (nstart<=nend) do begin
+        i := length(FBlockChainDataArray) - (nend-nstart+1);
+        bcd := CT_TBlockChainData_NUL;
+        opb := Node.Bank.SafeBox.Block(nend).blockchainInfo;
+        bcd.Block:=opb.block;
+        bcd.Timestamp := opb.timestamp;
+        bcd.BlockProtocolVersion := opb.protocol_version;
+        bcd.BlockProtocolAvailable := opb.protocol_available;
+        bcd.Reward := opb.reward;
+        bcd.Fee := opb.fee;
+        bcd.Target := opb.compact_target;
+        bn := Node.Bank.SafeBox.CalcBlockHashRateInHs(bcd.Block,HashRateAverageBlocksCount);
+        try
+          bcd.HashRateHs := bn.Value;
+          bcd.HashRateKhs := bn.Divide(1000).Value;
+        finally
+          bn.Free;
+        end;
+        bn := TBigNum.TargetToHashRate(opb.compact_target);
+        Try
+          bcd.HashRateTargetHs := bn.Value / (CT_NewLineSecondsAvg);
+          bcd.HashRateTargetKhs := bn.Divide(1000).Divide(CT_NewLineSecondsAvg).Value;
+        finally
+          bn.Free;
+        end;
+        bcd.MinerPayload := opb.block_payload;
+        bcd.PoW := opb.proof_of_work;
+        bcd.SafeBoxHash := opb.initial_safe_box_hash;
+        bcd.AccumulatedWork := Node.Bank.SafeBox.Block(bcd.Block).AccumulatedWork;
+        if (Node.Bank.LoadOperations(opc,nend)) then begin
+          bcd.OperationsCount := opc.Count;
+          bcd.Volume := opc.OperationsHashTree.TotalAmount + opc.OperationsHashTree.TotalFee;
+        end;
+        bcd.TimeAverage200:=Node.Bank.GetTargetSecondsAverage(bcd.Block,200);
+        bcd.TimeAverage150:=Node.Bank.GetTargetSecondsAverage(bcd.Block,150);
+        bcd.TimeAverage100:=Node.Bank.GetTargetSecondsAverage(bcd.Block,100);
+        bcd.TimeAverage75:=Node.Bank.GetTargetSecondsAverage(bcd.Block,75);
+        bcd.TimeAverage50:=Node.Bank.GetTargetSecondsAverage(bcd.Block,50);
+        bcd.TimeAverage25:=Node.Bank.GetTargetSecondsAverage(bcd.Block,25);
+        bcd.TimeAverage10:=Node.Bank.GetTargetSecondsAverage(bcd.Block,10);
+        FBlockChainDataArray[i] := bcd;
+        if (nend>0) then dec(nend) else break;
+      end;
+    finally
+      opc.Free;
+    end;
+  finally
+    if Assigned(FDrawGrid) then begin
+      if Length(FBlockChainDataArray)>0 then FDrawGrid.RowCount := length(FBlockChainDataArray)+1
+      else FDrawGrid.RowCount := 2;
+      FDrawGrid.Invalidate;
+    end;
   end;
   end;
-  FBlockChainGridUpdateThread := TBlockChainGridUpdateThread.Create(Self);
 end;
 end;
 
 
 end.
 end.