Skip to content

nostrability/schemata-validator-c

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

schemata-validator-c

C validator for Nostr protocol JSON schemas. This is the C equivalent of schemata-validator-rs, built on top of schemata-c.

Validates Nostr events, NIP-11 documents, and protocol messages against the canonical schemata definitions using Draft 7 JSON Schema.

Related projects

Project Language Role
nostrability/schemata JSON/JS Canonical schema definitions
schemata-c C Data library (schemas + registry)
jsonc-daccord C JSON Schema validation engine (nostrability fork)
schemata-validator-rs Rust Rust equivalent

When to use this

JSON Schema validation is not suited for runtime hot paths — it's slow by design due to the breadth of the specification. Use this library in CI and integration tests to catch schema drift at build time, not in production event processing.

Good for:

  • CI pipelines that verify your event construction matches the canonical schemas
  • Integration tests for clients and relays
  • Fuzz testing to discover broken event shapes

Not good for:

  • Validating every incoming event at runtime
  • Hot paths where latency matters

Known limitations

  • Not thread safe. The underlying jsonc-daccord library uses global mutable state. Use process-level parallelism (fork) if concurrent validation is needed.
  • No $ref resolution. Acceptable because schemata's compiled schemas are fully inlined (zero $ref usage).

Usage

The validator depends on three libraries: json-c (system), jsonc-daccord (sibling), and schemata-c (sibling).

Clone all three as siblings:

git clone https://github.com/nostrability/schemata-c.git
git clone https://github.com/nostrability/jsonc-daccord.git
git clone https://github.com/nostrability/schemata-validator-c.git

Add as a CMake subdirectory:

add_subdirectory(path/to/schemata-validator-c)
target_link_libraries(my_target PRIVATE schemata_validator)

Example: validate a Nostr event

#include <schemata/validator.h>
#include <stdio.h>

int main(void) {
    const char *event = "{"
        "\"id\":\"aabbccdd...\","
        "\"pubkey\":\"11223344...\","
        "\"created_at\":1700000000,"
        "\"kind\":1,"
        "\"tags\":[],"
        "\"content\":\"hello world\","
        "\"sig\":\"aabbccdd...\""
    "}";

    SchemataValidationResult *r = schemata_validate_note(event);
    if (r->valid) {
        printf("Valid kind-1 event\n");
    } else {
        for (size_t i = 0; i < r->error_count; i++) {
            printf("Error: %s (at %s)\n",
                   r->errors[i].message,
                   r->errors[i].instance_path);
        }
    }
    schemata_result_free(r);
    return 0;
}

Example: validate a NIP-11 document

SchemataValidationResult *r = schemata_validate_nip11(
    "{\"name\":\"My Relay\",\"supported_nips\":[1,11]}"
);
/* ... check r->valid ... */
schemata_result_free(r);

Example: validate a protocol message

SchemataValidationResult *r = schemata_validate_message(
    "[\"NOTICE\",\"rate limited\"]",
    SCHEMATA_RELAY,
    "Notice"
);
/* ... check r->valid ... */
schemata_result_free(r);

API

Function Description
schemata_validate(schema_json, data_json) Validate data against any JSON schema string
schemata_validate_note(event_json) Validate a Nostr event (looks up kind{N}Schema)
schemata_validate_nip11(doc_json) Validate a NIP-11 relay info document
schemata_validate_message(msg_json, subject, slug) Validate a relay/client protocol message
schemata_get_schema(key) Look up a schema by export name (delegates to schemata-c)
schemata_result_free(result) Free a validation result and all its allocated memory

SchemataValidationResult

typedef struct {
    bool valid;                         /* true if no errors */
    SchemataValidationError *errors;    /* schema violations */
    size_t error_count;
    SchemataValidationError *warnings;  /* additional properties, missing schemas */
    size_t warning_count;
} SchemataValidationResult;

SchemataValidationError

typedef struct {
    const char *instance_path;   /* JSON pointer to failing value */
    const char *keyword;         /* failing JSON Schema keyword */
    const char *message;         /* human-readable error message */
    const char *schema_path;     /* JSON pointer into schema */
} SchemataValidationError;

Errors are hard schema violations. Warnings flag additional properties not in the schema and unknown kinds/message types.

Internal features

  • Schema pre-processing: strips nested $id and $schema keywords that confuse validators
  • errorMessage enrichment: replaces generic validator errors with human-readable messages from schemata's errorMessage annotations (supports both string and keyword-keyed formats)
  • Additional properties warnings: detects properties not declared in the schema (allOf-aware) and reports them as warnings

Build & test

mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
make
ctest -V

With AddressSanitizer:

cmake .. -DCMAKE_BUILD_TYPE=Debug -DSCHEMATA_VALIDATOR_USE_ASAN=ON
make && ctest -V

Requires json-c and cmocka (auto-detected via pkg-config).

License

GPL-3.0-or-later

About

C jsonschema validator for schemata

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors