Skip to content

Commit 4bfdccd

Browse files
authored
Show BIP-110 signal in Block Header (#1588)
* Show BIP-110 signal in Block Header * Fix tests * Fix tests? * Move test to test_stratum_json * Use proper parameters for process_notification call * Add BIP-110 signal expiry * Fix test compile * Clean up field names
1 parent aba1387 commit 4bfdccd

File tree

12 files changed

+128
-20
lines changed

12 files changed

+128
-20
lines changed

components/stratum/coinbase_decoder.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <ctype.h>
99
#include "mbedtls/sha256.h"
1010

11+
#define BIP110_SIGNAL_BIT 4
12+
#define BIP110_SIGNAL_EXPIRY_BLOCK 965664
13+
1114
// Wrapper for SHA256 to match libbase58's expected signature
1215
static bool my_sha256(void *digest, const void *data, size_t datasz) {
1316
mbedtls_sha256(data, datasz, digest, 0);
@@ -144,14 +147,14 @@ esp_err_t coinbase_process_notification(const mining_notify *notification,
144147
const char *extranonce1,
145148
int extranonce2_len,
146149
const char *user_address,
147-
bool decode_outputs,
150+
bool decode_coinbase_tx,
148151
mining_notification_result_t *result) {
149152
if (!notification || !extranonce1 || !result) return ESP_ERR_INVALID_ARG;
150153

151154
// Initialize result
152155
result->total_value_satoshis = 0;
153156
result->user_value_satoshis = 0;
154-
result->decoding_enabled = decode_outputs;
157+
result->decode_coinbase_tx = decode_coinbase_tx;
155158

156159
// 1. Calculate difficulty
157160
result->network_difficulty = networkDifficulty(notification->target);
@@ -178,6 +181,9 @@ esp_err_t coinbase_process_notification(const mining_notify *notification,
178181
hex2bin(notification->coinbase_1 + (coinbase_1_offset * 2), (uint8_t *)&result->block_height, block_height_len);
179182
coinbase_1_offset += block_height_len;
180183

184+
// Detect BIP-110 signaling: check if bit 4 (0x00000010) is set in version
185+
result->bip110_signaling = decode_coinbase_tx && result->block_height < BIP110_SIGNAL_EXPIRY_BLOCK && (notification->version & (1U << BIP110_SIGNAL_BIT)) != 0;
186+
181187
// Calculate remaining scriptsig length (excluding block height part)
182188
int scriptsig_length = scriptsig_len - 1 - block_height_len;
183189
size_t extranonce1_len = strlen(extranonce1) / 2;
@@ -281,7 +287,7 @@ esp_err_t coinbase_process_notification(const mining_notify *notification,
281287

282288
if (offset + script_len > coinbase_2_len) break;
283289

284-
if (decode_outputs) {
290+
if (decode_coinbase_tx) {
285291
if (value_satoshis > 0) {
286292
char output_address[MAX_ADDRESS_STRING_LEN];
287293
coinbase_decode_address_from_scriptpubkey(coinbase_2_bin + offset, script_len, output_address, MAX_ADDRESS_STRING_LEN);

components/stratum/include/coinbase_decoder.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ typedef struct {
8585
int output_count;
8686
uint64_t total_value_satoshis;
8787
uint64_t user_value_satoshis;
88-
bool decoding_enabled;
88+
bool decode_coinbase_tx;
89+
bool bip110_signaling; // BIP-110: signaling via version bit 4 (0x00000010)
8990
} mining_notification_result_t;
9091

9192
/**
@@ -95,15 +96,15 @@ typedef struct {
9596
* @param extranonce1 Hex string of extranonce1
9697
* @param extranonce2_len Length of extranonce2 in bytes
9798
* @param user_address Payout address of the user
98-
* @param decode_outputs Enable coinbase tx decoding
99+
* @param decode_coinbase_tx Enable coinbase tx decoding
99100
* @param result Pointer to store the results
100101
* @return esp_err_t
101102
*/
102103
esp_err_t coinbase_process_notification(const mining_notify *notification,
103104
const char *extranonce1,
104105
int extranonce2_len,
105106
const char *user_address,
106-
bool decode_outputs,
107+
bool decode_coinbase_tx,
107108
mining_notification_result_t *result);
108109

109110
#endif // COINBASE_DECODER_H

components/stratum/test/test_coinbase_decoder.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,73 @@ TEST_CASE("Decode P2TR address", "[coinbase_decoder]")
119119

120120
TEST_ASSERT_EQUAL_STRING("bc1pllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqqc0cgpt", output);
121121
}
122+
123+
TEST_CASE("BIP-110 signaling not detected", "[coinbase_decoder]")
124+
{
125+
// Create a mining_notify without BIP-110 bit set
126+
mining_notify notify = { 0 };
127+
notify.version = 0x20000000; // No BIP-110 signaling
128+
notify.job_id = "test_job";
129+
notify.coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000";
130+
notify.coinbase_2 = "41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000";
131+
132+
mining_notification_result_t result = { 0 };
133+
134+
// Use valid extranonce1 (8 hex chars = 4 bytes)
135+
esp_err_t err = coinbase_process_notification(&notify, "01020304", 8, "", true, &result);
136+
TEST_ASSERT_EQUAL(ESP_OK, err);
137+
TEST_ASSERT_FALSE(result.bip110_signaling);
138+
}
139+
140+
TEST_CASE("BIP-110 signaling detected", "[coinbase_decoder]")
141+
{
142+
// Create a mining_notify with BIP-110 bit set (bit 4 = 0x00000010)
143+
mining_notify notify = { 0 };
144+
notify.version = 0x20000010; // Version with BIP-110 signaling
145+
notify.job_id = "test_job";
146+
notify.coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000";
147+
notify.coinbase_2 = "41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000";
148+
149+
mining_notification_result_t result = { 0 };
150+
151+
// Use valid extranonce1 (8 hex chars = 4 bytes)
152+
esp_err_t err = coinbase_process_notification(&notify, "01020304", 8, "", true, &result);
153+
TEST_ASSERT_EQUAL(ESP_OK, err);
154+
TEST_ASSERT_TRUE(result.bip110_signaling);
155+
}
156+
157+
TEST_CASE("BIP-110 signaling last block", "[coinbase_decoder]")
158+
{
159+
// Create a mining_notify with BIP-110 bit set (bit 4 = 0x00000010)
160+
mining_notify notify = { 0 };
161+
notify.version = 0x20000010; // Version with BIP-110 signaling
162+
notify.job_id = "test_job";
163+
notify.coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b031fbc0efabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000";
164+
notify.coinbase_2 = "41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000";
165+
166+
mining_notification_result_t result = { 0 };
167+
168+
// Use valid extranonce1 (8 hex chars = 4 bytes)
169+
esp_err_t err = coinbase_process_notification(&notify, "01020304", 8, "", true, &result);
170+
TEST_ASSERT_EQUAL(ESP_OK, err);
171+
TEST_ASSERT_EQUAL(965663, result.block_height);
172+
TEST_ASSERT_TRUE(result.bip110_signaling);
173+
}
174+
175+
TEST_CASE("BIP-110 signaling expired", "[coinbase_decoder]")
176+
{
177+
// Create a mining_notify with BIP-110 bit set (bit 4 = 0x00000010)
178+
mining_notify notify = { 0 };
179+
notify.version = 0x20000010; // Version with BIP-110 signaling
180+
notify.job_id = "test_job";
181+
notify.coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0320bc0efabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000";
182+
notify.coinbase_2 = "41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000";
183+
184+
mining_notification_result_t result = { 0 };
185+
186+
// Use valid extranonce1 (8 hex chars = 4 bytes)
187+
esp_err_t err = coinbase_process_notification(&notify, "01020304", 8, "", true, &result);
188+
TEST_ASSERT_EQUAL(ESP_OK, err);
189+
TEST_ASSERT_EQUAL(965664, result.block_height);
190+
TEST_ASSERT_FALSE(result.bip110_signaling);
191+
}

main/global_state.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#define HISTORY_LENGTH 100
2323
#define DIFF_STRING_SIZE 10
24+
#define MAX_BLOCK_SIGNALS 8
25+
#define MAX_BLOCK_SIGNAL_LEN 16
2426

2527
typedef struct {
2628
char message[64];
@@ -67,8 +69,8 @@ typedef struct
6769
uint16_t fallback_pool_difficulty;
6870
bool pool_extranonce_subscribe;
6971
bool fallback_pool_extranonce_subscribe;
70-
bool pool_decode_coinbase;
71-
bool fallback_pool_decode_coinbase;
72+
bool pool_decode_coinbase_tx;
73+
bool fallback_pool_decode_coinbase_tx;
7274
float response_time;
7375
bool use_fallback_stratum;
7476
uint16_t pool_is_tls;
@@ -152,6 +154,8 @@ typedef struct
152154
uint64_t coinbase_value_user_satoshis;
153155
uint64_t network_nonce_diff;
154156
char network_diff_string[DIFF_STRING_SIZE];
157+
char block_signals[MAX_BLOCK_SIGNALS][MAX_BLOCK_SIGNAL_LEN];
158+
int block_signals_count;
155159
} GlobalState;
156160

157161
#endif /* GLOBAL_STATE_H_ */

main/http_server/axe-os/src/app/components/home/home.component.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,12 @@ <h4 class="mb-0">
441441

442442
<div class="col-12 md:col-4">
443443
<div class="card">
444-
<h4 class="white-space-nowrap overflow-hidden text-overflow-ellipsis">Block Header</h4>
444+
<h4 class="white-space-nowrap overflow-hidden text-overflow-ellipsis">
445+
Block Header
446+
<span *ngIf="info.blockSignals && info.blockSignals.length > 0" class="vertical-align-bottom ml-2">
447+
<span *ngFor="let signal of info.blockSignals" class="p-badge p-badge-success ml-1">{{ signal }}</span>
448+
</span>
449+
</h4>
445450

446451
<div class="flex flex-nowrap">
447452
<div class="col-fixed-width text-500">

main/http_server/axe-os/src/app/services/system.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export class SystemApiService {
126126
blockHeight: 811111,
127127
scriptsig: "..%..h..,H...ckpool.eu/solo.ckpool.org/",
128128
networkDifficulty: 155970000000000,
129+
blockSignals: [],
129130
hashrateMonitor: {
130131
asics: [{
131132
total: 441.2579,

main/http_server/http_server.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -913,15 +913,15 @@ static esp_err_t GET_system_info(httpd_req_t * req)
913913
cJSON_AddNumberToObject(root, "stratumExtranonceSubscribe", nvs_config_get_bool(NVS_CONFIG_STRATUM_EXTRANONCE_SUBSCRIBE));
914914
cJSON_AddNumberToObject(root, "stratumTLS", nvs_config_get_u16(NVS_CONFIG_STRATUM_TLS));
915915
cJSON_AddStringToObject(root, "stratumCert", stratumCert);
916-
cJSON_AddNumberToObject(root, "stratumDecodeCoinbase", nvs_config_get_bool(NVS_CONFIG_STRATUM_DECODE_COINBASE));
916+
cJSON_AddNumberToObject(root, "stratumDecodeCoinbase", nvs_config_get_bool(NVS_CONFIG_STRATUM_DECODE_COINBASE_TX));
917917
cJSON_AddStringToObject(root, "fallbackStratumURL", fallbackStratumURL);
918918
cJSON_AddNumberToObject(root, "fallbackStratumPort", nvs_config_get_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT));
919919
cJSON_AddStringToObject(root, "fallbackStratumUser", fallbackStratumUser);
920920
cJSON_AddNumberToObject(root, "fallbackStratumSuggestedDifficulty", nvs_config_get_u16(NVS_CONFIG_FALLBACK_STRATUM_DIFFICULTY));
921921
cJSON_AddNumberToObject(root, "fallbackStratumExtranonceSubscribe", nvs_config_get_bool(NVS_CONFIG_FALLBACK_STRATUM_EXTRANONCE_SUBSCRIBE));
922922
cJSON_AddNumberToObject(root, "fallbackStratumTLS", nvs_config_get_u16(NVS_CONFIG_FALLBACK_STRATUM_TLS));
923923
cJSON_AddStringToObject(root, "fallbackStratumCert", fallbackStratumCert);
924-
cJSON_AddNumberToObject(root, "fallbackStratumDecodeCoinbase", nvs_config_get_bool(NVS_CONFIG_FALLBACK_STRATUM_DECODE_COINBASE));
924+
cJSON_AddNumberToObject(root, "fallbackStratumDecodeCoinbase", nvs_config_get_bool(NVS_CONFIG_FALLBACK_STRATUM_DECODE_COINBASE_TX));
925925
cJSON_AddFloatToObject(root, "responseTime", GLOBAL_STATE->SYSTEM_MODULE.response_time);
926926

927927
cJSON_AddStringToObject(root, "version", GLOBAL_STATE->SYSTEM_MODULE.version);
@@ -962,6 +962,12 @@ static esp_err_t GET_system_info(httpd_req_t * req)
962962
cJSON_AddStringToObject(root, "scriptsig", GLOBAL_STATE->scriptsig);
963963
cJSON_AddNumberToObject(root, "networkDifficulty", GLOBAL_STATE->network_nonce_diff);
964964

965+
cJSON *block_signals_array = cJSON_CreateArray();
966+
for (int i = 0; i < GLOBAL_STATE->block_signals_count; i++) {
967+
cJSON_AddItemToArray(block_signals_array, cJSON_CreateString(GLOBAL_STATE->block_signals[i]));
968+
}
969+
cJSON_AddItemToObject(root, "blockSignals", block_signals_array);
970+
965971
cJSON *outputs_array = cJSON_CreateArray();
966972
for (int i = 0; i < GLOBAL_STATE->coinbase_output_count; i++) {
967973
cJSON *output_obj = cJSON_CreateObject();

main/http_server/openapi.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ components:
192192
- blockHeight
193193
- scriptsig
194194
- networkDifficulty
195+
- blockSignals
195196
- blockFound
196197
- coinbaseOutputs
197198
- coinbaseValueTotalSatoshis
@@ -443,6 +444,11 @@ components:
443444
networkDifficulty:
444445
type: number
445446
description: Current network difficulty
447+
blockSignals:
448+
type: array
449+
description: Active block signaling (e.g., BIP-110)
450+
items:
451+
type: string
446452
blockFound:
447453
type: number
448454
description: Number of blocks found

main/nvs_config.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static Settings settings[NVS_CONFIG_COUNT] = {
5656
[NVS_CONFIG_STRATUM_EXTRANONCE_SUBSCRIBE] = {.nvs_key_name = "stratumxnsub", .type = TYPE_BOOL, .default_value = {.b = (bool)STRATUM_EXTRANONCE_SUBSCRIBE}, .rest_name = "stratumExtranonceSubscribe", .min = 0, .max = 1},
5757
[NVS_CONFIG_STRATUM_TLS] = {.nvs_key_name = "stratumtls", .type = TYPE_U16, .default_value = {.u16 = (uint16_t)CONFIG_STRATUM_TLS}, .rest_name = "stratumTLS", .min = 0, .max = 3},
5858
[NVS_CONFIG_STRATUM_CERT] = {.nvs_key_name = "stratumcert", .type = TYPE_STR, .default_value = {.str = (char *)CONFIG_STRATUM_CERT}, .rest_name = "stratumCert", .min = 0, .max = NVS_STR_LIMIT},
59-
[NVS_CONFIG_STRATUM_DECODE_COINBASE] = {.nvs_key_name = "stratumdecode", .type = TYPE_BOOL, .default_value = {.b = true}, .rest_name = "stratumDecodeCoinbase", .min = 0, .max = 1},
59+
[NVS_CONFIG_STRATUM_DECODE_COINBASE_TX] = {.nvs_key_name = "stratumdecode", .type = TYPE_BOOL, .default_value = {.b = true}, .rest_name = "stratumDecodeCoinbase", .min = 0, .max = 1},
6060
[NVS_CONFIG_FALLBACK_STRATUM_URL] = {.nvs_key_name = "fbstratumurl", .type = TYPE_STR, .default_value = {.str = (char *)CONFIG_FALLBACK_STRATUM_URL}, .rest_name = "fallbackStratumURL", .min = 0, .max = NVS_STR_LIMIT},
6161
[NVS_CONFIG_FALLBACK_STRATUM_PORT] = {.nvs_key_name = "fbstratumport", .type = TYPE_U16, .default_value = {.u16 = CONFIG_FALLBACK_STRATUM_PORT}, .rest_name = "fallbackStratumPort", .min = 0, .max = UINT16_MAX},
6262
[NVS_CONFIG_FALLBACK_STRATUM_USER] = {.nvs_key_name = "fbstratumuser", .type = TYPE_STR, .default_value = {.str = (char *)CONFIG_FALLBACK_STRATUM_USER}, .rest_name = "fallbackStratumUser", .min = 0, .max = NVS_STR_LIMIT},
@@ -65,7 +65,7 @@ static Settings settings[NVS_CONFIG_COUNT] = {
6565
[NVS_CONFIG_FALLBACK_STRATUM_EXTRANONCE_SUBSCRIBE] = {.nvs_key_name = "stratumfbxnsub", .type = TYPE_BOOL, .default_value = {.b = (bool)FALLBACK_STRATUM_EXTRANONCE_SUBSCRIBE}, .rest_name = "fallbackStratumExtranonceSubscribe", .min = 0, .max = 1},
6666
[NVS_CONFIG_FALLBACK_STRATUM_TLS] = {.nvs_key_name = "fbstratumtls", .type = TYPE_U16, .default_value = {.u16 = (uint16_t)CONFIG_FALLBACK_STRATUM_TLS}, .rest_name = "fallbackStratumTLS", .min = 0, .max = 3},
6767
[NVS_CONFIG_FALLBACK_STRATUM_CERT] = {.nvs_key_name = "fbstratumcert", .type = TYPE_STR, .default_value = {.str = (char *)CONFIG_FALLBACK_STRATUM_CERT}, .rest_name = "fallbackStratumCert", .min = 0, .max = NVS_STR_LIMIT},
68-
[NVS_CONFIG_FALLBACK_STRATUM_DECODE_COINBASE] = {.nvs_key_name = "fbstratumdecode", .type = TYPE_BOOL, .default_value = {.b = true}, .rest_name = "fallbackStratumDecodeCoinbase", .min = 0, .max = 1},
68+
[NVS_CONFIG_FALLBACK_STRATUM_DECODE_COINBASE_TX] = {.nvs_key_name = "fbstratumdecode", .type = TYPE_BOOL, .default_value = {.b = true}, .rest_name = "fallbackStratumDecodeCoinbase", .min = 0, .max = 1},
6969
[NVS_CONFIG_USE_FALLBACK_STRATUM] = {.nvs_key_name = "usefbstartum", .type = TYPE_BOOL, .rest_name = "useFallbackStratum", .min = 0, .max = 1},
7070

7171
[NVS_CONFIG_ASIC_FREQUENCY] = {.nvs_key_name = "asicfrequency_f", .type = TYPE_FLOAT, .default_value = {.f = CONFIG_ASIC_FREQUENCY}, .rest_name = "frequency", .min = 1, .max = UINT16_MAX},

main/nvs_config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ typedef enum {
1818
NVS_CONFIG_STRATUM_EXTRANONCE_SUBSCRIBE,
1919
NVS_CONFIG_STRATUM_TLS,
2020
NVS_CONFIG_STRATUM_CERT,
21-
NVS_CONFIG_STRATUM_DECODE_COINBASE,
21+
NVS_CONFIG_STRATUM_DECODE_COINBASE_TX,
2222
NVS_CONFIG_FALLBACK_STRATUM_URL,
2323
NVS_CONFIG_FALLBACK_STRATUM_PORT,
2424
NVS_CONFIG_FALLBACK_STRATUM_USER,
@@ -27,7 +27,7 @@ typedef enum {
2727
NVS_CONFIG_FALLBACK_STRATUM_EXTRANONCE_SUBSCRIBE,
2828
NVS_CONFIG_FALLBACK_STRATUM_TLS,
2929
NVS_CONFIG_FALLBACK_STRATUM_CERT,
30-
NVS_CONFIG_FALLBACK_STRATUM_DECODE_COINBASE,
30+
NVS_CONFIG_FALLBACK_STRATUM_DECODE_COINBASE_TX,
3131
NVS_CONFIG_USE_FALLBACK_STRATUM,
3232

3333
NVS_CONFIG_ASIC_FREQUENCY,

0 commit comments

Comments
 (0)