Browse Source

Merge pull request #212 from PascalCoin/master

Dev. update
Pascal Coin 4 years ago
parent
commit
da9409a07f
6 changed files with 306 additions and 122 deletions
  1. 70 2
      src/core/UAccounts.pas
  2. 4 0
      src/core/UConst.pas
  3. 181 100
      src/core/UEPasa.pas
  4. 1 1
      src/core/UPCRPCSend.pas
  5. 41 19
      src/core/URPC.pas
  6. 9 0
      src/libraries/sphere10/UCommon.pas

+ 70 - 2
src/core/UAccounts.pas

@@ -26,7 +26,7 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, UConst, UCrypto, SyncObjs, UThread, UBaseTypes,
   Classes, SysUtils, UConst, UCrypto, SyncObjs, UThread, UBaseTypes,
-  UPCOrderedLists, UPCDataTypes, UPCSafeBoxRootHash,
+  UPCOrderedLists, UPCDataTypes, UPCSafeBoxRootHash, UEPasa,
   UPCHardcodedRandomHashTable, UJSONFunctions,
   UPCHardcodedRandomHashTable, UJSONFunctions,
   {$IFDEF USE_ABSTRACTMEM}
   {$IFDEF USE_ABSTRACTMEM}
   UPCAbstractMem, UPCAbstractMemAccountKeys,
   UPCAbstractMem, UPCAbstractMemAccountKeys,
@@ -295,7 +295,9 @@ Type
     Function FindAccountByName(const aName : String) : Integer; overload;
     Function FindAccountByName(const aName : String) : Integer; overload;
     Function FindAccountByName(const aName : TRawBytes) : Integer; overload;
     Function FindAccountByName(const aName : TRawBytes) : Integer; overload;
     Function FindAccountsStartingByName(const AStartName : TRawBytes; const ARawList : TOrderedRawList; const AMax : Integer = 0) : Integer;
     Function FindAccountsStartingByName(const AStartName : TRawBytes; const ARawList : TOrderedRawList; const AMax : Integer = 0) : Integer;
-
+    Function TryResolveAccountByEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : boolean): Boolean; overload;
+    Function TryResolveAccountByEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : boolean; out AErrorMessage: String): Boolean; overload;
+    
     Procedure Clear;
     Procedure Clear;
     Function Account(account_number : Cardinal) : TAccount;
     Function Account(account_number : Cardinal) : TAccount;
     Function GetBlock(block_number : Cardinal) : TBlockAccount;
     Function GetBlock(block_number : Cardinal) : TBlockAccount;
@@ -4700,6 +4702,72 @@ begin
   end;
   end;
 end;
 end;
 
 
+Function TPCSafeBox.TryResolveAccountByEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : boolean): Boolean;
+var LErrMsg : String;
+begin
+  Result := TryResolveAccountByEPASA(AEPasa, AResolvedAccount, AResolvedKey, ARequiresPurchase, LErrMsg);
+end;
+
+Function TPCSafeBox.TryResolveAccountByEPASA(const AEPasa : TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : boolean; out AErrorMessage: String): Boolean;
+var
+  LKey : TAccountKey;
+  LErrMsg : String;
+begin
+  if (AEPasa.IsPayToKey) then begin
+    // Parse account key in EPASA
+    if NOT TAccountComp.AccountPublicKeyImport(AEPasa.Payload, LKey, LErrMsg) then begin
+      AResolvedAccount := CT_AccountNo_NUL;
+      AResolvedKey := CT_Account_NUL.accountInfo.accountKey;
+      ARequiresPurchase := False;
+      AErrorMessage := Format('Invalid key specified in PayToKey EPASA "%s". %s',[AEPasa.ToString(), LErrMsg]);
+      Exit(False);
+    end;
+    
+    // Try to find key in safebox 
+
+    // If key is found, then do not purchase new account and send to first account with key
+
+    // If no key found, find optimal public purchase account
+
+    // WIP (not implemented)
+    AResolvedAccount := CT_AccountNo_NUL;    
+    AResolvedKey := CT_Account_NUL.accountInfo.accountKey;
+    ARequiresPurchase := False;
+    AErrorMessage := 'Not implemented';
+    Result := False;     
+  end else if (AEPasa.IsAddressedByName) then begin
+    // Find account by name
+
+    // WIP (not implemented)
+    AResolvedAccount := CT_AccountNo_NUL;    
+    AResolvedKey := CT_Account_NUL.accountInfo.accountKey;
+    ARequiresPurchase := False;
+    AErrorMessage := 'Not implemented';
+    Result := False; 
+    
+  end else begin
+    // addressed by number
+    if NOT AEPasa.IsAddressedByNumber then
+      raise Exception.Create('Internal Error c8ecd69d-3621-4f5e-b4f1-9926ab2f5013');
+    if NOT AEPasa.Account.HasValue then raise Exception.Create('Internal Error 544c8cb9-b700-4b5f-93ca-4d045d0a06ae');
+
+    if (AEPasa.Account.Value < 0) or (AEPasa.Account.Value >= Self.AccountsCount) then begin
+      AResolvedAccount := CT_AccountNo_NUL;
+      AResolvedKey := CT_Account_NUL.accountInfo.accountKey;
+      ARequiresPurchase := False;
+      AErrorMessage := Format('Account number %d does not exist in safebox',[AEPasa.Account.Value]);
+      Exit(False);
+    end;
+    
+    AResolvedAccount := AEPasa.Account.Value;
+    AResolvedKey := CT_Account_NUL.accountInfo.accountKey;      
+    ARequiresPurchase := False;    
+    Result := true;
+  end;
+
+
+end;
+
 procedure TPCSafeBox.SearchBlockWhenOnSeparatedChain(blockNumber: Cardinal; out blockAccount: TBlockAccount);
 procedure TPCSafeBox.SearchBlockWhenOnSeparatedChain(blockNumber: Cardinal; out blockAccount: TBlockAccount);
   Function WasUpdatedBeforeOrigin : Boolean;
   Function WasUpdatedBeforeOrigin : Boolean;
   var j, maxUB : Integer;
   var j, maxUB : Integer;

+ 4 - 0
src/core/UConst.pas

@@ -219,6 +219,10 @@ Const
 
 
   CT_ACTIVATE_RANDOMHASH_V4 = {$IFDEF ACTIVATE_RANDOMHASH_V4}True{$ELSE}False{$ENDIF};
   CT_ACTIVATE_RANDOMHASH_V4 = {$IFDEF ACTIVATE_RANDOMHASH_V4}True{$ELSE}False{$ENDIF};
 
 
+  // Represents a non-existent account number
+  // (chosen as the last account in safebox, generated in year 6101)
+  CT_AccountNo_NUL = High(Cardinal);
+
   // App Params
   // App Params
   CT_PARAM_GridAccountsStream = 'GridAccountsStreamV2';
   CT_PARAM_GridAccountsStream = 'GridAccountsStreamV2';
   CT_PARAM_GridAccountsPos = 'GridAccountsPos';
   CT_PARAM_GridAccountsPos = 'GridAccountsPos';

+ 181 - 100
src/core/UEPasa.pas

@@ -27,7 +27,6 @@ uses
   SysUtils,
   SysUtils,
   TypInfo,
   TypInfo,
   uregexpr,
   uregexpr,
-  UAccounts,
   UCommon,
   UCommon,
   UCrypto,
   UCrypto,
   UEncoding;
   UEncoding;
@@ -43,76 +42,87 @@ type
     BadExtendedChecksum
     BadExtendedChecksum
   );
   );
 
 
-  { PayloadType}
-
-  PayloadType = (
-    NonDeterministic = 0,      // Payload encryption and encoding method not specified.
-    &Public = 1,               // Unencrypted, public payload.
-    RecipientKeyEncrypted = 2, // ECIES encrypted using recipient accounts public key.
-    SenderKeyEncrypted = 3,    // ECIES encrypted using sender accounts public key.
-    PasswordEncrypted = 4,     // AES encrypted using pwd param
-    AsciiFormatted = 5,        // Payload data encoded in ASCII
-    HexFormatted = 6,          // Payload data encoded in HEX
-    Base58Formatted = 7,       // Payload data encoded in Base58
-    AddressedByName = 8        // E-PASA addressed by account name (not number).
+  { TPayloadTrait }
+
+  TPayloadTrait = (
+    ptNonDeterministic = 0,      // Payload encryption and encoding method not specified.
+    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
+    ptAsciiFormatted = 5,        // Payload data encoded in ASCII
+    ptHexFormatted = 6,          // Payload data encoded in HEX
+    ptBase58Formatted = 7,       // Payload data encoded in Base58
+    ptAddressedByName = 8        // E-PASA addressed by account name (not number).
   );
   );
 
 
-  { PayloadTypeHelper }
+  { TPayloadTraitHelper }
 
 
-  PayloadTypeHelper = record helper for PayloadType
+  TPayloadTraitHelper = record helper for TPayloadTrait
   public
   public
-    function Value: Int32;
+    function ProtocolValue: byte;
   end;
   end;
 
 
-  { PayloadTypes }
+  { TPayloadType }
 
 
-  PayloadTypes = set of PayloadType;
+  TPayloadType = set of TPayloadTrait;
 
 
-  { PayloadTypesHelper }
+  { TPayloadTypesHelper }
 
 
-  PayloadTypesHelper = record helper for PayloadTypes
+  TPayloadTypeHelper = record helper for TPayloadType
   public
   public
-    function IsPayloadTypeInSet(APayloadType: PayloadType): Boolean; inline;
+    function HasTrait(APayloadTrait: TPayloadTrait): Boolean; inline;
+    function ProtocolValue : byte;
   end;
   end;
 
 
-
   { TEPasa }
   { TEPasa }
 
 
+
   TEPasa = record
   TEPasa = record
     strict private
     strict private
       var
       var
         FAccount, FAccountChecksum: TNullable<UInt32>;
         FAccount, FAccountChecksum: TNullable<UInt32>;
         FAccountName, FPayload, FPassword, FExtendedChecksum: String;
         FAccountName, FPayload, FPassword, FExtendedChecksum: String;
-        FPayloadTypes: PayloadTypes;
+        FPayloadType: TPayloadType;
 
 
       function GetAccount: TNullable<UInt32>; inline;
       function GetAccount: TNullable<UInt32>; inline;
       procedure SetAccount(const AValue: TNullable<UInt32>); inline;
       procedure SetAccount(const AValue: TNullable<UInt32>); inline;
       function GetAccountChecksum: TNullable<UInt32>; inline;
       function GetAccountChecksum: TNullable<UInt32>; inline;
       procedure SetAccountChecksum(const AValue: TNullable<UInt32>); inline;
       procedure SetAccountChecksum(const AValue: TNullable<UInt32>); inline;
-      function GetPayloadTypes: PayloadTypes; inline;
+      function GetPayloadType: TPayloadType; inline;
       function GetAccountName: String; inline;
       function GetAccountName: String; inline;
       procedure SetAccountName(const AValue: String); inline;
       procedure SetAccountName(const AValue: String); inline;
-      procedure SetPayloadTypes(const AValue: PayloadTypes); inline;
+      procedure SetPayloadType(const AValue: TPayloadType); inline;
       function GetExtendedChecksum: String; inline;
       function GetExtendedChecksum: String; inline;
       procedure SetExtendedChecksum(const AValue: String); inline;
       procedure SetExtendedChecksum(const AValue: String); inline;
       function GetPassword: String; inline;
       function GetPassword: String; inline;
       procedure SetPassword(const AValue: String); inline;
       procedure SetPassword(const AValue: String); inline;
       function GetPayload: String; inline;
       function GetPayload: String; inline;
       procedure SetPayload(const AValue: String); inline;
       procedure SetPayload(const AValue: String); inline;
-
+      function GetHasPayload: Boolean; inline;
+      function GetIsStandard: Boolean; inline;
+      function GetIsPayToKey: Boolean; inline;
+      function GetIsAddressedByName : Boolean; inline;
+      function GetIsAddressedByNumber : Boolean; inline;
+      class function GetEmptyValue : TEPasa; static;
     public
     public
-      function IsPayToKey: Boolean; inline;
-      function GetRawPayloadBytes(): TArray<Byte>; inline;
-      function ToString(): String; overload;
-      function ToString(AOmitExtendedChecksum: Boolean): String; overload;
-
       property Account: TNullable<UInt32> read GetAccount write SetAccount;
       property Account: TNullable<UInt32> read GetAccount write SetAccount;
       property AccountChecksum: TNullable<UInt32> read GetAccountChecksum write SetAccountChecksum;
       property AccountChecksum: TNullable<UInt32> read GetAccountChecksum write SetAccountChecksum;
       property AccountName: String read GetAccountName write SetAccountName;
       property AccountName: String read GetAccountName write SetAccountName;
-      property PayloadTypes: PayloadTypes read GetPayloadTypes write SetPayloadTypes;
+      property PayloadType: TPayloadType read GetPayloadType write SetPayloadType;
       property Payload: String read GetPayload write SetPayload;
       property Payload: String read GetPayload write SetPayload;
       property Password: String read GetPassword write SetPassword;
       property Password: String read GetPassword write SetPassword;
       property ExtendedChecksum: String read GetExtendedChecksum write SetExtendedChecksum;
       property ExtendedChecksum: String read GetExtendedChecksum write SetExtendedChecksum;
+      property IsAddressedByNumber: boolean read GetIsAddressedByNumber;
+      property IsAddressedByName: boolean read GetIsAddressedByName;
+      property IsPayToKey: boolean read GetIsPayToKey;
+      property IsStandard: boolean read GetIsStandard;
+      property HasPayload: boolean read GetHasPayload;
+      class property Empty : TEPasa read GetEmptyValue;
+
+      function GetRawPayloadBytes(): TArray<Byte>; inline;
+      function ToString(): String; overload;
+      function ToString(AOmitExtendedChecksum: Boolean): String; overload;
 
 
       class function TryParse(const AEPasaText: String; out AEPasa: TEPasa) : Boolean; static;
       class function TryParse(const AEPasaText: String; out AEPasa: TEPasa) : Boolean; static;
       class function Parse(const AEPasaText: String): TEPasa; static;
       class function Parse(const AEPasaText: String): TEPasa; static;
@@ -121,6 +131,8 @@ type
 
 
   end;
   end;
 
 
+
+
   { TEPasaParser }
   { TEPasaParser }
 
 
   TEPasaParser = class
   TEPasaParser = class
@@ -155,9 +167,9 @@ type
       function TryParse(const AEPasaText: String; out AEPasa: TEPasa; out AErrorCode: EPasaErrorCode): Boolean; overload;
       function TryParse(const AEPasaText: String; out AEPasa: TEPasa; out AErrorCode: EPasaErrorCode): Boolean; overload;
   end;
   end;
 
 
-  { TEPasaHelper }
+  { TEPasaComp }
 
 
-  TEPasaHelper = class sealed(TObject)
+  TEPasaComp = class sealed(TObject)
 
 
     strict private
     strict private
       class function ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>; static;
       class function ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>; static;
@@ -177,9 +189,11 @@ type
 
 
       class function ComputeExtendedChecksum(const AText: String): String; static;
       class function ComputeExtendedChecksum(const AText: String): String; static;
       class function IsValidExtendedChecksum(const AText: String; const AChecksum: String): Boolean; static;
       class function IsValidExtendedChecksum(const AText: String; const AChecksum: String): Boolean; static;
-      class function IsValidPayloadLength(APayloadType: PayloadTypes; const APayloadContent: String): Boolean; static;
+      class function IsValidPayloadLength(APayloadType: TPayloadType; const APayloadContent: String): Boolean; static;
       class function IsValidPasswordLength(const APasswordValue: String) : Boolean; static;
       class function IsValidPasswordLength(const APasswordValue: String) : Boolean; static;
 
 
+      class function GetPayloadTypeProtocolByte(const APayloadType : TPayloadType) : Byte;
+      class function GetPayloadTypeFromProtocolByte(AByte : Byte) : TPayloadType;
   end;
   end;
 
 
 resourcestring
 resourcestring
@@ -200,30 +214,40 @@ uses
   HlpConverters,
   HlpConverters,
   UMemory;
   UMemory;
 
 
-{ PayloadTypeHelper }
+var
+  EmptyEPasa : TEPasa;
+
+{ TPayloadTraitHelper }
 
 
-function PayloadTypeHelper.Value: Int32;
+function TPayloadTraitHelper.ProtocolValue: Byte;
 begin
 begin
   case Self of
   case Self of
-    NonDeterministic: Result := $00000000;
-    &Public: Result := $00000001;
-    RecipientKeyEncrypted: Result := $00000010;
-    SenderKeyEncrypted: Result := $00000100;
-    PasswordEncrypted: Result := $00001000;
-    AsciiFormatted: Result := $00010000;
-    HexFormatted: Result := $00100000;
-    Base58Formatted: Result := $01000000;
-    AddressedByName: Result := $10000000;
+    ptNonDeterministic: Result := 0;
+    ptPublic: Result := BYTE_BIT_0;
+    ptRecipientKeyEncrypted: Result := BYTE_BIT_1;
+    ptSenderKeyEncrypted: Result := BYTE_BIT_2;
+    ptPasswordEncrypted: Result := BYTE_BIT_3;
+    ptAsciiFormatted: Result := BYTE_BIT_4;
+    ptHexFormatted: Result := BYTE_BIT_5;
+    ptBase58Formatted: Result := BYTE_BIT_6;
+    ptAddressedByName: Result := BYTE_BIT_7;
   end;
   end;
+  raise Exception.Create('Internal Error 2faed11a-1b0f-447a-87d1-2e1735ac4ca2');
 end;
 end;
 
 
-{ PayloadTypesHelper }
+{ TPayloadTypeHelper }
+
+function TPayloadTypeHelper.HasTrait(APayloadTrait : TPayloadTrait) : Boolean;
+begin
+  Result := APayloadTrait in Self;
+end;
 
 
-function PayloadTypesHelper.IsPayloadTypeInSet(APayloadType : PayloadType) : Boolean;
+function TPayloadTypeHelper.ProtocolValue : Byte;
 begin
 begin
-  Result := APayloadType in Self;
+  Result := TEPasaComp.GetPayloadTypeProtocolByte(Self);
 end;
 end;
 
 
+
 { TEPasa }
 { TEPasa }
 
 
 function TEPasa.GetAccount: TNullable<UInt32>;
 function TEPasa.GetAccount: TNullable<UInt32>;
@@ -256,9 +280,9 @@ begin
   Result := FPayload;
   Result := FPayload;
 end;
 end;
 
 
-function TEPasa.GetPayloadTypes: PayloadTypes;
+function TEPasa.GetPayloadType: TPayloadType;
 begin
 begin
-  Result := FPayloadTypes;
+  Result := FPayloadType;
 end;
 end;
 
 
 procedure TEPasa.SetAccount(const AValue: TNullable<UInt32>);
 procedure TEPasa.SetAccount(const AValue: TNullable<UInt32>);
@@ -291,29 +315,50 @@ begin
   FPayload := AValue;
   FPayload := AValue;
 end;
 end;
 
 
-procedure TEPasa.SetPayloadTypes(const AValue: PayloadTypes);
+procedure TEPasa.SetPayloadType(const AValue: TPayloadType);
+begin
+  FPayloadType := AValue;
+end;
+
+function TEPasa.GetIsAddressedByNumber : Boolean;
+begin
+  Result := NOT PayloadType.HasTrait(ptAddressedByName);
+end;
+
+function TEPasa.GetIsAddressedByName : Boolean;
 begin
 begin
-  FPayloadTypes := AValue;
+  Result := (NOT IsPayToKey) AND PayloadType.HasTrait(ptAddressedByName);
 end;
 end;
 
 
-function TEPasa.IsPayToKey: Boolean;
+function TEPasa.GetIsPayToKey: Boolean;
 begin
 begin
   Result :=
   Result :=
     (AccountName = '@') and
     (AccountName = '@') and
-    (PayloadTypes.IsPayloadTypeInSet(PayloadType.AddressedByName) and
-    PayloadTypes.IsPayloadTypeInSet(PayloadType.Public) and
-    PayloadTypes.IsPayloadTypeInSet(PayloadType.Base58Formatted));
+    (PayloadType.HasTrait(ptAddressedByName) and
+    PayloadType.HasTrait(ptPublic) and
+    PayloadType.HasTrait(ptBase58Formatted));
+end;
+
+function TEPasa.GetIsStandard: Boolean;
+begin
+  Result := (NOT PayloadType.HasTrait(ptAddressedByName)) AND (NOT HasPayload);
+end;
+
+function TEPasa.GetHasPayload: Boolean;
+begin
+  Result := PayloadType.HasTrait(ptPublic) OR PayloadType.HasTrait(ptRecipientKeyEncrypted) OR PayloadType.HasTrait(ptSenderKeyEncrypted);
 end;
 end;
 
 
+
 function TEPasa.GetRawPayloadBytes: TArray<Byte>;
 function TEPasa.GetRawPayloadBytes: TArray<Byte>;
 begin
 begin
-  if (PayloadTypes.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
+  if (PayloadType.HasTrait(ptAsciiFormatted)) then
     Exit(TEncoding.ASCII.GetBytes(Payload));
     Exit(TEncoding.ASCII.GetBytes(Payload));
 
 
-  if (PayloadTypes.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
+  if (PayloadType.HasTrait(ptBase58Formatted)) then
     Exit(TPascalBase58Encoding.Decode(Payload));
     Exit(TPascalBase58Encoding.Decode(Payload));
 
 
-  if (PayloadTypes.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
+  if (PayloadType.HasTrait(ptHexFormatted)) then
     Exit(THexEncoding.Decode(Payload));
     Exit(THexEncoding.Decode(Payload));
 
 
   raise EPascalCoinException.CreateRes(@SUnknownPayloadEncoding);
   raise EPascalCoinException.CreateRes(@SUnknownPayloadEncoding);
@@ -324,7 +369,7 @@ var
   LPayloadContent: String;
   LPayloadContent: String;
 begin
 begin
   Result := string.Empty;
   Result := string.Empty;
-  if (PayloadTypes.IsPayloadTypeInSet(PayloadType.AddressedByName)) then begin
+  if (PayloadType.HasTrait(ptAddressedByName)) then begin
     Result := Result + TPascal64Encoding.Escape(AccountName);
     Result := Result + TPascal64Encoding.Escape(AccountName);
   end else begin
   end else begin
     Result := Result + Account.Value.ToString();
     Result := Result + Account.Value.ToString();
@@ -333,24 +378,24 @@ begin
     end;
     end;
   end;
   end;
 
 
-  if (PayloadTypes.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then begin
+  if (PayloadType.HasTrait(ptAsciiFormatted)) then begin
     LPayloadContent := String.Format('"%s"', [TPascalAsciiEncoding.Escape(Payload)]);
     LPayloadContent := String.Format('"%s"', [TPascalAsciiEncoding.Escape(Payload)]);
-  end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.HexFormatted)) then begin
+  end else if (PayloadType.HasTrait(ptHexFormatted)) then begin
     LPayloadContent := string.Format('0x%s', [Payload]);
     LPayloadContent := string.Format('0x%s', [Payload]);
-  end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then begin
+  end else if (PayloadType.HasTrait(ptBase58Formatted)) then begin
     LPayloadContent := string.Format('%s', [Payload]);
     LPayloadContent := string.Format('%s', [Payload]);
   end else begin
   end else begin
     // it is non-deterministic, so payload content is ignored
     // it is non-deterministic, so payload content is ignored
     LPayloadContent := string.Empty;
     LPayloadContent := string.Empty;
   end;
   end;
 
 
-  if (PayloadTypes.IsPayloadTypeInSet(PayloadType.Public)) then begin
+  if (PayloadType.HasTrait(ptPublic)) then begin
     Result := Result + string.Format('[%s]', [LPayloadContent]);
     Result := Result + string.Format('[%s]', [LPayloadContent]);
-  end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.RecipientKeyEncrypted)) then begin
+  end else if (PayloadType.HasTrait(ptRecipientKeyEncrypted)) then begin
     Result := Result + string.Format('(%s)', [LPayloadContent]);
     Result := Result + string.Format('(%s)', [LPayloadContent]);
-  end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.SenderKeyEncrypted)) then begin
+  end else if (PayloadType.HasTrait(ptSenderKeyEncrypted)) then begin
     Result := Result + string.Format('<%s>', [LPayloadContent]);
     Result := Result + string.Format('<%s>', [LPayloadContent]);
-  end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.PasswordEncrypted)) then begin
+  end else if (PayloadType.HasTrait(ptPasswordEncrypted)) then begin
     Result := Result + string.Format('{%s:%s}', [LPayloadContent, TPascalAsciiEncoding.Escape(Password)]);
     Result := Result + string.Format('{%s:%s}', [LPayloadContent, TPascalAsciiEncoding.Escape(Password)]);
   end else begin
   end else begin
     // it is non-deterministic, so payload omitted entirely
     // it is non-deterministic, so payload omitted entirely
@@ -389,6 +434,11 @@ begin
 end;
 end;
 
 
 
 
+class function TEPasa.GetEmptyValue : TEPasa;
+begin
+  Result := EmptyEPasa;
+end;
+
 { TEPasaParser }
 { TEPasaParser }
 
 
 class constructor TEPasaParser.CreateRegexEPasaParser;
 class constructor TEPasaParser.CreateRegexEPasaParser;
@@ -465,8 +515,8 @@ begin
     // when multiple enums are OR'ed in C#, they are combined and
     // when multiple enums are OR'ed in C#, they are combined and
     // if any of the enums numeric value is zero, it is excluded.
     // if any of the enums numeric value is zero, it is excluded.
     // in our case,"PayloadType.NonDeterministic" is always zero so we exclude it from our set.
     // in our case,"PayloadType.NonDeterministic" is always zero so we exclude it from our set.
-    AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.AddressedByName] -
-      [PayloadType.NonDeterministic];
+    AEPasa.PayloadType := AEPasa.PayloadType + [ptAddressedByName] -
+      [ptNonDeterministic];
     AEPasa.AccountName := TPascal64Encoding.Unescape(LAccountName);
     AEPasa.AccountName := TPascal64Encoding.Unescape(LAccountName);
     AEPasa.Account := Nil;
     AEPasa.Account := Nil;
     AEPasa.AccountChecksum := Nil;
     AEPasa.AccountChecksum := Nil;
@@ -504,23 +554,23 @@ begin
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           Exit(False);
           Exit(False);
         end;
         end;
-        AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.Public] -
-          [PayloadType.NonDeterministic];
+        AEPasa.PayloadType := AEPasa.PayloadType + [ptPublic] -
+          [ptNonDeterministic];
       end;
       end;
      '(': begin
      '(': begin
         if (LPayloadEndChar <> ')') then begin
         if (LPayloadEndChar <> ')') then begin
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           Exit(False);
           Exit(False);
         end;
         end;
-        AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.RecipientKeyEncrypted] - [PayloadType.NonDeterministic];
+        AEPasa.PayloadType := AEPasa.PayloadType + [ptRecipientKeyEncrypted] - [ptNonDeterministic];
       end;
       end;
     '<': begin
     '<': begin
         if (LPayloadEndChar <> '>') then begin
         if (LPayloadEndChar <> '>') then begin
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           Exit(False);
           Exit(False);
         end;
         end;
-        AEPasa.PayloadTypes := AEPasa.PayloadTypes +
-          [PayloadType.SenderKeyEncrypted] - [PayloadType.NonDeterministic];
+        AEPasa.PayloadType := AEPasa.PayloadType +
+          [ptSenderKeyEncrypted] - [ptNonDeterministic];
       end;
       end;
 
 
     '{': begin
     '{': begin
@@ -528,13 +578,13 @@ begin
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
           Exit(False);
           Exit(False);
         end;
         end;
-        AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.PasswordEncrypted] - [PayloadType.NonDeterministic];
+        AEPasa.PayloadType := AEPasa.PayloadType + [ptPasswordEncrypted] - [ptNonDeterministic];
       end
       end
       else raise ENotSupportedException.CreateResFmt(@SUnRecognizedStartCharacter, [LPayloadStartChar]);
       else raise ENotSupportedException.CreateResFmt(@SUnRecognizedStartCharacter, [LPayloadStartChar]);
   end;
   end;
 
 
   // Password
   // Password
-  if (AEPasa.PayloadTypes.IsPayloadTypeInSet(PayloadType.PasswordEncrypted)) then begin
+  if (AEPasa.PayloadType.HasTrait(ptPasswordEncrypted)) then begin
     if (LPayloadPasswordDelim = #0) then begin
     if (LPayloadPasswordDelim = #0) then begin
       AErrorCode := EPasaErrorCode.MissingPassword;
       AErrorCode := EPasaErrorCode.MissingPassword;
       Exit(False);
       Exit(False);
@@ -551,25 +601,25 @@ begin
     if (LPayloadContent = #0) then begin
     if (LPayloadContent = #0) then begin
       AEPasa.Payload := string.Empty;
       AEPasa.Payload := string.Empty;
     end else if (LPayloadContent.StartsWith('"')) then begin
     end else if (LPayloadContent.StartsWith('"')) then begin
-      AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.AsciiFormatted] - [PayloadType.NonDeterministic];
+      AEPasa.PayloadType := AEPasa.PayloadType + [ptAsciiFormatted] - [ptNonDeterministic];
       AEPasa.Payload := TPascalAsciiEncoding.UnEscape(LPayloadContent.Trim(['"']));
       AEPasa.Payload := TPascalAsciiEncoding.UnEscape(LPayloadContent.Trim(['"']));
     end else if (LPayloadContent.StartsWith('0x')) then begin
     end else if (LPayloadContent.StartsWith('0x')) then begin
-      AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.HexFormatted] - [PayloadType.NonDeterministic];
+      AEPasa.PayloadType := AEPasa.PayloadType + [ptHexFormatted] - [ptNonDeterministic];
       AEPasa.Payload := System.Copy(LPayloadContent, 3, LPayloadContent.Length - 2);
       AEPasa.Payload := System.Copy(LPayloadContent, 3, LPayloadContent.Length - 2);
     end else begin
     end else begin
-      AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.Base58Formatted] - [PayloadType.NonDeterministic];
+      AEPasa.PayloadType := AEPasa.PayloadType + [ptBase58Formatted] - [ptNonDeterministic];
       AEPasa.Payload := LPayloadContent;
       AEPasa.Payload := LPayloadContent;
     end;
     end;
   end;
   end;
 
 
   // Payload Lengths
   // Payload Lengths
-  if (not TEPasaHelper.IsValidPayloadLength(AEPasa.PayloadTypes, AEPasa.Payload)) then begin
+  if (not TEPasaComp.IsValidPayloadLength(AEPasa.PayloadType, AEPasa.Payload)) then begin
     AErrorCode := EPasaErrorCode.PayloadTooLarge;
     AErrorCode := EPasaErrorCode.PayloadTooLarge;
     Exit(False);
     Exit(False);
   end;
   end;
 
 
   // Extended Checksum
   // Extended Checksum
-  LActualChecksum := TEPasaHelper.ComputeExtendedChecksum(AEPasa.ToString(True));
+  LActualChecksum := TEPasaComp.ComputeExtendedChecksum(AEPasa.ToString(True));
   if (LExtendedChecksumDelim <> #0) then begin
   if (LExtendedChecksumDelim <> #0) then begin
     if (LExtendedChecksum <> LActualChecksum) then begin
     if (LExtendedChecksum <> LActualChecksum) then begin
       AErrorCode := EPasaErrorCode.BadExtendedChecksum;
       AErrorCode := EPasaErrorCode.BadExtendedChecksum;
@@ -582,16 +632,16 @@ begin
 end;
 end;
 
 
 
 
-{ TEPasaHelper }
+{ TEPasaComp }
 
 
-class function TEPasaHelper.ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>;
+class function TEPasaComp.ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>;
 begin
 begin
   System.SetLength(Result, System.SizeOf(UInt16));
   System.SetLength(Result, System.SizeOf(UInt16));
   Result[0] := Byte(AValue);
   Result[0] := Byte(AValue);
   Result[1] := Byte(AValue shr 8);
   Result[1] := Byte(AValue shr 8);
 end;
 end;
 
 
-class function TEPasaHelper.ComputeExtendedChecksum(const AText: String): String;
+class function TEPasaComp.ComputeExtendedChecksum(const AText: String): String;
 var
 var
   LHashInstance: IHashWithKey;
   LHashInstance: IHashWithKey;
   LChecksum: UInt16;
   LChecksum: UInt16;
@@ -602,53 +652,53 @@ begin
   Result := THexEncoding.Encode(ReadUInt16AsBytesLE(LChecksum), True);
   Result := THexEncoding.Encode(ReadUInt16AsBytesLE(LChecksum), True);
 end;
 end;
 
 
-class function TEPasaHelper.IsValidExtendedChecksum(const AText, AChecksum: String): Boolean;
+class function TEPasaComp.IsValidExtendedChecksum(const AText, AChecksum: String): Boolean;
 begin
 begin
   Result := ComputeExtendedChecksum(AText) = AChecksum;
   Result := ComputeExtendedChecksum(AText) = AChecksum;
 end;
 end;
 
 
-class function TEPasaHelper.IsValidPayloadLength(APayloadType: PayloadTypes; const APayloadContent: String): Boolean;
+class function TEPasaComp.IsValidPayloadLength(APayloadType: TPayloadType; const APayloadContent: String): Boolean;
 begin
 begin
   if (string.IsNullOrEmpty(APayloadContent)) then
   if (string.IsNullOrEmpty(APayloadContent)) then
     Exit(True);
     Exit(True);
 
 
-  if (APayloadType.IsPayloadTypeInSet(PayloadType.Public)) then begin
+  if (APayloadType.HasTrait(ptPublic)) then begin
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
+    if (APayloadType.HasTrait(ptAsciiFormatted)) then
       Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxPublicAsciiContentLength);
       Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxPublicAsciiContentLength);
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
+    if (APayloadType.HasTrait(ptHexFormatted)) then
       Exit(APayloadContent.Length <= MaxPublicHexContentLength);
       Exit(APayloadContent.Length <= MaxPublicHexContentLength);
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
+    if (APayloadType.HasTrait(ptBase58Formatted)) then
       Exit(APayloadContent.Length <= MaxPublicBase58ContentLength);
       Exit(APayloadContent.Length <= MaxPublicBase58ContentLength);
 
 
     // unknown encoding format
     // unknown encoding format
     Result := False;
     Result := False;
   end;
   end;
 
 
-  if (APayloadType.IsPayloadTypeInSet(PayloadType.SenderKeyEncrypted) or APayloadType.IsPayloadTypeInSet(PayloadType.RecipientKeyEncrypted)) then begin
+  if (APayloadType.HasTrait(ptSenderKeyEncrypted) or APayloadType.HasTrait(ptRecipientKeyEncrypted)) then begin
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
+    if (APayloadType.HasTrait(ptAsciiFormatted)) then
       Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxECIESAsciiContentLength);
       Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxECIESAsciiContentLength);
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
+    if (APayloadType.HasTrait(ptHexFormatted)) then
       Exit(APayloadContent.Length <= MaxECIESHexContentLength);
       Exit(APayloadContent.Length <= MaxECIESHexContentLength);
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
+    if (APayloadType.HasTrait(ptBase58Formatted)) then
       Exit(APayloadContent.Length <= MaxECIESBase58ContentLength);
       Exit(APayloadContent.Length <= MaxECIESBase58ContentLength);
     // unknown encoding format
     // unknown encoding format
     Result := False;
     Result := False;
   end;
   end;
 
 
-  if (APayloadType.IsPayloadTypeInSet(PayloadType.PasswordEncrypted)) then begin
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
+  if (APayloadType.HasTrait(ptPasswordEncrypted)) then begin
+    if (APayloadType.HasTrait(ptAsciiFormatted)) then
       Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxAESAsciiContentLength);
       Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxAESAsciiContentLength);
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
+    if (APayloadType.HasTrait(ptHexFormatted)) then
       Exit(APayloadContent.Length <= MaxAESHexContentLength);
       Exit(APayloadContent.Length <= MaxAESHexContentLength);
 
 
-    if (APayloadType.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
+    if (APayloadType.HasTrait(ptBase58Formatted)) then
       Exit(APayloadContent.Length <= MaxAESBase58ContentLength);
       Exit(APayloadContent.Length <= MaxAESBase58ContentLength);
 
 
     // unknown encoding format
     // unknown encoding format
@@ -659,10 +709,41 @@ begin
   Result := False;
   Result := False;
 end;
 end;
 
 
-class function TEPasaHelper.IsValidPasswordLength(const APasswordValue : String): Boolean;
+class function TEPasaComp.IsValidPasswordLength(const APasswordValue : String): Boolean;
 begin
 begin
   // no password length policy established (only client-side concern)
   // no password length policy established (only client-side concern)
   Result := True;
   Result := True;
 end;
 end;
 
 
+class function TEPasaComp.GetPayloadTypeProtocolByte(const APayloadType : TPayloadType) : Byte;
+var
+ LPayloadType : TPayloadTrait;
+begin
+  Result := 0; // NonDeterministic by default
+  for LPayloadType := Low(TPayloadTrait) to High(TPayloadTrait) do
+    if APayloadType.HasTrait(LPayloadType) then
+      Result := Result OR LPayloadType.ProtocolValue;
+end;
+
+class function TEPasaComp.GetPayloadTypeFromProtocolByte(AByte: Byte) : TPayloadType;
+var
+ LPayloadType : TPayloadTrait;
+ LPayloadTypeByte : byte;
+begin
+  if AByte = 0 then
+    Exit([ptNonDeterministic]);
+
+  Result := [];
+  for LPayloadType := Low(TPayloadTrait) to High(TPayloadTrait) do begin
+    LPayloadTypeByte := LPayloadType.ProtocolValue;
+    if (AByte AND LPayloadTypeByte) = LPayloadTypeByte then
+      Result := Result + [LPayloadType];
+  end;
+end;
+
+initialization
+
+EmptyEPasa := Default(TEPasa);
+
+
 end.
 end.

+ 1 - 1
src/core/UPCRPCSend.pas

@@ -59,7 +59,7 @@ Var LOpPayload : TOperationPayload;
 Begin
 Begin
   Result := Nil;
   Result := Nil;
   if Not ARPCProcess.RPCServer.CheckAndGetPrivateKeyInWallet(ASenderAccounKey,LPrivateKey,AErrorNum,AErrorDesc) then Exit(Nil);
   if Not ARPCProcess.RPCServer.CheckAndGetPrivateKeyInWallet(ASenderAccounKey,LPrivateKey,AErrorNum,AErrorDesc) then Exit(Nil);
-  if Not TPascalCoinJSONComp.CheckAndGetEncodedRAWPayload(ARawPayload,APayload_method,AEncodePwd,ASenderAccounKey,ATargetAccountKey,LOpPayload,AErrorNum,AErrorDesc) then Exit(Nil);
+  if Not TPascalCoinJSONComp.CheckAndGetEncodedRAWPayload(ARawPayload, APayload_method,AEncodePwd,ASenderAccounKey,ATargetAccountKey,LOpPayload,AErrorNum,AErrorDesc) then Exit(Nil);
   Result := TOpTransaction.CreateTransaction(ACurrent_protocol, ASender,ASender_last_n_operation+1, ATarget, LPrivateKey, AAmount, AFee, LOpPayload);
   Result := TOpTransaction.CreateTransaction(ACurrent_protocol, ASender,ASender_last_n_operation+1, ATarget, LPrivateKey, AAmount, AFee, LOpPayload);
   if Not Result.HasValidSignature then begin
   if Not Result.HasValidSignature then begin
     FreeAndNil(Result);
     FreeAndNil(Result);

+ 41 - 19
src/core/URPC.pas

@@ -27,7 +27,7 @@ interface
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
 Uses UThread, ULog, UConst, UNode, UAccounts, UCrypto, UBlockChain,
   UNetProtocol, UOpTransaction, UWallet, UTime, UPCEncryption, UTxMultiOperation,
   UNetProtocol, UOpTransaction, UWallet, UTime, UPCEncryption, UTxMultiOperation,
   UJSONFunctions, classes, blcksock, synsock,
   UJSONFunctions, classes, blcksock, synsock,
-  IniFiles, Variants, math, UBaseTypes,
+  IniFiles, Variants, math, UBaseTypes, UEPasa,
   {$IFDEF Use_OpenSSL}
   {$IFDEF Use_OpenSSL}
   UOpenSSL,
   UOpenSSL,
   {$ENDIF}
   {$ENDIF}
@@ -72,7 +72,8 @@ Type
     class Function HexaStringToOperationsHashTree(Const AHexaStringOperationsHashTree : String; ACurrentProtocol : Word; out AOperationsHashTree : TOperationsHashTree; var AErrors : String) : Boolean;
     class Function HexaStringToOperationsHashTree(Const AHexaStringOperationsHashTree : String; ACurrentProtocol : Word; out AOperationsHashTree : TOperationsHashTree; var AErrors : String) : Boolean;
     class Function CapturePubKey(const AInputParams : TPCJSONObject; const APrefix : String; var APubKey : TAccountKey; var AErrortxt : String) : Boolean;
     class Function CapturePubKey(const AInputParams : TPCJSONObject; const APrefix : String; var APubKey : TAccountKey; var AErrortxt : String) : Boolean;
     class function CheckAndGetEncodedRAWPayload(Const ARawPayload : TRawBytes; Const APayload_method, AEncodePwdForAES : String; const ASenderAccounKey, ATargetAccountKey : TAccountKey; out AOperationPayload : TOperationPayload; Var AErrorNum : Integer; Var AErrorDesc : String) : Boolean;
     class function CheckAndGetEncodedRAWPayload(Const ARawPayload : TRawBytes; Const APayload_method, AEncodePwdForAES : String; const ASenderAccounKey, ATargetAccountKey : TAccountKey; out AOperationPayload : TOperationPayload; Var AErrorNum : Integer; Var AErrorDesc : String) : Boolean;
-    class Function CaptureAccountNumber(const AInputParams : TPCJSONObject; const AParamName : String; const ABank : TPCBank; var AAccountNumber : Cardinal; var AErrorParam : String) : Boolean;
+    class Function CaptureAccountNumber(const AInputParams : TPCJSONObject; const AParamName : String; const ABank : TPCBank; out AResolvedAccount: Cardinal; var AErrorParam : String) : Boolean;
+    class Function CaptureEPASA(const AInputParams : TPCJSONObject; const AParamName : String; const ABank : TPCBank; out AEPasa: TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : Boolean; var AErrorParam : String) : Boolean;
   end;
   end;
 
 
   TRPCServerThread = Class;
   TRPCServerThread = Class;
@@ -154,7 +155,8 @@ Type
 
 
 implementation
 implementation
 
 
-Uses  {$IFNDEF FPC}windows,{$ENDIF}
+Uses
+  {$IFNDEF FPC}windows,{$ENDIF}
   SysUtils, Synautil,
   SysUtils, Synautil,
   UPCRPCSend,
   UPCRPCSend,
   UPCRPCOpData, UPCRPCFindAccounts, UPCRPCFindBlocks, UPCRPCFileUtils;
   UPCRPCOpData, UPCRPCFindAccounts, UPCRPCFindBlocks, UPCRPCFileUtils;
@@ -347,25 +349,41 @@ Begin
   end;
   end;
 end;
 end;
 
 
-class function TPascalCoinJSONComp.CaptureAccountNumber(const AInputParams : TPCJSONObject;
-  const AParamName: String; const ABank : TPCBank; var AAccountNumber: Cardinal;
-  var AErrorParam: String): Boolean;
+class Function TPascalCoinJSONComp.CaptureAccountNumber(const AInputParams : TPCJSONObject; const AParamName : String; const ABank : TPCBank; out AResolvedAccount: Cardinal; var AErrorParam : String) : Boolean;
+var
+  LEPasa : TEPasa;
+  LKey : TAccountKey;
+  LPurchase : Boolean;
+  LParamValue : String;
+begin
+  LParamValue := AInputParams.AsString(AParamName,'');
+  Result := CaptureEPASA(AInputParams, AParamName, ABank, LEPasa, AResolvedAccount, LKey, LPurchase, AErrorParam);
+  if Result AND (NOT LEPasa.IsStandard) then begin
+      AErrorParam := Format('"%s" is not valid Account Number for Param "%s"',[LParamValue,AParamName]);
+      Exit(False);
+  end;
+end;
+
+class function TPascalCoinJSONComp.CaptureEPASA(const AInputParams : TPCJSONObject; const AParamName : String; const ABank : TPCBank; out AEPasa: TEPasa; out AResolvedAccount: Cardinal; out AResolvedKey : TAccountKey; out ARequiresPurchase : Boolean; var AErrorParam : String): Boolean;
 var LParamValue : String;
 var LParamValue : String;
 Begin
 Begin
+  if not Assigned(ABank) then raise EArgumentNilException.Create('ABank');
   LParamValue := AInputParams.AsString(AParamName,'');
   LParamValue := AInputParams.AsString(AParamName,'');
   if Length(LParamValue)>0 then begin
   if Length(LParamValue)>0 then begin
-    Result := TAccountComp.AccountTxtNumberToAccountNumber(LParamValue,AAccountNumber);
-    if Not Result then begin
-      AErrorParam := Format('"%s" is no valid Account number for Param "%s"',[LParamValue,AParamName]);
-    end else if Assigned(ABank) then begin
-      if (AAccountNumber<0) or (AAccountNumber>=ABank.AccountsCount) then begin
-        Result := False;
-        AErrorParam := Format('Account %d does not exist in safebox (param "%s")',[AAccountNumber,AParamName]);
-      end;
-    end;
+    if Not TEPasa.TryParse(LParamValue, AEPasa) then begin
+      AEPasa := TEPasa.Empty;
+      AResolvedAccount := CT_AccountNo_NUL;
+      AResolvedKey := CT_Account_NUL.accountInfo.accountKey;
+      AErrorParam := Format('"%s" is not valid Account EPASA for Param "%s"',[LParamValue,AParamName]);
+      Exit(False);
+    end;
+    Result := ABank.SafeBox.TryResolveAccountByEPASA(AEPasa, AResolvedAccount, AResolvedKey, ARequiresPurchase, AErrorParam);
   end else begin
   end else begin
-    Result := False;
+    AEPasa := TEPasa.Empty;
+    AResolvedAccount := CT_AccountNo_NUL;
+    AResolvedKey := CT_Account_NUL.accountInfo.accountKey;
     AErrorParam := Format('Param "%s" not provided or null',[AParamName]);
     AErrorParam := Format('Param "%s" not provided or null',[AParamName]);
+    Exit(False);
   end;
   end;
 end;
 end;
 
 
@@ -405,16 +423,20 @@ begin
 end;
 end;
 
 
 class function TPascalCoinJSONComp.CheckAndGetEncodedRAWPayload(
 class function TPascalCoinJSONComp.CheckAndGetEncodedRAWPayload(
-  const ARawPayload: TRawBytes; const APayload_method, AEncodePwdForAES: String;
+  const ARawPayload: TRawBytes;
+//  const APayloadType : TPayloadType;
+  const APayload_method, AEncodePwdForAES: String;
   const ASenderAccounKey, ATargetAccountKey: TAccountKey;
   const ASenderAccounKey, ATargetAccountKey: TAccountKey;
-  out AOperationPayload : TOperationPayload; var AErrorNum: Integer;
+  out AOperationPayload : TOperationPayload;
+  var AErrorNum: Integer;
   var AErrorDesc: String): Boolean;
   var AErrorDesc: String): Boolean;
 begin
 begin
   AOperationPayload := CT_TOperationPayload_NUL;
   AOperationPayload := CT_TOperationPayload_NUL;
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   // TODO:
   // TODO:
   // Needs to assign AOperationPayload.payload_type based on PIP-0027
   // Needs to assign AOperationPayload.payload_type based on PIP-0027
   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+  //AOperationPayload.payload_type := APayloadType.ProtocolValue;
   if (Length(ARawPayload)>0) then begin
   if (Length(ARawPayload)>0) then begin
     if (APayload_method='none') then begin
     if (APayload_method='none') then begin
       AOperationPayload.payload_raw:=ARawPayload;
       AOperationPayload.payload_raw:=ARawPayload;

+ 9 - 0
src/libraries/sphere10/UCommon.pas

@@ -43,6 +43,15 @@ const
   MaxSeconds = MaxMilliseconds div 60;
   MaxSeconds = MaxMilliseconds div 60;
   MinSeconds = MinMilliseconds div 60;
   MinSeconds = MinMilliseconds div 60;
 
 
+  BYTE_BIT_0 = byte(1);
+  BYTE_BIT_1 = byte(2);
+  BYTE_BIT_2 = byte(4);
+  BYTE_BIT_3 = byte(8);
+  BYTE_BIT_4 = byte(16);
+  BYTE_BIT_5 = byte(32);
+  BYTE_BIT_6 = byte(64);
+  BYTE_BIT_7 = byte(128);
+
 { GLOBAL HELPER FUNCTIONS }
 { GLOBAL HELPER FUNCTIONS }