From 335edbed0684c809e7787525a9e38901e30f9c35 Mon Sep 17 00:00:00 2001 From: sapthasurendran Date: Tue, 24 May 2022 16:44:27 +0530 Subject: [PATCH] Node JS changes for Persistance Contributes to #394 Signed-off-by: sapthasurendran --- node/src/chaincodeeventsbuilder.ts | 8 +- node/src/chaincodeeventsrequest.ts | 7 +- node/src/gateway.ts | 111 +++++++++++++++-- node/src/offlinesign.test.ts | 187 +++++++++++++++++++++++++++++ node/src/proposal.test.ts | 22 ++++ node/src/transaction.test.ts | 31 +++++ 6 files changed, 351 insertions(+), 15 deletions(-) diff --git a/node/src/chaincodeeventsbuilder.ts b/node/src/chaincodeeventsbuilder.ts index 8f454ba76..23908e203 100644 --- a/node/src/chaincodeeventsbuilder.ts +++ b/node/src/chaincodeeventsbuilder.ts @@ -35,7 +35,7 @@ export class ChaincodeEventsBuilder { return new ChaincodeEventsRequestImpl({ client: this.#options.client, signingIdentity: this.#options.signingIdentity, - request: this.#newChaincodeEventsRequestProto(), + signedRequest: this.#newSignedChaincodeEventsRequestProto(), }); } @@ -51,4 +51,10 @@ export class ChaincodeEventsBuilder { } return result; } + + #newSignedChaincodeEventsRequestProto(): gateway.SignedChaincodeEventsRequest { + const result = new gateway.SignedChaincodeEventsRequest(); + result.setRequest(this.#newChaincodeEventsRequestProto().serializeBinary()); + return result; + } } diff --git a/node/src/chaincodeeventsrequest.ts b/node/src/chaincodeeventsrequest.ts index 3aa5b730b..35443df63 100644 --- a/node/src/chaincodeeventsrequest.ts +++ b/node/src/chaincodeeventsrequest.ts @@ -39,7 +39,7 @@ export interface ChaincodeEventsRequest extends Signable { export interface ChaincodeEventsRequestOptions { client: GatewayClient; signingIdentity: SigningIdentity; - request: gateway.ChaincodeEventsRequest; + signedRequest: gateway.SignedChaincodeEventsRequest; } export class ChaincodeEventsRequestImpl implements ChaincodeEventsRequest { @@ -50,8 +50,7 @@ export class ChaincodeEventsRequestImpl implements ChaincodeEventsRequest { constructor(options: Readonly) { this.#client = options.client; this.#signingIdentity = options.signingIdentity; - this.#signedRequest = new gateway.SignedChaincodeEventsRequest(); - this.#signedRequest.setRequest(options.request.serializeBinary()); + this.#signedRequest = options.signedRequest; } async getEvents(options?: Readonly): Promise> { @@ -61,7 +60,7 @@ export class ChaincodeEventsRequestImpl implements ChaincodeEventsRequest { } getBytes(): Uint8Array { - return this.#signedRequest.getRequest_asU8(); + return this.#signedRequest.serializeBinary(); } getDigest(): Uint8Array { diff --git a/node/src/gateway.ts b/node/src/gateway.ts index f39f34480..e8ee8f6b8 100644 --- a/node/src/gateway.ts +++ b/node/src/gateway.ts @@ -156,6 +156,13 @@ export interface Gateway { */ newSignedProposal(bytes: Uint8Array, signature: Uint8Array): Proposal; + /** + * Recreate a proposal from serialized data. + * @param bytes - Serialized proposal. + * @returns A proposal. + */ + newProposal(bytes: Uint8Array): Proposal; + /** * Create a transaction with the specified digital signature. Supports off-line signing flow. * @param bytes - Serialized proposal. @@ -164,6 +171,13 @@ export interface Gateway { */ newSignedTransaction(bytes: Uint8Array, signature: Uint8Array): Transaction; + /** + * Recreate a transaction from serialized data. + * @param bytes - Serialized proposal. + * @returns A transaction. + */ + newTransaction(bytes: Uint8Array): Transaction; + /** * Create a commit with the specified digital signature, which can be used to access information about a * transaction that is committed to the ledger. Supports off-line signing flow. @@ -173,6 +187,13 @@ export interface Gateway { */ newSignedCommit(bytes: Uint8Array, signature: Uint8Array): Commit; + /** + * Recreate a commit status request from serialized data. + * @param bytes - Serialized commit status request. + * @returns A commit status request. + */ + newCommit(bytes: Uint8Array): Commit; + /** * Create a chaincode events request with the specified digital signature. Supports off-line signing flow. * @param bytes - Serialized chaincode events request. @@ -181,6 +202,13 @@ export interface Gateway { */ newSignedChaincodeEventsRequest(bytes: Uint8Array, signature: Uint8Array): ChaincodeEventsRequest; + /** + * Recreate a chaincode events request from serialized data. + * @param bytes - Serialized chaincode events request. + * @returns A chaincode events request. + */ + newChaincodeEventsRequest(bytes: Uint8Array): ChaincodeEventsRequest; + /** * Create a block events request with the specified digital signature. Supports off-line signing flow. * @param bytes - Serialized block events request. @@ -189,6 +217,13 @@ export interface Gateway { */ newSignedBlockEventsRequest(bytes: Uint8Array, signature: Uint8Array): BlockEventsRequest; + /** + * Recreate a block events request from serialized data. + * @param bytes - Serialized block events request. + * @returns A block events request. + */ + newBlockEventsRequest(bytes: Uint8Array): BlockEventsRequest; + /** * Create a filtered block events request with the specified digital signature. Supports off-line signing flow. * @param bytes - Serialized filtered block events request. @@ -197,6 +232,13 @@ export interface Gateway { */ newSignedFilteredBlockEventsRequest(bytes: Uint8Array, signature: Uint8Array): FilteredBlockEventsRequest; + /** + * Recreate a filtered block events request from serialized data. + * @param bytes - Serialized filtered block events request. + * @returns A filtered block events request. + */ + newFilteredBlockEventsRequest(bytes: Uint8Array): FilteredBlockEventsRequest; + /** * Create a block and private data events request with the specified digital signature. Supports off-line signing * flow. @@ -206,6 +248,13 @@ export interface Gateway { */ newSignedBlockAndPrivateDataEventsRequest(bytes: Uint8Array, signature: Uint8Array): BlockAndPrivateDataEventsRequest; + /** + * Recreate a block and private data events request from serialized data. + * @param bytes - Serialized block and private data events request. + * @returns A block and private data events request. + */ + newBlockAndPrivateDataEventsRequest(bytes: Uint8Array): BlockAndPrivateDataEventsRequest; + /** * Close the gateway when it is no longer required. This releases all resources associated with networks and * contracts obtained using the Gateway, including removing event listeners. @@ -213,7 +262,7 @@ export interface Gateway { close(): void; } -class GatewayImpl { +class GatewayImpl implements Gateway { readonly #client: GatewayClient; readonly #signingIdentity: SigningIdentity; @@ -234,7 +283,7 @@ class GatewayImpl { }); } - newSignedProposal(bytes: Uint8Array, signature: Uint8Array): Proposal { + newProposal(bytes: Uint8Array): ProposalImpl { const proposedTransaction = gateway.ProposedTransaction.deserializeBinary(bytes); const signedProposal = assertDefined(proposedTransaction.getProposal(), 'Missing signed proposal'); const proposal = peer.Proposal.deserializeBinary(signedProposal.getProposalBytes_asU8()); @@ -247,12 +296,18 @@ class GatewayImpl { channelName: channelHeader.getChannelId(), proposedTransaction, }); + + return result; + } + + newSignedProposal(bytes: Uint8Array, signature: Uint8Array): Proposal { + const result = this.newProposal(bytes); result.setSignature(signature); return result; } - newSignedTransaction(bytes: Uint8Array, signature: Uint8Array): Transaction { + newTransaction(bytes: Uint8Array): TransactionImpl { const preparedTransaction = gateway.PreparedTransaction.deserializeBinary(bytes); const result = new TransactionImpl({ @@ -260,12 +315,18 @@ class GatewayImpl { signingIdentity: this.#signingIdentity, preparedTransaction, }); + + return result; + } + + newSignedTransaction(bytes: Uint8Array, signature: Uint8Array): Transaction { + const result = this.newTransaction(bytes); result.setSignature(signature); return result; } - newSignedCommit(bytes: Uint8Array, signature: Uint8Array): Commit { + newCommit(bytes: Uint8Array): CommitImpl { const signedRequest = gateway.SignedCommitStatusRequest.deserializeBinary(bytes); const request = gateway.CommitStatusRequest.deserializeBinary(signedRequest.getRequest_asU8()); @@ -275,25 +336,44 @@ class GatewayImpl { transactionId: request.getTransactionId(), signedRequest: signedRequest, }); + + return result; + } + + newSignedCommit(bytes: Uint8Array, signature: Uint8Array): Commit { + const result = this.newCommit(bytes); result.setSignature(signature); return result; } newSignedChaincodeEventsRequest(bytes: Uint8Array, signature: Uint8Array): ChaincodeEventsRequest { - const request = gateway.ChaincodeEventsRequest.deserializeBinary(bytes); + const result = this.newChaincodeEventsRequest(bytes); + result.setSignature(signature); + + return result; + } + + newChaincodeEventsRequest(bytes: Uint8Array): ChaincodeEventsRequestImpl { + const signedRequest = gateway.SignedChaincodeEventsRequest.deserializeBinary(bytes); const result = new ChaincodeEventsRequestImpl({ client: this.#client, signingIdentity: this.#signingIdentity, - request, + signedRequest, }); - result.setSignature(signature); return result; } newSignedBlockEventsRequest(bytes: Uint8Array, signature: Uint8Array): BlockEventsRequest { + const result = this.newBlockEventsRequest(bytes); + result.setSignature(signature); + + return result; + } + + newBlockEventsRequest(bytes: Uint8Array): BlockEventsRequestImpl { const request = common.Envelope.deserializeBinary(bytes); const result = new BlockEventsRequestImpl({ @@ -301,12 +381,18 @@ class GatewayImpl { signingIdentity: this.#signingIdentity, request, }); - result.setSignature(signature); return result; } newSignedFilteredBlockEventsRequest(bytes: Uint8Array, signature: Uint8Array): FilteredBlockEventsRequest { + const result = this.newFilteredBlockEventsRequest(bytes); + result.setSignature(signature); + + return result; + } + + newFilteredBlockEventsRequest(bytes: Uint8Array): FilteredBlockEventsRequestImpl { const request = common.Envelope.deserializeBinary(bytes); const result = new FilteredBlockEventsRequestImpl({ @@ -314,12 +400,18 @@ class GatewayImpl { signingIdentity: this.#signingIdentity, request, }); - result.setSignature(signature); return result; } newSignedBlockAndPrivateDataEventsRequest(bytes: Uint8Array, signature: Uint8Array): BlockAndPrivateDataEventsRequest { + const result = this.newBlockAndPrivateDataEventsRequest(bytes); + result.setSignature(signature); + + return result; + } + + newBlockAndPrivateDataEventsRequest(bytes: Uint8Array): BlockAndPrivateDataEventsRequestImpl { const request = common.Envelope.deserializeBinary(bytes); const result = new BlockAndPrivateDataEventsRequestImpl({ @@ -327,7 +419,6 @@ class GatewayImpl { signingIdentity: this.#signingIdentity, request, }); - result.setSignature(signature); return result; } diff --git a/node/src/offlinesign.test.ts b/node/src/offlinesign.test.ts index 87f8e930b..3b26a1dc2 100644 --- a/node/src/offlinesign.test.ts +++ b/node/src/offlinesign.test.ts @@ -76,6 +76,19 @@ describe('Offline sign', () => { expect(actual).toBe(expected.toString()); }); + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + + const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), expected); + const deserializedSignedProposal = gateway.newProposal(signedProposal.getBytes()); + await deserializedSignedProposal.evaluate(); + + const evaluateRequest = client.getEvaluateRequests()[0]; + const actual = Buffer.from(evaluateRequest.getProposedTransaction()?.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); + it('retains endorsing orgs', async () => { const expected = Buffer.from('MY_SIGNATURE'); @@ -108,6 +121,19 @@ describe('Offline sign', () => { expect(actual).toBe(expected.toString()); }); + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + + const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), expected); + const deserializedSignedProposal = gateway.newProposal(signedProposal.getBytes()); + await deserializedSignedProposal.endorse(); + + const endorseRequest = client.getEndorseRequests()[0]; + const actual = Buffer.from(endorseRequest.getProposedTransaction()?.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); + it('retains endorsing orgs', async () => { const expected = Buffer.from('MY_SIGNATURE'); @@ -143,6 +169,22 @@ describe('Offline sign', () => { const actual = Buffer.from(submitRequest.getPreparedTransaction()?.getSignature_asU8() ?? '').toString(); expect(actual).toBe(expected.toString()); }); + + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), Buffer.from('SIGNATURE')); + const unsignedTransaction = await signedProposal.endorse(); + + const signedTransaction = gateway.newSignedTransaction(unsignedTransaction.getBytes(), expected); + const deserializedSignedTransaction = gateway.newTransaction(signedTransaction.getBytes()); + await deserializedSignedTransaction.submit(); + + const submitRequest = client.getSubmitRequests()[0]; + const actual = Buffer.from(submitRequest.getPreparedTransaction()?.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); }); describe('commit', () => { @@ -171,6 +213,24 @@ describe('Offline sign', () => { const actual = Buffer.from(commitRequest.getSignature_asU8() ?? '').toString(); expect(actual).toBe(expected.toString()); }); + + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), Buffer.from('SIGNATURE')); + const unsignedTransaction = await signedProposal.endorse(); + const signedTransaction = gateway.newSignedTransaction(unsignedTransaction.getBytes(), Buffer.from('SIGNATURE')); + + const unsignedCommit = await signedTransaction.submit(); + const signedCommit = gateway.newSignedCommit(unsignedCommit.getBytes(), expected); + const deserializedSignedCommit = gateway.newCommit(signedCommit.getBytes()); + await deserializedSignedCommit.getStatus(); + + const commitRequest = client.getCommitStatusRequests()[0]; + const actual = Buffer.from(commitRequest.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); }); describe('chaincode events', () => { @@ -191,6 +251,19 @@ describe('Offline sign', () => { const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); expect(actual).toBe(expected.toString()); }); + + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + const unsignedRequest = network.newChaincodeEventsRequest('CHAINCODE_NAME'); + + const signedRequest = gateway.newSignedChaincodeEventsRequest(unsignedRequest.getBytes(), expected); + const deserializedSignedRequest = gateway.newChaincodeEventsRequest(signedRequest.getBytes()); + await deserializedSignedRequest.getEvents(); + + const eventsRequest = client.getChaincodeEventsRequests()[0]; + const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); }); describe('block events', () => { @@ -214,6 +287,22 @@ describe('Offline sign', () => { const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); expect(actual).toBe(expected.toString()); }); + + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + const stream = newDuplexStreamResponse([]); + client.mockBlockEventsResponse(stream); + + const unsignedRequest = network.newBlockEventsRequest(); + const signedRequest = gateway.newSignedBlockEventsRequest(unsignedRequest.getBytes(), expected); + const deserializedSignedRequest = gateway.newBlockEventsRequest(signedRequest.getBytes()); + await deserializedSignedRequest.getEvents(); + + expect(stream.write.mock.calls.length).toBe(1); + const eventsRequest = stream.write.mock.calls[0][0]; + const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); }); describe('filtered block events', () => { @@ -237,6 +326,22 @@ describe('Offline sign', () => { const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); expect(actual).toBe(expected.toString()); }); + + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + const stream = newDuplexStreamResponse([]); + client.mockFilteredBlockEventsResponse(stream); + + const unsignedRequest = network.newFilteredBlockEventsRequest(); + const signedRequest = gateway.newSignedFilteredBlockEventsRequest(unsignedRequest.getBytes(), expected); + const deserializedSignedRequest = gateway.newFilteredBlockEventsRequest(signedRequest.getBytes()); + await deserializedSignedRequest.getEvents(); + + expect(stream.write.mock.calls.length).toBe(1); + const eventsRequest = stream.write.mock.calls[0][0]; + const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); }); describe('block and private data events', () => { @@ -260,6 +365,22 @@ describe('Offline sign', () => { const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); expect(actual).toBe(expected.toString()); }); + + it('retains signature', async () => { + const expected = Buffer.from('MY_SIGNATURE'); + const stream = newDuplexStreamResponse([]); + client.mockBlockAndPrivateDataEventsResponse(stream); + + const unsignedRequest = network.newBlockAndPrivateDataEventsRequest(); + const signedRequest = gateway.newSignedBlockAndPrivateDataEventsRequest(unsignedRequest.getBytes(), expected); + const deserializedSignedRequest = gateway.newBlockAndPrivateDataEventsRequest(signedRequest.getBytes()); + await deserializedSignedRequest.getEvents(); + + expect(stream.write.mock.calls.length).toBe(1); + const eventsRequest = stream.write.mock.calls[0][0]; + const actual = Buffer.from(eventsRequest.getSignature_asU8() ?? '').toString(); + expect(actual).toBe(expected.toString()); + }); }); describe('serialization', () => { @@ -283,6 +404,16 @@ describe('Offline sign', () => { expect(actual).toEqual(expected); }); + it('proposal keeps same digest during deserialization', () => { + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const expected = unsignedProposal.getDigest(); + + const newProposal = gateway.newProposal(unsignedProposal.getBytes()); + const actual = newProposal.getDigest(); + + expect(actual).toEqual(expected); + }); + it('transaction keeps same digest', async () => { const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), Buffer.from('SIGNATURE')); @@ -295,6 +426,18 @@ describe('Offline sign', () => { expect(actual).toEqual(expected); }); + it('transaction keeps same digest during deserialization', async () => { + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), Buffer.from('SIGNATURE')); + const unsignedTransaction = await signedProposal.endorse(); + const expected = unsignedTransaction.getDigest(); + + const newTransaction = gateway.newTransaction(unsignedTransaction.getBytes()); + const actual = newTransaction.getDigest(); + + expect(actual).toEqual(expected); + }); + it('transaction keeps same transaction ID', async () => { const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), Buffer.from('SIGNATURE')); @@ -335,6 +478,20 @@ describe('Offline sign', () => { expect(actual).toEqual(expected); }); + it('commit keeps same digest during deserialization', async () => { + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const signedProposal = gateway.newSignedProposal(unsignedProposal.getBytes(), Buffer.from('SIGNATURE')); + const unsignedTransaction = await signedProposal.endorse(); + const signedTransaction = gateway.newSignedTransaction(unsignedTransaction.getBytes(), Buffer.from('SIGNATURE')); + const unsignedCommit = await signedTransaction.submit(); + const expected = unsignedCommit.getDigest(); + + const newCommit = gateway.newCommit(unsignedCommit.getBytes()); + const actual = newCommit.getDigest(); + + expect(actual).toEqual(expected); + }); + it('chaincode events request keeps same digest', () => { const unsignedRequest = network.newChaincodeEventsRequest('CHAINCODE_NAME'); const expected = unsignedRequest.getDigest(); @@ -355,6 +512,16 @@ describe('Offline sign', () => { expect(actual).toEqual(expected); }); + it('block events request keeps same digest during deserialization', () => { + const unsignedRequest = network.newBlockEventsRequest(); + const expected = unsignedRequest.getDigest(); + + const newRequest = gateway.newBlockEventsRequest(unsignedRequest.getBytes()); + const actual = newRequest.getDigest(); + + expect(actual).toEqual(expected); + }); + it('filtered block events request keeps same digest', () => { const unsignedRequest = network.newFilteredBlockEventsRequest(); const expected = unsignedRequest.getDigest(); @@ -365,6 +532,16 @@ describe('Offline sign', () => { expect(actual).toEqual(expected); }); + it('filtered block events request keeps same digest during deserialization', () => { + const unsignedRequest = network.newFilteredBlockEventsRequest(); + const expected = unsignedRequest.getDigest(); + + const newRequest = gateway.newFilteredBlockEventsRequest(unsignedRequest.getBytes()); + const actual = newRequest.getDigest(); + + expect(actual).toEqual(expected); + }); + it('block and private data events request keeps same digest', () => { const unsignedRequest = network.newBlockAndPrivateDataEventsRequest(); const expected = unsignedRequest.getDigest(); @@ -374,5 +551,15 @@ describe('Offline sign', () => { expect(actual).toEqual(expected); }); + + it('block and private data events request keeps same digest during deserialization', () => { + const unsignedRequest = network.newBlockAndPrivateDataEventsRequest(); + const expected = unsignedRequest.getDigest(); + + const request = gateway.newBlockAndPrivateDataEventsRequest(unsignedRequest.getBytes()); + const actual = request.getDigest(); + + expect(actual).toEqual(expected); + }); }); }); diff --git a/node/src/proposal.test.ts b/node/src/proposal.test.ts index d8bb4f9b8..c18b2e4c7 100644 --- a/node/src/proposal.test.ts +++ b/node/src/proposal.test.ts @@ -250,6 +250,17 @@ describe('Proposal', () => { expect(signature).toBe('MY_SIGNATURE'); }); + it('uses signer with newProposal', async () => { + signer.mockResolvedValue(Buffer.from('MY_SIGNATURE')); + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const newProposal = gateway.newProposal(unsignedProposal.getBytes()); + await newProposal.evaluate(); + + const evaluateRequest = client.getEvaluateRequests()[0]; + const signature = Buffer.from(evaluateRequest.getProposedTransaction()?.getSignature_asU8() ?? '').toString(); + expect(signature).toBe('MY_SIGNATURE'); + }); + it('uses hash', async () => { hash.mockReturnValue(Buffer.from('MY_DIGEST')); @@ -436,6 +447,17 @@ describe('Proposal', () => { expect(signature).toBe('MY_SIGNATURE'); }); + it('uses signer with newProposal', async () => { + signer.mockResolvedValue(Buffer.from('MY_SIGNATURE')); + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const newProposal = gateway.newProposal(unsignedProposal.getBytes()); + await newProposal.endorse(); + + const endorseRequest = client.getEndorseRequests()[0]; + const signature = Buffer.from(endorseRequest.getProposedTransaction()?.getSignature_asU8() ?? '').toString(); + expect(signature).toBe('MY_SIGNATURE'); + }); + it('uses hash', async () => { hash.mockReturnValue(Buffer.from('MY_DIGEST')); diff --git a/node/src/transaction.test.ts b/node/src/transaction.test.ts index 85e2c7679..b57e6c321 100644 --- a/node/src/transaction.test.ts +++ b/node/src/transaction.test.ts @@ -158,6 +158,20 @@ describe('Transaction', () => { expect(signature).toBe('MY_SIGNATURE'); }); + it('uses signer with newTransaction', async () => { + signer.mockResolvedValue(Buffer.from('MY_SIGNATURE')); + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const signedProposal = gateway.newProposal(unsignedProposal.getBytes()); + const unsignedTransaction = await signedProposal.endorse(); + + const signedTransaction = gateway.newTransaction(unsignedTransaction.getBytes()); + await signedTransaction.submit(); + + const submitRequest = client.getSubmitRequests()[0]; + const signature = Buffer.from(submitRequest.getPreparedTransaction()?.getSignature_asU8() ?? '').toString(); + expect(signature).toBe('MY_SIGNATURE'); + }); + it('uses signer for commit', async () => { signer.mockResolvedValue(Buffer.from('MY_SIGNATURE')); @@ -168,6 +182,23 @@ describe('Transaction', () => { expect(signature).toBe('MY_SIGNATURE'); }); + it('uses signer for newCommit', async () => { + signer.mockResolvedValue(Buffer.from('MY_SIGNATURE')); + + const unsignedProposal = contract.newProposal('TRANSACTION_NAME'); + const signedProposal = gateway.newProposal(unsignedProposal.getBytes()); + const unsignedTransaction = await signedProposal.endorse(); + + const signedTransaction = gateway.newTransaction(unsignedTransaction.getBytes()); + const unsignedCommit = await signedTransaction.submit(); + const deserializedSignedCommit = gateway.newCommit(unsignedCommit.getBytes()); + await deserializedSignedCommit.getStatus(); + + const statusRequest = client.getCommitStatusRequests()[0]; + const signature = Buffer.from(statusRequest.getSignature() ?? '').toString(); + expect(signature).toBe('MY_SIGNATURE'); + }); + it('uses hash', async () => { hash.mockReturnValue(Buffer.from('MY_DIGEST'));