@xyo-network/chain-validation 1.5.29 → 1.5.31
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 +126 -76
- 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 +1 -1
- package/dist/types/block/validators/Fields.d.ts.map +1 -1
- package/dist/types/block/validators/JsonSchema.d.ts +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/validateSchemaInBlock.d.ts.map +1 -1
- package/dist/types/elevatedPayload/payloads/validateTransferInBlock.d.ts +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 +2 -2
- package/dist/types/hydratedBlock/validateHydratedBlock.d.ts.map +1 -1
- package/dist/types/hydratedBlock/validators/Payloads.d.ts +2 -2
- 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 +2 -2
- package/dist/types/transaction/validateTransaction.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionDurationValidator.d.ts +2 -2
- package/dist/types/transaction/validators/TransactionDurationValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionElevationValidator.d.ts +2 -2
- package/dist/types/transaction/validators/TransactionElevationValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionFromValidator.d.ts +2 -2
- package/dist/types/transaction/validators/TransactionFromValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionGasValidator.d.ts +2 -2
- package/dist/types/transaction/validators/TransactionGasValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionJsonSchemaValidator.d.ts +2 -2
- package/dist/types/transaction/validators/TransactionJsonSchemaValidator.d.ts.map +1 -1
- package/dist/types/transaction/validators/TransactionProtocolValidator.d.ts +2 -2
- package/dist/types/transaction/validators/TransactionProtocolValidator.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/block/validateBlock.ts +3 -2
- package/src/block/validators/AllowedPayloadSchemas.ts +4 -4
- package/src/block/validators/Fields.ts +7 -5
- package/src/block/validators/JsonSchema.ts +7 -6
- package/src/block/validators/PreviousHash.ts +6 -5
- package/src/boundwitness/validators/BoundWitnessReferences.ts +9 -8
- package/src/boundwitness/validators/BoundWitnessSignatures.ts +5 -4
- package/src/elevatedPayload/payloads/validateChainStakeIntentInBlock.ts +4 -4
- package/src/elevatedPayload/payloads/validateHashInBlock.ts +4 -4
- package/src/elevatedPayload/payloads/validateSchemaInBlock.ts +3 -2
- package/src/elevatedPayload/payloads/validateTransferInBlock.ts +6 -4
- package/src/elevatedPayload/validatePayloadInBlock.ts +6 -5
- package/src/hydratedBlock/validateHydratedBlock.ts +7 -6
- package/src/hydratedBlock/validators/Payloads.ts +7 -6
- package/src/hydratedBlockState/validateHydratedBlockState.ts +7 -2
- package/src/hydratedBlockState/validators/RequiredBalance.ts +13 -4
- package/src/transaction/validateTransaction.ts +5 -5
- package/src/transaction/validators/TransactionDurationValidator.ts +12 -11
- package/src/transaction/validators/TransactionElevationValidator.ts +8 -8
- package/src/transaction/validators/TransactionFromValidator.ts +10 -9
- package/src/transaction/validators/TransactionGasValidator.ts +42 -18
- package/src/transaction/validators/TransactionJsonSchemaValidator.ts +9 -9
- package/src/transaction/validators/TransactionProtocolValidator.ts +9 -8
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Address } from '@xylabs/hex'
|
|
2
2
|
import type { BlockBoundWitness, BlockValidatorFunction } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import { BlockValidationError } from '@xyo-network/xl1-protocol'
|
|
3
4
|
|
|
4
5
|
import { BoundWitnessSignaturesValidator } from '../boundwitness/index.ts'
|
|
5
6
|
import {
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
export const validateBlock: BlockValidatorFunction = async (
|
|
11
12
|
block: BlockBoundWitness,
|
|
12
13
|
chainId?: Address,
|
|
13
|
-
): Promise<Error[]> => {
|
|
14
|
+
): Promise<(BlockValidationError | Error)[]> => {
|
|
14
15
|
const errors: Error[] = []
|
|
15
16
|
try {
|
|
16
17
|
const validators: BlockValidatorFunction[] = [
|
|
@@ -24,7 +25,7 @@ export const validateBlock: BlockValidatorFunction = async (
|
|
|
24
25
|
validators.map(validator => validator(block, chainId)),
|
|
25
26
|
)).flat())
|
|
26
27
|
} catch (ex) {
|
|
27
|
-
errors.push(new
|
|
28
|
+
errors.push(new BlockValidationError(block, 'validation excepted'), ex as Error)
|
|
28
29
|
}
|
|
29
30
|
return errors
|
|
30
31
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type BlockBoundWitness, type BlockValidatorFunction, isAllowedBlockPayloadSchema,
|
|
2
|
+
type BlockBoundWitness, BlockValidationError, type BlockValidatorFunction, isAllowedBlockPayloadSchema,
|
|
3
3
|
} from '@xyo-network/xl1-protocol'
|
|
4
4
|
|
|
5
5
|
export const BlockAllowedPayloadSchemasValidator: BlockValidatorFunction = (
|
|
6
6
|
block: BlockBoundWitness,
|
|
7
7
|
) => {
|
|
8
|
-
const errors: Error[] = []
|
|
8
|
+
const errors: (BlockValidationError | Error)[] = []
|
|
9
9
|
try {
|
|
10
10
|
for (const schema of block.payload_schemas) {
|
|
11
11
|
if (!isAllowedBlockPayloadSchema(schema)) {
|
|
12
|
-
errors.push(new
|
|
12
|
+
errors.push(new BlockValidationError(block, `payload schema not allowed in block: ${schema}`))
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
} catch (e) {
|
|
16
|
-
errors.push(new
|
|
16
|
+
errors.push(new BlockValidationError(block, `Failed BlockAllowedPayloadSchemasValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
17
17
|
}
|
|
18
18
|
return errors
|
|
19
19
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { Address, Hash } from '@xylabs/hex'
|
|
2
2
|
import { isDefined } from '@xylabs/typeof'
|
|
3
3
|
import { BoundWitnessSchema } from '@xyo-network/boundwitness-model'
|
|
4
|
-
import
|
|
4
|
+
import {
|
|
5
|
+
type BlockBoundWitness, BlockValidationError, type BlockValidatorFunction,
|
|
6
|
+
} from '@xyo-network/xl1-protocol'
|
|
5
7
|
|
|
6
8
|
export const BlockFieldsValidator: BlockValidatorFunction = (
|
|
7
9
|
block: BlockBoundWitness,
|
|
8
10
|
chainId?: Address,
|
|
9
11
|
) => {
|
|
10
|
-
const errors: Error[] = []
|
|
12
|
+
const errors: (BlockValidationError | Error)[] = []
|
|
11
13
|
try {
|
|
12
14
|
if (isDefined(chainId) && block.chain !== chainId.toLowerCase()) {
|
|
13
|
-
errors.push(new
|
|
15
|
+
errors.push(new BlockValidationError(block, 'Invalid chain id'))
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
// get transaction hashes
|
|
@@ -23,10 +25,10 @@ export const BlockFieldsValidator: BlockValidatorFunction = (
|
|
|
23
25
|
|
|
24
26
|
// check if transaction hashes are unique
|
|
25
27
|
if (new Set(txHashes).size < txHashes.length) {
|
|
26
|
-
errors.push(new
|
|
28
|
+
errors.push(new BlockValidationError(block, `Duplicate Transaction Hashes: ${txHashes}`))
|
|
27
29
|
}
|
|
28
30
|
} catch (e) {
|
|
29
|
-
errors.push(new
|
|
31
|
+
errors.push(new BlockValidationError(block, `Failed BlockFieldsValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
30
32
|
}
|
|
31
33
|
return errors
|
|
32
34
|
}
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { BlockBoundWitnessWithStorageMetaJsonSchema } from '@xyo-network/chain-schema'
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
type BlockBoundWitness, BlockValidationError, type BlockValidatorFunction,
|
|
4
|
+
} from '@xyo-network/xl1-protocol'
|
|
3
5
|
import type { AnySchema } from 'ajv'
|
|
4
6
|
import { Ajv } from 'ajv'
|
|
5
7
|
|
|
6
8
|
export const BlockJsonSchemaValidator = (jsonSchema: AnySchema = BlockBoundWitnessWithStorageMetaJsonSchema): BlockValidatorFunction => async (
|
|
7
9
|
block: BlockBoundWitness,
|
|
8
10
|
) => {
|
|
9
|
-
const errors: Error[] = []
|
|
11
|
+
const errors: (BlockValidationError | Error)[] = []
|
|
10
12
|
try {
|
|
11
13
|
const ajv = new Ajv({ allErrors: true, strict: true })
|
|
12
14
|
// see if you can export the super set
|
|
13
15
|
const validate = ajv.compile(jsonSchema)
|
|
14
16
|
await validate(block)
|
|
15
17
|
if ((validate.errors ?? []).length > 0) {
|
|
16
|
-
const error = new
|
|
17
|
-
error.
|
|
18
|
-
errors.push(error)
|
|
18
|
+
const error = new BlockValidationError(block, 'failed JSON schema validation: ')
|
|
19
|
+
errors.push(error, ...validate.errors?.map(e => new Error(` ${e.instancePath} ${e.message ?? ''}`)) ?? [])
|
|
19
20
|
}
|
|
20
21
|
} catch (e) {
|
|
21
|
-
errors.push(new
|
|
22
|
+
errors.push(new BlockValidationError(block, `Failed BlockJsonSchemaValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
22
23
|
}
|
|
23
24
|
return errors
|
|
24
25
|
}
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { isHash } from '@xylabs/hex'
|
|
2
2
|
import type { BlockBoundWitness, BlockValidatorFunction } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import { BlockValidationError } from '@xyo-network/xl1-protocol'
|
|
3
4
|
|
|
4
5
|
export const BlockPreviousHashValidator: BlockValidatorFunction = (
|
|
5
6
|
block: BlockBoundWitness,
|
|
6
7
|
) => {
|
|
7
|
-
const errors: Error[] = []
|
|
8
|
+
const errors: (BlockValidationError | Error)[] = []
|
|
8
9
|
try {
|
|
9
10
|
const blockNumber = block.block
|
|
10
11
|
if (blockNumber > 0n) {
|
|
11
12
|
// if this is not the first block, validate previous hashes
|
|
12
13
|
if (!isHash(block.previous)) {
|
|
13
|
-
errors.push(new
|
|
14
|
+
errors.push(new BlockValidationError(block, 'previous hash is missing or invalid'))
|
|
14
15
|
}
|
|
15
16
|
} else if (blockNumber === 0) {
|
|
16
17
|
// if this is the first block, validate previous hashes
|
|
17
18
|
if (block.previous !== null) {
|
|
18
|
-
errors.push(new
|
|
19
|
+
errors.push(new BlockValidationError(block, 'previous hash should not be set'))
|
|
19
20
|
}
|
|
20
21
|
} else {
|
|
21
22
|
// we have a negative block number
|
|
22
|
-
errors.push(new
|
|
23
|
+
errors.push(new BlockValidationError(block, 'invalid block number'))
|
|
23
24
|
}
|
|
24
25
|
} catch (e) {
|
|
25
|
-
errors.push(new
|
|
26
|
+
errors.push(new BlockValidationError(block, `Failed BlockPreviousHashValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
26
27
|
}
|
|
27
28
|
return errors
|
|
28
29
|
}
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
} from '@xyo-network/payload-model'
|
|
9
9
|
import { isAnyPayload } from '@xyo-network/payload-model'
|
|
10
10
|
import type { HydratedBoundWitnessValidationFunction, HydratedBoundWitnessWithHashStorageMeta } from '@xyo-network/xl1-protocol'
|
|
11
|
+
import { HydratedBoundWitnessValidationError } from '@xyo-network/xl1-protocol'
|
|
11
12
|
|
|
12
13
|
function getPayloadsFromPayloadArray(payloads: WithHashStorageMeta<Payload>[], hashes: Hash[]): (WithHashStorageMeta<Payload> | undefined)[] {
|
|
13
14
|
return hashes.map(hash => payloads.find(payload => payload._hash === hash || payload._dataHash === hash))
|
|
@@ -16,12 +17,12 @@ function getPayloadsFromPayloadArray(payloads: WithHashStorageMeta<Payload>[], h
|
|
|
16
17
|
export const BoundWitnessReferencesValidator
|
|
17
18
|
= <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]): HydratedBoundWitnessValidationFunction<T> => (
|
|
18
19
|
[bw, payloadSet]: HydratedBoundWitnessWithHashStorageMeta<T>,
|
|
19
|
-
): Promisable<Error[]> => {
|
|
20
|
-
const errors: Error[] = []
|
|
20
|
+
): Promisable<(HydratedBoundWitnessValidationError | Error)[]> => {
|
|
21
|
+
const errors: (HydratedBoundWitnessValidationError | Error)[] = []
|
|
21
22
|
try {
|
|
22
23
|
const payloads = getPayloadsFromPayloadArray(payloadSet, bw.payload_hashes)
|
|
23
24
|
if (payloads.length !== bw.payload_hashes.length) {
|
|
24
|
-
errors.push(new
|
|
25
|
+
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'unable to locate payloads'))
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
// check if payloads are valid and if their schemas match the declared schemas
|
|
@@ -31,23 +32,23 @@ export const BoundWitnessReferencesValidator
|
|
|
31
32
|
const payloadDataHashIndex = bw.payload_hashes.indexOf(payload._dataHash)
|
|
32
33
|
const payloadIndex = Math.max(payloadHashIndex, payloadDataHashIndex)
|
|
33
34
|
if (payloadIndex === -1) {
|
|
34
|
-
errors.push(new
|
|
35
|
+
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'payload hash not found'))
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
const declaredSchema = bw.payload_schemas[payloadIndex]
|
|
38
39
|
if (declaredSchema !== payload.schema) {
|
|
39
|
-
errors.push(new
|
|
40
|
+
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'mismatched schema'))
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
if (allowedSchemas && !allowedSchemas.includes(payload.schema)) {
|
|
43
|
-
errors.push(new
|
|
44
|
+
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], `disallowed schema [${payload.schema}]`))
|
|
44
45
|
}
|
|
45
46
|
} else {
|
|
46
|
-
errors.push(new
|
|
47
|
+
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'invalid payload'))
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
} catch (ex) {
|
|
50
|
-
errors.push(new
|
|
51
|
+
errors.push(new HydratedBoundWitnessValidationError([bw, payloadSet], 'validation excepted'), ex as Error)
|
|
51
52
|
}
|
|
52
53
|
return errors
|
|
53
54
|
}
|
|
@@ -4,21 +4,22 @@ 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
6
|
import type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol'
|
|
7
|
+
import { BoundWitnessValidationError } from '@xyo-network/xl1-protocol'
|
|
7
8
|
|
|
8
9
|
export const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction = async (
|
|
9
10
|
bw: BoundWitness,
|
|
10
|
-
)
|
|
11
|
-
const errors: Error[] = []
|
|
11
|
+
) => {
|
|
12
|
+
const errors: (BoundWitnessValidationError | Error)[] = []
|
|
12
13
|
try {
|
|
13
14
|
const dataHash = await BoundWitnessBuilder.dataHash(bw)
|
|
14
|
-
const results: [Address, Error[]][] = await Promise.all(bw.addresses.map(async (address, index) => {
|
|
15
|
+
const results: [Address, (Error | BoundWitnessValidationError)[]][] = await Promise.all(bw.addresses.map(async (address, index) => {
|
|
15
16
|
return [address, await BoundWitnessValidator.validateSignature(toArrayBuffer(dataHash), toArrayBuffer(address), toArrayBuffer(bw.$signatures[index]))]
|
|
16
17
|
}))
|
|
17
18
|
for (const [, bwErrors] of results) {
|
|
18
19
|
errors.push(...bwErrors)
|
|
19
20
|
}
|
|
20
21
|
} catch (ex) {
|
|
21
|
-
errors.push(new
|
|
22
|
+
errors.push(new BoundWitnessValidationError(bw, 'validation excepted'), ex as Error)
|
|
22
23
|
}
|
|
23
24
|
return errors
|
|
24
25
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { HydratedBlock, InBlockPayloadValidationFunction } from '@xyo-network/xl1-protocol'
|
|
2
|
-
import { isChainStakeIntent } from '@xyo-network/xl1-protocol'
|
|
2
|
+
import { InBlockPayloadValidationError, isChainStakeIntent } from '@xyo-network/xl1-protocol'
|
|
3
3
|
|
|
4
4
|
import { validateTypedPayloadInBlock } from '../lib/index.ts'
|
|
5
5
|
|
|
6
6
|
export const validateChainStakeIntentInBlock: InBlockPayloadValidationFunction = async (
|
|
7
7
|
payload,
|
|
8
8
|
block: HydratedBlock,
|
|
9
|
-
): Promise<Error[]> => {
|
|
10
|
-
const errors: Error[] = []
|
|
9
|
+
): Promise<(InBlockPayloadValidationError | Error)[]> => {
|
|
10
|
+
const errors: (InBlockPayloadValidationError | Error)[] = []
|
|
11
11
|
try {
|
|
12
12
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isChainStakeIntent))
|
|
13
13
|
} catch (e) {
|
|
14
|
-
errors.push(new
|
|
14
|
+
errors.push(new InBlockPayloadValidationError(block, payload, `Failed validateChainStakeIntentInBlock: ${e instanceof Error ? e.message : String(e)}`))
|
|
15
15
|
}
|
|
16
16
|
return errors
|
|
17
17
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { HydratedBlock, InBlockPayloadValidationFunction } from '@xyo-network/xl1-protocol'
|
|
2
|
-
import { isHashPayload } from '@xyo-network/xl1-protocol'
|
|
2
|
+
import { InBlockPayloadValidationError, isHashPayload } from '@xyo-network/xl1-protocol'
|
|
3
3
|
|
|
4
4
|
import { validateTypedPayloadInBlock } from '../lib/index.ts'
|
|
5
5
|
|
|
6
6
|
export const validateHashInBlock: InBlockPayloadValidationFunction = async (
|
|
7
7
|
payload,
|
|
8
8
|
block: HydratedBlock,
|
|
9
|
-
): Promise<Error[]> => {
|
|
10
|
-
const errors: Error[] = []
|
|
9
|
+
): Promise<(InBlockPayloadValidationError | Error)[]> => {
|
|
10
|
+
const errors: (InBlockPayloadValidationError | Error)[] = []
|
|
11
11
|
try {
|
|
12
12
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isHashPayload))
|
|
13
13
|
} catch (e) {
|
|
14
|
-
errors.push(new
|
|
14
|
+
errors.push(new InBlockPayloadValidationError(block, payload, `Failed validateHashInBlock: ${e instanceof Error ? e.message : String(e)}`))
|
|
15
15
|
}
|
|
16
16
|
return errors
|
|
17
17
|
}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { isSchemaPayload } from '@xyo-network/schema-payload-plugin'
|
|
2
2
|
import type { HydratedBlock, InBlockPayloadValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import { InBlockPayloadValidationError } from '@xyo-network/xl1-protocol'
|
|
3
4
|
|
|
4
5
|
import { validateTypedPayloadInBlock } from '../lib/index.ts'
|
|
5
6
|
|
|
6
7
|
export const validateSchemaInBlock: InBlockPayloadValidationFunction = async (
|
|
7
8
|
payload,
|
|
8
9
|
block: HydratedBlock,
|
|
9
|
-
): Promise<Error[]> => {
|
|
10
|
+
): Promise<(InBlockPayloadValidationError | Error)[]> => {
|
|
10
11
|
const errors: Error[] = []
|
|
11
12
|
try {
|
|
12
13
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isSchemaPayload))
|
|
13
14
|
} catch (e) {
|
|
14
|
-
errors.push(new
|
|
15
|
+
errors.push(new InBlockPayloadValidationError(block, payload, `Failed validateSchemaInBlock: ${e instanceof Error ? e.message : String(e)}`))
|
|
15
16
|
}
|
|
16
17
|
return errors
|
|
17
18
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
HydratedBlock,
|
|
3
|
+
InBlockPayloadValidationFunction,
|
|
3
4
|
} from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { InBlockPayloadValidationError, isTransfer } from '@xyo-network/xl1-protocol'
|
|
4
6
|
|
|
5
7
|
import { validateTypedPayloadInBlock } from '../lib/index.ts'
|
|
6
8
|
|
|
@@ -8,11 +10,11 @@ export const validateTransferInBlock: InBlockPayloadValidationFunction = async (
|
|
|
8
10
|
payload,
|
|
9
11
|
block: HydratedBlock,
|
|
10
12
|
): Promise<Error[]> => {
|
|
11
|
-
const errors: Error[] = []
|
|
13
|
+
const errors: (InBlockPayloadValidationError | Error)[] = []
|
|
12
14
|
try {
|
|
13
15
|
errors.push(...await validateTypedPayloadInBlock(payload, block, isTransfer))
|
|
14
16
|
} catch (e) {
|
|
15
|
-
errors.push(new
|
|
17
|
+
errors.push(new InBlockPayloadValidationError(block, payload, `Failed validateTransferInBlock: ${e instanceof Error ? e.message : String(e)}`))
|
|
16
18
|
}
|
|
17
19
|
return errors
|
|
18
20
|
}
|
|
@@ -6,7 +6,8 @@ import type {
|
|
|
6
6
|
InBlockPayloadValidationFunction,
|
|
7
7
|
} from '@xyo-network/xl1-protocol'
|
|
8
8
|
import {
|
|
9
|
-
ChainStakeIntentSchema, HashSchema,
|
|
9
|
+
ChainStakeIntentSchema, HashSchema, InBlockPayloadValidationError,
|
|
10
|
+
TransferSchema,
|
|
10
11
|
} from '@xyo-network/xl1-protocol'
|
|
11
12
|
|
|
12
13
|
import { validateTransactionInBlock } from './lib/index.ts'
|
|
@@ -25,17 +26,17 @@ const payloadValidators: Partial<Record<Schema, InBlockPayloadValidationFunction
|
|
|
25
26
|
export const validatePayloadInBlock: InBlockPayloadValidationFunction = async (
|
|
26
27
|
payload,
|
|
27
28
|
block: HydratedBlock,
|
|
28
|
-
): Promise<Error[]> => {
|
|
29
|
-
const errors: Error[] = []
|
|
29
|
+
): Promise<(InBlockPayloadValidationError | Error)[]> => {
|
|
30
|
+
const errors: (InBlockPayloadValidationError | Error)[] = []
|
|
30
31
|
try {
|
|
31
32
|
const validator = payloadValidators[payload.schema]
|
|
32
33
|
if (validator) {
|
|
33
34
|
errors.push(...await validator(payload, block))
|
|
34
35
|
} else {
|
|
35
|
-
errors.push(new
|
|
36
|
+
errors.push(new InBlockPayloadValidationError(block, payload, `Unsupported payload schema: ${payload.schema}`))
|
|
36
37
|
}
|
|
37
38
|
} catch (e) {
|
|
38
|
-
errors.push(new
|
|
39
|
+
errors.push(new InBlockPayloadValidationError(block, payload, `Failed validatePayloadInBlock: ${e instanceof Error ? e.message : String(e)}`))
|
|
39
40
|
}
|
|
40
41
|
return errors
|
|
41
42
|
}
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import type { Address } from '@xylabs/hex'
|
|
2
|
-
import type { HydratedBlock,
|
|
2
|
+
import type { HydratedBlock, HydratedBlockValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import { HydratedBlockValidationError } from '@xyo-network/xl1-protocol'
|
|
3
4
|
|
|
4
5
|
import { validateBlock } from '../block/index.ts'
|
|
5
6
|
import { BoundWitnessReferencesValidator } from '../boundwitness/index.ts'
|
|
6
7
|
import { PayloadsInBlockValidator } from './validators/index.ts'
|
|
7
8
|
|
|
8
|
-
export const validateHydratedBlock:
|
|
9
|
+
export const validateHydratedBlock: HydratedBlockValidationFunction = async (
|
|
9
10
|
hydratedBlock: HydratedBlock,
|
|
10
11
|
chainId?: Address,
|
|
11
|
-
additionalValidators:
|
|
12
|
-
): Promise<Error[]> => {
|
|
12
|
+
additionalValidators: HydratedBlockValidationFunction[] = [],
|
|
13
|
+
): Promise<(HydratedBlockValidationError | Error)[]> => {
|
|
13
14
|
const errors: Error[] = []
|
|
14
15
|
try {
|
|
15
16
|
errors.push(...await validateBlock(hydratedBlock[0], chainId))
|
|
16
|
-
const validators:
|
|
17
|
+
const validators: HydratedBlockValidationFunction[] = [
|
|
17
18
|
BoundWitnessReferencesValidator(),
|
|
18
19
|
PayloadsInBlockValidator,
|
|
19
20
|
...additionalValidators,
|
|
20
21
|
]
|
|
21
22
|
errors.push(...(await Promise.all(validators.map(v => v(hydratedBlock, chainId)))).flat())
|
|
22
23
|
} catch (e) {
|
|
23
|
-
errors.push(new
|
|
24
|
+
errors.push(new HydratedBlockValidationError(hydratedBlock, `Failed validateHydratedBlock: ${e instanceof Error ? e.message : String(e)}`))
|
|
24
25
|
}
|
|
25
26
|
return errors
|
|
26
27
|
}
|
|
@@ -2,15 +2,16 @@ import type { Hash } from '@xylabs/hex'
|
|
|
2
2
|
import type { Payload, WithHashStorageMeta } from '@xyo-network/payload-model'
|
|
3
3
|
import type {
|
|
4
4
|
HydratedBlock,
|
|
5
|
-
|
|
5
|
+
HydratedBlockValidationFunction,
|
|
6
6
|
} from '@xyo-network/xl1-protocol'
|
|
7
|
+
import { HydratedBlockValidationError } from '@xyo-network/xl1-protocol'
|
|
7
8
|
|
|
8
9
|
import { validatePayloadInBlock } from '../../elevatedPayload/validatePayloadInBlock.ts'
|
|
9
10
|
|
|
10
|
-
export const PayloadsInBlockValidator:
|
|
11
|
+
export const PayloadsInBlockValidator: HydratedBlockValidationFunction = async (
|
|
11
12
|
[block, payloads]: HydratedBlock,
|
|
12
13
|
) => {
|
|
13
|
-
const errors: Error[] = []
|
|
14
|
+
const errors: (HydratedBlockValidationError | Error)[] = []
|
|
14
15
|
try {
|
|
15
16
|
const payloadMap: Partial<Record<Hash, WithHashStorageMeta<Payload>>> = {}
|
|
16
17
|
for (const payload of payloads) {
|
|
@@ -27,15 +28,15 @@ export const PayloadsInBlockValidator: HydratedBlockValidatorFunction = async (
|
|
|
27
28
|
errors.push(...await validatePayloadInBlock(payload, [block, payloads]))
|
|
28
29
|
delete remainingPayloads[hash]
|
|
29
30
|
} else {
|
|
30
|
-
errors.push(new
|
|
31
|
+
errors.push(new HydratedBlockValidationError([block, payloads], `missing payload ${hash} ${schema}`))
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
if (Object.keys(remainingPayloads).length > 0) {
|
|
35
|
-
errors.push(new
|
|
36
|
+
errors.push(new HydratedBlockValidationError([block, payloads], `extra payloads ${Object.keys(payloadMap).join(', ')}`))
|
|
36
37
|
}
|
|
37
38
|
} catch (e) {
|
|
38
|
-
errors.push(new
|
|
39
|
+
errors.push(new HydratedBlockValidationError([block, payloads], `Failed PayloadsInBlockValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
return errors
|
|
@@ -2,6 +2,7 @@ import type { Address } from '@xylabs/hex'
|
|
|
2
2
|
import type {
|
|
3
3
|
AccountBalanceService, HydratedBlock, HydratedBlockStateValidationFunction,
|
|
4
4
|
} from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { HydratedBlockStateValidationError } from '@xyo-network/xl1-protocol'
|
|
5
6
|
|
|
6
7
|
import { validateHydratedBlock } from '../hydratedBlock/index.ts'
|
|
7
8
|
import { RequiredBalanceBlockStateValidator } from './validators/index.ts'
|
|
@@ -11,7 +12,7 @@ export const validateHydratedBlockState: HydratedBlockStateValidationFunction =
|
|
|
11
12
|
chainId: Address,
|
|
12
13
|
services: { accountBalance: AccountBalanceService },
|
|
13
14
|
additionalValidators: HydratedBlockStateValidationFunction[] = [],
|
|
14
|
-
): Promise<Error[]> => {
|
|
15
|
+
): Promise<(HydratedBlockStateValidationError | Error)[]> => {
|
|
15
16
|
const errors: Error[] = []
|
|
16
17
|
try {
|
|
17
18
|
errors.push(...await validateHydratedBlock(hydratedBlock, chainId))
|
|
@@ -21,7 +22,11 @@ export const validateHydratedBlockState: HydratedBlockStateValidationFunction =
|
|
|
21
22
|
]
|
|
22
23
|
errors.push(...(await Promise.all(validators.map(v => v(hydratedBlock, chainId, services)))).flat())
|
|
23
24
|
} catch (e) {
|
|
24
|
-
errors.push(new
|
|
25
|
+
errors.push(new HydratedBlockStateValidationError(
|
|
26
|
+
chainId,
|
|
27
|
+
hydratedBlock,
|
|
28
|
+
`Failed validateHydratedBlockState: ${e instanceof Error ? e.message : String(e)}`,
|
|
29
|
+
))
|
|
25
30
|
}
|
|
26
31
|
return errors
|
|
27
32
|
}
|
|
@@ -4,13 +4,14 @@ import { XYO_ZERO_ADDRESS } from '@xyo-network/chain-utils'
|
|
|
4
4
|
import type {
|
|
5
5
|
AccountBalanceService, HydratedBlock, HydratedBlockStateValidationFunction,
|
|
6
6
|
} from '@xyo-network/xl1-protocol'
|
|
7
|
+
import { HydratedBlockStateValidationError } from '@xyo-network/xl1-protocol'
|
|
7
8
|
|
|
8
9
|
export const RequiredBalanceBlockStateValidator: HydratedBlockStateValidationFunction = async (
|
|
9
10
|
block: HydratedBlock,
|
|
10
11
|
chainId: Address,
|
|
11
12
|
services: { accountBalance: AccountBalanceService },
|
|
12
13
|
) => {
|
|
13
|
-
const errors: Error[] = []
|
|
14
|
+
const errors: (HydratedBlockStateValidationError | Error)[] = []
|
|
14
15
|
try {
|
|
15
16
|
// TODO: Filter by non-producer elevated payloads
|
|
16
17
|
// to allow for transfers from ZERO address
|
|
@@ -23,16 +24,24 @@ export const RequiredBalanceBlockStateValidator: HydratedBlockStateValidationFun
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
const previous = block[0].previous
|
|
26
|
-
if (previous === null) return [new
|
|
27
|
+
if (previous === null) return [new HydratedBlockStateValidationError(chainId, block, 'Insufficient funds because first block')]
|
|
27
28
|
|
|
28
29
|
for (const [address, reqBalance] of Object.entries(requiredBalances) as [Address, bigint][]) {
|
|
29
30
|
const balance = hexToBigInt(services.accountBalance.getBalance(address))
|
|
30
31
|
if (address !== XYO_ZERO_ADDRESS && reqBalance > balance) {
|
|
31
|
-
errors.push(new
|
|
32
|
+
errors.push(new HydratedBlockStateValidationError(
|
|
33
|
+
chainId,
|
|
34
|
+
block,
|
|
35
|
+
`insufficient balance for ${address} ${balance} < ${requiredBalances[address]}`,
|
|
36
|
+
))
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
} catch (e) {
|
|
35
|
-
errors.push(new
|
|
40
|
+
errors.push(new HydratedBlockStateValidationError(
|
|
41
|
+
chainId,
|
|
42
|
+
block,
|
|
43
|
+
`Failed RequiredBalanceBlockStateValidator: ${e instanceof Error ? e.message : String(e)}`,
|
|
44
|
+
))
|
|
36
45
|
}
|
|
37
46
|
return await Promise.resolve(errors)
|
|
38
47
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Address } from '@xylabs/hex'
|
|
2
|
-
import type {
|
|
2
|
+
import type { HydratedTransaction, HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
3
|
import { isTransactionBoundWitness } from '@xyo-network/xl1-protocol'
|
|
4
4
|
|
|
5
5
|
import {
|
|
@@ -8,16 +8,16 @@ import {
|
|
|
8
8
|
} from './validators/index.ts'
|
|
9
9
|
|
|
10
10
|
export async function validateTransaction(
|
|
11
|
-
tx:
|
|
11
|
+
tx: HydratedTransaction,
|
|
12
12
|
chainId?: Address,
|
|
13
|
-
additionalValidators:
|
|
14
|
-
)
|
|
13
|
+
additionalValidators: HydratedTransactionValidationFunction[] = [],
|
|
14
|
+
) {
|
|
15
15
|
try {
|
|
16
16
|
if (!isTransactionBoundWitness(tx[0])) {
|
|
17
17
|
return [new Error('failed isTransactionBoundWitness identity check')]
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const validators:
|
|
20
|
+
const validators: HydratedTransactionValidationFunction[] = [
|
|
21
21
|
TransactionProtocolValidator,
|
|
22
22
|
TransactionJsonSchemaValidator,
|
|
23
23
|
TransactionDurationValidator,
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
HydratedTransaction,
|
|
2
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
3
3
|
} from '@xyo-network/xl1-protocol'
|
|
4
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
4
5
|
|
|
5
|
-
export const TransactionDurationValidator:
|
|
6
|
-
|
|
7
|
-
)
|
|
8
|
-
const errors: Error[] = []
|
|
6
|
+
export const TransactionDurationValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
7
|
+
tx: HydratedTransaction,
|
|
8
|
+
) => {
|
|
9
|
+
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
9
10
|
try {
|
|
10
|
-
const { exp, nbf } = tx
|
|
11
|
-
if (nbf < 0) errors.push(new
|
|
11
|
+
const { exp, nbf } = tx[0]
|
|
12
|
+
if (nbf < 0) errors.push(new HydratedTransactionValidationError(tx, 'Transaction nbf must be positive'))
|
|
12
13
|
|
|
13
|
-
if (exp < 0) errors.push(new
|
|
14
|
-
if (exp <= nbf) errors.push(new
|
|
15
|
-
if (exp - nbf > 10_000) errors.push(new
|
|
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(tx, 'Transaction exp must not be too far in the future'))
|
|
16
17
|
} catch (e) {
|
|
17
|
-
errors.push(new
|
|
18
|
+
errors.push(new HydratedTransactionValidationError(tx, `Failed TransactionDurationValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
return errors
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import type { Promisable } from '@xylabs/promise'
|
|
2
1
|
import { extractElevatedHashes } from '@xyo-network/chain-protocol'
|
|
3
2
|
import type {
|
|
4
|
-
|
|
3
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
5
4
|
} from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
6
6
|
|
|
7
|
-
export const TransactionElevationValidator:
|
|
8
|
-
tx:
|
|
9
|
-
)
|
|
10
|
-
const errors: Error[] = []
|
|
7
|
+
export const TransactionElevationValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
8
|
+
tx: HydratedTransaction,
|
|
9
|
+
) => {
|
|
10
|
+
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
11
11
|
try {
|
|
12
12
|
try {
|
|
13
13
|
extractElevatedHashes(tx)
|
|
14
14
|
} catch {
|
|
15
|
-
errors.push(new
|
|
15
|
+
errors.push(new HydratedTransactionValidationError(tx, 'Hydrated transaction does not include all script hashes'))
|
|
16
16
|
}
|
|
17
17
|
} catch (e) {
|
|
18
|
-
errors.push(new
|
|
18
|
+
errors.push(new HydratedTransactionValidationError(tx, `Failed TransactionElevationValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
19
19
|
}
|
|
20
20
|
return errors
|
|
21
21
|
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { asAddress } from '@xylabs/hex'
|
|
2
2
|
import { addressesContains } from '@xyo-network/boundwitness-validator'
|
|
3
3
|
import type {
|
|
4
|
-
HydratedTransaction,
|
|
4
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
5
5
|
} from '@xyo-network/xl1-protocol'
|
|
6
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
6
7
|
|
|
7
|
-
export const TransactionFromValidator:
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
-
const errors: Error[] = []
|
|
8
|
+
export const TransactionFromValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
9
|
+
tx: HydratedTransaction,
|
|
10
|
+
) => {
|
|
11
|
+
const errors: (HydratedTransactionValidationError | Error)[] = []
|
|
11
12
|
try {
|
|
12
|
-
const from = asAddress(tx.from)
|
|
13
|
-
if (from === undefined)errors.push(new
|
|
14
|
-
else if (!addressesContains(tx, from)) errors.push(new
|
|
13
|
+
const from = asAddress(tx[0].from)
|
|
14
|
+
if (from === undefined)errors.push(new HydratedTransactionValidationError(tx, 'Transaction from is not a valid address'))
|
|
15
|
+
else if (!addressesContains(tx[0], from)) errors.push(new HydratedTransactionValidationError(tx, 'Transaction from address must be listed in addresses'))
|
|
15
16
|
} catch (e) {
|
|
16
|
-
errors.push(new
|
|
17
|
+
errors.push(new HydratedTransactionValidationError(tx, `Failed TransactionFromValidator: ${e instanceof Error ? e.message : String(e)}`))
|
|
17
18
|
}
|
|
18
19
|
return errors
|
|
19
20
|
}
|