Quellcode durchsuchen

Implementation of "account_epasa" on JSON RPC api calls

Using TEPasaDecoder.DecodeEPASA
Removed  TAccountComp.TryDecodeEPASAPartial
Pascal Coin vor 4 Jahren
Ursprung
Commit
acd7e065c0

+ 8 - 1
CHANGELOG.md

@@ -14,8 +14,15 @@
 - Improved performance when downloading Safebox (Fresh installation)
 - JSON-RPC changes:  
   - Updated "Operation Object" return values:
+    - "senders" : ARRAY
+      - "account_epasa" : (String) If operation was using valid E-PASA format and can be decoded, will return E-PASA format used
+    - "receivers" : ARRAY
+      - "account_epasa" : (String) If operation was using valid E-PASA format and can be decoded, will return E-PASA format used
+  - Updated "Multi Operation Object" return values:
+    - "senders" : ARRAY
+      - "account_epasa" : (String) If operation was using valid E-PASA format and can be decoded, will return E-PASA format used
     - "receivers" : ARRAY
-      - "account_epasa" : (String) If operation was using valid E-PASA format, will return E-PASA format
+      - "account_epasa" : (String) If operation was using valid E-PASA format and can be decoded, will return E-PASA format used
   - Updated "findaccounts": 
     -New param "end" (integer, -1 for default): Will search from "start" to "end" (if "end"=-1 will search to the end)
   - New method "findblocks": Will search and return an array of "Block objects"

+ 1 - 104
src/core/UAccounts.pas

@@ -26,7 +26,7 @@ interface
 
 uses
   Classes, SysUtils, UConst, UCrypto, SyncObjs, UThread, UBaseTypes,
-  UPCOrderedLists, UPCDataTypes, UPCSafeBoxRootHash, UEPasa,
+  UPCOrderedLists, UPCDataTypes, UPCSafeBoxRootHash,
   UPCHardcodedRandomHashTable, UJSONFunctions,
   {$IFDEF USE_ABSTRACTMEM}
   UPCAbstractMem, UPCAbstractMemAccountKeys,
@@ -118,8 +118,6 @@ 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;
@@ -1900,107 +1898,6 @@ 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
-  AEPasa.Clear;
-  LPayloadType := TEPasaComp.FromProtocolValue(APayloadType);
-  if LPayloadType.HasTrait(ptNonDeterministic) then Exit(False);
-  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,
-     // would overwhelm the SafeBox with lookups, names are not resolved.
-     // So 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: Partial decoding does not decrypt due to performance penalty if always decrypting. This needs to be implemented as a IFuture<TBytes> value with lazy evaluation.
-    else if LRecipientKeyEncrypted then
-      Exit(False) // Todo: Partial decoding does not decrypt due to performance penalty if always decrypting. This needs to be implemented as a IFuture<TBytes> value with lazy evaluation.
-    else if LPasswordEncrypted then
-      Exit(False) // Todo: Partial decoding does not decrypt due to performance penalty if always decrypting. This needs to be implemented as a IFuture<TBytes> value with lazy evaluation..
-    else raise Exception.Create('Internal Error a0805389-df1a-4b40-b12e-d22327a3d049');
-
-    // decrypt data
-     if LAsciiFormatted then
-       LEPasaStr := LEPasaStr + '"' + TEncoding.ASCII.GetString(LUnencryptedPayloadBytes) + '"'
-     else if LHexFormatted then
-       LEPasaStr := LEPasaStr + '0x' + THexEncoding.Encode(LUnencryptedPayloadBytes)
-     else if LBase58Formatted then
-       LEPasaStr := LEPasaStr + TPascalBase58Encoding.Encode(LUnencryptedPayloadBytes)
-     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}

+ 1 - 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, UEPasa;
+  UPCDataTypes, UChunk;
 
 {
 
@@ -148,7 +148,6 @@ Type
   TMultiOpSenders = Array of TMultiOpSender;
   TMultiOpReceiver = Record
     Account : Cardinal;
-    AccountEPASA : TEPasa;
     Amount : Int64;
     Payload : TOperationPayload;
   end;

+ 12 - 0
src/core/UEPasaDecoder.pas

@@ -43,6 +43,7 @@ type
       out ADecodeEPasaResult : TDecodeEPasaResult; out AEPasa : TEPasa) : Boolean; overload;
     class Function TryDecodeEPASA(AAccount : Cardinal; const APayload : TOperationPayload; const ANode : TNode; const AWalletKeys : TWalletKeys; const APasswords : TList<String>;
       out AEPasa : TEPasa) : Boolean; overload;
+    class Function DecodeEPASA(AAccount : Cardinal; const APayload : TOperationPayload; const ANode : TNode; const AWalletKeys : TWalletKeys; const APasswords : TList<String>) : String; overload;
   End;
 
 implementation
@@ -121,6 +122,7 @@ begin
       while (Not LDone) and (i < APasswords.Count) do begin
         LPwd.FromString(APasswords[i]);
         if TPCEncryption.DoPascalCoinAESDecrypt(APayload.payload_raw,LPwd,LUnencryptedPayloadBytes) then begin
+          AEPasa.Password := APasswords[i];
           LDone := True;
         end;
         inc(i);
@@ -156,6 +158,16 @@ begin
   Result := true;
 end;
 
+class function TEPasaDecoder.DecodeEPASA(AAccount: Cardinal;
+  const APayload: TOperationPayload; const ANode: TNode;
+  const AWalletKeys: TWalletKeys; const APasswords: TList<String>): String;
+var LEPasa : TEPasa;
+begin
+  if TryDecodeEPASA(AAccount,APayload,ANode,AWalletKeys,APasswords,LEPasa) then begin
+    Result := LEPasa.ToClassicPASAString;
+  end else Result := '';
+end;
+
 class function TEPasaDecoder.TryDecodeEPASA(AAccount: Cardinal;
   const APayload: TOperationPayload; const ANode : TNode; const AWalletKeys: TWalletKeys;
   const APasswords: TList<String>; out AEPasa: TEPasa): Boolean;

+ 0 - 4
src/core/UOpTransaction.pas

@@ -1198,19 +1198,16 @@ 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;
     buy_account, transaction_with_auto_buy_account, transaction_with_auto_atomic_swap : begin
       SetLength(OperationResume.Receivers,2);
       OperationResume.Receivers[0] := CT_TMultiOpReceiver_NUL;
-      OperationResume.Receivers[0].AccountEPASA:=TAccountComp.DecodeEPASAPartial(FData.target, FData.payload.payload_raw, FData.payload.payload_type, TEPasa.Empty);
       OperationResume.Receivers[0].Account:=FData.target;
       OperationResume.Receivers[0].Amount:= (FData.amount - FData.AccountPrice);
       OperationResume.Receivers[0].Payload:=FData.payload;
       OperationResume.Receivers[1] := CT_TMultiOpReceiver_NUL;
-      OperationResume.Receivers[1].AccountEPASA:=TAccountComp.DecodeEPASAPartial(FData.SellerAccount, FData.payload.payload_raw, FData.payload.payload_type, TEPasa.Empty);
       OperationResume.Receivers[1].Account:=FData.SellerAccount;
       OperationResume.Receivers[1].Amount:= FData.AccountPrice;
       OperationResume.Receivers[1].Payload:=FData.payload;
@@ -2652,7 +2649,6 @@ begin
   //
   SetLength(OperationResume.Receivers,1);
   OperationResume.Receivers[0] := CT_TMultiOpReceiver_NUL;
-  OperationResume.Receivers[0].AccountEPASA.Clear;
   OperationResume.Receivers[0].Account:=FData.account_target;
   OperationResume.Receivers[0].Amount:=FData.amount;
   OperationResume.Receivers[0].Payload:=FData.payload;

+ 6 - 2
src/core/UPCRPCOpData.pas

@@ -297,7 +297,9 @@ begin
     LResultArray := AJSONResponse.GetAsArray('result');
 
     for i := 0 to LOperationsResumeList.Count-1 do begin
-      TPascalCoinJSONComp.FillOperationObject(LOperationsResumeList.OperationResume[i],ASender.Node.Bank.BlocksCount,LResultArray.GetAsObject( LResultArray.Count ));
+      TPascalCoinJSONComp.FillOperationObject(LOperationsResumeList.OperationResume[i],ASender.Node.Bank.BlocksCount,
+        ASender.Node,ASender.RPCServer.WalletKeys,ASender.RPCServer.PayloadPasswords,
+        LResultArray.GetAsObject( LResultArray.Count ));
     end;
     Result := True;
   finally
@@ -362,7 +364,9 @@ begin
       Exit;
     end;
     TPCOperation.OperationToOperationResume(0,LOpData,False,LSender.account,LOPR);
-    TPascalCoinJSONComp.FillOperationObject(LOPR,ASender.Node.Bank.BlocksCount,AJSONResponse.GetAsObject('result'));
+    TPascalCoinJSONComp.FillOperationObject(LOPR,ASender.Node.Bank.BlocksCount,
+      ASender.Node,ASender.RPCServer.WalletKeys,ASender.RPCServer.PayloadPasswords,
+      AJSONResponse.GetAsObject('result'));
     Result := True;
   finally
     LOpData.free;

+ 3 - 1
src/core/UPCRPCSend.pas

@@ -188,7 +188,9 @@ begin
         Exit;
       end;
       TPCOperation.OperationToOperationResume(0,LOpt,False,LSender.account,LOpr);
-      TPascalCoinJSONComp.FillOperationObject(LOpr,ASender.Node.Bank.BlocksCount,AJSONResponse.GetAsObject('result'));
+      TPascalCoinJSONComp.FillOperationObject(LOpr,ASender.Node.Bank.BlocksCount,
+        ASender.Node,ASender.RPCServer.WalletKeys,ASender.RPCServer.PayloadPasswords,
+        AJSONResponse.GetAsObject('result'));
       Result := true;
     finally
       LOpt.free;

+ 21 - 11
src/core/URPC.pas

@@ -67,9 +67,9 @@ Type
   public
     class procedure FillAccountObject(Const account : TAccount; jsonObj : TPCJSONObject);
     class procedure FillBlockObject(nBlock : Cardinal; ANode : TNode; jsonObject: TPCJSONObject);
-    class procedure FillOperationObject(Const OPR : TOperationResume; currentNodeBlocksCount : Cardinal; jsonObject : TPCJSONObject);
+    class procedure FillOperationObject(Const OPR : TOperationResume; currentNodeBlocksCount : Cardinal; const ANode : TNode; const AWalletKeys : TWalletKeys; const APasswords : TList<String>; jsonObject : TPCJSONObject); overload;
     class procedure FillOperationsHashTreeObject(Const OperationsHashTree : TOperationsHashTree; jsonObject : TPCJSONObject);
-    class procedure FillMultiOperationObject(current_protocol : Word; Const multiOperation : TOpMultiOperation; jsonObject : TPCJSONObject);
+    class procedure FillMultiOperationObject(current_protocol : Word; Const multiOperation : TOpMultiOperation; const ANode : TNode; const AWalletKeys : TWalletKeys; const APasswords : TList<String>; jsonObject : TPCJSONObject);
     class procedure FillPublicKeyObject(const PubKey : TAccountKey; jsonObj : TPCJSONObject);
     class function ToPascalCoins(jsonCurr : Real) : Int64;
     //
@@ -97,6 +97,7 @@ Type
     FValidIPs: String;
     FAllowUsePrivateKeys: Boolean;
     FNode : TNode;
+    FPayloadPasswords: TList<String>;
     procedure SetActive(AValue: Boolean);
     procedure SetIniFileName(const Value: String);
     procedure SetLogFileName(const Value: String);
@@ -111,6 +112,7 @@ Type
     Property Port : Word read FPort Write FPort;
     Property Active : Boolean read FActive write SetActive;
     Property WalletKeys : TWalletKeysExt read FWalletKeys write FWalletKeys;
+    Property PayloadPasswords: TList<String> read FPayloadPasswords;
     //
     Property JSON20Strict : Boolean read FJSON20Strict write FJSON20Strict;
     Property IniFileName : String read FIniFileName write SetIniFileName;
@@ -163,6 +165,7 @@ implementation
 Uses
   {$IFNDEF FPC}windows,{$ENDIF}
   SysUtils, Synautil,
+  UEPasaDecoder,
   UPCRPCSend,
   UPCRPCOpData, UPCRPCFindAccounts, UPCRPCFindBlocks, UPCRPCFileUtils;
 
@@ -214,7 +217,8 @@ begin
   end;
 end;
 
-class procedure TPascalCoinJSONComp.FillOperationObject(const OPR: TOperationResume; currentNodeBlocksCount : Cardinal; jsonObject: TPCJSONObject);
+class procedure TPascalCoinJSONComp.FillOperationObject(const OPR: TOperationResume; currentNodeBlocksCount : Cardinal;
+  const ANode : TNode; const AWalletKeys : TWalletKeys; const APasswords : TList<String>; jsonObject: TPCJSONObject);
 Var i : Integer;
   LOpChangeAccountInfoType : TOpChangeAccountInfoType;
   LString : String;
@@ -258,6 +262,7 @@ 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 := TEPasaDecoder.DecodeEPASA(OPR.Senders[i].Account,OPR.Senders[i].Payload,ANode,AWalletKeys,APasswords);
       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));
@@ -272,7 +277,7 @@ Begin
     for i:=Low(OPR.Receivers) to High(OPR.Receivers) do begin
       auxObj := jsonArr.GetAsObject(jsonArr.Count);
       auxObj.GetAsVariant('account').Value := OPR.Receivers[i].Account;
-      auxObj.GetAsVariant('account_epasa').Value := OPR.Receivers[i].AccountEPASA.ToString;
+      auxObj.GetAsVariant('account_epasa').Value := TEPasaDecoder.DecodeEPASA(OPR.Receivers[i].Account,OPR.Receivers[i].Payload,ANode,AWalletKeys,APasswords);
       auxObj.GetAsVariant('amount').Value :=  TAccountComp.FormatMoneyDecimal(OPR.Receivers[i].Amount);
       auxObj.GetAsVariant('amount_s').Value :=  TAccountComp.FormatMoney(OPR.Receivers[i].Amount);
       auxObj.GetAsVariant('payload').Value := TCrypto.ToHexaString(OPR.Receivers[i].Payload.payload_raw);
@@ -564,7 +569,8 @@ begin
   jsonObject.GetAsVariant('rawoperations').Value:=OperationsHashTreeToHexaString(OperationsHashTree);
 end;
 
-class procedure TPascalCoinJSONComp.FillMultiOperationObject(current_protocol : Word; const multiOperation: TOpMultiOperation; jsonObject: TPCJSONObject);
+class procedure TPascalCoinJSONComp.FillMultiOperationObject(current_protocol : Word; const multiOperation: TOpMultiOperation;
+  const ANode : TNode; const AWalletKeys : TWalletKeys; const APasswords : TList<String>; jsonObject: TPCJSONObject);
 Var i, nSigned, nNotSigned : Integer;
   opht : TOperationsHashTree;
   jsonArr : TPCJSONArray;
@@ -593,6 +599,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 := TEPasaDecoder.DecodeEPASA(multiOperation.Data.txSenders[i].Account,multiOperation.Data.txSenders[i].Payload,ANode,AWalletKeys,APasswords);
     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;
@@ -604,7 +611,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 := multiOperation.Data.txReceivers[i].AccountEPASA.ToString();
+    auxObj.GetAsVariant('account_epasa').Value := TEPasaDecoder.DecodeEPASA(multiOperation.Data.txReceivers[i].Account,multiOperation.Data.txReceivers[i].Payload,ANode,AWalletKeys,APasswords);
     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;
@@ -839,6 +846,7 @@ end;
 
 constructor TRPCServer.Create;
 begin
+  FPayloadPasswords := TList<String>.Create;
   FActive := false;
   FRPCLog := Nil;
   FIniFile := Nil;
@@ -857,6 +865,7 @@ end;
 destructor TRPCServer.Destroy;
 begin
   FreeAndNil(FRPCLog);
+  FreeAndNil(FPayloadPasswords);
   active := false;
   if _RPCServer=Self then _RPCServer:=Nil;
   inherited Destroy;
@@ -1131,7 +1140,9 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
 
   Procedure FillOperationResumeToJSONObject(Const OPR : TOperationResume; jsonObject : TPCJSONObject);
   Begin
-    TPascalCoinJSONComp.FillOperationObject(OPR,FNode.Bank.BlocksCount,jsonObject);
+    TPascalCoinJSONComp.FillOperationObject(OPR,FNode.Bank.BlocksCount,
+      Node,RPCServer.WalletKeys,RPCServer.PayloadPasswords,
+      jsonObject);
   end;
 
   Function GetAccountOperations(accountNumber : Cardinal; jsonArray : TPCJSONArray; maxBlocksDepth, startReg, maxReg: Integer; forceStartBlock : Cardinal) : Boolean;
@@ -2552,7 +2563,6 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
       jsonArr := params.GetAsArray('receivers');
       for i:=0 to jsonArr.Count-1 do begin
         receiver := CT_TMultiOpReceiver_NUL;
-        receiver.AccountEPASA.Clear;
         if NOT TryCaptureEPASA(jsonArr.GetAsObject(i), receiver.Account, ErrorNum, ErrorDesc) then
           Exit;
         receiver.Amount:= ToPascalCoins(jsonArr.GetAsObject(i).AsDouble('amount',0));
@@ -2612,7 +2622,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
         end;
       end;
       // Return multioperation object:
-      TPascalCoinJSONComp.FillMultiOperationObject(FNode.Bank.SafeBox.CurrentProtocol,mop,GetResultObject);
+      TPascalCoinJSONComp.FillMultiOperationObject(FNode.Bank.SafeBox.CurrentProtocol,mop,FNode,FRPCServer.WalletKeys,FRPCServer.PayloadPasswords, GetResultObject);
     finally
       OperationsHashTree.Free;
     end;
@@ -2749,7 +2759,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     Try
       InternalMultiOperationSignCold(mop,protocol,params.GetAsArray('accounts_and_keys'),j);
       // Return multioperation object:
-      TPascalCoinJSONComp.FillMultiOperationObject(protocol,mop,GetResultObject);
+      TPascalCoinJSONComp.FillMultiOperationObject(protocol,mop,FNode,FRPCServer.WalletKeys,FRPCServer.PayloadPasswords,GetResultObject);
       Result := True;
     finally
       senderOperationsHashTree.Free;
@@ -2800,7 +2810,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
         lSigners.Free;
       end;
       // Return multioperation object:
-      TPascalCoinJSONComp.FillMultiOperationObject(FNode.Bank.SafeBox.CurrentProtocol,mop,GetResultObject);
+      TPascalCoinJSONComp.FillMultiOperationObject(FNode.Bank.SafeBox.CurrentProtocol,mop,FNode,FRPCServer.WalletKeys,FRPCServer.PayloadPasswords,GetResultObject);
       Result := True;
     finally
       senderOperationsHashTree.Free;

+ 0 - 3
src/core/UTxMultiOperation.pas

@@ -427,13 +427,10 @@ begin
     If (w>0) then begin
       for i:=0 to w-1 do begin
         txr := CT_TMultiOpReceiver_NUL;
-        txr.AccountEPASA.Clear;
         stream.Read(txr.Account,SizeOf(txr.Account));
         stream.Read(txr.Amount,SizeOf(txr.Amount));
         LoadOperationPayloadFromStream(stream,txr.Payload);
         //
-        txr.AccountEPASA:=TAccountComp.DecodeEPASAPartial(txr.Account,txr.Payload.payload_raw,txr.Payload.payload_type,TEPasa.Empty);
-        //
         txreceivers[i] := txr;
       end;
     end;

+ 3 - 1
src/gui-classic/UFRMOperationsExplorer.pas

@@ -715,7 +715,9 @@ begin
     If op.OperationToOperationResume(FSourceNode.Bank.BlocksCount,op,True,op.SignerAccount,opr) then begin
       jsonObj := TPCJSONObject.Create;
       Try
-        TPascalCoinJSONComp.FillOperationObject(opr,FSourceNode.Bank.BlocksCount,jsonObj);
+        TPascalCoinJSONComp.FillOperationObject(opr,FSourceNode.Bank.BlocksCount,
+          SourceNode,SourceWalletKeys,Nil,
+          jsonObj);
         mOperationInfo.Lines.Add('JSON:');
         mOperationInfo.Lines.Add(jsonObj.ToJSON(False));
       Finally

+ 20 - 19
src/gui-classic/UFRMWallet.lfm

@@ -4,7 +4,7 @@ object FRMWallet: TFRMWallet
   Top = 201
   Width = 865
   Caption = 'Pascal full node Wallet (Classic GUI)'
-  ClientHeight = 600
+  ClientHeight = 580
   ClientWidth = 865
   Color = clBtnFace
   Constraints.MinHeight = 600
@@ -16,6 +16,7 @@ object FRMWallet: TFRMWallet
   OnCreate = FormCreate
   OnDestroy = FormDestroy
   Position = poScreenCenter
+  LCLVersion = '2.0.10.0'
   object pnlTop: TPanel
     Left = 0
     Height = 91
@@ -311,7 +312,7 @@ object FRMWallet: TFRMWallet
   object StatusBar: TStatusBar
     Left = 0
     Height = 23
-    Top = 577
+    Top = 557
     Width = 865
     Panels = <    
       item
@@ -331,7 +332,7 @@ object FRMWallet: TFRMWallet
   end
   object PageControl: TPageControl
     Left = 0
-    Height = 486
+    Height = 466
     Top = 91
     Width = 865
     ActivePage = tsMyAccounts
@@ -341,11 +342,11 @@ object FRMWallet: TFRMWallet
     OnChange = PageControlChange
     object tsMyAccounts: TTabSheet
       Caption = 'Account Explorer'
-      ClientHeight = 460
+      ClientHeight = 440
       ClientWidth = 857
       object Splitter1: TSplitter
         Left = 400
-        Height = 394
+        Height = 374
         Top = 66
         Width = 5
       end
@@ -471,17 +472,17 @@ object FRMWallet: TFRMWallet
       end
       object pnlAccounts: TPanel
         Left = 0
-        Height = 394
+        Height = 374
         Top = 66
         Width = 400
         Align = alLeft
         BevelOuter = bvNone
-        ClientHeight = 394
+        ClientHeight = 374
         ClientWidth = 400
         TabOrder = 1
         object dgAccounts: TDrawGrid
           Left = 0
-          Height = 360
+          Height = 340
           Top = 0
           Width = 400
           Align = alClient
@@ -495,7 +496,7 @@ object FRMWallet: TFRMWallet
         object pnlAccountsInfo: TPanel
           Left = 0
           Height = 34
-          Top = 360
+          Top = 340
           Width = 400
           Align = alBottom
           BevelOuter = bvNone
@@ -576,7 +577,7 @@ object FRMWallet: TFRMWallet
       end
       object pcAccountsOptions: TPageControl
         Left = 405
-        Height = 394
+        Height = 374
         Top = 66
         Width = 452
         ActivePage = tsMultiSelectAccounts
@@ -603,12 +604,12 @@ object FRMWallet: TFRMWallet
         end
         object tsMultiSelectAccounts: TTabSheet
           Caption = 'Selected Accounts For Batch Operation'
-          ClientHeight = 368
+          ClientHeight = 348
           ClientWidth = 444
           ImageIndex = 1
           object dgSelectedAccounts: TDrawGrid
             Left = 41
-            Height = 311
+            Height = 291
             Top = 31
             Width = 320
             Align = alLeft
@@ -645,7 +646,7 @@ object FRMWallet: TFRMWallet
           object pnlSelectedAccountsBottom: TPanel
             Left = 0
             Height = 26
-            Top = 342
+            Top = 322
             Width = 444
             Align = alBottom
             BevelOuter = bvNone
@@ -687,12 +688,12 @@ object FRMWallet: TFRMWallet
           end
           object pnlSelectedAccountsLeft: TPanel
             Left = 0
-            Height = 311
+            Height = 291
             Top = 31
             Width = 41
             Align = alLeft
             BevelOuter = bvNone
-            ClientHeight = 311
+            ClientHeight = 291
             ClientWidth = 41
             TabOrder = 3
             object sbSelectedAccountsAdd: TSpeedButton
@@ -1191,12 +1192,12 @@ object FRMWallet: TFRMWallet
   end
   object TimerUpdateStatus: TTimer
     OnTimer = TimerUpdateStatusTimer
-    left = 32
-    top = 56
+    Left = 32
+    Top = 56
   end
   object MainMenu: TMainMenu
-    left = 165
-    top = 160
+    Left = 165
+    Top = 160
     object miProject: TMenuItem
       Caption = 'Project'
       object miPrivatekeys: TMenuItem

+ 4 - 2
src/gui-classic/UFRMWallet.pas

@@ -1013,7 +1013,7 @@ begin
   if TEPasaDecoder.TryDecodeEPASA(OperationResume.DestAccount,OperationResume.OriginalPayload,FNode,FWalletKeys,Nil,LEPASA) then begin
     Strings.Add('EPASA: '+LEPASA.ToString);
   end else Strings.Add('No EPASA format');
-  Strings.Add(Format('Payload type:%s length:%d',['0x'+IntToHex(OperationResume.OriginalPayload.payload_type), length(OperationResume.OriginalPayload.payload_raw)]));
+  Strings.Add(Format('Payload type:%s length:%d',['0x'+IntToHex(OperationResume.OriginalPayload.payload_type,2), length(OperationResume.OriginalPayload.payload_raw)]));
   if (Length(OperationResume.OriginalPayload.payload_raw)>0) then begin
     If OperationResume.PrintablePayload<>'' then begin
       Strings.Add(Format('Payload (human): %s',[OperationResume.PrintablePayload]));
@@ -1025,7 +1025,9 @@ begin
   end;
   jsonObj := TPCJSONObject.Create;
   Try
-    TPascalCoinJSONComp.FillOperationObject(OperationResume,FNode.Bank.BlocksCount,jsonObj);
+    TPascalCoinJSONComp.FillOperationObject(OperationResume,FNode.Bank.BlocksCount,
+      FNode,FWalletKeys,Nil,
+      jsonObj);
     Strings.Add('OPERATION JSON:');
     Strings.Add(jsonObj.ToJSON(False));
   Finally

+ 11 - 1
src/gui-classic/UGridUtils.pas

@@ -1152,8 +1152,9 @@ begin
 end;
 
 procedure TOperationsGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
-Var s : String;
+Var s, saux : String;
   opr : TOperationResume;
+  LRectLeft, LRectRight : TRect;
 begin
   DrawGrid.Canvas.Font.Color:=clWindowText;
   opr := CT_TOperationResume_NUL;
@@ -1226,9 +1227,18 @@ begin
         Canvas_TextRect(DrawGrid.Canvas,Rect,s,State,[tfRight,tfVerticalCenter,tfSingleLine]);
       end else if ACol=7 then begin
         s := opr.PrintablePayload;
+        LRectRight := Rect;
         if opr.OriginalPayload.payload_type>0 then begin
+          saux := '0x'+IntToHex(opr.OriginalPayload.payload_type,2);
+          LRectLeft := Rect;
+          LRectLeft.Width := 30;
+          Rect.Inflate(-32,0,0,0);
           DrawGrid.Canvas.Font.Color := clBlue;
+          DrawGrid.Canvas.Font.Style := [fsBold];
+          Canvas_TextRect(DrawGrid.Canvas,LRectLeft,saux,State,[tfLeft,tfVerticalCenter,tfSingleLine]);
+          DrawGrid.Canvas.Font.Style := [];
         end;
+        DrawGrid.Canvas.Font.Color := clBlack;
         if opr.OriginalPayload.payload_raw.ToString=s then begin
           DrawGrid.Canvas.Font.Style := [fsBold];
         end;