Ver código fonte

Miner Account Recovery

Making miners recover accounts
notes:
  - needed to change Gridutils to make it compile, it expects Int64 instead of integer on my latest stable lazarus.
kapytanhook 3 anos atrás
pai
commit
0eb3f19429

+ 2 - 2
src/config.inc

@@ -30,8 +30,8 @@
   
 }
 
-  {$DEFINE PRODUCTION}
-  {.$DEFINE TESTNET}
+  {.$DEFINE PRODUCTION}
+  {$DEFINE TESTNET}
 
   // Activate to define CryptoLib4Pascal by default on all compilations
   {.$DEFINE Use_CryptoLib4Pascal}

+ 28 - 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,31 @@ begin
       Account.account_data.ToHexaString,Account.account_seal.ToHexaString ]);
 end;
 
+class function TAccountComp.AccountCanRecover(const Account: TAccount; currentBlockCount: Cardinal): Boolean;
+var
+  count: Int64;
+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

+ 29 - 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,34 @@ begin
    Result.OperationTxt := 'Miner reward';
 end;
 
+function TPCOperationsComp.AddMinerRecover(LRecoverAccounts: TAccountList): Boolean;
+var
+  LAccount: TAccount;
+  i: Integer;
+  errors: string;
+begin
+  Self.Lock;
+  errors := '';
+  Result := True;
+  try
+    for i:=0 to LRecoverAccounts.Count-1 do begin
+      LAccount := LRecoverAccounts[i];
+      if not(
+        Self.AddOperation(
+          True,
+          TOpRecoverFounds.Create(Self.OperationBlock.protocol_version, LAccount.account, LAccount.n_operation+1, 0, Self.AccountKey),
+          errors
+        )
+      ) then begin
+        // if it fails then it number of operations could be maxed out, not a problem
+        Break;
+      end;
+    end;
+  finally
+    Self.Unlock;
+  end;
+end;
+
 function TPCOperationsComp.ValidateOperationBlock(var errors : String): Boolean;
 Var i : Integer;
 begin

+ 40 - 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,40 @@ 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: Integer;
+begin
+  LIndexKey := 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;
+        while (LRecIndex < 100) do begin // Will recover at most 100 accounts per mined block
+          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;
+          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;

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

@@ -298,7 +298,7 @@ Var
   LApplyfilter : Boolean;
   LAccount : TAccount;
   LNode : TNode;
-  LAccountsList : TList<Integer>;
+  LAccountsList : TList<Int64>;
 begin
   LApplyfilter := ((FAccountsGridFilter.MinBalance>0) Or ((FAccountsGridFilter.MaxBalance>=0) And (FAccountsGridFilter.MaxBalance<CT_MaxWalletAmount)));
   FBalance := 0;
@@ -321,7 +321,7 @@ begin
             LAccountsNumbersList := FAccountsGridFilter.OrderedAccountsKeyList.AccountKeyList[i];
             if Assigned(LAccountsNumbersList) then begin
 
-              LAccountsList := TList<Integer>.Create;
+              LAccountsList := TList<Int64>.Create;
               Try
                 LAccountsNumbersList.FillList(j_min,500,LAccountsList);
                 for j := 0 to LAccountsList.Count - 1 do begin

BIN
src/libssl-1_1-x64.dll


BIN
src/libssl-1_1.dll


+ 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"/>