Skip to content

tmpim/noot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Noot

A smart contract network built on top of Krist

Noot is a deterministic state machine that processes transactions from the Krist blockchain to provide smart contract functionality. It enables token creation, minting, burning, and transfers using Krist's transaction metadata system.

Note: This project was developed silently 2 years ago and never released. Given that SwitchCraft 3 has shut down and Krist is less widely used today, this project is being released purely as educational material to demonstrate a smart contract implementation on top of Krist.

What is Krist?

Krist is a virtual currency and economy system that works across servers, originally created for the Minecraft mod ComputerCraft. Krist provides a simple transaction-based blockchain where users can send currency between addresses and attach metadata to transactions.

What is Noot?

Noot extends Krist by interpreting specially-formatted transaction metadata as smart contract operations. It maintains a deterministic state by processing Krist transactions in order, validating operations, and building an immutable chain of state changes.

Think of Noot as a Layer 2 solution for Krist - it uses Krist transactions as its data layer while providing higher-level functionality like custom tokens.

Features

  • Token System: Create, mint, burn, and transfer custom tokens
  • Deterministic State: All nodes processing the same transactions reach identical state
  • Immutable History: Complete audit trail of all operations via journaling
  • Real-time Sync: WebSocket connection to Krist for instant transaction processing
  • Type-Safe: Built with TypeScript and Zod for runtime validation
  • SQLite Storage: Efficient local database with full transaction history

Architecture

Core Components

graph TB
    Krist[Krist Blockchain<br/>Transaction Data Source]

    subgraph NootClient[Noot Client]
        VM[Transaction Processor VM<br/>- Parses CommonMeta format<br/>- Validates operations<br/>- Applies state changes]
        Contracts[Contract System<br/>- Genesis chain initialization<br/>- CreateToken, MintToken, BurnToken<br/>- TransferToken, TransferTokenOwnership<br/>- Journaling state validation]
        DB[SQLite Database<br/>- Chain state snapshots<br/>- Transaction history<br/>- Noot message log]
    end

    Krist -->|WebSocket + HTTP API| VM
    VM --> Contracts
    Contracts --> DB
Loading

State Machine

Noot maintains a ChainState object that contains:

  • Tokens: All created tokens with their metadata and balances
  • Owner: The address that initialized the chain (via Genesis)
  • Genesis: Initial chain configuration
  • Journal: Last processed message metadata for validation

Each transaction is processed through the VM which:

  1. Parses the transaction metadata using CommonMeta format
  2. Validates the operation against current state
  3. Applies state changes using Immer (immutable updates)
  4. Records the new state and journals the operation
  5. Stores everything in SQLite for persistence

Message Format

Noot messages are embedded in Krist transaction metadata using the CommonMeta format:

noot;v=0;n=T;op=CT;tkn=0;nam=MyToken;sym=MTK;dec=1000

All messages include:

  • v: Protocol version
  • n: Network (N=mainnet, T=testnet)
  • op: Operation code

Operations

Genesis (G)

Initializes a new Noot chain. Must be the first operation.

Parameters:

  • msg: Genesis message string

Example:

{
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.GENESIS,
  msg: "NOOT NOOT"
}

Create Token (CT)

Creates a new token with specified properties.

Parameters:

  • tkn: Token identifier (numeric)
  • nam: Token name
  • sym: Token symbol
  • dec: Decimals (for display purposes)

Example:

{
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.CREATE_TOKEN,
  tkn: 0,
  nam: "Noot Token",
  sym: "NOOT",
  dec: 1000
}

Mint Token (MT)

Creates new tokens and assigns them to an address. Only the token owner can mint.

Parameters:

  • tkn: Token identifier
  • dst: Destination address
  • amt: Amount to mint

Example:

{
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.MINT_TOKEN,
  tkn: 0,
  dst: "kxxxxxxxxx",
  amt: 1000
}

Transfer Token (TT)

Transfers tokens between addresses.

Parameters:

  • tkn: Token identifier
  • dst: Destination address
  • amt: Amount to transfer

Example:

{
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.TRANSFER_TOKEN,
  tkn: 0,
  dst: "kyyyyyyyy",
  amt: 100
}

Burn Token (BT)

Permanently destroys tokens from the sender's balance.

Parameters:

  • tkn: Token identifier
  • amt: Amount to burn

Example:

{
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.BURN_TOKEN,
  tkn: 0,
  amt: 50
}

Transfer Token Ownership (TTO)

Transfers ownership of a token to another address. Only the current owner can do this.

Parameters:

  • tkn: Token identifier
  • dst: New owner address

Example:

{
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.TRANSFER_TOKEN_OWNERSHIP,
  tkn: 0,
  dst: "kzzzzzzzz"
}

Flag (F)

A no-op operation that can be used for signaling or testing.

Parameters: None

Installation

# Install dependencies
pnpm install

# Build the project
pnpm build

# Run tests
pnpm test

Usage

Running a Noot Node

# Development mode
pnpm dev

# Production mode
pnpm build
node dist/src/cli.js

Configuration

Create a config.json file in the project root:

{
  "dbPath": "chain.db",
  "network": "T",
  "kristApiUrl": "https://krist.dev",
  "privateKey": "your-krist-private-key",
  "unsafe": false
}

Configuration Options:

  • dbPath: Path to SQLite database file (default: chain.db)
  • network: Network to operate on - N (mainnet) or T (testnet) (default: T)
  • kristApiUrl: Krist API endpoint (optional, uses default if not specified)
  • privateKey: Your Krist private key for posting transactions (optional, read-only without it)
  • unsafe: If true, crashes on invalid transactions instead of skipping them (default: false)
  • startFromTransaction: Transaction ID to start syncing from (optional, see Fast-Forward Mode below)

Fast-Forward Mode

By default, Noot uses fast-forward mode to skip old blockchain history and start from transaction 2739857. This dramatically improves startup time for new instances.

Automatic Fast-Forward:

{
  "dbPath": "chain.db",
  "network": "T"
}
  • Automatically starts from transaction 2739857
  • Fast startup (seconds instead of minutes)
  • Only recent chain data available

Custom Starting Point:

{
  "dbPath": "chain.db",
  "network": "T",
  "startFromTransaction": 2800000
}

Full Historical Sync:

{
  "dbPath": "chain.db",
  "network": "T",
  "startFromTransaction": 0
}
  • Syncs from the beginning of the chain
  • Slower startup but complete history

Programmatic Usage

import { NootClient } from "@tmpim/noot";

// Create and start a client
const client = new NootClient();
await client.start();

// Post a message (requires privateKey in config)
const noot = await client.postMessage({
  v: 0,
  n: NootNetwork.TESTNET,
  op: NootOperation.CREATE_TOKEN,
  tkn: 0,
  nam: "My Token",
  sym: "MTK",
  dec: 1000,
});

console.log("Created noot:", noot);

Database Schema

Noot uses SQLite with Drizzle ORM for data persistence:

Tables

krist_transactions: All Krist transactions

  • Indexed by: from, to, time
  • Stores raw transaction data

noots: Processed Noot messages

  • Indexed by: transaction_id, op, from, to, token, amount
  • Stores parsed message data and state patches

chain_state: Chain state snapshots

  • Stores complete state after each Noot message
  • Includes hash for integrity verification
  • Links to latest transaction and noot

How It Works

Startup Process

  1. Load Configuration: Read config from file or create default
  2. Open Database: Connect to SQLite and run migrations
  3. Seed Database: Initialize with default chain state if empty
  4. Catchup: Fetch and process all transactions since last known state
  5. Connect WebSocket: Subscribe to new transactions in real-time

Transaction Processing

  1. Book Transaction: Store raw Krist transaction in database
  2. Parse Metadata: Extract Noot message using CommonMeta parser
  3. Validate Message: Check message format with Zod schemas
  4. Apply Contract: Execute the appropriate contract function
  5. Journal: Record operation metadata (sequence, timestamp, originator)
  6. Snapshot State: Store new chain state with hash
  7. Persist: Save everything in a database transaction

Determinism Guarantees

  • Sequential Processing: Transactions processed in Krist ID order
  • Immutable State: Immer ensures no accidental mutations
  • Validation: Journaling contract enforces monotonic sequence/timestamp
  • Error Handling: Invalid operations are logged but don't halt the chain
  • State Hashing: Each state snapshot includes SHA-256 hash for verification

Development

Running Tests

# Run all tests
pnpm test

# Run tests in watch mode
pnpm test --watch

# Run specific test file
pnpm test src/client.test.ts

Database Migrations

# Generate migration from schema changes
pnpm generate

# Apply migrations
pnpm up

Technical Details

Dependencies

  • krist: Official Krist JavaScript library for API and WebSocket access
  • drizzle-orm: Type-safe SQL query builder
  • better-sqlite3: Fast SQLite3 bindings
  • zod: Runtime type validation
  • immer: Immutable state updates
  • winston: Logging
  • async-mutex: Concurrency control

Performance Considerations

  • Batch Processing: Transactions processed in batches during catchup
  • Indexed Queries: Database indexes on frequently queried fields
  • Mutex Protection: Catchup routine protected from concurrent execution
  • Efficient Serialization: JSON blobs for complex state objects

Security

  • Validation: All inputs validated with Zod schemas
  • Error Isolation: Invalid transactions don't crash the node (unless unsafe: true)
  • Deterministic Execution: No external dependencies in contract execution

Packages

@tmpim/noot

The core Noot client and smart contract processor.

@tmpim/noot-explorer

A modern blockchain explorer built with React Router. Provides a web interface for viewing chain statistics, transactions, tokens, and sending contract messages with preflight validation.

# Start the explorer
pnpm --filter @tmpim/noot-explorer dev

See packages/explorer/README.md for more details.

Future Enhancements

Potential areas for expansion:

  • Query API: REST/GraphQL API for querying chain state
  • Token Standards: Additional token types (NFTs, etc.)
  • Cross-Chain: Bridge to other Krist-based networks
  • Smart Contract SDK: Framework for custom contract development
  • Multi-Signature: Support for multi-sig token operations

License

MIT

Credits

Created by tmpim

Built on Krist by 3d6 and Lemmmy

About

A smart contract network built on top of Krist

Resources

Stars

Watchers

Forks