Skip to content
This repository was archived by the owner on Jun 30, 2025. It is now read-only.
Closed
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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Setup libsecret for node-keytar
run: |
sudo apt install gnome-keyring
sudo dbus-launch /usr/bin/gnome-keyring-daemon --unlock
if: startsWith(matrix.os, 'ubuntu-')
- run: npm ci --omit=dev
- run: npm ci
- run: npm run test:types
Expand All @@ -34,6 +39,8 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Setup libsecret for node-keytar
run: sudo apt install gnome-keyring
- run: npm ci
- run: npm run test:unit
env:
Expand Down Expand Up @@ -66,6 +73,9 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Setup libsecret for node-keytar
run: sudo apt install gnome-keyring

- name: Build and load Docker image
id: docker_build
uses: docker/build-push-action@v5
Expand Down
6 changes: 5 additions & 1 deletion commands/station.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { startPingLoop } from '../lib/telemetry.js'
import fs from 'node:fs/promises'
import { metrics } from '../lib/metrics.js'
import { paths } from '../lib/paths.js'
import { getStationId } from '../lib/station-id.js'
import pRetry from 'p-retry'
import { fetch } from 'undici'
import { ethAddressFromDelegated } from '@glif/filecoin-address'
Expand All @@ -22,6 +23,8 @@ const panic = msg => {
}

export const station = async ({ json, experimental }) => {
const STATION_ID = (await getStationId()).publicKey
Comment thread
bajtos marked this conversation as resolved.

if (!FIL_WALLET_ADDRESS) panic('FIL_WALLET_ADDRESS required')
if (FIL_WALLET_ADDRESS.startsWith('f1')) {
panic('f1 addresses are currently not supported. Please use an f4 or 0x address')
Expand All @@ -46,7 +49,7 @@ export const station = async ({ json, experimental }) => {
? FIL_WALLET_ADDRESS
: ethAddressFromDelegated(FIL_WALLET_ADDRESS)

startPingLoop().unref()
startPingLoop({ STATION_ID }).unref()
for (const moduleName of moduleNames) {
await fs.mkdir(join(paths.moduleCache, moduleName), { recursive: true })
await fs.mkdir(join(paths.moduleState, moduleName), { recursive: true })
Expand Down Expand Up @@ -82,6 +85,7 @@ export const station = async ({ json, experimental }) => {

const modules = [
zinniaRuntime.run({
STATION_ID,
FIL_WALLET_ADDRESS,
ethAddress,
STATE_ROOT: join(paths.moduleState, 'zinnia'),
Expand Down
24 changes: 24 additions & 0 deletions lib/station-id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import keytar from 'keytar'
import { subtle } from 'node:crypto'

const SERVICE_NAME = 'filecoin-station-core'

export async function getStationId () {
const storedKeys = await keytar.getPassword(SERVICE_NAME, 'station_id')
if (storedKeys) {
return JSON.parse(storedKeys)
}

const keyPair = /** @type {import('node:crypto').webcrypto.CryptoKeyPair} */(
/** @type {unknown} */(
await subtle.generateKey({ name: 'ED25519' }, true, ['sign', 'verify'])
)
)
const publicKey = await subtle.exportKey('spki', keyPair.publicKey)
const privateKey = await subtle.exportKey('pkcs8', keyPair.privateKey)

const keysToStore = JSON.stringify({ publicKey, privateKey })
await keytar.setPassword(SERVICE_NAME, 'station_id', keysToStore)

return { publicKey, privateKey }
}
3 changes: 2 additions & 1 deletion lib/telemetry.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ setInterval(() => {
})
}, 5_000).unref()

export const startPingLoop = () => {
export const startPingLoop = ({ STATION_ID }) => {
assert(FIL_WALLET_ADDRESS)
const processUUID = randomUUID()
return setInterval(() => {
Expand All @@ -53,6 +53,7 @@ export const startPingLoop = () => {
'wallet',
createHash('sha256').update(FIL_WALLET_ADDRESS).digest('hex')
)
point.stringField('station_id', STATION_ID)
point.stringField('process_uuid', processUUID)
point.stringField('version', pkg.version)
point.tag('station', 'core')
Expand Down
3 changes: 3 additions & 0 deletions lib/zinnia.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ const catchChildProcessExit = async ({
}

export async function run ({
STATION_ID,
FIL_WALLET_ADDRESS,
ethAddress,
STATE_ROOT,
Expand Down Expand Up @@ -354,6 +355,7 @@ export async function run ({
{
cwd: moduleSourcesDir,
env: {
STATION_ID,
FIL_WALLET_ADDRESS,
STATE_ROOT,
CACHE_ROOT
Expand Down Expand Up @@ -410,6 +412,7 @@ export async function run ({
// This infinite recursion has no risk of exceeding the maximum call stack
// size, as awaiting promises unwinds the stack
return run({
STATION_ID,
FIL_WALLET_ADDRESS,
ethAddress,
STATE_ROOT,
Expand Down
Loading