From f50f46362013c765834f7bd3384a5bc1391601a0 Mon Sep 17 00:00:00 2001 From: Vivek Teega Date: Sat, 11 May 2019 15:35:43 +0530 Subject: [PATCH] Change in parsing logic for contract condition --- .gitignore | 1 + models.py | 2 +- parsing.py | 33 ++++++++++----------- tracktokens-smartcontracts.py | 54 +++++++++++++++++++++++++++-------- 4 files changed, 59 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 2b71aab..6966618 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ tokens/ smartContracts/ *.sh system.db +config.ini diff --git a/models.py b/models.py index ff2ca56..3e33d7f 100644 --- a/models.py +++ b/models.py @@ -63,7 +63,7 @@ class ContractParticipants(ContractBase): id = Column('id', Integer, primary_key=True) participantAddress = Column('participantAddress', String) tokenAmount = Column('tokenAmount', Float) - userPreference = Column('userPreference', String) + userChoice = Column('userChoice', String) class ActiveContracts(SystemBase): __tablename__ = "activecontracts" diff --git a/parsing.py b/parsing.py index 7ad4935..4445a18 100644 --- a/parsing.py +++ b/parsing.py @@ -133,17 +133,22 @@ def extractContractType(text): return returnval -def extractContractCondition(text): - result = text.split("contractcondition:") - if len(result) != 1: - return result[1].strip()[1:-1] +def extractUserchoice(text): + result = re.split('userchoice:\s*', text) + if len(result) != 1 and result[1]!='': + return result[1].strip().strip('"').strip("'") else: return None def extractContractConditions(text, contracttype, marker): - rulestext = re.split('contractconditions:\s*', text)[-1] - rulelist = re.split('\d\.\s*', rulestext) + rulestext = re.split('contract-conditions:\s*', text)[-1] + #rulelist = re.split('\d\.\s*', rulestext) + rulelist = [] + for i in range(3): + rule = rulestext.split('({})'.format(i+1))[1].split('({})'.format(i+2))[0] + rulelist.append(rule.strip()) + if contracttype == 'one-time-event*': extractedRules = {} for rule in rulelist: @@ -156,15 +161,13 @@ def extractContractConditions(text, contracttype, marker): try: extractedRules['contractamount'] = float(contractamount) except: - print("something is wrong with userchoices conditions") + print("something is wrong with contract amount entered") elif rule[:11]=='userchoices': conditions = rule.split('userchoices=')[1] conditionlist = conditions.split('|') extractedRules['userchoices'] = {} for idx, condition in enumerate(conditionlist): extractedRules['userchoices'][idx] = condition.strip() - else: - print("something is wrong with userchoices conditions") elif rule[:10]=='expirytime': pattern = re.compile('[^expirytime=].*') searchResult = pattern.search(rule).group(0) @@ -274,12 +277,12 @@ def parse_flodata(string): elif not incorporation and transfer: # We are at the send/transfer of smart contract amount = extractAmount(cleanstring, hashList[0][:-1]) - userPreference = extractContractCondition(cleanstring) - if None not in [amount, userPreference]: + userChoice = extractUserchoice(cleanstring) + if None not in [amount, userChoice]: parsed_data = {'type': 'transfer', 'transferType': 'smartContract', 'flodata': string, 'tokenIdentification': hashList[0][:-1], 'operation': 'transfer', 'tokenAmount': amount, 'contractName': atList[0][:-1], - 'userPreference': userPreference} + 'userChoice': userChoice} else: parsed_data = {'type': 'noise'} @@ -297,9 +300,3 @@ def parse_flodata(string): parsed_data = {'type': 'noise'} return parsed_data - - -flodata = 'Create Smart Contract with the name elections@ of the type one-time-event* using the asset rmt# at the address FLO Address$ with contractconditions: 1. contractAmount=5rmt 2. userchoices=NAMO=WIN | NAMO=LOSE 3. expirytime= Tue May 21 2019 18:55:00 GMT+0530' - -parsed_flodata = parse_flodata(flodata) -print(parsed_flodata) \ No newline at end of file diff --git a/tracktokens-smartcontracts.py b/tracktokens-smartcontracts.py index fb78f45..6eed002 100755 --- a/tracktokens-smartcontracts.py +++ b/tracktokens-smartcontracts.py @@ -14,6 +14,20 @@ from sqlalchemy import create_engine, func, desc from models import SystemData, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, Base, ContractStructure, ContractBase, ContractParticipants, SystemBase, ActiveContracts +months = { 'jan' : 1, +'feb' : 2, +'mar' : 3, +'apr' : 4, +'may' : 5, +'jun' : 6, +'jul' : 7, +'aug' : 8, +'sep' : 9, +'oct' : 10, +'nov' : 11, +'dec' : 12 } + + committeeAddressList = ['oUc4dVvxwK7w5MHUHtev8UawN3eDjiZnNx'] def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress): @@ -153,7 +167,7 @@ def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress) return 1 -def startWorking(transaction_data, parsed_data): +def startWorking(transaction_data, parsed_data, blockinfo): # Do the necessary checks for the inputs and outputs @@ -249,9 +263,24 @@ def startWorking(transaction_data, parsed_data): # todo Rule 46 - If the transfer type is smart contract, then call the function transferToken to do sanity checks & lock the balance elif parsed_data['transferType'] == 'smartContract': # Check if the contract has expired - if parsed_data['expiryTime'] and time.time()>parsed_data['expiryTime']: - print('Contract has expired and will not accept any user participation') - return + engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True) + Base.metadata.create_all(bind=engine) + session = sessionmaker(bind=engine)() + result = session.query(ContractStructure).filter_by(attribute='expirytime').all() + + if result: + #now parse the expiry time in python + expirytime = result[0].value.strip() + expirytime_split = expirytime.split(' ') + parse_string = '{}/{}/{} {}'.format( expirytime_split[3], months[expirytime_split[1]], expirytime_split[2], expirytime_split[4]) + expirytime_object = parsing.arrow.get(parse_string, 'YYYY/M/D HH:mm:ss').replace(tzinfo=expirytime_split[5]) + blocktime_object = parsing.arrow.get(blockinfo['time']) + + if blocktime_object > expirytime_object: + print('Contract has expired and will not accept any user participation') + return + session.close() + # Check if the tokenAmount being transferred exists in the address & do the token transfer returnval = transferToken(parsed_data['tokenIdentification'], parsed_data['tokenAmount'], inputlist[0], outputlist[0]) if returnval is not None: @@ -259,7 +288,7 @@ def startWorking(transaction_data, parsed_data): 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'], userPreference=parsed_data['userPreference'])) + session.add(ContractParticipants(participantAddress=inputadd, tokenAmount=parsed_data['tokenAmount'], userChoice=parsed_data['userChoice'])) session.commit() session.close() else: @@ -298,7 +327,7 @@ def startWorking(transaction_data, parsed_data): # todo Rule 50 - Contract address mentioned in flodata field should be same as the receiver FLO address on the output side # henceforth we will not consider any flo private key initiated comment as valid from this address # Unlocking can only be done through smart contract system address - if parsed_data['contractAddress'] == outputlist[0]: + if parsed_data['contractAddress'] == inputadd: print("Hey I have passed the first test for smart contract") engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True) ContractBase.metadata.create_all(bind=engine) @@ -314,11 +343,11 @@ def startWorking(transaction_data, parsed_data): value=parsed_data['flodata'])) session.add( ContractStructure(attribute='contractamount', index=0, - value=parsed_data['contractConditions']['contractamount'].split(parsed_data['tokenIdentification'][:-1])[0])) + value=parsed_data['contractConditions']['contractamount'])) session.add( ContractStructure(attribute='expirytime', index=0, value=parsed_data['contractConditions']['expirytime'])) - for key, value in parsed_data['contractConditions']['smartcontractpays'].items(): + for key, value in parsed_data['contractConditions']['userchoices'].items(): session.add(ContractStructure(attribute='exitconditions', index=key, value=value)) session.commit() session.close() @@ -352,7 +381,7 @@ def startWorking(transaction_data, parsed_data): engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True) connection = engine.connect() - contractWinners = connection.execute('select * from contractparticipants where userPreference="{}"'.format(parsed_data['triggerCondition'])).fetchall() + contractWinners = connection.execute('select * from contractparticipants where userChoice="{}"'.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() @@ -431,7 +460,7 @@ if args.reset == 1: engine = create_engine('sqlite:///system.db', echo=True) SystemBase.metadata.create_all(bind=engine) session = sessionmaker(bind=engine)() -startblock = int(session.query(SystemData).filter_by(attribute='lastblockscanned').all()[0].value) +startblock = int(session.query(SystemData).filter_by(attribute='lastblockscanned').all()[0].value) + 1 session.commit() session.close() @@ -450,7 +479,7 @@ print("current_block_height : " + str(current_index)) for blockindex in range( startblock, current_index ): print(blockindex) - if blockindex == 3387978: + if blockindex == 590327: print('hello') # Scan every block @@ -470,6 +499,7 @@ for blockindex in range( startblock, current_index ): response = subprocess.check_output(string, shell=True) transaction_data = json.loads(response.decode("utf-8")) text = transaction_data["floData"] + text = text.replace("\n"," \n ") # todo Rule 9 - Reject all noise transactions. Further rules are in parsing.py @@ -477,7 +507,7 @@ for blockindex in range( startblock, current_index ): if parsed_data['type'] != 'noise': print(blockindex) print(parsed_data['type']) - startWorking(transaction_data, parsed_data) + startWorking(transaction_data, parsed_data, blockinfo) engine = create_engine('sqlite:///system.db') SystemBase.metadata.create_all(bind=engine)