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
4 changes: 1 addition & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ concurrency:
jobs:
build:
if: github.event.pull_request.draft == false
uses: start9labs/shared-workflows/.github/workflows/build.yml@master
# with:
# FREE_DISK_SPACE: true
uses: Start9Labs/start-technologies/.github/workflows/build.yml@master
secrets:
DEV_KEY: ${{ secrets.DEV_KEY }}
3 changes: 1 addition & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ on:

jobs:
release:
uses: start9labs/shared-workflows/.github/workflows/release.yml@master
uses: Start9Labs/start-technologies/.github/workflows/release.yml@master
with:
# FREE_DISK_SPACE: true
RELEASE_REGISTRY: ${{ vars.RELEASE_REGISTRY }}
S3_S9PKS_BASE_URL: ${{ vars.S3_S9PKS_BASE_URL }}
secrets:
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/tagAndRelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ concurrency:

jobs:
tag:
uses: start9labs/shared-workflows/.github/workflows/tagAndRelease.yml@master
uses: Start9Labs/start-technologies/.github/workflows/tagAndRelease.yml@master
with:
REFERENCE_REGISTRY: ${{ vars.REFERENCE_REGISTRY }}
# FREE_DISK_SPACE: true
RELEASE_REGISTRY: ${{ vars.RELEASE_REGISTRY }}
S3_S9PKS_BASE_URL: ${{ vars.S3_S9PKS_BASE_URL }}
secrets:
Expand Down
16 changes: 14 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# AGENTS.md

You are working in a StartOS service-package repository — a repo that builds a `.s9pk` for installation on StartOS.
This is a StartOS service-package repository — it builds a `.s9pk` for StartOS.

**Before doing anything in this repo, read [CONTRIBUTING.md](./CONTRIBUTING.md) and every document it links to.** That covers what this package is, how it's built, how it ships, and the conventions to follow. Do not begin work until you have read them all.
Develop it inside a StartOS packaging workspace created by `start-cli s9pk init-workspace`,
which provides the packaging guide and agent context one level up. If you're reading this in a
bare clone with no workspace, the full guide is at <https://docs.start9.com/packaging>.

Work this package's `TODO.md` from top to bottom. Keep `README.md` (architecture, for developers and LLMs) and `instructions.md` (end-user docs) in sync with your changes.

## This repo

- **Package id is `utxoracle`.** Depends (hard-required) on `bitcoind` for local JSON-RPC and chain data; mounts only Bitcoin's `main` volume read-only for the RPC cookie and keeps no state of its own. Exports a single `ui` interface on port 80. The run mode is chosen with the `configure` action and passed to `utxoracle.py` via the `UTXORACLE_MODE` env var.

## Inspecting a running install

To run a command inside the service's container (read its generated config, grep app logs), use `start-cli package attach utxoracle -n utxoracle-sub -- <cmd>`. Select the subcontainer by **name** with `-n` (the name passed to `SubContainer.of` in `main.ts` — here `utxoracle-sub`) or by image with `-i`. Note: `-s/--subcontainer` matches the internal **Guid**, not the name, so passing a name to `-s` fails with "no matching subcontainers".
43 changes: 0 additions & 43 deletions CONTRIBUTING.md

This file was deleted.

2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3.11-slim

# UTXOracle itself is pure Python stdlib and talks to Bitcoin Core over JSON-RPC.
# UTXOracle itself is pure Python stdlib and talks to Bitcoin over JSON-RPC.
# curl is only used by the entrypoint's RPC readiness probe.
RUN apt-get update && apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ARCHES := x86 arm
# overrides to s9pk.mk must precede the include statement
include s9pk.mk
include node_modules/@start9labs/start-sdk/s9pk.mk
40 changes: 23 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@

UTXOracle estimates the price of bitcoin by analyzing patterns in local
on-chain transaction data. This StartOS package runs UTXOracle against the
Bitcoin Core service on the same server and serves the generated result page
Bitcoin service on the same server and serves the generated result page
through a web interface.

## Image and Container Runtime

This package is a thin wrapper around upstream UTXOracle. The image is
`python:3.11-slim` with `utxoracle.py` vendored **verbatim** from
<https://utxo.live/oracle/UTXOracle.py> (see `UPDATING.md`) plus the StartOS
entrypoint. UTXOracle talks to Bitcoin Core over JSON-RPC using only the Python
entrypoint. UTXOracle talks to Bitcoin over JSON-RPC using only the Python
standard library — there is no `bitcoin-cli` and no raw block-file access.

The entrypoint writes a `bitcoin.conf` pointing at the StartOS Bitcoin Core
The entrypoint writes a `bitcoin.conf` pointing at the StartOS Bitcoin
service, shows a temporary status page, starts the web server, waits for Bitcoin
Core RPC readiness, runs the unmodified script, and serves the HTML chart it
RPC readiness, runs the unmodified script, and serves the HTML chart it
produces as `index.html`. If UTXOracle exits with an error, the web server keeps
running and the status page is replaced with a failure page.

Expand All @@ -38,17 +38,17 @@ recomputed on each run. Its only persistence is the run-mode setting, stored by
StartOS in `store.json` on the `startos` volume (read in `startos/main.ts`, not
mounted into the container).

The Bitcoin Core dependency volume is mounted read-only at `/mnt/bitcoind` so
The Bitcoin dependency volume is mounted read-only at `/mnt/bitcoind` so
UTXOracle can read the RPC cookie (`/mnt/bitcoind/.cookie`) for authentication.
All block data is fetched over JSON-RPC from the local Bitcoin Core service; the
All block data is fetched over JSON-RPC from the local Bitcoin service; the
package does not read raw block files.

## Installation and First-Run Flow

Install Bitcoin Core on the same StartOS server before starting UTXOracle.
Install Bitcoin on the same StartOS server before starting UTXOracle.
The entrypoint generates the `bitcoin.conf` that points UTXOracle at the local
Bitcoin Core service; no RPC username or password is generated or stored by this
package (it uses Bitcoin Core's cookie).
Bitcoin service; no RPC username or password is generated or stored by this
package (it uses Bitcoin's cookie).

When the service starts, the web interface becomes available first with a
temporary status page. The final UTXOracle result page appears after block
Expand All @@ -59,8 +59,12 @@ analysis completes.
The run mode (`rb` for today, `yesterday`, or a `YYYY/MM/DD` date) lives in
`store.json` on the `startos` volume. `startos/main.ts` reads it and passes it to
the container as the `UTXORACLE_MODE` environment variable. Set it through the
Configure action. The Bitcoin Core RPC connection is separate: the entrypoint
generates a `bitcoin.conf` at startup.
Configure action. The Bitcoin RPC connection is separate: `startos/main.ts`
resolves Bitcoin's bound RPC interface over the internal StartOS bridge and
passes its host and port to the container as the `RPC_HOST`/`RPC_PORT`
environment variables, which the entrypoint writes into a `bitcoin.conf` at
startup. While the address is unresolved the variables are absent and the
entrypoint waits for Bitcoin rather than dialing a placeholder.

## Network Access and Interfaces

Expand All @@ -85,7 +89,7 @@ run.
## Backups and Restore

Backups include the `startos` volume (the run-mode setting). Restore uses the
standard StartOS SDK backup flow for that volume. The Bitcoin Core dependency
standard StartOS SDK backup flow for that volume. The Bitcoin dependency
volume is not backed up by this package.

## Health Checks
Expand All @@ -97,20 +101,20 @@ volume is not backed up by this package.

## Dependencies

Bitcoin Core is required. The dependency version range and required health
Bitcoin is required. The dependency version range and required health
checks are declared in `startos/dependencies.ts`.

UTXOracle uses Bitcoin Core for JSON-RPC calls with RPC cookie authentication.
The Bitcoin Core dependency volume is mounted read-only solely to read the
UTXOracle uses Bitcoin for JSON-RPC calls with RPC cookie authentication.
The Bitcoin dependency volume is mounted read-only solely to read the
cookie file.

## Limitations and Differences

1. UTXOracle connects only to the Bitcoin Core service on the same StartOS
1. UTXOracle connects only to the Bitcoin service on the same StartOS
server.
2. The web interface is a static HTTP server that serves the generated
UTXOracle result page.
3. UTXOracle does not store Bitcoin Core RPC usernames or passwords.
3. UTXOracle does not store Bitcoin RPC usernames or passwords.
4. The result page updates when the service is run again; this package does not
provide a live streaming price feed.

Expand Down Expand Up @@ -142,6 +146,8 @@ dependencies:
- bitcoind
startos_managed_env_vars:
- UTXORACLE_MODE
- RPC_HOST
- RPC_PORT
actions:
- configure
health_checks:
Expand Down
2 changes: 1 addition & 1 deletion UPDATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The version is named in the banner near the top of the file (currently "Version
curl -fsSL https://utxo.live/oracle/UTXOracle.py -o utxoracle.py
```

This package does **not** patch the script — it is a thin wrapper. `docker_entrypoint.sh` supplies a `bitcoin.conf` (RPC host/port/cookie) pointing at the StartOS Bitcoin Core service and serves the HTML the script produces, so the upstream script runs unmodified. After updating, confirm upstream still reads `bitcoin.conf` for `rpcconnect`/`rpcport`/`rpccookiefile` and still writes an `UTXOracle_*.html` file; if those conventions change, adjust `docker_entrypoint.sh` (never the script).
This package does **not** patch the script — it is a thin wrapper. `docker_entrypoint.sh` supplies a `bitcoin.conf` (RPC host/port from the `RPC_HOST`/`RPC_PORT` env vars StartOS injects — `startos/main.ts` resolves Bitcoin's bound RPC interface over the internal bridge — plus the cookie path) pointing at the StartOS Bitcoin service and serves the HTML the script produces, so the upstream script runs unmodified. After updating, confirm upstream still reads `bitcoin.conf` for `rpcconnect`/`rpcport`/`rpccookiefile` and still writes an `UTXOracle_*.html` file; if those conventions change, adjust `docker_entrypoint.sh` (never the script).

**Privacy:** the entrypoint also strips the upstream "Live Updating Oracle" promo and its autoplay YouTube `<iframe>` from the result page so a self-hosted instance makes no external (Google/YouTube) requests — that iframe is the page's only external resource. After updating, re-check the served page for external URLs (`grep -E 'https?://' index.html`) and adjust the `sed` in `docker_entrypoint.sh` if upstream changes the markup. Ideally, ask upstream for a `--private`/`--no-embed` flag so this strip becomes unnecessary.

Expand Down
26 changes: 16 additions & 10 deletions docker_entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
#
# Thin StartOS wrapper around the unmodified upstream UTXOracle.py.
# It supplies the node connection (a bitcoin.conf pointing at the StartOS
# Bitcoin Core service), runs the script, and serves the HTML it produces.
# Bitcoin service), runs the script, and serves the HTML it produces.

set -eu

DATADIR="/app/datadir" # ephemeral data dir we hand to UTXOracle.py
RPC_HOST="bitcoind.startos"
RPC_PORT="8332"
# RPC host/port are injected by StartOS once the Bitcoin dependency resolves
# (main.ts resolves its bound RPC interface over the internal bridge). Until
# then they are unset; we do not fabricate an address, so bitcoin.conf omits
# them and wait_for_node keeps waiting until main restarts us with the real one.
RPC_HOST="${RPC_HOST:-}"
RPC_PORT="${RPC_PORT:-}"
COOKIE="/mnt/bitcoind/.cookie"

webserver_pid=""
Expand All @@ -22,12 +26,14 @@ trap terminate TERM INT
cd /app

# UTXOracle reads RPC settings from a standard bitcoin.conf in its data dir.
# rpcconnect/rpcport are written only once StartOS has resolved the address;
# while unresolved they are omitted rather than pointed at a placeholder.
mkdir -p "$DATADIR"
cat > "$DATADIR/bitcoin.conf" <<EOF
rpcconnect=${RPC_HOST}
rpcport=${RPC_PORT}
rpccookiefile=${COOKIE}
EOF
{
[ -n "$RPC_HOST" ] && echo "rpcconnect=${RPC_HOST}"
[ -n "$RPC_PORT" ] && echo "rpcport=${RPC_PORT}"
echo "rpccookiefile=${COOKIE}"
} > "$DATADIR/bitcoin.conf"

# The run mode, provided by StartOS via the daemon env (defaults to today).
argument="${UTXORACLE_MODE:-rb}"
Expand Down Expand Up @@ -69,7 +75,7 @@ wait_for_node() {
| grep -qE '"initialblockdownload": *false'; then
return 0
fi
echo "Waiting for Bitcoin Core RPC to be ready and synced..."
echo "Waiting for Bitcoin RPC to be ready and synced..."
sleep 10
done
}
Expand All @@ -92,7 +98,7 @@ run_utxoracle() {

rm -f /tmp/utxoracle_exit_code
rm -f /app/UTXOracle_*.html
write_status_page "UTXOracle is running" "Waiting for Bitcoin Core and computing the price."
write_status_page "UTXOracle is running" "Waiting for Bitcoin and computing the price."
start_webserver
wait_for_node

Expand Down
4 changes: 2 additions & 2 deletions instructions.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Instructions for UTXOracle

Before starting UTXOracle, install and start Bitcoin Core on the same StartOS server. UTXOracle connects to it over JSON-RPC and authenticates with Bitcoin Core's local `.cookie` file (`/mnt/bitcoind/.cookie`), so no RPC username or password is required.
Before starting UTXOracle, install and start Bitcoin on the same StartOS server. UTXOracle connects to it over JSON-RPC and authenticates with Bitcoin's local `.cookie` file (`/mnt/bitcoind/.cookie`), so no RPC username or password is required.

Use the **Configure** action to choose which price UTXOracle estimates on its next run:

- **Today** — the price from the most recent 144 blocks (the default).
- **Yesterday** — the consensus price for the previous full UTC day.
- **Specific Date** — pick a UTC date (from 2023-12-15 onward) with the date picker.

Changing the selection automatically restarts the service to recompute. "Today" works on a pruned node; evaluating a historical date requires an unpruned (archival) Bitcoin Core node, since a pruned node no longer stores those blocks.
Changing the selection automatically restarts the service to recompute. "Today" works on a pruned node; evaluating a historical date requires an unpruned (archival) Bitcoin node, since a pruned node no longer stores those blocks.

This package is a wrapper for [UTXOracle](https://utxo.live/oracle/) by [@SteveSimple](https://twitter.com/SteveSimple).
Loading