Create block API (todo docs)

master
Arinerron 2018-05-15 18:47:58 -07:00
parent e95feb06db
commit 9fdb6d8609
No known key found for this signature in database
GPG Key ID: 99383627861C62F0
2 changed files with 177 additions and 14 deletions

View File

@ -592,6 +592,20 @@ class Core:
return rows return rows
def getBlockDate(self, blockHash):
'''
Returns the date a block was received
'''
conn = sqlite3.connect(self.blockDB)
c = conn.cursor()
execute = 'SELECT dateReceived FROM hashes WHERE hash=?;'
args = (blockHash,)
for row in c.execute(execute, args):
for i in row:
return int(i)
return None
def getBlocksByType(self, blockType): def getBlocksByType(self, blockType):
''' '''
Returns a list of blocks by the type Returns a list of blocks by the type

View File

@ -18,13 +18,35 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
import core as onionrcore import core as onionrcore, logger
import json, os, datetime
class Block: class Block:
def __init__(self, hash = None, core = None): def __init__(self, hash = None, core = None):
self.hash = hash # input from arguments
self.core = core if (type(hash) == str) and (type(core) == str):
self.btype = hash
self.bcontent = core
self.hash = None
self.core = None
else:
self.btype = ''
self.bcontent = ''
self.hash = hash
self.core = core
# initialize variables
self.valid = True
self.raw = None
self.powHash = None
self.powToken = None
self.signed = False
self.signature = None
self.signedData = None
self.bheader = {}
self.bmetadata = {}
# handle arguments
if self.getCore() is None: if self.getCore() is None:
self.core = onionrcore.Core() self.core = onionrcore.Core()
if not self.getHash() is None: if not self.getHash() is None:
@ -48,13 +70,72 @@ class Block:
- (bool): indicates whether or not the operation was successful - (bool): indicates whether or not the operation was successful
''' '''
try:
# import from string
blockdata = data
# import from file
if blockdata is None:
filelocation = file
if filelocation is None:
if self.getHash() is None:
return False
filelocation = 'data/blocks/%s.dat' % self.getHash()
blockdata = open(filelocation, 'rb').read().decode('utf-8')
self.blockFile = filelocation
else:
self.blockFile = None
# parse block
self.raw = str(blockdata)
self.bheader = json.loads(self.getRaw()[:self.getRaw().index('\n')])
self.bcontent = self.getRaw()[self.getRaw().index('\n') + 1:]
self.bmetadata = json.loads(self.getHeader('meta'))
self.btype = self.getMetadata('type')
self.powHash = self.getMetadata('powHash')
self.powToken = self.getMetadata('powToken')
self.signed = ('sig' in self.getHeader() and self.getHeader('sig') != '')
self.signature = (None if not self.isSigned() else self.getHeader('sig'))
self.signedData = (None if not self.isSigned() else self.getHeader('meta') + '\n' + self.getContent())
self.date = self.getCore().getBlockDate(self.getHash())
if not self.getDate() is None:
self.date = datetime.datetime.fromtimestamp(self.getDate())
self.valid = True
return True
except Exception as e:
logger.error('Failed to update block data.', error = e, timestamp = False)
self.valid = False
return False return False
def delete(self): def delete(self):
if self.exists():
os.remove(self.getBlockFile())
return True
return False return False
def save(self): def save(self, sign = False, recreate = False):
return False try:
if self.isValid() is True:
if (recreate is True) and (not self.getBlockFile() is None):
with open(self.getBlockFile(), 'wb') as blockFile:
blockFile.write(self.getRaw().encode())
self.update()
else:
self.hash = self.getCore().insertBlock(self.getContent(), header = self.getType(), sign = sign)
self.update()
return True
else:
logger.warn('Not writing block; it is invalid.')
except Exception as e:
logger.error('Failed to save block.', error = e, timestamp = False)
return False
# getters # getters
@ -67,23 +148,50 @@ class Block:
def getType(self): def getType(self):
return self.btype return self.btype
def getMetadata(self): def getRaw(self):
return self.bmetadata return str(self.raw)
def getHeader(self, key = None):
if not key is None:
return self.getHeader()[key]
else:
return self.bheader
def getMetadata(self, key = None):
if not key is None:
return self.getMetadata()[key]
else:
return self.bmetadata
def getContent(self): def getContent(self):
return self.bcontent return str(self.bcontent)
def getDate(self): def getDate(self):
return self.date return self.date
def getBlockFile(self):
return self.blockFile
def isValid(self): def isValid(self):
return self.valid return self.valid
def isSigned(self): def isSigned(self):
return self.signed return self.signed
def getSigner(self): def getSignature(self):
return self.signer return self.signature
def getSignedData(self):
return self.signedData
def isSigner(self, signer, encodedData = True):
try:
if (not self.isSigned()) or (not self.getCore()._utils.validatePubKey(signer)):
return False
return bool(self.getCore()._crypto.edVerify(self.getSignedData(), signer, self.getSignature(), encodedData = encodedData))
except:
return False
# setters # setters
@ -92,7 +200,7 @@ class Block:
return self return self
def setContent(self, bcontent): def setContent(self, bcontent):
self.bcontent = bcontent self.bcontent = str(bcontent)
return self return self
# static # static
@ -100,8 +208,49 @@ class Block:
ORDER_DATE = 0 ORDER_DATE = 0
ORDER_ALPHABETIC = 1 ORDER_ALPHABETIC = 1
def getBlocks(type = None, signer = None, order = ORDER_DATE, reverse = False): def getBlocks(type = None, signer = None, signed = None, order = ORDER_DATE, reverse = False, core = None):
return None try:
core = (core if not core is None else onionrcore.Core())
relevant_blocks = list()
blocks = (core.getBlockList() if type is None else core.getBlocksByType(type))
for block in blocks:
if Block.exists(block):
block = Block(block)
relevant = True
if (not signed is None) and (block.isSigned() != bool(signed)):
relevant = False
if not signer is None:
if isinstance(signer, (str,)):
signer = [signer]
isSigner = False
for key in signer:
if block.isSigner(key):
isSigner = True
break
if not isSigner:
relevant = False
if relevant:
relevant_blocks.append(block)
return relevant_blocks
except Exception as e:
logger.debug(('Failed to get blocks: %s' % str(e)) + logger.parse_error())
return list()
def exists(hash): def exists(hash):
return None if hash is None:
return False
elif type(hash) == Block:
blockfile = hash.getBlockFile()
else:
blockfile = 'data/blocks/%s.dat' % hash
return os.path.exists(blockfile) and os.path.isfile(blockfile)