diff --git a/package-lock.json b/package-lock.json index 920874bd..b4c79ed8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.17", + "version": "13.0.0-beta.18", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.17", + "version": "13.0.0-beta.18", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", diff --git a/package.json b/package.json index c2f537e5..24cdd41d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-core", - "version": "13.0.0-beta.17", + "version": "13.0.0-beta.18", "description": "MultiversX SDK for JavaScript and TypeScript", "main": "out/index.js", "types": "out/index.d.js", diff --git a/src/transaction.spec.ts b/src/transaction.spec.ts index 0e26f2a4..c514a3ab 100644 --- a/src/transaction.spec.ts +++ b/src/transaction.spec.ts @@ -9,6 +9,7 @@ import { TokenTransfer } from "./tokens"; import { Transaction } from "./transaction"; import { TransactionComputer } from "./transactionComputer"; import { TransactionPayload } from "./transactionPayload"; +import { UserPublicKey, UserVerifier } from "@multiversx/sdk-wallet/out"; describe("test transaction", async () => { let wallets: Record; @@ -696,4 +697,62 @@ describe("test transaction", async () => { assert.equal(transaction.version, 2); assert.equal(transaction.options, 3); }); + + it("should compute bytes to verify transaction signature", async () => { + let transaction = new Transaction({ + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "D", + nonce: 7n, + }); + + transaction.signature = await wallets.alice.signer.sign( + transactionComputer.computeBytesForSigning(transaction), + ); + + const userVerifier = new UserVerifier(new UserPublicKey(wallets.alice.address.getPublicKey())); + const isSignedByAlice = userVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + const wrongVerifier = new UserVerifier(new UserPublicKey(wallets.bob.address.getPublicKey())); + const isSignedByBob = wrongVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + assert.equal(isSignedByAlice, true); + assert.equal(isSignedByBob, false); + }); + + it("should compute bytes to verify transaction signature (signed by hash)", async () => { + let transaction = new Transaction({ + sender: wallets.alice.address.toBech32(), + receiver: wallets.bob.address.toBech32(), + gasLimit: 50000n, + chainID: "D", + nonce: 7n, + }); + + transactionComputer.applyOptionsForHashSigning(transaction); + + transaction.signature = await wallets.alice.signer.sign(transactionComputer.computeHashForSigning(transaction)); + + const userVerifier = new UserVerifier(new UserPublicKey(wallets.alice.address.getPublicKey())); + const isSignedByAlice = userVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + const wrongVerifier = new UserVerifier(new UserPublicKey(wallets.bob.address.getPublicKey())); + const isSignedByBob = wrongVerifier.verify( + transactionComputer.computeBytesForVerifying(transaction), + transaction.signature, + ); + + assert.equal(isSignedByAlice, true); + assert.equal(isSignedByBob, false); + }); }); diff --git a/src/transactionComputer.ts b/src/transactionComputer.ts index 31707aed..d4117a39 100644 --- a/src/transactionComputer.ts +++ b/src/transactionComputer.ts @@ -55,6 +55,15 @@ export class TransactionComputer { return new Uint8Array(Buffer.from(serialized)); } + computeBytesForVerifying(transaction: ITransaction): Uint8Array { + const isTxSignedByHash = this.hasOptionsSetForHashSigning(transaction); + + if (isTxSignedByHash) { + return this.computeHashForSigning(transaction); + } + return this.computeBytesForSigning(transaction); + } + computeHashForSigning(transaction: ITransaction): Uint8Array { const plainTransaction = this.toPlainObjectForSigning(transaction); const signable = Buffer.from(JSON.stringify(plainTransaction));