├── .gitignore
├── .travis.yml
├── README.md
├── include
└── README
├── lib
└── README
├── platformio.ini
├── src
└── main.cpp
└── test
└── README
/.gitignore:
--------------------------------------------------------------------------------
1 | .pio
2 | .pioenvs
3 | .piolibdeps
4 |
5 | .vscode
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Continuous Integration (CI) is the practice, in software
2 | # engineering, of merging all developer working copies with a shared mainline
3 | # several times a day < https://docs.platformio.org/page/ci/index.html >
4 | #
5 | # Documentation:
6 | #
7 | # * Travis CI Embedded Builds with PlatformIO
8 | # < https://docs.travis-ci.com/user/integration/platformio/ >
9 | #
10 | # * PlatformIO integration with Travis CI
11 | # < https://docs.platformio.org/page/ci/travis.html >
12 | #
13 | # * User Guide for `platformio ci` command
14 | # < https://docs.platformio.org/page/userguide/cmd_ci.html >
15 | #
16 | #
17 | # Please choose one of the following templates (proposed below) and uncomment
18 | # it (remove "# " before each line) or use own configuration according to the
19 | # Travis CI documentation (see above).
20 | #
21 |
22 |
23 | #
24 | # Template #1: General project. Test it using existing `platformio.ini`.
25 | #
26 |
27 | # language: python
28 | # python:
29 | # - "2.7"
30 | #
31 | # sudo: false
32 | # cache:
33 | # directories:
34 | # - "~/.platformio"
35 | #
36 | # install:
37 | # - pip install -U platformio
38 | # - platformio update
39 | #
40 | # script:
41 | # - platformio run
42 |
43 |
44 | #
45 | # Template #2: The project is intended to be used as a library with examples.
46 | #
47 |
48 | # language: python
49 | # python:
50 | # - "2.7"
51 | #
52 | # sudo: false
53 | # cache:
54 | # directories:
55 | # - "~/.platformio"
56 | #
57 | # env:
58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c
59 | # - PLATFORMIO_CI_SRC=examples/file.ino
60 | # - PLATFORMIO_CI_SRC=path/to/test/directory
61 | #
62 | # install:
63 | # - pip install -U platformio
64 | # - platformio update
65 | #
66 | # script:
67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [
](https://api.gitsponsors.com/api/badge/link?p=geRLHB9gG7O844yXmOsdMDkT54Dv8iku2Sc8pV94VZgDF2FHm8PE78j963NT2XbWrwsgUczkNPW/xVnhCKJp98EmGUbidMh/NAkwlEXM33auuLs5V056193812+/f/On)
2 | # ESP32-Bitcoin
3 | Bitcoin mining algorithm implemented on the ESP32 ;)
4 |
5 | A small platformIO project to test the mining performance with a predefined hash count.
6 |
7 | More info: https://blog.ja-ke.tech/2019/03/16/esp32-bitcoin.html
8 |
--------------------------------------------------------------------------------
/include/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for project header files.
3 |
4 | A header file is a file containing C declarations and macro definitions
5 | to be shared between several project source files. You request the use of a
6 | header file in your project source file (C, C++, etc) located in `src` folder
7 | by including it, with the C preprocessing directive `#include'.
8 |
9 | ```src/main.c
10 |
11 | #include "header.h"
12 |
13 | int main (void)
14 | {
15 | ...
16 | }
17 | ```
18 |
19 | Including a header file produces the same results as copying the header file
20 | into each source file that needs it. Such copying would be time-consuming
21 | and error-prone. With a header file, the related declarations appear
22 | in only one place. If they need to be changed, they can be changed in one
23 | place, and programs that include the header file will automatically use the
24 | new version when next recompiled. The header file eliminates the labor of
25 | finding and changing all the copies as well as the risk that a failure to
26 | find one copy will result in inconsistencies within a program.
27 |
28 | In C, the usual convention is to give header files names that end with `.h'.
29 | It is most portable to use only letters, digits, dashes, and underscores in
30 | header file names, and at most one dot.
31 |
32 | Read more about using header files in official GCC documentation:
33 |
34 | * Include Syntax
35 | * Include Operation
36 | * Once-Only Headers
37 | * Computed Includes
38 |
39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
40 |
--------------------------------------------------------------------------------
/lib/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for project specific (private) libraries.
3 | PlatformIO will compile them to static libraries and link into executable file.
4 |
5 | The source code of each library should be placed in a an own separate directory
6 | ("lib/your_library_name/[here are source files]").
7 |
8 | For example, see a structure of the following two libraries `Foo` and `Bar`:
9 |
10 | |--lib
11 | | |
12 | | |--Bar
13 | | | |--docs
14 | | | |--examples
15 | | | |--src
16 | | | |- Bar.c
17 | | | |- Bar.h
18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
19 | | |
20 | | |--Foo
21 | | | |- Foo.c
22 | | | |- Foo.h
23 | | |
24 | | |- README --> THIS FILE
25 | |
26 | |- platformio.ini
27 | |--src
28 | |- main.c
29 |
30 | and a contents of `src/main.c`:
31 | ```
32 | #include
33 | #include
34 |
35 | int main (void)
36 | {
37 | ...
38 | }
39 |
40 | ```
41 |
42 | PlatformIO Library Dependency Finder will find automatically dependent
43 | libraries scanning project source files.
44 |
45 | More information about PlatformIO Library Dependency Finder
46 | - https://docs.platformio.org/page/librarymanager/ldf.html
47 |
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | ; PlatformIO Project Configuration File
2 | ;
3 | ; Build options: build flags, source filter
4 | ; Upload options: custom upload port, speed and extra flags
5 | ; Library options: dependencies, extra library storages
6 | ; Advanced options: extra scripting
7 | ;
8 | ; Please visit documentation for the other options and examples
9 | ; https://docs.platformio.org/page/projectconf.html
10 |
11 | [env:esp32doit-devkit-v1]
12 | platform = espressif32
13 | board = esp32doit-devkit-v1
14 | framework = arduino
15 | upload_port=/dev/ttyUSB0
16 | upload_protocol=esptool
17 | upload_speed=921600
18 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "mbedtls/md.h"
3 |
4 | #define THREADS 4
5 | #define SHARE_DIFF 20000
6 |
7 | int shares = 0;
8 |
9 | // Print sha256 in little endian
10 | void printHash(unsigned char* string) {
11 | Serial.print("Hash: ");
12 | for(int i=31; i>=0; i--){
13 | char str[3];
14 |
15 | sprintf(str, "%02x", (int)string[i]);
16 | Serial.print(str);
17 | }
18 | Serial.println();
19 | }
20 |
21 | // check if first 9 bytes are zero
22 | bool checkHash(unsigned char* string) {
23 | bool valid = true;
24 | for(uint8_t i=31; i>22; i--) {
25 | if(string[i] != 0)
26 | valid = false;
27 | }
28 | return valid;
29 | }
30 |
31 | void runWorker(void *name) {
32 | Serial.printf("\nRunning %s on core %d\n", (char *)name, xPortGetCoreID());
33 |
34 | // Header of Bitcoin block nr. 563333
35 | byte payload[] = {
36 | 0x0, 0x0, 0x0, 0x20, // version
37 | 0xa2, 0x17, 0x62, 0x4e, 0xf7, 0x72, 0x1b, 0x95, 0x4c, 0x7d, 0x93, 0x75, 0xaa, 0x85, 0xc1, 0x34, 0xe5, 0xb7, 0x66, 0xd2, 0x26, 0xa, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // prev hash
38 | 0xa5, 0x12, 0x42, 0x48, 0xfa, 0x62, 0xcb, 0xef, 0x22, 0xc1, 0x26, 0x8c, 0xc0, 0x24, 0x86, 0xec, 0xfb, 0x5, 0xc2, 0x6d, 0x45, 0xba, 0x42, 0xff, 0x7e, 0x9b, 0x34, 0x6c, 0x0, 0xdf, 0x60, 0xaf, // merkle root
39 | 0x5d, 0x80, 0x68, 0x5c, // time (2019-02-16)
40 | 0x88, 0x6f, 0x2e, 0x17, // difficulty bits
41 | 0x94, 0x4b, 0x40, 0x19 // nonce
42 | };
43 | const size_t payloadLength = 80;
44 | uint32_t targetNonce = 423644052; // 0x19404b94
45 |
46 |
47 | byte interResult[32]; // 256 bit
48 | byte shaResult[32]; // 256 bit
49 |
50 | mbedtls_md_context_t ctx;
51 | mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
52 |
53 | mbedtls_md_init(&ctx);
54 | mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
55 |
56 | uint32_t nonce = targetNonce-SHARE_DIFF;
57 |
58 | uint32_t startT = micros();
59 | while(true) {
60 | payload[76] = (nonce >> 0) & 0xFF;
61 | payload[77] = (nonce >> 8) & 0xFF;
62 | payload[78] = (nonce >> 16) & 0xFF;
63 | payload[79] = (nonce >> 24) & 0xFF;
64 |
65 | mbedtls_md_starts(&ctx);
66 | mbedtls_md_update(&ctx, payload, payloadLength);
67 | mbedtls_md_finish(&ctx, interResult);
68 |
69 | mbedtls_md_starts(&ctx);
70 | mbedtls_md_update(&ctx, interResult, 32);
71 | mbedtls_md_finish(&ctx, shaResult);
72 |
73 | if(checkHash(shaResult)) {
74 | // Comment this in if you want to run only a single time
75 | // break;
76 | nonce = targetNonce-SHARE_DIFF;
77 | Serial.printf("%s on core %d: ", (char *)name, xPortGetCoreID());
78 | Serial.printf("Share completed with nonce: %d | 0x%x\n", nonce, nonce);
79 | shares++;
80 | // vTaskDelay(1);
81 | }
82 |
83 | nonce++;
84 | }
85 | uint32_t duration = micros() - startT;
86 |
87 | mbedtls_md_free(&ctx);
88 |
89 | Serial.println(checkHash(shaResult)? "Valid Block found!" : "no valid block...");
90 | printHash(shaResult);
91 | Serial.printf("With nonce: %d | 0x%x\n", nonce, nonce);
92 | Serial.printf("In %d rounds, %f ms\n", SHARE_DIFF, duration/1000.0);
93 | Serial.printf("Hash Rate: %f kH/s", (1000.0/duration)*SHARE_DIFF);
94 | }
95 |
96 | void runMonitor(void *name) {
97 | unsigned long start = millis();
98 |
99 | while (1) {
100 | unsigned long elapsed = millis()-start;
101 | Serial.printf(">>> Completed %d share(s), %d hashes, avg. hashrate %.3f KH/s\n",
102 | shares, shares*SHARE_DIFF, (1.0*shares*SHARE_DIFF)/elapsed);
103 | delay(5000);
104 | }
105 | }
106 |
107 | void setup(){
108 | Serial.begin(9600);
109 | delay(3000);
110 |
111 | // Idle task that would reset WDT never runs, because core 0 gets fully utilized
112 | disableCore0WDT();
113 |
114 | for (size_t i = 0; i < THREADS; i++) {
115 | char *name = (char*) malloc(32);
116 | sprintf(name, "Worker[%d]", i);
117 |
118 | // Start mining tasks
119 | BaseType_t res = xTaskCreate(runWorker, name, 30000, (void*)name, 1, NULL);
120 | Serial.printf("Starting %s %s!\n", name, res == pdPASS? "successful":"failed");
121 | }
122 |
123 | // Higher prio monitor task
124 | xTaskCreate(runMonitor, "Monitor", 5000, NULL, 4, NULL);
125 | }
126 |
127 |
128 | void loop(){}
129 |
--------------------------------------------------------------------------------
/test/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for PIO Unit Testing and project tests.
3 |
4 | Unit Testing is a software testing method by which individual units of
5 | source code, sets of one or more MCU program modules together with associated
6 | control data, usage procedures, and operating procedures, are tested to
7 | determine whether they are fit for use. Unit testing finds problems early
8 | in the development cycle.
9 |
10 | More information about PIO Unit Testing:
11 | - https://docs.platformio.org/page/plus/unit-testing.html
12 |
--------------------------------------------------------------------------------