> For the complete documentation index, see [llms.txt](https://docs.stacks.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stacks.co/operate/staking-stx/generate-signer-signature.md).

# Generate a Signer Signature

{% hint style="info" %}
Updated for Stacks 4.x and PoX-5.
{% endhint %}

PoX-5 uses a one-time **signer-key grant**. You generate one grant per signer-manager contract and submit it once. Every staking call routed through that manager then relies on it until you revoke it. There is nothing to generate per transaction or per cycle.

The grant is what connects your signer node, the signer-manager contract that stakers stake to, and the pox-5 contract. Without an active grant, `stake` and every related call against your manager fails with `ERR_SIGNER_KEY_GRANT_NOT_FOUND` (u17).

{% hint style="info" %}
Doing the whole setup from the command line? [Deploy a Signer Manager Contract](/operate/deploy-a-signer-manager-contract.md) runs this step in sequence with the deploy, registration and admin rotation.
{% endhint %}

### Generate the grant

Run this on the signer host, where the private key already lives:

```sh
stacks-signer generate-staking-signature \
  --config /etc/stacks-signer/config.toml \
  --signer-manager <manager-principal> \
  --auth-id <unique-id> \
  --json
```

Adjust the config path to match your setup. Replace `<manager-principal>` with your signer-manager's contract principal. Replace `<unique-id>` with a uint you have not used before for this signer key and manager pair.

The command prints JSON. It contains your public key and the signature. It does not contain your private key, which is what makes it safe to move to whatever you use to build the next transaction.

{% hint style="danger" %}
Never paste a signer private key or seed phrase into a website, a chat, or an email. Generate the grant on the signer host.
{% endhint %}

For testing, the [signer key helper](https://stx.fan/signer/02-signer-key-helper.html) produces the same JSON offline. It is useful for seeing how the grant is built. For a real deployment, prefer the CLI so the private key never leaves the host.

### Submit it on-chain

The grant is signed off-chain. It is submitted on-chain by the signer-manager contract itself, in two calls:

1. `grant-signer-key` records the grant.
2. `register-signer` binds the manager to the key.

Both require `contract-caller` to equal the signer-manager. An account cannot submit either on the contract's behalf. Trying fails with `ERR_UNAUTHORIZED_SIGNER_REGISTRATION` (u26).

The reference signer-manager wraps both into a single `register-self` entrypoint, so in practice this is one transaction. See [Deploy a Signer Manager Contract](https://docs.stacks.co/operate/deploy-a-signer-manager-contract).

The [register-self page](https://stx.fan/signer/04-register-self.html) takes a completed grant and builds that transaction for you.

### What the grant contains

The signed message:

```clarity
message: { topic: "grant-authorization", signer-manager: <principal>, auth-id: <uint> }
domain:  { name: "pox-5-signer", version: "1.0.0", chain-id: <uint> }
```

* **`signer-manager`** is the contract principal the key is bound to. Every staker who later stakes through that manager relies on this one grant.
* **`auth-id`** is a replay guard. The tuple `(signer-key, signer-manager, auth-id)` can be consumed exactly once. Reusing it fails with `ERR_SIGNER_KEY_GRANT_USED` (u12). Pick a fresh value to issue a new grant.

Those two fields are the whole scope. A grant authorises a signer-manager and stands until you revoke it.

The `chain-id` in the domain comes from the `network` field in your signer config. A grant generated against the wrong network fails at `grant-signer-key` with `ERR_INVALID_SIGNATURE_PUBKEY` (u14), which reads as a wrong-key problem rather than a wrong-network one.

### One grant covers every entrypoint

| Entrypoint                 | Needs an active grant?                                                                  |
| -------------------------- | --------------------------------------------------------------------------------------- |
| `stake`                    | Yes                                                                                     |
| `stake-update`             | Yes, the same grant                                                                     |
| `register-for-bond`        | Yes, the same grant                                                                     |
| `update-bond-registration` | Yes. Rotating to a different signer-manager requires that manager to hold its own grant |
| `register-signer`          | No. Gated on `contract-caller == signer-manager` instead                                |

Lock period is bounded by `MAX_NUM_CYCLES` (96) at the `stake` and `register-for-bond` level, not by anything in the grant.

### Revoke a grant

`revoke-signer-grant` removes the binding. It takes `(signer-manager, signer-key)` in that order.

It must be sent directly by the Stacks principal derived from the signer key. No SIP-018 message is needed, and it cannot be forwarded through another contract. Calling it from any other principal fails with `ERR_UNAUTHORIZED` (u1).

Revoking is not a kill switch. It stops the manager accepting new stake. Existing positions are left intact and wind down as their locks expire.

### Using @stacks/bitcoin-staking

The SDK exposes the same flow for tooling:

```typescript
import {
  signSignerGrant,
  fetchEligibleGrantSignerKey,
  buildGrantSignerKey,
} from '@stacks/bitcoin-staking';

const signerSignature = signSignerGrant({ signerManager, authId, chainId, privateKey });

const eligible = await fetchEligibleGrantSignerKey({
  signerKey, signerManager, authId, signerSignature, network,
});

const tx = await buildGrantSignerKey({
  signerKey, signerManager, authId, signerSignature, publicKey, fee, nonce, network,
});
```

The package also provides `buildSignerGrantMessage`, `computeSignerGrantHash`, and `verifySignerGrant` as pure functions, plus `fetchVerifySignerKeyGrant` and `fetchSignerKeyGrantUsed` for reading on-chain state.

### What changed from PoX-4

If you ran a signer before Epoch 4.0, you generated a fresh signature for every call, scoped to that call:

```sh
# PoX-4. No longer valid.
stacks-signer generate-stacking-signature \
  --method stack-stx --max-amount 1000000000000 --auth-id 71948271489 \
  --period 1 --reward-cycle 100 --pox-address bc1... \
  --config ./config.toml --json
```

The command was renamed from `generate-stacking-signature` to `generate-staking-signature`. Five scoping flags collapsed into a single `--signer-manager`. The result is reusable, so you run it once per manager rather than once per transaction.

There are no `--method`, `--max-amount`, `--period`, `--reward-cycle`, or `--pox-address` flags, because a grant authorises a signer-manager rather than a specific call.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.stacks.co/operate/staking-stx/generate-signer-signature.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
