Skip to content
Open
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ This installation guide will be using Linux/Unix and Python 3.5 throughout.
Python will need to be installed on your system. To install python-pip run

```
sudo apt install python-pip3
sudo apt install python3-pip
```
If it is already installed, it may need to be upgraded by running

```
pip3 install upgrade pip
pip3 install --upgrade pip
```
Once you have python-pip installed you will need to install the python dependencies by running

Expand Down
44 changes: 37 additions & 7 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import re
import falcon
import pickle as pickle

import sys
import magic
import psutil
import time
from lib.ipfs import IPFSTools
from lib.db import MemeChainDB
from lib.memechain import MemeTx, Validate
Expand All @@ -23,6 +26,18 @@
# Memechain allowed content types
ALLOWED_IMAGE_TYPES = ('image/gif', 'image/jpeg', 'image/png')


def check_running():
counter = 0
for q in psutil.process_iter():
if q.name().find('sync'):
if len(q.cmdline())>1 and 'sync.py' in q.cmdline()[1]:
counter = counter + 1
if counter > 1:
return True
else:
return False

def validate_image_type(req, resp, resource, params):
if req.content_type not in ALLOWED_IMAGE_TYPES:
logger.error('COMMAND %s Failed %s: %s'
Expand Down Expand Up @@ -215,16 +230,23 @@ def on_post(self, req, resp):
logger.info('COMMAND %s Received' % self.__class__.__name__)
db = MemeChainDB(os.path.join(config['DATA_DIR'], 'memechain.json'))

while check_running():
time.sleep(3)
logger.info('Waiting for the synchronization process to complete add_meme')


# Generate random placeholder img name
img_placeholder_name = str(random.random()).split(".")[1]

ext = mimetypes.guess_extension(req.content_type)
if ext == '.jpe':
ext = '.jpg'


name = '{img_name}{ext}'.format(img_name=img_placeholder_name, ext=ext)
image_path = os.path.join(config['DATA_DIR'], name)


# Write image to local storage
with io.open(image_path, 'wb') as image_file:
while True:
Expand All @@ -234,6 +256,12 @@ def on_post(self, req, resp):

image_file.write(chunk)


if magic.from_file(image_path).lower().find(mimetypes.guess_extension(req.content_type)[1:]) < 0:
raise falcon.HTTPBadRequest( "Memechain error",
"Meme has not passed validation, file extension is wrong.")


# Check file size
meme_filesize = os.path.getsize(image_path) * 0.000001 # in MB

Expand All @@ -248,18 +276,15 @@ def on_post(self, req, resp):

# Add image to ipfs
ipfs_id = IPFSTools().add_meme(image_path)['Hash']

# Rename local img file to ipfs_id for easy reference
new_name = '{img_name}{ext}'.format(img_name=ipfs_id, ext=ext)
os.rename(image_path, os.path.join(config['DATA_DIR'], new_name))

# Add to Kekcoin chain
memetx = MemeTx(ipfs_id)
prev_block_memes = db.get_prev_block_memes()

if prev_block_memes:
memetx.generate_hashlink(prev_block_memes)

try:
Validate(memetx, db=db, ipfs_dir=config['DATA_DIR'],
prev_block_memes=prev_block_memes)
Expand All @@ -270,13 +295,18 @@ def on_post(self, req, resp):

logger.error('COMMAND %s Failed %s: %s'
% (self.__class__.__name__, 'Memechain Error',
"Meme has not passed memechain validation, file extension not supported."))
"Meme has not passed memechain validation, file extension not supported.%s") )
raise falcon.HTTPError(falcon.HTTP_400, "Memechain error",
"Meme has not passed validation, file extension not supported.")
"Meme has not passed validation, file extension not supported.%s" % e )

if memetx.is_meme_valid():


memetx.blockchain_write()

db.add_meme(**{"ipfs_id": ipfs_id, "hashlink": memetx.get_hashlink(),
"txid": memetx.get_txid(), "author": memetx.get_author(), "block": 0, "imgformat": ext[1:],
"status": "unconfirm"})
resp.status = falcon.HTTP_201
resp.set_header('Powered-By', 'Memechain')

Expand Down Expand Up @@ -335,4 +365,4 @@ def on_post(self, req, resp):
app.add_route('/api/getmemeimgbyhash/{ipfs_id}', get_meme_img_by_hash())

# Add meme command
app.add_route('/api/addmeme', add_meme())
app.add_route('/api/addmeme', add_meme())
8 changes: 6 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"RPC_USER" : "user",
"RPC_PASS" : "pass",
"RPC_PORT" : "13377",
"ALLOWED_IP_ADDRESSES" : []
}
"ALLOWED_IP_ADDRESSES" : [],
"ALLOWED_IMAGE_EXTENSIONS" : ["jpg","png","gif"],
"ENABLE_LOG_MEMTX_NOT_FOUND" : false,
"MULTIPLE_SYNC_RUNNING" : false,
"CHECK_FILES_ON_RUNNING" : true
}
Empty file modified data/debug.log
100644 → 100755
Empty file.
4 changes: 2 additions & 2 deletions lib/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ def create_raw_op_return_transaction(metadata):
"This tool set does not currently support reading op_return data with less than 4 chars")

input_tx = get_input()

print(round(float(input_tx["amount"]) - 1.1 * TX_BURN_AMOUNT, 8))
init_raw_tx = rpc.createrawtransaction([{"txid": input_tx["txid"], "vout": input_tx["vout"]}], {
input_tx["address"]: TX_BURN_AMOUNT, rpc.getnewaddress(): round(float(input_tx["amount"]) - 1.1 * TX_BURN_AMOUNT, 8)})
input_tx["address"]: round(float(input_tx["amount"]) - 1.1 * TX_BURN_AMOUNT, 8), rpc.getnewaddress(): TX_BURN_AMOUNT})

oldScriptPubKey = init_raw_tx[len(init_raw_tx) - 60:len(init_raw_tx) - 8]
newScriptPubKey = b"6a" + hexlify(bytes(chr(len(metadata)), encoding='utf-8')) + hexlify(bytes(metadata, encoding='utf-8'))
Expand Down
15 changes: 13 additions & 2 deletions lib/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,24 @@ class MemeChainDB(object):
def __init__(self, db_path):
self._db = TinyDB(db_path)

def add_meme(self, ipfs_id, hashlink, txid, block, imgformat, author):
def add_meme(self, ipfs_id, hashlink, txid, block, imgformat, author, status):
self._db.insert({"ipfs_id": ipfs_id, "hashlink": hashlink,
"txid": txid, "block": block, "imgformat" : imgformat, "author" : author})
"txid": txid, "block": block, "imgformat" : imgformat, "author" : author, "status": status})

def remove_meme(self, ipfs_id):
self._db.remove(Query().ipfs_id == ipfs_id)

def get_memechain_height(self):
return len(self._db)

def update_meme(self, ipfs_id, block):
memes = self._db.search(Query().ipfs_id == ipfs_id)
print(memes)
for meme in memes:
meme["block"] = block
meme["status"] = "confirm"
self._db.write_back(memes)

def search_by_block(self, block):
"""
Get a meme entry using block number as the search parameter
Expand Down Expand Up @@ -119,5 +127,8 @@ def get_prev_block_memes(self):
def get_last_meme(self):
return Index(self._db)[-1]

def get_all_memes(self):
return self._db.search(Query().ipfs_id.exists())

def get_meme_height_by_ipfs_id(self, ipfs_id):
return Index(self._db).return_index(self._db.get(Query().ipfs_id == ipfs_id)) + 1
33 changes: 22 additions & 11 deletions lib/memechain.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from hashlib import sha256

from logger import *
from .blockchain import *
from .ipfs import IPFSTools

Expand All @@ -14,13 +14,13 @@ def __init__(self, MemeTX, db, ipfs_dir, prev_block_memes, sync = False, genesis
if genesis == False:
self.is_valid = [self.check_ipfs_existance(MemeTX.get_ipfs_id(), ipfs_dir),
self.is_valid_hash_link(MemeTX, prev_block_memes),
self.check_duplicate(db, MemeTX.get_ipfs_id())]
self.check_duplicate(db, MemeTX.get_ipfs_id()),
self.check_file_ext(MemeTX.get_ipfs_id())]
else:
self.is_valid = [self.check_ipfs_existance(MemeTX.get_ipfs_id(), ipfs_dir)]

if sync == True:
self.is_valid.append(self.check_burn_amount(MemeTX))

MemeTX.set_is_valid(self.is_valid)

def is_valid_hash_link(self, MemeTX, prev_block_memes):
Expand All @@ -33,6 +33,7 @@ def is_valid_hash_link(self, MemeTX, prev_block_memes):
raw_str += ''.join(meme['ipfs_id'] for meme in prev_block_memes)
hashlink = sha256(raw_str.encode('utf-8')).hexdigest()[:16]
if hashlink != MemeTX.get_hashlink():
logger.info('COMMAND %s Failed %s: %s' % ('Sync', 'Memechain', "Invalid Hashlink %s." % hashlink))
return False
else:
return True
Expand All @@ -52,6 +53,7 @@ def check_ipfs_existance(self, ipfs_id, ipfs_dir):
# IPFS Tools should be instanciated.
ipfs = IPFSTools()
if not ipfs.get_meme(ipfs_id, ipfs_dir):
logger.info('COMMAND %s Failed %s: %s' % ('Sync', 'Memechain', "Meme does not exist on IPFS yet %s." % ipfs_id))
return False # Meme does not exist on IPFS yet
else:
return True # Meme already exists on global IPFS
Expand All @@ -65,8 +67,8 @@ def check_duplicate(self, db, ipfs_id):
ipfs_id - attribute of MemeTX
"""
meme = db.search_by_ipfs_id(ipfs_id)

if meme:
if meme and meme["status"] == "confirm":
logger.info('COMMAND %s Failed %s: %s' % ('Sync', 'Memechain', "Meme exist on db yet %s." % ipfs_id))
return False
else:
return True
Expand All @@ -76,12 +78,20 @@ def check_burn_amount(self, MemeTX):
Checks whether the correct amount of KEKs were burned for the MemeTx.
"""
burn_amount = get_tx_burn_amount(MemeTX.get_txid())

if float(burn_amount) == TX_BURN_AMOUNT:
return True
else:
logger.info('COMMAND %s Failed %s: %s' % ('Sync', 'Memechain', "Not correct amount of KEKs were burned for the MemeTx %s." % MemeTX.get_ipfs_id()))
return False

def check_file_ext(self, meme):
meme_filepath = IPFSTools().get_meme(meme, config['DATA_DIR'])
ext = meme_filepath.split(".")[-1]
if ext in config["ALLOWED_IMAGE_EXTENSIONS"]:
return True
else:
logger.info('COMMAND %s Failed %s: %s' % ('Sync', 'Memechain', "Not correct image file extension %s." % ext))
return False

class MemeTx(object):
"""
Expand All @@ -99,10 +109,12 @@ def set_is_valid(self, values):
self._is_valid = values

def is_meme_valid(self):
if False not in self._is_valid:
return True
else:
return False

for num, value in enumerate(self._is_valid, start=1):
if not value:
return num

return -1

def get_ipfs_id(self):
return self.ipfs_id
Expand Down Expand Up @@ -140,7 +152,6 @@ def generate_hashlink(self, prev_block_memes):

def blockchain_write(self):
metadata = self._identifier + self.command_bytes + self.ipfs_id + self.hashlink

rawtx, self.author = create_raw_op_return_transaction(metadata)
signedtx = sign_raw_transaction(rawtx)
self.txid = send_raw_transaction(signedtx)
2 changes: 2 additions & 0 deletions logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.DEBUG)


Loading