Browse Source

CoreUtls: added helpers for SafeBox and Node

Herman Schoenfeld 7 years ago
parent
commit
e92637ab14
1 changed files with 155 additions and 8 deletions
  1. 155 8
      src/core.utils/UCoreUtils.pas

+ 155 - 8
src/core.utils/UCoreUtils.pas

@@ -16,16 +16,20 @@ unit UCoreUtils;
 interface
 
 uses
-  Classes, SysUtils, UCrypto, UAccounts, UBlockChain, UCommon,
-  Generics.Collections, Generics.Defaults;
+  Classes, SysUtils, UCrypto, UAccounts, UBlockChain, UNode, UCommon, UNetProtocol,
+  Generics.Collections, Generics.Defaults, UCoreObjects;
 
 type
 
+{ TAccountKeyComparer }
+
 TAccountKeyComparer = class (TComparer<TAccountKey>)
   function Compare(constref ALeft, ARight: T): Integer; override;
   class function DoCompare(constref ALeft, ARight : TAccountKey) : Integer; inline;
 end;
 
+{ TAccountKeyEqualityComparer }
+
 TAccountKeyEqualityComparer = class(TEqualityComparer<TAccountKey>)
   public
     function Equals(constref ALeft, ARight: TAccountKey): Boolean; override;
@@ -36,20 +40,45 @@ end;
 
 { TCoreTool }
 
-TCoreTool = class(TObject)
-  class function GetSignerCandidates(ANumOps : Integer; const ACandidates : TArray<TAccount>) : TArray<TAccount>; static;
-  end;
+TCoreTool = class
+public
+  class function GetSignerCandidates(ANumOps : Integer; const ACandidates : array of TAccount) : TArray<TAccount>; static;
+end;
+
+{ TSafeBoxHelper }
+
+TSafeBoxHelper = class helper for TPCSafeBox
+  private
+    function GetKeysSummaryInternal(UseFilter: boolean; const AFilterKeys : array of TAccountKey; FetchAccounts : boolean = false) : TUserSummary;
+  public
+    function GetModifiedAccounts(const AAccounts : array of TAccount) : TArray<TAccount>;
+    function GetKeySummary(const AKey : TAccountKey; FetchAccounts : boolean = false) : TKeySummary;
+    function GetUserSummary(const AKeys : array of TAccountKey; FetchAccounts : boolean = false) : TUserSummary;
+    function GetSummaryAllKeys : TUserSummary;
+end;
+
+{ TNodeHelper }
+
+TNodeHelper = class helper for TNode
+  function HasBestKnownBlockchainTip : boolean;
+end;
+
+{ TAccountHelper }
 
 TAccountHelper = record helper for TAccount
   function GetAccountString : AnsiString;
   function GetInfoText(const ABank : TPCBank) : utf8string;
 end;
 
+{ TOperationResumeHelper }
+
 TOperationResumeHelper = record helper for TOperationResume
   function GetPrintableOPHASH : AnsiString;
   function GetInfoText(const ABank : TPCBank) : utf8string;
 end;
 
+{ TTimeSpanHelper }
+
 TTimeSpanHelper = record helper for TTimeSpan
   function TotalBlockCount : Integer;
 end;
@@ -61,15 +90,14 @@ uses
 
 { TCoreTool }
 
-class function TCoreTool.GetSignerCandidates(ANumOps: Integer;
-  const ACandidates: TArray<TAccount>): TArray<TAccount>;
+class function TCoreTool.GetSignerCandidates(ANumOps : Integer; const ACandidates : array of TAccount) : TArray<TAccount>;
 var
   i: Integer;
   Fee: Int64;
   acc: TAccount;
 begin
   //make deep copy of accounts!!! Very Important
-  Result := Copy(ACandidates);
+  Result := TArrayTool<TAccount>.Copy(ACandidates);
   Fee := ANumOps * CT_MOLINA;
   for i := High(Result) downto Low(Result) do
     begin
@@ -81,6 +109,125 @@ begin
     end;
 end;
 
+{ TNodeHelper }
+
+function TNodeHelper.HasBestKnownBlockchainTip : boolean;
+var
+  LReady : boolean;
+  LMsg : AnsiString;
+begin
+  LReady := Self.Bank.IsReady(LMsg);
+  if LReady AND TNetData.NetData.IsGettingNewBlockChainFromClient then
+    Result := Self.Bank.BlocksCount = TNetData.NetData.MaxRemoteOperationBlock.block;
+end;
+
+{ TSafeBoxHelper }
+
+function TSafeBoxHelper.GetModifiedAccounts(const AAccounts : array of TAccount) : TArray<TAccount>;
+var
+  i : integer;
+  LChanged : TList<TAccount>;
+  LAcc : TAccount;
+  GC : TDisposables;
+begin
+  LChanged := GC.AddObject( TList<TAccount>.Create ) as TList<TAccount>;
+  for i := Low(AAccounts) to High(AAccounts) do begin
+    LAcc := Self.Account(AAccounts[i].account);
+    if (LAcc.n_Operation <> AAccounts[i].n_operation) OR (LAcc.Balance <> AAccounts[i].balance) then
+      LChanged.Add(LAcc);
+  end;
+  Result := LChanged.ToArray;
+end;
+
+function TSafeBoxHelper.GetKeySummary(const AKey : TAccountKey; FetchAccounts : boolean = false) : TKeySummary;
+var
+  AKeysResult : TUserSummary;
+begin
+  AKeysResult := GetUserSummary([AKey], FetchAccounts);
+  if Length(AKeysResult.Items) = 0 then begin
+    Result := TKeySummary_Nil;
+    exit;
+  end;
+  Result := AKeysResult.Items[0];
+end;
+
+function TSafeBoxHelper.GetUserSummary(const AKeys : array of TAccountKey; FetchAccounts : boolean = false) : TUserSummary;
+begin
+  Result := GetKeysSummaryInternal(True, AKeys, FetchAccounts);
+end;
+
+function TSafeBoxHelper.GetSummaryAllKeys : TUserSummary;
+begin
+  Result := GetKeysSummaryInternal(False, [], False);
+end;
+
+function TSafeBoxHelper.GetKeysSummaryInternal(UseFilter: boolean; const AFilterKeys : array of TAccountKey; FetchAccounts : boolean = false) : TUserSummary;
+type
+  __TList_TAccount = TList<TAccount>;
+  __TPair_TAccountKey_TList_TAccount = TPair<TAccountKey, __TList_TAccount>;
+  __TObjectDictionary_TAccountKey_TList_TAccount = TObjectDictionary<TAccountKey, __TList_TAccount>;
+var
+  i,j : integer;
+  LAcc : TAccount;
+  LAccs : THashSet<TAccount>;
+  LKey : TAccountKey;
+  LValue : __TList_TAccount;
+  safeBox : TPCSafeBox;
+  GC : TDisposables;
+  LKeys : __TObjectDictionary_TAccountKey_TList_TAccount;
+  LPair : __TPair_TAccountKey_TList_TAccount;
+begin
+  // Setup local dictionary key -> account[]
+  LAccs := GC.AddObject( THashSet<TAccount>.Create ) as THashSet<TAccount>;
+  LKeys := GC.AddObject( __TObjectDictionary_TAccountKey_TList_TAccount.Create([doOwnsValues], TAccountKeyEqualityComparer.Create )) as __TObjectDictionary_TAccountKey_TList_TAccount;
+
+  if UseFilter then begin
+    for i := Low(AFilterKeys) to High(AFilterKeys) do
+      LKeys.Add(AFilterKeys[i], __TList_TAccount.Create);
+
+    for i := 0 to Self.AccountsCount - 1 do begin
+      LAcc := Self.Account(i);
+      if LKeys.TryGetValue(LAcc.accountInfo.accountKey, LValue) then
+        LValue.Add(LAcc);
+    end
+  end
+  else
+  for i := 0 to Self.AccountsCount - 1 do begin
+    LAcc := Self.Account(i);
+    if NOT LKeys.TryGetValue(LAcc.accountInfo.accountKey, LValue) then begin
+      LValue := __TList_TAccount.Create;
+      LKeys.Add(LAcc.accountInfo.accountKey, LValue);
+     end;
+     LValue.Add(LAcc);
+  end;
+
+  // Build the results
+  SetLength(Result.Items, LKeys.Count);
+  i := 0;
+  for LPair in LKeys do begin
+    Result.Items[i].Key := CT_AccountInfo_NUL.accountKey;
+    Result.Items[i].TotalPASA:=0;
+    Result.Items[i].TotalPASC:=0;
+    SetLength(Result.Items[i].Accounts, 0);
+    for j := 0 to LPair.Value.Count - 1 do begin
+      LAcc := LPair.Value[j];
+      Inc(Result.Items[i].TotalPASA);
+      Inc(Result.Items[i].TotalPASC, LAcc.balance);
+    end;
+    if FetchAccounts then begin
+      Result.Items[i].Accounts := LPair.Value.ToArray;
+      LAccs.AddRange(Result.Items[i].Accounts);
+    end;
+    Inc(i);
+  end;
+  Result.Keys := TArrayTool<TAccountKey>.Copy(AFilterKeys);
+  Result.Accounts := LAccs.ToArray;
+  for i := Low(Result.Items) to High(Result.Items) do begin
+    Inc(Result.TotalPASA, Result.Items[i].TotalPASA);
+    Inc(Result.TotalPASC, Result.Items[i].TotalPASC);
+  end;
+end;
+
 { TAccountKeyComparer }
 
 function TAccountKeyComparer.Compare(constref ALeft, ARight: T): Integer;