commit 3fc36663896bed20728a8e42a10634a9870a62a5 Author: bitcoinafterlife Date: Sun Mar 23 13:57:52 2025 -0400 init diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..56183e6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1168 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bal-server" +version = "0.1.0" +dependencies = [ + "bitcoin", + "bytes", + "confy", + "env_logger", + "hex-conservative", + "http-body-util", + "hyper", + "hyper-util", + "log", + "regex", + "serde", + "serde_json", + "sqlite", + "tokio", +] + +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + +[[package]] +name = "bitcoin" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae" +dependencies = [ + "bech32", + "bitcoin-internals", + "bitcoin_hashes", + "hex-conservative", + "hex_lit", + "secp256k1", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "confy" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45b1f4c00870f07dc34adcac82bb6a72cc5aabca8536ba1797e01df51d2ce9a0" +dependencies = [ + "directories", + "serde", + "thiserror", + "toml", +] + +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "serde" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "sqlite" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf42adadeba1af33e2778aa22a6e9c487d8a0e3170fe65e6cb8775b3c59eb99" +dependencies = [ + "libc", + "sqlite3-sys", +] + +[[package]] +name = "sqlite3-src" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "174d4a6df77c27db281fb23de1a6d968f3aaaa4807c2a1afa8056b971f947b4a" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "sqlite3-sys" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aed0b61828382e1103930d2d5df1972d493173319730b481192e63d929097321" +dependencies = [ + "libc", + "sqlite3-src", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9d0f6b2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "bal-server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +hyper = { version = "1.2", features = ["full"] } +tokio = { version = "1", features = ["full"] } +http-body-util = "0.1" +hyper-util = { version = "0.1", features = ["full"] } +bytes = "1.2" +serde = { version = "1.0.152", features = ["derive"] } # <- Only one serde version needed (serde or serde_derive) +serde_json = "1.0.116" +confy = "0.6.1" +bitcoin = "0.31.0" +sqlite = "0.34.0" +hex-conservative = "0.1.1" +regex = "1.10.4" +log = "0.4.21" +env_logger = "0.11.5" + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c319cca --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# bal-server + +## Installation + +```bash +$ git clone .... +$ cd bal-server +$ cargo build --release +$ sudo cp target/release/bal-server /usr/local/bin +$ bal-server +``` + +## Configuration + +The `bal-server` application can be configured using environment variables. The following variables are available: + +| Variable | Description | Default | +| --- | --- | --- | +| `BAL_SERVER_CONFIG_FILE` | Path to the configuration file. If the file does not exist, a new one will be created. | `$HOME/.config/bal-server/default-config.toml` | +| `BAL_SERVER_DB_FILE` | Path to the SQLite3 database file. If the file does not exist, a new one will be created. | `bal.db` | +| `BAL_SERVER_BIND_ADDRESS` | Public address for listening to requests. | `127.0.0.1` | +| `BAL_SERVER_BIND_PORT` | Default port for listening to requests. | `9137` | +| `BAL_SERVER_REGTEST_ADDRESS` | Bitcoin address for the regtest environment. | - | +| `BAL_SERVER_REGTEST_FIXED_FEE` | Fixed fee for the regtest environment. | 50000 | +| `BAL_SERVER_SIGNET_ADDRESS` | Bitcoin address for the signet environment. | - | +| `BAL_SERVER_SIGNET_FIXED_FEE` | Fixed fee for the signet environment. | 50000 | +| `BAL_SERVER_TESTNET_ADDRESS` | Bitcoin address for the testnet environment. | - | +| `BAL_SERVER_TESTNET_FIXED_FEE` | Fixed fee for the testnet environment. | 50000 | +| `BAL_SERVER_BITCOIN_ADDRESS` | Bitcoin address for the mainnet environment. | - | +| `BAL_SERVER_BITCOIN_FIXED_FEE` | Fixed fee for the mainnet environment. | 50000 | diff --git a/bal-server.env b/bal-server.env new file mode 100644 index 0000000..6ac7cf0 --- /dev/null +++ b/bal-server.env @@ -0,0 +1,11 @@ +RUST_LOG=info +BAL_SERVER_DB_FILE=/path/to/bal.db +BAL_SERVER_BIND_ADDRESS=127.0.0.1 +BAL_SERVER_BITCOIN_ADDRESS=your mainnet address +BAL_SERVER_BITCOIN_FEE=100000 +BAL_SERVER_REGTEST_ADDRESS= +BAL_SERVER_REGTEST_FEE=100000 +BAL_SERVER_TESTNET_ADDRESS= +BAL_SERVER_TESTNET_FEE=100000 +BAL_SERVER_SIGNET_ADDRESS= +BAL_SERVER_SIGNET_FEE=100000 diff --git a/bal-server.service b/bal-server.service new file mode 100644 index 0000000..baff88b --- /dev/null +++ b/bal-server.service @@ -0,0 +1,39 @@ +[Unit] +Description=bal-server daemon +After=network.target + +[Service] + +EnvironmentFile=/etc/bal/bal-server.env + +ExecStart=/usr/local/bin/bal-server + +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=bal-server + +Type=simple +PIDFile=/run/bal-server/bal-server.pid +Restart=always +TimeoutSec=300 +RestartSec=30 + +User=bal +UMask=0027 + +RuntimeDirectory=bal-server +RuntimeDirectoryMode=0710 + +PrivateTmp=true + +ProtectSystem=full + +NoNewPrivileges=true + +PrivateDevices=true + +MemoryDenyWriteExecute=true + +[Install] +WantedBy=multi-user.target + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2b68433 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,501 @@ + +use bytes::Bytes; +use http_body_util::{combinators::BoxBody, BodyExt, Empty, Full}; +use hyper::server::conn::http1; +use hyper::service::service_fn; +use hyper::{Method, Request, Response, StatusCode}; +use tokio::net::TcpListener; +use hyper_util::rt::TokioIo; + + +use std::net::IpAddr; +use std::env; + +use std::time::{SystemTime,UNIX_EPOCH}; +use std::sync::{Arc, Mutex, MutexGuard}; +use std::collections::HashMap; +use sqlite::{State,Connection}; + +use bitcoin::{consensus, Transaction, Network}; + +use hex_conservative::FromHex; +use regex::Regex; +use serde::{Serialize, Deserialize}; +use log::{info,error,trace,debug}; +use serde_json; + +#[derive(Debug, Clone,Serialize, Deserialize)] +struct NetConfig { + address: String, + fixed_fee: u64, +} + +impl Default for NetConfig { + fn default() -> Self { + NetConfig { + address: "".to_string(), + fixed_fee: 50000, + } + } +} + +impl NetConfig { + fn default_regtest() -> Self { + NetConfig { + address: "".to_string(), + fixed_fee: 50000, + } + } +} + +#[derive(Debug, Serialize, Deserialize,Clone)] +struct MyConfig { + regtest: NetConfig, + signet: NetConfig, + testnet4: NetConfig, + testnet3: NetConfig, + mainnet: NetConfig, + bind_address: String, + bind_port: u16, // Changed to u16 for port numbers + db_file: String, +} + +impl Default for MyConfig { + fn default() -> Self { + MyConfig { + regtest: NetConfig::default_regtest(), + signet: NetConfig::default(), // Use default for other networks + testnet4: NetConfig::default(), + testnet3: NetConfig::default(), + mainnet: NetConfig::default(), + bind_address: "127.0.0.1".to_string(), + bind_port: 9137, // Ensure this is a u16 + db_file: "../bal.db".to_string(), + } + } +} +impl MyConfig { + fn get_net_config(&self, param: &str) -> &NetConfig{ + match param { + "regtest" => &self.regtest, + "testnet" => &self.testnet3, + "signet" => &self.signet, + _ => &self.mainnet, + } + } +} + +async fn echo_info( + param: &str, + cfg: &MyConfig, +) -> Result>, hyper::Error> { + info!("echo info!!!{}",param); + let netconfig=MyConfig::get_net_config(cfg,param); + return Ok(Response::new(full("{\"address\":\"".to_owned()+&netconfig.address+"\",\"base_fee\":\""+&netconfig.fixed_fee.to_string()+"\"}"))); +} +async fn echo_search(whole_body: &Bytes, + cfg: &MyConfig, +) -> Result>, hyper::Error> { + info!("echo search!!!"); + let strbody = std::str::from_utf8(&whole_body).unwrap(); + info!("{}",strbody); + trace!("{}",strbody.len()); + + let mut response = Response::new(full("Bad data received".to_owned())); + *response.status_mut() = StatusCode::BAD_REQUEST; + if strbody.len() >0 && strbody.len()<=70 { + let db = sqlite::open(&cfg.db_file).unwrap(); + trace!("qua ci arrivo"); + let mut statement = db.prepare("SELECT * FROM tbl_tx WHERE txid = ?").unwrap(); + statement.bind((1, strbody)).unwrap(); + + while let Ok(State::Row) = statement.next() { + trace!("qua tutto ok"); + let mut response_data = HashMap::new(); + match statement.read::("status") { + Ok(value) => response_data.insert("status", value), + Err(e) => { + error!("Error reading status: {}", e); + break; + //response_data.insert("status", "Error".to_string()) + } + }; + + // Read the transaction (tx) + match statement.read::("tx") { + Ok(value) => response_data.insert("tx", value), + Err(e) => { + error!("Error reading tx: {}", e); + break; + //response_data.insert("tx", "Error".to_string()) + } + }; + + match statement.read::("our_address") { + Ok(value) => response_data.insert("our_address", value), + Err(e) => { + error!("Error reading address: {}", e); + break; + //response_data.insert("tx", "Error".to_string()) + } + }; + + match statement.read::("our_fees") { + Ok(value) => response_data.insert("our_fees", value), + Err(e) => { + error!("Error reading fees: {}", e); + break; + //response_data.insert("tx", "Error".to_string()) + } + }; + + // Read the request id (reqid) + match statement.read::("reqid") { + Ok(value) => response_data.insert("time", value), + Err(e) => { + error!("Error reading reqid: {}", e); + break; + //response_data.insert("time", "Error".to_string()) + } + }; + response = match serde_json::to_string(&response_data){ + Ok(json_data) => Response::new(full(json_data)), + Err(_) => {break;} + }; + + return Ok(response); + } + } + Ok(response) + + +} +async fn echo_push(whole_body: &Bytes, + cfg: &MyConfig, + param: &str, +) -> Result>, hyper::Error> { + //let whole_body = req.collect().await?.to_bytes(); + let strbody = std::str::from_utf8(&whole_body).unwrap(); + let lines = strbody.split("\n"); + + let mut response = Response::new(full("Bad data received".to_owned())); + *response.status_mut() = StatusCode::BAD_REQUEST; + debug!("network: {}", param); + let network = match param{ + "testnet" => Network::Testnet, + "signet" => Network::Signet, + "regtest" => Network::Regtest, + &_ => Network::Bitcoin, + }; + + let req_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_nanos(); + + + let sqltxshead = "INSERT INTO tbl_tx (txid, wtxid, ntxid, tx, locktime, reqid, network, our_address, our_fees)".to_string(); + let mut sqltxs = "".to_string(); + //let mut sqlinps = "INSERT INTO tbl_input (txid, in_txid,in_vout)".to_string(); + //let mut sqlouts = "INSERT INTO tbl_output (txid, script_pubkey, address, amount)\n".to_string(); + let mut union_tx = true; + let mut already_present = false; + //let mut union_inps = true; + //let mut union_outs = true; + let db = sqlite::open(&cfg.db_file).unwrap(); + let netconfig = MyConfig::get_net_config(cfg,param); + for line in lines { + if line.len() == 0{ + trace!("line len is: {}",line.len()); + continue + } + let linea = format!("{req_time}:{line}"); + info!("New Tx: {}", linea); + let raw_tx = match Vec::::from_hex(line) { + Ok(raw_tx) => raw_tx, + Err(err) => { + error!("rawtx error: {}",err); + continue + } + }; + if raw_tx.len() > 0 { + trace!("len: {}",raw_tx.len()); + let tx: Transaction = match consensus::deserialize(&raw_tx){ + Ok(tx) => tx, + Err(err) => {error!("error: unable to parse tx: {}\n{}",line,err);continue} + }; + let txid = tx.txid().to_string(); + trace!("txid: {}",txid); + let mut statement = db.prepare("SELECT * FROM tbl_tx WHERE txid = ?").unwrap(); + statement.bind((1,&txid[..])).unwrap(); + //statement.bind((1,"Bob")).unwrap(); + if let Ok(State::Row) = statement.next() { + trace!("already present"); + already_present=true; + continue; + } + let ntxid = tx.ntxid(); + let wtxid = tx.wtxid(); + let mut found = false; + let locktime = tx.lock_time; + let mut our_fees = 0; + let mut our_address:String = "".to_string(); + //dbg!(netconfig.fixed_fee); + if netconfig.fixed_fee >0 { + for output in tx.output{ + let script_pubkey = output.script_pubkey; + let address = match bitcoin::Address::from_script(script_pubkey.as_script(), network){ + Ok(address) => address.to_string(), + Err(_) => String::new(), + }; + //dbg!(&address); + let amount = output.value; + //dbg!(&amount); + //search wllexecutor output + if address == netconfig.address.to_string() && amount.to_sat() >= netconfig.fixed_fee{ + our_fees = amount.to_sat(); + our_address = netconfig.address.to_string(); + found = true; + trace!("address and fees are correct {}: {}",our_address,our_fees); + break; + }else { + trace!("address and fees not found {}: {}",address,amount.to_sat()); + trace!("address and fees not found {}: {}",netconfig.address.to_string(),netconfig.fixed_fee); + } + } + } else { found = true; } + if found == false{ + error!("willexecutor output not found "); + //return Ok(response) + } else { + if union_tx == false { + sqltxs = format!("{sqltxs} UNION ALL"); + }else{ + union_tx = false; + } + sqltxs = format!("{sqltxs} SELECT '{txid}', '{wtxid}', '{ntxid}', '{line}', '{locktime}', '{req_time}', '{network}','{our_address}',{our_fees}"); + } + + } + else{ + trace!("rawTx len is: {}",raw_tx.len()); + debug!("{}",&sqltxs); + } + } + debug!("SQL: {}",sqltxs); + if sqltxs.len()== 0{ + if already_present == true{ + //dbg!(already_present); + return Ok(Response::new(full("already present"))) + } + } + let _ = db.execute("BEGIN TRANSACTION"); + let sql = format!("{}{}",sqltxshead,sqltxs); + if let Err(err) = db.execute(&sql){ + error!("error executing sql:{} - {}",&sql,err); + let _ = db.execute("ROLLBACK"); + //dbg!(&already_present); + if already_present == true{ + trace!("already_present = True"); + return Ok(Response::new(full("already present"))) + } + + return Ok(response) + } + //if !error { + // if let Err(_) = db.execute(sqlinps){ + // let _ = db.execute("ROLLBACK"); + // error = true + // } + //} + //if !error { + // if let Err(_) = db.execute(sqlouts){ + // let _ = db.execute("ROLLBACK"); + // error = true; + // } + //} + let _ = db.execute("COMMIT"); + Ok(Response::new(full("thx"))) +} +fn create_database(db: Connection){ + info!("database sanity check"); + let _ = db.execute("CREATE TABLE IF NOT EXISTS tbl_tx (txid PRIMARY KEY, wtxid, ntxid, tx, locktime integer, network, network_fees, reqid, our_fees, our_address, status integer DEFAULT 0);"); + let _ = db.execute("CREATE TABLE IF NOT EXISTS tbl_input (txid, in_txid,in_vout, spend_txidi);"); + let _ = db.execute("CREATE TABLE IF NOT EXISTS tbl_output (txid, script_pubkey, address, amount);"); + + let _ = db.execute("CREATE UNIQUE INDEX idx_tbl_input ON(txid, txid,in_txid,in_vout)"); + +} + + + +fn match_uri<'a>(path: &str, uri: &'a str) -> Option<&'a str> { + let re = Regex::new(path).unwrap(); + if let Some(captures) = re.captures(uri) { + if let Some(param) = captures.name("param") { + return Some(param.as_str()); + } + } + None +} + +/// This is our service handler. It receives a Request, routes on its +/// path, and returns a Future of a Response. + +async fn echo( + req: Request, + cfg: &MyConfig, +) -> Result>, hyper::Error> { + + let mut not_found = Response::new(empty()); + *not_found.status_mut() = StatusCode::NOT_FOUND; + let mut ret: Result>, hyper::Error> = Ok(not_found); + + let uri = req.uri().path().to_string(); + //dbg!(&req); + //dbg!(&uri); + match req.method() { + // Serve some instructions at / + &Method::POST => { + let whole_body = req.collect().await?.to_bytes(); + if let Some(param) = match_uri(r"^?/?(?P[^/]?+)?/pushtxs$",uri.as_str()) { + //let whole_body = collect_body(req,512_000).await?; + ret = echo_push(&whole_body,cfg,param).await; + } + if uri=="/searchtx"{ + //let whole_body = collect_body(req,64).await?; + ret = echo_search(&whole_body,cfg).await; + } + ret + } + &Method::GET => { + if let Some(param) = match_uri(r"^?/?(?P[^/]?+)?/info$",uri.as_str()) { + ret = echo_info(param,cfg).await; + } + ret + } + + // Return the 404 Not Found for other routes. + _ => ret + } +} + +fn empty() -> BoxBody { + Empty::::new() + .map_err(|never| match never {}) + .boxed() +} + +fn full>(chunk: T) -> BoxBody { + Full::new(chunk.into()) + .map_err(|never| match never {}) + .boxed() +} +fn parse_env(cfg: &Arc>){ + let mut cfg_lock = cfg.lock().unwrap(); + match env::var("BAL_SERVER_DB_FILE") { + Ok(value) => { + cfg_lock.db_file = value;}, + Err(_) => {}, + } + match env::var("BAL_SERVER_BIND_ADDRESS") { + Ok(value) => { + cfg_lock.bind_address = value;}, + Err(_) => {}, + } + match env::var("BAL_SERVER_BIND_PORT") { + Ok(value) => { + cfg_lock.bind_address = value;}, + Err(_) => {}, + } + cfg_lock = parse_env_netconfig(cfg_lock,"regtest"); + cfg_lock = parse_env_netconfig(cfg_lock,"signet"); + cfg_lock = parse_env_netconfig(cfg_lock,"testnet3"); + cfg_lock = parse_env_netconfig(cfg_lock,"testnet"); + drop(parse_env_netconfig(cfg_lock,"bitcoin")); + +} +fn parse_env_netconfig<'a>(mut cfg_lock: MutexGuard<'a, MyConfig>, chain: &'a str) -> MutexGuard<'a, MyConfig>{ + let cfg = match chain{ + "regtest" => &mut cfg_lock.regtest, + "signet" => &mut cfg_lock.signet, + "testnet3" => &mut cfg_lock.testnet3, + "testnet" => &mut cfg_lock.testnet4, + &_ => &mut cfg_lock.mainnet, + }; + match env::var(format!("BAL_SERVER_{}_ADDRESS",chain.to_uppercase())) { + Ok(value) => { cfg.address = value; }, + Err(_) => {}, + } + match env::var(format!("BAL_SERVER_{}_FIXE_FEE",chain.to_uppercase())) { + Ok(value) => { + match value.parse::(){ + Ok(value) =>{ cfg.fixed_fee = value; }, + Err(_) => {}, + } + } + Err(_) => {}, + } + cfg_lock +} +fn get_default_config()-> MyConfig { + + let file = confy::get_configuration_file_path("bal-server",None).expect("Error while getting path"); + info!("Default configuration file path is: {:#?}", file); + confy::load("bal-server",None).expect("cant_load") +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::init(); + let cfg: Arc> = match env::var("BAL_SERVER_CONFIG_FILE") { + Ok(value) => { + Arc::new(Mutex::new( + match confy::load_path(value.to_string()){ + Ok(val) => { + info!("The configuration file path is: {:#?}", value); + val + }, + Err(err) => { + error!("{}",err); + get_default_config() + } + } + )) + }, + Err(_) => { + Arc::new(Mutex::new(get_default_config())) + }, + }; + + parse_env(&cfg); + let cfg_lock = cfg.lock().unwrap(); + + let db = sqlite::open(&cfg_lock.db_file).unwrap(); + create_database(db); + + let addr = cfg_lock.bind_address.to_string(); + info!("bind address:{}",addr); + let addr: IpAddr = addr.parse()?; + + let listener = TcpListener::bind((addr,cfg_lock.bind_port)).await?; + info!("Listening on http://{}:{}", addr,cfg_lock.bind_port); + + + loop { + let (stream, _) = listener.accept().await?; + let io = TokioIo::new(stream); + + tokio::task::spawn({ + let cfg = cfg_lock.clone(); + async move { + if let Err(err) = http1::Builder::new() + .serve_connection(io, service_fn(|req: Request| async { + echo(req,&cfg).await + })) + .await + { + error!("Error serving connection: {:?}", err); + } + + } + }); + } +}