commit 5e0a559addda00177df990e9c93ac8fa1015ecd3 Author: BitcoinMechanic Date: Thu Oct 17 20:32:03 2024 -0700 initial commit diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..dbbc418 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "datum_gateway"] + path = datum_gateway + url = https://github.com/OCEAN-xyz/datum_gateway diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d80c1c9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +FROM debian:bookworm-slim AS build + +RUN apt update && \ + apt-get install -y build-essential cmake curl libmicrohttpd-dev libjansson-dev \ + libcurl4-openssl-dev libpq-dev libgcrypt20-dev libsodium-dev \ + netcat-traditional pkg-config git + +ARG ARCH +ARG PLATFORM + +COPY /.git /parent_dir/.git + +ADD ./datum_gateway /parent_dir/datum_gateway +WORKDIR /parent_dir/datum_gateway +RUN git status +RUN cmake . && make + +FROM debian:bookworm-slim AS final + +RUN apt update && \ + apt-get install -y curl netcat-traditional libmicrohttpd12 libjansson4 libsodium23 + +ARG ARCH +ARG PLATFORM +RUN curl -sLo /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_${PLATFORM} && chmod +x /usr/local/bin/yq + +WORKDIR /root + +COPY --from=build /parent_dir/datum_gateway/datum_gateway /usr/local/bin/datum_gateway + +RUN chmod +x /usr/local/bin/datum_gateway +ADD ./docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh +RUN chmod a+x /usr/local/bin/docker_entrypoint.sh +ADD ./check-stratum.sh /usr/local/bin/check-stratum.sh +RUN chmod a+x /usr/local/bin/check-stratum.sh +ADD ./check-bitcoin.sh /usr/local/bin/check-bitcoin.sh +RUN chmod a+x /usr/local/bin/check-bitcoin.sh +ADD ./check-dashboard.sh /usr/local/bin/check-dashboard.sh +RUN chmod a+x /usr/local/bin/check-dashboard.sh +ADD ./check-blocknotify.sh /usr/local/bin/check-blocknotify.sh +RUN chmod a+x /usr/local/bin/check-blocknotify.sh + +WORKDIR /root diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md new file mode 100644 index 0000000..aea0aca --- /dev/null +++ b/INSTRUCTIONS.md @@ -0,0 +1,112 @@ + +# Welcome to Datum-Gateway! + +Quick-start guide for those already mining on OCEAN: + +1. Bitcoin Knots is required. This can be found in the Start9 Community Marketplace. + +2. Set up simpleproxy as explained in the last section of this document. + +3. Put a valid Bitcoin address into Datum-Gateway's config and start the service. + +4. Point your miners to the IP and PORT of your Start9 Server and Datum-Gateway service respectively. *(Something like 192.168.x.y replacing x and y as necessary for the Start9 Server IP. 23334 is the default port for Datum-Gateway.)* + +See below for more comprehensive instructions. + +# StartOS Version + +**Warning** - using Datum-Gateway on StartOS v0.3.5.1 in a typical scenario requires making the service accessible over LAN via IP:Port. This requires tinkering with your StartOS server as most Bitcoin mining hardware cannot use mDNS. + +If you feel comfortable doing that, follow the instructions for installing `simpleproxy` at the bottom of this document. + +If you do not, you should wait for StartOS v0.3.6. + +# Basic Information + +Datum-Gateway is for solo mining! + +You can Lottery Mine where you pay yourself the entire block reward for any blocks your find. + +You can also Pool Mine on a pool that supports DATUM where you will split rewards with other miners for increased cash flow. + +By default, Datum-Gateway will do the latter on https://ocean.xyz without any additional configuration beyond entering a Bitcoin address under "Bitcoin Address". + +# Pooled Mining on OCEAN + +Datum-Gateway is configured to connect to OCEAN by default. This means splitting rewards with other miners on OCEAN whilst making your own blocks. + +By default, rewards from mining on OCEAN will go to Bitcoin addresses written in your **miners**, *not* your **Datum-Gateway config** unless you disable **Pool Pass Full Users**. + +**If you have mined on OCEAN before and wish to use Datum-Gateway now, you can leave the Bitcoin addresses in your miners, they will override what is written in Datum's config - just leave "Pool Pass Full Users" enabled.** + +(You will still need to enter a valid Bitcoin address into your Datum-Gateway config. This is simply a fail-safe should the pool go down and it will be where your rewards go if you successfully Lottery Mine a block. Datum-Gateway will not start without a valid Bitcoin address configured.) + +If you chose to write only worker names in your miners and omit Bitcoin address(es) then you must disable **"Pool Pass Full Users"** and then the Bitcoin address in your Datum-Gateway config will be what gets used on OCEAN. Choose this option if you would like to just have worker names in your miners rather than Bitcoin addresses with worker names appended. See the next section for more details on setting up your miners. + +# Setting Up Your Miners + +Point your miners to the IP address of your Start9 Server followed by the port of the Datum-Gateway service. This is 23334 by default so in your miner UI under **"Stratum URL"/"Host"/"Pool"/similar** you will enter something like this: + +`stratum+tcp://192.168.x.y:23334` +or +`stratum+tcp://10.0.0.x:23334` replacing x/y as appropriate. + +Under **"Username"/"Worker"** enter a Bitcoin address. This is where your OCEAN rewards will go. You can append this with unique worker information if desired. + +Examples: + +Just a Bitcoin address for if you do not wish to identify workers on OCEAN's stats: + +`bc1qabcdefghijklmnopqrstuvwxyz` in each of your miner's usernames. This will make all workers collectively appear as `default` on OCEAN's stats. You may wish to do this to obscure the number of workers you have or their hashrate as OCEAN's stats are all public. + +If you wish to identify each worker then you can append worker names to the addresses as follows: + +`bc1qabcdefghijklmnopqrstuvwxyz.bitaxe` + +`bc1qabcdefghijklmnopqrstuvwxyz.bitaxe2` + +`bc1qabcdefghijklmnopqrstuvwxyz.whatsminer2000` + +`bc1qabcdefghijklmnopqrstuvwxyz.antmineringarage` + +etc + +**You can also omit the Bitcoin address from your miners and just use worker names. You must then disable "Pool Pass Full Users" and the Bitcoin address in your Datum-Gateway's config will be used.** + +**Password** can be left blank. If your miner insists on having something written there, you can write "x" or whatever you'd like. + +# Lottery Mining + +To lottery mine with Datum-Gateway, simply remove the text from **Datum Pool Host** in your config. + +With default settings, you will Pool Mine on OCEAN and automatically switch to Lottery Mining if the pool were to ever go offline. If you wish to disable this, disable **Failover To Lottery** in your config. + +**Note: Lottery Mining means no rewards unless you find blocks. Make sure you're familiar with the differences to Pooled Mining.** + +# Installing and Running simpleproxy + +**For StartOS v0.3.5.1 you'll need to do the following:** + +ssh in to your Start9 Server + +Copy and paste the following lines of code one by one: + +`sudo -i` + +`/usr/lib/startos/scripts/chroot-and-upgrade` + +`apt install simpleproxy -y` + +Now copy and paste the following chunk of code in one command: + +echo -e '[Unit]\nDescription=Simpleproxy Datum Forward\nWants=podman.service\nAfter=podman.service\n\n[Service]\nType=simple\nRestart=always\nRestartSec=3\nExecStartPre=/bin/bash -c "/bin/systemctl set-environment IP=$(ip route | grep default | awk '\''{print $9}'\'')"\nExecStart=/usr/bin/simpleproxy -L ${IP}:23334 -R datum.embassy:23335\n\n[Install]\nWantedBy=multi-user.target' > /lib/systemd/system/simpleproxy.datum.service + +Next, copy and paste the following: + +`systemctl enable simpleproxy.datum.service` + +Then finally: + +`exit` + +Your server will now restart and will be accessible to miners on your LAN! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cbdb1f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2024 Bitcoin Ocean, LLC & Jason Hughes + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..57cf729 --- /dev/null +++ b/Makefile @@ -0,0 +1,74 @@ +PKG_ID := $(shell yq e ".id" < manifest.yaml) +PKG_VERSION := $(shell yq e ".version" < manifest.yaml) +TS_FILES := $(shell find . -name \*.ts ) + +# delete the target of a rule if it has changed and its recipe exits with a nonzero exit status +.DELETE_ON_ERROR: + +all: verify + +verify: $(PKG_ID).s9pk + @start-sdk verify s9pk $(PKG_ID).s9pk + @echo " Done!" + @echo " Filesize: $(shell du -h $(PKG_ID).s9pk) is ready" + +install: + @if [ ! -f ~/.embassy/config.yaml ]; then echo "You must define \"host: http://server-name.local\" in ~/.embassy/config.yaml config file first."; exit 1; fi + @echo "\nInstalling to $$(grep -v '^#' ~/.embassy/config.yaml | cut -d'/' -f3) ...\n" + @[ -f $(PKG_ID).s9pk ] || ( $(MAKE) && echo "\nInstalling to $$(grep -v '^#' ~/.embassy/config.yaml | cut -d'/' -f3) ...\n" ) + @start-cli package install $(PKG_ID).s9pk + +clean: + rm -rf docker-images + rm -f $(PKG_ID).s9pk + rm -f scripts/*.js + +clean-manifest: + @sed -i '' '/^[[:blank:]]*#/d' manifest.yaml + @echo; echo "Comments successfully removed from manifest.yaml file."; echo + +# BEGIN REBRANDING +rebranding: + @read -p "Enter new package ID name (must be a single word): " NEW_PKG_ID; \ + read -p "Enter new package title: " NEW_PKG_TITLE; \ + find . \( -name "*.md" -o -name ".gitignore" -o -name "manifest.yaml" -o -name "*Service.yml" \) -type f -not -path "./datum/*" -exec sed -i '' -e "s/datum/$$NEW_PKG_ID/g; s/Hello World/$$NEW_PKG_TITLE/g" {} +; \ + echo; echo "Rebranding complete."; echo " New package ID name is: $$NEW_PKG_ID"; \ + echo " New package title is: $$NEW_PKG_TITLE"; \ + sed -i '' -e '/^# BEGIN REBRANDING/,/^# END REBRANDING/ s/^#*/#/' Makefile + @echo; echo "Note: Rebranding code has been commented out in Makefile"; echo +# END REBRANDING + +scripts/embassy.js: $(TS_FILES) + deno bundle scripts/embassy.ts scripts/embassy.js + +arm: + @rm -f docker-images/x86_64.tar + ARCH=aarch64 $(MAKE) + +x86: + @rm -f docker-images/aarch64.tar + ARCH=x86_64 $(MAKE) + +docker-images/aarch64.tar: Dockerfile docker_entrypoint.sh datum_gateway icon.png INSTRUCTIONS.md check-bitcoin.sh check-blocknotify.sh check-dashboard.sh check-stratum.sh +ifeq ($(ARCH),x86_64) +else + mkdir -p docker-images + docker buildx build --tag start9/$(PKG_ID)/main:$(PKG_VERSION) --build-arg ARCH=aarch64 --build-arg PLATFORM=arm64 --platform=linux/arm64 -o type=docker,dest=docker-images/aarch64.tar . +endif + +docker-images/x86_64.tar: Dockerfile docker_entrypoint.sh datum_gateway icon.png INSTRUCTIONS.md check-bitcoin.sh check-blocknotify.sh check-dashboard.sh check-stratum.sh +ifeq ($(ARCH),aarch64) +else + mkdir -p docker-images + docker buildx build --tag start9/$(PKG_ID)/main:$(PKG_VERSION) --build-arg ARCH=x86_64 --build-arg PLATFORM=amd64 --platform=linux/amd64 -o type=docker,dest=docker-images/x86_64.tar . +endif + +$(PKG_ID).s9pk: manifest.yaml INSTRUCTIONS.md icon.png LICENSE scripts/embassy.js docker-images/aarch64.tar docker-images/x86_64.tar +ifeq ($(ARCH),aarch64) + @echo "start-sdk: Preparing aarch64 package ..." +else ifeq ($(ARCH),x86_64) + @echo "start-sdk: Preparing x86_64 package ..." +else + @echo "start-sdk: Preparing Universal Package ..." +endif + @start-sdk pack diff --git a/README.md b/README.md new file mode 100644 index 0000000..2fa2277 --- /dev/null +++ b/README.md @@ -0,0 +1,121 @@ +

+ Project Logo +

+ +# Datum for StartOS + +Datum is a simple, minimal project that serves as a template for creating a service that runs on StartOS. This repository creates the `s9pk` package that is installed to run `datum` on [StartOS](https://github.com/Start9Labs/start-os/). Learn more about service packaging in the [Developer Docs](https://start9.com/latest/developer-docs/). + +## Dependencies + +Install the system dependencies below to build this project by following the instructions in the provided links. You can find instructions on how to set up the appropriate build environment in the [Developer Docs](https://docs.start9.com/latest/developer-docs/packaging). + +- [docker](https://docs.docker.com/get-docker) +- [docker-buildx](https://docs.docker.com/buildx/working-with-buildx/) +- [yq](https://mikefarah.gitbook.io/yq) +- [deno](https://deno.land/) +- [make](https://www.gnu.org/software/make/) +- [start-sdk](https://github.com/Start9Labs/start-os/tree/sdk/) + +## Build environment +Prepare your StartOS build environment. In this example we are using Ubuntu 20.04. +1. Install docker +``` +curl -fsSL https://get.docker.com | bash +sudo usermod -aG docker "$USER" +exec sudo su -l $USER +``` +2. Set buildx as the default builder +``` +docker buildx install +docker buildx create --use +``` +3. Enable cross-arch emulated builds in docker +``` +docker run --privileged --rm linuxkit/binfmt:v0.8 +``` +4. Install yq +``` +sudo snap install yq +``` +5. Install deno +``` +sudo snap install deno +``` +6. Install essentials build packages +``` +sudo apt-get install -y build-essential openssl libssl-dev libc6-dev clang libclang-dev ca-certificates +``` +7. Install Rust +``` +curl https://sh.rustup.rs -sSf | sh +# Choose nr 1 (default install) +source $HOME/.cargo/env +``` +8. Build and install start-sdk +``` +git clone https://github.com/Start9Labs/start-os.git && \ + cd start-os && git submodule update --init --recursive && \ + make sdk +``` +Initialize sdk & verify install +``` +start-sdk init +start-sdk --version +``` +Now you are ready to build the `datum` package! + +## Cloning + +Clone the project locally: + +``` +git clone https://github.com/Start9Labs/datum-startos.git +cd datum-startos +git submodule update --init --recursive +``` + +## Building + +To build the `datum` package for all platforms using start-sdk, run the following command: + +``` +make +``` + +To build the `datum` package for a single platform using start-sdk, run: + +``` +# for amd64 +make x86 +``` +or +``` +# for arm64 +make arm +``` + +## Installing (on StartOS) + +Run the following commands to determine successful install: +> :information_source: Change server-name.local to your Start9 server address + +``` +start-cli auth login +# Enter your StartOS password +start-cli --host https://server-name.local package install datum.s9pk +``` + +If you already have your `start-cli` config file setup with a default `host`, you can install simply by running: + +``` +make install +``` + +> **Tip:** You can also install the datum.s9pk using **Sideload Service** under the **System > Manage** section. + +### Verify Install + +Go to your StartOS Services page, select **Datum**, configure and start the service. Then, verify its interfaces are accessible. + +**Done!** diff --git a/check-bitcoin.sh b/check-bitcoin.sh new file mode 100644 index 0000000..4f23c3c --- /dev/null +++ b/check-bitcoin.sh @@ -0,0 +1,19 @@ +#!/bin/bash + + + +read DURATION +if [ "$DURATION" -le 1000 ]; then + exit 60 +else + b_host="bitcoind.embassy" + b_username=$(yq e '.bitcoind.rpcuser' /root/start9/config.yaml) + b_password=$(yq e '.bitcoind.rpcpassword' /root/start9/config.yaml) + + b_gbc_result=$(curl -sS --user $b_username:$b_password --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getblocktemplate", "params": [{"rules": ["segwit"]}]}' -H 'content-type: application/json;' http://$b_host:8332/) + error_code=$? + if [ $error_code -ne 0 ]; then + echo $b_gbc_result >&2 + exit $error_code + fi +fi diff --git a/check-blocknotify.sh b/check-blocknotify.sh new file mode 100644 index 0000000..39a400e --- /dev/null +++ b/check-blocknotify.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +blocknotify=$(yq e '.bitcoind.blocknotify' "/root/start9/config.yaml") + +if [ "$blocknotify" = "null" ] || [ -z "$blocknotify" ]; then + echo "Error: The blocknotify field is null or not set in Bitcoin's configuration. Your Start9 Bitcoin package may not support adding this. Knots is required." >&2 + exit 1 +fi + +if [ "$blocknotify" != "curl -s -m5 http://datum.embassy:7152/NOTIFY" ]; then + echo "Error: The blocknotify field is not set correctly. Please delete it and auto-configure Knots from Datum Gateway then restart Datum Gateway." >&2 + exit 1 +fi \ No newline at end of file diff --git a/check-dashboard.sh b/check-dashboard.sh new file mode 100644 index 0000000..6fc53cc --- /dev/null +++ b/check-dashboard.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +read DURATION +if [ "$DURATION" -le 1000 ]; then + exit 60 +else + if curl -sS http://datum.embassy:7152 >/dev/null; then + exit 0 + else + echo "The dashboard is not ready" >&2 + exit 1 + fi +fi diff --git a/check-stratum.sh b/check-stratum.sh new file mode 100644 index 0000000..ba621b3 --- /dev/null +++ b/check-stratum.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +read DURATION +if [ "$DURATION" -le 1000 ]; then + exit 60 +else + if nc -z -w2 127.0.0.1 23335 >/dev/null; then + exit 0 + else + echo "The stratum server does not seem to be responding to requests" >&2 + exit 1 + fi +fi diff --git a/datum_gateway b/datum_gateway new file mode 160000 index 0000000..206104c --- /dev/null +++ b/datum_gateway @@ -0,0 +1 @@ +Subproject commit 206104c6828ba6d46edeb52d802f23e3969a4f5d diff --git a/docker_entrypoint.sh b/docker_entrypoint.sh new file mode 100755 index 0000000..8558020 --- /dev/null +++ b/docker_entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +mkdir -p /root/data + +blocknotify=$(yq e '.bitcoind.blocknotify' "/root/start9/config.yaml") + +if [ "$blocknotify" = "null" ] || [ -z "$blocknotify" ]; then + echo "Error: The blocknotify field is null or not set in Bitcoin's configuration. Your Start9 Bitcoin package may not support adding this. Knots is required." + exit 1 +else + echo "blocknotify is set to: $blocknotify" +fi + +yq eval -o=json /root/start9/config.yaml > /root/data/datum_gateway_config.json +printf "\n\n [i] Starting Datum Gateway ...\n\n" + +exec datum_gateway -c /root/data/datum_gateway_config.json \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..4320f97 Binary files /dev/null and b/icon.png differ diff --git a/manifest.yaml b/manifest.yaml new file mode 100644 index 0000000..d3f87ac --- /dev/null +++ b/manifest.yaml @@ -0,0 +1,165 @@ +# Example written in yaml (toml and json are also acceptable) + +# The package identifier used by the OS. This must be unique amongst all other known packages +id: datum + # A human readable service title +title: "Datum Gateway" +# Service version - accepts up to four digits, where the last confirms to revisions necessary for StartOS - see documentation: https://github.com/Start9Labs/emver-rs. This value will change with each release of the service. +version: 0.1.0 +# Release notes for the update - can be a string, paragraph or URL +release-notes: | + - Initial Release +license: MIT +wrapper-repo: "https://github.com/ocean-xyz/datum-gateway-startos" +upstream-repo: "https://github.com/ocean-xyz/datum-gateway" +support-site: "https://ocean.xyz" +marketing-site: "https://ocean.xyz" +build: ["make"] +description: + short: Make block templates and issue work to your miners + long: | + Datum-gateway allows miners to use their Bitcoin node to generate their own templates and issue work to their miners while still sharing rewards on a pool or solo mining. +assets: + license: LICENSE + icon: icon.png + instructions: INSTRUCTIONS.md +main: + type: docker + image: main + entrypoint: "docker_entrypoint.sh" + args: [] + mounts: + main: /root + gpu-acceleration: false +hardware-requirements: + arch: + - x86_64 + - aarch64 +health-checks: + dashboard: + name: Datum Dashboard + success-message: The Datum-gateway dashboard is accessible. + type: docker + image: main + system: false + entrypoint: check-dashboard.sh + args: [] + mounts: {} + io-format: json + inject: true + stratum: + name: Stratum Interface + success-message: Stratum port is available. Ensure you're forwarding with simpleproxy and then connect your miner(s). + type: docker + image: main + system: false + entrypoint: check-stratum.sh + args: [] + mounts: {} + io-format: json + inject: true + bitcoin: + name: Bitcoin RPC + success-message: Bitcoin RPC available. + type: docker + image: main + system: false + entrypoint: check-bitcoin.sh + args: [] + mounts: {} + io-format: json + inject: true + blocknotify: + name: Bitcoind Blocknotify Setting + success-message: blocknotify set correctly. + type: docker + image: main + system: false + entrypoint: check-blocknotify.sh + args: [] + mounts: {} + io-format: json + inject: true +config: + get: + type: script + set: + type: script +properties: ~ +volumes: + main: + type: data +interfaces: + main: + name: Web UI + description: Dashboard for Datum-gateway + tor-config: + port-mapping: + 80: "7152" + lan-config: + 443: + ssl: true + internal: 7152 + ui: true + protocols: + - tcp + - http + mining: + name: Mining Interface + description: Point your ASICs here! + lan-config: + 23335: + ssl: false + internal: 23335 + ui: false + protocols: + - tcp + - stratum + - http +dependencies: + bitcoind: + version: ">=0.21.1.2 <29.0.0" + requirement: + type: "required" + description: Used to generate block templates + config: + check: + type: script + auto-configure: + type: script +backup: + create: + type: docker + image: compat + system: true + entrypoint: compat + args: + - duplicity + - create + - /mnt/backup + - /root + mounts: + BACKUP: "/mnt/backup" + main: "/root/data" + restore: + type: docker + image: compat + system: true + entrypoint: compat + args: + - duplicity + - restore + - /mnt/backup + - /root + mounts: + BACKUP: "/mnt/backup" + main: "/root/data" +migrations: + from: + "*": + type: script + args: ["from"] + to: + "*": + type: script + args: ["to"] diff --git a/scripts/deps.ts b/scripts/deps.ts new file mode 100644 index 0000000..090054d --- /dev/null +++ b/scripts/deps.ts @@ -0,0 +1 @@ +export * from "https://deno.land/x/embassyd_sdk@v0.3.1.1.2/mod.ts"; diff --git a/scripts/embassy.ts b/scripts/embassy.ts new file mode 100644 index 0000000..14d127a --- /dev/null +++ b/scripts/embassy.ts @@ -0,0 +1,5 @@ +export { setConfig } from "./procedures/setConfig.ts"; +export { getConfig } from "./procedures/getConfig.ts"; +export { properties } from "./procedures/properties.ts"; +export { migration } from "./procedures/migrations.ts"; +export { dependencies } from "./procedures/dependencies.ts"; diff --git a/scripts/procedures/dependencies.ts b/scripts/procedures/dependencies.ts new file mode 100644 index 0000000..0d12572 --- /dev/null +++ b/scripts/procedures/dependencies.ts @@ -0,0 +1,36 @@ +import { matches, types as T } from "../deps.ts"; + +const { shape, boolean, string, any } = matches; + +const matchOldBitcoindConfig = shape({ + rpc: shape({ + enable: boolean + }), + advanced: any +}) + +export const dependencies: T.ExpectedExports.dependencies = { + bitcoind: { + // deno-lint-ignore require-await + async check(_effects, configInput) { + if (matchOldBitcoindConfig.test(configInput) && !configInput.rpc.enable) { + return { error: "Must have RPC enabled" }; + } else if (matchOldBitcoindConfig.test(configInput) && (!configInput.advanced.blocknotify)) { + return { error: "Blocknotify must not be null" }; + } else if (matchOldBitcoindConfig.test(configInput)) { + return { result: null } + } + return { result: null }; + }, + // deno-lint-ignore require-await + async autoConfigure(_effects, configInput) { + if (matchOldBitcoindConfig.test(configInput)) { + configInput.rpc.enable = true; + configInput.advanced.blocknotify = "curl -s -m5 http://datum.embassy:7152/NOTIFY"; + return { result: configInput } + } else { + return { result: configInput }; + } + }, + }, +}; diff --git a/scripts/procedures/getConfig.ts b/scripts/procedures/getConfig.ts new file mode 100644 index 0000000..72c854d --- /dev/null +++ b/scripts/procedures/getConfig.ts @@ -0,0 +1,331 @@ +// // To utilize the default config system built, this file is required. It defines the *structure* of the configuration file. These structured options display as changeable UI elements within the "Config" section of the service details page in the StartOS UI. + +import { compat, types as T } from "../deps.ts"; + +export const getConfig: T.ExpectedExports.getConfig = compat.getConfig({ + "bitcoind": { + type: "object", + name: "Bitcoin RPC settings", + description: "RPC settings for bitcoind", + spec: { + rpcuser: { + type: "pointer", + name: "RPC Username", + description: "The username for Bitcoin Core's RPC interface", + subtype: "package", + "package-id": "bitcoind", + target: "config", + multi: false, + selector: "$.rpc.username", + }, + rpcpassword: { + type: "pointer", + name: "RPC Password", + description: "The password for Bitcoin Core's RPC interface", + subtype: "package", + "package-id": "bitcoind", + target: "config", + multi: false, + selector: "$.rpc.password", + }, + rpcurl: { + type: "string", + name: "RPC URL", + description: "RPC URL for communication with local bitcoind. (GBT Template Source)", + nullable: false, + default: "http://bitcoind.embassy:8332", + }, + work_update_seconds: { + type: "number", + name: "Work Update (Seconds)", + description: "How frequently should Bitcoind send updated templates", + nullable: true, + range: "[5,120)", + integral: true, + default: 40, + units: "seconds", + }, + blocknotify: { + type: "pointer", + name: "Block Notify", + description: "Does Bitcoind have blocknotify? This should say curl -s -m5 http://datum.embassy:7152/NOTIFY", + subtype: "package", + "package-id": "bitcoind", + target: "config", + multi: false, + selector: "$.advanced.blocknotify", + }, + //notify_fallback? + }, + }, + "stratum": { + type: "object", + name: "Stratum Server Settings", + description: "Configure the Datum gateway's stratum server.", + spec: { + listen_port: { + type: "number", + name: "Listen Port", + description: "Listening port for Stratum Gateway.", + nullable: true, + range: "[0,65535]", + integral: false, + default: 23335, + }, + max_clients_per_thread: { + type: "number", + name: "Maximum Clients Per Thread", + description: "Maximum clients per Stratum server thread.", + nullable: true, + range: "[0,*)", + integral: true, + default: 1000, + }, + max_threads: { + type: "number", + name: "Max Threads", + description: "Maximum Stratum server threads (integer, default: 8)", + nullable: true, + range: "[0,*)", + integral: true, + default: 8, + }, + max_clients: { + type: "number", + name: "Max Clients", + description: "Maximum total Stratum clients before rejecting connections (integer, default: 2048)", + nullable: true, + range: "[0,*)", + integral: true, + default: 2048, + }, + vardiff_min: { + type: "number", + name: "Minimum Difficulty", + description: "Work difficulty floor (integer, default: 16384)", + nullable: true, + range: "[0,*)", + integral: true, + default: 16384, + }, + vardiff_target_shares_min: { + type: "number", + name: "Target Shares per Minute", + description: "Adjust work difficulty to target this many shares per minute (integer, default: 8)", + nullable: true, + range: "[0,*)", + integral: true, + default: 8, + }, + vardiff_quickdiff_count: { + type: "number", + name: "Difficulty Update Speed", + description: "How many shares before considering a quick diff update (integer, default: 8)", + nullable: true, + range: "[0,*)", + integral: true, + default: 8, + }, + vardiff_quickdiff_delta: { + type: "number", + name: "Difficulty Delta", + description: "How many times faster than our target does the miner have to be before we enforce a quick diff bump (integer, default: 8)", + nullable: true, + range: "[0,*)", + integral: true, + default: 8, + }, + share_stale_seconds: { + type: "number", + name: "Seconds Until Shares Considered Stale", + description: "How many seconds after a job is generated before a share submission is considered stale? (integer, default: 120)", + nullable: true, + range: "[0,*)", + integral: true, + default: 120, + }, + fingerprint_miners: { + type: "boolean", + name: "Fingerprint Miners", + description: "Attempt to fingerprint miners for better use of coinbase space (boolean, default: true)", + default: true, + nullable: false, + }, + // empty_block_speedup: { + // type: "boolean", + // name: "Empty Block Speedup", + // description: "Get on the latest block as fast as possible by sending blank work first (highly recommended) (boolean, default: true)", + // default: true, + // nullable: false, + // }, + }, + }, + "mining": { + type: "object", + name: "Mining Settings", + description: "Mining settings", + spec: { + pool_address: { + type: "string", + name: "Bitcoin Address", + description: "Bitcoin address used for mining on DATUM Pool, and for solo mining rewards.", + nullable: false, + pattern: "[0-9a-zA-Z]{20,88}", + "pattern-description": + "Must be a valid Bitcoin address.", + }, + coinbase_tag_primary: { + type: "string", + name: "Primary Coinbase Tag", + description: "Text to have in the primary coinbase tag when solo (overridden by DATUM Pool with the pool's name.)", + default: "Datum User", + nullable: true, + }, + coinbase_tag_secondary: { + type: "string", + name: "Secondary Coinbase Tag", + description: "Text to have in the secondary coinbase tag. If you're mining on a pool, this is what you label your blocks with.", + default: "Datum Miner", + nullable: true, + }, + // coinbase_tag_tertiary: { + // type: "string", + // name: "Tertiary Coinbase Tag", + // description: "Text to have in the tertiary coinbase tag. Suggested to be a longer name/description/url/etc", + // default: "Datum User", + // nullable: true, + // }, + coinbase_unique_id: { + type: "number", + name: "Coinbase Unique ID", + description: "A unique ID between 1 and 65535. This is appended to the coinbase. Make unique per instance of datum with the same coinbase tags.", + integral: true, + range: "[1,65535]", + default: 120, + nullable: true, + }, + }, + }, + "api": { + type: "object", + name: "API", + description: "Settings for the Datum Gateway Dashboard", + spec: { + listen_port: { + type: "number", + name: "Listen Port", + description: "Listening port for Datum Gateway Dashboard.", + nullable: false, + range: "[0,65535]", + integral: true, + default: 7152, + }, + }, + }, + // "extra_block_submissions": { + // type: "object", + // name: "Extra Block Submissions", + // description: "Additional places to submit solved blocks", + // spec: { + // type: "string", + // name: "URL", + // descrption: "Array of bitcoind RPC URLs to submit our blocks to directly. Include auth info: http://user:pass@IP (string_array)", + // nullable: true, + // }, + // }, + "logger": { + type: "object", + name: "Logger", + description: "Log Settings", + spec: { + log_level_console: { + type: "number", + name: "Log Level Console", + description: "Minimum log level for console messages (0=All, 1=Debug, 2=Info, 3=Warn, 4=Error, 5=Fatal) (integer, default: 2)", + integral: true, + range: "[0,5)", + default: 2, + nullable: false, + }, + }, + }, + "datum":{ + type: "object", + name: "Datum", + description: "Datum-Gateway settings. These are set to mine on OCEAN by default. Modify to switch to another Datum-supporting pool, or to solo mine.", + spec: { + pool_host: { + type: "string", + name: "Pool Host", + description: "Remote DATUM server host/ip to use for decentralized pooled mining (string, default: datum.mine.ocean.xyz)", + default: "datum.mine.ocean.xyz", + nullable: true, + }, + pool_port: { + type: "number", + name: "Pool Port", + description: "Remote DATUM server port (integer, default: 28915)", + range: "[0,65535]", + default: 28915, + integral: true, + nullable: true, + }, + pool_pubkey: { + type: "string", + name: "Pool Pubkey", + description: "Public key of the DATUM server for initiating encrypted connection. Get from secure location, or set to empty to auto-fetch.", + default: "f21f2f0ef0aa1970468f22bad9bb7f4535146f8e4a8f646bebc93da3d89b1406f40d032f09a417d94dc068055df654937922d2c89522e3e8f6f0e649de473003", + nullable: true, + }, + // pool_username: { + // type: "string", + // name: "Pool Username", + // description: "Pool username when using DATUM, if different than mining.pool_address (string, defaults to empty)", + // default: "", + // nullable: true, + // }, + pool_pass_workers: { + type: "boolean", + name: "Pool Pass Workers", + description: "Pass stratum miner usernames as sub-worker names to the pool (boolean, default: true)", + default: true, + nullable: true, + }, + pool_pass_full_users: { + type: "boolean", + name: "Pool Pass Full Users", + description: "Pass stratum miner usernames as raw usernames to the pool (use if putting multiple payout addresses on miners behind this gateway)", + default: true, + nullable: true, + }, + always_pay_self: { + type: "boolean", + name: "Always Pay Self", + description: "Always include my datum.pool_username payout in my blocks if possible (boolean, default: true)", + default: true, + nullable: true, + }, + // pay_self_below_minimum: { + // type: "boolean", + // name: "Pay Self Below Minimum", + // description: "If datum.always_pay_self, include even if below the pool's minimum payout (boolean, default: false)", + // default: false, + // nullable: true, + // }, + // allow_low_local_diff: { + // type: "boolean", + // name: "Allow Low Local Diff", + // description: "Do full local stratum vardiff even if below the pool's minimum difficulty for my connection. (boolean, default: false)", + // default: false, + // nullable: true, + // }, + pooled_mining_only: { + type: "boolean", + name: "Pooled Mining Only", + description: "If the DATUM pool server becomes unavailable, terminate miner connections (otherwise, 100% of any blocks you find pay mining.pool_address) (boolean, default: true)", + default: true, + nullable: true, + }, + }, + }, +}); diff --git a/scripts/procedures/migrations.ts b/scripts/procedures/migrations.ts new file mode 100644 index 0000000..fe4371e --- /dev/null +++ b/scripts/procedures/migrations.ts @@ -0,0 +1,4 @@ +import { compat, types as T } from "../deps.ts"; + +export const migration: T.ExpectedExports.migration = compat.migrations + .fromMapping({}, "0.3.5" ); diff --git a/scripts/procedures/properties.ts b/scripts/procedures/properties.ts new file mode 100644 index 0000000..dff99aa --- /dev/null +++ b/scripts/procedures/properties.ts @@ -0,0 +1,3 @@ +import { compat, types as T } from "../deps.ts"; + +export const properties: T.ExpectedExports.properties = compat.properties; diff --git a/scripts/procedures/setConfig.ts b/scripts/procedures/setConfig.ts new file mode 100644 index 0000000..be7d2db --- /dev/null +++ b/scripts/procedures/setConfig.ts @@ -0,0 +1,9 @@ +// This is where any configuration rules related to the configuration would go. These ensure that the user can only create a valid config. + +//import { compat, } from "../deps.ts"; + +//export const setConfig = compat.setConfig; + +import { compat, types as T } from "../deps.ts"; + +export const setConfig: T.ExpectedExports.setConfig = compat.setConfig;