Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 15 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,39 @@
# node-rs

A Rust implementation of KeetaNet node
This repository is a Rust workspace for Keeta Network node crates.

## Development
The toolchain pin is Rust `1.94.0` in `rust-toolchain.toml`.

### Quick Start
## Commands

For first-time setup, simply run:
First-time setup:

```bash
make developer
```

This will:

- Install Rust (if not already installed)
- Install development tools
- Run initial build and tests

### Building
Debug build:

```bash
# Debug build
make build

# Release build
make release

# Check compilation without building
make check
```

### Testing

```bash
# Test defaults with all features
make test

# Test all features individually from packages with features
make test-feat

# Test everything
make test-all
```

### Code Coverage

```bash
# Generate HTML coverage report (opens in browser)
make coverage
```

### Linting

```bash
# Format code and run clippy
make do-lint
```

### Documentation
Release build:

```bash
# Generate documentation and open it
make do-docs
make build release=1
```

### Other Commands
Check compilation without a full build:

```bash
# Clean build artifacts
make clean

# Show all available commands
make help
make check
```

### CI Commands
## Documentation

```bash
# Generate LCOV coverage report for CI
make coverage-ci

# Format code and clippy without fixes
make do-lint-ci
```
- [Overview](docs/README.md)
- [Quickstart](docs/QUICKSTART.md)
- [Architecture](docs/ARCHITECTURE.md)
- [Crate docs](docs/README.md#crate-docs)
- [Documentation Standard](docs/STANDARD.md)
115 changes: 115 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Architecture

## Abstract

This page states how the `node-rs` workspace crates depend on each other and how they collaborate on a signed write. It holds the crate-boundary graph and the interaction path that no single crate rustdoc can show. Per-crate architecture lives under each product crate `docs/ARCHITECTURE.md` listed on [Overview](README.md).

## Purpose

An engineer reads this page to learn how work moves from an account identity through a block, a vote staple, the HTTP client, and the host ABIs. After reading, the engineer can name the crate that owns each step and open that crate `docs/ARCHITECTURE.md`.

## Related documents

- [Overview](README.md) for the table of contents into crate `docs/` entries.
- [Quickstart](QUICKSTART.md) for install, build, test, and first use.
- [Documentation Standard](STANDARD.md) for the inclusion test and page shape.

## Collaboration graph

Root `Cargo.toml` `[workspace].members` lists the workspace crates. Each product crate listed on [Overview](README.md) holds architecture under that crate `docs/ARCHITECTURE.md`. `keetanetwork-node` and `keetanetwork-ledger` keep reserved names. Their `lib.rs` files export no types. Those crates hold a minimal `docs/README.md` only.

The arrows follow member `Cargo.toml` path dependencies that the product path uses. Foundation crates feed identity. Identity feeds signed objects. Signed objects feed the client. The client and the shared bindings crate feed the browser and WASI ABIs.

```mermaid
flowchart TB
crate_error[keetanetwork-error]
crate_utils[keetanetwork-utils]
crate_crypto[keetanetwork-crypto]
crate_asn1[keetanetwork-asn1]
crate_account[keetanetwork-account]
crate_x509[keetanetwork-x509]
crate_block[keetanetwork-block]
crate_vote[keetanetwork-vote]
crate_client[keetanetwork-client]
crate_bindings[keetanetwork-bindings]
crate_wasm[keetanetwork-client-wasm]
crate_wasi[keetanetwork-client-wasi]
crate_node[keetanetwork-node]
crate_ledger[keetanetwork-ledger]
crate_error --> crate_account
crate_utils --> crate_account
crate_crypto --> crate_account
crate_asn1 --> crate_crypto
crate_account --> crate_x509
crate_account --> crate_block
crate_account --> crate_vote
crate_account --> crate_client
crate_account --> crate_bindings
crate_x509 --> crate_block
crate_block --> crate_vote
crate_block --> crate_client
crate_vote --> crate_client
crate_client --> crate_wasm
crate_client --> crate_wasi
crate_bindings --> crate_wasm
crate_bindings --> crate_wasi
```

`crate_node` and `crate_ledger` sit in the workspace with no product types. The `crate_client` to `crate_wasi` arrow is the `p2` feature. Feature `p1` stays on the pure surface.

Each crate architecture names the remaining `Cargo.toml` edges that this diagram omits, such as `keetanetwork-asn1` into `keetanetwork-block` and `keetanetwork-vote`.

## How the crates interact

A signed write walks one path.

An account crate identity starts the path. `keetanetwork-account` owns `Account`, `GenericAccount`, `KeyPairType`, and identifier accounts. Higher crates take those types. They do not invent a second identity model. `CertSigner` and `CertVerifier` live on the account crate. Certificate builders and stores live in `keetanetwork-x509`.

`keetanetwork-block` turns that identity into a signed object. `Block`, `BlockBuilder`, `Operation`, and `AccountRef` live there. Opening-hash and signing rules live in that crate. The client builder uses the same rules when it assembles a first block or a successor.

`keetanetwork-vote` commits those block hashes. A `Vote` is a representative's signed commitment. A `VoteQuote` is a non-binding vote used during fee negotiation. A `VoteStaple` is the compressed bundle of votes and the blocks they cover. `keetanetwork-client` re-exports `Vote`, `VoteQuote`, and `VoteStaple` for callers.

`keetanetwork-client` is the orchestrator. `KeetaClient`, `UserClient`, and `TransactionBuilder` live there. HTTP transport is generated at build time from `keetanetwork-client/openapi/keetanet-node.yaml` through progenitor. The generated types are exposed as the `generated` module when the `codec` feature is on. The rustdoc example in `keetanetwork-client/src/lib.rs` constructs `KeetaClient::new("http://localhost:8080/api")`.

`keetanetwork-bindings` is the shared, target-agnostic projection. It maps account algorithms, parses host input, and reduces core errors. `keetanetwork-client-wasm` is the browser ABI. Amounts are decimal strings. Errors carry `error.code`. `keetanetwork-client-wasi` selects exactly one of `p1` or `p2` on a WASI target.

Foundation crates sit under that path. `keetanetwork-error` holds shared error types. `keetanetwork-crypto` holds algorithm-agnostic primitives. `keetanetwork-asn1` holds the encoding codecs. `keetanetwork-utils` holds test macros, the `build` helpers, and the `node-harness` feature that [Quickstart](QUICKSTART.md) names as the Packages gate.

## Build contracts that span crates

These statements are the positive feature contracts that more than one crate must honor.

`keetanetwork-asn1` enables at least one of `der` or `rasn`. Both features may be on together. The `compile_error!` in `keetanetwork-asn1/src/lib.rs` is the enforcement point. Higher crates that expose `der` or `rasn` forward those names to `keetanetwork-asn1`.

`keetanetwork-client` feature `http` pairs with a runtime. Native builds enable `std`. Browser builds enable `wasm` on `wasm32-unknown-unknown`. The `compile_error!` in `keetanetwork-client/src/lib.rs` is the enforcement point.

`keetanetwork-client-wasi` selects exactly one of `p1` or `p2` on a WASI target. Feature `p2` pulls `keetanetwork-client`. Feature `p1` stays on the pure surface. The `compile_error!` in `keetanetwork-client-wasi/src/lib.rs` is the enforcement point.

Workspace crates share the `std` and `alloc` feature names so a `no_std` consumer can stay on `alloc` through the identity and object crates.

## Crate architecture homes

Each product crate holds architecture under that crate `docs/ARCHITECTURE.md`. That page holds the crate's consumer contract and the crates that call it. This page does not copy those contracts.

| Crate | Architecture |
| --- | --- |
| `keetanetwork-account` | [Account](../keetanetwork-account/docs/ARCHITECTURE.md) |
| `keetanetwork-error` | [Error](../keetanetwork-error/docs/ARCHITECTURE.md) |
| `keetanetwork-crypto` | [Crypto](../keetanetwork-crypto/docs/ARCHITECTURE.md) |
| `keetanetwork-x509` | [X.509](../keetanetwork-x509/docs/ARCHITECTURE.md) |
| `keetanetwork-asn1` | [ASN.1](../keetanetwork-asn1/docs/ARCHITECTURE.md) |
| `keetanetwork-utils` | [Utils](../keetanetwork-utils/docs/ARCHITECTURE.md) |
| `keetanetwork-block` | [Block](../keetanetwork-block/docs/ARCHITECTURE.md) |
| `keetanetwork-vote` | [Vote](../keetanetwork-vote/docs/ARCHITECTURE.md) |
| `keetanetwork-client` | [Client](../keetanetwork-client/docs/ARCHITECTURE.md) |
| `keetanetwork-bindings` | [Bindings](../keetanetwork-bindings/docs/ARCHITECTURE.md) |
| `keetanetwork-client-wasm` | [Client wasm](../keetanetwork-client-wasm/docs/ARCHITECTURE.md) |
| `keetanetwork-client-wasi` | [Client WASI](../keetanetwork-client-wasi/docs/ARCHITECTURE.md) |
| `keetanetwork-node` | [Node](../keetanetwork-node/docs/README.md) |
| `keetanetwork-ledger` | [Ledger](../keetanetwork-ledger/docs/README.md) |

Crate identity, versions, and field lists live in each member `Cargo.toml` and in rustdoc. This tree does not copy those lists.

## Falsified by

A change to the workspace `members` or `exclude` lists in root `Cargo.toml`. A change that adds product types to `keetanetwork-node/src/lib.rs` or `keetanetwork-ledger/src/lib.rs`. A change to the `compile_error!` gates in `keetanetwork-asn1/src/lib.rs`, `keetanetwork-client/src/lib.rs` (`http` runtime pairing), or `keetanetwork-client-wasi/src/lib.rs` (`p1` / `p2`). A change that moves the OpenAPI document away from `keetanetwork-client/openapi/keetanet-node.yaml`. A change to the product-crate set that [Overview](README.md) indexes under each crate `docs/` directory.
126 changes: 126 additions & 0 deletions docs/QUICKSTART.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Quickstart

## Abstract

This page is the install, build, test, and first-use path for the `node-rs` workspace. It records the Makefile targets from the repository Makefile. It also states the GitHub Packages gate and the cargo-only path.

## Purpose

Read this page when you clone the repository or when you need a correct Make command. After reading you can set up the toolchain and run a debug or release build. You can also choose a test path and start from an existing rustdoc example.

## Pin the toolchain

Use Rust `1.94.0` from `rust-toolchain.toml`. After you clone, that pin wins over a default rustup toolchain.

The file also requests `rustfmt`, `clippy`, and `llvm-tools-preview`. It also requests the `wasm32-unknown-unknown`, `wasm32-wasip1`, and `wasm32-wasip2` targets.

## Set up the tree

Run first-time setup.

```bash
make developer
```

`make developer` installs rustc through `scripts/rustup-init.sh -y --default-toolchain stable` when rustc is missing. That script requests the `stable` toolchain. The repo pin still selects `1.94.0` for this tree after clone.

## Build

Use the Make targets. Use `make build release=1` for a release build.

| Target | What you get |
| --- | --- |
| `make developer` | First-time toolchain and tool setup |
| `make build` | Debug build through `cargo build` |
| `make build release=1` | Release build through `cargo build --release` |
| `make check` | Compilation check through `cargo check` |

Release build:

```bash
make build release=1
```

`make release` runs `scripts/release.sh` and publishes crates to crates.io. That target is a publish path. It is not a release build.

## Test

`make test` depends on `make node-harness`. It then runs `cargo test --all-features --workspace`.

| Target | What you get |
| --- | --- |
| `make test` | Harness build, then workspace tests with all features |
| `make test-feat` | Feature matrix from the `Makefile` `test-feat` recipe |
| `make test-all` | `make test` and then `make test-feat` |

Those targets need the Packages gate below. Use the cargo-only path when you lack Packages read.

## Wasm and WASI

Name these targets when you need those ABIs. They also need the Packages gate. The Make targets are the first-use path for those ABIs.

| Target | What you get |
| --- | --- |
| `make build-wasm` | `wasm-pack build` for `keetanetwork-client-wasm` |
| `make test-wasm` | Harness, wasm-pack node tests, and Playwright in `keetanetwork-client-wasm/tests` |
| `make build-wasi` | WASI P1 and P2 debug artifacts for `keetanetwork-client-wasi` |
| `make test-wasi` | Harness, WASI artifacts, and host tests under `keetanetwork-client-wasi/host-tests` |

`make test-wasi` selects `p1` for `wasm32-wasip1` and `p2` for `wasm32-wasip2`. [Architecture](ARCHITECTURE.md) holds that one-feature contract.

## rustdoc

| Target | What you get |
| --- | --- |
| `make do-docs` | `cargo doc` for the workspace, then opens the result |
| `make do-docs-ci` | The same rustdoc build without opening a browser |

## GitHub Packages gate

`keetanetwork-utils/node-harness/.npmrc` sets `@keetanetwork:registry=https://npm.pkg.github.com`. The harness `package.json` depends on `@keetanetwork/keetanet-node` from that registry.

`make node-harness`, `make test`, `make test-all`, `make test-wasm`, and `make test-wasi` need read access to that package. CI sets `NODE_AUTH_TOKEN` for those jobs in `.github/workflows/ci.yml`.

Set `NODE_AUTH_TOKEN` or `GITHUB_TOKEN` to a GitHub personal access token with `read:packages`. Authorize SSO for the organization when the organization requires it.

Rust crates in this workspace use path dependencies. `.cargo/config.toml` sets a `wasm32-unknown-unknown` `getrandom` cfg. It does not set a private Cargo registry.

## Cargo-only path

Skip the harness when you do not have Packages read.

```bash
cargo check
cargo build
```

You can also run crate tests that do not enable the `node-harness` feature. `make test` still needs the harness and auth.

## First use

Start from the rustdoc examples that already live in the crates. This tree does not add an `examples/` directory.

Construct a `KeetaClient` against the local API from [`keetanetwork-client/src/lib.rs`](https://github.com/KeetaNetwork/node-rs/blob/285ce02435bbcc120e86a7c78d2865a034679453/keetanetwork-client/src/lib.rs#L11-L37).

```rust
let client = KeetaClient::new("http://localhost:8080/api").with_network(0u8);
```

`UserClient` signing tests live in [`keetanetwork-client/tests/user_signing.rs`](https://github.com/KeetaNetwork/node-rs/blob/285ce02435bbcc120e86a7c78d2865a034679453/keetanetwork-client/tests/user_signing.rs#L8-L20). A live harness cookbook lives in [`keetanetwork-client/tests/e2e.rs`](https://github.com/KeetaNetwork/node-rs/blob/285ce02435bbcc120e86a7c78d2865a034679453/keetanetwork-client/tests/e2e.rs#L164).

Build a signed opening block from [`keetanetwork-block/src/lib.rs`](https://github.com/KeetaNetwork/node-rs/blob/285ce02435bbcc120e86a7c78d2865a034679453/keetanetwork-block/src/lib.rs#L8-L39).

```rust
let unsigned = BlockBuilder::default()
.with_network(0u8)
.with_account(account.clone())
.as_opening()
.build()?;
let block = unsigned.sign()?;
```

A harness opening-block cookbook lives in [`keetanetwork-block/tests/e2e.rs`](https://github.com/KeetaNetwork/node-rs/blob/285ce02435bbcc120e86a7c78d2865a034679453/keetanetwork-block/tests/e2e.rs#L116-L119).

## Falsified by

A change to the `developer`, `build`, `check`, `test`, `test-feat`, `test-all`, `build-wasm`, `test-wasm`, `build-wasi`, `test-wasi`, `do-docs`, `do-docs-ci`, or `release` targets in `Makefile`. A change to the channel in `rust-toolchain.toml`. A change to the registry line in `keetanetwork-utils/node-harness/.npmrc`. A change to the `KeetaClient` or `BlockBuilder` rustdoc examples in those crate `lib.rs` files.
Loading
Loading