* Removed hard coded data dir in daemon launch
* Documented subprocess pow better * Calculate block size better for pow + Added monero donation addressmaster
parent
3322778ff4
commit
7e058b29e0
|
@ -69,12 +69,14 @@ More docs coming soon.
|
||||||
|
|
||||||
The following applies to Ubuntu Bionic. Other distros may have different package or command names.
|
The following applies to Ubuntu Bionic. Other distros may have different package or command names.
|
||||||
|
|
||||||
|
`$ sudo apt install python3-pip python3-dev tor`
|
||||||
|
|
||||||
* Have python3.6+, python3-pip, Tor (daemon, not browser) installed (python3-dev recommended)
|
* Have python3.6+, python3-pip, Tor (daemon, not browser) installed (python3-dev recommended)
|
||||||
* Clone the git repo: `$ git clone https://gitlab.com/beardog/onionr`
|
* Clone the git repo: `$ git clone https://gitlab.com/beardog/onionr`
|
||||||
* cd into install direction: `$ cd onionr/`
|
* cd into install direction: `$ cd onionr/`
|
||||||
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements.txt`
|
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements.txt`
|
||||||
|
|
||||||
(--require-hashes is intended to prevent exploitation via compromise of Pypi/CA certificates)
|
(--require-hashes is intended to prevent exploitation via compromise of PyPi/CA certificates)
|
||||||
|
|
||||||
## Help out
|
## Help out
|
||||||
|
|
||||||
|
@ -95,7 +97,9 @@ Contribute money:
|
||||||
|
|
||||||
Donating at least $5 gets you cool Onionr stickers. Get in touch if you want them.
|
Donating at least $5 gets you cool Onionr stickers. Get in touch if you want them.
|
||||||
|
|
||||||
Bitcoin: [1onion55FXzm6h8KQw3zFw2igpHcV7LPq](bitcoin:1onion55FXzm6h8KQw3zFw2igpHcV7LPq) (Contact us for privacy coins like Monero)
|
Bitcoin: [1onion55FXzm6h8KQw3zFw2igpHcV7LPq](bitcoin:1onion55FXzm6h8KQw3zFw2igpHcV7LPq) (Contact us for a unique address or for other coins)
|
||||||
|
|
||||||
|
Monero: 4B5BA24d1P3R5aWEpkGY5TP7buJJcn2aSGBVRQCHhpiahxeB4aWsu15XwmuTjC6VF62NApZeJGTS248RMVECP8aW73Uj2ax
|
||||||
|
|
||||||
USD (Card/Paypal): [Ko-Fi](https://www.ko-fi.com/beardogkf)
|
USD (Card/Paypal): [Ko-Fi](https://www.ko-fi.com/beardogkf)
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ def daemon(o_inst):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# remove runcheck if it exists
|
# remove runcheck if it exists
|
||||||
if os.path.isfile('data/.runcheck'):
|
if os.path.isfile('%s/.runcheck' % (o_inst.onionrCore.dataDir,)):
|
||||||
logger.debug('Runcheck file found on daemon start, deleting in advance.')
|
logger.debug('Runcheck file found on daemon start, deleting in advance.')
|
||||||
os.remove('data/.runcheck')
|
os.remove('%s/.runcheck' % (o_inst.onionrCore.dataDir,))
|
||||||
|
|
||||||
Thread(target=api.API, args=(o_inst, o_inst.debug, onionr.API_VERSION)).start()
|
Thread(target=api.API, args=(o_inst, o_inst.debug, onionr.API_VERSION)).start()
|
||||||
Thread(target=api.PublicAPI, args=[o_inst.getClientApi()]).start()
|
Thread(target=api.PublicAPI, args=[o_inst.getClientApi()]).start()
|
||||||
|
|
|
@ -53,14 +53,9 @@ def getDifficultyForNewBlock(data, ourBlock=True):
|
||||||
dataSize = 0
|
dataSize = 0
|
||||||
if isinstance(data, onionrblockapi.Block):
|
if isinstance(data, onionrblockapi.Block):
|
||||||
dataSize = len(data.getRaw().encode('utf-8'))
|
dataSize = len(data.getRaw().encode('utf-8'))
|
||||||
elif isinstance(data, str):
|
|
||||||
dataSize = len(data.encode('utf-8'))
|
|
||||||
elif isinstance(data, bytes):
|
|
||||||
dataSize = len(data)
|
|
||||||
elif isinstance(data, int):
|
|
||||||
dataSize = data
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('not Block, str, or int')
|
dataSize = len(onionrutils.OnionrUtils.strToBytes(data))
|
||||||
|
|
||||||
if ourBlock:
|
if ourBlock:
|
||||||
minDifficulty = config.get('general.minimum_send_pow', 4)
|
minDifficulty = config.get('general.minimum_send_pow', 4)
|
||||||
else:
|
else:
|
||||||
|
@ -131,8 +126,6 @@ class DataPOW:
|
||||||
for i in range(max(1, threadCount)):
|
for i in range(max(1, threadCount)):
|
||||||
t = threading.Thread(name = 'thread%s' % i, target = self.pow, args = (True,myCore))
|
t = threading.Thread(name = 'thread%s' % i, target = self.pow, args = (True,myCore))
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def pow(self, reporting = False, myCore = None):
|
def pow(self, reporting = False, myCore = None):
|
||||||
startTime = math.floor(time.time())
|
startTime = math.floor(time.time())
|
||||||
|
|
|
@ -1,34 +1,39 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import subprocess, sys, os
|
import subprocess, os
|
||||||
import multiprocessing, threading, time, json, math, binascii
|
import multiprocessing, threading, time, json, math
|
||||||
from multiprocessing import Pipe, Process
|
from multiprocessing import Pipe, Process
|
||||||
import core, onionrblockapi, config, onionrutils, logger, onionrproofs
|
import core, onionrblockapi, config, onionrutils, logger, onionrproofs
|
||||||
|
|
||||||
class SubprocessPOW:
|
class SubprocessPOW:
|
||||||
def __init__(self, data, metadata, core_inst=None, subprocCount=None):
|
def __init__(self, data, metadata, core_inst=None, subproc_count=None):
|
||||||
|
'''
|
||||||
|
Onionr proof of work using multiple processes
|
||||||
|
Accepts block data, block metadata
|
||||||
|
and optionally an onionr core library instance.
|
||||||
|
if subproc_count is not set, os.cpu_count() is used to determine the number of processes
|
||||||
|
|
||||||
|
Do to Python GIL multiprocessing or use of external libraries is necessary to accelerate CPU bound tasks
|
||||||
|
'''
|
||||||
|
# Option to accept existing core instance to save memory
|
||||||
if core_inst is None:
|
if core_inst is None:
|
||||||
core_inst = core.Core()
|
core_inst = core.Core()
|
||||||
if subprocCount is None:
|
# No known benefit to using more processes than there are cores.
|
||||||
subprocCount = os.cpu_count()
|
# Note: os.cpu_count perhaps not always accurate
|
||||||
self.subprocCount = subprocCount
|
if subproc_count is None:
|
||||||
|
subproc_count = os.cpu_count()
|
||||||
|
self.subproc_count = subproc_count
|
||||||
self.result = ''
|
self.result = ''
|
||||||
self.shutdown = False
|
self.shutdown = False
|
||||||
self.core_inst = core_inst
|
self.core_inst = core_inst
|
||||||
self.data = data
|
self.data = data
|
||||||
self.metadata = metadata
|
self.metadata = metadata
|
||||||
|
|
||||||
dataLen = len(data) + len(json.dumps(metadata))
|
# dump dict to measure bytes of json metadata. Cannot reuse later because the pow token must be added
|
||||||
|
json_metadata = json.dumps(metadata).encode()
|
||||||
|
|
||||||
#if forceDifficulty > 0:
|
self.data = onionrutils.OnionrUtils.strToBytes(data)
|
||||||
# self.difficulty = forceDifficulty
|
# Calculate difficulty. Dumb for now, may use good algorithm in the future.
|
||||||
#else:
|
self.difficulty = onionrproofs.getDifficultyForNewBlock(bytes(json_metadata + b'\n' + self.data))
|
||||||
# Calculate difficulty. Dumb for now, may use good algorithm in the future.
|
|
||||||
self.difficulty = onionrproofs.getDifficultyForNewBlock(dataLen)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.data = self.data.encode()
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
logger.info('Computing POW (difficulty: %s)...' % self.difficulty)
|
logger.info('Computing POW (difficulty: %s)...' % self.difficulty)
|
||||||
|
|
||||||
|
@ -38,9 +43,10 @@ class SubprocessPOW:
|
||||||
self.payload = None
|
self.payload = None
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
startTime = self.core_inst._utils.getEpoch()
|
# Create a new thread for each subprocess
|
||||||
for x in range(self.subprocCount):
|
for x in range(self.subproc_count):
|
||||||
threading.Thread(target=self._spawn_proc).start()
|
threading.Thread(target=self._spawn_proc).start()
|
||||||
|
# Monitor the processes for a payload, shut them down when its found
|
||||||
while True:
|
while True:
|
||||||
if self.payload is None:
|
if self.payload is None:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
@ -49,6 +55,7 @@ class SubprocessPOW:
|
||||||
return self.payload
|
return self.payload
|
||||||
|
|
||||||
def _spawn_proc(self):
|
def _spawn_proc(self):
|
||||||
|
# Create a child proof of work process, wait for data and send shutdown signal when its found
|
||||||
parent_conn, child_conn = Pipe()
|
parent_conn, child_conn = Pipe()
|
||||||
p = Process(target=self.do_pow, args=(child_conn,))
|
p = Process(target=self.do_pow, args=(child_conn,))
|
||||||
p.start()
|
p.start()
|
||||||
|
@ -67,24 +74,24 @@ class SubprocessPOW:
|
||||||
self.payload = payload
|
self.payload = payload
|
||||||
|
|
||||||
def do_pow(self, pipe):
|
def do_pow(self, pipe):
|
||||||
nonce = int(binascii.hexlify(os.urandom(2)), 16)
|
nonce = -10000000 # Start nonce at negative 10 million so that the chosen nonce is likely to be small in length
|
||||||
nonceStart = nonce
|
nonceStart = nonce
|
||||||
data = self.data
|
data = self.data
|
||||||
metadata = self.metadata
|
metadata = self.metadata
|
||||||
puzzle = self.puzzle
|
puzzle = self.puzzle
|
||||||
difficulty = self.difficulty
|
difficulty = self.difficulty
|
||||||
mcore = core.Core()
|
mcore = core.Core() # I think we make a new core here because of multiprocess bugs
|
||||||
while True:
|
while True:
|
||||||
metadata['pow'] = nonce
|
# Break if shutdown received
|
||||||
payload = json.dumps(metadata).encode() + b'\n' + data
|
|
||||||
token = mcore._crypto.sha3Hash(payload)
|
|
||||||
try:
|
|
||||||
# on some versions, token is bytes
|
|
||||||
token = token.decode()
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
if pipe.poll() and pipe.recv() == 'shutdown':
|
if pipe.poll() and pipe.recv() == 'shutdown':
|
||||||
break
|
break
|
||||||
|
# Load nonce into block metadata
|
||||||
|
metadata['pow'] = nonce
|
||||||
|
# Serialize metadata, combine with block data
|
||||||
|
payload = json.dumps(metadata).encode() + b'\n' + data
|
||||||
|
# Check sha3_256 hash of block, compare to puzzle. Send payload if puzzle finished
|
||||||
|
token = mcore._crypto.sha3Hash(payload)
|
||||||
|
token = onionrutils.OnionrUtils.bytesToStr(token) # ensure token is string
|
||||||
if puzzle == token[0:difficulty]:
|
if puzzle == token[0:difficulty]:
|
||||||
pipe.send(payload)
|
pipe.send(payload)
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in New Issue