@ar.io/wayfinder-core 0.0.3-alpha.2 → 0.0.3-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/classifiers/gql-classifier.d.ts +30 -0
- package/dist/classifiers/gql-classifier.d.ts.map +1 -0
- package/dist/classifiers/gql-classifier.js +45 -0
- package/dist/gateways/network.d.ts +1 -4
- package/dist/gateways/network.d.ts.map +1 -1
- package/dist/gateways/network.js +1 -1
- package/dist/gateways/simple-cache.d.ts.map +1 -1
- package/dist/gateways/static.d.ts +1 -4
- package/dist/gateways/static.d.ts.map +1 -1
- package/dist/gateways/static.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/routing/ping.js +1 -1
- package/dist/utils/hash.d.ts.map +1 -1
- package/dist/utils/hash.js +1 -1
- package/dist/verification/data-root-verifier.d.ts +4 -2
- package/dist/verification/data-root-verifier.d.ts.map +1 -1
- package/dist/verification/data-root-verifier.js +12 -1
- package/dist/verification/signature-verifier.d.ts +117 -0
- package/dist/verification/signature-verifier.d.ts.map +1 -0
- package/dist/verification/signature-verifier.js +362 -0
- package/dist/wayfinder.d.ts +3 -2
- package/dist/wayfinder.d.ts.map +1 -1
- package/dist/wayfinder.js +13 -12
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WayFinder
|
|
3
|
+
* Copyright (C) 2022-2025 Permanent Data Solutions, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { DataClassifier } from '../../types/wayfinder.js';
|
|
18
|
+
import { Logger } from '../wayfinder.js';
|
|
19
|
+
export declare class GqlClassifier implements DataClassifier {
|
|
20
|
+
private readonly gqlEndpoint;
|
|
21
|
+
private readonly logger;
|
|
22
|
+
constructor({ gqlEndpoint, logger, }?: {
|
|
23
|
+
gqlEndpoint?: string;
|
|
24
|
+
logger?: Logger;
|
|
25
|
+
});
|
|
26
|
+
classify({ txId, }: {
|
|
27
|
+
txId: string;
|
|
28
|
+
}): Promise<'ans104' | 'transaction'>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=gql-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gql-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/gql-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAExD,qBAAa,aAAc,YAAW,cAAc;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAM;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,EACV,WAA0D,EAC1D,MAAsB,GACvB,GAAE;QACD,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACZ;IAKA,QAAQ,CAAC,EACb,IAAI,GACL,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC;CAuCxD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defaultLogger } from '../wayfinder.js';
|
|
2
|
+
export class GqlClassifier {
|
|
3
|
+
gqlEndpoint;
|
|
4
|
+
logger;
|
|
5
|
+
constructor({ gqlEndpoint = 'https://arweave-search.goldsky.com/graphql', logger = defaultLogger, } = {}) {
|
|
6
|
+
this.gqlEndpoint = new URL(gqlEndpoint);
|
|
7
|
+
this.logger = logger;
|
|
8
|
+
}
|
|
9
|
+
async classify({ txId, }) {
|
|
10
|
+
const response = await fetch(this.gqlEndpoint.toString(), {
|
|
11
|
+
method: 'POST',
|
|
12
|
+
headers: {
|
|
13
|
+
'Content-Type': 'application/json',
|
|
14
|
+
},
|
|
15
|
+
body: JSON.stringify({
|
|
16
|
+
query: `
|
|
17
|
+
query GetTransaction($id: ID!) {
|
|
18
|
+
transactions(ids: [$id]) {
|
|
19
|
+
edges {
|
|
20
|
+
node {
|
|
21
|
+
bundledIn {
|
|
22
|
+
id
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
`,
|
|
29
|
+
variables: {
|
|
30
|
+
id: txId,
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
this.logger.debug('Failed to fetch transaction from GraphQL', {
|
|
36
|
+
txId,
|
|
37
|
+
status: response.status,
|
|
38
|
+
});
|
|
39
|
+
return 'transaction';
|
|
40
|
+
}
|
|
41
|
+
const result = await response.json();
|
|
42
|
+
const bundledIn = result.data?.transaction?.bundledIn;
|
|
43
|
+
return bundledIn ? 'ans104' : 'transaction';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -33,9 +33,6 @@ export declare class NetworkGatewaysProvider implements GatewaysProvider {
|
|
|
33
33
|
filter?: (gateway: any) => boolean;
|
|
34
34
|
logger?: Logger;
|
|
35
35
|
});
|
|
36
|
-
getGateways(
|
|
37
|
-
path?: string;
|
|
38
|
-
subdomain?: string;
|
|
39
|
-
}): Promise<URL[]>;
|
|
36
|
+
getGateways(): Promise<URL[]>;
|
|
40
37
|
}
|
|
41
38
|
//# sourceMappingURL=network.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/gateways/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAExD,qBAAa,uBAAwB,YAAW,gBAAgB;IAC9D,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,MAAM,CAA6D;IAC3E,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,MAAM,CAAS;gBAEX,EACV,IAAI,EACJ,MAAwB,EACxB,SAAkB,EAClB,KAAY,EACZ,MAAqC,EACrC,MAAsB,GACvB,EAAE;QACD,IAAI,EAAE,YAAY,CAAC;QACnB,MAAM,CAAC,EAAE,qBAAqB,GAAG,eAAe,GAAG,gBAAgB,CAAC;QACpE,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;QAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC;QACnC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IASK,WAAW,
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/gateways/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAExD,qBAAa,uBAAwB,YAAW,gBAAgB;IAC9D,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,MAAM,CAA6D;IAC3E,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,MAAM,CAAS;gBAEX,EACV,IAAI,EACJ,MAAwB,EACxB,SAAkB,EAClB,KAAY,EACZ,MAAqC,EACrC,MAAsB,GACvB,EAAE;QACD,IAAI,EAAE,YAAY,CAAC;QACnB,MAAM,CAAC,EAAE,qBAAqB,GAAG,eAAe,GAAG,gBAAgB,CAAC;QACpE,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;QAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC;QACnC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IASK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;CA0DpC"}
|
package/dist/gateways/network.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-cache.d.ts","sourceRoot":"","sources":["../../src/gateways/simple-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAExD,qBAAa,2BAA4B,YAAW,gBAAgB;IAClE,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAS;gBAEX,EACV,gBAAgB,EAChB,UAAoB,EAAE,SAAS;IAC/B,MAAsB,GACvB,EAAE;QACD,gBAAgB,EAAE,gBAAgB,CAAC;QACnC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAQK,WAAW,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"simple-cache.d.ts","sourceRoot":"","sources":["../../src/gateways/simple-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAExD,qBAAa,2BAA4B,YAAW,gBAAgB;IAClE,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAS;gBAEX,EACV,gBAAgB,EAChB,UAAoB,EAAE,SAAS;IAC/B,MAAsB,GACvB,EAAE;QACD,gBAAgB,EAAE,gBAAgB,CAAC;QACnC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAQK,WAAW,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CACxE,GAAG,EAAE,CACN;CAmCF"}
|
|
@@ -20,9 +20,6 @@ export declare class StaticGatewaysProvider implements GatewaysProvider {
|
|
|
20
20
|
constructor({ gateways }: {
|
|
21
21
|
gateways: string[];
|
|
22
22
|
});
|
|
23
|
-
getGateways(
|
|
24
|
-
path?: string;
|
|
25
|
-
subdomain?: string;
|
|
26
|
-
}): Promise<URL[]>;
|
|
23
|
+
getGateways(): Promise<URL[]>;
|
|
27
24
|
}
|
|
28
25
|
//# sourceMappingURL=static.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/gateways/static.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,sBAAuB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,QAAQ,CAAQ;gBACZ,EAAE,QAAQ,EAAE,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE;IAI1C,WAAW,
|
|
1
|
+
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/gateways/static.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,sBAAuB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,QAAQ,CAAQ;gBACZ,EAAE,QAAQ,EAAE,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE;IAI1C,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;CAGpC"}
|
package/dist/gateways/static.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -25,4 +25,5 @@ export * from './gateways/simple-cache.js';
|
|
|
25
25
|
export * from './gateways/static.js';
|
|
26
26
|
export * from './verification/data-root-verifier.js';
|
|
27
27
|
export * from './verification/hash-verifier.js';
|
|
28
|
+
export * from './verification/signature-verifier.js';
|
|
28
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sCAAsC,CAAC;AAGrD,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AAGrC,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sCAAsC,CAAC;AAGrD,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AAGrC,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/routing/ping.js
CHANGED
package/dist/utils/hash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAGxD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI,aAAa,CAAC,UAAU,CAAC,CAQlC;AAED,wBAAuB,6BAA6B,CAClD,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GACjC,aAAa,CAAC,UAAU,CAAC,CAa3B;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,MAAM,EACN,
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAGxD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI,aAAa,CAAC,UAAU,CAAC,CAQlC;AAED,wBAAuB,6BAA6B,CAClD,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GACjC,aAAa,CAAC,UAAU,CAAC,CAa3B;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,MAAM,EACN,SAAoB,EACpB,MAAsB,GACvB,EAAE;IACD,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA2C9B"}
|
package/dist/utils/hash.js
CHANGED
|
@@ -39,7 +39,7 @@ export async function* readableStreamToAsyncIterable(stream) {
|
|
|
39
39
|
reader.releaseLock();
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
export async function hashDataStreamToB64Url({ stream, algorithm = '
|
|
42
|
+
export async function hashDataStreamToB64Url({ stream, algorithm = 'sha256', logger = defaultLogger, }) {
|
|
43
43
|
try {
|
|
44
44
|
logger.debug('Starting to hash data stream', {
|
|
45
45
|
algorithm,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataStream, VerificationStrategy } from '../../types/wayfinder.js';
|
|
1
|
+
import { DataClassifier, DataStream, VerificationStrategy } from '../../types/wayfinder.js';
|
|
2
2
|
import { Logger } from '../wayfinder.js';
|
|
3
3
|
export declare const convertDataStreamToDataRoot: ({ stream, }: {
|
|
4
4
|
stream: DataStream;
|
|
@@ -7,10 +7,12 @@ export declare class DataRootVerificationStrategy implements VerificationStrateg
|
|
|
7
7
|
private readonly trustedGateways;
|
|
8
8
|
private readonly maxConcurrency;
|
|
9
9
|
private readonly logger;
|
|
10
|
-
|
|
10
|
+
private readonly classifier;
|
|
11
|
+
constructor({ trustedGateways, maxConcurrency, logger, classifier, }: {
|
|
11
12
|
trustedGateways: URL[];
|
|
12
13
|
maxConcurrency?: number;
|
|
13
14
|
logger?: Logger;
|
|
15
|
+
classifier?: DataClassifier;
|
|
14
16
|
});
|
|
15
17
|
/**
|
|
16
18
|
* Get the data root for a given txId from all trusted gateways and ensure they all match.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-root-verifier.d.ts","sourceRoot":"","sources":["../../src/verification/data-root-verifier.ts"],"names":[],"mappings":"AA0BA,OAAO,
|
|
1
|
+
{"version":3,"file":"data-root-verifier.d.ts","sourceRoot":"","sources":["../../src/verification/data-root-verifier.ts"],"names":[],"mappings":"AA0BA,OAAO,EACL,cAAc,EACd,UAAU,EACV,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,MAAM,EAAiB,MAAM,iBAAiB,CAAC;AAExD,eAAO,MAAM,2BAA2B,GAAU,aAE/C;IACD,MAAM,EAAE,UAAU,CAAC;CACpB,KAAG,OAAO,CAAC,MAAM,CAwDjB,CAAC;AAGF,qBAAa,4BAA6B,YAAW,oBAAoB;IACvE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;gBAChC,EACV,eAAe,EACf,cAAkB,EAClB,MAAsB,EACtB,UAA0C,GAC3C,EAAE;QACD,eAAe,EAAE,GAAG,EAAE,CAAC;QACvB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,cAAc,CAAC;KAC7B;IAOD;;;;OAIG;IACG,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAuCxD,UAAU,CAAC,EACf,IAAI,EACJ,IAAI,GACL,EAAE;QACD,IAAI,EAAE,UAAU,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;CA0BlB"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import Arweave from 'arweave';
|
|
18
18
|
import { MAX_CHUNK_SIZE, MIN_CHUNK_SIZE, buildLayers, generateLeaves, } from 'arweave/node/lib/merkle.js';
|
|
19
19
|
import { pLimit } from 'plimit-lit';
|
|
20
|
+
import { GqlClassifier } from '../classifiers/gql-classifier.js';
|
|
20
21
|
import { toB64Url } from '../utils/base64.js';
|
|
21
22
|
import { isAsyncIterable, readableStreamToAsyncIterable, } from '../utils/hash.js';
|
|
22
23
|
import { defaultLogger } from '../wayfinder.js';
|
|
@@ -64,14 +65,17 @@ export const convertDataStreamToDataRoot = async ({ stream, }) => {
|
|
|
64
65
|
const root = await buildLayers(leaves);
|
|
65
66
|
return toB64Url(new Uint8Array(root.id));
|
|
66
67
|
};
|
|
68
|
+
// TODO: this is a TransactionDataRootVerificationStrategy, we will hold of on implementing Ans104DataRootVerificationStrategy for now
|
|
67
69
|
export class DataRootVerificationStrategy {
|
|
68
70
|
trustedGateways;
|
|
69
71
|
maxConcurrency;
|
|
70
72
|
logger;
|
|
71
|
-
|
|
73
|
+
classifier;
|
|
74
|
+
constructor({ trustedGateways, maxConcurrency = 1, logger = defaultLogger, classifier = new GqlClassifier({ logger }), }) {
|
|
72
75
|
this.trustedGateways = trustedGateways;
|
|
73
76
|
this.maxConcurrency = maxConcurrency;
|
|
74
77
|
this.logger = logger;
|
|
78
|
+
this.classifier = classifier;
|
|
75
79
|
}
|
|
76
80
|
/**
|
|
77
81
|
* Get the data root for a given txId from all trusted gateways and ensure they all match.
|
|
@@ -111,6 +115,13 @@ export class DataRootVerificationStrategy {
|
|
|
111
115
|
return dataRoot;
|
|
112
116
|
}
|
|
113
117
|
async verifyData({ data, txId, }) {
|
|
118
|
+
// classify the data, if ans104 throw an error
|
|
119
|
+
const dataType = await this.classifier.classify({ txId });
|
|
120
|
+
if (dataType === 'ans104') {
|
|
121
|
+
throw new Error('ANS-104 data is not supported for data root verification', {
|
|
122
|
+
cause: { txId },
|
|
123
|
+
});
|
|
124
|
+
}
|
|
114
125
|
const [computedDataRoot, trustedDataRoot] = await Promise.all([
|
|
115
126
|
convertDataStreamToDataRoot({
|
|
116
127
|
stream: data,
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { DataClassifier, DataStream, VerificationStrategy } from '../../types/wayfinder.js';
|
|
2
|
+
import { Logger } from '../wayfinder.js';
|
|
3
|
+
/**
|
|
4
|
+
* Implementation of DataVerificationStrategy that verifies data item signatures
|
|
5
|
+
* using trusted gateways to provide the metadata needed for verification.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Ans104SignatureVerificationStrategy implements VerificationStrategy {
|
|
8
|
+
private readonly trustedGateways;
|
|
9
|
+
private readonly maxConcurrency;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
constructor({ trustedGateways, maxConcurrency, logger, }: {
|
|
12
|
+
trustedGateways: URL[];
|
|
13
|
+
maxConcurrency?: number;
|
|
14
|
+
logger?: Logger;
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Gets data item information from trusted gateways
|
|
18
|
+
*
|
|
19
|
+
* @param txId - The transaction ID to get information for
|
|
20
|
+
* @returns Object containing offsets and root transaction ID
|
|
21
|
+
*/
|
|
22
|
+
private getDataItemAttributes;
|
|
23
|
+
/**
|
|
24
|
+
* Fetches just the bytes header data of a data item from a trusted gateway needed for signature verification.
|
|
25
|
+
*
|
|
26
|
+
* @param txId - The transaction ID to get signature data for
|
|
27
|
+
* @returns The bytes containing the data item up to the data section
|
|
28
|
+
*/
|
|
29
|
+
getSignatureData({ txId, }: {
|
|
30
|
+
txId: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
signatureType: number;
|
|
33
|
+
signature: Uint8Array;
|
|
34
|
+
owner: Uint8Array;
|
|
35
|
+
target: Uint8Array;
|
|
36
|
+
anchor: Uint8Array;
|
|
37
|
+
tags: Uint8Array;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Verifies the signature of a data item using trusted gateways to get the signature data
|
|
41
|
+
* and then verifying it against the data payload.
|
|
42
|
+
*
|
|
43
|
+
* This implementation follows the ANS-104 standard for verifying data item signatures:
|
|
44
|
+
* 1. Get the signature data from the trusted gateway
|
|
45
|
+
* 2. Parse the signature components (owner, signature type, tags, etc.)
|
|
46
|
+
* 3. Calculate the deep hash of all components and the data
|
|
47
|
+
* 4. Verify the signature against the deep hash
|
|
48
|
+
*
|
|
49
|
+
* @param data - The data stream to verify
|
|
50
|
+
* @param txId - The transaction ID of the data
|
|
51
|
+
*/
|
|
52
|
+
verifyData({ data, txId, }: {
|
|
53
|
+
data: DataStream;
|
|
54
|
+
txId: string;
|
|
55
|
+
}): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Implementation of SignatureDataProvider that fetches signature data directly
|
|
59
|
+
* from a trusted gateway's /tx/<tx-id>/signature endpoint.
|
|
60
|
+
*/
|
|
61
|
+
export declare class TransactionSignatureVerificationStrategy implements VerificationStrategy {
|
|
62
|
+
private readonly trustedGateways;
|
|
63
|
+
private readonly logger;
|
|
64
|
+
constructor({ trustedGateways, logger, }: {
|
|
65
|
+
trustedGateways: URL[];
|
|
66
|
+
maxConcurrency?: number;
|
|
67
|
+
logger?: Logger;
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Fetches signature data directly from a trusted gateway's /tx/<tx-id>/signature endpoint.
|
|
71
|
+
*
|
|
72
|
+
* @param txId - The transaction ID to get signature data for
|
|
73
|
+
* @returns The signature data as a Uint8Array
|
|
74
|
+
*/
|
|
75
|
+
getSignatureData({ txId, }: {
|
|
76
|
+
txId: string;
|
|
77
|
+
}): Promise<{
|
|
78
|
+
format: number;
|
|
79
|
+
owner: string;
|
|
80
|
+
target: string;
|
|
81
|
+
anchor: string;
|
|
82
|
+
quantity: string;
|
|
83
|
+
reward: string;
|
|
84
|
+
dataRoot: string;
|
|
85
|
+
dataSize: number;
|
|
86
|
+
lastTx: string;
|
|
87
|
+
tags: {
|
|
88
|
+
name: string;
|
|
89
|
+
value: string;
|
|
90
|
+
}[];
|
|
91
|
+
signature: string;
|
|
92
|
+
}>;
|
|
93
|
+
verifyData({ data, txId, }: {
|
|
94
|
+
data: DataStream;
|
|
95
|
+
txId: string;
|
|
96
|
+
}): Promise<void>;
|
|
97
|
+
}
|
|
98
|
+
export declare const SignatureVerificationStrategies: {
|
|
99
|
+
ans104: typeof Ans104SignatureVerificationStrategy;
|
|
100
|
+
transaction: typeof TransactionSignatureVerificationStrategy;
|
|
101
|
+
};
|
|
102
|
+
export declare class SignatureVerificationStrategy {
|
|
103
|
+
private readonly ans104;
|
|
104
|
+
private readonly transaction;
|
|
105
|
+
private readonly classifier;
|
|
106
|
+
constructor({ trustedGateways, maxConcurrency, logger, classifier, }: {
|
|
107
|
+
trustedGateways: URL[];
|
|
108
|
+
maxConcurrency?: number;
|
|
109
|
+
logger?: Logger;
|
|
110
|
+
classifier?: DataClassifier;
|
|
111
|
+
});
|
|
112
|
+
verifyData({ data, txId, }: {
|
|
113
|
+
data: DataStream;
|
|
114
|
+
txId: string;
|
|
115
|
+
}): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=signature-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature-verifier.d.ts","sourceRoot":"","sources":["../../src/verification/signature-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WayFinder
|
|
3
|
+
* Copyright (C) 2022-2025 Permanent Data Solutions, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { Arweave, DataItem, deepHash, indexToType, stringToBuffer, } from '@dha-team/arbundles';
|
|
18
|
+
import { pLimit } from 'plimit-lit';
|
|
19
|
+
import { GqlClassifier } from '../classifiers/gql-classifier.js';
|
|
20
|
+
import { arioGatewayHeaders } from '../utils/ario.js';
|
|
21
|
+
import { fromB64Url } from '../utils/base64.js';
|
|
22
|
+
import { isAsyncIterable, readableStreamToAsyncIterable, } from '../utils/hash.js';
|
|
23
|
+
import { defaultLogger } from '../wayfinder.js';
|
|
24
|
+
import { convertDataStreamToDataRoot } from './data-root-verifier.js';
|
|
25
|
+
/**
|
|
26
|
+
* Implementation of DataVerificationStrategy that verifies data item signatures
|
|
27
|
+
* using trusted gateways to provide the metadata needed for verification.
|
|
28
|
+
*/
|
|
29
|
+
export class Ans104SignatureVerificationStrategy {
|
|
30
|
+
trustedGateways;
|
|
31
|
+
maxConcurrency;
|
|
32
|
+
logger;
|
|
33
|
+
constructor({ trustedGateways, maxConcurrency = 1, logger = defaultLogger, }) {
|
|
34
|
+
this.trustedGateways = trustedGateways;
|
|
35
|
+
this.maxConcurrency = maxConcurrency;
|
|
36
|
+
this.logger = logger;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Gets data item information from trusted gateways
|
|
40
|
+
*
|
|
41
|
+
* @param txId - The transaction ID to get information for
|
|
42
|
+
* @returns Object containing offsets and root transaction ID
|
|
43
|
+
*/
|
|
44
|
+
async getDataItemAttributes(txId) {
|
|
45
|
+
// Try each gateway until we get the information we need
|
|
46
|
+
const throttle = pLimit(this.maxConcurrency);
|
|
47
|
+
const dataItemAttributesPromises = this.trustedGateways.map(async (gateway) => {
|
|
48
|
+
return throttle(async () => {
|
|
49
|
+
// TODO: add sandbox support to the URL - useful to test against localhost with it disabled
|
|
50
|
+
// const sandbox = sandboxFromId(txId);
|
|
51
|
+
const url = `${gateway.protocol}//${gateway.hostname}:${gateway.port}/${txId}`;
|
|
52
|
+
// Make a HEAD request to get headers without fetching the full data
|
|
53
|
+
const response = await fetch(url, {
|
|
54
|
+
method: 'HEAD',
|
|
55
|
+
redirect: 'follow',
|
|
56
|
+
mode: 'cors',
|
|
57
|
+
headers: {
|
|
58
|
+
'Cache-Control': 'no-cache',
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error('Failed to fetch data item info from trusted gateway', {
|
|
63
|
+
cause: {
|
|
64
|
+
txId,
|
|
65
|
+
gateway: gateway.toString(),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const dataItemOffset = response.headers.get(arioGatewayHeaders.dataItemOffset);
|
|
70
|
+
const dataItemDataOffset = response.headers.get(arioGatewayHeaders.dataItemDataOffset);
|
|
71
|
+
const rootTransactionId = response.headers.get(arioGatewayHeaders.rootTransactionId);
|
|
72
|
+
const dataItemSize = response.headers.get(arioGatewayHeaders.dataItemSize);
|
|
73
|
+
// if any are undefined, throw an error
|
|
74
|
+
if (dataItemOffset &&
|
|
75
|
+
dataItemDataOffset &&
|
|
76
|
+
rootTransactionId &&
|
|
77
|
+
dataItemSize) {
|
|
78
|
+
throttle.clearQueue();
|
|
79
|
+
return {
|
|
80
|
+
gateway,
|
|
81
|
+
dataItemOffset: parseInt(dataItemOffset, 10),
|
|
82
|
+
dataItemDataOffset: parseInt(dataItemDataOffset, 10),
|
|
83
|
+
rootTransactionId,
|
|
84
|
+
dataItemSize: parseInt(dataItemSize, 10),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// if we get here, we didn't get the information we need from this gateway
|
|
88
|
+
throw new Error('Missing data item attributes from trusted gateway', {
|
|
89
|
+
cause: {
|
|
90
|
+
txId,
|
|
91
|
+
gateway: gateway.toString(),
|
|
92
|
+
dataItemOffset,
|
|
93
|
+
dataItemDataOffset,
|
|
94
|
+
rootTransactionId,
|
|
95
|
+
dataItemSize,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
const { gateway, dataItemOffset, dataItemDataOffset, rootTransactionId, dataItemSize, } = await Promise.any(dataItemAttributesPromises);
|
|
101
|
+
this.logger.debug('Successfully fetched data item attributes for txId', {
|
|
102
|
+
txId,
|
|
103
|
+
dataItemOffset,
|
|
104
|
+
dataItemDataOffset,
|
|
105
|
+
rootTransactionId,
|
|
106
|
+
dataItemSize,
|
|
107
|
+
gateway: gateway.toString(),
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
dataItemOffset,
|
|
111
|
+
dataItemDataOffset,
|
|
112
|
+
rootTransactionId,
|
|
113
|
+
dataItemSize,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Fetches just the bytes header data of a data item from a trusted gateway needed for signature verification.
|
|
118
|
+
*
|
|
119
|
+
* @param txId - The transaction ID to get signature data for
|
|
120
|
+
* @returns The bytes containing the data item up to the data section
|
|
121
|
+
*/
|
|
122
|
+
async getSignatureData({ txId, }) {
|
|
123
|
+
const { rootTransactionId, dataItemOffset, dataItemDataOffset } = await this.getDataItemAttributes(txId);
|
|
124
|
+
// this byte range is the header data of the data item within it's parent transaction, containing all the header data needed for signature verification
|
|
125
|
+
const rangeStart = dataItemOffset;
|
|
126
|
+
const rangeEnd = dataItemDataOffset - 1;
|
|
127
|
+
// TODO: we are fetching data here via range request - we may not want to do this concurrently and instead shuffle gateways before iterating through each
|
|
128
|
+
for (const gateway of this.trustedGateways) {
|
|
129
|
+
try {
|
|
130
|
+
const url = `${gateway.toString()}${rootTransactionId}`;
|
|
131
|
+
const response = await fetch(url, {
|
|
132
|
+
method: 'GET',
|
|
133
|
+
redirect: 'follow',
|
|
134
|
+
mode: 'cors',
|
|
135
|
+
headers: {
|
|
136
|
+
Range: `bytes=${rangeStart}-${rangeEnd}`,
|
|
137
|
+
'Cache-Control': 'no-cache',
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
if (!response.ok || response.body === null) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// create the data item object from just the headers, so we can get the components easily
|
|
144
|
+
// this is somewhat of a hack as we are not including the data when creating the DataItem object
|
|
145
|
+
const trustedDataItemHeaderBytes = Buffer.from(await response.arrayBuffer());
|
|
146
|
+
const dataItem = new DataItem(trustedDataItemHeaderBytes);
|
|
147
|
+
// first verify the data item id matches the txId before we do any other verification
|
|
148
|
+
const dataItemId = await dataItem.id;
|
|
149
|
+
if (dataItemId !== txId) {
|
|
150
|
+
throw new Error('Data item ID does not match txId', {
|
|
151
|
+
cause: { dataItemId, txId },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// now get the components needed for verification from the DataItem
|
|
155
|
+
const signatureType = dataItem.signatureType;
|
|
156
|
+
const signature = dataItem.rawSignature;
|
|
157
|
+
const owner = dataItem.rawOwner;
|
|
158
|
+
const target = dataItem.rawTarget;
|
|
159
|
+
const anchor = dataItem.rawAnchor;
|
|
160
|
+
const tags = dataItem.rawTags;
|
|
161
|
+
return {
|
|
162
|
+
signatureType,
|
|
163
|
+
signature,
|
|
164
|
+
owner,
|
|
165
|
+
target,
|
|
166
|
+
anchor,
|
|
167
|
+
tags,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
this.logger.debug('Failed to fetch data item signature bytes', {
|
|
172
|
+
error: error.message,
|
|
173
|
+
stack: error.stack,
|
|
174
|
+
txId,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
throw new Error('Failed to fetch data item signature bytes', {
|
|
179
|
+
cause: { txId, rootTransactionId, dataItemOffset, dataItemDataOffset },
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Verifies the signature of a data item using trusted gateways to get the signature data
|
|
184
|
+
* and then verifying it against the data payload.
|
|
185
|
+
*
|
|
186
|
+
* This implementation follows the ANS-104 standard for verifying data item signatures:
|
|
187
|
+
* 1. Get the signature data from the trusted gateway
|
|
188
|
+
* 2. Parse the signature components (owner, signature type, tags, etc.)
|
|
189
|
+
* 3. Calculate the deep hash of all components and the data
|
|
190
|
+
* 4. Verify the signature against the deep hash
|
|
191
|
+
*
|
|
192
|
+
* @param data - The data stream to verify
|
|
193
|
+
* @param txId - The transaction ID of the data
|
|
194
|
+
*/
|
|
195
|
+
async verifyData({ data, txId, }) {
|
|
196
|
+
// fetch signature data from trusted gateway
|
|
197
|
+
const trustedSignatureData = await this.getSignatureData({ txId });
|
|
198
|
+
if (!DataItem.isDataItem(trustedSignatureData)) {
|
|
199
|
+
throw new Error('TxId is not a data item', {
|
|
200
|
+
cause: { txId },
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// ensure data is in the right format for verification
|
|
204
|
+
const asyncIterable = isAsyncIterable(data)
|
|
205
|
+
? data
|
|
206
|
+
: readableStreamToAsyncIterable(data);
|
|
207
|
+
const { signatureType, signature, owner, target, anchor, tags } = trustedSignatureData;
|
|
208
|
+
// calculate the deep hash of all components including the data stream
|
|
209
|
+
// this follows the arbundles DataItem.verify() approach but prevents loading the entire data stream into memory
|
|
210
|
+
const signatureData = await deepHash([
|
|
211
|
+
stringToBuffer('dataitem'),
|
|
212
|
+
stringToBuffer('1'),
|
|
213
|
+
stringToBuffer(`${signatureType}`),
|
|
214
|
+
new Uint8Array(owner),
|
|
215
|
+
new Uint8Array(target),
|
|
216
|
+
new Uint8Array(anchor),
|
|
217
|
+
new Uint8Array(tags),
|
|
218
|
+
asyncIterable,
|
|
219
|
+
]);
|
|
220
|
+
const signer = indexToType[signatureType];
|
|
221
|
+
const isValid = await signer.verify(new Uint8Array(owner), signatureData, new Uint8Array(signature));
|
|
222
|
+
if (!isValid) {
|
|
223
|
+
throw new Error('Data item signature verification failed', {
|
|
224
|
+
cause: { txId },
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Implementation of SignatureDataProvider that fetches signature data directly
|
|
231
|
+
* from a trusted gateway's /tx/<tx-id>/signature endpoint.
|
|
232
|
+
*/
|
|
233
|
+
export class TransactionSignatureVerificationStrategy {
|
|
234
|
+
trustedGateways;
|
|
235
|
+
logger;
|
|
236
|
+
constructor({ trustedGateways, logger = defaultLogger, }) {
|
|
237
|
+
this.trustedGateways = trustedGateways;
|
|
238
|
+
this.logger = logger;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Fetches signature data directly from a trusted gateway's /tx/<tx-id>/signature endpoint.
|
|
242
|
+
*
|
|
243
|
+
* @param txId - The transaction ID to get signature data for
|
|
244
|
+
* @returns The signature data as a Uint8Array
|
|
245
|
+
*/
|
|
246
|
+
async getSignatureData({ txId, }) {
|
|
247
|
+
this.logger.debug('Getting signature data for txId', {
|
|
248
|
+
txId,
|
|
249
|
+
trustedGateways: this.trustedGateways,
|
|
250
|
+
});
|
|
251
|
+
// TODO: shuffle gateways before iterating through each and potentially allow for concurrent requests
|
|
252
|
+
for (const gateway of this.trustedGateways) {
|
|
253
|
+
try {
|
|
254
|
+
const url = `${gateway.toString()}tx/${txId}`;
|
|
255
|
+
const response = await fetch(url, {
|
|
256
|
+
method: 'GET',
|
|
257
|
+
redirect: 'follow',
|
|
258
|
+
mode: 'cors',
|
|
259
|
+
headers: {
|
|
260
|
+
'Cache-Control': 'no-cache',
|
|
261
|
+
'Content-Type': 'application/json',
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
if (!response.ok) {
|
|
265
|
+
throw new Error('Failed to fetch signature data from trusted gateway', {
|
|
266
|
+
cause: { txId, gateway: gateway.toString() },
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const tx = await response.json();
|
|
270
|
+
return {
|
|
271
|
+
format: tx.format,
|
|
272
|
+
owner: tx.owner,
|
|
273
|
+
target: tx.target,
|
|
274
|
+
anchor: tx.anchor,
|
|
275
|
+
quantity: tx.quantity,
|
|
276
|
+
reward: tx.reward,
|
|
277
|
+
dataRoot: tx.data_root,
|
|
278
|
+
dataSize: tx.data_size,
|
|
279
|
+
lastTx: tx.last_tx,
|
|
280
|
+
tags: tx.tags,
|
|
281
|
+
signature: tx.signature,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
this.logger.debug('Error fetching signature data', {
|
|
286
|
+
error: error.message,
|
|
287
|
+
stack: error.stack,
|
|
288
|
+
txId,
|
|
289
|
+
gateway: gateway.toString(),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
throw new Error('Failed to fetch signature data from any trusted gateway', {
|
|
294
|
+
cause: { txId },
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
async verifyData({ data, txId, }) {
|
|
298
|
+
const { format, owner, target, quantity, reward, dataSize, lastTx, tags, signature, } = await this.getSignatureData({ txId });
|
|
299
|
+
const tagList = tags.map((tag) => [
|
|
300
|
+
fromB64Url(tag.name),
|
|
301
|
+
fromB64Url(tag.value),
|
|
302
|
+
]);
|
|
303
|
+
// use the provided data stream to compute the data root for the signature data
|
|
304
|
+
const computedDataRoot = await convertDataStreamToDataRoot({
|
|
305
|
+
stream: data,
|
|
306
|
+
});
|
|
307
|
+
// compute the signature data using the computed data root and retrieved signature data
|
|
308
|
+
const signatureData = await deepHash([
|
|
309
|
+
stringToBuffer(format.toString()),
|
|
310
|
+
fromB64Url(owner),
|
|
311
|
+
fromB64Url(target),
|
|
312
|
+
stringToBuffer(quantity),
|
|
313
|
+
stringToBuffer(reward),
|
|
314
|
+
fromB64Url(lastTx),
|
|
315
|
+
tagList,
|
|
316
|
+
stringToBuffer(dataSize.toString()),
|
|
317
|
+
fromB64Url(computedDataRoot),
|
|
318
|
+
]);
|
|
319
|
+
// verify the signature using the computed signature data and the computed signature data
|
|
320
|
+
const isValid = await Arweave.crypto.verify(owner, signatureData, fromB64Url(signature));
|
|
321
|
+
if (!isValid) {
|
|
322
|
+
throw new Error('Transaction signature verification failed', {
|
|
323
|
+
cause: { txId },
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
export const SignatureVerificationStrategies = {
|
|
329
|
+
ans104: Ans104SignatureVerificationStrategy,
|
|
330
|
+
transaction: TransactionSignatureVerificationStrategy,
|
|
331
|
+
// TODO: ans102
|
|
332
|
+
};
|
|
333
|
+
export class SignatureVerificationStrategy {
|
|
334
|
+
ans104;
|
|
335
|
+
transaction;
|
|
336
|
+
classifier;
|
|
337
|
+
constructor({ trustedGateways, maxConcurrency = 1, logger = defaultLogger, classifier = new GqlClassifier({ logger }), }) {
|
|
338
|
+
this.ans104 = new Ans104SignatureVerificationStrategy({
|
|
339
|
+
trustedGateways,
|
|
340
|
+
maxConcurrency,
|
|
341
|
+
logger,
|
|
342
|
+
});
|
|
343
|
+
this.transaction = new TransactionSignatureVerificationStrategy({
|
|
344
|
+
trustedGateways,
|
|
345
|
+
logger,
|
|
346
|
+
});
|
|
347
|
+
this.classifier = classifier;
|
|
348
|
+
}
|
|
349
|
+
async verifyData({ data, txId, }) {
|
|
350
|
+
const dataType = await this.classifier.classify({ txId });
|
|
351
|
+
switch (dataType) {
|
|
352
|
+
case 'ans104':
|
|
353
|
+
return this.ans104.verifyData({ data, txId });
|
|
354
|
+
case 'transaction':
|
|
355
|
+
return this.transaction.verifyData({ data, txId });
|
|
356
|
+
default:
|
|
357
|
+
throw new Error('Unknown data type', {
|
|
358
|
+
cause: { dataType },
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
package/dist/wayfinder.d.ts
CHANGED
|
@@ -109,8 +109,9 @@ export declare function sandboxFromId(id: string): string;
|
|
|
109
109
|
* @param resolveUrl - the function to construct the redirect url for ar:// requests
|
|
110
110
|
* @returns a wrapped fetch function that supports ar:// protocol and always returns Response
|
|
111
111
|
*/
|
|
112
|
-
export declare const createWayfinderClient: ({ resolveUrl, verifyData, selectGateway, emitter, logger, strict, }: {
|
|
113
|
-
|
|
112
|
+
export declare const createWayfinderClient: ({ getGateways, resolveUrl, verifyData, selectGateway, emitter, logger, strict, }: {
|
|
113
|
+
getGateways: GatewaysProvider["getGateways"];
|
|
114
|
+
selectGateway: RoutingStrategy["selectGateway"];
|
|
114
115
|
resolveUrl: (params: {
|
|
115
116
|
originalUrl: string;
|
|
116
117
|
selectedGateway: URL;
|
package/dist/wayfinder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wayfinder.d.ts","sourceRoot":"","sources":["../src/wayfinder.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"wayfinder.d.ts","sourceRoot":"","sources":["../src/wayfinder.ts"],"names":[],"mappings":"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"}
|
package/dist/wayfinder.js
CHANGED
|
@@ -185,18 +185,18 @@ export function sandboxFromId(id) {
|
|
|
185
185
|
* @param resolveUrl - the function to construct the redirect url for ar:// requests
|
|
186
186
|
* @returns a wrapped fetch function that supports ar:// protocol and always returns Response
|
|
187
187
|
*/
|
|
188
|
-
export const createWayfinderClient = ({ resolveUrl, verifyData, selectGateway, emitter = new WayfinderEmitter(), logger = defaultLogger, strict = false, }) => {
|
|
188
|
+
export const createWayfinderClient = ({ getGateways, resolveUrl, verifyData, selectGateway, emitter = new WayfinderEmitter(), logger = defaultLogger, strict = false, }) => {
|
|
189
189
|
return async (input, init) => {
|
|
190
|
-
|
|
191
|
-
if (typeof url !== 'string') {
|
|
190
|
+
if (!(input instanceof URL)) {
|
|
192
191
|
logger?.debug('URL is not a string, skipping routing', {
|
|
193
|
-
|
|
192
|
+
input,
|
|
194
193
|
});
|
|
195
194
|
emitter?.emit('routing-skipped', {
|
|
196
|
-
originalUrl: JSON.stringify(
|
|
195
|
+
originalUrl: JSON.stringify(input),
|
|
197
196
|
});
|
|
198
|
-
return fetch(
|
|
197
|
+
return fetch(input, init);
|
|
199
198
|
}
|
|
199
|
+
const url = input.toString();
|
|
200
200
|
emitter?.emit('routing-started', {
|
|
201
201
|
originalUrl: url,
|
|
202
202
|
});
|
|
@@ -205,7 +205,11 @@ export const createWayfinderClient = ({ resolveUrl, verifyData, selectGateway, e
|
|
|
205
205
|
for (let i = 0; i < maxRetries; i++) {
|
|
206
206
|
try {
|
|
207
207
|
// select the target gateway
|
|
208
|
-
const selectedGateway = await selectGateway(
|
|
208
|
+
const selectedGateway = await selectGateway({
|
|
209
|
+
gateways: await getGateways(),
|
|
210
|
+
path: input.pathname.split('/')[1],
|
|
211
|
+
subdomain: input.hostname.split('.')[0],
|
|
212
|
+
});
|
|
209
213
|
logger?.debug('Selected gateway', {
|
|
210
214
|
originalUrl: url,
|
|
211
215
|
selectedGateway: selectedGateway.toString(),
|
|
@@ -477,11 +481,8 @@ export class Wayfinder {
|
|
|
477
481
|
};
|
|
478
482
|
// create a wayfinder client with the routing strategy and gateways provider
|
|
479
483
|
this.request = createWayfinderClient({
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
gateways: await this.gatewaysProvider.getGateways(),
|
|
483
|
-
});
|
|
484
|
-
},
|
|
484
|
+
getGateways: this.gatewaysProvider.getGateways.bind(this.gatewaysProvider),
|
|
485
|
+
selectGateway: this.routingStrategy.selectGateway.bind(this.routingStrategy),
|
|
485
486
|
resolveUrl: resolveWayfinderUrl,
|
|
486
487
|
verifyData: this.verifyData,
|
|
487
488
|
emitter: this.emitter,
|
package/package.json
CHANGED