-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from qubic-li/master
Init 1.9.0 Client
- Loading branch information
Showing
83 changed files
with
417 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"package":"qubminer-1.9.0", | ||
"name": "qubminer", | ||
"version": "1.9.0", | ||
"description": "Qubminer 1.9.0", | ||
"maintainer":"Worm ([email protected])", | ||
"platforms": ["nvidia"], | ||
"dual_coin": false, | ||
"algo": ["qubic"], | ||
"executable": ["qli-Client"], | ||
"rev": 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import json | ||
import os | ||
import re | ||
import ravinos | ||
import io | ||
|
||
|
||
def process_user_config(custom_user_config, settings): | ||
# Remove unnecessary spaces around colon and double quotes | ||
custom_user_config = custom_user_config.replace(' :', ':') | ||
custom_user_config = custom_user_config.replace(': ', ':') | ||
custom_user_config = custom_user_config.replace('"', '') | ||
|
||
# Iterate through each line in the custom user config | ||
for line in custom_user_config.split(' '): | ||
line = line.strip() | ||
if not line: | ||
continue | ||
else: | ||
# Split parameter and value using regex | ||
param, value = re.split(r':\s*', line, 1) | ||
param_high = param.upper() | ||
modified_param = param_high | ||
modified_param = modified_param.replace('PAYOUTID', 'payoutId') | ||
modified_param = modified_param.replace('AMOUNTOFTHREADS', 'amountOfThreads') | ||
modified_param = modified_param.replace('ACCESSTOKEN', 'accessToken') | ||
modified_param = modified_param.replace('ALLOWHWINFOCOLLECT', 'allowHwInfoCollect') | ||
modified_param = modified_param.replace('HUGEPAGES', 'hugePages') | ||
modified_param = modified_param.replace('CPUONLY', 'cpuOnly') | ||
modified_param = modified_param.replace('ALIAS', 'alias') | ||
modified_param = modified_param.replace('OVERWRITES', 'overwrites') | ||
if param != modified_param: | ||
param = modified_param | ||
if value: | ||
if param == 'overwrites': | ||
value = value.replace("{", "").replace("}", "") | ||
pairs = value.split(',') | ||
|
||
if 'overwrites' in settings: | ||
overwrites_data = settings['overwrites'] | ||
else: | ||
overwrites_data = {} | ||
|
||
for pair in pairs: | ||
param_2, value_2 = pair.split(':') | ||
if value_2 == 'false': | ||
overwrites_data[param_2] = False | ||
else: | ||
overwrites_data[param_2] = value_2 | ||
|
||
settings['overwrites'] = overwrites_data | ||
else: | ||
if value == 'null': | ||
settings[param] = None | ||
elif re.match(r'^[0-9]+(\.[0-9]+)?$', value): | ||
settings[param] = int(value) | ||
else: | ||
settings[param] = value | ||
return settings | ||
|
||
|
||
def run_program(mode, miner_dir, log_file, hugePages): | ||
run_command = "{}/qubminer.sh {} {} {} {}".format(miner_dir, miner_dir, log_file, mode, hugePages) | ||
ravinos.run(run_command) | ||
|
||
|
||
def check_and_run(miner_dir, log_file, hugePages): | ||
# Check if CPU and GPU config files exist | ||
cpu_exists = os.path.exists("{}/cpu/appsettings.json".format(miner_dir)) | ||
gpu_exists = os.path.exists("{}/gpu/appsettings.json".format(miner_dir)) | ||
|
||
# Run program based on the existence of CPU and GPU config files | ||
if cpu_exists and gpu_exists: | ||
run_program(3, miner_dir, log_file, hugePages) # Both CPU and GPU | ||
elif cpu_exists: | ||
run_program(2, miner_dir, log_file, hugePages) # Only CPU | ||
elif gpu_exists: | ||
run_program(1, miner_dir, log_file, hugePages) # Only GPU | ||
else: | ||
# Exit if no CPU and GPU config files are found | ||
print("ERROR: No CPU and GPU config file found, exiting") | ||
exit(1) | ||
|
||
|
||
# Main script logic | ||
cfg = ravinos.get_config() | ||
miner_dir = cfg['miner_dir'] | ||
log_file = cfg['log_file'] | ||
|
||
# Read global settings | ||
with io.open("{}/appsettings_global.json".format(miner_dir), 'r', encoding='utf-8-sig') as f: | ||
global_settings = json.load(f)['Settings'] | ||
|
||
# Copy qli-Client to CPU and GPU directories | ||
os.system("cp {}/qli-Client {}/cpu/qli-Client".format(miner_dir, miner_dir)) | ||
os.system("cp {}/qli-Client {}/gpu/qli-Client".format(miner_dir, miner_dir)) | ||
|
||
# Copy lscpu tool to CPU and GPU directories | ||
os.system("cp {}/syslib/lscpu {}/cpu/lscpu".format(miner_dir, miner_dir)) | ||
os.system("cp {}/syslib/lscpu {}/gpu/lscpu".format(miner_dir, miner_dir)) | ||
|
||
# Delete old settings files for CPU and GPU | ||
os.system("rm -rf {}/cpu/appsettings.json".format(miner_dir)) | ||
os.system("rm -rf {}/gpu/appsettings.json".format(miner_dir)) | ||
|
||
# Processing the alias | ||
if cfg['auth_config']['worker']: | ||
global_settings.update({"alias": cfg['auth_config']['worker']}) | ||
|
||
# Processing user configuration | ||
if cfg['args']: | ||
args_string = " ".join(cfg['args']) | ||
global_settings = process_user_config(args_string, global_settings) | ||
|
||
# Adding URL settings | ||
url = cfg['coins'][0]['pools'][0]['url'] | ||
match = re.match(r"(https?://[^?]+)", url) | ||
if match: | ||
global_settings.update({"baseUrl": match.group(1)}) | ||
|
||
# Settings for hugePages parameter | ||
hugePages = global_settings.get('hugePages') | ||
|
||
# Additional check in the Settings for only CPU mining | ||
if global_settings.get('cpuOnly') != 'yes': | ||
settings_gpu = global_settings.copy() | ||
settings_gpu['alias'] += '-gpu' | ||
settings_gpu['amountOfThreads'] = 0 | ||
settings_gpu.pop('hugePages', None) | ||
with open("{}/gpu/appsettings.json".format(miner_dir), 'w') as f: | ||
json.dump({'Settings': settings_gpu}, f) | ||
|
||
# Additional check and modification in the Settings for CPU mining | ||
if global_settings.get('cpuOnly') == 'yes' or global_settings.get('amountOfThreads') != 0: | ||
settings_cpu = global_settings.copy() | ||
settings_cpu['alias'] += '-cpu' | ||
settings_cpu['allowHwInfoCollect'] = False | ||
settings_cpu.pop('cpuOnly', None) | ||
settings_cpu.pop('hugePages', None) | ||
if 'overwrites' in settings_cpu: | ||
overwrites = settings_cpu['overwrites'] | ||
if 'CUDA' in overwrites: | ||
overwrites.pop('CUDA', None) | ||
with open("{}/cpu/appsettings.json".format(miner_dir), 'w') as f: | ||
json.dump({'Settings': settings_cpu}, f) | ||
|
||
# Copy necessary libs | ||
os.system("cp {}/syslib/*.* /usr/lib/".format(miner_dir)) | ||
os.system("cp {}/syslib/bash /bin/".format(miner_dir)) | ||
|
||
# Update LD_LIBRARY_PATH | ||
os.environ['LD_LIBRARY_PATH'] = '{}:{}'.format(os.getcwd(), os.environ.get('LD_LIBRARY_PATH', '')) | ||
|
||
# Check and run the miner | ||
check_and_run(miner_dir, log_file, hugePages) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
import re | ||
import os | ||
import time | ||
import ravinos as ro | ||
|
||
cfg = ro.get_config() | ||
log_file_path = cfg['log_file'] | ||
|
||
threshold = 3 * 60 | ||
|
||
hash_rate_regex = r'GPU #(\d+): (\d+) it/s' | ||
cpu_hash_rate_regex = r'\| (\d+) it/s \|' | ||
solution_regex = r'SOL: (\d+)/(\d+)' | ||
|
||
# Delete statistic file if time from las change > threshold | ||
if os.path.exists(log_file_path): | ||
last_modified = os.path.getmtime(log_file_path) | ||
current_time = time.time() | ||
|
||
if current_time - last_modified > threshold: | ||
open(log_file_path, 'w').close() | ||
|
||
# If file big - flush | ||
file_size = os.path.getsize(log_file_path) | ||
if file_size > 100 * 1024: | ||
with open(log_file_path, 'r') as log_file_read: | ||
lines = log_file_read.readlines()[-200:] | ||
with open(log_file_path, 'w') as log_file_write: | ||
log_file_write.writelines(lines) | ||
|
||
stats = ro.get_stats() | ||
|
||
top = {} | ||
total_accepted_gpu = 0 | ||
total_rejected_gpu = 0 | ||
total_accepted_cpu = 0 | ||
total_rejected_cpu = 0 | ||
cpu_hash_rate = 0 | ||
|
||
try: | ||
with open(log_file_path, 'r') as log_file: | ||
lines = log_file.readlines()[-150:] | ||
|
||
client_type = 'gpu' | ||
|
||
for line in lines: | ||
|
||
if 'xGPU' in line: | ||
client_type = 'gpu' | ||
elif 'xCPU' in line: | ||
client_type = 'cpu' | ||
|
||
if 'Trainer:' in line and client_type == 'gpu': | ||
matches = re.findall(hash_rate_regex, line) | ||
for match in matches: | ||
gpu_id, hash_rate = int(match[0]), int(match[1]) | ||
if gpu_id not in top or top[gpu_id] < hash_rate: | ||
top[gpu_id] = hash_rate | ||
|
||
elif client_type == 'cpu': | ||
cpu_match = re.search(cpu_hash_rate_regex, line) | ||
if cpu_match: | ||
cpu_hash_rate = int(cpu_match.group(1)) | ||
|
||
sol_match = re.search(solution_regex, line) | ||
if sol_match: | ||
accepted, rejected = map(int, sol_match.groups()) | ||
if client_type == 'gpu': | ||
total_accepted_gpu = accepted | ||
total_rejected_gpu = rejected | ||
elif client_type == 'cpu': | ||
total_accepted_cpu = accepted | ||
total_rejected_cpu = rejected | ||
|
||
for gpu in stats['mpu']: | ||
if gpu['id'] in top: | ||
gpu['hash_rate1'] = top[gpu['id']] | ||
if gpu['id'] == 0: | ||
gpu['hash_rate2'] = cpu_hash_rate | ||
|
||
stats['shares']['accepted'] = total_accepted_gpu + total_accepted_cpu | ||
stats['shares']['rejected'] = (total_accepted_gpu + total_accepted_cpu) - (total_rejected_gpu + total_rejected_cpu) | ||
stats['shares']['invalid'] = (total_accepted_gpu + total_accepted_cpu) - (total_rejected_gpu + total_rejected_cpu) | ||
|
||
except IOError as e: | ||
print("Error while extracting stats: {}".format(str(e))) | ||
|
||
ro.set_stats(stats) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,87 @@ | ||
# raveos | ||
# Qubic RaveOs Miner | ||
This is the integration of the main client from qubic.li to RaveOs. | ||
|
||
Qubminer are now successfully integrated into RaveOS. | ||
|
||
***No fees. Absolutely - FREE.*** | ||
|
||
![Qubminer](/img/Header.png) | ||
|
||
## Qubic Resources | ||
|
||
- [Qubic Website](https://web.qubic.li/) | ||
- [Qubic Web Wallet](https://wallet.qubic.li/) | ||
- [Qubic Mining Pool](https://app.qubic.li/public/) | ||
- [Official Qubic Client](https://github.com/qubic-li/client?tab=readme-ov-file#download) | ||
|
||
## :warning: HiveOs Mandatory Installation Instructions | ||
- The CPU where you run the Client must support AVX2 or AVX512 CPU instructions | ||
`cat /proc/cpuinfo | grep avx2`(check if `avx2` is in the result) | ||
- Cuda 12+ drivers (535+) | ||
`upgrade 8926-2226` (or newer) | ||
- RAM >= 16Go improves CPU it/s | ||
- Higher RAM frequencies improves CPU it/s | ||
- Do not overload your CPUs with threads, instead, aim to find the sweetpoint | ||
|
||
*Only NVIDIA GPU compatible* | ||
<br> | ||
|
||
## Configuration | ||
The startup script takes values from the flight sheet to complete the default configuration (`appsettings_global.json`). | ||
|
||
There are a lot of necessary libraries for work into syslib folder | ||
|
||
Each time the miner starts, the `appsettings.json` file is recreated | ||
|
||
### The main settings: | ||
![Flight Sheet](/img/FlightSheet.png) | ||
|
||
### GPU+CPU (Dual) mining: | ||
![Flight Sheet Dual](/img/FlightSheetDual.png) | ||
<br> | ||
Extra config arguments exemple: | ||
``` | ||
"accessToken":"YOUROWNTOKEN" | ||
"amountOfThreads":4 | ||
``` | ||
|
||
### GPU mining: | ||
![Flight Sheet GPU](/img/FlightSheetGPU.png) | ||
<br> | ||
Extra config arguments exemple: | ||
``` | ||
"accessToken":"YOUROWNTOKEN" | ||
``` | ||
|
||
### CPU mining: | ||
![Flight Sheet CPU](/img/FlightSheetCPU.png) | ||
<br> | ||
Extra config arguments exemple: | ||
``` | ||
"cpuOnly":"yes" | ||
"amountOfThreads":24 | ||
"accessToken":"YOUROWNTOKEN" | ||
``` | ||
|
||
### Recommended RaveOS GPU overclocks : | ||
|
||
Please use "Tunning Settings" from workers's dashboard to set global or specific OC: | ||
|
||
**Medium** | ||
3000 series ```nvidia-smi -lmc 7000 && nvidia-smi -lgc 1500``` | ||
4000 series ```nvidia-smi -lmc 7000 && nvidia-smi -lgc 2400``` | ||
**High** | ||
3000 series ```nvidia-smi -lmc 7000 && nvidia-smi -lgc 1700``` | ||
4000 series ```nvidia-smi -lmc 7000 && nvidia-smi -lgc 2900``` | ||
|
||
|
||
### Extra config arguments Box (options): | ||
|
||
| Setting | Description | | ||
| ---- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| ```"accessToken":``` | This is you personal JWT Token which you can obtain from the Control Panel at qubic.li | | ||
| ```"payoutId":``` | This is the ID you want to get token payout for your found solutions. | | ||
| ```"hugePages":nnnn``` | Depending on your environment you might want to enable huge pages. This can increase your iterations per second. The trainer will tell you what is the optimal setting when it detects a wrong value. The number depends on the number of threads: nb_threads * 52 (e.g., 16 * 52 = 832). If trainer is unstable please remove. | | ||
| ```"overwrites": {"AVX512": false}``` | Disable AVX512 and enforce AVX2 (AVX Intel CPU not working) | | ||
| ```"overwrites": {"SKYLAKE": true}``` | Enforce SKYLAKE (AVX Intel CPU not working) | | ||
<br> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"Settings": { | ||
"baseUrl": "https://mine.qubic.li/", | ||
"amountOfThreads": 0, | ||
"payoutId": null, | ||
"accessToken": null, | ||
"alias": "qubic.li Client", | ||
"allowHwInfoCollect": true, | ||
"overwrites": {"CUDA": "12"} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Oops, something went wrong.