Browse Source

TNode.TryFindAccountByKey and TNode.TryFindPublicSaleAccount

PascalCoin 4 years ago
parent
commit
44c1d3bb39
1 changed files with 74 additions and 0 deletions
  1. 74 0
      src/core/UNode.pas

+ 74 - 0
src/core/UNode.pas

@@ -128,6 +128,9 @@ Type
     class function NodeVersion : String;
     class function GetPascalCoinDataFolder : String;
     class procedure SetPascalCoinDataFolder(const ANewDataFolder : String);
+    //
+    function TryFindAccountByKey(const APubKey : TAccountKey; out AAccountNumber : Cardinal) : Boolean;
+    function TryFindPublicSaleAccount(AMaximumPrice : Int64; APreventRaceCondition : Boolean; out AAccountNumber : Cardinal) : Boolean;
   End;
 
   TThreadSafeNodeNotifyEvent = Class(TPCThread)
@@ -766,6 +769,77 @@ begin
   dec(FDisabledsNewBlocksCount);
 end;
 
+function TNode.TryFindAccountByKey(const APubKey: TAccountKey;
+  out AAccountNumber: Cardinal): Boolean;
+  // Finds the smallest numbered account with selected key (or returns false)
+var Lpka : TSafeboxPubKeysAndAccounts;
+  LAccountsNumberList : TAccountsNumbersList;
+begin
+  Result := False;
+  Lpka := Bank.SafeBox.OrderedAccountKeysList;
+  if Assigned(Lpka) then begin
+    LAccountsNumberList := Lpka.GetAccountsUsingThisKey(APubKey);
+    if Assigned(LAccountsNumberList) then begin
+      if LAccountsNumberList.Count>0 then begin
+        AAccountNumber := LAccountsNumberList.Get(0);
+        Result := True;
+      end;
+    end;
+  end;
+end;
+
+function TNode.TryFindPublicSaleAccount(AMaximumPrice: Int64; APreventRaceCondition : Boolean;
+  out AAccountNumber: Cardinal): Boolean;
+  // Finds an account at or below argument purchase price (or returns false)
+  // APreventRaceCondition: When True will return a random account in valid range price
+  // Limitations: Account must be >0
+var LtempAccNumber : Integer;
+  LLastValidAccount, LCurrAccount : TAccount;
+  LContinueSearching : Boolean;
+begin
+  Result := False;
+
+  // Sorted list: Bank.SafeBox.AccountsOrderedBySalePrice
+  // Note: List is sorted by Sale price (ASCENDING), but NOT by public/private sale, must check
+
+  if Not Bank.SafeBox.AccountsOrderedBySalePrice.FindLowest(LtempAccNumber) then Exit(False);
+  LCurrAccount := GetMempoolAccount(LtempAccNumber);
+
+  if (LCurrAccount.accountInfo.price<=AMaximumPrice)
+    and (TAccountComp.IsAccountForPublicSale(LCurrAccount.accountInfo)) then begin
+    LLastValidAccount := LCurrAccount;
+    LContinueSearching := (APreventRaceCondition) And (Random(50)=0);
+  end else begin
+    LLastValidAccount := CT_Account_NUL;
+    LContinueSearching := True;
+  end;
+
+  while (LCurrAccount.accountInfo.price<=AMaximumPrice) and (LContinueSearching) do begin
+
+    if TAccountComp.IsAccountForPublicSale(LCurrAccount.accountInfo) then LLastValidAccount := LCurrAccount;
+
+    if Not (Bank.SafeBox.AccountsOrderedBySalePrice.FindSuccessor(LtempAccNumber,LtempAccNumber)) then Break;
+    LCurrAccount := GetMempoolAccount(LtempAccNumber);
+
+    // If price increased, then do not continue and use LastValidAccount
+    if (LLastValidAccount.account>0)
+      and (LLastValidAccount.accountInfo.price <> LCurrAccount.accountInfo.price) then Break;
+
+    // Continue?
+    LContinueSearching :=
+      (LLastValidAccount.account=0) // This means that no valid account has been found yet...
+      or
+      (LContinueSearching And (Random(50)=0)); // Random prevention
+  end;
+  if (LLastValidAccount.account>0) then begin
+    AAccountNumber := LLastValidAccount.account;
+    Result := True;
+  end else begin
+    AAccountNumber := 0;
+    Result := False;
+  end;
+end;
+
 function TNode.TryLockNode(MaxWaitMilliseconds: Cardinal): Boolean;
 begin
   Result := TPCThread.TryProtectEnterCriticalSection(Self,MaxWaitMilliseconds,FLockMempool);