# PoS

## Proof-of-Stake (PoS) Authenticator

For security-critical operations — especially those involving **subnet membership** and **DHT participation** — Hypertensor recommends using the **Proof-of-Stake (PoS) Authenticator**.

This authenticator ensures that only nodes with a valid on-chain stake can:

* Join the DHT
* Update routing tables
* Register heartbeat or protocol records
* Participate in critical peer-to-peer interactions

***

### **How It Works**

The PoS authenticator combines **cryptographic identity verification** with **on-chain staking validation**. It utilizes the [Signature Authorizer](/subnet-template/authorizers/signature-authorizer.md) for cryptographic handshakes.

When a node attempts to make a DHT request, the authenticator:

1. **Verifies the Peer ID Signature**
   * The Subnet Template comes with the option to use **RSA** or **Ed25519** schemes.
   * Ensures the peer controls the corresponding private key.
2. **Checks On-Chain Stake**
   * Queries the **Hypertensor blockchain** to verify that the peer ID is **staked** in the target `subnet_id`.
   * Prevents unauthenticated or free-rider nodes from participating in the network.
3. **Caches the Result**
   * After a successful stake verification, the result is cached for **5 minutes** to reduce load on the chain.
   * This cooldown ensures a balance between security and performance.

***

### **When to Use It**

The PoS Authenticator is ideal for:

* **Joining the DHT**
* **Updating DHT routing tables**
* **Publishing or modifying DHT records**
* **Authenticating peers in sensitive protocols (e.g., scoring, validation, consensus)**

> ⚠️ Nodes without a valid stake will be rejected from performing any critical or trusted actions in the network.

***

**Built-In Support**

The Hypertensor subnet template includes ready-to-use PoS authenticators for:

* `Ed25519`
* `RSA`

You can select the appropriate one depending on your key infrastructure.

```python
class ProofOfStakeAuthorizer(AuthorizerBase):
    def __init__(
        self,
        signature_authorizer: SignatureAuthorizer,
        pos: ProofOfStake
    ):
        super().__init__()
        self.signature_authorizer = signature_authorizer
        self.pos = pos

    async def sign_request(
        self,
        request: AuthorizedRequestBase,
        service_public_key: Optional[Ed25519PublicKey | RSAPublicKey]
    ) -> None:
        await self.signature_authorizer.sign_request(request, service_public_key)

    async def validate_request(self, request: AuthorizedRequestBase) -> bool:
        client_public_key, current_time, nonce, valid = await self.signature_authorizer.do_validate_request(request)
        if not valid:
            return False

        # Verify proof of stake
        try:
            proof_of_stake = self.pos.proof_of_stake(client_public_key)
            if not proof_of_stake:
                return False
        except Exception as e:
            logger.debug(f"Proof of stake failed, validate_request={e}", exc_info=True)
            return False

        self.signature_authorizer._recent_nonces.store(
            nonce, None, current_time + self.signature_authorizer._MAX_CLIENT_SERVICER_TIME_DIFF.total_seconds() * 3
        )

        return True

    async def sign_response(self, response: AuthorizedResponseBase, request: AuthorizedRequestBase) -> None:
        await self.signature_authorizer.sign_response(response, request)

    async def validate_response(self, response: AuthorizedResponseBase, request: AuthorizedRequestBase) -> bool:
        service_public_key, valid = await self.signature_authorizer.do_validate_response(response, request)
        if not valid:
            return False

        # Verify proof of stake
        try:
            proof_of_stake = self.pos.proof_of_stake(service_public_key)
            if not proof_of_stake:
                return False
        except Exception as e:
            logger.debug(f"Proof of stake failed, validate_response={e}", exc_info=True)
            return False

        return True
```


---

# Agent Instructions: 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:

```
GET https://docs.hypertensor.org/subnet-template/authorizers/pos.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
