@xyo-network/chain-validation 1.4.8 → 1.5.0
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/index.mjs +251 -172
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/types/block/validateBlock.d.ts.map +1 -1
- package/dist/types/block/validators/AllowedPayloadSchemas.d.ts.map +1 -1
- package/dist/types/block/validators/Fields.d.ts.map +1 -1
- package/dist/types/block/validators/JsonSchema.d.ts.map +1 -1
- package/dist/types/block/validators/PreviousHash.d.ts.map +1 -1
- package/dist/types/elevatedPayload/lib/validateElevatedFromBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/lib/validateElevatedFromTransaction.d.ts.map +1 -1
- package/dist/types/elevatedPayload/lib/validateIncludedInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/lib/validateTransactionInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/lib/validateTypedPayloadInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/payloads/validateChainStakeIntentInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/payloads/validateHashInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/payloads/validateSchemaInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/payloads/validateTransferInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/validatePayloadInBlock.d.ts.map +1 -1
- package/dist/types/hydratedBlock/validateHydratedBlock.d.ts.map +1 -1
- package/dist/types/hydratedBlock/validators/Payloads.d.ts.map +1 -1
- package/dist/types/hydratedBlockState/validateHydratedBlockState.d.ts.map +1 -1
- package/dist/types/hydratedBlockState/validators/RequiredBalance.d.ts.map +1 -1
- package/dist/types/transaction/validateTransaction.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionDurationValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionElevationValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionFromValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionGasValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionProtocolValidator.d.ts.map +1 -1
- package/package.json +24 -25
- package/src/block/validateBlock.ts +5 -4
- package/src/block/validators/AllowedPayloadSchemas.ts +7 -3
- package/src/block/validators/Fields.ts +6 -2
- package/src/block/validators/JsonSchema.ts +12 -8
- package/src/block/validators/PreviousHash.ts +15 -11
- package/src/elevatedPayload/lib/validateElevatedFromBlock.ts +9 -4
- package/src/elevatedPayload/lib/validateElevatedFromTransaction.ts +11 -7
- package/src/elevatedPayload/lib/validateIncludedInBlock.ts +6 -2
- package/src/elevatedPayload/lib/validateTransactionInBlock.ts +8 -4
- package/src/elevatedPayload/lib/validateTypedPayloadInBlock.ts +10 -6
- package/src/elevatedPayload/payloads/validateChainStakeIntentInBlock.ts +5 -1
- package/src/elevatedPayload/payloads/validateHashInBlock.ts +5 -1
- package/src/elevatedPayload/payloads/validateSchemaInBlock.ts +5 -1
- package/src/elevatedPayload/payloads/validateTransferInBlock.ts +5 -1
- package/src/elevatedPayload/validatePayloadInBlock.ts +9 -5
- package/src/hydratedBlock/validateHydratedBlock.ts +13 -7
- package/src/hydratedBlock/validators/Payloads.ts +21 -16
- package/src/hydratedBlockState/validateHydratedBlockState.ts +15 -8
- package/src/hydratedBlockState/validators/RequiredBalance.ts +25 -34
- package/src/transaction/validateTransaction.ts +17 -13
- package/src/transaction/validators/TransactionDurationValidator.ts +9 -5
- package/src/transaction/validators/TransactionElevationValidator.ts +7 -3
- package/src/transaction/validators/TransactionFromValidator.ts +7 -3
- package/src/transaction/validators/TransactionGasValidator.ts +18 -14
- package/src/transaction/validators/TransactionProtocolValidator.ts +1 -5
package/dist/neutral/index.mjs
CHANGED
|
@@ -66,10 +66,14 @@ var BoundWitnessSignaturesValidator = /* @__PURE__ */ __name(async (bw) => {
|
|
|
66
66
|
import { isAllowedBlockPayloadSchema } from "@xyo-network/xl1-protocol";
|
|
67
67
|
var BlockAllowedPayloadSchemasValidator = /* @__PURE__ */ __name((block) => {
|
|
68
68
|
const errors = [];
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
try {
|
|
70
|
+
for (const schema of block.payload_schemas) {
|
|
71
|
+
if (!isAllowedBlockPayloadSchema(schema)) {
|
|
72
|
+
errors.push(new Error(`payload schema not allowed in block: ${schema}`));
|
|
73
|
+
}
|
|
72
74
|
}
|
|
75
|
+
} catch (e) {
|
|
76
|
+
errors.push(new Error(`Failed BlockAllowedPayloadSchemasValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
73
77
|
}
|
|
74
78
|
return errors;
|
|
75
79
|
}, "BlockAllowedPayloadSchemasValidator");
|
|
@@ -78,8 +82,12 @@ var BlockAllowedPayloadSchemasValidator = /* @__PURE__ */ __name((block) => {
|
|
|
78
82
|
import { isDefined } from "@xylabs/typeof";
|
|
79
83
|
var BlockFieldsValidator = /* @__PURE__ */ __name((block, chainId) => {
|
|
80
84
|
const errors = [];
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
try {
|
|
86
|
+
if (isDefined(chainId) && block.chain !== chainId.toLowerCase()) {
|
|
87
|
+
errors.push(new Error("invalid chain id"));
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
errors.push(new Error(`Failed BlockFieldsValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
83
91
|
}
|
|
84
92
|
return errors;
|
|
85
93
|
}, "BlockFieldsValidator");
|
|
@@ -89,16 +97,20 @@ import { BlockBoundWitnessWithStorageMetaJsonSchema } from "@xyo-network/chain-s
|
|
|
89
97
|
import { Ajv } from "ajv";
|
|
90
98
|
var BlockJsonSchemaValidator = /* @__PURE__ */ __name((jsonSchema = BlockBoundWitnessWithStorageMetaJsonSchema) => async (block) => {
|
|
91
99
|
const errors = [];
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
try {
|
|
101
|
+
const ajv2 = new Ajv({
|
|
102
|
+
allErrors: true,
|
|
103
|
+
strict: true
|
|
104
|
+
});
|
|
105
|
+
const validate2 = ajv2.compile(jsonSchema);
|
|
106
|
+
await validate2(block);
|
|
107
|
+
if ((validate2.errors ?? []).length > 0) {
|
|
108
|
+
const error = new Error("failed JSON schema validation");
|
|
109
|
+
error.cause = validate2.errors;
|
|
110
|
+
errors.push(error);
|
|
111
|
+
}
|
|
112
|
+
} catch (e) {
|
|
113
|
+
errors.push(new Error(`Failed BlockJsonSchemaValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
102
114
|
}
|
|
103
115
|
return errors;
|
|
104
116
|
}, "BlockJsonSchemaValidator");
|
|
@@ -107,23 +119,28 @@ var BlockJsonSchemaValidator = /* @__PURE__ */ __name((jsonSchema = BlockBoundWi
|
|
|
107
119
|
import { isHash } from "@xylabs/hex";
|
|
108
120
|
var BlockPreviousHashValidator = /* @__PURE__ */ __name((block) => {
|
|
109
121
|
const errors = [];
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
122
|
+
try {
|
|
123
|
+
const blockNumber = block.block;
|
|
124
|
+
if (blockNumber > 0n) {
|
|
125
|
+
if (!isHash(block.previous)) {
|
|
126
|
+
errors.push(new Error("previous hash is missing or invalid"));
|
|
127
|
+
}
|
|
128
|
+
} else if (blockNumber === 0) {
|
|
129
|
+
if (block.previous !== null) {
|
|
130
|
+
errors.push(new Error("previous hash should not be set"));
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
errors.push(new Error("invalid block number"));
|
|
118
134
|
}
|
|
119
|
-
}
|
|
120
|
-
errors.push(new Error(
|
|
135
|
+
} catch (e) {
|
|
136
|
+
errors.push(new Error(`Failed BlockPreviousHashValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
121
137
|
}
|
|
122
138
|
return errors;
|
|
123
139
|
}, "BlockPreviousHashValidator");
|
|
124
140
|
|
|
125
141
|
// src/block/validateBlock.ts
|
|
126
142
|
var validateBlock = /* @__PURE__ */ __name(async (block, chainId) => {
|
|
143
|
+
const errors = [];
|
|
127
144
|
try {
|
|
128
145
|
const validators = [
|
|
129
146
|
BoundWitnessSignaturesValidator,
|
|
@@ -132,14 +149,11 @@ var validateBlock = /* @__PURE__ */ __name(async (block, chainId) => {
|
|
|
132
149
|
BlockJsonSchemaValidator(),
|
|
133
150
|
BlockAllowedPayloadSchemasValidator
|
|
134
151
|
];
|
|
135
|
-
|
|
136
|
-
return errors;
|
|
152
|
+
errors.push(...(await Promise.all(validators.map((validator) => validator(block, chainId)))).flat());
|
|
137
153
|
} catch (ex) {
|
|
138
|
-
|
|
139
|
-
new Error("validation excepted"),
|
|
140
|
-
ex
|
|
141
|
-
];
|
|
154
|
+
errors.push(new Error("validation excepted"), ex);
|
|
142
155
|
}
|
|
156
|
+
return errors;
|
|
143
157
|
}, "validateBlock");
|
|
144
158
|
|
|
145
159
|
// src/elevatedPayload/validatePayloadInBlock.ts
|
|
@@ -160,28 +174,37 @@ var isElevatedFromBlock = /* @__PURE__ */ __name((payload, [, payloads]) => {
|
|
|
160
174
|
}, "isElevatedFromBlock");
|
|
161
175
|
|
|
162
176
|
// src/elevatedPayload/lib/validateElevatedFromBlock.ts
|
|
163
|
-
import {
|
|
177
|
+
import { transactionsFromHydratedBlock } from "@xyo-network/chain-protocol";
|
|
164
178
|
var validateElevatedFromBlock = /* @__PURE__ */ __name((payload, block) => {
|
|
165
179
|
const errors = [];
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
180
|
+
try {
|
|
181
|
+
const txs = transactionsFromHydratedBlock(block);
|
|
182
|
+
const allTxPayloadHashes = new Set(txs.flatMap((tx) => tx.payload_hashes));
|
|
183
|
+
if (allTxPayloadHashes.has(payload._hash)) {
|
|
184
|
+
errors.push(new Error(`Transaction may not include block payload hash [${payload.schema}]: ${payload._hash}`));
|
|
185
|
+
}
|
|
186
|
+
} catch (e) {
|
|
187
|
+
errors.push(new Error(`Failed validateElevatedFromBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
169
188
|
}
|
|
170
189
|
return errors;
|
|
171
190
|
}, "validateElevatedFromBlock");
|
|
172
191
|
|
|
173
192
|
// src/elevatedPayload/lib/validateElevatedFromTransaction.ts
|
|
174
|
-
import { transactionsFromHydratedBlock } from "@xyo-network/chain-protocol";
|
|
193
|
+
import { transactionsFromHydratedBlock as transactionsFromHydratedBlock2 } from "@xyo-network/chain-protocol";
|
|
175
194
|
var validateElevatedFromTransaction = /* @__PURE__ */ __name((payload, block) => {
|
|
176
195
|
const errors = [];
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
196
|
+
try {
|
|
197
|
+
const txs = transactionsFromHydratedBlock2(block);
|
|
198
|
+
if (txs.length > 0) {
|
|
199
|
+
const hashes = txs.flatMap((tx) => tx.payload_hashes);
|
|
200
|
+
if (!hashes.includes(payload._hash)) {
|
|
201
|
+
errors.push(new Error("Transaction does not include payload"));
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
errors.push(new Error("No Transactions in block"));
|
|
182
205
|
}
|
|
183
|
-
}
|
|
184
|
-
errors.push(new Error(
|
|
206
|
+
} catch (e) {
|
|
207
|
+
errors.push(new Error(`Failed validateElevatedFromTransaction: ${e instanceof Error ? e.message : String(e)}`));
|
|
185
208
|
}
|
|
186
209
|
return errors;
|
|
187
210
|
}, "validateElevatedFromTransaction");
|
|
@@ -191,10 +214,14 @@ import { isStorageMeta } from "@xyo-network/payload-model";
|
|
|
191
214
|
import { isTransactionBoundWitness as isTransactionBoundWitness2 } from "@xyo-network/xl1-protocol";
|
|
192
215
|
var validateTransactionInBlock = /* @__PURE__ */ __name(async (payload, _block) => {
|
|
193
216
|
const errors = [];
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
217
|
+
try {
|
|
218
|
+
if (isTransactionBoundWitness2(payload) && isStorageMeta(payload)) {
|
|
219
|
+
errors.push(...await BoundWitnessSignaturesValidator(payload));
|
|
220
|
+
} else {
|
|
221
|
+
errors.push(new Error("Payload failed isTransactionBoundWitness or isStorageMeta"));
|
|
222
|
+
}
|
|
223
|
+
} catch (e) {
|
|
224
|
+
errors.push(new Error(`Failed validateTransactionInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
198
225
|
}
|
|
199
226
|
return errors;
|
|
200
227
|
}, "validateTransactionInBlock");
|
|
@@ -203,14 +230,18 @@ var validateTransactionInBlock = /* @__PURE__ */ __name(async (payload, _block)
|
|
|
203
230
|
import { isStorageMeta as isStorageMeta2 } from "@xyo-network/payload-model";
|
|
204
231
|
var validateTypedPayloadInBlock = /* @__PURE__ */ __name(async (payload, block, identityFunction) => {
|
|
205
232
|
const errors = [];
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
|
|
233
|
+
try {
|
|
234
|
+
if (identityFunction(payload) && isStorageMeta2(payload)) {
|
|
235
|
+
if (isElevatedFromBlock(payload, block)) {
|
|
236
|
+
errors.push(...await validateElevatedFromBlock(payload, block));
|
|
237
|
+
} else {
|
|
238
|
+
errors.push(...await validateElevatedFromTransaction(payload, block));
|
|
239
|
+
}
|
|
209
240
|
} else {
|
|
210
|
-
errors.push(
|
|
241
|
+
errors.push(new Error("Payload failed identityFunction or isElevated or isStorageMeta"));
|
|
211
242
|
}
|
|
212
|
-
}
|
|
213
|
-
errors.push(new Error(
|
|
243
|
+
} catch (e) {
|
|
244
|
+
errors.push(new Error(`Failed validateTypedPayloadInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
214
245
|
}
|
|
215
246
|
return errors;
|
|
216
247
|
}, "validateTypedPayloadInBlock");
|
|
@@ -219,7 +250,11 @@ var validateTypedPayloadInBlock = /* @__PURE__ */ __name(async (payload, block,
|
|
|
219
250
|
import { isChainStakeIntent } from "@xyo-network/xl1-protocol";
|
|
220
251
|
var validateChainStakeIntentInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
221
252
|
const errors = [];
|
|
222
|
-
|
|
253
|
+
try {
|
|
254
|
+
errors.push(...await validateTypedPayloadInBlock(payload, block, isChainStakeIntent));
|
|
255
|
+
} catch (e) {
|
|
256
|
+
errors.push(new Error(`Failed validateChainStakeIntentInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
257
|
+
}
|
|
223
258
|
return errors;
|
|
224
259
|
}, "validateChainStakeIntentInBlock");
|
|
225
260
|
|
|
@@ -227,7 +262,11 @@ var validateChainStakeIntentInBlock = /* @__PURE__ */ __name(async (payload, blo
|
|
|
227
262
|
import { isHashPayload } from "@xyo-network/xl1-protocol";
|
|
228
263
|
var validateHashInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
229
264
|
const errors = [];
|
|
230
|
-
|
|
265
|
+
try {
|
|
266
|
+
errors.push(...await validateTypedPayloadInBlock(payload, block, isHashPayload));
|
|
267
|
+
} catch (e) {
|
|
268
|
+
errors.push(new Error(`Failed validateHashInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
269
|
+
}
|
|
231
270
|
return errors;
|
|
232
271
|
}, "validateHashInBlock");
|
|
233
272
|
|
|
@@ -235,7 +274,11 @@ var validateHashInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
|
235
274
|
import { isSchemaPayload } from "@xyo-network/schema-payload-plugin";
|
|
236
275
|
var validateSchemaInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
237
276
|
const errors = [];
|
|
238
|
-
|
|
277
|
+
try {
|
|
278
|
+
errors.push(...await validateTypedPayloadInBlock(payload, block, isSchemaPayload));
|
|
279
|
+
} catch (e) {
|
|
280
|
+
errors.push(new Error(`Failed validateSchemaInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
281
|
+
}
|
|
239
282
|
return errors;
|
|
240
283
|
}, "validateSchemaInBlock");
|
|
241
284
|
|
|
@@ -243,7 +286,11 @@ var validateSchemaInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
|
243
286
|
import { isTransfer } from "@xyo-network/xl1-protocol";
|
|
244
287
|
var validateTransferInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
245
288
|
const errors = [];
|
|
246
|
-
|
|
289
|
+
try {
|
|
290
|
+
errors.push(...await validateTypedPayloadInBlock(payload, block, isTransfer));
|
|
291
|
+
} catch (e) {
|
|
292
|
+
errors.push(new Error(`Failed validateTransferInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
293
|
+
}
|
|
247
294
|
return errors;
|
|
248
295
|
}, "validateTransferInBlock");
|
|
249
296
|
|
|
@@ -257,11 +304,15 @@ var payloadValidators = {
|
|
|
257
304
|
};
|
|
258
305
|
var validatePayloadInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
259
306
|
const errors = [];
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
307
|
+
try {
|
|
308
|
+
const validator = payloadValidators[payload.schema];
|
|
309
|
+
if (validator) {
|
|
310
|
+
errors.push(...await validator(payload, block));
|
|
311
|
+
} else {
|
|
312
|
+
errors.push(new Error(`Unsupported payload schema: ${payload.schema}`));
|
|
313
|
+
}
|
|
314
|
+
} catch (e) {
|
|
315
|
+
errors.push(new Error(`Failed validatePayloadInBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
265
316
|
}
|
|
266
317
|
return errors;
|
|
267
318
|
}, "validatePayloadInBlock");
|
|
@@ -269,88 +320,98 @@ var validatePayloadInBlock = /* @__PURE__ */ __name(async (payload, block) => {
|
|
|
269
320
|
// src/hydratedBlock/validators/Payloads.ts
|
|
270
321
|
var PayloadsInBlockValidator = /* @__PURE__ */ __name(async ([block, payloads]) => {
|
|
271
322
|
const errors = [];
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
for (let i = 0; i < block.payload_hashes.length; i++) {
|
|
277
|
-
const hash = block.payload_hashes[i];
|
|
278
|
-
const schema = block.payload_schemas[i];
|
|
279
|
-
const payload = payloadMap[hash];
|
|
280
|
-
if (payload) {
|
|
281
|
-
errors.push(...await validatePayloadInBlock(payload, [
|
|
282
|
-
block,
|
|
283
|
-
payloads
|
|
284
|
-
]));
|
|
285
|
-
delete payloadMap[hash];
|
|
286
|
-
} else {
|
|
287
|
-
errors.push(new Error(`missing payload ${hash} ${schema}`));
|
|
323
|
+
try {
|
|
324
|
+
const payloadMap = {};
|
|
325
|
+
for (const payload of payloads) {
|
|
326
|
+
payloadMap[payload._hash] = payload;
|
|
288
327
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
328
|
+
const remainingPayloads = {
|
|
329
|
+
...payloadMap
|
|
330
|
+
};
|
|
331
|
+
for (let i = 0; i < block.payload_hashes.length; i++) {
|
|
332
|
+
const hash = block.payload_hashes[i];
|
|
333
|
+
const schema = block.payload_schemas[i];
|
|
334
|
+
const payload = payloadMap[hash];
|
|
335
|
+
if (payload) {
|
|
336
|
+
errors.push(...await validatePayloadInBlock(payload, [
|
|
337
|
+
block,
|
|
338
|
+
payloads
|
|
339
|
+
]));
|
|
340
|
+
delete remainingPayloads[hash];
|
|
341
|
+
} else {
|
|
342
|
+
errors.push(new Error(`missing payload ${hash} ${schema}`));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (Object.keys(remainingPayloads).length > 0) {
|
|
346
|
+
errors.push(new Error(`extra payloads ${Object.keys(payloadMap).join(", ")}`));
|
|
347
|
+
}
|
|
348
|
+
} catch (e) {
|
|
349
|
+
errors.push(new Error(`Failed PayloadsInBlockValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
292
350
|
}
|
|
293
351
|
return errors;
|
|
294
352
|
}, "PayloadsInBlockValidator");
|
|
295
353
|
|
|
296
354
|
// src/hydratedBlock/validateHydratedBlock.ts
|
|
297
355
|
var validateHydratedBlock = /* @__PURE__ */ __name(async (hydratedBlock, chainId, additionalValidators = []) => {
|
|
298
|
-
const errors =
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
...(await Promise.all(validators.map((v) => v(hydratedBlock, chainId)))).flat()
|
|
307
|
-
|
|
356
|
+
const errors = [];
|
|
357
|
+
try {
|
|
358
|
+
errors.push(...await validateBlock(hydratedBlock[0], chainId));
|
|
359
|
+
const validators = [
|
|
360
|
+
BoundWitnessReferencesValidator(),
|
|
361
|
+
PayloadsInBlockValidator,
|
|
362
|
+
...additionalValidators
|
|
363
|
+
];
|
|
364
|
+
errors.push(...(await Promise.all(validators.map((v) => v(hydratedBlock, chainId)))).flat());
|
|
365
|
+
} catch (e) {
|
|
366
|
+
errors.push(new Error(`Failed validateHydratedBlock: ${e instanceof Error ? e.message : String(e)}`));
|
|
367
|
+
}
|
|
368
|
+
return errors;
|
|
308
369
|
}, "validateHydratedBlock");
|
|
309
370
|
|
|
310
371
|
// src/hydratedBlockState/validateHydratedBlockState.ts
|
|
311
|
-
var validateHydratedBlockState = /* @__PURE__ */ __name(async (hydratedBlock, chainId,
|
|
312
|
-
const errors =
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
...(await Promise.all(validators.map((v) => v(hydratedBlock, chainId,
|
|
320
|
-
|
|
372
|
+
var validateHydratedBlockState = /* @__PURE__ */ __name(async (hydratedBlock, chainId, services, additionalValidators = []) => {
|
|
373
|
+
const errors = [];
|
|
374
|
+
try {
|
|
375
|
+
errors.push(...await validateHydratedBlock(hydratedBlock, chainId));
|
|
376
|
+
const validators = [
|
|
377
|
+
// RequiredBalanceBlockStateValidator,
|
|
378
|
+
...additionalValidators
|
|
379
|
+
];
|
|
380
|
+
errors.push(...(await Promise.all(validators.map((v) => v(hydratedBlock, chainId, services)))).flat());
|
|
381
|
+
} catch (e) {
|
|
382
|
+
errors.push(new Error(`Failed validateHydratedBlockState: ${e instanceof Error ? e.message : String(e)}`));
|
|
383
|
+
}
|
|
384
|
+
return errors;
|
|
321
385
|
}, "validateHydratedBlockState");
|
|
322
386
|
|
|
323
387
|
// src/hydratedBlockState/validators/RequiredBalance.ts
|
|
324
|
-
import {
|
|
325
|
-
import {
|
|
326
|
-
|
|
327
|
-
var RequiredBalanceBlockStateValidator = /* @__PURE__ */ __name(async (block, chainId, archivist) => {
|
|
388
|
+
import { hexToBigInt } from "@xylabs/hex";
|
|
389
|
+
import { netBalancesForPayloads } from "@xyo-network/chain-protocol";
|
|
390
|
+
var RequiredBalanceBlockStateValidator = /* @__PURE__ */ __name(async (block, chainId, services) => {
|
|
328
391
|
const errors = [];
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
392
|
+
try {
|
|
393
|
+
const netBalances = netBalancesForPayloads(block[1]);
|
|
394
|
+
const netBalanceAddresses = Object.keys(netBalances);
|
|
395
|
+
const requiredBalances = {};
|
|
396
|
+
for (const address of netBalanceAddresses) {
|
|
397
|
+
if (netBalances[address] < 0n) {
|
|
398
|
+
requiredBalances[address] = -netBalances[address];
|
|
399
|
+
}
|
|
335
400
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
for (const [address, reqBalance] of Object.entries(requiredBalances)) {
|
|
346
|
-
const balance = parseSignedBigInt(summaryBalances.balances[address] ?? {
|
|
347
|
-
positive: "00"
|
|
348
|
-
});
|
|
349
|
-
if (reqBalance > balance) {
|
|
350
|
-
errors.push(new Error(`insufficient balance for ${address} ${balance} < ${requiredBalances[address]}`));
|
|
401
|
+
const previous = block[0].previous;
|
|
402
|
+
if (previous === null) return [
|
|
403
|
+
new Error("Insufficient funds because first block")
|
|
404
|
+
];
|
|
405
|
+
for (const [address, reqBalance] of Object.entries(requiredBalances)) {
|
|
406
|
+
const balance = hexToBigInt(services.accountBalance.getBalance(address));
|
|
407
|
+
if (reqBalance > balance) {
|
|
408
|
+
errors.push(new Error(`insufficient balance for ${address} ${balance} < ${requiredBalances[address]}`));
|
|
409
|
+
}
|
|
351
410
|
}
|
|
411
|
+
} catch (e) {
|
|
412
|
+
errors.push(new Error(`Failed RequiredBalanceBlockStateValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
352
413
|
}
|
|
353
|
-
return errors;
|
|
414
|
+
return await Promise.resolve(errors);
|
|
354
415
|
}, "RequiredBalanceBlockStateValidator");
|
|
355
416
|
|
|
356
417
|
// src/transaction/validateTransaction.ts
|
|
@@ -359,11 +420,15 @@ import { isTransactionBoundWitness as isTransactionBoundWitness3 } from "@xyo-ne
|
|
|
359
420
|
// src/transaction/validators/TransactionDurationValidator.ts
|
|
360
421
|
var TransactionDurationValidator = /* @__PURE__ */ __name(([tx]) => {
|
|
361
422
|
const errors = [];
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
423
|
+
try {
|
|
424
|
+
const { exp, nbf } = tx;
|
|
425
|
+
if (nbf < 0) errors.push(new Error("Transaction nbf must be positive"));
|
|
426
|
+
if (exp < 0) errors.push(new Error("Transaction exp must be positive"));
|
|
427
|
+
if (exp <= nbf) errors.push(new Error("Transaction exp must greater than nbf"));
|
|
428
|
+
if (exp - nbf > 1e4) errors.push(new Error("Transaction exp must not be too far in the future"));
|
|
429
|
+
} catch (e) {
|
|
430
|
+
errors.push(new Error(`Failed TransactionDurationValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
431
|
+
}
|
|
367
432
|
return errors;
|
|
368
433
|
}, "TransactionDurationValidator");
|
|
369
434
|
|
|
@@ -372,9 +437,13 @@ import { extractElevatedHashes } from "@xyo-network/chain-protocol";
|
|
|
372
437
|
var TransactionElevationValidator = /* @__PURE__ */ __name((tx) => {
|
|
373
438
|
const errors = [];
|
|
374
439
|
try {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
440
|
+
try {
|
|
441
|
+
extractElevatedHashes(tx);
|
|
442
|
+
} catch {
|
|
443
|
+
errors.push(new Error("Hydrated transaction does not include all script hashes"));
|
|
444
|
+
}
|
|
445
|
+
} catch (e) {
|
|
446
|
+
errors.push(new Error(`Failed TransactionElevationValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
378
447
|
}
|
|
379
448
|
return errors;
|
|
380
449
|
}, "TransactionElevationValidator");
|
|
@@ -384,39 +453,47 @@ import { asAddress } from "@xylabs/hex";
|
|
|
384
453
|
import { addressesContains } from "@xyo-network/boundwitness-validator";
|
|
385
454
|
var TransactionFromValidator = /* @__PURE__ */ __name(([tx]) => {
|
|
386
455
|
const errors = [];
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
456
|
+
try {
|
|
457
|
+
const from = asAddress(tx.from);
|
|
458
|
+
if (from === void 0) errors.push(new Error("Transaction from is not a valid address"));
|
|
459
|
+
else if (!addressesContains(tx, from)) errors.push(new Error("Transaction from address must be listed in addresses"));
|
|
460
|
+
} catch (e) {
|
|
461
|
+
errors.push(new Error(`Failed TransactionFromValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
462
|
+
}
|
|
390
463
|
return errors;
|
|
391
464
|
}, "TransactionFromValidator");
|
|
392
465
|
|
|
393
466
|
// src/transaction/validators/TransactionGasValidator.ts
|
|
394
|
-
import { hexToBigInt } from "@xylabs/hex";
|
|
467
|
+
import { hexToBigInt as hexToBigInt2 } from "@xylabs/hex";
|
|
395
468
|
import { AttoXL1, minTransactionFees } from "@xyo-network/xl1-protocol";
|
|
396
469
|
var TransactionGasValidator = /* @__PURE__ */ __name(([tx]) => {
|
|
397
470
|
const errors = [];
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
471
|
+
try {
|
|
472
|
+
if (tx?.fees === void 0) {
|
|
473
|
+
errors.push(new Error("Missing fees"));
|
|
474
|
+
} else {
|
|
475
|
+
const { base, gasLimit, gasPrice, priority } = parseFees(tx.fees);
|
|
476
|
+
if (base === void 0) errors.push(new Error("fees.base must be defined and a valid number"));
|
|
477
|
+
else if (base < minTransactionFees.base) errors.push(new Error(`fees.base must be >= ${minTransactionFees.base}`));
|
|
478
|
+
if (gasLimit === void 0) errors.push(new Error("fees.gasLimit must be defined and a valid number"));
|
|
479
|
+
else if (gasLimit < minTransactionFees.gasLimit) errors.push(new Error(`fees.gasLimit must be >= ${minTransactionFees.gasLimit}`));
|
|
480
|
+
if (gasPrice === void 0) errors.push(new Error("fees.gasPrice must be defined and a valid number"));
|
|
481
|
+
else if (gasPrice < minTransactionFees.gasPrice) errors.push(new Error(`fees.gasPrice must be >= ${minTransactionFees.gasPrice}`));
|
|
482
|
+
if (priority === void 0) errors.push(new Error("fees.priority must be defined and a valid number"));
|
|
483
|
+
else if (priority < minTransactionFees.priority) errors.push(new Error(`fees.priority must be >= ${minTransactionFees.priority}`));
|
|
484
|
+
}
|
|
485
|
+
} catch (e) {
|
|
486
|
+
errors.push(new Error(`Failed TransactionGasValidator: ${e instanceof Error ? e.message : String(e)}`));
|
|
410
487
|
}
|
|
411
488
|
return errors;
|
|
412
489
|
}, "TransactionGasValidator");
|
|
413
490
|
var parseFees = /* @__PURE__ */ __name((fees) => {
|
|
414
491
|
const ret = {};
|
|
415
492
|
const { base, gasLimit, gasPrice, priority } = fees;
|
|
416
|
-
if (base !== void 0) ret.base = AttoXL1(
|
|
417
|
-
if (gasLimit !== void 0) ret.gasLimit = AttoXL1(
|
|
418
|
-
if (gasPrice !== void 0) ret.gasPrice = AttoXL1(
|
|
419
|
-
if (priority !== void 0) ret.priority = AttoXL1(
|
|
493
|
+
if (base !== void 0) ret.base = AttoXL1(hexToBigInt2(base));
|
|
494
|
+
if (gasLimit !== void 0) ret.gasLimit = AttoXL1(hexToBigInt2(gasLimit));
|
|
495
|
+
if (gasPrice !== void 0) ret.gasPrice = AttoXL1(hexToBigInt2(gasPrice));
|
|
496
|
+
if (priority !== void 0) ret.priority = AttoXL1(hexToBigInt2(priority));
|
|
420
497
|
return ret;
|
|
421
498
|
}, "parseFees");
|
|
422
499
|
|
|
@@ -445,39 +522,41 @@ var TransactionJsonSchemaValidator = /* @__PURE__ */ __name(([tx]) => {
|
|
|
445
522
|
}, "TransactionJsonSchemaValidator");
|
|
446
523
|
|
|
447
524
|
// src/transaction/validators/TransactionProtocolValidator.ts
|
|
448
|
-
import { BoundWitnessWrapper } from "@xyo-network/boundwitness-wrapper";
|
|
449
525
|
var TransactionProtocolValidator = /* @__PURE__ */ __name(async ([tx], chainId) => {
|
|
450
526
|
const errors = [];
|
|
451
527
|
try {
|
|
452
|
-
if (!await BoundWitnessWrapper.parse(tx).getValid()) {
|
|
453
|
-
errors.push(new Error("failed basic boundwitness parse"));
|
|
454
|
-
}
|
|
455
528
|
if (chainId !== void 0 && tx.chain !== chainId) {
|
|
456
529
|
errors.push(new Error("invalid chain id"));
|
|
457
530
|
}
|
|
458
531
|
} catch (ex) {
|
|
459
532
|
errors.push(new Error("validation excepted"), ex);
|
|
460
533
|
}
|
|
461
|
-
return errors;
|
|
534
|
+
return await Promise.resolve(errors);
|
|
462
535
|
}, "TransactionProtocolValidator");
|
|
463
536
|
|
|
464
537
|
// src/transaction/validateTransaction.ts
|
|
465
538
|
async function validateTransaction(tx, chainId, additionalValidators = []) {
|
|
466
|
-
|
|
539
|
+
try {
|
|
540
|
+
if (!isTransactionBoundWitness3(tx[0])) {
|
|
541
|
+
return [
|
|
542
|
+
new Error("failed isTransactionBoundWitness identity check")
|
|
543
|
+
];
|
|
544
|
+
}
|
|
545
|
+
const validators = [
|
|
546
|
+
TransactionProtocolValidator,
|
|
547
|
+
TransactionJsonSchemaValidator,
|
|
548
|
+
TransactionDurationValidator,
|
|
549
|
+
TransactionFromValidator,
|
|
550
|
+
TransactionGasValidator,
|
|
551
|
+
TransactionElevationValidator,
|
|
552
|
+
...additionalValidators
|
|
553
|
+
];
|
|
554
|
+
return (await Promise.all(validators.map((v) => v(tx, chainId)))).flat();
|
|
555
|
+
} catch (e) {
|
|
467
556
|
return [
|
|
468
|
-
new Error(
|
|
557
|
+
new Error(`Failed TransactionGasValidator: ${e instanceof Error ? e.message : String(e)}`)
|
|
469
558
|
];
|
|
470
559
|
}
|
|
471
|
-
const validators = [
|
|
472
|
-
TransactionProtocolValidator,
|
|
473
|
-
TransactionJsonSchemaValidator,
|
|
474
|
-
TransactionDurationValidator,
|
|
475
|
-
TransactionFromValidator,
|
|
476
|
-
TransactionGasValidator,
|
|
477
|
-
TransactionElevationValidator,
|
|
478
|
-
...additionalValidators
|
|
479
|
-
];
|
|
480
|
-
return (await Promise.all(validators.map((v) => v(tx, chainId)))).flat();
|
|
481
560
|
}
|
|
482
561
|
__name(validateTransaction, "validateTransaction");
|
|
483
562
|
export {
|