Skip to content

Dashmate is incorrectly generating the rpcauth credentials on first restart #2497

Open

Description

@ktechmidas

Expected Behavior

rpccredentials should be put inside dash.conf correctly when running dashmate restart after changing them in the config.json

Current Behavior

The password is 1234567

Hashing in dash.conf is as follows:
rpcauth=dashrpc:a512ab492f0faed0ba66e9240e34e961$5e001c5d08dd753958047e39d742154dee89d247af07ee237da751b0f72c9740

Change password to 123456789 in the config.json

Run dashmate restart

dashmate@hp-masternode-1:~/.dashmate$ curl http://127.0.0.1:20002 --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getbestblockhash", "params": []}' -H 'Content-Type: application/json' --user dashrpc:123456789 -X POST -i
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="jsonrpc"
Date: Fri, 14 Mar 2025 09:07:48 GMT
Content-Length: 0
Content-Type: text/html; charset=ISO-8859-1

Hashing as follows:
rpcauth=dashrpc:8463fda0e18385de17be64d5f4ba7aa6$26245e43ea7593569d0a1c41940dce498ef1a78f434ea83a239e2fb87ad391ad

Run dashmate restart again without changing the config and curl works:

dashmate@hp-masternode-1:~/.dashmate$ curl http://127.0.0.1:20002 --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getbestblockhash", "params": []}' -H 'Content-Type: application/json' --user dashrpc:123456789 -X POST -i
HTTP/1.1 200 OK
Content-Type: application/json
Date: Fri, 14 Mar 2025 09:09:27 GMT
Content-Length: 107

{"result":"000000e808c758463dbf41480e1a579ab5b05b96c146b094838c309d3ad8b01d","error":null,"id":"curltest"}

Hashing is as follows in the dash.conf

rpcauth=dashrpc:6b4e1f9358596c8bf19cd4cf219278f3$e38553ba9b93b0ab0e953dbee8ea8723f20a3ec1ec4b56724bdefd6d0765dd29

Possible Solution

As we can see, the hashing changes between the two restarts. The first restart appears not to read the config file with an updated password correctly.

Steps to Reproduce (for bugs)

Steps above

Context

This bug ensures rpc can't be connected to properly with a password change until two dashmate restarts have been done

Your Environment

  • Version used: 2.0.0-dev.1
  • Environment name and version (e.g. Chrome 39, node.js 5.4):
  • Operating System and version (desktop, server, or mobile): Ubuntu 24.04 server
  • Link to your project:

Activity

  1. added
    dashmateDashmate related
    effort: SSmall effort — a few hours or less
    staleLikely outdated — candidate for closing
    priority: lowLow priority — nice to have
    and removed
    staleLikely outdated — candidate for closing
    on Mar 12, 2026
  2. bezibalazs commented on Aug 28, 2026

    @bezibalazs
    Collaborator

    Triage on current master (507192c, v4.x) — this still reproduces, and the
    mechanism is an ordering one rather than anything wrong with the credential
    generation.

    The rendering itself is correct. templates/core/dash.conf.dot:39-41
    generates a fresh random salt per render and HMACs the password with it, so a
    rendered rpcauth always verifies against the password it was rendered from.
    I checked this without Docker by driving the real template through the real
    renderTemplateFactory code path (script below):

    • a render of password X authenticates X and rejects the old password
    • two renders of the same password produce different hashes — expected,
      the salt is crypto.randomBytes(16) each time

    So the "different hash on the second restart" in the report is by design, not a
    symptom. Worth ruling out before anyone goes looking in the template.

    The actual problem is when rendering happens. writeConfigTemplates — the
    thing that regenerates dash.conf — is only called from
    src/oclif/command/BaseCommand.js:190-196, inside the command's finally
    teardown, and only when configFile.isChanged().

    restart is stopNodeTask → startNodeTask
    (src/listr/tasks/restartNodeTaskFactory.js:22-31); neither renders, and
    ConfigBaseCommand adds no render step either. So containers are always started
    from whatever dash.conf is already on disk, and any re-render happens
    strictly afterwards. A config change therefore cannot affect the containers
    started by the same invocation — it lands on the next start. That is the
    "two restarts" symptom.

    There is a second path worth separating out. Nothing in stop/start calls
    config.set(), and Config.changed is only set there
    (src/config/Config.js:222). A config freshly read from disk reports
    isChanged() === false (asserted in the script). So if the password was changed
    by hand-editing config.json rather than via dashmate config set, the
    render is skipped entirely and no number of restarts fixes it — dashmate config render is the only thing that syncs it.

    That distinction matters for what the fix should be, and I can't tell from the
    report which path was taken. @ktechmidas — do you remember whether you edited
    config.json directly, or used dashmate config set?

    Unchanged since the report. I diffed BaseCommand.js at 7b569ab
    (2025-03-14, the day this was filed) against master: the render was in
    async finally() then and is in teardown now. #4248 reworked the locking around
    it but not the ordering.

    Shape of a fix, for whoever picks this up — the choice is a design call, not
    obvious to me:

    1. Render service configs at the start of any command that brings containers
      up, rather than in teardown. Most correct, touches the most.
    2. Have startNodeTask render before dockerCompose.up. Narrower, leaves other
      commands with the same latent gap.
    3. Detect on load that config.json is newer than the rendered dash.conf and
      re-render (also fixes the hand-edit path).

    Repro script (no Docker needed) — drop in packages/dashmate/ and run
    node repro-2497.mjs. It uses the real base config and real template:

    ✓ the template renders a valid rpcauth for the password it is given
    ✓ two renders of the SAME password produce DIFFERENT hashes (random salt)
    ✓ an old-password render does NOT authenticate the new password
    ✓ a freshly loaded config is NOT marked changed; only set() marks it
    4/4 passed
    

    I have not been able to run dashmate end-to-end (no Docker in my environment),
    so the container-level behaviour is inferred from the call graph rather than
    observed. Everything above the "shape of a fix" section is verified against the
    code; the two-restart sequence specifically is not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdashmateDashmate relatedeffort: SSmall effort — a few hours or lesspriority: lowLow priority — nice to havepriority: mediumMedium priority

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions