High-Performance Modular Blockchain Framework Powered by Kotlin with Proof of Stake
Kokonut is a lightweight and scalable blockchain framework written in Kotlin. Designed for educational and research purposes, it implements Proof of Stake (PoS) consensus with core blockchain principles (Staking, Validation, Wallets) using an intuitive multi-module architecture.
This project is organized as a Gradle multi-module project, where each module plays a distinct role in the blockchain network.
:library (Core Framework)Contains the core blockchain framework with a clean, minimal architecture:
library/src/main/kotlin/kokonut/
βββ core/ # Core blockchain data structures
β βββ Block.kt
β βββ BlockChain.kt
β βββ Data.kt
β βββ FuelNodeInfo.kt
β βββ NetworkRules.kt
β βββ NodeHandshake.kt
β βββ Policy.kt
β βββ Transaction.kt
β βββ Validator.kt
β βββ ValidatorOnboardingInfo.kt
βββ state/ # State management
β βββ NodeState.kt
β βββ ValidatorState.kt
βββ util/ # Utilities and API
βββ API.kt
βββ FullNode.kt
βββ GenesisGenerator.kt
βββ NodeType.kt
βββ Router.kt
βββ SQLite.kt
βββ Utility.kt
βββ ValidatorPool.kt
βββ ValidatorSession.kt
βββ Wallet.kt
core/: Core blockchain entities (Block, BlockChain, Transaction, Validator)state/: Node and validator state enumsutil/: HTTP API, routing, utilities, and wallet management:fuelnode (Bootstrap Node)Acts as the network entry point and provides Node Discovery services.
:fullnode (Main Node)The core node that maintains and operates the actual blockchain network.
:lightnode (Wallet Client)A desktop wallet application for users (built with Compose Desktop).
.pem key files./stakeLock if needed before validationRequirement: Kokonut requires Java 17 or higher.
Run the following command in the project root to build the entire project.
# Windows
./gradlew.bat build
# Mac/Linux
./gradlew build
Each node can be run individually. The recommended order is Fuel Node β Full Node (Multiple) β Light Node.
./gradlew.bat :fuelnode:run
http://[::]:80 (Dual Stack IPv4/IPv6) by default.http://[2001:db8::1]:80).:: (dual stack), IPv4-only clients may experience limitations in P2P scenarios../gradlew.bat :fullnode:run
Full Nodes must join an existing network:
KOKONUT_PEER to a reachable Fuel Node or peer Full Node (e.g., http://<FUEL_NODE_IP>:80).Optional:
KOKONUT_FULLNODE_REWARD_RECEIVER to control where the onboarding reward is credited for the Full Node (defaults to the Full Nodeβs own URL as seen by the server).KOKONUT_ADVERTISE_ADDRESS to the publicly reachable base URL for this Full Node (used as the source address for propagation so other Full Nodes can pull your chain correctly).KOKONUT_TREASURY_ADDRESS to override the treasury address (default: KOKONUT_TREASURY).KOKONUT_STAKE_VAULT_ADDRESS to override the stake vault address (default: KOKONUT_STAKE_VAULT)../gradlew.bat :lightnode:run
.pem key files to log in.Full Nodes and the Fuel Node interact via HTTP APIs.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Node status and information dashboard (HTML) |
POST |
/handshake |
Client handshake (returns network info) |
GET |
/getLastBlock |
Get the last block of the current chain |
GET |
/getChain |
Get the entire blockchain data |
GET |
/getBalance?address= |
Get wallet balance for a given address (returns JSON) |
GET |
/isValid |
Check the integrity of the local blockchain |
GET |
/getTotalCurrencyVolume |
Get the total supply of KNT |
GET |
/getReward |
Get the current reward policy value |
GET |
/getValidators |
Get the current validator set |
POST |
/stakeLock |
Lock stake to stakeVault (creates on-chain STAKE_LOCK block) |
POST |
/startValidating |
Register a validator session (requires stake >= minimum) |
POST |
/stopValidating |
Stop validating session |
POST |
/addBlock |
Submit a validated block (network propagation) |
| Method | Endpoint | Description |
|---|---|---|
GET |
/getGenesisBlock |
Download the Genesis Block data |
POST |
/heartbeat |
Full Node heartbeat registration (discovery) |
GET |
/getFullNodes |
Get the list of active Full Nodes |
GET |
/getPolicy |
Get protocol/version policy |
GET |
/getChain |
Get the blockchain data |
On the first successful Light Node connect (POST /handshake from a LIGHT client), the Full Node appends a VALIDATOR_ONBOARDING block to the chain and records two onboarding transactions:
KOKONUT_FULLNODE_REWARD_RECEIVER)These payouts are funded by the treasury (KOKONUT_TREASURY_ADDRESS).
Persistence: This onboarding event is stored in kovault.db (SQLite). If you keep kovault.db via Docker volume mounts, the 1-time rule survives container rebuilds.
To become an active validator, you must lock at least the network minimum stake (currently 1 KNT) to the stakeVault address.
POST /stakeLock, which appends a STAKE_LOCK block containing an on-chain transfer from your validator address to the stakeVault.POST /stakeLock (if needed) before starting validation.POST /stopValidating call creates an UNSTAKE block that returns your deposit from stakeVault to your validator address.Chain Integrity: All blocks maintain strict timestamp consistency between blocks and their embedded transactions, ensuring hash validation integrity across the network.
Note: In the current model, validator stake and rewards are derived from the blockchain history (the chain is the source of truth).
git checkout -b feature/amazing-feature).git commit -m 'Add some amazing feature').git push origin feature/amazing-feature).core/ packageutil/ packagestate/ packagepreviousHash validation and exact index verification in block addition/stopValidating API, syncs chain, and updates balancepreviousHash + index).SLASH transactions to penalize malicious validators.License
This project is licensed under the MIT License. See the LICENSE file for details.
Official Docker images are available on Docker Hub.
volta2030/knt_fuelnodevolta2030/knt_fullnodeTo ensure data persistence (blockchain data, keys), you must mount a volume to /data.
These images set KOKONUT_DATA_DIR=/data, so kovault.db will be created under the mounted /data directory.
The Fuel Node acts as the network bootstrapper.
# -p 80:80 : Bind container port 80 to host port 80
# -v ./data:/data : Persist blockchain data to host's ./data directory
docker run -d \
--name knt_fuelnode \
-p 80:80 \
-v $(pwd)/data_fuel:/data \
volta2030/knt_fuelnode
Full Nodes connect to the network. You can specify a peer to connect to using KOKONUT_PEER.
# -e KOKONUT_PEER : Address of a known node (e.g., Fuel Node or another Full Node)
# -v ./data_full:/data : Use a separate data directory for the Full Node
docker run -d \
--name knt_fullnode \
-p 8080:80 \
-e KOKONUT_PEER="http://<FUEL_NODE_IP>:80" \
-v $(pwd)/data_full:/data \
volta2030/knt_fullnode
Critical Note: Full Nodes MUST configure
KOKONUT_PEERto join an existing network. IfKOKONUT_PEERis omitted or the target peer is unreachable, the Full Node will fail to start (throw an exception). This mechanism prevents accidental network splitting (Split Brain). Only the Fuel Node is allowed to start without a peer to generate the Genesis Block.Note: Replace
<FUEL_NODE_IP>with the actual IP address or domain of your Fuel Node. If running on the same machine, use the hostβs local network IP.