Implement the mining software
This commit is contained in:
@@ -158,7 +158,7 @@ A "block transfer" message is sent back in response to a "block request" message
|
|||||||
| protocol version = 0 (BE) | 2 |
|
| protocol version = 0 (BE) | 2 |
|
||||||
| capable version = 0 (BE) | 2 |
|
| capable version = 0 (BE) | 2 |
|
||||||
| type = 7 (BE) | 1 |
|
| type = 7 (BE) | 1 |
|
||||||
| padding (nullbytes) | 220 |
|
| padding (nullbytes) | 252 |
|
||||||
|
|
||||||
The node should answer to a "Mining task request" with a "Mining task response"
|
The node should answer to a "Mining task request" with a "Mining task response"
|
||||||
|
|
||||||
@@ -173,6 +173,7 @@ The node should answer to a "Mining task request" with a "Mining task response"
|
|||||||
| previous hash | 32 |
|
| previous hash | 32 |
|
||||||
| timestamp (unix time in seconds, BE) | 8 |
|
| timestamp (unix time in seconds, BE) | 8 |
|
||||||
| difficulty sum (BE) | 32 |
|
| difficulty sum (BE) | 32 |
|
||||||
|
| threshold | 32 |
|
||||||
|
|
||||||
The node tells the miner "timestamp", "previous hash", "difficulty sum" and "transaction" for the new block.
|
The node tells the miner "timestamp", "previous hash", "difficulty sum" and "transaction" for the new block.
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def main():
|
|||||||
if len(block) != 292:
|
if len(block) != 292:
|
||||||
break
|
break
|
||||||
timestamp = int.from_bytes(block[244:252], "big")
|
timestamp = int.from_bytes(block[244:252], "big")
|
||||||
time_info = time.strftime("%d.%m.%Y %H:%M.%S", time.localtime(timestamp))
|
time_info = time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(timestamp))
|
||||||
message = prepare_message(block[148:180])
|
message = prepare_message(block[148:180])
|
||||||
print(f"[{time_info}] {message}")
|
print(f"[{time_info}] {message}")
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
|||||||
1
miner/.gitignore
vendored
Normal file
1
miner/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
385
miner/Cargo.lock
generated
Normal file
385
miner/Cargo.lock
generated
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||||
|
|
||||||
|
[[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 = "carrotcoin_miner"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"clap",
|
||||||
|
"num_cpus",
|
||||||
|
"rand",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.153"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||||
|
|
||||||
|
[[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 = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
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",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "strsim"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.55"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[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.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||||
13
miner/Cargo.toml
Normal file
13
miner/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "carrotcoin_miner"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
base64 = "0.22.0"
|
||||||
|
clap = { version = "4.5.3", features = ["derive"] }
|
||||||
|
num_cpus = "1.16.0"
|
||||||
|
rand = "0.8.5"
|
||||||
|
sha2 = "0.10.8"
|
||||||
198
miner/src/main.rs
Normal file
198
miner/src/main.rs
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
use base64::prelude::*;
|
||||||
|
use clap::Parser;
|
||||||
|
use rand::Rng;
|
||||||
|
use sha2::Digest;
|
||||||
|
use sha2::Sha256;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
use std::net::Ipv6Addr;
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::sync::mpsc::TryRecvError;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
/// Carrotcoin miner
|
||||||
|
#[derive(Parser)]
|
||||||
|
struct Args {
|
||||||
|
/// Wallet address for the mining reward
|
||||||
|
#[arg(short, long)]
|
||||||
|
wallet: String,
|
||||||
|
|
||||||
|
/// Message to encode in each block (maximum 32 bytes)
|
||||||
|
#[arg(short, long)]
|
||||||
|
message: Option<String>,
|
||||||
|
|
||||||
|
/// Number of threads to start
|
||||||
|
#[arg(short, long)]
|
||||||
|
thread_count: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Task {
|
||||||
|
prefix: Vec<u8>,
|
||||||
|
threshold: [u8; 32],
|
||||||
|
work_counter: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_mining_worker(task: Arc<Mutex<Task>>, results: mpsc::Sender<Vec<u8>>) {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
loop {
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
let mut lock_guard = task.lock().unwrap();
|
||||||
|
let prefix = lock_guard.prefix.clone();
|
||||||
|
hasher.update(&prefix);
|
||||||
|
let threshold = lock_guard.threshold.clone();
|
||||||
|
lock_guard.work_counter += 1;
|
||||||
|
drop(lock_guard);
|
||||||
|
let start = rng.gen_range(0..((1u64 << 50) - 1)) << 14;
|
||||||
|
for nonce in start..(start + (1 << 14)) {
|
||||||
|
let mut hasher_cloned = hasher.clone();
|
||||||
|
let nonce_bytes = nonce.to_be_bytes();
|
||||||
|
hasher_cloned.update(nonce_bytes);
|
||||||
|
let result_hash: [u8; 32] = hasher_cloned.finalize().into();
|
||||||
|
if result_hash[0] == 0 && result_hash <= threshold {
|
||||||
|
let mut block = Vec::with_capacity(292);
|
||||||
|
block.extend_from_slice(&prefix);
|
||||||
|
block.extend_from_slice(&nonce_bytes);
|
||||||
|
results.send(block).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_threads(task: &Arc<Mutex<Task>>, results: &mpsc::Sender<Vec<u8>>, thread_count: usize) {
|
||||||
|
for _ in 0..thread_count {
|
||||||
|
let task_cloned = task.clone();
|
||||||
|
let results_cloned = results.clone();
|
||||||
|
thread::spawn(|| run_mining_worker(task_cloned, results_cloned));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_message(message_string: &str) -> Option<Vec<u8>> {
|
||||||
|
let message_bytes = message_string.as_bytes();
|
||||||
|
if message_bytes.len() > 32 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut message_buffer = Vec::with_capacity(32);
|
||||||
|
message_buffer.extend_from_slice(&message_bytes);
|
||||||
|
message_buffer.resize(32, 0);
|
||||||
|
Some(message_buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_statistics(duration: Duration, work_counter: usize, threshold: &[u8]) {
|
||||||
|
let duration_seconds = duration.as_secs_f64();
|
||||||
|
let mut hash_numeric = 0f64;
|
||||||
|
for byte_value in threshold {
|
||||||
|
hash_numeric = hash_numeric * 256.0 + f64::from(*byte_value);
|
||||||
|
}
|
||||||
|
let difficulty = 2.0f64.powi(256) / hash_numeric;
|
||||||
|
let relative_difficulty = difficulty / 2.0f64.powi(28);
|
||||||
|
let hashrate = (work_counter as f64) / duration_seconds * 2.0f64.powi(14);
|
||||||
|
let hashrate_mhs = hashrate / 1e6;
|
||||||
|
let expected_reward = hashrate * 3600f64 / difficulty;
|
||||||
|
println!("difficulty: {relative_difficulty:.02}; hashrate: {hashrate_mhs:.02} Mh/s; expected reward: {expected_reward:.04} cc / hour");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
let public_key = match BASE64_STANDARD.decode(args.wallet) {
|
||||||
|
Ok(key_bytes) if key_bytes.len() == 32 => key_bytes,
|
||||||
|
Ok(_) => {
|
||||||
|
eprintln!("The wallet address is not exactly 32 bytes, so it is invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Failed to base64-decode the wallet address.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let message = match build_message(args.message.as_deref().unwrap_or("")) {
|
||||||
|
Some(message) => message,
|
||||||
|
None => {
|
||||||
|
eprintln!("The provided block message ist too long. Must be at most 32 bytes.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let thread_count = args.thread_count.unwrap_or_else(num_cpus::get);
|
||||||
|
|
||||||
|
let mut last_statistic_time = Instant::now();
|
||||||
|
let mut statistic_output_delay = Duration::from_secs(5);
|
||||||
|
|
||||||
|
let socket = UdpSocket::bind((Ipv6Addr::UNSPECIFIED, 0)).unwrap();
|
||||||
|
let mut threads_started = false;
|
||||||
|
socket.connect((Ipv6Addr::LOCALHOST, 62039)).unwrap();
|
||||||
|
socket.set_nonblocking(true).unwrap();
|
||||||
|
let task = Arc::new(Mutex::new(Task {
|
||||||
|
prefix: Vec::new(),
|
||||||
|
threshold: [0u8; 32],
|
||||||
|
work_counter: 0,
|
||||||
|
}));
|
||||||
|
let (results_tx, results_rx) = mpsc::channel();
|
||||||
|
let mut request = vec![0u8; 257];
|
||||||
|
request[4] = 7;
|
||||||
|
loop {
|
||||||
|
let mut recv_buffer = vec![0u8; 512];
|
||||||
|
loop {
|
||||||
|
match socket.recv(&mut recv_buffer) {
|
||||||
|
Ok(size) => {
|
||||||
|
if size == 257 && &recv_buffer[0..5] == &[0, 0, 0, 0, 8] {
|
||||||
|
let transaction = &recv_buffer[5..153];
|
||||||
|
let previous_hash = &recv_buffer[153..185];
|
||||||
|
let timestamp = &recv_buffer[185..193];
|
||||||
|
let difficulty_sum = &recv_buffer[193..225];
|
||||||
|
let threshold = &recv_buffer[225..257];
|
||||||
|
let mut prefix = Vec::with_capacity(292);
|
||||||
|
prefix.extend_from_slice(transaction);
|
||||||
|
prefix.extend_from_slice(&message);
|
||||||
|
prefix.extend_from_slice(&public_key);
|
||||||
|
prefix.extend_from_slice(previous_hash);
|
||||||
|
prefix.extend_from_slice(timestamp);
|
||||||
|
prefix.extend_from_slice(difficulty_sum);
|
||||||
|
let mut lock = task.lock().unwrap();
|
||||||
|
lock.prefix = prefix;
|
||||||
|
lock.threshold = threshold.try_into().unwrap();
|
||||||
|
let current_time = Instant::now();
|
||||||
|
let duration = current_time - last_statistic_time;
|
||||||
|
if duration >= statistic_output_delay {
|
||||||
|
show_statistics(duration, lock.work_counter, threshold);
|
||||||
|
last_statistic_time = current_time;
|
||||||
|
lock.work_counter = 0;
|
||||||
|
statistic_output_delay = Duration::from_secs(60);
|
||||||
|
}
|
||||||
|
if !threads_started {
|
||||||
|
start_threads(&task, &results_tx, thread_count);
|
||||||
|
threads_started = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if e.kind() == ErrorKind::WouldBlock {
|
||||||
|
break;
|
||||||
|
} else if e.kind() == ErrorKind::ConnectionRefused {
|
||||||
|
eprintln!("Node is not running locally!");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
panic!("{e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.send(&request).unwrap();
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
let mined_block = match results_rx.try_recv() {
|
||||||
|
Ok(block) => Some(block),
|
||||||
|
Err(e) if e == TryRecvError::Empty => None,
|
||||||
|
Err(e) => panic!("{e}"),
|
||||||
|
};
|
||||||
|
if let Some(block) = mined_block {
|
||||||
|
let mut block_transfer = Vec::with_capacity(297);
|
||||||
|
block_transfer.extend_from_slice(b"\0\0\0\0\x02");
|
||||||
|
block_transfer.extend_from_slice(&block);
|
||||||
|
socket.send(&block_transfer).unwrap();
|
||||||
|
println!("I found a carrot! \u{1f955}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
node.py
13
node.py
@@ -362,8 +362,8 @@ def receiver(node, b):
|
|||||||
receive_observer.publish(identifier, event_obj)
|
receive_observer.publish(identifier, event_obj)
|
||||||
elif msg_type == 7:
|
elif msg_type == 7:
|
||||||
# mining task request
|
# mining task request
|
||||||
if msg_len != 225:
|
if msg_len != 257:
|
||||||
log(f"Got a mining task request of wrong length ({msg_len} bytes from {sender}, but expected 255 bytes)")
|
log(f"Got a mining task request of wrong length ({msg_len} bytes from {sender}, but expected 257 bytes)")
|
||||||
continue
|
continue
|
||||||
transaction = b.open_transactions.get_transaction(0)
|
transaction = b.open_transactions.get_transaction(0)
|
||||||
if transaction is not None:
|
if transaction is not None:
|
||||||
@@ -374,8 +374,8 @@ def receiver(node, b):
|
|||||||
timestamp_raw = t.to_bytes(8, "big")
|
timestamp_raw = t.to_bytes(8, "big")
|
||||||
latest_block = b.get_latest_block()
|
latest_block = b.get_latest_block()
|
||||||
if latest_block is not None:
|
if latest_block is not None:
|
||||||
B_1_difficulty_sum, _ = latest_block.get_difficulty_info(0, blockchain)
|
B_1_difficulty_sum, _ = latest_block.get_difficulty_info(0, b)
|
||||||
B_10_difficulty_sum, B_10_timestamp = latest_block.get_difficulty_info(9, blockchain)
|
B_10_difficulty_sum, B_10_timestamp = latest_block.get_difficulty_info(9, b)
|
||||||
D = B_1_difficulty_sum - B_10_difficulty_sum
|
D = B_1_difficulty_sum - B_10_difficulty_sum
|
||||||
T = t - B_10_timestamp
|
T = t - B_10_timestamp
|
||||||
calculated_difficulty = D * 3000 // 9 // T
|
calculated_difficulty = D * 3000 // 9 // T
|
||||||
@@ -383,13 +383,16 @@ def receiver(node, b):
|
|||||||
difficulty_sum = B_1_difficulty_sum + block_difficulty
|
difficulty_sum = B_1_difficulty_sum + block_difficulty
|
||||||
previous_hash = latest_block.own_hash
|
previous_hash = latest_block.own_hash
|
||||||
else:
|
else:
|
||||||
|
block_difficulty = 2**28
|
||||||
difficulty_sum = 2**29
|
difficulty_sum = 2**29
|
||||||
previous_hash = 32 * b"\0"
|
previous_hash = 32 * b"\0"
|
||||||
|
threshold = (2**256 - 1) // block_difficulty
|
||||||
response = b"\0\0\0\0\x08" + \
|
response = b"\0\0\0\0\x08" + \
|
||||||
transaction_raw + \
|
transaction_raw + \
|
||||||
previous_hash + \
|
previous_hash + \
|
||||||
timestamp_raw + \
|
timestamp_raw + \
|
||||||
difficulty_sum.to_bytes(32, "big")
|
difficulty_sum.to_bytes(32, "big") + \
|
||||||
|
threshold.to_bytes(32, "big")
|
||||||
node.node_socket.sendto(response, addr)
|
node.node_socket.sendto(response, addr)
|
||||||
elif msg_type == 9:
|
elif msg_type == 9:
|
||||||
# payment request
|
# payment request
|
||||||
|
|||||||
Reference in New Issue
Block a user