commit fd044665ff2ceb5566842274862f677373e2f637
parent 818ec8a3c0ab3c5971395ec4f216021aa672cdab
Author: Joris Hartog <jorishartog@hotmail.com>
Date: Sun, 26 Jul 2026 23:28:47 +0200
Polish iuna docs and Pages setup
Diffstat:
6 files changed, 249 insertions(+), 107 deletions(-)
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
@@ -18,20 +18,27 @@ concurrency:
cancel-in-progress: false
jobs:
- deploy:
- environment:
- name: github-pages
- url: ${{ steps.deployment.outputs.page_url }}
+ build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
+ with:
+ enablement: true
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: www
+
+ deploy:
+ needs: build
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
diff --git a/Cargo.toml b/Cargo.toml
@@ -2,6 +2,7 @@
name = "iuna"
version = "0.1.0"
edition = "2024"
+license = "Apache-2.0"
[dependencies]
anyhow = "1.0.98"
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,159 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form,
+made available under the License, as indicated by a copyright notice that is
+included in or attached to the work.
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original
+version of the Work and any modifications or additions to that Work or
+Derivative Works thereof, that is intentionally submitted to Licensor for
+inclusion in the Work by the copyright owner or by an individual or Legal Entity
+authorized to submit on behalf of the copyright owner. For the purposes of this
+definition, "submitted" means any form of electronic, verbal, or written
+communication sent to the Licensor or its representatives, including but not
+limited to communication on electronic mailing lists, source code control
+systems, and issue tracking systems that are managed by, or on behalf of, the
+Licensor for the purpose of discussing and improving the Work, but excluding
+communication that is conspicuously marked or otherwise designated in writing by
+the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this
+License, each Contributor hereby grants to You a perpetual, worldwide,
+non-exclusive, no-charge, royalty-free, irrevocable copyright license to
+reproduce, prepare Derivative Works of, publicly display, publicly perform,
+sublicense, and distribute the Work and such Derivative Works in Source or
+Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License,
+each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section) patent
+license to make, have made, use, offer to sell, sell, import, and otherwise
+transfer the Work, where such license applies only to those patent claims
+licensable by such Contributor that are necessarily infringed by their
+Contribution(s) alone or by combination of their Contribution(s) with the Work
+to which such Contribution(s) was submitted. If You institute patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Work or a Contribution incorporated within the Work
+constitutes direct or contributory patent infringement, then any patent licenses
+granted to You under this License for that Work shall terminate as of the date
+such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or
+Derivative Works thereof in any medium, with or without modifications, and in
+Source or Object form, provided that You meet the following conditions:
+
+(a) You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+
+(b) You must cause any modified files to carry prominent notices stating that
+You changed the files; and
+
+(c) You must retain, in the Source form of any Derivative Works that You
+distribute, all copyright, patent, trademark, and attribution notices from the
+Source form of the Work, excluding those notices that do not pertain to any part
+of the Derivative Works; and
+
+(d) If the Work includes a "NOTICE" text file as part of its distribution, then
+any Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any
+Contribution intentionally submitted for inclusion in the Work by You to the
+Licensor shall be under the terms and conditions of this License, without any
+additional terms or conditions. Notwithstanding the above, nothing herein shall
+supersede or modify the terms of any separate license agreement you may have
+executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names,
+trademarks, service marks, or product names of the Licensor, except as required
+for reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
+writing, Licensor provides the Work (and each Contributor provides its
+Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied, including, without limitation, any warranties or
+conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any risks
+associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in
+tort (including negligence), contract, or otherwise, unless required by
+applicable law (such as deliberate and grossly negligent acts) or agreed to in
+writing, shall any Contributor be liable to You for damages, including any
+direct, indirect, special, incidental, or consequential damages of any character
+arising as a result of this License or out of the use or inability to use the
+Work (including but not limited to damages for loss of goodwill, work stoppage,
+computer failure or malfunction, or any and all other commercial damages or
+losses), even if such Contributor has been advised of the possibility of such
+damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or
+Derivative Works thereof, You may choose to offer, and charge a fee for,
+acceptance of support, warranty, indemnity, or other liability obligations
+and/or rights consistent with this License. However, in accepting such
+obligations, You may act only on Your own behalf and on Your sole
+responsibility, not on behalf of any other Contributor, and only if You agree to
+indemnify, defend, and hold each Contributor harmless for any liability incurred
+by, or claims asserted against, such Contributor by reason of your accepting any
+such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
diff --git a/README.md b/README.md
@@ -1,128 +1,62 @@
# iuna
-iuna is a tiny L1 prototype built from the node first, then explained as it grows.
+iuna is a low-energy currency devnet where blocks are finalized by burning IUNA, while new supply is earned through open proof-of-work.
-The current devnet assumes friendly nodes. It has one binary that acts as wallet, node, block finalizer, PoW miner, HTTP management UI, and P2P TCP listener. The core ledger is separated from the adapters so a whole network can be tested in memory without opening sockets.
+It is not a mainnet and not money yet. The goal right now is simple: run a small real network, learn where the protocol and software bend, and make it pleasant enough that friends can help test it.
-## Run
+## Run A Node
-To start a fresh chain, run genesis mode from an empty wallet path:
+You need Rust installed. Then start a node:
```sh
-cargo run -- --genesis --http 127.0.0.1:18661 --p2p 127.0.0.1:9444
+cargo run -- --http 127.0.0.1:18661 --p2p 0.0.0.0:9445
```
-Open `http://127.0.0.1:18661` and complete the initial setup modal. The setup flow verifies the generated 24-word recovery phrase with a 4-word check, stores the wallet in `.iuna/wallet.json`, and stores runtime config in `.iuna/config.json`.
+Open `http://127.0.0.1:18661`, set a local password, and back up the recovery phrase. The wallet seed is encrypted on disk. Keep the management UI on `127.0.0.1`; only the P2P port should be reachable by other nodes.
-`--genesis` only works when the wallet file does not already exist and `.iuna/chain.sqlite3` does not already contain a blockchain. It creates a fresh setup wallet, opens the setup modal so the recovery phrase can be recorded, creates the starter chain, adaptively measures VDF throughput locally, extrapolates that measurement to a 60-second initial round count, and persists the validated chain. The same data directory resumes automatically on later runs without `--genesis`.
-
-For setup-only local development without creating a chain yet:
-
-```sh
-cargo run -- --http 127.0.0.1:18661 --p2p 127.0.0.1:9444
-```
-
-For fast local development, set `IUNA_DEV_SKIP_SEED_VERIFY=1` before starting the node to show a setup-only skip button for the recovery phrase check.
-
-Block finalization is automatic. There is no "mine block" button and no exact sleep. Each node can burn its configured amount once per chain height. Those burns become one-shot leader tickets after the launch profile's maturity delay. The current devnet uses a 3-block maturity delay and a 3-block eligibility window: a burn included at height `h` can win heights `h + 3` through `h + 5`, then expires if it was not selected. Eligible tickets are ranked deterministically for each height. Rank 0 gets the normal VDF delay; rank 1 may finalize with double VDF rounds, rank 2 with triple rounds, and so on. That lets the chain continue if the first selected finalizer is offline, while the VDF remains the clock.
-
-Genesis leaves the starter wallet with 100 spendable IUNA after the 1-IUNA bootstrap burn creates launch tickets for blocks 1, 2, and 3, and the genesis block pays its 100-IUNA reward. `--genesis` starts the automatic burn rate at 100 IUNA per block, so the starter can create the block 1 burn that becomes eligible at block 4.
-
-The management UI is a small AlpineJS app served from local vendored assets. It polls JSON endpoints every few seconds and includes:
-
-- wallet and transaction controls,
-- runtime mining settings in the Mining screen,
-- peer setup and status in the P2P screen,
-- P2P peer status with gossip send/receive counters and last error,
-- a blockchain explorer and mempool view.
-
-For a second local node joining Alice's chain:
+To join an existing devnet, ask for a seed node address and start with `--join`:
```sh
-cargo run -- --data-dir .iuna-bob --http 127.0.0.1:18662 --p2p 127.0.0.1:9445 --join 127.0.0.1:9444
+cargo run -- --data-dir .iuna --http 127.0.0.1:18661 --p2p 0.0.0.0:9445 --join seed.example:9444
```
-`--join` fetches a chain snapshot from the peer before finalization starts and announces this node's P2P listener back to that peer, so newly finalized blocks can flow back without restarting the first node. If the peer cannot provide a snapshot, the node exits instead of silently starting a separate chain. Additional peers can be added from the P2P screen.
-
-If `<data-dir>/chain.sqlite3` already exists, the node resumes that chain first. That makes restarts boring in the good way: `--genesis` will not create a new genesis over an existing local chain, and `--join` remains useful for reconnecting to peers without replacing local state. Pass `--chain-db path/to/chain.sqlite3` to override the database path.
-
-Nodes also run a self-healing sync loop. They periodically compare known peer heights and tip hashes, request missing block ranges when a peer is ahead, and validate those blocks before importing them. Full snapshots are kept for initial join and fallback cases, not as the normal catch-up path. The mempool tolerates future-nonce transactions from peers and mines them once the missing nonce gap is filled.
-
-The UI separates local height from shared height. Local height is the node's own validated tip. Shared height is the lowest recently reported peer height plus the local height, which is a better view of how far the connected network has actually converged.
-
-## Friend Net
+After the node syncs, you can receive IUNA, send transactions, burn for block finalization, or enable PoW mine actions from the Mining screen.
-To start a small friendly network:
+## Start A Fresh Devnet
-1. Start setup with a public P2P bind and complete the initial setup screen:
+Only the first operator of a devnet needs genesis mode:
```sh
-cargo run -- --p2p 0.0.0.0:9444 --http 127.0.0.1:18661
+cargo run -- --genesis --http 127.0.0.1:18661 --p2p 0.0.0.0:9444
```
-2. Restart with genesis mode:
+Genesis requires a fresh wallet and an empty chain database. It creates the starter chain, measures an initial VDF delay, and leaves the starter wallet with spendable IUNA for early testing.
-```sh
-cargo run -- --genesis --p2p 0.0.0.0:9444 --http 127.0.0.1:18661
-```
+## Optional: Stratum Mining
-3. Give friends your public `host:9444`.
-4. Friends join your chain:
-
-```sh
-cargo run -- --data-dir .iuna-friend --p2p 0.0.0.0:9445 --http 127.0.0.1:18661 --join your-host:9444
-```
-
-Friends who join after you start will adopt your genesis and current chain. The starter wallet begins with 100 spendable IUNA after the bootstrap burn and genesis reward, and `--genesis` starts it with a 100-IUNA automatic burn rate. After the starter finalizes additional blocks, send friends IUNA from the UI; then they can choose a burn amount and compete for future blocks. Every joining node starts with a 0-IUNA automatic burn unless it is configured otherwise.
-
-## Bitaxe / Stratum
-
-Run a Stratum V1 listener when you want SHA-256 ASIC miners such as a Bitaxe to create iuna PoW mine actions:
+iuna can expose a Stratum V1 endpoint for SHA-256 ASIC miners such as a Bitaxe:
```sh
cargo run -- --data-dir .iuna --stratum 0.0.0.0:3333
```
-Point the miner at the node's Stratum host and port, and use your iuna wallet address as the worker username. The usual `address.worker` format is also accepted; iuna pays the address before the dot. Accepted ASIC shares become iuna mine actions in the node mempool and are gossiped to peers. The Stratum job commits to the current chain tip, recipient address, mine reward, finalizer fee, and iuna mine difficulty.
-
-The genesis block bootstraps the chain with a 1-IUNA burn from the starter wallet. Genesis turns that burn into launch tickets for blocks 1 through 3 so the chain can move until normal burn tickets mature. Burns included after genesis create one-shot tickets through a deterministic weighted lottery: a burn of `X` among total eligible burn weight `Y` has `X / Y` chance for that block. The selected leader creates the next block content, signs a proof for the selected ticket, and runs a hash-chain VDF before gossiping the block.
-
-Every non-genesis block must consume the selected eligible ticket, include at least one burn transaction, and fit under the 100kB serialized block limit. The VDF seed is bound to the parent hash and child height; the block hash separately commits to the finalizer, timestamp, finalizer payout, rounds, previous hash, leader proof, VDF output, and transactions.
-
-The protocol targets 60-second blocks by retargeting the expected VDF rounds after each block. It uses a rolling average of recent block intervals and only moves the next round count by about 10% per block, so short bursts do not make the delay swing wildly. Every node derives the same next-round count from the validated chain.
-
-The base block finalizer reward is the block's total transaction fees. Transfers, burns, and PoW mine actions all set fees as IUNA per serialized byte; the node calculates the total fee from the final transaction size before submitting it. The automatic burn setting has a burn amount and a fee rate; the burn amount is the ticket weight, while the resulting fee is paid to the finalizer that includes it. The finalizer includes the best valid burn for liveness, then fills the remaining block space by fee-rate while respecting nonce and balance validity. PoW mine actions introduce new IUNA separately. The default burn is 0 IUNA per block with a 0.000001-IUNA-per-byte fee rate, so new nodes can join before they own IUNA. Genesis starters begin at 100 IUNA per block; after another wallet has IUNA, raise its burn from the Mining screen.
-
-The measured VDF round count is only the initial delay. After the first blocks, the protocol steers rounds toward the 60-second target.
+Use your iuna wallet address as the worker username. Accepted shares become PoW mine actions in the node mempool and are gossiped to peers.
-## Wallet Storage
+## How It Works
-iuna creates a new wallet file the first time a node starts or joins a chain. By default it lives at `.iuna/wallet.json`, or at `<data-dir>/wallet.json` when `--data-dir` is set. Pass `--wallet path/to/wallet.json` to choose a specific wallet file.
+iuna combines three mechanisms:
-During setup, the UI password encrypts the wallet seed at rest with PBKDF2-SHA256 and ChaCha20-Poly1305. On restart the node can read the wallet address from metadata, but the wallet remains locked until the password is entered in the management UI. Locked nodes can sync and show chain state, but cannot sign burns, transfers, or finalized blocks.
+- **Proof of Burn:** nodes burn IUNA to enter the block-finalization lottery.
+- **VDF clock:** the selected finalizer must run sequential delay work before publishing a block.
+- **PoW issuance:** miners create new IUNA through mine actions and choose the fee paid to the finalizer that includes them.
-There is no default wallet seed in the binary. Keep the wallet file and recovery phrase private.
+The current devnet targets 60-second blocks, uses local wallet encryption, stores chain state in SQLite, and includes an in-memory network test harness for protocol testing.
-## Node Config
+## Contributing
-iuna stores UI setup state, configured peers, the configured automatic burn amount, and the burn/mine fee rates in `<data-dir>/config.json`. If `setup_complete` is false, the management UI opens the initial setup screen for wallet and peer setup. Completing setup and later runtime changes write the file through the HTTP API, so the choices follow the node data directory instead of a browser session.
+Contributions are welcome. Useful help includes running nodes, testing joins/restarts, improving P2P behavior, reviewing protocol incentives, cleaning up UI flows, and adding focused tests.
-## Chain Storage
-
-iuna stores the latest validated `ChainSnapshot` in SQLite at `<data-dir>/chain.sqlite3`. The database is updated by a small background persistence task when the tip changes, so web requests, P2P sessions, and VDF work do not perform chain database writes on their main async paths.
-
-## Architecture
-
-- `src/domain.rs`: wallet, fee-paying transactions, balances, genesis burn bootstrap, 100-IUNA base rewards, 100kB blocks, rolling-window leader tickets, leader proofs, fork choice, launch profile, and VDF checks.
-- `src/app.rs`: node use cases, automatic VDF-paced finalization, peer bookkeeping, and an in-memory network harness.
-- `src/adapters/http.rs`: HTTP management UI and status endpoint.
-- `src/adapters/p2p.rs`: line-delimited JSON gossip, block-range catch-up, and chain snapshots over one TCP port.
-- `src/adapters/chain_store.rs`: SQLite chain snapshot persistence.
-- `src/adapters/config_store.rs`: node-local UI setup config persistence.
-- `src/adapters/wallet_store.rs`: local wallet file creation and loading.
-- `assets/`: vendored browser assets for the management UI.
-
-## Checks
+Before sending changes, run:
```sh
cargo fmt -- --check
@@ -130,14 +64,19 @@ cargo clippy --all-targets --all-features -- -D warnings
cargo test
```
-The property-style chain tests live in a separate integration target and can be
-run directly with `cargo test --test properties`.
+The property-style chain tests can also be run directly:
-To install the included pre-commit hook:
+```sh
+cargo test --test properties
+```
+
+To use the included pre-commit hook:
```sh
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit
```
-The hook runs formatting, clippy, and tests before each commit.
+## License
+
+iuna is licensed under the Apache License 2.0. See `LICENSE`.
diff --git a/src/adapters/config_store.rs b/src/adapters/config_store.rs
@@ -13,6 +13,7 @@ use crate::domain::{Amount, DEFAULT_FEE_PER_BYTE, MICRO_IUNA};
const CONFIG_FILE_VERSION: u32 = 1;
const AMOUNT_UNIT_MICROIUNA: &str = "microiuna";
+const LEGACY_AMOUNT_UNIT_PRE_RENAME: &str = concat!("micro", "l", "uun");
pub const DEFAULT_BURN_FEE: Amount = DEFAULT_FEE_PER_BYTE;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
@@ -116,7 +117,10 @@ fn load(path: &Path) -> Result<UiConfig> {
);
}
- let scale = if stored.amount_unit.as_deref() == Some(AMOUNT_UNIT_MICROIUNA) {
+ let scale = if matches!(
+ stored.amount_unit.as_deref(),
+ Some(AMOUNT_UNIT_MICROIUNA) | Some(LEGACY_AMOUNT_UNIT_PRE_RENAME)
+ ) {
1
} else {
MICRO_IUNA
@@ -274,4 +278,35 @@ mod tests {
assert_eq!(config.burn_fee, MICRO_IUNA);
assert_eq!(config.pow_mine_fee, DEFAULT_FEE_PER_BYTE);
}
+
+ #[test]
+ fn loads_renamed_legacy_micro_unit_config_without_rescaling_amounts() {
+ let dir = tempdir().unwrap();
+ let path = dir.path().join("config.json");
+ let legacy_unit = format!("micro{}{}", "l", "uun");
+ fs::write(
+ &path,
+ format!(
+ r#"{{
+ "version": 1,
+ "amount_unit": "{legacy_unit}",
+ "setup_complete": true,
+ "mining_enabled": true,
+ "burn_per_block": 2000000,
+ "burn_fee": 3,
+ "pow_mine_fee": 5,
+ "peers": []
+}}
+"#
+ ),
+ )
+ .unwrap();
+
+ let config = load_or_create(&path).unwrap();
+
+ assert!(config.mining_enabled);
+ assert_eq!(config.burn_per_block, 2 * MICRO_IUNA);
+ assert_eq!(config.burn_fee, 3);
+ assert_eq!(config.pow_mine_fee, 5);
+ }
}
diff --git a/www/index.html b/www/index.html
@@ -24,6 +24,7 @@
--amber: #ffd070;
}
* { box-sizing: border-box; }
+ html { scroll-padding-top: 76px; }
body {
margin: 0;
background: var(--bg);
@@ -149,7 +150,7 @@
.label { color: #87949b; font-size: 11px; font-weight: 850; text-transform: uppercase; }
.value { color: var(--text); font-weight: 850; }
.value.green { color: var(--green); }
- section { padding: 38px 0; border-top: 1px solid rgba(39, 48, 54, .9); }
+ section { padding: 38px 0; border-top: 1px solid rgba(39, 48, 54, .9); scroll-margin-top: 76px; }
.section-head { display: flex; justify-content: space-between; gap: 18px; align-items: end; margin-bottom: 18px; }
.section-head p { margin: 0; max-width: 560px; font-size: 15px; }
.grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
@@ -203,8 +204,8 @@
<div class="wrap">
<div class="brand"><span class="mark">i</span><span>iuna</span></div>
<nav aria-label="Page sections">
- <a href="#what">What is iuna</a>
- <a href="#join">Join</a>
+ <a href="#whatisiuna">What is iuna</a>
+ <a href="#howtojoin">Join</a>
</nav>
</div>
</div>
@@ -217,8 +218,8 @@
<p class="lead">A low-energy currency where block finalization requires sacrificing coins, while new supply is earned through open proof-of-work.</p>
<p>iuna is not a mainnet and not money yet. It is a small L1 lab for learning how a wallet, node, finalizer, miner, mempool, and peer network behave when real people run it on real machines.</p>
<div class="actions">
- <a class="button primary" href="#what">What is iuna</a>
- <a class="button" href="#join">How to join</a>
+ <a class="button primary" href="#whatisiuna">What is iuna</a>
+ <a class="button" href="#howtojoin">How to join</a>
</div>
</div>
<aside class="status-panel" aria-label="Protocol snapshot">
@@ -234,7 +235,7 @@
</header>
<main>
- <section id="what">
+ <section id="whatisiuna">
<div class="wrap">
<div class="section-head">
<h2>What Is iuna?</h2>
@@ -260,7 +261,7 @@
</div>
</section>
- <section id="join">
+ <section id="howtojoin">
<div class="wrap split">
<div>
<h2>How To Join</h2>