@xyo-network/chain-validation 1.5.32 → 1.5.34
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 +81 -61
- 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/boundwitness/validators/BoundWitnessReferences.d.ts.map +1 -1
- package/dist/types/boundwitness/validators/BoundWitnessSignatures.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/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/TransactionJsonSchemaValidator.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/block/validateBlock.ts +3 -2
- package/src/block/validators/AllowedPayloadSchemas.ts +12 -2
- package/src/block/validators/Fields.ts +15 -4
- package/src/block/validators/JsonSchema.ts +13 -2
- package/src/block/validators/PreviousHash.ts +10 -5
- package/src/boundwitness/validators/BoundWitnessReferences.ts +8 -7
- package/src/boundwitness/validators/BoundWitnessSignatures.ts +3 -2
- package/src/elevatedPayload/payloads/validateChainStakeIntentInBlock.ts +7 -1
- package/src/elevatedPayload/payloads/validateHashInBlock.ts +7 -1
- package/src/elevatedPayload/payloads/validateSchemaInBlock.ts +7 -1
- package/src/elevatedPayload/payloads/validateTransferInBlock.ts +7 -1
- package/src/elevatedPayload/validatePayloadInBlock.ts +8 -2
- package/src/hydratedBlock/validateHydratedBlock.ts +6 -2
- package/src/hydratedBlock/validators/Payloads.ts +8 -4
- package/src/hydratedBlockState/validateHydratedBlockState.ts +2 -1
- package/src/hydratedBlockState/validators/RequiredBalance.ts +11 -2
- package/src/transaction/validators/TransactionDurationValidator.ts +15 -5
- package/src/transaction/validators/TransactionElevationValidator.ts +7 -2
- package/src/transaction/validators/TransactionFromValidator.ts +16 -4
- package/src/transaction/validators/TransactionGasValidator.ts +28 -5
- package/src/transaction/validators/TransactionJsonSchemaValidator.ts +8 -2
- package/src/transaction/validators/TransactionProtocolValidator.ts +3 -3
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import { toJsonString } from '@xylabs/object'
|
|
1
3
|
import { BlockBoundWitnessWithStorageMetaJsonSchema } from '@xyo-network/chain-schema'
|
|
4
|
+
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
2
5
|
import {
|
|
3
6
|
type BlockBoundWitness, BlockValidationError, type BlockValidatorFunction,
|
|
4
7
|
} from '@xyo-network/xl1-protocol'
|
|
@@ -15,11 +18,19 @@ export const BlockJsonSchemaValidator = (jsonSchema: AnySchema = BlockBoundWitne
|
|
|
15
18
|
const validate = ajv.compile(jsonSchema)
|
|
16
19
|
await validate(block)
|
|
17
20
|
if ((validate.errors ?? []).length > 0) {
|
|
18
|
-
const error = new BlockValidationError(
|
|
21
|
+
const error = new BlockValidationError(
|
|
22
|
+
(block as WithStorageMeta<BlockBoundWitness>)?._hash ?? ZERO_HASH,
|
|
23
|
+
block,
|
|
24
|
+
`failed JSON schema validation: ${toJsonString(block, 10)} ${toJsonString(validate.errors, 10)}`,
|
|
25
|
+
)
|
|
19
26
|
errors.push(error, ...validate.errors?.map(e => new Error(` ${e.instancePath} ${e.message ?? ''}`)) ?? [])
|
|
20
27
|
}
|
|
21
28
|
} catch (e) {
|
|
22
|
-
errors.push(new BlockValidationError(
|
|
29
|
+
errors.push(new BlockValidationError(
|
|
30
|
+
(block as WithStorageMeta<BlockBoundWitness>)?._hash ?? ZERO_HASH,
|
|
31
|
+
block,
|
|
32
|
+
`Failed BlockJsonSchemaValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
33
|
+
))
|
|
23
34
|
}
|
|
24
35
|
return errors
|
|
25
36
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { isHash } from '@xylabs/hex'
|
|
1
|
+
import { isHash, ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
2
3
|
import type { BlockBoundWitness, BlockValidatorFunction } from '@xyo-network/xl1-protocol'
|
|
3
4
|
import { BlockValidationError } from '@xyo-network/xl1-protocol'
|
|
4
5
|
|
|
@@ -11,19 +12,23 @@ export const BlockPreviousHashValidator: BlockValidatorFunction = (
|
|
|
11
12
|
if (blockNumber > 0n) {
|
|
12
13
|
// if this is not the first block, validate previous hashes
|
|
13
14
|
if (!isHash(block.previous)) {
|
|
14
|
-
errors.push(new BlockValidationError(block, 'previous hash is missing or invalid'))
|
|
15
|
+
errors.push(new BlockValidationError((block as WithStorageMeta<BlockBoundWitness>)?._hash ?? ZERO_HASH, block, 'previous hash is missing or invalid'))
|
|
15
16
|
}
|
|
16
17
|
} else if (blockNumber === 0) {
|
|
17
18
|
// if this is the first block, validate previous hashes
|
|
18
19
|
if (block.previous !== null) {
|
|
19
|
-
errors.push(new BlockValidationError(block, 'previous hash should not be set'))
|
|
20
|
+
errors.push(new BlockValidationError((block as WithStorageMeta<BlockBoundWitness>)?._hash ?? ZERO_HASH, block, 'previous hash should not be set'))
|
|
20
21
|
}
|
|
21
22
|
} else {
|
|
22
23
|
// we have a negative block number
|
|
23
|
-
errors.push(new BlockValidationError(block, 'invalid block number'))
|
|
24
|
+
errors.push(new BlockValidationError((block as WithStorageMeta<BlockBoundWitness>)?._hash ?? ZERO_HASH, block, 'invalid block number'))
|
|
24
25
|
}
|
|
25
26
|
} catch (e) {
|
|
26
|
-
errors.push(new BlockValidationError(
|
|
27
|
+
errors.push(new BlockValidationError(
|
|
28
|
+
(block as WithStorageMeta<BlockBoundWitness>)?._hash ?? ZERO_HASH,
|
|
29
|
+
block,
|
|
30
|
+
`Failed BlockPreviousHashValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
31
|
+
))
|
|
27
32
|
}
|
|
28
33
|
return errors
|
|
29
34
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Hash, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import type { Promisable } from '@xylabs/promise'
|
|
3
3
|
import type { BoundWitness } from '@xyo-network/boundwitness-model'
|
|
4
4
|
import type {
|
|
@@ -15,6 +15,7 @@ function getPayloadsFromPayloadArray(payloads: WithHashStorageMeta<Payload>[], h
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export const BoundWitnessReferencesValidator
|
|
18
|
+
// eslint-disable-next-line complexity
|
|
18
19
|
= <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]): HydratedBoundWitnessValidationFunction<T> => (
|
|
19
20
|
[bw, payloadSet]: HydratedBoundWitnessWithHashStorageMeta<T>,
|
|
20
21
|
): Promisable<(HydratedBoundWitnessValidationError | Error)[]> => {
|
|
@@ -22,7 +23,7 @@ export const BoundWitnessReferencesValidator
|
|
|
22
23
|
try {
|
|
23
24
|
const payloads = getPayloadsFromPayloadArray(payloadSet, bw.payload_hashes)
|
|
24
25
|
if (payloads.length !== bw.payload_hashes.length) {
|
|
25
|
-
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'unable to locate payloads'))
|
|
26
|
+
errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'unable to locate payloads'))
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
// check if payloads are valid and if their schemas match the declared schemas
|
|
@@ -32,23 +33,23 @@ export const BoundWitnessReferencesValidator
|
|
|
32
33
|
const payloadDataHashIndex = bw.payload_hashes.indexOf(payload._dataHash)
|
|
33
34
|
const payloadIndex = Math.max(payloadHashIndex, payloadDataHashIndex)
|
|
34
35
|
if (payloadIndex === -1) {
|
|
35
|
-
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'payload hash not found'))
|
|
36
|
+
errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'payload hash not found'))
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
const declaredSchema = bw.payload_schemas[payloadIndex]
|
|
39
40
|
if (declaredSchema !== payload.schema) {
|
|
40
|
-
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'mismatched schema'))
|
|
41
|
+
errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'mismatched schema'))
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
if (allowedSchemas && !allowedSchemas.includes(payload.schema)) {
|
|
44
|
-
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], `disallowed schema [${payload.schema}]`))
|
|
45
|
+
errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `disallowed schema [${payload.schema}]`))
|
|
45
46
|
}
|
|
46
47
|
} else {
|
|
47
|
-
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'invalid payload'))
|
|
48
|
+
errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'invalid payload'))
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
} catch (ex) {
|
|
51
|
-
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'validation excepted'), ex as Error)
|
|
52
|
+
errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'validation excepted'), ex as Error)
|
|
52
53
|
}
|
|
53
54
|
return errors
|
|
54
55
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { toArrayBuffer } from '@xylabs/arraybuffer'
|
|
2
|
-
import type
|
|
2
|
+
import { type Address, ZERO_HASH } from '@xylabs/hex'
|
|
3
3
|
import { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'
|
|
4
4
|
import type { BoundWitness } from '@xyo-network/boundwitness-model'
|
|
5
5
|
import { BoundWitnessValidator } from '@xyo-network/boundwitness-validator'
|
|
6
|
+
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
6
7
|
import type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol'
|
|
7
8
|
import { BoundWitnessValidationError } from '@xyo-network/xl1-protocol'
|
|
8
9
|
|
|
@@ -19,7 +20,7 @@ export const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction = a
|
|
|
19
20
|
errors.push(...bwErrors)
|
|
20
21
|
}
|
|
21
22
|
} catch (ex) {
|
|
22
|
-
errors.push(new BoundWitnessValidationError(bw, 'validation excepted'), ex as Error)
|
|
23
|
+
errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation excepted'), ex as Error)
|
|
23
24
|
}
|
|
24
25
|
return errors
|
|
25
26
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import type { HydratedBlock, InBlockPayloadValidationFunction } from '@xyo-network/xl1-protocol'
|
|
2
3
|
import { InBlockPayloadValidationError, isChainStakeIntent } from '@xyo-network/xl1-protocol'
|
|
3
4
|
|
|
@@ -11,7 +12,12 @@ export const validateChainStakeIntentInBlock: InBlockPayloadValidationFunction =
|
|
|
11
12
|
try {
|
|
12
13
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isChainStakeIntent))
|
|
13
14
|
} catch (e) {
|
|
14
|
-
errors.push(new InBlockPayloadValidationError(
|
|
15
|
+
errors.push(new InBlockPayloadValidationError(
|
|
16
|
+
block[0]?._hash ?? ZERO_HASH,
|
|
17
|
+
block,
|
|
18
|
+
payload,
|
|
19
|
+
`Failed validateChainStakeIntentInBlock: ${e instanceof Error ? e.message : String(e)}`,
|
|
20
|
+
))
|
|
15
21
|
}
|
|
16
22
|
return errors
|
|
17
23
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import type { HydratedBlock, InBlockPayloadValidationFunction } from '@xyo-network/xl1-protocol'
|
|
2
3
|
import { InBlockPayloadValidationError, isHashPayload } from '@xyo-network/xl1-protocol'
|
|
3
4
|
|
|
@@ -11,7 +12,12 @@ export const validateHashInBlock: InBlockPayloadValidationFunction = async (
|
|
|
11
12
|
try {
|
|
12
13
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isHashPayload))
|
|
13
14
|
} catch (e) {
|
|
14
|
-
errors.push(new InBlockPayloadValidationError(
|
|
15
|
+
errors.push(new InBlockPayloadValidationError(
|
|
16
|
+
(block?.[0])?._hash ?? ZERO_HASH,
|
|
17
|
+
block,
|
|
18
|
+
payload,
|
|
19
|
+
`Failed validateHashInBlock: ${e instanceof Error ? e.message : String(e)}`,
|
|
20
|
+
))
|
|
15
21
|
}
|
|
16
22
|
return errors
|
|
17
23
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import { isSchemaPayload } from '@xyo-network/schema-payload-plugin'
|
|
2
3
|
import type { HydratedBlock, InBlockPayloadValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
4
|
import { InBlockPayloadValidationError } from '@xyo-network/xl1-protocol'
|
|
@@ -12,7 +13,12 @@ export const validateSchemaInBlock: InBlockPayloadValidationFunction = async (
|
|
|
12
13
|
try {
|
|
13
14
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isSchemaPayload))
|
|
14
15
|
} catch (e) {
|
|
15
|
-
errors.push(new InBlockPayloadValidationError(
|
|
16
|
+
errors.push(new InBlockPayloadValidationError(
|
|
17
|
+
(block?.[0])?._hash ?? ZERO_HASH,
|
|
18
|
+
block,
|
|
19
|
+
payload,
|
|
20
|
+
`Failed validateSchemaInBlock: ${e instanceof Error ? e.message : String(e)}`,
|
|
21
|
+
))
|
|
16
22
|
}
|
|
17
23
|
return errors
|
|
18
24
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import type {
|
|
2
3
|
HydratedBlock,
|
|
3
4
|
InBlockPayloadValidationFunction,
|
|
@@ -14,7 +15,12 @@ export const validateTransferInBlock: InBlockPayloadValidationFunction = async (
|
|
|
14
15
|
try {
|
|
15
16
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isTransfer))
|
|
16
17
|
} catch (e) {
|
|
17
|
-
errors.push(new InBlockPayloadValidationError(
|
|
18
|
+
errors.push(new InBlockPayloadValidationError(
|
|
19
|
+
(block?.[0])?._hash ?? ZERO_HASH,
|
|
20
|
+
block,
|
|
21
|
+
payload,
|
|
22
|
+
`Failed validateTransferInBlock: ${e instanceof Error ? e.message : String(e)}`,
|
|
23
|
+
))
|
|
18
24
|
}
|
|
19
25
|
return errors
|
|
20
26
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import { BoundWitnessSchema } from '@xyo-network/boundwitness-model'
|
|
2
3
|
import type { Schema } from '@xyo-network/payload-model'
|
|
3
4
|
import { SchemaSchema } from '@xyo-network/schema-payload-plugin'
|
|
@@ -33,10 +34,15 @@ export const validatePayloadInBlock: InBlockPayloadValidationFunction = async (
|
|
|
33
34
|
if (validator) {
|
|
34
35
|
errors.push(...await validator(payload, block))
|
|
35
36
|
} else {
|
|
36
|
-
errors.push(new InBlockPayloadValidationError(block, payload, `Unsupported payload schema: ${payload.schema}`))
|
|
37
|
+
errors.push(new InBlockPayloadValidationError((block?.[0])?._hash ?? ZERO_HASH, block, payload, `Unsupported payload schema: ${payload.schema}`))
|
|
37
38
|
}
|
|
38
39
|
} catch (e) {
|
|
39
|
-
errors.push(new InBlockPayloadValidationError(
|
|
40
|
+
errors.push(new InBlockPayloadValidationError(
|
|
41
|
+
(block?.[0])?._hash ?? ZERO_HASH,
|
|
42
|
+
block,
|
|
43
|
+
payload,
|
|
44
|
+
`Failed validatePayloadInBlock: ${e instanceof Error ? e.message : String(e)}`,
|
|
45
|
+
))
|
|
40
46
|
}
|
|
41
47
|
return errors
|
|
42
48
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Address, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import type { HydratedBlock, HydratedBlockValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
3
|
import { HydratedBlockValidationError } from '@xyo-network/xl1-protocol'
|
|
4
4
|
|
|
@@ -21,7 +21,11 @@ export const validateHydratedBlock: HydratedBlockValidationFunction = async (
|
|
|
21
21
|
]
|
|
22
22
|
errors.push(...(await Promise.all(validators.map(v => v(hydratedBlock, chainId)))).flat())
|
|
23
23
|
} catch (e) {
|
|
24
|
-
errors.push(new HydratedBlockValidationError(
|
|
24
|
+
errors.push(new HydratedBlockValidationError(
|
|
25
|
+
hydratedBlock?.[0]?._hash ?? ZERO_HASH,
|
|
26
|
+
hydratedBlock,
|
|
27
|
+
`Failed validateHydratedBlock: ${e instanceof Error ? e.message : String(e)}`,
|
|
28
|
+
))
|
|
25
29
|
}
|
|
26
30
|
return errors
|
|
27
31
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Hash, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import type { Payload, WithHashStorageMeta } from '@xyo-network/payload-model'
|
|
3
3
|
import type {
|
|
4
4
|
HydratedBlock,
|
|
@@ -28,15 +28,19 @@ export const PayloadsInBlockValidator: HydratedBlockValidationFunction = async (
|
|
|
28
28
|
errors.push(...await validatePayloadInBlock(payload, [block, payloads]))
|
|
29
29
|
delete remainingPayloads[hash]
|
|
30
30
|
} else {
|
|
31
|
-
errors.push(new HydratedBlockValidationError([block, payloads], `missing payload ${hash} ${schema}`))
|
|
31
|
+
errors.push(new HydratedBlockValidationError(block?._hash ?? ZERO_HASH, [block, payloads], `missing payload ${hash} ${schema}`))
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (Object.keys(remainingPayloads).length > 0) {
|
|
36
|
-
errors.push(new HydratedBlockValidationError([block, payloads], `extra payloads ${Object.keys(payloadMap).join(', ')}`))
|
|
36
|
+
errors.push(new HydratedBlockValidationError(block?._hash ?? ZERO_HASH, [block, payloads], `extra payloads ${Object.keys(payloadMap).join(', ')}`))
|
|
37
37
|
}
|
|
38
38
|
} catch (e) {
|
|
39
|
-
errors.push(new HydratedBlockValidationError(
|
|
39
|
+
errors.push(new HydratedBlockValidationError(
|
|
40
|
+
block?._hash ?? ZERO_HASH,
|
|
41
|
+
[block, payloads],
|
|
42
|
+
`Failed PayloadsInBlockValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
43
|
+
))
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
return errors
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Address, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import type {
|
|
3
3
|
AccountBalanceService, HydratedBlock, HydratedBlockStateValidationFunction,
|
|
4
4
|
} from '@xyo-network/xl1-protocol'
|
|
@@ -23,6 +23,7 @@ export const validateHydratedBlockState: HydratedBlockStateValidationFunction =
|
|
|
23
23
|
errors.push(...(await Promise.all(validators.map(v => v(hydratedBlock, chainId, services)))).flat())
|
|
24
24
|
} catch (e) {
|
|
25
25
|
errors.push(new HydratedBlockStateValidationError(
|
|
26
|
+
hydratedBlock?.[0]?._hash ?? ZERO_HASH,
|
|
26
27
|
chainId,
|
|
27
28
|
hydratedBlock,
|
|
28
29
|
`Failed validateHydratedBlockState: ${e instanceof Error ? e.message : String(e)}`,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type Address, hexToBigInt, ZERO_HASH,
|
|
3
|
+
} from '@xylabs/hex'
|
|
2
4
|
import { netBalancesForPayloads } from '@xyo-network/chain-protocol'
|
|
3
5
|
import { XYO_ZERO_ADDRESS } from '@xyo-network/chain-utils'
|
|
4
6
|
import type {
|
|
@@ -24,12 +26,18 @@ export const RequiredBalanceBlockStateValidator: HydratedBlockStateValidationFun
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
const previous = block[0].previous
|
|
27
|
-
if (previous === null) return [new HydratedBlockStateValidationError(
|
|
29
|
+
if (previous === null) return [new HydratedBlockStateValidationError(
|
|
30
|
+
block?.[0]?._hash ?? ZERO_HASH,
|
|
31
|
+
chainId,
|
|
32
|
+
block,
|
|
33
|
+
'Insufficient funds because first block',
|
|
34
|
+
)]
|
|
28
35
|
|
|
29
36
|
for (const [address, reqBalance] of Object.entries(requiredBalances) as [Address, bigint][]) {
|
|
30
37
|
const balance = hexToBigInt(services.accountBalance.getBalance(address))
|
|
31
38
|
if (address !== XYO_ZERO_ADDRESS && reqBalance > balance) {
|
|
32
39
|
errors.push(new HydratedBlockStateValidationError(
|
|
40
|
+
block?.[0]?._hash ?? ZERO_HASH,
|
|
33
41
|
chainId,
|
|
34
42
|
block,
|
|
35
43
|
`insufficient balance for ${address} ${balance} < ${requiredBalances[address]}`,
|
|
@@ -38,6 +46,7 @@ export const RequiredBalanceBlockStateValidator: HydratedBlockStateValidationFun
|
|
|
38
46
|
}
|
|
39
47
|
} catch (e) {
|
|
40
48
|
errors.push(new HydratedBlockStateValidationError(
|
|
49
|
+
block?.[0]?._hash ?? ZERO_HASH,
|
|
41
50
|
chainId,
|
|
42
51
|
block,
|
|
43
52
|
`Failed RequiredBalanceBlockStateValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
@@ -1,21 +1,31 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import type {
|
|
2
3
|
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
3
4
|
} from '@xyo-network/xl1-protocol'
|
|
4
5
|
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
5
6
|
|
|
7
|
+
// eslint-disable-next-line complexity
|
|
6
8
|
export const TransactionDurationValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
7
9
|
tx: HydratedTransaction,
|
|
8
10
|
) => {
|
|
9
11
|
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
10
12
|
try {
|
|
11
13
|
const { exp, nbf } = tx[0]
|
|
12
|
-
if (nbf < 0) errors.push(new HydratedTransactionValidationError(tx, 'Transaction nbf must be positive'))
|
|
14
|
+
if (nbf < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction nbf must be positive'))
|
|
13
15
|
|
|
14
|
-
if (exp < 0) errors.push(new HydratedTransactionValidationError(tx, 'Transaction exp must be positive'))
|
|
15
|
-
if (exp <= nbf) errors.push(new HydratedTransactionValidationError(tx, 'Transaction exp must greater than nbf'))
|
|
16
|
-
if (exp - nbf > 10_000) errors.push(new HydratedTransactionValidationError(
|
|
16
|
+
if (exp < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must be positive'))
|
|
17
|
+
if (exp <= nbf) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must greater than nbf'))
|
|
18
|
+
if (exp - nbf > 10_000) errors.push(new HydratedTransactionValidationError(
|
|
19
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
20
|
+
tx,
|
|
21
|
+
'Transaction exp must not be too far in the future',
|
|
22
|
+
))
|
|
17
23
|
} catch (e) {
|
|
18
|
-
errors.push(new HydratedTransactionValidationError(
|
|
24
|
+
errors.push(new HydratedTransactionValidationError(
|
|
25
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
26
|
+
tx,
|
|
27
|
+
`Failed TransactionDurationValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
28
|
+
))
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
return errors
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
1
2
|
import { extractElevatedHashes } from '@xyo-network/chain-protocol'
|
|
2
3
|
import type {
|
|
3
4
|
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
@@ -12,10 +13,14 @@ export const TransactionElevationValidator: HydratedTransactionValidationFunctio
|
|
|
12
13
|
try {
|
|
13
14
|
extractElevatedHashes(tx)
|
|
14
15
|
} catch {
|
|
15
|
-
errors.push(new HydratedTransactionValidationError(tx, 'Hydrated transaction does not include all script hashes'))
|
|
16
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Hydrated transaction does not include all script hashes'))
|
|
16
17
|
}
|
|
17
18
|
} catch (e) {
|
|
18
|
-
errors.push(new HydratedTransactionValidationError(
|
|
19
|
+
errors.push(new HydratedTransactionValidationError(
|
|
20
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
21
|
+
tx,
|
|
22
|
+
`Failed TransactionElevationValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
23
|
+
))
|
|
19
24
|
}
|
|
20
25
|
return errors
|
|
21
26
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { asAddress } from '@xylabs/hex'
|
|
1
|
+
import { asAddress, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import { addressesContains } from '@xyo-network/boundwitness-validator'
|
|
3
3
|
import type {
|
|
4
4
|
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
@@ -11,10 +11,22 @@ export const TransactionFromValidator: HydratedTransactionValidationFunction<Tra
|
|
|
11
11
|
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
12
12
|
try {
|
|
13
13
|
const from = asAddress(tx[0].from)
|
|
14
|
-
if (from === undefined)errors.push(new HydratedTransactionValidationError(
|
|
15
|
-
|
|
14
|
+
if (from === undefined)errors.push(new HydratedTransactionValidationError(
|
|
15
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
16
|
+
tx,
|
|
17
|
+
'Transaction from is not a valid address',
|
|
18
|
+
))
|
|
19
|
+
else if (!addressesContains(tx[0], from)) errors.push(new HydratedTransactionValidationError(
|
|
20
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
21
|
+
tx,
|
|
22
|
+
'Transaction from address must be listed in addresses',
|
|
23
|
+
))
|
|
16
24
|
} catch (e) {
|
|
17
|
-
errors.push(new HydratedTransactionValidationError(
|
|
25
|
+
errors.push(new HydratedTransactionValidationError(
|
|
26
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
27
|
+
tx,
|
|
28
|
+
`Failed TransactionFromValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
29
|
+
))
|
|
18
30
|
}
|
|
19
31
|
return errors
|
|
20
32
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hexToBigInt } from '@xylabs/hex'
|
|
1
|
+
import { hexToBigInt, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import type {
|
|
3
3
|
HydratedTransaction,
|
|
4
4
|
HydratedTransactionValidationFunction,
|
|
@@ -10,52 +10,75 @@ import {
|
|
|
10
10
|
minTransactionFees,
|
|
11
11
|
} from '@xyo-network/xl1-protocol'
|
|
12
12
|
|
|
13
|
+
// eslint-disable-next-line complexity
|
|
13
14
|
export const TransactionGasValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
14
15
|
tx: HydratedTransaction,
|
|
15
16
|
) => {
|
|
16
17
|
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
17
18
|
try {
|
|
18
19
|
if (tx?.[0].fees === undefined) {
|
|
19
|
-
errors.push(new HydratedTransactionValidationError(
|
|
20
|
+
errors.push(new HydratedTransactionValidationError(
|
|
21
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
22
|
+
tx,
|
|
23
|
+
'Missing fees',
|
|
24
|
+
))
|
|
20
25
|
} else {
|
|
21
26
|
const {
|
|
22
27
|
base, gasLimit, gasPrice, priority,
|
|
23
28
|
} = parseFees(tx[0].fees)
|
|
24
29
|
|
|
25
30
|
if (base === undefined) errors.push(new HydratedTransactionValidationError(
|
|
31
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
26
32
|
tx,
|
|
27
33
|
'fees.base must be defined and a valid number',
|
|
28
34
|
))
|
|
29
35
|
else if (base < minTransactionFees.base) errors.push(new HydratedTransactionValidationError(
|
|
36
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
30
37
|
tx,
|
|
31
38
|
`fees.base must be >= ${minTransactionFees.base}`,
|
|
32
39
|
))
|
|
33
40
|
|
|
34
|
-
if (gasLimit === undefined) errors.push(new HydratedTransactionValidationError(
|
|
41
|
+
if (gasLimit === undefined) errors.push(new HydratedTransactionValidationError(
|
|
42
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
43
|
+
tx,
|
|
44
|
+
'fees.gasLimit must be defined and a valid number',
|
|
45
|
+
))
|
|
35
46
|
else if (gasLimit < minTransactionFees.gasLimit) errors.push(new HydratedTransactionValidationError(
|
|
47
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
36
48
|
tx,
|
|
37
49
|
`fees.gasLimit must be >= ${minTransactionFees.gasLimit}`,
|
|
38
50
|
))
|
|
39
51
|
|
|
40
52
|
if (gasPrice === undefined) errors.push(
|
|
41
|
-
new HydratedTransactionValidationError(
|
|
53
|
+
new HydratedTransactionValidationError(
|
|
54
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
55
|
+
tx,
|
|
56
|
+
'fees.gasPrice must be defined and a valid number',
|
|
57
|
+
),
|
|
42
58
|
)
|
|
43
59
|
else if (gasPrice < minTransactionFees.gasPrice) errors.push(new HydratedTransactionValidationError(
|
|
60
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
44
61
|
tx,
|
|
45
62
|
`fees.gasPrice must be >= ${minTransactionFees.gasPrice}`,
|
|
46
63
|
))
|
|
47
64
|
|
|
48
65
|
if (priority === undefined) errors.push(new HydratedTransactionValidationError(
|
|
66
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
49
67
|
tx,
|
|
50
68
|
'fees.priority must be defined and a valid number',
|
|
51
69
|
))
|
|
52
70
|
else if (priority < minTransactionFees.priority) errors.push(new HydratedTransactionValidationError(
|
|
71
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
53
72
|
tx,
|
|
54
73
|
`fees.priority must be >= ${minTransactionFees.priority}`,
|
|
55
74
|
))
|
|
56
75
|
}
|
|
57
76
|
} catch (e) {
|
|
58
|
-
errors.push(new HydratedTransactionValidationError(
|
|
77
|
+
errors.push(new HydratedTransactionValidationError(
|
|
78
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
79
|
+
tx,
|
|
80
|
+
`Failed TransactionGasValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
81
|
+
))
|
|
59
82
|
}
|
|
60
83
|
return errors
|
|
61
84
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import { toJsonString } from '@xylabs/object'
|
|
1
3
|
import { TransactionBoundWitnessJsonSchema } from '@xyo-network/chain-schema'
|
|
2
4
|
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
3
5
|
import type {
|
|
@@ -19,12 +21,16 @@ export const TransactionJsonSchemaValidator: HydratedTransactionValidationFuncti
|
|
|
19
21
|
if (validate === undefined) validate = ajv.compile(TransactionBoundWitnessJsonSchema)
|
|
20
22
|
// see if you can export the super set
|
|
21
23
|
if (!validate(PayloadBuilder.omitStorageMeta(tx[0]))) {
|
|
22
|
-
const error = new HydratedTransactionValidationError(
|
|
24
|
+
const error = new HydratedTransactionValidationError(
|
|
25
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
26
|
+
tx,
|
|
27
|
+
`failed JSON schema validation: ${toJsonString(tx, 10)} ${toJsonString(validate.errors, 10)}`,
|
|
28
|
+
)
|
|
23
29
|
error.cause = validate.errors
|
|
24
30
|
errors.push(error)
|
|
25
31
|
}
|
|
26
32
|
} catch (ex) {
|
|
27
|
-
errors.push(new HydratedTransactionValidationError(tx, 'validation excepted'), ex as Error)
|
|
33
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted'), ex as Error)
|
|
28
34
|
}
|
|
29
35
|
return errors
|
|
30
36
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Address, ZERO_HASH } from '@xylabs/hex'
|
|
2
2
|
import type {
|
|
3
3
|
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
4
4
|
} from '@xyo-network/xl1-protocol'
|
|
@@ -11,10 +11,10 @@ export const TransactionProtocolValidator: HydratedTransactionValidationFunction
|
|
|
11
11
|
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
12
12
|
try {
|
|
13
13
|
if (chainId !== undefined && tx[0].chain !== chainId) {
|
|
14
|
-
errors.push(new HydratedTransactionValidationError(tx, 'invalid chain id'))
|
|
14
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'invalid chain id'))
|
|
15
15
|
}
|
|
16
16
|
} catch (ex) {
|
|
17
|
-
errors.push(new HydratedTransactionValidationError(tx, 'validation excepted'), ex as Error)
|
|
17
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted'), ex as Error)
|
|
18
18
|
}
|
|
19
19
|
return await Promise.resolve(errors)
|
|
20
20
|
}
|