@xyo-network/xl1-validation 1.25.26 → 1.25.28
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/neutral/block/index.d.ts +2 -0
- package/dist/neutral/block/index.d.ts.map +1 -0
- package/dist/neutral/block/validators/BlockCumulativeBalanceValidator.d.ts +4 -0
- package/dist/neutral/block/validators/BlockCumulativeBalanceValidator.d.ts.map +1 -0
- package/dist/neutral/block/validators/index.d.ts +2 -0
- package/dist/neutral/block/validators/index.d.ts.map +1 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessReferences.d.ts +1 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessReferences.d.ts.map +1 -1
- package/dist/neutral/boundwitness/validators/BoundWitnessSignatures.d.ts +1 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessSignatures.d.ts.map +1 -1
- package/dist/neutral/index.d.ts +1 -0
- package/dist/neutral/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +66 -7
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/neutral/transaction/validateTransaction.d.ts +1 -0
- package/dist/neutral/transaction/validateTransaction.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionDurationValidator.d.ts +1 -0
- package/dist/neutral/transaction/validators/TransactionDurationValidator.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionElevationValidator.d.ts +1 -0
- package/dist/neutral/transaction/validators/TransactionElevationValidator.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionFromValidator.d.ts +1 -0
- package/dist/neutral/transaction/validators/TransactionFromValidator.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionGasValidator.d.ts +1 -0
- package/dist/neutral/transaction/validators/TransactionGasValidator.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionJsonSchemaValidator.d.ts +1 -0
- package/dist/neutral/transaction/validators/TransactionJsonSchemaValidator.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionProtocolValidator.d.ts +1 -0
- package/dist/neutral/transaction/validators/TransactionProtocolValidator.d.ts.map +1 -1
- package/dist/neutral/transaction/validators/TransactionTransfersValidator.d.ts +6 -0
- package/dist/neutral/transaction/validators/TransactionTransfersValidator.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/block/index.ts +1 -0
- package/src/block/validators/BlockCumulativeBalanceValidator.ts +76 -0
- package/src/block/validators/index.ts +1 -0
- package/src/boundwitness/validators/BoundWitnessReferences.ts +1 -0
- package/src/boundwitness/validators/BoundWitnessSignatures.ts +1 -0
- package/src/index.ts +1 -0
- package/src/transaction/validateTransaction.ts +1 -0
- package/src/transaction/validators/TransactionDurationValidator.ts +1 -0
- package/src/transaction/validators/TransactionElevationValidator.ts +1 -0
- package/src/transaction/validators/TransactionFromValidator.ts +1 -0
- package/src/transaction/validators/TransactionGasValidator.ts +1 -0
- package/src/transaction/validators/TransactionJsonSchemaValidator.ts +1 -0
- package/src/transaction/validators/TransactionProtocolValidator.ts +1 -0
- package/src/transaction/validators/TransactionTransfersValidator.ts +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/block/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HydratedBlockStateValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Creates a block state validator that checks cumulative outflows per address do not exceed pre-block balances. */
|
|
3
|
+
export declare function BlockCumulativeBalanceValidatorFactory(): HydratedBlockStateValidationFunction;
|
|
4
|
+
//# sourceMappingURL=BlockCumulativeBalanceValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BlockCumulativeBalanceValidator.d.ts","sourceRoot":"","sources":["../../../../src/block/validators/BlockCumulativeBalanceValidator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,oCAAoC,EAErC,MAAM,2BAA2B,CAAA;AAelC,oHAAoH;AACpH,wBAAgB,sCAAsC,IAAI,oCAAoC,CAqD7F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/block/validators/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BoundWitness, Schema } from '@xyo-network/sdk-js';
|
|
2
2
|
import type { HydratedBoundWitnessValidationFunction } from '@xyo-network/xl1-protocol';
|
|
3
|
+
/** Creates a validator that checks all payload references in a BoundWitness are present, have matching schemas, and optionally conform to an allowed schema list. */
|
|
3
4
|
export declare const BoundWitnessReferencesValidator: <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]) => HydratedBoundWitnessValidationFunction<T>;
|
|
4
5
|
//# sourceMappingURL=BoundWitnessReferences.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BoundWitnessReferences.d.ts","sourceRoot":"","sources":["../../../../src/boundwitness/validators/BoundWitnessReferences.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EAEZ,MAAM,EAEP,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,sCAAsC,EAAoC,MAAM,2BAA2B,CAAA;AAOzH,eAAO,MAAM,+BAA+B,GAEvC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,iBAAiB,MAAM,EAAE,KAAG,sCAAsC,CAAC,CAAC,CAuC7G,CAAA"}
|
|
1
|
+
{"version":3,"file":"BoundWitnessReferences.d.ts","sourceRoot":"","sources":["../../../../src/boundwitness/validators/BoundWitnessReferences.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EAEZ,MAAM,EAEP,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,sCAAsC,EAAoC,MAAM,2BAA2B,CAAA;AAOzH,qKAAqK;AACrK,eAAO,MAAM,+BAA+B,GAEvC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,iBAAiB,MAAM,EAAE,KAAG,sCAAsC,CAAC,CAAC,CAuC7G,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates that all signatures on a BoundWitness are cryptographically valid for their corresponding addresses. */
|
|
2
3
|
export declare const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction;
|
|
3
4
|
//# sourceMappingURL=BoundWitnessSignatures.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BoundWitnessSignatures.d.ts","sourceRoot":"","sources":["../../../../src/boundwitness/validators/BoundWitnessSignatures.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAA;AAG/E,eAAO,MAAM,+BAA+B,EAAE,8BAsB7C,CAAA"}
|
|
1
|
+
{"version":3,"file":"BoundWitnessSignatures.d.ts","sourceRoot":"","sources":["../../../../src/boundwitness/validators/BoundWitnessSignatures.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAA;AAG/E,qHAAqH;AACrH,eAAO,MAAM,+BAA+B,EAAE,8BAsB7C,CAAA"}
|
package/dist/neutral/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA"}
|
package/dist/neutral/index.mjs
CHANGED
|
@@ -1,3 +1,61 @@
|
|
|
1
|
+
// src/block/validators/BlockCumulativeBalanceValidator.ts
|
|
2
|
+
import {
|
|
3
|
+
hexToBigInt
|
|
4
|
+
} from "@xylabs/sdk-js";
|
|
5
|
+
import {
|
|
6
|
+
HydratedBlockStateValidationError,
|
|
7
|
+
isTransactionBoundWitnessWithHashMeta,
|
|
8
|
+
isTransfer
|
|
9
|
+
} from "@xyo-network/xl1-protocol";
|
|
10
|
+
function transactionFeeCost(tx) {
|
|
11
|
+
const {
|
|
12
|
+
base,
|
|
13
|
+
gasLimit,
|
|
14
|
+
gasPrice,
|
|
15
|
+
priority
|
|
16
|
+
} = tx.fees;
|
|
17
|
+
return hexToBigInt(base) + hexToBigInt(priority) + hexToBigInt(gasLimit) * hexToBigInt(gasPrice);
|
|
18
|
+
}
|
|
19
|
+
function BlockCumulativeBalanceValidatorFactory() {
|
|
20
|
+
return async (context, hydratedBlock) => {
|
|
21
|
+
const [blockBw, payloads] = hydratedBlock;
|
|
22
|
+
const transactions = payloads.filter(isTransactionBoundWitnessWithHashMeta);
|
|
23
|
+
if (transactions.length === 0) return [];
|
|
24
|
+
const outflows = {};
|
|
25
|
+
for (const tx of transactions) {
|
|
26
|
+
const feeCost = transactionFeeCost(tx);
|
|
27
|
+
const feePayer = tx.from;
|
|
28
|
+
outflows[feePayer] = (outflows[feePayer] ?? 0n) + feeCost;
|
|
29
|
+
const txPayloadHashes = new Set(tx.payload_hashes);
|
|
30
|
+
for (const payload of payloads) {
|
|
31
|
+
if (!txPayloadHashes.has(payload._hash) || !isTransfer(payload)) continue;
|
|
32
|
+
const { from } = payload;
|
|
33
|
+
for (const amount of Object.values(payload.transfers)) {
|
|
34
|
+
outflows[from] = (outflows[from] ?? 0n) + hexToBigInt(amount);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const addresses = Object.keys(outflows);
|
|
39
|
+
if (addresses.length === 0) return [];
|
|
40
|
+
const balances = await context.accountBalance.accountBalances(addresses);
|
|
41
|
+
const chainId = await context.chainIdAtBlockNumber(blockBw.block);
|
|
42
|
+
const errors = [];
|
|
43
|
+
for (const address of addresses) {
|
|
44
|
+
const balance = balances[address] ?? 0n;
|
|
45
|
+
const totalOutflow = outflows[address];
|
|
46
|
+
if (totalOutflow > balance) {
|
|
47
|
+
errors.push(new HydratedBlockStateValidationError(
|
|
48
|
+
blockBw._hash,
|
|
49
|
+
chainId,
|
|
50
|
+
hydratedBlock,
|
|
51
|
+
`Cumulative outflow for address ${address} exceeds available balance: outflow ${totalOutflow} > balance ${balance}`
|
|
52
|
+
));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return errors;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
1
59
|
// src/boundwitness/validators/BoundWitnessReferences.ts
|
|
2
60
|
import { ZERO_HASH } from "@xylabs/sdk-js";
|
|
3
61
|
import { isAnyPayload } from "@xyo-network/sdk-js";
|
|
@@ -148,7 +206,7 @@ var TransactionFromValidator = (context, tx) => {
|
|
|
148
206
|
};
|
|
149
207
|
|
|
150
208
|
// src/transaction/validators/TransactionGasValidator.ts
|
|
151
|
-
import { hexToBigInt, ZERO_HASH as ZERO_HASH6 } from "@xylabs/sdk-js";
|
|
209
|
+
import { hexToBigInt as hexToBigInt2, ZERO_HASH as ZERO_HASH6 } from "@xylabs/sdk-js";
|
|
152
210
|
import {
|
|
153
211
|
AttoXL1,
|
|
154
212
|
HydratedTransactionValidationError as HydratedTransactionValidationError4,
|
|
@@ -231,10 +289,10 @@ var parseFees = (fees) => {
|
|
|
231
289
|
gasPrice,
|
|
232
290
|
priority
|
|
233
291
|
} = fees;
|
|
234
|
-
if (base !== void 0) ret.base = AttoXL1(
|
|
235
|
-
if (gasLimit !== void 0) ret.gasLimit = AttoXL1(
|
|
236
|
-
if (gasPrice !== void 0) ret.gasPrice = AttoXL1(
|
|
237
|
-
if (priority !== void 0) ret.priority = AttoXL1(
|
|
292
|
+
if (base !== void 0) ret.base = AttoXL1(hexToBigInt2(base));
|
|
293
|
+
if (gasLimit !== void 0) ret.gasLimit = AttoXL1(hexToBigInt2(gasLimit));
|
|
294
|
+
if (gasPrice !== void 0) ret.gasPrice = AttoXL1(hexToBigInt2(gasPrice));
|
|
295
|
+
if (priority !== void 0) ret.priority = AttoXL1(hexToBigInt2(priority));
|
|
238
296
|
return ret;
|
|
239
297
|
};
|
|
240
298
|
|
|
@@ -282,7 +340,7 @@ var TransactionProtocolValidator = async (context, tx) => {
|
|
|
282
340
|
|
|
283
341
|
// src/transaction/validators/TransactionTransfersValidator.ts
|
|
284
342
|
import { isDefined, isUndefined } from "@xylabs/sdk-js";
|
|
285
|
-
import { HydratedTransactionValidationError as HydratedTransactionValidationError7, isTransfer } from "@xyo-network/xl1-protocol";
|
|
343
|
+
import { HydratedTransactionValidationError as HydratedTransactionValidationError7, isTransfer as isTransfer2 } from "@xyo-network/xl1-protocol";
|
|
286
344
|
import {
|
|
287
345
|
completedStepRewardAddress,
|
|
288
346
|
derivedReceiveAddress,
|
|
@@ -316,7 +374,7 @@ function TransactionTransfersValidatorFactory(signerValidators = [SelfSignerVali
|
|
|
316
374
|
const signer = hydratedTx[0].from;
|
|
317
375
|
try {
|
|
318
376
|
const payloads = elevatedPayloads(hydratedTx);
|
|
319
|
-
const transfers = payloads.filter(
|
|
377
|
+
const transfers = payloads.filter(isTransfer2);
|
|
320
378
|
for (const transfer of transfers) {
|
|
321
379
|
if (isUndefined(signerValidators.find((v) => v(signer, transfer.from, transfer.context)))) {
|
|
322
380
|
errors.push(new HydratedTransactionValidationError7(
|
|
@@ -353,6 +411,7 @@ async function validateTransaction(context, tx, additionalValidators) {
|
|
|
353
411
|
}
|
|
354
412
|
}
|
|
355
413
|
export {
|
|
414
|
+
BlockCumulativeBalanceValidatorFactory,
|
|
356
415
|
BoundWitnessReferencesValidator,
|
|
357
416
|
BoundWitnessSignaturesValidator,
|
|
358
417
|
CompletedStepRewardAddressValidatorFactory,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/boundwitness/validators/BoundWitnessReferences.ts","../../src/boundwitness/validators/BoundWitnessSignatures.ts","../../src/transaction/validateTransaction.ts","../../src/transaction/validators/TransactionDurationValidator.ts","../../src/transaction/validators/TransactionElevationValidator.ts","../../src/transaction/validators/TransactionFromValidator.ts","../../src/transaction/validators/TransactionGasValidator.ts","../../src/transaction/validators/TransactionJsonSchemaValidator.ts","../../src/transaction/validators/TransactionProtocolValidator.ts","../../src/transaction/validators/TransactionTransfersValidator.ts"],"sourcesContent":["import type { Hash, Promisable } from '@xylabs/sdk-js'\nimport { ZERO_HASH } from '@xylabs/sdk-js'\nimport type {\n BoundWitness,\n Payload,\n Schema,\n WithHashMeta,\n} from '@xyo-network/sdk-js'\nimport { isAnyPayload } from '@xyo-network/sdk-js'\nimport type { HydratedBoundWitnessValidationFunction, HydratedBoundWitnessWithHashMeta } from '@xyo-network/xl1-protocol'\nimport { HydratedBoundWitnessValidationError } from '@xyo-network/xl1-protocol'\n\nfunction getPayloadsFromPayloadArray(payloads: WithHashMeta<Payload>[], hashes: Hash[]): (WithHashMeta<Payload> | undefined)[] {\n return hashes.map(hash => payloads.find(payload => payload._hash === hash || payload._dataHash === hash))\n}\n\nexport const BoundWitnessReferencesValidator\n\n = <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]): HydratedBoundWitnessValidationFunction<T> => (\n [bw, payloadSet]: HydratedBoundWitnessWithHashMeta<T>,\n // eslint-disable-next-line complexity\n ): Promisable<HydratedBoundWitnessValidationError[]> => {\n const errors: HydratedBoundWitnessValidationError[] = []\n try {\n const payloads = getPayloadsFromPayloadArray(payloadSet, bw.payload_hashes)\n if (payloads.length !== bw.payload_hashes.length) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'unable to locate payloads'))\n }\n\n // check if payloads are valid and if their schemas match the declared schemas\n for (let payload of payloads) {\n if (isAnyPayload(payload)) {\n const payloadHashIndex = bw.payload_hashes.indexOf(payload._hash)\n const payloadDataHashIndex = bw.payload_hashes.indexOf(payload._dataHash)\n const payloadIndex = Math.max(payloadHashIndex, payloadDataHashIndex)\n if (payloadIndex === -1) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'payload hash not found'))\n }\n\n const declaredSchema = bw.payload_schemas[payloadIndex]\n if (declaredSchema !== payload.schema) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'mismatched schema'))\n }\n\n if (allowedSchemas && !allowedSchemas.includes(payload.schema)) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `disallowed schema [${payload.schema}]`))\n }\n } else {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'invalid payload'))\n }\n }\n } catch (ex) {\n const error = new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `validation excepted: ${ex}`)\n error.cause = ex\n errors.push(error)\n }\n return errors\n }\n","import { type Address, ZERO_HASH } from '@xylabs/sdk-js'\nimport { toArrayBuffer } from '@xylabs/sdk-js'\nimport type { BoundWitness, WithStorageMeta } from '@xyo-network/sdk-js'\nimport { BoundWitnessBuilder, BoundWitnessValidator } from '@xyo-network/sdk-js'\nimport type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol'\nimport { BoundWitnessValidationError } from '@xyo-network/xl1-protocol'\n\nexport const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction = async (\n bw: BoundWitness,\n) => {\n const errors: BoundWitnessValidationError[] = []\n try {\n const dataHash = await BoundWitnessBuilder.dataHash(bw)\n const results: [Address, Error[]][] = await Promise.all(bw.addresses.map(async (address, index) => {\n return [address, await BoundWitnessValidator.validateSignature(\n toArrayBuffer(dataHash),\n toArrayBuffer(address),\n toArrayBuffer(bw.$signatures[index] ?? undefined),\n )]\n }))\n for (const [, bwErrors] of results) {\n for (const bwError of bwErrors) {\n errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation errors', bwError))\n }\n }\n } catch (ex) {\n errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation excepted', ex))\n }\n return errors\n}\n","import type {\n HydratedTransactionValidationFunction,\n HydratedTransactionValidationFunctionContext,\n HydratedTransactionWithHashMeta,\n} from '@xyo-network/xl1-protocol'\nimport { isTransactionBoundWitness } from '@xyo-network/xl1-protocol'\n\nimport {\n TransactionDurationValidator,\n TransactionElevationValidator, TransactionFromValidator, TransactionGasValidator, TransactionProtocolValidator,\n} from './validators/index.ts'\n\nexport async function validateTransaction(\n context: HydratedTransactionValidationFunctionContext,\n tx: HydratedTransactionWithHashMeta,\n additionalValidators?: HydratedTransactionValidationFunction[],\n) {\n try {\n if (!isTransactionBoundWitness(tx[0])) {\n return [new Error('failed isTransactionBoundWitness identity check')]\n }\n\n const validators: HydratedTransactionValidationFunction<HydratedTransactionValidationFunctionContext>[] = [\n TransactionProtocolValidator,\n TransactionDurationValidator,\n TransactionFromValidator,\n TransactionGasValidator,\n TransactionElevationValidator,\n ...(additionalValidators ?? []),\n ]\n return (await Promise.all(validators.map(v => v(context, tx)))).flat()\n } catch (ex) {\n return [(new Error(`Failed TransactionGasValidator: ${ex}`))]\n }\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\n\nexport const TransactionDurationValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n// eslint-disable-next-line complexity\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n const { exp, nbf } = tx[0]\n if (nbf < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction nbf must be positive'))\n\n if (exp < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must be positive'))\n if (exp <= nbf) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must greater than nbf'))\n if (exp - nbf > 10_000) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Transaction exp must not be too far in the future',\n ))\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionDurationValidator: ${ex}`,\n ex,\n ))\n }\n\n return errors\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\nimport { extractElevatedHashes } from '@xyo-network/xl1-protocol-sdk'\n\nexport const TransactionElevationValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n try {\n extractElevatedHashes(tx)\n } catch {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Hydrated transaction does not include all script hashes'))\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionElevationValidator: ${ex}`,\n ex,\n ))\n }\n return errors\n}\n","import { asAddress, ZERO_HASH } from '@xylabs/sdk-js'\nimport { addressesContains } from '@xyo-network/sdk-js'\nimport type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\n\nexport const TransactionFromValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n const from = asAddress(tx[0].from)\n if (from === undefined)errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Transaction from is not a valid address',\n ))\n else if (!addressesContains(tx[0], from)) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Transaction from address must be listed in addresses',\n ))\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionFromValidator: ${ex}`,\n ex,\n ))\n }\n return errors\n}\n","import { hexToBigInt, ZERO_HASH } from '@xylabs/sdk-js'\nimport type {\n HydratedTransactionValidationFunction,\n TransactionFeesBigInt, TransactionFeesHex,\n} from '@xyo-network/xl1-protocol'\nimport {\n AttoXL1,\n HydratedTransactionValidationError,\n minTransactionFees,\n} from '@xyo-network/xl1-protocol'\n\nexport const TransactionGasValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n// eslint-disable-next-line complexity\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n if (tx?.[0].fees === undefined) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Missing fees',\n ))\n } else {\n const {\n base, gasLimit, gasPrice, priority,\n } = parseFees(tx[0].fees)\n\n if (base === undefined) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.base must be defined and a valid number',\n ))\n else if (base < minTransactionFees.base) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.base must be >= ${minTransactionFees.base}`,\n ))\n\n if (gasLimit === undefined) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.gasLimit must be defined and a valid number',\n ))\n else if (gasLimit < minTransactionFees.gasLimit) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.gasLimit must be >= ${minTransactionFees.gasLimit}`,\n ))\n\n if (gasPrice === undefined) errors.push(\n new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.gasPrice must be defined and a valid number',\n ),\n )\n else if (gasPrice < minTransactionFees.gasPrice) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.gasPrice must be >= ${minTransactionFees.gasPrice}`,\n ))\n\n if (priority === undefined) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.priority must be defined and a valid number',\n ))\n else if (priority < minTransactionFees.priority) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.priority must be >= ${minTransactionFees.priority}`,\n ))\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionGasValidator: ${ex}`,\n ex,\n ))\n }\n return errors\n}\n\nconst parseFees = (fees: TransactionFeesHex): Partial<TransactionFeesBigInt> => {\n const ret: Partial<TransactionFeesBigInt> = {}\n const {\n base, gasLimit, gasPrice, priority,\n } = fees\n if (base !== undefined) ret.base = AttoXL1(hexToBigInt(base))\n if (gasLimit !== undefined) ret.gasLimit = AttoXL1(hexToBigInt(gasLimit))\n if (gasPrice !== undefined) ret.gasPrice = AttoXL1(hexToBigInt(gasPrice))\n if (priority !== undefined) ret.priority = AttoXL1(hexToBigInt(priority))\n return ret\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport { PayloadBuilder } from '@xyo-network/sdk-js'\nimport type { HydratedTransactionValidationFunction, TransactionBoundWitness } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\nimport { TransactionBoundWitnessJsonSchema } from '@xyo-network/xl1-schema'\nimport type { ValidateFunction } from 'ajv'\nimport { Ajv } from 'ajv'\n\nconst ajv = new Ajv({ allErrors: true, strict: true })\n\nlet validate: ValidateFunction<TransactionBoundWitness> | undefined\n\nexport const TransactionJsonSchemaValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n if (validate === undefined) validate = ajv.compile(TransactionBoundWitnessJsonSchema)\n if (!validate(PayloadBuilder.omitStorageMeta(tx[0]))) {\n const error = new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `failed JSON schema validation: ${ajv.errorsText(validate.errors, { separator: '\\n' })}`,\n )\n error.cause = validate.errors\n errors.push(error)\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))\n }\n return errors\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport type {\n ChainId,\n HydratedTransactionValidationFunction,\n} from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\n\nexport const TransactionProtocolValidator: HydratedTransactionValidationFunction = async (\n context: { chainId?: ChainId },\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n if (context?.chainId !== undefined && tx[0].chain !== context.chainId) {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, `invalid chain id [${context.chainId}, ${tx[0].chain}]`))\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))\n }\n return await Promise.resolve(errors)\n}\n","import type { Address } from '@xylabs/sdk-js'\nimport { isDefined, isUndefined } from '@xylabs/sdk-js'\nimport type {\n HydratedTransactionValidationFunction, StepIdentity,\n Transfer,\n} from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError, isTransfer } from '@xyo-network/xl1-protocol'\nimport {\n completedStepRewardAddress, derivedReceiveAddress, elevatedPayloads,\n} from '@xyo-network/xl1-protocol-sdk'\n\nexport type SignerValidator = (signer: Address, signee: Address, context?: { address?: Address; scope?: string; step?: StepIdentity }) => boolean\n\nexport type SignerMapping = Map<Address, Address[]>\n\nexport const SelfSignerValidator: SignerValidator = (signer: Address, signee: Address) => signer === signee\n\nexport const CompletedStepRewardAddressValidatorFactory = (allowedSigners: Address[]): SignerValidator => (\n signer: Address,\n signee: Address,\n context?: { step?: StepIdentity },\n) => {\n const step = context?.step\n if (isDefined(step)) {\n const contextAddress = completedStepRewardAddress(step)\n return allowedSigners.includes(signer) && signee === contextAddress\n } else {\n return false\n }\n}\n\nexport const DerivedReceiveAddressValidatorFactory = (allowedSigners: Address[], allowedScope: string): SignerValidator => (\n signer: Address,\n signee: Address,\n context?: { address?: Address; scope?: string },\n) => {\n const { address, scope } = context ?? {}\n if (scope !== allowedScope) {\n return false\n }\n if (isDefined(address)) {\n const derivedAddress = derivedReceiveAddress(address, scope)\n return allowedSigners.includes(signer) && signee === derivedAddress\n } else {\n return false\n }\n}\n\nexport function TransactionTransfersValidatorFactory(\n signerValidators: SignerValidator[] = [SelfSignerValidator],\n): HydratedTransactionValidationFunction {\n return async (\n context,\n hydratedTx,\n ) => {\n const errors: HydratedTransactionValidationError[] = []\n const signer = hydratedTx[0].from\n try {\n const payloads = elevatedPayloads(hydratedTx)\n const transfers = payloads.filter(isTransfer) as Transfer[]\n for (const transfer of transfers) {\n if (isUndefined(signerValidators.find(v => v(signer, transfer.from, transfer.context)))) {\n errors.push(new HydratedTransactionValidationError(\n hydratedTx[0]._hash,\n hydratedTx,\n `transfer from address ${transfer.from} is not authorized by signer ${signer}`,\n ))\n }\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(hydratedTx[0]._hash, hydratedTx, 'validation excepted', ex))\n }\n return await Promise.resolve(errors)\n }\n}\n"],"mappings":"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","names":["ZERO_HASH","ZERO_HASH","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","HydratedTransactionValidationError"]}
|
|
1
|
+
{"version":3,"sources":["../../src/block/validators/BlockCumulativeBalanceValidator.ts","../../src/boundwitness/validators/BoundWitnessReferences.ts","../../src/boundwitness/validators/BoundWitnessSignatures.ts","../../src/transaction/validateTransaction.ts","../../src/transaction/validators/TransactionDurationValidator.ts","../../src/transaction/validators/TransactionElevationValidator.ts","../../src/transaction/validators/TransactionFromValidator.ts","../../src/transaction/validators/TransactionGasValidator.ts","../../src/transaction/validators/TransactionJsonSchemaValidator.ts","../../src/transaction/validators/TransactionProtocolValidator.ts","../../src/transaction/validators/TransactionTransfersValidator.ts"],"sourcesContent":["import {\n type Address, type Hex, hexToBigInt,\n} from '@xylabs/sdk-js'\nimport type {\n HydratedBlockStateValidationFunction,\n TransactionBoundWitnessWithHashMeta,\n} from '@xyo-network/xl1-protocol'\nimport {\n HydratedBlockStateValidationError,\n isTransactionBoundWitnessWithHashMeta,\n isTransfer,\n} from '@xyo-network/xl1-protocol'\n\n/** Compute the maximum fee commitment for a transaction (base + priority + gasLimit * gasPrice). */\nfunction transactionFeeCost(tx: TransactionBoundWitnessWithHashMeta): bigint {\n const {\n base, gasLimit, gasPrice, priority,\n } = tx.fees\n return hexToBigInt(base) + hexToBigInt(priority) + (hexToBigInt(gasLimit) * hexToBigInt(gasPrice))\n}\n\n/** Creates a block state validator that checks cumulative outflows per address do not exceed pre-block balances. */\nexport function BlockCumulativeBalanceValidatorFactory(): HydratedBlockStateValidationFunction {\n return async (context, hydratedBlock) => {\n const [blockBw, payloads] = hydratedBlock\n\n // Find all transactions in the block\n const transactions = payloads.filter(isTransactionBoundWitnessWithHashMeta)\n\n if (transactions.length === 0) return []\n\n // Accumulate outflows per address\n const outflows: Record<Address, bigint> = {}\n\n for (const tx of transactions) {\n // Fee cost charged to the transaction sender\n const feeCost = transactionFeeCost(tx)\n const feePayer = tx.from\n outflows[feePayer] = (outflows[feePayer] ?? 0n) + feeCost\n\n // Find transfer payloads belonging to this transaction\n const txPayloadHashes = new Set(tx.payload_hashes)\n for (const payload of payloads) {\n if (!txPayloadHashes.has(payload._hash) || !isTransfer(payload)) continue\n const { from } = payload\n for (const amount of Object.values(payload.transfers) as Hex[]) {\n outflows[from] = (outflows[from] ?? 0n) + hexToBigInt(amount)\n }\n }\n }\n\n // Query pre-block balances for all addresses with outflows\n const addresses = Object.keys(outflows) as Address[]\n if (addresses.length === 0) return []\n\n const balances = await context.accountBalance.accountBalances(addresses)\n\n // Check each address\n const chainId = await context.chainIdAtBlockNumber(blockBw.block)\n const errors: HydratedBlockStateValidationError[] = []\n for (const address of addresses) {\n const balance = balances[address] ?? 0n\n const totalOutflow = outflows[address]\n if (totalOutflow > balance) {\n errors.push(new HydratedBlockStateValidationError(\n blockBw._hash,\n chainId,\n hydratedBlock,\n `Cumulative outflow for address ${address} exceeds available balance: outflow ${totalOutflow} > balance ${balance}`,\n ))\n }\n }\n\n return errors\n }\n}\n","import type { Hash, Promisable } from '@xylabs/sdk-js'\nimport { ZERO_HASH } from '@xylabs/sdk-js'\nimport type {\n BoundWitness,\n Payload,\n Schema,\n WithHashMeta,\n} from '@xyo-network/sdk-js'\nimport { isAnyPayload } from '@xyo-network/sdk-js'\nimport type { HydratedBoundWitnessValidationFunction, HydratedBoundWitnessWithHashMeta } from '@xyo-network/xl1-protocol'\nimport { HydratedBoundWitnessValidationError } from '@xyo-network/xl1-protocol'\n\nfunction getPayloadsFromPayloadArray(payloads: WithHashMeta<Payload>[], hashes: Hash[]): (WithHashMeta<Payload> | undefined)[] {\n return hashes.map(hash => payloads.find(payload => payload._hash === hash || payload._dataHash === hash))\n}\n\n/** Creates a validator that checks all payload references in a BoundWitness are present, have matching schemas, and optionally conform to an allowed schema list. */\nexport const BoundWitnessReferencesValidator\n\n = <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]): HydratedBoundWitnessValidationFunction<T> => (\n [bw, payloadSet]: HydratedBoundWitnessWithHashMeta<T>,\n // eslint-disable-next-line complexity\n ): Promisable<HydratedBoundWitnessValidationError[]> => {\n const errors: HydratedBoundWitnessValidationError[] = []\n try {\n const payloads = getPayloadsFromPayloadArray(payloadSet, bw.payload_hashes)\n if (payloads.length !== bw.payload_hashes.length) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'unable to locate payloads'))\n }\n\n // check if payloads are valid and if their schemas match the declared schemas\n for (let payload of payloads) {\n if (isAnyPayload(payload)) {\n const payloadHashIndex = bw.payload_hashes.indexOf(payload._hash)\n const payloadDataHashIndex = bw.payload_hashes.indexOf(payload._dataHash)\n const payloadIndex = Math.max(payloadHashIndex, payloadDataHashIndex)\n if (payloadIndex === -1) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'payload hash not found'))\n }\n\n const declaredSchema = bw.payload_schemas[payloadIndex]\n if (declaredSchema !== payload.schema) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'mismatched schema'))\n }\n\n if (allowedSchemas && !allowedSchemas.includes(payload.schema)) {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `disallowed schema [${payload.schema}]`))\n }\n } else {\n errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'invalid payload'))\n }\n }\n } catch (ex) {\n const error = new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `validation excepted: ${ex}`)\n error.cause = ex\n errors.push(error)\n }\n return errors\n }\n","import { type Address, ZERO_HASH } from '@xylabs/sdk-js'\nimport { toArrayBuffer } from '@xylabs/sdk-js'\nimport type { BoundWitness, WithStorageMeta } from '@xyo-network/sdk-js'\nimport { BoundWitnessBuilder, BoundWitnessValidator } from '@xyo-network/sdk-js'\nimport type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol'\nimport { BoundWitnessValidationError } from '@xyo-network/xl1-protocol'\n\n/** Validates that all signatures on a BoundWitness are cryptographically valid for their corresponding addresses. */\nexport const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction = async (\n bw: BoundWitness,\n) => {\n const errors: BoundWitnessValidationError[] = []\n try {\n const dataHash = await BoundWitnessBuilder.dataHash(bw)\n const results: [Address, Error[]][] = await Promise.all(bw.addresses.map(async (address, index) => {\n return [address, await BoundWitnessValidator.validateSignature(\n toArrayBuffer(dataHash),\n toArrayBuffer(address),\n toArrayBuffer(bw.$signatures[index] ?? undefined),\n )]\n }))\n for (const [, bwErrors] of results) {\n for (const bwError of bwErrors) {\n errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation errors', bwError))\n }\n }\n } catch (ex) {\n errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation excepted', ex))\n }\n return errors\n}\n","import type {\n HydratedTransactionValidationFunction,\n HydratedTransactionValidationFunctionContext,\n HydratedTransactionWithHashMeta,\n} from '@xyo-network/xl1-protocol'\nimport { isTransactionBoundWitness } from '@xyo-network/xl1-protocol'\n\nimport {\n TransactionDurationValidator,\n TransactionElevationValidator, TransactionFromValidator, TransactionGasValidator, TransactionProtocolValidator,\n} from './validators/index.ts'\n\n/** Validates a hydrated transaction using built-in validators plus any additional validators provided. */\nexport async function validateTransaction(\n context: HydratedTransactionValidationFunctionContext,\n tx: HydratedTransactionWithHashMeta,\n additionalValidators?: HydratedTransactionValidationFunction[],\n) {\n try {\n if (!isTransactionBoundWitness(tx[0])) {\n return [new Error('failed isTransactionBoundWitness identity check')]\n }\n\n const validators: HydratedTransactionValidationFunction<HydratedTransactionValidationFunctionContext>[] = [\n TransactionProtocolValidator,\n TransactionDurationValidator,\n TransactionFromValidator,\n TransactionGasValidator,\n TransactionElevationValidator,\n ...(additionalValidators ?? []),\n ]\n return (await Promise.all(validators.map(v => v(context, tx)))).flat()\n } catch (ex) {\n return [(new Error(`Failed TransactionGasValidator: ${ex}`))]\n }\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\n\n/** Validates that transaction timing fields (nbf and exp) are positive, correctly ordered, and within allowed duration limits. */\nexport const TransactionDurationValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n// eslint-disable-next-line complexity\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n const { exp, nbf } = tx[0]\n if (nbf < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction nbf must be positive'))\n\n if (exp < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must be positive'))\n if (exp <= nbf) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must greater than nbf'))\n if (exp - nbf > 10_000) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Transaction exp must not be too far in the future',\n ))\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionDurationValidator: ${ex}`,\n ex,\n ))\n }\n\n return errors\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\nimport { extractElevatedHashes } from '@xyo-network/xl1-protocol-sdk'\n\n/** Validates that a hydrated transaction includes all required elevated script hashes. */\nexport const TransactionElevationValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n try {\n extractElevatedHashes(tx)\n } catch {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Hydrated transaction does not include all script hashes'))\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionElevationValidator: ${ex}`,\n ex,\n ))\n }\n return errors\n}\n","import { asAddress, ZERO_HASH } from '@xylabs/sdk-js'\nimport { addressesContains } from '@xyo-network/sdk-js'\nimport type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\n\n/** Validates that the transaction's from field is a valid address and is included in the BoundWitness addresses. */\nexport const TransactionFromValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n const from = asAddress(tx[0].from)\n if (from === undefined)errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Transaction from is not a valid address',\n ))\n else if (!addressesContains(tx[0], from)) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Transaction from address must be listed in addresses',\n ))\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionFromValidator: ${ex}`,\n ex,\n ))\n }\n return errors\n}\n","import { hexToBigInt, ZERO_HASH } from '@xylabs/sdk-js'\nimport type {\n HydratedTransactionValidationFunction,\n TransactionFeesBigInt, TransactionFeesHex,\n} from '@xyo-network/xl1-protocol'\nimport {\n AttoXL1,\n HydratedTransactionValidationError,\n minTransactionFees,\n} from '@xyo-network/xl1-protocol'\n\n/** Validates that transaction fee fields (base, gasLimit, gasPrice, priority) are present and meet minimum requirements. */\nexport const TransactionGasValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n// eslint-disable-next-line complexity\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n if (tx?.[0].fees === undefined) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'Missing fees',\n ))\n } else {\n const {\n base, gasLimit, gasPrice, priority,\n } = parseFees(tx[0].fees)\n\n if (base === undefined) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.base must be defined and a valid number',\n ))\n else if (base < minTransactionFees.base) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.base must be >= ${minTransactionFees.base}`,\n ))\n\n if (gasLimit === undefined) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.gasLimit must be defined and a valid number',\n ))\n else if (gasLimit < minTransactionFees.gasLimit) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.gasLimit must be >= ${minTransactionFees.gasLimit}`,\n ))\n\n if (gasPrice === undefined) errors.push(\n new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.gasPrice must be defined and a valid number',\n ),\n )\n else if (gasPrice < minTransactionFees.gasPrice) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.gasPrice must be >= ${minTransactionFees.gasPrice}`,\n ))\n\n if (priority === undefined) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n 'fees.priority must be defined and a valid number',\n ))\n else if (priority < minTransactionFees.priority) errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `fees.priority must be >= ${minTransactionFees.priority}`,\n ))\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `Failed TransactionGasValidator: ${ex}`,\n ex,\n ))\n }\n return errors\n}\n\nconst parseFees = (fees: TransactionFeesHex): Partial<TransactionFeesBigInt> => {\n const ret: Partial<TransactionFeesBigInt> = {}\n const {\n base, gasLimit, gasPrice, priority,\n } = fees\n if (base !== undefined) ret.base = AttoXL1(hexToBigInt(base))\n if (gasLimit !== undefined) ret.gasLimit = AttoXL1(hexToBigInt(gasLimit))\n if (gasPrice !== undefined) ret.gasPrice = AttoXL1(hexToBigInt(gasPrice))\n if (priority !== undefined) ret.priority = AttoXL1(hexToBigInt(priority))\n return ret\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport { PayloadBuilder } from '@xyo-network/sdk-js'\nimport type { HydratedTransactionValidationFunction, TransactionBoundWitness } from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\nimport { TransactionBoundWitnessJsonSchema } from '@xyo-network/xl1-schema'\nimport type { ValidateFunction } from 'ajv'\nimport { Ajv } from 'ajv'\n\nconst ajv = new Ajv({ allErrors: true, strict: true })\n\nlet validate: ValidateFunction<TransactionBoundWitness> | undefined\n\n/** Validates a transaction against the TransactionBoundWitness JSON schema using AJV. */\nexport const TransactionJsonSchemaValidator: HydratedTransactionValidationFunction = (\n context,\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n if (validate === undefined) validate = ajv.compile(TransactionBoundWitnessJsonSchema)\n if (!validate(PayloadBuilder.omitStorageMeta(tx[0]))) {\n const error = new HydratedTransactionValidationError(\n tx?.[0]?._hash ?? ZERO_HASH,\n tx,\n `failed JSON schema validation: ${ajv.errorsText(validate.errors, { separator: '\\n' })}`,\n )\n error.cause = validate.errors\n errors.push(error)\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))\n }\n return errors\n}\n","import { ZERO_HASH } from '@xylabs/sdk-js'\nimport type {\n ChainId,\n HydratedTransactionValidationFunction,\n} from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'\n\n/** Validates that the transaction's chain ID matches the expected chain ID from the validation context. */\nexport const TransactionProtocolValidator: HydratedTransactionValidationFunction = async (\n context: { chainId?: ChainId },\n tx,\n) => {\n const errors: HydratedTransactionValidationError[] = []\n try {\n if (context?.chainId !== undefined && tx[0].chain !== context.chainId) {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, `invalid chain id [${context.chainId}, ${tx[0].chain}]`))\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))\n }\n return await Promise.resolve(errors)\n}\n","import type { Address } from '@xylabs/sdk-js'\nimport { isDefined, isUndefined } from '@xylabs/sdk-js'\nimport type {\n HydratedTransactionValidationFunction, StepIdentity,\n Transfer,\n} from '@xyo-network/xl1-protocol'\nimport { HydratedTransactionValidationError, isTransfer } from '@xyo-network/xl1-protocol'\nimport {\n completedStepRewardAddress, derivedReceiveAddress, elevatedPayloads,\n} from '@xyo-network/xl1-protocol-sdk'\n\n/** Function type that checks whether a signer is authorized to sign for a given signee address. */\nexport type SignerValidator = (signer: Address, signee: Address, context?: { address?: Address; scope?: string; step?: StepIdentity }) => boolean\n\n/** Maps addresses to their list of authorized signer addresses. */\nexport type SignerMapping = Map<Address, Address[]>\n\n/** A signer validator that only allows an address to sign for itself. */\nexport const SelfSignerValidator: SignerValidator = (signer: Address, signee: Address) => signer === signee\n\n/** Creates a signer validator that authorizes specified signers to sign for completed step reward addresses. */\nexport const CompletedStepRewardAddressValidatorFactory = (allowedSigners: Address[]): SignerValidator => (\n signer: Address,\n signee: Address,\n context?: { step?: StepIdentity },\n) => {\n const step = context?.step\n if (isDefined(step)) {\n const contextAddress = completedStepRewardAddress(step)\n return allowedSigners.includes(signer) && signee === contextAddress\n } else {\n return false\n }\n}\n\n/** Creates a signer validator that authorizes specified signers to sign for derived receive addresses within a given scope. */\nexport const DerivedReceiveAddressValidatorFactory = (allowedSigners: Address[], allowedScope: string): SignerValidator => (\n signer: Address,\n signee: Address,\n context?: { address?: Address; scope?: string },\n) => {\n const { address, scope } = context ?? {}\n if (scope !== allowedScope) {\n return false\n }\n if (isDefined(address)) {\n const derivedAddress = derivedReceiveAddress(address, scope)\n return allowedSigners.includes(signer) && signee === derivedAddress\n } else {\n return false\n }\n}\n\n/** Creates a transaction validator that checks all transfers are authorized by the transaction signer. */\nexport function TransactionTransfersValidatorFactory(\n signerValidators: SignerValidator[] = [SelfSignerValidator],\n): HydratedTransactionValidationFunction {\n return async (\n context,\n hydratedTx,\n ) => {\n const errors: HydratedTransactionValidationError[] = []\n const signer = hydratedTx[0].from\n try {\n const payloads = elevatedPayloads(hydratedTx)\n const transfers = payloads.filter(isTransfer) as Transfer[]\n for (const transfer of transfers) {\n if (isUndefined(signerValidators.find(v => v(signer, transfer.from, transfer.context)))) {\n errors.push(new HydratedTransactionValidationError(\n hydratedTx[0]._hash,\n hydratedTx,\n `transfer from address ${transfer.from} is not authorized by signer ${signer}`,\n ))\n }\n }\n } catch (ex) {\n errors.push(new HydratedTransactionValidationError(hydratedTx[0]._hash, hydratedTx, 'validation excepted', ex))\n }\n return await Promise.resolve(errors)\n }\n}\n"],"mappings":"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","names":["ZERO_HASH","ZERO_HASH","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","hexToBigInt","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","ZERO_HASH","HydratedTransactionValidationError","HydratedTransactionValidationError","isTransfer"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction, HydratedTransactionValidationFunctionContext, HydratedTransactionWithHashMeta } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates a hydrated transaction using built-in validators plus any additional validators provided. */
|
|
2
3
|
export declare function validateTransaction(context: HydratedTransactionValidationFunctionContext, tx: HydratedTransactionWithHashMeta, additionalValidators?: HydratedTransactionValidationFunction[]): Promise<Error[]>;
|
|
3
4
|
//# sourceMappingURL=validateTransaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateTransaction.d.ts","sourceRoot":"","sources":["../../../src/transaction/validateTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qCAAqC,EACrC,4CAA4C,EAC5C,+BAA+B,EAChC,MAAM,2BAA2B,CAAA;AAQlC,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,4CAA4C,EACrD,EAAE,EAAE,+BAA+B,EACnC,oBAAoB,CAAC,EAAE,qCAAqC,EAAE,oBAmB/D"}
|
|
1
|
+
{"version":3,"file":"validateTransaction.d.ts","sourceRoot":"","sources":["../../../src/transaction/validateTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qCAAqC,EACrC,4CAA4C,EAC5C,+BAA+B,EAChC,MAAM,2BAA2B,CAAA;AAQlC,0GAA0G;AAC1G,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,4CAA4C,EACrD,EAAE,EAAE,+BAA+B,EACnC,oBAAoB,CAAC,EAAE,qCAAqC,EAAE,oBAmB/D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates that transaction timing fields (nbf and exp) are positive, correctly ordered, and within allowed duration limits. */
|
|
2
3
|
export declare const TransactionDurationValidator: HydratedTransactionValidationFunction;
|
|
3
4
|
//# sourceMappingURL=TransactionDurationValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionDurationValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionDurationValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AAGtF,eAAO,MAAM,4BAA4B,EAAE,qCA2B1C,CAAA"}
|
|
1
|
+
{"version":3,"file":"TransactionDurationValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionDurationValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AAGtF,kIAAkI;AAClI,eAAO,MAAM,4BAA4B,EAAE,qCA2B1C,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates that a hydrated transaction includes all required elevated script hashes. */
|
|
2
3
|
export declare const TransactionElevationValidator: HydratedTransactionValidationFunction;
|
|
3
4
|
//# sourceMappingURL=TransactionElevationValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionElevationValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionElevationValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AAItF,eAAO,MAAM,6BAA6B,EAAE,qCAoB3C,CAAA"}
|
|
1
|
+
{"version":3,"file":"TransactionElevationValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionElevationValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AAItF,0FAA0F;AAC1F,eAAO,MAAM,6BAA6B,EAAE,qCAoB3C,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates that the transaction's from field is a valid address and is included in the BoundWitness addresses. */
|
|
2
3
|
export declare const TransactionFromValidator: HydratedTransactionValidationFunction;
|
|
3
4
|
//# sourceMappingURL=TransactionFromValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionFromValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionFromValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AAGtF,eAAO,MAAM,wBAAwB,EAAE,qCA0BtC,CAAA"}
|
|
1
|
+
{"version":3,"file":"TransactionFromValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionFromValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AAGtF,oHAAoH;AACpH,eAAO,MAAM,wBAAwB,EAAE,qCA0BtC,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates that transaction fee fields (base, gasLimit, gasPrice, priority) are present and meet minimum requirements. */
|
|
2
3
|
export declare const TransactionGasValidator: HydratedTransactionValidationFunction;
|
|
3
4
|
//# sourceMappingURL=TransactionGasValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionGasValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionGasValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qCAAqC,EAEtC,MAAM,2BAA2B,CAAA;AAOlC,eAAO,MAAM,uBAAuB,EAAE,qCAyErC,CAAA"}
|
|
1
|
+
{"version":3,"file":"TransactionGasValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionGasValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qCAAqC,EAEtC,MAAM,2BAA2B,CAAA;AAOlC,4HAA4H;AAC5H,eAAO,MAAM,uBAAuB,EAAE,qCAyErC,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates a transaction against the TransactionBoundWitness JSON schema using AJV. */
|
|
2
3
|
export declare const TransactionJsonSchemaValidator: HydratedTransactionValidationFunction;
|
|
3
4
|
//# sourceMappingURL=TransactionJsonSchemaValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionJsonSchemaValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionJsonSchemaValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qCAAqC,EAA2B,MAAM,2BAA2B,CAAA;AAU/G,eAAO,MAAM,8BAA8B,EAAE,qCAoB5C,CAAA"}
|
|
1
|
+
{"version":3,"file":"TransactionJsonSchemaValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionJsonSchemaValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qCAAqC,EAA2B,MAAM,2BAA2B,CAAA;AAU/G,yFAAyF;AACzF,eAAO,MAAM,8BAA8B,EAAE,qCAoB5C,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol';
|
|
2
|
+
/** Validates that the transaction's chain ID matches the expected chain ID from the validation context. */
|
|
2
3
|
export declare const TransactionProtocolValidator: HydratedTransactionValidationFunction;
|
|
3
4
|
//# sourceMappingURL=TransactionProtocolValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionProtocolValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionProtocolValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,qCAAqC,EACtC,MAAM,2BAA2B,CAAA;AAGlC,eAAO,MAAM,4BAA4B,EAAE,qCAa1C,CAAA"}
|
|
1
|
+
{"version":3,"file":"TransactionProtocolValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionProtocolValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,qCAAqC,EACtC,MAAM,2BAA2B,CAAA;AAGlC,2GAA2G;AAC3G,eAAO,MAAM,4BAA4B,EAAE,qCAa1C,CAAA"}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import type { Address } from '@xylabs/sdk-js';
|
|
2
2
|
import type { HydratedTransactionValidationFunction, StepIdentity } from '@xyo-network/xl1-protocol';
|
|
3
|
+
/** Function type that checks whether a signer is authorized to sign for a given signee address. */
|
|
3
4
|
export type SignerValidator = (signer: Address, signee: Address, context?: {
|
|
4
5
|
address?: Address;
|
|
5
6
|
scope?: string;
|
|
6
7
|
step?: StepIdentity;
|
|
7
8
|
}) => boolean;
|
|
9
|
+
/** Maps addresses to their list of authorized signer addresses. */
|
|
8
10
|
export type SignerMapping = Map<Address, Address[]>;
|
|
11
|
+
/** A signer validator that only allows an address to sign for itself. */
|
|
9
12
|
export declare const SelfSignerValidator: SignerValidator;
|
|
13
|
+
/** Creates a signer validator that authorizes specified signers to sign for completed step reward addresses. */
|
|
10
14
|
export declare const CompletedStepRewardAddressValidatorFactory: (allowedSigners: Address[]) => SignerValidator;
|
|
15
|
+
/** Creates a signer validator that authorizes specified signers to sign for derived receive addresses within a given scope. */
|
|
11
16
|
export declare const DerivedReceiveAddressValidatorFactory: (allowedSigners: Address[], allowedScope: string) => SignerValidator;
|
|
17
|
+
/** Creates a transaction validator that checks all transfers are authorized by the transaction signer. */
|
|
12
18
|
export declare function TransactionTransfersValidatorFactory(signerValidators?: SignerValidator[]): HydratedTransactionValidationFunction;
|
|
13
19
|
//# sourceMappingURL=TransactionTransfersValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionTransfersValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionTransfersValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,KAAK,EACV,qCAAqC,EAAE,YAAY,EAEpD,MAAM,2BAA2B,CAAA;AAMlC,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAAE,KAAK,OAAO,CAAA;AAEjJ,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;AAEnD,eAAO,MAAM,mBAAmB,EAAE,eAAyE,CAAA;AAE3G,eAAO,MAAM,0CAA0C,GAAI,gBAAgB,OAAO,EAAE,KAAG,eAYtF,CAAA;AAED,eAAO,MAAM,qCAAqC,GAAI,gBAAgB,OAAO,EAAE,EAAE,cAAc,MAAM,KAAG,eAevG,CAAA;AAED,wBAAgB,oCAAoC,CAClD,gBAAgB,GAAE,eAAe,EAA0B,GAC1D,qCAAqC,CAwBvC"}
|
|
1
|
+
{"version":3,"file":"TransactionTransfersValidator.d.ts","sourceRoot":"","sources":["../../../../src/transaction/validators/TransactionTransfersValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,KAAK,EACV,qCAAqC,EAAE,YAAY,EAEpD,MAAM,2BAA2B,CAAA;AAMlC,mGAAmG;AACnG,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAAE,KAAK,OAAO,CAAA;AAEjJ,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;AAEnD,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,EAAE,eAAyE,CAAA;AAE3G,gHAAgH;AAChH,eAAO,MAAM,0CAA0C,GAAI,gBAAgB,OAAO,EAAE,KAAG,eAYtF,CAAA;AAED,+HAA+H;AAC/H,eAAO,MAAM,qCAAqC,GAAI,gBAAgB,OAAO,EAAE,EAAE,cAAc,MAAM,KAAG,eAevG,CAAA;AAED,0GAA0G;AAC1G,wBAAgB,oCAAoC,CAClD,gBAAgB,GAAE,eAAe,EAA0B,GAC1D,qCAAqC,CAwBvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/xl1-validation",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.28",
|
|
4
4
|
"description": "XYO Layer One SDK Validation",
|
|
5
5
|
"homepage": "https://xylabs.com",
|
|
6
6
|
"bugs": {
|
|
@@ -38,21 +38,21 @@
|
|
|
38
38
|
"!**/*.test.*"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@xyo-network/xl1-protocol": "~1.25.
|
|
42
|
-
"@xyo-network/xl1-protocol-sdk": "~1.25.
|
|
43
|
-
"@xyo-network/xl1-schema": "~1.25.
|
|
41
|
+
"@xyo-network/xl1-protocol": "~1.25.28",
|
|
42
|
+
"@xyo-network/xl1-protocol-sdk": "~1.25.28",
|
|
43
|
+
"@xyo-network/xl1-schema": "~1.25.28"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/node": "^25.
|
|
46
|
+
"@types/node": "^25.5.0",
|
|
47
47
|
"@xylabs/sdk-js": "^5.0.86",
|
|
48
|
-
"@xylabs/ts-scripts-yarn3": "~7.4.
|
|
49
|
-
"@xylabs/tsconfig": "~7.4.
|
|
48
|
+
"@xylabs/ts-scripts-yarn3": "~7.4.25",
|
|
49
|
+
"@xylabs/tsconfig": "~7.4.25",
|
|
50
50
|
"@xyo-network/sdk-js": "^5.3.16",
|
|
51
51
|
"ajv": "^8.18.0",
|
|
52
52
|
"axios": "^1.13.6",
|
|
53
53
|
"ethers": "^6.16.0",
|
|
54
54
|
"typescript": "~5.9.3",
|
|
55
|
-
"vitest": "~4.
|
|
55
|
+
"vitest": "~4.1.1",
|
|
56
56
|
"zod": "~4.3.6"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './validators/index.ts'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Address, type Hex, hexToBigInt,
|
|
3
|
+
} from '@xylabs/sdk-js'
|
|
4
|
+
import type {
|
|
5
|
+
HydratedBlockStateValidationFunction,
|
|
6
|
+
TransactionBoundWitnessWithHashMeta,
|
|
7
|
+
} from '@xyo-network/xl1-protocol'
|
|
8
|
+
import {
|
|
9
|
+
HydratedBlockStateValidationError,
|
|
10
|
+
isTransactionBoundWitnessWithHashMeta,
|
|
11
|
+
isTransfer,
|
|
12
|
+
} from '@xyo-network/xl1-protocol'
|
|
13
|
+
|
|
14
|
+
/** Compute the maximum fee commitment for a transaction (base + priority + gasLimit * gasPrice). */
|
|
15
|
+
function transactionFeeCost(tx: TransactionBoundWitnessWithHashMeta): bigint {
|
|
16
|
+
const {
|
|
17
|
+
base, gasLimit, gasPrice, priority,
|
|
18
|
+
} = tx.fees
|
|
19
|
+
return hexToBigInt(base) + hexToBigInt(priority) + (hexToBigInt(gasLimit) * hexToBigInt(gasPrice))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Creates a block state validator that checks cumulative outflows per address do not exceed pre-block balances. */
|
|
23
|
+
export function BlockCumulativeBalanceValidatorFactory(): HydratedBlockStateValidationFunction {
|
|
24
|
+
return async (context, hydratedBlock) => {
|
|
25
|
+
const [blockBw, payloads] = hydratedBlock
|
|
26
|
+
|
|
27
|
+
// Find all transactions in the block
|
|
28
|
+
const transactions = payloads.filter(isTransactionBoundWitnessWithHashMeta)
|
|
29
|
+
|
|
30
|
+
if (transactions.length === 0) return []
|
|
31
|
+
|
|
32
|
+
// Accumulate outflows per address
|
|
33
|
+
const outflows: Record<Address, bigint> = {}
|
|
34
|
+
|
|
35
|
+
for (const tx of transactions) {
|
|
36
|
+
// Fee cost charged to the transaction sender
|
|
37
|
+
const feeCost = transactionFeeCost(tx)
|
|
38
|
+
const feePayer = tx.from
|
|
39
|
+
outflows[feePayer] = (outflows[feePayer] ?? 0n) + feeCost
|
|
40
|
+
|
|
41
|
+
// Find transfer payloads belonging to this transaction
|
|
42
|
+
const txPayloadHashes = new Set(tx.payload_hashes)
|
|
43
|
+
for (const payload of payloads) {
|
|
44
|
+
if (!txPayloadHashes.has(payload._hash) || !isTransfer(payload)) continue
|
|
45
|
+
const { from } = payload
|
|
46
|
+
for (const amount of Object.values(payload.transfers) as Hex[]) {
|
|
47
|
+
outflows[from] = (outflows[from] ?? 0n) + hexToBigInt(amount)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Query pre-block balances for all addresses with outflows
|
|
53
|
+
const addresses = Object.keys(outflows) as Address[]
|
|
54
|
+
if (addresses.length === 0) return []
|
|
55
|
+
|
|
56
|
+
const balances = await context.accountBalance.accountBalances(addresses)
|
|
57
|
+
|
|
58
|
+
// Check each address
|
|
59
|
+
const chainId = await context.chainIdAtBlockNumber(blockBw.block)
|
|
60
|
+
const errors: HydratedBlockStateValidationError[] = []
|
|
61
|
+
for (const address of addresses) {
|
|
62
|
+
const balance = balances[address] ?? 0n
|
|
63
|
+
const totalOutflow = outflows[address]
|
|
64
|
+
if (totalOutflow > balance) {
|
|
65
|
+
errors.push(new HydratedBlockStateValidationError(
|
|
66
|
+
blockBw._hash,
|
|
67
|
+
chainId,
|
|
68
|
+
hydratedBlock,
|
|
69
|
+
`Cumulative outflow for address ${address} exceeds available balance: outflow ${totalOutflow} > balance ${balance}`,
|
|
70
|
+
))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return errors
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './BlockCumulativeBalanceValidator.ts'
|
|
@@ -14,6 +14,7 @@ function getPayloadsFromPayloadArray(payloads: WithHashMeta<Payload>[], hashes:
|
|
|
14
14
|
return hashes.map(hash => payloads.find(payload => payload._hash === hash || payload._dataHash === hash))
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/** Creates a validator that checks all payload references in a BoundWitness are present, have matching schemas, and optionally conform to an allowed schema list. */
|
|
17
18
|
export const BoundWitnessReferencesValidator
|
|
18
19
|
|
|
19
20
|
= <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]): HydratedBoundWitnessValidationFunction<T> => (
|
|
@@ -5,6 +5,7 @@ import { BoundWitnessBuilder, BoundWitnessValidator } from '@xyo-network/sdk-js'
|
|
|
5
5
|
import type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol'
|
|
6
6
|
import { BoundWitnessValidationError } from '@xyo-network/xl1-protocol'
|
|
7
7
|
|
|
8
|
+
/** Validates that all signatures on a BoundWitness are cryptographically valid for their corresponding addresses. */
|
|
8
9
|
export const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction = async (
|
|
9
10
|
bw: BoundWitness,
|
|
10
11
|
) => {
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
TransactionElevationValidator, TransactionFromValidator, TransactionGasValidator, TransactionProtocolValidator,
|
|
11
11
|
} from './validators/index.ts'
|
|
12
12
|
|
|
13
|
+
/** Validates a hydrated transaction using built-in validators plus any additional validators provided. */
|
|
13
14
|
export async function validateTransaction(
|
|
14
15
|
context: HydratedTransactionValidationFunctionContext,
|
|
15
16
|
tx: HydratedTransactionWithHashMeta,
|
|
@@ -2,6 +2,7 @@ import { ZERO_HASH } from '@xylabs/sdk-js'
|
|
|
2
2
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
3
|
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
4
4
|
|
|
5
|
+
/** Validates that transaction timing fields (nbf and exp) are positive, correctly ordered, and within allowed duration limits. */
|
|
5
6
|
export const TransactionDurationValidator: HydratedTransactionValidationFunction = (
|
|
6
7
|
context,
|
|
7
8
|
tx,
|
|
@@ -3,6 +3,7 @@ import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-pro
|
|
|
3
3
|
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
4
4
|
import { extractElevatedHashes } from '@xyo-network/xl1-protocol-sdk'
|
|
5
5
|
|
|
6
|
+
/** Validates that a hydrated transaction includes all required elevated script hashes. */
|
|
6
7
|
export const TransactionElevationValidator: HydratedTransactionValidationFunction = (
|
|
7
8
|
context,
|
|
8
9
|
tx,
|
|
@@ -3,6 +3,7 @@ import { addressesContains } from '@xyo-network/sdk-js'
|
|
|
3
3
|
import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'
|
|
4
4
|
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
5
5
|
|
|
6
|
+
/** Validates that the transaction's from field is a valid address and is included in the BoundWitness addresses. */
|
|
6
7
|
export const TransactionFromValidator: HydratedTransactionValidationFunction = (
|
|
7
8
|
context,
|
|
8
9
|
tx,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
minTransactionFees,
|
|
10
10
|
} from '@xyo-network/xl1-protocol'
|
|
11
11
|
|
|
12
|
+
/** Validates that transaction fee fields (base, gasLimit, gasPrice, priority) are present and meet minimum requirements. */
|
|
12
13
|
export const TransactionGasValidator: HydratedTransactionValidationFunction = (
|
|
13
14
|
context,
|
|
14
15
|
tx,
|
|
@@ -10,6 +10,7 @@ const ajv = new Ajv({ allErrors: true, strict: true })
|
|
|
10
10
|
|
|
11
11
|
let validate: ValidateFunction<TransactionBoundWitness> | undefined
|
|
12
12
|
|
|
13
|
+
/** Validates a transaction against the TransactionBoundWitness JSON schema using AJV. */
|
|
13
14
|
export const TransactionJsonSchemaValidator: HydratedTransactionValidationFunction = (
|
|
14
15
|
context,
|
|
15
16
|
tx,
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from '@xyo-network/xl1-protocol'
|
|
6
6
|
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
7
7
|
|
|
8
|
+
/** Validates that the transaction's chain ID matches the expected chain ID from the validation context. */
|
|
8
9
|
export const TransactionProtocolValidator: HydratedTransactionValidationFunction = async (
|
|
9
10
|
context: { chainId?: ChainId },
|
|
10
11
|
tx,
|
|
@@ -9,12 +9,16 @@ import {
|
|
|
9
9
|
completedStepRewardAddress, derivedReceiveAddress, elevatedPayloads,
|
|
10
10
|
} from '@xyo-network/xl1-protocol-sdk'
|
|
11
11
|
|
|
12
|
+
/** Function type that checks whether a signer is authorized to sign for a given signee address. */
|
|
12
13
|
export type SignerValidator = (signer: Address, signee: Address, context?: { address?: Address; scope?: string; step?: StepIdentity }) => boolean
|
|
13
14
|
|
|
15
|
+
/** Maps addresses to their list of authorized signer addresses. */
|
|
14
16
|
export type SignerMapping = Map<Address, Address[]>
|
|
15
17
|
|
|
18
|
+
/** A signer validator that only allows an address to sign for itself. */
|
|
16
19
|
export const SelfSignerValidator: SignerValidator = (signer: Address, signee: Address) => signer === signee
|
|
17
20
|
|
|
21
|
+
/** Creates a signer validator that authorizes specified signers to sign for completed step reward addresses. */
|
|
18
22
|
export const CompletedStepRewardAddressValidatorFactory = (allowedSigners: Address[]): SignerValidator => (
|
|
19
23
|
signer: Address,
|
|
20
24
|
signee: Address,
|
|
@@ -29,6 +33,7 @@ export const CompletedStepRewardAddressValidatorFactory = (allowedSigners: Addre
|
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
/** Creates a signer validator that authorizes specified signers to sign for derived receive addresses within a given scope. */
|
|
32
37
|
export const DerivedReceiveAddressValidatorFactory = (allowedSigners: Address[], allowedScope: string): SignerValidator => (
|
|
33
38
|
signer: Address,
|
|
34
39
|
signee: Address,
|
|
@@ -46,6 +51,7 @@ export const DerivedReceiveAddressValidatorFactory = (allowedSigners: Address[],
|
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
|
|
54
|
+
/** Creates a transaction validator that checks all transfers are authorized by the transaction signer. */
|
|
49
55
|
export function TransactionTransfersValidatorFactory(
|
|
50
56
|
signerValidators: SignerValidator[] = [SelfSignerValidator],
|
|
51
57
|
): HydratedTransactionValidationFunction {
|