Skip to content

Commit

Permalink
fix: modify return type of signDataItem function, tweak implementatio…
Browse files Browse the repository at this point in the history
…n of ArweaveSigner header
  • Loading branch information
dtfiedler committed Sep 22, 2023
1 parent e9f8116 commit 305312b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 19 deletions.
6 changes: 4 additions & 2 deletions src/common/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,21 @@ export class TurboAuthenticatedUploadService
signal,
}: TurboFileFactory &
TurboAbortSignal): Promise<TurboUploadDataItemResponse> {
const { signedDataItem, signedDataItemSize } =
const { dataItemStreamFactory, dataItemSizeFactory } =
await this.signer.signDataItem({
fileStreamFactory,
fileSizeFactory,
});
const signedDataItem = dataItemStreamFactory();
const fileSize = dataItemSizeFactory();
// TODO: add p-limit constraint or replace with separate upload class
return this.httpService.post<TurboUploadDataItemResponse>({
endpoint: `/tx`,
signal,
data: signedDataItem,
headers: {
'content-type': 'application/octet-stream',
'content-length': `${signedDataItemSize}`,
'content-length': `${fileSize}`,
},
});
}
Expand Down
42 changes: 33 additions & 9 deletions src/node/signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ import { randomBytes } from 'node:crypto';
import { Readable } from 'node:stream';

import { JWKInterface } from '../common/jwk.js';
import { TurboWalletSigner } from '../types.js';
import { StreamSizeFactory, TurboWalletSigner } from '../types.js';
import { toB64Url } from '../utils/base64.js';

// TODO: is this deterministic for arweave wallets?
export const SIGNED_DATA_ITEM_HEADERS_SIZE = 1044;

export class TurboNodeArweaveSigner implements TurboWalletSigner {
protected privateKey: JWKInterface;
protected signer: ArweaveSigner; // TODO: replace with internal signer class
Expand All @@ -41,17 +38,20 @@ export class TurboNodeArweaveSigner implements TurboWalletSigner {
fileSizeFactory,
}: {
fileStreamFactory: () => Readable;
fileSizeFactory: () => number;
fileSizeFactory: StreamSizeFactory;
}): Promise<{
signedDataItem: Readable;
signedDataItemSize: number;
dataItemStreamFactory: () => Readable;
dataItemSizeFactory: StreamSizeFactory;
}> {
// TODO: replace with our own signer implementation
const [stream1, stream2] = [fileStreamFactory(), fileStreamFactory()];
const signedDataItem = await streamSigner(stream1, stream2, this.signer);
const signedDataItemSize = this.calculateSignedDataHeadersSize({
dataSize: fileSizeFactory(),
});
return {
signedDataItem: signedDataItem,
signedDataItemSize: fileSizeFactory() + SIGNED_DATA_ITEM_HEADERS_SIZE,
dataItemStreamFactory: () => signedDataItem,
dataItemSizeFactory: () => signedDataItemSize,
};
}

Expand All @@ -67,4 +67,28 @@ export class TurboNodeArweaveSigner implements TurboWalletSigner {
'x-signature': toB64Url(Buffer.from(signature)),
};
}

// TODO: make dynamic that accepts anchor and target and tags to return the size of the headers + data
// reference https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md#13-dataitem-format
private calculateSignedDataHeadersSize({ dataSize }: { dataSize: number }) {
const anchor = 1; // + whatever they provide (max of 33)
const target = 1; // + whatever they provide (max of 33)
const tags = 0;
const signatureLength = 512;
const ownerLength = 512;
const signatureTypeLength = 2;
const numOfTagsLength = 8; // https://github.com/Bundlr-Network/arbundles/blob/master/src/tags.ts#L191-L198
const numOfTagsBytesLength = 8;
return [
anchor,
target,
tags,
signatureLength,
ownerLength,
signatureTypeLength,
numOfTagsLength,
numOfTagsBytesLength,
dataSize,
].reduce((totalSize, currentSize) => (totalSize += currentSize));
}
}
5 changes: 1 addition & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,7 @@ export interface TurboWalletSigner {
signDataItem({
fileStreamFactory,
fileSizeFactory,
}: TurboFileFactory): Promise<{
signedDataItem: Readable | Buffer;
signedDataItemSize: number;
}>;
}: TurboFileFactory): Promise<TurboSignedDataItemFactory>;
generateSignedRequestHeaders(): Promise<TurboSignedRequestHeaders>;
}

Expand Down
9 changes: 5 additions & 4 deletions src/web/signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ export class TurboWebArweaveSigner implements TurboWalletSigner {
fileStreamFactory: () => ReadableStream;
fileSizeFactory: StreamSizeFactory;
}): Promise<{
signedDataItem: Buffer;
signedDataItemSize: number;
// axios only supports Readables, Buffers, or Blobs - so we need to convert the stream to a buffer
dataItemStreamFactory: () => Buffer;
dataItemSizeFactory: StreamSizeFactory;
}> {
// TODO: converts the readable stream to a buffer bc incrementally signing ReadableStreams is not trivial
const buffer = await readableStreamToBuffer({
Expand All @@ -51,8 +52,8 @@ export class TurboWebArweaveSigner implements TurboWalletSigner {
const signedDataItem = createData(buffer, this.signer);
await signedDataItem.sign(this.signer);
return {
signedDataItem: signedDataItem.getRaw(),
signedDataItemSize: signedDataItem.getRaw().length,
dataItemStreamFactory: () => signedDataItem.getRaw(),
dataItemSizeFactory: () => signedDataItem.getRaw().length,
};
}

Expand Down

0 comments on commit 305312b

Please sign in to comment.