MTLsim
A simulator for MTL mode in DNSSEC.
Installation
Option 1: Nix Flake (recommended)
Install Nix from the NixOS website and run:
nix shell github:malmeloo/mtlsim
This will build the simulator and drop you in a shell where the mtlsim command is available.
Option 2: Python / UV
Install UV, clone the repository and run the simulator with:
uv run mtlsim
Only Python 3.13+ is officially supported.
Usage
The simulator workflow looks like this:
- Ingest zone and query events, convert into JSONL format;
- Run the simulation with the ingested data;
- Analyze the results.
Ingest zone events
mtlsim comes with a set of CLI commands to ingest and generate zone and query data from various sources. To view all commands, run mtlsim --help.
Zone input data is expected to be in JSONL format:
{"timestamp":"2026-07-20T05:00:00","removed":[],"added":[["example", "DS"], ["example", "NSEC3"]]}
{"timestamp":"2026-07-20T06:00:00","removed":[["example", "DS"]],"added":[["example", "NSEC3"]]}
"added" and "removed" are lists of tuples indicating RRSIG records, where each tuple contains a domain name and a record type. "added" contains RRSIGs that were added or updated, while "removed" contains RRSIGs that were removed.
Ingest query events
Query / resolver input data is also expected to be in JSONL format:
{"timestamp":"2026-07-20T05:00:00","type": "given", "query_name": "example", "query_type": "DS"}
{"timestamp":"2026-07-20T05:00:01","type": "given", "query_name": "example", "query_type": "DS"}
Several fields are available for query events:
- given: the event contains the query name and type
- random: the event contains a record type, and the query name is randomly generated from the zone
- random_seeded: same as random, but the random generator is seeded for reproducibility
type: Literal["given", "random", "random_seeded"] = "given"
query_name: str | None
query_type: str | None
seed: str | None
Simulation
Example command to run a simulation:
mtlsim simulate --zone-input inputs/nl/zone.jsonl --query-input inputs/nl/resolver_1.jsonl --strategy single_inf --tag nl-singleinf-1
Results will be written to logs/<tag>-<timestamp>.jsonl. The tag is used to identify the simulation run, and the timestamp is automatically generated.
Example output log:
{"timestamp":"2026-03-11T14:00:00","type":"new_ladder","sid":"648628cc-09db-4602-9583-fb3cb47b5b40"}
{"timestamp":"2026-03-11T14:00:00","type":"ladder_add","sid":"648628cc-09db-4602-9583-fb3cb47b5b40","count":9683849}
{"timestamp":"2026-03-11T14:04:00.420860","type":"query","sig_type":"full"}
{"timestamp":"2026-03-11T14:07:54.039826","type":"query","sig_type":"condensed"}
Analyzing results
Analysis can be done with the mtlsim analyze command. For example, to analyze all results from the logs directory, run:
mtlsim analyze logs/*.jsonl
Analysis results will be written to output/<tag>.json. If multiple files with the same tag but different timestamps are provided, analysis will only be done on the latest file.
Example output:
{
"run_name": "single_inf_0.01",
"timestamp": "2026-06-12T13:30:20",
"time_between_fullsig": [
63653.10127186775,
87375.85578608513,
69382.63759803772,
4492.899500846863
// (elapsed time in seconds between full signature checks)
],
"queries_between_fullsig": [
622,
870,
687,
38
// (number of queries between full signature checks)
],
"ladder_sizes": {
"f0493d15-1666-41a7-a118-1b9bbb2d37fd": [
["2026-03-11T14:00:00", 0],
["2026-03-11T14:00:00", 9683849],
["2026-03-11T14:30:00", 9684793],
["2026-03-11T15:00:00", 9685610]
// ... [timestamp, integer] pairs
]
// potentially additional ladder UUIDs
}
}
Release files for mtlsim 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mtlsim-0.1.0.tar.gz | 30.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mtlsim-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 67.5 kB
Release files / mtlsim-0.1.0.tar.gz
| Download URL | mtlsim-0.1.0.tar.gz |
|---|---|
| Size | 30.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ff950aa1282c428116dceb3a332260528450572e17b50e8e5af7b9e0d3c27308
|
|
BLAKE2b-256 checksum How to use checksums |
3bac5b4165b00a2a39362dc1e93d7c55f0d4181616416bdbfa72318622403f2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.05","id":"yarara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mtlsim-0.1.0-py3-none-any.whl
| Download URL | mtlsim-0.1.0-py3-none-any.whl |
|---|---|
| Size | 37.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
62a33af4d29e4a8ceacfe69f009189eef9cd3e6331c688922ae02af2ff7ab90b
|
|
BLAKE2b-256 checksum How to use checksums |
119c27904c023375ff331eb651dfe711d82d3e2c5f0ff56a0e5b8ee800bd772e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.05","id":"yarara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|