Mar 04, 10-11 AM (97)
Mar 04, 11-12 PM (40)
Mar 04, 12-1 PM (47)
Mar 04, 1-2 PM (66)
Mar 04, 2-3 PM (81)
Mar 04, 3-4 PM (102)
Mar 04, 4-5 PM (18)
Mar 04, 5-6 PM (62)
Mar 04, 6-7 PM (60)
Mar 04, 7-8 PM (39)
Mar 04, 8-9 PM (56)
Mar 04, 9-10 PM (15)
Mar 04, 10-11 PM (26)
Mar 04, 11-12 AM (26)
Mar 05, 12-1 AM (15)
Mar 05, 1-2 AM (18)
Mar 05, 2-3 AM (17)
Mar 05, 3-4 AM (16)
Mar 05, 4-5 AM (3)
Mar 05, 5-6 AM (9)
Mar 05, 6-7 AM (27)
Mar 05, 7-8 AM (20)
Mar 05, 8-9 AM (31)
Mar 05, 9-10 AM (72)
Mar 05, 10-11 AM (43)
Mar 05, 11-12 PM (53)
Mar 05, 12-1 PM (65)
Mar 05, 1-2 PM (51)
Mar 05, 2-3 PM (68)
Mar 05, 3-4 PM (64)
Mar 05, 4-5 PM (55)
Mar 05, 5-6 PM (57)
Mar 05, 6-7 PM (66)
Mar 05, 7-8 PM (20)
Mar 05, 8-9 PM (21)
Mar 05, 9-10 PM (8)
Mar 05, 10-11 PM (22)
Mar 05, 11-12 AM (21)
Mar 06, 12-1 AM (11)
Mar 06, 1-2 AM (18)
Mar 06, 2-3 AM (8)
Mar 06, 3-4 AM (0)
Mar 06, 4-5 AM (11)
Mar 06, 5-6 AM (5)
Mar 06, 6-7 AM (16)
Mar 06, 7-8 AM (65)
Mar 06, 8-9 AM (35)
Mar 06, 9-10 AM (46)
Mar 06, 10-11 AM (48)
Mar 06, 11-12 PM (45)
Mar 06, 12-1 PM (48)
Mar 06, 1-2 PM (89)
Mar 06, 2-3 PM (93)
Mar 06, 3-4 PM (37)
Mar 06, 4-5 PM (40)
Mar 06, 5-6 PM (20)
Mar 06, 6-7 PM (16)
Mar 06, 7-8 PM (22)
Mar 06, 8-9 PM (15)
Mar 06, 9-10 PM (13)
Mar 06, 10-11 PM (28)
Mar 06, 11-12 AM (22)
Mar 07, 12-1 AM (16)
Mar 07, 1-2 AM (1)
Mar 07, 2-3 AM (6)
Mar 07, 3-4 AM (0)
Mar 07, 4-5 AM (1)
Mar 07, 5-6 AM (5)
Mar 07, 6-7 AM (7)
Mar 07, 7-8 AM (7)
Mar 07, 8-9 AM (4)
Mar 07, 9-10 AM (3)
Mar 07, 10-11 AM (0)
Mar 07, 11-12 PM (4)
Mar 07, 12-1 PM (6)
Mar 07, 1-2 PM (2)
Mar 07, 2-3 PM (6)
Mar 07, 3-4 PM (22)
Mar 07, 4-5 PM (21)
Mar 07, 5-6 PM (5)
Mar 07, 6-7 PM (0)
Mar 07, 7-8 PM (7)
Mar 07, 8-9 PM (10)
Mar 07, 9-10 PM (7)
Mar 07, 10-11 PM (37)
Mar 07, 11-12 AM (28)
Mar 08, 12-1 AM (3)
Mar 08, 1-2 AM (5)
Mar 08, 2-3 AM (5)
Mar 08, 3-4 AM (1)
Mar 08, 4-5 AM (1)
Mar 08, 5-6 AM (1)
Mar 08, 6-7 AM (0)
Mar 08, 7-8 AM (3)
Mar 08, 8-9 AM (8)
Mar 08, 9-10 AM (2)
Mar 08, 10-11 AM (0)
Mar 08, 11-12 PM (1)
Mar 08, 12-1 PM (3)
Mar 08, 1-2 PM (6)
Mar 08, 2-3 PM (6)
Mar 08, 3-4 PM (15)
Mar 08, 4-5 PM (0)
Mar 08, 5-6 PM (31)
Mar 08, 6-7 PM (7)
Mar 08, 7-8 PM (8)
Mar 08, 8-9 PM (12)
Mar 08, 9-10 PM (1)
Mar 08, 10-11 PM (25)
Mar 08, 11-12 AM (25)
Mar 09, 12-1 AM (6)
Mar 09, 1-2 AM (5)
Mar 09, 2-3 AM (21)
Mar 09, 3-4 AM (20)
Mar 09, 4-5 AM (2)
Mar 09, 5-6 AM (4)
Mar 09, 6-7 AM (3)
Mar 09, 7-8 AM (21)
Mar 09, 8-9 AM (36)
Mar 09, 9-10 AM (29)
Mar 09, 10-11 AM (44)
Mar 09, 11-12 PM (31)
Mar 09, 12-1 PM (60)
Mar 09, 1-2 PM (24)
Mar 09, 2-3 PM (74)
Mar 09, 3-4 PM (60)
Mar 09, 4-5 PM (127)
Mar 09, 5-6 PM (50)
Mar 09, 6-7 PM (54)
Mar 09, 7-8 PM (23)
Mar 09, 8-9 PM (25)
Mar 09, 9-10 PM (13)
Mar 09, 10-11 PM (60)
Mar 09, 11-12 AM (24)
Mar 10, 12-1 AM (5)
Mar 10, 1-2 AM (35)
Mar 10, 2-3 AM (34)
Mar 10, 3-4 AM (6)
Mar 10, 4-5 AM (3)
Mar 10, 5-6 AM (5)
Mar 10, 6-7 AM (20)
Mar 10, 7-8 AM (69)
Mar 10, 8-9 AM (110)
Mar 10, 9-10 AM (30)
Mar 10, 10-11 AM (30)
Mar 10, 11-12 PM (53)
Mar 10, 12-1 PM (65)
Mar 10, 1-2 PM (51)
Mar 10, 2-3 PM (89)
Mar 10, 3-4 PM (39)
Mar 10, 4-5 PM (44)
Mar 10, 5-6 PM (26)
Mar 10, 6-7 PM (10)
Mar 10, 7-8 PM (30)
Mar 10, 8-9 PM (15)
Mar 10, 9-10 PM (33)
Mar 10, 10-11 PM (30)
Mar 10, 11-12 AM (43)
Mar 11, 12-1 AM (13)
Mar 11, 1-2 AM (10)
Mar 11, 2-3 AM (6)
Mar 11, 3-4 AM (0)
Mar 11, 4-5 AM (4)
Mar 11, 5-6 AM (2)
Mar 11, 6-7 AM (19)
Mar 11, 7-8 AM (39)
Mar 11, 8-9 AM (84)
Mar 11, 9-10 AM (6)
Mar 11, 10-11 AM (1)
4,573 commits this week Mar 04, 2026 - Mar 11, 2026
fix: npm vulnerabilities (#1631)
* fix: Update biometric plugin and other dependencies, adjust biometric hook types

* fix(deps): update @types/node and sync lockfile to resolve CI failures

* fix: update biometrics hook to use full AvailableResult object

* feat: update biometric tests and mocks to include authentication strength and device security properties

* fix: security vulnerabilities in package-lock.json
Leios ThreadNet (#1883)
In order to have quicker iteration speeds during Leios prototype
development we want to enable running "simulated networks".

cardano-node has this ability because of the `io-classes` abstraction
used, which is ultimately reified in the ThreadNet tests.

This PR implements the `run-threadnet` CLI that runs a simulated
cardano-node network as specified by the user.

DONE:
- [x] Wire in Leios specifics into ThreadNet machinery such that we can
observe Leios state and events after each run
- [x] Collect traces
  - [x] Store traces in the configure locations
  - [x] Augment traces with SlotNo and CoreNodeId information
- [x] Collect relevant state
  - [x] Leios in memory store
- [x] Implement `run-threadnet` CLI
  - [x] Design and implement the configuration format
  - [x] Tranlsate it into the ThreadNet configuration
  - [x] Implement a simple & configurable tx generator
- [x] Configured the Nix build to only work with GHC96
- it's slow and painful to maintain green builds across all compiler
versions and platforms, reducing it to essentials.
- [x] Refactored `ThreadNet.Network` bits for clarity (during debugging)

### Example: Run the threadnet for 30 slots and generated a 1000
transactions per slot

$ cat run-threadnet-example-config/example-threadnet-config.json

```json

{                                                                                                                                                                                                                    
    "tncCoreNodes" : [                                                                                                                                                                                               
        {                                                                                                                                                                                                            
            "cncCardanoConfig" : "run-threadnet-example-config/config.json",
            "cncKesSigningKey" : "run-threadnet-example-config/pools-keys/pool1/kes.skey",
            "cncOCert" : "run-threadnet-example-config/pools-keys/pool1/opcert.cert",
            "cncVrfSigningKey" : "run-threadnet-example-config/pools-keys/pool1/vrf.skey",
            "cncLog": "node0.log"                                                                         
        },                                                                                                
        {                        
            "cncCardanoConfig" : "run-threadnet-example-config/config.json",
            "cncKesSigningKey" : "run-threadnet-example-config/pools-keys/pool2/kes.skey",
            "cncOCert" : "run-threadnet-example-config/pools-keys/pool2/opcert.cert",
            "cncVrfSigningKey" : "run-threadnet-example-config/pools-keys/pool2/vrf.skey",
            "cncLog": "node1.log"
        },
        {
            "cncCardanoConfig" : "run-threadnet-example-config/config.json",
            "cncKesSigningKey" : "run-threadnet-example-config/pools-keys/pool3/kes.skey",
            "cncOCert" : "run-threadnet-example-config/pools-keys/pool3/opcert.cert",
            "cncVrfSigningKey" : "run-threadnet-example-config/pools-keys/pool3/vrf.skey",
            "cncLog": "node2.log"
        }
    ],
    "tncTopology" : [
        [ 0, 1],
        [ 0, 2],
        [ 1, 2]
    ],
    "tncTxGenerators" : [
        {
            "tgcSubmitToNodes" : [
                0
            ],
            "tgcTxGeneratorKind" : {
                "tacPaymentSigningKey" : "run-threadnet-example-config/stake-delegators/delegator2/payment.skey"
            }
        }
    ]
}

```

and run with

```shell
$ cabal run ouroboros-consensus-cardano:run-threadnet
Usage: run-threadnet COMMAND

  Run ThreadNet, ie. run nodes in a simulated IO environment

Available options:
  -h,--help                Show this help text

Available commands:
  run                      Run the simulation
  dump-example-config      Dump an example configuration file
                           (example-threadnet.config)

$ cabal run ouroboros-consensus-cardano:run-threadnet -- run --threadnet-config run-threadnet-example-config/example-threadnet-config.json --slots 30 --txs-per-slot 1000
...
("current slot",SlotNo 29)
("current slot",SlotNo 29)
("current slot",SlotNo 29)
*** Tips
Just (SlotNo 29,fromList [(CoreId (CoreNodeId 0),At (BlockNo 1)),(CoreId (CoreNodeId 1),At (BlockNo 1)),(CoreId (CoreNodeId 2),At (BlockNo 1))])
*** Leios
("eb-slotno",fromList [(CoreId (CoreNodeId 0),fromList []),(CoreId (CoreNodeId 1),fromList []),(CoreId (CoreNodeId 2),fromList [("\179@Af:\160\130\204\205\ACKFU\251t\EMk\EOT\172*\152s\145\187I\192\191\235=4\244\149\233",SlotNo 10),("\240\ESC \155\DC2\a\247\167\248x\NUL\ETB\254\194\bv\170\GS\139.\201\249\182h\186\184;\SOH\141\188\255J",SlotNo 7)])])
("eb-points",fromList [(CoreId (CoreNodeId 0),fromList []),(CoreId (CoreNodeId 1),fromList []),(CoreId (CoreNodeId 2),fromList [(7,("\240\ESC \155\DC2\a\247\167\248x\NUL\ETB\254\194\bv\170\GS\139.\201\249\182h\186\184;SOH\141\188\255J",13827)),(10, "\179@Af:160\130\204\205\ACKFU\251t\EMk\EOT\172*\152s\145\187I\192\191\235=4\244\149\233",13827))])])
("eb-txs",fromList [(CoreId (CoreNodeId 0),0),(CoreId (CoreNodeId 1),0),(CoreId (CoreNodeId 2),768)])
*** Outputting log files

$ grep -i leios node*.log
node0.log:FromLeios (MkTraceLeiosKernel "leiosFetchLogic: wait for leios ready")
node1.log:FromLeios (MkTraceLeiosKernel "leiosFetchLogic: wait for leios ready")
node2.log:FromLeios (MkTraceLeiosKernel "leiosFetchLogic: wait for leios ready")
node2.log:FromLeios (TraceLeiosBlockForged {slot = SlotNo 7, eb = MkLeiosEb {leiosEbTxs = [("\236\216\134\a\233'\158\DC3\175\211\210\228v^<\t\212f|\219\DC4\160\&5I\n\205\199?\140gJ\220",229),("\177\SUB\137V\156R@\
node2.log:FromLeios (TraceLeiosBlockStored {slot = SlotNo 7, eb = MkLeiosEb {leiosEbTxs = [("\236\216\134\a\233'\158\DC3\175\211\210\228v^<\t\212f|\219\DC4\160\&5I\n\205\199?\140gJ\220",229),("\177\SUB\137V\156R@\
node2.log:FromLeios (TraceLeiosBlockForged {slot = SlotNo 10, eb = MkLeiosEb {leiosEbTxs = [("\138\138H\226\SUB\147\149\&4\169\143\179\240\173\214Ue\229\210x^\227q\198\DC3f=b\170\DEL\237v|",229),("\224\DC4\132\170
node2.log:FromLeios (TraceLeiosBlockStored {slot = SlotNo 10, eb = MkLeiosEb {leiosEbTxs = [("\138\138H\226\SUB\147\149\&4\169\143\179\240\173\214Ue\229\210x^\227q\198\DC3f=b\170\DEL\237v|",229),("\224\DC4\132\170
```