Create and Validate a Block
Create an ALX Block from JSON content and verify the deterministic contentHash and blockHash.
Prerequisites
- Node.js 20, 21, or 22
- ALX JavaScript SDK (
@alx-protocol/sdk)
See Quick Start for installation instructions. Block creation and validation run locally without an API key, network connection, or blockchain.
Workflow
- Create a root Block from JSON content with an empty parent set.
- Inspect the generated
contentHashandblockHash. - Validate the Block using
validateBlock(). - Modify the Block content, parent set, or stored hash without recomputing the identities.
- Run
validateBlock()again to identify the mismatch.
Validation Requirements
validateBlock() requires:
contentHash— Matches the canonicalized content.blockHash— Matches the canonicalized content and normalized parent set.parentHashes— Already normalized, without the Block's ownblockHash.- Block structure — Exactly the five protocol fields, with
protocolVersion"1".
Validation runs locally using Block data. Conforming implementations produce equivalent results from equivalent protocol inputs. Block defines the complete validation rules.
- Example
- Output
- Failure Cases
Create a root Block, validate both deterministic identities, and fail the process if validation does not pass.
Create validate-block.mjs and run the script with node validate-block.mjs:
import {
createBlock,
validateBlock,
} from '@alx-protocol/sdk';
const content = {type: 'example', value: 1};
const block = createBlock(content, []);
const result = validateBlock(block);
console.log(JSON.stringify({
contentHash: result.contentHash,
blockHash: result.blockHash,
ok: result.ok,
}, null, 2));
if (!result.ok) process.exitCode = 1;
// Steps 4 and 5: change the content without recomputing the hashes.
const tampered = {...block, content: {type: 'example', value: 2}};
console.log(validateBlock(tampered).ok);
node validate-block.mjs
The overall result is true only when both deterministic identity checks pass.
Both match values and ok are true. The empty parent array makes the result a root Block. The final false is the tampered copy.
{
"contentHash": {
"stored": "0x36b14491b8e08618dbf55e0b54ba54a0967a7b00961c5fe8c99cf1cd17b302dc",
"recomputed": "0x36b14491b8e08618dbf55e0b54ba54a0967a7b00961c5fe8c99cf1cd17b302dc",
"match": true
},
"blockHash": {
"stored": "0x340c01c8f75bd385b15e7712ace74bb638e7122473fab280ba55c5719a7a76eb",
"recomputed": "0x340c01c8f75bd385b15e7712ace74bb638e7122473fab280ba55c5719a7a76eb",
"match": true
},
"ok": true
}
false
Change one protocol input at a time and inspect the deterministic identity that fails.
validateBlock() throws ALX_INVALID_HASH for a malformed hash before any comparison, and ALX_SCHEMA_INVALID for missing or extra fields. Validate Blocks lists every error identifier. Passing the same parents to createBlock() in a different order produces the same identity; a stored Block whose parentHashes are out of order fails validation.
| Change | contentHash.match | blockHash.match | ok |
|---|---|---|---|
Modify content | false | false | false |
Modify stored contentHash only | false | true | false |
| Modify the parent set | true | false | false |
Modify stored blockHash only | true | false | false |
Reorder stored parentHashes | true | true | false |
Related Documentation
Continue with the protocol rules for Block structure, Block identity, canonicalization, and validation.