Spine of betting smart contract

This commit introduces the betting smart contract on FLO blockchain
This commit is contained in:
Vivek Teega 2019-03-23 20:49:53 +00:00
parent 11a4aa09c6
commit f49693d71b
8 changed files with 309 additions and 731 deletions

View File

@ -1,6 +1,6 @@
[DEFAULT]
NET = testnet
FLO_CLI_PATH = /usr/local/bin/flo-cli
START_BLOCK = 489130
START_BLOCK = 498770

View File

@ -3,6 +3,7 @@ from sqlalchemy import Column, Integer, Float, String, ForeignKey
Base = declarative_base()
ContractBase = declarative_base()
SystemBase = declarative_base()
class Extra(Base):
__tablename__ = "extra"
@ -52,4 +53,18 @@ class ContractStructure(ContractBase):
index = Column('index', Integer)
value = Column('value', String)
class ContractParticipants(ContractBase):
__tablename__ = "contractparticipants"
id = Column('id', Integer, primary_key=True)
participantAddress = Column('participantAddress', String)
tokenAmount = Column('tokenAmount', Float)
contractCondition = Column('contractCondition', String)
class ActiveContracts(SystemBase):
__tablename__ = "activecontracts"
id = Column('id', Integer, primary_key=True)
contractName = Column('contractName', String)
contractAddress = Column('contractAddress', String)

View File

@ -7,7 +7,7 @@ amount = None
def isTransfer(text):
wordlist = ['transfer','send','give'] #keep everything lowercase
wordlist = ['transfer','send','give'] # keep everything lowercase
textList = text.split(' ')
for word in wordlist:
if word in textList:
@ -27,7 +27,9 @@ def isIncorp(text):
def isSmartContract(text):
textList = text.split(' ')
for word in textList:
if word[-1] == '@':
if word == '':
continue
if word.endswith('@'):
return word
return False
@ -48,27 +50,13 @@ def isSmartContractPay(text):
return False
def extractOperation(text):
operationList = ['send', 'transfer', 'give'] # keep everything lowercase
count = 0
returnval = None
for operation in operationList:
count = count + text.count(operation)
if count > 1:
return 'Too many'
if count == 1 and (returnval is None):
returnval = operation
return returnval
# todo pass marker to the function and support all types
def extractAmount(text):
def extractAmount(text, marker):
count = 0
returnval = None
splitText = re.split("\W+", text)
for word in splitText:
word = word.replace('rmt', '')
word = word.replace(marker, '')
try:
float(word)
count = count + 1
@ -84,7 +72,9 @@ def extractAmount(text):
def extractMarker(text):
textList = text.split(' ')
for word in textList:
if word[-1] == '#':
if word == '':
continue
if word.endswith('#'):
return word
return False
@ -97,17 +87,20 @@ def extractInitTokens(text):
result = float(word)
if textList[idx+1] in base_units:
return result*base_units[textList[idx+1]]
return res
return result
except:
continue
return None
def extractAddress(text):
textList = text.split(' ')
for word in textList:
if word == '':
continue
if word[-1] == '$':
return word
return False
return None
def extractContractType(text):
@ -124,7 +117,11 @@ def extractContractType(text):
def extractContractCondition(text):
return text.split("contractcondition:")[1][1:-1]
result = text.split("contractcondition:")
if len(result) != 1:
return result[1].strip()[1:-1]
else:
return None
def extractContractConditions(text, contracttype, marker):
@ -149,9 +146,19 @@ def extractContractConditions(text, contracttype, marker):
else:
print("something is wrong with smartcontractpays conditions")
if 'userassetcommitment' in extractedRules and 'smartcontractpays' in extractedRules:
return extractedRules
else:
return None
return None
return extractedRules
return False
def extractTriggerCondition(text):
searchResult = re.search('\".*\"', text)
if searchResult is None:
searchResult = re.search('\'.*\'', text)
return searchResult
return searchResult
# Combine test
@ -163,45 +170,83 @@ def parse_flodata(string):
nospacestring = re.sub(' +', ' ', string)
cleanstring = nospacestring.lower()
atList = []
hashList = []
if isTransfer(cleanstring):
if isSmartContract(cleanstring):
contractname = isSmartContract(cleanstring)
marker = extractMarker(cleanstring)
operation = extractOperation(cleanstring)
amount = extractAmount(cleanstring)
contractcondition = extractContractCondition(cleanstring)
parsed_data = { 'type': 'transfer', 'transferType': 'smartContract', 'flodata': string, 'tokenIdentification': marker[:-1],
'operation': operation, 'tokenAmount': amount, 'contractName': contractname, 'contractCondition': contractcondition}
else:
marker = extractMarker(cleanstring)
operation = extractOperation(cleanstring)
amount = extractAmount(cleanstring)
address = extractAddress(nospacestring)
parsed_data = {'type': 'transfer', 'transferType': 'token', 'flodata': string, 'tokenIdentification': marker[:-1], 'operation': operation,
'amount': amount, 'address': address}
for word in cleanstring.split(' '):
if word.endswith('@'):
atList.append(word)
if word.endswith('#'):
hashList.append(word)
elif isSmartContractPay(nospacestring):
contractConditions = isSmartContractPay(nospacestring)
parsed_data = {'type': 'smartContractPays', 'flodata': string, 'smartContractTrigger':contractConditions['smartContractTrigger'], 'smartContractName':contractConditions['smartContractName']}
elif isSmartContract(cleanstring):
contractname = isSmartContract(cleanstring)
marker = extractMarker(cleanstring)
contracttype = extractContractType(cleanstring)
contractaddress = extractAddress(nospacestring)
contractconditions = extractContractConditions(cleanstring, 'betting*', marker)
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1], 'tokenIdentification': marker[:-1], 'contractName': contractname[:-1], 'contractAddress':contractaddress[:-1], 'flodata': string, 'contractConditions': contractconditions}
elif isIncorp(cleanstring):
incMarker = extractMarker(cleanstring)
initTokens = extractInitTokens(cleanstring)
parsed_data = {'type': 'tokenIncorporation', 'flodata': string, 'tokenIdentification': incMarker[:-1], 'tokenAmount': initTokens}
else:
# Filter noise first - check if the words end with either @ or #
if (len(atList)==0 and len(hashList)==0) or len(atList)>1 or len(hashList)>1:
parsed_data = {'type': 'noise'}
elif len(hashList)==1 and len(atList)==0:
# Passing the above check means token creation or transfer
incorporation = isIncorp(cleanstring)
transfer = isTransfer(cleanstring)
if incorporation and not transfer:
initTokens = extractInitTokens(cleanstring)
if initTokens is not None:
parsed_data = {'type': 'tokenIncorporation', 'flodata': string, 'tokenIdentification': hashList[0][:-1],
'tokenAmount': initTokens}
else:
parsed_data = {'type': 'noise'}
elif not incorporation and transfer:
amount = extractAmount(cleanstring, hashList[0][:-1])
address = extractAddress(nospacestring)
if None not in [amount, address]:
parsed_data = {'type': 'transfer', 'transferType': 'token', 'flodata': string,
'tokenIdentification': hashList[0][:-1],
'tokenAmount': amount, 'address': address[:-1]}
else:
parsed_data = {'type': 'noise'}
else:
parsed_data = {'type': 'noise'}
elif len(hashList)==1 and len(atList)==1:
# Passing the above check means Smart Contract creation or transfer
incorporation = isIncorp(cleanstring)
transfer = isTransfer(cleanstring)
if incorporation and not transfer:
contracttype = extractContractType(cleanstring)
contractaddress = extractAddress(nospacestring)
contractconditions = extractContractConditions(cleanstring, 'betting*', marker)
if None not in [contracttype, contractaddress, contractconditions]:
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1],
'tokenIdentification': hashList[0][:-1], 'contractName': atList[0][:-1],
'contractAddress': contractaddress[:-1], 'flodata': string,
'contractConditions': contractconditions}
else:
parsed_data = {'type': 'noise'}
elif not incorporation and transfer:
amount = extractAmount(cleanstring, hashList[0][:-1])
contractcondition = extractContractCondition(cleanstring)
if None not in [amount, contractcondition]:
parsed_data = {'type': 'transfer', 'transferType': 'smartContract', 'flodata': string,
'tokenIdentification': hashList[0][:-1],
'operation': 'transfer', 'tokenAmount': amount, 'contractName': atList[0][:-1],
'contractCondition': contractcondition}
else:
parsed_data = {'type': 'noise'}
else:
parsed_data = {'type': 'noise'}
elif len(hashList)==0 and len(atList)==1:
# Passing the above check means Smart Contract pays | exitcondition triggered from the committee
triggerCondition = extractTriggerCondition(cleanstring)
if triggerCondition is not None:
parsed_data = {'type': 'smartContractPays', 'contractName': atList[0][:-1], 'triggerCondition': triggerCondition.group().strip()[1:-1]}
else:
parsed_data = {'type':'noise'}
return parsed_data
result = parse_flodata('create electionbetting@ at address oM4pCYsbT5xg7bqLNCTXmoADUs6zBwLfXi$ of type betting* using the token rmt# with contractconditions: 1. userAssetCommitment="1rmt" 2. smartContractPays="NAMO=WIN | NAMO=LOOSE 3. expirydate=1553040000"')
result = parse_flodata("for contractname@ Smart Contract System says 'NAMO=WIN'")
print(result)

Binary file not shown.

Binary file not shown.

View File

@ -1,302 +0,0 @@
import requests
import json
import sqlite3
import argparse
import configparser
import subprocess
import sys
import parsing
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine, func, desc
from models import Extra, TransactionHistory, TransactionTable, TransferLogs, Webtable, Base, ContractStructure
def startWorking(transaction_data, parsed_data):
engine = create_engine('sqlite:///databases/{}.db'.format(parsed_data['marker'][:-1]), echo=True)
Base.metadata.create_all(bind=engine)
Session = sessionmaker(bind=engine)
session = Session()
# Play area
if parsed_data['type'] == 'transfer':
if parsed_data['amount'] is None:
print("Value for token transfer has not been specified")
return
elif parsed_data['type'] == 'incorporation':
if parsed_data['initTokens'] is None:
print("Value for token transfer has not been specified")
return
inputlist = []
querylist = []
for obj in transaction_data["vin"]:
querylist.append([obj["txid"], obj["vout"]])
inputval = 0
inputadd = ''
for query in querylist:
string = "{} getrawtransaction {} 1".format(localapi, str(query[0]))
response = subprocess.check_output(string, shell=True)
content = json.loads(response.decode("utf-8"))
for objec in content["vout"]:
if objec["n"] == query[1]:
inputadd = objec["scriptPubKey"]["addresses"][0]
inputval = inputval + objec["value"]
inputlist = [[inputadd, inputval]]
if len(inputlist) > 1:
print("Program has detected more than one input address ")
print("This transaction will be discarded")
break
outputlist = []
for obj in transaction_data["vout"]:
if obj["scriptPubKey"]["type"] == "pubkeyhash":
if inputlist[0][0] == obj["scriptPubKey"]["addresses"][0]:
continue
temp = []
temp.append(obj["scriptPubKey"]["addresses"][0])
temp.append(obj["value"])
outputlist.append(temp)
print("\n\nInput List")
print(inputlist)
print("\nOutput List")
print(outputlist)
if len(inputlist) > 1:
print("Program has detected more than one input address ")
print("This transaction will be discarded")
continue
# Check if the transaction is of the type 'incorporation' or 'smartcontract'
if parsed_data['type'] == 'smartcontract':
print("I JUST FOUND THE INCORPORATION OF SMART CONTRACT \n" + str(parsed_data))
if parsed_data['contracttype'] == 'betting*':
print("Smart contract is of the type betting")
if parsed_data['contractname'] is not None and parsed_data['contractaddress'][:-1] == outputlist[0][0]:
print("Hey I have passed the first test for smart contract")
#check if a db with contractname exists
scengine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractname'][:-1]), echo=True)
Base.metadata.create_all(bind=scengine)
scsession = sessionmaker(bind=scengine)()
scsession.add(ContractStructure(attribute='contracttype', index=0, value=parsed_data['contracttype'][:-1]))
scsession.add(ContractStructure(attribute='contractname', index=0, value=parsed_data['contractname'][:-1]))
scsession.add(
ContractStructure(attribute='marker', index=0, value=parsed_data['marker'][:-1]))
scsession.commit()
scsession.close()
sys.exit(0)
elif parsed_data['type'] == 'incorporation':
session.add(TransactionTable(address=outputlist[0][0], parentid=0, transferBalance=parsed_data['initTokens']))
session.commit()
#transferDescription = "Root address = " + str(root_address) + " has been initialized with " + str(root_init_value) + " tokens"
#blockchainReference = '{}tx/'.format(neturl)
#session.add(TransferLogs(primaryIDReference=1, transferDescription=transferDescription, transferIDConsumed=0, blockchainReference=blockchainReference))
#session.add(TransactionHistory(blockno=root_block_index, fromAddress='', toAddress=root_address, amount=root_init_value, blockchainReference=blockchainReference))
#session.commit()
return
availableTokens = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputlist[0][0]).all()[0][0]
commentTransferAmount = parsed_data['amount']
if availableTokens is None:
print("The input address dosen't exist in our database ")
elif availableTokens < commentTransferAmount:
print("\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
continue
elif availableTokens >= commentTransferAmount:
'''if len(commentTransferAmount) != len(outputlist):
print("The parameters in the comments aren't enough")
print("This transaction will be discarded")
continue'''
# if output[0] == inputlist[0][0]:
# continue
#c.execute("SELECT * FROM transactiontable WHERE address=?", (inputlist[0][0],))
#table = c.fetchall()
table = session.query(TransactionTable).filter_by(address=inputlist[0][0]).all()
pidlst = []
checksum = 0
for row in table:
if checksum >= commentTransferAmount:
break
pidlst.append(row.id)
checksum = checksum + row.transferBalance
balance = commentTransferAmount
#c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", (outputlist[i][0],))
#opbalance = c.fetchall()[0][0]
opbalance = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=outputlist[0][0]).all()[0][0]
if opbalance is None:
opbalance = 0
#c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", (inputlist[0][0],))
#ipbalance = c.fetchall()[0][0]
ipbalance = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputlist[0][0]).all()[0][0]
for pid in pidlst:
#c.execute("SELECT transferBalance FROM transactiontable WHERE id=?", (pid,))
#temp = c.fetchall()
#temp = temp[0][0]
temp = session.query(TransactionTable.transferBalance).filter_by(id=pid).all()[0][0]
if balance <= temp:
#c.execute("INSERT INTO transactiontable (address, parentid, transferBalance) VALUES (?,?,?)",
# (outputlist[i][0], pid, balance))
#c.execute("UPDATE transactiontable SET transferBalance=? WHERE id=?", (temp - balance, pid))
session.add(TransactionTable(address=outputlist[0][0], parentid=pid, transferBalance=balance))
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
entry[0].transferBalance = temp - balance
session.commit()
## transaction logs section ##
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
lastid = result[-1].id
transferDescription = str(balance) + " tokens transferred to " + str(
outputlist[0][0]) + " from " + str(inputlist[0][0])
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransferLogs(primaryIDReference=lastid, transferDescription=transferDescription,
transferIDConsumed=pid, blockchainReference=blockchainReference))
transferDescription = str(inputlist[0][0]) + " balance UPDATED from " + str(
temp) + " to " + str(temp - balance)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransferLogs(primaryIDReference=pid, transferDescription=transferDescription,
blockchainReference=blockchainReference))
## transaction history table ##
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputlist[0][0],
toAddress=outputlist[0][0], amount=str(balance),
blockchainReference=blockchainReference))
##webpage table section ##
transferDescription = str(commentTransferAmount) + " tokens transferred from " + str(
inputlist[0][0]) + " to " + str(outputlist[0][0])
session.add(
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
transferDescription = "UPDATE " + str(outputlist[0][0]) + " balance from " + str(
opbalance) + " to " + str(opbalance + commentTransferAmount)
session.add(
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
transferDescription = "UPDATE " + str(inputlist[0][0]) + " balance from " + str(
ipbalance) + " to " + str(ipbalance - commentTransferAmount)
session.add(
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
balance = 0
session.commit()
elif balance > temp:
session.add(TransactionTable(address=outputlist[0][0], parentid=pid, transferBalance=temp))
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
entry[0].transferBalance = 0
session.commit()
##transaction logs section ##
session.query(TransactionTable.id).order_by(desc(TransactionTable.id))
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
lastid = result[-1].id
transferDescription = str(temp) + " tokens transferred to " + str(
outputlist[0][0]) + " from " + str(inputlist[0][0])
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransactionTable(primaryIDReference=lastid, transferDescription=transferDescription,
transferIDConsumed=pid, blockchainReference=blockchainReference))
transferDescription = str() + " balance UPDATED from " + str(temp) + " to " + str(0)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransactionTable(primaryIDReference=pid, transferDescription=transferDescription,
blockchainReference=blockchainReference))
## transaction history table ##
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputlist[0][0],
toAddress=outputlist[0][0], amount=str(balance),
blockchainReference=blockchainReference))
balance = balance - temp
session.commit()
# Finishing statements
session.commit()
session.close()
# Read configuration
config = configparser.ConfigParser()
config.read('config.ini')
# Read command line arguments
parser = argparse.ArgumentParser(description='Script tracks RMT using FLO data on the FLO blockchain - https://flo.cash')
parser.add_argument('-r', '--reset', nargs='?', const=1, type=int, help='Purge existing db and rebuild it')
args = parser.parse_args()
# Assignment the flo-cli command
if config['DEFAULT']['NET'] == 'mainnet':
neturl = 'https://florincoin.info/'
localapi = config['DEFAULT']['FLO_CLI_PATH']
elif config['DEFAULT']['NET'] == 'testnet':
neturl = 'https://testnet.florincoin.info/'
localapi = '{} --testnet'.format(config['DEFAULT']['FLO_CLI_PATH'])
else:
print("NET parameter is wrong\nThe script will exit now ")
# Delete database directory if reset is set to 1
if args.reset == 1:
import os
import shutil
apppath = os.path.dirname(os.path.realpath(__file__))
dirpath = os.path.join(apppath, 'databases')
shutil.rmtree(dirpath)
os.mkdir(dirpath)
# Read start block no
startblock = int(config['DEFAULT']['START_BLOCK'])
# Find current block height
string = "{} getblockcount".format(localapi)
response = subprocess.check_output(string, shell=True)
current_index = json.loads(response.decode("utf-8"))
print("current_block_height : " + str(current_index))
for blockindex in range( startblock, current_index ):
print(blockindex)
# Scan every block
string = "{} getblockhash {}".format(localapi, str(blockindex))
response = subprocess.check_output(string, shell=True)
blockhash = response.decode("utf-8")
string = "{} getblock {}".format(localapi, str(blockhash))
response = subprocess.check_output(string, shell=True)
blockinfo = json.loads(response.decode("utf-8"))
# Scan every transaction
for transaction in blockinfo["tx"]:
string = "{} getrawtransaction {} 1".format(localapi, str(transaction))
response = subprocess.check_output(string, shell=True)
transaction_data = json.loads(response.decode("utf-8"))
text = transaction_data["floData"]
text = text[5:]
parsed_data = parsing.parse_flodata(text)
if parsed_data['type'] != 'noise':
print(blockindex)
print(parsed_data['type'])
startWorking(transaction_data, parsed_data)

View File

@ -1,351 +0,0 @@
import requests
import json
import sqlite3
import argparse
import configparser
import subprocess
# Read configuration
config = configparser.ConfigParser()
config.read('config.ini')
# Read command line arguments
parser = argparse.ArgumentParser(description='Script tracks RMT using FLO data on the FLO blockchain - https://flo.cash')
parser.add_argument('-r', '--reset', nargs='?', const=1, type=int, help='Purge existing db and rebuild it')
args = parser.parse_args()
if config['DEFAULT']['NET'] == 'mainnet':
neturl = 'https://florincoin.info/'
localapi = config['DEFAULT']['FLO_CLI_PATH']
elif config['DEFAULT']['NET'] == 'testnet':
neturl = 'https://testnet.florincoin.info/'
localapi = '{} --testnet'.format(config['DEFAULT']['FLO_CLI_PATH'])
else:
print('NET parameter is wrong')
def listcheck(lst):
for element in lst:
try:
float(element)
except ValueError:
print("values to be transferred aren't in the right format")
return 1
return 0
def startTracking(blockindex, config, conn, c):
string = "{} getblockhash {}".format(localapi, str(blockindex))
response = subprocess.check_output(string, shell=True)
blockhash = response.decode("utf-8")
string = "{} getblock {}".format(localapi, str(blockhash))
response = subprocess.check_output(string, shell=True)
blockinfo = json.loads(response.decode("utf-8"))
for transaction in blockinfo["tx"]:
string = "{} getrawtransaction {} 1".format(localapi, str(transaction))
response = subprocess.check_output(string, shell=True)
data = json.loads(response.decode("utf-8"))
text = data["floData"]
text = text[5:]
comment_list = text.split("#")
if comment_list[0] == config['DEFAULT']['PREFIX']:
print("I just saw "+str(config['DEFAULT']['PREFIX']))
commentTransferAmount = comment_list[1:]
#if not all(isinstance(x, (int, float)) for x in commentTransferAmount):
# print("Values to be transffered aren't in the right format")
# continue
if len(commentTransferAmount) == 0:
print("Value for token transfer has not been specified")
continue
returnval = listcheck(commentTransferAmount)
if returnval == 1:
continue
commentTransferAmount = list(map(float, commentTransferAmount))
inputlist = []
querylist = []
for obj in data["vin"]:
querylist.append([obj["txid"], obj["vout"]])
inputval = 0
inputadd = ''
for query in querylist:
string = "{} getrawtransaction {} 1".format(localapi, str(query[0]))
response = subprocess.check_output(string, shell=True)
content = json.loads(response.decode("utf-8"))
for objec in content["vout"]:
if objec["n"] == query[1]:
inputadd = objec["scriptPubKey"]["addresses"][0]
inputval = inputval + objec["value"]
inputlist = [[inputadd, inputval]]
if len(inputlist) > 1:
print("Program has detected more than one input address ")
print("This transaction will be discarded")
continue
outputlist = []
for obj in data["vout"]:
if obj["scriptPubKey"]["type"] == "pubkeyhash":
if inputlist[0][0] == obj["scriptPubKey"]["addresses"][0]:
continue
temp = []
temp.append(obj["scriptPubKey"]["addresses"][0])
temp.append(obj["value"])
outputlist.append(temp)
print("\n\nInput List")
print(inputlist)
print("\nOutput List")
print(outputlist)
if len(inputlist) > 1:
print("Program has detected more than one input address ")
print("This transaction will be discarded")
continue
c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?" , (inputlist[0][0],))
availableTokens = c.fetchall()
availableTokens = availableTokens[0][0]
if availableTokens is None:
print("The input address dosen't exist in our database ")
elif availableTokens < sum(commentTransferAmount):
print("\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
continue
elif availableTokens >= sum(commentTransferAmount):
if len(commentTransferAmount) != len(outputlist):
print("The parameters in the comments aren't enough")
print("This transaction will be discarded")
continue
for i in range(len(commentTransferAmount)):
# if output[0] == inputlist[0][0]:
# continue
c.execute("SELECT * FROM transactiontable WHERE address=?",(inputlist[0][0],))
table = c.fetchall()
pidlst = []
checksum = 0
for row in table:
if checksum >= commentTransferAmount[i]:
break
pidlst.append(row[0])
checksum = checksum + row[3]
balance = commentTransferAmount[i]
c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", ( outputlist[i][0],))
opbalance = c.fetchall()[0][0]
if opbalance is None:
opbalance = 0
c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", ( inputlist[0][0],))
ipbalance = c.fetchall()[0][0]
for pid in pidlst:
c.execute("SELECT transferBalance FROM transactiontable WHERE id=?", (pid,))
temp = c.fetchall()
temp = temp[0][0]
if balance <= temp:
c.execute("INSERT INTO transactiontable (address, parentid, transferBalance) VALUES (?,?,?)", (outputlist[i][0],pid,balance))
c.execute("UPDATE transactiontable SET transferBalance=? WHERE id=?", (temp-balance, pid))
## transaction logs section ##
c.execute("SELECT id FROM transactiontable ORDER BY id DESC LIMIT 1")
lastid = c.fetchall()[0][0]
transferDescription = str(balance) + " tokens transferred to " + str(outputlist[i][0]) + " from " + str(inputlist[0][0])
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, transferIDConsumed, blockchainReference)
VALUES (?,?,?,?)""", ( lastid, transferDescription, pid, blockchainReference))
transferDescription = str(inputlist[0][0]) + " balance UPDATED from " + str(temp) + " to " + str(temp-balance)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, blockchainReference)
VALUES (?,?,?)""", ( pid, transferDescription, blockchainReference))
## transaction history table ##
c.execute(
'''INSERT INTO transactionHistory (blockno, fromAddress, toAddress, amount, blockchainReference) VALUES (?,?,?,?,?)''',
(blockindex, inputlist[0][0], outputlist[0][0], str(balance), blockchainReference))
##webpage table section ##
transferDescription = str(commentTransferAmount[i]) + " tokens transferred from " + str(inputlist[0][0]) + " to " + str(outputlist[i][0])
c.execute("""INSERT INTO webtable (transferDescription, blockchainReference)
VALUES (?,?)""", ( transferDescription, blockchainReference))
transferDescription = "UPDATE " + str(outputlist[i][0]) + " balance from " + str(opbalance) + " to " + str(opbalance + commentTransferAmount[i])
c.execute("""INSERT INTO webtable (transferDescription, blockchainReference)
VALUES (?,?)""", ( transferDescription, blockchainReference))
transferDescription = "UPDATE " + str(inputlist[0][0]) + " balance from " + str(ipbalance) + " to " + str(ipbalance - commentTransferAmount[i])
c.execute("""INSERT INTO webtable (transferDescription, blockchainReference)
VALUES (?,?)""", ( transferDescription, blockchainReference))
balance = 0
conn.commit()
elif balance > temp:
c.execute("INSERT INTO transactiontable (address, parentid, transferBalance) VALUES (?,?,?)", (outputlist[i][0], pid, temp ))
c.execute("UPDATE transactiontable SET transferBalance=? WHERE id=?", (0, pid))
##transaction logs section ##
c.execute("SELECT id FROM transactiontable ORDER BY id DESC LIMIT 1")
lastid = c.fetchall()[0][0]
transferDescription = str(temp) + " tokens transferred to " + str(outputlist[i][0]) + " from " + str(inputlist[0][0])
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, transferIDConsumed, blockchainReference)
VALUES (?,?,?,?)""", ( lastid, transferDescription, pid, blockchainReference))
transferDescription = str() + " balance UPDATED from " + str(temp) + " to " + str(0)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, blockchainReference)
VALUES (?,?,?)""", ( pid, transferDescription, blockchainReference))
## transaction history table ##
c.execute(
'''INSERT INTO transactionHistory (blockno, fromAddress, toAddress, amount, blockchainReference) VALUES (?,?,?,?,?)''',
(blockindex, inputlist[0][0], outputlist[0][0], str(balance), blockchainReference))
balance = balance - temp
conn.commit()
def resetDatabase(c, conn):
c.execute("DROP TABLE IF EXISTS transactiontable")
c.execute("""CREATE TABLE transactiontable (
id INTEGER PRIMARY KEY AUTOINCREMENT,
address TEXT,
parentid INT,
transferBalance REAL
)""")
c.execute("DROP TABLE IF EXISTS transferlogs")
c.execute("""CREATE TABLE transferlogs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
primaryIDReference INTEGER,
transferDescription TEXT,
transferIDConsumed INT,
blockchainReference TEXT
)""")
c.execute("DROP TABLE IF EXISTS webtable")
c.execute("""CREATE TABLE webtable (
id INTEGER PRIMARY KEY AUTOINCREMENT,
transferDescription TEXT,
blockchainReference TEXT
)""")
c.execute("DROP TABLE IF EXISTS transactionHistory")
c.execute("""CREATE TABLE transactionHistory (
id INTEGER PRIMARY KEY AUTOINCREMENT,
blockno INT,
fromAddress TEXT,
toAddress TEXT,
amount REAL,
blockchainReference TEXT
)""")
c.execute("DROP TABLE IF EXISTS extra")
c.execute("CREATE TABLE extra ( id INTEGER PRIMARY KEY , lastblockscanned INT)")
conn.commit()
def main():
# Connect to db
conn = sqlite3.connect(config['DEFAULT']['DB_NAME'])
c = conn.cursor()
# get current block height
string = "{} getblockcount".format(localapi)
response = subprocess.check_output(string, shell=True)
current_index = json.loads(response.decode("utf-8"))
print("current_block_height : " + str(current_index))
if args.reset == 1:
resetDatabase(c, conn)
# Read root address
root_address = config['DEFAULT']['ROOT_ADDRESS']
root_init_value = int(config['DEFAULT']['INIT_TOKEN_NO'])
# Find root address's block no
string = "{}ext/getaddress/{}/".format(neturl, str(root_address))
response = requests.get(string)
content = json.loads(response.content.decode("utf-8"))
root_trans_hash = ''
for cur in content["last_txs"]:
if cur["type"] == "vout":
root_trans_hash = cur["addresses"]
break
string = "{} getrawtransaction {} 1".format(localapi, str(root_trans_hash))
response = subprocess.check_output(string, shell=True)
content = json.loads(response.decode("utf-8"))
root_block_hash = content["blockhash"]
string = "{} getblock {}".format(localapi, str(root_block_hash))
response = subprocess.check_output(string, shell=True)
content = json.loads(response.decode("utf-8"))
root_block_index = content["height"]
# root_block_index = 26066
print("root_block_index = " + str(root_block_index))
c.execute("INSERT INTO transactiontable ( address, parentid, transferBalance) VALUES (?,?,?)",
(root_address, 0, root_init_value))
conn.commit()
transferDescription = "Root address = " + str(root_address) + " has been initialized with " + str(
root_init_value) + " tokens"
blockchainReference = '{}tx/'.format(neturl)
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, transferIDConsumed, blockchainReference)
VALUES (?,?,?,?)""",
(1, transferDescription, 0, blockchainReference))
c.execute(
'''INSERT INTO transactionHistory (blockno, fromAddress, toAddress, amount, blockchainReference) VALUES (?,?,?,?,?)''',
(root_block_index, '', root_address, root_init_value, blockchainReference))
c.execute("INSERT INTO extra (id, lastblockscanned) VALUES (?,?)", (1, root_block_index))
conn.commit()
lastblockscanned = root_block_index
else:
response = requests.get("{}api/getblockcount".format(neturl))
string = "{} getblockcount".format(localapi)
response = subprocess.check_output(string, shell=True)
current_index = json.loads(response.decode("utf-8"))
c.execute("SELECT lastblockscanned FROM extra WHERE id=1")
lastblockscanned = c.fetchall()[0][0]
# run loop and pass blockno
for blockindex in range(lastblockscanned + 1, current_index+1):
if blockindex == 3127800:
print('hi')
print(blockindex)
startTracking(blockindex, config, conn, c)
c.execute("UPDATE extra SET lastblockscanned=? WHERE id=?", (blockindex,1))
conn.commit()
conn.commit()
conn.close()
if __name__ == "__main__":
main()

View File

@ -10,7 +10,121 @@ import os
import shutil
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine, func, desc
from models import Extra, TransactionHistory, TransactionTable, TransferLogs, Webtable, Base, ContractStructure, ContractBase
from models import Extra, TransactionHistory, TransactionTable, TransferLogs, Webtable, Base, ContractStructure, ContractBase, ContractParticipants, SystemBase, ActiveContracts
committeeAddressList = ['oUc4dVvxwK7w5MHUHtev8UawN3eDjiZnNx']
def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress):
engine = create_engine('sqlite:///tokens/{}.db'.format(tokenIdentification), echo=True)
Base.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
availableTokens = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputAddress).all()[0][0]
commentTransferAmount = tokenAmount
if availableTokens is None:
print("The input address dosen't exist in our database ")
session.close()
return None
elif availableTokens < commentTransferAmount:
print(
"\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
session.close()
return None
elif availableTokens >= commentTransferAmount:
table = session.query(TransactionTable).filter(TransactionTable.address==inputAddress, TransactionTable.transferBalance>0).all()
pidlst = []
checksum = 0
for row in table:
if checksum >= commentTransferAmount:
break
pidlst.append(row.id)
checksum = checksum + row.transferBalance
balance = commentTransferAmount
opbalance = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=outputAddress).all()[0][0]
if opbalance is None:
opbalance = 0
ipbalance = availableTokens
for pid in pidlst:
temp = session.query(TransactionTable.transferBalance).filter_by(id=pid).all()[0][0]
if balance <= temp:
session.add(TransactionTable(address=outputAddress, parentid=pid, transferBalance=balance))
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
entry[0].transferBalance = temp - balance
session.commit()
## transaction logs section ##
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
lastid = result[-1].id
transferDescription = str(balance) + " tokens transferred to " + str(
outputAddress) + " from " + str(inputAddress)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransferLogs(primaryIDReference=lastid, transferDescription=transferDescription,
transferIDConsumed=pid, blockchainReference=blockchainReference))
transferDescription = str(inputAddress) + " balance UPDATED from " + str(
temp) + " to " + str(temp - balance)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransferLogs(primaryIDReference=pid, transferDescription=transferDescription,
blockchainReference=blockchainReference))
## transaction history table ##
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputAddress,
toAddress=outputAddress, amount=str(balance),
blockchainReference=blockchainReference))
##webpage table section ##
transferDescription = str(commentTransferAmount) + " tokens transferred from " + str(
inputAddress) + " to " + str(outputAddress)
session.add(
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
transferDescription = "UPDATE " + str(outputAddress) + " balance from " + str(
opbalance) + " to " + str(opbalance + commentTransferAmount)
session.add(
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
transferDescription = "UPDATE " + str(inputAddress) + " balance from " + str(
ipbalance) + " to " + str(ipbalance - commentTransferAmount)
session.add(
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
balance = 0
session.commit()
elif balance > temp:
session.add(TransactionTable(address=outputAddress, parentid=pid, transferBalance=temp))
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
entry[0].transferBalance = 0
session.commit()
##transaction logs section ##
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
lastid = result[-1].id
transferDescription = str(temp) + " tokens transferred to " + str(outputAddress) + " from " + str(inputAddress)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransferLogs(primaryIDReference=lastid, transferDescription=transferDescription,
transferIDConsumed=pid, blockchainReference=blockchainReference))
transferDescription = str() + " balance UPDATED from " + str(temp) + " to " + str(0)
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
session.add(TransferLogs(primaryIDReference=pid, transferDescription=transferDescription,
blockchainReference=blockchainReference))
## transaction history table ##
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputAddress,
toAddress=outputAddress, amount=str(balance),
blockchainReference=blockchainReference))
balance = balance - temp
session.commit()
session.close()
return 1
def startWorking(transaction_data, parsed_data):
@ -67,25 +181,30 @@ def startWorking(transaction_data, parsed_data):
if parsed_data['type'] == 'transfer':
print('Found a transaction of the type transfer')
if parsed_data['transferType'] == 'smartContract':
print('do something')
if parsed_data['transferType'] == 'token':
elif parsed_data['transferType'] == 'token':
engine = create_engine('sqlite:///tokens/{}.db'.format(parsed_data['tokenIdentification']), echo=True)
Base.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
availableTokens = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputlist[0][0]).all()[0][0]
commentTransferAmount = parsed_data['amount']
if availableTokens is None:
print("The input address dosen't exist in our database ")
returnval = transferToken(parsed_data['tokenIdentification'], parsed_data['tokenAmount'], inputlist[0][0], outputlist[0][0])
if returnval is None:
print("Something went wrong in the token transfer method")
elif availableTokens < commentTransferAmount:
print(
"\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
return
elif parsed_data['transferType'] == 'smartContract':
# Check if the tokenAmount being transferred exists in the address & do the token transfer
returnval = transferToken(parsed_data['tokenIdentification'], parsed_data['tokenAmount'], inputlist[0][0], outputlist[0][0])
if returnval is not None:
# Store participant details in the smart contract's db
engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True)
Base.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
session.add(ContractParticipants(participantAddress=inputadd, tokenAmount=parsed_data['tokenAmount'],
contractCondition=parsed_data['contractCondition']))
session.commit()
session.close()
else:
print("Something went wrong in the smartcontract token transfer method")
elif availableTokens >= commentTransferAmount:
print("well i've reached here")
elif parsed_data['type'] == 'tokenIncorporation':
if not os.path.isfile('./tokens/{}.db'.format(parsed_data['tokenIdentification'])):
@ -112,7 +231,7 @@ def startWorking(transaction_data, parsed_data):
session.add(
ContractStructure(attribute='tokenIdentification', index=0, value=parsed_data['tokenIdentification']))
session.add(
ContractStructure(attribute='contractAddress', index=0, value=parsed_data['contractAddress'][:-1]))
ContractStructure(attribute='contractAddress', index=0, value=parsed_data['contractAddress']))
session.add(
ContractStructure(attribute='flodata', index=0,
value=parsed_data['flodata']))
@ -123,11 +242,50 @@ def startWorking(transaction_data, parsed_data):
session.add(ContractStructure(attribute='exitconditions', index=key, value=value))
session.commit()
session.close()
# Store smart contract address in system's db, to be ignored during future transfers
engine = create_engine('sqlite:///system.db',
echo=True)
SystemBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
session.add(
ActiveContracts(contractName=parsed_data['contractName'], contractAddress=parsed_data['contractAddress']))
session.commit()
session.close()
else:
print('Transaction rejected as a smartcontract with same name has already been incorporated')
elif parsed_data['type'] == 'smartContractPays':
print('Found a transaction of the type smartContractPays')
# Check if input address is a committee address
if inputlist[0][0] in committeeAddressList:
# Check if the output address is an active Smart contract address
engine = create_engine('sqlite:///system.db', echo=True)
connection = engine.connect()
activeContracts = connection.execute('select * from activecontracts').fetchall()
connection.close()
# Change columns into rows - https://stackoverflow.com/questions/44360162/how-to-access-a-column-in-a-list-of-lists-in-python
activeContracts = list(zip(*activeContracts))
if outputlist[0][0] in activeContracts[2] and parsed_data['contractName'] in activeContracts[1]:
engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True)
connection = engine.connect()
contractWinners = connection.execute('select * from contractparticipants where contractCondition="{}"'.format(parsed_data['triggerCondition'])).fetchall()
tokenSum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0]
tokenIdentification = connection.execute('select value from contractstructure where attribute="tokenIdentification"').fetchall()[0][0]
connection.close()
contractWinners = list(zip(*contractWinners))
for address in contractWinners[1]:
transferToken(tokenIdentification, tokenSum/len(contractWinners[1]), outputlist[0][0], address)
else:
print('This trigger doesn\'t apply to an active contract. It will be discarded')
else:
print('Input address is not part of the committee address list. This trigger is rejected')
@ -150,6 +308,13 @@ elif config['DEFAULT']['NET'] == 'testnet':
else:
print("NET parameter is wrong\nThe script will exit now ")
apppath = os.path.dirname(os.path.realpath(__file__))
dirpath = os.path.join(apppath, 'tokens')
if not os.path.isdir(dirpath):
os.mkdir(dirpath)
dirpath = os.path.join(apppath, 'smartContracts')
if not os.path.isdir(dirpath):
os.mkdir(dirpath)
# Delete database and smartcontract directory if reset is set to 1
if args.reset == 1:
@ -160,6 +325,9 @@ if args.reset == 1:
dirpath = os.path.join(apppath, 'smartContracts')
shutil.rmtree(dirpath)
os.mkdir(dirpath)
dirpath = os.path.join(apppath, 'system.db')
if os.path.exists(dirpath):
os.remove(dirpath)
# Read start block no
@ -191,6 +359,9 @@ for blockindex in range( startblock, current_index ):
transaction_data = json.loads(response.decode("utf-8"))
text = transaction_data["floData"]
if blockindex == 498385:
print('debug point')
parsed_data = parsing.parse_flodata(text)
if parsed_data['type'] != 'noise':
print(blockindex)