Browse Source

PIP-0032: fixes

Herman Schoenfeld 6 years ago
parent
commit
6244142e49

BIN
resources/wallet/key-16x16.bmp


+ 16 - 6
src/core/UAccounts.pas

@@ -130,7 +130,8 @@ Type
   public
   public
     Class Function IsValidAccountKey(const account: TAccountKey; var errors : String): Boolean;
     Class Function IsValidAccountKey(const account: TAccountKey; var errors : String): Boolean;
     Class Function IsValidAccountInfo(const accountInfo: TAccountInfo; var errors : String): Boolean;
     Class Function IsValidAccountInfo(const accountInfo: TAccountInfo; var errors : String): Boolean;
-    Class Function IsValidHashLockKey(const AAccount : TAccount; const AKey : TRawBytes) : Boolean;
+    Class Function IsValidAccountHashLockKey(const AAccount : TAccount; const AKey : TRawBytes) : Boolean;
+    Class Function IsValidHashLockKey(const AKey : TRawBytes; out AError : String) : Boolean;
     Class Function CalculateHashLock(const AKey : TRawBytes) : T32Bytes;
     Class Function CalculateHashLock(const AKey : TRawBytes) : T32Bytes;
     Class Function IsAccountForSale(const accountInfo: TAccountInfo) : Boolean;
     Class Function IsAccountForSale(const accountInfo: TAccountInfo) : Boolean;
     Class Function IsAccountForSwap(const accountInfo: TAccountInfo) : Boolean;
     Class Function IsAccountForSwap(const accountInfo: TAccountInfo) : Boolean;
@@ -1383,11 +1384,20 @@ begin
   end;
   end;
 end;
 end;
 
 
-Class Function TAccountComp.IsValidHashLockKey(const AAccount : TAccount; const AKey : TRawBytes) : Boolean;
+Class Function TAccountComp.IsValidAccountHashLockKey(const AAccount : TAccount; const AKey : TRawBytes) : Boolean;
 begin
 begin
   Result := BytesEqual( TBaseType.ToRawBytes( CalculateHashLock( AKey ) ), AAccount.account_data);
   Result := BytesEqual( TBaseType.ToRawBytes( CalculateHashLock( AKey ) ), AAccount.account_data);
 end;
 end;
 
 
+Class Function TAccountComp.IsValidHashLockKey(const AKey : TRawBytes; out AError : String) : Boolean;
+begin
+  if (Length(AKey) < CT_HashLockKey_MinBytes) OR (Length(AKey) > CT_HashLockKey_MaxBytes) then begin
+    AError := Format('Hash-lock key must be %d to %d bytes in length',[CT_HashLockKey_MinBytes,CT_HashLockKey_MaxBytes]);
+    Exit(False);
+  end;
+  Result := true;
+end;
+
 Class Function TAccountComp.CalculateHashLock(const AKey : TRawBytes) : T32Bytes;
 Class Function TAccountComp.CalculateHashLock(const AKey : TRawBytes) : T32Bytes;
 begin
 begin
   Result := TBaseType.To32Bytes( TCrypto.DoSha256(AKey) );
   Result := TBaseType.To32Bytes( TCrypto.DoSha256(AKey) );
@@ -1426,7 +1436,7 @@ begin
       exit;
       exit;
 
 
    if (account.accountInfo.state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]) then
    if (account.accountInfo.state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]) then
-     if NOT IsValidHashLockKey(account, APayload) then
+     if NOT IsValidAccountHashLockKey(account, APayload) then
        exit;
        exit;
 
 
   Result := true;
   Result := true;
@@ -4000,7 +4010,7 @@ begin
     Exit;
     Exit;
   end;
   end;
   if (LPBuyerAccount^.balance < (AAmount+AFee)) then begin
   if (LPBuyerAccount^.balance < (AAmount+AFee)) then begin
-    AErrors := 'Insuficient founds';
+    AErrors := 'Insufficient Funds';
     Exit;
     Exit;
   end;
   end;
   if (AFee>CT_MaxTransactionFee) then begin
   if (AFee>CT_MaxTransactionFee) then begin
@@ -4028,7 +4038,7 @@ begin
       TAccountComp.FormatMoney(LPAccountToBuy^.balance)+' + amount '+TAccountComp.FormatMoney(AAmount);
       TAccountComp.FormatMoney(LPAccountToBuy^.balance)+' + amount '+TAccountComp.FormatMoney(AAmount);
     Exit;
     Exit;
   end;
   end;
-  if TAccountComp.IsAccountForSwap(LPAccountToBuy^.accountInfo) AND (NOT TAccountComp.IsValidHashLockKey(LPAccountToBuy^, AHashLockKey)) then begin
+  if TAccountComp.IsAccountForSwap(LPAccountToBuy^.accountInfo) AND (NOT TAccountComp.IsValidAccountHashLockKey(LPAccountToBuy^, AHashLockKey)) then begin
     AErrors := 'Account is not unlocked by supplied hash lock key';
     AErrors := 'Account is not unlocked by supplied hash lock key';
     Exit;
     Exit;
   end;
   end;
@@ -4525,7 +4535,7 @@ begin
     Exit;
     Exit;
   end;
   end;
   if (P_signer^.balance < fee) then begin
   if (P_signer^.balance < fee) then begin
-    errors := 'Insuficient founds';
+    errors := 'Insufficient Funds';
     Exit;
     Exit;
   end;
   end;
   if (TAccountComp.IsAccountLocked(P_signer^.accountInfo,Origin_BlocksCount)) then begin
   if (TAccountComp.IsAccountLocked(P_signer^.accountInfo,Origin_BlocksCount)) then begin

+ 15 - 16
src/core/UBlockChain.pas

@@ -112,7 +112,7 @@ uses
 
 
 Type
 Type
   // Moved from UOpTransaction to here
   // Moved from UOpTransaction to here
-  TOpChangeAccountInfoType = (public_key, account_name, account_type, list_for_public_sale, list_for_private_sale, delist, account_data );
+  TOpChangeAccountInfoType = (public_key, account_name, account_type, list_for_public_sale, list_for_private_sale, delist, account_data, list_for_account_swap, list_for_coin_swap );
   TOpChangeAccountInfoTypes = Set of TOpChangeAccountInfoType;
   TOpChangeAccountInfoTypes = Set of TOpChangeAccountInfoType;
 
 
   // MultiOp... will allow a MultiOperation
   // MultiOp... will allow a MultiOperation
@@ -561,7 +561,7 @@ Const
   CT_TMultiOpSender_NUL : TMultiOpSender =  (Account:0;Amount:0;N_Operation:0;Payload:Nil;Signature:(r:Nil;s:Nil));
   CT_TMultiOpSender_NUL : TMultiOpSender =  (Account:0;Amount:0;N_Operation:0;Payload:Nil;Signature:(r:Nil;s:Nil));
   CT_TMultiOpReceiver_NUL : TMultiOpReceiver = (Account:0;Amount:0;Payload:Nil);
   CT_TMultiOpReceiver_NUL : TMultiOpReceiver = (Account:0;Amount:0;Payload: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;Seller_Account:-1;Account_Price:-1;Locked_Until_Block:0;Fee:0;Signature:(r:Nil;s: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;Seller_Account:-1;Account_Price:-1;Locked_Until_Block:0;Fee:0;Signature:(r:Nil;s:Nil));
-  CT_TOpChangeAccountInfoType_Txt : Array[Low(TOpChangeAccountInfoType)..High(TOpChangeAccountInfoType)] of String = ('public_key','account_name','account_type','list_for_public_sale','list_for_private_sale', 'delist', 'account_data');
+  CT_TOpChangeAccountInfoType_Txt : Array[Low(TOpChangeAccountInfoType)..High(TOpChangeAccountInfoType)] of String = ('public_key','account_name','account_type','list_for_public_sale','list_for_private_sale', 'delist', 'account_data','list_for_account_swap','list_for_coin_swap');
 
 
 implementation
 implementation
 
 
@@ -3262,7 +3262,7 @@ begin
       Result := true;
       Result := true;
     End;
     End;
     CT_Op_ListAccountForSale : begin
     CT_Op_ListAccountForSale : begin
-      case TOpListAccountForSale(Operation).SubType of
+      case TOpListAccountForSaleOrSwap(Operation).OpSubType of
         CT_OpSubtype_ListAccountForPrivateSale:  begin
         CT_OpSubtype_ListAccountForPrivateSale:  begin
           OperationResume.OpSubtype := CT_OpSubtype_ListAccountForPrivateSale;
           OperationResume.OpSubtype := CT_OpSubtype_ListAccountForPrivateSale;
           OperationResume.OperationTxt := 'List account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccount(Operation).Data.account_target)+' for private sale price '+
           OperationResume.OperationTxt := 'List account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccount(Operation).Data.account_target)+' for private sale price '+
@@ -3276,20 +3276,19 @@ begin
         CT_OpSubtype_ListAccountForAccountSwap:  begin
         CT_OpSubtype_ListAccountForAccountSwap:  begin
             OperationResume.OpSubtype := CT_OpSubtype_ListAccountForAccountSwap;
             OperationResume.OpSubtype := CT_OpSubtype_ListAccountForAccountSwap;
             OperationResume.OperationTxt :=
             OperationResume.OperationTxt :=
-            'List atomic account swap '+
-            ' for account ' + TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccountForSale(Operation).Data.account_target) +
-            ' hash-locked by ' + TCrypto.ToHexaString( TBaseType.ToRawBytes( TOpListAccountForSale(Operation).Data.hash_lock) ) +
-            ' time-locked until block ' + inttostr(TOpListAccountForSale(Operation).Data.locked_until_block) +
-            ' to counterparty key ' + TAccountComp.AccountPublicKeyExport( TOpListAccountForSale(Operation).Data.new_public_key);
+            'List account ' + TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccountForSaleOrSwap(Operation).Data.account_target) +
+            ' for atomic account swap with hash-lock "' + TCrypto.ToHexaString( TBaseType.ToRawBytes( TOpListAccountForSaleOrSwap(Operation).Data.hash_lock) ) + '"' +
+            ' time-locked till ' + inttostr(TOpListAccountForSaleOrSwap(Operation).Data.locked_until_block) +
+            ' to counterparty key ' + TAccountComp.AccountPublicKeyExport( TOpListAccountForSaleOrSwap(Operation).Data.new_public_key);
         end;
         end;
         CT_OpSubtype_ListAccountForCoinSwap:  begin
         CT_OpSubtype_ListAccountForCoinSwap:  begin
             OperationResume.OpSubtype := CT_OpSubtype_ListAccountForCoinSwap;
             OperationResume.OpSubtype := CT_OpSubtype_ListAccountForCoinSwap;
             OperationResume.OperationTxt :=
             OperationResume.OperationTxt :=
-            'List atomic coin swap '+TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccountForSale(Operation).Data.account_target)+
-            ' for ' + TAccountComp.FormatMoney(TOpListAccountForSale(Operation).Data.account_price) + ' PASC' +
-            ' hash-locked by ' + TCrypto.ToHexaString( TBaseType.ToRawBytes( TOpListAccountForSale(Operation).Data.hash_lock) ) +
-            ' time-locked until block ' + inttostr(TOpListAccountForSale(Operation).Data.locked_until_block) +
-            ' to counterparty account ' + TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccountForSale(Operation).Data.account_to_pay);
+            'List account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccountForSaleOrSwap(Operation).Data.account_target)+
+            ' for atomic coin swap of ' + TAccountComp.FormatMoney(TOpListAccountForSaleOrSwap(Operation).Data.account_price) + ' PASC' +
+            ' with hash-lock "' + TCrypto.ToHexaString( TBaseType.ToRawBytes( TOpListAccountForSaleOrSwap(Operation).Data.hash_lock) ) + '"' +
+            ' time-locked till ' + inttostr(TOpListAccountForSaleOrSwap(Operation).Data.locked_until_block) +
+            ' to counterparty account ' + TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccountForSaleOrSwap(Operation).Data.account_to_pay);
         end;
         end;
       end;
       end;
       OperationResume.newKey := TOpListAccount(Operation).Data.new_public_key;
       OperationResume.newKey := TOpListAccount(Operation).Data.new_public_key;
@@ -3305,20 +3304,20 @@ begin
       OperationResume.DestAccount:=TOpBuyAccount(Operation).Data.target;
       OperationResume.DestAccount:=TOpBuyAccount(Operation).Data.target;
       if TOpBuyAccount(Operation).Data.sender=Affected_account_number then begin
       if TOpBuyAccount(Operation).Data.sender=Affected_account_number then begin
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountBuyer;
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountBuyer;
-        OperationResume.OperationTxt := 'Buy account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.target)+' for '+TAccountComp.FormatMoney(TOpBuyAccount(Operation).Data.AccountPrice)+' PASC';
+        OperationResume.OperationTxt := 'Buy account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.target)+' for '+TAccountComp.FormatMoney(TOpBuyAccount(Operation).Data.AccountPrice)+' PASC' + ' with payload hex "' + TCrypto.ToHexaString(TOpBuyAccount(Operation).Data.Payload) +'"';
         OperationResume.Amount := Int64(TOpBuyAccount(Operation).Data.amount) * (-1);
         OperationResume.Amount := Int64(TOpBuyAccount(Operation).Data.amount) * (-1);
         Result := true;
         Result := true;
       end else if TOpBuyAccount(Operation).Data.target=Affected_account_number then begin
       end else if TOpBuyAccount(Operation).Data.target=Affected_account_number then begin
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountTarget;
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountTarget;
         OperationResume.OperationTxt := 'Purchased account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.target)+' by '+
         OperationResume.OperationTxt := 'Purchased account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.target)+' by '+
-          TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.sender)+' for '+TAccountComp.FormatMoney(TOpBuyAccount(Operation).Data.AccountPrice)+' PASC';
+          TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.sender)+' for '+TAccountComp.FormatMoney(TOpBuyAccount(Operation).Data.AccountPrice)+' PASC' + ' with payload hex "' + TCrypto.ToHexaString(TOpBuyAccount(Operation).Data.Payload) +'"';;
         OperationResume.Amount := Int64(TOpBuyAccount(Operation).Data.amount) - Int64(TOpBuyAccount(Operation).Data.AccountPrice);
         OperationResume.Amount := Int64(TOpBuyAccount(Operation).Data.amount) - Int64(TOpBuyAccount(Operation).Data.AccountPrice);
         OperationResume.Fee := 0;
         OperationResume.Fee := 0;
         Result := true;
         Result := true;
       end else if TOpBuyAccount(Operation).Data.SellerAccount=Affected_account_number then begin
       end else if TOpBuyAccount(Operation).Data.SellerAccount=Affected_account_number then begin
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountSeller;
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountSeller;
         OperationResume.OperationTxt := 'Sold account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.target)+' by '+
         OperationResume.OperationTxt := 'Sold account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.target)+' by '+
-          TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.sender)+' for '+TAccountComp.FormatMoney(TOpBuyAccount(Operation).Data.AccountPrice)+' PASC';
+          TAccountComp.AccountNumberToAccountTxtNumber(TOpBuyAccount(Operation).Data.sender)+' for '+TAccountComp.FormatMoney(TOpBuyAccount(Operation).Data.AccountPrice)+' PASC' + ' with payload hex "' + TCrypto.ToHexaString(TOpBuyAccount(Operation).Data.Payload) +'"';;
         OperationResume.Amount := TOpBuyAccount(Operation).Data.AccountPrice;
         OperationResume.Amount := TOpBuyAccount(Operation).Data.AccountPrice;
         OperationResume.Fee := 0;
         OperationResume.Fee := 0;
         Result := true;
         Result := true;

+ 7 - 4
src/core/UConst.pas

@@ -108,6 +108,9 @@ Const
   CT_AccountInfo_ForAccountSwap = 1001;
   CT_AccountInfo_ForAccountSwap = 1001;
   CT_AccountInfo_ForCoinSwap = 1002;
   CT_AccountInfo_ForCoinSwap = 1002;
 
 
+  CT_HashLockKey_MinBytes = 4;
+  CT_HashLockKey_MaxBytes = 128;
+
   CT_PROTOCOL_1 = 1;
   CT_PROTOCOL_1 = 1;
   CT_PROTOCOL_2 = 2;
   CT_PROTOCOL_2 = 2;
   CT_PROTOCOL_3 = 3;
   CT_PROTOCOL_3 = 3;
@@ -116,10 +119,10 @@ Const
   CT_BUILD_PROTOCOL = CT_PROTOCOL_4;
   CT_BUILD_PROTOCOL = CT_PROTOCOL_4;
 
 
   CT_BlockChain_Protocol_Available: Word = 4; // Protocol 4 flag
   CT_BlockChain_Protocol_Available: Word = 4; // Protocol 4 flag
-  CT_Protocol_Upgrade_v2_MinBlock = {$IFDEF PRODUCTION}115000{$ELSE}50{$ENDIF};
-  CT_Protocol_Upgrade_v3_MinBlock = {$IFDEF PRODUCTION}210000{$ELSE}250{$ENDIF};
-  CT_Protocol_Upgrade_v4_MinBlock = {$IFDEF PRODUCTION}260000{$ELSE}400{$ENDIF};
-  CT_Protocol_Upgrade_v5_MinBlock = {$IFDEF PRODUCTION}999999999{$ELSE}500{$ENDIF}; // TODO Need define v5 for production!
+  CT_Protocol_Upgrade_v2_MinBlock = {$IFDEF PRODUCTION}115000{$ELSE}47{$ENDIF};
+  CT_Protocol_Upgrade_v3_MinBlock = {$IFDEF PRODUCTION}210000{$ELSE}48{$ENDIF};
+  CT_Protocol_Upgrade_v4_MinBlock = {$IFDEF PRODUCTION}260000{$ELSE}49{$ENDIF};
+  CT_Protocol_Upgrade_v5_MinBlock = {$IFDEF PRODUCTION}999999999{$ELSE}50{$ENDIF}; // TODO Need define v5 for production!
 
 
 
 
   CT_MagicNetIdentification = {$IFDEF PRODUCTION}$0A043580{$ELSE}$05000001{$ENDIF}; // Unix timestamp 168048000 ... It's Albert birthdate!
   CT_MagicNetIdentification = {$IFDEF PRODUCTION}$0A043580{$ELSE}$05000001{$ENDIF}; // Unix timestamp 168048000 ... It's Albert birthdate!

+ 54 - 34
src/core/UOpTransaction.pas

@@ -174,8 +174,8 @@ Type
     function IsValidSignatureBasedOnCurrentSafeboxState(ASafeBoxTransaction : TPCSafeBoxTransaction) : Boolean; override;
     function IsValidSignatureBasedOnCurrentSafeboxState(ASafeBoxTransaction : TPCSafeBoxTransaction) : Boolean; override;
   End;
   End;
 
 
-  // NEW OPERATIONS PROTOCOL 2 (note: lat_SetHLTC* added in v5 as a separate network operation implemented as a private sale subclass)
-  TOpListAccountOperationType = (lat_Unknown, lat_ListForSale, lat_DelistAccount);
+  // NEW OPERATIONS PROTOCOL 2
+  TOpListAccountOperationType = (lat_Unknown, lat_ListAccount, lat_DelistAccount);
 
 
   TOpListAccountData = Record
   TOpListAccountData = Record
     account_signer,
     account_signer,
@@ -244,13 +244,13 @@ Type
     function IsValidSignatureBasedOnCurrentSafeboxState(ASafeBoxTransaction : TPCSafeBoxTransaction) : Boolean; override;
     function IsValidSignatureBasedOnCurrentSafeboxState(ASafeBoxTransaction : TPCSafeBoxTransaction) : Boolean; override;
   End;
   End;
 
 
-  TOpListAccountForSale = Class(TOpListAccount)
+  TOpListAccountForSaleOrSwap = Class(TOpListAccount)
   private
   private
-    FSubType : Integer;
+    function GetOpSubType : Integer;
   public
   public
     class function OpType : Byte; override;
     class function OpType : Byte; override;
-    Constructor CreateListAccountForSale(ACurrentProtocol : Word; AListOpSubType : Integer; AAccountSigner, ANOperation, AAccountTarget: Cardinal; AAccountPrice, AFee: UInt64; AAccountToPay: Cardinal;  ANewPublicKey: TAccountKey; ALockedUntilBlock: Cardinal; AKey: TECPrivateKey; const AHashLock : T32Bytes; const APayload: TRawBytes);
-    property SubType : Integer read FSubType;
+    Constructor CreateListAccountForSaleOrSwap(ACurrentProtocol : Word; AListOpSubType : Integer; AAccountSigner, ANOperation, AAccountTarget: Cardinal; AAccountPrice, AFee: UInt64; AAccountToPay: Cardinal;  ANewPublicKey: TAccountKey; ALockedUntilBlock: Cardinal; AKey: TECPrivateKey; const AHashLock : T32Bytes; const APayload: TRawBytes);
+    property OpSubType : Integer read GetOpSubType;
   End;
   End;
 
 
   TOpDelistAccountForSale = Class(TOpListAccount)
   TOpDelistAccountForSale = Class(TOpListAccount)
@@ -364,7 +364,7 @@ Begin
   TPCOperationsComp.RegisterOperationClass(TOpTransaction);
   TPCOperationsComp.RegisterOperationClass(TOpTransaction);
   TPCOperationsComp.RegisterOperationClass(TOpChangeKey);
   TPCOperationsComp.RegisterOperationClass(TOpChangeKey);
   TPCOperationsComp.RegisterOperationClass(TOpRecoverFounds);
   TPCOperationsComp.RegisterOperationClass(TOpRecoverFounds);
-  TPCOperationsComp.RegisterOperationClass(TOpListAccountForSale);
+  TPCOperationsComp.RegisterOperationClass(TOpListAccountForSaleOrSwap);
   TPCOperationsComp.RegisterOperationClass(TOpDelistAccountForSale);
   TPCOperationsComp.RegisterOperationClass(TOpDelistAccountForSale);
   TPCOperationsComp.RegisterOperationClass(TOpBuyAccount);
   TPCOperationsComp.RegisterOperationClass(TOpBuyAccount);
   TPCOperationsComp.RegisterOperationClass(TOpChangeKeySigned);
   TPCOperationsComp.RegisterOperationClass(TOpChangeKeySigned);
@@ -1195,22 +1195,25 @@ function TOpTransaction.toString: String;
 begin
 begin
   case FData.opTransactionStyle of
   case FData.opTransactionStyle of
     transaction :
     transaction :
-      Result := Format('Transaction from %s to %s amount:%s fee:%s (n_op:%d) payload size:%d',[
+      Result := Format('Transaction from %s to %s amount:%s fee:%s (n_op:%d) payload size:%d payload:%s',[
          TAccountComp.AccountNumberToAccountTxtNumber(FData.sender),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.sender),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.target),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.target),
-         TAccountComp.FormatMoney(FData.amount),TAccountComp.FormatMoney(FData.fee),FData.n_operation,Length(FData.payload)]);
+         TAccountComp.FormatMoney(FData.amount),TAccountComp.FormatMoney(FData.fee),FData.n_operation,Length(FData.payload),
+         TCrypto.ToHexaString(FData.payload)]);
     transaction_with_auto_buy_account :
     transaction_with_auto_buy_account :
-      Result := Format('Transaction/Buy account %s by %s paying %s to %s amount:%s fee:%s (n_op:%d) payload size:%d',[
+      Result := Format('Transaction/Buy account %s by %s paying %s to %s amount:%s fee:%s (n_op:%d) payload size:%d payload:%s',[
          TAccountComp.AccountNumberToAccountTxtNumber(FData.target),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.target),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.sender),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.sender),
          TAccountComp.FormatMoney(FData.AccountPrice), TAccountComp.AccountNumberToAccountTxtNumber(FData.SellerAccount),
          TAccountComp.FormatMoney(FData.AccountPrice), TAccountComp.AccountNumberToAccountTxtNumber(FData.SellerAccount),
-         TAccountComp.FormatMoney(FData.amount),TAccountComp.FormatMoney(FData.fee),FData.n_operation,Length(FData.payload)]);
+         TAccountComp.FormatMoney(FData.amount),TAccountComp.FormatMoney(FData.fee),FData.n_operation,Length(FData.payload),
+         TCrypto.ToHexaString(FData.payload)]);
     buy_account :
     buy_account :
-      Result := Format('Buy account %s by %s paying %s to %s amount:%s fee:%s (n_op:%d) payload size:%d',[
+      Result := Format('Buy account %s by %s paying %s to %s amount:%s fee:%s (n_op:%d) payload size:%d payload:%s',[
          TAccountComp.AccountNumberToAccountTxtNumber(FData.target),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.target),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.sender),
          TAccountComp.AccountNumberToAccountTxtNumber(FData.sender),
          TAccountComp.FormatMoney(FData.AccountPrice), TAccountComp.AccountNumberToAccountTxtNumber(FData.SellerAccount),
          TAccountComp.FormatMoney(FData.AccountPrice), TAccountComp.AccountNumberToAccountTxtNumber(FData.SellerAccount),
-         TAccountComp.FormatMoney(FData.amount),TAccountComp.FormatMoney(FData.fee),FData.n_operation,Length(FData.payload)]);
+         TAccountComp.FormatMoney(FData.amount),TAccountComp.FormatMoney(FData.fee),FData.n_operation,Length(FData.payload),
+         TCrypto.ToHexaString(FData.payload)]);
   else raise Exception.Create('ERROR DEV 20170424-2');
   else raise Exception.Create('ERROR DEV 20170424-2');
   end;
   end;
 end;
 end;
@@ -1794,8 +1797,8 @@ begin
     LIsPublicSale := false;
     LIsPublicSale := false;
     LIsPrivateSale := false;
     LIsPrivateSale := false;
   end;
   end;
-  LIsCoinSwap := (OpType = CT_Op_ListAccountForSale) AND (FData.account_state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]);
-  if LIsCoinSwap then begin
+  LIsSwap := (OpType = CT_Op_ListAccountForSale) AND (FData.account_state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]);
+  if LIsSwap then begin
     if FData.account_state =  as_ForAtomicCoinSwap then begin
     if FData.account_state =  as_ForAtomicCoinSwap then begin
       LIsAccountSwap := false;
       LIsAccountSwap := false;
       LIsCoinSwap := true;
       LIsCoinSwap := true;
@@ -1837,7 +1840,8 @@ begin
       errors := 'Invalid account to pay number';
       errors := 'Invalid account to pay number';
       Exit;
       Exit;
     end;
     end;
-    if (FData.account_target = FData.account_to_pay) then begin
+    if (FData.account_target = FData.account_to_pay) AND NOT (LIsAccountSwap AND (FData.account_price = 0))  then begin
+      // Note: atomic account swap with 0 sale price can have tself as seller
       errors := 'Account to pay is itself';
       errors := 'Account to pay is itself';
       Exit;
       Exit;
     end;
     end;
@@ -1846,7 +1850,7 @@ begin
       Exit;
       Exit;
     end;
     end;
     if (NOT LIsSwap) AND (FData.account_price<=0) then begin
     if (NOT LIsSwap) AND (FData.account_price<=0) then begin
-      errors := 'Account for sale price must be > 0';
+      errors := 'Account for sale price must be greater than 0';
       exit;
       exit;
     end;
     end;
     if (FData.locked_until_block > (AccountTransaction.FreezedSafeBox.BlocksCount + CT_MaxFutureBlocksLockedAccount)) then begin
     if (FData.locked_until_block > (AccountTransaction.FreezedSafeBox.BlocksCount + CT_MaxFutureBlocksLockedAccount)) then begin
@@ -1982,12 +1986,12 @@ begin
   Stream.Read(FData.account_target,Sizeof(FData.account_target));
   Stream.Read(FData.account_target,Sizeof(FData.account_target));
   Stream.Read(w,2);
   Stream.Read(w,2);
   case w of
   case w of
-    CT_Op_ListAccountForSale : FData.operation_type := lat_ListForSale;
+    CT_Op_ListAccountForSale : FData.operation_type := lat_ListAccount;
     CT_Op_DelistAccount : FData.operation_type := lat_DelistAccount;
     CT_Op_DelistAccount : FData.operation_type := lat_DelistAccount;
     else exit; // Invalid data info
     else exit; // Invalid data info
   end;
   end;
   Stream.Read(FData.n_operation,Sizeof(FData.n_operation));
   Stream.Read(FData.n_operation,Sizeof(FData.n_operation));
-  if (FData.operation_type in [lat_ListForSale]) then begin
+  if (FData.operation_type in [lat_ListAccount]) then begin
     Stream.Read(FData.account_price,Sizeof(FData.account_price));
     Stream.Read(FData.account_price,Sizeof(FData.account_price));
     Stream.Read(FData.account_to_pay,Sizeof(FData.account_to_pay));
     Stream.Read(FData.account_to_pay,Sizeof(FData.account_to_pay));
     if Stream.Read(FData.public_key.EC_OpenSSL_NID,Sizeof(FData.public_key.EC_OpenSSL_NID))<0 then exit;
     if Stream.Read(FData.public_key.EC_OpenSSL_NID,Sizeof(FData.public_key.EC_OpenSSL_NID))<0 then exit;
@@ -2007,7 +2011,8 @@ begin
       if TStreamOp.ReadAnsiString(Stream, FData.hash_lock) < 0 then exit;  // the hash-lock if any
       if TStreamOp.ReadAnsiString(Stream, FData.hash_lock) < 0 then exit;  // the hash-lock if any
     end else begin
     end else begin
       // On V4 and below only as_ForSale is possible
       // On V4 and below only as_ForSale is possible
-      FData.account_state := as_ForSale;
+      if FData.operation_type = lat_ListAccount then
+        FData.account_state := as_ForSale;
     end;
     end;
   end;
   end;
   Stream.Read(FData.fee,Sizeof(FData.fee));
   Stream.Read(FData.fee,Sizeof(FData.fee));
@@ -2026,19 +2031,25 @@ begin
   OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
   OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
   OperationResume.Changers[0].Account:=FData.account_target;
   OperationResume.Changers[0].Account:=FData.account_target;
   case FData.operation_type of
   case FData.operation_type of
-    lat_ListForSale : begin
+    lat_ListAccount : begin
         if (FData.new_public_key.EC_OpenSSL_NID=CT_TECDSA_Public_Nul.EC_OpenSSL_NID) then begin
         if (FData.new_public_key.EC_OpenSSL_NID=CT_TECDSA_Public_Nul.EC_OpenSSL_NID) then begin
           OperationResume.Changers[0].Changes_type:=[list_for_public_sale];
           OperationResume.Changers[0].Changes_type:=[list_for_public_sale];
         end else begin
         end else begin
-          OperationResume.Changers[0].Changes_type:=[list_for_private_sale];
+          if FData.account_state = as_ForAtomicAccountSwap then
+            OperationResume.Changers[0].Changes_type:=[list_for_account_swap, account_data]
+          else if FData.account_state = as_ForAtomicAccountSwap then
+            OperationResume.Changers[0].Changes_type:=[list_for_coin_swap, account_data]
+          else
+            OperationResume.Changers[0].Changes_type:=[list_for_private_sale];
           OperationResume.Changers[0].New_Accountkey := FData.new_public_key;
           OperationResume.Changers[0].New_Accountkey := FData.new_public_key;
           OperationResume.Changers[0].Locked_Until_Block := FData.locked_until_block;
           OperationResume.Changers[0].Locked_Until_Block := FData.locked_until_block;
         end;
         end;
         OperationResume.Changers[0].Seller_Account:=FData.account_to_pay;
         OperationResume.Changers[0].Seller_Account:=FData.account_to_pay;
         OperationResume.Changers[0].Account_Price:=FData.account_price;
         OperationResume.Changers[0].Account_Price:=FData.account_price;
-        if (FData.account_state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]) then
+        if (FData.account_state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]) then begin
           OperationResume.Changers[0].New_Data := TBaseType.ToRawBytes( FData.hash_lock );
           OperationResume.Changers[0].New_Data := TBaseType.ToRawBytes( FData.hash_lock );
-      end;
+        end;
+    end;
     lat_DelistAccount : begin
     lat_DelistAccount : begin
         OperationResume.Changers[0].Changes_type:=[delist];
         OperationResume.Changers[0].Changes_type:=[delist];
       end;
       end;
@@ -2083,13 +2094,13 @@ begin
   Stream.Write(FData.account_signer,Sizeof(FData.account_signer));
   Stream.Write(FData.account_signer,Sizeof(FData.account_signer));
   Stream.Write(FData.account_target,Sizeof(FData.account_target));
   Stream.Write(FData.account_target,Sizeof(FData.account_target));
   case FData.operation_type of
   case FData.operation_type of
-    lat_ListForSale : w := CT_Op_ListAccountForSale;
+    lat_ListAccount : w := CT_Op_ListAccountForSale;
     lat_DelistAccount : w := CT_Op_DelistAccount;
     lat_DelistAccount : w := CT_Op_DelistAccount;
   else raise Exception.Create('ERROR DEV 20170412-1');
   else raise Exception.Create('ERROR DEV 20170412-1');
   end;
   end;
   Stream.Write(w,2);
   Stream.Write(w,2);
   Stream.Write(FData.n_operation,Sizeof(FData.n_operation));
   Stream.Write(FData.n_operation,Sizeof(FData.n_operation));
-  if FData.operation_type in [lat_ListForSale] then begin
+  if FData.operation_type in [lat_ListAccount] then begin
     Stream.Write(FData.account_price,Sizeof(FData.account_price));
     Stream.Write(FData.account_price,Sizeof(FData.account_price));
     Stream.Write(FData.account_to_pay,Sizeof(FData.account_to_pay));
     Stream.Write(FData.account_to_pay,Sizeof(FData.account_to_pay));
     Stream.Write(FData.public_key.EC_OpenSSL_NID,Sizeof(FData.public_key.EC_OpenSSL_NID));
     Stream.Write(FData.public_key.EC_OpenSSL_NID,Sizeof(FData.public_key.EC_OpenSSL_NID));
@@ -2124,7 +2135,7 @@ end;
 function TOpListAccount.SellerAccount: Int64;
 function TOpListAccount.SellerAccount: Int64;
 begin
 begin
   Case FData.operation_type of
   Case FData.operation_type of
-    lat_ListForSale : Result := FData.account_to_pay;
+    lat_ListAccount : Result := FData.account_to_pay;
   else Result:=inherited SellerAccount;
   else Result:=inherited SellerAccount;
   end;
   end;
 end;
 end;
@@ -2132,7 +2143,7 @@ end;
 function TOpListAccount.toString: String;
 function TOpListAccount.toString: String;
 begin
 begin
   case FData.operation_type of
   case FData.operation_type of
-    lat_ListForSale : begin
+    lat_ListAccount : begin
       case FData.account_state of
       case FData.account_state of
         as_ForSale: begin
         as_ForSale: begin
           if (FData.new_public_key.EC_OpenSSL_NID=CT_TECDSA_Public_Nul.EC_OpenSSL_NID) then begin
           if (FData.new_public_key.EC_OpenSSL_NID=CT_TECDSA_Public_Nul.EC_OpenSSL_NID) then begin
@@ -2149,7 +2160,7 @@ begin
           end;
           end;
         end;
         end;
         as_ForAtomicAccountSwap: begin
         as_ForAtomicAccountSwap: begin
-          Result := Format('List account %s for atomic account swap hash-lock:%s time-locked until block:%d fee:%s (n_op:%d) payload size:%d',[
+          Result := Format('List account %s for atomic account swap hash-lock:%s time-lock:%d fee:%s (n_op:%d) payload size:%d',[
             TAccountComp.AccountNumberToAccountTxtNumber(FData.account_target),
             TAccountComp.AccountNumberToAccountTxtNumber(FData.account_target),
             TCrypto.ToHexaString( TBaseType.ToRawBytes( FData.hash_lock ) ),
             TCrypto.ToHexaString( TBaseType.ToRawBytes( FData.hash_lock ) ),
             FData.locked_until_block,
             FData.locked_until_block,
@@ -2159,7 +2170,7 @@ begin
           );
           );
         end;
         end;
         as_ForAtomicCoinSwap: begin
         as_ForAtomicCoinSwap: begin
-          Result := Format('List account %s for atomic coin swap for %s PASC hash-lock:%s time-locked until block:%d fee:%s (n_op:%d) payload size:%d',[
+          Result := Format('List account %s for atomic coin swap for %s PASC hash-lock:%s time-lock:%d fee:%s (n_op:%d) payload size:%d',[
             TAccountComp.AccountNumberToAccountTxtNumber(FData.account_target),
             TAccountComp.AccountNumberToAccountTxtNumber(FData.account_target),
             TAccountComp.FormatMoney(FData.account_price),
             TAccountComp.FormatMoney(FData.account_price),
             TCrypto.ToHexaString( TBaseType.ToRawBytes( FData.hash_lock ) ),
             TCrypto.ToHexaString( TBaseType.ToRawBytes( FData.hash_lock ) ),
@@ -2227,9 +2238,9 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TOpListAccountForSale }
+{ TOpListAccountForSaleOrSwap }
 
 
-constructor TOpListAccountForSale.CreateListAccountForSale(ACurrentProtocol : Word; AListOpSubType : Integer; AAccountSigner, ANOperation, AAccountTarget: Cardinal; AAccountPrice, AFee: UInt64; AAccountToPay: Cardinal;  ANewPublicKey: TAccountKey; ALockedUntilBlock: Cardinal; AKey: TECPrivateKey;  const AHashLock : T32Bytes; const APayload: TRawBytes);
+constructor TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(ACurrentProtocol : Word; AListOpSubType : Integer; AAccountSigner, ANOperation, AAccountTarget: Cardinal; AAccountPrice, AFee: UInt64; AAccountToPay: Cardinal;  ANewPublicKey: TAccountKey; ALockedUntilBlock: Cardinal; AKey: TECPrivateKey;  const AHashLock : T32Bytes; const APayload: TRawBytes);
 begin
 begin
   inherited Create(ACurrentProtocol);
   inherited Create(ACurrentProtocol);
   if NOT (AListOpSubType IN [CT_OpSubtype_ListAccountForPublicSale, CT_OpSubtype_ListAccountForPrivateSale, CT_OpSubtype_ListAccountForAccountSwap, CT_OpSubtype_ListAccountForCoinSwap]) then
   if NOT (AListOpSubType IN [CT_OpSubtype_ListAccountForPublicSale, CT_OpSubtype_ListAccountForPrivateSale, CT_OpSubtype_ListAccountForAccountSwap, CT_OpSubtype_ListAccountForCoinSwap]) then
@@ -2247,7 +2258,7 @@ begin
   end;
   end;
   FData.account_signer := AAccountSigner;
   FData.account_signer := AAccountSigner;
   FData.account_target := AAccountTarget;
   FData.account_target := AAccountTarget;
-  FData.operation_type := lat_ListForSale;
+  FData.operation_type := lat_ListAccount;
   FData.n_operation := ANOperation;
   FData.n_operation := ANOperation;
   FData.account_price := AAccountPrice;
   FData.account_price := AAccountPrice;
   FData.account_to_pay := AAccountToPay;
   FData.account_to_pay := AAccountToPay;
@@ -2270,11 +2281,20 @@ begin
   end;
   end;
 end;
 end;
 
 
-class function TOpListAccountForSale.OpType: Byte;
+class function TOpListAccountForSaleOrSwap.OpType: Byte;
 begin
 begin
   Result := CT_Op_ListAccountForSale;
   Result := CT_Op_ListAccountForSale;
 end;
 end;
 
 
+function GetOpSubType : Integer;
+begin
+  case FData.accountState of
+    as_ForSale:
+      if (FData.new_public_key.EC_OpenSSL_NID<>0) then Exit(CT_OpSubtype_ListAccountForPrivateSale) else Exit(CT_OpSubtype_ListAccountForPublicSale);
+    as_ForAtomicAccountSwap: Exit(CT_OpSubtype_ListAccountForAccountSwap);
+    as_ForAtomicCoinSwap: Exit(CT_OpSubtype_ListAccountForCoinSwap);
+  end;
+end;
 
 
 { TOpDelistAccountForSale }
 { TOpDelistAccountForSale }
 
 

+ 3 - 3
src/core/URPC.pas

@@ -1147,7 +1147,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
   // It assumes that account_number,account_last_n_operation and account_pubkey are correct
   // It assumes that account_number,account_last_n_operation and account_pubkey are correct
   Function CreateOperationListAccountForSale(current_protocol : Word; AListType : Word; account_signer, account_last_n_operation, account_listed : Cardinal; const account_signer_pubkey: TAccountKey;
   Function CreateOperationListAccountForSale(current_protocol : Word; AListType : Word; account_signer, account_last_n_operation, account_listed : Cardinal; const account_signer_pubkey: TAccountKey;
     account_price : UInt64; locked_until_block : Cardinal; account_to_pay : Cardinal; Const new_account_pubkey : TAccountKey;
     account_price : UInt64; locked_until_block : Cardinal; account_to_pay : Cardinal; Const new_account_pubkey : TAccountKey;
-    fee : UInt64; const AHashLock: T32Bytes; const RawPayload : TRawBytes; Const Payload_method, EncodePwd : String) : TOpListAccountForSale;
+    fee : UInt64; const AHashLock: T32Bytes; const RawPayload : TRawBytes; Const Payload_method, EncodePwd : String) : TOpListAccountForSaleOrSwap;
   // "payload_method" types: "none","dest"(default),"sender","aes"(must provide "pwd" param)
   // "payload_method" types: "none","dest"(default),"sender","aes"(must provide "pwd" param)
   var privateKey : TECPrivateKey;
   var privateKey : TECPrivateKey;
     errors : String;
     errors : String;
@@ -1161,7 +1161,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
        aux_target_pubkey := new_account_pubkey;
        aux_target_pubkey := new_account_pubkey;
     end else aux_target_pubkey := account_signer_pubkey;
     end else aux_target_pubkey := account_signer_pubkey;
     if Not CheckAndGetEncodedRAWPayload(RawPayload,Payload_method,EncodePwd,account_signer_pubkey,aux_target_pubkey,f_raw) then Exit(Nil);
     if Not CheckAndGetEncodedRAWPayload(RawPayload,Payload_method,EncodePwd,account_signer_pubkey,aux_target_pubkey,f_raw) then Exit(Nil);
-    Result := TOpListAccountForSale.CreateListAccountForSale(
+    Result := TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(
       current_protocol,
       current_protocol,
       AListType,
       AListType,
       account_signer,
       account_signer,
@@ -1545,7 +1545,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
     // "new_b58_pubkey" or "new_enc_pubkey" is the future public key for this sale (private sale), otherwise is open and everybody can buy
     // "new_b58_pubkey" or "new_enc_pubkey" is the future public key for this sale (private sale), otherwise is open and everybody can buy
     // "enc_hash_lock" (optional) hex-encoded hash-lock for an atomic swap
     // "enc_hash_lock" (optional) hex-encoded hash-lock for an atomic swap
   var
   var
-    opSale: TOpListAccountForSale;
+    opSale: TOpListAccountForSaleOrSwap;
     listType : Integer;
     listType : Integer;
     account_signer, account_target, seller_account : Cardinal;
     account_signer, account_target, seller_account : Cardinal;
     locked_until_block : Cardinal;
     locked_until_block : Cardinal;

+ 124 - 0
src/gui-classic/UFRMHashLock.dfm

@@ -0,0 +1,124 @@
+object FRMHashLock: TFRMHashLock
+  Left = 0
+  Top = 0
+  BorderStyle = bsDialog
+  Caption = 'Atomic Swap Hash-Lock '
+  ClientHeight = 270
+  ClientWidth = 548
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poOwnerFormCenter
+  OnCloseQuery = FormCloseQuery
+  OnCreate = FormCreate
+  DesignSize = (
+    548
+    270)
+  PixelsPerInch = 96
+  TextHeight = 13
+  object lblError: TLabel
+    Left = 19
+    Top = 239
+    Width = 282
+    Height = 13
+    AutoSize = False
+    Caption = 'Errors detected'
+    Color = clBtnFace
+    Font.Charset = DEFAULT_CHARSET
+    Font.Color = clRed
+    Font.Height = -11
+    Font.Name = 'Tahoma'
+    Font.Style = []
+    ParentColor = False
+    ParentFont = False
+  end
+  object btnCancel: TBitBtn
+    Left = 424
+    Top = 231
+    Width = 116
+    Height = 31
+    Anchors = [akRight, akBottom]
+    Kind = bkCancel
+    NumGlyphs = 2
+    TabOrder = 0
+    OnClick = btnCancelClick
+  end
+  object btnSet: TBitBtn
+    Left = 307
+    Top = 231
+    Width = 111
+    Height = 31
+    Anchors = [akRight, akBottom]
+    Caption = 'Set Hash-Lock'
+    Kind = bkOK
+    NumGlyphs = 2
+    TabOrder = 1
+    OnClick = btnSetClick
+  end
+  object GroupBox1: TGroupBox
+    Left = 8
+    Top = 14
+    Width = 532
+    Height = 83
+    Caption = 'Mode'
+    TabOrder = 2
+    object rbHashLock: TRadioButton
+      Left = 11
+      Top = 25
+      Width = 446
+      Height = 17
+      Caption = 
+        'Hash-Lock - the 32 byte hash-lock provided to you by the counter' +
+        'party'
+      TabOrder = 0
+    end
+    object rbHashLockKey: TRadioButton
+      Left = 11
+      Top = 48
+      Width = 478
+      Height = 17
+      Caption = 
+        'Hash-Lock Key - a secret that will be hashed to create the 32 by' +
+        'te hash-lock'
+      TabOrder = 1
+      WordWrap = True
+    end
+  end
+  object GroupBox2: TGroupBox
+    Left = 8
+    Top = 103
+    Width = 532
+    Height = 122
+    Caption = 'Data'
+    TabOrder = 3
+    DesignSize = (
+      532
+      122)
+    object Label2: TLabel
+      Left = 11
+      Top = 21
+      Width = 266
+      Height = 13
+      Caption = 'Please enter the hash lock data as a hexadecimal string'
+    end
+    object meHashLockData: TMemo
+      Left = 11
+      Top = 40
+      Width = 505
+      Height = 67
+      Anchors = [akLeft, akTop, akRight, akBottom]
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clBlack
+      Font.Height = -16
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      ParentFont = False
+      TabOrder = 0
+      WantReturns = False
+    end
+  end
+end

+ 105 - 0
src/gui-classic/UFRMHashLock.pas

@@ -0,0 +1,105 @@
+unit UFRMHashLock;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+interface
+
+uses
+  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, UWallet, Buttons, {$IFDEF FPC}LMessages,{$ENDIF}
+  clipbrd, UConst, UGUIUtils, UBaseTypes;
+
+type
+  TFRMHashLock = class(TForm)
+    btnCancel: TBitBtn;
+    btnSet: TBitBtn;
+    GroupBox1: TGroupBox;
+    rbHashLock: TRadioButton;
+    rbHashLockKey: TRadioButton;
+    GroupBox2: TGroupBox;
+    meHashLockData: TMemo;
+    Label2: TLabel;
+    lblError: TLabel;
+    procedure btnSetClick(Sender: TObject);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    procedure btnCancelClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+  private
+    { Private declarations }
+    FHashLock : T32Bytes;
+    function GetError : String;
+    procedure SetError(const AMsg : String);
+  public
+    { Public declarations }
+    property Error : String read GetError write SetError;
+    property HashLock : T32Bytes read FHashLock;
+  end;
+
+
+implementation
+
+uses UCrypto, UAccounts;
+
+{$R *.dfm}
+
+procedure TFRMHashLock.btnCancelClick(Sender: TObject);
+begin
+  Error := '';
+end;
+
+procedure TFRMHashLock.btnSetClick(Sender: TObject);
+var
+  LData : TRawBytes;
+  LErr : string;
+begin
+  Error := '';
+  if (NOT rbHashLock.Checked) AND (NOT rbHashLockKey.Checked) then begin
+    Error := 'Select the hash-lock mode';
+    Exit;
+  end;
+
+  if NOT TCrypto.IsHexString(meHashLockData.Text) then begin
+    Error := 'Data is not hexadecimal format';
+    Exit;
+  end;
+
+  LData := TCrypto.HexaToRaw(meHashLockData.Text);
+
+  if (rbHashLock.Checked) then begin
+    if Length(LData) <> 32 then begin
+      Error := 'Hash-lock must be 32bytes';
+      Exit;
+    end;
+    FHashLock := TBaseType.To32Bytes(LData);
+  end else if (rbHashLockKey.Checked) then begin
+    if NOT TAccountComp.IsValidHashLockKey(LData, LErr) then begin
+      Error := LErr;
+      Exit;
+    end;
+    FHashLock := TAccountComp.CalculateHashLock(LData);
+  end else Error := 'INTERNAL ERROR: 8356DE573BA748618EDD6603B22D9EAD';
+end;
+
+procedure TFRMHashLock.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+  CanClose := Error = '';
+end;
+
+procedure TFRMHashLock.FormCreate(Sender: TObject);
+begin
+  Error := '';
+end;
+
+function TFRMHashLock.GetError : String;
+begin
+  Result := lblError.Caption;
+end;
+
+procedure TFRMHashLock.SetError(const AMsg : String);
+begin
+  lblError.Caption := AMsg;
+end;
+
+end.

+ 3 - 0
src/gui-classic/UFRMHashLock.vlb

@@ -0,0 +1,3 @@
+[]
+Coordinates=0,0,91,36
+

+ 419 - 316
src/gui-classic/UFRMOperation.dfm

@@ -2,9 +2,9 @@ object FRMOperation: TFRMOperation
   Left = 498
   Left = 498
   Top = 222
   Top = 222
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
-  BorderStyle = bsSingle
+  BorderStyle = bsDialog
   Caption = 'New Operation'
   Caption = 'New Operation'
-  ClientHeight = 493
+  ClientHeight = 515
   ClientWidth = 608
   ClientWidth = 608
   Color = clBtnFace
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Charset = DEFAULT_CHARSET
@@ -61,8 +61,8 @@ object FRMOperation: TFRMOperation
     ParentColor = False
     ParentColor = False
   end
   end
   object bbExecute: TBitBtn
   object bbExecute: TBitBtn
-    Left = 300
-    Top = 445
+    Left = 307
+    Top = 476
     Width = 130
     Width = 130
     Height = 31
     Height = 31
     Caption = 'Execute (F12)'
     Caption = 'Execute (F12)'
@@ -88,8 +88,8 @@ object FRMOperation: TFRMOperation
     OnClick = actExecuteExecute
     OnClick = actExecuteExecute
   end
   end
   object bbCancel: TBitBtn
   object bbCancel: TBitBtn
-    Left = 465
-    Top = 445
+    Left = 461
+    Top = 476
     Width = 116
     Width = 116
     Height = 31
     Height = 31
     Kind = bkCancel
     Kind = bkCancel
@@ -100,14 +100,15 @@ object FRMOperation: TFRMOperation
     Left = 25
     Left = 25
     Top = 72
     Top = 72
     Width = 556
     Width = 556
-    Height = 351
+    Height = 398
     ActivePage = tsOperation
     ActivePage = tsOperation
     TabOrder = 1
     TabOrder = 1
     object tsOperation: TTabSheet
     object tsOperation: TTabSheet
       TabVisible = False
       TabVisible = False
+      ExplicitHeight = 373
       object lblFee: TLabel
       object lblFee: TLabel
         Left = 15
         Left = 15
-        Top = 188
+        Top = 220
         Width = 69
         Width = 69
         Height = 13
         Height = 13
         Caption = 'Operation Fee'
         Caption = 'Operation Fee'
@@ -115,8 +116,8 @@ object FRMOperation: TFRMOperation
         ParentColor = False
         ParentColor = False
       end
       end
       object lblSignerAccount: TLabel
       object lblSignerAccount: TLabel
-        Left = 176
-        Top = 188
+        Left = 277
+        Top = 221
         Width = 131
         Width = 131
         Height = 13
         Height = 13
         Caption = 'Signer account (Fee payer)'
         Caption = 'Signer account (Fee payer)'
@@ -124,8 +125,8 @@ object FRMOperation: TFRMOperation
         ParentColor = False
         ParentColor = False
       end
       end
       object sbSearchSignerAccount: TSpeedButton
       object sbSearchSignerAccount: TSpeedButton
-        Left = 411
-        Top = 184
+        Left = 512
+        Top = 217
         Width = 23
         Width = 23
         Height = 22
         Height = 22
         Glyph.Data = {
         Glyph.Data = {
@@ -159,9 +160,9 @@ object FRMOperation: TFRMOperation
       end
       end
       object gbPayload: TGroupBox
       object gbPayload: TGroupBox
         Left = 13
         Left = 13
-        Top = 211
+        Top = 240
         Width = 521
         Width = 521
-        Height = 119
+        Height = 137
         Caption = ' Payload: '
         Caption = ' Payload: '
         TabOrder = 2
         TabOrder = 2
         object lblEncryptPassword: TLabel
         object lblEncryptPassword: TLabel
@@ -176,17 +177,17 @@ object FRMOperation: TFRMOperation
         object Label4: TLabel
         object Label4: TLabel
           Left = 255
           Left = 255
           Top = 15
           Top = 15
-          Width = 67
+          Width = 64
           Height = 13
           Height = 13
-          Caption = 'Payload data:'
+          Caption = 'Payload Data'
           Color = clBtnFace
           Color = clBtnFace
           ParentColor = False
           ParentColor = False
         end
         end
         object lblEncryptionErrors: TLabel
         object lblEncryptionErrors: TLabel
           Left = 255
           Left = 255
           Top = 96
           Top = 96
-          Width = 246
-          Height = 13
+          Width = 187
+          Height = 33
           AutoSize = False
           AutoSize = False
           Caption = 'Errors detected'
           Caption = 'Errors detected'
           Color = clBtnFace
           Color = clBtnFace
@@ -252,7 +253,7 @@ object FRMOperation: TFRMOperation
           Left = 255
           Left = 255
           Top = 37
           Top = 37
           Width = 246
           Width = 246
-          Height = 57
+          Height = 53
           Font.Charset = DEFAULT_CHARSET
           Font.Charset = DEFAULT_CHARSET
           Font.Color = clBlack
           Font.Color = clBlack
           Font.Height = -16
           Font.Height = -16
@@ -274,20 +275,28 @@ object FRMOperation: TFRMOperation
           TabStop = True
           TabStop = True
           OnClick = memoPayloadClick
           OnClick = memoPayloadClick
         end
         end
+        object cbPayloadAsHex: TCheckBox
+          Left = 448
+          Top = 96
+          Width = 97
+          Height = 17
+          Caption = 'As Hex'
+          TabOrder = 6
+        end
       end
       end
       object ebFee: TEdit
       object ebFee: TEdit
         Left = 90
         Left = 90
-        Top = 184
+        Top = 217
         Width = 70
         Width = 70
         Height = 21
         Height = 21
         TabOrder = 1
         TabOrder = 1
       end
       end
       object PageControlOpType: TPageControl
       object PageControlOpType: TPageControl
         Left = 13
         Left = 13
-        Top = 11
-        Width = 521
-        Height = 167
-        ActivePage = tsChangeInfo
+        Top = 7
+        Width = 524
+        Height = 204
+        ActivePage = tsListAccount
         TabOrder = 0
         TabOrder = 0
         OnChange = PageControlOpTypeChange
         OnChange = PageControlOpTypeChange
         object tsTransaction: TTabSheet
         object tsTransaction: TTabSheet
@@ -376,297 +385,390 @@ object FRMOperation: TFRMOperation
           end
           end
         end
         end
         object tsChangePrivateKey: TTabSheet
         object tsChangePrivateKey: TTabSheet
-          Caption = 'Change key'
+          Caption = 'Change Key'
           ImageIndex = 1
           ImageIndex = 1
-          object gbChangeKey: TGroupBox
-            Left = 7
-            Top = 6
-            Width = 488
-            Height = 118
-            Caption = ' Change type: '
+          object lblNewPrivateKey: TLabel
+            Left = 57
+            Top = 40
+            Width = 78
+            Height = 13
+            Caption = 'New private key'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object lblChangeKeyErrors: TLabel
+            Left = 145
+            Top = 15
+            Width = 331
+            Height = 13
+            Alignment = taRightJustify
+            AutoSize = False
+            Caption = 'Errors detected'
+            Color = clBtnFace
+            Font.Charset = DEFAULT_CHARSET
+            Font.Color = clRed
+            Font.Height = -11
+            Font.Name = 'Tahoma'
+            Font.Style = []
+            ParentColor = False
+            ParentFont = False
+          end
+          object lblNewOwnerErrors: TLabel
+            Left = 173
+            Top = 68
+            Width = 302
+            Height = 13
+            Alignment = taRightJustify
+            AutoSize = False
+            Caption = 'Errors detected'
+            Color = clBtnFace
+            Font.Charset = DEFAULT_CHARSET
+            Font.Color = clRed
+            Font.Height = -11
+            Font.Name = 'Tahoma'
+            Font.Style = []
+            ParentColor = False
+            ParentFont = False
+          end
+          object lblNewOwnerPublicKey: TLabel
+            Left = 24
+            Top = 90
+            Width = 109
+            Height = 13
+            Caption = 'New owners public key'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object rbChangeKeyWithAnother: TRadioButton
+            Left = 12
+            Top = 20
+            Width = 114
+            Height = 19
+            Caption = 'Change private key'
             TabOrder = 0
             TabOrder = 0
-            object lblNewPrivateKey: TLabel
-              Left = 57
-              Top = 40
-              Width = 78
-              Height = 13
-              Caption = 'New private key'
-              Color = clBtnFace
-              ParentColor = False
-            end
-            object lblNewOwnerPublicKey: TLabel
-              Left = 24
-              Top = 90
-              Width = 109
-              Height = 13
-              Caption = 'New owners public key'
-              Color = clBtnFace
-              ParentColor = False
-            end
-            object lblNewOwnerErrors: TLabel
-              Left = 173
-              Top = 68
-              Width = 302
-              Height = 13
-              Alignment = taRightJustify
-              AutoSize = False
-              Caption = 'Errors detected'
-              Color = clBtnFace
-              Font.Charset = DEFAULT_CHARSET
-              Font.Color = clRed
-              Font.Height = -11
-              Font.Name = 'Tahoma'
-              Font.Style = []
-              ParentColor = False
-              ParentFont = False
-            end
-            object lblChangeKeyErrors: TLabel
-              Left = 145
-              Top = 15
-              Width = 331
-              Height = 13
-              Alignment = taRightJustify
-              AutoSize = False
-              Caption = 'Errors detected'
-              Color = clBtnFace
-              Font.Charset = DEFAULT_CHARSET
-              Font.Color = clRed
-              Font.Height = -11
-              Font.Name = 'Tahoma'
-              Font.Style = []
-              ParentColor = False
-              ParentFont = False
-            end
-            object rbChangeKeyWithAnother: TRadioButton
-              Left = 12
-              Top = 20
-              Width = 114
-              Height = 19
-              Caption = 'Change private key'
-              TabOrder = 0
-            end
-            object cbNewPrivateKey: TComboBox
-              Left = 145
-              Top = 37
-              Width = 294
-              Height = 21
-              Style = csDropDownList
-              Sorted = True
-              TabOrder = 1
-            end
-            object ebNewPublicKey: TEdit
-              Left = 144
-              Top = 87
-              Width = 331
-              Height = 21
-              TabOrder = 4
-            end
-            object bbChangePrivateKeyKeys: TBitBtn
-              Left = 445
-              Top = 36
-              Width = 31
-              Height = 22
-              Glyph.Data = {
-                36050000424D3605000000000000360400002800000010000000100000000100
-                0800000000000001000000000000000000000001000000010000FF00FF008C6B
-                6C0087707000AE877C000D7FA9006F7C88006D7C94001F7ECE000E80AA001180
-                A7001081AB00048CB900078DBC000B8DBA000C8DBA00088EBC001285B0007882
-                95006092BD005EA8BE000A91C1000F9DCE002087DE0011A7D10030BCDC001F89
-                E00059A9DC0044BADD004ABFE00057AEF4004DB1F90049B2FF004EB7FF0057B1
-                F60050B6FE0022D7FC0024D7FF0024D8FD0039D7FB0035D8FD004BC6DC0046C6
-                E40048D5EE0075D3E90058E9FD006FE6FF0070E6FF0071F9FE007BFFFF008683
-                88008B8697008F989B00969594009C919000AD858000AD868500AB939500A49E
-                9900B1979400B5A09F008AA5AD00CAA08C00CDAC9300C2A69A00F3BE8000C6AE
-                A000CFB7A100D3BBA200F4C88E00F5CB9A00F5D09C00F8D09800DAC5B700E4CC
-                A900EFD2A900ECD1AC00F6DAAB00F5DEB500F5E1B600F9E1B100FEEAB900FFF2
-                BA00A1C6C8008DE6FA0081F8FE008CFAFD008DFCFE0097FCFD009BFBFD00B8ED
-                F600A7FFFF00AAFFFE00ADFFFE00B6F6FF00B1FCFD00B4FFFF00ECDDCC00E8DD
-                D600FFF7C600FCF5CD00FCF7D100FAF6D600FFFBD500FEFED600F7F2D900FEFF
-                D900FFFEDD00C6F5FF00C6FEFF00D2FFFF00FEF7E000FBFCE100FDFFE100FFFF
-                E400E3FEFF00F9F6F200FFFFF400F1FBFC00F5FFFE00FBFFFF00000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                0000000000000000000000000000000000000000000000000000000000000000
-                00000000000000000605000004080408080A000000000011191A000B2A23272D
-                531B080000001116201D0B552C23272E531C1509003207201D000F552C23272B
-                3A3F41030112202000000F552C252938606771684236200000000B5F5D6B3B61
-                74676A67513D000000000B59181735716A676A63474B360000000F282C23396A
-                6A6A6A4C404D360000000B552C2534656A654F455049360000000B552C251343
-                6247446E7336000000000B552C25263C3E4B4E483636000000000F55542F3057
-                523331020000000000000B77766D5F5C5C5C2F08000000000000001476726C5C
-                5A58100000000000000000000F0F0B0F0F0F0000000000000000}
-              TabOrder = 2
-              OnClick = bbChangePrivateKeyKeysClick
-            end
-            object rbChangeKeyTransferAccountToNewOwner: TRadioButton
-              Left = 12
-              Top = 67
-              Width = 180
-              Height = 19
-              Caption = 'Transfer account to a new owner'
-              TabOrder = 3
-            end
+          end
+          object cbNewPrivateKey: TComboBox
+            Left = 145
+            Top = 37
+            Width = 294
+            Height = 21
+            Style = csDropDownList
+            Sorted = True
+            TabOrder = 1
+          end
+          object bbChangePrivateKeyKeys: TBitBtn
+            Left = 445
+            Top = 36
+            Width = 31
+            Height = 22
+            Glyph.Data = {
+              36050000424D3605000000000000360400002800000010000000100000000100
+              0800000000000001000000000000000000000001000000010000FF00FF008C6B
+              6C0087707000AE877C000D7FA9006F7C88006D7C94001F7ECE000E80AA001180
+              A7001081AB00048CB900078DBC000B8DBA000C8DBA00088EBC001285B0007882
+              95006092BD005EA8BE000A91C1000F9DCE002087DE0011A7D10030BCDC001F89
+              E00059A9DC0044BADD004ABFE00057AEF4004DB1F90049B2FF004EB7FF0057B1
+              F60050B6FE0022D7FC0024D7FF0024D8FD0039D7FB0035D8FD004BC6DC0046C6
+              E40048D5EE0075D3E90058E9FD006FE6FF0070E6FF0071F9FE007BFFFF008683
+              88008B8697008F989B00969594009C919000AD858000AD868500AB939500A49E
+              9900B1979400B5A09F008AA5AD00CAA08C00CDAC9300C2A69A00F3BE8000C6AE
+              A000CFB7A100D3BBA200F4C88E00F5CB9A00F5D09C00F8D09800DAC5B700E4CC
+              A900EFD2A900ECD1AC00F6DAAB00F5DEB500F5E1B600F9E1B100FEEAB900FFF2
+              BA00A1C6C8008DE6FA0081F8FE008CFAFD008DFCFE0097FCFD009BFBFD00B8ED
+              F600A7FFFF00AAFFFE00ADFFFE00B6F6FF00B1FCFD00B4FFFF00ECDDCC00E8DD
+              D600FFF7C600FCF5CD00FCF7D100FAF6D600FFFBD500FEFED600F7F2D900FEFF
+              D900FFFEDD00C6F5FF00C6FEFF00D2FFFF00FEF7E000FBFCE100FDFFE100FFFF
+              E400E3FEFF00F9F6F200FFFFF400F1FBFC00F5FFFE00FBFFFF00000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              0000000000000000000000000000000000000000000000000000000000000000
+              00000000000000000605000004080408080A000000000011191A000B2A23272D
+              531B080000001116201D0B552C23272E531C1509003207201D000F552C23272B
+              3A3F41030112202000000F552C252938606771684236200000000B5F5D6B3B61
+              74676A67513D000000000B59181735716A676A63474B360000000F282C23396A
+              6A6A6A4C404D360000000B552C2534656A654F455049360000000B552C251343
+              6247446E7336000000000B552C25263C3E4B4E483636000000000F55542F3057
+              523331020000000000000B77766D5F5C5C5C2F08000000000000001476726C5C
+              5A58100000000000000000000F0F0B0F0F0F0000000000000000}
+            TabOrder = 2
+            OnClick = bbChangePrivateKeyKeysClick
+          end
+          object rbChangeKeyTransferAccountToNewOwner: TRadioButton
+            Left = 12
+            Top = 67
+            Width = 180
+            Height = 19
+            Caption = 'Transfer account to a new owner'
+            TabOrder = 3
+          end
+          object ebNewPublicKey: TEdit
+            Left = 144
+            Top = 87
+            Width = 331
+            Height = 21
+            TabOrder = 4
           end
           end
         end
         end
-        object tsListForSale: TTabSheet
-          Caption = 'List account for sale'
+        object tsListAccount: TTabSheet
+          Caption = 'List Account'
           ImageIndex = 3
           ImageIndex = 3
-          object gbSaleType: TGroupBox
-            Left = 7
-            Top = 5
-            Width = 499
-            Height = 131
-            Caption = ' Sale type: '
+          object lblListAccountErrors: TLabel
+            Left = 11
+            Top = 7
+            Width = 456
+            Height = 13
+            AutoSize = False
+            Caption = 'Errors detected'
+            Color = clBtnFace
+            Font.Charset = DEFAULT_CHARSET
+            Font.Color = clRed
+            Font.Height = -11
+            Font.Name = 'Tahoma'
+            Font.Style = []
+            ParentColor = False
+            ParentFont = False
+          end
+          object lblPrice: TLabel
+            Left = 44
+            Top = 83
+            Width = 46
+            Height = 13
+            Alignment = taRightJustify
+            Caption = 'Sale Price'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object lblSeller: TLabel
+            Left = 277
+            Top = 83
+            Width = 68
+            Height = 13
+            Alignment = taRightJustify
+            Caption = 'Seller Account'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object sbSearchListerSellerAccount: TSpeedButton
+            Left = 476
+            Top = 78
+            Width = 23
+            Height = 22
+            Glyph.Data = {
+              36030000424D3603000000000000360000002800000010000000100000000100
+              18000000000000030000120B0000120B00000000000000000000FF00FF4A667C
+              BE9596FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FF6B9CC31E89E84B7AA3C89693FF00FFFF00FFFF00FFFF
+              00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF4BB4FE51B5FF
+              2089E94B7AA2C69592FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FFFF00FF51B7FE51B3FF1D87E64E7AA0CA9792FF00FFFF
+              00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+              51B7FE4EB2FF1F89E64E7BA2B99497FF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF52B8FE4BB1FF2787D95F6A76FF
+              00FFB0857FC09F94C09F96BC988EFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+              FF00FFFF00FF55BDFFB5D6EDBF9D92BB9B8CE7DAC2FFFFE3FFFFE5FDFADAD8C3
+              B3B58D85FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFCEA795FD
+              EEBEFFFFD8FFFFDAFFFFDBFFFFE6FFFFFBEADDDCAE837FFF00FFFF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FFC1A091FBDCA8FEF7D0FFFFDBFFFFE3FFFFF8FFFF
+              FDFFFFFDC6A99CFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC1A091FEE3ACF1
+              C491FCF2CAFFFFDDFFFFE4FFFFF7FFFFF7FFFFE9EEE5CBB9948CFF00FFFF00FF
+              FF00FFFF00FFFF00FFC2A191FFE6AEEEB581F7DCAEFEFDD8FFFFDFFFFFE3FFFF
+              E4FFFFE0F3ECD2BB968EFF00FFFF00FFFF00FFFF00FFFF00FFBC978CFBE7B7F4
+              C791F2C994F8E5B9FEFCD8FFFFDDFFFFDCFFFFE0E2D2BAB68E86FF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FFD9C3A9FFFEE5F7DCB8F2C994F5D4A5FAE8BDFDF4
+              C9FDFBD6B69089FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB58D85E8
+              DEDDFFFEF2F9D8A3F4C48CF9D49FFDEAB8D0B49FB89086FF00FFFF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FFFF00FFAD827FC9AA9EEFE0B7EFDFB2E7CEACB890
+              86B89086FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+              00FFFF00FFBA968ABB988CB79188FF00FFFF00FFFF00FFFF00FF}
+            OnClick = sbSearchListerSellerAccountClick
+          end
+          object lblNewKey: TLabel
+            Left = 41
+            Top = 110
+            Width = 49
+            Height = 13
+            Alignment = taRightJustify
+            Caption = 'Buyer Key'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object lblTimeLock: TLabel
+            Left = 43
+            Top = 137
+            Width = 47
+            Height = 13
+            Alignment = taRightJustify
+            Caption = 'Time-Lock'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object lblHashLock: TLabel
+            Left = 222
+            Top = 137
+            Width = 49
+            Height = 13
+            Caption = 'Hash-Lock'
+            Color = clBtnFace
+            ParentColor = False
+          end
+          object btnHashLock: TSpeedButton
+            Left = 476
+            Top = 132
+            Width = 23
+            Height = 22
+            Glyph.Data = {
+              36030000424D3603000000000000360000002800000010000000100000000100
+              18000000000000030000120B0000120B00000000000000000000FF00FF53B6F0
+              4A95DFC6CEEDFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FF1B59D3298DEA7AFDFF47A2E6C1C9ECFF00FFFF00FFFF
+              00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF3F9BE4207EE2
+              1C74DE7AFFFF4398E1CFD5F0FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FFA3B5E758CDF52B81DD1676DC72FCFF4390DFE5E9F7FF
+              00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB385EA
+              57D1F7287CD90F72DB71FFFF4DA9E8ECB4F9FF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FFFF00FFFF00FF96A7E258D3F72883D90F5FCF6EFFFF50
+              AFE8B0B7E5FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+              FF00FF9EADE456D8F8277CD40E56C86DF6FF2DBEF10E85DD1777D7167EDB166D
+              D17C92D8FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF97A7E356DAF92781D40D
+              97E30ECFFC0ECCFA0ECFFB0ED0FB0ED5FF12BAF45279D1FF00FFFF00FFFF00FF
+              FF00FFFF00FFFF00FFB486EA56CCF31ED1FA09BCF411BFF410BFF310BFF310BE
+              F30FD3FD05B2EFA2B4E6FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF6486D72C
+              E3FD09C1F311C4F410C4F40EC8F60ECCF70BC1F30BDCFE3581D6FF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FF4A95DF1DE4FD0CC5F311C7F40ED1F70FC2F139C6
+              F01FD6F805D1F843BBEBFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF4491DF1A
+              E8FD00C5F206CEF600C2F27AAAE5FF00FF8CC9ED64F4FF70CFEFFF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FF6390DC44F3FE0ECFF429DAF635D8F5FF00FFFF00
+              FF9DC4EA63FFFF7EBDE8FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFBFCEF0AD
+              EBF972F8FF5DE3F65EEAF964D7F384E4F559F1FC5CE8F8B1C6EDFF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FFFF00FF9EB9E99DE5F77DF9FD63F2FC60F7FD66FC
+              FE77EBF9A7C3EBFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+              00FFCDDAF39CC1EC8AC7EC85C5EB9CC8EDB3C5EDFF00FFFF00FF}
+          end
+          object sbTimeLock: TSpeedButton
+            Left = 187
+            Top = 133
+            Width = 23
+            Height = 22
+            Glyph.Data = {
+              36030000424D3603000000000000360000002800000010000000100000000100
+              18000000000000030000120B0000120B00000000000000000000FF00FF53B6F0
+              4A95DFC6CEEDFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FF1B59D3298DEA7AFDFF47A2E6C1C9ECFF00FFFF00FFFF
+              00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF3F9BE4207EE2
+              1C74DE7AFFFF4398E1CFD5F0FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FFA3B5E758CDF52B81DD1676DC72FCFF4390DFE5E9F7FF
+              00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB385EA
+              57D1F7287CD90F72DB71FFFF4DA9E8ECB4F9FF00FFFF00FFFF00FFFF00FFFF00
+              FFFF00FFFF00FFFF00FFFF00FFFF00FF96A7E258D3F72883D90F5FCF6EFFFF50
+              AFE8B0B7E5FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+              FF00FF9EADE456D8F8277CD40E56C86DF6FF2DBEF10E85DD1777D7167EDB166D
+              D17C92D8FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF97A7E356DAF92781D40D
+              97E30ECFFC0ECCFA0ECFFB0ED0FB0ED5FF12BAF45279D1FF00FFFF00FFFF00FF
+              FF00FFFF00FFFF00FFB486EA56CCF31ED1FA09BCF411BFF410BFF310BFF310BE
+              F30FD3FD05B2EFA2B4E6FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF6486D72C
+              E3FD09C1F311C4F410C4F40EC8F60ECCF70BC1F30BDCFE3581D6FF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FF4A95DF1DE4FD0CC5F311C7F40ED1F70FC2F139C6
+              F01FD6F805D1F843BBEBFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF4491DF1A
+              E8FD00C5F206CEF600C2F27AAAE5FF00FF8CC9ED64F4FF70CFEFFF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FF6390DC44F3FE0ECFF429DAF635D8F5FF00FFFF00
+              FF9DC4EA63FFFF7EBDE8FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFBFCEF0AD
+              EBF972F8FF5DE3F65EEAF964D7F384E4F559F1FC5CE8F8B1C6EDFF00FFFF00FF
+              FF00FFFF00FFFF00FFFF00FFFF00FF9EB9E99DE5F77DF9FD63F2FC60F7FD66FC
+              FE77EBF9A7C3EBFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+              00FFCDDAF39CC1EC8AC7EC85C5EB9CC8EDB3C5EDFF00FFFF00FF}
+            Visible = False
+          end
+          object rbListAccountForPublicSale: TRadioButton
+            Left = 11
+            Top = 28
+            Width = 119
+            Height = 17
+            Caption = 'List for Public Sale'
             TabOrder = 0
             TabOrder = 0
-            object Label1: TLabel
-              Left = 81
-              Top = 62
-              Width = 50
-              Height = 13
-              Caption = 'Sale price:'
-              Color = clBtnFace
-              ParentColor = False
-            end
-            object Label3: TLabel
-              Left = 229
-              Top = 62
-              Width = 142
-              Height = 13
-              Caption = 'Seller account (where to pay)'
-              Color = clBtnFace
-              ParentColor = False
-            end
-            object lblSaleNewOwnerPublicKey: TLabel
-              Left = 20
-              Top = 85
-              Width = 109
-              Height = 13
-              Caption = 'New owners public key'
-              Color = clBtnFace
-              ParentColor = False
-            end
-            object lblSaleLockedUntilBlock: TLabel
-              Left = 44
-              Top = 109
-              Width = 87
-              Height = 13
-              Caption = 'Locked until block:'
-              Color = clBtnFace
-              ParentColor = False
-            end
-            object lblListAccountErrors: TLabel
-              Left = 145
-              Top = 15
-              Width = 331
-              Height = 13
-              Alignment = taRightJustify
-              AutoSize = False
-              Caption = 'Errors detected'
-              Color = clBtnFace
-              Font.Charset = DEFAULT_CHARSET
-              Font.Color = clRed
-              Font.Height = -11
-              Font.Name = 'Tahoma'
-              Font.Style = []
-              ParentColor = False
-              ParentFont = False
-            end
-            object sbSearchListerSellerAccount: TSpeedButton
-              Left = 467
-              Top = 59
-              Width = 23
-              Height = 22
-              Glyph.Data = {
-                36030000424D3603000000000000360000002800000010000000100000000100
-                18000000000000030000120B0000120B00000000000000000000FF00FF4A667C
-                BE9596FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-                FFFF00FFFF00FFFF00FF6B9CC31E89E84B7AA3C89693FF00FFFF00FFFF00FFFF
-                00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF4BB4FE51B5FF
-                2089E94B7AA2C69592FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-                FFFF00FFFF00FFFF00FFFF00FF51B7FE51B3FF1D87E64E7AA0CA9792FF00FFFF
-                00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-                51B7FE4EB2FF1F89E64E7BA2B99497FF00FFFF00FFFF00FFFF00FFFF00FFFF00
-                FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF52B8FE4BB1FF2787D95F6A76FF
-                00FFB0857FC09F94C09F96BC988EFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-                FF00FFFF00FF55BDFFB5D6EDBF9D92BB9B8CE7DAC2FFFFE3FFFFE5FDFADAD8C3
-                B3B58D85FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFCEA795FD
-                EEBEFFFFD8FFFFDAFFFFDBFFFFE6FFFFFBEADDDCAE837FFF00FFFF00FFFF00FF
-                FF00FFFF00FFFF00FFFF00FFC1A091FBDCA8FEF7D0FFFFDBFFFFE3FFFFF8FFFF
-                FDFFFFFDC6A99CFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC1A091FEE3ACF1
-                C491FCF2CAFFFFDDFFFFE4FFFFF7FFFFF7FFFFE9EEE5CBB9948CFF00FFFF00FF
-                FF00FFFF00FFFF00FFC2A191FFE6AEEEB581F7DCAEFEFDD8FFFFDFFFFFE3FFFF
-                E4FFFFE0F3ECD2BB968EFF00FFFF00FFFF00FFFF00FFFF00FFBC978CFBE7B7F4
-                C791F2C994F8E5B9FEFCD8FFFFDDFFFFDCFFFFE0E2D2BAB68E86FF00FFFF00FF
-                FF00FFFF00FFFF00FFFF00FFD9C3A9FFFEE5F7DCB8F2C994F5D4A5FAE8BDFDF4
-                C9FDFBD6B69089FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB58D85E8
-                DEDDFFFEF2F9D8A3F4C48CF9D49FFDEAB8D0B49FB89086FF00FFFF00FFFF00FF
-                FF00FFFF00FFFF00FFFF00FFFF00FFAD827FC9AA9EEFE0B7EFDFB2E7CEACB890
-                86B89086FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-                00FFFF00FFBA968ABB988CB79188FF00FFFF00FFFF00FFFF00FF}
-              OnClick = sbSearchListerSellerAccountClick
-            end
-            object rbListAccountForPublicSale: TRadioButton
-              Left = 10
-              Top = 20
-              Width = 141
-              Height = 17
-              Caption = 'List account for public sale'
-              TabOrder = 0
-            end
-            object rbListAccountForPrivateSale: TRadioButton
-              Left = 10
-              Top = 40
-              Width = 174
-              Height = 17
-              Caption = 'List account for private sale'
-              TabOrder = 1
-            end
-            object ebSalePrice: TEdit
-              Left = 137
-              Top = 59
-              Width = 86
-              Height = 21
-              TabOrder = 2
-            end
-            object ebSellerAccount: TEdit
-              Left = 378
-              Top = 59
-              Width = 83
-              Height = 21
-              TabOrder = 3
-            end
-            object ebSaleNewOwnerPublicKey: TEdit
-              Left = 137
-              Top = 82
-              Width = 324
-              Height = 21
-              TabOrder = 4
-            end
-            object ebSaleLockedUntilBlock: TEdit
-              Left = 137
-              Top = 106
-              Width = 86
-              Height = 21
-              TabOrder = 5
-            end
+          end
+          object rbListAccountForPrivateSale: TRadioButton
+            Left = 11
+            Top = 51
+            Width = 121
+            Height = 17
+            Caption = 'List for Private Sale'
+            TabOrder = 1
+          end
+          object rbListAccountForAccountSwap: TRadioButton
+            Left = 157
+            Top = 28
+            Width = 159
+            Height = 17
+            Caption = 'List for Atomic Account Swap'
+            TabOrder = 2
+          end
+          object rbListAccountForCoinSwap: TRadioButton
+            Left = 157
+            Top = 51
+            Width = 159
+            Height = 17
+            Caption = 'List for Atomic Coin Swap'
+            TabOrder = 3
+          end
+          object ebPrice: TEdit
+            Left = 96
+            Top = 79
+            Width = 106
+            Height = 21
+            TabOrder = 4
+            TextHint = 'PASC Quantity'
+          end
+          object ebSellerAccount: TEdit
+            Left = 351
+            Top = 79
+            Width = 119
+            Height = 21
+            TabOrder = 5
+            TextHint = 'Account Number'
+          end
+          object ebNewKey: TEdit
+            Left = 96
+            Top = 106
+            Width = 374
+            Height = 21
+            TabOrder = 6
+            TextHint = 'BASE58 Encoded Public Key Of New Owner'
+          end
+          object ebTimeLock: TEdit
+            Left = 96
+            Top = 133
+            Width = 85
+            Height = 21
+            Hint = 'Block Number '
+            ParentShowHint = False
+            ShowHint = False
+            TabOrder = 7
+            TextHint = 'Block number'
+          end
+          object ebHashLock: TEdit
+            Left = 277
+            Top = 133
+            Width = 193
+            Height = 21
+            TabOrder = 8
           end
           end
         end
         end
-        object tsDelist: TTabSheet
-          Caption = 'Delist account'
+        object tsDelistAccount: TTabSheet
+          Caption = 'Delist Account'
           ImageIndex = 3
           ImageIndex = 3
           object lblDelistErrors: TLabel
           object lblDelistErrors: TLabel
             Left = 13
             Left = 13
@@ -686,7 +788,7 @@ object FRMOperation: TFRMOperation
           end
           end
         end
         end
         object tsBuyAccount: TTabSheet
         object tsBuyAccount: TTabSheet
-          Caption = 'Buy account'
+          Caption = 'Buy Account'
           ImageIndex = 4
           ImageIndex = 4
           object lblAccountToBuy: TLabel
           object lblAccountToBuy: TLabel
             Left = 13
             Left = 13
@@ -740,9 +842,9 @@ object FRMOperation: TFRMOperation
           object Label2: TLabel
           object Label2: TLabel
             Left = 204
             Left = 204
             Top = 61
             Top = 61
-            Width = 231
+            Width = 234
             Height = 13
             Height = 13
-            Caption = 'excessive amount will remain on bought account'
+            Caption = 'any over-payment will remain on bought account'
             Color = clBtnFace
             Color = clBtnFace
             Font.Charset = DEFAULT_CHARSET
             Font.Charset = DEFAULT_CHARSET
             Font.Color = clGray
             Font.Color = clGray
@@ -803,14 +905,14 @@ object FRMOperation: TFRMOperation
           object cbBuyNewKey: TComboBox
           object cbBuyNewKey: TComboBox
             Left = 118
             Left = 118
             Top = 85
             Top = 85
-            Width = 294
+            Width = 355
             Height = 21
             Height = 21
             Style = csDropDownList
             Style = csDropDownList
             Sorted = True
             Sorted = True
             TabOrder = 2
             TabOrder = 2
           end
           end
           object bbBuyNewKey: TBitBtn
           object bbBuyNewKey: TBitBtn
-            Left = 418
+            Left = 479
             Top = 84
             Top = 84
             Width = 31
             Width = 31
             Height = 22
             Height = 22
@@ -918,8 +1020,8 @@ object FRMOperation: TFRMOperation
         end
         end
       end
       end
       object ebSignerAccount: TEdit
       object ebSignerAccount: TEdit
-        Left = 325
-        Top = 184
+        Left = 426
+        Top = 217
         Width = 82
         Width = 82
         Height = 21
         Height = 21
         TabOrder = 3
         TabOrder = 3
@@ -928,6 +1030,7 @@ object FRMOperation: TFRMOperation
     object tsGlobalError: TTabSheet
     object tsGlobalError: TTabSheet
       ImageIndex = 1
       ImageIndex = 1
       TabVisible = False
       TabVisible = False
+      ExplicitHeight = 373
       object lblGlobalErrors: TLabel
       object lblGlobalErrors: TLabel
         Left = 40
         Left = 40
         Top = 50
         Top = 50
@@ -1051,8 +1154,8 @@ object FRMOperation: TFRMOperation
     OnKeyPress = ebSenderAccountKeyPress
     OnKeyPress = ebSenderAccountKeyPress
   end
   end
   object ActionList: TActionList
   object ActionList: TActionList
-    Left = 140
-    Top = 350
+    Left = 212
+    Top = 294
     object actExecute: TAction
     object actExecute: TAction
       Caption = 'Execute (F12)'
       Caption = 'Execute (F12)'
       ShortCut = 123
       ShortCut = 123

+ 288 - 109
src/gui-classic/UFRMOperation.pas

@@ -32,8 +32,7 @@ uses
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, UNode, UWallet, UCrypto, Buttons, UBlockChain,
   Dialogs, StdCtrls, UNode, UWallet, UCrypto, Buttons, UBlockChain,
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UFRMMemoText,
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UFRMMemoText,
-  UPCEncryption,
-  UBaseTypes, UPCOrderedLists;
+  UPCEncryption, UBaseTypes, UPCOrderedLists;
 
 
 Const
 Const
   CM_PC_WalletKeysChanged = WM_USER + 1;
   CM_PC_WalletKeysChanged = WM_USER + 1;
@@ -58,7 +57,6 @@ type
     lblChangeInfoErrors: TLabel;
     lblChangeInfoErrors: TLabel;
     PageControlLocked: TPageControl;
     PageControlLocked: TPageControl;
     sbSearchBuyAccount: TSpeedButton;
     sbSearchBuyAccount: TSpeedButton;
-    sbSearchListerSellerAccount: TSpeedButton;
     sbSearchDestinationAccount: TSpeedButton;
     sbSearchDestinationAccount: TSpeedButton;
     sbSearchSignerAccount: TSpeedButton;
     sbSearchSignerAccount: TSpeedButton;
     tsChangeInfo: TTabSheet;
     tsChangeInfo: TTabSheet;
@@ -91,31 +89,9 @@ type
     ebDestAccount: TEdit;
     ebDestAccount: TEdit;
     ebAmount: TEdit;
     ebAmount: TEdit;
     tsChangePrivateKey: TTabSheet;
     tsChangePrivateKey: TTabSheet;
-    gbChangeKey: TGroupBox;
-    lblNewPrivateKey: TLabel;
-    lblNewOwnerPublicKey: TLabel;
-    lblNewOwnerErrors: TLabel;
-    lblChangeKeyErrors: TLabel;
-    rbChangeKeyWithAnother: TRadioButton;
-    cbNewPrivateKey: TComboBox;
-    ebNewPublicKey: TEdit;
-    bbChangePrivateKeyKeys: TBitBtn;
-    rbChangeKeyTransferAccountToNewOwner: TRadioButton;
-    tsListForSale: TTabSheet;
-    gbSaleType: TGroupBox;
-    Label1: TLabel;
-    Label3: TLabel;
-    lblSaleNewOwnerPublicKey: TLabel;
-    lblSaleLockedUntilBlock: TLabel;
-    rbListAccountForPublicSale: TRadioButton;
-    rbListAccountForPrivateSale: TRadioButton;
-    ebSalePrice: TEdit;
-    ebSellerAccount: TEdit;
-    ebSaleNewOwnerPublicKey: TEdit;
-    ebSaleLockedUntilBlock: TEdit;
-    tsDelist: TTabSheet;
+    tsListAccount: TTabSheet;
+    tsDelistAccount: TTabSheet;
     tsBuyAccount: TTabSheet;
     tsBuyAccount: TTabSheet;
-    lblListAccountErrors: TLabel;
     lblAccountToBuy: TLabel;
     lblAccountToBuy: TLabel;
     ebAccountToBuy: TEdit;
     ebAccountToBuy: TEdit;
     lblBuyAmount: TLabel;
     lblBuyAmount: TLabel;
@@ -126,6 +102,34 @@ type
     bbBuyNewKey: TBitBtn;
     bbBuyNewKey: TBitBtn;
     Label2: TLabel;
     Label2: TLabel;
     lblDelistErrors: TLabel;
     lblDelistErrors: TLabel;
+    lblListAccountErrors: TLabel;
+    rbListAccountForPublicSale: TRadioButton;
+    rbListAccountForPrivateSale: TRadioButton;
+    rbListAccountForAccountSwap: TRadioButton;
+    rbListAccountForCoinSwap: TRadioButton;
+    lblPrice: TLabel;
+    ebPrice: TEdit;
+    lblSeller: TLabel;
+    ebSellerAccount: TEdit;
+    sbSearchListerSellerAccount: TSpeedButton;
+    ebNewKey: TEdit;
+    lblNewKey: TLabel;
+    lblTimeLock: TLabel;
+    ebTimeLock: TEdit;
+    rbChangeKeyWithAnother: TRadioButton;
+    lblNewPrivateKey: TLabel;
+    cbNewPrivateKey: TComboBox;
+    lblChangeKeyErrors: TLabel;
+    bbChangePrivateKeyKeys: TBitBtn;
+    lblNewOwnerErrors: TLabel;
+    rbChangeKeyTransferAccountToNewOwner: TRadioButton;
+    lblNewOwnerPublicKey: TLabel;
+    ebNewPublicKey: TEdit;
+    lblHashLock: TLabel;
+    ebHashLock: TEdit;
+    btnHashLock: TSpeedButton;
+    sbTimeLock: TSpeedButton;
+    cbPayloadAsHex: TCheckBox;
     procedure ebNewPublicKeyExit(Sender: TObject);
     procedure ebNewPublicKeyExit(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
@@ -141,6 +145,7 @@ type
     procedure sbSearchDestinationAccountClick(Sender: TObject);
     procedure sbSearchDestinationAccountClick(Sender: TObject);
     procedure sbSearchListerSellerAccountClick(Sender: TObject);
     procedure sbSearchListerSellerAccountClick(Sender: TObject);
     procedure sbSearchSignerAccountClick(Sender: TObject);
     procedure sbSearchSignerAccountClick(Sender: TObject);
+    procedure sbHashLockClick(Sender: TObject);
     procedure updateInfoClick(Sender: TObject);
     procedure updateInfoClick(Sender: TObject);
     procedure bbBuyNewKeyClick(Sender: TObject);
     procedure bbBuyNewKeyClick(Sender: TObject);
     procedure ebAccountNumberExit(Sender: TObject);
     procedure ebAccountNumberExit(Sender: TObject);
@@ -161,7 +166,7 @@ type
     Function UpdatePayload(Const SenderAccount : TAccount; var errors : String) : Boolean;
     Function UpdatePayload(Const SenderAccount : TAccount; var errors : String) : Boolean;
     Function UpdateOpTransaction(Const SenderAccount : TAccount; var DestAccount : TAccount; var amount : Int64; var errors : String) : Boolean;
     Function UpdateOpTransaction(Const SenderAccount : TAccount; var DestAccount : TAccount; var amount : Int64; var errors : String) : Boolean;
     Function UpdateOpChangeKey(Const TargetAccount : TAccount; var SignerAccount : TAccount; var NewPublicKey : TAccountKey; var errors : String) : Boolean;
     Function UpdateOpChangeKey(Const TargetAccount : TAccount; var SignerAccount : TAccount; var NewPublicKey : TAccountKey; var errors : String) : Boolean;
-    Function UpdateOpListForSale(Const TargetAccount : TAccount; var SalePrice : Int64; var SellerAccount,SignerAccount : TAccount; var NewOwnerPublicKey : TAccountKey; var LockedUntilBlock : Cardinal; var errors : String) : Boolean;
+    Function UpdateOpListAccount(Const TargetAccount : TAccount; var SalePrice : Int64; var SellerAccount,SignerAccount : TAccount; var NewOwnerPublicKey : TAccountKey; var LockedUntilBlock : Cardinal; var HashLock : T32Bytes; var errors : String) : Boolean;
     Function UpdateOpDelist(Const TargetAccount : TAccount; var SignerAccount : TAccount; var errors : String) : Boolean;
     Function UpdateOpDelist(Const TargetAccount : TAccount; var SignerAccount : TAccount; var errors : String) : Boolean;
     Function UpdateOpBuyAccount(Const SenderAccount : TAccount; var AccountToBuy : TAccount; var amount : Int64; var NewPublicKey : TAccountKey; var errors : String) : Boolean;
     Function UpdateOpBuyAccount(Const SenderAccount : TAccount; var AccountToBuy : TAccount; var amount : Int64; var NewPublicKey : TAccountKey; var errors : String) : Boolean;
     Function UpdateOpChangeInfo(Const TargetAccount : TAccount; var SignerAccount : TAccount; var changeName : Boolean; var newName : TRawBytes; var changeType : Boolean; var newType : Word; var errors : String) : Boolean;
     Function UpdateOpChangeInfo(Const TargetAccount : TAccount; var SignerAccount : TAccount; var changeName : Boolean; var newName : TRawBytes; var changeType : Boolean; var newType : Word; var errors : String) : Boolean;
@@ -183,8 +188,8 @@ type
 implementation
 implementation
 
 
 uses
 uses
-  UConst, UOpTransaction, UFRMNewPrivateKeyType, UFRMWalletKeys,
-  UCommon, UGUIUtils, UPCDataTypes, ULog;
+  UConst, UOpTransaction, UFRMNewPrivateKeyType, UFRMWalletKeys, UFRMHashLock,
+  UCommon, UPCDataTypes, ULog, UGUIUtils;
 
 
 {$IFnDEF FPC}
 {$IFnDEF FPC}
   {$R *.dfm}
   {$R *.dfm}
@@ -192,28 +197,6 @@ uses
   {$R *.lfm}
   {$R *.lfm}
 {$ENDIF}
 {$ENDIF}
 
 
-Type
-  { Created by Herman Schoenfeld as TArrayTool in v2.0
-    Moved here from UCommon.pas and renamed in order to be Delphi specific (Delphi will no longer use UCommon.pas) }
-  TArrayTool_internal<T> = class
-    public
-      class procedure Swap(var Values : array of T; Item1Index, Item2Index : Integer);
-    end;
-
-{ TArrayTool_internal }
-
-class procedure TArrayTool_internal<T>.Swap(var Values : array of T; Item1Index, Item2Index : Integer);
-var temp : T; len, recSize : Integer; itemSize : Integer;
-begin
-  len := Length(Values);
-  recSize := SizeOf(T);
-  if (Item1Index < 0) OR (Item1Index > len) then Raise Exception.Create('Invalid Parameter: Item1Index out of bounds');
-  if (Item2Index < 0) OR (Item2Index > len) then Raise Exception.Create('Invalid Parameter: Item2Index out of bounds');
-  temp := Values[Item1Index];
-  Values[Item1Index] := Values[Item2Index];
-  Values[Item2Index] := temp;
-end;
-
 { TFRMOperation }
 { TFRMOperation }
 
 
 procedure TFRMOperation.actExecuteExecute(Sender: TObject);
 procedure TFRMOperation.actExecuteExecute(Sender: TObject);
@@ -229,6 +212,7 @@ Var errors : String;
   _lockedUntil, _signer_n_ops : Cardinal;
   _lockedUntil, _signer_n_ops : Cardinal;
   dooperation : Boolean;
   dooperation : Boolean;
   _newOwnerPublicKey : TECDSA_Public;
   _newOwnerPublicKey : TECDSA_Public;
+  LHashLock : T32Bytes;
   _newName : TRawBytes;
   _newName : TRawBytes;
   _newType : Word;
   _newType : Word;
   _changeName, _changeType, _V2, _executeSigner  : Boolean;
   _changeName, _changeType, _V2, _executeSigner  : Boolean;
@@ -295,7 +279,7 @@ loop_start:
         if _V2 then begin
         if _V2 then begin
           // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
           // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
           if (iAcc < Length(_senderAccounts) - 1) AND (account.account = signerAccount.account) then begin
           if (iAcc < Length(_senderAccounts) - 1) AND (account.account = signerAccount.account) then begin
-            TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1); // ensure signer account processed last
+            TArrayTool<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1); // ensure signer account processed last
             goto loop_start; // TODO: remove ugly hack with refactoring!
             goto loop_start; // TODO: remove ugly hack with refactoring!
           end;
           end;
 
 
@@ -312,19 +296,23 @@ loop_start:
         inc(_totalfee,_fee);
         inc(_totalfee,_fee);
         operationstxt := 'Change private key to '+TAccountComp.GetECInfoTxt(_newOwnerPublicKey.EC_OpenSSL_NID);
         operationstxt := 'Change private key to '+TAccountComp.GetECInfoTxt(_newOwnerPublicKey.EC_OpenSSL_NID);
         {%endregion}
         {%endregion}
-      end else if (PageControlOpType.ActivePage = tsListForSale) then begin
+      end else if (PageControlOpType.ActivePage = tsListAccount) then begin
         {%region Operation: List For Sale}
         {%region Operation: List For Sale}
-        If Not UpdateOpListForSale(account,_salePrice,destAccount,signerAccount,_newOwnerPublicKey,_lockedUntil,errors) then raise Exception.Create(errors);
+        If Not UpdateOpListAccount(account,_salePrice,destAccount,signerAccount,_newOwnerPublicKey, _lockedUntil, LHashLock, errors) then raise Exception.Create(errors);
         // Special fee account:
         // Special fee account:
         if signerAccount.balance>DefaultFee then _fee := DefaultFee
         if signerAccount.balance>DefaultFee then _fee := DefaultFee
         else _fee := signerAccount.balance;
         else _fee := signerAccount.balance;
         if (rbListAccountForPublicSale.Checked) then begin
         if (rbListAccountForPublicSale.Checked) then begin
-          op := TOpListAccountForSale.CreateListAccountForSale(FNode.Bank.SafeBox.CurrentProtocol, CT_OpSubtype_ListAccountForPublicSale, signerAccount.account,signerAccount.n_operation+1+iAcc, account.account,_salePrice,_fee,destAccount.account,CT_TECDSA_Public_Nul,0,wk.PrivateKey, CT_HashLock_NUL, FEncodedPayload);
+          op := TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(FNode.Bank.SafeBox.CurrentProtocol, CT_OpSubtype_ListAccountForPublicSale, signerAccount.account,signerAccount.n_operation+1+iAcc, account.account,_salePrice,_fee,destAccount.account,CT_TECDSA_Public_Nul,0,wk.PrivateKey, CT_HashLock_NUL, FEncodedPayload);
         end else if (rbListAccountForPrivateSale.Checked) then begin
         end else if (rbListAccountForPrivateSale.Checked) then begin
-          op := TOpListAccountForSale.CreateListAccountForSale(FNode.Bank.SafeBox.CurrentProtocol, CT_OpSubtype_ListAccountForPrivateSale, signerAccount.account,signerAccount.n_operation+1+iAcc, account.account,_salePrice,_fee,destAccount.account,_newOwnerPublicKey,_lockedUntil,wk.PrivateKey, CT_HashLock_NUL, FEncodedPayload);
+          op := TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(FNode.Bank.SafeBox.CurrentProtocol, CT_OpSubtype_ListAccountForPrivateSale, signerAccount.account,signerAccount.n_operation+1+iAcc, account.account,_salePrice,_fee,destAccount.account,_newOwnerPublicKey,_lockedUntil,wk.PrivateKey, CT_HashLock_NUL, FEncodedPayload);
+        end  else if (rbListAccountForAccountSwap.Checked) then begin
+          op := TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(FNode.Bank.SafeBox.CurrentProtocol, CT_OpSubtype_ListAccountForAccountSwap, signerAccount.account,signerAccount.n_operation+1+iAcc, account.account,_salePrice,_fee,destAccount.account,_newOwnerPublicKey,_lockedUntil,wk.PrivateKey, LHashLock, FEncodedPayload);
+        end  else if (rbListAccountForCoinSwap.Checked) then begin
+          op := TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(FNode.Bank.SafeBox.CurrentProtocol, CT_OpSubtype_ListAccountForCoinSwap, signerAccount.account,signerAccount.n_operation+1+iAcc, account.account,_salePrice,_fee,destAccount.account,_newOwnerPublicKey,_lockedUntil,wk.PrivateKey, LHashLock, FEncodedPayload);
         end else raise Exception.Create('Select Sale type');
         end else raise Exception.Create('Select Sale type');
         {%endregion}
         {%endregion}
-      end else if (PageControlOpType.ActivePage = tsDelist) then begin
+      end else if (PageControlOpType.ActivePage = tsDelistAccount) then begin
         {%region Operation: Delist For Sale}
         {%region Operation: Delist For Sale}
         if Not UpdateOpDelist(account,signerAccount,errors) then raise Exception.Create(errors);
         if Not UpdateOpDelist(account,signerAccount,errors) then raise Exception.Create(errors);
         // Special fee account:
         // Special fee account:
@@ -455,6 +443,7 @@ begin
   end;
   end;
 end;
 end;
 
 
+
 procedure TFRMOperation.CM_WalletChanged(var Msg: TMessage);
 procedure TFRMOperation.CM_WalletChanged(var Msg: TMessage);
 begin
 begin
    UpdateWalletKeys;
    UpdateWalletKeys;
@@ -558,19 +547,21 @@ begin
   lblListAccountErrors.Caption := '';
   lblListAccountErrors.Caption := '';
   rbListAccountForPublicSale.OnClick := updateInfoClick;
   rbListAccountForPublicSale.OnClick := updateInfoClick;
   rbListAccountForPrivateSale.OnClick := updateInfoClick;
   rbListAccountForPrivateSale.OnClick := updateInfoClick;
-  ebSalePrice.Text := TAccountComp.FormatMoney(0);
-  ebSalePrice.OnChange := updateInfoClick;
-  ebSalePrice.OnExit := ebCurrencyExit;
+  rbListAccountForAccountSwap.OnClick := updateInfoClick;
+  rbListAccountForCoinSwap.OnClick := updateInfoClick;
+  ebPrice.Text := TAccountComp.FormatMoney(0);
+  ebPrice.OnChange := updateInfoClick;
+  ebPrice.OnExit := ebCurrencyExit;
 
 
   ebSellerAccount.Text := '';
   ebSellerAccount.Text := '';
   ebSellerAccount.OnChange := updateInfoClick;
   ebSellerAccount.OnChange := updateInfoClick;
   ebSellerAccount.OnExit := ebAccountNumberExit;
   ebSellerAccount.OnExit := ebAccountNumberExit;
   ebSellerAccount.OnKeyDown := ebAccountKeyDown;
   ebSellerAccount.OnKeyDown := ebAccountKeyDown;
   ebSellerAccount.tag := CT_AS_MyAccounts;
   ebSellerAccount.tag := CT_AS_MyAccounts;
-  ebSaleNewOwnerPublicKey.Text := '';
-  ebSaleNewOwnerPublicKey.OnChange := updateInfoClick;
-  ebSaleLockedUntilBlock.Text := '';
-  ebSaleLockedUntilBlock.OnChange := updateInfoClick;
+  ebNewKey.Text := '';
+  ebNewKey.OnChange := updateInfoClick;
+  ebTimeLock.Text := '';
+  ebTimeLock.OnChange := updateInfoClick;
 
 
   //
   //
   lblDelistErrors.Caption := '';
   lblDelistErrors.Caption := '';
@@ -590,6 +581,7 @@ begin
   //
   //
   sbSearchDestinationAccount.OnClick := sbSearchDestinationAccountClick;
   sbSearchDestinationAccount.OnClick := sbSearchDestinationAccountClick;
   sbSearchListerSellerAccount.OnClick := sbSearchListerSellerAccountClick;
   sbSearchListerSellerAccount.OnClick := sbSearchListerSellerAccountClick;
+  btnHashLock.OnClick := sbHashLockClick;
   sbSearchBuyAccount.OnClick := sbSearchBuyAccountClick;
   sbSearchBuyAccount.OnClick := sbSearchBuyAccountClick;
   //
   //
   ebFee.Text := TAccountComp.FormatMoney(0);
   ebFee.Text := TAccountComp.FormatMoney(0);
@@ -709,6 +701,21 @@ begin
   searchAccount(ebSignerAccount);
   searchAccount(ebSignerAccount);
 end;
 end;
 
 
+procedure TFRMOperation.sbHashLockClick(Sender: TObject);
+var
+  LFRM : TFRMHashLock;
+begin
+  LFRM := TFRMHashLock.Create(Self);
+  try
+    case TModalResult(LFRM.ShowModal) of
+      mrOK: ebHashLock.Text := TBaseType.ToRawBytes ( LFRM.HashLock ).ToHexaString;
+    end;
+  finally
+    FreeAndNil(LFRM);
+  end;
+end;
+
+
 procedure TFRMOperation.SetDefaultFee(const Value: Int64);
 procedure TFRMOperation.SetDefaultFee(const Value: Int64);
 var wd : Boolean;
 var wd : Boolean;
 begin
 begin
@@ -794,10 +801,18 @@ begin
   end;
   end;
 end;
 end;
 
 
+var GInUpdateInfoClick : boolean;
 procedure TFRMOperation.updateInfoClick(Sender: TObject);
 procedure TFRMOperation.updateInfoClick(Sender: TObject);
 Var errors : String;
 Var errors : String;
 begin
 begin
-  UpdateOperationOptions(errors);
+  if NOT GInUpdateInfoClick then begin
+    GInUpdateInfoClick := true;
+    try
+      UpdateOperationOptions(errors);
+    finally
+    GInUpdateInfoClick := false;
+    end;
+  end;
 end;
 end;
 
 
 function TFRMOperation.UpdateOpBuyAccount(const SenderAccount: TAccount; var AccountToBuy: TAccount; var amount: Int64; var NewPublicKey: TAccountKey; var errors: String): Boolean;
 function TFRMOperation.UpdateOpBuyAccount(const SenderAccount: TAccount; var AccountToBuy: TAccount; var amount: Int64; var NewPublicKey: TAccountKey; var errors: String): Boolean;
@@ -821,8 +836,8 @@ begin
       exit;
       exit;
     end;
     end;
     AccountToBuy := FNode.GetMempoolAccount(c);
     AccountToBuy := FNode.GetMempoolAccount(c);
-    If not TAccountComp.IsAccountForSale(AccountToBuy.accountInfo) then begin
-      errors := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(c)+' is not for sale';
+    If not TAccountComp.IsAccountForSaleOrSwap(AccountToBuy.accountInfo) then begin
+      errors := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(c)+' is not for sale or swap';
       exit;
       exit;
     end;
     end;
     If Not TAccountComp.TxtToMoney(ebBuyAmount.Text,amount) then begin
     If Not TAccountComp.TxtToMoney(ebBuyAmount.Text,amount) then begin
@@ -833,7 +848,7 @@ begin
       errors := 'Account price '+TAccountComp.FormatMoney(AccountToBuy.accountInfo.price);
       errors := 'Account price '+TAccountComp.FormatMoney(AccountToBuy.accountInfo.price);
       exit;
       exit;
     end;
     end;
-    if (amount+DefaultFee > SenderAccount.balance) then begin
+    if TAccountComp.IsAccountForSale(AccountToBuy.accountInfo) AND (amount+DefaultFee > SenderAccount.balance) then begin
       errors := 'Insufficient funds';
       errors := 'Insufficient funds';
       exit;
       exit;
     end;
     end;
@@ -1008,10 +1023,10 @@ begin
   lblDelistErrors.Caption := '';
   lblDelistErrors.Caption := '';
   errors := '';
   errors := '';
   Result := false;
   Result := false;
-  if not (PageControlOpType.ActivePage=tsDelist) then exit;
+  if not (PageControlOpType.ActivePage=tsDelistAccount) then exit;
   try
   try
-    if Not TAccountComp.IsAccountForSale(TargetAccount.accountInfo) then begin
-      errors := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(TargetAccount.account)+' is not for sale';
+    if Not TAccountComp.IsAccountForSaleOrSwap(TargetAccount.accountInfo) then begin
+      errors := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(TargetAccount.account)+' is not for sale or swap';
       exit;
       exit;
     end;
     end;
     if (TAccountComp.IsAccountLocked(TargetAccount.accountInfo,FNode.Bank.BlocksCount)) then begin
     if (TAccountComp.IsAccountLocked(TargetAccount.accountInfo,FNode.Bank.BlocksCount)) then begin
@@ -1059,6 +1074,7 @@ Var
   e : String;
   e : String;
   sender_account,dest_account,seller_account, account_to_buy, signer_account : TAccount;
   sender_account,dest_account,seller_account, account_to_buy, signer_account : TAccount;
   publicKey : TAccountKey;
   publicKey : TAccountKey;
+  LHashLock : T32Bytes;
   salePrice, amount : Int64;
   salePrice, amount : Int64;
   auxC : Cardinal;
   auxC : Cardinal;
   changeName,changeType : Boolean;
   changeName,changeType : Boolean;
@@ -1125,9 +1141,9 @@ begin
     Result := UpdateOpTransaction(GetDefaultSenderAccount,dest_account,amount,errors);
     Result := UpdateOpTransaction(GetDefaultSenderAccount,dest_account,amount,errors);
   end else if (PageControlOpType.ActivePage = tsChangePrivateKey) then begin
   end else if (PageControlOpType.ActivePage = tsChangePrivateKey) then begin
     Result := UpdateOpChangeKey(GetDefaultSenderAccount,signer_account,publicKey,errors);
     Result := UpdateOpChangeKey(GetDefaultSenderAccount,signer_account,publicKey,errors);
-  end else if (PageControlOpType.ActivePage = tsListForSale) then begin
-    Result := UpdateOpListForSale(GetDefaultSenderAccount,salePrice,seller_account,signer_account,publicKey,auxC,errors);
-  end else if (PageControlOpType.ActivePage = tsDelist) then begin
+  end else if (PageControlOpType.ActivePage = tsListAccount) then begin
+    Result := UpdateOpListAccount(GetDefaultSenderAccount,salePrice,seller_account,signer_account,publicKey,auxC,LHashLock,errors);
+  end else if (PageControlOpType.ActivePage = tsDelistAccount) then begin
     Result := UpdateOpDelist(GetDefaultSenderAccount,signer_account,errors);
     Result := UpdateOpDelist(GetDefaultSenderAccount,signer_account,errors);
   end else if (PageControlOpType.ActivePage = tsBuyAccount) then begin
   end else if (PageControlOpType.ActivePage = tsBuyAccount) then begin
     Result := UpdateOpBuyAccount(GetDefaultSenderAccount,account_to_buy,amount,publicKey,errors);
     Result := UpdateOpBuyAccount(GetDefaultSenderAccount,account_to_buy,amount,publicKey,errors);
@@ -1142,7 +1158,7 @@ begin
   end else if (PageControlOpType.ActivePage=tsChangePrivateKey) then begin
   end else if (PageControlOpType.ActivePage=tsChangePrivateKey) then begin
     rbEncryptedWithOldEC.Caption := 'Encrypted with old public key';
     rbEncryptedWithOldEC.Caption := 'Encrypted with old public key';
     rbEncryptedWithEC.Caption := 'Encrypted with new public key';
     rbEncryptedWithEC.Caption := 'Encrypted with new public key';
-  end else if ((PageControlOpType.ActivePage=tsListForSale) Or (PageControlOpType.ActivePage=tsDelist)) then begin
+  end else if ((PageControlOpType.ActivePage=tsListAccount) Or (PageControlOpType.ActivePage=tsDelistAccount)) then begin
     rbEncryptedWithOldEC.Caption := 'Encrypted with target public key';
     rbEncryptedWithOldEC.Caption := 'Encrypted with target public key';
     rbEncryptedWithEC.Caption := 'Encrypted with signer public key';
     rbEncryptedWithEC.Caption := 'Encrypted with signer public key';
   end else if (PageControlOpType.ActivePage=tsBuyAccount) then begin
   end else if (PageControlOpType.ActivePage=tsBuyAccount) then begin
@@ -1151,8 +1167,8 @@ begin
   end;
   end;
   ebSignerAccount.Enabled:= ((PageControlOpType.ActivePage=tsChangePrivateKey) And (FNode.Bank.SafeBox.CurrentProtocol>=CT_PROTOCOL_2))
   ebSignerAccount.Enabled:= ((PageControlOpType.ActivePage=tsChangePrivateKey) And (FNode.Bank.SafeBox.CurrentProtocol>=CT_PROTOCOL_2))
     Or ((PageControlOpType.ActivePage=tsChangeInfo) And (SenderAccounts.Count=1))
     Or ((PageControlOpType.ActivePage=tsChangeInfo) And (SenderAccounts.Count=1))
-    Or (PageControlOpType.ActivePage=tsListForSale)
-    Or (PageControlOpType.ActivePage=tsDelist);
+    Or (PageControlOpType.ActivePage=tsListAccount)
+    Or (PageControlOpType.ActivePage=tsDelistAccount);
   sbSearchSignerAccount.Enabled:=ebSignerAccount.Enabled;
   sbSearchSignerAccount.Enabled:=ebSignerAccount.Enabled;
   lblSignerAccount.Enabled := ebSignerAccount.Enabled;
   lblSignerAccount.Enabled := ebSignerAccount.Enabled;
   lblChangeName.Enabled:= (PageControlOpType.ActivePage=tsChangeInfo) And (SenderAccounts.Count=1);
   lblChangeName.Enabled:= (PageControlOpType.ActivePage=tsChangeInfo) And (SenderAccounts.Count=1);
@@ -1161,32 +1177,54 @@ begin
   UpdatePayload(sender_account, e);
   UpdatePayload(sender_account, e);
 end;
 end;
 
 
-function TFRMOperation.UpdateOpListForSale(const TargetAccount: TAccount;
+function TFRMOperation.UpdateOpListAccount(const TargetAccount: TAccount;
   var SalePrice: Int64; var SellerAccount, SignerAccount: TAccount;
   var SalePrice: Int64; var SellerAccount, SignerAccount: TAccount;
   var NewOwnerPublicKey: TAccountKey; var LockedUntilBlock: Cardinal;
   var NewOwnerPublicKey: TAccountKey; var LockedUntilBlock: Cardinal;
-  var errors: String): Boolean;
-var auxC : Cardinal;
+  var HashLock : T32Bytes; var errors: String): Boolean;
+var auxC : Cardinal; LBytes : TBytes;
 begin
 begin
   Result := False;
   Result := False;
   SalePrice := 0; SellerAccount := CT_Account_NUL;
   SalePrice := 0; SellerAccount := CT_Account_NUL;
   NewOwnerPublicKey := CT_TECDSA_Public_Nul;
   NewOwnerPublicKey := CT_TECDSA_Public_Nul;
   LockedUntilBlock := 0; errors := '';
   LockedUntilBlock := 0; errors := '';
-  if (PageControlOpType.ActivePage <> tsListForSale) then exit;
+  if (PageControlOpType.ActivePage <> tsListAccount) then exit;
   lblListAccountErrors.Caption := '';
   lblListAccountErrors.Caption := '';
   Try
   Try
     if (rbListAccountForPublicSale.Checked) Or (rbListAccountForPrivateSale.Checked) then begin
     if (rbListAccountForPublicSale.Checked) Or (rbListAccountForPrivateSale.Checked) then begin
+      {%region 'List Account Options'}
+      lblPrice.Visible := true;
+      lblPrice.Caption := 'Sale Price';
+      lblPrice.Enabled := true;
+      ebPrice.Visible := true;
+      ebPrice.Enabled := true;
+      lblNewKey.Visible := true;
+      lblNewKey.Enabled := true;
+      lblNewKey.Caption := 'Buyer Key';
+      ebNewKey.Visible := true;
+      ebNewKey.Enabled := true;
+      lblSeller.Visible := true;
+      lblSeller.Caption := 'Seller Account';
+      ebSellerAccount.Visible := true;
+      sbSearchListerSellerAccount.Visible := true;
+      lblTimeLock.Visible := true;
+      ebTimeLock.Visible := true;
+      sbTimeLock.Visible := true;
+      lblHashLock.Visible := false;
+      ebHashLock.Visible := false;
+      btnHashLock.Visible := false;
+      btnHashLock.Enabled := false;
       if rbListAccountForPublicSale.Checked then begin
       if rbListAccountForPublicSale.Checked then begin
-        lblSaleNewOwnerPublicKey.Enabled := false;
-        ebSaleNewOwnerPublicKey.Enabled := false;
-        ebSaleLockedUntilBlock.Enabled := false;
-        lblSaleLockedUntilBlock.Enabled := false;
+        lblNewKey.Enabled := false;
+        ebNewKey.Enabled := false;
+        ebTimeLock.Enabled := false;
+        lblTimeLock.Enabled := false;
       end else if rbListAccountForPrivateSale.Checked then begin
       end else if rbListAccountForPrivateSale.Checked then begin
-        lblSaleNewOwnerPublicKey.Enabled := true;
-        ebSaleNewOwnerPublicKey.Enabled := true;
-        ebSaleLockedUntilBlock.Enabled := true;
-        lblSaleLockedUntilBlock.Enabled := true;
+        lblNewKey.Enabled := true;
+        ebNewKey.Enabled := true;
+        ebTimeLock.Enabled := true;
+        lblTimeLock.Enabled := true;
       end;
       end;
-      if not TAccountComp.TxtToMoney(ebSalePrice.Text,salePrice) then begin
+      if not TAccountComp.TxtToMoney(ebPrice.Text,salePrice) then begin
         errors := 'Invalid price';
         errors := 'Invalid price';
         exit;
         exit;
       end;
       end;
@@ -1216,11 +1254,13 @@ begin
 
 
       SellerAccount := FNode.GetMempoolAccount(auxC);
       SellerAccount := FNode.GetMempoolAccount(auxC);
       if rbListAccountForPrivateSale.Checked then begin
       if rbListAccountForPrivateSale.Checked then begin
-        lblSaleNewOwnerPublicKey.Enabled := true;
-        ebSaleNewOwnerPublicKey.Enabled := true;
-        ebSaleLockedUntilBlock.Enabled := true;
-        lblSaleLockedUntilBlock.Enabled := true;
-        If Not TAccountComp.AccountKeyFromImport(ebSaleNewOwnerPublicKey.Text,NewOwnerPublicKey,errors) then begin
+        lblNewKey.Visible := true;
+        lblNewKey.Enabled := true;
+        ebNewKey.Visible := true;
+        ebNewKey.Enabled := true;
+        ebTimeLock.Enabled := true;
+        lblTimeLock.Enabled := true;
+        If Not TAccountComp.AccountKeyFromImport(ebNewKey.Text,NewOwnerPublicKey,errors) then begin
           errors := 'Public key: '+errors;
           errors := 'Public key: '+errors;
           exit;
           exit;
         end else begin
         end else begin
@@ -1231,7 +1271,7 @@ begin
           errors := 'New public key for private sale is the same public key';
           errors := 'New public key for private sale is the same public key';
           Exit;
           Exit;
         end;
         end;
-        LockedUntilBlock := StrToIntDef(ebSaleLockedUntilBlock.Text,0);
+        LockedUntilBlock := StrToIntDef(ebTimeLock.Text,0);
         if LockedUntilBlock=0 then begin
         if LockedUntilBlock=0 then begin
           errors := 'Insert locking block';
           errors := 'Insert locking block';
           exit;
           exit;
@@ -1241,11 +1281,141 @@ begin
         errors := 'This operation needs PROTOCOL 2 active';
         errors := 'This operation needs PROTOCOL 2 active';
         exit;
         exit;
       end;
       end;
+    {%endregion}
+    end else if (rbListAccountForAccountSwap.Checked) Or (rbListAccountForCoinSwap.Checked) then begin
+      {%region 'Atomic Swap Options'}
+      lblPrice.Visible := true;
+      ebPrice.Visible := true;
+      lblNewKey.Visible := true;
+      ebNewKey.Visible := true;
+      lblTimeLock.Visible := true;
+      ebTimeLock.Visible := true;
+      sbTimeLock.Enabled := true;
+      lblHashLock.Visible := true;
+      ebHashLock.Visible := true;
+      btnHashLock.Visible := true;
+      btnHashLock.Enabled := true;
+
+      if rbListAccountForAccountSwap.Checked then begin
+        lblSeller.Visible := False;
+        ebSellerAccount.Visible := False;
+        sbSearchListerSellerAccount.Visible := false;
+        lblNewKey.Caption := 'Counterparty Key';
+        lblNewKey.Visible := true;
+        lblNewKey.Enabled := true;
+        ebNewKey.Visible := true;
+        ebNewKey.Enabled := true;
+        lblPrice.Enabled := false;
+        ebPrice.Enabled := false;
+        ebPrice.Text := 'ALL BALANCE';
+      end else if rbListAccountForCoinSwap.Checked then begin
+        lblSeller.Visible := true;
+        lblSeller.Caption := 'Counterparty Account';
+        ebSellerAccount.Visible := true;
+        sbSearchListerSellerAccount.Visible := true;
+        lblNewKey.Visible := false;
+        ebNewKey.Visible := false;
+        lblPrice.Caption := 'Swap Amount';
+        lblPrice.Enabled := true;
+        ebPrice.Enabled := true;
+      end;
+
+      // COMMON SWAP VALDATION
+      // V5 Check
+      If (FNode.Bank.SafeBox.CurrentProtocol<CT_PROTOCOL_5) then begin
+        errors := 'This operation needs PROTOCOL 5 or greater';
+        exit;
+      end;
+
+      // Signer
+      If Not TAccountComp.AccountTxtNumberToAccountNumber(ebSignerAccount.Text,auxC) then begin
+        errors := 'Invalid signer account';
+        exit;
+      end;
+      if (auxC<0) Or (auxC >= FNode.Bank.AccountsCount) then begin
+        errors := 'Signer account does not exists '+TAccountComp.AccountNumberToAccountTxtNumber(auxC);
+        exit;
+      end;
+      SignerAccount := FNode.GetMempoolAccount(auxC);
+
+      // Time-Lock
+      LockedUntilBlock := StrToIntDef(ebTimeLock.Text,0);
+      if LockedUntilBlock=0 then begin
+        errors := 'Insert locking block';
+        exit;
+      end;
+
+      // Hash-Lock
+      HashLock := CT_HashLock_NUL;
+      if (NOT TCrypto.HexaToRaw(ebHashLock.Text, LBytes)) OR (Length(LBytes) <> 32) then begin
+        errors := 'Hash-Lock is required (32byte hexstring)';
+        exit;
+      end;
+      HashLock := TBaseType.To32Bytes(LBytes);
+
+      // Account Swap Validation
+      if rbListAccountForAccountSwap.Checked then begin
+        // Sale price is 0
+        SalePrice := 0;
+
+        // Counterparty key
+        If Not TAccountComp.AccountKeyFromImport(ebNewKey.Text,NewOwnerPublicKey,errors) then begin
+          errors := 'Counterparty Key: '+errors;
+          exit;
+        end else begin
+          lblListAccountErrors.Font.Color := clGreen;
+          lblListAccountErrors.Caption := 'New key type: '+TAccountComp.GetECInfoTxt(NewOwnerPublicKey.EC_OpenSSL_NID);
+        end;
+        if TAccountComp.EqualAccountKeys(NewOwnerPublicKey,TargetAccount.accountInfo.accountKey) then begin
+          errors := 'New public key for private sale is the same public key';
+          Exit;
+        end;
+
+        // Seller account is target account (but price is 0, never receives)
+        SellerAccount := TargetAccount;
+      end else if (rbListAccountForCoinSwap.Checked) then begin
+        // Coin Swap Validation
+        // Price
+        IF NOT TAccountComp.TxtToMoney(ebPrice.Text,salePrice) then begin
+          errors := 'Invalid swap amount';
+          exit;
+        end;
+
+        // Counterparty Account (Seller variable)
+        If Not TAccountComp.AccountTxtNumberToAccountNumber(ebSellerAccount.Text,auxC) then begin
+          errors := 'Invalid counterparty account';
+          exit;
+        end;
+        if (auxC<0) Or (auxC >= FNode.Bank.AccountsCount) then begin
+          errors := 'Counterparty account does not exists '+TAccountComp.AccountNumberToAccountTxtNumber(auxC);
+          exit;
+        end;
+        if (auxC=TargetAccount.account) then begin
+          errors := 'Counterparty account cannot be same account';
+          exit;
+        end;
+        SellerAccount := FNode.GetMempoolAccount(auxC);
+
+        // New Owner Public Key is the same public key
+        NewOwnerPublicKey := TargetAccount.accountInfo.accountKey;
+      end;
+
+    {%endregion}
     end else begin
     end else begin
-      lblSaleNewOwnerPublicKey.Enabled := false;
-      ebSaleNewOwnerPublicKey.Enabled := false;
-      ebSaleLockedUntilBlock.Enabled := false;
-      lblSaleLockedUntilBlock.Enabled := false;
+      lblPrice.Visible := false;
+      ebPrice.Visible := false;
+      lblNewKey.Visible := false;
+      ebNewKey.Visible := false;
+      lblSeller.Visible := false;
+      ebSellerAccount.Visible := false;
+      sbSearchListerSellerAccount.Visible := false;
+      lblTimeLock.Visible := false;
+      ebTimeLock.Visible := false;
+      sbTimeLock.Visible := false;
+      lblHashLock.Visible := false;
+      ebHashLock.Visible := false;
+      btnHashLock.Visible := false;
+      btnHashLock.Enabled := false;
       errors := 'Select a sale type';
       errors := 'Select a sale type';
       exit;
       exit;
     end;
     end;
@@ -1308,6 +1478,7 @@ Var payload_u : AnsiString;
   i : Integer;
   i : Integer;
   valid : Boolean;
   valid : Boolean;
   wk : TWalletKey;
   wk : TWalletKey;
+  LPayloadBytes : TRawBytes;
 begin
 begin
   valid := false;
   valid := false;
   payload_encrypted := Nil;
   payload_encrypted := Nil;
@@ -1319,15 +1490,23 @@ begin
       valid := true;
       valid := true;
       exit;
       exit;
     end;
     end;
+    if cbPayloadAsHex.Checked then begin
+      if NOT TCrypto.HexaToRaw(payload_u, LPayloadBytes) then begin
+        valid := false;
+        errors := 'Payload not hex-formatted';
+        exit;
+      end;
+    end else LPayloadBytes := TEncoding.ANSI.GetBytes(payload_u);
+
     if (rbEncryptedWithOldEC.Checked) then begin
     if (rbEncryptedWithOldEC.Checked) then begin
       // Use sender
       // Use sender
       errors := 'Error encrypting';
       errors := 'Error encrypting';
       account := FNode.GetMempoolAccount(SenderAccount.account);
       account := FNode.GetMempoolAccount(SenderAccount.account);
-      TPCEncryption.DoPascalCoinECIESEncrypt(account.accountInfo.accountKey,TEncoding.ANSI.GetBytes(payload_u),payload_encrypted);
+      TPCEncryption.DoPascalCoinECIESEncrypt(account.accountInfo.accountKey,LPayloadBytes,payload_encrypted);
       valid := Length(payload_encrypted)>0;
       valid := Length(payload_encrypted)>0;
     end else if (rbEncryptedWithEC.Checked) then begin
     end else if (rbEncryptedWithEC.Checked) then begin
       errors := 'Error encrypting';
       errors := 'Error encrypting';
-      if (PageControlOpType.ActivePage=tsTransaction) or (PageControlOpType.ActivePage=tsListForSale) or (PageControlOpType.ActivePage=tsDelist)
+      if (PageControlOpType.ActivePage=tsTransaction) or (PageControlOpType.ActivePage=tsListAccount) or (PageControlOpType.ActivePage=tsDelistAccount)
         or (PageControlOpType.ActivePage=tsBuyAccount) then begin
         or (PageControlOpType.ActivePage=tsBuyAccount) then begin
         // With dest public key
         // With dest public key
         If (PageControlOpType.ActivePage=tsTransaction) then begin
         If (PageControlOpType.ActivePage=tsTransaction) then begin
@@ -1335,12 +1514,12 @@ begin
             errors := 'Invalid dest account number';
             errors := 'Invalid dest account number';
             exit;
             exit;
           end;
           end;
-        end else if (PageControlOpType.ActivePage=tsListForSale) then begin
+        end else if (PageControlOpType.ActivePage=tsListAccount) then begin
           If Not TAccountComp.AccountTxtNumberToAccountNumber(ebSignerAccount.Text,dest_account_number) then begin
           If Not TAccountComp.AccountTxtNumberToAccountNumber(ebSignerAccount.Text,dest_account_number) then begin
             errors := 'Invalid signer account number';
             errors := 'Invalid signer account number';
             exit;
             exit;
           end;
           end;
-        end else if (PageControlOpType.ActivePage=tsDelist) then begin
+        end else if (PageControlOpType.ActivePage=tsDelistAccount) then begin
           If Not TAccountComp.AccountTxtNumberToAccountNumber(ebSignerAccount.Text,dest_account_number) then begin
           If Not TAccountComp.AccountTxtNumberToAccountNumber(ebSignerAccount.Text,dest_account_number) then begin
             errors := 'Invalid signer account number';
             errors := 'Invalid signer account number';
             exit;
             exit;
@@ -1359,7 +1538,7 @@ begin
           exit;
           exit;
         end;
         end;
         account := FNode.GetMempoolAccount(dest_account_number);
         account := FNode.GetMempoolAccount(dest_account_number);
-        TPCEncryption.DoPascalCoinECIESEncrypt(account.accountInfo.accountKey,TEncoding.ANSI.GetBytes(payload_u),payload_encrypted);
+        TPCEncryption.DoPascalCoinECIESEncrypt(account.accountInfo.accountKey,LPayloadBytes,payload_encrypted);
         valid := Length(payload_encrypted)>0;
         valid := Length(payload_encrypted)>0;
       end else if (PageControlOpType.ActivePage=tsChangePrivateKey) then begin
       end else if (PageControlOpType.ActivePage=tsChangePrivateKey) then begin
         if (rbChangeKeyWithAnother.Checked) then begin
         if (rbChangeKeyWithAnother.Checked) then begin
@@ -1381,7 +1560,7 @@ begin
           exit;
           exit;
         end;
         end;
         if public_key.EC_OpenSSL_NID<>CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then begin
         if public_key.EC_OpenSSL_NID<>CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then begin
-          TPCEncryption.DoPascalCoinECIESEncrypt(public_key,TEncoding.ANSI.GetBytes(payload_u),payload_encrypted);
+          TPCEncryption.DoPascalCoinECIESEncrypt(public_key,LPayloadBytes,payload_encrypted);
           valid := Length(payload_encrypted)>0;
           valid := Length(payload_encrypted)>0;
         end else begin
         end else begin
           valid := false;
           valid := false;
@@ -1392,10 +1571,10 @@ begin
         errors := 'This operation does not allow this kind of payload';
         errors := 'This operation does not allow this kind of payload';
       end;
       end;
     end else if (rbEncrptedWithPassword.Checked) then begin
     end else if (rbEncrptedWithPassword.Checked) then begin
-      payload_encrypted := TPCEncryption.DoPascalCoinAESEncrypt(TEncoding.ANSI.GetBytes(payload_u),TEncoding.ANSI.GetBytes(ebEncryptPassword.Text));
+      payload_encrypted := TPCEncryption.DoPascalCoinAESEncrypt(LPayloadBytes,TEncoding.ANSI.GetBytes(ebEncryptPassword.Text));
       valid := Length(payload_encrypted)>0;
       valid := Length(payload_encrypted)>0;
     end else if (rbNotEncrypted.Checked) then begin
     end else if (rbNotEncrypted.Checked) then begin
-      payload_encrypted := TEncoding.ANSI.GetBytes(payload_u);
+      payload_encrypted := LPayloadBytes;
       valid := true;
       valid := true;
     end else begin
     end else begin
       errors := 'Must select an encryption option for payload';
       errors := 'Must select an encryption option for payload';

+ 15 - 14
src/gui-classic/UFRMPayloadDecoder.dfm

@@ -3,9 +3,9 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
   Top = 0
   Top = 0
   ActiveControl = ebOphash
   ActiveControl = ebOphash
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
-  BorderStyle = bsSingle
+  BorderStyle = bsToolWindow
   Caption = 'Operation Information/Decoder'
   Caption = 'Operation Information/Decoder'
-  ClientHeight = 406
+  ClientHeight = 458
   ClientWidth = 691
   ClientWidth = 691
   Color = clBtnFace
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Charset = DEFAULT_CHARSET
@@ -68,13 +68,13 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
   object lblOperationTxt: TLabel
   object lblOperationTxt: TLabel
     Left = 90
     Left = 90
     Top = 101
     Top = 101
-    Width = 561
-    Height = 22
+    Width = 579
+    Height = 68
     AutoSize = False
     AutoSize = False
     Caption = '000'
     Caption = '000'
     Font.Charset = DEFAULT_CHARSET
     Font.Charset = DEFAULT_CHARSET
     Font.Color = clBlack
     Font.Color = clBlack
-    Font.Height = -16
+    Font.Height = -13
     Font.Name = 'Tahoma'
     Font.Name = 'Tahoma'
     Font.Style = [fsBold]
     Font.Style = [fsBold]
     ParentFont = False
     ParentFont = False
@@ -182,15 +182,16 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
   end
   end
   object PageControl: TPageControl
   object PageControl: TPageControl
     Left = 20
     Left = 20
-    Top = 140
+    Top = 191
     Width = 653
     Width = 653
-    Height = 206
-    ActivePage = tsDecoded
+    Height = 202
+    ActivePage = tsDecodeMethods
     TabOrder = 2
     TabOrder = 2
     OnChanging = PageControlChanging
     OnChanging = PageControlChanging
     object tsDecoded: TTabSheet
     object tsDecoded: TTabSheet
       Caption = 'Payload'
       Caption = 'Payload'
-      ExplicitWidth = 623
+      ExplicitLeft = 0
+      ExplicitHeight = 178
       object Label7: TLabel
       object Label7: TLabel
         Left = 15
         Left = 15
         Top = 94
         Top = 94
@@ -269,10 +270,10 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
     object tsDecodeMethods: TTabSheet
     object tsDecodeMethods: TTabSheet
       Caption = 'Decode methods'
       Caption = 'Decode methods'
       ImageIndex = 1
       ImageIndex = 1
-      ExplicitWidth = 623
+      ExplicitHeight = 161
       object lblPasswordsInfo: TLabel
       object lblPasswordsInfo: TLabel
         Left = 235
         Left = 235
-        Top = 162
+        Top = 143
         Width = 81
         Width = 81
         Height = 13
         Height = 13
         Caption = 'lblPasswordsInfo'
         Caption = 'lblPasswordsInfo'
@@ -308,7 +309,7 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
         Left = 235
         Left = 235
         Top = 10
         Top = 10
         Width = 390
         Width = 390
-        Height = 146
+        Height = 127
         ScrollBars = ssBoth
         ScrollBars = ssBoth
         TabOrder = 3
         TabOrder = 3
         OnChange = cbMethodPublicPayloadClick
         OnChange = cbMethodPublicPayloadClick
@@ -343,8 +344,8 @@ object FRMPayloadDecoder: TFRMPayloadDecoder
     end
     end
   end
   end
   object bbClose: TBitBtn
   object bbClose: TBitBtn
-    Left = 572
-    Top = 362
+    Left = 560
+    Top = 413
     Width = 97
     Width = 97
     Height = 25
     Height = 25
     Cancel = True
     Cancel = True

+ 16 - 0
src/gui-classic/UFRMWallet.dfm

@@ -671,6 +671,10 @@ object FRMWallet: TFRMWallet
         object tsMultiSelectAccounts: TTabSheet
         object tsMultiSelectAccounts: TTabSheet
           Caption = 'Selected Accounts For Batch Operation'
           Caption = 'Selected Accounts For Batch Operation'
           ImageIndex = 1
           ImageIndex = 1
+          ExplicitLeft = 0
+          ExplicitTop = 0
+          ExplicitWidth = 0
+          ExplicitHeight = 0
           object dgSelectedAccounts: TDrawGrid
           object dgSelectedAccounts: TDrawGrid
             Left = 41
             Left = 41
             Top = 31
             Top = 31
@@ -862,6 +866,10 @@ object FRMWallet: TFRMWallet
     object tsPendingOperations: TTabSheet
     object tsPendingOperations: TTabSheet
       Caption = 'Pending Operations'
       Caption = 'Pending Operations'
       ImageIndex = 5
       ImageIndex = 5
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object dgPendingOperations: TDrawGrid
       object dgPendingOperations: TDrawGrid
         Left = 0
         Left = 0
         Top = 86
         Top = 86
@@ -1000,6 +1008,10 @@ object FRMWallet: TFRMWallet
     object tsOperations: TTabSheet
     object tsOperations: TTabSheet
       Caption = 'Operations Explorer'
       Caption = 'Operations Explorer'
       ImageIndex = 1
       ImageIndex = 1
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object Panel1: TPanel
       object Panel1: TPanel
         Left = 0
         Left = 0
         Top = 0
         Top = 0
@@ -1048,6 +1060,10 @@ object FRMWallet: TFRMWallet
     object tsLogs: TTabSheet
     object tsLogs: TTabSheet
       Caption = 'Logs'
       Caption = 'Logs'
       ImageIndex = 2
       ImageIndex = 2
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
       object pnlTopLogs: TPanel
       object pnlTopLogs: TPanel
         Left = 0
         Left = 0
         Top = 0
         Top = 0

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

@@ -385,12 +385,12 @@ begin
   TNode.Node.NetServer.Active := true;
   TNode.Node.NetServer.Active := true;
   FLastTC := 0;
   FLastTC := 0;
   FLastMsg := '';
   FLastMsg := '';
-  if (TNode.Node.Bank.BlocksCount<=1) then begin
+{  if (TNode.Node.Bank.BlocksCount<=1) then begin
     while (Not Terminated) And (Not TNode.Node.IsReady(currentProcess) Or (TNode.Node.Bank.BlocksCount<=1)) do begin
     while (Not Terminated) And (Not TNode.Node.IsReady(currentProcess) Or (TNode.Node.Bank.BlocksCount<=1)) do begin
       Synchronize(ThreadSafeNotify);
       Synchronize(ThreadSafeNotify);
       Sleep(200);
       Sleep(200);
     end;
     end;
-  end;
+  end;}
   if Not Terminated then begin
   if Not Terminated then begin
     Synchronize( FRMWallet.DoUpdateAccounts );
     Synchronize( FRMWallet.DoUpdateAccounts );
     Synchronize( FRMWallet.FinishedLoadingApp );
     Synchronize( FRMWallet.FinishedLoadingApp );

+ 0 - 1
src/gui-classic/UGUIUtils.pas

@@ -11,7 +11,6 @@ uses
 
 
 function InputQueryPassword(ACaption, APrompt : String; var defValue : String) : Boolean;
 function InputQueryPassword(ACaption, APrompt : String; var defValue : String) : Boolean;
 
 
-
 implementation
 implementation
 
 
 function InputQueryPassword(ACaption, APrompt : String; var defValue : String) : Boolean;
 function InputQueryPassword(ACaption, APrompt : String; var defValue : String) : Boolean;

+ 10 - 3
src/pascalcoin_miner.lpi

@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
   <ProjectOptions>
   <ProjectOptions>
-    <Version Value="10"/>
+    <Version Value="12"/>
     <PathDelim Value="\"/>
     <PathDelim Value="\"/>
     <General>
     <General>
       <Flags>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
+        <CompatibilityMode Value="True"/>
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="PascalCoinMiner"/>
       <Title Value="PascalCoinMiner"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
@@ -25,9 +25,16 @@
     </PublishOptions>
     </PublishOptions>
     <RunParams>
     <RunParams>
       <local>
       <local>
-        <FormatVersion Value="1"/>
         <CommandLineParams Value="-c 1 -s -n TEST"/>
         <CommandLineParams Value="-c 1 -s -n TEST"/>
       </local>
       </local>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default">
+          <local>
+            <CommandLineParams Value="-c 1 -s -n TEST"/>
+          </local>
+        </Mode0>
+      </Modes>
     </RunParams>
     </RunParams>
     <RequiredPackages Count="1">
     <RequiredPackages Count="1">
       <Item1>
       <Item1>

+ 3 - 4
src/pascalcoin_wallet_classic.dpr

@@ -17,9 +17,7 @@ uses
   UAccounts in 'core\UAccounts.pas',
   UAccounts in 'core\UAccounts.pas',
   {$IFDEF Use_OpenSSL}
   {$IFDEF Use_OpenSSL}
   UAES in 'core\UAES.pas',
   UAES in 'core\UAES.pas',
-  UECIES in 'core\UECIES.pas',
-  UOpenSSL in 'core\UOpenSSL.pas',
-  {$ENDIF}
+  {$ENDIF }
   UBaseTypes in 'core\UBaseTypes.pas',
   UBaseTypes in 'core\UBaseTypes.pas',
   UBlockChain in 'core\UBlockChain.pas',
   UBlockChain in 'core\UBlockChain.pas',
   UChunk in 'core\UChunk.pas',
   UChunk in 'core\UChunk.pas',
@@ -60,7 +58,8 @@ uses
   UPCDataTypes in 'core\UPCDataTypes.pas',
   UPCDataTypes in 'core\UPCDataTypes.pas',
   UPCOrderedLists in 'core\UPCOrderedLists.pas',
   UPCOrderedLists in 'core\UPCOrderedLists.pas',
   UPCOperationsSignatureValidator in 'core\UPCOperationsSignatureValidator.pas',
   UPCOperationsSignatureValidator in 'core\UPCOperationsSignatureValidator.pas',
-  UPCTNetDataExtraMessages in 'core\UPCTNetDataExtraMessages.pas';
+  UPCTNetDataExtraMessages in 'core\UPCTNetDataExtraMessages.pas',
+  UFRMHashLock in 'gui-classic\UFRMHashLock.pas' {FRMHashLock};
 
 
 {$R *.res}
 {$R *.res}
 
 

+ 89 - 12
src/pascalcoin_wallet_classic.dproj

@@ -4,10 +4,10 @@
         <MainSource>pascalcoin_wallet_classic.dpr</MainSource>
         <MainSource>pascalcoin_wallet_classic.dpr</MainSource>
         <Base>True</Base>
         <Base>True</Base>
         <Config Condition="'$(Config)'==''">Debug</Config>
         <Config Condition="'$(Config)'==''">Debug</Config>
-        <TargetedPlatforms>1153</TargetedPlatforms>
+        <TargetedPlatforms>1025</TargetedPlatforms>
         <AppType>Application</AppType>
         <AppType>Application</AppType>
         <FrameworkType>VCL</FrameworkType>
         <FrameworkType>VCL</FrameworkType>
-        <ProjectVersion>18.4</ProjectVersion>
+        <ProjectVersion>18.6</ProjectVersion>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
     </PropertyGroup>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
     <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@@ -34,6 +34,12 @@
         <Cfg_1>true</Cfg_1>
         <Cfg_1>true</Cfg_1>
         <Base>true</Base>
         <Base>true</Base>
     </PropertyGroup>
     </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
+        <Cfg_1_Win64>true</Cfg_1_Win64>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
     <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
     <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
         <Cfg_2>true</Cfg_2>
         <Cfg_2>true</Cfg_2>
         <CfgParent>Base</CfgParent>
         <CfgParent>Base</CfgParent>
@@ -51,6 +57,12 @@
         <Cfg_2>true</Cfg_2>
         <Cfg_2>true</Cfg_2>
         <Base>true</Base>
         <Base>true</Base>
     </PropertyGroup>
     </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
+        <Cfg_2_Win64>true</Cfg_2_Win64>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
     <PropertyGroup Condition="'$(Base)'!=''">
     <PropertyGroup Condition="'$(Base)'!=''">
         <DCC_E>false</DCC_E>
         <DCC_E>false</DCC_E>
         <DCC_F>false</DCC_F>
         <DCC_F>false</DCC_F>
@@ -78,6 +90,11 @@
     <PropertyGroup Condition="'$(Base_Win64)'!=''">
     <PropertyGroup Condition="'$(Base_Win64)'!=''">
         <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
         <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
         <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
         <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+        <DCC_Namespace>System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
     </PropertyGroup>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_1)'!=''">
     <PropertyGroup Condition="'$(Cfg_1)'!=''">
         <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
         <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
@@ -87,7 +104,11 @@
     </PropertyGroup>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
     <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
-        <AppEnableHighDPI>true</AppEnableHighDPI>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
     </PropertyGroup>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_2)'!=''">
     <PropertyGroup Condition="'$(Cfg_2)'!=''">
         <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
         <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
@@ -99,9 +120,13 @@
     </PropertyGroup>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
     <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
-        <AppEnableHighDPI>true</AppEnableHighDPI>
         <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
         <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
         <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys>
         <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
     </PropertyGroup>
     </PropertyGroup>
     <ItemGroup>
     <ItemGroup>
         <DelphiCompile Include="$(MainSource)">
         <DelphiCompile Include="$(MainSource)">
@@ -115,13 +140,11 @@
         <DCCReference Include="core\UChunk.pas"/>
         <DCCReference Include="core\UChunk.pas"/>
         <DCCReference Include="core\UConst.pas"/>
         <DCCReference Include="core\UConst.pas"/>
         <DCCReference Include="core\UCrypto.pas"/>
         <DCCReference Include="core\UCrypto.pas"/>
-        <DCCReference Include="core\UECIES.pas"/>
         <DCCReference Include="core\UFileStorage.pas"/>
         <DCCReference Include="core\UFileStorage.pas"/>
         <DCCReference Include="core\ULog.pas"/>
         <DCCReference Include="core\ULog.pas"/>
         <DCCReference Include="core\UNetProtection.pas"/>
         <DCCReference Include="core\UNetProtection.pas"/>
         <DCCReference Include="core\UNetProtocol.pas"/>
         <DCCReference Include="core\UNetProtocol.pas"/>
         <DCCReference Include="core\UNode.pas"/>
         <DCCReference Include="core\UNode.pas"/>
-        <DCCReference Include="core\UOpenSSL.pas"/>
         <DCCReference Include="core\UOpTransaction.pas"/>
         <DCCReference Include="core\UOpTransaction.pas"/>
         <DCCReference Include="core\UPoolMinerThreads.pas"/>
         <DCCReference Include="core\UPoolMinerThreads.pas"/>
         <DCCReference Include="core\UPoolMining.pas"/>
         <DCCReference Include="core\UPoolMining.pas"/>
@@ -138,10 +161,6 @@
             <Form>FRMAbout</Form>
             <Form>FRMAbout</Form>
             <FormType>dfm</FormType>
             <FormType>dfm</FormType>
         </DCCReference>
         </DCCReference>
-        <DCCReference Include="gui-classic\UFRMAccountInfo.pas">
-            <Form>FRMAccountInfo</Form>
-            <FormType>dfm</FormType>
-        </DCCReference>
         <DCCReference Include="gui-classic\UFRMAccountSelect.pas">
         <DCCReference Include="gui-classic\UFRMAccountSelect.pas">
             <Form>FRMAccountSelect</Form>
             <Form>FRMAccountSelect</Form>
             <FormType>dfm</FormType>
             <FormType>dfm</FormType>
@@ -194,6 +213,12 @@
         <DCCReference Include="gui-classic\UGUIUtils.pas"/>
         <DCCReference Include="gui-classic\UGUIUtils.pas"/>
         <DCCReference Include="core\UPCDataTypes.pas"/>
         <DCCReference Include="core\UPCDataTypes.pas"/>
         <DCCReference Include="core\UPCOrderedLists.pas"/>
         <DCCReference Include="core\UPCOrderedLists.pas"/>
+        <DCCReference Include="core\UPCOperationsSignatureValidator.pas"/>
+        <DCCReference Include="core\UPCTNetDataExtraMessages.pas"/>
+        <DCCReference Include="gui-classic\UFRMHashLock.pas">
+            <Form>FRMHashLock</Form>
+            <FormType>dfm</FormType>
+        </DCCReference>
         <BuildConfiguration Include="Debug">
         <BuildConfiguration Include="Debug">
             <Key>Cfg_2</Key>
             <Key>Cfg_2</Key>
             <CfgParent>Base</CfgParent>
             <CfgParent>Base</CfgParent>
@@ -221,7 +246,6 @@
             </Delphi.Personality>
             </Delphi.Personality>
             <Platforms>
             <Platforms>
                 <Platform value="iOSDevice64">True</Platform>
                 <Platform value="iOSDevice64">True</Platform>
-                <Platform value="Linux64">True</Platform>
                 <Platform value="Win32">True</Platform>
                 <Platform value="Win32">True</Platform>
                 <Platform value="Win64">False</Platform>
                 <Platform value="Win64">False</Platform>
             </Platforms>
             </Platforms>
@@ -241,7 +265,6 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
                     <Platform Name="Win32">
                     <Platform Name="Win32">
-                        <RemoteDir>Contents\MacOS</RemoteDir>
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                     </Platform>
                     </Platform>
                 </DeployClass>
                 </DeployClass>
@@ -251,6 +274,12 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
                 </DeployClass>
                 </DeployClass>
+                <DeployClass Name="AndroidFileProvider">
+                    <Platform Name="Android">
+                        <RemoteDir>res\xml</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
                 <DeployClass Name="AndroidGDBServer">
                 <DeployClass Name="AndroidGDBServer">
                     <Platform Name="Android">
                     <Platform Name="Android">
                         <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                         <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
@@ -287,6 +316,12 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
                 </DeployClass>
                 </DeployClass>
+                <DeployClass Name="AndroidSplashStylesV21">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
                 <DeployClass Name="Android_DefaultAppIcon">
                 <DeployClass Name="Android_DefaultAppIcon">
                     <Platform Name="Android">
                     <Platform Name="Android">
                         <RemoteDir>res\drawable</RemoteDir>
                         <RemoteDir>res\drawable</RemoteDir>
@@ -365,6 +400,11 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                         <Extensions>.framework</Extensions>
                         <Extensions>.framework</Extensions>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
                     <Platform Name="Win32">
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                     </Platform>
                     </Platform>
@@ -387,6 +427,11 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                         <Extensions>.dylib</Extensions>
                         <Extensions>.dylib</Extensions>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
                     <Platform Name="Win32">
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                         <Extensions>.dll;.bpl</Extensions>
                         <Extensions>.dll;.bpl</Extensions>
@@ -410,6 +455,11 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                         <Extensions>.dylib</Extensions>
                         <Extensions>.dylib</Extensions>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
                     <Platform Name="Win32">
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                         <Extensions>.bpl</Extensions>
                         <Extensions>.bpl</Extensions>
@@ -432,6 +482,10 @@
                         <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
                         <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
                     <Platform Name="Win32">
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                     </Platform>
                     </Platform>
@@ -568,23 +622,41 @@
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
                 </DeployClass>
                 </DeployClass>
+                <DeployClass Name="ProjectOSXDebug">
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
                 <DeployClass Name="ProjectOSXEntitlements">
                 <DeployClass Name="ProjectOSXEntitlements">
                     <Platform Name="OSX32">
                     <Platform Name="OSX32">
                         <RemoteDir>..\</RemoteDir>
                         <RemoteDir>..\</RemoteDir>
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                 </DeployClass>
                 </DeployClass>
                 <DeployClass Name="ProjectOSXInfoPList">
                 <DeployClass Name="ProjectOSXInfoPList">
                     <Platform Name="OSX32">
                     <Platform Name="OSX32">
                         <RemoteDir>Contents</RemoteDir>
                         <RemoteDir>Contents</RemoteDir>
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                 </DeployClass>
                 </DeployClass>
                 <DeployClass Name="ProjectOSXResource">
                 <DeployClass Name="ProjectOSXResource">
                     <Platform Name="OSX32">
                     <Platform Name="OSX32">
                         <RemoteDir>Contents\Resources</RemoteDir>
                         <RemoteDir>Contents\Resources</RemoteDir>
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                 </DeployClass>
                 </DeployClass>
                 <DeployClass Required="true" Name="ProjectOutput">
                 <DeployClass Required="true" Name="ProjectOutput">
                     <Platform Name="Android">
                     <Platform Name="Android">
@@ -607,6 +679,10 @@
                         <RemoteDir>Contents\MacOS</RemoteDir>
                         <RemoteDir>Contents\MacOS</RemoteDir>
                         <Operation>1</Operation>
                         <Operation>1</Operation>
                     </Platform>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                     <Platform Name="Win32">
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Operation>0</Operation>
                     </Platform>
                     </Platform>
@@ -646,6 +722,7 @@
                 <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
                 <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
                 <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
                 <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
                 <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
                 <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
                 <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
                 <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
             </Deployment>
             </Deployment>
         </BorlandProject>
         </BorlandProject>