Skip to content
This repository was archived by the owner on Nov 9, 2022. It is now read-only.

Commit 0aef784

Browse files
committed
ANS Caching and Verification (#72)
1 parent 366f6c9 commit 0aef784

File tree

7 files changed

+82
-15
lines changed

7 files changed

+82
-15
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@arweave/gateway",
3-
"version": "0.9.1",
3+
"version": "0.10.1",
44
"main": "dist/src/Gateway.js",
55
"repository": "git@github.com:ArweaveTeam/gateway.git",
66
"author": "Arweave <hello@arweave.org>",
@@ -15,6 +15,7 @@
1515
"dev:restart": "npm run migrate:down && npm run migrate:latest && npm run dev:start",
1616
"import:transaction": "npm run dev:build && node dist/src/import/transaction.import.js",
1717
"import:tags": "npm run dev:build && node dist/src/import/tags.import.ts",
18+
"verify:ans": "npm run dev:build && node dist/src/caching/ans.verify.js",
1819
"verify:prune": "npm run dev:build && node dist/src/verify/prune.verify.js",
1920
"verify:transaction": "npm run dev:build && node dist/src/verify/transaction.verify.js",
2021
"migrate:down": "knex migrate:down",

src/caching/ans.caching.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {DataItemJson} from 'arweave-bundles';
33
import {ansBundles} from '../utility/ans.utility';
44
import {getDataFromChunks} from '../query/node.query';
55
import {tagToUTF8} from '../query/transaction.query';
6+
import {cacheANSEntries} from './ans.entry.caching';
67

78
export async function streamAndCacheAns(id: string): Promise<boolean> {
89
try {
@@ -24,12 +25,14 @@ export async function streamAndCacheAns(id: string): Promise<boolean> {
2425
signature: ansTx.signature,
2526
tags: tagToUTF8(ansTx.tags),
2627
};
27-
28+
2829
ansTxsConverted.push(newAnsTx);
2930
}
3031

3132
write(`${process.cwd()}/cache/tx/${id}`, JSON.stringify(ansTxsConverted, null, 2));
3233

34+
await cacheANSEntries(ansTxs);
35+
3336
return true;
3437
} catch (error) {
3538
remove(`${process.cwd()}/cache/tx/${id}`);

src/caching/ans.entry.caching.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {exists, write} from 'fs-jetpack';
2+
import {DataItemJson} from 'arweave-bundles';
3+
import {b64UrlToBuffer} from '../utility/encoding.utility';
4+
5+
export async function cacheANSEntries(entries: Array<DataItemJson>) {
6+
for (let i = 0; i < entries.length; i++) {
7+
const entry = entries[i];
8+
const id = entry.id;
9+
const data = entry.data;
10+
11+
const bufferData = Buffer.from(b64UrlToBuffer(data));
12+
13+
if (exists(`${process.cwd()}/cache/tx/${id}`) === false) {
14+
write(`${process.cwd()}/cache/tx/${id}`, bufferData.toString('utf-8'));
15+
}
16+
}
17+
}

src/caching/ans.verify.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'colors';
2+
import {connection} from '../database/connection.database';
3+
import {toB64url} from '../query/transaction.query';
4+
import {cacheAnsFile} from './file.caching';
5+
6+
const name = toB64url('Bundle-Type');
7+
const value = toB64url('ANS-102');
8+
9+
export async function ansVerify(offset: number = 0) {
10+
const query = await connection
11+
.queryBuilder()
12+
.select('*')
13+
.from('tags')
14+
.where('name', name)
15+
.where('value', value)
16+
.orderByRaw('created_at ASC')
17+
.limit(10)
18+
.offset(offset);
19+
20+
for (let i = 0; i < query.length; i++) {
21+
const item = query[i];
22+
23+
try {
24+
await cacheAnsFile(item.tx_id);
25+
} catch (error) {
26+
console.log(`Could not cache ${item.tx_id}`.red);
27+
}
28+
}
29+
30+
console.log(`Successfully cached ANS bundles at offset ${offset}`.green);
31+
32+
if (query.length === 0) {
33+
console.log(`Successfully cached all ANS bundles. Good work!`.green.bold);
34+
process.exit();
35+
} else {
36+
ansVerify(offset + 10);
37+
}
38+
}
39+
40+
(async () => await ansVerify())();

src/database/sync.database.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {transaction, tagValue, Tag} from '../query/transaction.query';
1515
import {getDataFromChunks} from '../query/node.query';
1616
import {importBlocks, importTransactions, importTags} from './import.database';
1717
import {DatabaseTag} from './transaction.database';
18+
import {cacheANSEntries} from '../caching/ans.entry.caching';
1819

1920
config();
2021
mkdir('snapshot');
@@ -202,6 +203,7 @@ export async function processAns(id: string, height: number, retry: boolean = tr
202203
const ansPayload = await getDataFromChunks(id);
203204
const ansTxs = await ansBundles.unbundleData(ansPayload.toString('utf-8'));
204205

206+
await cacheANSEntries(ansTxs);
205207
await processANSTransaction(ansTxs, height);
206208
} catch (error) {
207209
if (retry) {

src/query/node.query.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export async function getDataFromChunks(id: string, retry: boolean = true): Prom
6262
} catch (error) {
6363
if (retry) {
6464
console.error(`error retrieving data from ${id}, please note that this may be a cancelled transaction`.red.bold);
65-
return await getDataFromChunks(id, true);
65+
return await getDataFromChunks(id, false);
6666
} else {
6767
throw error;
6868
}

src/route/data.route.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,27 @@ export async function dataRoute(req: Request, res: Response) {
3232
}
3333
}
3434

35-
const metadata = await getTransaction(transaction);
36-
const contentType = tagValue(metadata.tags, 'Content-Type');
37-
const ans102 = tagValue(metadata.tags, 'Bundle-Type') === 'ANS-102';
38-
39-
res.setHeader('content-type', contentType);
40-
41-
if (ans102) {
42-
await cacheAnsFile(transaction);
43-
} else {
44-
await cacheFile(transaction);
45-
}
35+
try {
36+
const metadata = await getTransaction(transaction);
37+
const contentType = tagValue(metadata.tags, 'Content-Type');
38+
const ans102 = tagValue(metadata.tags, 'Bundle-Type') === 'ANS-102';
39+
40+
res.setHeader('content-type', contentType);
41+
42+
if (ans102) {
43+
await cacheAnsFile(transaction);
44+
} else {
45+
await cacheFile(transaction);
46+
}
47+
} catch (error) {
48+
49+
}
4650

4751
if (exists(`${process.cwd()}/cache/tx/${transaction}`)) {
4852
res.status(200);
4953
res.sendFile(`${process.cwd()}/cache/tx/${transaction}`);
5054
} else {
5155
res.status(500);
52-
res.json({status: 'ERROR', message: 'Could not retrieve tx, please retry'});
56+
res.json({status: 'ERROR', message: 'Could not retrieve transaction'});
5357
}
5458
}

0 commit comments

Comments
 (0)