Browse Source

Moving Ordered lists to UPCOrderedLists.pas

Created new unit UPCOrderedLists that will store ordered lists objects
PascalCoin 6 years ago
parent
commit
c13ebb15d0

+ 1 - 445
src/core/UAccounts.pas

@@ -23,7 +23,7 @@ unit UAccounts;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, UConst, UCrypto, SyncObjs, UThread, UBaseTypes;
+  Classes, SysUtils, UConst, UCrypto, SyncObjs, UThread, UBaseTypes, UPCOrderedLists;
 
 
 {$I config.inc}
 {$I config.inc}
 
 
@@ -157,37 +157,12 @@ Type
     Class Function AccountToTxt(const Account : TAccount) : AnsiString;
     Class Function AccountToTxt(const Account : TAccount) : AnsiString;
   End;
   End;
 
 
-  TCardinalsArray = Array of Cardinal;
-
   { Estimated TAccount size:
   { Estimated TAccount size:
     4 + 200 (max aprox) + 8 + 4 + 4 = 220 max aprox
     4 + 200 (max aprox) + 8 + 4 + 4 = 220 max aprox
     Estimated TBlockAccount size:
     Estimated TBlockAccount size:
     4 + (5 * 220) + 4 + 32 = 1140 max aprox
     4 + (5 * 220) + 4 + 32 = 1140 max aprox
   }
   }
 
 
-  TOrderedCardinalList = Class
-  private
-    FOrderedList : TList;
-    FDisabledsCount : Integer;
-    FModifiedWhileDisabled : Boolean;
-    FOnListChanged: TNotifyEvent;
-    Procedure NotifyChanged;
-  public
-    Constructor Create;
-    Destructor Destroy; override;
-    Function Add(Value : Cardinal) : Integer;
-    Procedure Remove(Value : Cardinal);
-    Procedure Clear;
-    Function Get(index : Integer) : Cardinal;
-    Function Count : Integer;
-    Function Find(const Value: Cardinal; var Index: Integer): Boolean;
-    Procedure Disable;
-    Procedure Enable;
-    Property OnListChanged : TNotifyEvent read FOnListChanged write FOnListChanged;
-    Procedure CopyFrom(Sender : TOrderedCardinalList);
-    Function ToArray : TCardinalsArray;
-  End;
-
   TPCSafeBox = Class;
   TPCSafeBox = Class;
   TPCSafeBoxHeader = Record
   TPCSafeBoxHeader = Record
     protocol : Word;
     protocol : Word;
@@ -238,51 +213,6 @@ Type
     procedure CopyFrom(const source : TOrderedAccountKeysList);
     procedure CopyFrom(const source : TOrderedAccountKeysList);
   End;
   End;
 
 
-  // Maintans a Cardinal ordered (without duplicates) list with TRawData each
-
-  { TOrderedCardinalListWithRaw }
-
-  TOrderedCardinalListWithRaw = Class
-  private
-    FList : TList;
-    Function Find(value : Cardinal; var Index: Integer): Boolean;
-  public
-    Constructor Create;
-    Destructor Destroy; Override;
-    Procedure Clear;
-    Function Add(const Value: Cardinal; const RawData : TRawBytes) : Integer;
-    Function Count : Integer;
-    Function GetCardinal(index : Integer) : Cardinal;
-    function GetRaw(index : Integer) : TRawBytes;
-    Procedure Delete(index : Integer);
-    Function IndexOf(value : Cardinal) : Integer;
-    Function IndexOfRaw(const RawData : TRawBytes) : Integer;
-  end;
-
-  // Maintains a TRawBytes (AnsiString) list ordered to quick search withoud duplicates
-
-  { TOrderedRawList }
-
-  TOrderedRawList = Class
-  private
-    FList : TList;
-    Function Find(const RawData: TRawBytes; var Index: Integer): Boolean;
-  public
-    Constructor Create;
-    Destructor Destroy; Override;
-    Procedure Clear;
-    Function Add(Const RawData : TRawBytes; tagValue : Integer = 0) : Integer;
-    Procedure Remove(Const RawData : TRawBytes);
-    Function Count : Integer;
-    Function Get(index : Integer) : TRawBytes;
-    Procedure Delete(index : Integer);
-    procedure SetTag(Const RawData : TRawBytes; newTagValue : Integer);
-    function GetTag(Const RawData : TRawBytes) : Integer; overload;
-    function GetTag(index : Integer) : Integer; overload;
-    Function IndexOf(Const RawData : TRawBytes) : Integer;
-    Procedure CopyFrom(master : TOrderedRawList);
-  End;
-
   // SafeBox is a box that only can be updated using SafeBoxTransaction, and this
   // SafeBox is a box that only can be updated using SafeBoxTransaction, and this
   // happens only when a new BlockChain is included. After this, a new "SafeBoxHash"
   // happens only when a new BlockChain is included. After this, a new "SafeBoxHash"
   // is created, so each SafeBox has a unique SafeBoxHash
   // is created, so each SafeBox has a unique SafeBoxHash
@@ -5218,379 +5148,5 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TOrderedCardinalList }
-
-function TOrderedCardinalList.Add(Value: Cardinal): Integer;
-var nc : Integer;
-begin
-  if Find(Value,Result) then exit
-  else begin
-    nc := FOrderedList.Capacity;
-    if (nc <= FOrderedList.Count) then begin
-      nc := nc SHL 1;
-      if (nc > FOrderedList.Capacity) then begin
-        {$IFDEF HIGHLOG}TLog.NewLog(ltdebug,ClassName,Format('Increase capacity from %d to %d for %s',[FOrderedList.Capacity,nc,IntToHex(Integer(FOrderedList),8)]));{$ENDIF}
-        FOrderedList.Capacity:=nc;
-      end;
-    end;
-    FOrderedList.Insert(Result,TObject(Value));
-    NotifyChanged;
-  end;
-end;
-
-procedure TOrderedCardinalList.Clear;
-begin
-  FOrderedList.Clear;
-  NotifyChanged;
-end;
-
-procedure TOrderedCardinalList.CopyFrom(Sender: TOrderedCardinalList);
-Var i : Integer;
-begin
-  if Self=Sender then exit;
-  Disable;
-  Try
-    Clear;
-    FOrderedList.Capacity:=Sender.FOrderedList.Capacity;
-    for I := 0 to Sender.Count - 1 do begin
-      Add(Sender.Get(i));
-    end;
-  Finally
-    Enable;
-  End;
-end;
-
-function TOrderedCardinalList.Count: Integer;
-begin
-  Result := FOrderedList.Count;
-end;
-
-constructor TOrderedCardinalList.Create;
-begin
-  FOrderedList := TList.Create;
-  FDisabledsCount := 0;
-  FModifiedWhileDisabled := false;
-end;
-
-destructor TOrderedCardinalList.Destroy;
-begin
-  FOrderedList.Free;
-  inherited;
-end;
-
-procedure TOrderedCardinalList.Disable;
-begin
-  inc(FDisabledsCount);
-end;
-
-procedure TOrderedCardinalList.Enable;
-begin
-  if FDisabledsCount<=0 then raise Exception.Create('Dev error. Invalid disabled counter');
-  dec(FDisabledsCount);
-  if (FDisabledsCount=0) And (FModifiedWhileDisabled) then NotifyChanged;
-end;
-
-function TOrderedCardinalList.Find(const Value: Cardinal; var Index: Integer): Boolean;
-var L, H, I: Integer;
-  C : Int64;
-begin
-  Result := False;
-  L := 0;
-  H := FOrderedList.Count - 1;
-  // Optimization when inserting always a ordered list
-  if (H>0) then begin
-    C := Int64(FOrderedList[H]) - Int64(Value);
-    if (C<0) then begin
-      Index := H+1;
-      Exit;
-    end else if (C=0) then begin
-      Index := H;
-      Result := True;
-      Exit;
-    end;
-  end;
-  while L <= H do
-  begin
-    I := (L + H) shr 1;
-    C := Int64(FOrderedList[I]) - Int64(Value);
-    if C < 0 then L := I + 1 else
-    begin
-      H := I - 1;
-      if C = 0 then
-      begin
-        Result := True;
-        L := I;
-      end;
-    end;
-  end;
-  Index := L;
-end;
-
-function TOrderedCardinalList.Get(index: Integer): Cardinal;
-begin
-  Result := Cardinal(FOrderedList[index]);
-end;
-
-procedure TOrderedCardinalList.NotifyChanged;
-begin
-  if FDisabledsCount>0 then begin
-    FModifiedWhileDisabled := true;
-    exit;
-  end;
-  FModifiedWhileDisabled := false;
-  if Assigned(FOnListChanged) then FOnListChanged(Self);
-end;
-
-procedure TOrderedCardinalList.Remove(Value: Cardinal);
-Var i : Integer;
-begin
-  if Find(Value,i) then begin
-    FOrderedList.Delete(i);
-    NotifyChanged;
-  end;
-end;
-
-Function TOrderedCardinalList.ToArray : TCardinalsArray;
-var i : integer;
-begin
-  SetLength(Result, self.Count);
-  for i := 0 to self.Count - 1 do
-    Result[i] := Self.Get(i);
-end;
-
-{ TOrderedRawList }
-
-Type TRawListData = Record
-    RawData : TRawBytes;
-    tag : Integer;
-  End;
-  PRawListData = ^TRawListData;
-
-function TOrderedRawList.Add(const RawData: TRawBytes; tagValue : Integer = 0) : Integer;
-Var P : PRawListData;
-begin
-  if Find(RawData,Result) then begin
-    PRawListData(FList[Result])^.tag := tagValue;
-  end else begin
-    New(P);
-    P^.RawData := RawData;
-    P^.tag := tagValue;
-    FList.Insert(Result,P);
-  end;
-end;
-
-procedure TOrderedRawList.Remove(const RawData: TRawBytes);
-Var i : Integer;
-begin
-  i := IndexOf(RawData);
-  If i>=0 then Delete(i);
-end;
-
-procedure TOrderedRawList.Clear;
-Var P : PRawListData;
-  i : Integer;
-begin
-  for i := FList.Count - 1 downto 0 do begin
-    P := FList[i];
-    Dispose(P);
-  end;
-  FList.Clear;
-end;
-
-function TOrderedRawList.Count: Integer;
-begin
-  Result := FList.Count;
-end;
-
-constructor TOrderedRawList.Create;
-begin
-  FList := TList.Create;
-end;
-
-procedure TOrderedRawList.Delete(index: Integer);
-Var P : PRawListData;
-begin
-  P := PRawListData(FList[index]);
-  FList.Delete(index);
-  Dispose(P);
-end;
-
-destructor TOrderedRawList.Destroy;
-begin
-  Clear;
-  FreeAndNil(FList);
-  inherited;
-end;
-
-
-function TOrderedRawList.Find(const RawData: TRawBytes; var Index: Integer): Boolean;
-var L, H, I: Integer;
-  c : Integer;
-begin
-  Result := False;
-  L := 0;
-  H := FList.Count - 1;
-  while L <= H do
-  begin
-    I := (L + H) shr 1;
-    c := TBaseType.BinStrComp(PRawListData(FList[i])^.RawData,RawData);
-    if C < 0 then L := I + 1 else
-    begin
-      H := I - 1;
-      if C = 0 then
-      begin
-        Result := True;
-        L := I;
-      end;
-    end;
-  end;
-  Index := L;
-end;
-
-function TOrderedRawList.Get(index: Integer): TRawBytes;
-begin
-  Result := PRawListData(FList[index])^.RawData;
-end;
-
-function TOrderedRawList.GetTag(index: Integer): Integer;
-begin
-  Result := PRawListData(FList[index])^.tag;
-end;
-
-function TOrderedRawList.GetTag(const RawData: TRawBytes): Integer;
-Var i : Integer;
-begin
-  if Not Find(RawData,i) then begin
-    Result := 0;
-  end else begin
-    Result := PRawListData(FList[i])^.tag;
-  end;
-end;
-
-function TOrderedRawList.IndexOf(const RawData: TRawBytes): Integer;
-begin
-  if Not Find(RawData,Result) then Result := -1;
-end;
-
-procedure TOrderedRawList.CopyFrom(master: TOrderedRawList);
-Var i : Integer;
-begin
-  If master=Self then Exit;
-  Clear;
-  For i:=0 to master.Count-1 do begin
-    Add(master.Get(i),master.GetTag(i));
-  end;
-end;
-
-procedure TOrderedRawList.SetTag(const RawData: TRawBytes; newTagValue: Integer);
-begin
-  Add(RawData,newTagValue);
-end;
-
-{ TOrderedCardinalListWithRaw }
-
-Type TCardinalListData = Record
-    value : Cardinal;
-    rawData : TRawBytes;
-  End;
-  PCardinalListData = ^TCardinalListData;
-
-function TOrderedCardinalListWithRaw.Find(value: Cardinal; var Index: Integer): Boolean;
-var L, H, I: Integer;
-  c : Integer;
-begin
-  Result := False;
-  L := 0;
-  H := FList.Count - 1;
-  while L <= H do
-  begin
-    I := (L + H) shr 1;
-    c := Int64(PCardinalListData(FList[I])^.value) - Int64(Value);
-    if C < 0 then L := I + 1 else
-    begin
-      H := I - 1;
-      if C = 0 then
-      begin
-        Result := True;
-        L := I;
-      end;
-    end;
-  end;
-  Index := L;
-end;
-
-constructor TOrderedCardinalListWithRaw.Create;
-begin
-  FList := TList.Create;
-end;
-
-destructor TOrderedCardinalListWithRaw.Destroy;
-begin
-  Clear;
-  FreeAndNil(FList);
-  inherited Destroy;
-end;
-
-procedure TOrderedCardinalListWithRaw.Clear;
-Var i : Integer;
-  P : PCardinalListData;
-begin
-  for i:=0 to FList.Count-1 do begin
-    P := FList[i];
-    P^.rawData:='';
-    Dispose(P);
-  end;
-  FList.Clear;
-end;
-
-function TOrderedCardinalListWithRaw.Add(const Value: Cardinal; const RawData: TRawBytes): Integer;
-Var P : PCardinalListData;
-begin
-  If Find(Value,Result) then begin
-    P := FList[Result];
-    P^.rawData:=RawData;
-  end else begin
-    New(P);
-    P^.value:=Value;
-    P^.rawData:=rawData;
-    FList.Insert(Result,P);
-  end;
-end;
-
-function TOrderedCardinalListWithRaw.Count: Integer;
-begin
-  Result := FList.Count;
-end;
-
-function TOrderedCardinalListWithRaw.GetCardinal(index: Integer): Cardinal;
-begin
-  Result := PCardinalListData(FList[index])^.value;
-end;
-
-function TOrderedCardinalListWithRaw.GetRaw(index: Integer): TRawBytes;
-begin
-  Result := PCardinalListData(FList[index])^.rawData;
-end;
-
-procedure TOrderedCardinalListWithRaw.Delete(index: Integer);
-Var P : PCardinalListData;
-begin
-  P := PCardinalListData( FList[index] );
-  FList.Delete(index);
-  Dispose(P);
-end;
-
-function TOrderedCardinalListWithRaw.IndexOf(value: Cardinal): Integer;
-begin
-  If Not Find(value,Result) then Result := -1;
-end;
-
-function TOrderedCardinalListWithRaw.IndexOfRaw(const RawData: TRawBytes): Integer;
-begin
-  For Result := 0 to FList.Count-1 do begin
-    If TBaseType.BinStrComp( PCardinalListData( FList[Result] )^.rawData , RawData ) = 0 then Exit;
-  end;
-  Result := -1;
-end;
 
 
 end.
 end.

+ 7 - 17
src/core/UBaseTypes.pas

@@ -1,6 +1,6 @@
 unit UBaseTypes;
 unit UBaseTypes;
 
 
-{ Copyright (c) 2017 by Albert Molina
+{ Copyright (c) 2017-19 by Albert Molina
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
@@ -14,6 +14,11 @@ unit UBaseTypes;
   16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
   16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
 
 
   THIS LICENSE HEADER MUST NOT BE REMOVED.
   THIS LICENSE HEADER MUST NOT BE REMOVED.
+
+
+  This Unit will define basic Types of data for PascalCoin
+  This unit must not need other units from PascalCoin, is a "top" unit
+
 }
 }
 
 
 {$IFDEF FPC}
 {$IFDEF FPC}
@@ -27,7 +32,7 @@ uses
 
 
 Type
 Type
   // Raw data in a maximum 65k bytes
   // Raw data in a maximum 65k bytes
-  TDynRawBytes = Array of Byte;
+  TDynRawBytes = TBytes;
   // Raw data in a maximum 256 bytes
   // Raw data in a maximum 256 bytes
   T256RawBytes = TDynRawBytes;
   T256RawBytes = TDynRawBytes;
 
 
@@ -103,21 +108,6 @@ Type
     class function GetElapsedMilliseconds(Const previousTickCount : TTickCount) : Int64;
     class function GetElapsedMilliseconds(Const previousTickCount : TTickCount) : Int64;
   End;
   End;
 
 
-  //HS -- removed, TNotifyManyEvent in UCommon.pas
-  {TNotifyEventToMany = Class
-  private
-    FList : Array of TNotifyEvent;
-  public
-    function IndexOf(search : TNotifyEvent) : Integer;
-    procedure Add(newNotifyEvent : TNotifyEvent);
-    procedure Remove(removeNotifyEvent : TNotifyEvent);
-    procedure Invoke(sender : TObject);
-    function Count : Integer;
-    procedure Delete(index : Integer);
-    Constructor Create;
-  End;}
-
-
 implementation
 implementation
 
 
 {$IFNDEF FPC}
 {$IFNDEF FPC}

+ 1 - 1
src/core/UNetProtocol.pas

@@ -29,7 +29,7 @@ Uses
   {LCLIntf, LCLType, LMessages,}
   {LCLIntf, LCLType, LMessages,}
 {$ENDIF}
 {$ENDIF}
   UBlockChain, Classes, SysUtils, UAccounts, UThread,
   UBlockChain, Classes, SysUtils, UAccounts, UThread,
-  UCrypto, UTCPIP, SyncObjs, UBaseTypes, UCommon,
+  UCrypto, UTCPIP, SyncObjs, UBaseTypes, UCommon, UPCOrderedLists,
   UNetProtection;
   UNetProtection;
 
 
 {$I config.inc}
 {$I config.inc}

+ 1 - 1
src/core/UNode.pas

@@ -34,7 +34,7 @@ unit UNode;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, UBlockChain, UNetProtocol, UAccounts, UCrypto, UThread, SyncObjs, ULog, UBaseTypes;
+  Classes, SysUtils, UBlockChain, UNetProtocol, UAccounts, UCrypto, UThread, SyncObjs, ULog, UBaseTypes, UPCOrderedLists;
 
 
 {$I config.inc}
 {$I config.inc}
 
 

+ 484 - 0
src/core/UPCOrderedLists.pas

@@ -0,0 +1,484 @@
+unit UPCOrderedLists;
+
+{ Copyright (c) 2016-2019 by Albert Molina
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+  This unit is a part of the PascalCoin Project, an infinitely scalable
+  cryptocurrency. Find us here:
+  Web: https://www.pascalcoin.org
+  Source: https://github.com/PascalCoin/PascalCoin
+
+  If you like it, consider a donation using Bitcoin:
+  16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
+
+  THIS LICENSE HEADER MUST NOT BE REMOVED.
+}
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+interface
+
+uses
+  Classes, SysUtils, UBaseTypes;
+
+Type
+  TCardinalsArray = Array of Cardinal;
+
+  // Maintans a Cardinal ordered (without duplicates) list with TRawData each
+
+  { TOrderedCardinalList }
+
+  TOrderedCardinalList = Class
+  private
+    FOrderedList : TList;
+    FDisabledsCount : Integer;
+    FModifiedWhileDisabled : Boolean;
+    FOnListChanged: TNotifyEvent;
+    Procedure NotifyChanged;
+  public
+    Constructor Create;
+    Destructor Destroy; override;
+    Function Add(Value : Cardinal) : Integer;
+    Procedure Remove(Value : Cardinal);
+    Procedure Clear;
+    Function Get(index : Integer) : Cardinal;
+    Function Count : Integer;
+    Function Find(const Value: Cardinal; var Index: Integer): Boolean;
+    Property OnListChanged : TNotifyEvent read FOnListChanged write FOnListChanged;
+    Procedure CopyFrom(Sender : TOrderedCardinalList);
+    Procedure Disable;
+    Procedure Enable;
+    Function ToArray : TCardinalsArray;
+  End;
+
+
+  // Maintans a Cardinal ordered (without duplicates) list with TRawData each
+
+  { TOrderedCardinalListWithRaw }
+
+  TOrderedCardinalListWithRaw = Class
+  private
+    FList : TList;
+    Function Find(value : Cardinal; var Index: Integer): Boolean;
+  public
+    Constructor Create;
+    Destructor Destroy; Override;
+    Procedure Clear;
+    Function Add(const Value: Cardinal; const RawData : TRawBytes) : Integer;
+    Function Count : Integer;
+    Function GetCardinal(index : Integer) : Cardinal;
+    function GetRaw(index : Integer) : TRawBytes;
+    Procedure Delete(index : Integer);
+    Function IndexOf(value : Cardinal) : Integer;
+    Function IndexOfRaw(const RawData : TRawBytes) : Integer;
+  end;
+
+  // Maintains a TRawBytes (AnsiString) list ordered to quick search withoud duplicates
+
+  { TOrderedRawList }
+
+  TOrderedRawList = Class
+  private
+    FList : TList;
+  public
+    Constructor Create;
+    Destructor Destroy; Override;
+    Procedure Clear;
+    Function Add(Const RawData : TRawBytes; tagValue : Integer = 0) : Integer;
+    Procedure Remove(Const RawData : TRawBytes);
+    Function Count : Integer;
+    Function Get(index : Integer) : TRawBytes;
+    Procedure Delete(index : Integer);
+    procedure SetTag(Const RawData : TRawBytes; newTagValue : Integer);
+    function GetTag(Const RawData : TRawBytes) : Integer; overload;
+    function GetTag(index : Integer) : Integer; overload;
+    Function IndexOf(Const RawData : TRawBytes) : Integer;
+    Procedure CopyFrom(master : TOrderedRawList);
+    Function Find(const RawData: TRawBytes; var Index: Integer): Boolean;
+  End;
+
+
+
+implementation
+
+{ TOrderedCardinalList }
+
+function TOrderedCardinalList.Add(Value: Cardinal): Integer;
+var nc : Integer;
+begin
+  if Find(Value,Result) then exit
+  else begin
+    nc := FOrderedList.Capacity;
+    if (nc <= FOrderedList.Count) then begin
+      nc := nc SHL 1;
+      if (nc > FOrderedList.Capacity) then begin
+        {$IFDEF HIGHLOG}TLog.NewLog(ltdebug,ClassName,Format('Increase capacity from %d to %d for %s',[FOrderedList.Capacity,nc,IntToHex(Integer(FOrderedList),8)]));{$ENDIF}
+        FOrderedList.Capacity:=nc;
+      end;
+    end;
+    FOrderedList.Insert(Result,TObject(Value));
+    NotifyChanged;
+  end;
+end;
+
+procedure TOrderedCardinalList.Clear;
+begin
+  FOrderedList.Clear;
+  NotifyChanged;
+end;
+
+procedure TOrderedCardinalList.CopyFrom(Sender: TOrderedCardinalList);
+Var i : Integer;
+begin
+  if Self=Sender then exit;
+  Disable;
+  Try
+    Clear;
+    FOrderedList.Capacity:=Sender.FOrderedList.Capacity;
+    for I := 0 to Sender.Count - 1 do begin
+      Add(Sender.Get(i));
+    end;
+  Finally
+    Enable;
+  End;
+end;
+
+function TOrderedCardinalList.Count: Integer;
+begin
+  Result := FOrderedList.Count;
+end;
+
+constructor TOrderedCardinalList.Create;
+begin
+  FOrderedList := TList.Create;
+  FDisabledsCount := 0;
+  FModifiedWhileDisabled := false;
+end;
+
+destructor TOrderedCardinalList.Destroy;
+begin
+  FOrderedList.Free;
+  inherited;
+end;
+
+procedure TOrderedCardinalList.Disable;
+begin
+  inc(FDisabledsCount);
+end;
+
+procedure TOrderedCardinalList.Enable;
+begin
+  if FDisabledsCount<=0 then raise Exception.Create('Dev error. Invalid disabled counter');
+  dec(FDisabledsCount);
+  if (FDisabledsCount=0) And (FModifiedWhileDisabled) then NotifyChanged;
+end;
+
+function TOrderedCardinalList.Find(const Value: Cardinal; var Index: Integer): Boolean;
+var L, H, I: Integer;
+  C : Int64;
+begin
+  Result := False;
+  L := 0;
+  H := FOrderedList.Count - 1;
+  // Optimization when inserting always a ordered list
+  if (H>0) then begin
+    C := Int64(FOrderedList[H]) - Int64(Value);
+    if (C<0) then begin
+      Index := H+1;
+      Exit;
+    end else if (C=0) then begin
+      Index := H;
+      Result := True;
+      Exit;
+    end;
+  end;
+  while L <= H do
+  begin
+    I := (L + H) shr 1;
+    C := Int64(FOrderedList[I]) - Int64(Value);
+    if C < 0 then L := I + 1 else
+    begin
+      H := I - 1;
+      if C = 0 then
+      begin
+        Result := True;
+        L := I;
+      end;
+    end;
+  end;
+  Index := L;
+end;
+
+function TOrderedCardinalList.Get(index: Integer): Cardinal;
+begin
+  Result := Cardinal(FOrderedList[index]);
+end;
+
+procedure TOrderedCardinalList.NotifyChanged;
+begin
+  if FDisabledsCount>0 then begin
+    FModifiedWhileDisabled := true;
+    exit;
+  end;
+  FModifiedWhileDisabled := false;
+  if Assigned(FOnListChanged) then FOnListChanged(Self);
+end;
+
+procedure TOrderedCardinalList.Remove(Value: Cardinal);
+Var i : Integer;
+begin
+  if Find(Value,i) then begin
+    FOrderedList.Delete(i);
+    NotifyChanged;
+  end;
+end;
+
+Function TOrderedCardinalList.ToArray : TCardinalsArray;
+var i : integer;
+begin
+  SetLength(Result, self.Count);
+  for i := 0 to self.Count - 1 do
+    Result[i] := Self.Get(i);
+end;
+
+{ TOrderedRawList }
+
+Type TRawListData = Record
+    RawData : TRawBytes;
+    tag : Integer;
+  End;
+  PRawListData = ^TRawListData;
+
+function TOrderedRawList.Add(const RawData: TRawBytes; tagValue : Integer = 0) : Integer;
+Var P : PRawListData;
+begin
+  if Find(RawData,Result) then begin
+    PRawListData(FList[Result])^.tag := tagValue;
+  end else begin
+    New(P);
+    P^.RawData := RawData;
+    P^.tag := tagValue;
+    FList.Insert(Result,P);
+  end;
+end;
+
+procedure TOrderedRawList.Remove(const RawData: TRawBytes);
+Var i : Integer;
+begin
+  i := IndexOf(RawData);
+  If i>=0 then Delete(i);
+end;
+
+procedure TOrderedRawList.Clear;
+Var P : PRawListData;
+  i : Integer;
+begin
+  for i := FList.Count - 1 downto 0 do begin
+    P := FList[i];
+    Dispose(P);
+  end;
+  FList.Clear;
+end;
+
+function TOrderedRawList.Count: Integer;
+begin
+  Result := FList.Count;
+end;
+
+constructor TOrderedRawList.Create;
+begin
+  FList := TList.Create;
+end;
+
+procedure TOrderedRawList.Delete(index: Integer);
+Var P : PRawListData;
+begin
+  P := PRawListData(FList[index]);
+  FList.Delete(index);
+  Dispose(P);
+end;
+
+destructor TOrderedRawList.Destroy;
+begin
+  Clear;
+  FreeAndNil(FList);
+  inherited;
+end;
+
+
+function TOrderedRawList.Find(const RawData: TRawBytes; var Index: Integer): Boolean;
+var L, H, I: Integer;
+  c : Integer;
+begin
+  Result := False;
+  L := 0;
+  H := FList.Count - 1;
+  while L <= H do
+  begin
+    I := (L + H) shr 1;
+    c := TBaseType.BinStrComp(PRawListData(FList[i])^.RawData,RawData);
+    if C < 0 then L := I + 1 else
+    begin
+      H := I - 1;
+      if C = 0 then
+      begin
+        Result := True;
+        L := I;
+      end;
+    end;
+  end;
+  Index := L;
+end;
+
+function TOrderedRawList.Get(index: Integer): TRawBytes;
+begin
+  Result := PRawListData(FList[index])^.RawData;
+end;
+
+function TOrderedRawList.GetTag(index: Integer): Integer;
+begin
+  Result := PRawListData(FList[index])^.tag;
+end;
+
+function TOrderedRawList.GetTag(const RawData: TRawBytes): Integer;
+Var i : Integer;
+begin
+  if Not Find(RawData,i) then begin
+    Result := 0;
+  end else begin
+    Result := PRawListData(FList[i])^.tag;
+  end;
+end;
+
+function TOrderedRawList.IndexOf(const RawData: TRawBytes): Integer;
+begin
+  if Not Find(RawData,Result) then Result := -1;
+end;
+
+procedure TOrderedRawList.CopyFrom(master: TOrderedRawList);
+Var i : Integer;
+begin
+  If master=Self then Exit;
+  Clear;
+  For i:=0 to master.Count-1 do begin
+    Add(master.Get(i),master.GetTag(i));
+  end;
+end;
+
+procedure TOrderedRawList.SetTag(const RawData: TRawBytes; newTagValue: Integer);
+begin
+  Add(RawData,newTagValue);
+end;
+
+{ TOrderedCardinalListWithRaw }
+
+Type TCardinalListData = Record
+    value : Cardinal;
+    rawData : TRawBytes;
+  End;
+  PCardinalListData = ^TCardinalListData;
+
+function TOrderedCardinalListWithRaw.Find(value: Cardinal; var Index: Integer): Boolean;
+var L, H, I: Integer;
+  c : Integer;
+begin
+  Result := False;
+  L := 0;
+  H := FList.Count - 1;
+  while L <= H do
+  begin
+    I := (L + H) shr 1;
+    c := Int64(PCardinalListData(FList[I])^.value) - Int64(Value);
+    if C < 0 then L := I + 1 else
+    begin
+      H := I - 1;
+      if C = 0 then
+      begin
+        Result := True;
+        L := I;
+      end;
+    end;
+  end;
+  Index := L;
+end;
+
+constructor TOrderedCardinalListWithRaw.Create;
+begin
+  FList := TList.Create;
+end;
+
+destructor TOrderedCardinalListWithRaw.Destroy;
+begin
+  Clear;
+  FreeAndNil(FList);
+  inherited Destroy;
+end;
+
+procedure TOrderedCardinalListWithRaw.Clear;
+Var i : Integer;
+  P : PCardinalListData;
+begin
+  for i:=0 to FList.Count-1 do begin
+    P := FList[i];
+    P^.rawData:='';
+    Dispose(P);
+  end;
+  FList.Clear;
+end;
+
+function TOrderedCardinalListWithRaw.Add(const Value: Cardinal; const RawData: TRawBytes): Integer;
+Var P : PCardinalListData;
+begin
+  If Find(Value,Result) then begin
+    P := FList[Result];
+    P^.rawData:=RawData;
+  end else begin
+    New(P);
+    P^.value:=Value;
+    P^.rawData:=rawData;
+    FList.Insert(Result,P);
+  end;
+end;
+
+function TOrderedCardinalListWithRaw.Count: Integer;
+begin
+  Result := FList.Count;
+end;
+
+function TOrderedCardinalListWithRaw.GetCardinal(index: Integer): Cardinal;
+begin
+  Result := PCardinalListData(FList[index])^.value;
+end;
+
+function TOrderedCardinalListWithRaw.GetRaw(index: Integer): TRawBytes;
+begin
+  Result := PCardinalListData(FList[index])^.rawData;
+end;
+
+procedure TOrderedCardinalListWithRaw.Delete(index: Integer);
+Var P : PCardinalListData;
+begin
+  P := PCardinalListData( FList[index] );
+  FList.Delete(index);
+  Dispose(P);
+end;
+
+function TOrderedCardinalListWithRaw.IndexOf(value: Cardinal): Integer;
+begin
+  If Not Find(value,Result) then Result := -1;
+end;
+
+function TOrderedCardinalListWithRaw.IndexOfRaw(const RawData: TRawBytes): Integer;
+begin
+  For Result := 0 to FList.Count-1 do begin
+    If TBaseType.BinStrComp( PCardinalListData( FList[Result] )^.rawData , RawData ) = 0 then Exit;
+  end;
+  Result := -1;
+end;
+
+end.
+

+ 1 - 0
src/core/URPC.pas

@@ -25,6 +25,7 @@ interface
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
   UNetProtocol, UOpTransaction, UWallet, UTime, UAES, UECIES, UTxMultiOperation,
   UNetProtocol, UOpTransaction, UWallet, UTime, UAES, UECIES, UTxMultiOperation,
   UJSONFunctions, classes, blcksock, synsock, IniFiles, Variants, math, UBaseTypes, UOpenSSL,
   UJSONFunctions, classes, blcksock, synsock, IniFiles, Variants, math, UBaseTypes, UOpenSSL,
+  UPCOrderedLists,
   UNetProtection;
   UNetProtection;
 
 
 Const
 Const

+ 1 - 1
src/gui-classic/UFRMAccountSelect.pas

@@ -30,7 +30,7 @@ uses
 {$ENDIF}
 {$ENDIF}
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, UAccounts, Grids, StdCtrls, Buttons, ExtCtrls, UWallet, UNode,
   Dialogs, UAccounts, Grids, StdCtrls, Buttons, ExtCtrls, UWallet, UNode,
-  UGridUtils, UConst, UThread;
+  UGridUtils, UConst, UThread, UPCOrderedLists;
 
 
 const
 const
   CT_AS_MyAccounts = $0001;
   CT_AS_MyAccounts = $0001;

+ 1 - 1
src/gui-classic/UFRMOperation.pas

@@ -32,7 +32,7 @@ uses
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, UNode, UWallet, UCrypto, Buttons, UBlockChain,
   Dialogs, StdCtrls, UNode, UWallet, UCrypto, Buttons, UBlockChain,
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UFRMMemoText,
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UFRMMemoText,
-  UBaseTypes;
+  UBaseTypes, UPCOrderedLists;
 
 
 Const
 Const
   CM_PC_WalletKeysChanged = WM_USER + 1;
   CM_PC_WalletKeysChanged = WM_USER + 1;

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

@@ -323,7 +323,7 @@ Uses UFolderHelper, UOpenSSL, UOpenSSLdef, UTime, UFileStorage,
   UFRMRandomOperations,
   UFRMRandomOperations,
   {$ENDIF}
   {$ENDIF}
   UFRMAbout, UFRMOperation, UFRMWalletKeys, UFRMPayloadDecoder, UFRMNodesIp, UFRMMemoText,
   UFRMAbout, UFRMOperation, UFRMWalletKeys, UFRMPayloadDecoder, UFRMNodesIp, UFRMMemoText,
-  USettings, UCommon;
+  USettings, UCommon, UPCOrderedLists;
 
 
 Type
 Type
 
 

+ 1 - 1
src/gui-classic/UGridUtils.pas

@@ -31,7 +31,7 @@ uses
   LCLIntf, LCLType, LMessages,
   LCLIntf, LCLType, LMessages,
 {$ENDIF}
 {$ENDIF}
   Classes, Grids, UNode, UAccounts, UBlockChain, UAppParams,
   Classes, Grids, UNode, UAccounts, UBlockChain, UAppParams,
-  UWallet, UCrypto, UPoolMining, URPC, UBaseTypes;
+  UWallet, UCrypto, UPoolMining, URPC, UBaseTypes, UPCOrderedLists;
 
 
 Type
 Type
   // TAccountsGrid implements a visual integration of TDrawGrid
   // TAccountsGrid implements a visual integration of TDrawGrid