pyrxd.security — Typed primitives + errors

Security primitives for pyrxd.

This package contains the security foundation the rest of the SDK is built on: exception hierarchy, key-material wrappers, secure RNG helpers, and typed newtypes enforcing trust-boundary invariants.

Nothing in this package should ever log, print, or format raw key material.

class pyrxd.security.BlockHeight[source]

Bases: int

Non-negative block height with a generous sanity ceiling.

MAX: ClassVar[int] = 10000000
static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

BlockHeight

exception pyrxd.security.CovenantError[source]

Bases: RxdSdkError

Raised for covenant construction or verification failures.

class pyrxd.security.Hex20[source]

Bases: _FixedBytes

Exactly 20 raw bytes (e.g. a hash160 public-key hash).

class pyrxd.security.Hex32[source]

Bases: _FixedBytes

Exactly 32 raw bytes (e.g. a hash digest).

exception pyrxd.security.KeyMaterialError[source]

Bases: RxdSdkError

Raised for errors touching private keys, mnemonics, or WIFs.

Constructors raising this error MUST NOT include the offending key material in the message — pass a static description only.

class pyrxd.security.Nbits[source]

Bases: bytes

The compact difficulty target (nBits) from a block header.

Wire format

nBits is a 4-byte little-endian encoding of a uint32. When decoded:
  • exponent = nBits_uint32 >> 24 (high byte, little-endian: byte[3])

  • mantissa = nBits_uint32 & 0x007fffff (low 3 bytes)

  • target   = mantissa * 256^(exponent-3)

This type accepts the raw 4 wire bytes and validates the three conditions Bitcoin Core enforces on target-word parsing. A malformed nBits can be used to forge PoW (e.g. a negative target evaluates the comparison weirdly, a zero target is trivially satisfied, an over-large exponent shifts out of range). Rejecting these at the trust boundary protects every SPV check downstream.

static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

Nbits

exception pyrxd.security.NetworkError[source]

Bases: RxdSdkError

Raised for transport / RPC / network failures.

class pyrxd.security.Photons[source]

Bases: int

Non-negative integer amount in photons (RXD smallest unit).

static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

Photons

class pyrxd.security.PrivateKeyMaterial[source]

Bases: SecretBytes

A SecretBytes whose contents are a valid secp256k1 private key.

Invariants enforced at construction:
  • length is exactly 32 bytes

  • integer value is in the valid scalar range [1, N-1]

__init__(data)[source]
Parameters:

data (bytes)

Return type:

None

classmethod from_wif(wif)[source]

Decode a WIF-encoded private key.

On failure raises KeyMaterialError WITHOUT embedding the input wif in the message — an attacker watching logs must not learn any part of the candidate key.

Implementation is self-contained (no heavy coincurve dependency) so the security module can be imported before the rest of the SDK.

Parameters:

wif (str)

Return type:

PrivateKeyMaterial

classmethod generate()[source]

Generate a fresh random private key using the secure RNG.

Return type:

PrivateKeyMaterial

class pyrxd.security.RawTx[source]

Bases: bytes

Raw transaction bytes.

Enforces the 64-byte Merkle-forgery defense: any candidate transaction must be strictly greater than 64 bytes. A 64-byte “transaction” can be forged from an internal Merkle-tree node, letting an attacker prove inclusion of bogus data. See audit finding 02-F-1 and Bitcoin BIP-141’s segwit commitment for the historical context (and the CVE-2017-12842 family for concrete exploits).

MIN_SIZE: ClassVar[int] = 65
static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

RawTx

exception pyrxd.security.RxdSdkError[source]

Bases: Exception

Base class for every exception raised by pyrxd.

Applying redact to each positional arg on construction defends against accidental key-material leakage when callers pass user-supplied values straight into the exception.

__init__(*args)[source]
Parameters:

args (Any)

Return type:

None

class pyrxd.security.Satoshis[source]

Bases: int

Non-negative integer amount in satoshis, capped at Bitcoin max supply.

MAX: ClassVar[int] = 2100000000000000
static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

Satoshis

class pyrxd.security.SecretBytes[source]

Bases: object

A wrapper around bytes that will not leak its contents on repr/str.

The internal storage is a bytearray so zeroize() can mutate it in place. unsafe_raw_bytes returns an immutable bytes copy.

__init__(data)[source]
Parameters:

data (bytes)

Return type:

None

classmethod from_hex(h)[source]

Construct from a hex string.

The hex string itself is not embedded in any error message — an attacker who can see the exception must not learn the invalid input was “0x…” with specific bytes.

Parameters:

h (str)

Return type:

SecretBytes

unsafe_raw_bytes()[source]

Return the raw secret bytes.

Named unsafe_* on purpose: every call site should be auditable with a single grep. Prefer SDK methods that consume SecretBytes directly over pulling the raw bytes out.

Return type:

bytes

zeroize()[source]

Best-effort overwrite of the internal buffer with zeros.

Python’s memory model does not guarantee that every copy of a string or bytes object is scrubbed; only the buffer we own is cleared. Call this when you know a key will not be used again.

Return type:

None

class pyrxd.security.SighashFlag[source]

Bases: int

A valid Radiant sighash flag byte.

SIGHASH_ALL: ClassVar[int] = 65
SIGHASH_ALL_ANYONECANPAY: ClassVar[int] = 193
SIGHASH_NONE: ClassVar[int] = 66
SIGHASH_NONE_ANYONECANPAY: ClassVar[int] = 194
SIGHASH_SINGLE: ClassVar[int] = 67
SIGHASH_SINGLE_ANYONECANPAY: ClassVar[int] = 195
static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

SighashFlag

exception pyrxd.security.SpvVerificationError[source]

Bases: RxdSdkError

Raised when an SPV proof (Merkle path, header chain) fails to verify.

class pyrxd.security.Txid[source]

Bases: str

A lowercase-hex transaction id (64 chars).

static __new__(cls, value)[source]
Parameters:

value (Any)

Return type:

Txid

exception pyrxd.security.ValidationError[source]

Bases: RxdSdkError

Raised when input fails a trust-boundary validation check.

pyrxd.security.redact(value)[source]

Return a redacted representation of value if it looks sensitive.

  • str longer than 8 chars that looks like key material -> "<redacted>"

  • bytes longer than 8 bytes -> "<redacted:Nb>"

  • other types -> returned unchanged

Parameters:

value (Any)

Return type:

Any

pyrxd.security.secure_random_bytes(n)[source]

Return n cryptographically secure random bytes.

Thin wrapper over secrets.token_bytes(). Exists so callers have a single chokepoint to audit/mock and so the n <= 0 guard lives in one place.

Parameters:

n (int)

Return type:

bytes

pyrxd.security.secure_scalar_mod_n()[source]

Draw a uniform random scalar in [1, N-1] and return it wrapped.

Convenience wrapper combining pyrxd.security.rng.secure_scalar_bytes_mod_n() with PrivateKeyMaterial. Lives in this module (not rng) so rng has no dependency on PrivateKeyMaterial — that keeps the import graph acyclic.

Return type:

PrivateKeyMaterial