Jelajahi Sumber

PIP-0032: fixes

Herman Schoenfeld 6 tahun lalu
induk
melakukan
6244142e49

TEMPAT SAMPAH
resources/wallet/key-16x16.bmp


+ 16 - 6
src/core/UAccounts.pas

@@ -130,7 +130,8 @@ Type
   public
     Class Function IsValidAccountKey(const account: TAccountKey; 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 IsAccountForSale(const accountInfo: TAccountInfo) : Boolean;
     Class Function IsAccountForSwap(const accountInfo: TAccountInfo) : Boolean;
@@ -1383,11 +1384,20 @@ begin
   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
   Result := BytesEqual( TBaseType.ToRawBytes( CalculateHashLock( AKey ) ), AAccount.account_data);
 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;
 begin
   Result := TBaseType.To32Bytes( TCrypto.DoSha256(AKey) );
@@ -1426,7 +1436,7 @@ begin
       exit;
 
    if (account.accountInfo.state in [as_ForAtomicAccountSwap, as_ForAtomicCoinSwap]) then
-     if NOT IsValidHashLockKey(account, APayload) then
+     if NOT IsValidAccountHashLockKey(account, APayload) then
        exit;
 
   Result := true;
@@ -4000,7 +4010,7 @@ begin
     Exit;
   end;
   if (LPBuyerAccount^.balance < (AAmount+AFee)) then begin
-    AErrors := 'Insuficient founds';
+    AErrors := 'Insufficient Funds';
     Exit;
   end;
   if (AFee>CT_MaxTransactionFee) then begin
@@ -4028,7 +4038,7 @@ begin
       TAccountComp.FormatMoney(LPAccountToBuy^.balance)+' + amount '+TAccountComp.FormatMoney(AAmount);
     Exit;
   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';
     Exit;
   end;
@@ -4525,7 +4535,7 @@ begin
     Exit;
   end;
   if (P_signer^.balance < fee) then begin
-    errors := 'Insuficient founds';
+    errors := 'Insufficient Funds';
     Exit;
   end;
   if (TAccountComp.IsAccountLocked(P_signer^.accountInfo,Origin_BlocksCount)) then begin

+ 15 - 16
src/core/UBlockChain.pas

@@ -112,7 +112,7 @@ uses
 
 Type
   // 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;
 
   // 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_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_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
 
@@ -3262,7 +3262,7 @@ begin
       Result := true;
     End;
     CT_Op_ListAccountForSale : begin
-      case TOpListAccountForSale(Operation).SubType of
+      case TOpListAccountForSaleOrSwap(Operation).OpSubType of
         CT_OpSubtype_ListAccountForPrivateSale:  begin
           OperationResume.OpSubtype := CT_OpSubtype_ListAccountForPrivateSale;
           OperationResume.OperationTxt := 'List account '+TAccountComp.AccountNumberToAccountTxtNumber(TOpListAccount(Operation).Data.account_target)+' for private sale price '+
@@ -3276,20 +3276,19 @@ begin
         CT_OpSubtype_ListAccountForAccountSwap:  begin
             OperationResume.OpSubtype := CT_OpSubtype_ListAccountForAccountSwap;
             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;
         CT_OpSubtype_ListAccountForCoinSwap:  begin
             OperationResume.OpSubtype := CT_OpSubtype_ListAccountForCoinSwap;
             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;
       OperationResume.newKey := TOpListAccount(Operation).Data.new_public_key;
@@ -3305,20 +3304,20 @@ begin
       OperationResume.DestAccount:=TOpBuyAccount(Operation).Data.target;
       if TOpBuyAccount(Operation).Data.sender=Affected_account_number then begin
         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);
         Result := true;
       end else if TOpBuyAccount(Operation).Data.target=Affected_account_number then begin
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountTarget;
         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.Fee := 0;
         Result := true;
       end else if TOpBuyAccount(Operation).Data.SellerAccount=Affected_account_number then begin
         OperationResume.OpSubtype := CT_OpSubtype_BuyAccountSeller;
         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.Fee := 0;
         Result := true;

+ 7 - 4
src/core/UConst.pas

@@ -108,6 +108,9 @@ Const
   CT_AccountInfo_ForAccountSwap = 1001;
   CT_AccountInfo_ForCoinSwap = 1002;
 
+  CT_HashLockKey_MinBytes = 4;
+  CT_HashLockKey_MaxBytes = 128;
+
   CT_PROTOCOL_1 = 1;
   CT_PROTOCOL_2 = 2;
   CT_PROTOCOL_3 = 3;
@@ -116,10 +119,10 @@ Const
   CT_BUILD_PROTOCOL = CT_PROTOCOL_4;
 
   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!

+ 54 - 34
src/core/UOpTransaction.pas

@@ -174,8 +174,8 @@ Type
     function IsValidSignatureBasedOnCurrentSafeboxState(ASafeBoxTransaction : TPCSafeBoxTransaction) : Boolean; override;
   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
     account_signer,
@@ -244,13 +244,13 @@ Type
     function IsValidSignatureBasedOnCurrentSafeboxState(ASafeBoxTransaction : TPCSafeBoxTransaction) : Boolean; override;
   End;
 
-  TOpListAccountForSale = Class(TOpListAccount)
+  TOpListAccountForSaleOrSwap = Class(TOpListAccount)
   private
-    FSubType : Integer;
+    function GetOpSubType : Integer;
   public
     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;
 
   TOpDelistAccountForSale = Class(TOpListAccount)
@@ -364,7 +364,7 @@ Begin
   TPCOperationsComp.RegisterOperationClass(TOpTransaction);
   TPCOperationsComp.RegisterOperationClass(TOpChangeKey);
   TPCOperationsComp.RegisterOperationClass(TOpRecoverFounds);
-  TPCOperationsComp.RegisterOperationClass(TOpListAccountForSale);
+  TPCOperationsComp.RegisterOperationClass(TOpListAccountForSaleOrSwap);
   TPCOperationsComp.RegisterOperationClass(TOpDelistAccountForSale);
   TPCOperationsComp.RegisterOperationClass(TOpBuyAccount);
   TPCOperationsComp.RegisterOperationClass(TOpChangeKeySigned);
@@ -1195,22 +1195,25 @@ function TOpTransaction.toString: String;
 begin
   case FData.opTransactionStyle of
     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.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 :
-      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.sender),
          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 :
-      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.sender),
          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');
   end;
 end;
@@ -1794,8 +1797,8 @@ begin
     LIsPublicSale := false;
     LIsPrivateSale := false;
   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
       LIsAccountSwap := false;
       LIsCoinSwap := true;
@@ -1837,7 +1840,8 @@ begin
       errors := 'Invalid account to pay number';
       Exit;
     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';
       Exit;
     end;
@@ -1846,7 +1850,7 @@ begin
       Exit;
     end;
     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;
     end;
     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(w,2);
   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;
     else exit; // Invalid data info
   end;
   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_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;
@@ -2007,7 +2011,8 @@ begin
       if TStreamOp.ReadAnsiString(Stream, FData.hash_lock) < 0 then exit;  // the hash-lock if any
     end else begin
       // 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;
   Stream.Read(FData.fee,Sizeof(FData.fee));
@@ -2026,19 +2031,25 @@ begin
   OperationResume.Changers[0] := CT_TMultiOpChangeInfo_NUL;
   OperationResume.Changers[0].Account:=FData.account_target;
   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
           OperationResume.Changers[0].Changes_type:=[list_for_public_sale];
         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].Locked_Until_Block := FData.locked_until_block;
         end;
         OperationResume.Changers[0].Seller_Account:=FData.account_to_pay;
         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 );
-      end;
+        end;
+    end;
     lat_DelistAccount : begin
         OperationResume.Changers[0].Changes_type:=[delist];
       end;
@@ -2083,13 +2094,13 @@ begin
   Stream.Write(FData.account_signer,Sizeof(FData.account_signer));
   Stream.Write(FData.account_target,Sizeof(FData.account_target));
   case FData.operation_type of
-    lat_ListForSale : w := CT_Op_ListAccountForSale;
+    lat_ListAccount : w := CT_Op_ListAccountForSale;
     lat_DelistAccount : w := CT_Op_DelistAccount;
   else raise Exception.Create('ERROR DEV 20170412-1');
   end;
   Stream.Write(w,2);
   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_to_pay,Sizeof(FData.account_to_pay));
     Stream.Write(FData.public_key.EC_OpenSSL_NID,Sizeof(FData.public_key.EC_OpenSSL_NID));
@@ -2124,7 +2135,7 @@ end;
 function TOpListAccount.SellerAccount: Int64;
 begin
   Case FData.operation_type of
-    lat_ListForSale : Result := FData.account_to_pay;
+    lat_ListAccount : Result := FData.account_to_pay;
   else Result:=inherited SellerAccount;
   end;
 end;
@@ -2132,7 +2143,7 @@ end;
 function TOpListAccount.toString: String;
 begin
   case FData.operation_type of
-    lat_ListForSale : begin
+    lat_ListAccount : begin
       case FData.account_state of
         as_ForSale: 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;
         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),
             TCrypto.ToHexaString( TBaseType.ToRawBytes( FData.hash_lock ) ),
             FData.locked_until_block,
@@ -2159,7 +2170,7 @@ begin
           );
         end;
         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.FormatMoney(FData.account_price),
             TCrypto.ToHexaString( TBaseType.ToRawBytes( FData.hash_lock ) ),
@@ -2227,9 +2238,9 @@ begin
   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
   inherited Create(ACurrentProtocol);
   if NOT (AListOpSubType IN [CT_OpSubtype_ListAccountForPublicSale, CT_OpSubtype_ListAccountForPrivateSale, CT_OpSubtype_ListAccountForAccountSwap, CT_OpSubtype_ListAccountForCoinSwap]) then
@@ -2247,7 +2258,7 @@ begin
   end;
   FData.account_signer := AAccountSigner;
   FData.account_target := AAccountTarget;
-  FData.operation_type := lat_ListForSale;
+  FData.operation_type := lat_ListAccount;
   FData.n_operation := ANOperation;
   FData.account_price := AAccountPrice;
   FData.account_to_pay := AAccountToPay;
@@ -2270,11 +2281,20 @@ begin
   end;
 end;
 
-class function TOpListAccountForSale.OpType: Byte;
+class function TOpListAccountForSaleOrSwap.OpType: Byte;
 begin
   Result := CT_Op_ListAccountForSale;
 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 }
 

+ 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
   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;
-    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)
   var privateKey : TECPrivateKey;
     errors : String;
@@ -1161,7 +1161,7 @@ function TRPCProcess.ProcessMethod(const method: String; params: TPCJSONObject;
        aux_target_pubkey := new_account_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);
-    Result := TOpListAccountForSale.CreateListAccountForSale(
+    Result := TOpListAccountForSaleOrSwap.CreateListAccountForSaleOrSwap(
       current_protocol,
       AListType,
       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
     // "enc_hash_lock" (optional) hex-encoded hash-lock for an atomic swap
   var
-    opSale: TOpListAccountForSale;
+    opSale: TOpListAccountForSaleOrSwap;
     listType : Integer;
     account_signer, account_target, seller_account : 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
   Top = 222
   BorderIcons = [biSystemMenu]
-  BorderStyle = bsSingle
+  BorderStyle = bsDialog
   Caption = 'New Operation'
-  ClientHeight = 493
+  ClientHeight = 515
   ClientWidth = 608
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
@@ -61,8 +61,8 @@ object FRMOperation: TFRMOperation
     ParentColor = False
   end
   object bbExecute: TBitBtn
-    Left = 300
-    Top = 445
+    Left = 307
+    Top = 476
     Width = 130
     Height = 31
     Caption = 'Execute (F12)'
@@ -88,8 +88,8 @@ object FRMOperation: TFRMOperation
     OnClick = actExecuteExecute
   end
   object bbCancel: TBitBtn
-    Left = 465
-    Top = 445
+    Left = 461
+    Top = 476
     Width = 116
     Height = 31
     Kind = bkCancel
@@ -100,14 +100,15 @@ object FRMOperation: TFRMOperation
     Left = 25
     Top = 72
     Width = 556
-    Height = 351
+    Height = 398
     ActivePage = tsOperation
     TabOrder = 1
     object tsOperation: TTabSheet
       TabVisible = False
+      ExplicitHeight = 373
       object lblFee: TLabel
         Left = 15
-        Top = 188
+        Top = 220
         Width = 69
         Height = 13
         Caption = 'Operation Fee'
@@ -115,8 +116,8 @@ object FRMOperation: TFRMOperation
         ParentColor = False
       end
       object lblSignerAccount: TLabel
-        Left = 176
-        Top = 188
+        Left = 277
+        Top = 221
         Width = 131
         Height = 13
         Caption = 'Signer account (Fee payer)'
@@ -124,8 +125,8 @@ object FRMOperation: TFRMOperation
         ParentColor = False
       end
       object sbSearchSignerAccount: TSpeedButton
-        Left = 411
-        Top = 184
+        Left = 512
+        Top = 217
         Width = 23
         Height = 22
         Glyph.Data = {
@@ -159,9 +160,9 @@ object FRMOperation: TFRMOperation
       end
       object gbPayload: TGroupBox
         Left = 13
-        Top = 211
+        Top = 240
         Width = 521
-        Height = 119
+        Height = 137
         Caption = ' Payload: '
         TabOrder = 2
         object lblEncryptPassword: TLabel
@@ -176,17 +177,17 @@ object FRMOperation: TFRMOperation
         object Label4: TLabel
           Left = 255
           Top = 15
-          Width = 67
+          Width = 64
           Height = 13
-          Caption = 'Payload data:'
+          Caption = 'Payload Data'
           Color = clBtnFace
           ParentColor = False
         end
         object lblEncryptionErrors: TLabel
           Left = 255
           Top = 96
-          Width = 246
-          Height = 13
+          Width = 187
+          Height = 33
           AutoSize = False
           Caption = 'Errors detected'
           Color = clBtnFace
@@ -252,7 +253,7 @@ object FRMOperation: TFRMOperation
           Left = 255
           Top = 37
           Width = 246
-          Height = 57
+          Height = 53
           Font.Charset = DEFAULT_CHARSET
           Font.Color = clBlack
           Font.Height = -16
@@ -274,20 +275,28 @@ object FRMOperation: TFRMOperation
           TabStop = True
           OnClick = memoPayloadClick
         end
+        object cbPayloadAsHex: TCheckBox
+          Left = 448
+          Top = 96
+          Width = 97
+          Height = 17
+          Caption = 'As Hex'
+          TabOrder = 6
+        end
       end
       object ebFee: TEdit
         Left = 90
-        Top = 184
+        Top = 217
         Width = 70
         Height = 21
         TabOrder = 1
       end
       object PageControlOpType: TPageControl
         Left = 13
-        Top = 11
-        Width = 521
-        Height = 167
-        ActivePage = tsChangeInfo
+        Top = 7
+        Width = 524
+        Height = 204
+        ActivePage = tsListAccount
         TabOrder = 0
         OnChange = PageControlOpTypeChange
         object tsTransaction: TTabSheet
@@ -376,297 +385,390 @@ object FRMOperation: TFRMOperation
           end
         end
         object tsChangePrivateKey: TTabSheet
-          Caption = 'Change key'
+          Caption = 'Change Key'
           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
-            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
-        object tsListForSale: TTabSheet
-          Caption = 'List account for sale'
+        object tsListAccount: TTabSheet
+          Caption = 'List Account'
           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
-            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
-        object tsDelist: TTabSheet
-          Caption = 'Delist account'
+        object tsDelistAccount: TTabSheet
+          Caption = 'Delist Account'
           ImageIndex = 3
           object lblDelistErrors: TLabel
             Left = 13
@@ -686,7 +788,7 @@ object FRMOperation: TFRMOperation
           end
         end
         object tsBuyAccount: TTabSheet
-          Caption = 'Buy account'
+          Caption = 'Buy Account'
           ImageIndex = 4
           object lblAccountToBuy: TLabel
             Left = 13
@@ -740,9 +842,9 @@ object FRMOperation: TFRMOperation
           object Label2: TLabel
             Left = 204
             Top = 61
-            Width = 231
+            Width = 234
             Height = 13
-            Caption = 'excessive amount will remain on bought account'
+            Caption = 'any over-payment will remain on bought account'
             Color = clBtnFace
             Font.Charset = DEFAULT_CHARSET
             Font.Color = clGray
@@ -803,14 +905,14 @@ object FRMOperation: TFRMOperation
           object cbBuyNewKey: TComboBox
             Left = 118
             Top = 85
-            Width = 294
+            Width = 355
             Height = 21
             Style = csDropDownList
             Sorted = True
             TabOrder = 2
           end
           object bbBuyNewKey: TBitBtn
-            Left = 418
+            Left = 479
             Top = 84
             Width = 31
             Height = 22
@@ -918,8 +1020,8 @@ object FRMOperation: TFRMOperation
         end
       end
       object ebSignerAccount: TEdit
-        Left = 325
-        Top = 184
+        Left = 426
+        Top = 217
         Width = 82
         Height = 21
         TabOrder = 3
@@ -928,6 +1030,7 @@ object FRMOperation: TFRMOperation
     object tsGlobalError: TTabSheet
       ImageIndex = 1
       TabVisible = False
+      ExplicitHeight = 373
       object lblGlobalErrors: TLabel
         Left = 40
         Top = 50
@@ -1051,8 +1154,8 @@ object FRMOperation: TFRMOperation
     OnKeyPress = ebSenderAccountKeyPress
   end
   object ActionList: TActionList
-    Left = 140
-    Top = 350
+    Left = 212
+    Top = 294
     object actExecute: TAction
       Caption = 'Execute (F12)'
       ShortCut = 123

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

@@ -32,8 +32,7 @@ uses
   Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, UNode, UWallet, UCrypto, Buttons, UBlockChain,
   UAccounts, UFRMAccountSelect, ActnList, ComCtrls, Types, UFRMMemoText,
-  UPCEncryption,
-  UBaseTypes, UPCOrderedLists;
+  UPCEncryption, UBaseTypes, UPCOrderedLists;
 
 Const
   CM_PC_WalletKeysChanged = WM_USER + 1;
@@ -58,7 +57,6 @@ type
     lblChangeInfoErrors: TLabel;
     PageControlLocked: TPageControl;
     sbSearchBuyAccount: TSpeedButton;
-    sbSearchListerSellerAccount: TSpeedButton;
     sbSearchDestinationAccount: TSpeedButton;
     sbSearchSignerAccount: TSpeedButton;
     tsChangeInfo: TTabSheet;
@@ -91,31 +89,9 @@ type
     ebDestAccount: TEdit;
     ebAmount: TEdit;
     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;
-    lblListAccountErrors: TLabel;
     lblAccountToBuy: TLabel;
     ebAccountToBuy: TEdit;
     lblBuyAmount: TLabel;
@@ -126,6 +102,34 @@ type
     bbBuyNewKey: TBitBtn;
     Label2: 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 FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
@@ -141,6 +145,7 @@ type
     procedure sbSearchDestinationAccountClick(Sender: TObject);
     procedure sbSearchListerSellerAccountClick(Sender: TObject);
     procedure sbSearchSignerAccountClick(Sender: TObject);
+    procedure sbHashLockClick(Sender: TObject);
     procedure updateInfoClick(Sender: TObject);
     procedure bbBuyNewKeyClick(Sender: TObject);
     procedure ebAccountNumberExit(Sender: TObject);
@@ -161,7 +166,7 @@ type
     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 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 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;
@@ -183,8 +188,8 @@ type
 implementation
 
 uses
-  UConst, UOpTransaction, UFRMNewPrivateKeyType, UFRMWalletKeys,
-  UCommon, UGUIUtils, UPCDataTypes, ULog;
+  UConst, UOpTransaction, UFRMNewPrivateKeyType, UFRMWalletKeys, UFRMHashLock,
+  UCommon, UPCDataTypes, ULog, UGUIUtils;
 
 {$IFnDEF FPC}
   {$R *.dfm}
@@ -192,28 +197,6 @@ uses
   {$R *.lfm}
 {$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 }
 
 procedure TFRMOperation.actExecuteExecute(Sender: TObject);
@@ -229,6 +212,7 @@ Var errors : String;
   _lockedUntil, _signer_n_ops : Cardinal;
   dooperation : Boolean;
   _newOwnerPublicKey : TECDSA_Public;
+  LHashLock : T32Bytes;
   _newName : TRawBytes;
   _newType : Word;
   _changeName, _changeType, _V2, _executeSigner  : Boolean;
@@ -295,7 +279,7 @@ loop_start:
         if _V2 then begin
           // 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
-            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!
           end;
 
@@ -312,19 +296,23 @@ loop_start:
         inc(_totalfee,_fee);
         operationstxt := 'Change private key to '+TAccountComp.GetECInfoTxt(_newOwnerPublicKey.EC_OpenSSL_NID);
         {%endregion}
-      end else if (PageControlOpType.ActivePage = tsListForSale) then begin
+      end else if (PageControlOpType.ActivePage = tsListAccount) then begin
         {%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:
         if signerAccount.balance>DefaultFee then _fee := DefaultFee
         else _fee := signerAccount.balance;
         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
-          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');
         {%endregion}
-      end else if (PageControlOpType.ActivePage = tsDelist) then begin
+      end else if (PageControlOpType.ActivePage = tsDelistAccount) then begin
         {%region Operation: Delist For Sale}
         if Not UpdateOpDelist(account,signerAccount,errors) then raise Exception.Create(errors);
         // Special fee account:
@@ -455,6 +443,7 @@ begin
   end;
 end;
 
+
 procedure TFRMOperation.CM_WalletChanged(var Msg: TMessage);
 begin
    UpdateWalletKeys;
@@ -558,19 +547,21 @@ begin
   lblListAccountErrors.Caption := '';
   rbListAccountForPublicSale.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.OnChange := updateInfoClick;
   ebSellerAccount.OnExit := ebAccountNumberExit;
   ebSellerAccount.OnKeyDown := ebAccountKeyDown;
   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 := '';
@@ -590,6 +581,7 @@ begin
   //
   sbSearchDestinationAccount.OnClick := sbSearchDestinationAccountClick;
   sbSearchListerSellerAccount.OnClick := sbSearchListerSellerAccountClick;
+  btnHashLock.OnClick := sbHashLockClick;
   sbSearchBuyAccount.OnClick := sbSearchBuyAccountClick;
   //
   ebFee.Text := TAccountComp.FormatMoney(0);
@@ -709,6 +701,21 @@ begin
   searchAccount(ebSignerAccount);
 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);
 var wd : Boolean;
 begin
@@ -794,10 +801,18 @@ begin
   end;
 end;
 
+var GInUpdateInfoClick : boolean;
 procedure TFRMOperation.updateInfoClick(Sender: TObject);
 Var errors : String;
 begin
-  UpdateOperationOptions(errors);
+  if NOT GInUpdateInfoClick then begin
+    GInUpdateInfoClick := true;
+    try
+      UpdateOperationOptions(errors);
+    finally
+    GInUpdateInfoClick := false;
+    end;
+  end;
 end;
 
 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;
     end;
     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;
     end;
     If Not TAccountComp.TxtToMoney(ebBuyAmount.Text,amount) then begin
@@ -833,7 +848,7 @@ begin
       errors := 'Account price '+TAccountComp.FormatMoney(AccountToBuy.accountInfo.price);
       exit;
     end;
-    if (amount+DefaultFee > SenderAccount.balance) then begin
+    if TAccountComp.IsAccountForSale(AccountToBuy.accountInfo) AND (amount+DefaultFee > SenderAccount.balance) then begin
       errors := 'Insufficient funds';
       exit;
     end;
@@ -1008,10 +1023,10 @@ begin
   lblDelistErrors.Caption := '';
   errors := '';
   Result := false;
-  if not (PageControlOpType.ActivePage=tsDelist) then exit;
+  if not (PageControlOpType.ActivePage=tsDelistAccount) then exit;
   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;
     end;
     if (TAccountComp.IsAccountLocked(TargetAccount.accountInfo,FNode.Bank.BlocksCount)) then begin
@@ -1059,6 +1074,7 @@ Var
   e : String;
   sender_account,dest_account,seller_account, account_to_buy, signer_account : TAccount;
   publicKey : TAccountKey;
+  LHashLock : T32Bytes;
   salePrice, amount : Int64;
   auxC : Cardinal;
   changeName,changeType : Boolean;
@@ -1125,9 +1141,9 @@ begin
     Result := UpdateOpTransaction(GetDefaultSenderAccount,dest_account,amount,errors);
   end else if (PageControlOpType.ActivePage = tsChangePrivateKey) then begin
     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);
   end else if (PageControlOpType.ActivePage = tsBuyAccount) then begin
     Result := UpdateOpBuyAccount(GetDefaultSenderAccount,account_to_buy,amount,publicKey,errors);
@@ -1142,7 +1158,7 @@ begin
   end else if (PageControlOpType.ActivePage=tsChangePrivateKey) then begin
     rbEncryptedWithOldEC.Caption := 'Encrypted with old 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';
     rbEncryptedWithEC.Caption := 'Encrypted with signer public key';
   end else if (PageControlOpType.ActivePage=tsBuyAccount) then begin
@@ -1151,8 +1167,8 @@ begin
   end;
   ebSignerAccount.Enabled:= ((PageControlOpType.ActivePage=tsChangePrivateKey) And (FNode.Bank.SafeBox.CurrentProtocol>=CT_PROTOCOL_2))
     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;
   lblSignerAccount.Enabled := ebSignerAccount.Enabled;
   lblChangeName.Enabled:= (PageControlOpType.ActivePage=tsChangeInfo) And (SenderAccounts.Count=1);
@@ -1161,32 +1177,54 @@ begin
   UpdatePayload(sender_account, e);
 end;
 
-function TFRMOperation.UpdateOpListForSale(const TargetAccount: TAccount;
+function TFRMOperation.UpdateOpListAccount(const TargetAccount: TAccount;
   var SalePrice: Int64; var SellerAccount, SignerAccount: TAccount;
   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
   Result := False;
   SalePrice := 0; SellerAccount := CT_Account_NUL;
   NewOwnerPublicKey := CT_TECDSA_Public_Nul;
   LockedUntilBlock := 0; errors := '';
-  if (PageControlOpType.ActivePage <> tsListForSale) then exit;
+  if (PageControlOpType.ActivePage <> tsListAccount) then exit;
   lblListAccountErrors.Caption := '';
   Try
     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
-        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
-        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;
-      if not TAccountComp.TxtToMoney(ebSalePrice.Text,salePrice) then begin
+      if not TAccountComp.TxtToMoney(ebPrice.Text,salePrice) then begin
         errors := 'Invalid price';
         exit;
       end;
@@ -1216,11 +1254,13 @@ begin
 
       SellerAccount := FNode.GetMempoolAccount(auxC);
       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;
           exit;
         end else begin
@@ -1231,7 +1271,7 @@ begin
           errors := 'New public key for private sale is the same public key';
           Exit;
         end;
-        LockedUntilBlock := StrToIntDef(ebSaleLockedUntilBlock.Text,0);
+        LockedUntilBlock := StrToIntDef(ebTimeLock.Text,0);
         if LockedUntilBlock=0 then begin
           errors := 'Insert locking block';
           exit;
@@ -1241,11 +1281,141 @@ begin
         errors := 'This operation needs PROTOCOL 2 active';
         exit;
       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
-      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';
       exit;
     end;
@@ -1308,6 +1478,7 @@ Var payload_u : AnsiString;
   i : Integer;
   valid : Boolean;
   wk : TWalletKey;
+  LPayloadBytes : TRawBytes;
 begin
   valid := false;
   payload_encrypted := Nil;
@@ -1319,15 +1490,23 @@ begin
       valid := true;
       exit;
     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
       // Use sender
       errors := 'Error encrypting';
       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;
     end else if (rbEncryptedWithEC.Checked) then begin
       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
         // With dest public key
         If (PageControlOpType.ActivePage=tsTransaction) then begin
@@ -1335,12 +1514,12 @@ begin
             errors := 'Invalid dest account number';
             exit;
           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
             errors := 'Invalid signer account number';
             exit;
           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
             errors := 'Invalid signer account number';
             exit;
@@ -1359,7 +1538,7 @@ begin
           exit;
         end;
         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;
       end else if (PageControlOpType.ActivePage=tsChangePrivateKey) then begin
         if (rbChangeKeyWithAnother.Checked) then begin
@@ -1381,7 +1560,7 @@ begin
           exit;
         end;
         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;
         end else begin
           valid := false;
@@ -1392,10 +1571,10 @@ begin
         errors := 'This operation does not allow this kind of payload';
       end;
     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;
     end else if (rbNotEncrypted.Checked) then begin
-      payload_encrypted := TEncoding.ANSI.GetBytes(payload_u);
+      payload_encrypted := LPayloadBytes;
       valid := true;
     end else begin
       errors := 'Must select an encryption option for payload';

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

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

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

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

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

@@ -385,12 +385,12 @@ begin
   TNode.Node.NetServer.Active := true;
   FLastTC := 0;
   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
       Synchronize(ThreadSafeNotify);
       Sleep(200);
     end;
-  end;
+  end;}
   if Not Terminated then begin
     Synchronize( FRMWallet.DoUpdateAccounts );
     Synchronize( FRMWallet.FinishedLoadingApp );

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

@@ -11,7 +11,6 @@ uses
 
 function InputQueryPassword(ACaption, APrompt : String; var defValue : String) : Boolean;
 
-
 implementation
 
 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"?>
 <CONFIG>
   <ProjectOptions>
-    <Version Value="10"/>
+    <Version Value="12"/>
     <PathDelim Value="\"/>
     <General>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
+        <CompatibilityMode Value="True"/>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="PascalCoinMiner"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
@@ -25,9 +25,16 @@
     </PublishOptions>
     <RunParams>
       <local>
-        <FormatVersion Value="1"/>
         <CommandLineParams Value="-c 1 -s -n TEST"/>
       </local>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default">
+          <local>
+            <CommandLineParams Value="-c 1 -s -n TEST"/>
+          </local>
+        </Mode0>
+      </Modes>
     </RunParams>
     <RequiredPackages Count="1">
       <Item1>

+ 3 - 4
src/pascalcoin_wallet_classic.dpr

@@ -17,9 +17,7 @@ uses
   UAccounts in 'core\UAccounts.pas',
   {$IFDEF Use_OpenSSL}
   UAES in 'core\UAES.pas',
-  UECIES in 'core\UECIES.pas',
-  UOpenSSL in 'core\UOpenSSL.pas',
-  {$ENDIF}
+  {$ENDIF }
   UBaseTypes in 'core\UBaseTypes.pas',
   UBlockChain in 'core\UBlockChain.pas',
   UChunk in 'core\UChunk.pas',
@@ -60,7 +58,8 @@ uses
   UPCDataTypes in 'core\UPCDataTypes.pas',
   UPCOrderedLists in 'core\UPCOrderedLists.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}
 

+ 89 - 12
src/pascalcoin_wallet_classic.dproj

@@ -4,10 +4,10 @@
         <MainSource>pascalcoin_wallet_classic.dpr</MainSource>
         <Base>True</Base>
         <Config Condition="'$(Config)'==''">Debug</Config>
-        <TargetedPlatforms>1153</TargetedPlatforms>
+        <TargetedPlatforms>1025</TargetedPlatforms>
         <AppType>Application</AppType>
         <FrameworkType>VCL</FrameworkType>
-        <ProjectVersion>18.4</ProjectVersion>
+        <ProjectVersion>18.6</ProjectVersion>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@@ -34,6 +34,12 @@
         <Cfg_1>true</Cfg_1>
         <Base>true</Base>
     </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)'!=''">
         <Cfg_2>true</Cfg_2>
         <CfgParent>Base</CfgParent>
@@ -51,6 +57,12 @@
         <Cfg_2>true</Cfg_2>
         <Base>true</Base>
     </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)'!=''">
         <DCC_E>false</DCC_E>
         <DCC_F>false</DCC_F>
@@ -78,6 +90,11 @@
     <PropertyGroup Condition="'$(Base_Win64)'!=''">
         <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>
+        <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 Condition="'$(Cfg_1)'!=''">
         <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
@@ -87,7 +104,11 @@
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
-        <AppEnableHighDPI>true</AppEnableHighDPI>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_2)'!=''">
         <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
@@ -99,9 +120,13 @@
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
-        <AppEnableHighDPI>true</AppEnableHighDPI>
         <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>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
     </PropertyGroup>
     <ItemGroup>
         <DelphiCompile Include="$(MainSource)">
@@ -115,13 +140,11 @@
         <DCCReference Include="core\UChunk.pas"/>
         <DCCReference Include="core\UConst.pas"/>
         <DCCReference Include="core\UCrypto.pas"/>
-        <DCCReference Include="core\UECIES.pas"/>
         <DCCReference Include="core\UFileStorage.pas"/>
         <DCCReference Include="core\ULog.pas"/>
         <DCCReference Include="core\UNetProtection.pas"/>
         <DCCReference Include="core\UNetProtocol.pas"/>
         <DCCReference Include="core\UNode.pas"/>
-        <DCCReference Include="core\UOpenSSL.pas"/>
         <DCCReference Include="core\UOpTransaction.pas"/>
         <DCCReference Include="core\UPoolMinerThreads.pas"/>
         <DCCReference Include="core\UPoolMining.pas"/>
@@ -138,10 +161,6 @@
             <Form>FRMAbout</Form>
             <FormType>dfm</FormType>
         </DCCReference>
-        <DCCReference Include="gui-classic\UFRMAccountInfo.pas">
-            <Form>FRMAccountInfo</Form>
-            <FormType>dfm</FormType>
-        </DCCReference>
         <DCCReference Include="gui-classic\UFRMAccountSelect.pas">
             <Form>FRMAccountSelect</Form>
             <FormType>dfm</FormType>
@@ -194,6 +213,12 @@
         <DCCReference Include="gui-classic\UGUIUtils.pas"/>
         <DCCReference Include="core\UPCDataTypes.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">
             <Key>Cfg_2</Key>
             <CfgParent>Base</CfgParent>
@@ -221,7 +246,6 @@
             </Delphi.Personality>
             <Platforms>
                 <Platform value="iOSDevice64">True</Platform>
-                <Platform value="Linux64">True</Platform>
                 <Platform value="Win32">True</Platform>
                 <Platform value="Win64">False</Platform>
             </Platforms>
@@ -241,7 +265,6 @@
                         <Operation>1</Operation>
                     </Platform>
                     <Platform Name="Win32">
-                        <RemoteDir>Contents\MacOS</RemoteDir>
                         <Operation>0</Operation>
                     </Platform>
                 </DeployClass>
@@ -251,6 +274,12 @@
                         <Operation>1</Operation>
                     </Platform>
                 </DeployClass>
+                <DeployClass Name="AndroidFileProvider">
+                    <Platform Name="Android">
+                        <RemoteDir>res\xml</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
                 <DeployClass Name="AndroidGDBServer">
                     <Platform Name="Android">
                         <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
@@ -287,6 +316,12 @@
                         <Operation>1</Operation>
                     </Platform>
                 </DeployClass>
+                <DeployClass Name="AndroidSplashStylesV21">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
                 <DeployClass Name="Android_DefaultAppIcon">
                     <Platform Name="Android">
                         <RemoteDir>res\drawable</RemoteDir>
@@ -365,6 +400,11 @@
                         <Operation>1</Operation>
                         <Extensions>.framework</Extensions>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                     </Platform>
@@ -387,6 +427,11 @@
                         <Operation>1</Operation>
                         <Extensions>.dylib</Extensions>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Extensions>.dll;.bpl</Extensions>
@@ -410,6 +455,11 @@
                         <Operation>1</Operation>
                         <Extensions>.dylib</Extensions>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Extensions>.bpl</Extensions>
@@ -432,6 +482,10 @@
                         <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
                         <Operation>0</Operation>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                     </Platform>
@@ -568,23 +622,41 @@
                         <Operation>1</Operation>
                     </Platform>
                 </DeployClass>
+                <DeployClass Name="ProjectOSXDebug">
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
                 <DeployClass Name="ProjectOSXEntitlements">
                     <Platform Name="OSX32">
                         <RemoteDir>..\</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                 </DeployClass>
                 <DeployClass Name="ProjectOSXInfoPList">
                     <Platform Name="OSX32">
                         <RemoteDir>Contents</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                 </DeployClass>
                 <DeployClass Name="ProjectOSXResource">
                     <Platform Name="OSX32">
                         <RemoteDir>Contents\Resources</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                 </DeployClass>
                 <DeployClass Required="true" Name="ProjectOutput">
                     <Platform Name="Android">
@@ -607,6 +679,10 @@
                         <RemoteDir>Contents\MacOS</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                     </Platform>
@@ -646,6 +722,7 @@
                 <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
                 <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
                 <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
                 <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
             </Deployment>
         </BorlandProject>