Rotor Machine State
Wiring an Enigma by hand, one node at a time
- rotors
- stepper
- entry
- reflector
- reflector_rotor
- plugboard
- auxilliary_rotors
- cipher_machine
This is the assemble-the-machine node, and it's the one the rest of the rotor category exists to feed. RotorCipherMachine takes a chain of rotors and a stepping rule and returns cipher_machine - a MACHINE object, the thing Rotor Machine Encrypt/Decrypt and Rotor Machine State Descriptor consume.
If you've ever read a page about the Enigma and wondered what a plugboard physically does, this node is a fairly honest answer: the wiring you build here is the signal path, stage by stage.
What it wants
Two required inputs. rotors is a ROTORS chain - you don't type a list, you chain Rotor Machine Rotor nodes through their previous_rotor input, so the resulting stack is ordered. Slot 0 is the leftmost rotor. stepper is a STEPPER from either the preset stepper or the rule-based one, and it has to agree with how many rotors you passed, or the node refuses.
Then five optional inputs, and their tooltips are unusually clear because the author is clearly an Enigma nerd:
entry- the entry wheel. Applied first inbound, inverted outbound. Identity on Wehrmacht Enigmas, so most historical builds can leave it empty.reflector- the static UKW. Must be an involution (every letter maps back to itself through it). Use this orreflector_rotor, not both; the node raises if you try.reflector_rotor- a reflector that occupies a slot and takes a position, i.e. exactly one rotor with involutive wiring. This is for machines where the reflector turns, and it's the source of the nastiest slot arithmetic in the pack (below).plugboard- the Steckerbrett, applied outermost before the entry wheel. Also must be an involution.auxilliary_rotors- extra rotors that aren't in the signal path. They exist for steppers that behave differently than the path implies. Note the spelling:auxilliary_rotors, if you're scripting the prompt JSON.
How the path gets built
The mechanism is worth understanding because it explains every error message you'll hit. The node assembles a stage list: plugboard, then entry wheel, then the rotor stack walked from the rightmost rotor to the leftmost (you list rotors left-to-right, signal goes right-to-left), then the reflector, then the same stages inverted on the way back out.
Every stage declares an input alphabet and an output alphabet, and the node validates that consecutive stages agree. If they don't, you get something like stage 3 outputs 'ABC...' but stage 4 expects '···' - and the fix is not to fiddle with the reflector, it's to insert a Rotor Machine Rotor Mapper stage to convert between alphabets. That's the whole reason the mapper node exists: a machine that mixes alphabets (letters in, grouped digits out) needs explicit conversion points.
The same validation pass enforces the involution rule on the reflector and plugboard, and rejects a reflector rotor whose wiring isn't its own inverse. These are real constraints from the machine's mathematics: a non-involutive reflector means the outbound path doesn't land where the inbound path came from, and decryption stops being reciprocal.
Slot 0 is reserved, and that changes your key setting
The detail that bites everyone: when reflector_rotor is present, the node puts it at slot 0 and shifts every path rotor to slot 1, 2, 3. Positions are read from the machine's slot list, so a three-rotor Enigma that uses a reflector rotor needs a four-character position string. Feed it three and you get positions has 3 entries, machine has 4 rotors. It's not a bug, it's the reflector having a start position - but it reads like a bug at 1am.
Second trap: auxilliary_rotors and the preset stepper don't mix. The node says so plainly - preset steppers count every rotor including aux, so use a rule or circuit stepper if you're adding them.
Installing it
Manager → ComfyUI ARG Toolkit → install → restart → refresh. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/AzelusLightvale/ComfyUI-ARG-Toolkit
pip install -r requirements.txt
No models, no downloads - the rotor category is pure Python and doesn't even touch the cryptography dependency. The shared requirements file still pins torch and torchaudio, so a manual pip install -r is heavier than the feature justifies.
How to use it without guessing
Build rotors, chain them, pick a stepper, wire the output into Rotor Machine State Descriptor before you add any text. Now you also need a POSITIONS object - that's Rotor Machine Positions, with one character per slot from left to right, and each character must exist in that rotor's alphabet.
A working Wehrmacht-ish sanity check: three rotors with the pack's default wiring, a Rotor Machine Permutation set to Enigma reflector B (YRUHQSLDPXNGOKMIEBFZCWVJAT), no plugboard, preset stepper on Enigma with k set to 3, positions AAA. Type the same letter twice in the encrypt node and you should get two different letters back - that's the rotors stepping between keystrokes, and the one behaviour that tells you the assembly is alive.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| rotors | ROTORS | — | |
| stepper | STEPPER | — | |
| entryopt | PERMUTATION | Entry wheel (ETW). Applied first on the way in, and inverted on the way out. Identity for Wehrmacht Enigmas. | |
| reflectoropt | PERMUTATION | Static reflector (UKW). Must be an involution. Use this OR reflector_rotor, not both. | |
| reflector_rotoropt | PERMUTATION | Reflector that takes a position (slot 0). A chain of exactly one rotor with an involutive wiring. | |
| plugboardopt | PERMUTATION | Steckerbrett. Applied outermost, before the entry wheel. Must be an involution. | |
| auxilliary_rotorsopt | ROTORS | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| cipher_machine | MACHINE | — |