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
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target-dir = "target"
10 changes: 5 additions & 5 deletions .github/actions/greenfloor-maturin-wheels/action.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: GreenFloor maturin wheels
description: Ensure and optionally install the GreenFloor signer PyO3 wheel.
description: Ensure and optionally install the GreenFloor engine PyO3 wheel.

inputs:
operation:
Expand All @@ -18,8 +18,8 @@ runs:
with:
operation: ${{ inputs.operation }}
builder: maturin
tree-path: greenfloor-signer-pyo3
source-path: greenfloor-signer-pyo3/Cargo.toml
cache-key-prefix: signer-pyo3-wheelhouse
wheelhouse-subdir: greenfloor-signer-pyo3
tree-path: greenfloor-engine-pyo3
source-path: greenfloor-engine-pyo3/Cargo.toml
cache-key-prefix: engine-pyo3-wheelhouse
wheelhouse-subdir: greenfloor-engine-pyo3
rust-already-configured: ${{ inputs.rust-already-configured }}
4 changes: 2 additions & 2 deletions .github/actions/rust-cache-greenfloor/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ runs:
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
greenfloor-signer -> target
greenfloor-signer-pyo3 -> target
greenfloor-engine -> target
greenfloor-engine-pyo3 -> target
cache-workspace-crates: true
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ jobs:
- uses: ./.github/actions/rust-cache-greenfloor
if: matrix.run_rust_tests

- name: Build and test greenfloor-signer
- name: Build and test greenfloor-engine
if: matrix.run_rust_tests
run: |
cargo build --manifest-path greenfloor-signer/Cargo.toml
cargo test --manifest-path greenfloor-signer/Cargo.toml
cargo build --manifest-path greenfloor-engine/Cargo.toml
cargo test --manifest-path greenfloor-engine/Cargo.toml

- uses: ./.github/actions/greenfloor-maturin-wheels
with:
Expand All @@ -98,9 +98,9 @@ jobs:
- name: "Test suite (pytest)"
run: pytest -v --tb=short

- name: Pytest (signer marker)
- name: Pytest (engine marker)
if: matrix.run_rust_tests
run: pytest -v --tb=short -m signer
run: pytest -v --tb=short -m engine

- uses: ./.github/actions/wheel-cache
if: matrix.run_sdk_integration
Expand All @@ -113,6 +113,6 @@ jobs:
wheelhouse-subdir: chia-wallet-sdk
rust-already-configured: ${{ matrix.run_rust_tests }}

- name: Pytest (greenfloor_signer + chia-wallet-sdk offer round-trip on Ubuntu)
- name: Pytest (greenfloor_engine + chia-wallet-sdk offer round-trip on Ubuntu)
if: matrix.run_sdk_integration
run: GREENFLOOR_RUN_SIGNER_INTEGRATION_TESTS=1 pytest -vv -s tests/test_greenfloor_signer_integration.py
run: GREENFLOOR_RUN_ENGINE_INTEGRATION_TESTS=1 pytest -vv -s tests/test_greenfloor_engine_integration.py
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ __pycache__/
dist/
build/
*.egg-info/
target/
greenfloor-native/target/
greenfloor-signer-pyo3/target/
greenfloor-signer-pyo3/python/
greenfloor-signer/target/
greenfloor-engine-pyo3/target/
greenfloor-engine-pyo3/python/
greenfloor-engine/target/
.coverage
.coverage.*
htmlcov/
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ Severity tags:
- `[MUST]` `greenfloor/core/coin_ops/`: coin-op deterministic policy (plan, fee budget, inventory, min-amount guard) shared by CLI and daemon.
- `[MUST]` `greenfloor/config`: parse/validate config, resolve paths, resolve quote assets.
- `[MUST]` `greenfloor/* adapters`: side effects only (network, filesystem, wallet, notifications).
- `[MUST]` Signing/execution path is adapter -> canonical Rust kernel (`greenfloor-signer` / `greenfloor_kernel` PyO3); legacy `greenfloor/signing.py` re-exports adapters only.
- `[MUST]` `greenfloor-signer/`: canonical vault KMS signing implementation; new vault spend/offer logic lands here first.
- `[MUST]` Signing/execution path is adapter -> canonical Rust engine (`greenfloor-engine` crate / `greenfloor_engine` PyO3); legacy `greenfloor/signing.py` re-exports adapters only.
- `[MUST]` `greenfloor-engine/`: canonical Rust engine crate; new vault spend/offer logic lands here first.
- `[MUST]` `greenfloor/cli/manager.py`: operator CLI router (argparse + dispatch).
- `[MUST]` `greenfloor/cli/coin_ops_list.py`, `coin_ops_split.py`, `coin_ops_combine.py`: coin list/split/combine CLI commands (`coin_ops.py` re-exports).
- `[MUST]` `greenfloor/cli/cats.py`: local CAT catalog CLI commands.
Expand All @@ -57,7 +57,7 @@ Severity tags:
## Design Constraints

- `[MUST]` Prefer direct function calls within the package; do not spawn subprocesses for same-env Python calls unless isolation/security is documented in `docs/decisions/`.
- `[MUST]` Signing/execution path is adapter -> canonical Rust kernel (`greenfloor-signer` crate, `greenfloor_kernel` PyO3 module).
- `[MUST]` Signing/execution path is adapter -> canonical Rust engine (`greenfloor-engine` crate, `greenfloor_engine` PyO3 module).
- `[MUST]` Avoid unnecessary indirection layers (`executor`, `worker`, `engine`, etc.).
- `[MUST]` Keep one distinct responsibility per file; merge pass-through modules into functions.
- `[MUST]` Eliminate duplicated logic blocks (>10 lines) by extracting shared helpers.
Expand Down
2 changes: 1 addition & 1 deletion config/program.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ runtime:
market_slot_count: 4
dry_run: false

# Local Rust signer (greenfloor-signer) for vault KMS offer execution.
# Local Rust engine for vault KMS offer execution.
# Written to ~/.greenfloor/config/signer.yaml at runtime for PyO3 load_signer_config.
signer:
coinset_msp_base_url: "https://api-msp.coinset.org"
Expand Down
2 changes: 1 addition & 1 deletion docs/decisions/0002-signing-pipeline-consolidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ To avoid signing-path drift, the canonical in-process entrypoints are:

New signing integrations should route through these APIs instead of introducing alternate signing stacks.

**Update (2026-05):** ADR 0006 makes `greenfloor-signer` the canonical vault signing
**Update (2026-05):** ADR 0006 makes `greenfloor-engine` the canonical vault signing
implementation. Python APIs above are migration wrappers until Rust paths replace them.
10 changes: 5 additions & 5 deletions docs/decisions/0006-rust-signer-canonical-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ Accepted

## Decision

`greenfloor-signer` is the canonical signing implementation for vault KMS paths.
`greenfloor-engine` is the canonical signing implementation for vault KMS paths.
Python signing in `greenfloor/signing.py` remains during migration but is **legacy**;
new vault spend, mixed-split, and offer behavior lands in Rust first.

Migration order:

1. **Now:** `greenfloor-signer` CLI for operator/debug flows and CI parity tests.
2. **Next:** Python daemon/CLI invoke `greenfloor-signer` (or a PyO3 wrapper) instead of
1. **Now:** `greenfloor-engine` CLI for operator/debug flows and CI parity tests.
2. **Next:** Python daemon/CLI invoke `greenfloor-engine` (or a PyO3 wrapper) instead of
duplicating spend logic in `greenfloor/signing.py`.
3. **End state:** Remove duplicated Python vault spend paths; Python keeps orchestration,
config, and adapters only.
Expand All @@ -32,10 +32,10 @@ until local Rust offer paths reach production parity for each market flow.

## Consequences

- Feature work for vault CAT spends and offers targets `greenfloor-signer/` first.
- Feature work for vault CAT spends and offers targets `greenfloor-engine/` first.
- Python parity tests validate cross-language hash/spend contracts during migration.
- ADR 0002 canonical Python APIs become thin wrappers until removed.
- Coinset IO in Rust (`greenfloor-signer/src/coinset/`) is allowed for signer paths;
- Coinset IO in Rust (`greenfloor-engine/src/coinset/`) is allowed for signer paths;
Python adapters remain for daemon orchestration until cutover.
- Vault CAT coin selection for offers and mixed splits goes through
`OfferCoinsetBackend` (live coinset adapter + simulator test backend).
Expand Down
6 changes: 3 additions & 3 deletions docs/decisions/0007-rust-signer-pyo3-boundary.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Accepted
## Decision

Vault KMS signing, offer creation, bootstrap mixed-splits, and asset ID resolution run
through the in-process `greenfloor_signer` PyO3 extension backed by `greenfloor-signer`.
through the in-process `greenfloor_engine` PyO3 extension backed by `greenfloor-engine`.

Configuration and vault member metadata come from `program.yaml` (`signer:` + `vault:`).
On-chain IO uses `api-msp.coinset.org` via the Rust MSP coinset client.
Expand All @@ -26,11 +26,11 @@ orchestration (manager, daemon, Dexie/Splash publish, ladder planning).

- Rust simulator atomic-take roundtrip for CAT:CAT requested legs remains sell-CAT/request-XCH only;
buy-side and cat-cat fixtures validate offer build + `create_offer_request` shape.
- Operator `greenfloor-signer create-offer` CLI parity with live Coinset is covered by PyO3 in
- Operator `greenfloor-engine create-offer` CLI parity with live Coinset is covered by PyO3 in
production paths; dedicated subprocess JSON parity tests are not required while PyO3 is canonical.

## Consequences

- CI builds `greenfloor-signer-pyo3` wheel alongside `greenfloor-native`.
- CI builds `greenfloor-engine-pyo3` wheel alongside `greenfloor-native`.
- Golden offer fixtures export from Rust simulator tests.
- Python tests validate wiring and `validate_offer`; Rust tests validate spend semantics.
52 changes: 52 additions & 0 deletions docs/decisions/0010-rust-engine-crate-naming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 0010 - Rust Engine Crate Naming

## Status

Accepted

Updated 2026-05-29: the Rust source directories, Cargo package, CLI binary,
Rust library target, and PyO3 module now use engine naming.

## Context

The Rust implementation was introduced as a signer for vault KMS paths. The crate
now also owns deterministic daemon policy: cycle orchestration, offer
reconciliation, and coin-op planning. The old "signer" name no longer describes
the scope.

## Decision

**Completed during this migration phase:**

- Rename source paths to `greenfloor-engine/` and `greenfloor-engine-pyo3/`.
- Rename the Cargo package and CLI binary to `greenfloor-engine`, and the Rust
library target and PyO3 module to `greenfloor_engine`.
- `greenfloor.core.engine_bridge.import_engine()` remains the canonical Python
bridge API for in-process Rust policy; `import_signer` remains a migration alias.
- `engine_bridge` imports `greenfloor_engine`; use `engine_rebuild_hint(module=...)`
and `require_engine_method()` for operator rebuild text and stale-symbol errors.
- Group Rust policy by domain module (`cycle/`, `coin_ops/`, `offer/`, `vault/`) inside the crate.

**Remaining compatibility:**

- Retain `greenfloor.core.engine_bridge.import_signer` as a Python migration alias
until legacy call sites disappear.

## Naming map

| Layer | Current | Target |
| -------------------- | ------------------------------- | -------------------------- |
| Cargo crate | `greenfloor-engine` | done |
| PyO3 module | `greenfloor_engine` | done |
| Python bridge | `engine_bridge.import_engine()` | unchanged |
| Vault/sign path docs | "Rust signer" | "Rust engine (vault path)" |

## Consequences

- New Python policy surfaces use `engine_bridge`, not ad-hoc `importlib` copies.
- Adapter IO paths (`rust_signer`, `coinset`, `bls_signing`, `native_offer`, etc.) import
the engine through `engine_bridge.import_engine()`.
- Legacy module shims (`greenfloor.core.fee_budget`, `inventory`, `coin_ops_policy`) were
removed once call sites imported `greenfloor.core.coin_ops` only; coin-op policy now lives
in `_bridge.py` with `CoinOpsEngineProtocol` typing the PyO3 surface.
- ADR 0006/0007 remain valid; this ADR clarifies naming without changing boundaries.
51 changes: 0 additions & 51 deletions docs/decisions/0010-rust-kernel-crate-naming.md

This file was deleted.

28 changes: 14 additions & 14 deletions docs/decisions/0011-offer-request-python-import-boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,41 @@ Accepted (2026-05-28)

## Context

Offer-request leg math moved into `greenfloor-signer` with PyO3 bindings. Python needs stable
Offer-request leg math moved into `greenfloor-engine` with PyO3 bindings. Python needs stable
import paths for runtime, daemon dispatch, vault request construction, and BLS offer building
without growing `policy_bridge.py` into a flat FFI catalog.

## Decision

### Canonical Rust surface

- `greenfloor-signer/src/offer/request.rs` — leg math, validation, `normalize_offer_side`,
- `greenfloor-engine/src/offer/request.rs` — leg math, validation, `normalize_offer_side`,
`normalize_offer_asset_id`, `signer_split_asset_id`, `compute_signer_offer_leg_amounts`.

### Python modules (import from here, not `policy_bridge`)

| Module | Use for |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `greenfloor.core.offer_request_bridge` | Direct kernel access to offer-request symbols (internal bridge). |
| `greenfloor.core.offer_bootstrap_bridge` | **Stable runtime imports** — bootstrap DTOs, planner, and phase kernel wrappers. |
| `greenfloor.core.offer_request_bridge` | Direct engine access to offer-request symbols (internal bridge). |
| `greenfloor.core.offer_bootstrap_bridge` | **Stable runtime imports** — bootstrap DTOs, planner, and phase engine wrappers. |
| `greenfloor.core.offer_bootstrap_policy` | Backward-compatible re-export of `offer_bootstrap_bridge` (no logic). |
| `greenfloor.core.offer_policy` | **Stable runtime/daemon/BLS imports** — re-exports leg math + Dexie/publish helpers. |
| `greenfloor.core.signer_offer_request` | Low-level `SignerCreateOfferRequest` / `signer_create_offer_request_from_fields` (KMS plan-dict spends only). |
| `greenfloor.core.offer_action` | **Canonical offer create** — typed action request/result, pure shaping, create-phase outcome mapping. |
| `greenfloor.runtime.offer_action_build` | Build action requests from `OfferBuildContext` plus local/signer runtime orchestration (asset resolution + BLS create). |
| `greenfloor.adapters.offer_action` | Kernel IO only (`build_*_offer_for_action`). |
| `greenfloor.adapters.offer_action` | Engine IO only (`build_*_offer_for_action`). |

### Offer-action create path (2026-05)

- **New market-action offer creation** must use `core/offer_action` + `adapters/offer_action`
(signer) or `runtime/offer_action_build` (local BLS). Do not add call sites to
`rust_signer.build_vault_cat_offer` for that flow.
- Local BLS resolves ticker symbols via `resolve_action_assets_for_build_context` before kernel
- Local BLS resolves ticker symbols via `resolve_action_assets_for_build_context` before engine
dispatch when ids are not already canonical.

### `policy_bridge.py` role

- Owns **pricing/publish/retry** kernel wrappers and re-exports offer-request symbols for
- Owns **pricing/publish/retry** engine wrappers and re-exports offer-request symbols for
backward compatibility during migration.
- **New code** should import offer-request helpers from `offer_policy` or
`signer_offer_request`, not add new `policy_bridge` call sites.
Expand All @@ -49,22 +49,22 @@ without growing `policy_bridge.py` into a flat FFI catalog.

- `prepare_offer_build_context()` normalizes `action_side` once; `OfferBuildContext.action_side`
is always `"buy"` or `"sell"`.
- `PlannedAction.side` from the cycle kernel is already `"buy"` or `"sell"`; dispatch uses
`planned_action_side()` (no kernel round-trip) instead of re-normalizing per hop.
- `PlannedAction.side` from the cycle engine is already `"buy"` or `"sell"`; dispatch uses
`planned_action_side()` (no engine round-trip) instead of re-normalizing per hop.
- `normalize_offer_side()` in `offer_request_bridge` uses a fast path for common inputs and
calls the kernel only for non-standard values; parity tests lock equivalence.
calls the engine only for non-standard values; parity tests lock equivalence.

## Consequences

- Next offer-migration PRs add symbols to `offer_request_py.rs` + `offer_request_bridge.py`, not
`offer_build_py.rs` / `policy_bridge.py` bodies.
- Bootstrap planner symbols use `offer_bootstrap_bridge.py` and `offer_bootstrap_py.rs` (not
`offer_build_py.rs`). Bridges call `kernel_bridge.bootstrap_kernel()` (`BootstrapKernelProtocol`).
Kernel API: `plan_bootstrap_mixed_outputs(ladder_entries=...)` returns `BootstrapPlanOutcome`
`offer_build_py.rs`). Bridges call `engine_bridge.bootstrap_engine()` (`BootstrapEngineProtocol`).
Engine API: `plan_bootstrap_mixed_outputs(ladder_entries=...)` returns `BootstrapPlanOutcome`
(`ready` / `needs_split` / `cannot_fund` / `invalid_ladder` / `invalid_coins`).
- Rust layout: `greenfloor-signer/src/offer/bootstrap/planner.rs` (deficit planner),
- Rust layout: `greenfloor-engine/src/offer/bootstrap/planner.rs` (deficit planner),
`offer/bootstrap/phase.rs` (early/executed phase snapshots). PyO3 marshalling:
`greenfloor-signer-pyo3/src/py_utils/bootstrap_marshal.rs`.
`greenfloor-engine-pyo3/src/py_utils/bootstrap_marshal.rs`.
- Runtime orchestration lives in `greenfloor/runtime/offer_bootstrap.py`
(`BootstrapRuntimeDeps`, `BootstrapPreflight`, `BootstrapSplitExecution`). Phase DTOs live in
`greenfloor.offer_bootstrap`; early/executed phase mapping is Rust via `offer_bootstrap_bridge.py`.
Expand Down
Loading
Loading