Browse Source

PIP-0027: EPASA hydration from protocol objects

Herman Schoenfeld 4 years ago
parent
commit
92d57fddad
6 changed files with 135 additions and 19 deletions
  1. 102 0
      src/core/UAccounts.pas
  2. 4 2
      src/core/UBlockChain.pas
  3. 21 3
      src/core/UEPasa.pas
  4. 1 8
      src/core/UNode.pas
  5. 3 1
      src/core/UOpTransaction.pas
  6. 4 5
      src/core/URPC.pas

+ 102 - 0
src/core/UAccounts.pas

@@ -118,6 +118,8 @@ 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 DecodeEPASAPartial(AAccount : Cardinal; const APayload : TBytes; APayloadType : Byte; ADefault : TEPasa) : TEPasa;
+    Class Function TryDecodeEPASAPartial(AAccount : Cardinal; const APayload : TBytes; APayloadType : Byte; out AEPasa : TEPasa) : Boolean;
   End;
 
   TPCSafeBox = Class;
@@ -1898,6 +1900,106 @@ begin
   end;
 end;
 
+class Function TAccountComp.DecodeEPASAPartial(AAccount : Cardinal; const APayload : TBytes; APayloadType : Byte; ADefault : TEPasa) : TEPasa;
+begin
+  if NOT TryDecodeEPASAPartial(AAccount, APayload, APayloadType, Result) then
+    Result := ADefault;
+end;
+
+class Function TAccountComp.TryDecodeEPASAPartial(AAccount : Cardinal; const APayload : TBytes; APayloadType : Byte; out AEPasa : TEPasa) : Boolean;
+var
+  LPayloadType : TPayloadType;
+  LUnencryptedPayloadBytes : TBytes;
+  LEPasaStr : String;
+  LPublic, LRecipientKeyEncrypted, LSenderKeyEncrypted,
+  LPasswordEncrypted, LAsciiFormatted, LHexFormatted, LBase58Formatted, LAddressedByName : Boolean;
+begin
+  LPayloadType := TEPasaComp.FromProtocolValue(APayloadType);
+  LPublic := LPayloadType.HasTrait(ptPublic);
+  LRecipientKeyEncrypted := LPayloadType.HasTrait(ptRecipientKeyEncrypted);
+  LSenderKeyEncrypted := LPayloadType.HasTrait(ptSenderKeyEncrypted);
+  LPasswordEncrypted := LPayloadType.HasTrait(ptPasswordEncrypted);
+  LAsciiFormatted := LPayloadType.HasTrait(ptAsciiFormatted);
+  LHexFormatted := LPayloadType.HasTrait(ptHexFormatted);
+  LBase58Formatted := LPayloadType.HasTrait(ptBase58Formatted);
+  LAddressedByName := LPayloadType.HasTrait(ptAddressedByName);
+
+  if LPayloadType.HasTrait(ptAddressedByName) then begin
+     (*LEPasaStr := Self.GetMempoolAccount(AAccount).name.ToPrintable;
+     if LEPasaStr.IsEmpty then
+       Exit(False); *)
+     // Note: since doing a name resolution for every encountered addressed-by-name EPASA,
+     // in V5 addressed-by-name EPASA's auto-resolved as addressed-by-number
+     LEPasaStr := TAccountComp.AccountNumberToAccountTxtNumber(AAccount);
+  end else LEPasaStr := TAccountComp.AccountNumberToAccountTxtNumber(AAccount);
+
+
+  // payload opening char
+  if LPublic then begin
+     LEPasaStr := LEPasaStr + '[';
+  end;
+
+  if LSenderKeyEncrypted then begin
+     LEPasaStr := LEPasaStr + '<';
+  end;
+
+  if LRecipientKeyEncrypted then begin
+     LEPasaStr := LEPasaStr + '(';
+  end;
+
+  if LPasswordEncrypted then begin
+     LEPasaStr := LEPasaStr + '{';
+  end;
+
+  // payload data
+  if LPublic OR LSenderKeyEncrypted OR LRecipientKeyEncrypted OR LPasswordEncrypted then begin
+
+    if LPublic then
+      LUnencryptedPayloadBytes := APayload
+    else if LSenderKeyEncrypted then
+      Exit(False) // todo
+    else if LRecipientKeyEncrypted then
+      Exit(False) // todo
+    else if LPasswordEncrypted then
+      Exit(False) // todo
+    else raise Exception.Create('Internal Error a0805389-df1a-4b40-b12e-d22327a3d049');
+
+    // decrypt data
+     if LAsciiFormatted then
+       LEPasaStr := LEPasaStr + '"' + TEncoding.ASCII.GetString(APayload) + '"'
+     else if LHexFormatted then
+       LEPasaStr := LEPasaStr + '0x' + THexEncoding.Encode(APayload)
+     else if LBase58Formatted then
+       LEPasaStr := LEPasaStr + TPascalBase58Encoding.Encode(APayload)
+     else raise Exception.Create('Internal Error 67a61d3e-eef2-40a9-8d92-45570f400c1e');
+  end;
+
+  // payload closing char
+  if LPublic then begin
+     LEPasaStr := LEPasaStr + ']';
+  end;
+
+  if LSenderKeyEncrypted then begin
+     LEPasaStr := LEPasaStr + '>';
+  end;
+
+  if LRecipientKeyEncrypted then begin
+     LEPasaStr := LEPasaStr + ')';
+  end;
+
+  if LPasswordEncrypted then begin
+     LEPasaStr := LEPasaStr + '}';
+  end;
+
+  // Parse as EPASA
+  if NOT TEPasa.TryParse(LEPasaStr, AEPasa) then
+    Exit(False);
+
+  Result := true;
+end;
+
+
+
 {$IFNDEF VER210}
 {$DEFINE DELPHIXE}
 {$ENDIF}

+ 4 - 2
src/core/UBlockChain.pas

@@ -28,7 +28,7 @@ uses
   Classes, UCrypto, UAccounts, ULog, UThread, SyncObjs, UBaseTypes, SysUtils,
   {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF},
   {$IFDEF USE_ABSTRACTMEM}UPCAbstractMem,{$ENDIF}
-  UPCDataTypes, UChunk;
+  UPCDataTypes, UChunk, UEPasa;
 
 {
 
@@ -139,6 +139,7 @@ Type
 
   TMultiOpSender = Record
     Account : Cardinal;
+    AccountEPASA : TEPasa;
     Amount : Int64;
     N_Operation : Cardinal;
     OpData : TMultiOpData; // Filled only when Operation is TOpData type
@@ -148,6 +149,7 @@ Type
   TMultiOpSenders = Array of TMultiOpSender;
   TMultiOpReceiver = Record
     Account : Cardinal;
+    AccountEPASA : TEPasa;
     Amount : Int64;
     Payload : TOperationPayload;
   end;
@@ -575,7 +577,7 @@ Type
 Const
   CT_TOperationPayload_NUL : TOperationPayload = (payload_type:0;payload_raw: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:Nil;y:Nil);OperationTxt:'';Amount:0;Fee:0;Balance:0;OriginalPayload:(payload_type:0;payload_raw:nil);PrintablePayload:'';OperationHash:Nil;OperationHash_OLD:Nil;errors:'';isMultiOperation:False;Senders:Nil;Receivers:Nil;changers:Nil);
-  CT_TMultiOpSender_NUL : TMultiOpSender =  (Account:0;Amount:0;N_Operation:0;Payload:(payload_type:0;payload_raw:Nil);Signature:(r:Nil;s:Nil));
+  CT_TMultiOpSender_NUL : TMultiOpSender =  (Account:0;(*AccountEPASA:TEPasa.Empty;*)Amount:0;N_Operation:0;Payload:(payload_type:0;payload_raw:Nil);Signature:(r:Nil;s:Nil));
   CT_TMultiOpReceiver_NUL : TMultiOpReceiver = (Account:0;Amount:0;Payload:(payload_type:0;payload_raw:Nil));
   CT_TMultiOpChangeInfo_NUL : TMultiOpChangeInfo = (Account:0;N_Operation:0;Changes_type:[];New_Accountkey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);New_Name:Nil;New_Type:0;New_Data:Nil;Seller_Account:-1;Account_Price:-1;Locked_Until_Block:0;
     Hashed_secret:Nil;

+ 21 - 3
src/core/UEPasa.pas

@@ -46,7 +46,7 @@ type
 
   TPayloadTrait = (
     ptNonDeterministic = 0,      // Payload encryption and encoding method not specified.
-    ptPublic = 1,               // Unencrypted, public payload.
+    ptPublic = 1,                // Unencrypted, public payload.
     ptRecipientKeyEncrypted = 2, // ECIES encrypted using recipient accounts public key.
     ptSenderKeyEncrypted = 3,    // ECIES encrypted using sender accounts public key.
     ptPasswordEncrypted = 4,     // AES encrypted using pwd param
@@ -73,7 +73,6 @@ type
   public
     function HasTrait(APayloadTrait: TPayloadTrait): Boolean; inline;
     function ToProtocolValue : byte;
-    class function FromProtocolValue(AValue : Byte) : TPayloadType; static;
   end;
 
   { TEPasa }
@@ -196,6 +195,7 @@ type
 
       class function GetPayloadTypeProtocolByte(const APayloadType : TPayloadType) : Byte;
       class function GetPayloadTypeFromProtocolByte(AByte : Byte) : TPayloadType;
+      class function FromProtocolValue(AVal : Byte) : TPayloadType;
   end;
 
 resourcestring
@@ -249,7 +249,6 @@ begin
   Result := TEPasaComp.GetPayloadTypeProtocolByte(Self);
 end;
 
-
 { TEPasa }
 
 function TEPasa.GetAccount: TNullable<UInt32>;
@@ -748,6 +747,25 @@ begin
   end;
 end;
 
+class function TEPasaComp.FromProtocolValue(AVal : Byte) : TPayloadType;
+begin
+  if AVal = 0 then begin
+    Exit([ptNonDeterministic]);
+  end;
+  Result := [];
+  if AVal AND BYTE_BIT_0 <> 0 then Result := Result + [ptPublic];
+  if AVal AND BYTE_BIT_1 <> 0 then Result := Result + [ptRecipientKeyEncrypted];
+  if AVal AND BYTE_BIT_2 <> 0 then Result := Result + [ptSenderKeyEncrypted];
+  if AVal AND BYTE_BIT_3 <> 0 then Result := Result + [ptPasswordEncrypted];
+  if AVal AND BYTE_BIT_4 <> 0 then Result := Result + [ptAsciiFormatted];
+  if AVal AND BYTE_BIT_5 <> 0 then Result := Result + [ptHexFormatted];
+  if AVal AND BYTE_BIT_6 <> 0 then Result := Result + [ptBase58Formatted];
+  if AVal AND BYTE_BIT_7 <> 0 then Result := Result + [ptAddressedByName];
+end;
+
+
+
+
 initialization
 
 EmptyEPasa := Default(TEPasa);

+ 1 - 8
src/core/UNode.pas

@@ -35,7 +35,7 @@ interface
 
 uses
   Classes, SysUtils,
-  {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF}, UPCDataTypes,
+  {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF}, UPCDataTypes, UEncoding,
   UBlockChain, UNetProtocol, UAccounts, UCrypto, UEPasa, UThread, SyncObjs, ULog, UBaseTypes, UPCOrderedLists;
 
 {$I ./../config.inc}
@@ -131,7 +131,6 @@ Type
     //
     function TryFindAccountByKey(const APubKey : TAccountKey; out AAccountNumber : Cardinal) : Boolean;
     function TryFindPublicSaleAccount(AMaximumPrice : Int64; APreventRaceCondition : Boolean; out AAccountNumber : Cardinal) : Boolean;
-    Function TryDecodeEPASA(AAccount : Cardinal; const APayload : TBytes; APayloadType : Byte; out LEPasa : TEPasa) : Boolean;
     Function TryResolveEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal): Boolean; overload;
     Function TryResolveEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal; out AErrorMessage: String): Boolean; overload;
     Function TryResolveEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : boolean): Boolean; overload;
@@ -846,12 +845,6 @@ begin
   end;
 end;
 
-
-Function TNode.TryDecodeEPASA(AAccount : Cardinal; const APayload : TBytes; APayloadType : Byte; out LEPasa : TEPasa) : Boolean;
-begin
-  dddddd
-end;
-
 Function TNode.TryResolveEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal): Boolean;
 var LErrMsg : String;
 begin

+ 3 - 1
src/core/UOpTransaction.pas

@@ -27,7 +27,7 @@ interface
 
 Uses UCrypto, UBlockChain, Classes, UAccounts, UBaseTypes,
   {$IFNDEF FPC}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF},
-  UPCDataTypes;
+  UPCDataTypes, UEPasa;
 
 Type
   // Operations Type
@@ -1189,6 +1189,7 @@ begin
   SetLength(OperationResume.Senders,1);
   OperationResume.Senders[0] := CT_TMultiOpSender_NUL;
   OperationResume.Senders[0].Account:=FData.sender;
+  OperationResume.Senders[0].AccountEPASA := TAccountComp.DecodeEPASAPartial(FData.sender, FData.payload.payload_raw, FData.payload.payload_type, TEPasa.Empty);
   OperationResume.Senders[0].Amount:=Int64(FData.amount + FData.fee);
   OperationResume.Senders[0].N_Operation:=FData.n_operation;
   OperationResume.Senders[0].Payload:=FData.payload;
@@ -1198,6 +1199,7 @@ begin
       SetLength(OperationResume.Receivers,1);
       OperationResume.Receivers[0] := CT_TMultiOpReceiver_NUL;
       OperationResume.Receivers[0].Account:=FData.target;
+      OperationResume.Receivers[0].AccountEPASA:=TAccountComp.DecodeEPASAPartial(FData.target, FData.payload.payload_raw, FData.payload.payload_type, TEPasa.Empty);
       OperationResume.Receivers[0].Amount:=FData.amount;
       OperationResume.Receivers[0].Payload:=FData.payload;
     end;

+ 4 - 5
src/core/URPC.pas

@@ -158,7 +158,6 @@ Type
     class function FindRegisteredProcessMethod(Const AMethodName : String) : TRPCProcessMethod;
   end;
 
-
 implementation
 
 Uses
@@ -253,13 +252,13 @@ Begin
     jsonObject.GetAsVariant('signer_account').Value:=OPR.SignerAccount;
     if (OPR.n_operation>0) then jsonObject.GetAsVariant('n_operation').Value:=OPR.n_operation;
   end;
-  // New V3: Will include senders[], receivers[] and changers[]
+    // New V3: Will include senders[], receivers[] and changers[]
     jsonArr := jsonObject.GetAsArray('senders');
     for i:=Low(OPR.senders) to High(OPR.Senders) do begin
       LString := TCrypto.ToHexaString(OPR.Senders[i].Payload.payload_raw);
       auxObj := jsonArr.GetAsObject(jsonArr.Count);
       auxObj.GetAsVariant('account').Value := OPR.Senders[i].Account;
-      auxObj.GetAsVariant('account_epasa').Value := FNode.DecodeEPASA(OPR.Senders[i].Account, LString, OPR.Senders[i].Payload.payload_type).ToString();
+      auxObj.GetAsVariant('account_epasa').Value := OPR.Senders[i].AccountEPASA.ToString();
       if (OPR.Senders[i].N_Operation>0) then auxObj.GetAsVariant('n_operation').Value := OPR.Senders[i].N_Operation;
       auxObj.GetAsVariant('amount').Value := TAccountComp.FormatMoneyDecimal(OPR.Senders[i].Amount * (-1));
       auxObj.GetAsVariant('amount_s').Value := TAccountComp.FormatMoney (OPR.Senders[i].Amount * (-1));
@@ -590,7 +589,7 @@ begin
     LStr := TCrypto.ToHexaString(multiOperation.Data.txSenders[i].Payload.payload_raw);
     auxObj := jsonArr.GetAsObject(jsonArr.Count);
     auxObj.GetAsVariant('account').Value := multiOperation.Data.txSenders[i].Account;
-    auxObj.GetAsVariant('account_epasa').Value := FNode.DecodeEPASA(multiOperation.Data.txSenders[i].Account, LStr, multiOperation.Data.txSenders[i].Payload.payload_type).ToString();
+    auxObj.GetAsVariant('account_epasa').Value := multiOperation.Data.txSenders[i].AccountEPASA.ToString();
     auxObj.GetAsVariant('n_operation').Value := multiOperation.Data.txSenders[i].N_Operation;
     auxObj.GetAsVariant('amount').Value := TAccountComp.FormatMoneyDecimal(multiOperation.Data.txSenders[i].Amount * (-1));
     auxObj.GetAsVariant('payload').Value := LStr;
@@ -602,7 +601,7 @@ begin
     LStr := TCrypto.ToHexaString(multiOperation.Data.txSenders[i].Payload.payload_raw);
     auxObj := jsonArr.GetAsObject(jsonArr.Count);
     auxObj.GetAsVariant('account').Value := multiOperation.Data.txReceivers[i].Account;
-    auxObj.GetAsVariant('account_epasa').Value := FNode.DecodeEPASA(multiOperation.Data.txReceivers[i].Account, LStr, multiOperation.Data.txReceivers[i].Payload.payload_type).ToString();
+    auxObj.GetAsVariant('account_epasa').Value := multiOperation.Data.txReceivers[i].AccountEPASA.ToString();
     auxObj.GetAsVariant('amount').Value := TAccountComp.FormatMoneyDecimal(multiOperation.Data.txReceivers[i].Amount);
     auxObj.GetAsVariant('payload').Value := TCrypto.ToHexaString(multiOperation.Data.txReceivers[i].Payload.payload_raw);
     auxObj.GetAsVariant('payload_type').Value := multiOperation.Data.txReceivers[i].Payload.payload_type;