﻿# MeshChainCore

A minimal, modular blockchain micro core written in a single Java file with zero external dependencies.

Its only job is to be the **smallest possible trustworthy kernel**: manage identities, build and sign blocks, elect a server public key by majority vote across a mesh network, and verify chain integrity. Everything else — consensus rules, storage backends, REST APIs, coin rewards, P2P sync — is added by plugging in your own modules.

---

## Background

This core was designed for a **mesh file-storage network** where:

- Multiple HTTP servers each host a set of files named by their SHA-256 hash (e.g. `abc123….jpg`).
- Each server exposes a `/files.txt` manifest and an `/info/<hash>.json` metadata file per stored file.
- The `/info/<hash>.json` carries a `public_key` field identifying the key associated with that file on that server.
- A block is anchored to a specific mesh filename. The block records **two public keys**: the local miner's key and the key that the majority of mesh servers agree upon for that file.

```
Mesh server layout          Local node layout
─────────────────           ─────────────────
/files.txt                  keys/
/files/<sha256>.<ext>         private.key
/info/<sha256>.json           public.key
                            json_blocks/
                              <index>_<hash>.json
                            servers.txt
```

---

## Quick Start

### Requirements

- Java 8 or later
- No build tool required; no external libraries

### Compile

```bash
javac MeshChainCore.java
```

### Run (standalone smoke test)

```bash
# Generates keys, shows chain status, verifies integrity
java MeshChainCore

# Mint a block anchored to a specific mesh file
java MeshChainCore "abc123def456...ab12.jpg"
```

On first run, RSA-2048 keys are generated and saved to `keys/`. On subsequent runs they are loaded automatically.

### servers.txt

Create a `servers.txt` in the working directory with one mesh server per line:

```
https://node1.example.com/mesh/1
https://node2.example.com
http://localhost/meento/1
```

Lines starting with `#` are ignored. Trailing filenames (e.g. `index.php`) are stripped automatically.

---

## Block JSON Schema

Every block is a JSON file stored under `json_blocks/`. The schema is fixed — extend your data through the `metadata` object only.

```json
{
  "v":             1,
  "index":         1,
  "timestamp":     1779307684119,
  "file_ref":      "<sha256>.<ext>",
  "file_hash":     "<sha256 hex, 64 chars>",
  "previous_hash": "<sha256 hex of previous block, or 64 zeros for genesis>",
  "miner_key":     "<Base64 RSA-2048 DER public key>",
  "server_key":    "<Base64 RSA public key elected by majority vote, or empty>",
  "metadata":      {},
  "block_hash":    "<sha256 hex of the canonical string>",
  "signature":     "<Base64 RSA-SHA256 signature over the canonical string>"
}
```

The **canonical string** that is hashed and signed has this exact format (no JSON — order is guaranteed):

```
v=1
index=1
ts=1779307684119
file_ref=abc123….jpg
file_hash=abc123…
prev=0000…0000
miner=MIIBIjAN…
server=
meta={}
```

---

## Architecture

### Core responsibilities (this file, ~520 lines)

| Responsibility | Method |
|---|---|
| Key pair generation / loading | `init()` → `loadOrGenerateKeys()` |
| Block construction and signing | `mintBlock()` + `BlockBuilder` |
| Server public key majority election | `electServerPublicKey()` |
| Chain integrity verification | `verifyChain()` |

### What is deliberately absent (add as modules)

- Proof-of-work / proof-of-storage difficulty loop
- File downloading and caching pipeline
- Coin reward accounting and balance queries
- P2P block propagation and sync
- HTTP server or REST endpoints
- Database or IPFS persistence
- Admin UI or CLI menus

---

## Extension Points

The core exposes three Java interfaces. Provide your own implementations before calling `init()`.

### `BlockStore`

Controls where blocks are persisted.

```java
public interface BlockStore {
    void        save(Block block)   throws Exception;
    List<Block> loadAll()           throws Exception;
    Block       loadLatest()        throws Exception;
    long        count()             throws Exception;
}
```

Default: one JSON file per block under `json_blocks/`, written atomically via tmp-then-rename.

### `ConsensusMechanism`

A gate that must return `true` before any block is built. Replace with proof-of-work, proof-of-storage, or any other rule.

```java
public interface ConsensusMechanism {
    boolean check(String fileRef, List<String> servers) throws Exception;
}
```

Default: always returns `true` (no gate).

### `EventSink`

Receives a JSON string for every domain event (`CORE_INIT`, `BLOCK_ADDED`). Wire it to Spring's `ApplicationEventPublisher`, Kafka, WebSockets, or anything else.

```java
public interface EventSink {
    void emit(String eventJson);
}
```

Default: no-op.

---

## Configuration

All tunables have sensible defaults and can be overridden with setters before calling `init()`.

| Setter | Default | Description |
|---|---|---|
| `setBlocksDir(String)` | `json_blocks` | Directory for block JSON files |
| `setKeysDir(String)` | `keys` | Directory for RSA key files |
| `setServersFile(String)` | `servers.txt` | Path to the mesh server list |
| `setConnectMs(int)` | `8000` | HTTP connection timeout (ms) |
| `setReadMs(int)` | `30000` | HTTP read timeout (ms) |
| `setThreadPool(int)` | `16` | Threads for parallel server polling |
| `setBlockStore(BlockStore)` | File-based | Swap storage backend |
| `setConsensusMechanism(ConsensusMechanism)` | No-op | Swap consensus rule |
| `setEventSink(EventSink)` | No-op | Swap event bus |

---

## Integration Examples

### Plain Java

```java
MeshChainCore core = new MeshChainCore();
core.setConsensusMechanism(new MyProofOfStorageConsensus());
core.init();

// Mint a block
Block b = core.mintBlock("abc123….jpg", "{\"reward\":50}");

// Verify the whole chain
List<String> errors = core.verifyChain();
```

### Spring Boot

```java
@Configuration
public class BlockchainConfig {

    @Bean
    public MeshChainCore meshChainCore(
            EntityManager em,
            ApplicationEventPublisher publisher) throws Exception {

        MeshChainCore core = new MeshChainCore();
        core.setBlockStore(new JpaBlockStore(em));
        core.setConsensusMechanism(new ProofOfStorageConsensus());
        core.setEventSink(json -> publisher.publishEvent(new BlockEvent(json)));
        core.init();
        return core;
    }
}

// In any @Service
@Autowired MeshChainCore core;

public Block mine(String fileRef) throws Exception {
    return core.mintBlock(fileRef, null);
}
```

### Parsing a block received over the network

```java
String json = receiveFromPeer();
MeshChainCore.Block block = MeshChainCore.parseBlock(json);
```

---

## Security

| Property | Implementation |
|---|---|
| Identity | RSA-2048 key pairs; private key never leaves `keys/private.key` |
| Block signing | `SHA256withRSA` over the canonical string |
| Tamper detection | Block hash covers every field; `previous_hash` links the chain |
| Server key election | Strict majority (> 50 % of responding servers must agree) |
| Network safety | Only `http`/`https` schemes fetched; redirects not followed |
| Atomic writes | Blocks written to `.tmp` then renamed; no torn files on crash |
| Input safety | No Java serialisation of untrusted data; hand-rolled JSON extractor |

---

## File Layout After First Run

```
project/
├── MeshChainCore.java
├── servers.txt
├── keys/
│   ├── private.key        ← RSA-2048 PKCS#8, Base64
│   └── public.key         ← RSA-2048 X.509, Base64
└── json_blocks/
    ├── 00000000000000000001_abc123….json
    └── 00000000000000000002_deadbe….json
```

Block filenames are `<20-digit-index>_<fileHash>.json`, so they sort correctly in any file browser.

---

## Modules You Can Add

The interfaces above are the only coupling points. Suggested modules and recommended frameworks:

| Module | Suggested approach |
|---|---|
| Proof-of-storage consensus | Implement `ConsensusMechanism`; reuse the file-download logic from `MeshBlockchain.java` |
| REST API | Spring Boot `@RestController`; inject `MeshChainCore` bean |
| JPA block store | Implement `BlockStore` with a `@Repository` |
| P2P sync | Spring WebFlux WebSocket; call `parseBlock()` on received JSON, then `blockStore.save()` |
| Coin wallet | Listen to `BLOCK_ADDED` events via `EventSink`; tally `metadata.reward` per key |
| Explorer UI | Spring MVC `@Controller`; call `blockStore.loadAll()` and render |
| IPFS storage | Implement `BlockStore`; pin block JSON via the IPFS HTTP API |

---

## Compatibility

- **Java 8+** — no preview features, no records, no var
- **Zero external libraries** — only `java.*`, `javax.crypto.*`
- **Framework-agnostic** — works standalone or inside Spring Boot, Quarkus, Micronaut, etc.