Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Init 1.9.0 Client #1

Merged
merged 1 commit into from
Apr 4, 2024
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
Init 1.9.0 Client
  • Loading branch information
Worm committed Apr 4, 2024
commit bb6e64e113bfaf1e2204b8e75b2dd986ff556cce
12 changes: 12 additions & 0 deletions RAVINOS/manifest.json
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
}
155 changes: 155 additions & 0 deletions RAVINOS/start.py
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)
91 changes: 91 additions & 0 deletions RAVINOS/stats.py
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)
88 changes: 87 additions & 1 deletion README.md
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>
11 changes: 11 additions & 0 deletions appsettings_global.json
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"}
}
}
Binary file added img/FlightSheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/FlightSheetCPU.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/FlightSheetDual.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/FlightSheetGPU.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/Header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added qli-Client
Binary file not shown.
Loading