This commit is contained in:
waalge 2025-03-21 15:42:45 +00:00
commit 9d0bded0a5
10 changed files with 1505 additions and 0 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
db/
data/
tmp/
result
secrets/
.direnv/
target/
# Added by cargo
/target

1
.pre-commit-config.yaml Symbolic link
View File

@ -0,0 +1 @@
/nix/store/jg6yhrj8z8jb1x00fwhidh9kddzvwxj2-pre-commit-config.json

811
Cargo.lock generated Normal file
View File

@ -0,0 +1,811 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "base58"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bech32"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
[[package]]
name = "bitflags"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cpufeatures"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
[[package]]
name = "crunchy"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "cryptoxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "382ce8820a5bb815055d3553a610e8cb542b2d767bbacea99038afda96cd760d"
[[package]]
name = "curve25519-dalek"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"digest",
"fiat-crypto",
"rustc_version",
"subtle",
"zeroize",
]
[[package]]
name = "curve25519-dalek-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "der"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
dependencies = [
"const-oid",
"zeroize",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "ed25519"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"pkcs8",
"signature",
]
[[package]]
name = "ed25519-dalek"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
"serde",
"sha2",
"signature",
"subtle",
"zeroize",
]
[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"windows-targets",
]
[[package]]
name = "half"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "log"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minicbor"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0452a60c1863c1f50b5f77cd295e8d2786849f35883f0b9e18e7e6e1b5691b0"
dependencies = [
"half",
"minicbor-derive",
]
[[package]]
name = "minicbor-derive"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd2209fff77f705b00c737016a48e73733d7fbccb8b007194db148f03561fb70"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pallas-codec"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1584d615857c0a44058fb612e892e9e0cc47b56c3c82cdf7347b5c1d1193598c"
dependencies = [
"hex",
"minicbor",
"serde",
"thiserror",
]
[[package]]
name = "pallas-crypto"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37c1d642326ce402eb9191aeacc3dd0bf2b499848e97a56396c978a6eb9dd31a"
dependencies = [
"cryptoxide",
"hex",
"pallas-codec",
"rand_core 0.6.4",
"serde",
"thiserror",
"zeroize",
]
[[package]]
name = "pallas-primitives"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d30f5053073554d016a9f009c077f9a84275951a611cce54230de6c54d34d9b"
dependencies = [
"base58",
"bech32",
"hex",
"log",
"pallas-codec",
"pallas-crypto",
"serde",
"serde_json",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy 0.7.35",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.0",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.15",
]
[[package]]
name = "rand_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
dependencies = [
"getrandom 0.3.1",
"zerocopy 0.8.17",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "semver"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"digest",
"rand_core 0.6.4",
]
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subbit-xyz-iou"
version = "0.0.0"
dependencies = [
"anyhow",
"clap",
"ed25519-dalek",
"hex",
"minicbor",
"pallas-primitives",
"rand",
"rand_chacha 0.9.0",
"serde",
"serde_json",
]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi"
version = "0.13.3+wasi-0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wit-bindgen-rt"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
"bitflags",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive 0.7.35",
]
[[package]]
name = "zerocopy"
version = "0.8.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713"
dependencies = [
"zerocopy-derive 0.8.17",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

22
Cargo.toml Normal file
View File

@ -0,0 +1,22 @@
[package]
name = "subbit-xyz-iou"
version = "0.0.0"
edition = "2021"
publish = false
# license = "MIT" -- set to apache
[package.metadata.release]
release = false
[dependencies]
anyhow = "1.0.95"
clap = { version = "4.5.18", features = ["derive"] }
# cryptoxide = "0.4.4"
ed25519-dalek = { version = "2.1.1", features = ["digest"] }
hex = "0.4.3"
minicbor = { version = "0.25.1", features = ["derive"] }
pallas-primitives = "0.32.0"
rand = "0.8.5"
rand_chacha = "0.9.0"
serde = { version = "1.0.213", features = ["derive"] }
serde_json = "1.0.138"

229
flake.lock Normal file
View File

@ -0,0 +1,229 @@
{
"nodes": {
"crane": {
"locked": {
"lastModified": 1736566337,
"narHash": "sha256-SC0eDcZPqISVt6R0UfGPyQLrI0+BppjjtQ3wcSlk0oI=",
"owner": "ipetkov",
"repo": "crane",
"rev": "9172acc1ee6c7e1cbafc3044ff850c568c75a5a3",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"git-hooks-nix": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1734797603,
"narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1735264675,
"narHash": "sha256-MgdXpeX2GuJbtlBrH9EdsUeWl/yXEubyvxM1G+yO4Ak=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "d49da4c08359e3c39c4e27c74ac7ac9b70085966",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1733096140,
"narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1730741070,
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1715447595,
"narHash": "sha256-VsVAUQOj/cS1LCOmMjAGeRksXIAdPnFIjCQ0XLkCsT0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "062ca2a9370a27a35c524dc82d540e6e9824b652",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"git-hooks-nix": "git-hooks-nix",
"nixpkgs": "nixpkgs",
"rust-flake": "rust-flake",
"treefmt-nix": "treefmt-nix"
}
},
"rust-flake": {
"inputs": {
"crane": "crane",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1736806612,
"narHash": "sha256-WioA+Vk7suDK+Ek77rDlbuxV6WqwFt30JsKHrmDCSiU=",
"owner": "juspay",
"repo": "rust-flake",
"rev": "b5f39885e2fcf137bfaf75decc077f9cca2bd984",
"type": "github"
},
"original": {
"owner": "juspay",
"repo": "rust-flake",
"type": "github"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"rust-flake",
"nixpkgs"
]
},
"locked": {
"lastModified": 1736700680,
"narHash": "sha256-9gmWIb8xsycWHEYpd2SiVIAZnUULX6Y+IMMZBcDUCQU=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "5d1865c0da63b4c949f383d982b6b43519946e8f",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1735135567,
"narHash": "sha256-8T3K5amndEavxnludPyfj3Z1IkcFdRpR23q+T0BVeZE=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "9e09d30a644c57257715902efbb3adc56c79cf28",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

66
flake.nix Normal file
View File

@ -0,0 +1,66 @@
{
description = "Subbit.xyz iou generator";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
rust-flake.url = "github:juspay/rust-flake";
flake-parts.url = "github:hercules-ci/flake-parts";
git-hooks-nix.url = "github:cachix/git-hooks.nix";
git-hooks-nix.inputs.nixpkgs.follows = "nixpkgs";
treefmt-nix.url = "github:numtide/treefmt-nix";
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs:
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.rust-flake.flakeModules.default
inputs.rust-flake.flakeModules.nixpkgs
inputs.git-hooks-nix.flakeModule
inputs.treefmt-nix.flakeModule
];
systems = [
"x86_64-linux"
];
perSystem = {
self',
config,
inputs',
pkgs,
lib,
system,
...
}: {
devShells.default = pkgs.mkShell {
inputsFrom = [
self'.devShells.rust
config.pre-commit.devShell
];
shellHook = ''
echo 1>&2 "Welcome to the development shell!"
${config.pre-commit.installationScript}
'';
name = "subbit-xyz-iou";
packages = with pkgs; [
];
};
treefmt = {
projectRootFile = "flake.nix";
flakeFormatter = true;
programs = {
prettier = {
enable = true;
settings = {
printWidth = 80;
proseWrap = "always";
};
};
alejandra.enable = true;
rustfmt.enable = true;
};
};
pre-commit.settings.hooks.treefmt.enable = true;
};
flake = {
};
};
}

5
rust-toolchain.toml Normal file
View File

@ -0,0 +1,5 @@
[toolchain]
channel = "stable"
components = [ "rustfmt", "rustc-dev", "rust-analyzer", ]
targets = [ "wasm32-unknown-unknown", "x86_64-unknown-linux-gnu" ]
profile = "default"

285
src/main.rs Normal file
View File

@ -0,0 +1,285 @@
use clap::{Parser, Subcommand};
use ed25519_dalek::{ed25519::signature::SignerMut, Signature, SigningKey, VerifyingKey};
use minicbor;
use pallas_primitives::PlutusData;
use rand::prelude::*;
use rand_chacha::rand_core::{RngCore, SeedableRng};
use serde::{Deserialize, Serialize};
#[derive(Parser)]
#[command(arg_required_else_help(true), version, about)]
struct Args {
#[command(subcommand)]
cmd: Option<Command>,
}
#[derive(Subcommand)]
enum Command {
/// Gen a keypair from seed some sensible ephemeral key args to be used with `add`
GenKeys { seed: Option<u64> },
/// Sign an iou
Sign {
/// Signing key (hex encoded)
skey: String,
/// Subbit id (hex encoded)
id: String,
/// Amount (unsigned integer u64. Seems to be largest permitted)
amt: u64,
},
/// Verify an iou signature
Verify {
/// Verifying key (hex encoded)
vkey: String,
/// Subbit id (hex encoded)
id: String,
/// Amount (unsigned integer u64. Seems to be largest permitted)
amt: u64,
/// Signature (hex encoded)
sig: String,
},
/// Generate a random signed iou to test against aiken
GenSignedIou { seed: Option<u64> },
}
fn main() -> anyhow::Result<()> {
let args = Args::parse();
match args.cmd {
Some(Command::GenKeys { seed }) => {
let skey = skey_from_seed(seed)?;
println!("{}", serde_json::to_string(&KeyPairHex::from_skey(&skey))?);
}
Some(Command::Sign { skey, id, amt }) => {
let skey = skey_from_hex(&skey)?;
let iou = Iou::from_cli(id, amt)?;
let msg = iou.to_vec()?;
let sig = sign(&mut skey.clone(), msg.clone());
let _ver = verify(&skey.verifying_key(), &msg, &sig);
println!("{}", sig_to_hex(&sig));
}
Some(Command::Verify { vkey, id, amt, sig }) => {
let vkey = vkey_from_hex(&vkey)?;
let iou = Iou::from_cli(id, amt)?;
let msg = iou.to_vec()?;
let sig = sig_from_hex(&sig)?;
let res = verify(&vkey, &msg, &sig)?;
println!("{:?}", res);
}
Some(Command::GenSignedIou { seed }) => {
let siou = SignedIou::gen(seed)?;
// println!("{}", serde_json::to_string(&siou)?) ;
//println!("{}", serde_json::to_string(&SignedIou::gen(seed )?)?) ;
println!("");
siou.aiken_fmt(seed);
println!("");
aiken_test(seed);
println!("");
}
None => {
println!("See help");
}
}
Ok(())
}
pub fn arr32(bytes: Vec<u8>) -> [u8; 32] {
let arr: [u8; 32] = TryInto::try_into(bytes).expect("");
arr
}
pub fn arr64(bytes: Vec<u8>) -> [u8; 64] {
let arr: [u8; 64] = TryInto::try_into(bytes).expect("");
arr
}
pub fn vkey_from_bytes(bytes: Vec<u8>) -> Result<VerifyingKey, anyhow::Error> {
Ok(VerifyingKey::from_bytes(&arr32(bytes))?)
}
pub fn vkey_to_bytes(key: &VerifyingKey) -> Vec<u8> {
Into::<Vec<u8>>::into(key.to_bytes())
}
pub fn vkey_from_hex(s: &str) -> Result<VerifyingKey, anyhow::Error> {
vkey_from_bytes(hex::decode(s)?)
}
pub fn vkey_to_hex(key: &VerifyingKey) -> String {
hex::encode(key.to_bytes())
}
pub fn seed_arr(seed: Option<u64>) -> [u8; 32] {
let seed = match seed {
Some(seed) => seed,
None => rand::random::<u64>(),
};
let mut as_bytes: Vec<u8> = seed.to_le_bytes().into();
as_bytes.resize(32, 0);
arr32(as_bytes)
}
pub fn skey_from_seed(seed: Option<u64>) -> Result<SigningKey, anyhow::Error> {
let arr = seed_arr(seed);
Ok(SigningKey::from_bytes(&arr))
}
pub fn skey_from_bytes(bytes: Vec<u8>) -> Result<SigningKey, anyhow::Error> {
Ok(SigningKey::from_bytes(&arr32(bytes)))
}
pub fn skey_from_hex(s: &str) -> Result<SigningKey, anyhow::Error> {
skey_from_bytes(hex::decode(s)?)
}
pub fn skey_to_hex(key: &SigningKey) -> String {
hex::encode(key.to_bytes())
}
pub fn sign(key: &mut SigningKey, msg: Vec<u8>) -> Signature {
key.try_sign(&msg).unwrap()
}
pub fn verify(key: &VerifyingKey, msg: &Vec<u8>, sig: &Signature) -> Result<(), anyhow::Error> {
let res = key.verify_strict(msg, sig)?;
Ok(res)
}
pub fn sig_from_bytes(bytes: Vec<u8>) -> Result<Signature, anyhow::Error> {
Ok(Signature::try_from(&arr64(bytes))?)
}
pub fn sig_to_bytes(sig: &Signature) -> Vec<u8> {
Into::<Vec<u8>>::into(sig.to_bytes())
}
pub fn sig_from_hex(s: &str) -> Result<Signature, anyhow::Error> {
sig_from_bytes(hex::decode(s)?)
}
pub fn sig_to_hex(sig: &Signature) -> String {
hex::encode(sig.to_bytes())
}
#[derive(Serialize, Deserialize)]
struct KeyPairHex {
skey: String,
vkey: String,
}
impl KeyPairHex {
fn from_skey(skey: &SigningKey) -> Self {
Self {
skey: skey_to_hex(&skey.clone()),
vkey: vkey_to_hex(&skey.verifying_key()),
}
}
}
pub fn id_from_hex(s: &str) -> Result<Vec<u8>, anyhow::Error> {
let id = hex::decode(s)?;
Ok(id)
}
#[derive(Serialize, Deserialize)]
struct Iou {
subbit_id: Vec<u8>,
amount: u64,
}
impl Iou {
fn from_cli(id: String, amt: u64) -> Result<Self, anyhow::Error> {
Ok(Self {
subbit_id: id_from_hex(&id)?,
amount: amt,
})
}
fn to_plutus_data(self: &Self) -> Result<PlutusData, anyhow::Error> {
let data = PlutusData::Constr(pallas_primitives::Constr {
tag: 121,
any_constructor: None,
fields: pallas_primitives::MaybeIndefArray::Indef(vec![
PlutusData::BoundedBytes(pallas_primitives::BoundedBytes::from(
self.subbit_id.clone(),
)),
PlutusData::BigInt(pallas_primitives::BigInt::Int(
pallas_primitives::Int::try_from(self.amount as i128)?,
)),
]),
});
Ok(data)
}
fn to_vec(self: &Self) -> Result<Vec<u8>, anyhow::Error> {
let v = minicbor::to_vec(self.to_plutus_data()?)?;
Ok(v)
}
fn gen(seed: Option<u64>) -> Self {
let mut rng: rand_chacha::ChaCha8Rng = SeedableRng::seed_from_u64(seed.unwrap_or(0));
let subbit_id: Vec<u8> = rng.next_u64().to_le_bytes().into();
let amount = rng.next_u64();
Iou { subbit_id, amount }
}
}
#[derive(Serialize, Deserialize)]
struct SignedIou {
vkey: String,
subbit_id: String,
amount: u64,
msg: String,
sig: String,
}
impl SignedIou {
fn gen(seed: Option<u64>) -> Result<Self, anyhow::Error> {
let skey = skey_from_seed(seed)?;
let vkey = skey.verifying_key();
let iou = Iou::gen(seed);
let msg = iou.to_vec()?;
let sig = sign(&mut skey.clone(), msg.clone());
Ok(Self {
vkey: vkey_to_hex(&vkey),
subbit_id: hex::encode(iou.subbit_id),
amount: iou.amount,
msg: hex::encode(&msg),
sig: sig_to_hex(&sig),
})
}
fn aiken_fmt(self: Self, seed: Option<u64>) {
let Self {
vkey,
subbit_id,
amount,
msg,
sig,
} = self;
println!("const i{} = IouTest {{", seed.unwrap_or(0),);
println!(" vkey: {}", aiken_hex(&vkey));
println!(" subbit_id: {}", aiken_hex(&subbit_id));
println!(" amount: {},", amount);
println!(" msg: {}", aiken_hex(&msg));
println!(" sig: {}", aiken_hex(&sig));
println!("}}");
}
}
fn aiken_test(seed: Option<u64>) {
println!("test test_i{} () {{", seed.unwrap_or(0));
println!(" let i = i{}", seed.unwrap_or(0));
println!(" verify_iou(i.vkey, i.subbit_id, t.Iou (i.amount, i.sig))");
println!("}}");
}
fn aiken_hex<T>(thing: &T) -> String
where
T: ToString,
{
format!("#\"{}\"", thing.to_string())
}
// Want scenario.
// This is (step, input, output)

70
test.ak Normal file
View File

@ -0,0 +1,70 @@
const i0 = IouTest {
vkey: #"3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29",
subbit_id: #"6c3b9aa767f785b5",
amount: 8594738769458413623,
msg: #"d8799f486c3b9aa767f785b51b7746a55fbad8c037ff",
sig: #"8bb7cb5fc82b23fac9114e9a4913f3b01c4db608e6189f01eeb431c7cd0c8c6e28484cdcc25aa895a715622598110754ede40f390797179a70e373856450ce03"
}
test test_i0 () {
let i = i0
verify_iou(i.vkey, i.subbit_id, t.Iou (i.amount, i.sig))
}
const i1 = IouTest {
vkey: #"cecc1507dc1ddd7295951c290888f095adb9044d1b73d696e6df065d683bd4fc",
subbit_id: #"b10da48cea4c0967",
amount: 1482817706323250795,
msg: #"d8799f48b10da48cea4c09671b149406d8fc0e8e6bff",
sig: #"7f96d963c32e225ae0a1fe1491466f277cd4cde77cd4f8335578fd888b61942af64972e02efc3a603241f2d84bb5df95b18f57e2f88e4d63c249716b068d8d01"
}
test test_i1 () {
let i = i1
verify_iou(i.vkey, i.subbit_id, t.Iou (i.amount, i.sig))
}
const i2 = IouTest {
vkey: #"6b79c57e6a095239282c04818e96112f3f03a4001ba97a564c23852a3f1ea5fc",
subbit_id: #"c51b8a31c98b9fe1",
amount: 10116765682372994352,
msg: #"d8799f48c51b8a31c98b9fe11b8c65f8c985b46530ff",
sig: #"7e6161aab7aff7d73afe83b176d0f3549dc81a5c69ff35aaa7576417e69d7eb81b070d8aa4ae115a6beff99851be1b6266b66d4b2a3d56b4ae499bbc66d8f306"
}
test test_i2 () {
let i = i2
verify_iou(i.vkey, i.subbit_id, t.Iou (i.amount, i.sig))
}
const i3 = IouTest {
vkey: #"dadbd184a2d526f1ebdd5c06fdad9359b228759b4d7f79d66689fa254aad8546",
subbit_id: #"5de9bc1bb4cb7a9f",
amount: 1499751601245649308,
msg: #"d8799f485de9bc1bb4cb7a9f1b14d03022a391f99cff",
sig: #"c6ca9a4e75691b030d416bb8316d4cf43601b8764d88f8cdbd36207136334abbd819cd00ac77962f7a8dbc494d253f147b5c9d78bf3a77fb6435d0f318d32d09"
}
test test_i3 () {
let i = i3
verify_iou(i.vkey, i.subbit_id, t.Iou (i.amount, i.sig))
}
const i4 = IouTest {
vkey: #"9be3287795907809407e14439ff198d5bfc7dce6f9bc743cb369146f610b4801",
subbit_id: #"22cfaefc92e4edb9",
amount: 1287912097577021104,
msg: #"d8799f4822cfaefc92e4edb91b11df953aa601aeb0ff",
sig: #"8775af7f57f681bddb8ad3682f662dcfd0fbb09b0a0fe652d880fc3d96f60f66225f4d5bc31e7a1acb729ffebec5ed0666b93e4acbc26392103a1e7878638f0e"
}
test test_i4 () {
let i = i4
verify_iou(i.vkey, i.subbit_id, t.Iou (i.amount, i.sig))
}