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
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,34 @@ The server can be configured through environment variables or by modifying the d

### Bitcoin Core Configuration

Configure the Bitcoin Core RPC connection:
Configure the Bitcoin Core RPC connection using either a cookie file or username/password.

#### Cookie file authentication (recommended)

When Bitcoin Core is started without explicit `rpcuser`/`rpcpassword` settings, it
generates a `.cookie` file in its data directory. Point the server at this file:

```
BITCOIN_RPC_URL=http://127.0.0.1:38332 # Bitcoin Core RPC URL
BITCOIN_RPC_COOKIE_FILE=~/.bitcoin/.cookie # Path to cookie file
```
BITCOIN_RPC_URL=http://127.0.0.1:38332 # Bitcoin Core RPC host

The cookie file is re-read at server startup. If Bitcoin Core restarts (and
generates a new cookie), the server must be restarted as well.

#### Username/password authentication

Alternatively, configure explicit RPC credentials:

```
BITCOIN_RPC_URL=http://127.0.0.1:38332 # Bitcoin Core RPC URL
BITCOIN_RPC_USER=user # Bitcoin Core RPC username
BITCOIN_RPC_PASS=password # Bitcoin Core RPC password
```

If `BITCOIN_RPC_COOKIE_FILE` is set, it takes priority over `BITCOIN_RPC_USER`
and `BITCOIN_RPC_PASS`.

### Layer 2 Configuration

Configure Layer 2 CLI paths and RPC connections:
Expand Down
44 changes: 41 additions & 3 deletions config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { access, constants } = require('fs/promises');
const { access, constants, readFile } = require('fs/promises');
const path = require('path');
const axios = require('axios');
const { makeRpcCallBTC } = require('./utils/bitcoin-rpc');
Expand Down Expand Up @@ -43,6 +43,31 @@ async function verifyExecutable(filePath, name) {
}
}

// Read Bitcoin Core cookie file and return { user, password }
async function readCookieFile(cookieFile) {
const expandedPath = cookieFile.replace(/^~/, process.env.HOME);
const resolvedPath = path.resolve(expandedPath);
try {
const contents = (await readFile(resolvedPath, 'utf-8')).trim();
const separatorIndex = contents.indexOf(':');
if (separatorIndex === -1) {
throw new Error(`Invalid cookie file format in ${resolvedPath}: expected "user:password"`);
}
return {
user: contents.substring(0, separatorIndex),
password: contents.substring(separatorIndex + 1)
};
} catch (error) {
if (error.code === 'ENOENT') {
throw new Error(`Bitcoin Core cookie file not found at ${resolvedPath}. Is Bitcoin Core running?`);
}
if (error.code === 'EACCES') {
throw new Error(`Permission denied reading cookie file at ${resolvedPath}.`);
}
throw error;
}
}

// Verify Bitcoin Core RPC connection
async function verifyBitcoinRpc(config) {
try {
Expand All @@ -52,7 +77,10 @@ async function verifyBitcoinRpc(config) {
if (error.code === 'ECONNREFUSED') {
throw new Error(`Could not connect to Bitcoin Core at ${config.bitcoin.host}:${config.bitcoin.port}`);
} else if (error.response && error.response.status === 401) {
throw new Error('Bitcoin Core RPC authentication failed. Check your username and password.');
const hint = config.bitcoin.cookieFile
? 'Check your cookie file path.'
: 'Check your username and password.';
throw new Error(`Bitcoin Core RPC authentication failed. ${hint}`);
}
throw new Error(`Bitcoin Core RPC verification failed: ${error.message}`);
}
Expand Down Expand Up @@ -89,6 +117,15 @@ async function verifyBitNamesConnection(config) {
// Verify all CLI tools are available
async function verifyConfig(config) {
try {
// If cookie file is configured, read credentials from it
if (config.bitcoin.cookieFile) {
console.log('Reading Bitcoin Core cookie file...');
const cookie = await readCookieFile(config.bitcoin.cookieFile);
config.bitcoin.user = cookie.user;
config.bitcoin.password = cookie.password;
console.log('Cookie file read successfully');
}

// First verify Bitcoin Core connection
console.log('Verifying Bitcoin Core RPC connection...');
await verifyBitcoinRpc(config);
Expand Down Expand Up @@ -122,7 +159,8 @@ const config = {
bitcoin: {
url: process.env.BITCOIN_RPC_URL || defaultConfig.bitcoin.url,
user: process.env.BITCOIN_RPC_USER || defaultConfig.bitcoin.user,
password: process.env.BITCOIN_RPC_PASS || defaultConfig.bitcoin.password
password: process.env.BITCOIN_RPC_PASS || defaultConfig.bitcoin.password,
cookieFile: process.env.BITCOIN_RPC_COOKIE_FILE || null
},
thunder: {
cliPath: process.env.THUNDER_CLI_PATH || defaultConfig.thunder.cliPath,
Expand Down