def slasher_verify(tx, txs, out, DB): address=tools.addr(tx) acc=tools.db_get(address) if acc['secrets'][str(tx['on_block'])]['slashed']: tools.log('Someone already slashed them, or they already took the reward.') return False if not sign_verify(tx['tx1'], [], [''], {}): tools.log('one was not a valid tx') return False if not sign_verify(tx['tx2'], [], [''], {}): tools.log('two was not a valid tx') return False tx1=copy.deepcopy(tx['tx1']) tx2=copy.deepcopy(tx['tx2']) tx1.pop('signatures') tx2.pop('signatures') tx1=unpackage(package(tx1)) tx2=unpackage(package(tx2)) msg1=tools.det_hash(tx1) msg2=tools.det_hash(tx2) if msg1==msg2: tools.log('this is the same tx twice...') return False if tx1['on_block']!=tx2['on_block']: tools.log('these are on different lengths') return False return True
def slasher_verify(tx, txs, out, DB): address = tools.addr(tx) acc = tools.db_get(address) if acc["secrets"][str(tx["on_block"])]["slashed"]: tools.log("Someone already slashed them, or they already took the reward.") return False if not sign_verify(tx["tx1"], [], [""], {}): tools.log("one was not a valid tx") return False if not sign_verify(tx["tx2"], [], [""], {}): tools.log("two was not a valid tx") return False tx1 = copy.deepcopy(tx["tx1"]) tx2 = copy.deepcopy(tx["tx2"]) tx1.pop("signatures") tx2.pop("signatures") tx1 = unpackage(package(tx1)) tx2 = unpackage(package(tx2)) msg1 = tools.det_hash(tx1) msg2 = tools.det_hash(tx2) if msg1 == msg2: tools.log("this is the same tx twice...") return False if tx1["on_block"] != tx2["on_block"]: tools.log("these are on different lengths") return False return True
def slasher_verify(tx, txs, out, DB): address = tools.addr(tx) acc = tools.db_get(address) if acc['secrets'][str(tx['on_block'])]['slashed']: tools.log( 'Someone already slashed them, or they already took the reward.') return False if not sign_verify(tx['tx1'], [], [''], {}): tools.log('one was not a valid tx') return False if not sign_verify(tx['tx2'], [], [''], {}): tools.log('two was not a valid tx') return False tx1 = copy.deepcopy(tx['tx1']) tx2 = copy.deepcopy(tx['tx2']) tx1.pop('signatures') tx2.pop('signatures') tx1 = unpackage(package(tx1)) tx2 = unpackage(package(tx2)) msg1 = tools.det_hash(tx1) msg2 = tools.det_hash(tx2) if msg1 == msg2: tools.log('this is the same tx twice...') return False if tx1['on_block'] != tx2['on_block']: tools.log('these are on different lengths') return False return True
def block_check(block, DB): if 'error' in block or 'error' in DB: return False if type(block)!=type({'a':1}): print('type error') return False #print('DB: ' +str(DB)) length=copy.deepcopy(DB['length']) if int(block['length'])!=int(length)+1: return False if block['diffLength']!=hexSum(DB['diffLength'], hexInvert(block['target'])): print('diff length') return False if length >= 0: if tools.det_hash(db_get(length, DB))!=block['prevHash']: return False a=copy.deepcopy(block) a.pop('nonce') if u'target' not in block.keys(): return False half_way={u'nonce':block['nonce'], u'halfHash':tools.det_hash(a)} if tools.det_hash(half_way)>block['target']: return False if block['target']!=target(DB, block['length']): return False earliest=median(recent_blockthings('time', DB)) if 'time' not in block: return False if block['time']>time.time(): return False if block['time']<earliest: return False return True
def block_check(block, DB): def log_(txt): pass #return tools.log(txt) def tx_check(txs): start = copy.deepcopy(txs) out = [] start_copy = [] while start != start_copy: if start == []: return False # Block passes this test start_copy = copy.deepcopy(start) if transactions.tx_check[start[-1]['type']](start[-1], out, [''], DB): out.append(start.pop()) else: return True # Block is invalid return True # Block is invalid if not isinstance(block, dict): return False if 'error' in block: return False if not tools.E_check(block, 'length', [int]): log_('no length') return False length = DB['length'] if int(block['length']) != int(length) + 1: log_('wrong longth') return False if block['diffLength'] != hexSum(DB['diffLength'], hexInvert(block['target'])): log_('diflength error') return False if length >= 0: if tools.det_hash(tools.db_get(length, DB)) != block['prevHash']: log_('det hash error') return False a = copy.deepcopy(block) a.pop('nonce') if u'target' not in block.keys(): log_('target error') return False half_way = {u'nonce': block['nonce'], u'halfHash': tools.det_hash(a)} if tools.det_hash(half_way) > block['target']: log_('det hash error 2') return False if block['target'] != target.target(DB, block['length']): log_('wrong target') return False earliest = median(recent_blockthings('times', DB, custom.mmm)) if 'time' not in block: log_('no time') return False if block['time'] > time.time()+60*6: log_('too late') return False if block['time'] < earliest: log_('too early') return False if tx_check(block['txs']): log_('tx check') return False return True
def POW(block, restart_signal): halfHash = tools.det_hash(block) block[u'nonce'] = random.randint(0, 10000000000000000000000000000000000000000) count = 0 while tools.det_hash({u'nonce': block['nonce'], u'halfHash': halfHash}) > block['target']: count += 1 block[u'nonce'] += 1 if restart_signal.is_set(): restart_signal.clear() return {'solution_found': True} return block
def block_check(block, DB): def tx_check(txs): start = copy.deepcopy(txs) out = [] start_copy = [] while start != start_copy: if start == []: return False # Block passes this test start_copy = copy.deepcopy(start) if transactions.tx_check[start[-1]['type']](start[-1], out, DB): out.append(start.pop()) else: return True # Block is invalid return True # Block is invalid if not isinstance(block, dict): return False if 'error' in block: return False if 'length' not in block: return False length = DB['length'] if int(block['length']) != int(length) + 1: return False if block['diffLength'] != hexSum(DB['diffLength'], hexInvert(block['target'])): return False if length >= 0: if tools.det_hash(db_get(length, DB)) != block['prevHash']: return False a = copy.deepcopy(block) a.pop('nonce') if u'target' not in block.keys(): return False half_way = {u'nonce': block['nonce'], u'halfHash': tools.det_hash(a)} if tools.det_hash(half_way) > block['target']: return False if block['target'] != target(DB, block['length']): return False earliest = median(recent_blockthings('time', DB, custom.mmm)) if 'time' not in block: return False if block['time'] > time.time(): return False if block['time'] < earliest: return False if tx_check(block['txs']): return False if len(filter(lambda tx: tx['type']=='mint', block['txs']))!=1: return False return True
def POW(block, hashes, target): halfHash=tools.det_hash(block) block[u'nonce']=random.randint(0,100000000000000000) count=0 while tools.det_hash({u'nonce':block['nonce'], u'halfHash':halfHash})>target: count+=1 block[u'nonce']+=1 if count>hashes: return {'error':False} ''' for testing sudden loss in hashpower from miners. if block[u'length']>150:# and block[u'nonce']%10==0: time.sleep(0.1) else: time.sleep(0.01) ''' return block
def insert_block(pubkey, rewarded_pubkey): length = tools.db_get('length') if length == -1: # this is the first ever block candidate_block = genesis(pubkey) else: # get the last block prev_block = tools.db_get(length) candidate_block = make_block(prev_block, tools.db_get('txs'), pubkey) txs = copy.deepcopy(candidate_block['txs']) flag = True for tx in txs: if tx['type'] == 'mint': # no need to add reward flag = False if flag: txs = txs + [make_mint(rewarded_pubkey)] candidate_block['txs'] = txs if tools.db_existence('privkey'): privkey = tools.db_get('privkey') else: return 'no private key is known, so the tx cannot be signed. Here is the tx: \n' + str( tools.package(txs).encode('base64').replace('\n', '')) candidate_block['auth_sign'] = tools.sign(tools.det_hash(candidate_block), privkey) candidate_block['auth_pubkey'] = pubkey if candidate_block is None: return else: custom.queues['suggested_blocks'].put(candidate_block)
def spend_verify(tx, txs, DB): tx_copy=copy.copy(tx) tx_copy.pop('signature') if not pt.ecdsa_verify(tools.det_hash(tx_copy), tx['signature'], tx['id']): return False if tx['amount']<custom.fee: return False if int(blockchain.db_get(tx['id'], DB)['amount'])<int(tx['amount']): return False return True
def reward_verify(tx, txs, out, DB): address=tools.addr(tx) acc=tools.db_get(address) relative_reward=tools.relative_reward(tx['on_block'], address) sign_tx=sign_transaction(tx['on_block'], address) length=tools.local_get('length') if len(sign_tx['jackpots'])!=tx['jackpots']: tools.log('wrong number of jackpots') return False if length-custom.long_time+custom.medium_time/2<tx['on_block']or length-custom.long_time-custom.medium_time/2>tx['on_block']: tools.log('you did not wait the correct amount of time') return False if acc['secrets'][str(tx['on_block'])]['slashed']: tools.log('you were slashed, or you already claimed your reward at this height') return False if tx['amount']!=relative_reward+sign_tx['amount']: tools.log('reward wrong size') return False if sign_tx['secret_hash']!=tools.det_hash(tx['reveal']): tools.log('entropy+salt does not match') return False if tx['reveal']['entropy'] not in [0,1]: tools.log('entropy must be either 0 or 1') return False return True
def home(DB, dic): if 'BrainWallet' in dic: dic['privkey']=tools.det_hash(dic['BrainWallet']) elif 'privkey' not in dic: return "<p>You didn't type in your brain wallet.</p>" privkey=dic['privkey'] pubkey=tools.privtopub(dic['privkey']) address=tools.make_address([pubkey], 1) if 'do' in dic.keys(): if dic['do']=='spend': spend(float(dic['amount']), pubkey, privkey, dic['to'], DB) out=empty_page out=out.format('<p>your address: ' +str(address)+'</p>{}') out=out.format('<p>current block: ' +str(DB['length'])+'</p>{}') balance=blockchain.db_get(address, DB)['amount'] for tx in DB['txs']: if tx['type'] == 'spend' and tx['to'] == address: balance += tx['amount'] - custom.fee if tx['type'] == 'spend' and tx['pubkeys'][0] == pubkey: balance -= tx['amount'] out=out.format('<p>current balance is: ' +str(balance/100000.0)+'</p>{}') if balance>0: out=out.format(easyForm('/home', 'spend money', ''' <input type="hidden" name="do" value="spend"> <input type="text" name="to" value="address to give to"> <input type="text" name="amount" value="amount to spend"> <input type="hidden" name="privkey" value="{}">'''.format(privkey))) txt=''' <input type="hidden" name="privkey" value="{}">''' s=easyForm('/home', 'Refresh', txt.format(privkey)) return out.format(s)
def easy_add_transaction(tx_orig, privkey='default'): tx = copy.deepcopy(tx_orig) if privkey in ['default', 'Default']: if tools.db_existence('privkey'): privkey = tools.db_get('privkey') else: return 'No private key is known, so the tx cannot be signed. ' pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) if 'count' not in tx: try: tx['count'] = tools.count(address, {}) except: tx['count'] = 1 # add our pubkey if 'pubkeys' not in tx: tx['pubkeys'] = [pubkey] # this is IMPORTANT # when adding new transaction which is signed by us, # this procedure is applied. tx without signatures is signed with our privkey. if 'signatures' not in tx: tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] return blockchain.add_tx(tx)
def home(DB, dic): if 'BrainWallet' in dic: dic['privkey'] = tools.det_hash(dic['BrainWallet']) elif 'privkey' not in dic: return "<p>You didn't type in your brain wallet.</p>" privkey = dic['privkey'] pubkey = tools.privtopub(dic['privkey']) address = tools.make_address([pubkey], 1) if 'do' in dic: if dic['do'] == 'spend': spend(float(dic['amount']), pubkey, privkey, dic['to'], DB) out = empty_page out = out.format('<p>your address: ' + str(address) + '</p>{}') out = out.format('<p>current block: ' + str(DB['length']) + '</p>{}') balance = blockchain.db_get(address, DB)['amount'] for tx in DB['txs']: if tx['type'] == 'spend' and tx['to'] == address: balance += tx['amount'] - custom.fee if tx['type'] == 'spend' and tx['pubkeys'][0] == pubkey: balance -= tx['amount'] out = out.format('<p>current balance is: ' + str(balance/100000.0) + '</p>{}') if balance > 0: out = out.format(easyForm('/home', 'spend money', ''' <input type="hidden" name="do" value="spend"> <input type="text" name="to" value="address to give to"> <input type="text" name="amount" value="amount to spend"> <input type="hidden" name="privkey" value="{}">'''.format(privkey))) txt=''' <input type="hidden" name="privkey" value="{}">''' s = easyForm('/home', 'Refresh', txt.format(privkey)) return out.format(s)
def spend_verify(tx, txs, DB): def sigs_match(sigs, pubs, msg): return all(tools.verify(msg, sig, pub) for sig in sigs for pub in pubs) tx_copy = copy.deepcopy(tx) tx_copy_2 = copy.deepcopy(tx) tx_copy.pop('signatures') if len(tx['pubkeys']) == 0: return False if len(tx['signatures']) > len(tx['pubkeys']): return False msg = tools.det_hash(tx_copy) if not sigs_match(copy.deepcopy(tx['signatures']), copy.deepcopy(tx['pubkeys']), msg): return False if tx['amount'] < custom.fee: return False address = addr(tx_copy_2) total_cost = 0 for Tx in filter(lambda t: address == addr(t), [tx] + txs): if Tx['type'] == 'spend': total_cost += Tx['amount'] if Tx['type'] == 'mint': total_cost -= custom.block_reward return int(blockchain.db_get(address, DB)['amount']) >= total_cost
def main(c=0): if type(c)==int: p={'command':sys.argv[1:]} else: p={'command':c} if len(p['command'])==0: p['command'].append(' ') c=p['command'] if c[0]=='make_PM': tx=build_pm() return run_command({'command':['pushtx', tools.package(tx).encode('base64')]}) elif c[0]=='buy_shares': tx=build_buy_shares() return run_command({'command':['pushtx', tools.package(tx).encode('base64')]}) elif c[0]=='start': r=connect({'command':'blockcount'}) if is_off(r): p=raw_input('what is your password?\n') daemonize(lambda: threads.main(p)) else: print('blockchain is already running') elif c[0]=='new_address': if len(c)<2: print('what is your brain wallet? not enough inputs.') else: privkey=tools.det_hash(c[1]) pubkey=tools.privtopub(privkey) address=tools.make_address([pubkey], 1) return({'brain':str(c[1]), 'privkey':str(privkey), 'pubkey':str(pubkey), 'address':str(address)}) else: return run_command(p)
def reveal_jury_vote_check(tx, txs, out, DB): if not transactions.signature_check(tx): out[0]+='signature check' return False address=addr(tx) acc=tools.db_get(address, DB) if not E_check(tx, 'decision_id', [str, unicode]): out[0]+='decision id error' return False if is_number(tx['decision_id']): out[0]+='that can not be a number' return False decision=tools.db_get(tx['decision_id'], DB) if decision['state']!='proposed': out[0]+='this decision has already been decided' return False if not E_check(tx, 'old_vote', [str, unicode]): return False if not E_check(tx, 'secret', [str, unicode]): return False if not E_check(tx, 'new_vote', [str, unicode]): out[0]+='new vote error' return False if tx['decision_id'] not in acc['votes']: out[0]+='decision id not in acc[votes] error' return False answer_hash=acc['votes'][tx['decision_id']] if not answer_hash==tools.det_hash([tx['new_vote'], tx['secret']]): out[0]+='hash does not match' return False if not E_check(tx, 'old_vote', [str, unicode]): out[0]+='old vote does not exist error' return False if not txs_tools.fee_check(tx, txs, DB): return False return True
def reward_verify(tx, txs, out, DB): address = tools.addr(tx) acc = tools.db_get(address) relative_reward = tools.relative_reward(tx['on_block'], address) sign_tx = sign_transaction(tx['on_block'], address) length = tools.local_get('length') if len(sign_tx['jackpots']) != tx['jackpots']: tools.log('wrong number of jackpots') return False if length - custom.long_time + custom.medium_time / 2 < tx[ 'on_block'] or length - custom.long_time - custom.medium_time / 2 > tx[ 'on_block']: tools.log('you did not wait the correct amount of time') return False if acc['secrets'][str(tx['on_block'])]['slashed']: tools.log( 'you were slashed, or you already claimed your reward at this height' ) return False if tx['amount'] != relative_reward + sign_tx['amount']: tools.log('reward wrong size') return False if sign_tx['secret_hash'] != tools.det_hash(tx['reveal']): tools.log('entropy+salt does not match') return False if tx['reveal']['entropy'] not in [0, 1]: tools.log('entropy must be either 0 or 1') return False return True
def reward_verify(tx, txs, out, DB): address = tools.addr(tx) acc = tools.db_get(address) relative_reward = tools.relative_reward(tx["on_block"], address) sign_tx = sign_transaction(tx["on_block"], address) length = tools.local_get("length") if len(sign_tx["jackpots"]) != tx["jackpots"]: tools.log("wrong number of jackpots") return False if ( length - custom.long_time + custom.medium_time / 2 < tx["on_block"] or length - custom.long_time - custom.medium_time / 2 > tx["on_block"] ): tools.log("you did not wait the correct amount of time") return False if acc["secrets"][str(tx["on_block"])]["slashed"]: tools.log("you were slashed, or you already claimed your reward at this height") return False if tx["amount"] != relative_reward + sign_tx["amount"]: tools.log("reward wrong size") return False if sign_tx["secret_hash"] != tools.det_hash(tx["reveal"]): tools.log("entropy+salt does not match") return False if tx["reveal"]["entropy"] not in [0, 1]: tools.log("entropy must be either 0 or 1") return False return True
def sign(tx, privkey): pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) if 'pubkeys' not in tx: tx['pubkeys'] = [pubkey] if 'signatures' not in tx: tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] return tx
def sign(tx, privkey): pubkey=tools.privtopub(privkey) address=tools.make_address([pubkey], 1) if 'pubkeys' not in tx: tx['pubkeys']=[pubkey] if 'signatures' not in tx: tx['signatures']=[tools.sign(tools.det_hash(tx), privkey)] return tx
def POW(block, hashes, target): halfHash = tools.det_hash(block) block[u'nonce'] = random.randint(0, 100000000000000000) count = 0 while tools.det_hash({ u'nonce': block['nonce'], u'halfHash': halfHash }) > target: count += 1 block[u'nonce'] += 1 if count > hashes: return {'error': False} ''' for testing sudden loss in hashpower from miners. if block[u'length']>150: else: time.sleep(0.01) ''' return block
def common_buy_shares(tx, num_states, brainwallet): privkey = tools.det_hash(brainwallet) pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) tx['pubkeys'] = [pubkey] tx['count'] = tools.count(address, {}) cost = txs_tools.cost_to_buy_shares(tx) tx['price_limit'] = int(cost * 1.01) + 1 print( 'now for a little proof of work. This may take several minutes. The purpose of this pow is to make it more difficult for a front runner to steal your trade.' ) tx = tools.unpackage(tools.package(tx)) tx = tools.POW(tx) tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] print('tx for copy/pasting into pushtx: ' + tools.package(tx).encode('base64')) return tx
def easy_add_transaction(tx_orig, privkey, DB): tx = copy.deepcopy(tx_orig) pubkey = pt.privtopub(privkey) try: tx['count'] = blockchain.count(pubkey, DB) except: tx['count'] = 1 tx['signature'] = pt.ecdsa_sign(tools.det_hash(tx), privkey) blockchain.add_tx(tx, DB)
def sign(tx, privkey): pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) tx = add_recent_hash(tx) if "pubkeys" not in tx: tx["pubkeys"] = [pubkey] if "signatures" not in tx: tx["signatures"] = [tools.sign(tools.det_hash(tx), privkey)] return tx
def POW(block, hashes): halfHash = tools.det_hash(block) block[u'nonce'] = random.randint(0, 100000000000000000) count = 0 while tools.det_hash({u'nonce': block['nonce'], u'halfHash': halfHash}) > block['target']: count += 1 block[u'nonce'] += 1 if count > hashes: return {'error': False} if restart_signal.is_set(): restart_signal.clear() return {'solution_found': True} ''' for testing sudden loss in hashpower from miners. if block[u'length']>150: else: time.sleep(0.01) ''' return block
def block_check(block, DB): def log_(txt): pass #return tools.log(txt) def tx_check(txs): start = copy.deepcopy(txs) out = [] start_copy = [] invalid_because = [''] while start != start_copy: if start == []: return False # Block passes this test start_copy = copy.deepcopy(start) if transactions.tx_check[start[0]['type']](start[0], out, invalid_because, DB): out.append(start.pop()) else: tools.log('invalid tx: '+str(invalid_because[0])) return True # Block is invalid tools.log('block invalid because it has no txs') return True # Block is invalid if 'error' in block: log_('error in block') return False length =tools.local_get('length') if type(block['length'])!=type(1): log_('wrong length type') return False if int(block['length']) != int(length) + 1: log_('wrong longth') return False block_creator_address=tools.addr(block) mint_address=tools.addr(filter(lambda t: t['type']=='mint', block['txs'])[0]) if block_creator_address!=mint_address: log_('bad mint') return False if block['root_hash']!=tools.db_root(): log_('bad root, have: '+str(tools.db_root())+' need ' +str(block['root_hash'])) return False txs=filter(lambda x: x['type']=='mint', block['txs']) if len(txs)!=1: log_('wrong number of mint txs') return False txs=filter(lambda x: x['type']=='sign', block['txs']) txs=map(lambda x: len(x['jackpots']), txs) if sum(txs)<custom.signers*2/3 and length>-1: log_('not enough signatures') return False if length >= 0: prev_block=tools.db_get(length) to_hash={'prev_hash':prev_block['block_hash'], 'txs':block['txs']} if not block['block_hash']==tools.det_hash(to_hash): log_('det hash error') return False #total money spent must be less than the total amount of money in signed deposits for this block. if tx_check(block['txs']): log_('tx check') return False return True
def easy_add_transaction(tx_orig, privkey, DB): tx=copy.deepcopy(tx_orig) pubkey=tools.privtopub(privkey) try: tx['count']=blockchain.count(pubkey, DB) except: tx['count']=1 tx['signature']=[tools.sign(tools.det_hash(tx), privkey)] print('CREATED TX: ' +str(tx)) blockchain.add_tx(tx, DB)
def easy_add_transaction(tx_orig, privkey, DB): tx = copy.deepcopy(tx_orig) pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) try: tx['count'] = blockchain.count(address, DB) except: tx['count'] = 1 tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] blockchain.add_tx(tx, DB)
def fork_check(newblocks, DB): #if we are on a fork, return True try: length=copy.deepcopy(DB['length']) block=blockchain.db_get(length, DB) recent_hash=tools.det_hash(block) return recent_hash not in map(tools.det_hash, newblocks) except Exception as e: #print('ERROR: ' +str(e)) return False
def easy_add_transaction(tx_orig, privkey, DB): tx=copy.deepcopy(tx_orig) pubkey=tools.privtopub(privkey) address=tools.make_address([pubkey], 1) try: tx['count']=blockchain.count(address, DB) except: tx['count']=1 tx['signatures']=[tools.sign(tools.det_hash(tx), privkey)] blockchain.add_tx(tx, DB)
def easy_add_transaction(tx_orig, DB): tx = copy.deepcopy(tx_orig) if 'pubkeys' not in tx: tx['pubkeys']=[DB['pubkey']] try: tx['count'] = tools.count(DB['address'], DB) except: tx['count'] = 1 tx['signatures'] = [tools.sign(tools.det_hash(tx), DB['privkey'])] return(blockchain.add_tx(tx, DB))
def make_block(prev_block, txs, pubkey, DB): leng=int(prev_block['length'])+1 out={'version':custom.version, 'txs':txs+[make_mint(pubkey, DB)], 'length':leng, 'time':time.time(), 'target':blockchain.target(DB, leng), 'prevHash':tools.det_hash(prev_block)} out=tools.unpackage(tools.package(out)) return out
def make_block(prev_block, txs, pubkey): leng = int(prev_block['length']) + 1 out = {'version': custom.version, 'txs': txs, # dont forget to add coinbase transaction ;) 'length': leng, 'time': time.time(), 'prevHash': tools.det_hash(prev_block)} out = tools.unpackage(tools.package(out)) return out
def easy_add_transaction(tx_orig, DB): tx = copy.deepcopy(tx_orig) if 'pubkeys' not in tx: tx['pubkeys'] = [DB['pubkey']] try: tx['count'] = tools.count(DB['address'], DB) except: tx['count'] = 1 tx['signatures'] = [tools.sign(tools.det_hash(tx), DB['privkey'])] return (blockchain.add_tx(tx, DB))
def buy_shares_check(tx, txs, out, DB): #make sure that we can only buy the shares of undecided markets. if not transactions.signature_check(tx): out[0]+='signature check' return False a=copy.deepcopy(tx) a.pop('signatures') half_way=tools.make_half_way(a) if tools.det_hash(half_way)>custom.buy_shares_target: out[0]+='insufficient POW' return False if not E_check(tx, 'buy', list): out[0]+='buy error' return False if not E_check(tx, 'PM_id', [str, unicode]): out[0]+='pm id error' return False pm=tools.db_get(tx['PM_id'], DB) if 'decisions' not in pm: out[0]+='that is not a prediction market yet' return False if len(tx['buy'])!=len(pm['shares_purchased']): out[0]+='buy length error' return False stop=True for i in tx['buy']: if i!=0: stop=False if stop: out[0]+='you need to buy a non-zero amount of at least one share' return False if 'price_limit' in tx: price = txs_tools.cost_to_buy_shares(tx) if price>tx['price_limit']: out[0]+='that is outside the price limit for that tx '+str(price) + ' is bigger than ' +str(tx) return False for purchase in tx['buy']: if type(purchase)!=int: return False for i in range(len(tx['buy'])): if tx['buy'][i]+pm['shares_purchased'][i]<0: out[0]+='PM cannot have negative shares' return False if not txs_tools.fee_check(tx, txs, DB): out[0]+='fee check error' return False for dec in pm['decisions']: decision = tools.db_get(dec, DB) bad=True if decision['state'] not in ['yes', 'no']: bad=False if bad: out[0]+='this PM is already expired. you cannot buy shares.' return False return True
def spend_verify(tx, txs, DB): tx_copy = copy.copy(tx) tx_copy.pop("signature") msg = tools.det_hash(tx_copy) if not pt.ecdsa_verify(msg, tx["signature"], tx["id"]): return False if tx["amount"] < custom.fee: return False if int(blockchain.db_get(tx["id"], DB)["amount"]) < int(tx["amount"]): return False return True
def build_buy_shares(): tx={'type':'buy_shares', 'PM_id':str(raw_input('What is the unique name for this prediction market?\n>'))} num_states=int(raw_input('how many states does this pm have?\n>')) tx['buy']=[] for i in range(num_states): tx['buy'].append(int(raw_input('how many shares do you want to buy of state '+str(i)+'? To sell states, use negative numbers.\n>'))) brainwallet=str(raw_input('What is your brainwallet\n>')) privkey=tools.det_hash(brainwallet) pubkey=tools.privtopub(privkey) address=tools.make_address([pubkey], 1) tx['pubkeys']=[pubkey] tx['count'] = tools.count(address, {}) cost=txs_tools.cost_to_buy_shares(tx) tx['price_limit']=int(cost*1.01) print('now for a little proof of work. This may take several minutes. The purpose of this pow is to make it more difficult for a front runner to steal your trade.') tx=tools.unpackage(tools.package(tx)) tx=tools.POW(tx) tx['signatures']=[tools.sign(tools.det_hash(tx), privkey)] print('tx for copy/pasting into pushtx: '+tools.package(tx).encode('base64')) return tx
def pushtx(DB, args): try: a = args[0].decode('base64') except: a = args[0] tx = tools.unpackage(a) if len(args) == 1: return easy_add_transaction(tx, DB) if args[1] == 'default': return easy_add_transaction(tx, DB, tools.db_get('privkey')) privkey = tools.det_hash(args[1]) return easy_add_transaction(tx, DB, privkey)
def make_block(prev_block, txs, pubkey): leng = int(prev_block['length']) + 1 out = { 'version': custom.version, 'txs': txs, # dont forget to add coinbase transaction ;) 'length': leng, 'time': time.time(), 'prevHash': tools.det_hash(prev_block) } out = tools.unpackage(tools.package(out)) return out
def vote_on_decision(DB): if len(DB['args'])<3: return('not enough inputs') decision_id=DB['args'][1] answer=DB['args'][2] acc=tools.db_get(DB['address'], DB) value=[answer, str(random.random())+str(random.random())] answer_hash=tools.det_hash(value) DB['memoized_votes'][answer_hash]=value old_vote='unsure' if decision_id in acc['votes']: #this is always False... old_vote=acc['votes'][decision_id] tx={'type':'jury_vote', 'vote_id':DB['args'][0], 'decision_id':decision_id, 'old_vote':old_vote, 'new_vote':answer_hash} return easy_add_transaction(tx, DB)
def make_block(prev_block, txs, pubkey, DB): leng = int(prev_block['length']) + 1 target = blockchain.target(DB, leng) diffLength = blockchain.hexSum(prev_block['diffLength'], blockchain.hexInvert(target)) out = {'version': custom.version, 'txs': txs + [make_mint(pubkey, DB)], 'length': leng, 'time': time.time(), 'diffLength': diffLength, 'target': target, 'prevHash': tools.det_hash(prev_block)} out = tools.unpackage(tools.package(out)) return out
def signature_check(tx):#verify that a transaction has a valid ECDSA signature on it. tx_copy = copy.deepcopy(tx) tx_copy.pop('signatures') if len(tx['pubkeys']) == 0: tools.log('pubkey error') return False if len(tx['signatures']) > len(tx['pubkeys']): tools.log('sigs too long') return False msg = tools.det_hash(tx_copy) if not sigs_match(copy.deepcopy(tx['signatures']), copy.deepcopy(tx['pubkeys']), msg): tools.log('sigs do not match') return False return True
def easy_add_transaction(tx_orig, DB, privkey='default'): tx = copy.deepcopy(tx_orig) try: tx['count'] = tools.count(DB['address'], DB) except: tx['count'] = 1 if privkey=='default': if 'privkey' in DB: privkey=DB['privkey'] else: return('no private key is known, so the tx cannot be signed. Here is the tx: \n'+str(tools.package(tx_orig).encode('base64').replace('\n', ''))) if 'pubkeys' not in tx: tx['pubkeys']=[tools.privtopub(privkey)] tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] tools.log('collect winnings 3') return(blockchain.add_tx(tx, DB))
def create_sign_tx(): on_block=tools.local_get('length')+1 if on_block==0: time.sleep(1) return{'error':'not ready'} r=tools.det_random(on_block) jackpots=[] address=tools.local_get('address') l=max(-1, on_block-1-(custom.long_time*2-custom.medium_time)) election_block=tools.db_get(l+1) proof=tools.local_get('balance_proofs'+str(l)) if 'root_hash' not in election_block: return({'error':'database changed'}) a=tools.db_verify(election_block['root_hash'], address, proof) if a==False: #tools.log('election block: ' +str(election_block)) #tools.log('proof: ' +str(proof)) return({'error':'not valid proof'}) old_balance=a['amount'] M=custom.all_money for j in range(custom.jackpot_nonces): if tools.winner(old_balance, M, r, address, j): jackpots.append(j) if len(jackpots)>0: tx={'on_block':on_block, 'jackpots':jackpots, 'type':'sign', 'amount':M/3000/3} tx['B']=old_balance tx['proof']=proof if proof=='empty': time.sleep(1) return {'error':'not ready'} secrets=tools.local_get('secrets') if str(on_block) in secrets: secret=secrets[str(on_block)] else: secret=tools.unpackage(tools.package({'salt':str(random.random())+str(random.random()), 'entropy':random.randint(0,1)})) secrets[str(on_block)]=secret tools.local_put('secrets', secrets) tx['secret_hash']=tools.det_hash(secret) if on_block>0: block=tools.db_get(on_block-1) if 'amount' in block and block['amount']==0: return({'error':'database changed'}) #tools.log('on_block: ' +str(a)) tx['prev']=block['block_hash'] else: tx= {'error':'no jackpots'} return tx
def trade_shares(DB, args): #args = [ PM_id, buy ] privkey = tools.db_get('privkey') pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) tx = { 'type': 'buy_shares', 'PM_id': args[0], 'buy': csv2vec(args[1]), 'pubkeys': [pubkey], 'count': tools.count(address, {}) } cost = txs_tools.cost_to_buy_shares(tx) tx['price_limit'] = int(cost * 1.01) + 1 tx = tools.unpackage(tools.package(tx)) tx = tools.POW(tx) tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] return easy_add_transaction(tx, DB, privkey)
def buy_block(DB, args): gap = 1 #this should be an argument. #we should also let the user delete as many blocks first as they want, to build a fork from a point in history. length = tools.local_get('length') prev_block = tools.db_get(length) txs = tools.local_get('txs') privkey = tools.local_get('privkey') height = tools.local_get('height') block = default_block(length + 1, height + gap, txs + [sign(mint_tx(gap), privkey)]) to_hash = '' if length > -1: to_hash = {'prev_hash': prev_block['block_hash'], 'txs': block['txs']} block['block_hash'] = tools.det_hash(to_hash) block['root_hash'] = tools.db_root() block = sign(block, privkey) block = tools.unpackage(tools.package(block)) DB['suggested_blocks'].put(block) return block
def easy_add_transaction(tx_orig, DB, privkey='default'): tx = copy.deepcopy(tx_orig) if privkey in ['default', 'Default']: if tools.db_existence('privkey'): privkey = tools.db_get('privkey') else: return ('no private key is known, so the tx cannot be signed. Here is the tx: \n' + str( tools.package(tx_orig).encode('base64').replace('\n', ''))) pubkey = tools.privtopub(privkey) address = tools.make_address([pubkey], 1) if 'count' not in tx: try: tx['count'] = tools.count(address, {}) except: tx['count'] = 1 if 'pubkeys' not in tx: tx['pubkeys'] = [pubkey] if 'signatures' not in tx: tx['signatures'] = [tools.sign(tools.det_hash(tx), privkey)] return (blockchain.add_tx(tx, DB))
def signature_check(tx): tx_copy = copy.deepcopy(tx) if not E_check(tx, 'signatures', list): tools.log('no signautres') return False if not E_check(tx, 'pubkeys', list): tools.log('no pubkeys') return False tx_copy.pop('signatures') if len(tx['pubkeys']) == 0: tools.log('pubkey error') return False if len(tx['signatures']) > len(tx['pubkeys']): tools.log('sigs too long') return False msg = tools.det_hash(tx_copy) if not sigs_match(copy.deepcopy(tx['signatures']), copy.deepcopy(tx['pubkeys']), msg): tools.log('sigs do not match') return False return True