Browse Source

Merge upstream

Herman Schoenfeld 6 years ago
parent
commit
a6e5af1463

+ 19 - 21
PIP/PIP-0027.md

@@ -157,13 +157,11 @@ The following validation rules must be applied to Payload lengths
 
 
 #### Payload Type
 #### Payload Type
 
 
-In order for an operation receiver to **automatically decode** an E-PASA from the raw network payload in the **exact same form** that it was entered by the sender, an additional *PayloadType* field is required for all operations that carry a Payload.
+In order for a recipient of an operation to **automatically** and **deterministically** decode an E-PASA from a raw network payload, the PascalCoin protocol needs additional data to describe the Payload.
 
 
-The PayloadType indicates how the raw network payload was encrypted and has general-purposes usage beyond this PIP.
+This PIP proposes pre-fixing all Payloads in operations with a single-byte value called the **PayloadType**. The PayloadType describes the encryption and encoding of the Payload.
 
 
-For E-PASA, the PayloadType allows the receiver to deterministically and unambiguously derive the E-PASA used by the sender, including the encryption type and payload type (i.e. ascii/hex/base58) as well as if an account name was used instead of an account number.
-
-This capability is fundamental for using E-PASA as an *address-space* in Layer-2 applications. Without this, a Layer-2 application could decode a single raw network payload in a multitude of E-PASA forms breaking the 1-1 relationship necessary to establish uniqueness.
+PayloadType will allow E-PASA's to be deterministically decoded by the recipient and prevent ambiguous decodings.  This capability is fundamental for using E-PASA as an *address-space* since uniqueness requires a 1-1 mapping. With this feature, Layer-2 apps can safely use E-PASA as Layer-2 addresses.
 
 
 #### Payload Type Specification:
 #### Payload Type Specification:
 
 
@@ -172,49 +170,49 @@ This capability is fundamental for using E-PASA as an *address-space* in Layer-2
 	public enum PayloadType {
 	public enum PayloadType {
 
 
 		/// <summary>
 		/// <summary>
-		/// Payload encoding method not specified.
+		/// Payload encryption and encoding method not specified.
 		/// </summary>
 		/// </summary>
 		NonDeterministic = 0x00000000,
 		NonDeterministic = 0x00000000,
 
 
 		/// <summary>
 		/// <summary>
-		/// Not encrypted public payload.
+		/// Unencrypted, public payload.
 		/// </summary>
 		/// </summary>
 		Public = 0x00000001,
 		Public = 0x00000001,
 
 
 		/// <summary>
 		/// <summary>
-		/// Encrypted using recipient accounts public key.
+		/// ECIES encrypted using recipient accounts public key.
 		/// </summary>		
 		/// </summary>		
 		RecipientKeyEncrypted = 0x00000010,
 		RecipientKeyEncrypted = 0x00000010,
 
 
 		/// <summary>
 		/// <summary>
-		/// Encrypted using sender accounts public key.
+		/// ECIES encrypted using sender accounts public key.
 		/// </summary>
 		/// </summary>
 		SenderKeyEncrypted = 0x00000100,
 		SenderKeyEncrypted = 0x00000100,
 
 
 		/// <summary>
 		/// <summary>
-		/// Encrypted data using pwd param
+		/// AES encrypted using pwd param
 		/// </summary>
 		/// </summary>
-		AESEncrypted = 0x00001000,
+		PasswordEncrypted = 0x00001000,
 
 
 		/// <summary>
 		/// <summary>
-		/// Payload data is ASCII
+		/// Payload data encoded in ASCII
 		/// </summary>
 		/// </summary>
-		AsciiFormatted = 0x0001000,
+		AsciiFormatted = 0x00010000,
 
 
 		/// <summary>
 		/// <summary>
-		/// Payload data is HEX
+		/// Payload data encoded in HEX
 		/// </summary>
 		/// </summary>
-		HexFormatted = 0x0010000,
+		HexFormatted = 0x00100000,
 
 
 		/// <summary>
 		/// <summary>
-		/// Payload data is Base58
+		/// Payload data encoded in Base58
 		/// </summary>
 		/// </summary>
-		Base58Formatted = 0x0100000,
+		Base58Formatted = 0x01000000,
 
 
 		/// <summary>
 		/// <summary>
-		/// E-Pasa encoding uses account name
+		/// E-PASA addressed by account name (not number).
 		/// </summary>
 		/// </summary>
-		AddressedByName = 0x1000000,
+		AddressedByName = 0x10000000,
 
 
 	}
 	}
 ```
 ```
@@ -469,7 +467,7 @@ After matching with the above regex, the named groups need to be extracted and v
 					errorCode = EPasaErrorCode.MismatchedPayloadEncoding;
 					errorCode = EPasaErrorCode.MismatchedPayloadEncoding;
 					return false;
 					return false;
 				}
 				}
-				epasa.PayloadType = epasa.PayloadType | PayloadType.AESEncrypted;
+				epasa.PayloadType = epasa.PayloadType | PayloadType.PasswordEncrypted;
 				break;
 				break;
 			default:
 			default:
 				throw new NotSupportedException($"Unrecognized start character '{payloadStartChar}'");
 				throw new NotSupportedException($"Unrecognized start character '{payloadStartChar}'");
@@ -477,7 +475,7 @@ After matching with the above regex, the named groups need to be extracted and v
 		}
 		}
  
  
 		// Password
 		// Password
-		if (epasa.PayloadType.HasFlag(PayloadType.AESEncrypted)) {
+		if (epasa.PayloadType.HasFlag(PayloadType.PasswordEncrypted)) {
 			if (payloadPasswordDelim == null) {
 			if (payloadPasswordDelim == null) {
 				errorCode = EPasaErrorCode.MissingPassword;
 				errorCode = EPasaErrorCode.MissingPassword;
 				return false;
 				return false;

+ 1 - 1
src/core/UConst.pas

@@ -173,7 +173,7 @@ Const
   CT_OpSubtype_Data_Signer                = 103;
   CT_OpSubtype_Data_Signer                = 103;
   CT_OpSubtype_Data_Receiver              = 104;
   CT_OpSubtype_Data_Receiver              = 104;
 
 
-  CT_ClientAppVersion : String = {$IFDEF PRODUCTION}'4.0.3b'{$ELSE}{$IFDEF TESTNET}'TESTNET 4.0.3b'{$ELSE}{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : String = {$IFDEF PRODUCTION}'4.0.3c'{$ELSE}{$IFDEF TESTNET}'TESTNET 4.0.3c'{$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'
   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};
                     {$ELSE}'pascaltestnet1.dynamic-dns.net;pascaltestnet2.dynamic-dns.net;pascaltestnet1.dns1.us;pascaltestnet2.dns1.us'{$ENDIF};

+ 1 - 1
src/core/UNetProtocol.pas

@@ -2630,7 +2630,7 @@ begin
   If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
   If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
     and (TPlatform.GetElapsedMilliseconds(FLastHelloTS)>(1000*FRandomWaitSecondsSendHello)) then begin
     and (TPlatform.GetElapsedMilliseconds(FLastHelloTS)>(1000*FRandomWaitSecondsSendHello)) then begin
     iPending := TNetData.NetData.PendingRequest(Self,ops);
     iPending := TNetData.NetData.PendingRequest(Self,ops);
-    If iPending>=2 then begin
+    If iPending>=3 then begin
       TLog.NewLog(ltDebug,Classname,'Pending requests without response... closing connection to '+ClientRemoteAddr+' > '+ops);
       TLog.NewLog(ltDebug,Classname,'Pending requests without response... closing connection to '+ClientRemoteAddr+' > '+ops);
       Connected := false;
       Connected := false;
     end else begin
     end else begin

+ 7 - 1
src/core/UPCOperationsSignatureValidator.pas

@@ -310,13 +310,19 @@ end;
 
 
 procedure TPCOperationsSignatureValidatorThread.BCExecute;
 procedure TPCOperationsSignatureValidatorThread.BCExecute;
 var LOperation : TPCOperation;
 var LOperation : TPCOperation;
+    LIsValid : Boolean;
 begin
 begin
   repeat
   repeat
     LOperation := FValidator.GetNextOperation(Self);
     LOperation := FValidator.GetNextOperation(Self);
     if Assigned(LOperation) then begin
     if Assigned(LOperation) then begin
       if Not LOperation.HasValidSignature then begin
       if Not LOperation.HasValidSignature then begin
         // Only will validate if HasValidSignature is False (Not validated before)
         // Only will validate if HasValidSignature is False (Not validated before)
-        FValidator.SetOperationCheckResult(Self,LOperation, LOperation.IsValidSignatureBasedOnCurrentSafeboxState(FValidator.FSafeBoxTransaction));
+        try
+          LIsValid := LOperation.IsValidSignatureBasedOnCurrentSafeboxState(FValidator.FSafeBoxTransaction);
+        except
+          LIsValid := False;
+        end;
+        FValidator.SetOperationCheckResult(Self,LOperation, LIsValid);
       end;
       end;
     end;
     end;
   until (Not Assigned(LOperation)) or (Terminated);
   until (Not Assigned(LOperation)) or (Terminated);

+ 6 - 1
src/gui-classic/UFRMWallet.pas

@@ -275,6 +275,7 @@ type
     FMustProcessWalletChanged : Boolean;
     FMustProcessWalletChanged : Boolean;
     FMustProcessNetConnectionUpdated : Boolean;
     FMustProcessNetConnectionUpdated : Boolean;
     FThreadActivate : TObject;
     FThreadActivate : TObject;
+    FLastAccountsGridInvalidateTC : TTickCount;
     Procedure OnNewAccount(Sender : TObject);
     Procedure OnNewAccount(Sender : TObject);
     Procedure OnReceivedHelloMessage(Sender : TObject);
     Procedure OnReceivedHelloMessage(Sender : TObject);
     Procedure OnNetStatisticsChanged(Sender : TObject);
     Procedure OnNetStatisticsChanged(Sender : TObject);
@@ -1117,6 +1118,7 @@ begin
   {$IFDEF TESTNET}
   {$IFDEF TESTNET}
   FLastAskForAccountTC := 0;
   FLastAskForAccountTC := 0;
   {$ENDIF}
   {$ENDIF}
+  FLastAccountsGridInvalidateTC := TPlatform.GetTickCount;
   FLastNodesCacheUpdatedTS := Now;
   FLastNodesCacheUpdatedTS := Now;
   FBackgroundPanel := Nil;
   FBackgroundPanel := Nil;
   FBackgroundLabel := Nil;
   FBackgroundLabel := Nil;
@@ -2045,7 +2047,10 @@ begin
   if Not Assigned(FNode) then Exit;
   if Not Assigned(FNode) then Exit;
 
 
   if Not RefreshData then begin
   if Not RefreshData then begin
-    dgAccounts.Invalidate;
+    if TPlatform.GetElapsedMilliseconds(FLastAccountsGridInvalidateTC)>1000 then begin
+      FLastAccountsGridInvalidateTC := TPlatform.GetTickCount;
+      dgAccounts.Invalidate;
+    end;
     exit;
     exit;
   end;
   end;
   LApplyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or ((FMaxAccountBalance<CT_MaxWalletAmount) and (FMaxAccountBalance>=0)));
   LApplyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or ((FMaxAccountBalance<CT_MaxWalletAmount) and (FMaxAccountBalance>=0)));

+ 73 - 42
src/gui-classic/UGridUtils.pas

@@ -57,6 +57,7 @@ Type
     FAccountsGridFilter : TAccountsGridFilter;
     FAccountsGridFilter : TAccountsGridFilter;
     FBalance : Int64;
     FBalance : Int64;
     FIsProcessing : Boolean;
     FIsProcessing : Boolean;
+    FProcessedList : TOrderedCardinalList;
   protected
   protected
     procedure SynchronizedOnTerminated;
     procedure SynchronizedOnTerminated;
     procedure BCExecute; override;
     procedure BCExecute; override;
@@ -81,8 +82,15 @@ Type
     FAccountsGridFilter: TAccountsGridFilter;
     FAccountsGridFilter: TAccountsGridFilter;
     FOnAccountsGridUpdatedData: TNotifyEvent;
     FOnAccountsGridUpdatedData: TNotifyEvent;
     FAccountsGridDatasource: TAccountsGridDatasource;
     FAccountsGridDatasource: TAccountsGridDatasource;
+    //
+    FBufferLastAccountNumber : Integer;
+    FBufferLastAccount : TAccount;
+    FBufferNodeAccountsCount : Integer;
+    FBufferNodeBlocksCount : Integer;
+    //
     procedure SetDrawGrid(const Value: TDrawGrid);
     procedure SetDrawGrid(const Value: TDrawGrid);
     Procedure InitGrid;
     Procedure InitGrid;
+    Procedure InitGridRowCount;
     Procedure OnNodeNewOperation(Sender : TObject);
     Procedure OnNodeNewOperation(Sender : TObject);
     procedure OnGridDrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
     procedure OnGridDrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
     procedure SetNode(const Value: TNode);
     procedure SetNode(const Value: TNode);
@@ -95,6 +103,7 @@ Type
     procedure UpdateAccountsBalance;
     procedure UpdateAccountsBalance;
   protected
   protected
     procedure Notification(AComponent: TComponent; Operation: TOperation); Override;
     procedure Notification(AComponent: TComponent; Operation: TOperation); Override;
+    procedure BufferGetAccount(AAccountNumber : Integer; var AAccount : TAccount; var ANodeBlocksCount, ANodeAccountsCount : Integer);
   public
   public
     Constructor Create(AOwner : TComponent); override;
     Constructor Create(AOwner : TComponent); override;
     Destructor Destroy; override;
     Destructor Destroy; override;
@@ -271,7 +280,7 @@ uses
 { TAccountsGridUpdateThread }
 { TAccountsGridUpdateThread }
 
 
 procedure TAccountsGridUpdateThread.BCExecute;
 procedure TAccountsGridUpdateThread.BCExecute;
-Var Laccl, LacclTemp : TOrderedCardinalList;
+Var
   l : TOrderedCardinalList;
   l : TOrderedCardinalList;
   i,j : Integer;
   i,j : Integer;
   c  : Cardinal;
   c  : Cardinal;
@@ -283,10 +292,6 @@ begin
   FBalance := 0;
   FBalance := 0;
   LNode := FAccountsGrid.Node;
   LNode := FAccountsGrid.Node;
   try
   try
-    Laccl := TOrderedCardinalList.Create;
-    Try
-      Laccl.Clear;
-
       if (Assigned(FAccountsGridFilter.OrderedAccountsKeyList)) then begin
       if (Assigned(FAccountsGridFilter.OrderedAccountsKeyList)) then begin
         if (FAccountsGridFilter.indexAccountsKeyList<0) then i := 0
         if (FAccountsGridFilter.indexAccountsKeyList<0) then i := 0
         else i := FAccountsGridFilter.indexAccountsKeyList;
         else i := FAccountsGridFilter.indexAccountsKeyList;
@@ -302,11 +307,11 @@ begin
               LAccount := LNode.Bank.SafeBox.Account(l.Get(j));
               LAccount := LNode.Bank.SafeBox.Account(l.Get(j));
               if LApplyfilter then begin
               if LApplyfilter then begin
                 if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
                 if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
-                  Laccl.Add(LAccount.account);
+                  FProcessedList.Add(LAccount.account);
                   FBalance := FBalance + LAccount.balance;
                   FBalance := FBalance + LAccount.balance;
                 end;
                 end;
               end else begin
               end else begin
-                Laccl.Add(LAccount.account);
+                FProcessedList.Add(LAccount.account);
                 FBalance := FBalance + LAccount.balance;
                 FBalance := FBalance + LAccount.balance;
               end;
               end;
               if Terminated then Exit;
               if Terminated then Exit;
@@ -322,26 +327,12 @@ begin
         while (c<LNode.Bank.SafeBox.AccountsCount) and (Not Terminated) do begin
         while (c<LNode.Bank.SafeBox.AccountsCount) and (Not Terminated) do begin
           LAccount := LNode.Bank.SafeBox.Account(c);
           LAccount := LNode.Bank.SafeBox.Account(c);
           if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
           if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
-            Laccl.Add(LAccount.account);
+            FProcessedList.Add(LAccount.account);
             FBalance := FBalance + LAccount.balance;
             FBalance := FBalance + LAccount.balance;
           end;
           end;
           inc(c);
           inc(c);
         end;
         end;
       end;
       end;
-    Finally
-      try
-        if Not Terminated then begin
-          LacclTemp := FAccountsGrid.LockAccountsList;
-          try
-            LacclTemp.CopyFrom(Laccl);
-          finally
-            FAccountsGrid.UnlockAccountsList;
-          end;
-        end;
-      finally
-        Laccl.Free;
-      end;
-    End;
   Finally
   Finally
     FisProcessing := False;
     FisProcessing := False;
     if Not Terminated then
     if Not Terminated then
@@ -356,18 +347,29 @@ begin
   FAccountsGrid := AAccountsGrid;
   FAccountsGrid := AAccountsGrid;
   FAccountsGridFilter := AAccountsGridFilter;
   FAccountsGridFilter := AAccountsGridFilter;
   FisProcessing := True;
   FisProcessing := True;
+  FProcessedList := TOrderedCardinalList.Create;
   Suspended := False;
   Suspended := False;
 end;
 end;
 
 
 destructor TAccountsGridUpdateThread.Destroy;
 destructor TAccountsGridUpdateThread.Destroy;
 begin
 begin
+  FreeAndNil(FProcessedList);
   inherited;
   inherited;
 end;
 end;
 
 
 procedure TAccountsGridUpdateThread.SynchronizedOnTerminated;
 procedure TAccountsGridUpdateThread.SynchronizedOnTerminated;
+var LacclTemp : TOrderedCardinalList;
 begin
 begin
-  FAccountsGrid.FAccountsBalance := FBalance;
-  if Assigned(FAccountsGrid.FOnAccountsGridUpdatedData) then  FAccountsGrid.FOnAccountsGridUpdatedData(FAccountsGrid);
+  if Not Terminated then begin
+    FAccountsGrid.FAccountsBalance := FBalance;
+    LacclTemp := FAccountsGrid.LockAccountsList;
+    try
+      LacclTemp.CopyFrom( FProcessedList );
+    finally
+      FAccountsGrid.UnlockAccountsList;
+    end;
+    if Assigned(FAccountsGrid.FOnAccountsGridUpdatedData) then  FAccountsGrid.FOnAccountsGridUpdatedData(FAccountsGrid);
+  end;
 end;
 end;
 
 
 { TAccountsGrid }
 { TAccountsGrid }
@@ -387,6 +389,21 @@ begin
   end else Result := -1;
   end else Result := -1;
 end;
 end;
 
 
+procedure TAccountsGrid.BufferGetAccount(AAccountNumber: Integer;
+  var AAccount: TAccount; var ANodeBlocksCount, ANodeAccountsCount: Integer);
+begin
+  if FBufferLastAccountNumber<>AAccountNumber then begin
+    FBufferNodeAccountsCount := Node.Bank.AccountsCount;
+    if (AAccountNumber>=FBufferNodeAccountsCount) then FBufferLastAccount := CT_Account_NUL
+    else FBufferLastAccount := Node.GetMempoolAccount(AAccountNumber);
+    FBufferNodeBlocksCount := Node.Bank.BlocksCount;
+    FBufferLastAccountNumber := AAccountNumber;
+  end;
+  AAccount := FBufferLastAccount;
+  ANodeBlocksCount := FBufferNodeBlocksCount;
+  ANodeAccountsCount := FBufferNodeAccountsCount;
+end;
+
 constructor TAccountsGrid.Create(AOwner: TComponent);
 constructor TAccountsGrid.Create(AOwner: TComponent);
 Var i : Integer;
 Var i : Integer;
 begin
 begin
@@ -417,6 +434,7 @@ begin
   FOnAccountsGridUpdatedData := Nil;
   FOnAccountsGridUpdatedData := Nil;
   FAccountsGridFilter := CT_TAccountsGridFilter_NUL;
   FAccountsGridFilter := CT_TAccountsGridFilter_NUL;
   FAccountsGridDatasource := acds_Node;
   FAccountsGridDatasource := acds_Node;
+  FBufferLastAccountNumber := -1;
 end;
 end;
 
 
 destructor TAccountsGrid.Destroy;
 destructor TAccountsGrid.Destroy;
@@ -430,7 +448,7 @@ end;
 function TAccountsGrid.GetAccountsCount: Integer;
 function TAccountsGrid.GetAccountsCount: Integer;
 begin
 begin
   if Not Assigned(Node) then Exit(0);
   if Not Assigned(Node) then Exit(0);
-  
+
   case FAccountsGridDatasource of
   case FAccountsGridDatasource of
     acds_Node: Result := Node.Bank.AccountsCount;
     acds_Node: Result := Node.Bank.AccountsCount;
   else
   else
@@ -447,15 +465,7 @@ procedure TAccountsGrid.InitGrid;
 Var i : Integer;
 Var i : Integer;
 begin
 begin
   if Not assigned(DrawGrid) then exit;
   if Not assigned(DrawGrid) then exit;
-  if FAccountsGridDatasource=acds_Node then begin
-    if Assigned(Node) then begin
-      if Node.Bank.AccountsCount<1 then DrawGrid.RowCount := 2
-      else DrawGrid.RowCount := Node.Bank.AccountsCount+1;
-    end else DrawGrid.RowCount := 2;
-  end else begin
-    if FAccountsList.Count<1 then DrawGrid.RowCount := 2
-    else DrawGrid.RowCount := FAccountsList.Count+1;
-  end;
+  InitGridRowCount;
   DrawGrid.FixedRows := 1;
   DrawGrid.FixedRows := 1;
   if Length(FColumns)=0 then DrawGrid.ColCount := 1
   if Length(FColumns)=0 then DrawGrid.ColCount := 1
   else DrawGrid.ColCount := Length(FColumns);
   else DrawGrid.ColCount := Length(FColumns);
@@ -469,10 +479,29 @@ begin
     {goColMoving, goEditing, }goTabs, goRowSelect, {goAlwaysShowEditor,}
     {goColMoving, goEditing, }goTabs, goRowSelect, {goAlwaysShowEditor,}
     goThumbTracking{$IFnDEF FPC}, goFixedColClick, goFixedRowClick, goFixedHotTrack{$ENDIF}];
     goThumbTracking{$IFnDEF FPC}, goFixedColClick, goFixedRowClick, goFixedHotTrack{$ENDIF}];
   if FAllowMultiSelect then DrawGrid.Options := DrawGrid.Options + [goRangeSelect];
   if FAllowMultiSelect then DrawGrid.Options := DrawGrid.Options + [goRangeSelect];
+  FBufferLastAccountNumber := -1;
   FDrawGrid.Invalidate;
   FDrawGrid.Invalidate;
   if Assigned(FOnUpdated) then FOnUpdated(Self);
   if Assigned(FOnUpdated) then FOnUpdated(Self);
 end;
 end;
 
 
+procedure TAccountsGrid.InitGridRowCount;
+var LRowCount : Integer;
+begin
+  if Not assigned(DrawGrid) then exit;
+  if FAccountsGridDatasource=acds_Node then begin
+    if Assigned(Node) then begin
+      if Node.Bank.AccountsCount<1 then LRowCount := 2
+      else LRowCount := Node.Bank.AccountsCount+1;
+    end else LRowCount := 2;
+  end else begin
+    if FAccountsList.Count<1 then LRowCount := 2
+    else LRowCount := FAccountsList.Count+1;
+  end;
+  if DrawGrid.RowCount<>LRowCount then DrawGrid.RowCount:=LRowCount;
+  FBufferLastAccountNumber := -1;
+  FDrawGrid.Invalidate;
+end;
+
 function TAccountsGrid.IsUpdatingData: Boolean;
 function TAccountsGrid.IsUpdatingData: Boolean;
 begin
 begin
   if Assigned(FAccountsGridUpdateThread) then Result := FAccountsGridUpdateThread.IsProcessing
   if Assigned(FAccountsGridUpdateThread) then Result := FAccountsGridUpdateThread.IsProcessing
@@ -588,7 +617,8 @@ Begin
 end;
 end;
 {$ENDIF}
 {$ENDIF}
 
 
-procedure TAccountsGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
+procedure TAccountsGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Longint;
+  Rect: TRect; State: TGridDrawState);
   Function FromColorToColor(colorstart,colordest : Integer; step,totalsteps : Integer) : Integer;
   Function FromColorToColor(colorstart,colordest : Integer; step,totalsteps : Integer) : Integer;
   var sr,sg,sb,dr,dg,db : Byte;
   var sr,sg,sb,dr,dg,db : Byte;
     i : Integer;
     i : Integer;
@@ -611,6 +641,7 @@ Var C : TAccountColumn;
   n_acc : Int64;
   n_acc : Int64;
   account : TAccount;
   account : TAccount;
   ndiff : Cardinal;
   ndiff : Cardinal;
+  LNodeBlocksCount,LNodeAccountsCount : Integer;
 begin
 begin
   if Not Assigned(Node) then exit;
   if Not Assigned(Node) then exit;
 
 
@@ -628,9 +659,8 @@ begin
   end else begin
   end else begin
     n_acc := AccountNumber(ARow);
     n_acc := AccountNumber(ARow);
     if (n_acc>=0) then begin
     if (n_acc>=0) then begin
-      if (n_acc>=Node.Bank.AccountsCount) then account := CT_Account_NUL
-      else account := Node.GetMempoolAccount(n_acc);
-      ndiff := Node.Bank.BlocksCount - account.updated_block;
+      BufferGetAccount(n_acc,account,LNodeBlocksCount,LNodeAccountsCount);
+      ndiff := LNodeBlocksCount - account.updated_block;
       if (gdSelected in State) then
       if (gdSelected in State) then
         If (gdFocused in State) then DrawGrid.Canvas.Brush.Color := clGradientActiveCaption
         If (gdFocused in State) then DrawGrid.Canvas.Brush.Color := clGradientActiveCaption
         else DrawGrid.Canvas.Brush.Color := clGradientInactiveCaption
         else DrawGrid.Canvas.Brush.Color := clGradientInactiveCaption
@@ -668,7 +698,7 @@ begin
           Canvas_TextRect(DrawGrid.Canvas,Rect,s,State,[tfRight,tfVerticalCenter,tfSingleLine]);
           Canvas_TextRect(DrawGrid.Canvas,Rect,s,State,[tfRight,tfVerticalCenter,tfSingleLine]);
         End;
         End;
         act_updated_state : Begin
         act_updated_state : Begin
-          if TAccountComp.IsAccountBlockedByProtocol(account.account,Node.Bank.BlocksCount) then begin
+          if TAccountComp.IsAccountBlockedByProtocol(account.account,LNodeBlocksCount) then begin
             DrawGrid.Canvas.Brush.Color := clRed;
             DrawGrid.Canvas.Brush.Color := clRed;
           end else if ndiff=0 then begin
           end else if ndiff=0 then begin
             DrawGrid.Canvas.Brush.Color := RGB(255,128,0);
             DrawGrid.Canvas.Brush.Color := RGB(255,128,0);
@@ -692,7 +722,7 @@ begin
             // Show price for sale
             // Show price for sale
             s := TAccountComp.FormatMoney(account.accountInfo.price);
             s := TAccountComp.FormatMoney(account.accountInfo.price);
             if TAccountComp.IsAccountForSaleAcceptingTransactions(account.accountInfo) then begin
             if TAccountComp.IsAccountForSaleAcceptingTransactions(account.accountInfo) then begin
-              if TAccountComp.IsAccountLocked(account.accountInfo,Node.Bank.BlocksCount) then begin
+              if TAccountComp.IsAccountLocked(account.accountInfo,LNodeBlocksCount) then begin
                 DrawGrid.Canvas.Font.Color := clNavy;
                 DrawGrid.Canvas.Font.Color := clNavy;
               end else begin
               end else begin
                 DrawGrid.Canvas.Font.Color := clRed;
                 DrawGrid.Canvas.Font.Color := clRed;
@@ -713,6 +743,7 @@ end;
 
 
 procedure TAccountsGrid.OnNodeNewOperation(Sender: TObject);
 procedure TAccountsGrid.OnNodeNewOperation(Sender: TObject);
 begin
 begin
+  FBufferLastAccountNumber := -1;
   If Assigned(FDrawGrid) then FDrawGrid.Invalidate;
   If Assigned(FDrawGrid) then FDrawGrid.Invalidate;
 end;
 end;
 
 
@@ -804,7 +835,7 @@ end;
 procedure TAccountsGrid.UnlockAccountsList;
 procedure TAccountsGrid.UnlockAccountsList;
 begin
 begin
   UpdateAccountsBalance;
   UpdateAccountsBalance;
-  InitGrid;
+  InitGridRowCount;
 end;
 end;
 
 
 procedure TAccountsGrid.UpdateAccountsBalance;
 procedure TAccountsGrid.UpdateAccountsBalance;
@@ -837,7 +868,7 @@ begin
       end;
       end;
     end;
     end;
   end;
   end;
-  InitGrid;
+  InitGridRowCount;
   if Assigned(FOnAccountsGridUpdatedData) then FOnAccountsGridUpdatedData(Self);
   if Assigned(FOnAccountsGridUpdatedData) then FOnAccountsGridUpdatedData(Self);
 end;
 end;