Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions main/global_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef struct PoolConfig
bool decode_coinbase_tx;
uint16_t sv2_channel_type;
char * sv2_authority_pubkey;
bool sv2_require_auth;
} PoolConfig;

#define HISTORY_LENGTH 100
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,20 @@ <h2 class="mb-3 text-main">Pool Configurations <span class="text-sm text-seconda
</small>
</div>
</div>

<!-- SV2 Require Authentication -->
<div class="flex flex-col md:flex-row md:items-center gap-2">
<label [htmlFor]="'stratumV2RequireAuth_' + poolControl.get('id')?.value" class="w-full md:w-2/12 font-medium cursor-pointer select-none">
<tooltip-text-icon
text="Require Authentication"
tooltip="Refuse to connect unless the server certificate is verified against the Authority Pubkey above. Protects against the man-in-the-middle redirect described for the Authority Pubkey. When enabled without a key set, the miner will not connect."
/>
</label>
<div class="w-full md:w-10/12 flex items-center">
<app-checkbox [name]="'stratumV2RequireAuth_' + poolControl.get('id')?.value" [inputId]="'stratumV2RequireAuth_' + poolControl.get('id')?.value" formControlName="stratumV2RequireAuth"
[binary]="true"></app-checkbox>
</div>
</div>
</ng-container>

<!-- Advanced Options Border/Legend -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ export class PoolComponent implements OnInit {
stratumCert: '',
stratumDecodeCoinbase: true,
stratumV2ChannelType: 'extended',
stratumV2AuthorityPubkey: ''
stratumV2AuthorityPubkey: '',
stratumV2RequireAuth: false
});
}

Expand All @@ -117,7 +118,8 @@ export class PoolComponent implements OnInit {
stratumCert: '',
stratumDecodeCoinbase: true,
stratumV2ChannelType: 'extended',
stratumV2AuthorityPubkey: ''
stratumV2AuthorityPubkey: '',
stratumV2RequireAuth: false
});
}

Expand Down Expand Up @@ -149,7 +151,8 @@ export class PoolComponent implements OnInit {
stratumCert: [pool.stratumCert || ''],
stratumDecodeCoinbase: [pool.stratumDecodeCoinbase == true, [Validators.required]],
stratumV2ChannelType: [pool.stratumV2ChannelType || 'extended'],
stratumV2AuthorityPubkey: [pool.stratumV2AuthorityPubkey || '', [this.base58Validator()]]
stratumV2AuthorityPubkey: [pool.stratumV2AuthorityPubkey || '', [this.base58Validator()]],
stratumV2RequireAuth: [pool.stratumV2RequireAuth == true]
});
});

Expand Down Expand Up @@ -273,7 +276,8 @@ export class PoolComponent implements OnInit {
stratumCert: [''],
stratumDecodeCoinbase: [true, [Validators.required]],
stratumV2ChannelType: ['extended'],
stratumV2AuthorityPubkey: ['', [this.base58Validator()]]
stratumV2AuthorityPubkey: ['', [this.base58Validator()]],
stratumV2RequireAuth: [false]
});

this.poolsArray.push(poolGroup);
Expand Down
6 changes: 4 additions & 2 deletions main/http_server/axe-os/src/app/services/system.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ export class SystemApiService {
stratumCert: "",
stratumDecodeCoinbase: true,
stratumV2ChannelType: "extended" as const,
stratumV2AuthorityPubkey: ""
stratumV2AuthorityPubkey: "",
stratumV2RequireAuth: false
},
{
id: 1,
Expand All @@ -127,7 +128,8 @@ export class SystemApiService {
stratumCert: "",
stratumDecodeCoinbase: true,
stratumV2ChannelType: "extended" as const,
stratumV2AuthorityPubkey: ""
stratumV2AuthorityPubkey: "",
stratumV2RequireAuth: false
}
],
stratumProtocol: "SV1" as const,
Expand Down
2 changes: 2 additions & 0 deletions main/http_server/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ static bool validate_pool_json(const cJSON *pool_item, int i) {
}

if (!validate_string_field(cJSON_GetObjectItem(pool_item, "stratumV2AuthorityPubkey"), "stratumV2AuthorityPubkey", 128, i)) return false;
if (!validate_bool_or_num(cJSON_GetObjectItem(pool_item, "stratumV2RequireAuth"), "stratumV2RequireAuth", i)) return false;

return true;
}
Expand Down Expand Up @@ -813,6 +814,7 @@ static void update_pool_nvs(const cJSON *pool_item, int i) {
add_bool_field_default(p_obj, pool_item, "stratumDecodeCoinbase", true);
add_string_field_default(p_obj, pool_item, "stratumV2ChannelType", SV2_CHANNEL_TYPE_EXTENDED);
add_string_field_default(p_obj, pool_item, "stratumV2AuthorityPubkey", "");
add_bool_field_default(p_obj, pool_item, "stratumV2RequireAuth", false);

char *json_str = cJSON_PrintUnformatted(p_obj);
if (json_str) {
Expand Down
3 changes: 3 additions & 0 deletions main/http_server/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ components:
type: string
description: SV2 authority public key for certificate verification (base58-encoded)
pattern: "^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]*$"
stratumV2RequireAuth:
type: boolean
description: Refuse to connect unless the SV2 server certificate is verified against the authority pubkey
id:
type: integer
description: Pool NVS slot index (0 to 7)
Expand Down
3 changes: 2 additions & 1 deletion main/http_server/system_api_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ static void system_api_add_config(cJSON *root, GlobalState *g) {
cJSON_AddBoolToObject(p_obj, "stratumDecodeCoinbase", p->decode_coinbase_tx);
cJSON_AddStringToObject(p_obj, "stratumV2ChannelType", p->sv2_channel_type == SV2_CHANNEL_STANDARD ? SV2_CHANNEL_TYPE_STANDARD : SV2_CHANNEL_TYPE_EXTENDED);
cJSON_AddStringToObject(p_obj, "stratumV2AuthorityPubkey", p->sv2_authority_pubkey ? p->sv2_authority_pubkey : "");

cJSON_AddBoolToObject(p_obj, "stratumV2RequireAuth", p->sv2_require_auth);

cJSON_AddItemToArray(pools_arr, p_obj);
}
}
Expand Down
6 changes: 6 additions & 0 deletions main/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static void parse_pool_config_json(const char *json_str, PoolConfig *cfg, int in
cfg->decode_coinbase_tx = true;
cfg->sv2_channel_type = SV2_CHANNEL_EXTENDED;
cfg->sv2_authority_pubkey = strdup("");
cfg->sv2_require_auth = false;

if (!json_str || strlen(json_str) == 0) {
return;
Expand Down Expand Up @@ -136,6 +137,11 @@ static void parse_pool_config_json(const char *json_str, PoolConfig *cfg, int in
cfg->sv2_authority_pubkey = strdup(item->valuestring);
}

item = cJSON_GetObjectItem(root, "stratumV2RequireAuth");
if (item && (cJSON_IsBool(item) || cJSON_IsNumber(item))) {
cfg->sv2_require_auth = cJSON_IsTrue(item) || (cJSON_IsNumber(item) && item->valueint != 0);
}

cJSON_Delete(root);
}

Expand Down
17 changes: 16 additions & 1 deletion main/tasks/stratum_v2_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,9 +714,24 @@ void stratum_v2_task(void *pvParameters)
}
GLOBAL_STATE->sv2_noise_ctx = noise_ctx;

// Load optional authority pubkey from NVS
// Load the optional authority pubkey and whether this pool requires it
uint8_t auth_key[32];
bool has_auth = stratum_v2_load_authority_pubkey(GLOBAL_STATE, auth_key, use_fallback);
uint16_t auth_pool_idx = use_fallback ? GLOBAL_STATE->SYSTEM_MODULE.secondary_pool_index
: GLOBAL_STATE->SYSTEM_MODULE.primary_pool_index;
bool require_auth = GLOBAL_STATE->SYSTEM_MODULE.pools[auth_pool_idx].sv2_require_auth;

// When auth is required but no usable authority key is configured,
// refuse to connect rather than mine against an unverifiable server
if (require_auth && !has_auth) {
ESP_LOGE(TAG, "SV2 authentication required but no authority pubkey configured, refusing to connect");
snprintf(GLOBAL_STATE->SYSTEM_MODULE.pool_connection_info,
sizeof(GLOBAL_STATE->SYSTEM_MODULE.pool_connection_info), "SV2: Auth required - no key");
stratum_v2_close_connection(GLOBAL_STATE);
retry_attempts++;
continue;
}

if (has_auth) {
ESP_LOGI(TAG, "Authority pubkey configured, will verify server certificate");
} else {
Expand Down
Loading