diff --git a/src/request/sign-transaction/SignTransaction.js b/src/request/sign-transaction/SignTransaction.js index 725acd8d..27815601 100644 --- a/src/request/sign-transaction/SignTransaction.js +++ b/src/request/sign-transaction/SignTransaction.js @@ -182,21 +182,16 @@ class SignTransaction { return; } - const privateKey = key.derivePrivateKey(request.keyPath); - const publicKey = Nimiq.PublicKey.derive(privateKey); + const publicKey = key.derivePublicKey(request.keyPath); + const signature = key.sign(request.keyPath, request.transaction.serializeContent()); - const tx = request.transaction; - - // Manually create signature proof, because tx.sign(keyPair) does not support HTLC redeeming transactions. - const signature = Nimiq.Signature.create(privateKey, publicKey, tx.serializeContent()); - const proof = Nimiq.SignatureProof.singleSig(publicKey, signature); - tx.proof = proof.serialize(); + request.transaction.proof = Nimiq.SignatureProof.singleSig(publicKey, signature).serialize(); /** @type {KeyguardRequest.SignTransactionResult} */ const result = { publicKey: publicKey.serialize(), - signature: tx.proof.subarray(tx.proof.length - 64), - serializedTx: tx.serialize(), + signature: signature.serialize(), + serializedTx: request.transaction.serialize(), }; resolve(result); } diff --git a/src/request/swap-iframe/SwapIFrameApi.js b/src/request/swap-iframe/SwapIFrameApi.js index c4c9f571..d244b376 100644 --- a/src/request/swap-iframe/SwapIFrameApi.js +++ b/src/request/swap-iframe/SwapIFrameApi.js @@ -429,14 +429,34 @@ class SwapIFrameApi extends BitcoinRequestParserMixin(RequestParser) { // eslint const feePerUnit = Number(transaction.fee) / transaction.serializedSize; const fee = BigInt(Math.ceil(feePerUnit * 167)); // 167 = NIM HTLC refunding tx size + /** + * Calculate future ValidityStartHeight for the refund transaction. + * + * This is not exact, unfortunately. But hopefully close enough. The calculated VSH is always + * smaller than it should be (blocks are faster than 1/second on average, time taken between + * request creation and this code is subtracted as well). Additionally, if the user's system + * clock is off, the resulting VHS will be wrong, too. + * + * But the watchtower only sends the refund transaction once the timeout _timestamp_ of the swap + * has passed, at which point the transaction will still be valid (except if totally wrong because + * of system clock). + * + * If the refund transaction is invalid when it is supposed to be sent, the user can always + * trigger a refund manually from the transaction details in the Wallet. + */ + const validityStartHeight = Math.max( + transaction.validityStartHeight, + transaction.validityStartHeight + + (parsedRequest.fund.htlcDetails.timeoutTimestamp - Math.round(Date.now() / 1e3)), + ); + // Create refund transaction const refundTransaction = new Nimiq.Transaction( transaction.recipient, Nimiq.AccountType.HTLC, new Uint8Array(0), transaction.sender, Nimiq.AccountType.Basic, new Uint8Array(0), transaction.value - fee, fee, Nimiq.TransactionFlag.None, - transaction.validityStartHeight - + (parsedRequest.fund.htlcDetails.timeoutTimestamp - Math.round(Date.now() / 1e3)), + validityStartHeight, CONFIG.NIMIQ_NETWORK_ID, );