Skip to content

Commit 13dac37

Browse files
committed
Use transferable objects for signing worker communication
Transfer content buffer to worker and signature buffer back to main thread instead of copying, improving performance for large messages.
1 parent 3e84fc6 commit 13dac37

File tree

3 files changed

+31
-17
lines changed

3 files changed

+31
-17
lines changed

packages/sdk/src/signature/SigningService.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* The worker is lazily initialized on first use and shared across all MessageSigner instances.
77
*/
8-
import { wrap, releaseProxy, type Remote } from 'comlink'
8+
import { wrap, releaseProxy, transfer, type Remote } from 'comlink'
99
import { Lifecycle, scoped } from 'tsyringe'
1010
import { createSigningWorker } from '@/createSigningWorker'
1111
import { SigningResult, SigningRequest } from './signingUtils'
@@ -30,7 +30,9 @@ export class SigningService {
3030
}
3131

3232
async sign(request: SigningRequest): Promise<SigningResult> {
33-
return this.getWorkerApi().createSignature(request)
33+
return this.getWorkerApi().createSignature(
34+
transfer(request, [request.payloadInput.content.buffer])
35+
)
3436
}
3537

3638
destroy(): void {

packages/sdk/src/signature/SigningWorker.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expose } from 'comlink'
1+
import { expose, transfer } from 'comlink'
22
import {
33
createSignatureFromData,
44
SigningResult,
@@ -9,7 +9,11 @@ const workerApi = {
99
createSignature: async (
1010
request: SigningRequest
1111
): Promise<SigningResult> => {
12-
return createSignatureFromData(request)
12+
const result = await createSignatureFromData(request)
13+
if (result.type === 'success') {
14+
return transfer(result, [result.signature.buffer])
15+
}
16+
return result
1317
},
1418
}
1519

packages/sdk/test/unit/SigningService.test.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,29 @@ describe('SigningService', () => {
2626
const privateKey = identity.getPrivateKey()
2727
const publisherId = await identity.getUserId()
2828

29-
const payloadInput = {
30-
messageId: {
31-
streamId: toStreamID('test-stream'),
32-
streamPartition: 0,
33-
timestamp: Date.now(),
34-
sequenceNumber: 0,
35-
publisherId,
36-
msgChainId: 'test-chain'
37-
},
38-
content: utf8ToBinary(JSON.stringify({ hello: 'world' })),
39-
messageType: StreamMessageType.MESSAGE
29+
const content = utf8ToBinary(JSON.stringify({ hello: 'world' }))
30+
const messageId = {
31+
streamId: toStreamID('test-stream'),
32+
streamPartition: 0,
33+
timestamp: Date.now(),
34+
sequenceNumber: 0,
35+
publisherId,
36+
msgChainId: 'test-chain'
4037
}
4138

4239
const request: SigningRequest = {
43-
payloadInput,
40+
payloadInput: {
41+
messageId,
42+
content,
43+
messageType: StreamMessageType.MESSAGE
44+
},
4445
privateKey,
4546
signatureType: SignatureType.ECDSA_SECP256K1_EVM
4647
}
4748

49+
// Copy content before signing since the buffer is transferred to the worker
50+
const contentCopy = new Uint8Array(content)
51+
4852
const result = await signingService.sign(request)
4953

5054
if (result.type !== 'success') {
@@ -54,7 +58,11 @@ describe('SigningService', () => {
5458
expect(result.signature.length).toBeGreaterThan(0)
5559

5660
// Verify the signature is valid by checking it against the payload
57-
const payload = createSignaturePayload(payloadInput)
61+
const payload = createSignaturePayload({
62+
messageId,
63+
content: contentCopy,
64+
messageType: StreamMessageType.MESSAGE
65+
})
5866
const signingUtil = new EcdsaSecp256k1Evm()
5967
const isValid = await signingUtil.verifySignature(await identity.getUserIdRaw(), payload, result.signature)
6068
expect(isValid).toBe(true)

0 commit comments

Comments
 (0)