Browse Source

TOperationResume

PascalCoin 7 years ago
parent
commit
0dbcf5679e
3 changed files with 134 additions and 2 deletions
  1. 3 2
      src/core/UBlockChain.pas
  2. 98 0
      src/core/UOpTransaction.pas
  3. 33 0
      src/core/UTxMultiOperation.pas

+ 3 - 2
src/core/UBlockChain.pas

@@ -132,6 +132,7 @@ Type
     New_Accountkey: TAccountKey;  // If (changes_mask and $0001)=$0001 then change account key
     New_Accountkey: TAccountKey;  // If (changes_mask and $0001)=$0001 then change account key
     New_Name: TRawBytes;          // If (changes_mask and $0002)=$0002 then change name
     New_Name: TRawBytes;          // If (changes_mask and $0002)=$0002 then change name
     New_Type: Word;               // If (changes_mask and $0004)=$0004 then change type
     New_Type: Word;               // If (changes_mask and $0004)=$0004 then change type
+    Fee: Int64;
     Signature: TECDSA_SIG;
     Signature: TECDSA_SIG;
   end;
   end;
   TMultiOpChangesInfo = Array of TMultiOpChangeInfo;
   TMultiOpChangesInfo = Array of TMultiOpChangeInfo;
@@ -471,7 +472,7 @@ Const
   CT_TOperationResume_NUL : TOperationResume = (valid:false;Block:0;NOpInsideBlock:-1;OpType:0;OpSubtype:0;time:0;AffectedAccount:0;SignerAccount:-1;n_operation:0;DestAccount:-1;SellerAccount:-1;newKey:(EC_OpenSSL_NID:0;x:'';y:'');OperationTxt:'';Amount:0;Fee:0;Balance:0;OriginalPayload:'';PrintablePayload:'';OperationHash:'';OperationHash_OLD:'';errors:'';isMultiOperation:False;Senders:Nil;Receivers:Nil;changers:Nil);
   CT_TOperationResume_NUL : TOperationResume = (valid:false;Block:0;NOpInsideBlock:-1;OpType:0;OpSubtype:0;time:0;AffectedAccount:0;SignerAccount:-1;n_operation:0;DestAccount:-1;SellerAccount:-1;newKey:(EC_OpenSSL_NID:0;x:'';y:'');OperationTxt:'';Amount:0;Fee:0;Balance:0;OriginalPayload:'';PrintablePayload:'';OperationHash:'';OperationHash_OLD:'';errors:'';isMultiOperation:False;Senders:Nil;Receivers:Nil;changers:Nil);
   CT_TMultiOpSender_NUL : TMultiOpSender =  (Account:0;Amount:0;N_Operation:0;Payload:'';Signature:(r:'';s:''));
   CT_TMultiOpSender_NUL : TMultiOpSender =  (Account:0;Amount:0;N_Operation:0;Payload:'';Signature:(r:'';s:''));
   CT_TMultiOpReceiver_NUL : TMultiOpReceiver = (Account:0;Amount:0;Payload:'');
   CT_TMultiOpReceiver_NUL : TMultiOpReceiver = (Account:0;Amount:0;Payload:'');
-  CT_TMultiOpChangeInfo_NUL : TMultiOpChangeInfo = (Account:0;N_Operation:0;Changes_type:[];New_Accountkey:(EC_OpenSSL_NID:0;x:'';y:'');New_Name:'';New_Type:0;Signature:(r:'';s:''));
+  CT_TMultiOpChangeInfo_NUL : TMultiOpChangeInfo = (Account:0;N_Operation:0;Changes_type:[];New_Accountkey:(EC_OpenSSL_NID:0;x:'';y:'');New_Name:'';New_Type:0;Fee:0;Signature:(r:'';s:''));
   CT_TOpChangeAccountInfoType_Txt : Array[Low(TOpChangeAccountInfoType)..High(TOpChangeAccountInfoType)] of AnsiString = ('public_key','account_name','account_type');
   CT_TOpChangeAccountInfoType_Txt : Array[Low(TOpChangeAccountInfoType)..High(TOpChangeAccountInfoType)] of AnsiString = ('public_key','account_name','account_type');
 
 
 implementation
 implementation
@@ -2616,7 +2617,7 @@ begin
   If TCrypto.IsHumanReadable(OperationResume.OriginalPayload) then OperationResume.PrintablePayload := OperationResume.OriginalPayload
   If TCrypto.IsHumanReadable(OperationResume.OriginalPayload) then OperationResume.PrintablePayload := OperationResume.OriginalPayload
   else OperationResume.PrintablePayload := TCrypto.ToHexaString(OperationResume.OriginalPayload);
   else OperationResume.PrintablePayload := TCrypto.ToHexaString(OperationResume.OriginalPayload);
   OperationResume.OperationHash:=TPCOperation.OperationHashValid(Operation,Block);
   OperationResume.OperationHash:=TPCOperation.OperationHashValid(Operation,Block);
-  if (Block<CT_Protocol_Upgrade_v2_MinBlock) then begin
+  if (Block>0) And (Block<CT_Protocol_Upgrade_v2_MinBlock) then begin
     OperationResume.OperationHash_OLD:=TPCOperation.OperationHash_OLD(Operation,Block);
     OperationResume.OperationHash_OLD:=TPCOperation.OperationHash_OLD(Operation,Block);
   end;
   end;
   OperationResume.valid := true;
   OperationResume.valid := true;

+ 98 - 0
src/core/UOpTransaction.pas

@@ -73,6 +73,7 @@ Type
     procedure InitializeData; override;
     procedure InitializeData; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
+    procedure FillOperationResume(Block : Cardinal; getInfoForAllAccounts : Boolean; Affected_account_number : Cardinal; var OperationResume : TOperationResume); override;
   public
   public
     function GetBufferForOpHash(UseProtocolV2 : Boolean): TRawBytes; override;
     function GetBufferForOpHash(UseProtocolV2 : Boolean): TRawBytes; override;
     function DoOperation(AccountPreviousUpdatedBlock : TAccountPreviousBlockInfo; AccountTransaction : TPCSafeBoxTransaction; var errors : AnsiString) : Boolean; override;
     function DoOperation(AccountPreviousUpdatedBlock : TAccountPreviousBlockInfo; AccountTransaction : TPCSafeBoxTransaction; var errors : AnsiString) : Boolean; override;
@@ -103,6 +104,7 @@ Type
     procedure InitializeData; override;
     procedure InitializeData; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
+    procedure FillOperationResume(Block : Cardinal; getInfoForAllAccounts : Boolean; Affected_account_number : Cardinal; var OperationResume : TOperationResume); override;
   public
   public
     Class Function GetOperationHashToSign(const op : TOpChangeKeyData) : TRawBytes;
     Class Function GetOperationHashToSign(const op : TOpChangeKeyData) : TRawBytes;
     Class Function DoSignOperation(key : TECPrivateKey; var op : TOpChangeKeyData) : Boolean;
     Class Function DoSignOperation(key : TECPrivateKey; var op : TOpChangeKeyData) : Boolean;
@@ -139,6 +141,7 @@ Type
     procedure InitializeData; override;
     procedure InitializeData; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
+    procedure FillOperationResume(Block : Cardinal; getInfoForAllAccounts : Boolean; Affected_account_number : Cardinal; var OperationResume : TOperationResume); override;
   public
   public
     class function OpType : Byte; override;
     class function OpType : Byte; override;
 
 
@@ -203,6 +206,7 @@ Type
     procedure InitializeData; override;
     procedure InitializeData; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
+    procedure FillOperationResume(Block : Cardinal; getInfoForAllAccounts : Boolean; Affected_account_number : Cardinal; var OperationResume : TOperationResume); override;
   public
   public
     Class Function GetOperationHashToSign(const operation : TOpListAccountData) : TRawBytes;
     Class Function GetOperationHashToSign(const operation : TOpListAccountData) : TRawBytes;
     Class Function DoSignOperation(key : TECPrivateKey; var operation : TOpListAccountData) : Boolean;
     Class Function DoSignOperation(key : TECPrivateKey; var operation : TOpListAccountData) : Boolean;
@@ -257,6 +261,7 @@ Type
     procedure InitializeData; override;
     procedure InitializeData; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
     function LoadOpFromStream(Stream: TStream; LoadExtendedData : Boolean): Boolean; override;
+    procedure FillOperationResume(Block : Cardinal; getInfoForAllAccounts : Boolean; Affected_account_number : Cardinal; var OperationResume : TOperationResume); override;
   public
   public
     Class Function GetOperationHashToSign(const op : TOpChangeAccountInfoData) : TRawBytes;
     Class Function GetOperationHashToSign(const op : TOpChangeAccountInfoData) : TRawBytes;
     Class Function DoSignOperation(key : TECPrivateKey; var op : TOpChangeAccountInfoData) : Boolean;
     Class Function DoSignOperation(key : TECPrivateKey; var op : TOpChangeAccountInfoData) : Boolean;
@@ -356,6 +361,30 @@ begin
   Result := true;
   Result := true;
 end;
 end;
 
 
+procedure TOpChangeAccountInfo.FillOperationResume(Block: Cardinal; getInfoForAllAccounts: Boolean; Affected_account_number: Cardinal; var OperationResume: TOperationResume);
+begin
+  inherited FillOperationResume(Block, getInfoForAllAccounts, Affected_account_number, OperationResume);
+  SetLength(OperationResume.Changers,1);
+  OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
+  OperationResume.Changers[0].Account := FData.account_target;
+  OperationResume.Changers[0].Changes_type := FData.changes_type;
+  OperationResume.Changers[0].New_Accountkey := FData.new_accountkey;
+  OperationResume.Changers[0].New_Name := FData.new_name;
+  OperationResume.Changers[0].New_Type := FData.new_type;
+  If (FData.account_signer=FData.account_target) then begin
+    OperationResume.Changers[0].N_Operation := FData.n_operation;
+    OperationResume.Changers[0].Signature := FData.sign;
+    OperationResume.Changers[0].Fee := FData.fee;
+  end else begin
+    SetLength(OperationResume.Changers,2);
+    OperationResume.Changers[1] := CT_TMultiOpChangeInfo_NUL;
+    OperationResume.Changers[1].Account := FData.account_signer;
+    OperationResume.Changers[1].N_Operation := FData.n_operation;
+    OperationResume.Changers[1].Fee := FData.fee;
+    OperationResume.Changers[1].Signature := FData.sign;
+  end;
+end;
+
 class function TOpChangeAccountInfo.GetOperationHashToSign(const op: TOpChangeAccountInfoData): TRawBytes;
 class function TOpChangeAccountInfo.GetOperationHashToSign(const op: TOpChangeAccountInfoData): TRawBytes;
 var Stream : TMemoryStream;
 var Stream : TMemoryStream;
   b : Byte;
   b : Byte;
@@ -938,6 +967,23 @@ begin
   Result := true;
   Result := true;
 end;
 end;
 
 
+procedure TOpTransaction.FillOperationResume(Block: Cardinal; getInfoForAllAccounts: Boolean; Affected_account_number: Cardinal; var OperationResume: TOperationResume);
+begin
+  inherited FillOperationResume(Block, getInfoForAllAccounts, Affected_account_number, OperationResume);
+  SetLength(OperationResume.Senders,1);
+  OperationResume.Senders[0] := CT_TMultiOpSender_NUL;
+  OperationResume.Senders[0].Account:=FData.sender;
+  OperationResume.Senders[0].Amount:=Int64(FData.amount + FData.fee) * (-1);
+  OperationResume.Senders[0].N_Operation:=FData.n_operation;
+  OperationResume.Senders[0].Payload:=FData.payload;
+  OperationResume.Senders[0].Signature:=FData.sign;
+  SetLength(OperationResume.Receivers,1);
+  OperationResume.Receivers[0] := CT_TMultiOpReceiver_NUL;
+  OperationResume.Receivers[0].Account:=FData.target;
+  OperationResume.Receivers[0].Amount:=FData.amount;
+  OperationResume.Receivers[0].Payload:=FData.payload;
+end;
+
 function TOpTransaction.OperationAmount: Int64;
 function TOpTransaction.OperationAmount: Int64;
 begin
 begin
   Result := FData.amount;
   Result := FData.amount;
@@ -1282,6 +1328,28 @@ begin
   Result := true;
   Result := true;
 end;
 end;
 
 
+procedure TOpChangeKey.FillOperationResume(Block: Cardinal; getInfoForAllAccounts: Boolean; Affected_account_number: Cardinal; var OperationResume: TOperationResume);
+begin
+  inherited FillOperationResume(Block, getInfoForAllAccounts, Affected_account_number, OperationResume);
+  SetLength(OperationResume.Changers,1);
+  OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
+  OperationResume.Changers[0].Account := FData.account_target;
+  OperationResume.Changers[0].Changes_type := [public_key];
+  OperationResume.Changers[0].New_Accountkey := FData.new_accountkey;
+  if (FData.account_signer=FData.account_target) then begin
+    OperationResume.Changers[0].N_Operation := FData.n_operation;
+    OperationResume.Changers[0].Fee := FData.fee;
+    OperationResume.Changers[0].Signature := FData.sign;
+  end else begin
+    SetLength(OperationResume.Changers,2);
+    OperationResume.Changers[1] := CT_TMultiOpChangeInfo_NUL;
+    OperationResume.Changers[1].Account := FData.account_signer;
+    OperationResume.Changers[1].N_Operation := FData.n_operation;
+    OperationResume.Changers[1].Fee := FData.fee;
+    OperationResume.Changers[1].Signature := FData.sign;
+  end;
+end;
+
 function TOpChangeKey.OperationAmount: Int64;
 function TOpChangeKey.OperationAmount: Int64;
 begin
 begin
   Result := 0;
   Result := 0;
@@ -1437,6 +1505,16 @@ begin
   Result := true;
   Result := true;
 end;
 end;
 
 
+procedure TOpRecoverFounds.FillOperationResume(Block: Cardinal; getInfoForAllAccounts: Boolean; Affected_account_number: Cardinal; var OperationResume: TOperationResume);
+begin
+  inherited FillOperationResume(Block, getInfoForAllAccounts, Affected_account_number, OperationResume);
+  SetLength(OperationResume.Changers,1);
+  OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
+  OperationResume.Changers[0].Account := FData.account;
+  OperationResume.Changers[0].Fee := FData.fee;
+  OperationResume.Changers[0].N_Operation := FData.n_operation;
+end;
+
 function TOpRecoverFounds.OperationAmount: Int64;
 function TOpRecoverFounds.OperationAmount: Int64;
 begin
 begin
   Result := 0;
   Result := 0;
@@ -1720,6 +1798,26 @@ begin
   Result := true;
   Result := true;
 end;
 end;
 
 
+procedure TOpListAccount.FillOperationResume(Block: Cardinal; getInfoForAllAccounts: Boolean; Affected_account_number: Cardinal; var OperationResume: TOperationResume);
+begin
+  inherited FillOperationResume(Block, getInfoForAllAccounts, Affected_account_number, OperationResume);
+  SetLength(OperationResume.Changers,1);
+  OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
+  OperationResume.Changers[0].Account:=FData.account_target;
+  if (FData.account_signer = FData.account_target) then begin
+    OperationResume.Changers[0].Fee:=FData.fee;
+    OperationResume.Changers[0].N_Operation:=FData.n_operation;
+    OperationResume.Changers[0].Signature:=FData.sign;
+  end else begin
+    SetLength(OperationResume.Changers,2);
+    OperationResume.Changers[1] := CT_TMultiOpChangeInfo_NUL;
+    OperationResume.Changers[1].Account := FData.account_signer;
+    OperationResume.Changers[1].N_Operation := FData.n_operation;
+    OperationResume.Changers[1].Fee := FData.fee;
+    OperationResume.Changers[1].Signature := FData.sign;
+  end;
+end;
+
 function TOpListAccount.N_Operation: Cardinal;
 function TOpListAccount.N_Operation: Cardinal;
 begin
 begin
   Result := FData.n_operation;
   Result := FData.n_operation;

+ 33 - 0
src/core/UTxMultiOperation.pas

@@ -101,6 +101,7 @@ Type
     FTotalAmount : Int64;
     FTotalAmount : Int64;
     FTotalFee : Int64;
     FTotalFee : Int64;
     Function IndexOfAccountChangeNameTo(const newName : AnsiString) : Integer;
     Function IndexOfAccountChangeNameTo(const newName : AnsiString) : Integer;
+    procedure ClearSignatures;
   protected
   protected
     procedure InitializeData; override;
     procedure InitializeData; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
     function SaveOpToStream(Stream: TStream; SaveExtendedData : Boolean): Boolean; override;
@@ -249,6 +250,17 @@ begin
   Result := -1;
   Result := -1;
 end;
 end;
 
 
+procedure TOpMultiOperation.ClearSignatures;
+var i : Integer;
+begin
+  for i:=0 to High(FData.txSenders) do begin
+    FData.txSenders[i].Signature := CT_TECDSA_SIG_Nul;
+  end;
+  for i:=0 to High(FData.changesInfo) do begin
+    FData.changesInfo[i].Signature := CT_TECDSA_SIG_Nul;
+  end;
+end;
+
 procedure TOpMultiOperation.InitializeData;
 procedure TOpMultiOperation.InitializeData;
 begin
 begin
   inherited InitializeData;
   inherited InitializeData;
@@ -881,6 +893,11 @@ begin
     // Allow receivers as a duplicate!
     // Allow receivers as a duplicate!
     If (receivers[i].Amount<=0) then Exit; // Must always receive >0
     If (receivers[i].Amount<=0) then Exit; // Must always receive >0
   end;
   end;
+  // Max Senders
+  If (length(senders)+length(FData.txSenders)) > CT_MAX_MultiOperation_Senders then Exit;
+  // Max Receivers
+  If (length(receivers)+length(FData.txReceivers)) > CT_MAX_MultiOperation_Receivers then Exit;
+
   // Ok, let's go
   // Ok, let's go
   FHasValidSignature:=False;
   FHasValidSignature:=False;
   If setInRandomOrder then begin
   If setInRandomOrder then begin
@@ -908,6 +925,7 @@ begin
       FData.txReceivers[j] := receivers[i];
       FData.txReceivers[j] := receivers[i];
       inc(total_receive,receivers[i].Amount);
       inc(total_receive,receivers[i].Amount);
     end;
     end;
+    ClearSignatures;
   end else begin
   end else begin
     j := length(FData.txSenders);
     j := length(FData.txSenders);
     SetLength(FData.txSenders,length(FData.txSenders)+length(senders));
     SetLength(FData.txSenders,length(FData.txSenders)+length(senders));
@@ -929,6 +947,8 @@ end;
 
 
 function TOpMultiOperation.AddChangeInfos(const changes: TMultiOpChangesInfo; setInRandomOrder : Boolean): Boolean;
 function TOpMultiOperation.AddChangeInfos(const changes: TMultiOpChangesInfo; setInRandomOrder : Boolean): Boolean;
 Var i,j,k : Integer;
 Var i,j,k : Integer;
+  ct : TOpChangeAccountInfoType;
+  ctypes : TOpChangeAccountInfoTypes;
 begin
 begin
   Result := False;
   Result := False;
   // Check not duplicate / invalid data
   // Check not duplicate / invalid data
@@ -937,7 +957,19 @@ begin
     If IndexOfAccountChanger(changes[i].Account)>=0 then Exit;
     If IndexOfAccountChanger(changes[i].Account)>=0 then Exit;
     If IndexOfAccountChanger(changes[i].Account,i+1,changes)>=0 then Exit;
     If IndexOfAccountChanger(changes[i].Account,i+1,changes)>=0 then Exit;
     If (changes[i].Changes_type=[]) then Exit; // Must change something
     If (changes[i].Changes_type=[]) then Exit; // Must change something
+    // check valid Change type
+    for ct:=Low(TOpChangeAccountInfoType) to High(TOpChangeAccountInfoType) do begin
+      case ct of
+        public_key,account_name,account_type : ; // Allowed
+      else
+        if (ct in changes[i].Changes_type) then begin
+          Exit; // Not allowed multioperation change type
+        end;
+      end;
+    end;
   end;
   end;
+  // Max Changers
+  If (length(changes)+length(FData.changesInfo)) > CT_MAX_MultiOperation_Changers then Exit;
   // Ok, let's go
   // Ok, let's go
   FHasValidSignature:=False;
   FHasValidSignature:=False;
   // Important:
   // Important:
@@ -957,6 +989,7 @@ begin
         j := Random(length(FData.changesInfo)); // Find random position 0..n-1
         j := Random(length(FData.changesInfo)); // Find random position 0..n-1
       end else j:=0;
       end else j:=0;
       for k:=High(FData.changesInfo) downto (j+1) do FData.changesInfo[k] := FData.changesInfo[k-1];
       for k:=High(FData.changesInfo) downto (j+1) do FData.changesInfo[k] := FData.changesInfo[k-1];
+      ClearSignatures;
     end else j := High(FData.changesInfo);
     end else j := High(FData.changesInfo);
     FData.changesInfo[j] := changes[i];
     FData.changesInfo[j] := changes[i];
   end;
   end;