Skip to main content

Synopsis

cowboy secrets drives the CIP-24 Cowboy Blockchain Secrets Service (CBSS): it registers encrypted secret versions on chain, manages which actors may read them, and runs the account-scoped DKG that produces the release key the secrets are wrapped to. The secret value itself is never stored on chain — only a key hash, a pointer to the encrypted CBFS payload, and the wrapped data-encryption key. Write commands sign with the key found by key auto-discovery. key-hash, encrypt, build-tx, and submit-signed never touch a private key; list and account-key read one only to default --account to its address. With --json, a write reports one versioned JSON result and waits for its transaction to commit first. Parent flags:

Subcommands

cowboy secrets key-hash

Compute a CBSS key hash locally from an owner account and a key name, without a signing key or network request. Prints the hash as 0x hex. Flags:

cowboy secrets set

Encrypt and submit a new secret version, or submit pre-encrypted fields. Behavior:
  1. Resolve the plaintext value. --value-file <path> reads a file (- reads stdin); a trailing newline is stripped. Passing VALUE inline is refused when stdin is a terminal, because it would land in shell history.
  2. If any of --committee-n, --committee-t, or --preferred-proxy is given, the command takes the per-secret committee-override path: both --committee-n and --committee-t are required, t must be in 1..=n, and if --preferred-proxy is supplied it must be repeated exactly n times.
  3. Plaintext mode (KEY or VALUE given): derive the owner account from the signing key and compute the key hash from the account and KEY. Fetch the account’s release key from the RPC; if none exists yet, submit RequestAccountDkg and wait up to 300 seconds (following finalized cbss.committee.rotated events, with backoff) for the committee to commit one. Resolve the next version number, IBE-encrypt the value to the release key, place the ciphertext at the CBFS location (--cbfs-output / --cbfs-uri; see --help), then submit SetSecret with the policy and wait for it to commit.
  4. Pre-encrypted mode (no KEY/VALUE): requires --key-hash, --recipient-account, --cbfs-uri, --cbfs-envelope, --wrap-epoch, --wrapped-dek-ciphertext, --wrapped-dek-nonce, --wrapped-dek-ephemeral-u, and --wrapped-dek-aad, and builds SetSecret from them directly.
  5. Sign and POST /submit; print the transaction hash and the node response.
Flags: Example:

cowboy secrets finalize

Finalize a pending secret-specific CBSS version with encrypted fields. Behavior:
  1. Resolve the plaintext value as in set.
  2. If KEY or VALUE is given, encrypt the value for the pending version and submit FinalizeSecretVersion.
  3. Otherwise require --key-hash, --cbfs-uri, --cbfs-envelope, --wrap-epoch, and the four --wrapped-dek-* flags, and build FinalizeSecretVersion from them.
Flags:

cowboy secrets request-account-dkg

Request an account-scoped CBSS DKG ceremony for the signing account. Flags: Example:

cowboy secrets expire-account-dkg

Expire a timed-out account-scoped DKG and settle the requester refund. Flags:

cowboy secrets policy

Replace the policy of one secret version. Flags:

cowboy secrets grant-actor

Atomically add one reader, preserving the current policy and TEE requirement. Flags:

cowboy secrets delete-version

Delete one secret version. Behavior:
  1. Unless --yes is passed, print a summary and require the operator to type yes. If stdin is not a terminal and --yes is absent, the command refuses.
  2. Submit DeleteSecretVersion.
Flags:

cowboy secrets delete

Delete all active versions of a secret. Uses the same confirmation gate as delete-version. Flags:

cowboy secrets reshare

Request a proactive secret-sharing reshare for the caller’s account-scoped release key. Submits RequestReshare with scope Account(<signer address>); the committee completes the reshare and submits RotateCommittee as a separate chain event. Its only flag is --json (emit one versioned JSON result; waits for the transaction to commit).

cowboy secrets list

List the metadata of every secret registered to an account. Read-only; queries GET /cbss/secrets/{account} and signs nothing. Flags: Example:

cowboy secrets account-key

Show whether an account has a CBSS release key, the key secrets set encrypts to. It appears once the DKG from request-account-dkg commits. Prints the committee epoch and threshold when ready. Signs nothing. Flags:

cowboy secrets encrypt

Keyless owner-side encryption for an external (in-browser) signer. IBE-encrypts the value to the account’s release key and prints machine JSON on stdout; no private key is touched. Behavior:
  1. Fetch the account’s release key. If none exists, print {"needs_dkg":true} and exit successfully — run the DKG flow first.
  2. Resolve the next version, fetch the chain id, and encrypt.
  3. Print a JSON object with needs_dkg: false, chain_id, account, key_hash, version, wrap_epoch, wrapped_dek, and envelope_b64. With --ingest-endpoint, an ingest object (url, headers, signing_digest) is included for the caller to sign and POST.
Flags:

cowboy secrets build-tx

Build an unsigned CBSS transaction for an external signer. Behavior:
  1. Fetch the sender nonce and base fee, and decode the closed /chain-info response to pin the real chain ID and instance for this operation.
  2. Build the instruction for --kind: set-secret (requires --key-hash, --wrap-epoch, the four --wrapped-dek-* flags, and --cbfs-uri), grant-secret-actor (requires --key-hash, --version, and exactly one --actor, and accepts nothing else), request-account-dkg, or delete-secret (requires --key-hash).
  3. Build version-3 bytes through the canonical codec with a native secp256k1 placeholder slot. Print a JSON object with unsigned_tx_hex, the identity-bound signing_digest, and nonce.
Flags:

cowboy secrets submit-signed

Submit a transaction signed externally. For the signing handoff, use cowboy transaction sign-hash --expect-tx-hex with the unsigned transaction bytes and signing digest. Its output identifies the signed slot and mode; build the canonical SignatureSlot JSON from that output and pass it as --signature below. Behavior:
  1. Decode --unsigned-tx-hex strictly as v3. Parse --signature as the canonical SignatureSlot JSON object (algorithm, mode, public_key, signature) and require its descriptor to match the frozen primary slot before attaching its signature. At genesis this is algorithm 1, mode 0 or 1, public_key: null, and 65-byte low-S r||s||v with recovery ID 0 or 1. Untagged signature hex is refused.
  2. Fetch the trusted chain identity from /chain-info, run the complete structural and signature preflight, and require the recovered signer to equal tx.from before submitting. Wrong-version bytes, reserved fields and duplicate signers reject.
  3. With --prepare, print the complete signed transaction together with chain_identity and slot_index, then stop. Otherwise POST /submit and print {"tx_hash": ..., "result": ...} on stdout (progress lines go to stderr).
Flags:

Edge Cases

  • An inline VALUE (or --value on encrypt) is refused when stdin is a terminal; use --value-file or pipe the value on stdin with --value-file -.
  • Supplying both an inline value and --value-file is an error.
  • A committee override needs both --committee-n and --committee-t; --preferred-proxy must then be repeated exactly committee-n times.
  • set in plaintext mode auto-requests an account DKG when the account has no release key and waits up to 300 seconds for it; encrypt instead prints {"needs_dkg":true} and exits.
  • delete and delete-version refuse to run without --yes when stdin is not a terminal.
  • A --cycles-limit, --cells-limit, or --access-limit of zero is refused by build-tx before any RPC call.
  • Write commands sign with resource limits from the node’s estimate. Only build-tx sets explicit limits (5,000,000 cycles and cells by default).