Add createChain and mergeChain

This commit is contained in:
Arinerron 2018-06-04 19:26:04 -07:00
parent 6ff3c2c519
commit 9c2acb7099
3 changed files with 113 additions and 78 deletions

View File

@ -467,7 +467,12 @@ class Onionr:
os.makedirs(plugins.get_plugins_folder(plugin_name)) os.makedirs(plugins.get_plugins_folder(plugin_name))
with open(plugins.get_plugins_folder(plugin_name) + '/main.py', 'a') as main: with open(plugins.get_plugins_folder(plugin_name) + '/main.py', 'a') as main:
main.write(open('static-data/default_plugin.py').read().replace('$user', os.getlogin()).replace('$date', datetime.datetime.now().strftime('%Y-%m-%d')).replace('$name', plugin_name)) contents = ''
with open('static-data/default_plugin.py', 'rb') as file:
contents = file.read()
# TODO: Fix $user. os.getlogin() is B U G G Y
main.write(contents.replace('$user', 'some random developer').replace('$date', datetime.datetime.now().strftime('%Y-%m-%d')).replace('$name', plugin_name))
with open(plugins.get_plugins_folder(plugin_name) + '/info.json', 'a') as main: with open(plugins.get_plugins_folder(plugin_name) + '/info.json', 'a') as main:
main.write(json.dumps({'author' : 'anonymous', 'description' : 'the default description of the plugin', 'version' : '1.0'})) main.write(json.dumps({'author' : 'anonymous', 'description' : 'the default description of the plugin', 'version' : '1.0'}))
@ -585,7 +590,7 @@ class Onionr:
'Known Peers Count' : str(len(self.onionrCore.listPeers()) - 1), 'Known Peers Count' : str(len(self.onionrCore.listPeers()) - 1),
'Enabled Plugins Count' : str(len(config.get('plugins')['enabled'])) + ' / ' + str(len(os.listdir('data/plugins/'))), 'Enabled Plugins Count' : str(len(config.get('plugins')['enabled'])) + ' / ' + str(len(os.listdir('data/plugins/'))),
'Known Blocks Count' : str(totalBlocks), 'Known Blocks Count' : str(totalBlocks),
'Percent Blocks Signed' : str(round(100 * signedBlocks / totalBlocks, 2)) + '%' 'Percent Blocks Signed' : str(round(100 * signedBlocks / totalBlocks, 2)) + '%' # TODO: div by zero error
} }
# color configuration # color configuration

View File

@ -19,7 +19,7 @@
''' '''
import core as onionrcore, logger import core as onionrcore, logger
import json, os, datetime import json, os, datetime, base64
class Block: class Block:
def __init__(self, hash = None, core = None): def __init__(self, hash = None, core = None):
@ -469,7 +469,7 @@ class Block:
return list() return list()
def merge(child, file = None, maximumFollows = 32, core = None): def mergeChain(child, file = None, maximumFollows = 32, core = None):
''' '''
Follows a child Block to its root parent Block, merging content Follows a child Block to its root parent Block, merging content
@ -485,6 +485,8 @@ class Block:
maximumFollows = max(0, maximumFollows) maximumFollows = max(0, maximumFollows)
# type conversions # type conversions
if type(child) == list:
child = child[-1]
if type(child) == str: if type(child) == str:
child = Block(child) child = Block(child)
if (not file is None) and (type(file) == str): if (not file is None) and (type(file) == str):
@ -521,21 +523,37 @@ class Block:
for hash in blocks: for hash in blocks:
block = Block(hash, core = core) block = Block(hash, core = core)
contents = block.getContent() contents = block.getContent()
contents = base64.b64decode(contents.encode())
if file is None: if file is None:
buffer += contents buffer += contents.decode()
else: else:
file.write(contents) file.write(contents)
return (None if not file is None else buffer) return (None if not file is None else buffer)
def create(data = None, chunksize = 4999000, file = None, type = 'chunk', sign = True): def createChain(data = None, chunksize = 99800, file = None, type = 'chunk', sign = True, encrypt = False, verbose = False):
''' '''
Creates a chain of blocks to store larger amounts of data Creates a chain of blocks to store larger amounts of data
The chunksize is set to 4999000 because it provides the least amount of PoW for the most amount of data. The chunksize is set to 99800 because it provides the least amount of PoW for the most amount of data.
TODO: Add docs Inputs:
- data (*): if `file` is None, the data to be stored in blocks
- file (file/str): the filename or file object to read from (or None to read `data` instead)
- chunksize (int): the number of bytes per block chunk
- type (str): the type header for each of the blocks
- sign (bool): whether or not to sign each block
- encrypt (str): the public key to encrypt to, or False to disable encryption
- verbose (bool): whether or not to return a tuple containing more info
Outputs:
- if `verbose`:
- (tuple):
- (str): the child block hash
- (list): all block hashes associated with storing the file
- if not `verbose`:
- (str): the child block hash
''' '''
blocks = list() blocks = list()
@ -547,13 +565,26 @@ class Block:
return blocks return blocks
elif isinstance(file, str): elif isinstance(file, str):
file = open(file, 'rb') file = open(file, 'rb')
if isinstance(data, str): if not isinstance(data, str):
data = str(data) data = str(data)
if not file is None: if not file is None:
while True: filesize = os.stat(file.name).st_size
# read chunksize bytes from the file offset = filesize % chunksize
maxtimes = int(filesize / chunksize)
for times in range(0, maxtimes + 1):
# read chunksize bytes from the file (end -> beginning)
if times < maxtimes:
file.seek(- ((times + 1) * chunksize), 2)
content = file.read(chunksize) content = file.read(chunksize)
else:
file.seek(0, 0)
content = file.read(offset)
# encode it- python is really bad at handling certain bytes that
# are often present in binaries.
content = base64.b64encode(content).decode()
# if it is the end of the file, exit # if it is the end of the file, exit
if not content: if not content:
@ -569,7 +600,10 @@ class Block:
# remember the hash in cache # remember the hash in cache
blocks.append(hash) blocks.append(hash)
elif not data is None: elif not data is None:
for content in [data[n:n + chunksize] for n in range(0, len(data), chunksize)]: for content in reversed([data[n:n + chunksize] for n in range(0, len(data), chunksize)]):
# encode chunk with base64
content = base64.b64encode(content.encode()).decode()
# create block # create block
block = Block() block = Block()
block.setType(type) block.setType(type)
@ -580,7 +614,10 @@ class Block:
# remember the hash in cache # remember the hash in cache
blocks.append(hash) blocks.append(hash)
return blocks # return different things depending on verbosity
if verbose:
return (blocks[-1], blocks)
return blocks[-1]
def exists(hash): def exists(hash):
''' '''

View File

@ -138,24 +138,17 @@ class OnionrTests(unittest.TestCase):
logger.info('Running BlockAPI test #2...') logger.info('Running BlockAPI test #2...')
original_content = 'onionr' original_content = 'onionr'
contents = [original_content[i:i+2] for i in range(0, len(original_content), 2)]
contents.reverse()
blocks = list() logger.debug('original: %s' % original_content)
parent = None
for content in contents: blocks = Block.createChain(data = original_content, chunksize = 2, verbose = True)
block = Block('test', content)
block.setParent(parent)
parent = block
print('block "%s": %s' % (content, block.save()))
blocks.append(block)
child = blocks[-1] logger.debug(blocks[1])
merged = Block.merge(child) child = blocks[0]
merged = Block.mergeChain(child)
print('merged blocks: %s' % merged) logger.debug('merged blocks (child: %s): %s' % (child, merged))
if merged != original_content: if merged != original_content:
self.assertTrue(False) self.assertTrue(False)