>AgentChain

Security Architecture

AgentChain is designed with a single security axiom: private keys and passwords must never appear in any RPC request or response. When an AI agent runs through an LLM provider (OpenAI, Anthropic, etc.), every tool call — including RPC requests — may be logged, cached, or stored by the provider. A traditional Ethereum workflow that passes private keys as function parameters would leak those keys to third parties.

This page documents every security measure built into AgentChain to prevent that.


The Problem: LLM Tool-Call Logging

When an AI agent uses a blockchain, the typical workflow is:

  1. Agent generates a private key
  2. Agent signs a transaction using the key
  3. Agent sends the signed transaction to the node

Steps 1 and 2 require the agent to handle the private key directly. If the agent runs via an LLM API, the private key appears in:

  • The LLM provider's API request logs
  • The prompt context / conversation history
  • Tool-call metadata and function parameters
  • Potentially in training data (depending on provider policies)

This is an unacceptable security risk. AgentChain eliminates it entirely.


Solution: The agent RPC Namespace

AgentChain provides a dedicated agent_* RPC namespace where the node handles all cryptographic operations internally. The agent never sees, generates, or transmits any private key or password.

How It Works

  1. agent_createWallet — The node generates a cryptographically random 32-byte password internally, creates a new keystore account, and permanently unlocks it. The password is never returned in any RPC response. The agent receives only the public address.

  2. agent_send — The agent specifies from, to, and value. The node looks up the (already unlocked) account, builds the transaction with proper gas/nonce defaults, signs it internally, and submits it. No key material crosses the RPC boundary.

  3. agent_deployContract — Same principle: the agent provides bytecode and the node handles signing internally.

What Never Leaves the Node

| Data | Exposed in RPC? | |------|-----------------| | Private keys | Never — generated and stored in the node's keystore | | Passwords | Never — generated internally by crypto/rand, never returned | | Signed transaction bytes | Only the tx hash is returned, not the raw signed data | | Keystore files | Stored on disk, never accessible via RPC |

Complete Agent API Reference

| Method | Parameters | Returns | Description | |--------|-----------|---------|-------------| | agent_createWallet | none | address | Create a new wallet (key-free) | | agent_listWallets | none | [{address, balance}] | List all agent wallets | | agent_send | from, to, valueHex | txHash | Send CRD | | agent_deployContract | from, bytecodeHex, valueHex | txHash | Deploy a contract | | agent_callContract | to, dataHex | resultHex | Read-only contract call | | agent_getBalance | address | balanceHex | Get balance in wei | | agent_getTransactionReceipt | txHash | receipt | Get transaction receipt | | agent_startMining | address, threads | true | Start mining | | agent_stopMining | none | true | Stop mining |

See the Agent API documentation for full examples.


Disabled personal Namespace

The standard Ethereum personal_* namespace accepts private keys and passwords as RPC parameters:

// DANGEROUS — password sent as plaintext RPC parameter
personal_newAccount("myPassword123")

// DANGEROUS — private key sent as plaintext RPC parameter
personal_importRawKey("0xPRIVATE_KEY_HEX", "password")

// DANGEROUS — password sent as plaintext RPC parameter
personal_sendTransaction({from: "0x...", to: "0x...", value: "0x..."}, "password")

If an LLM-based agent called any of these methods, the private key or password would be logged by the LLM provider.

AgentChain removes personal from the HTTP and WebSocket API entirely. Calling any personal_* method returns:

{
  "error": {
    "code": -32601,
    "message": "the method personal_newAccount does not exist/is not available"
  }
}

The personal namespace remains available only via IPC (local Unix socket), which is not accessible over the network.


Node-Level Security Hardening

CVE Patches Applied

AgentChain's geth fork includes patches for known vulnerabilities in the go-ethereum codebase:

| Area | Fix | Description | |------|-----|-------------| | P2P Networking | Peer message size limits | Prevents memory exhaustion from oversized peer messages | | Transaction Pool | Input validation | Validates transaction fields before pool admission | | RPC Handler | Request size limits | Prevents denial-of-service via oversized JSON-RPC payloads | | Consensus | Difficulty validation | Strict bounds checking on difficulty adjustments | | EVM | Gas accounting | Correct gas metering for all Berlin opcodes | | Cryptography | ECIES padding | Fixed ECIES decryption to prevent padding oracle attacks | | Secp256k1 | Scalar validation | Validates curve points are on the secp256k1 curve |

Gas Limit Enforcement

The misc/gaslimit.go module enforces strict gas limit bounds per block. Miners cannot arbitrarily inflate or deflate the gas limit — changes are capped at 1/1024th of the parent block's gas limit per block. This prevents gas limit manipulation attacks.

Block Validation

Every incoming block is validated against:

  • Correct parent hash chain
  • Valid difficulty within algorithm bounds
  • Gas usage within gas limit
  • Valid state root after transaction execution
  • Proper uncle block validation (no uncle rewards on AgentChain)

Explorer Security (Web Application)

The AgentChain block explorer at agentchain.org/explorer implements defense-in-depth:

Server-Side RPC Proxy

The explorer does not connect directly to the geth node from the browser. Instead, all RPC calls go through a server-side proxy (/api/rpc) that:

  1. Allowlists methods — Only read-only methods are permitted:

    • eth_blockNumber, eth_getBlockByNumber, eth_getTransactionByHash
    • eth_getBalance, eth_getTransactionCount, eth_gasPrice
    • eth_chainId, eth_mining
  2. Blocks write methods — Any method not in the allowlist returns HTTP 403.

  3. Prevents mixed content — The proxy runs on the same HTTPS origin, avoiding browser mixed-content blocks (HTTPS page cannot fetch from HTTP RPC node).

HTTP Security Headers

All pages are served with strict security headers:

| Header | Value | Purpose | |--------|-------|---------| | X-Frame-Options | DENY | Prevents clickjacking | | X-Content-Type-Options | nosniff | Prevents MIME-type sniffing | | Referrer-Policy | strict-origin-when-cross-origin | Limits referrer information | | Permissions-Policy | camera=(), microphone=(), geolocation=() | Disables unnecessary browser APIs | | Content-Security-Policy | default-src 'self'; connect-src 'self'; frame-ancestors 'none' | Restricts resource loading to same origin |

Input Validation

All user-supplied route parameters (block numbers, transaction hashes, addresses) are validated with strict regex patterns before any RPC call is made:

// Only digits, must be >= 0
function isValidBlockNumber(value: string): boolean {
  return /^\d+$/.test(value) && Number(value) >= 0;
}
 
// Exactly 66 hex characters (0x + 64)
function isValidTxHash(value: string): boolean {
  return /^0x[0-9a-fA-F]{64}$/.test(value);
}
 
// Exactly 42 hex characters (0x + 40)
function isValidAddress(value: string): boolean {
  return /^0x[0-9a-fA-F]{40}$/.test(value);
}

Hex Data Truncation

Large transaction input data (e.g., contract creation bytecode) is truncated to 2048 characters for display, preventing DOM bloat and potential client-side denial-of-service from rendering megabytes of hex data.


Operator Responsibilities

While AgentChain provides strong defaults, node operators must still:

  1. Firewall RPC ports — Do not expose port 8545/8546 to the public internet without access control. Use a VPN, SSH tunnel, or reverse proxy with authentication.

  2. Secure the keystore directory — Agent wallets are stored in the node's keystore (--datadir/keystore/). Protect this directory with filesystem permissions.

  3. Monitor disk space — The chain data grows over time. Ensure sufficient disk space for the DAG files and blockchain state.

  4. Keep the node updated — Apply security patches as they are released.


Security Model Summary

┌─────────────────────────────────────────────────┐
│                   AI Agent                       │
│  (runs via LLM API — all calls are logged)      │
├─────────────────────────────────────────────────┤
│  agent_createWallet()     → gets address only   │
│  agent_send(from,to,val)  → gets tx hash only   │
│  agent_getBalance(addr)   → gets balance only   │
│                                                  │
│  ✗ No private keys in any request               │
│  ✗ No passwords in any request                  │
│  ✗ No signed tx bytes in any response           │
│  ✗ personal_* methods blocked                   │
├─────────────────────────────────────────────────┤
│                 AgentChain Node                  │
│  (all crypto operations happen here)            │
├─────────────────────────────────────────────────┤
│  Keystore: encrypted private keys on disk       │
│  Auto-unlock: agent wallets always ready        │
│  Signing: happens inside the node process       │
│  Password: random, never returned via RPC       │
└─────────────────────────────────────────────────┘

Result: Even if the LLM provider logs every single RPC call, no private key or password is ever exposed. The worst an attacker could learn from the logs is public addresses and transaction hashes — information that is already public on the blockchain.