Skip to content

Latest commit

 

History

History
380 lines (292 loc) · 8.7 KB

File metadata and controls

380 lines (292 loc) · 8.7 KB

server

HTTP REST API server for the multisig coordinator, powered by the multisig engine.

architecture

The server is built with axum and wraps the multisig engine to expose HTTP endpoints for multisig operations. All business logic is handled by the engine - the server layer simply handles HTTP request/response serialization and validation.

On startup, the server:

  1. Establishes a PostgreSQL connection pool.
  2. Creates and starts a MultisigEngine with a dedicated Miden runtime thread.
  3. Wraps the engine in an App state accessible to all route handlers.
  4. Binds to the configured TCP listener.

configuration

Configuration is loaded from base_config.ron and can be overridden via environment variables with the prefix MIDENMULTISIG_.

base configuration

Config(
    app: AppConfig(
        listen: "localhost:59059",
        network_id_hrp: "mtst",
        cors_allowed_origins: ["*"],
    ),
    db: DbConfig(
        db_url: "postgres://multisig:multisig_password@localhost:5432/multisig",
        max_conn: 10,
    ),
    miden: MidenConfig(
        node_url: "https://rpc.testnet.miden.io:443",
        store_path: "./store",
        keystore_path: "./keystore",
        timeout: "30s",
    ),
)

CORS Configuration

The cors_allowed_origins field controls which origins can make cross-origin requests to the server:

  • Empty array []: CORS is disabled
  • Specific origins: Only listed origins are allowed, e.g., ["http://localhost:3000", "https://example.com"]
  • Wildcard ["*"]: All origins are allowed (permissive mode, default for development)

By default, the base configuration uses ["*"] to allow all CORS requests for local development convenience. For production deployments, it's recommended to override this with specific allowed origins.

environment variable overrides

Use double underscores (__) to override nested configuration fields:

# override app config
export MIDENMULTISIG_APP__LISTEN="0.0.0.0:8080"
export MIDENMULTISIG_APP__NETWORK_ID_HRP="mtst"

# configure CORS allowed origins for specific origins
export MIDENMULTISIG_APP__CORS_ALLOWED_ORIGINS='["http://localhost:3000", "http://example.com"]'

# override database config
export MIDENMULTISIG_DB__DB_URL="postgres://user:pass@db-host:5432/multisig"
export MIDENMULTISIG_DB__MAX_CONN="20"

# override miden config
export MIDENMULTISIG_MIDEN__NODE_URL="https://rpc.testnet.miden.io:443"
export MIDENMULTISIG_MIDEN__STORE_PATH="./miden-store.sqlite3"
export MIDENMULTISIG_MIDEN__KEYSTORE_PATH="./keystore"
export MIDENMULTISIG_MIDEN__TIMEOUT="60s"

database setup

Before starting the server, ensure database migrations have been run. See the database migrations section for detailed instructions.

running the server

# using cargo
cargo run --bin miden-multisig-coordinator-server --release

http api

health check

Check if the server is running.

curl -X GET http://localhost:59059/health

Response: 200 OK


create multisig account

Creates a new multisig account with specified approvers and threshold.

Endpoint: POST /api/v1/multisig-account/create

curl -X POST http://localhost:59059/api/v1/multisig-account/create \
  -H "Content-Type: application/json" \
  -d '{
    "threshold": 2,
    "approvers": [
      "mtst1abc...",
      "mtst1def...",
      "mtst1ghi..."
    ],
    "pub_key_commits": [
      "<base64_encoded_public_key_1>",
      "<base64_encoded_public_key_2>",
      "<base64_encoded_public_key_3>"
    ]
  }'

Response:

{
  "address": "mtst1xyz...",
  "created_at": "2025-10-19T12:00:00Z",
  "updated_at": "2025-10-19T12:00:00Z"
}

propose transaction

Proposes a new transaction for a multisig account.

Endpoint: POST /api/v1/multisig-tx/propose

curl -X POST http://localhost:59059/api/v1/multisig-tx/propose \
  -H "Content-Type: application/json" \
  -d '{
    "multisig_account_address": "mtst1xyz...",
    "tx_request": "<base64_encoded_transaction_request>"
  }'

Response:

{
  "tx_id": "550e8400-e29b-41d4-a716-446655440000",
  "tx_summary": "<base64_encoded_transaction_summary>"
}

add signature

Submits an approver's signature for a pending transaction. If the signature threshold is met, the transaction is automatically processed.

Endpoint: POST /api/v1/signature/add

curl -X POST http://localhost:59059/api/v1/signature/add \
  -H "Content-Type: application/json" \
  -d '{
    "tx_id": "550e8400-e29b-41d4-a716-446655440000",
    "approver": "mtst1abc...",
    "signature": "<base64_encoded_signature>"
  }'

Response:

{
  "tx_result": "<base64_encoded_transaction_result_if_threshold_met>"
}

Note: tx_result is either null if threshold is not yet met, or contains the base64-encoded transaction result if the transaction was executed.


list consumable notes

Retrieves consumable notes' note-ids for an account tracked by the coordinator.

Endpoint: POST /api/v1/consumable-notes/list

# get consumable notes for a specific account
curl -X POST http://localhost:59059/api/v1/consumable-notes/list \
  -H "Content-Type: application/json" \
  -d '{
    "address": "mtst1xyz..."
  }'

# get all consumable notes (across all accounts)
curl -X POST http://localhost:59059/api/v1/consumable-notes/list \
  -H "Content-Type: application/json" \
  -d '{
    "address": null
  }'

Response:

{
  "note_ids": [
    {
      "note_id": "0xabc123...",
      "note_id_file_bytes": "<base64_encoded_note_file>"
    },
    {
      "note_id": "0xdef456...",
      "note_id_file_bytes": "<base64_encoded_note_file>"
    },
    {
      "note_id": "0x789ghi...",
      "note_id_file_bytes": "<base64_encoded_note_file>"
    }
  ]
}

get multisig account details

Retrieves details of a multisig account.

Endpoint: POST /api/v1/multisig-account/details

curl -X POST http://localhost:59059/api/v1/multisig-account/details \
  -H "Content-Type: application/json" \
  -d '{
    "multisig_account_address": "mtst1xyz..."
  }'

Response:

{
  "multisig_account": {
    "address": "mtst1xyz...",
    "kind": "public",
    "threshold": 2,
    "created_at": "2025-10-19T12:00:00Z",
    "updated_at": "2025-10-19T12:00:00Z"
  }
}

list approvers

Lists all approvers for a specific multisig account.

Endpoint: POST /api/v1/multisig-account/approver/list

curl -X POST http://localhost:59059/api/v1/multisig-account/approver/list \
  -H "Content-Type: application/json" \
  -d '{
    "multisig_account_address": "mtst1xyz..."
  }'

Response:

{
  "approvers": [
    {
      "address": "mtst1abc...",
      "pub_key_commit": "<base64_encoded_public_key_1>"
    },
    {
      "address": "mtst1def...",
      "pub_key_commit": "<base64_encoded_public_key_2>"
    },
    {
      "address": "mtst1ghi...",
      "pub_key_commit": "<base64_encoded_public_key_3>"
    }
  ]
}

get transaction statistics

Retrieves transaction statistics for a multisig account.

Endpoint: POST /api/v1/multisig-tx/stats

curl -X POST http://localhost:59059/api/v1/multisig-tx/stats \
  -H "Content-Type: application/json" \
  -d '{
    "multisig_account_address": "mtst1xyz..."
  }'

Response:

{
  "tx_stats": {
    "total": 42,
    "last_month": 15,
    "total_success": 38
  }
}

list transactions

Lists all transactions for a multisig account, optionally filtered by status.

Endpoint: POST /api/v1/multisig-tx/list

# list all transactions
curl -X POST http://localhost:59059/api/v1/multisig-tx/list \
  -H "Content-Type: application/json" \
  -d '{
    "multisig_account_address": "mtst1xyz...",
    "tx_status_filter": null
  }'

# filter by status (pending/success/failure)
curl -X POST http://localhost:59059/api/v1/multisig-tx/list \
  -H "Content-Type: application/json" \
  -d '{
    "multisig_account_address": "mtst1xyz...",
    "tx_status_filter": "pending"
  }'

Response:

{
  "txs": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "multisig_account_address": "mtst1xyz...",
      "status": "pending",
      "tx_request": "<base64_encoded_transaction_request>",
      "tx_summary": "<base64_encoded_transaction_summary>",
      "tx_summary_commit": "<base64_encoded_transaction_summary_commitment>",
      "input_note_ids": [
        {
          "note_id": "0xabc123...",
          "note_id_file_bytes": "<base64_encoded_note_file>"
        }
      ],
      "signature_count": 1,
      "created_at": "2025-10-19T12:00:00Z",
      "updated_at": "2025-10-19T12:00:00Z"
    }
  ]
}

Note: signature_count is omitted if zero.