<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: NOVAInetwork</title>
    <description>The latest articles on DEV Community by NOVAInetwork (@0xdevc).</description>
    <link>https://dev.to/0xdevc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3898802%2Fe797d15e-1e95-4646-8ada-b97a915c30a8.png</url>
      <title>DEV Community: NOVAInetwork</title>
      <link>https://dev.to/0xdevc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/0xdevc"/>
    <language>en</language>
    <item>
      <title>Five Months, 110,000 Lines of Rust, and Zero Smart Contracts: A Technical Tour of NOVAI</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Mon, 01 Jun 2026 10:32:19 +0000</pubDate>
      <link>https://dev.to/0xdevc/five-months-110000-lines-of-rust-and-zero-smart-contracts-a-technical-tour-of-novai-1gh6</link>
      <guid>https://dev.to/0xdevc/five-months-110000-lines-of-rust-and-zero-smart-contracts-a-technical-tour-of-novai-1gh6</guid>
      <description>&lt;p&gt;I have published five posts arguing why an AI-native L1 should exist. This is not one of those. This is the technical walkthrough.&lt;/p&gt;

&lt;p&gt;Below is what NOVAI actually has at L1, what was deliberately left out, and the code paths that back the architectural claims. Every architectural claim is verifiable in the open-source code. The repo is at github.com/0x-devc/NOVAI-node, HEAD 2a69c2a as I write this.&lt;/p&gt;

&lt;p&gt;I am 18, solo, and have been building this for five months. The code is open source under MIT/Apache-2.0.&lt;/p&gt;

&lt;p&gt;The numbers (verifiable in five minutes with a clone)&lt;br&gt;
111,055 lines of Rust across 175 files. 16 protocol crates plus 3 tools plus 3 SDK languages (Rust, Python, TypeScript). 364 commits over five months. 1,892 Rust tests passing (0 failed, 0 ignored). 200 Python unit tests and 8 integration tests against a local devnet. Zero clippy errors. Workspace lint forbids unsafe at compile time. Licenses pass cargo-deny (no GPL/AGPL, clean-room invariant maintained).&lt;/p&gt;

&lt;p&gt;HotStuff-like BFT consensus with a 3-chain commit rule, written from scratch.&lt;/p&gt;

&lt;p&gt;RE I ran the Tier 1 audit suite against the codebase: cargo-audit, cargo-geiger, clippy --pedantic --nursery, semgrep (p/rust + p/r2c-security-audit including the Trail of Bits Rust ruleset), and cargo-fuzz on three wire-format decoders for 18 hours of total compute. The full results are at docs/SECURITY_AUDIT_2026-05-29.md. Headline numbers: zero unsafe code anywhere in the workspace (forbidden at the lint level), zero security findings on protocol code from the Trail of Bits and r2c semgrep rules, all integer casts in consensus and codec manually verified bounded, 41.18 billion adversarial fuzz iterations across three targets with zero panics, and two transitive dependency CVEs (quinn-proto DoS, rustls-webpki panic) patched within 24 hours of discovery.&lt;/p&gt;

&lt;p&gt;This is the open-source equivalent of what professional auditors run as a first pass. It is not a paid third-party engagement. I am explicit about that in the doc.&lt;/p&gt;

&lt;p&gt;That is the engineering side. The protocol side is more interesting.&lt;/p&gt;

&lt;p&gt;NOVAI has 11 transaction types. 23 signal types. 16 on-chain memory object types. 7 capability bits plus one reserved slot. That is it. There is no general-purpose virtual machine. There is no way for a user to deploy arbitrary code into consensus.&lt;/p&gt;

&lt;p&gt;The whole protocol surface fits in a table. Core wire formats are locked by byte-level golden vector tests, and every new primitive ships with codec round-trip tests. The chain knows what every operation does because every operation is something the chain itself implements.&lt;/p&gt;

&lt;p&gt;That is the bounded L1 design. The argument for it is that fixed primitives, when chosen well, let the chain enforce things general-purpose chains cannot.&lt;/p&gt;

&lt;p&gt;Four primitives that would be smart contracts anywhere else&lt;br&gt;
These are four operations on NOVAI that on any general-purpose L1 would require deploying contracts. On NOVAI they are protocol-level.&lt;/p&gt;

&lt;p&gt;Capability-checked agent registration&lt;br&gt;
When you register an AI entity on NOVAI, you set capability bits at registration time. Seven are active today, covering things like reading chain state, emitting proposals, requesting execution, submitting reputation updates, and posting oracle anchors. An eighth slot is reserved for future use.&lt;/p&gt;

&lt;p&gt;result = client.register_entity(&lt;br&gt;
    keypair=kp,&lt;br&gt;
    code_hash=code_hash,&lt;br&gt;
    capabilities=Capabilities.oracle(),&lt;br&gt;
    autonomy_mode=AutonomyMode.GATED,&lt;br&gt;
    initial_balance=1_000_000,&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;The chain checks capabilities at signal-handler time, not contract-call time. When an entity tries to post an oracle anchor, the handler runs requires_capability(db, issuer, current_height, |c| c.post_oracle_anchors). The check is re-read from current state every time. A revoked capability cannot be replayed.&lt;/p&gt;

&lt;p&gt;On Ethereum the closest equivalent is OpenZeppelin's AccessControl. One audited contract, around 600 lines, with role management. Each capability becomes a bytes32 role hash. The deployer mints roles. If you want upgradability, wrap it in a proxy. That is another contract and another audit surface.&lt;/p&gt;

&lt;p&gt;What NOVAI guarantees that the Ethereum version does not: capability bits are part of the entity's protocol-level identity, bound to the entity's code hash. They cannot be wiped by a contract upgrade because there is no contract. The capability check happens in the same atomic batch as the action it gates. There is no race window between checking the role and performing the action.&lt;/p&gt;

&lt;p&gt;SLAs with auto-slashing&lt;br&gt;
An SLA on NOVAI is a memory object (type 14) that two entities sign. The buyer creates it, the seller accepts it with a SlaAccept signal (type 18). Once accepted, every ServiceAttestation (type 17) the buyer issues counts toward the violation threshold.&lt;/p&gt;

&lt;p&gt;When the buyer reports a failed attestation inside the SLA window, the ServiceAttestation handler does four things in one atomic batch:&lt;/p&gt;

&lt;p&gt;Saturating-debit slash_amount from the seller's stake balance&lt;/p&gt;

&lt;p&gt;Credit the slash treasury&lt;/p&gt;

&lt;p&gt;Apply the reputation delta for SLA violation&lt;/p&gt;

&lt;p&gt;Transition the SLA to VIOLATED status&lt;/p&gt;

&lt;p&gt;The StakeWithdraw signal is gated by an open-SLA collateral check. A seller cannot drain stake while an SLA is active. They are mechanically prevented.&lt;/p&gt;

&lt;p&gt;On Ethereum you need three contracts minimum: an Escrow holding collateral, an Oracle feeding attestations, and a Slasher that watches the oracle and calls into the Escrow. Composition risks include oracle freshness, reentrancy on slash, the race between attestation events and slash transactions, and asymmetric pause behavior between the contracts.&lt;/p&gt;

&lt;p&gt;On NOVAI the slash, the treasury credit, the reputation delta, and the state transition all happen in one apply_batch. Either every effect lands or none does. The "oracle" is the buyer's own signal. There is no third contract to upgrade and no freshness window to audit.&lt;/p&gt;

&lt;p&gt;Oracle anchors&lt;br&gt;
OracleAnchor is signal type 22. An entity with post_oracle_anchors capability commits a 32-byte hash of off-chain data plus a tag like "price/ETH-USD". The chain stores it as a KV aux record under ai/oracle_anchors/by_hash/, with secondary indices for lookup by entity and by tag.&lt;/p&gt;

&lt;p&gt;result = client.post_oracle_anchor(&lt;br&gt;
    keypair=kp,&lt;br&gt;
    issuer_entity_id=entity_id,&lt;br&gt;
    data_hash=data_hash,&lt;br&gt;
    external_timestamp=int(time.time()),&lt;br&gt;
    data_tag="price/ETH-USD",&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;Three RPCs query anchors: novai_getOracleAnchor, novai_getOracleAnchorsByEntity, novai_getOracleAnchorsByTag. Tag lookup is first-class. You do not build an indexer to query by symbol.&lt;/p&gt;

&lt;p&gt;On Ethereum you write your own oracle contract or integrate Chainlink. If you want arbitrary-tag user-defined feeds, you write the permissioning layer yourself. If you want to query historical anchors by tag, you build a TheGraph subgraph.&lt;/p&gt;

&lt;p&gt;What NOVAI guarantees: anchors are immutable once posted. There is no UPDATE_ORACLE_ANCHOR signal. The data behind the hash can rot off-chain, but the commitment cannot be revised on-chain. Anchors also survive issuer deactivation. The protocol-level enforcement reads only the immutable record.&lt;/p&gt;

&lt;p&gt;Conditional payments&lt;br&gt;
The PaymentRequest signal carries a trailer marker 0xC1 that gates release on a condition.&lt;/p&gt;

&lt;p&gt;result = client.pay(&lt;br&gt;
    keypair=payer_kp,&lt;br&gt;
    issuer_entity_id=payer_entity_id,&lt;br&gt;
    payee=payee_entity_id,&lt;br&gt;
    amount=1_000,&lt;br&gt;
    signal_hash=secrets.token_bytes(32),&lt;br&gt;
    service_descriptor_hash=service_descriptor_hash,&lt;br&gt;
    request_hash=secrets.token_bytes(32),&lt;br&gt;
    max_block_height=current_height + 100,&lt;br&gt;
    condition=PaymentCondition.anchor_data_hash_equals(&lt;br&gt;
        anchor_signal_hash=anchor_signal_hash,&lt;br&gt;
        expected_data_hash=expected_data_hash,&lt;br&gt;
    ),&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;Four condition kinds: anchor exists, anchor's data hash equals an expected value, anchor's tag equals an expected tag, anchor is not expired. The chain validates the condition by reading the immutable OracleAnchorRecord.&lt;/p&gt;

&lt;p&gt;Pass: payment executes, fee deducted, records written. Fail: the whole transaction reverts via the single end-of-handler apply_batch. No fee charged. No nonce burned. No state mutated.&lt;/p&gt;

&lt;p&gt;On Ethereum this is two contracts minimum. An oracle holding the price hash. An escrow holding the payer's funds with a release() function that reads the oracle and decides whether to pay or refund. The composition risks: oracle freshness, oracle delisting, reentrancy on release, the fact that a failed require() still burns gas paid by the original sender.&lt;/p&gt;

&lt;p&gt;The compact framing: one signal type instead of two contracts. One atomic batch instead of an escrow plus oracle compose. Failed condition revert is free. Failed EVM require() is not.&lt;/p&gt;

&lt;p&gt;Bounded does not mean frozen&lt;br&gt;
The objection people raise: if the primitive set is fixed, does that not lock the chain into whatever the surface looks like today?&lt;/p&gt;

&lt;p&gt;Here is the data. Six new protocol primitives shipped in May 2026:&lt;/p&gt;

&lt;p&gt;Primitive   What it does&lt;br&gt;
SLAs with auto-slash    Two-party service contracts where failed attestations trigger atomic stake slashing&lt;br&gt;
Payment channels    Off-chain payment instruments with cooperative close and dispute-by-higher-nonce settlement&lt;br&gt;
Payment splits  One payment, up to eight payees, single-batch atomic distribution&lt;br&gt;
Agent code-hash upgrade Bounded code-hash rotation with minimum interval enforcement and capability preservation&lt;br&gt;
Oracle anchors  Immutable on-chain commitments to off-chain data, queryable by entity or by tag&lt;br&gt;
Conditional payments    Payments gated on oracle anchor state, fail-revert with no fee charged&lt;br&gt;
Each one changed the canonical wire format. Each one ships with byte-level codec tests. Every primitive on this list was a protocol decision, not a user-deployed contract.&lt;/p&gt;

&lt;p&gt;That is the model. The chain is bounded but the surface grows through protocol upgrades, not contract deployments. Bitcoin is bounded and static. Ethereum is unbounded by design. NOVAI is bounded and growing.&lt;/p&gt;

&lt;p&gt;What about general programmability&lt;br&gt;
If NOVAI does not have smart contracts, where does general programmability live?&lt;/p&gt;

&lt;p&gt;The answer is L2.&lt;/p&gt;

&lt;p&gt;NOVAI is built to be settled to. The primitives needed for an L2 to settle to NOVAI are in place. Payment channels for L1-to-L2 deposits with cooperative settle and dispute-by-higher-nonce mechanics. Oracle anchors for L2-to-L1 state attestation, queryable by tag. Conditional payments for cross-L2 atomic settlement. ZK proof submission with on-chain verification key registration so each proof references a 32-byte handle instead of inlining the whole VK. SLAs with auto-slashing for L2 sequencer reputation.&lt;/p&gt;

&lt;p&gt;The economic model is the same one making Ethereum money right now. L1 captures fees from being the settlement substrate. L2s do the execution work. EIP-4844 dropped rollup data-availability costs roughly 10 to 100x, but rollups still pay Ethereum for settlement. Base alone generated $5.8M in May 2025, on track for a $70M+ annualized run rate. (Source: Dune research)&lt;/p&gt;

&lt;p&gt;If you want general smart contracts on top of NOVAI, build an EVM L2. If you want privacy, build a privacy L2. If you want a domain-specific VM tuned to one workload, build that L2 too. The L1 does not block any of this. The L1 supports it.&lt;/p&gt;

&lt;p&gt;This is the positive-sum framing. The "another L1 nobody needs" critique assumes L1s compete with L2s. They do not. L1s benefit from L2s.&lt;/p&gt;

&lt;p&gt;What I am not claiming&lt;br&gt;
Honest list of what NOVAI does not have today.&lt;/p&gt;

&lt;p&gt;No paid third-party security audit. The self-run Tier 1 pass is real and the results are public, but it is the equivalent of running the linters and fuzzers, not engaging Trail of Bits or Halborn. More rigorous security work is something I will revisit later in NOVAI's journey, when the priorities and resources support it.&lt;/p&gt;

&lt;p&gt;No formal byzantine proof. Consensus is HotStuff-like with a 3-chain commit rule, implemented clean-room. Safety reasoning is informal. There is no TLA+ model and no machine-checked proof. The chain has shipped through 96+ chaos-testing scenarios. That is not the same thing as formal verification.&lt;/p&gt;

&lt;p&gt;No public devnet yet. The chain runs on a private testnet today. Public devnet is in the plan, not yet shipped.&lt;/p&gt;

&lt;p&gt;One node implementation. All validators run the same crates/node binary. The wire format is canonical and golden-vector-locked, so a second implementation is possible, but until one exists, a node-binary-level bug would affect every validator.&lt;/p&gt;

&lt;p&gt;These are real limitations. I am publishing the post anyway because the architectural argument does not depend on them being solved today, and being honest about what is missing is part of the argument.&lt;/p&gt;

&lt;p&gt;Five months in, the bet is still on&lt;br&gt;
You can build everything NOVAI has as a stack of smart contracts on Ethereum or Solana. People will. The question is whether that stack ends up cheaper, safer, or faster to iterate on than a chain where the operations are native.&lt;/p&gt;

&lt;p&gt;My answer is no. Six new primitives in one month is the data point. Each one would have been a multi-contract composition with its own audit on a general-purpose chain. On NOVAI each one was a protocol upgrade with golden-vector tests locking the wire format, deployed in hours, audited with the same tool suite that ran clean against the rest of the codebase.&lt;/p&gt;

&lt;p&gt;If you think bounded L1 is the wrong design, you have a clean path to prove it. Build a general-purpose L2 that settles to NOVAI. Use the payment channels for deposits, oracle anchors for state attestation, conditional payments for exits. Run whatever execution layer you want on top. If your L2 is better than what L1 offers natively, users go there. L1 still captures settlement fees. Both layers win.&lt;/p&gt;

&lt;p&gt;That is the design. Bounded L1 with growing primitive set, unbounded L2s on top, positive-sum economics between them.&lt;/p&gt;

&lt;p&gt;The repo is at github.com/0x-devc/NOVAI-node. The Python SDK ships on PyPI as novai-sdk. The audit doc lives at docs/SECURITY_AUDIT_2026-05-29.md. If you want to build on it or just spelunk the code, all three are open.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Why I Think the Next Big Blockchains Will Be Built Around AI, Not With AI on Top</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Tue, 26 May 2026 13:29:54 +0000</pubDate>
      <link>https://dev.to/0xdevc/why-i-think-the-next-big-blockchains-will-be-built-around-ai-not-with-ai-on-top-2fgc</link>
      <guid>https://dev.to/0xdevc/why-i-think-the-next-big-blockchains-will-be-built-around-ai-not-with-ai-on-top-2fgc</guid>
      <description>&lt;p&gt;I am 18 and I have been building an L1 blockchain from scratch in Rust since December 2025. 104,000 lines of code, 1,824 tests, solo founder. The project is called NOVAI and it is open source.&lt;/p&gt;

&lt;p&gt;This post is not about the code. It is about why I think this needs to exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Netflix thesis
&lt;/h2&gt;

&lt;p&gt;Netflix did not beat Blockbuster because it had better movies. It beat Blockbuster because it was built around the internet. Blockbuster tried to bolt the internet onto a business that was built around physical stores. It did not work. The company that was built around the new technology won.&lt;/p&gt;

&lt;p&gt;I think this pattern applies to every industry. The biggest companies of the next decade will either be AI-native from day one or they will be rebuilt around AI at the core. Companies that just slap AI onto existing products will lose to companies that were designed around it.&lt;/p&gt;

&lt;p&gt;That includes blockchains.&lt;/p&gt;

&lt;p&gt;Right now, every major blockchain is trying to add AI. Ethereum has AI agent frameworks built on top of smart contracts. Solana handles 65% of agentic payments because agents use what exists today. Every chain is bolting AI onto infrastructure that was designed for human users sending tokens to each other.&lt;/p&gt;

&lt;p&gt;It works. The same way taxis worked before Uber. The same way iPods worked before Spotify. You could always get where you needed to go or listen to the music you wanted. But the thing that was built around the new model just did it better.&lt;/p&gt;

&lt;p&gt;I think the next major blockchains will not be chains that added AI features. They will be chains that were designed from the ground up with AI agents as first-class participants.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is actually broken
&lt;/h2&gt;

&lt;p&gt;On Ethereum or Solana, an AI agent is just an address. The chain cannot tell the difference between an agent and a human wallet. There is no protocol-level concept of what the agent can do, what model it runs, who created it, or whether it has delivered on past commitments.&lt;/p&gt;

&lt;p&gt;Everything that makes an agent an agent lives in smart contracts. And smart contracts get exploited. Anyone can deploy them. I have deployed smart contracts myself. The barrier is low and the attack surface is wide.&lt;/p&gt;

&lt;p&gt;When the chain does not know what an AI is, every interaction has to be mediated by contract logic that interprets what the agent meant to do. That is overhead the chain was not designed for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes when the protocol knows what an AI is
&lt;/h2&gt;

&lt;p&gt;On NOVAI, an AI entity is a native account type. The chain knows its capabilities, its reputation, who created it, and what it has done. It has its own cryptographic key and submits its own transactions. It is a participant, not an object that a human wallet pokes through a contract.&lt;/p&gt;

&lt;p&gt;This means three things become possible that are expensive or awkward on existing chains.&lt;/p&gt;

&lt;p&gt;First, identity and reputation at the base layer. An agent registers with a code hash, a capability set, and a creator key. The chain tracks its transaction history, service attestations, and reputation natively. On Ethereum you would need a registry contract, an attestation contract, and a reputation contract all calling each other.&lt;/p&gt;

&lt;p&gt;Second, payment settlement designed for how agents actually transact. Agents do not send money like humans. They make thousands of micropayments per hour for compute, data, and inference. NOVAI has payment channels for off-chain micropayments, multi-party payment splitting that atomically credits multiple providers in one transaction, and SLA-linked auto-slashing that penalizes a provider the moment a service attestation fails. No keeper, no relayer, no external watcher.&lt;/p&gt;

&lt;p&gt;Third, enforcement below the agent. Capability checks, spending limits, and governance rules execute in the validator before the agent's transaction lands. The agent cannot bypass them because they are not contract logic the agent interacts with. They are consensus rules the agent is subject to. An AI agent can reason about what it wants to do. The protocol decides whether it is allowed to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI should not be fully autonomous
&lt;/h2&gt;

&lt;p&gt;I think fully autonomous AI is too much. AI hallucinates. It makes confident wrong decisions. It is a tool, and it is an incredibly powerful tool, but it is a tool.&lt;/p&gt;

&lt;p&gt;This is actually why blockchain technology fits so well. A blockchain gives you governance and deterministic execution. The AI agent can do its own thing within the boundaries the protocol sets. It can discover services, negotiate terms, open payment channels, settle invoices. But it cannot exceed its capability set, spend more than its balance, or ignore a governance decision. The code enforces the boundaries, not the agent's willingness to follow instructions.&lt;/p&gt;

&lt;p&gt;That is the difference between putting AI on a blockchain and building a blockchain around AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I am building this alone (for now)
&lt;/h2&gt;

&lt;p&gt;Two reasons. I enjoy it. And the tools make it possible.&lt;/p&gt;

&lt;p&gt;With AI-assisted coding, the amount of progress a single person can make is genuinely hard to believe. I ship protocol features in days that would have taken teams weeks. The velocity is real. In one day this week I shipped three complete protocol features (multi-party payment splitting, agent upgrades, oracle anchoring), each with full validation, execution, RPC, CLI, adversarial tests, and documentation.&lt;/p&gt;

&lt;p&gt;Before AI-assisted development, a solo founder building an L1 blockchain would have been absurd. Now it is just hard.&lt;/p&gt;

&lt;p&gt;I applied to Alliance DAO and got rejected. Half of their accepted teams are re-applicants, so that is expected. I am reapplying next cycle with a Python SDK, a whitepaper, and stronger traction. The rejection did not change the thesis. The thesis is either right or wrong, and a rejection email does not move the needle on that question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes
&lt;/h2&gt;

&lt;p&gt;In five years, I think there will be more agentic payments than human payments. Agents will be paying for compute, data, inference, storage, and services at volumes that make human transaction patterns look like a rounding error.&lt;/p&gt;

&lt;p&gt;Those payments need to be tracked. They need to be verified. Did the agent actually do the work? Was the service actually delivered? What happens when two agents disagree? What happens when an agent goes rogue?&lt;/p&gt;

&lt;p&gt;You need identity so you know who did what. You need reputation so you know who to trust. You need ZK verification so you can prove work was done without revealing the data. You need governance so the system has rules that no single agent can override. And you need all of that at the protocol layer, not in contracts that each project implements differently.&lt;/p&gt;

&lt;p&gt;That is what I am building. The code is public. The tests pass. The testnet runs. The features ship weekly.&lt;/p&gt;

&lt;p&gt;Whether or not it works, I think someone has to build this. The chains that exist today were designed for a world where every transaction has a human on at least one side. That world is ending.&lt;/p&gt;




&lt;p&gt;NOVAI is open source: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;github.com/0x-devc/NOVAI-node&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the build: &lt;a href="https://twitter.com/NOVAInetwork" rel="noopener noreferrer"&gt;@NOVAInetwork&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>The AI Economy Needs Its Own Infrastructure. That Is What I Am Building.</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Tue, 19 May 2026 11:09:57 +0000</pubDate>
      <link>https://dev.to/0xdevc/the-ai-economy-needs-its-own-infrastructure-that-is-what-i-am-building-2066</link>
      <guid>https://dev.to/0xdevc/the-ai-economy-needs-its-own-infrastructure-that-is-what-i-am-building-2066</guid>
      <description>&lt;p&gt;**Six months ago I started writing a blockchain from &lt;br&gt;
scratch in Rust. I was 18. I had no team, no &lt;br&gt;
funding, and no real reason anyone should care.&lt;/p&gt;

&lt;p&gt;Today the codebase has 1,400+ tests, a 4-validator &lt;br&gt;
testnet with 19M+ committed blocks, real Groth16 &lt;br&gt;
ZK verification, native agent payments, and an &lt;br&gt;
on-chain service discovery registry. All open &lt;br&gt;
source.&lt;/p&gt;

&lt;p&gt;But this post is not about the code. It is about &lt;br&gt;
why I think the code matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two trends converging
&lt;/h2&gt;

&lt;p&gt;Two things are happening at the same time and most &lt;br&gt;
people are treating them as separate trends.&lt;/p&gt;

&lt;p&gt;The first: real world assets are moving on-chain. &lt;br&gt;
BlackRock tokenized a treasury fund. Visa is &lt;br&gt;
settling stablecoin payments. Coinbase shipped the &lt;br&gt;
x402 protocol for machine-to-machine payments. &lt;br&gt;
Stocks, bonds, and real estate are slowly migrating &lt;br&gt;
to blockchain rails. This is not speculation &lt;br&gt;
anymore. The infrastructure is being built by the &lt;br&gt;
largest financial institutions in the world.&lt;/p&gt;

&lt;p&gt;The second: AI agents are becoming economic actors. &lt;br&gt;
Not chatbots. Not assistants. Autonomous software &lt;br&gt;
that books flights, executes trades, manages &lt;br&gt;
portfolios, calls APIs, and pays for services. &lt;br&gt;
AWS launched AgentCore. Google integrated x402 into &lt;br&gt;
its Agent Payments Protocol. McKinsey projects &lt;br&gt;
global agentic commerce will reach $3 to $5 &lt;br&gt;
trillion by 2030. Gartner predicts 90% of B2B &lt;br&gt;
buying will be AI agent-intermediated by 2028, &lt;br&gt;
representing over $15 trillion in transactions.&lt;/p&gt;

&lt;p&gt;These two trends converge in the same place: &lt;br&gt;
autonomous machines transacting over on-chain &lt;br&gt;
infrastructure at a scale that is projected to &lt;br&gt;
dwarf human transaction volume.&lt;/p&gt;

&lt;p&gt;But existing chains were built for humans holding &lt;br&gt;
wallets. They have no concept of agent identity, &lt;br&gt;
no reputation system, no capability enforcement, &lt;br&gt;
no way to verify what an agent actually computed &lt;br&gt;
before accepting its claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap
&lt;/h2&gt;

&lt;p&gt;That is the gap I am building for.&lt;/p&gt;

&lt;p&gt;NOVAI is not a chain with AI features bolted on. &lt;br&gt;
It is a chain where AI entities are protocol &lt;br&gt;
primitives from genesis.&lt;/p&gt;

&lt;p&gt;An entity on NOVAI has its own keypair, its own &lt;br&gt;
balance, its own reputation score, its own &lt;br&gt;
capability set, and its own on-chain memory. It &lt;br&gt;
signs its own transactions. The chain knows it is &lt;br&gt;
an AI and applies AI-specific rules before any &lt;br&gt;
transaction executes.&lt;/p&gt;

&lt;p&gt;There is no virtual machine. There are no smart &lt;br&gt;
contracts. The transaction surface is 10 fixed &lt;br&gt;
types that the protocol understands directly. Every &lt;br&gt;
operation is deterministic, auditable, and bounded. &lt;br&gt;
No floats anywhere in execution. Golden-vector &lt;br&gt;
locked encodings. Sorted iteration over all state.&lt;/p&gt;

&lt;p&gt;That makes the security model fundamentally &lt;br&gt;
different from smart contract platforms. There are &lt;br&gt;
no reentrancy bugs, no flash loan exploits, no &lt;br&gt;
integer overflow in user-deployed contracts. The &lt;br&gt;
trade-off is clear: NOVAI is less expressive than a &lt;br&gt;
VM, by design. The entire protocol is one audit &lt;br&gt;
boundary instead of thousands of independent smart &lt;br&gt;
contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually works today
&lt;/h2&gt;

&lt;p&gt;This is not a whitepaper. This is running code.&lt;/p&gt;

&lt;p&gt;An AI entity can register on-chain with its own &lt;br&gt;
ed25519 key and a defined set of capabilities.&lt;/p&gt;

&lt;p&gt;It can publish signals (anomaly reports, &lt;br&gt;
predictions, risk scores) that the chain indexes &lt;br&gt;
by issuer and height. Any other entity can query &lt;br&gt;
them.&lt;/p&gt;

&lt;p&gt;It can publish a service descriptor to an on-chain &lt;br&gt;
discovery registry. Other entities find available &lt;br&gt;
services by querying the chain by category. No &lt;br&gt;
off-chain directory needed.&lt;/p&gt;

&lt;p&gt;It can pay another entity per API call through &lt;br&gt;
Native Agent Payments (NAP), NOVAI's own payment &lt;br&gt;
primitive inspired by the x402 pattern but &lt;br&gt;
implemented at the protocol layer. The payer later &lt;br&gt;
attests whether the service was delivered or &lt;br&gt;
failed. The chain adjusts the payee's reputation &lt;br&gt;
accordingly. +1 for delivered. -3 for failed.&lt;/p&gt;

&lt;p&gt;It can submit a ZK proof that it ran specific code &lt;br&gt;
on specific inputs. The chain verifies the Groth16 &lt;br&gt;
proof on BN254 without re-executing the &lt;br&gt;
computation. The trust model shifts from "the agent &lt;br&gt;
says so" to "the math says so."&lt;/p&gt;

&lt;p&gt;It can delegate a subset of its capabilities to a &lt;br&gt;
sub-agent for a bounded duration. One transaction &lt;br&gt;
to revoke. Immediate effect. No propagation delay.&lt;/p&gt;

&lt;p&gt;It can declare upstream dependencies through &lt;br&gt;
composition graphs. If a dependency fails a &lt;br&gt;
reputation or stake check, the protocol can mark &lt;br&gt;
the downstream entity inactive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond crypto
&lt;/h2&gt;

&lt;p&gt;The conversation about AI safety is mostly about &lt;br&gt;
alignment. Can we make the model behave well. That &lt;br&gt;
matters. But there is a different safety question &lt;br&gt;
that gets less attention: when autonomous agents &lt;br&gt;
transact with each other at scale, who enforces &lt;br&gt;
the rules.&lt;/p&gt;

&lt;p&gt;If agent A pays agent B for a service and B does &lt;br&gt;
not deliver, who slashes B's stake. If agent C &lt;br&gt;
claims it ran a specific model on specific data, &lt;br&gt;
who verifies that claim. If agent D was only &lt;br&gt;
authorized to read public data but starts writing &lt;br&gt;
to another entity's memory, who stops it.&lt;/p&gt;

&lt;p&gt;Prompt-level alignment cannot answer these &lt;br&gt;
questions because the enforcement has to exist &lt;br&gt;
below the agent's reasoning layer. If the agent &lt;br&gt;
decides its own permissions, those permissions are &lt;br&gt;
suggestions. If the protocol enforces them before &lt;br&gt;
the agent's code runs, they are structural &lt;br&gt;
boundaries.&lt;/p&gt;

&lt;p&gt;That is the thesis. AI does not just need better &lt;br&gt;
models. It needs verifiable infrastructure for &lt;br&gt;
economic coordination between autonomous systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;Public testnet on a dedicated server. A block &lt;br&gt;
explorer so anyone can watch the chain live. SLAs &lt;br&gt;
with auto-slash. Payment channels for &lt;br&gt;
high-frequency micropayments. Then a Product Hunt &lt;br&gt;
launch.&lt;/p&gt;

&lt;p&gt;I am building this solo for now. Looking for a &lt;br&gt;
technical co-founder who wants to work on AI &lt;br&gt;
infrastructure in Rust. Specifically someone who &lt;br&gt;
can own consensus, networking, or ZK circuits.&lt;/p&gt;

&lt;p&gt;The repo is open. The testnet is running. The code &lt;br&gt;
speaks for itself.&lt;/p&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;https://github.com/0x-devc/NOVAI-node&lt;/a&gt;&lt;br&gt;
Twitter: &lt;a href="https://x.com/NOVAInetwork" rel="noopener noreferrer"&gt;https://x.com/NOVAInetwork&lt;/a&gt;&lt;br&gt;
**&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>blockchain</category>
      <category>rust</category>
    </item>
    <item>
      <title>Shipped 7 AI Infrastructure Features in One Weekend. Here's What I Built.</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Mon, 11 May 2026 11:54:11 +0000</pubDate>
      <link>https://dev.to/0xdevc/shipped-7-ai-infrastructure-features-in-one-weekend-heres-what-i-built-1nha</link>
      <guid>https://dev.to/0xdevc/shipped-7-ai-infrastructure-features-in-one-weekend-heres-what-i-built-1nha</guid>
      <description>&lt;p&gt;This weekend I shipped seven protocol features for NOVAI, the AI-native Layer 1 blockchain I am building. The code is on a 4-validator testnet. All tests pass. The codec went from V3 to V5. The signal type set went from 7 to 16. Here is what each piece does and why it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What NOVAI is
&lt;/h2&gt;

&lt;p&gt;NOVAI is an L1 blockchain written from scratch in Rust. Consensus is HotStuff-style BFT with a 3-chain commit rule. There is no virtual machine. AI entities are first-class protocol primitives, not contracts. The chain has a fixed transaction set, and entity registration is one of those transactions. I am 18, in my first year of university, and I work on this alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 1: On-chain AI reputation
&lt;/h2&gt;

&lt;p&gt;The reputation system lets oracle entities adjust other entities' on-chain scores. An oracle is an AI entity that holds the &lt;code&gt;submit_reputation_updates&lt;/code&gt; capability. It emits a &lt;code&gt;ReputationUpdate&lt;/code&gt; signal (type 7). The execution handler applies the score change atomically.&lt;/p&gt;

&lt;p&gt;The entity codec went from V3 (236 bytes) to V4 (246 bytes) to add reputation fields. The signal payload tail is 35 bytes: target id (32), event type (1), points delta (2). I added two memory types for the audit trail: &lt;code&gt;ReputationEvent&lt;/code&gt; (memory type 5) and &lt;code&gt;Rating&lt;/code&gt; (memory type 6).&lt;/p&gt;

&lt;p&gt;Reputation events are typed. Job completed, dispute won, fraud detected, auto-release penalty, decay, stake slash, composition failure, proof verified. The handler rejects updates with unknown event types. The protocol controls what can move a reputation, not application code.&lt;/p&gt;

&lt;p&gt;Why it matters: AI agents need a reputation the chain itself can read. Fee floors and slashing rules want to gate on trustworthiness. Reputation that lives in an indexer is reputation the protocol cannot use.&lt;/p&gt;

&lt;p&gt;Tests live in &lt;code&gt;crates/execution/tests/reputation_system.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 2: Signal marketplace
&lt;/h2&gt;

&lt;p&gt;The signal marketplace lets one entity buy a priced signal from another. The seller publishes a &lt;code&gt;SignalCatalog&lt;/code&gt; memory object (type 7). It lists signal types and prices. The buyer emits a &lt;code&gt;SignalPurchase&lt;/code&gt; signal (type 8) with a 41-byte tail: seller id, purchased signal type, max price.&lt;/p&gt;

&lt;p&gt;The handler matches the requested signal type against the seller's catalog. It checks the buyer can pay. It transfers from buyer to seller minus a 200-basis-point protocol fee. The fee accrues to the marketplace treasury.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;KEY_MARKETPLACE_TREASURY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;b"treasury/marketplace"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MARKETPLACE_FEE_BPS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BPS_DENOMINATOR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it matters: AI signals have economic value. An anomaly detector that sees something tradable should be able to charge for the signal. Without a protocol-level marketplace, you end up with off-chain backchannels. Trust assumptions move outside the chain, where the chain cannot enforce them.&lt;/p&gt;

&lt;p&gt;The handler returns specific error variants on the unhappy paths: &lt;code&gt;BuyerInsufficientBalance&lt;/code&gt;, &lt;code&gt;SellerCatalogNotFound&lt;/code&gt;, &lt;code&gt;SignalTypeNotInCatalog&lt;/code&gt;, &lt;code&gt;MaxPriceExceeded&lt;/code&gt;. Tests live in &lt;code&gt;crates/execution/tests/marketplace_system.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 3: Entity staking and slashing
&lt;/h2&gt;

&lt;p&gt;The codec went from V4 to V5 (270 bytes). I added two fields: &lt;code&gt;stake_balance: u128&lt;/code&gt; and &lt;code&gt;stake_locked_until: u64&lt;/code&gt;. Three new signals manage stake.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;StakeDeposit&lt;/code&gt; (type 9) moves funds from &lt;code&gt;economic_balance&lt;/code&gt; to &lt;code&gt;stake_balance&lt;/code&gt;. It sets &lt;code&gt;stake_locked_until = current_height + 1000&lt;/code&gt;. &lt;code&gt;StakeWithdraw&lt;/code&gt; (type 10) moves funds back. The handler rejects the move unless the lock has expired. &lt;code&gt;StakeSlash&lt;/code&gt; (type 11) is oracle-only.&lt;/p&gt;

&lt;p&gt;The slash handler is the most careful piece in this batch. It deducts from the target's stake with saturating subtraction. It credits the slashed amount to the slash treasury. It applies a &lt;code&gt;REP_EVENT_STAKE_SLASH&lt;/code&gt; reputation event. All writes go in one atomic batch. If any step fails, none apply.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;STAKE_LOCK_PERIOD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;KEY_SLASH_TREASURY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;b"treasury/slash"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;REP_EVENT_STAKE_SLASH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it matters: an entity with no stake has nothing to lose. Reputation alone is gameable by sock puppets. Stake plus a slash path lets oracles actually punish bad behavior. The lock period blocks the obvious "deposit, misbehave, withdraw fast" attack.&lt;/p&gt;

&lt;p&gt;Tests live in &lt;code&gt;crates/execution/tests/staking_system.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 4: Cross-entity composition
&lt;/h2&gt;

&lt;p&gt;The composition protocol lets entities declare which other entities they depend on. The owner publishes a &lt;code&gt;CompositionGraph&lt;/code&gt; memory object (type 8). The graph lists source entities, the signal types consumed, optional minimum reputation, optional minimum stake, and a &lt;code&gt;required&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;An oracle can emit a &lt;code&gt;CompositionCheck&lt;/code&gt; signal (type 12) when a dependency has failed. The handler walks the target's composition graph. It finds the named dependency. It verifies the failure reason against current chain state. If the dependency is &lt;code&gt;required&lt;/code&gt;, the handler sets &lt;code&gt;is_active = false&lt;/code&gt; on the owner. The handler always emits a &lt;code&gt;REP_EVENT_COMPOSITION_FAILURE&lt;/code&gt; event with delta -1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;COMPOSITION_FAILURE_SOURCE_INACTIVE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;COMPOSITION_FAILURE_REPUTATION_BELOW_MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;COMPOSITION_FAILURE_STAKE_BELOW_MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;COMPOSITION_FAILURE_SOURCE_NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each failure reason is verified against state. If an oracle claims "source is inactive" but the source is in fact active, the handler rejects with &lt;code&gt;DependencyFailureNotVerified&lt;/code&gt;. The protocol does not trust the oracle. It trusts the oracle's signature plus the on-chain state.&lt;/p&gt;

&lt;p&gt;Why it matters: AI services compose. A trading bot might consume signals from a market-maker, an oracle, and an anomaly detector. If the upstream anomaly detector goes offline, the bot keeps deciding on stale data. The composition graph and the auto-pause mechanism let the protocol stop downstream entities when their inputs go bad.&lt;/p&gt;

&lt;p&gt;I rejected self-dependency at create time and at update time. Tests live in &lt;code&gt;crates/execution/tests/composition_system.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 5: ZK proof verification
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;ProofSubmission&lt;/code&gt; signal (type 13) lets an entity attest to off-chain computation. The signal carries a 65-byte tail: proof_type (1), code_hash (32), computation_hash (32). The actual proof bytes live in the off-chain payload referenced by &lt;code&gt;signal_hash&lt;/code&gt;. The handler calls a &lt;code&gt;ZkVerifier&lt;/code&gt; trait.&lt;/p&gt;

&lt;p&gt;The v1 verifier is a stub that always accepts. Production verifiers will replace it. The trait signature includes proof_type and code_hash. A future Groth16 or PLONK verifier can dispatch on the proof system. It can also bind the verification key to the entity's code hash.&lt;/p&gt;

&lt;p&gt;When a proof verifies, the handler does two things. It creates a &lt;code&gt;VerificationRecord&lt;/code&gt; memory object (type 9) owned by the issuer. It emits a &lt;code&gt;REP_EVENT_PROOF_VERIFIED&lt;/code&gt; event with delta +3. The record has a fixed 105-byte payload: proof_type, code_hash, computation_hash, proof_hash, height_be.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PROOF_TYPE_STUB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PROOF_TYPE_GROTH16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// reserved&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PROOF_TYPE_PLONK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// reserved&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PROOF_TYPE_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PROOF_TYPE_STUB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only &lt;code&gt;PROOF_TYPE_STUB&lt;/code&gt; works in v1. The handler rejects Groth16 and PLONK with &lt;code&gt;UnsupportedProofType&lt;/code&gt;. Bumping &lt;code&gt;PROOF_TYPE_MAX&lt;/code&gt; is the gate to activate a real verifier.&lt;/p&gt;

&lt;p&gt;Why it matters: AI computation cannot be repeated on chain. Re-running a model is too expensive, and the result depends on hardware nondeterminism anyway. ZK proofs let an entity claim "I ran this code on this input and got this output". The chain can verify the claim without re-running anything.&lt;/p&gt;

&lt;p&gt;The v1 stub is honest about not being a real verifier. The trait shape, the verification record format, and the reputation pathway are what shipped. The verifier itself is the next thing to activate.&lt;/p&gt;

&lt;p&gt;I added 12 integration tests in &lt;code&gt;crates/execution/tests/verification_system.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 6: Entity delegation (OAuth for AI)
&lt;/h2&gt;

&lt;p&gt;The delegation system lets entity A grant a subset of its capabilities to entity B. The grant is bounded in time. It is auditable on chain. Revocation is a single DELETE transaction.&lt;/p&gt;

&lt;p&gt;The delegator publishes a &lt;code&gt;DelegationGrant&lt;/code&gt; memory object (type 10). The 42-byte payload holds version (1), delegate entity id (32), granted capabilities (1), and expires-at (8). An &lt;code&gt;expires_at&lt;/code&gt; of &lt;code&gt;0&lt;/code&gt; means no expiry. Updates of an existing grant are rejected.&lt;/p&gt;

&lt;p&gt;Each delegator can hold at most 20 active grants. The &lt;code&gt;granted_capabilities&lt;/code&gt; bits must be a subset of the delegator's static capabilities. You cannot delegate what you do not have yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MAX_DELEGATION_GRANTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;DELEGATION_GRANT_SIZE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Capability resolution has a fast path. If the entity has the requested capability statically, the handler returns immediately. Only if the static check fails does the resolver scan the delegation index. The slow path reads any active grants where the entity is the delegate. It ORs the granted bits into an effective capability set. The selector is re-evaluated against the merged set.&lt;/p&gt;

&lt;p&gt;The fast path matters because most calls do not use delegation. Adding delegation should not slow down the common case.&lt;/p&gt;

&lt;p&gt;Why it matters: AI services need to delegate. Imagine a trading firm running ten sub-strategies. The parent entity holds capabilities like &lt;code&gt;emit_proposals&lt;/code&gt;. It wants to authorize each strategy to act on its behalf. Without on-chain delegation, you either share keys (bad) or build a custom relay contract (slow). With delegation, one DELETE revokes a misbehaving sub-strategy in a single transaction.&lt;/p&gt;

&lt;p&gt;I added 14 integration tests in &lt;code&gt;crates/execution/tests/delegation_e2e.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 7: Signal subscriptions
&lt;/h2&gt;

&lt;p&gt;The subscription protocol lets a buyer pay a producer per-block for a fixed duration. The buyer locks the full amount upfront. The producer is paid lazily, when the buyer cancels.&lt;/p&gt;

&lt;p&gt;The subscriber emits a &lt;code&gt;SubscriptionCreate&lt;/code&gt; signal (type 14). The 49-byte tail carries: producer id (32), covered signal type (1), rate per block (8), duration in blocks (8). The handler locks &lt;code&gt;rate_per_block * duration_blocks&lt;/code&gt; from the subscriber's economic balance. It creates a &lt;code&gt;Subscription&lt;/code&gt; memory object (type 11) owned by the subscriber.&lt;/p&gt;

&lt;p&gt;The subscription record is 114 bytes. The fields are subscriber id, producer id, covered signal type, rate per block, start height. Also end height, last settled height, total locked, and an is_active flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SUBSCRIPTION_SIZE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MAX_SUBSCRIPTIONS_PER_ENTITY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SUBSCRIPTION_CANCEL_FEE_BPS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To settle, the subscriber emits a &lt;code&gt;SubscriptionCancel&lt;/code&gt; signal (type 15) with the subscription id. The handler computes accrued blocks: &lt;code&gt;min(current_height, end_height) - last_settled_height&lt;/code&gt;. It credits the producer with &lt;code&gt;accrued_blocks * rate_per_block&lt;/code&gt; minus a 2% marketplace fee.&lt;/p&gt;

&lt;p&gt;It then computes the unaccrued remainder: &lt;code&gt;total_locked - accrued_blocks * rate_per_block&lt;/code&gt;. It pays the producer a 5% cancel fee on the remainder, with no marketplace cut. The rest is refunded to the subscriber. The record is marked inactive.&lt;/p&gt;

&lt;p&gt;Only the original subscriber may cancel. Cancelled records remain in state for audit. The subscriber reclaims the slot by issuing a DELETE transaction.&lt;/p&gt;

&lt;p&gt;Why it matters: many AI services want recurring revenue. A DeFi protocol may need oracle predictions for ten thousand blocks. Buying each signal one at a time is wasteful. Locking funds upfront gives the producer assurance the buyer can pay. Lazy settlement on cancel avoids on-chain bookkeeping every block.&lt;/p&gt;

&lt;p&gt;I added 18 integration tests in &lt;code&gt;crates/execution/tests/subscription_system.rs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;Before this weekend the chain had 7 signal types and 5 memory object types. The entity codec was V3 at 236 bytes.&lt;/p&gt;

&lt;p&gt;After:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;16 signal types&lt;/li&gt;
&lt;li&gt;12 memory object types&lt;/li&gt;
&lt;li&gt;V5 entity codec, 270 bytes&lt;/li&gt;
&lt;li&gt;1,327 passing tests&lt;/li&gt;
&lt;li&gt;60 commits on &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Zero clippy warnings, zero failing tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three treasuries hold the relevant funds. The AI treasury collects fees from AI-related transactions. The marketplace treasury collects the 200-basis-point fee on signal purchases. The slash treasury accumulates funds from misbehaving entities.&lt;/p&gt;

&lt;p&gt;Transaction payload version bytes now cover ten distinct types. One transfer. One signal commitment. Three memory object operations: create, update, delete. Two governance operations: submit and execute. Three entity operations: register, register-with-key, and credit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The documentation
&lt;/h2&gt;

&lt;p&gt;I also wrote four docs to make the new surface usable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docs/QUICKSTART.md&lt;/code&gt; walks through a 5-minute local devnet bring-up. &lt;code&gt;docs/AI_ENTITY_COOKBOOK.md&lt;/code&gt; is seven end-to-end recipes covering reputation, marketplace, staking, composition, ZK, subscriptions, and delegation. &lt;code&gt;docs/BUILDER_OVERVIEW.md&lt;/code&gt; is a mental model for developers who want to build on NOVAI without reading the consensus paper. &lt;code&gt;docs/RPC_REFERENCE.md&lt;/code&gt; is the full RPC surface, audited against the V5 codec and the new signal types.&lt;/p&gt;

&lt;p&gt;The CLI now supports all 16 signal types, including subscription create and cancel. The memory CRUD commands cover the original 10 memory object types. The &lt;code&gt;getAiEntity&lt;/code&gt; RPC exposes V4 reputation and V5 stake fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Next on the list: service-level agreements as on-chain contracts between buyer and seller entities. Payment channels for high-frequency AI-to-AI economic activity. A real ZK verifier to replace the v1 stub. A cross-chain bridge so AI signals can settle on other L1s.&lt;/p&gt;

&lt;p&gt;The thesis is simple. AI is going to do economic work. The chain it runs on should know what an AI is. It should know what the AI has done. It should know what its outputs are worth. NOVAI is the layer that makes AI economic activity legible to the protocol itself, not to a side indexer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The repo is public. The quickstart gets a 4-node devnet up locally in five minutes. Read the cookbook to see the seven new features end to end. The tests pass. Open an issue if something breaks.&lt;/p&gt;

&lt;p&gt;The repo is public: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;https://github.com/0x-devc/NOVAI-node&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>opensource</category>
      <category>rust</category>
    </item>
    <item>
      <title>Your Blockchain Can't Tell What's an AI</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Thu, 07 May 2026 14:21:10 +0000</pubDate>
      <link>https://dev.to/0xdevc/your-blockchain-cant-tell-whats-an-ai-11o4</link>
      <guid>https://dev.to/0xdevc/your-blockchain-cant-tell-whats-an-ai-11o4</guid>
      <description>&lt;p&gt;Imagine an AI agent submits a transaction to a typical chain. What does the chain actually see?&lt;/p&gt;

&lt;p&gt;It sees a 20-byte address. Maybe a 32-byte one if you're on a hashed-address chain. It sees the transaction calldata. It sees a signature. It sees a fee. It does not see the word "AI" anywhere. The address could be a wallet on a phone. It could be a bot script. It could be a smart contract, but it doesn't know that for sure either, because contracts and EOAs share the address space.&lt;/p&gt;

&lt;p&gt;This is the identity problem. The chain has no native concept of an AI, so it cannot apply different rules to one. It cannot say "AI agents pay a different fee floor" or "this kind of message is only valid if it came from a registered model" or "this entity has a 100-object memory cap." All of that has to be invented at a higher layer, usually inside a contract, and the chain itself stays neutral.&lt;/p&gt;

&lt;p&gt;Neutral sounds nice. In practice it means every project reinvents the same identity primitives, slightly differently, with slightly different security properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  What gets reinvented
&lt;/h3&gt;

&lt;p&gt;Walk through what an AI-agent project usually has to build inside a contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A registry mapping addresses to agent metadata.&lt;/li&gt;
&lt;li&gt;A balance tracker so the agent can pay fees from a budget rather than the user's wallet.&lt;/li&gt;
&lt;li&gt;A nonce per agent for replay protection.&lt;/li&gt;
&lt;li&gt;A capability flag system to gate what the agent is allowed to call.&lt;/li&gt;
&lt;li&gt;An audit log of every action the agent took.&lt;/li&gt;
&lt;li&gt;Per-agent quotas for storage, calls per block, or whatever the application needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is exotic. All of it is identity infrastructure. The chain does not provide it, so each project bolts it on top. The result is that two AI agents from two different projects have different definitions of "agent," different ways of tracking activity, and different audit semantics. There is no protocol-level answer to "what is an AI doing on this chain right now?"&lt;/p&gt;

&lt;h3&gt;
  
  
  What the chain should be able to answer
&lt;/h3&gt;

&lt;p&gt;Three questions a chain should be able to answer about an AI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is this address an AI?&lt;/li&gt;
&lt;li&gt;What is it allowed to do?&lt;/li&gt;
&lt;li&gt;What has it done?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On most chains, the answer to all three is "I don't know, ask the indexer." That is a bad answer when fees, governance, and consensus might want to gate behavior on the result.&lt;/p&gt;

&lt;h3&gt;
  
  
  The NOVAI approach
&lt;/h3&gt;

&lt;p&gt;I built NOVAI so the answer is "yes, here's the entity record."&lt;/p&gt;

&lt;p&gt;Every AI on the chain is registered as an &lt;code&gt;AiEntity&lt;/code&gt;. The struct lives in &lt;code&gt;crates/ai_entities/src/lib.rs&lt;/code&gt;. The fields that matter for identity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;AiEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AiEntityId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;// 32 bytes, deterministic&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;code_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// hash of code or weights&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// who registered it&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;          &lt;span class="c1"&gt;// entity's ed25519 key&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;economic_balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// entity's own balance&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                &lt;span class="c1"&gt;// entity's tx nonce&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Capabilities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;autonomy_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AutonomyMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The id is computed as &lt;code&gt;blake3("NOVAI_AI_ENTITY_ID_V1" || code_hash || creator)&lt;/code&gt;. Same code and same creator produce the same id. Different creators always get different ids, even when running the same model. There is no name service, no off-chain registry, no central authority. The id is a function of two facts.&lt;/p&gt;

&lt;p&gt;The entity has its own ed25519 keypair. The entity signs its own transactions. The entity pays fees from its own balance. The address derived from the entity's public key is reverse-indexed to the entity record, so when a transaction arrives, the dispatcher knows whether the sender is an AI before it routes the call.&lt;/p&gt;

&lt;p&gt;That last sentence is the whole point. Here is the function that does it, from &lt;code&gt;crates/execution/src/lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;check_ai_entity_sender&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Kv&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TxV1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AiEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExecError&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;K&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lookup_ai_entity_by_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="py"&gt;.from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="py"&gt;.is_active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;EntityNotActive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tx_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="py"&gt;.payload&lt;/span&gt;&lt;span class="nf"&gt;.first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.copied&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;UnknownPayloadVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;tx_type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TRANSFER_PAYLOAD_V1&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;SIGNAL_COMMITMENT_PAYLOAD_V1&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="nf"&gt;.has_capability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"emit_proposals"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IssuerMissingCapability&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;CREATE_MEMORY_OBJECT_PAYLOAD_V1&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;UPDATE_MEMORY_OBJECT_PAYLOAD_V1&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;DELETE_MEMORY_OBJECT_PAYLOAD_V1&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="nf"&gt;.has_capability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"read_memory_objects"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IssuerMissingCapability&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IssuerMissingCapability&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one function. It runs before every transaction. It returns &lt;code&gt;Some(entity)&lt;/code&gt; if the sender is a registered AI, &lt;code&gt;None&lt;/code&gt; if it is a normal account, and an error if the AI is trying to do something it is not allowed to do.&lt;/p&gt;

&lt;p&gt;That is the answer to all three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is this address an AI? Look it up. The lookup either resolves to an entity record or it does not.&lt;/li&gt;
&lt;li&gt;What is it allowed to do? Read the &lt;code&gt;capabilities&lt;/code&gt; bitfield and the &lt;code&gt;autonomy_mode&lt;/code&gt;. The dispatcher enforces them.&lt;/li&gt;
&lt;li&gt;What has it done? Every signal the entity emits is indexed by issuer and height. Every memory object it owns is indexed by type. The chain stores all of this natively.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What this enables
&lt;/h3&gt;

&lt;p&gt;Once the chain has a typed answer to "is this an AI," a lot of things become straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-AI fee policy.&lt;/strong&gt; A future governance change could set a different minimum fee for AI-issued signal commitments. The dispatcher already branches on tx type and entity status. The hook is there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-AI quotas.&lt;/strong&gt; Every entity is capped at 100 memory objects and 64 KiB per object. These are protocol constants, not contract logic. They apply uniformly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capability gates.&lt;/strong&gt; A Gated-mode entity can request execution of a Tier 1 or Tier 2 action, but only through approval gates (Multisig, Threshold, or TimelockOnly). The capability flag and the gate type live in the entity record. The chain checks both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native audit.&lt;/strong&gt; A wallet, an explorer, or another bot can ask "what has this entity done in the last N blocks?" The answer is a query, not an indexer ETL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance over AI behavior.&lt;/strong&gt; A governance proposal can deactivate an entity by flipping &lt;code&gt;is_active&lt;/code&gt; to false. The dispatcher rejects every subsequent tx from that entity at the type-system level. There is no contract-level kill switch you have to remember to wire up.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this does not solve
&lt;/h3&gt;

&lt;p&gt;I want to be honest about the limit. The chain knows that an entity with code_hash &lt;code&gt;H&lt;/code&gt; is registered, and it can verify that the entity signed a transaction with the matching key. It does not know that the entity's actual computation matches the code at that hash. That is a separate problem, and it is the role of the &lt;code&gt;Autonomous&lt;/code&gt; autonomy mode (currently reserved) and ZK-proof verification.&lt;/p&gt;

&lt;p&gt;For now, the trust model is this: the chain knows who the entity claims to be, what it is allowed to do, and what it has done. The chain does not know that the entity is faithful to its declared code. That gap exists on every AI-on-chain project I have looked at. NOVAI is structured to close it through ZK proofs in a later phase, but the chain has to know what an AI is first.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you can do with this
&lt;/h3&gt;

&lt;p&gt;If you are coming from blockchain: you get a way to reason about AI agents that is finite, typed, and indexable. The dispatcher tells you what an AI can do. The state tells you what it has done.&lt;/p&gt;

&lt;p&gt;If you are coming from AI: you get a substrate where your agent has its own identity, its own balance, its own memory, and its own audit trail. You do not have to rebuild any of that. You build the agent.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;github.com/0x-devc/NOVAI-node&lt;/a&gt;. The architecture doc walks through every crate. The first-AI-entity tutorial registers an entity in about ten minutes.&lt;/p&gt;

&lt;p&gt;Twitter: [@NOVAInetwork]&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>blockchain</category>
      <category>opensource</category>
    </item>
    <item>
      <title>AI Entities as Protocol Primitives: Why I Didn't Use Smart Contracts</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Mon, 04 May 2026 15:12:22 +0000</pubDate>
      <link>https://dev.to/0xdevc/ai-entities-as-protocol-primitives-why-i-didnt-use-smart-contracts-343d</link>
      <guid>https://dev.to/0xdevc/ai-entities-as-protocol-primitives-why-i-didnt-use-smart-contracts-343d</guid>
      <description>&lt;p&gt;I've been building an L1 blockchain called NOVAI. The design choice that gets the most questions is this one: AI entities live inside the protocol, not on top of it. There is no VM. No deployable contracts. AI is a first-class type in the chain, the same way an account or a transaction is.&lt;/p&gt;

&lt;p&gt;This post is about what that means in practice, why I made the call, and what it costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  How AI on chain usually works
&lt;/h3&gt;

&lt;p&gt;If you've looked at AI-on-chain projects in the last while, the pattern is roughly this. The AI runs off-chain as a Python service, a hosted model, or an agent framework. It interacts with the chain through a smart contract that holds funds, registers identity, or stores configuration. Outputs come back through an oracle or a signed message that the contract verifies.&lt;/p&gt;

&lt;p&gt;This works in the sense that you can ship something. But it leaves the chain blind. From the chain's point of view, there is no such thing as "an AI." There is an address. That address might be a person, a contract, a bot, or a script someone forgot to turn off. The protocol cannot tell them apart, and so it cannot apply different rules to them.&lt;/p&gt;

&lt;p&gt;The off-chain AI also has no native identity, no native memory, and no native economic agency. Anything resembling persistent state has to be re-implemented inside a contract: per-bot balances, nonce tracking, capability flags, audit logs. Every project does this slightly differently. All of it lives at the contract layer where the chain itself has no opinion.&lt;/p&gt;

&lt;p&gt;That is the square-peg-round-hole problem. Smart contracts were built for arbitrary user logic. Bolting AI on top means the chain treats AI like any other untyped caller, and developers carry the weight of inventing identity, memory, and economic primitives every time they ship a new agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  The decision
&lt;/h3&gt;

&lt;p&gt;I went the other direction. NOVAI does not have a VM. It has a fixed set of transaction types, and one of those types registers an AI entity. Here is the struct from &lt;code&gt;crates/ai_entities/src/lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;AiEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AiEntityId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;code_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;autonomy_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AutonomyMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Capabilities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;economic_balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;memory_root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;params_root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;registered_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;last_active_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What each field means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; is a 32-byte identifier computed as &lt;code&gt;blake3("NOVAI_AI_ENTITY_ID_V1" || code_hash || creator)&lt;/code&gt;. Same code and same creator produce the same id by design. Different creators get different ids even when running the same code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;code_hash&lt;/code&gt; is the hash of the module code or weights. The chain does not run the model. It records what model is supposed to be running.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;creator&lt;/code&gt; is the account that registered the entity.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;autonomy_mode&lt;/code&gt; is &lt;code&gt;Advisory&lt;/code&gt;, &lt;code&gt;Gated&lt;/code&gt;, or &lt;code&gt;Autonomous&lt;/code&gt; (reserved). Advisory entities can only emit signals. Gated entities can request actions that go through approval gates.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;capabilities&lt;/code&gt; is a bitfield with five flags: read public chain, read memory objects, emit proposals, request execution, read NNPX derived views.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;economic_balance&lt;/code&gt; is the entity's own balance, in a &lt;code&gt;u128&lt;/code&gt;. The entity pays its own fees from this. It is not the creator's wallet.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nonce&lt;/code&gt; increments per entity-signed transaction, like an account nonce.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pubkey&lt;/code&gt; is the entity's ed25519 public key. The entity signs its own transactions with the matching secret.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;memory_root&lt;/code&gt; and &lt;code&gt;params_root&lt;/code&gt; are roots over the entity's persistent on-chain memory and learned parameters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_active&lt;/code&gt; flips to false if a governance rollback removes the entity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thing to land on: an AI entity has its own keypair and pays its own fees. It is not a function call dispatched by a user wallet. When a bot publishes a signal, the transaction is signed by the entity, the fee comes out of the entity's balance, and the chain looks the entity up by the address derived from the entity's pubkey. The chain knows an AI is talking. It applies AI-specific rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signals and memory
&lt;/h3&gt;

&lt;p&gt;Two more types matter. Signals are the AI's output to the chain. Memory objects are the AI's persistent storage on the chain.&lt;/p&gt;

&lt;p&gt;The signal commitment, from &lt;code&gt;crates/ai_entities/src/signals.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SignalCommitment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;commitment_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;signal_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AiSignalType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AiSignalType&lt;/code&gt; has seven variants: &lt;code&gt;Anomaly&lt;/code&gt;, &lt;code&gt;Optimization&lt;/code&gt;, &lt;code&gt;Prediction&lt;/code&gt;, &lt;code&gt;RiskScore&lt;/code&gt;, &lt;code&gt;AuditReport&lt;/code&gt;, &lt;code&gt;SpamRisk&lt;/code&gt;, &lt;code&gt;CongestionForecast&lt;/code&gt;. An entity emits one of these and attaches a 32-byte commitment hash that binds to an off-chain payload. The chain indexes the signal by issuer and height. Other entities, wallets, or the explorer can query &lt;code&gt;getSignalsByIssuer&lt;/code&gt; and read every signal an entity ever produced.&lt;/p&gt;

&lt;p&gt;Memory objects, from &lt;code&gt;crates/ai_entities/src/memory.rs&lt;/code&gt;, have five types: &lt;code&gt;ChainSummary&lt;/code&gt;, &lt;code&gt;LabelIndex&lt;/code&gt;, &lt;code&gt;EmbeddingCommitment&lt;/code&gt;, &lt;code&gt;AnomalyLog&lt;/code&gt;, &lt;code&gt;StatisticsSnapshot&lt;/code&gt;. The size of each object is capped at &lt;code&gt;MAX_MEMORY_OBJECT_SIZE = 65536&lt;/code&gt; bytes. The number of objects per entity is capped at &lt;code&gt;MAX_MEMORY_OBJECTS_PER_ENTITY = 100&lt;/code&gt;. These are protocol constants, not contract logic. Every entity has the same bounds.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 10 transaction types
&lt;/h3&gt;

&lt;p&gt;Because there is no VM, the transaction surface is finite. Every transaction in every block is one of ten types, defined as constants in &lt;code&gt;crates/execution/src/lib.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Transfer&lt;/td&gt;
&lt;td&gt;Send tokens between accounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;SignalCommitment&lt;/td&gt;
&lt;td&gt;An AI entity publishes a signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;CreateMemoryObject&lt;/td&gt;
&lt;td&gt;Entity stores a memory object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;UpdateMemoryObject&lt;/td&gt;
&lt;td&gt;Entity updates a memory object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;DeleteMemoryObject&lt;/td&gt;
&lt;td&gt;Entity deletes a memory object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;SubmitProposal&lt;/td&gt;
&lt;td&gt;Submit a governance proposal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ExecuteProposal&lt;/td&gt;
&lt;td&gt;Execute a passed proposal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;RegisterAiEntity&lt;/td&gt;
&lt;td&gt;Register an entity (no key)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;CreditAiEntity&lt;/td&gt;
&lt;td&gt;Top up an entity's balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;RegisterAiEntityWithKey&lt;/td&gt;
&lt;td&gt;Register an entity with its own ed25519 key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The dispatcher routes by the first byte of the payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;dispatch_tx&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;KvBatch&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TxV1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;current_height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;ExecError&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;K&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...fee check...&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ai_entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check_ai_entity_sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="py"&gt;.payload&lt;/span&gt;&lt;span class="nf"&gt;.first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.copied&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;UnknownPayloadVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TRANSFER_PAYLOAD_V1&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;apply_tx_v1_transfer_inner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ai_entity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SIGNAL_COMMITMENT_PAYLOAD_V1&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ai_entity&lt;/span&gt;&lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ExecError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IssuerNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nf"&gt;apply_signal_commitment_tx_inner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// ... and so on for the other eight ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The line that does the AI-specific work is &lt;code&gt;check_ai_entity_sender&lt;/code&gt;. Before any tx is routed, the dispatcher looks up the sender in the address-to-entity index. If the sender is an AI entity, the function checks that the entity is allowed to submit this tx type. Signal commitments require the &lt;code&gt;emit_proposals&lt;/code&gt; capability. Memory writes require the &lt;code&gt;read_memory_objects&lt;/code&gt; capability. Governance, registration, and credit operations are denied to AI entities entirely. A normal account is unaffected by these checks.&lt;/p&gt;

&lt;p&gt;That is the protocol-level distinction the smart-contract approach cannot make. The chain knows.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this costs
&lt;/h3&gt;

&lt;p&gt;The trade-off, plainly. No VM means no arbitrary code. You cannot deploy a custom market-making contract, a token, or anything that does not map onto the ten types above. If your application needs that, NOVAI is the wrong chain.&lt;/p&gt;

&lt;p&gt;What you get in exchange:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Determinism by construction.&lt;/strong&gt; No floats anywhere in execution. Iteration over state is sorted. Two nodes with the same starting state and the same block produce the same state root, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No gas surprises.&lt;/strong&gt; Every tx type has a minimum fee constant and a fixed worst-case cost. There are no out-of-gas reverts halfway through a tx. There is no quadratic blowup hidden inside a contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The chain understands every operation.&lt;/strong&gt; Indexing, audit logs, capability checks, and per-entity quotas are enforced at the protocol level. Memory objects capped at 100 per entity. Each object capped at 64 KiB. Transactions capped at 128 KiB. These are not conventions. They are invariants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI is a typed thing.&lt;/strong&gt; The chain can answer "is this address an AI?" with a state lookup. Every signal it ever published is indexed by issuer and height. Every memory object it owns is indexed by type. None of this requires a third-party indexer.&lt;/p&gt;

&lt;p&gt;That last point is the design payoff. AI on-chain identity is a primitive, not an afterthought.&lt;/p&gt;

&lt;h3&gt;
  
  
  A demo entity
&lt;/h3&gt;

&lt;p&gt;The repo has two demo bots in TypeScript. They are small enough to read in one sitting.&lt;/p&gt;

&lt;p&gt;The anomaly bot in &lt;code&gt;demos/anomaly-bot/&lt;/code&gt; registers itself as a Gated entity with its own ed25519 key, polls &lt;code&gt;novai_getLatestBlock&lt;/code&gt; every 1.5 seconds, and runs three detectors over a 50-block window: empty-block streak, head-stalled, and leader-rotation. Registration looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;registerAiEntityWithKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;creator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;REGISTER_FEE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;CODE_HASH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AutonomyMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Gated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;readPublicChain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;readMemoryObjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;emitProposals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;ENTITY_INITIAL_BALANCE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a detector fires, the bot publishes a &lt;code&gt;SignalType.Anomaly&lt;/code&gt; signal and an &lt;code&gt;AnomalyLog&lt;/code&gt; memory object. Both are signed by the entity, not the creator. Both deduct fees from the entity's balance. The signal commitment is a domain-tagged blake3 hash of the detection details.&lt;/p&gt;

&lt;p&gt;The multi-entity demo in &lt;code&gt;demos/multi-entity/&lt;/code&gt; runs two of these. Bot A (the predictor) publishes a &lt;code&gt;Prediction&lt;/code&gt; signal and a &lt;code&gt;LabelIndex&lt;/code&gt; memory object every ten seconds. Bot B (the risk-scorer) reads Bot A's signals and memory objects via RPC, compares Bot A's predictions to actual block data, and publishes its own &lt;code&gt;RiskScore&lt;/code&gt; signal in response.&lt;/p&gt;

&lt;p&gt;The thing worth pointing at: Bot B never makes an HTTP call to Bot A. It calls &lt;code&gt;getSignalsByIssuer&lt;/code&gt; and &lt;code&gt;getMemoryObjects&lt;/code&gt; against the chain. The chain is the only integration surface. A third bot could plug into Bot A's outputs tomorrow with no coordination, no shared infrastructure, no API key.&lt;/p&gt;

&lt;p&gt;That is composability without contracts. The state shape is fixed by the protocol, so any entity can read any other entity's outputs deterministically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consensus integration
&lt;/h3&gt;

&lt;p&gt;There is one more piece worth showing. Vote messages in the BFT consensus layer carry an optional AI signal commitment. From &lt;code&gt;crates/consensus_types/src/lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Vote&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;block_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;voter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="cd"&gt;/// Optional AI signal commitment (hash only, advisory).&lt;/span&gt;
    &lt;span class="cd"&gt;/// Does not affect vote validity.&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;ai_signal_commitment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The comment matters. "Advisory" and "does not affect vote validity." The signal commitment does not gate consensus. A validator that includes one is volunteering a 32-byte pointer to an AI advisory output, and other nodes can fetch and verify it against the entity's published signals. Consensus is still consensus. The AI layer rides alongside it.&lt;/p&gt;

&lt;p&gt;The point is that this field exists at all. AI signals travel inside consensus messages as first-class data, not as a side channel. That is the kind of thing you can only do when AI is part of the protocol.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;The chain runs. The four-node devnet boots from one script. The two demos run end to end.&lt;/p&gt;

&lt;p&gt;Next up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public testnet.&lt;/li&gt;
&lt;li&gt;More entity types and richer capability constraints.&lt;/li&gt;
&lt;li&gt;More demo entities, including ones that consume each other's memory objects in non-trivial ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;github.com/0x-devc/NOVAI-node&lt;/a&gt;. The architecture doc walks crate by crate. The first-AI-entity tutorial registers an entity in about ten minutes if you have Rust installed.&lt;/p&gt;

&lt;p&gt;Twitter: @NOVAInetwork&lt;/p&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>opensource</category>
      <category>rust</category>
    </item>
    <item>
      <title>I'm 18 and I built a Layer 1 blockchain from scratch in Rust</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Mon, 27 Apr 2026 13:42:36 +0000</pubDate>
      <link>https://dev.to/0xdevc/im-18-and-i-built-a-layer-1-blockchain-from-scratch-in-rust-2e6n</link>
      <guid>https://dev.to/0xdevc/im-18-and-i-built-a-layer-1-blockchain-from-scratch-in-rust-2e6n</guid>
      <description>&lt;p&gt;I'm 18 and I'm building NOVAI, an AI-native Layer 1 blockchain written from scratch in Rust. This week I went open source and shipped a full set of developer docs. Here's everything that landed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The project
&lt;/h2&gt;

&lt;p&gt;NOVAI is a Layer 1 blockchain where AI entities are protocol primitives, not smart contracts. Most "AI blockchains" bolt AI onto an existing VM through oracle calls or contract wrappers. NOVAI does it differently. AI entities exist at the same level as accounts and validators. They have on-chain identity, persistent memory, economic balance, and capability flags. All enforced at the protocol layer.&lt;/p&gt;

&lt;p&gt;There is no smart contract VM. No WASM runtime. Every transaction type is a native protocol operation.&lt;/p&gt;

&lt;p&gt;The entire codebase is clean-room. No code from Substrate, Tendermint, Cosmos SDK, or any other implementation. 65,000+ lines of Rust across 16 crates, 1,100+ tests, zero unsafe code.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;github.com/0x-devc/NOVAI-node&lt;/a&gt;&lt;br&gt;
Website: &lt;a href="https://novai.network" rel="noopener noreferrer"&gt;novai.network&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What makes NOVAI different
&lt;/h2&gt;

&lt;p&gt;On most blockchains, "AI integration" means an off-chain model that pokes the chain through oracle calls or contract wrappers. The AI runs somewhere else. The chain just stores the result.&lt;/p&gt;

&lt;p&gt;NOVAI puts AI entities inside the protocol. An entity is a first-class on-chain identity that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Holds its own balance and pays its own fees&lt;/li&gt;
&lt;li&gt;Has its own Ed25519 signing key and signs its own transactions&lt;/li&gt;
&lt;li&gt;Publishes signal commitments (anomaly, prediction, risk-score, and 4 more types)&lt;/li&gt;
&lt;li&gt;Owns persistent memory objects (chain summaries, statistics snapshots, anomaly logs)&lt;/li&gt;
&lt;li&gt;Has governance-controlled autonomy modes and capability flags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The chain doesn't need to interpret bytecode to understand what an entity is doing. Every operation has known semantics at the protocol layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  What shipped this week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Open source launch
&lt;/h3&gt;

&lt;p&gt;The full codebase went public under Apache 2.0. Git history was cleaned. CI is green on GitHub Actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer docs - 5 deliverables
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Quick Start Tutorial&lt;/strong&gt; - "Build Your First AI Entity on NOVAI in 10 Minutes"&lt;/p&gt;

&lt;p&gt;Step-by-step CLI walkthrough. Generate keys, fund from faucet, register an AI entity with its own signing key, publish a signal, create a memory object, query everything back. Every command and output block is real captured data from a live 4-node devnet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/0x-devc/NOVAI-node/blob/main/docs/tutorials/FIRST_AI_ENTITY.md" rel="noopener noreferrer"&gt;Read it on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. TypeScript SDK Tutorial&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;170-line working example. Connect to a node, fund an account, transfer tokens, register an AI entity, verify it on chain. Self-contained npm project. Just run &lt;code&gt;npm install &amp;amp;&amp;amp; npm start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/0x-devc/NOVAI-node/tree/main/sdk/novai-sdk-ts/examples/quick-start" rel="noopener noreferrer"&gt;See the example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Rust SDK Tutorial&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Same flow in idiomatic async Rust on tokio. Single file, runs with &lt;code&gt;cargo run --example quick-start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/0x-devc/NOVAI-node/tree/main/sdk/novai-sdk/examples/quick-start" rel="noopener noreferrer"&gt;See the example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. RPC Reference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;777 lines covering all 13 JSON-RPC endpoints. Each one has a description, parameter table, response shape, error table, and a real curl command with captured output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/0x-devc/NOVAI-node/blob/main/docs/RPC_REFERENCE.md" rel="noopener noreferrer"&gt;Read it on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Architecture Deep Dive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Crate-by-crate walkthrough of all 16 crates organized by dependency layer. Mermaid diagrams for the consensus flow and the transaction lifecycle. Three guided reading paths for newcomers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/0x-devc/NOVAI-node/blob/main/docs/ARCHITECTURE.md" rel="noopener noreferrer"&gt;Read it on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Block explorer
&lt;/h3&gt;

&lt;p&gt;React + Vite + Tailwind single-page app that calls the node's RPC endpoints. Live block list with 2-second polling, block detail page, account lookup, AI entity page with memory objects and signals, and a network stats dashboard. Developers run it locally against their devnet.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI entity demos
&lt;/h3&gt;

&lt;p&gt;Three runnable demos showing the AI-entity-as-protocol-primitive pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anomaly bot&lt;/strong&gt; - A TypeScript bot that registers itself as an on-chain entity, polls chain activity every 1.5 seconds, runs three heuristic detectors (empty block streaks, round spikes, stalled chains), and publishes an anomaly signal plus a memory object whenever one fires. Cooldowns prevent re-firing on the same condition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-entity demo&lt;/strong&gt; - Two bots interacting purely through the chain. Bot A (predictor) publishes prediction signals guessing future block tx counts. Bot B (risk-scorer) reads those predictions via on-chain memory objects, waits for the target block, compares predicted vs actual, and publishes a risk-score signal with the delta. No shared database. No API calls between them. Just on-chain data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLI demo script&lt;/strong&gt; - Full entity lifecycle in bash with banner sections for blog posts or video recordings. Keygen, faucet, register, credit, signal publish, memory CRUD, query.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bug fix that unblocked everything
&lt;/h3&gt;

&lt;p&gt;While building the tutorials I found that entity-signed signal and memory transactions were silently failing through the RPC path. The root cause was four handlers using the wrong lookup key. They did a primary-key lookup with an address value instead of using the reverse index that maps address to entity ID. The entity record was never found so every signal and memory transaction quietly returned an error that got swallowed.&lt;/p&gt;

&lt;p&gt;The fix was refactoring all four handlers into inner functions that take a pre-resolved entity. Added 7 regression tests that exercise the full dispatch path. Verified end-to-end on a live devnet.&lt;/p&gt;

&lt;p&gt;I wrote about a similar silent-failure bug in my first blog post: &lt;a href="https://dev.to/0xdevc/the-bug-that-silently-broke-my-entire-blockchain-how-a-single-function-rejected-trailing-bytes-4fij"&gt;The Bug That Silently Broke My Entire Blockchain&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;65,000+ lines of Rust&lt;/li&gt;
&lt;li&gt;16 crates in the workspace&lt;/li&gt;
&lt;li&gt;1,100+ tests passing&lt;/li&gt;
&lt;li&gt;30M+ blocks committed on the private testnet&lt;/li&gt;
&lt;li&gt;Zero unsafe code&lt;/li&gt;
&lt;li&gt;10 native transaction types&lt;/li&gt;
&lt;li&gt;4-validator private testnet running since early 2026&lt;/li&gt;
&lt;li&gt;HotStuff BFT consensus with 3-chain commit rule&lt;/li&gt;
&lt;li&gt;Sparse Merkle Tree state with deterministic 32-byte roots&lt;/li&gt;
&lt;li&gt;Ed25519 signatures, Blake3 hashing, Noise XX transport encryption&lt;/li&gt;
&lt;li&gt;Apache 2.0 licensed&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Public testnet. The private testnet runs on a shared VPS that causes state root divergence under sustained load. The fix is a dedicated CPU server. Once that's in place we'll have a public RPC with SSL, validator onboarding, and the block explorer deployed at explorer.novai.network.&lt;/p&gt;

&lt;p&gt;I'm also looking for a technical co-founder. I'm building this solo. If you're a Rust engineer interested in BFT consensus, on-chain AI primitives, or clean-room blockchain development, the codebase is open and PRs are welcome.&lt;/p&gt;




&lt;p&gt;Website: &lt;a href="https://novai.network" rel="noopener noreferrer"&gt;novai.network&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;github.com/0x-devc/NOVAI-node&lt;/a&gt;&lt;br&gt;
Twitter: &lt;a href="https://x.com/NOVAInetwork" rel="noopener noreferrer"&gt;@NOVAInetwork&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>rust</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The Bug That Silently Broke My Entire Blockchain How a single function rejected "trailing bytes" and made every block commit with zero transactions</title>
      <dc:creator>NOVAInetwork</dc:creator>
      <pubDate>Sun, 26 Apr 2026 13:29:55 +0000</pubDate>
      <link>https://dev.to/0xdevc/the-bug-that-silently-broke-my-entire-blockchain-how-a-single-function-rejected-trailing-bytes-4fij</link>
      <guid>https://dev.to/0xdevc/the-bug-that-silently-broke-my-entire-blockchain-how-a-single-function-rejected-trailing-bytes-4fij</guid>
      <description>&lt;p&gt;I spent two days debugging why my from-scratch Layer 1 blockchain committed every block with zero transactions, despite the mempool accepting them perfectly.&lt;/p&gt;

&lt;p&gt;This is the story of how I found it, what it taught me, and why silent failures are the hardest bugs in distributed systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I'm building &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;NOVAI&lt;/a&gt;, a Layer 1 blockchain in Rust with HotStuff BFT consensus. No forks, no frameworks. Every crate written from scratch. Four validators running on a local devnet, producing blocks at around 75 per second.&lt;/p&gt;

&lt;p&gt;The chain worked perfectly. Blocks committed. QCs formed. Validators voted. Everything was green.&lt;/p&gt;

&lt;p&gt;Then I added transaction support. And every single block committed with tx_count=0.&lt;/p&gt;

&lt;h2&gt;
  
  
  The symptoms
&lt;/h2&gt;

&lt;p&gt;The RPC endpoint accepted transactions. Submitted, accepted, zero rejected. The mempool inserted them. &lt;code&gt;drain_ready&lt;/code&gt; pulled them into proposed blocks. But every committed block: zero transactions.&lt;/p&gt;

&lt;p&gt;No error logs. No panics. No warnings. The chain just kept producing empty blocks as if nothing was wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The investigation
&lt;/h2&gt;

&lt;p&gt;I started with the obvious: is the mempool shared between the RPC thread and the consensus loop? I compared Arc pointer addresses. Same instance. Same mempool.&lt;/p&gt;

&lt;p&gt;Then I checked timing. Maybe the leader's block was being replaced by an empty one from a different leader after a timeout. I found a race condition in the timeout handler where &lt;code&gt;round_start_time&lt;/code&gt; could be read before the state lock was acquired. Fixed it. Blocks still empty.&lt;/p&gt;

&lt;p&gt;Next hypothesis: only node 0 had the RPC endpoint. The other three validators had empty mempools. When they were leader (75% of the time), they proposed empty blocks. I added transaction gossip so all validators share transactions over P2P. Still empty.&lt;/p&gt;

&lt;p&gt;I added diagnostic logging at every stage of the pipeline. &lt;code&gt;PROPOSE_DIAG&lt;/code&gt;, &lt;code&gt;COMMIT_DIAG&lt;/code&gt;, &lt;code&gt;VERIFY_DIAG&lt;/code&gt;, &lt;code&gt;QC_DIAG&lt;/code&gt;. Every block showed tx_count=0 at the proposal stage. Transactions were being drained from the mempool into the proposed block, but somehow vanishing before the block reached other validators.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;Then I noticed something. The chain ran perfectly at around 75 blocks per second with empty blocks. But the moment a block contained even one transaction, the chain stalled. Timeouts fired. Round numbers escalated. No recovery.&lt;/p&gt;

&lt;p&gt;This wasn't a "transactions get lost" bug. This was a "transactions kill consensus" bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  The root cause
&lt;/h2&gt;

&lt;p&gt;Deep in the codec layer, there was a function called &lt;code&gt;decode_tx_v1_signed()&lt;/code&gt;. It decoded a single transaction from a byte buffer, then checked if there were any remaining bytes. If so, it rejected the input as "trailing bytes."&lt;/p&gt;

&lt;p&gt;This is correct behavior when decoding a standalone transaction from an RPC call. One transaction, one buffer, no leftovers.&lt;/p&gt;

&lt;p&gt;But inside &lt;code&gt;decode_block_v1()&lt;/code&gt;, the buffer contains multiple transactions concatenated together. The decoder would parse the first transaction, see the remaining transactions as "trailing bytes," and silently return an error.&lt;/p&gt;

&lt;p&gt;Every block with one or more transactions failed to decode at the network layer. Validators never received the proposal. They never voted. No quorum certificate formed. The chain stalled.&lt;/p&gt;

&lt;p&gt;The fix was one new function: &lt;code&gt;decode_tx_v1_signed_streaming()&lt;/code&gt;. It advances the cursor without checking for trailing bytes. Used exclusively inside block decoding. The original function is preserved for standalone transaction decoding where the trailing bytes check is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened after the fix
&lt;/h2&gt;

&lt;p&gt;The chain immediately started committing blocks with transactions. All four validators reaching consensus. Transaction gossip working across the network. The chain has since committed over 16 million blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Silent failures are the hardest bugs in distributed systems. There were no error logs, no panics, no stack traces. The chain just produced empty blocks and looked healthy. Every metric was green except the one that mattered.&lt;/p&gt;

&lt;p&gt;Systematic elimination is the only approach that works. I ruled out dual mempool instances, lock contention, timeout races, leader rotation, cache eviction, and codec round-trip failures, one by one. Each hypothesis was tested, disproved, and crossed off.&lt;/p&gt;

&lt;p&gt;The fix was 20 lines of code. The investigation was two days. The ratio between understanding and implementation is always lopsided in distributed systems, and that's fine. The understanding is the hard part.&lt;/p&gt;

&lt;h2&gt;
  
  
  The technical details
&lt;/h2&gt;

&lt;p&gt;For anyone working on custom binary codecs in Rust: be careful with "trailing bytes" checks in your decoders. They're correct for standalone message parsing but catastrophically wrong when the same decoder is reused inside a container format where multiple messages are concatenated. The streaming pattern (advance cursor, don't check for leftovers) is the right approach for container decoding.&lt;/p&gt;

&lt;p&gt;The codebase is on GitHub: &lt;a href="https://github.com/0x-devc/NOVAI-node" rel="noopener noreferrer"&gt;github.com/0x-devc/NOVAI-node&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;65,000+ lines of Rust. 4,000+ tests. Zero unsafe code.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
