From 479c45c7edbf9b7167d2f2c5c4055b09127b1c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren?= Date: Thu, 10 Aug 2023 17:22:21 +0200 Subject: [PATCH] Make SignStakingResult an array to allow signing and returning multiple transactions This is used for type = UPDATE_STAKER, which should also reactivate all stake. In a future Albatross update, this functionality will be added to the update_staker transaction type, so again only one tx is required to be signed and returned. --- client/src/PublicRequest.ts | 4 +-- src/request/sign-staking/SignStaking.js | 41 ++++++++++++++-------- src/request/sign-staking/SignStakingApi.js | 5 +++ 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/client/src/PublicRequest.ts b/client/src/PublicRequest.ts index 07eb8b831..434b1e32b 100644 --- a/client/src/PublicRequest.ts +++ b/client/src/PublicRequest.ts @@ -512,10 +512,10 @@ export type ListLegacyResult = LegacyKeyInfoObject[]; export type SignTransactionResult = SignatureResult & { serializedTx: Uint8Array, }; -export type SignStakingResult = SignatureResult & { +export type SignStakingResult = Array; export type SimpleResult = { success: boolean }; export type SignedBitcoinTransaction = { transactionHash: string, diff --git a/src/request/sign-staking/SignStaking.js b/src/request/sign-staking/SignStaking.js index be4ea5e93..539187de2 100644 --- a/src/request/sign-staking/SignStaking.js +++ b/src/request/sign-staking/SignStaking.js @@ -155,70 +155,81 @@ class SignStaking { const privateKey = Albatross.PrivateKey.unserialize(powPrivateKey.serialize()); const keyPair = Albatross.KeyPair.derive(privateKey); - /** @type {Albatross.Transaction} */ - let tx; + /** @type {Albatross.Transaction[]} */ + const txs = []; switch (request.type) { case SignStakingApi.IncomingStakingType.CREATE_STAKER: - tx = Albatross.TransactionBuilder.newCreateStaker( + txs.push(Albatross.TransactionBuilder.newCreateStaker( keyPair.toAddress(), Albatross.Address.fromString(/** @type {Nimiq.Address} */ (request.delegation).toHex()), BigInt(request.transaction.value), BigInt(request.transaction.fee), request.transaction.validityStartHeight, request.transaction.networkId, - ); + )); break; case SignStakingApi.IncomingStakingType.ADD_STAKE: - tx = Albatross.TransactionBuilder.newStake( + txs.push(Albatross.TransactionBuilder.newStake( keyPair.toAddress(), keyPair.toAddress(), BigInt(request.transaction.value), BigInt(request.transaction.fee), request.transaction.validityStartHeight, request.transaction.networkId, - ); + )); break; case SignStakingApi.IncomingStakingType.UPDATE_STAKER: - tx = Albatross.TransactionBuilder.newUpdateStaker( + txs.push(Albatross.TransactionBuilder.newUpdateStaker( keyPair.toAddress(), Albatross.Address.fromString(/** @type {Nimiq.Address} */ (request.delegation).toHex()), BigInt(request.transaction.fee), request.transaction.validityStartHeight, request.transaction.networkId, - ); + )); + if (request.newInactiveBalance !== undefined) { + txs.push(Albatross.TransactionBuilder.newSetInactiveStake( + keyPair.toAddress(), + BigInt(request.newInactiveBalance), + BigInt(request.transaction.fee), + request.transaction.validityStartHeight, + request.transaction.networkId, + )); + } break; case SignStakingApi.IncomingStakingType.SET_INACTIVE_STAKE: - tx = Albatross.TransactionBuilder.newSetInactiveStake( + txs.push(Albatross.TransactionBuilder.newSetInactiveStake( keyPair.toAddress(), BigInt(request.newInactiveBalance), BigInt(request.transaction.fee), request.transaction.validityStartHeight, request.transaction.networkId, - ); + )); break; case SignStakingApi.IncomingStakingType.UNSTAKE: - tx = Albatross.TransactionBuilder.newUnstake( + txs.push(Albatross.TransactionBuilder.newUnstake( keyPair.toAddress(), BigInt(request.transaction.value), BigInt(request.transaction.fee), request.transaction.validityStartHeight, request.transaction.networkId, - ); + )); break; default: throw new Errors.KeyguardError('Unreachable'); } - tx = tx.sign(keyPair); + await Promise.all(txs.map(async (tx, i, arr) => { + arr[i] = await tx.sign(keyPair); + })); /** @type {KeyguardRequest.SignStakingResult} */ - const result = { + const result = txs.map((tx) => ({ publicKey: keyPair.publicKey.serialize(), signature: tx.proof.subarray(tx.proof.length - 64), data: request.transaction.data, serializedTx: tx.serialize(), - }; + })); resolve(result); } diff --git a/src/request/sign-staking/SignStakingApi.js b/src/request/sign-staking/SignStakingApi.js index 9aa363a6d..0083995a8 100644 --- a/src/request/sign-staking/SignStakingApi.js +++ b/src/request/sign-staking/SignStakingApi.js @@ -30,6 +30,11 @@ class SignStakingApi extends TopLevelApi { case SignStakingApi.IncomingStakingType.CREATE_STAKER: case SignStakingApi.IncomingStakingType.UPDATE_STAKER: { parsedRequest.delegation = this.parseAddress(request.delegation, 'delegation'); + parsedRequest.newInactiveBalance = this.parseNonNegativeFiniteNumber( + request.newInactiveBalance, + true, + 'newInactiveBalance', + ); const data = new Nimiq.SerialBuffer( 1 // Data type + 1 // Option<> indicator