# How to unregister a Validator Node using the Keystore file

**URL:** <https://radixtalk.com/t/how-to-unregister-a-validator-node-using-the-keystore-file/64>\
**Category:** Validators\
**Tags:** howto, python\
**Created:** [25 December 2021 14:07 UTC](https://radixtalk.com/t/how-to-unregister-a-validator-node-using-the-keystore-file/64 "2021-12-25T14:07:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stuart](https://radixtalk.com/letter_avatar_proxy/v4/letter/s/cab0a1/32.png) [@Stuart](https://radixtalk.com/u/Stuart)\
**Post date:** [25 December 2021 14:07 UTC](https://radixtalk.com/t/how-to-unregister-a-validator-node-using-the-keystore-file/64/1 "2021-12-25T14:07:26Z")

</div>

The script below will unregister a validator node given its node-keystore.ks file and password. This is really only for emergency use where you’re unable to unregister a node because it is still syncing.

The script reads the node-keystore.ks file which is in a PKCS12 format, extracts its private key, generates the corresponding public key, validator address and validator wallet address. Then using this data it submits a build transaction request to [https://mainnet.radixdlt.com/construction](https://mainnet.radixdlt.com/construction) with an UnregisterValidator action.

The response is read, the blobToSign is signed using the keystore private key, and a finalize transaction request is built and submitted to [https://mainnet.radixdlt.com/construction](https://mainnet.radixdlt.com/construction) again.

\*Ensure that your validator wallet address has at least 5.1 XRD to successfully unregister the node. You will require an additional 5.1 XRD to re-register the node again later

```python
import bech32
import ecdsa
import hashlib
from cryptography.hazmat.primitives.serialization import pkcs12
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
from cryptography.hazmat.backends import default_backend
from ecdsa.curves import SECP256k1
from ecdsa.util import sigencode_der
from getpass import getpass

import requests
import json

print ("Enter your Keystore Password:")
pw = getpass()

password = pw.encode()

# Read the Radix Keystore File (which is in PKCS12 format)
with open("node-keystore.ks", "rb") as f:
  private_key, certificate, additional_certificates = pkcs12.load_key_and_certificates(f.read(), password, default_backend())

# Extract the unencrypted Private Key bytes
private_key_bytes = private_key.private_bytes(Encoding.DER, PrivateFormat.PKCS8, NoEncryption())

# Convert into Elliptic Curve Digital Signature Algorithm (ecdsa) private key object
private_key = ecdsa.SigningKey.from_der(private_key_bytes, hashfunc=hashlib.sha256)

# Derive public key from private key
verifying_key = private_key.get_verifying_key()

# Convert public key into compressed format so that we can generate the Validator Address
public_key_compressed_bytes = verifying_key.to_string("compressed")
public_key_compressed_bytes_hex = public_key_compressed_bytes.hex()
print("Validator Public Key (Compressed): ", public_key_compressed_bytes_hex)

# Generate Validator Address from the Compressed Public Key
public_key_bytes5 = bech32.convertbits(public_key_compressed_bytes, 8, 5)
validator_address = bech32.bech32_encode("rv", public_key_bytes5)
print("Validator Address: ", validator_address)

# Convert Compressed Public Key into a Radix Engine Address
readdr_bytes = b"\x04" + public_key_compressed_bytes

# Convert Radix Engine Address into Validator Wallet Address
readdr_bytes5 = bech32.convertbits(readdr_bytes, 8, 5)
validator_wallet_address = bech32.bech32_encode("rdx", readdr_bytes5)
print("Validator Wallet Address: ", validator_wallet_address)

# Construct RPC request
data = f"""
   {{
  "network_identifier": {{
    "network": "mainnet"
  }},
  "actions": [
    {{
      "type": "UnregisterValidator",
      "validator": {{
        "address": "{validator_address}"
      }}
    }}
  ],
  "fee_payer": {{
    "address": "{validator_wallet_address}"
  }},
  "disable_token_mint_and_burn": true
 }}
"""

print("Build Transaction Request JSON: ", data)

req = requests.Request('POST', 'https://mainnet.radixdlt.com/transaction/build', data=data)
prepared = req.prepare()
prepared.headers['Content-Type'] = 'application/json'
s = requests.Session()

# Send Request to Unregister Validator
resp = s.send(prepared)

# Get JSON Response
resp_json = resp.json()
print("Build Transaction Response JSON: \n", json.dumps(resp_json, indent=3))

# Extract fields from JSON Response
blob = resp_json['transaction_build']['unsigned_transaction']
blob_to_sign = resp_json['transaction_build']['payload_to_sign']

# Sign the blob_to_sign with the Keystore Private Key and convert to DER format
signature_der = private_key.sign_digest(bytearray.fromhex(blob_to_sign), sigencode=sigencode_der).hex()

# Finalize RPC Request
data = f"""
{{
      "network_identifier":{{
        "network": "mainnet"
      }},
      "unsigned_transaction": "{blob}",
      "signature": {{
         "bytes": "{signature_der}",
         "public_key": {{
           "hex": "{public_key_compressed_bytes_hex}"
    }}
  }},
  "submit": true
}}
"""
print("Finalize Transaction Request JSON: ", data)

req = requests.Request('POST', 'https://mainnet.radixdlt.com/transaction/finalize', data=data)
prepared = req.prepare()
prepared.headers['Content-Type'] = 'application/json'
s = requests.Session()

# Send Request to Unregister Validator
resp = s.send(prepared)

# Get JSON Response
resp_json = resp.json()
print("Finalize Transaction Response JSON: \n", json.dumps(resp_json, indent=3))

```

**Updates:**

- 2022-02-25: Changed to use new Gateway API (Thanks @Faraz)
- 2022-08-03: Gateway host name updated to [mainnet.radixdlt.com](http://mainnet.radixdlt.com) (Faraz)

This work by [RadixPool.com](https://radixpool.com) is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).

---

<div class="post-metadata">

**Author:** ![Mattia](https://radixtalk.com/user_avatar/radixtalk.com/mattia/32/64_2.png) [@Mattia](https://radixtalk.com/u/Mattia)\
**Post date:** [1 February 2022 09:48 UTC](https://radixtalk.com/t/how-to-unregister-a-validator-node-using-the-keystore-file/64/2 "2022-02-01T09:48:22Z")

</div>

Hi Stuart, thank you for the great script. Do you know if it’s still working, with the new API?

---

<div class="post-metadata">

**Author:** ![Stuart](https://radixtalk.com/letter_avatar_proxy/v4/letter/s/cab0a1/32.png) [@Stuart](https://radixtalk.com/u/Stuart)\
**Post date:** [1 February 2022 10:02 UTC](https://radixtalk.com/t/how-to-unregister-a-validator-node-using-the-keystore-file/64/3 "2022-02-01T10:02:05Z")

</div>

The script will still work whilst [mainnet.radixdlt.com](http://mainnet.radixdlt.com) is still supporting the old archive nodes.

I’ll make sure I add a new version that supports the new api before the old archive nodes are retired.
