Sfoglia il codice sorgente

Merge pull request #52 from kapytanhook/MinerAccountRecovery

Miner Account Recovery - Good job!
Albert Molina 3 anni fa
parent
commit
5d41575979

+ 2 - 0
.gitignore

@@ -53,3 +53,5 @@ dunit.ini
 /PIP/resources/*.DS_Store
 /PIP/resources/PIP-0034A/*.DS_Store
 /src/*.tvsconfig
+src/libssl-1_1.dll
+src/libssl-1_1-x64.dll

+ 26 - 0
src/core/UAccounts.pas

@@ -118,12 +118,15 @@ Type
     Class procedure SaveTOperationBlockToStream(const stream : TStream; const operationBlock:TOperationBlock);
     Class Function LoadTOperationBlockFromStream(const stream : TStream; var operationBlock:TOperationBlock) : Boolean;
     Class Function AccountToTxt(const Account : TAccount) : String;
+    Class Function AccountCanRecover(const Account: TAccount; currentBlockCount: Cardinal) : Boolean;
   End;
 
   TPCSafeBox = Class;
 
   TAccountKeyArray = array of TAccountKey;
 
+  TAccountList = TList<TAccount>;
+
   // This is a class to quickly find accountkeys and their respective account number/s
 
   { TOrderedAccountKeysList }
@@ -1724,6 +1727,29 @@ begin
       Account.account_data.ToHexaString,Account.account_seal.ToHexaString ]);
 end;
 
+class function TAccountComp.AccountCanRecover(const Account: TAccount; currentBlockCount: Cardinal): Boolean;
+begin
+  Result := True;
+  if TAccountComp.IsAccountBlockedByProtocol(Account.account, currentBlockCount) then begin
+    Result := False; // 'account is blocked for protocol';
+     Exit;
+  end;
+  if TAccountComp.IsAccountLocked(Account.accountInfo,currentBlockCount) then begin
+    Result := False; // 'account is locked';
+    Exit;
+  end;
+  // check boundary 1 gotten from TOpRecoverFounds.DoOperation
+  if( Account.updated_on_block_active_mode + CT_RecoverFoundsWaitInactiveCount >= currentBlockCount ) then begin
+    Result := False; // 'account is active';
+    Exit;
+  end;
+  // check boundary 2 gotten from TOpRecoverFounds.DoOperation
+  if( TAccountComp.AccountBlock(Account.account) + CT_RecoverFoundsWaitInactiveCount >= currentBlockCount ) then begin
+    Result := False; // 'account block is active';
+    Exit;
+  end;
+end;
+
 class function TAccountComp.IsValidAccountInfo(const AAccountInfo: TAccountInfo; ACurrentProtocol : Word; var errors: String): Boolean;
 Var s : String;
 begin

+ 41 - 0
src/core/UBlockChain.pas

@@ -432,6 +432,7 @@ Type
     function LoadBlockFromStream(Stream: TStream; var errors: String): Boolean;
     //
     Function GetMinerRewardPseudoOperation : TOperationResume;
+    Function AddMinerRecover(LRecoverAccounts: TAccountList) : Boolean;
     Function ValidateOperationBlock(var errors : String) : Boolean;
     Property IsOnlyOperationBlock : Boolean read FIsOnlyOperationBlock;
     Procedure Lock;
@@ -2116,6 +2117,46 @@ begin
    Result.OperationTxt := 'Miner reward';
 end;
 
+function TPCOperationsComp.AddMinerRecover(LRecoverAccounts: TAccountList): Boolean;
+var
+  LAccount: TAccount;
+  LOpRecoverFounds: TOpRecoverFounds;
+  i: Integer;
+  errors: string;
+begin
+  Self.Lock;
+  errors := '';
+  Result := True;
+  try
+    for i:=0 to LRecoverAccounts.Count-1 do begin
+      LAccount := LRecoverAccounts[i];
+      LOpRecoverFounds := TOpRecoverFounds.Create(
+        Self.OperationBlock.protocol_version,
+        LAccount.account,
+        LAccount.n_operation+1,
+        LAccount.balance,
+        Self.AccountKey
+      );
+      try
+        if not(
+          Self.AddOperation(
+            True,
+            LOpRecoverFounds,
+            errors
+          )
+        ) then begin
+          // if it fails then it number of operations could be maxed out, not a problem
+          Break;
+        end;
+      finally
+        LOpRecoverFounds.Free;
+      end;
+    end;
+  finally
+    Self.Unlock;
+  end;
+end;
+
 function TPCOperationsComp.ValidateOperationBlock(var errors : String): Boolean;
 Var i : Integer;
 begin

+ 44 - 1
src/core/UPoolMining.pas

@@ -31,7 +31,8 @@ Uses
   {LCLIntf, LCLType, LMessages,}
 {$ENDIF}
   UTCPIP, SysUtils, UThread, SyncObjs, Classes, UJSONFunctions, UPCEncryption, UNode,
-  UCrypto, UAccounts, UConst, UBlockChain, UBaseTypes, UPCDataTypes,
+  UCrypto, UAccounts, UConst, UBlockChain, UBaseTypes, UPCDataTypes, UOpTransaction,
+  UPCAccountsOrdenations,
   {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF};
 
 Const
@@ -140,6 +141,8 @@ Type
   End;
 
 
+  { TPoolMiningServer }
+
   TPoolMiningServer = Class(TNetTcpIpServer)
   private
     FIncomingsCounter : Integer;
@@ -154,6 +157,7 @@ Type
     FMinerOperations : TPCOperationsComp;
     FMaxOperationsPerBlock: Integer;
     FMax0FeeOperationsPerBlock: Integer;
+    Procedure CheckMinerRecover(nbOperations: TPCOperationsComp);
     Procedure DoProcessJSON(json : TPCJSONObject; ResponseMethod : String; Client : TJSONRPCTcpIpClient);
     Procedure OnNodeNewBlock(Sender : TObject);
     Procedure OnNodeOperationsChanged(Sender : TObject);
@@ -801,6 +805,7 @@ begin
       try
         if (Not (TPCOperationsComp.EqualsOperationBlock(FMinerOperations.OperationBlock,LLockedMempool.OperationBlock))) then begin
           FMinerOperations.Clear(true);
+          CheckMinerRecover(LLockedMempool);
           if LLockedMempool.Count>0 then begin
             // First round: Select with fee > 0
             i := 0;
@@ -942,6 +947,44 @@ begin
   End;
 end;
 
+// Looks for accounts to recover, adds up to 100 recoverFounds Operations to nbOperations
+procedure TPoolMiningServer.CheckMinerRecover(nbOperations: TPCOperationsComp);
+var
+  LAccOrd: TAccountsOrderedByUpdatedBlock;
+  LAccount: TAccount;
+  LRecoverAccounts: TList<TAccount>;
+  LIndexKey, LRecIndex, LRecoverAccountsCount: Integer;
+begin
+  LIndexKey := 0;
+  LRecoverAccountsCount := 0;
+  LRecoverAccounts := TList<TAccount>.Create(); // make a list of RecoverAccounts
+  nbOperations.Lock;
+  try
+    LAccOrd := nbOperations.bank.SafeBox.AccountsOrderedByUpdatedBlock; // Walk AccountsOrderedByUpdatedBlock, this keeps a list of the oldest accounts
+    if Assigned(LAccOrd) then begin
+      LAccount := CT_Account_NUL;
+      if LAccOrd.First(LIndexKey) then begin
+        LRecIndex := 0;
+        LRecoverAccountsCount := LAccOrd.Count;
+        while ((LRecIndex < LRecoverAccountsCount) and (LRecIndex < CT_MAX_0_fee_operations_per_block_by_miner)) do begin
+          LAccount := FNodeNotifyEvents.Node.GetMempoolAccount(LIndexKey);
+          if(TAccountComp.AccountCanRecover(LAccount, nbOperations.OperationBlock.block)) then begin // does the AccountCanRecover check, !locked, old enough, etc
+            LRecoverAccounts.Add(LAccount);
+          end else begin
+            Break; // we could not recover this account, then we can never recover move recent accounts
+          end;
+          if Not LAccOrd.Next(LIndexKey) then Break;
+          Inc(LRecIndex);
+        end;
+        nbOperations.AddMinerRecover(LRecoverAccounts);
+      end;
+    end;
+  finally
+    nbOperations.Unlock;
+    LRecoverAccounts.Free; // destroy the list, operations have been added
+  end;
+end;
+
 procedure TPoolMiningServer.OnNewIncommingConnection(Sender: TObject; Client: TNetTcpIpClient);
 var bClient : TJSONRPCTcpIpClient;
   jsonobj : TPCJSONObject;

+ 10 - 6
src/pascalcoin_wallet_classic.lpi

@@ -42,7 +42,7 @@
         <PackageName Value="LCL"/>
       </Item1>
     </RequiredPackages>
-    <Units Count="37">
+    <Units Count="39">
       <Unit0>
         <Filename Value="pascalcoin_wallet_classic.dpr"/>
         <IsPartOfProject Value="True"/>
@@ -222,6 +222,15 @@
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
       </Unit36>
+      <Unit37>
+        <Filename Value="gui-classic\UFRMAskForAccount.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit37>
+      <Unit38>
+        <Filename Value="core\UPCTNetDataExtraMessages.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit38>
     </Units>
   </ProjectOptions>
   <CompilerOptions>
@@ -240,11 +249,6 @@
         <SyntaxMode Value="Delphi"/>
       </SyntaxOptions>
     </Parsing>
-    <CodeGeneration>
-      <Optimizations>
-        <OptimizationLevel Value="2"/>
-      </Optimizations>
-    </CodeGeneration>
     <Linking>
       <Debugging>
         <GenerateDebugInfo Value="False"/>